diff --git a/lib/Screens/allTrips/list_all_plans.dart b/lib/Screens/allTrips/list_all_plans.dart index 5d55f45..35835ee 100644 --- a/lib/Screens/allTrips/list_all_plans.dart +++ b/lib/Screens/allTrips/list_all_plans.dart @@ -204,7 +204,8 @@ class _ListAllPlansState extends State { Future> fetchPlans() async { late String apiUrldata; - apiUrldata = '$apiUrl/api/plans?org_id=$orgId'; + // apiUrldata = '$apiUrl/api/plans?org_id=$orgId'; + apiUrldata = '$apiUrl/api/allPlans?org_id=$orgId'; // if (roleUser == "Org Admin") { // apiUrldata = '$apiUrl/api/plans?org_id=$orgId'; @@ -283,7 +284,7 @@ class _ListAllPlansState extends State { } } - void deletePlan(String planId) async { + void deletePlan(String planId, userId) async { bool confirmed = await apiService.showCancelConfirmationDialog( context, layoutColor, @@ -293,6 +294,7 @@ class _ListAllPlansState extends State { try { Map planData = await ApiService().getViewPlan( planId, + userId, context, ); print("ViewAAA - $planData"); @@ -1135,6 +1137,7 @@ class _ListAllPlansState extends State { ); deletePlan( plan.planId, + userId, ); }, ), @@ -1455,6 +1458,7 @@ class _ListAllPlansState extends State { ); deletePlan( plan.planId, + userId, ); }, ), diff --git a/lib/Screens/allTrips/plan_info_mdl.dart b/lib/Screens/allTrips/plan_info_mdl.dart index 7b05dc6..0dd91e6 100644 --- a/lib/Screens/allTrips/plan_info_mdl.dart +++ b/lib/Screens/allTrips/plan_info_mdl.dart @@ -143,14 +143,17 @@ class _TripInformationState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - keyValueRow("Action", item["action"]), - keyValueRow("Approver", item["approver"]), + keyValueRow("Action", item["action"] ?? '-'), + keyValueRow("Approver", item["approver"] ?? '-'), keyValueRow( "Is Action Done", - item["is_action_done"], + item["is_action_done"] ?? '-', + ), + keyValueRow("Action On", item["action_on"] ?? '-'), + keyValueRow( + "Email Status", + item["email_status"] ?? '-', ), - keyValueRow("Action On", item["action_on"]), - keyValueRow("Email Status", item["email_status"]), ], ), ), diff --git a/lib/Screens/allTrips/travel_agent_list.dart b/lib/Screens/allTrips/travel_agent_list.dart index 3ddc47d..525718b 100644 --- a/lib/Screens/allTrips/travel_agent_list.dart +++ b/lib/Screens/allTrips/travel_agent_list.dart @@ -364,6 +364,7 @@ class _TravelAgentListPlansState extends State { try { Map planData = await ApiService().getViewPlan( planId, + userId, context, ); print("ViewAAA - $planData"); diff --git a/lib/Screens/approvals/approval_dialogs.dart b/lib/Screens/approvals/approval_dialogs.dart index d8b772c..b022164 100644 --- a/lib/Screens/approvals/approval_dialogs.dart +++ b/lib/Screens/approvals/approval_dialogs.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; Future showApprovalDialog( BuildContext context, @@ -115,6 +116,11 @@ Future showApprovalDialog( TextField( style: TextStyle(fontFamily: "Inter", fontSize: 14), maxLines: 3, + inputFormatters: [ + FilteringTextInputFormatter.allow( + RegExp(r'[a-zA-Z0-9 _-]'), + ), + ], onChanged: (value) => remarks = value, decoration: InputDecoration( hintText: "Remarks...", @@ -263,8 +269,14 @@ Future showRejectDialog1( const Text("Please enter reason for rejection."), const SizedBox(height: 10), TextField( + inputFormatters: [ + FilteringTextInputFormatter.allow( + RegExp(r'[a-zA-Z0-9 _-]'), + ), + ], maxLines: 3, onChanged: (value) => remarks = value, + decoration: const InputDecoration( hintText: "Remarks...", hintStyle: TextStyle( diff --git a/lib/Screens/approvals/approval_list.dart b/lib/Screens/approvals/approval_list.dart index bba41eb..4550be2 100644 --- a/lib/Screens/approvals/approval_list.dart +++ b/lib/Screens/approvals/approval_list.dart @@ -256,7 +256,7 @@ class _ApprovalListState extends State { } } - void deletePlan(String planId) async { + void deletePlan(String planId, userId) async { // try { // Map planData = await getViewPlan(planId); // print("ViewAAA - $planData"); @@ -275,6 +275,7 @@ class _ApprovalListState extends State { try { Map planData = await ApiService().getViewPlan( planId, + userId, context, ); print("ViewAAA - $planData"); @@ -1207,6 +1208,7 @@ class _ApprovalListState extends State { ); deletePlan( plan.planId, + userId, ); }, ), diff --git a/lib/Screens/authentication/login/login_widget.dart b/lib/Screens/authentication/login/login_widget.dart index 4b238f7..57da01b 100644 --- a/lib/Screens/authentication/login/login_widget.dart +++ b/lib/Screens/authentication/login/login_widget.dart @@ -4,6 +4,7 @@ import 'dart:html' as html; import 'package:encrypt/encrypt.dart' as encrypt; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:frontend/config/apiUrl.dart'; import 'package:google_fonts/google_fonts.dart'; @@ -580,6 +581,7 @@ class _LoginWidgetState extends State { _buildLabel("Email Address"), TextFormField( controller: _emailController, + inputFormatters: [], style: GoogleFonts.poppins( fontWeight: FontWeight.w600, fontSize: 11, diff --git a/lib/Screens/costCenter/costCenterDetails.dart b/lib/Screens/costCenter/costCenterDetails.dart index d31040d..25a62ef 100644 --- a/lib/Screens/costCenter/costCenterDetails.dart +++ b/lib/Screens/costCenter/costCenterDetails.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:http/http.dart' as http; @@ -314,6 +315,11 @@ class CostCenterDataState extends State { child: TextField( controller: controllers["name"], focusNode: focusNodes["nameFocusNode"], + inputFormatters: [ + FilteringTextInputFormatter.allow( + RegExp(r'[a-zA-Z0-9 _-]'), + ), + ], style: const TextStyle(fontSize: 12), decoration: const InputDecoration( labelText: "Name", @@ -356,6 +362,11 @@ class CostCenterDataState extends State { child: TextField( controller: controllers["description"], focusNode: focusNodes["descriptionFocusNode"], + inputFormatters: [ + FilteringTextInputFormatter.allow( + RegExp(r'[a-zA-Z0-9 _-]'), + ), + ], style: const TextStyle(fontSize: 12), maxLines: null, expands: true, diff --git a/lib/Screens/department/departmentDetails.dart b/lib/Screens/department/departmentDetails.dart index fa99d0e..9261a81 100644 --- a/lib/Screens/department/departmentDetails.dart +++ b/lib/Screens/department/departmentDetails.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:http/http.dart' as http; @@ -313,6 +314,11 @@ class DepartmentDataState extends State { child: SizedBox( height: 40, child: TextField( + inputFormatters: [ + FilteringTextInputFormatter.allow( + RegExp(r'[a-zA-Z0-9 _-]'), + ), + ], controller: controllers["dropdown_value"], focusNode: focusNodes["dropdown_valueFocusNode"], style: const TextStyle(fontSize: 12), diff --git a/lib/Screens/department/department_list.dart b/lib/Screens/department/department_list.dart index 0efd1eb..e057313 100644 --- a/lib/Screens/department/department_list.dart +++ b/lib/Screens/department/department_list.dart @@ -320,6 +320,7 @@ class DepartmentListState extends State { height: 40, child: TextField( controller: searchController, + onChanged: filterDepartment, decoration: InputDecoration( hintText: "Search ...", diff --git a/lib/Screens/dialog/user_selection_dialog.dart b/lib/Screens/dialog/user_selection_dialog.dart index 116905d..4274539 100644 --- a/lib/Screens/dialog/user_selection_dialog.dart +++ b/lib/Screens/dialog/user_selection_dialog.dart @@ -176,11 +176,6 @@ class _UserSelectionDialogState extends State { await apiService.logout(context); return null; // throw Exception('Failed to load users'); - } else if (response.statusCode == 403) { - print("403-FORB"); - await apiService.logout(context); - return null; - // throw Exception('Failed to load users'); } else { throw Exception( 'Failed to load users. Status Code: ${response.statusCode}', diff --git a/lib/Screens/group/group.dart b/lib/Screens/group/group.dart index bb83be3..7e51335 100644 --- a/lib/Screens/group/group.dart +++ b/lib/Screens/group/group.dart @@ -4,6 +4,7 @@ import 'dart:io'; import 'package:dropdown_search/dropdown_search.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:frontend/Screens/organization/mailSettings.dart'; import 'package:frontend/Screens/organization/themeColor.dart'; import 'package:frontend/utils/auth_utils.dart'; @@ -481,6 +482,9 @@ class _groupState extends State { height: 40, child: TextField( controller: controllers["name"], + inputFormatters: [ + FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z0-9 _-]')), + ], style: TextStyle(fontSize: 12), onChanged: (value) { _clearError("name"); @@ -527,6 +531,9 @@ class _groupState extends State { height: 40, child: TextField( controller: controllers["description"], + inputFormatters: [ + FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z0-9 _-]')), + ], onChanged: (value) { _clearError("description"); }, diff --git a/lib/Screens/group/groupDetails.dart b/lib/Screens/group/groupDetails.dart index 083d51b..f4f9406 100644 --- a/lib/Screens/group/groupDetails.dart +++ b/lib/Screens/group/groupDetails.dart @@ -426,7 +426,11 @@ class GroupDataState extends State { height: 40, child: TextField( focusNode: focusNodes["nameFocusNode"], - + inputFormatters: [ + FilteringTextInputFormatter.allow( + RegExp(r'[a-zA-Z0-9 _-]'), + ), + ], controller: controllers["name"], style: const TextStyle(fontSize: 12), decoration: const InputDecoration( @@ -779,7 +783,11 @@ class GroupDataState extends State { child: TextField( controller: controllers["description"], focusNode: focusNodes["descriptionFocusNode"], - + inputFormatters: [ + FilteringTextInputFormatter.allow( + RegExp(r'[a-zA-Z0-9 _-]'), + ), + ], style: const TextStyle(fontSize: 12), maxLines: null, expands: true, diff --git a/lib/Screens/hotels/hotelsDetails.dart b/lib/Screens/hotels/hotelsDetails.dart index fbdcb1f..5f6ae71 100644 --- a/lib/Screens/hotels/hotelsDetails.dart +++ b/lib/Screens/hotels/hotelsDetails.dart @@ -372,6 +372,11 @@ class HotelsDataState extends State { height: 40, child: TextField( focusNode: focusNodes["hotel_nameFocusNode"], + inputFormatters: [ + FilteringTextInputFormatter.allow( + RegExp(r'[a-zA-Z0-9 _-]'), + ), + ], controller: controllers["hotel_name"], style: const TextStyle(fontSize: 12), decoration: const InputDecoration( @@ -415,6 +420,11 @@ class HotelsDataState extends State { child: TextField( focusNode: focusNodes["hotel_chainFocusNode"], controller: controllers["hotel_chain"], + inputFormatters: [ + FilteringTextInputFormatter.allow( + RegExp(r'[a-zA-Z0-9 _-]'), + ), + ], style: const TextStyle(fontSize: 12), decoration: const InputDecoration( labelText: "Hotel Chain", @@ -458,9 +468,10 @@ class HotelsDataState extends State { child: TextField( focusNode: focusNodes["categoryFocusNode"], controller: controllers["category"], + inputFormatters: [ FilteringTextInputFormatter.allow( - RegExp(r'[a-zA-Z0-9 ]'), + RegExp(r'[a-z A-Z0-9 ]'), ), ], style: const TextStyle(fontSize: 12), @@ -665,6 +676,11 @@ class HotelsDataState extends State { height: 40, child: TextField( focusNode: focusNodes["cityFocusNode"], + inputFormatters: [ + FilteringTextInputFormatter.allow( + RegExp(r'[a-zA-Z0-9 _-]'), + ), + ], controller: controllers["city"], style: const TextStyle(fontSize: 12), decoration: const InputDecoration( diff --git a/lib/Screens/hotels/hotels_list.dart b/lib/Screens/hotels/hotels_list.dart index 39cae10..c12d1d3 100644 --- a/lib/Screens/hotels/hotels_list.dart +++ b/lib/Screens/hotels/hotels_list.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:go_router/go_router.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:http/http.dart' as http; @@ -379,6 +380,11 @@ class HotelsDataListState extends State { height: 40, child: TextField( controller: searchController, + inputFormatters: [ + FilteringTextInputFormatter.allow( + RegExp(r'[a-zA-Z0-9 _-]'), + ), + ], onChanged: filterHotels, decoration: InputDecoration( hintText: "Search ...", diff --git a/lib/Screens/itnerary/accomodations.dart b/lib/Screens/itnerary/accomodations.dart index f97538f..4c05288 100644 --- a/lib/Screens/itnerary/accomodations.dart +++ b/lib/Screens/itnerary/accomodations.dart @@ -1,5 +1,6 @@ import 'package:dropdown_search/dropdown_search.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:intl/intl.dart'; import 'package:responsive_builder/responsive_builder.dart'; @@ -664,6 +665,9 @@ class _AccomodationScreenState extends State { focusNode: _destinationFocusNode, controller: _destinationController, style: TextStyle(fontSize: 12), + inputFormatters: [ + FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z0-9 _-]')), + ], decoration: InputDecoration( labelText: "Destination", labelStyle: TextStyle(fontSize: 12, color: Colors.grey), @@ -1503,6 +1507,9 @@ class _AccomodationScreenState extends State { child: TextField( focusNode: _commentsFocusNode, controller: _commentsController, + inputFormatters: [ + FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z0-9 _-]')), + ], style: TextStyle(fontSize: 12), decoration: InputDecoration( labelText: "Comments", diff --git a/lib/Screens/itnerary/bus.dart b/lib/Screens/itnerary/bus.dart index ebc41d8..c36c5c5 100644 --- a/lib/Screens/itnerary/bus.dart +++ b/lib/Screens/itnerary/bus.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:intl/intl.dart'; import 'package:responsive_builder/responsive_builder.dart'; @@ -466,6 +467,9 @@ class _BusScreenState extends State { focusNode: _fromFocusNode, controller: _fromController, style: const TextStyle(fontSize: 12), + inputFormatters: [ + FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z0-9 _-]')), + ], decoration: const InputDecoration( labelText: "From", labelStyle: TextStyle(fontSize: 12, color: Colors.grey), @@ -503,6 +507,9 @@ class _BusScreenState extends State { child: TextField( focusNode: _toFocusNode, controller: _toController, + inputFormatters: [ + FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z0-9 _-]')), + ], style: const TextStyle(fontSize: 12), decoration: const InputDecoration( labelText: "To", @@ -548,6 +555,7 @@ class _BusScreenState extends State { child: TextField( focusNode: _dateFocusNode, controller: _dateController, + readOnly: true, style: const TextStyle(fontSize: 12), decoration: const InputDecoration( @@ -656,6 +664,9 @@ class _BusScreenState extends State { child: TextField( focusNode: _commentsFocusNode, controller: _buscommentsController, + inputFormatters: [ + FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z0-9 _-]')), + ], style: TextStyle(fontSize: 12), decoration: InputDecoration( labelText: "Comments", diff --git a/lib/Screens/itnerary/flights.dart b/lib/Screens/itnerary/flights.dart index faf766a..16f2bb4 100644 --- a/lib/Screens/itnerary/flights.dart +++ b/lib/Screens/itnerary/flights.dart @@ -1,5 +1,6 @@ import 'package:dropdown_search/dropdown_search.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:frontend/services/apiService.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:intl/intl.dart'; @@ -2520,6 +2521,9 @@ class FlightScreenState extends State { focusNode: focusNodes["_comments1FocusNode"], // controller: _commentsController, controller: textControllers["_comments1Controller"], + inputFormatters: [ + FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z0-9 _-]')), + ], // maxLines: 6, // keyboardType: TextInputType.multiline, style: TextStyle(fontSize: 12), diff --git a/lib/Screens/itnerary/forex.dart b/lib/Screens/itnerary/forex.dart index 7c1f3ff..c8d5ef2 100644 --- a/lib/Screens/itnerary/forex.dart +++ b/lib/Screens/itnerary/forex.dart @@ -1147,6 +1147,11 @@ class _ForexScreenState extends State { child: TextField( focusNode: focusNodes["_forexStartDate"], controller: textControllers["_forexStartDate"], + inputFormatters: [ + FilteringTextInputFormatter.allow( + RegExp(r'[a-zA-Z0-9 _-]'), + ), + ], readOnly: true, style: const TextStyle(fontSize: 12), decoration: InputDecoration( @@ -1234,6 +1239,11 @@ class _ForexScreenState extends State { child: TextField( focusNode: focusNodes["_forexEndDate"], controller: textControllers["_forexEndDate"], + inputFormatters: [ + FilteringTextInputFormatter.allow( + RegExp(r'[a-zA-Z0-9 _-]'), + ), + ], readOnly: true, style: const TextStyle(fontSize: 12), decoration: const InputDecoration( @@ -1678,6 +1688,7 @@ class _ForexScreenState extends State { height: 30, child: TextField( focusNode: focusNodes["_transport"], + controller: textControllers["_transport"], onChanged: (value) { setState(() { @@ -2232,6 +2243,9 @@ class _ForexScreenState extends State { child: TextField( focusNode: focusNodes["_comments"], controller: textControllers["_comments"], + inputFormatters: [ + FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z0-9 _-]')), + ], style: TextStyle(fontSize: 12), decoration: InputDecoration( labelText: "Comments", @@ -2340,6 +2354,11 @@ class _ForexScreenState extends State { onChanged: (value) { errorMessages.remove("delivery_location"); }, + inputFormatters: [ + FilteringTextInputFormatter.allow( + RegExp(r'[a-zA-Z0-9 _-]'), + ), + ], style: TextStyle(fontSize: 12), decoration: InputDecoration( labelText: "Location", diff --git a/lib/Screens/itnerary/insurance.dart b/lib/Screens/itnerary/insurance.dart index 6e0a724..0f8e24e 100644 --- a/lib/Screens/itnerary/insurance.dart +++ b/lib/Screens/itnerary/insurance.dart @@ -1,5 +1,6 @@ import 'package:dropdown_search/dropdown_search.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:intl/intl.dart'; import 'package:responsive_builder/responsive_builder.dart'; @@ -1180,7 +1181,9 @@ class _InsuranceScreenState extends State { height: 40, child: TextField( focusNode: focusNodes["nominee_nameFocusNode"], - + inputFormatters: [ + FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z0-9 _-]')), + ], // focusNode: _nomineeFocusNode, controller: _nomineeController, style: TextStyle(fontSize: 12), @@ -1290,6 +1293,9 @@ class _InsuranceScreenState extends State { focusNode: focusNodes["nominee_relationshipFocusNode"], controller: _nomineerelationController, style: TextStyle(fontSize: 12), + inputFormatters: [ + FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z0-9 _-]')), + ], decoration: InputDecoration( labelText: "Nominee Relationship", labelStyle: TextStyle(fontSize: 12, color: Colors.grey), @@ -1340,6 +1346,9 @@ class _InsuranceScreenState extends State { // focusNode: _commentsFocusNode, focusNode: focusNodes["commentsFocusNode"], controller: _insuranceCommentsController, + inputFormatters: [ + FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z0-9 _-]')), + ], style: TextStyle(fontSize: 12), decoration: InputDecoration( labelText: "Comments", diff --git a/lib/Screens/itnerary/miscellaneous.dart b/lib/Screens/itnerary/miscellaneous.dart index e5e0a06..d35a375 100644 --- a/lib/Screens/itnerary/miscellaneous.dart +++ b/lib/Screens/itnerary/miscellaneous.dart @@ -1,5 +1,6 @@ import 'package:dropdown_search/dropdown_search.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:intl/intl.dart'; import 'package:responsive_builder/responsive_builder.dart'; @@ -125,9 +126,9 @@ class _MiscellaneousScreenState extends State { setState(() { layoutColor = - layoutString != null - ? Color(int.parse(layoutString)) - : Colors.redAccent; + layoutString != null + ? Color(int.parse(layoutString)) + : Colors.redAccent; }); } @@ -309,106 +310,114 @@ class _MiscellaneousScreenState extends State { width: isDesktop ? MediaQuery.of(context).size.width * 0.34 - : null,//MediaQuery.of(context).size.width * 0.66, + : null, //MediaQuery.of(context).size.width * 0.66, child: SizedBox( height: 40, width: double.infinity, - child: Focus( - focusNode: _hotelNameFocusNode, - onFocusChange: (hasFocus) { - setState(() { - _hotelNameFocused = hasFocus; - }); + child: Focus( + focusNode: _hotelNameFocusNode, + onFocusChange: (hasFocus) { + setState(() { + _hotelNameFocused = hasFocus; + }); + }, + child: GestureDetector( + // + onTap: () { + // Request focus when user taps + _hotelNameFocusNode?.requestFocus(); }, - child: GestureDetector( - // - onTap: () { - // Request focus when user taps - _hotelNameFocusNode?.requestFocus(); - }, - child: DropdownSearch>( - // focusNode: _taxiReqFocusNode, - items: purposeList.cast>(), - selectedItem: purposeList.firstWhere( - (item) => item['dropdown_key'] == selectedSpecialType, - orElse: () => {}, - ), - itemAsString: (item) => item['dropdown_value'] ?? '', - popupProps: PopupProps.menu( - showSearchBox: false, - fit: FlexFit.loose, - menuProps: const MenuProps(backgroundColor: Colors.white), - itemBuilder: (context, item, isSelected) { - return Padding( - padding: const EdgeInsets.symmetric( - horizontal: 10, - vertical: 5, + child: DropdownSearch>( + // focusNode: _taxiReqFocusNode, + items: purposeList.cast>(), + selectedItem: purposeList.firstWhere( + (item) => item['dropdown_key'] == selectedSpecialType, + orElse: () => {}, + ), + itemAsString: (item) => item['dropdown_value'] ?? '', + popupProps: PopupProps.menu( + showSearchBox: false, + fit: FlexFit.loose, + menuProps: const MenuProps(backgroundColor: Colors.white), + itemBuilder: (context, item, isSelected) { + return Padding( + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 5, + ), + child: Text( + item['dropdown_value'] ?? '', + style: GoogleFonts.poppins( + fontSize: 12, + color: Colors.black, + ), + ), + ); + }, + ), + dropdownDecoratorProps: DropDownDecoratorProps( + dropdownSearchDecoration: InputDecoration( + // border: InputBorder.none, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(4), + borderSide: BorderSide( + color: + (_hotelNameFocused ?? false) + ? layoutColor! + : Colors.white, + width: 0.5, + ), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + (_hotelNameFocused ?? false) + ? layoutColor + : Colors.white, + // : const Color(0xFFD6D5E6), + width: 0.5, + // const Color(0xFFD6D5E6), + ), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: layoutColor, width: 0.5), + ), + contentPadding: EdgeInsets.symmetric( + horizontal: 10, + vertical: 10, + ), ), - child: Text( - item['dropdown_value'] ?? '', + ), + dropdownBuilder: (context, selectedItem) { + if (selectedItem == null || selectedItem.isEmpty) { + return Text( + "Select ", + style: GoogleFonts.poppins( + color: Colors.grey, + fontSize: 13, + ), + ); + } + return Text( + selectedItem['dropdown_value'] ?? '', style: GoogleFonts.poppins( fontSize: 12, color: Colors.black, ), - ), - ); - }, - ), - dropdownDecoratorProps: DropDownDecoratorProps( - dropdownSearchDecoration: InputDecoration( - // border: InputBorder.none, - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(4), - borderSide: BorderSide( - color: - (_hotelNameFocused ?? false) - ? layoutColor! - : Colors.white, - width: 0.5, - ), - ), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: - (_hotelNameFocused ?? false) - ? layoutColor - : Colors.white, - // : const Color(0xFFD6D5E6), - width: 0.5, - // const Color(0xFFD6D5E6), - ), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide(color: layoutColor, width: 0.5), - ), - contentPadding: EdgeInsets.symmetric( - horizontal: 10, - vertical: 10, - ), + ); + }, + onChanged: + purposeList.isNotEmpty + ? (newValue) { + setState(() { + selectedSpecialType = newValue as String?; + }); + print("Updating form data: -> ${newValue ?? ""}"); + } + : null, ), ), - dropdownBuilder: (context, selectedItem) { - if (selectedItem == null || selectedItem.isEmpty) { - return Text( - "Select ", - style: GoogleFonts.poppins(color: Colors.grey, fontSize: 13), - ); - } - return Text( - selectedItem['dropdown_value'] ?? '', - style: GoogleFonts.poppins(fontSize: 12, color: Colors.black), - ); - }, - onChanged: - purposeList.isNotEmpty - ? (newValue) { - setState(() { - selectedSpecialType = newValue as String?; - }); - print("Updating form data: -> ${newValue ?? ""}"); - } - : null, - ),),) + ), ), ), if (errorMessages["special_request"] != null) ...[ @@ -439,10 +448,13 @@ class _MiscellaneousScreenState extends State { width: isDesktop ? MediaQuery.of(context).size.width * 0.34 - : null,//MediaQuery.of(context).size.width * 0.66, + : null, //MediaQuery.of(context).size.width * 0.66, child: SizedBox( height: 40, child: TextField( + inputFormatters: [ + FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z0-9 _-]')), + ], focusNode: _commentsFocusNode, controller: _commentsController, style: TextStyle(fontSize: 12), diff --git a/lib/Screens/itnerary/sample.dart b/lib/Screens/itnerary/sample.dart index 021a40d..d4b34ce 100644 --- a/lib/Screens/itnerary/sample.dart +++ b/lib/Screens/itnerary/sample.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:intl/intl.dart'; import 'package:responsive_builder/responsive_builder.dart'; @@ -11,8 +12,12 @@ class ForexScreen extends StatefulWidget { final Function(String tab, String key, String value) updateFormData; final Function(bool) onClose; - ForexScreen({required this.formData, required this.updateFormData, - required this.onClose, this.apiData}); + ForexScreen({ + required this.formData, + required this.updateFormData, + required this.onClose, + this.apiData, + }); @override _ForexScreenState createState() => _ForexScreenState(); @@ -95,57 +100,55 @@ class _ForexScreenState extends State { }); }); - - - _tripTypeController = - TextEditingController(text: widget.formData["tripType"] ?? ""); - _hotelNameController = - TextEditingController(text: widget.formData["_hotelName"] ?? ""); - _fromController = - TextEditingController(text: widget.formData["_from"] ?? ""); - _toController = - TextEditingController(text: widget.formData["_Check_In_Time"] ?? ""); - _dateController = - TextEditingController(text: widget.formData["_Check_Out"] ?? ""); - _endDateController = - TextEditingController(text: widget.formData["_Check_In"] ?? ""); - _timeController = - TextEditingController(text: widget.formData["_Check_Out_Time"] ?? ""); - _commentsController = - TextEditingController(text: widget.formData["_comments"] ?? ""); + _tripTypeController = TextEditingController( + text: widget.formData["tripType"] ?? "", + ); + _hotelNameController = TextEditingController( + text: widget.formData["_hotelName"] ?? "", + ); + _fromController = TextEditingController( + text: widget.formData["_from"] ?? "", + ); + _toController = TextEditingController( + text: widget.formData["_Check_In_Time"] ?? "", + ); + _dateController = TextEditingController( + text: widget.formData["_Check_Out"] ?? "", + ); + _endDateController = TextEditingController( + text: widget.formData["_Check_In"] ?? "", + ); + _timeController = TextEditingController( + text: widget.formData["_Check_Out_Time"] ?? "", + ); + _commentsController = TextEditingController( + text: widget.formData["_comments"] ?? "", + ); // Save data when user types _tripTypeController.addListener(() { - widget.updateFormData( - "Bus", "_tripType", _tripTypeController.text); + widget.updateFormData("Bus", "_tripType", _tripTypeController.text); }); // Save data when user types _hotelNameController.addListener(() { - widget.updateFormData( - "Bus", "_hotelName", _hotelNameController.text); + widget.updateFormData("Bus", "_hotelName", _hotelNameController.text); }); _fromController.addListener(() { - widget.updateFormData( - "Bus", "_from", _fromController.text); + widget.updateFormData("Bus", "_from", _fromController.text); }); _toController.addListener(() { - widget.updateFormData( - "Bus", "_Check_In_Time", _toController.text); + widget.updateFormData("Bus", "_Check_In_Time", _toController.text); }); _dateController.addListener(() { - widget.updateFormData( - "Bus", "_Check_Out", _dateController.text); + widget.updateFormData("Bus", "_Check_Out", _dateController.text); }); _endDateController.addListener(() { - widget.updateFormData( - "Bus", "_Check_In", _endDateController.text); + widget.updateFormData("Bus", "_Check_In", _endDateController.text); }); _timeController.addListener(() { - widget.updateFormData( - "Bus", "_Check_Out_Time", _timeController.text); + widget.updateFormData("Bus", "_Check_Out_Time", _timeController.text); }); _commentsController.addListener(() { - widget.updateFormData( - "Bus", "_comments", _commentsController.text); + widget.updateFormData("Bus", "_comments", _commentsController.text); }); } @@ -163,56 +166,60 @@ class _ForexScreenState extends State { super.dispose(); } - - @override Widget build(BuildContext context) { - return ResponsiveBuilder(builder: (context, sizingInfo) { - bool isMobile = sizingInfo.isMobile; - bool isDesktop = sizingInfo.deviceScreenType == DeviceScreenType.desktop; + return ResponsiveBuilder( + builder: (context, sizingInfo) { + bool isMobile = sizingInfo.isMobile; + bool isDesktop = + sizingInfo.deviceScreenType == DeviceScreenType.desktop; - return Container( - color: Color(0xFFF4F4FB), - child: Form( - key: _formKey, - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - children: [ - Align( - alignment: Alignment.centerRight, - child: InkWell( - onTap: () { - widget.onClose(false); - }, - child: Icon( - Icons.close, - size: 18, + return Container( + color: Color(0xFFF4F4FB), + child: Form( + key: _formKey, + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + children: [ + Align( + alignment: Alignment.centerRight, + child: InkWell( + onTap: () { + widget.onClose(false); + }, + child: Icon( + Icons.close, + size: 18, + color: Color(0xFF575A74), + ), + ), + ), + Text( + "Forex List", + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, color: Color(0xFF575A74), ), ), - ), - Text("Forex List", - style: - TextStyle(fontSize: 18, fontWeight: FontWeight.bold,color: Color(0xFF575A74))), - SizedBox( - height: 6, - ), - Padding( - padding: const EdgeInsets.all(28.0), - child: Center( - child: Column(children: _buildAccomadtionForm(isDesktop)), + SizedBox(height: 6), + Padding( + padding: const EdgeInsets.all(28.0), + child: Center( + child: Column(children: _buildAccomadtionForm(isDesktop)), + ), ), - ) - ], + ], + ), ), ), - ), - ); - }); + ); + }, + ); } - List _buildAccomadtionForm (bool isDesktop) { + List _buildAccomadtionForm(bool isDesktop) { List buildResponsiveRow(List children) { return [ isDesktop ? Row(children: children) : Column(children: children), @@ -222,14 +229,12 @@ class _ForexScreenState extends State { List> rowBuilders = [ _builClassType(isDesktop), - _buildSecondRow(isDesktop) + _buildSecondRow(isDesktop), ]; return [ - ...buildResponsiveRow(_buildFirstRow(isDesktop)), - // Iterate over rowBuilders and wrap each in a responsive container ...rowBuilders.expand((row) => buildResponsiveRow(row)), @@ -247,23 +252,21 @@ class _ForexScreenState extends State { ]; } - - List _buildFirstRow(isDesktop) { - DateTime? _selectedCheckOutDate; DateTime? _selectedEndDate; - Future _selectCheckOutDate(BuildContext context) async { DateTime now = DateTime.now(); DateTime today = DateTime(now.year, now.month, now.day); DateTime? pickedDate = await showDatePicker( context: context, - initialDate: _selectedCheckOutDate != null && _selectedCheckOutDate!.isAfter(today) - ? _selectedCheckOutDate! - : today, + initialDate: + _selectedCheckOutDate != null && + _selectedCheckOutDate!.isAfter(today) + ? _selectedCheckOutDate! + : today, firstDate: today, lastDate: DateTime(2100), ); @@ -274,18 +277,20 @@ class _ForexScreenState extends State { _dateController.text = DateFormat('yyyy-MM-dd').format(pickedDate); }); } - }; + } + + ; Future _selectForexEndDate(BuildContext context) async { - DateTime now = DateTime.now(); DateTime today = DateTime(now.year, now.month, now.day); DateTime? pickedDate = await showDatePicker( context: context, - initialDate: _selectedEndDate != null && _selectedEndDate!.isAfter(today) - ? _selectedEndDate! - : today, + initialDate: + _selectedEndDate != null && _selectedEndDate!.isAfter(today) + ? _selectedEndDate! + : today, firstDate: today, lastDate: DateTime(2100), ); @@ -298,7 +303,6 @@ class _ForexScreenState extends State { } } - return [ Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -306,9 +310,10 @@ class _ForexScreenState extends State { Text( "Forex Start Date", style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74)), + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), ), SizedBox(height: 5), CustomTextFieldWrapper( @@ -330,32 +335,30 @@ class _ForexScreenState extends State { floatingLabelBehavior: FloatingLabelBehavior.never, border: InputBorder.none, contentPadding: EdgeInsets.symmetric(vertical: 16), - suffixIcon: Icon(Icons.calendar_today, - size: 16, color: Colors.grey), + suffixIcon: Icon( + Icons.calendar_today, + size: 16, + color: Colors.grey, + ), ), ), ), ), - ), ), ], ), - if (isDesktop) - Spacer() - else - SizedBox( - height: 8, - ), + if (isDesktop) Spacer() else SizedBox(height: 8), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "Forex End Date", style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74)), + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), ), SizedBox(height: 5), CustomTextFieldWrapper( @@ -377,46 +380,50 @@ class _ForexScreenState extends State { floatingLabelBehavior: FloatingLabelBehavior.never, border: InputBorder.none, contentPadding: EdgeInsets.symmetric(vertical: 16), - suffixIcon: Icon(Icons.calendar_today, - size: 16, color: Colors.grey), + suffixIcon: Icon( + Icons.calendar_today, + size: 16, + color: Colors.grey, + ), ), ), ), ), - ), ), ], ), - - ]; } - - - List _buildTripType(bool isDesktop){ - + List _buildTripType(bool isDesktop) { List purposeList = widget.apiData?['flight_trip_type'] ?? []; - List> dropdownItems = purposeList - .map((item)=>DropdownMenuItem( - value: item['dropdown_value'], - child: Text(item['dropdown_value']), - )).toList(); + List> dropdownItems = + purposeList + .map( + (item) => DropdownMenuItem( + value: item['dropdown_value'], + child: Text(item['dropdown_value']), + ), + ) + .toList(); if (dropdownItems.isEmpty) { dropdownItems.add( DropdownMenuItem( value: null, - child: Text("No options available", style: TextStyle(color: Colors.grey)), + child: Text( + "No options available", + style: TextStyle(color: Colors.grey), + ), ), ); } // Default selected value - String? selectedPurpose = dropdownItems.isNotEmpty ? dropdownItems.first.value : null; - + String? selectedPurpose = + dropdownItems.isNotEmpty ? dropdownItems.first.value : null; return [ CustomTextFieldWrapper( @@ -432,51 +439,62 @@ class _ForexScreenState extends State { decoration: InputDecoration( border: InputBorder.none, contentPadding: EdgeInsets.symmetric( - horizontal: 10), // Proper padding + horizontal: 10, + ), // Proper padding ), - onChanged: purposeList.isNotEmpty - ? (newValue) { - setState(() { - selectedPurpose = newValue; - }); - print("Updating form data: Flight -> trip_type -> ${newValue ?? ""}"); + onChanged: + purposeList.isNotEmpty + ? (newValue) { + setState(() { + selectedPurpose = newValue; + }); + print( + "Updating form data: Flight -> trip_type -> ${newValue ?? ""}", + ); - - widget.updateFormData("Flight", "trip_type", newValue ?? ""); - } - : null, + widget.updateFormData( + "Flight", + "trip_type", + newValue ?? "", + ); + } + : null, items: dropdownItems, ), - - ), ), ]; } - - List _builClassType(bool isDesktop){ - + List _builClassType(bool isDesktop) { List purposeList = widget.apiData?['flight_class'] ?? []; - List> dropdownItems = purposeList - .map((item)=>DropdownMenuItem( - value: item['dropdown_value'], - child: Text(item['dropdown_value']), - )).toList(); + List> dropdownItems = + purposeList + .map( + (item) => DropdownMenuItem( + value: item['dropdown_value'], + child: Text(item['dropdown_value']), + ), + ) + .toList(); if (dropdownItems.isEmpty) { dropdownItems.add( DropdownMenuItem( value: null, - child: Text("No options available", style: TextStyle(color: Colors.grey)), + child: Text( + "No options available", + style: TextStyle(color: Colors.grey), + ), ), ); } // Default selected value - String? selectedPurpose = dropdownItems.isNotEmpty ? dropdownItems.first.value : null; + String? selectedPurpose = + dropdownItems.isNotEmpty ? dropdownItems.first.value : null; return [ Column( @@ -485,9 +503,10 @@ class _ForexScreenState extends State { Text( "Class *", style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74)), + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), ), SizedBox(height: 5), CustomTextFieldWrapper( @@ -504,15 +523,17 @@ class _ForexScreenState extends State { decoration: InputDecoration( border: InputBorder.none, contentPadding: EdgeInsets.symmetric( - horizontal: 10), // Proper padding + horizontal: 10, + ), // Proper padding ), - onChanged: purposeList.isNotEmpty - ? (newValue) { - setState(() { - selectedPurpose = newValue; - }); - } - : null, + onChanged: + purposeList.isNotEmpty + ? (newValue) { + setState(() { + selectedPurpose = newValue; + }); + } + : null, items: dropdownItems, ), @@ -535,27 +556,30 @@ class _ForexScreenState extends State { ]; } - List _buildSecondRow(bool isDesktop) { return [ - Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "Transport", style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74)), + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), ), SizedBox(height: 5), CustomTextFieldItnerarySubWrapper( isFocused: _fromFocus, + isDesktop: isDesktop, child: SizedBox( height: 40, - child: TextField( + child: TextField( + inputFormatters: [ + FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z0-9_-]')), + ], focusNode: _fromFocusNode, controller: _fromController, style: const TextStyle(fontSize: 12), @@ -565,28 +589,23 @@ class _ForexScreenState extends State { floatingLabelBehavior: FloatingLabelBehavior.never, border: InputBorder.none, contentPadding: EdgeInsets.symmetric(vertical: 16), - ), ), ), ), ], ), - if (isDesktop) - Spacer() - else - SizedBox( - height: 8, - ), + if (isDesktop) Spacer() else SizedBox(height: 8), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "Accomodation", style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74)), + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), ), SizedBox(height: 5), CustomTextFieldItnerarySubWrapper( @@ -611,21 +630,17 @@ class _ForexScreenState extends State { ), ], ), - if (isDesktop) - Spacer() - else - SizedBox( - height: 8, - ), + if (isDesktop) Spacer() else SizedBox(height: 8), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "Telephone", style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74)), + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), ), SizedBox(height: 5), CustomTextFieldItnerarySubWrapper( @@ -633,7 +648,7 @@ class _ForexScreenState extends State { isDesktop: isDesktop, child: SizedBox( height: 40, - child: TextField( + child: TextField( focusNode: _fromFocusNode, controller: _fromController, style: const TextStyle(fontSize: 12), @@ -643,34 +658,29 @@ class _ForexScreenState extends State { floatingLabelBehavior: FloatingLabelBehavior.never, border: InputBorder.none, contentPadding: EdgeInsets.symmetric(vertical: 16), - ), ), ), ), ], ), - if (isDesktop) - Spacer() - else - SizedBox( - height: 8, - ), + if (isDesktop) Spacer() else SizedBox(height: 8), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "Other Expenses", style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74)), + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), ), SizedBox(height: 5), CustomTextFieldItnerarySubWrapper( isFocused: _toFocus, isDesktop: isDesktop, - color:Colors.transparent, + color: Colors.transparent, child: SizedBox( height: 40, @@ -680,7 +690,11 @@ class _ForexScreenState extends State { "Rs ", // focusNode: _toFocusNode, // controller: _toController, - style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w600,color: Color(0xFF575A74)), + style: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), // decoration: const InputDecoration( // labelText: "To", // labelStyle: TextStyle(fontSize: 12, color: Colors.grey), @@ -694,43 +708,48 @@ class _ForexScreenState extends State { ), ], ), - - ]; } List _buildCardDetailsRow(bool isDesktop) { - List purposeList = widget.apiData?['flight_class'] ?? []; - List> dropdownItems = purposeList - .map((item)=>DropdownMenuItem( - value: item['dropdown_value'], - child: Text(item['dropdown_value']), - )).toList(); + List> dropdownItems = + purposeList + .map( + (item) => DropdownMenuItem( + value: item['dropdown_value'], + child: Text(item['dropdown_value']), + ), + ) + .toList(); if (dropdownItems.isEmpty) { dropdownItems.add( DropdownMenuItem( value: null, - child: Text("No options available", style: TextStyle(color: Colors.grey)), + child: Text( + "No options available", + style: TextStyle(color: Colors.grey), + ), ), ); } // Default selected value - String? selectedPurpose = dropdownItems.isNotEmpty ? dropdownItems.first.value : null; + String? selectedPurpose = + dropdownItems.isNotEmpty ? dropdownItems.first.value : null; return [ - Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "Card Number*", style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74)), + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), ), SizedBox(height: 5), CustomTextFieldItnerarySubWrapper( @@ -738,7 +757,7 @@ class _ForexScreenState extends State { isDesktop: isDesktop, child: SizedBox( height: 40, - child: TextField( + child: TextField( focusNode: _fromFocusNode, controller: _fromController, style: const TextStyle(fontSize: 12), @@ -748,7 +767,6 @@ class _ForexScreenState extends State { floatingLabelBehavior: FloatingLabelBehavior.never, border: InputBorder.none, contentPadding: EdgeInsets.symmetric(vertical: 16), - ), ), ), @@ -756,21 +774,17 @@ class _ForexScreenState extends State { ], ), - if (isDesktop) - Spacer() - else - SizedBox( - height: 8, - ), + if (isDesktop) Spacer() else SizedBox(height: 8), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "Currency*", style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74)), + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), ), SizedBox(height: 5), CustomTextFieldItnerarySubWrapper( @@ -787,36 +801,34 @@ class _ForexScreenState extends State { decoration: InputDecoration( border: InputBorder.none, contentPadding: EdgeInsets.symmetric( - horizontal: 10), // Proper padding + horizontal: 10, + ), // Proper padding ), - onChanged: purposeList.isNotEmpty - ? (newValue) { - setState(() { - selectedPurpose = newValue; - }); - } - : null, + onChanged: + purposeList.isNotEmpty + ? (newValue) { + setState(() { + selectedPurpose = newValue; + }); + } + : null, items: dropdownItems, ), ), ), ], ), - if (isDesktop) - Spacer() - else - SizedBox( - height: 8, - ), + if (isDesktop) Spacer() else SizedBox(height: 8), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "Card*", style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74)), + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), ), SizedBox(height: 5), CustomTextFieldItnerarySubWrapper( @@ -841,21 +853,17 @@ class _ForexScreenState extends State { ), ], ), - if (isDesktop) - Spacer() - else - SizedBox( - height: 8, - ), + if (isDesktop) Spacer() else SizedBox(height: 8), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "Cash*", style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74)), + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), ), SizedBox(height: 5), CustomTextFieldItnerarySubWrapper( @@ -863,7 +871,7 @@ class _ForexScreenState extends State { isDesktop: isDesktop, child: SizedBox( height: 40, - child: TextField( + child: TextField( focusNode: _fromFocusNode, controller: _fromController, style: const TextStyle(fontSize: 12), @@ -873,16 +881,12 @@ class _ForexScreenState extends State { floatingLabelBehavior: FloatingLabelBehavior.never, border: InputBorder.none, contentPadding: EdgeInsets.symmetric(vertical: 16), - ), ), ), ), ], ), - - - ]; } @@ -894,17 +898,19 @@ class _ForexScreenState extends State { Text( "Delivery Location", style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74)), + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), ), SizedBox(height: 5), CustomTextFieldWrapper( isFocused: _commentsFocus, // Dropdown doesn't use focus isDesktop: isDesktop, - width: isDesktop - ? MediaQuery.of(context).size.width * 0.4 - : MediaQuery.of(context).size.width * 0.66, + width: + isDesktop + ? MediaQuery.of(context).size.width * 0.4 + : MediaQuery.of(context).size.width * 0.66, child: TextField( focusNode: _commentsFocusNode, controller: _commentsController, @@ -921,7 +927,7 @@ class _ForexScreenState extends State { ), ), ], - ) + ), ]; } @@ -944,10 +950,14 @@ class _ForexScreenState extends State { ), Text( "Check If You Don't Have a forex Account", - style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: Color(0xFF575A74)), + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), ), ], - ) + ), ]; } @@ -960,9 +970,7 @@ class _ForexScreenState extends State { }, style: ElevatedButton.styleFrom( backgroundColor: Colors.grey[400], // Light grey color - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12), ), child: Text( @@ -971,7 +979,6 @@ class _ForexScreenState extends State { ), ), SizedBox(width: 10), // Space between buttons - // Save Changes Button ElevatedButton( onPressed: () { @@ -979,9 +986,7 @@ class _ForexScreenState extends State { }, style: ElevatedButton.styleFrom( backgroundColor: Colors.blue, // Primary color for save - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12), ), child: Text( @@ -991,4 +996,4 @@ class _ForexScreenState extends State { ), ]; } -} \ No newline at end of file +} diff --git a/lib/Screens/itnerary/taxi.dart b/lib/Screens/itnerary/taxi.dart index 779dfd2..7e2da95 100644 --- a/lib/Screens/itnerary/taxi.dart +++ b/lib/Screens/itnerary/taxi.dart @@ -348,6 +348,7 @@ class _TaxiScreenState extends State { child: TextField( focusNode: _numPassengerFocusNode, controller: _numPassengerController, + style: const TextStyle(fontSize: 12), keyboardType: TextInputType.numberWithOptions(decimal: true), inputFormatters: [ @@ -850,6 +851,9 @@ class _TaxiScreenState extends State { focusNode: _destinationFocusNode, controller: _destinationController, style: const TextStyle(fontSize: 12), + inputFormatters: [ + FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z0-9 _-]')), + ], decoration: const InputDecoration( labelText: "Destination", labelStyle: TextStyle(fontSize: 12, color: Colors.grey), @@ -888,6 +892,9 @@ class _TaxiScreenState extends State { focusNode: _locationFocusNode, controller: _locationController, style: const TextStyle(fontSize: 12), + inputFormatters: [ + FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z0-9 _-]')), + ], decoration: const InputDecoration( labelText: "Pickup Location", labelStyle: TextStyle(fontSize: 12, color: Colors.grey), @@ -932,6 +939,11 @@ class _TaxiScreenState extends State { child: TextField( focusNode: _dateFocusNode, controller: _dateController, + inputFormatters: [ + FilteringTextInputFormatter.allow( + RegExp(r'[a-zA-Z0-9 _-]'), + ), + ], readOnly: true, style: const TextStyle(fontSize: 12), decoration: const InputDecoration( @@ -985,6 +997,11 @@ class _TaxiScreenState extends State { child: TextField( focusNode: _timeFocusNode, controller: _timeController, + inputFormatters: [ + FilteringTextInputFormatter.allow( + RegExp(r'[a-zA-Z0-9 _-]'), + ), + ], readOnly: true, style: const TextStyle(fontSize: 12), decoration: const InputDecoration( @@ -1045,6 +1062,9 @@ class _TaxiScreenState extends State { focusNode: _commentsFocusNode, controller: _taxiCommentsController, style: TextStyle(fontSize: 12), + inputFormatters: [ + FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z0-9 _-]')), + ], decoration: InputDecoration( labelText: "Comments", labelStyle: TextStyle(fontSize: 12, color: Colors.grey), diff --git a/lib/Screens/itnerary/train.dart b/lib/Screens/itnerary/train.dart index 3b0ca4d..0637bd2 100644 --- a/lib/Screens/itnerary/train.dart +++ b/lib/Screens/itnerary/train.dart @@ -1,5 +1,6 @@ import 'package:dropdown_search/dropdown_search.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:intl/intl.dart'; import 'package:responsive_builder/responsive_builder.dart'; @@ -466,6 +467,9 @@ class _TrainScreenState extends State { focusNode: _trainNoFocusNode, controller: _trainNoController, style: TextStyle(fontSize: 12), + inputFormatters: [ + FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z0-9_-]')), + ], decoration: InputDecoration( labelText: "Train number", labelStyle: TextStyle(fontSize: 12, color: Colors.grey), @@ -1356,6 +1360,9 @@ class _TrainScreenState extends State { // maxLines: 6, // keyboardType: TextInputType.multiline, style: TextStyle(fontSize: 12), + inputFormatters: [ + FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z0-9 _-]')), + ], decoration: InputDecoration( labelText: "Comments", labelStyle: TextStyle(fontSize: 12, color: Colors.grey), diff --git a/lib/Screens/itnerary/visa.dart b/lib/Screens/itnerary/visa.dart index 28682d4..110ebef 100644 --- a/lib/Screens/itnerary/visa.dart +++ b/lib/Screens/itnerary/visa.dart @@ -1,5 +1,6 @@ import 'package:dropdown_search/dropdown_search.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:intl/intl.dart'; import 'package:responsive_builder/responsive_builder.dart'; @@ -163,9 +164,9 @@ class _VisaScreenState extends State { setState(() { layoutColor = - layoutString != null - ? Color(int.parse(layoutString)) - : Colors.redAccent; + layoutString != null + ? Color(int.parse(layoutString)) + : Colors.redAccent; }); } @@ -549,7 +550,7 @@ class _VisaScreenState extends State { width: isDesktop ? MediaQuery.of(context).size.width * 0.34 - : null,//MediaQuery.of(context).size.width * 0.66, + : null, //MediaQuery.of(context).size.width * 0.66, child: SizedBox( height: 40, child: Focus( @@ -566,104 +567,108 @@ class _VisaScreenState extends State { // Request focus when user taps _countryFocusNode?.requestFocus(); }, - child: DropdownSearch( - selectedItem: countryMap[selectedCountry], - popupProps: PopupProps.menu( - showSearchBox: true, - fit: FlexFit.loose, - constraints: BoxConstraints(maxHeight: 200), - menuProps: const MenuProps(backgroundColor: Colors.white), - itemBuilder: (context, item, isSelected) { - print("contryItem - $item"); + child: DropdownSearch( + selectedItem: countryMap[selectedCountry], + popupProps: PopupProps.menu( + showSearchBox: true, + fit: FlexFit.loose, + constraints: BoxConstraints(maxHeight: 200), + menuProps: const MenuProps(backgroundColor: Colors.white), + itemBuilder: (context, item, isSelected) { + print("contryItem - $item"); - final match = RegExp(r'^(.*)\s\((.*)\)$').firstMatch(item); - final countryName = match?.group(1) ?? ''; - final countryCode = match?.group(2) ?? ''; - return Container( - color: Colors.white, - padding: EdgeInsets.symmetric( - horizontal: 10, - vertical: 6, - ), - child: Padding( - padding: const EdgeInsets.only(right: 1.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - countryName, - style: GoogleFonts.poppins(fontSize: 11.5), + final match = RegExp( + r'^(.*)\s\((.*)\)$', + ).firstMatch(item); + final countryName = match?.group(1) ?? ''; + final countryCode = match?.group(2) ?? ''; + return Container( + color: Colors.white, + padding: EdgeInsets.symmetric( + horizontal: 10, + vertical: 6, + ), + child: Padding( + padding: const EdgeInsets.only(right: 1.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + countryName, + style: GoogleFonts.poppins(fontSize: 11.5), + ), + Text( + countryCode, + style: GoogleFonts.poppins( + fontSize: 11.5, + color: Colors.grey, + ), + ), + ], ), - Text( - countryCode, - style: GoogleFonts.poppins( - fontSize: 11.5, - color: Colors.grey, - ), - ), - ], - ), - ), - ); - }, - searchFieldProps: TextFieldProps( - decoration: InputDecoration( - hintText: "Search ...", - contentPadding: EdgeInsets.symmetric(horizontal: 10), - ), - ), - ), - items: countryMap.values.toList(), - dropdownDecoratorProps: DropDownDecoratorProps( - dropdownSearchDecoration: InputDecoration( - // border: InputBorder.none, - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(5), - borderSide: BorderSide( - color: - (_countryFocused ?? false) - ? layoutColor! - : Colors.white, - width: 1, - ), - ), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: - (_countryFocused ?? false) - ? layoutColor - : Colors.white, - // : const Color(0xFFD6D5E6), - width: 1, - // const Color(0xFFD6D5E6), - ), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide(color: layoutColor, width: 1), - ), - contentPadding: EdgeInsets.symmetric(horizontal: 10), - ), - ), - dropdownBuilder: - (context, selectedItem) => Align( - alignment: Alignment.centerLeft, - child: Text( - selectedItem ?? "Select ", - style: GoogleFonts.poppins( - fontSize: 12, - color: Colors.black, + ), + ); + }, + searchFieldProps: TextFieldProps( + decoration: InputDecoration( + hintText: "Search ...", + contentPadding: EdgeInsets.symmetric(horizontal: 10), ), ), ), - onChanged: (String? newValue) { - setState(() { - selectedCountry = - countryMap.entries - .firstWhere((entry) => entry.value == newValue) - .key; - }); - }, - ),),), + items: countryMap.values.toList(), + dropdownDecoratorProps: DropDownDecoratorProps( + dropdownSearchDecoration: InputDecoration( + // border: InputBorder.none, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(5), + borderSide: BorderSide( + color: + (_countryFocused ?? false) + ? layoutColor! + : Colors.white, + width: 1, + ), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + (_countryFocused ?? false) + ? layoutColor + : Colors.white, + // : const Color(0xFFD6D5E6), + width: 1, + // const Color(0xFFD6D5E6), + ), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: layoutColor, width: 1), + ), + contentPadding: EdgeInsets.symmetric(horizontal: 10), + ), + ), + dropdownBuilder: + (context, selectedItem) => Align( + alignment: Alignment.centerLeft, + child: Text( + selectedItem ?? "Select ", + style: GoogleFonts.poppins( + fontSize: 12, + color: Colors.black, + ), + ), + ), + onChanged: (String? newValue) { + setState(() { + selectedCountry = + countryMap.entries + .firstWhere((entry) => entry.value == newValue) + .key; + }); + }, + ), + ), + ), ), ), if (errorMessages["country_code"] != null) ...[ @@ -729,115 +734,120 @@ class _VisaScreenState extends State { child: SizedBox( height: 40, width: double.infinity, - child: Focus( - focusNode: _tripTypeFocusNode, - onFocusChange: (hasFocus) { - setState(() { - _tripTypeFocused = hasFocus; - }); + child: Focus( + focusNode: _tripTypeFocusNode, + onFocusChange: (hasFocus) { + setState(() { + _tripTypeFocused = hasFocus; + }); + }, + child: GestureDetector( + // + onTap: () { + // Request focus when user taps + _tripTypeFocusNode?.requestFocus(); }, - child: GestureDetector( - // - onTap: () { - // Request focus when user taps - _tripTypeFocusNode?.requestFocus(); - }, - child: DropdownSearch>( - items: purposeList.cast>(), - selectedItem: purposeList.firstWhere( - (item) => item['dropdown_key'] == selectedPurpose, - orElse: () => {}, - ), - itemAsString: (item) => item['dropdown_value'] ?? '', - popupProps: PopupProps.menu( - showSearchBox: false, - fit: FlexFit.loose, - menuProps: const MenuProps(backgroundColor: Colors.white), - itemBuilder: (context, item, isSelected) { - return Padding( - padding: const EdgeInsets.symmetric( - horizontal: 10, - vertical: 5, + child: DropdownSearch>( + items: purposeList.cast>(), + selectedItem: purposeList.firstWhere( + (item) => item['dropdown_key'] == selectedPurpose, + orElse: () => {}, + ), + itemAsString: (item) => item['dropdown_value'] ?? '', + popupProps: PopupProps.menu( + showSearchBox: false, + fit: FlexFit.loose, + menuProps: const MenuProps(backgroundColor: Colors.white), + itemBuilder: (context, item, isSelected) { + return Padding( + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 5, + ), + child: Text( + item['dropdown_value'] ?? '', + style: GoogleFonts.poppins( + fontSize: 12, + color: Colors.black, + ), + ), + ); + }, + ), + dropdownDecoratorProps: DropDownDecoratorProps( + dropdownSearchDecoration: InputDecoration( + // border: InputBorder.none, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(5), + borderSide: BorderSide( + color: + (_tripTypeFocused ?? false) + ? layoutColor! + : Colors.white, + width: 0.5, + ), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + (_tripTypeFocused ?? false) + ? layoutColor + : Colors.white, + // : const Color(0xFFD6D5E6), + width: 0.5, + // const Color(0xFFD6D5E6), + ), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: layoutColor, + width: 0.5, + ), + ), + contentPadding: EdgeInsets.symmetric( + horizontal: 10, + vertical: 10, + ), ), - child: Text( - item['dropdown_value'] ?? '', + ), + dropdownBuilder: (context, selectedItem) { + if (selectedItem == null || selectedItem.isEmpty) { + return Text( + "Select ", + style: GoogleFonts.poppins( + color: Colors.grey, + fontSize: 13, + ), + ); + } + return Text( + selectedItem['dropdown_value'] ?? '', style: GoogleFonts.poppins( fontSize: 12, color: Colors.black, ), - ), - ); - }, - ), - dropdownDecoratorProps: DropDownDecoratorProps( - dropdownSearchDecoration: InputDecoration( - // border: InputBorder.none, - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(5), - borderSide: BorderSide( - color: - (_tripTypeFocused ?? false) - ? layoutColor! - : Colors.white, - width: 0.5, - ), - ), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: - (_tripTypeFocused ?? false) - ? layoutColor - : Colors.white, - // : const Color(0xFFD6D5E6), - width: 0.5, - // const Color(0xFFD6D5E6), - ), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide(color: layoutColor, width: 0.5), - ), - contentPadding: EdgeInsets.symmetric( - horizontal: 10, - vertical: 10, - ), + ); + }, + // focusNode: _tripTypeFocusNode, // Assign the correct focus node + // value: selectedPurpose, + // style: TextStyle(fontSize: 12), + // decoration: InputDecoration( + // border: InputBorder.none, + // contentPadding: + // EdgeInsets.symmetric(horizontal: 10), // Proper padding + // ), + onChanged: + purposeList.isNotEmpty + ? (Map? newValue) { + setState(() { + selectedPurpose = newValue?['dropdown_key']; + print("Selected Purpose: ${selectedPurpose}"); + }); + } + : null, ), ), - dropdownBuilder: (context, selectedItem) { - if (selectedItem == null || selectedItem.isEmpty) { - return Text( - "Select ", - style: GoogleFonts.poppins( - color: Colors.grey, - fontSize: 13, - ), - ); - } - return Text( - selectedItem['dropdown_value'] ?? '', - style: GoogleFonts.poppins( - fontSize: 12, - color: Colors.black, - ), - ); - }, - // focusNode: _tripTypeFocusNode, // Assign the correct focus node - // value: selectedPurpose, - // style: TextStyle(fontSize: 12), - // decoration: InputDecoration( - // border: InputBorder.none, - // contentPadding: - // EdgeInsets.symmetric(horizontal: 10), // Proper padding - // ), - onChanged: - purposeList.isNotEmpty - ? (Map? newValue) { - setState(() { - selectedPurpose = newValue?['dropdown_key']; - print("Selected Purpose: ${selectedPurpose}"); - }); - } - : null, - ),),), + ), ), ), if (errorMessages["type_of_visa"] != null) ...[ @@ -933,6 +943,9 @@ class _VisaScreenState extends State { child: TextField( focusNode: _commentsFocusNode, controller: _visaCommentsController, + inputFormatters: [ + FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z0-9 _-]')), + ], style: TextStyle(fontSize: 12), decoration: InputDecoration( labelText: "Comments", diff --git a/lib/Screens/myTemplates/template.dart b/lib/Screens/myTemplates/template.dart index dd85dac..1625014 100644 --- a/lib/Screens/myTemplates/template.dart +++ b/lib/Screens/myTemplates/template.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'dart:io' as io show Directory, File; import 'package:delta_to_html/delta_to_html.dart'; import 'package:flutter/cupertino.dart' as dom; +import 'package:flutter/services.dart'; import 'package:flutter_quill/flutter_quill.dart' hide Text; import 'package:flutter/material.dart'; import 'package:flutter_quill/flutter_quill.dart' hide Text; @@ -636,6 +637,9 @@ class TemplateState extends State