mirror of
https://gitlab.com/comunic/comunicmobile
synced 2025-06-19 08:15:16 +00:00
Display Forez presence
This commit is contained in:
@ -60,7 +60,7 @@ class _AuthorizedGroupPageScreenState
|
||||
|
||||
// Forez presence tab
|
||||
_GroupPageTab(
|
||||
widget: (c) => ForezPresenceSection(),
|
||||
widget: (c) => ForezPresenceSection(groupID: _group.id),
|
||||
label: tr("Presence"),
|
||||
visible: _group.isForezGroup,
|
||||
),
|
||||
|
@ -1,3 +1,10 @@
|
||||
import 'package:comunic/helpers/forez_presence_helper.dart';
|
||||
import 'package:comunic/helpers/users_helper.dart';
|
||||
import 'package:comunic/lists/forez_presences_set.dart';
|
||||
import 'package:comunic/lists/users_list.dart';
|
||||
import 'package:comunic/ui/widgets/account_image_widget.dart';
|
||||
import 'package:comunic/ui/widgets/async_screen_widget.dart';
|
||||
import 'package:comunic/ui/widgets/forez_presence_calendar_widget.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// Forez presence section
|
||||
@ -5,13 +12,77 @@ import 'package:flutter/material.dart';
|
||||
/// @author Pierre Hubert
|
||||
|
||||
class ForezPresenceSection extends StatefulWidget {
|
||||
final int groupID;
|
||||
|
||||
const ForezPresenceSection({
|
||||
Key key,
|
||||
@required this.groupID,
|
||||
}) : assert(groupID != null),
|
||||
super(key: key);
|
||||
|
||||
@override
|
||||
_ForezPresenceSectionState createState() => _ForezPresenceSectionState();
|
||||
}
|
||||
|
||||
class _ForezPresenceSectionState extends State<ForezPresenceSection> {
|
||||
PresenceSet _presences;
|
||||
UsersList _users;
|
||||
DateTime _currentDay = DateTime.now();
|
||||
|
||||
List<int> get _currentListOfUsers => _presences.getUsersAtDate(_currentDay);
|
||||
|
||||
Future<void> _refresh() async {
|
||||
await ForezPresenceHelper.refreshCache(widget.groupID);
|
||||
|
||||
_presences = await ForezPresenceHelper.getAll(widget.groupID);
|
||||
_users = await UsersHelper().getList(_presences.usersID);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container();
|
||||
return Stack(
|
||||
children: <Widget>[
|
||||
AsyncScreenWidget(
|
||||
onReload: _refresh,
|
||||
onBuild: _buildList,
|
||||
errorMessage: "Erreur lors du chargement des présences !",
|
||||
),
|
||||
Positioned(
|
||||
right: 10,
|
||||
bottom: 10,
|
||||
child: FloatingActionButton(
|
||||
backgroundColor: Colors.green,
|
||||
onPressed: () {},
|
||||
child: Icon(Icons.edit),
|
||||
),
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildList() {
|
||||
final currentList = _currentListOfUsers;
|
||||
return ListView.builder(
|
||||
itemCount: currentList.length + 1,
|
||||
itemBuilder: (c, i) =>
|
||||
i == 0 ? _buildCalendar() : _buildUser(currentList[i - 1]),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildCalendar() => PresenceCalendarWidget(
|
||||
presenceSet: _presences,
|
||||
mode: CalendarDisplayMode.MULTIPLE_USERS,
|
||||
selectedDay: _currentDay,
|
||||
onDayClicked: _selectDay,
|
||||
);
|
||||
|
||||
void _selectDay(DateTime dt) => setState(() => _currentDay = dt);
|
||||
|
||||
Widget _buildUser(int userID) {
|
||||
final user = _users.getUser(userID);
|
||||
return ListTile(
|
||||
leading: AccountImageWidget(user: user),
|
||||
title: Text(user.fullName),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
165
lib/ui/widgets/forez_presence_calendar_widget.dart
Normal file
165
lib/ui/widgets/forez_presence_calendar_widget.dart
Normal file
@ -0,0 +1,165 @@
|
||||
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,
|
||||
}) : assert(presenceSet != null),
|
||||
assert(mode != null),
|
||||
super(key: key);
|
||||
|
||||
@override
|
||||
_PresenceCalendarWidgetState createState() => _PresenceCalendarWidgetState();
|
||||
}
|
||||
|
||||
class _PresenceCalendarWidgetState extends State<PresenceCalendarWidget> {
|
||||
CalendarController _calendarController;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_calendarController = CalendarController();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_calendarController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return TableCalendar(
|
||||
calendarController: _calendarController,
|
||||
locale: "fr_FR",
|
||||
weekendDays: [],
|
||||
onHeaderTapped: _pickDate,
|
||||
builders: CalendarBuilders(dayBuilder: _dayBuilder),
|
||||
onDaySelected: _selectedDay,
|
||||
availableCalendarFormats: const {CalendarFormat.month: "Mois"},
|
||||
);
|
||||
}
|
||||
|
||||
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)),
|
||||
);
|
||||
|
||||
if (pickedDate != null) {
|
||||
_calendarController.setSelectedDay(pickedDate, animate: true);
|
||||
setState(() {});
|
||||
}
|
||||
}
|
||||
|
||||
Widget _dayBuilder(
|
||||
BuildContext context, DateTime date, List<dynamic> events) {
|
||||
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 day, List<dynamic> events, List<dynamic> holidays) {
|
||||
if (widget.onDayClicked != null) widget.onDayClicked(day);
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
}) : assert(text != null),
|
||||
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,
|
||||
);
|
||||
}
|
Reference in New Issue
Block a user