From 563f808dfc0c6a6129f172ae2767b0fe5e5a0a54 Mon Sep 17 00:00:00 2001 From: venbaittech Date: Thu, 12 Jun 2025 18:20:54 +0530 Subject: [PATCH] changes --- lib/Screens/allTrips/list_all_plans.dart | 63 ++- lib/Screens/itnerary/insurance.dart | 368 +++++++++++++++--- .../create_user/create_user.dart | 2 + .../create_user/personal_details.dart | 2 +- .../create_user/traveller_details.dart | 13 +- 5 files changed, 370 insertions(+), 78 deletions(-) diff --git a/lib/Screens/allTrips/list_all_plans.dart b/lib/Screens/allTrips/list_all_plans.dart index 86fb2a6..84235dd 100644 --- a/lib/Screens/allTrips/list_all_plans.dart +++ b/lib/Screens/allTrips/list_all_plans.dart @@ -651,6 +651,16 @@ class _ListAllPlansState extends State { ), ), columns: [ + DataColumn( + label: Text( + 'S.NO', + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, + ), + ), + ), + DataColumn( label: Text( 'Trip ID', @@ -669,6 +679,16 @@ class _ListAllPlansState extends State { ), ), ), + + DataColumn( + label: Text( + 'Trip Type', + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, + ), + ), + ), DataColumn( label: Text( 'Emp Code', @@ -687,15 +707,7 @@ class _ListAllPlansState extends State { ), ), ), - DataColumn( - label: Text( - 'Trip Type', - style: GoogleFonts.poppins( - fontSize: 13, - fontWeight: FontWeight.w600, - ), - ), - ), + DataColumn( label: Text( 'Created On', @@ -725,9 +737,21 @@ class _ListAllPlansState extends State { ), ], rows: - paginatedPlans.map((plan) { + // paginatedPlans.map((plan) + paginatedPlans.asMap().entries.map((entry) { + int index = entry.key; + var plan = entry.value; return DataRow( cells: [ + DataCell( + Text( + "${index + 1}", + style: TextStyle( + fontSize: 13, + fontFamily: "Inter", + ), + ), + ), DataCell( Text( plan.planId, @@ -748,6 +772,15 @@ class _ListAllPlansState extends State { overflow: TextOverflow.ellipsis, ), ), + DataCell( + Text( + plan.tripType, + style: TextStyle( + fontSize: 13, + fontFamily: "Inter", + ), + ), + ), DataCell( Text( plan.employeeCode ?? " - ", @@ -768,15 +801,7 @@ class _ListAllPlansState extends State { ), ), ), - DataCell( - Text( - plan.tripType, - style: TextStyle( - fontSize: 13, - fontFamily: "Inter", - ), - ), - ), + DataCell( Text( _formatDate(plan.createdOn), diff --git a/lib/Screens/itnerary/insurance.dart b/lib/Screens/itnerary/insurance.dart index f46fc26..3784e7a 100644 --- a/lib/Screens/itnerary/insurance.dart +++ b/lib/Screens/itnerary/insurance.dart @@ -45,10 +45,13 @@ class _InsuranceScreenState extends State { late TextEditingController _tripTypeController = TextEditingController(); late TextEditingController _startDateController = TextEditingController(); + late TextEditingController _dateOfBirthController = TextEditingController(); late TextEditingController _endDateController = TextEditingController(); late TextEditingController _insuranceCommentsController = TextEditingController(); late TextEditingController _nomineeController = TextEditingController(); + late TextEditingController _nomineerelationController = + TextEditingController(); bool _isHotelNameFocused = false; bool _startDateFocus = false; @@ -65,9 +68,12 @@ class _InsuranceScreenState extends State { Map data = { "type_of_insurance": selectedInsuranceType, "start_date": _startDateController.text, + "end_date": _endDateController.text, "comments": _insuranceCommentsController.text, "nominee_name": _nomineeController.text, + "nominee_dob": _dateOfBirthController.text, + "nominee_relationship": _nomineerelationController.text, "created_by": widget.loginUser, "updated_by": widget.loginUser, }; @@ -125,6 +131,13 @@ class _InsuranceScreenState extends State { _endDateController = TextEditingController( text: widget.selectedItem?['end_date'] ?? "", ); + + _dateOfBirthController = TextEditingController( + text: widget.selectedItem?['nominee_dob'] ?? "", + ); + _nomineerelationController = TextEditingController( + text: widget.selectedItem?['nominee_relationship'] ?? "", + ); _nomineeController = TextEditingController( text: widget.selectedItem?['nominee_name'] ?? "", ); @@ -147,15 +160,24 @@ class _InsuranceScreenState extends State { // ✅ Only set controller after value is updated // final parsedDate = // DateTime.tryParse(flightFirstTripDateNotifier.value ?? ''); - final parsedDate = DateFormat("dd-MM-yyyy").parse(flightFirstTripDateNotifier.value ?? ''); - if (parsedDate != null) { _startDateController.text = DateFormat('dd-MM-yyyy').format(parsedDate); } + final parsedDate = DateFormat( + "dd-MM-yyyy", + ).parse(flightFirstTripDateNotifier.value ?? ''); + if (parsedDate != null) { + _startDateController.text = DateFormat('dd-MM-yyyy').format(parsedDate); + } - final parsedEndDate = DateFormat("dd-MM-yyyy").parse(flightLastTripDateNotifier.value ?? ''); - if (parsedEndDate != null) { _endDateController.text = DateFormat('dd-MM-yyyy').format(parsedEndDate); } + final parsedEndDate = DateFormat( + "dd-MM-yyyy", + ).parse(flightLastTripDateNotifier.value ?? ''); + if (parsedEndDate != null) { + _endDateController.text = DateFormat( + 'dd-MM-yyyy', + ).format(parsedEndDate); + } print("parsedDate $parsedDate"); print("parsedEndDate $parsedEndDate"); - }); } @@ -203,6 +225,9 @@ class _InsuranceScreenState extends State { "type_of_insurance", "start_date", "end_date", + "nominee_name", + "nominee_dob", + "nominee_relationship", ]; // Check validation for each field @@ -311,6 +336,7 @@ class _InsuranceScreenState extends State { List> rowBuilders = [ // _builClassType(isDesktop), _buildSecondRow(isDesktop), + _buildSecondSubRow(isDesktop), ]; return [ @@ -752,7 +778,7 @@ class _InsuranceScreenState extends State { child: DropdownSearch>( items: purposeList.cast>(), selectedItem: purposeList.firstWhere( - (item) => item['dropdown_key'] == selectedInsuranceType, + (item) => item['dropdown_key'] == selectedInsuranceType, orElse: () => {}, ), itemAsString: (item) => item['dropdown_value'] ?? '', @@ -779,7 +805,10 @@ class _InsuranceScreenState extends State { dropdownDecoratorProps: const DropDownDecoratorProps( dropdownSearchDecoration: InputDecoration( border: InputBorder.none, - contentPadding: EdgeInsets.symmetric(horizontal: 10,vertical: 10,), + contentPadding: EdgeInsets.symmetric( + horizontal: 10, + vertical: 10, + ), ), ), dropdownBuilder: (context, selectedItem) { @@ -801,58 +830,59 @@ class _InsuranceScreenState extends State { ); }, onChanged: - purposeList.isNotEmpty - ? (Map? newValue) { - setState(() { - selectedInsuranceType= newValue?['dropdown_key']; - print("selected Insurance Type: ${selectedInsuranceType}"); - }); - } - : null, - ), - ), - ), - - ], - ), - - if (isDesktop) Spacer() else SizedBox(height: 8), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Nominee", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74), - ), - ), - SizedBox(height: 5), - CustomTextFieldWrapper( - isFocused: _nomineeFocus, - isDesktop: isDesktop, - width: isDesktop ? MediaQuery.of(context).size.width * 0.15 : null, - // width: isDesktop ? MediaQuery.of(context).size.width * 0.34 : null, - child: SizedBox( - height: 40, - child: TextField( - focusNode: _nomineeFocusNode, - controller: _nomineeController, - style: TextStyle(fontSize: 12), - decoration: InputDecoration( - labelText: "Nominee", - labelStyle: TextStyle(fontSize: 12, color: Colors.grey), - floatingLabelBehavior: FloatingLabelBehavior.never, - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric(vertical: 16), - // contentPadding: EdgeInsets.symmetric(horizontal: 1,vertical: 1), - ), + purposeList.isNotEmpty + ? (Map? newValue) { + setState(() { + selectedInsuranceType = newValue?['dropdown_key']; + print( + "selected Insurance Type: ${selectedInsuranceType}", + ); + }); + } + : null, ), ), ), ], ), + + // if (isDesktop) Spacer() else SizedBox(height: 8), + // Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // Text( + // "Nominee", + // style: GoogleFonts.poppins( + // fontSize: 12, + // fontWeight: FontWeight.w600, + // color: Color(0xFF575A74), + // ), + // ), + // SizedBox(height: 5), + // CustomTextFieldWrapper( + // isFocused: _nomineeFocus, + // isDesktop: isDesktop, + // width: isDesktop ? MediaQuery.of(context).size.width * 0.15 : null, + // // width: isDesktop ? MediaQuery.of(context).size.width * 0.34 : null, + // child: SizedBox( + // height: 40, + // child: TextField( + // focusNode: _nomineeFocusNode, + // controller: _nomineeController, + // style: TextStyle(fontSize: 12), + // decoration: InputDecoration( + // labelText: "Nominee", + // labelStyle: TextStyle(fontSize: 12, color: Colors.grey), + // floatingLabelBehavior: FloatingLabelBehavior.never, + // border: InputBorder.none, + // contentPadding: EdgeInsets.symmetric(vertical: 16), + // // contentPadding: EdgeInsets.symmetric(horizontal: 1,vertical: 1), + // ), + // ), + // ), + // ), + // ], + // ), if (isDesktop) Spacer() else SizedBox(height: 8), Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -869,7 +899,7 @@ class _InsuranceScreenState extends State { CustomTextFieldWrapper( isFocused: _startDateFocus, isDesktop: isDesktop, - width: isDesktop ? MediaQuery.of(context).size.width * 0.11 : null, + width: isDesktop ? MediaQuery.of(context).size.width * 0.16 : null, child: SizedBox( height: 40, child: GestureDetector( @@ -928,7 +958,7 @@ class _InsuranceScreenState extends State { CustomTextFieldWrapper( isFocused: _endDateFocus, isDesktop: isDesktop, - width: isDesktop ? MediaQuery.of(context).size.width * 0.11 : null, + width: isDesktop ? MediaQuery.of(context).size.width * 0.16 : null, child: SizedBox( height: 40, child: GestureDetector( @@ -982,7 +1012,8 @@ class _InsuranceScreenState extends State { errorMessages["end_date"]!, style: const TextStyle(color: Colors.red, fontSize: 12), maxLines: 2, // Allow it to wrap onto two lines - overflow: TextOverflow.ellipsis, // Add ellipsis if it still overflows + overflow: + TextOverflow.ellipsis, // Add ellipsis if it still overflows ), ], ], @@ -991,6 +1022,229 @@ class _InsuranceScreenState extends State { ]; } + List _buildSecondSubRow(bool isDesktop) { + List purposeList = + widget.apiData?['insurance_type_of_insurance'] ?? []; + // selectedInsuranceType = purposeList.isNotEmpty ? purposeList.first['dropdown_value'] : null; + + List> dropdownItems = + purposeList + .map( + (item) => DropdownMenuItem( + value: item['dropdown_key'], + child: Text(item['dropdown_value']), + ), + ) + .toList(); + + if (dropdownItems.isEmpty) { + dropdownItems.add( + DropdownMenuItem( + value: null, + child: Text( + "No options available", + style: TextStyle(color: Colors.grey), + ), + ), + ); + } + + // Default selected value + selectedInsuranceType ??= + dropdownItems.isNotEmpty ? dropdownItems.first.value : null; + + // ---------------------------------------------------------------- + + DateTime? _selectedCheckDOBDate; + + Future _selectCheckDOBOutDate(BuildContext context) async { + DateTime now = DateTime.now(); + DateTime today = DateTime(now.year, now.month, now.day); + + // Parse date from notifier if available, else use today + DateTime initialDate; + + initialDate = today; + + final pickedDate = await showDatePicker( + context: context, + initialDate: initialDate, + firstDate: DateTime(1900), + lastDate: today, + initialEntryMode: DatePickerEntryMode.calendarOnly, + ); + + // DateTime? pickedDate = await showDatePicker( + // context: context, + // initialDate: _selectedCheckOutDate != null && + // _selectedCheckOutDate!.isAfter(today) + // ? _selectedCheckOutDate! + // : today, + // firstDate: today, + // lastDate: DateTime(2100), + // ); + + if (pickedDate != null && pickedDate != _selectedCheckDOBDate) { + setState(() { + _selectedCheckDOBDate = pickedDate; + _dateOfBirthController.text = DateFormat( + 'dd-MM-yyyy', + ).format(pickedDate); + }); + } + } + + return [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Nominee*", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), + ), + SizedBox(height: 5), + CustomTextFieldWrapper( + isFocused: _nomineeFocus, + isDesktop: isDesktop, + // width: isDesktop ? MediaQuery.of(context).size.width * 0.15 : null, + width: isDesktop ? MediaQuery.of(context).size.width * 0.31 : null, + // width: isDesktop ? MediaQuery.of(context).size.width * 0.34 : null, + child: SizedBox( + height: 40, + child: TextField( + focusNode: _nomineeFocusNode, + controller: _nomineeController, + style: TextStyle(fontSize: 12), + decoration: InputDecoration( + labelText: "Nominee", + labelStyle: TextStyle(fontSize: 12, color: Colors.grey), + floatingLabelBehavior: FloatingLabelBehavior.never, + border: InputBorder.none, + contentPadding: EdgeInsets.symmetric(vertical: 16), + // contentPadding: EdgeInsets.symmetric(horizontal: 1,vertical: 1), + ), + ), + ), + ), + if (errorMessages["nominee_name"] != null) ...[ + SizedBox(height: 5), // Space before error message + Text("Required", style: TextStyle(color: Colors.red, fontSize: 12)), + ], + ], + ), + if (isDesktop) Spacer() else SizedBox(height: 8), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Date of Birth*", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w500, + color: Color(0xFF575A74), + ), + ), + SizedBox(height: 5), + CustomTextFieldWrapper( + isFocused: _startDateFocus, + isDesktop: isDesktop, + width: isDesktop ? MediaQuery.of(context).size.width * 0.16 : null, + // width: isDesktop ? MediaQuery.of(context).size.width * 0.11 : null, + child: SizedBox( + height: 40, + child: GestureDetector( + onTap: () async { + await _selectCheckDOBOutDate(context); + // await _selectDateOfBirth(context); + if (_dateOfBirthController.text.isNotEmpty) { + setState(() { + errorMessages.remove( + "nominee_dob", + ); // Removes the key completely + }); + } + }, + child: AbsorbPointer( + child: TextField( + focusNode: _startDateFocusNode, + controller: _dateOfBirthController, + readOnly: true, + style: const TextStyle(fontSize: 12), + decoration: const InputDecoration( + labelText: "Select ", + labelStyle: TextStyle(fontSize: 12, color: Colors.grey), + floatingLabelBehavior: FloatingLabelBehavior.never, + border: InputBorder.none, + contentPadding: EdgeInsets.symmetric(vertical: 16), + suffixIcon: Icon( + Icons.calendar_today, + size: 16, + color: Colors.grey, + ), + ), + ), + ), + ), + ), + ), + if (errorMessages["nominee_dob"] != null) ...[ + SizedBox(height: 5), // Space before error message + Text("Required", style: TextStyle(color: Colors.red, fontSize: 12)), + ], + ], + ), + if (isDesktop) Spacer() else SizedBox(height: 8), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Relationship*", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w500, + color: Color(0xFF575A74), + ), + ), + SizedBox(height: 5), + + // + CustomTextFieldWrapper( + isFocused: false, + isDesktop: isDesktop, + width: isDesktop ? MediaQuery.of(context).size.width * 0.16 : null, + // width: isDesktop ? MediaQuery.of(context).size.width * 0.31 : null, + // width: isDesktop ? MediaQuery.of(context).size.width * 0.34 : null, + child: SizedBox( + height: 40, + child: TextField( + // focusNode: _nomineeFocusNode, + controller: _nomineerelationController, + style: TextStyle(fontSize: 12), + decoration: InputDecoration( + labelText: "Nominee Relationship", + labelStyle: TextStyle(fontSize: 12, color: Colors.grey), + floatingLabelBehavior: FloatingLabelBehavior.never, + border: InputBorder.none, + contentPadding: EdgeInsets.symmetric(vertical: 16), + // contentPadding: EdgeInsets.symmetric(horizontal: 1,vertical: 1), + ), + ), + ), + ), + if (errorMessages["nominee_relationship"] != null) ...[ + SizedBox(height: 5), // Space before error message + Text("Required", style: TextStyle(color: Colors.red, fontSize: 12)), + ], + ], + ), + if (isDesktop) Spacer() else SizedBox(height: 8), + ]; + } + List _buildThirdRow(bool isDesktop) { return [ Column( diff --git a/lib/Screens/userManagement/create_user/create_user.dart b/lib/Screens/userManagement/create_user/create_user.dart index a7bfba0..9036a43 100644 --- a/lib/Screens/userManagement/create_user/create_user.dart +++ b/lib/Screens/userManagement/create_user/create_user.dart @@ -153,7 +153,9 @@ class _CreateUserFormDetialsState extends State { "address": controllers["address"]?.text, "gender": selectedGender, // "gender": personalDetailsKey.currentState?.selectedGender, + // "agent_supported_service_ids": selectedServiceIds, "agent_supported_service_ids": selectedServiceIds, + "postal_code": controllers["postalCode"]?.text, "country_code": selectedCountry, "employee_code": controllers["employeeCode"]?.text, diff --git a/lib/Screens/userManagement/create_user/personal_details.dart b/lib/Screens/userManagement/create_user/personal_details.dart index 8e0b572..d972825 100644 --- a/lib/Screens/userManagement/create_user/personal_details.dart +++ b/lib/Screens/userManagement/create_user/personal_details.dart @@ -451,7 +451,7 @@ class PersonalDetailsState extends State { } else { selectedServiceIds.add({"service_id": serviceId}); } - + print("selectedServiceIdsUser --- $selectedServiceIds"); // Call the parent's callback widget.onServiceIdsChanged!(selectedServiceIds); }); diff --git a/lib/Screens/userManagement/create_user/traveller_details.dart b/lib/Screens/userManagement/create_user/traveller_details.dart index b9649df..e93e168 100644 --- a/lib/Screens/userManagement/create_user/traveller_details.dart +++ b/lib/Screens/userManagement/create_user/traveller_details.dart @@ -3656,7 +3656,16 @@ class TravellerDetailsState extends State { .map((e) => _buildVisaDataRow1(e, isDesktop)), // _buildVisaDataRow1(isDesktop), - IconForVisa(), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + " * I confirm my passport is valid for next 6 months", + style: GoogleFonts.poppins(fontSize: 10), + ), + IconForVisa(), + ], + ), ], ); } @@ -3677,6 +3686,7 @@ class TravellerDetailsState extends State { buildVisaValidFrom(entry), SizedBox(width: 15), buildVisaValidUpTo(entry), + SizedBox( height: 60, child: Center( @@ -3713,6 +3723,7 @@ class TravellerDetailsState extends State { buildVisaValidFrom(entry), SizedBox(height: 8), buildVisaValidUpTo(entry), + IconButton( icon: Icon( Icons.remove_circle_sharp,