diff --git a/lib/model/attendance/attendence_filter_sheet.dart b/lib/model/attendance/attendence_filter_sheet.dart index d145918..6d6ea57 100644 --- a/lib/model/attendance/attendence_filter_sheet.dart +++ b/lib/model/attendance/attendence_filter_sheet.dart @@ -5,7 +5,7 @@ import 'package:intl/intl.dart'; import 'package:marco/helpers/widgets/my_text.dart'; import 'package:marco/helpers/utils/permission_constants.dart'; -class AttendanceFilterBottomSheet extends StatelessWidget { +class AttendanceFilterBottomSheet extends StatefulWidget { final AttendanceController controller; final PermissionController permissionController; final String selectedTab; @@ -17,35 +17,93 @@ class AttendanceFilterBottomSheet extends StatelessWidget { required this.selectedTab, }); + @override + _AttendanceFilterBottomSheetState createState() => + _AttendanceFilterBottomSheetState(); +} + +class _AttendanceFilterBottomSheetState + extends State { + late String? tempSelectedProjectId; + late String tempSelectedTab; + bool showProjectList = false; + + @override + void initState() { + super.initState(); + tempSelectedProjectId = widget.controller.selectedProjectId; + tempSelectedTab = widget.selectedTab; + } + String getLabelText() { - final startDate = controller.startDateAttendance; - final endDate = controller.endDateAttendance; + final startDate = widget.controller.startDateAttendance; + final endDate = widget.controller.endDateAttendance; if (startDate != null && endDate != null) { - final start = DateFormat('dd MM yyyy').format(startDate); - final end = DateFormat('dd MM yyyy').format(endDate); + final start = DateFormat('dd/MM/yyyy').format(startDate); + final end = DateFormat('dd/MM/yyyy').format(endDate); return "$start - $end"; } return "Date Range"; } - @override - Widget build(BuildContext context) { - String? tempSelectedProjectId = controller.selectedProjectId; - String tempSelectedTab = selectedTab; - bool showProjectList = false; - - final accessibleProjects = controller.projects + List buildProjectList() { + final accessibleProjects = widget.controller.projects .where((project) => - permissionController.isUserAssignedToProject(project.id.toString())) + widget.permissionController.isUserAssignedToProject( + project.id.toString())) .toList(); - bool hasRegularizationPermission = - permissionController.hasPermission(Permissions.regularizeAttendance); + if (accessibleProjects.isEmpty) { + return [ + const Padding( + padding: EdgeInsets.all(12.0), + child: Center(child: Text('No Projects Assigned')), + ), + ]; + } + + return accessibleProjects.map((project) { + final isSelected = tempSelectedProjectId == project.id.toString(); + return ListTile( + dense: true, + contentPadding: const EdgeInsets.symmetric(horizontal: 16), + title: Text(project.name), + trailing: isSelected ? const Icon(Icons.check) : null, + onTap: () { + setState(() { + tempSelectedProjectId = project.id.toString(); + showProjectList = false; + }); + }, + ); + }).toList(); + } + + List buildMainFilters() { + final accessibleProjects = widget.controller.projects + .where((project) => + widget.permissionController.isUserAssignedToProject( + project.id.toString())) + .toList(); + + final selectedProject = accessibleProjects.isNotEmpty + ? accessibleProjects.firstWhere( + (p) => p.id.toString() == tempSelectedProjectId, + orElse: () => accessibleProjects[0], + ) + : null; + + final selectedProjectName = selectedProject?.name ?? "Select Project"; + + final hasRegularizationPermission = widget.permissionController + .hasPermission(Permissions.regularizeAttendance); + final viewOptions = [ {'label': 'Today\'s Attendance', 'value': 'todaysAttendance'}, {'label': 'Attendance Logs', 'value': 'attendanceLogs'}, {'label': 'Regularization Requests', 'value': 'regularizationRequests'}, ]; + final filteredViewOptions = viewOptions.where((item) { if (item['value'] == 'regularizationRequests') { return hasRegularizationPermission; @@ -53,190 +111,152 @@ class AttendanceFilterBottomSheet extends StatelessWidget { return true; }).toList(); - return StatefulBuilder(builder: (context, setState) { - List filterWidgets; + List widgets = [ + Padding( + padding: const EdgeInsets.fromLTRB(16, 12, 16, 4), + child: Align( + alignment: Alignment.centerLeft, + child: MyText.titleSmall( + "Project", + fontWeight: 600, + ), + ), + ), + ListTile( + dense: true, + contentPadding: const EdgeInsets.symmetric(horizontal: 16), + title: Text(selectedProjectName), + trailing: const Icon(Icons.arrow_drop_down), + onTap: () => setState(() => showProjectList = true), + ), + const Divider(), + Padding( + padding: const EdgeInsets.fromLTRB(16, 12, 16, 4), + child: Align( + alignment: Alignment.centerLeft, + child: MyText.titleSmall( + "View", + fontWeight: 600, + ), + ), + ), + ...filteredViewOptions.map((item) { + return RadioListTile( + dense: true, + contentPadding: const EdgeInsets.symmetric(horizontal: 12), + title: Text(item['label']!), + value: item['value']!, + groupValue: tempSelectedTab, + onChanged: (value) => setState(() => tempSelectedTab = value!), + ); + }).toList(), + ]; - if (showProjectList) { - filterWidgets = accessibleProjects.isEmpty - ? [ - const Padding( - padding: EdgeInsets.all(12.0), - child: Center(child: Text('No Projects Assigned')), + if (tempSelectedTab == 'attendanceLogs') { + widgets.addAll([ + const Divider(), + Padding( + padding: const EdgeInsets.fromLTRB(16, 12, 16, 4), + child: Align( + alignment: Alignment.centerLeft, + child: MyText.titleSmall( + "Date Range", + fontWeight: 600, + ), + ), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + child: InkWell( + borderRadius: BorderRadius.circular(10), + onTap: () => widget.controller.selectDateRangeForAttendance( + context, + widget.controller, + ), + child: Ink( + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: Colors.grey.shade400), + borderRadius: BorderRadius.circular(10), + ), + padding: + const EdgeInsets.symmetric(horizontal: 16, vertical: 14), + child: Row( + children: [ + Icon(Icons.date_range, color: Colors.black87), + const SizedBox(width: 12), + Expanded( + child: Text( + getLabelText(), + style: const TextStyle( + fontSize: 16, + color: Colors.black87, + fontWeight: FontWeight.w500, + ), + overflow: TextOverflow.ellipsis, + ), + ), + const Icon(Icons.arrow_drop_down, color: Colors.black87), + ], + ), + ), + ), + ), + ]); + } + + return widgets; + } + + @override + Widget build(BuildContext context) { + return Padding( + padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + // Drag handle + Padding( + padding: const EdgeInsets.only(top: 12, bottom: 8), + child: Center( + child: Container( + width: 40, + height: 4, + decoration: BoxDecoration( + color: Colors.grey[400], + borderRadius: BorderRadius.circular(4), + ), ), - ] - : accessibleProjects.map((project) { - final isSelected = - tempSelectedProjectId == project.id.toString(); - return ListTile( - dense: true, - contentPadding: const EdgeInsets.symmetric(horizontal: 16), - title: Text(project.name), - trailing: isSelected ? const Icon(Icons.check) : null, - onTap: () { - setState(() { - tempSelectedProjectId = project.id.toString(); - showProjectList = false; - }); - }, - ); - }).toList(); - } else { - final selectedProject = accessibleProjects.isNotEmpty - ? accessibleProjects.firstWhere( - (p) => p.id.toString() == tempSelectedProjectId, - orElse: () => accessibleProjects[0], - ) - : null; - - final selectedProjectName = selectedProject?.name ?? "Select Project"; - - filterWidgets = [ - Padding( - padding: const EdgeInsets.fromLTRB(16, 12, 16, 4), - child: Align( - alignment: Alignment.centerLeft, - child: MyText.titleSmall( - "Project", - fontWeight: 600, ), ), - ), - ListTile( - dense: true, - contentPadding: const EdgeInsets.symmetric(horizontal: 16), - title: Text(selectedProjectName), - trailing: const Icon(Icons.arrow_drop_down), - onTap: () => setState(() => showProjectList = true), - ), - const Divider(), - Padding( - padding: const EdgeInsets.fromLTRB(16, 12, 16, 4), - child: Align( - alignment: Alignment.centerLeft, - child: MyText.titleSmall( - "View", - fontWeight: 600, - ), - ), - ), - ...filteredViewOptions.map((item) { - return RadioListTile( - dense: true, - contentPadding: const EdgeInsets.symmetric(horizontal: 12), - title: Text(item['label']!), - value: item['value']!, - groupValue: tempSelectedTab, - onChanged: (value) => setState(() => tempSelectedTab = value!), - ); - }).toList(), - ]; - - if (tempSelectedTab == 'attendanceLogs') { - filterWidgets.addAll([ + if (showProjectList) ...buildProjectList() else ...buildMainFilters(), const Divider(), Padding( - padding: const EdgeInsets.fromLTRB(16, 12, 16, 4), - child: Align( - alignment: Alignment.centerLeft, - child: MyText.titleSmall( - "Date Range", - fontWeight: 600, + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + child: SizedBox( + width: double.infinity, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: const Color.fromARGB(255, 95, 132, 255), + padding: const EdgeInsets.symmetric(vertical: 12), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + child: const Text('Apply Filter'), + onPressed: () { + Navigator.pop(context, { + 'projectId': tempSelectedProjectId, + 'selectedTab': tempSelectedTab, + }); + }, ), ), ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), - child: InkWell( - borderRadius: BorderRadius.circular(10), - onTap: () => controller.selectDateRangeForAttendance( - context, - controller, - ), - child: Ink( - decoration: BoxDecoration( - color: const Color.fromARGB(255, 255, 255, 255), - border: Border.all(color: Colors.grey.shade400), - borderRadius: BorderRadius.circular(10), - ), - padding: - const EdgeInsets.symmetric(horizontal: 16, vertical: 14), - child: Row( - children: [ - Icon(Icons.date_range, - color: const Color.fromARGB(255, 9, 9, 9)), - const SizedBox(width: 12), - Expanded( - child: Text( - getLabelText(), - style: const TextStyle( - fontSize: 16, - color: Colors.black87, - fontWeight: FontWeight.w500, - ), - overflow: TextOverflow.ellipsis, - ), - ), - const Icon(Icons.arrow_drop_down, - color: Color.fromARGB(255, 0, 0, 0)), - ], - ), - ), - ), - ), - ]); - } - } - - return Padding( - padding: EdgeInsets.only( - bottom: MediaQuery.of(context).viewInsets.bottom, + ], ), - child: SingleChildScrollView( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Padding( - padding: const EdgeInsets.only(top: 12, bottom: 8), - child: Center( - child: Container( - width: 40, - height: 4, - decoration: BoxDecoration( - color: Colors.grey[400], - borderRadius: BorderRadius.circular(4), - ), - ), - ), - ), - ...filterWidgets, - const Divider(), - Padding( - padding: - const EdgeInsets.symmetric(horizontal: 16, vertical: 12), - child: SizedBox( - width: double.infinity, - child: ElevatedButton( - style: ElevatedButton.styleFrom( - backgroundColor: const Color.fromARGB(255, 95, 132, 255), - padding: const EdgeInsets.symmetric(vertical: 12), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - ), - child: const Text('Apply Filter'), - onPressed: () { - Navigator.pop(context, { - 'projectId': tempSelectedProjectId, - 'selectedTab': tempSelectedTab, - }); - }, - ), - ), - ), - ], - ), - ), - ); - }); + ), + ); } }