sonumber added
This commit is contained in:
parent
1c77a03067
commit
4926b48e4f
@ -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),
|
||||
),
|
||||
],
|
||||
|
||||
@ -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 ...",
|
||||
|
||||
@ -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),
|
||||
|
||||
@ -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
@ -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(
|
||||
|
||||
Loading…
Reference in New Issue
Block a user