import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:marco/helpers/theme/app_theme.dart'; import 'package:marco/helpers/utils/mixins/ui_mixin.dart'; import 'package:marco/helpers/widgets/my_flex.dart'; import 'package:marco/helpers/widgets/my_flex_item.dart'; import 'package:marco/helpers/widgets/my_spacing.dart'; import 'package:marco/helpers/widgets/my_text.dart'; import 'package:marco/controller/attendance/attendance_screen_controller.dart'; import 'package:marco/controller/permission_controller.dart'; import 'package:marco/model/attendance/attendence_filter_sheet.dart'; import 'package:marco/controller/project_controller.dart'; import 'package:marco/view/Attendence/regularization_requests_tab.dart'; import 'package:marco/view/Attendence/attendance_logs_tab.dart'; import 'package:marco/view/Attendence/todays_attendance_tab.dart'; import 'package:marco/helpers/widgets/my_refresh_indicator.dart'; class AttendanceScreen extends StatefulWidget { const AttendanceScreen({super.key}); @override State createState() => _AttendanceScreenState(); } class _AttendanceScreenState extends State with UIMixin { final attendanceController = Get.put(AttendanceController()); final permissionController = Get.put(PermissionController()); final projectController = Get.find(); String selectedTab = 'todaysAttendance'; @override void initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) { // Listen for future project selection changes ever(projectController.selectedProjectId, (projectId) async { if (projectId.isNotEmpty) await _loadData(projectId); }); // Load initial data final projectId = projectController.selectedProjectId.value; if (projectId.isNotEmpty) _loadData(projectId); }); } Future _loadData(String projectId) async { try { await attendanceController.loadAttendanceData(projectId); attendanceController.update(['attendance_dashboard_controller']); } catch (e) { debugPrint("Error loading data: $e"); } } Future _refreshData() async { final projectId = projectController.selectedProjectId.value; if (projectId.isNotEmpty) await _loadData(projectId); } Widget _buildAppBar() { return AppBar( backgroundColor: const Color(0xFFF5F5F5), elevation: 0.5, automaticallyImplyLeading: false, titleSpacing: 0, title: Padding( padding: MySpacing.xy(16, 0), child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ IconButton( icon: const Icon(Icons.arrow_back_ios_new, color: Colors.black, size: 20), onPressed: () => Get.offNamed('/dashboard'), ), MySpacing.width(8), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ MyText.titleLarge('Attendance', fontWeight: 700, color: Colors.black), MySpacing.height(2), GetBuilder( builder: (projectController) { final projectName = projectController.selectedProject?.name ?? 'Select Project'; return Row( children: [ const Icon(Icons.work_outline, size: 14, color: Colors.grey), MySpacing.width(4), Expanded( child: MyText.bodySmall( projectName, fontWeight: 600, overflow: TextOverflow.ellipsis, color: Colors.grey[700], ), ), ], ); }, ), ], ), ), ], ), ), ); } Widget _buildFilterSearchRow() { return Padding( padding: MySpacing.xy(8, 8), child: Row( children: [ Expanded( child: SizedBox( height: 35, child: Obx(() { final query = attendanceController.searchQuery.value; return TextField( controller: TextEditingController(text: query) ..selection = TextSelection.collapsed(offset: query.length), onChanged: (value) { attendanceController.searchQuery.value = value; }, decoration: InputDecoration( contentPadding: const EdgeInsets.symmetric(horizontal: 12), prefixIcon: const Icon(Icons.search, size: 20, color: Colors.grey), suffixIcon: query.isNotEmpty ? IconButton( icon: const Icon(Icons.close, size: 18, color: Colors.grey), onPressed: () { attendanceController.searchQuery.value = ''; }, ) : null, hintText: 'Search by name', filled: true, fillColor: Colors.white, border: OutlineInputBorder( borderRadius: BorderRadius.circular(10), borderSide: BorderSide(color: Colors.grey.shade300), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(10), borderSide: BorderSide(color: Colors.grey.shade300), ), ), ); }), ), ), MySpacing.width(8), // 🛠️ Filter Icon (no red dot here anymore) Container( height: 35, width: 35, decoration: BoxDecoration( color: Colors.white, border: Border.all(color: Colors.grey.shade300), borderRadius: BorderRadius.circular(10), ), child: IconButton( padding: EdgeInsets.zero, constraints: BoxConstraints(), icon: const Icon(Icons.tune, size: 20, color: Colors.black87), onPressed: () async { final result = await showModalBottomSheet>( context: context, isScrollControlled: true, backgroundColor: Colors.transparent, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(12)), ), builder: (context) => AttendanceFilterBottomSheet( controller: attendanceController, permissionController: permissionController, selectedTab: selectedTab, ), ); if (result != null) { final selectedProjectId = projectController.selectedProjectId.value; final selectedView = result['selectedTab'] as String?; if (selectedProjectId.isNotEmpty) { try { await attendanceController .fetchEmployeesByProject(selectedProjectId); await attendanceController .fetchAttendanceLogs(selectedProjectId); await attendanceController .fetchRegularizationLogs(selectedProjectId); await attendanceController .fetchProjectData(selectedProjectId); } catch (_) {} attendanceController .update(['attendance_dashboard_controller']); } if (selectedView != null && selectedView != selectedTab) { setState(() => selectedTab = selectedView); } } }, ), ), MySpacing.width(8), // ⋮ Pending Actions Menu (red dot here instead) if (selectedTab == 'attendanceLogs') Obx(() { final showPending = attendanceController.showPendingOnly.value; return Stack( children: [ Container( height: 35, width: 35, decoration: BoxDecoration( color: Colors.white, border: Border.all(color: Colors.grey.shade300), borderRadius: BorderRadius.circular(10), ), child: PopupMenuButton( padding: EdgeInsets.zero, icon: const Icon(Icons.more_vert, size: 20, color: Colors.black87), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10), ), itemBuilder: (context) => [ const PopupMenuItem( enabled: false, height: 30, child: Text( "Preferences", style: TextStyle( fontWeight: FontWeight.bold, color: Colors.grey, ), ), ), PopupMenuItem( value: 0, enabled: false, child: Obx(() => Row( children: [ const SizedBox(width: 10), const Expanded( child: Text('Show Pending Actions')), Switch.adaptive( value: attendanceController .showPendingOnly.value, activeColor: Colors.indigo, onChanged: (val) { attendanceController .showPendingOnly.value = val; Navigator.pop(context); }, ), ], )), ), ], ), ), if (showPending) Positioned( top: 6, right: 6, child: Container( height: 8, width: 8, decoration: const BoxDecoration( color: Colors.red, shape: BoxShape.circle, ), ), ), ], ); }), ], ), ); } Widget _buildNoProjectWidget() { return Center( child: Padding( padding: const EdgeInsets.all(24.0), child: MyText.titleMedium( 'No Records Found', fontWeight: 600, color: Colors.grey[600], ), ), ); } Widget _buildSelectedTabContent() { switch (selectedTab) { case 'attendanceLogs': return AttendanceLogsTab(controller: attendanceController); case 'regularizationRequests': return RegularizationRequestsTab(controller: attendanceController); case 'todaysAttendance': default: return TodaysAttendanceTab(controller: attendanceController); } } @override Widget build(BuildContext context) { return Scaffold( appBar: PreferredSize( preferredSize: const Size.fromHeight(72), child: _buildAppBar(), ), body: SafeArea( child: GetBuilder( init: attendanceController, tag: 'attendance_dashboard_controller', builder: (controller) { final selectedProjectId = projectController.selectedProjectId.value; final noProjectSelected = selectedProjectId.isEmpty; return MyRefreshIndicator( onRefresh: _refreshData, child: SingleChildScrollView( physics: const AlwaysScrollableScrollPhysics(), padding: MySpacing.zero, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ MySpacing.height(flexSpacing), _buildFilterSearchRow(), MyFlex( children: [ MyFlexItem( sizes: 'lg-12 md-12 sm-12', child: noProjectSelected ? _buildNoProjectWidget() : _buildSelectedTabContent(), ), ], ), ], ), ), ); }, ), ), ); } }