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",
"deposit_on_card",
"deposit_on_cash",
"currency",
// "card_number",
];
@ -269,6 +270,14 @@ class _ForexScreenState extends State<ForexScreen> {
requiredFields.add("delivery_location");
} else {
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
@ -1267,14 +1276,25 @@ class _ForexScreenState extends State<ForexScreen> {
countryList = widget.apiCountryData ?? [];
// Map country codes to country names
countryMap = {
for (var item in countryList)
item['country_code'] as String: item['country_name'] as String,
};
// countryMap = {
// for (var item in countryList)
// item['country_code'] as String: item['country_name'] as String,
//
// };
// 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();
Map<String, String> tempCountryMap = {};
selectedCountry ??= null;
// // Set default selected value
@ -1375,18 +1395,45 @@ class _ForexScreenState extends State<ForexScreen> {
menuProps: const MenuProps(
backgroundColor: Colors.white,
),
itemBuilder:
(context, item, isSelected) => Container(
color: Colors.white,
padding: EdgeInsets.symmetric(
horizontal: 10,
vertical: 6,
),
child: Text(
item,
style: GoogleFonts.poppins(fontSize: 11.5),
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: 2.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,
),
),
],
),
),
);
},
searchFieldProps: TextFieldProps(
decoration: InputDecoration(
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,),
@ -2174,6 +2228,16 @@ class _ForexScreenState extends State<ForexScreen> {
focusNode: focusNodes["_cardNumber"],
controller: textControllers["_cardNumber"],
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(
labelText: "Card Number",
labelStyle: TextStyle(fontSize: 12, color: Colors.grey),
@ -2187,7 +2251,7 @@ class _ForexScreenState extends State<ForexScreen> {
if (errorMessages["card_number"] != null) ...[
SizedBox(height: 5), // Space before error message
Text(
"Required",
errorMessages["card_number"]!,
style: TextStyle(color: Colors.red, fontSize: 12),
),
],

View File

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

View File

@ -123,38 +123,40 @@ class _FlightListWidgetState extends State<FlightListWidget> {
// "Flight Booking List",
// style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
// ),
MouseRegion(
cursor:
widget.isViewMode
? SystemMouseCursors.forbidden
: SystemMouseCursors.click,
child: GestureDetector(
onTap:
widget.isViewMode
? null
: () {
widget.onAddNew("Flight", true);
// checkClass();
print("New data");
},
child: Row(
mainAxisSize:
MainAxisSize.min, // Ensures content fits nicely
children: [
// Text(
// "Add New",
// style: TextStyle(fontSize: 13),
// ),
// SizedBox(width: 8), // spacing between icon and text
Icon(
Icons.add_circle_sharp,
size: 30,
color: Color(0xFF114D8B),
widget.flightList.isNotEmpty
? MouseRegion(
cursor:
widget.isViewMode
? SystemMouseCursors.forbidden
: SystemMouseCursors.click,
child: GestureDetector(
onTap:
widget.isViewMode
? null
: () {
widget.onAddNew("Flight", true);
// checkClass();
print("New data");
},
child: Row(
mainAxisSize:
MainAxisSize.min, // Ensures content fits nicely
children: [
// Text(
// "Add New",
// style: TextStyle(fontSize: 13),
// ),
// SizedBox(width: 8), // spacing between icon and text
Icon(
Icons.add_circle_sharp,
size: 30,
color: Color(0xFF114D8B),
),
],
),
],
),
),
),
),
)
: SizedBox.shrink(),
],
),
const SizedBox(height: 16),

View File

@ -383,6 +383,7 @@ class CreateNewPlansState extends State<CreateNewPlan> {
final TextEditingController _tripTitleController = TextEditingController();
final TextEditingController _descriptionController = TextEditingController();
final TextEditingController _soNumberController = TextEditingController();
final TextEditingController _excepntldescriptionController =
TextEditingController();
final TextEditingController _remarksController = TextEditingController();
@ -420,6 +421,7 @@ class CreateNewPlansState extends State<CreateNewPlan> {
bool showDomestic = false;
bool showInternational = false;
bool hasAction = true;
bool hasSoNumber = false;
bool hasExceptionalClass = false;
late Map<String, String> costCenterMap;
@ -478,7 +480,7 @@ class CreateNewPlansState extends State<CreateNewPlan> {
"description": _descriptionController.text,
"exceptional_plan_reason": _excepntldescriptionController.text,
"functional_department": selectedFuncDept,
"so_number": "12345",
"so_number": _soNumberController.text,
"created_by": selfId,
"updated_by": selfId,
"is_active": "1",
@ -503,6 +505,7 @@ class CreateNewPlansState extends State<CreateNewPlan> {
"description",
"excepntldescription",
"functional_department",
"so_number",
];
void handleItineraryUpdate(String type, List<Map<String, dynamic>> newList) {
@ -666,6 +669,12 @@ class CreateNewPlansState extends State<CreateNewPlan> {
_descriptionController.text =
widget.selectedPlanData['description'] ?? '';
_soNumberController.text = widget.selectedPlanData['so_number'] ?? '';
if (_soNumberController.text != "") {
hasSoNumber = true;
}
_excepntldescriptionController.text =
widget.selectedPlanData['exceptional_plan_reason'] ?? '';
@ -1159,6 +1168,8 @@ class CreateNewPlansState extends State<CreateNewPlan> {
"purpose_of_travel": selectedPurpose,
if (hasExceptionalClass)
"exceptional_plan_reason": _excepntldescriptionController.text,
if (hasSoNumber) "so_number": _soNumberController.text,
};
print("validateForm.....3");
for (var entry in requiredFields.entries) {
@ -1771,7 +1782,7 @@ class CreateNewPlansState extends State<CreateNewPlan> {
children: [
_buildDescriptionColumn(isDesktop),
SizedBox(height: 15),
_buildNonDescriptionColumn(),
if (hasExceptionalClass) _buildNonDescriptionColumn(),
],
),
@ -1895,6 +1906,10 @@ class CreateNewPlansState extends State<CreateNewPlan> {
isFocused: false,
padding: const EdgeInsets.symmetric(horizontal: 0),
// 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,
child: SizedBox(
height: 35,
@ -2369,6 +2384,7 @@ class CreateNewPlansState extends State<CreateNewPlan> {
),
SizedBox(height: 5),
CustomTextFieldWrapper(
width: isDesktop ? MediaQuery.of(context).size.width * 0.15 : null,
// isFocused: focusStates["cost_center_idFocused"] ??
isFocused: false,
padding: const EdgeInsets.symmetric(horizontal: 0),
@ -2572,7 +2588,7 @@ class CreateNewPlansState extends State<CreateNewPlan> {
CustomTextFieldWrapper(
width:
isDesktop
? MediaQuery.of(context).size.width * 0.2
? MediaQuery.of(context).size.width * 0.15
: MediaQuery.of(context).size.width * 0.88,
// isFocused: focusStates["purpose_of_travelFocused"] ?? false,
isFocused: false,
@ -2907,11 +2923,26 @@ class CreateNewPlansState extends State<CreateNewPlan> {
widget.isViewMode
? null
: (Map<String, dynamic>? newValue) {
dynamic val =
newValue?['dropdown_value']
.toString();
setState(() {
selectedFuncDept =
newValue?['dropdown_key']
.toString();
if (val ==
" Others (Kindly enter SO number )") {
hasSoNumber = true;
} else {
hasSoNumber = false;
_soNumberController.text = "";
}
});
print(
"selectedFuncDept1 - ${newValue?['dropdown_value'].toString()}",
);
print(
"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 [
CustomTextFieldWrapper(
// isFocused: focusStates["trip_plannedFocused"] ?? false,
width:
widget.isDesktop
? MediaQuery.of(context).size.width * 0.32
: MediaQuery.of(context).size.width * 0.88,
isFocused: false,
padding: const EdgeInsets.symmetric(horizontal: 0),
isDesktop: isDesktop,
@ -3425,9 +3510,10 @@ class CreateNewPlansState extends State<CreateNewPlan> {
CustomTextFieldWrapper(
isFocused: focusStates["descriptionFocused"] ?? false,
// isFocused: _isdescriptionFocused,
// width: isDesktop
// ? MediaQuery.of(context).size.width * 0.38
// : MediaQuery.of(context).size.width * 0.85,
width:
widget.isDesktop
? MediaQuery.of(context).size.width * 0.32
: MediaQuery.of(context).size.width * 0.88,
isDesktop: widget.isDesktop,
child: SizedBox(
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;
List<dynamic>? resolvedUserData;
// String? userIdsApi;
late List<String> userIdsApi;
late List<String> groupIdsApi;
late Map<String, String> userMap;
@ -169,7 +170,7 @@ class _OfficeDetailsState extends State<OfficeDetails> {
label,
field,
value,
userId,
userId ?? "",
);
if (response.isNotEmpty) {
_clearError(field);
@ -224,6 +225,7 @@ class _OfficeDetailsState extends State<OfficeDetails> {
Future<void> fetchUsers() async {
try {
print("Test Users");
List<dynamic> users = await apiService.fetchUsers();
setState(() {
// apiUserData = users;
@ -249,10 +251,12 @@ class _OfficeDetailsState extends State<OfficeDetails> {
Future<void> fetchDepartment() async {
try {
print("Test department");
List<dynamic> department = await apiService.fetchDepartmentCostCenter();
setState(() {
apiCostData = department;
});
print("Test department Completeed- $apiCostData");
} catch (e) {
print('Error fetching department list: $e');
}
@ -260,6 +264,7 @@ class _OfficeDetailsState extends State<OfficeDetails> {
Future<void> fetchFindGroup() async {
try {
print("Test Groups");
final result = await apiService.fetchAllGroup();
setState(() {
apiAllGroups = result;
@ -430,14 +435,17 @@ class _OfficeDetailsState extends State<OfficeDetails> {
child: TextField(
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
controller: widget.controllers["employeeCode"],
enabled: !widget.isViewMode,
onChanged: (value) {
_clearError("employee_code");
final updaterUserId = widget.userIdApi ?? "";
apiCheckDuplicate(
"Employee Code",
"employee_code",
value,
widget.userIdApi,
updaterUserId,
);
},
decoration: InputDecoration(
@ -526,7 +534,11 @@ class _OfficeDetailsState extends State<OfficeDetails> {
// Map department_id to department_name
Map<String, String> departmentMap = {
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(