sonumber added

This commit is contained in:
venbaittech 2025-06-23 16:10:39 +05:30
parent 1c77a03067
commit 4926b48e4f
6 changed files with 1990 additions and 1488 deletions

View File

@ -260,6 +260,7 @@ class _ForexScreenState extends State<ForexScreen> {
"country_code", "country_code",
"deposit_on_card", "deposit_on_card",
"deposit_on_cash", "deposit_on_cash",
"currency",
// "card_number", // "card_number",
]; ];
@ -269,6 +270,14 @@ class _ForexScreenState extends State<ForexScreen> {
requiredFields.add("delivery_location"); requiredFields.add("delivery_location");
} else { } else {
requiredFields.add("card_number"); requiredFields.add("card_number");
// Check if card_number has at least 16 digits
}
final cardNumber = data["card_number"]?.toString() ?? '';
if (cardNumber.length < 16) {
// Show error or return false
print("Card number must be 16 digits");
errorMessages["card_number"] = "Card number must be 16 digits";
} }
// Check validation for each field // Check validation for each field
@ -1267,14 +1276,25 @@ class _ForexScreenState extends State<ForexScreen> {
countryList = widget.apiCountryData ?? []; countryList = widget.apiCountryData ?? [];
// Map country codes to country names // Map country codes to country names
countryMap = { // countryMap = {
for (var item in countryList) // for (var item in countryList)
item['country_code'] as String: item['country_name'] as String, // item['country_code'] as String: item['country_name'] as String,
}; //
// };
// Extract only country codes for processing // Extract only country codes for processing
// countryCodes = countryMap.keys.toList();
countryMap = {
for (var country in countryList)
(country['country_code'] ?? ''):
'${country['country_name'] ?? ''} (${country['country_code'] ?? ''})',
};
countryCodes = countryMap.keys.toList(); countryCodes = countryMap.keys.toList();
Map<String, String> tempCountryMap = {};
selectedCountry ??= null; selectedCountry ??= null;
// // Set default selected value // // Set default selected value
@ -1375,18 +1395,45 @@ class _ForexScreenState extends State<ForexScreen> {
menuProps: const MenuProps( menuProps: const MenuProps(
backgroundColor: Colors.white, backgroundColor: Colors.white,
), ),
itemBuilder: itemBuilder: (context, item, isSelected) {
(context, item, isSelected) => Container( 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, color: Colors.white,
padding: EdgeInsets.symmetric( padding: EdgeInsets.symmetric(
horizontal: 10, horizontal: 10,
vertical: 6, vertical: 6,
), ),
child: Text( child: Padding(
item, padding: const EdgeInsets.only(right: 2.0),
style: GoogleFonts.poppins(fontSize: 11.5), 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,
),
),
],
),
),
);
},
searchFieldProps: TextFieldProps( searchFieldProps: TextFieldProps(
decoration: InputDecoration( decoration: InputDecoration(
hintText: "Search ...", hintText: "Search ...",
@ -1489,6 +1536,13 @@ class _ForexScreenState extends State<ForexScreen> {
), ),
), ),
), ),
if (errorMessages["currency"] != null) ...[
SizedBox(height: 5), // Space before error message
Text(
errorMessages["currency"]!,
style: TextStyle(color: Colors.red, fontSize: 12),
),
],
], ],
), ),
// if (isDesktop)SizedBox(width: 8,) else SizedBox(height: 8,), // if (isDesktop)SizedBox(width: 8,) else SizedBox(height: 8,),
@ -2174,6 +2228,16 @@ class _ForexScreenState extends State<ForexScreen> {
focusNode: focusNodes["_cardNumber"], focusNode: focusNodes["_cardNumber"],
controller: textControllers["_cardNumber"], controller: textControllers["_cardNumber"],
style: const TextStyle(fontSize: 12), style: const TextStyle(fontSize: 12),
inputFormatters: [
FilteringTextInputFormatter.allow(RegExp(r'[0-9\s]')),
LengthLimitingTextInputFormatter(16),
],
onChanged: (value) {
setState(() {
errorMessages.remove("card_number");
});
},
decoration: const InputDecoration( decoration: const InputDecoration(
labelText: "Card Number", labelText: "Card Number",
labelStyle: TextStyle(fontSize: 12, color: Colors.grey), labelStyle: TextStyle(fontSize: 12, color: Colors.grey),
@ -2187,7 +2251,7 @@ class _ForexScreenState extends State<ForexScreen> {
if (errorMessages["card_number"] != null) ...[ if (errorMessages["card_number"] != null) ...[
SizedBox(height: 5), // Space before error message SizedBox(height: 5), // Space before error message
Text( Text(
"Required", errorMessages["card_number"]!,
style: TextStyle(color: Colors.red, fontSize: 12), style: TextStyle(color: Colors.red, fontSize: 12),
), ),
], ],

View File

@ -353,9 +353,15 @@ class _VisaScreenState extends State<VisaScreen> {
countryList = widget.apiCountryData ?? []; countryList = widget.apiCountryData ?? [];
// Map country codes to country names // Map country codes to country names
// countryMap = {
// for (var item in countryList)
// item['country_code'] as String: item['country_name'] as String,
// };
countryMap = { countryMap = {
for (var item in countryList) for (var country in countryList)
item['country_code'] as String: item['country_name'] as String, (country['country_code'] ?? ''):
'${country['country_name'] ?? ''} (${country['country_code'] ?? ''})',
}; };
// Extract only country codes for processing // Extract only country codes for processing
@ -526,18 +532,39 @@ class _VisaScreenState extends State<VisaScreen> {
fit: FlexFit.loose, fit: FlexFit.loose,
constraints: BoxConstraints(maxHeight: 200), constraints: BoxConstraints(maxHeight: 200),
menuProps: const MenuProps(backgroundColor: Colors.white), menuProps: const MenuProps(backgroundColor: Colors.white),
itemBuilder: itemBuilder: (context, item, isSelected) {
(context, item, isSelected) => Container( 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, color: Colors.white,
padding: EdgeInsets.symmetric( padding: EdgeInsets.symmetric(
horizontal: 10, horizontal: 10,
vertical: 6, vertical: 6,
), ),
child: Text( child: Padding(
item, padding: const EdgeInsets.only(right: 4.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
countryName,
style: GoogleFonts.poppins(fontSize: 11.5), style: GoogleFonts.poppins(fontSize: 11.5),
), ),
Text(
countryCode,
style: GoogleFonts.poppins(
fontSize: 11.5,
color: Colors.grey,
), ),
),
],
),
),
);
},
searchFieldProps: TextFieldProps( searchFieldProps: TextFieldProps(
decoration: InputDecoration( decoration: InputDecoration(
hintText: "Search ...", hintText: "Search ...",

View File

@ -123,7 +123,8 @@ class _FlightListWidgetState extends State<FlightListWidget> {
// "Flight Booking List", // "Flight Booking List",
// style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), // style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
// ), // ),
MouseRegion( widget.flightList.isNotEmpty
? MouseRegion(
cursor: cursor:
widget.isViewMode widget.isViewMode
? SystemMouseCursors.forbidden ? SystemMouseCursors.forbidden
@ -154,7 +155,8 @@ class _FlightListWidgetState extends State<FlightListWidget> {
], ],
), ),
), ),
), )
: SizedBox.shrink(),
], ],
), ),
const SizedBox(height: 16), const SizedBox(height: 16),

