import 'dart:async'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'package:my_attendance/screens/history_screen.dart'; import 'package:my_attendance/screens/leave_request_screen.dart'; import 'package:my_attendance/screens/correction_screen.dart'; import 'package:my_attendance/services/attendance_service.dart'; import 'package:my_attendance/services/settings_service.dart'; import 'package:my_attendance/widgets/settings_dialog.dart'; import 'package:my_attendance/widgets/info_dialog.dart'; import 'package:provider/provider.dart'; import 'package:my_attendance/models/attendance_entry.dart'; import 'package:my_attendance/widgets/stats_dialog.dart'; class HomeScreen extends StatefulWidget { const HomeScreen({super.key}); @override State createState() => _HomeScreenState(); } class _HomeScreenState extends State { Timer? _timer; @override void initState() { super.initState(); // Periodically update the UI to check if logout is available _timer = Timer.periodic(const Duration(seconds: 1), (timer) { if (mounted) { setState(() {}); } }); } @override void dispose() { _timer?.cancel(); super.dispose(); } void _showSettingsDialog() { showDialog(context: context, builder: (context) => const SettingsDialog()); } @override Widget build(BuildContext context) { final attendanceService = Provider.of(context); final settingsService = Provider.of(context); final todayEntry = attendanceService.todayEntry; final isLoggedIn = todayEntry != null && todayEntry.entryType == EntryType.work && todayEntry.logoutTime == null; final hasLoggedOut = todayEntry != null && todayEntry.entryType == EntryType.work && todayEntry.logoutTime != null; final isDayFinalized = todayEntry != null && (todayEntry.entryType == EntryType.leave || todayEntry.entryType == EntryType.wfh); bool canLogOut = false; if (isLoggedIn) { final workDuration = settingsService.settings.dailyWorkDuration; if (todayEntry.loginTime != null) { final timeWorked = DateTime.now().difference(todayEntry.loginTime!); canLogOut = timeWorked >= workDuration; } } return Scaffold( appBar: AppBar( title: const Text('My Attendance'), actions: [ IconButton( icon: const Icon(Icons.history), onPressed: () => Navigator.of(context).pushNamed(HistoryScreen.routeName), ), IconButton( icon: const Icon(Icons.bar_chart), onPressed: () async { await Provider.of( context, listen: false, ).calculateStats(); showDialog(context: context, builder: (_) => const StatsDialog()); }, ), IconButton( icon: const Icon(Icons.edit_calendar_outlined), onPressed: () => Navigator.of(context).pushNamed(CorrectionScreen.routeName), ), PopupMenuButton( icon: const Icon(Icons.settings), onSelected: (value) { if (value == 'working_hour') { _showSettingsDialog(); } else if (value == 'info') { showDialog( context: context, builder: (context) => const InfoDialog(), ); } }, itemBuilder: (context) => [ const PopupMenuItem( value: 'working_hour', child: Text('Working Hour'), ), const PopupMenuItem( value: 'info', child: Text('Info'), ), ], ), ], ), body: SafeArea( child: Center( child: Padding( padding: const EdgeInsets.all(24.0), child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ if (attendanceService.isLoading && todayEntry == null) const Center(child: CircularProgressIndicator()) else Container( padding: const EdgeInsets.all(24), decoration: BoxDecoration( gradient: LinearGradient( colors: [ Theme.of(context).colorScheme.surfaceContainerHighest, Theme.of(context).colorScheme.surfaceContainer, ], begin: Alignment.topLeft, end: Alignment.bottomRight, ), borderRadius: BorderRadius.circular(16), ), child: isLoggedIn ? _buildLoggedInUI( context, todayEntry.loginTime!, settingsService.settings.dailyWorkDuration, ) : hasLoggedOut ? _buildLoggedOutUI(context, todayEntry) : isDayFinalized ? _buildFinalizedUI(context, todayEntry) : _buildNotLoggedInUI(context), ), const SizedBox(height: 32), ElevatedButton.icon( onPressed: isLoggedIn || hasLoggedOut || isDayFinalized ? null : attendanceService.logIn, style: ElevatedButton.styleFrom( padding: const EdgeInsets.symmetric(vertical: 16), textStyle: const TextStyle( fontSize: 18, fontWeight: FontWeight.bold, ), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), icon: const Icon(Icons.login), label: const Text('Log In'), ), const SizedBox(height: 16), ElevatedButton.icon( onPressed: isLoggedIn && canLogOut ? attendanceService.logOut : null, style: ElevatedButton.styleFrom( padding: const EdgeInsets.symmetric(vertical: 16), backgroundColor: Theme.of(context).colorScheme.error, foregroundColor: Theme.of(context).colorScheme.onError, textStyle: const TextStyle( fontSize: 18, fontWeight: FontWeight.bold, ), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), icon: const Icon(Icons.logout), label: const Text('Log Out'), ), const SizedBox(height: 24), const Divider(), const SizedBox(height: 24), Row( children: [ Expanded( child: OutlinedButton.icon( onPressed: isDayFinalized || isLoggedIn || hasLoggedOut ? null : () { Navigator.of( context, ).pushNamed(LeaveRequestScreen.routeName); }, icon: const Icon(Icons.beach_access), label: const Text('Request Leave'), style: OutlinedButton.styleFrom( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), ), ), const SizedBox(width: 16), Expanded( child: OutlinedButton.icon( onPressed: isDayFinalized || isLoggedIn || hasLoggedOut ? null : attendanceService.markAsWfh, icon: const Icon(Icons.home_work), label: const Text('Work From Home'), style: OutlinedButton.styleFrom( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), ), ), ], ), ], ), ), ), ), ); } Widget _buildLoggedInUI( BuildContext context, DateTime loginTime, Duration workDuration, ) { final now = DateTime.now(); final timeWorked = now.difference(loginTime); final remaining = workDuration - timeWorked; return Column( children: [ Text( 'Logged in at: ${DateFormat.jm().format(loginTime)}', style: Theme.of(context).textTheme.titleLarge, textAlign: TextAlign.center, ), const SizedBox(height: 24), Text('Time Worked', style: Theme.of(context).textTheme.bodyMedium), Text( _formatDuration(timeWorked), style: Theme.of( context, ).textTheme.displaySmall?.copyWith(fontWeight: FontWeight.bold), ), const SizedBox(height: 16), if (remaining > Duration.zero) ...[ Text('Time Remaining', style: Theme.of(context).textTheme.bodyMedium), Text( _formatDuration(remaining), style: Theme.of(context).textTheme.headlineMedium, ), ], ], ); } Widget _buildLoggedOutUI(BuildContext context, AttendanceEntry entry) { if (entry.loginTime == null || entry.logoutTime == null) { return const Text("Data Error"); // Should not happen for this UI state } final totalWork = entry.logoutTime!.difference(entry.loginTime!); return Column( children: [ Text( 'Checked out for today.', style: Theme.of(context).textTheme.titleLarge, textAlign: TextAlign.center, ), const SizedBox(height: 16), Text('Total Work', style: Theme.of(context).textTheme.bodyMedium), Text( _formatDuration(totalWork), style: Theme.of( context, ).textTheme.displaySmall?.copyWith(fontWeight: FontWeight.bold), ), ], ); } Widget _buildFinalizedUI(BuildContext context, AttendanceEntry entry) { String message = 'Status for today:'; String status = ''; if (entry.entryType == EntryType.wfh) { status = 'Work From Home'; } else if (entry.entryType == EntryType.leave) { switch (entry.leaveType) { case LeaveType.sick: status = 'On Sick Leave'; break; case LeaveType.annual: status = 'On Annual Leave'; break; case LeaveType.nationalHoliday: status = 'National Holiday'; break; case LeaveType.companyWfh: status = 'Company WFH'; break; default: status = 'On Leave'; } } return Column( children: [ Text( message, style: Theme.of(context).textTheme.titleLarge, textAlign: TextAlign.center, ), const SizedBox(height: 16), Text( status, style: Theme.of(context).textTheme.headlineSmall?.copyWith( fontWeight: FontWeight.bold, color: Theme.of(context).colorScheme.primary, ), textAlign: TextAlign.center, ), ], ); } Widget _buildNotLoggedInUI(BuildContext context) { return Text( 'Not logged in for today.', style: Theme.of(context).textTheme.headlineMedium, textAlign: TextAlign.center, ); } } String _formatDuration(Duration d) { d = Duration(seconds: d.inSeconds); // Truncate to seconds final hours = d.inHours.toString().padLeft(2, '0'); final minutes = d.inMinutes.remainder(60).toString().padLeft(2, '0'); final seconds = d.inSeconds.remainder(60).toString().padLeft(2, '0'); return '$hours:$minutes:$seconds'; }