import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:generp/Models/ordersModels/commonResponse.dart'; import 'package:intl/intl.dart'; import 'package:provider/provider.dart'; import '../../Models/hrmModels/leaveApplicationLIstResponse.dart'; import '../../services/api_calling.dart'; import '../HomeScreenNotifier.dart'; class LeaveApplicationListProvider extends ChangeNotifier { leaveApplicationLIstResponse? _response; bool _isLoading = false; String? _errorMessage; leaveApplicationLIstResponse? get response => _response; bool get isLoading => _isLoading; String? get errorMessage => _errorMessage; // Filter states String _selectedStatus = "All"; String _selectedDateRange = "This Month"; DateTimeRange? _customDateRange; String get selectedStatus => _selectedStatus; String get selectedDateRange => _selectedDateRange; DateTimeRange? get customDateRange => _customDateRange; // Date controllers for filter UI final TextEditingController fromDateController = TextEditingController(); final TextEditingController toDateController = TextEditingController(); // Controllers for Add Leave form final TextEditingController fromDateField = TextEditingController(); final TextEditingController toDateField = TextEditingController(); final TextEditingController fromTimeField = TextEditingController(); final TextEditingController toTimeField = TextEditingController(); final TextEditingController reasonController = TextEditingController(); // Status options for filter final List statusOptions = ["All", "Requested", "Approved", "Rejected"]; // Date range options for filter final List dateRangeOptions = [ "All", "Today", "Yesterday", "This Month", "Past 7 days", "Last Month", "Custom", ]; // Loading state for Add Leave bool _isSubmitting = false; bool get isSubmitting => _isSubmitting; CommonResponse? _addResponse; CommonResponse? get addResponse => _addResponse; DateTime? _selectedDate; DateTime? get selectedDate => _selectedDate; /// Fetch leave application list with filters Future fetchLeaveApplications(BuildContext context, mode, {String? status, String? dateRange, DateTimeRange? customRange}) async { _isLoading = true; _errorMessage = null; notifyListeners(); try { final provider = Provider.of(context, listen: false); final filterStatus = status ?? _selectedStatus; final filterDateRange = dateRange ?? _selectedDateRange; final filterCustomRange = customRange ?? _customDateRange; final dateParams = _getDateRangeParams(filterDateRange, filterCustomRange); final result = await ApiCalling.leaveApplicationListAPI( provider.session, provider.empId, dateParams['from']!, dateParams['to']!, mode ); debugPrint( 'Fetching leave applications from: ${dateParams['from']} to: ${dateParams['to']}'); if (result != null) { _response = result; if (filterStatus != "All" && _response?.requestList != null) { _response!.requestList = _response!.requestList! .where((item) => item.status?.toLowerCase() == filterStatus.toLowerCase()) .toList(); } if (_response?.requestList == null || _response!.requestList!.isEmpty) { _errorMessage = "No leave applications found!"; } } else { _errorMessage = "No data found!"; } } catch (e) { _errorMessage = "Error: $e"; debugPrint('Error fetching leave applications: $e'); } _isLoading = false; notifyListeners(); } /// --- Add Leave Request --- Future addLeaveRequest( BuildContext context, { required String fromDate, required String fromTime, required String toDate, required String toTime, required String leaveType, required String reason, }) async { _isSubmitting = true; _errorMessage = null; _addResponse = null; notifyListeners(); try { final homeProvider = Provider.of(context, listen: false); final result = await ApiCalling.leaveRequestAddAPI( homeProvider.session, homeProvider.empId, fromDate, fromTime, toDate, toTime, leaveType, reason, ); if (result != null) { _addResponse = result; if (result.error != null && result.error!.isNotEmpty) { _errorMessage = result.error; } } else { _errorMessage = "Failed to submit leave request!"; } } catch (e) { _errorMessage = "Error submitting leave request: $e"; } _isSubmitting = false; notifyListeners(); } /// Set status filter void setStatusFilter(String status) { _selectedStatus = status; notifyListeners(); } /// Set date range filter void setDateRangeFilter(String dateRange, {DateTimeRange? customRange}) { _selectedDateRange = dateRange; if (customRange != null) { _customDateRange = customRange; fromDateController.text = _formatDate(customRange.start); toDateController.text = _formatDate(customRange.end); } notifyListeners(); } /// Clear all filters void clearFilters() { _selectedStatus = "All"; _selectedDateRange = "This Month"; _customDateRange = null; fromDateController.clear(); toDateController.clear(); notifyListeners(); } /// Reset form and data void resetForm() { _response = null; _errorMessage = null; clearFilters(); notifyListeners(); } /// Get date range parameters for API Map _getDateRangeParams( String dateRange, DateTimeRange? customRange) { final now = DateTime.now(); final formatter = DateFormat("dd MMM yyyy"); late DateTime from; late DateTime to; switch (dateRange) { case "All": from = DateTime(now.year - 1); to = now; break; case "Today": from = now; to = now; break; case "Yesterday": from = now.subtract(const Duration(days: 1)); to = now.subtract(const Duration(days: 1)); break; case "This Month": from = DateTime(now.year, now.month, 1); to = DateTime(now.year, now.month + 1, 0); break; case "Past 7 days": from = now.subtract(const Duration(days: 6)); to = now; break; case "Last Month": from = DateTime(now.year, now.month - 1, 1); to = DateTime(now.year, now.month, 0); break; case "Custom": if (customRange != null) { from = customRange.start; to = customRange.end; } else { from = now.subtract(const Duration(days: 30)); to = now; } break; default: from = now; to = now; } return { "from": formatter.format(from), "to": formatter.format(to), }; } /// Format date String _formatDate(DateTime date) { return DateFormat("dd MMM yyyy").format(date); } /// Show Cupertino DatePicker for leave form void showDatePickerDialog(BuildContext context, {bool isFromDate = true}) { DateTime? currentDate = DateTime.now(); showCupertinoModalPopup( context: context, builder: (BuildContext context) => Container( height: 250, padding: const EdgeInsets.only(top: 6.0), margin: EdgeInsets.only( bottom: MediaQuery.of(context).viewInsets.bottom, ), color: CupertinoColors.systemBackground.resolveFrom(context), child: SafeArea( top: false, child: Column( children: [ SizedBox( height: 55, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ CupertinoButton( child: const Text("Cancel", style: TextStyle(color: Colors.blue)), onPressed: () => Navigator.pop(context), ), CupertinoButton( child: const Text("Done", style: TextStyle(color: Colors.blue)), onPressed: () { if (isFromDate) { fromDateField.text = _formatDate(currentDate ?? DateTime.now()); } else { toDateField.text = _formatDate(currentDate ?? DateTime.now()); } Navigator.pop(context); }, ), ], ), ), Expanded( child: CupertinoDatePicker( dateOrder: DatePickerDateOrder.dmy, initialDateTime: currentDate, mode: CupertinoDatePickerMode.date, onDateTimeChanged: (DateTime newDate) { currentDate = newDate; }, ), ), ], ), ), ), ); } /// Apply filters void applyFilters(BuildContext context,mode) { fetchLeaveApplications( context, mode, status: _selectedStatus, dateRange: _selectedDateRange, customRange: _customDateRange, ); } /// Export List> prepareExportData() { final headers = [ 'ID', 'Applied Date', 'From Date', 'To Date', 'Leave Type', 'Status', 'Reason', ]; if (_response?.requestList == null) { return [headers]; } final rows = _response!.requestList!.map((item) => [ item.id ?? '', item.appliedDate ?? '', item.fromPeriod ?? '', item.toPeriod ?? '', '', // leave type if available item.status ?? '', '', // reason if available ]).toList(); return [headers, ...rows]; } /// Set selected single date (if needed) void setSelectedDate(DateTime date) { _selectedDate = date; notifyListeners(); } }