1
0
mirror of https://gitlab.com/comunic/comunicmobile synced 2024-11-22 04:49:21 +00:00
comunicmobile/lib/ui/widgets/forez_presence_calendar_widget.dart
2022-03-11 16:40:56 +01:00

171 lines
4.7 KiB
Dart

import 'package:comunic/lists/forez_presences_set.dart';
import 'package:comunic/utils/date_utils.dart' as date_utils;
/// Forez presence calendar widget
///
/// This widget is used only by Forez groups
///
/// @author Pierre Hubert
import 'package:flutter/material.dart';
import 'package:table_calendar/table_calendar.dart';
enum CalendarDisplayMode { SINGLE_USER, MULTIPLE_USERS }
extension DateOnlyCompare on DateTime {
bool isSameDate(DateTime? other) => date_utils.isSameDate(this, other);
}
class PresenceCalendarWidget extends StatefulWidget {
final PresenceSet presenceSet;
final void Function(DateTime)? onDayClicked;
final CalendarDisplayMode mode;
final DateTime? selectedDay;
const PresenceCalendarWidget({
Key? key,
required this.presenceSet,
this.onDayClicked,
this.mode = CalendarDisplayMode.SINGLE_USER,
this.selectedDay,
}) : super(key: key);
@override
_PresenceCalendarWidgetState createState() => _PresenceCalendarWidgetState();
}
class _PresenceCalendarWidgetState extends State<PresenceCalendarWidget> {
DateTime? selectedDay = DateTime.now();
@override
void didUpdateWidget(covariant PresenceCalendarWidget oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.selectedDay != widget.selectedDay) {
selectedDay = widget.selectedDay;
setState(() {});
}
}
@override
Widget build(BuildContext context) {
return TableCalendar(
firstDay: DateTime.utc(2020, 01, 01),
lastDay: DateTime.now().add(Duration(days: 365 * 2)),
selectedDayPredicate: (d) => d == selectedDay,
locale: "fr_FR",
weekendDays: [],
onHeaderTapped: _pickDate,
calendarBuilders: CalendarBuilders(
defaultBuilder: _dayBuilder,
todayBuilder: _dayBuilder,
selectedBuilder: _dayBuilder,
),
onDaySelected: _selectedDay,
availableCalendarFormats: const {CalendarFormat.month: "Mois"},
focusedDay: selectedDay!,
onPageChanged: (s) {
setState(() {
selectedDay = s;
});
},
);
}
void _pickDate(DateTime date) async {
final pickedDate = await showDatePicker(
context: context,
initialDate: date,
firstDate: DateTime.now().subtract(Duration(days: 20)),
lastDate: DateTime.now().add(Duration(days: 365 * 5)),
);
setState(() {
if (pickedDate != null) selectedDay = pickedDate;
});
}
Widget _dayBuilder(BuildContext context, DateTime date, DateTime focusedDay) {
if (widget.presenceSet.containsDate(date)) {
// Show the number of users who are present
if (widget.mode == CalendarDisplayMode.MULTIPLE_USERS)
return Stack(
children: [
CellWidget(
text: date.day.toString(),
color: Colors.green,
textColor: Colors.white,
circle: false,
selected: date.isSameDate(widget.selectedDay),
),
Positioned(
child: Material(
child: Padding(
padding: const EdgeInsets.all(2.0),
child: Text(widget.presenceSet.countAtDate(date).toString()),
),
textStyle: TextStyle(color: Colors.white),
color: Colors.red,
),
bottom: 4,
right: 4,
),
],
);
// Only show green circle
else
return CellWidget(
text: date.day.toString(),
color: Colors.green,
textColor: Colors.white,
);
}
return CellWidget(
text: date.day.toString(),
selected: date.isSameDate(widget.selectedDay),
);
}
void _selectedDay(DateTime selecteDay, DateTime focusedDay) {
if (widget.onDayClicked != null) widget.onDayClicked!(selecteDay);
setState(() {});
}
}
class CellWidget extends StatelessWidget {
final String text;
final Color? color;
final Color? textColor;
final bool circle;
final bool? selected;
const CellWidget({
Key? key,
required this.text,
this.color,
this.textColor,
this.circle = true,
this.selected,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return AnimatedContainer(
duration: const Duration(milliseconds: 250),
decoration: _buildCellDecoration(),
margin: const EdgeInsets.all(6.0),
alignment: Alignment.center,
child: Text(
text,
textAlign: TextAlign.center,
style: TextStyle(color: selected ?? false ? Colors.white : textColor),
),
);
}
Decoration _buildCellDecoration() => BoxDecoration(
shape: circle ? BoxShape.circle : BoxShape.rectangle,
color: selected ?? false ? Colors.deepPurple : color,
);
}