View File

@ -383,6 +383,7 @@ class CreateNewPlansState extends State<CreateNewPlan> {
final TextEditingController _tripTitleController = TextEditingController(); final TextEditingController _tripTitleController = TextEditingController();
final TextEditingController _descriptionController = TextEditingController(); final TextEditingController _descriptionController = TextEditingController();
final TextEditingController _soNumberController = TextEditingController();
final TextEditingController _excepntldescriptionController = final TextEditingController _excepntldescriptionController =
TextEditingController(); TextEditingController();
final TextEditingController _remarksController = TextEditingController(); final TextEditingController _remarksController = TextEditingController();
@ -420,6 +421,7 @@ class CreateNewPlansState extends State<CreateNewPlan> {
bool showDomestic = false; bool showDomestic = false;
bool showInternational = false; bool showInternational = false;
bool hasAction = true; bool hasAction = true;
bool hasSoNumber = false;
bool hasExceptionalClass = false; bool hasExceptionalClass = false;
late Map<String, String> costCenterMap; late Map<String, String> costCenterMap;
@ -478,7 +480,7 @@ class CreateNewPlansState extends State<CreateNewPlan> {
"description": _descriptionController.text, "description": _descriptionController.text,
"exceptional_plan_reason": _excepntldescriptionController.text, "exceptional_plan_reason": _excepntldescriptionController.text,
"functional_department": selectedFuncDept, "functional_department": selectedFuncDept,
"so_number": "12345", "so_number": _soNumberController.text,
"created_by": selfId, "created_by": selfId,
"updated_by": selfId, "updated_by": selfId,
"is_active": "1", "is_active": "1",
@ -503,6 +505,7 @@ class CreateNewPlansState extends State<CreateNewPlan> {
"description", "description",
"excepntldescription", "excepntldescription",
"functional_department", "functional_department",
"so_number",
]; ];
void handleItineraryUpdate(String type, List<Map<String, dynamic>> newList) { void handleItineraryUpdate(String type, List<Map<String, dynamic>> newList) {
@ -666,6 +669,12 @@ class CreateNewPlansState extends State<CreateNewPlan> {
_descriptionController.text = _descriptionController.text =
widget.selectedPlanData['description'] ?? ''; widget.selectedPlanData['description'] ?? '';
_soNumberController.text = widget.selectedPlanData['so_number'] ?? '';
if (_soNumberController.text != "") {
hasSoNumber = true;
}
_excepntldescriptionController.text = _excepntldescriptionController.text =
widget.selectedPlanData['exceptional_plan_reason'] ?? ''; widget.selectedPlanData['exceptional_plan_reason'] ?? '';
@ -1159,6 +1168,8 @@ class CreateNewPlansState extends State<CreateNewPlan> {
"purpose_of_travel": selectedPurpose, "purpose_of_travel": selectedPurpose,
if (hasExceptionalClass) if (hasExceptionalClass)
"exceptional_plan_reason": _excepntldescriptionController.text, "exceptional_plan_reason": _excepntldescriptionController.text,
if (hasSoNumber) "so_number": _soNumberController.text,
}; };
print("validateForm.....3"); print("validateForm.....3");
for (var entry in requiredFields.entries) { for (var entry in requiredFields.entries) {
@ -1771,7 +1782,7 @@ class CreateNewPlansState extends State<CreateNewPlan> {
children: [ children: [
_buildDescriptionColumn(isDesktop), _buildDescriptionColumn(isDesktop),
SizedBox(height: 15), SizedBox(height: 15),
_buildNonDescriptionColumn(), if (hasExceptionalClass) _buildNonDescriptionColumn(),
], ],
), ),
@ -1895,6 +1906,10 @@ class CreateNewPlansState extends State<CreateNewPlan> {
isFocused: false, isFocused: false,
padding: const EdgeInsets.symmetric(horizontal: 0), padding: const EdgeInsets.symmetric(horizontal: 0),
// isFocused: focusStates["trip_typeFocused"] ?? false, // isFocused: focusStates["trip_typeFocused"] ?? false,
width:
widget.isDesktop
? MediaQuery.of(context).size.width * 0.32
: MediaQuery.of(context).size.width * 0.88,
isDesktop: widget.isDesktop, isDesktop: widget.isDesktop,
child: SizedBox( child: SizedBox(
height: 35, height: 35,
@ -2369,6 +2384,7 @@ class CreateNewPlansState extends State<CreateNewPlan> {
), ),
SizedBox(height: 5), SizedBox(height: 5),
CustomTextFieldWrapper( CustomTextFieldWrapper(
width: isDesktop ? MediaQuery.of(context).size.width * 0.15 : null,
// isFocused: focusStates["cost_center_idFocused"] ?? // isFocused: focusStates["cost_center_idFocused"] ??
isFocused: false, isFocused: false,
padding: const EdgeInsets.symmetric(horizontal: 0), padding: const EdgeInsets.symmetric(horizontal: 0),
@ -2572,7 +2588,7 @@ class CreateNewPlansState extends State<CreateNewPlan> {
CustomTextFieldWrapper( CustomTextFieldWrapper(
width: width:
isDesktop isDesktop
? MediaQuery.of(context).size.width * 0.2 ? MediaQuery.of(context).size.width * 0.15
: MediaQuery.of(context).size.width * 0.88, : MediaQuery.of(context).size.width * 0.88,
// isFocused: focusStates["purpose_of_travelFocused"] ?? false, // isFocused: focusStates["purpose_of_travelFocused"] ?? false,
isFocused: false, isFocused: false,
@ -2907,11 +2923,26 @@ class CreateNewPlansState extends State<CreateNewPlan> {
widget.isViewMode widget.isViewMode
? null ? null
: (Map<String, dynamic>? newValue) { : (Map<String, dynamic>? newValue) {
dynamic val =
newValue?['dropdown_value']
.toString();
setState(() { setState(() {
selectedFuncDept = selectedFuncDept =
newValue?['dropdown_key'] newValue?['dropdown_key']
.toString(); .toString();
if (val ==
" Others (Kindly enter SO number )") {
hasSoNumber = true;
} else {
hasSoNumber = false;
_soNumberController.text = "";
}
}); });
print(
"selectedFuncDept1 - ${newValue?['dropdown_value'].toString()}",
);
print( print(
"selectedFuncDept - $selectedFuncDept", "selectedFuncDept - $selectedFuncDept",
); );
@ -2959,6 +2990,56 @@ class CreateNewPlansState extends State<CreateNewPlan> {
), ),
], ],
), ),
SizedBox(width: 25, height: 5),
hasSoNumber
? Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"SO Number *", // Your label
style: GoogleFonts.poppins(
fontSize: 12,
fontWeight: FontWeight.w600,
color: Color(0xFF575A74),
),
),
SizedBox(height: 5),
CustomTextFieldWrapper(
isFocused: focusStates["so_numberFocused"] ?? false,
// isFocused: _isdescriptionFocused,
width:
widget.isDesktop
? MediaQuery.of(context).size.width * 0.2
: null,
isDesktop: widget.isDesktop,
child: SizedBox(
height: 35,
child: TextField(
focusNode: focusNodes["so_numberFocusNode"],
controller: _soNumberController,
style: TextStyle(fontSize: 12),
decoration: InputDecoration(
labelText: "SO Number",
labelStyle: TextStyle(fontSize: 12, color: Colors.grey),
floatingLabelBehavior: FloatingLabelBehavior.never,
border: InputBorder.none,
contentPadding: EdgeInsets.symmetric(vertical: 16),
),
),
),
),
if (validationErrors["so_number"] != null)
Padding(
padding: EdgeInsets.only(top: 4),
child: Text(
validationErrors["so_number"]!,
style: GoogleFonts.poppins(fontSize: 12, color: Colors.red),
),
),
],
)
: SizedBox.shrink(),
]; ];
} }
@ -2972,6 +3053,10 @@ class CreateNewPlansState extends State<CreateNewPlan> {
return [ return [
CustomTextFieldWrapper( CustomTextFieldWrapper(
// isFocused: focusStates["trip_plannedFocused"] ?? false, // isFocused: focusStates["trip_plannedFocused"] ?? false,
width:
widget.isDesktop
? MediaQuery.of(context).size.width * 0.32
: MediaQuery.of(context).size.width * 0.88,
isFocused: false, isFocused: false,
padding: const EdgeInsets.symmetric(horizontal: 0), padding: const EdgeInsets.symmetric(horizontal: 0),
isDesktop: isDesktop, isDesktop: isDesktop,
@ -3425,9 +3510,10 @@ class CreateNewPlansState extends State<CreateNewPlan> {
CustomTextFieldWrapper( CustomTextFieldWrapper(
isFocused: focusStates["descriptionFocused"] ?? false, isFocused: focusStates["descriptionFocused"] ?? false,
// isFocused: _isdescriptionFocused, // isFocused: _isdescriptionFocused,
// width: isDesktop width:
// ? MediaQuery.of(context).size.width * 0.38 widget.isDesktop
// : MediaQuery.of(context).size.width * 0.85, ? MediaQuery.of(context).size.width * 0.32
: MediaQuery.of(context).size.width * 0.88,
isDesktop: widget.isDesktop, isDesktop: widget.isDesktop,
child: SizedBox( child: SizedBox(
height: 55, height: 55,

File diff suppressed because it is too large Load Diff

View File

@ -76,6 +76,7 @@ class _OfficeDetailsState extends State<OfficeDetails> {
late Future<List<dynamic>> futureUsers; late Future<List<dynamic>> futureUsers;
List<dynamic>? resolvedUserData; List<dynamic>? resolvedUserData;
// String? userIdsApi;
late List<String> userIdsApi; late List<String> userIdsApi;
late List<String> groupIdsApi; late List<String> groupIdsApi;
late Map<String, String> userMap; late Map<String, String> userMap;
@ -169,7 +170,7 @@ class _OfficeDetailsState extends State<OfficeDetails> {
label, label,
field, field,
value, value,
userId, userId ?? "",
); );
if (response.isNotEmpty) { if (response.isNotEmpty) {
_clearError(field); _clearError(field);
@ -224,6 +225,7 @@ class _OfficeDetailsState extends State<OfficeDetails> {
Future<void> fetchUsers() async { Future<void> fetchUsers() async {
try { try {
print("Test Users");
List<dynamic> users = await apiService.fetchUsers(); List<dynamic> users = await apiService.fetchUsers();
setState(() { setState(() {
// apiUserData = users; // apiUserData = users;
@ -249,10 +251,12 @@ class _OfficeDetailsState extends State<OfficeDetails> {
Future<void> fetchDepartment() async { Future<void> fetchDepartment() async {
try { try {
print("Test department");
List<dynamic> department = await apiService.fetchDepartmentCostCenter(); List<dynamic> department = await apiService.fetchDepartmentCostCenter();
setState(() { setState(() {
apiCostData = department; apiCostData = department;
}); });
print("Test department Completeed- $apiCostData");
} catch (e) { } catch (e) {
print('Error fetching department list: $e'); print('Error fetching department list: $e');
} }
@ -260,6 +264,7 @@ class _OfficeDetailsState extends State<OfficeDetails> {
Future<void> fetchFindGroup() async { Future<void> fetchFindGroup() async {
try { try {
print("Test Groups");
final result = await apiService.fetchAllGroup(); final result = await apiService.fetchAllGroup();
setState(() { setState(() {
apiAllGroups = result; apiAllGroups = result;
@ -430,14 +435,17 @@ class _OfficeDetailsState extends State<OfficeDetails> {
child: TextField( child: TextField(
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black), style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
controller: widget.controllers["employeeCode"], controller: widget.controllers["employeeCode"],
enabled: !widget.isViewMode, enabled: !widget.isViewMode,
onChanged: (value) { onChanged: (value) {
_clearError("employee_code"); _clearError("employee_code");
final updaterUserId = widget.userIdApi ?? "";
apiCheckDuplicate( apiCheckDuplicate(
"Employee Code", "Employee Code",
"employee_code", "employee_code",
value, value,
widget.userIdApi, updaterUserId,
); );
}, },
decoration: InputDecoration( decoration: InputDecoration(
@ -526,7 +534,11 @@ class _OfficeDetailsState extends State<OfficeDetails> {
// Map department_id to department_name // Map department_id to department_name
Map<String, String> departmentMap = { Map<String, String> departmentMap = {
for (var item in apiCostData ?? []) for (var item in apiCostData ?? [])
item['department_id'] as String: item['name'] as String, if (item['dropdown_key'] != null &&
item['dropdown_value'] != null &&
int.tryParse(item['dropdown_key'].toString()) != 5)
item['dropdown_key'].toString(): item['dropdown_value'].toString(),
// item['department_id'] as String: item['name'] as String,
}; };
return Column( return Column(