import 'dart:io'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:generp/Models/hrmModels/tourExpensesAddViewResponse.dart'; import 'package:intl/intl.dart'; import 'package:provider/provider.dart'; import '../../Models/hrmModels/tourExpensesListResponse.dart'; import '../../services/api_calling.dart'; import '../HomeScreenNotifier.dart'; class TourExpensesProvider extends ChangeNotifier { tourExpensesListResponse? _response; bool _isLoading = false; String? _errorMessage; tourExpensesListResponse? get response => _response; bool get isLoading => _isLoading; String? get errorMessage => _errorMessage; tourExpensesAddViewResponse? _response2; tourExpensesAddViewResponse? get response2 => _response2; List get daAmountList => _response2?.daAmount?.map((e) => e.toString()).toList() ?? []; List get tourTypeList => _response2?.tourType ?? []; List get travelTypeList => _response2?.travelType ?? []; // Controllers for Add form final TextEditingController fromDateField = TextEditingController(); final TextEditingController toDateField = TextEditingController(); final TextEditingController dateController = TextEditingController(); DateTime? _date; DateTime? _fromDate; DateTime? _toDate; /// Format date (yyyy-MM-dd) String _formatDate(DateTime date) { return DateFormat('yyyy-MM-dd').format(date); } /// Set single date void setDate(DateTime newDate) { _date = newDate; dateController.text = _formatDate(newDate); notifyListeners(); } /// Fetch tour expenses list Future fetchTourExpenses(BuildContext context, String pageNumber, {bool append = false}) async { _isLoading = true; _errorMessage = null; notifyListeners(); try { final provider = Provider.of(context, listen: false); final result = await ApiCalling.tourExpensesListAPI( provider.empId, provider.session, pageNumber, ); debugPrint( 'empId: ${provider.empId}, session: ${provider.session}, pageNumber: $pageNumber'); if (result != null) { if (append && _response != null && _response!.tourList != null) { // Append with deduplication final existingIds = _response!.tourList!.map((e) => e.id).toSet(); final newItems = (result.tourList ?? []) .where((item) => !existingIds.contains(item.id)) .toList(); _response!.tourList!.addAll(newItems); } else { // First page or refresh _response = result; } } else { _errorMessage = "No data found!"; } } catch (e) { _errorMessage = "Error: $e"; } _isLoading = false; notifyListeners(); } Future fetchTourExpensesAddView(BuildContext context, String tourBillId) async { _isLoading = true; _errorMessage = null; notifyListeners(); try { final provider = Provider.of(context, listen: false); final result = await ApiCalling.tourExpensesAddViewAPI( provider.empId, provider.session, tourBillId, ); debugPrint('empId: ${provider.empId}, session: ${provider.session}, tourBillId: $tourBillId'); if (result != null) { _response2 = result; } else { _errorMessage = "No data found!"; } } catch (e) { _errorMessage = "Error: $e"; } _isLoading = false; notifyListeners(); } Future addTourBill({ required BuildContext context, required String placeOfVisit, required String daAmount, required String tourType, required String tourDate, required List> travelExpenses, required List> hotelExpenses, required List> otherExpenses, List? travelImages, List? hotelImages, List? otherImages, }) async { _isLoading = true; _errorMessage = null; notifyListeners(); try { final homeProvider = Provider.of(context, listen: false); if ((homeProvider.session ?? "").isEmpty || (homeProvider.empId ?? "").isEmpty) { _errorMessage = "Invalid session or employee ID"; _isLoading = false; notifyListeners(); return false; } debugPrint("Submitting Tour Bill => " "place: $placeOfVisit, da: $daAmount, type: $tourType, " "date: $tourDate, travelExp: ${travelExpenses.length}, " "hotelExp: ${hotelExpenses.length}, " "otherExp: ${otherExpenses.length}, " "travelImages: ${travelImages?.length}, " "hotelImages: ${hotelImages?.length}," "otherImages: ${otherImages?.length}"); final result = await ApiCalling.addTourBillAPI( sessionId: homeProvider.session ?? "", empId: homeProvider.empId ?? "", placeOfVisit: placeOfVisit, daAmount: daAmount, tourType: tourType, tourDate: tourDate, travelExpenses: travelExpenses, hotelExpenses: hotelExpenses, otherExpenses: otherExpenses, travelImages: travelImages, hotelImages: hotelImages, otherImages: otherImages, ); if (result != null) { debugPrint(" Tour Bill Added Successfully"); _isLoading = false; notifyListeners(); return true; } else { _errorMessage = "Failed to add Tour Bill"; _isLoading = false; notifyListeners(); return false; } } catch (e) { _errorMessage = "Error: $e"; _isLoading = false; notifyListeners(); return false; } } /// Show Cupertino DatePicker for leave form /// Show Cupertino DatePicker for leave form Future showDatePickerDialog(BuildContext context, {bool isFromDate = true}) async { DateTime currentDate = DateTime.now(); DateTime? pickedDate; await 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: () { pickedDate = currentDate; if (isFromDate) { fromDateField.text = _formatDate(pickedDate!); } else { toDateField.text = _formatDate(pickedDate!); } Navigator.pop(context); }, ), ], ), ), Expanded( child: CupertinoDatePicker( dateOrder: DatePickerDateOrder.dmy, initialDateTime: currentDate, mode: CupertinoDatePickerMode.date, onDateTimeChanged: (DateTime newDate) { currentDate = newDate; }, ), ), ], ), ), ), ); return pickedDate; } }