import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:shamsi_date/shamsi_date.dart'; import '../../core/sync/sync_engine.dart'; import 'hr_api.dart'; import 'hr_providers.dart'; class AttendanceScreen extends ConsumerStatefulWidget { const AttendanceScreen({super.key}); @override ConsumerState createState() => _AttendanceScreenState(); } class _AttendanceScreenState extends ConsumerState { final _reasonController = TextEditingController(); Jalali? _leaveStart; Jalali? _leaveEnd; String? _message; @override void dispose() { _reasonController.dispose(); super.dispose(); } Future _clock(bool isIn) async { final session = ref.read(hrSessionProvider); if (session == null) { setState(() => _message = 'ابتدا وارد شوید'); return; } final api = ref.read(hrApiProvider); final sync = ref.read(syncEngineProvider); try { if (isIn) { await api.clockIn(cafeId: session.cafeId, employeeId: session.employeeId); } else { await api.clockOut(cafeId: session.cafeId, employeeId: session.employeeId); } ref.invalidate(todayShiftProvider); setState(() => _message = isIn ? 'ورود ثبت شد' : 'خروج ثبت شد'); } catch (_) { sync.enqueueAttendance( action: isIn ? 'clock-in' : 'clock-out', cafeId: session.cafeId, employeeId: session.employeeId, ); setState(() => _message = 'آفلاین ذخیره شد — پس از اتصال همگام‌سازی می‌شود'); } } Future _submitLeave() async { final session = ref.read(hrSessionProvider); if (session == null || _leaveStart == null || _leaveEnd == null) return; final api = ref.read(hrApiProvider); try { await api.submitLeave( cafeId: session.cafeId, employeeId: session.employeeId, startDate: _formatDate(_leaveStart!), endDate: _formatDate(_leaveEnd!), reason: _reasonController.text, ); setState(() => _message = 'درخواست مرخصی ثبت شد'); } catch (e) { setState(() => _message = 'خطا در ثبت مرخصی'); } } String _formatDate(Jalali d) => '${d.year.toString().padLeft(4, '0')}-${d.month.toString().padLeft(2, '0')}-${d.day.toString().padLeft(2, '0')}'; @override Widget build(BuildContext context) { final shiftAsync = ref.watch(todayShiftProvider); final todayJalali = Jalali.now(); return Directionality( textDirection: TextDirection.rtl, child: Scaffold( appBar: AppBar(title: const Text('حضور و غیاب')), body: ListView( padding: const EdgeInsets.all(16), children: [ Text( 'امروز: ${todayJalali.year}/${todayJalali.month.toString().padLeft(2, '0')}/${todayJalali.day.toString().padLeft(2, '0')}', style: Theme.of(context).textTheme.titleMedium, ), const SizedBox(height: 12), shiftAsync.when( data: (shift) => Card( child: Padding( padding: const EdgeInsets.all(16), child: Text('شیفت: ${shift?['label'] ?? '—'}'), ), ), loading: () => const Center(child: CircularProgressIndicator()), error: (_, __) => const Text('شیفت امروز در دسترس نیست'), ), const SizedBox(height: 16), Row( children: [ Expanded( child: FilledButton( onPressed: () => _clock(true), child: const Text('ورود'), ), ), const SizedBox(width: 12), Expanded( child: OutlinedButton( onPressed: () => _clock(false), child: const Text('خروج'), ), ), ], ), const Divider(height: 32), Text('درخواست مرخصی', style: Theme.of(context).textTheme.titleMedium), const SizedBox(height: 8), ListTile( title: Text(_leaveStart == null ? 'از تاریخ' : _formatDate(_leaveStart!)), trailing: const Icon(Icons.calendar_today), onTap: () async { final picked = await showDatePicker( context: context, initialDate: DateTime.now(), firstDate: DateTime.now().subtract(const Duration(days: 365)), lastDate: DateTime.now().add(const Duration(days: 365)), ); if (picked != null) setState(() => _leaveStart = Jalali.fromDateTime(picked)); }, ), ListTile( title: Text(_leaveEnd == null ? 'تا تاریخ' : _formatDate(_leaveEnd!)), trailing: const Icon(Icons.calendar_today), onTap: () async { final picked = await showDatePicker( context: context, initialDate: DateTime.now(), firstDate: DateTime.now().subtract(const Duration(days: 365)), lastDate: DateTime.now().add(const Duration(days: 365)), ); if (picked != null) setState(() => _leaveEnd = Jalali.fromDateTime(picked)); }, ), TextField( controller: _reasonController, decoration: const InputDecoration(labelText: 'دلیل'), maxLines: 2, ), const SizedBox(height: 12), FilledButton(onPressed: _submitLeave, child: const Text('ثبت مرخصی')), if (_message != null) ...[ const SizedBox(height: 16), Text(_message!, style: TextStyle(color: Theme.of(context).colorScheme.primary)), ], ], ), ), ); } }