merge with old code
This commit is contained in:
commit
03a5fbfaf1
BIN
assets/images/IconsImg/Frame.png
Normal file
BIN
assets/images/IconsImg/Frame.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 391 B |
BIN
assets/images/IconsImg/ViceVersaArrow.png
Normal file
BIN
assets/images/IconsImg/ViceVersaArrow.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 75 KiB |
@ -651,6 +651,16 @@ class _ListAllPlansState extends State<ListAllPlans> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
columns: [
|
columns: [
|
||||||
|
DataColumn(
|
||||||
|
label: Text(
|
||||||
|
'S.NO',
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 13,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
DataColumn(
|
DataColumn(
|
||||||
label: Text(
|
label: Text(
|
||||||
'Trip ID',
|
'Trip ID',
|
||||||
@ -669,6 +679,16 @@ class _ListAllPlansState extends State<ListAllPlans> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
|
DataColumn(
|
||||||
|
label: Text(
|
||||||
|
'Trip Type',
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 13,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
DataColumn(
|
DataColumn(
|
||||||
label: Text(
|
label: Text(
|
||||||
'Emp Code',
|
'Emp Code',
|
||||||
@ -687,15 +707,7 @@ class _ListAllPlansState extends State<ListAllPlans> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
DataColumn(
|
|
||||||
label: Text(
|
|
||||||
'Trip Type',
|
|
||||||
style: GoogleFonts.poppins(
|
|
||||||
fontSize: 13,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
DataColumn(
|
DataColumn(
|
||||||
label: Text(
|
label: Text(
|
||||||
'Created On',
|
'Created On',
|
||||||
@ -725,9 +737,21 @@ class _ListAllPlansState extends State<ListAllPlans> {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
rows:
|
rows:
|
||||||
paginatedPlans.map((plan) {
|
// paginatedPlans.map((plan)
|
||||||
|
paginatedPlans.asMap().entries.map((entry) {
|
||||||
|
int index = entry.key;
|
||||||
|
var plan = entry.value;
|
||||||
return DataRow(
|
return DataRow(
|
||||||
cells: [
|
cells: [
|
||||||
|
DataCell(
|
||||||
|
Text(
|
||||||
|
"${index + 1}",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 13,
|
||||||
|
fontFamily: "Inter",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
DataCell(
|
DataCell(
|
||||||
Text(
|
Text(
|
||||||
plan.planId,
|
plan.planId,
|
||||||
@ -748,6 +772,15 @@ class _ListAllPlansState extends State<ListAllPlans> {
|
|||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
DataCell(
|
||||||
|
Text(
|
||||||
|
plan.tripType,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 13,
|
||||||
|
fontFamily: "Inter",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
DataCell(
|
DataCell(
|
||||||
Text(
|
Text(
|
||||||
plan.employeeCode ?? " - ",
|
plan.employeeCode ?? " - ",
|
||||||
@ -768,15 +801,7 @@ class _ListAllPlansState extends State<ListAllPlans> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
DataCell(
|
|
||||||
Text(
|
|
||||||
plan.tripType,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 13,
|
|
||||||
fontFamily: "Inter",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
DataCell(
|
DataCell(
|
||||||
Text(
|
Text(
|
||||||
_formatDate(plan.createdOn),
|
_formatDate(plan.createdOn),
|
||||||
@ -867,6 +892,10 @@ class _ListAllPlansState extends State<ListAllPlans> {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
if (plan.statusValue ==
|
||||||
|
"Pending Approval" ||
|
||||||
|
plan.statusValue ==
|
||||||
|
"Partially Approved")
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Image.asset(
|
icon: Image.asset(
|
||||||
'assets/images/IconsImg/edit.png',
|
'assets/images/IconsImg/edit.png',
|
||||||
|
|||||||
@ -97,7 +97,7 @@ class _ApprovalListState extends State<ApprovalList> {
|
|||||||
setState(() {
|
setState(() {
|
||||||
futurePlans = fetchPlans();
|
futurePlans = fetchPlans();
|
||||||
});
|
});
|
||||||
|
print("Token availa");
|
||||||
// Wait for futurePlans to be fetched and update allPlans
|
// Wait for futurePlans to be fetched and update allPlans
|
||||||
futurePlans.then((plans) {
|
futurePlans.then((plans) {
|
||||||
setState(() {
|
setState(() {
|
||||||
@ -186,7 +186,9 @@ class _ApprovalListState extends State<ApprovalList> {
|
|||||||
|
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
final data = json.decode(response.body);
|
final data = json.decode(response.body);
|
||||||
|
print('plansJson1');
|
||||||
List<dynamic> plansJson = data['data'];
|
List<dynamic> plansJson = data['data'];
|
||||||
|
print('plansJson $plansJson');
|
||||||
return plansJson.map((json) => Plan.fromJson(json)).toList();
|
return plansJson.map((json) => Plan.fromJson(json)).toList();
|
||||||
} else {
|
} else {
|
||||||
throw Exception('Failed to load plans');
|
throw Exception('Failed to load plans');
|
||||||
@ -345,6 +347,8 @@ class _ApprovalListState extends State<ApprovalList> {
|
|||||||
(plan.userName?.toLowerCase().contains(lowerQuery) ?? false) ||
|
(plan.userName?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||||
(plan.travellerName?.toLowerCase().contains(lowerQuery) ??
|
(plan.travellerName?.toLowerCase().contains(lowerQuery) ??
|
||||||
false) ||
|
false) ||
|
||||||
|
(plan.approverName?.toLowerCase().contains(lowerQuery) ??
|
||||||
|
false) ||
|
||||||
(plan.tripType?.toLowerCase().contains(lowerQuery) ?? false) ||
|
(plan.tripType?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||||
(plan.createdOn?.toLowerCase().contains(lowerQuery) ?? false) ||
|
(plan.createdOn?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||||
(plan.statusValue?.toLowerCase().contains(lowerQuery) ?? false);
|
(plan.statusValue?.toLowerCase().contains(lowerQuery) ?? false);
|
||||||
@ -672,7 +676,7 @@ class _ApprovalListState extends State<ApprovalList> {
|
|||||||
),
|
),
|
||||||
DataColumn(
|
DataColumn(
|
||||||
label: Text(
|
label: Text(
|
||||||
'Emp Code',
|
'Traveller',
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
@ -681,7 +685,7 @@ class _ApprovalListState extends State<ApprovalList> {
|
|||||||
),
|
),
|
||||||
DataColumn(
|
DataColumn(
|
||||||
label: Text(
|
label: Text(
|
||||||
'Traveller',
|
'Approver',
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
@ -751,19 +755,40 @@ class _ApprovalListState extends State<ApprovalList> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
DataCell(
|
DataCell(
|
||||||
Text(
|
Column(
|
||||||
plan.employeeCode ?? " - ",
|
crossAxisAlignment:
|
||||||
style: TextStyle(
|
CrossAxisAlignment.start,
|
||||||
fontSize: 13,
|
mainAxisAlignment:
|
||||||
fontFamily: "Inter",
|
MainAxisAlignment.center,
|
||||||
),
|
|
||||||
),
|
children: [
|
||||||
),
|
SizedBox(height: 1),
|
||||||
DataCell(
|
|
||||||
Text(
|
Text(
|
||||||
plan.userName.isNotEmpty
|
plan.userName.isNotEmpty
|
||||||
? plan.userName
|
? plan.userName
|
||||||
: plan.travellerName,
|
: plan.travellerName,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 12,
|
||||||
|
fontFamily: "Inter",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: 3),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
"(${plan.employeeCode})" ??
|
||||||
|
" - ",
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 10,
|
||||||
|
// fontFamily: "Inter",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
DataCell(
|
||||||
|
Text(
|
||||||
|
plan.approverName ?? " ",
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
fontFamily: "Inter",
|
fontFamily: "Inter",
|
||||||
@ -875,6 +900,10 @@ class _ApprovalListState extends State<ApprovalList> {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
if (plan.statusValue ==
|
||||||
|
"Pending Approval" ||
|
||||||
|
plan.statusValue ==
|
||||||
|
"Partially Approved")
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Image.asset(
|
icon: Image.asset(
|
||||||
'assets/images/IconsImg/edit.png',
|
'assets/images/IconsImg/edit.png',
|
||||||
@ -890,6 +919,9 @@ class _ApprovalListState extends State<ApprovalList> {
|
|||||||
print(
|
print(
|
||||||
"Approver Edit2 : ${plan.delegaterId}",
|
"Approver Edit2 : ${plan.delegaterId}",
|
||||||
);
|
);
|
||||||
|
print(
|
||||||
|
"Approver Edit3 : ${plan.approver_status}",
|
||||||
|
);
|
||||||
Navigator.pop(
|
Navigator.pop(
|
||||||
context,
|
context,
|
||||||
);
|
);
|
||||||
@ -1130,6 +1162,10 @@ class _ApprovalListState extends State<ApprovalList> {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
if (plan.statusValue ==
|
||||||
|
"Pending Approval" ||
|
||||||
|
plan.statusValue ==
|
||||||
|
"Partially Approved")
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Image.asset(
|
icon: Image.asset(
|
||||||
'assets/images/IconsImg/edit.png',
|
'assets/images/IconsImg/edit.png',
|
||||||
@ -1139,7 +1175,13 @@ class _ApprovalListState extends State<ApprovalList> {
|
|||||||
tooltip:
|
tooltip:
|
||||||
'Edit The Trip Details',
|
'Edit The Trip Details',
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.pop(context);
|
Navigator.pop(
|
||||||
|
context,
|
||||||
|
);
|
||||||
|
print(
|
||||||
|
"Approver Edit3 : ${plan.approver_status}",
|
||||||
|
);
|
||||||
|
|
||||||
ApiService.viewPlanForApprover(
|
ApiService.viewPlanForApprover(
|
||||||
context,
|
context,
|
||||||
plan.planId,
|
plan.planId,
|
||||||
|
|||||||
@ -127,7 +127,6 @@ class ForexDataState extends State<ForexData> {
|
|||||||
selectedCountryName =
|
selectedCountryName =
|
||||||
data['country_name']; // For dropdown label or display
|
data['country_name']; // For dropdown label or display
|
||||||
selectedCurrency = data['currency']; // Optional if used elsewhere
|
selectedCurrency = data['currency']; // Optional if used elsewhere
|
||||||
|
|
||||||
controllers['currency']?.text = data['currency'] ?? '';
|
controllers['currency']?.text = data['currency'] ?? '';
|
||||||
controllers['cash']?.text = data['cash_percentage'] ?? '';
|
controllers['cash']?.text = data['cash_percentage'] ?? '';
|
||||||
controllers['card']?.text = data['card_percentage'] ?? '';
|
controllers['card']?.text = data['card_percentage'] ?? '';
|
||||||
@ -336,6 +335,16 @@ class ForexDataState extends State<ForexData> {
|
|||||||
|
|
||||||
selectedCountry ??= null;
|
selectedCountry ??= null;
|
||||||
|
|
||||||
|
void setCurrencyFromSelectedCountry(String selectedCountryCode) {
|
||||||
|
final matchedCountry = countryList.firstWhere(
|
||||||
|
(item) => item['country_code'] == selectedCountryCode,
|
||||||
|
orElse: () => {},
|
||||||
|
);
|
||||||
|
|
||||||
|
final currency = matchedCountry['currency'] ?? '';
|
||||||
|
controllers["currency"]?.text = currency;
|
||||||
|
}
|
||||||
|
|
||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
backgroundColor: Colors.white,
|
backgroundColor: Colors.white,
|
||||||
contentPadding: const EdgeInsets.fromLTRB(34, 30, 34, 30),
|
contentPadding: const EdgeInsets.fromLTRB(34, 30, 34, 30),
|
||||||
@ -426,6 +435,7 @@ class ForexDataState extends State<ForexData> {
|
|||||||
.firstWhere((entry) => entry.value == newValue)
|
.firstWhere((entry) => entry.value == newValue)
|
||||||
.key;
|
.key;
|
||||||
selectedCountryName = newValue;
|
selectedCountryName = newValue;
|
||||||
|
setCurrencyFromSelectedCountry(selectedCountry!);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -457,6 +467,7 @@ class ForexDataState extends State<ForexData> {
|
|||||||
isFocused: false,
|
isFocused: false,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
|
|
||||||
// width: isDesktop
|
// width: isDesktop
|
||||||
// ? MediaQuery.of(context).size.width * 0.330
|
// ? MediaQuery.of(context).size.width * 0.330
|
||||||
// : MediaQuery.of(context).size.width * 0.66,
|
// : MediaQuery.of(context).size.width * 0.66,
|
||||||
@ -464,9 +475,13 @@ class ForexDataState extends State<ForexData> {
|
|||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
controller: controllers["currency"],
|
controller: controllers["currency"],
|
||||||
style: const TextStyle(fontSize: 12),
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 11,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
labelText: "Currency",
|
labelText: "Currency",
|
||||||
|
enabled: false,
|
||||||
labelStyle: TextStyle(fontSize: 11, color: Colors.grey),
|
labelStyle: TextStyle(fontSize: 11, color: Colors.grey),
|
||||||
floatingLabelBehavior: FloatingLabelBehavior.never,
|
floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
|
|||||||
@ -356,6 +356,9 @@ class _ForexScreenState extends State<ForexScreen> {
|
|||||||
print("card - $card");
|
print("card - $card");
|
||||||
print("cash - $cash");
|
print("cash - $cash");
|
||||||
|
|
||||||
|
_validateCardAmount(card);
|
||||||
|
_validateCashAmount(cash);
|
||||||
|
|
||||||
if (!isValidForexData(data)) {
|
if (!isValidForexData(data)) {
|
||||||
// && errorMessages.isNotEmpty) {
|
// && errorMessages.isNotEmpty) {
|
||||||
print("Validation Failed: Required fields are missing.");
|
print("Validation Failed: Required fields are missing.");
|
||||||
@ -411,7 +414,6 @@ class _ForexScreenState extends State<ForexScreen> {
|
|||||||
textControllers["_forexStartDate"]?.addListener(_onFieldChanged);
|
textControllers["_forexStartDate"]?.addListener(_onFieldChanged);
|
||||||
textControllers["_forexEndDate"]?.addListener(_onFieldChanged);
|
textControllers["_forexEndDate"]?.addListener(_onFieldChanged);
|
||||||
|
|
||||||
|
|
||||||
flightFirstTripDateNotifier = ValueNotifier<String?>(null);
|
flightFirstTripDateNotifier = ValueNotifier<String?>(null);
|
||||||
flightLastTripDateNotifier = ValueNotifier<String?>(null);
|
flightLastTripDateNotifier = ValueNotifier<String?>(null);
|
||||||
|
|
||||||
@ -428,26 +430,62 @@ class _ForexScreenState extends State<ForexScreen> {
|
|||||||
// ✅ Only set controller after value is updated
|
// ✅ Only set controller after value is updated
|
||||||
// final parsedDate =
|
// final parsedDate =
|
||||||
// DateTime.tryParse(flightFirstTripDateNotifier.value ?? '');
|
// DateTime.tryParse(flightFirstTripDateNotifier.value ?? '');
|
||||||
|
// -----------------------------------
|
||||||
|
|
||||||
|
// final parsedDate = DateFormat(
|
||||||
|
// "dd-MM-yyyy",
|
||||||
|
// ).parse(flightFirstTripDateNotifier.value ?? '');
|
||||||
|
// if (parsedDate != null) {
|
||||||
|
// textControllers["_forexStartDate"]?.text = DateFormat(
|
||||||
|
// 'dd-MM-yyyy',
|
||||||
|
// ).format(parsedDate);
|
||||||
|
// }
|
||||||
|
final flightDateStr = flightFirstTripDateNotifier.value;
|
||||||
|
|
||||||
|
if (flightDateStr != null && flightDateStr.trim().isNotEmpty) {
|
||||||
|
try {
|
||||||
final parsedDate = DateFormat(
|
final parsedDate = DateFormat(
|
||||||
"dd-MM-yyyy",
|
"dd-MM-yyyy",
|
||||||
).parse(flightFirstTripDateNotifier.value ?? '');
|
).parse(flightDateStr.trim());
|
||||||
if (parsedDate != null) {
|
|
||||||
textControllers["_forexStartDate"]?.text = DateFormat(
|
textControllers["_forexStartDate"]?.text = DateFormat(
|
||||||
'dd-MM-yyyy',
|
'dd-MM-yyyy',
|
||||||
).format(parsedDate);
|
).format(parsedDate);
|
||||||
|
} catch (e) {
|
||||||
|
print("Error parsing flightFirstTripDate: $e");
|
||||||
|
// Optionally show an error message to the user or log it
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
print("flightFirstTripDateNotifier is null or empty");
|
||||||
}
|
}
|
||||||
|
|
||||||
final parsedEndDate = DateFormat(
|
final flightDateEnd = flightLastTripDateNotifier.value;
|
||||||
|
|
||||||
|
if (flightDateEnd != null && flightDateEnd.trim().isNotEmpty) {
|
||||||
|
try {
|
||||||
|
final parsedDate = DateFormat(
|
||||||
"dd-MM-yyyy",
|
"dd-MM-yyyy",
|
||||||
).parse(flightLastTripDateNotifier.value ?? '');
|
).parse(flightDateEnd.trim());
|
||||||
if (parsedEndDate != null) {
|
|
||||||
textControllers["_forexEndDate"]?.text = DateFormat(
|
textControllers["_forexEndDate"]?.text = DateFormat(
|
||||||
'dd-MM-yyyy',
|
'dd-MM-yyyy',
|
||||||
).format(parsedEndDate);
|
).format(parsedDate);
|
||||||
|
} catch (e) {
|
||||||
|
print("Error parsing flightEndTripDate: $e");
|
||||||
|
// Optionally show an error message to the user or log it
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
print("flightEndTripDateNotifier is null or empty");
|
||||||
}
|
}
|
||||||
|
|
||||||
handleUpdatedField();
|
// final parsedEndDate = DateFormat(
|
||||||
|
// "dd-MM-yyyy",
|
||||||
|
// ).parse(flightLastTripDateNotifier.value ?? '');
|
||||||
|
// if (parsedEndDate != null) {
|
||||||
|
// textControllers["_forexEndDate"]?.text = DateFormat(
|
||||||
|
// 'dd-MM-yyyy',
|
||||||
|
// ).format(parsedEndDate);
|
||||||
|
// }
|
||||||
|
|
||||||
|
handleUpdatedField();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -468,16 +506,22 @@ class _ForexScreenState extends State<ForexScreen> {
|
|||||||
print("UPDATAED SELECTION");
|
print("UPDATAED SELECTION");
|
||||||
|
|
||||||
textControllers["_forexStartDate"] = initController("start_date");
|
textControllers["_forexStartDate"] = initController("start_date");
|
||||||
textControllers["_forexStartDate"]?.addListener(_onFieldChanged); // Reattach
|
textControllers["_forexStartDate"]?.addListener(
|
||||||
|
_onFieldChanged,
|
||||||
|
); // Reattach
|
||||||
textControllers["_forexEndDate"] = initController("end_date");
|
textControllers["_forexEndDate"] = initController("end_date");
|
||||||
textControllers["_forexEndDate"]?.addListener(_onFieldChanged); // Reattach
|
textControllers["_forexEndDate"]?.addListener(
|
||||||
|
_onFieldChanged,
|
||||||
|
); // Reattach
|
||||||
textControllers["_transport"] = initController("transport");
|
textControllers["_transport"] = initController("transport");
|
||||||
textControllers["_accomodation"] = initController("accommodation");
|
textControllers["_accomodation"] = initController("accommodation");
|
||||||
textControllers["_telephone"] = initController("telephone");
|
textControllers["_telephone"] = initController("telephone");
|
||||||
textControllers["_cardNumber"] = initController("card_number");
|
textControllers["_cardNumber"] = initController("card_number");
|
||||||
textControllers["_card"] = initController("deposit_on_card");
|
textControllers["_card"] = initController("deposit_on_card");
|
||||||
textControllers["_cash"] = initController("deposit_on_cash");
|
textControllers["_cash"] = initController("deposit_on_cash");
|
||||||
textControllers["_deliveryLocation"] = initController("delivery_location");
|
textControllers["_deliveryLocation"] = initController(
|
||||||
|
"delivery_location",
|
||||||
|
);
|
||||||
textControllers["_comments"] = initController("comments");
|
textControllers["_comments"] = initController("comments");
|
||||||
|
|
||||||
// Set dropdown values
|
// Set dropdown values
|
||||||
@ -1162,7 +1206,8 @@ class _ForexScreenState extends State<ForexScreen> {
|
|||||||
errorMessages["end_date"]!,
|
errorMessages["end_date"]!,
|
||||||
style: const TextStyle(color: Colors.red, fontSize: 12),
|
style: const TextStyle(color: Colors.red, fontSize: 12),
|
||||||
maxLines: 2, // Allow it to wrap onto two lines
|
maxLines: 2, // Allow it to wrap onto two lines
|
||||||
overflow: TextOverflow.ellipsis, // Add ellipsis if it still overflows
|
overflow:
|
||||||
|
TextOverflow.ellipsis, // Add ellipsis if it still overflows
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
@ -2129,7 +2174,7 @@ class _ForexScreenState extends State<ForexScreen> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Delivery Location",
|
"Delivery Location *",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
@ -2149,6 +2194,9 @@ class _ForexScreenState extends State<ForexScreen> {
|
|||||||
child: TextField(
|
child: TextField(
|
||||||
focusNode: focusNodes["_deliveryLocation"],
|
focusNode: focusNodes["_deliveryLocation"],
|
||||||
controller: textControllers["_deliveryLocation"],
|
controller: textControllers["_deliveryLocation"],
|
||||||
|
onChanged: (value) {
|
||||||
|
errorMessages.remove("delivery_location");
|
||||||
|
},
|
||||||
style: TextStyle(fontSize: 12),
|
style: TextStyle(fontSize: 12),
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: "Location",
|
labelText: "Location",
|
||||||
@ -2194,10 +2242,10 @@ class _ForexScreenState extends State<ForexScreen> {
|
|||||||
onChanged: (bool? value) {
|
onChanged: (bool? value) {
|
||||||
setState(() {
|
setState(() {
|
||||||
isChecked = value!;
|
isChecked = value!;
|
||||||
if (isChecked) {
|
// if (isChecked) {
|
||||||
textControllers["_cardNumber"]
|
// textControllers["_cardNumber"]
|
||||||
?.clear(); // Clear the value when isChecked is true
|
// ?.clear(); // Clear the value when isChecked is true
|
||||||
}
|
// }
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|||||||
@ -45,10 +45,13 @@ class _InsuranceScreenState extends State<InsuranceScreen> {
|
|||||||
|
|
||||||
late TextEditingController _tripTypeController = TextEditingController();
|
late TextEditingController _tripTypeController = TextEditingController();
|
||||||
late TextEditingController _startDateController = TextEditingController();
|
late TextEditingController _startDateController = TextEditingController();
|
||||||
|
late TextEditingController _dateOfBirthController = TextEditingController();
|
||||||
late TextEditingController _endDateController = TextEditingController();
|
late TextEditingController _endDateController = TextEditingController();
|
||||||
late TextEditingController _insuranceCommentsController =
|
late TextEditingController _insuranceCommentsController =
|
||||||
TextEditingController();
|
TextEditingController();
|
||||||
late TextEditingController _nomineeController = TextEditingController();
|
late TextEditingController _nomineeController = TextEditingController();
|
||||||
|
late TextEditingController _nomineerelationController =
|
||||||
|
TextEditingController();
|
||||||
|
|
||||||
bool _isHotelNameFocused = false;
|
bool _isHotelNameFocused = false;
|
||||||
bool _startDateFocus = false;
|
bool _startDateFocus = false;
|
||||||
@ -65,9 +68,12 @@ class _InsuranceScreenState extends State<InsuranceScreen> {
|
|||||||
Map<String, dynamic> data = {
|
Map<String, dynamic> data = {
|
||||||
"type_of_insurance": selectedInsuranceType,
|
"type_of_insurance": selectedInsuranceType,
|
||||||
"start_date": _startDateController.text,
|
"start_date": _startDateController.text,
|
||||||
|
|
||||||
"end_date": _endDateController.text,
|
"end_date": _endDateController.text,
|
||||||
"comments": _insuranceCommentsController.text,
|
"comments": _insuranceCommentsController.text,
|
||||||
"nominee_name": _nomineeController.text,
|
"nominee_name": _nomineeController.text,
|
||||||
|
"nominee_dob": _dateOfBirthController.text,
|
||||||
|
"nominee_relationship": _nomineerelationController.text,
|
||||||
"created_by": widget.loginUser,
|
"created_by": widget.loginUser,
|
||||||
"updated_by": widget.loginUser,
|
"updated_by": widget.loginUser,
|
||||||
};
|
};
|
||||||
@ -125,6 +131,13 @@ class _InsuranceScreenState extends State<InsuranceScreen> {
|
|||||||
_endDateController = TextEditingController(
|
_endDateController = TextEditingController(
|
||||||
text: widget.selectedItem?['end_date'] ?? "",
|
text: widget.selectedItem?['end_date'] ?? "",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
_dateOfBirthController = TextEditingController(
|
||||||
|
text: widget.selectedItem?['nominee_dob'] ?? "",
|
||||||
|
);
|
||||||
|
_nomineerelationController = TextEditingController(
|
||||||
|
text: widget.selectedItem?['nominee_relationship'] ?? "",
|
||||||
|
);
|
||||||
_nomineeController = TextEditingController(
|
_nomineeController = TextEditingController(
|
||||||
text: widget.selectedItem?['nominee_name'] ?? "",
|
text: widget.selectedItem?['nominee_name'] ?? "",
|
||||||
);
|
);
|
||||||
@ -147,15 +160,24 @@ class _InsuranceScreenState extends State<InsuranceScreen> {
|
|||||||
// ✅ Only set controller after value is updated
|
// ✅ Only set controller after value is updated
|
||||||
// final parsedDate =
|
// final parsedDate =
|
||||||
// DateTime.tryParse(flightFirstTripDateNotifier.value ?? '');
|
// DateTime.tryParse(flightFirstTripDateNotifier.value ?? '');
|
||||||
final parsedDate = DateFormat("dd-MM-yyyy").parse(flightFirstTripDateNotifier.value ?? '');
|
final parsedDate = DateFormat(
|
||||||
if (parsedDate != null) { _startDateController.text = DateFormat('dd-MM-yyyy').format(parsedDate); }
|
"dd-MM-yyyy",
|
||||||
|
).parse(flightFirstTripDateNotifier.value ?? '');
|
||||||
|
if (parsedDate != null) {
|
||||||
|
_startDateController.text = DateFormat('dd-MM-yyyy').format(parsedDate);
|
||||||
|
}
|
||||||
|
|
||||||
final parsedEndDate = DateFormat("dd-MM-yyyy").parse(flightLastTripDateNotifier.value ?? '');
|
final parsedEndDate = DateFormat(
|
||||||
if (parsedEndDate != null) { _endDateController.text = DateFormat('dd-MM-yyyy').format(parsedEndDate); }
|
"dd-MM-yyyy",
|
||||||
|
).parse(flightLastTripDateNotifier.value ?? '');
|
||||||
|
if (parsedEndDate != null) {
|
||||||
|
_endDateController.text = DateFormat(
|
||||||
|
'dd-MM-yyyy',
|
||||||
|
).format(parsedEndDate);
|
||||||
|
}
|
||||||
|
|
||||||
print("parsedDate $parsedDate");
|
print("parsedDate $parsedDate");
|
||||||
print("parsedEndDate $parsedEndDate");
|
print("parsedEndDate $parsedEndDate");
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,6 +225,9 @@ class _InsuranceScreenState extends State<InsuranceScreen> {
|
|||||||
"type_of_insurance",
|
"type_of_insurance",
|
||||||
"start_date",
|
"start_date",
|
||||||
"end_date",
|
"end_date",
|
||||||
|
"nominee_name",
|
||||||
|
"nominee_dob",
|
||||||
|
"nominee_relationship",
|
||||||
];
|
];
|
||||||
|
|
||||||
// Check validation for each field
|
// Check validation for each field
|
||||||
@ -311,6 +336,7 @@ class _InsuranceScreenState extends State<InsuranceScreen> {
|
|||||||
List<List<Widget>> rowBuilders = [
|
List<List<Widget>> rowBuilders = [
|
||||||
// _builClassType(isDesktop),
|
// _builClassType(isDesktop),
|
||||||
_buildSecondRow(isDesktop),
|
_buildSecondRow(isDesktop),
|
||||||
|
_buildSecondSubRow(isDesktop),
|
||||||
];
|
];
|
||||||
|
|
||||||
return [
|
return [
|
||||||
@ -779,7 +805,10 @@ class _InsuranceScreenState extends State<InsuranceScreen> {
|
|||||||
dropdownDecoratorProps: const DropDownDecoratorProps(
|
dropdownDecoratorProps: const DropDownDecoratorProps(
|
||||||
dropdownSearchDecoration: InputDecoration(
|
dropdownSearchDecoration: InputDecoration(
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding: EdgeInsets.symmetric(horizontal: 10,vertical: 10,),
|
contentPadding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 10,
|
||||||
|
vertical: 10,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
dropdownBuilder: (context, selectedItem) {
|
dropdownBuilder: (context, selectedItem) {
|
||||||
@ -805,54 +834,55 @@ class _InsuranceScreenState extends State<InsuranceScreen> {
|
|||||||
? (Map<String, dynamic>? newValue) {
|
? (Map<String, dynamic>? newValue) {
|
||||||
setState(() {
|
setState(() {
|
||||||
selectedInsuranceType = newValue?['dropdown_key'];
|
selectedInsuranceType = newValue?['dropdown_key'];
|
||||||
print("selected Insurance Type: ${selectedInsuranceType}");
|
print(
|
||||||
|
"selected Insurance Type: ${selectedInsuranceType}",
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
||||||
if (isDesktop) Spacer() else SizedBox(height: 8),
|
// if (isDesktop) Spacer() else SizedBox(height: 8),
|
||||||
Column(
|
// Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
// children: [
|
||||||
Text(
|
// Text(
|
||||||
"Nominee",
|
// "Nominee",
|
||||||
style: GoogleFonts.poppins(
|
// style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
// fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
// fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF575A74),
|
// color: Color(0xFF575A74),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
SizedBox(height: 5),
|
// SizedBox(height: 5),
|
||||||
CustomTextFieldWrapper(
|
// CustomTextFieldWrapper(
|
||||||
isFocused: _nomineeFocus,
|
// isFocused: _nomineeFocus,
|
||||||
isDesktop: isDesktop,
|
// isDesktop: isDesktop,
|
||||||
width: isDesktop ? MediaQuery.of(context).size.width * 0.15 : null,
|
// width: isDesktop ? MediaQuery.of(context).size.width * 0.15 : null,
|
||||||
// width: isDesktop ? MediaQuery.of(context).size.width * 0.34 : null,
|
// // width: isDesktop ? MediaQuery.of(context).size.width * 0.34 : null,
|
||||||
child: SizedBox(
|
// child: SizedBox(
|
||||||
height: 40,
|
// height: 40,
|
||||||
child: TextField(
|
// child: TextField(
|
||||||
focusNode: _nomineeFocusNode,
|
// focusNode: _nomineeFocusNode,
|
||||||
controller: _nomineeController,
|
// controller: _nomineeController,
|
||||||
style: TextStyle(fontSize: 12),
|
// style: TextStyle(fontSize: 12),
|
||||||
decoration: InputDecoration(
|
// decoration: InputDecoration(
|
||||||
labelText: "Nominee",
|
// labelText: "Nominee",
|
||||||
labelStyle: TextStyle(fontSize: 12, color: Colors.grey),
|
// labelStyle: TextStyle(fontSize: 12, color: Colors.grey),
|
||||||
floatingLabelBehavior: FloatingLabelBehavior.never,
|
// floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||||
border: InputBorder.none,
|
// border: InputBorder.none,
|
||||||
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
// contentPadding: EdgeInsets.symmetric(vertical: 16),
|
||||||
// contentPadding: EdgeInsets.symmetric(horizontal: 1,vertical: 1),
|
// // contentPadding: EdgeInsets.symmetric(horizontal: 1,vertical: 1),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
],
|
// ],
|
||||||
),
|
// ),
|
||||||
if (isDesktop) Spacer() else SizedBox(height: 8),
|
if (isDesktop) Spacer() else SizedBox(height: 8),
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
@ -869,7 +899,7 @@ class _InsuranceScreenState extends State<InsuranceScreen> {
|
|||||||
CustomTextFieldWrapper(
|
CustomTextFieldWrapper(
|
||||||
isFocused: _startDateFocus,
|
isFocused: _startDateFocus,
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
width: isDesktop ? MediaQuery.of(context).size.width * 0.11 : null,
|
width: isDesktop ? MediaQuery.of(context).size.width * 0.16 : null,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
@ -928,7 +958,7 @@ class _InsuranceScreenState extends State<InsuranceScreen> {
|
|||||||
CustomTextFieldWrapper(
|
CustomTextFieldWrapper(
|
||||||
isFocused: _endDateFocus,
|
isFocused: _endDateFocus,
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
width: isDesktop ? MediaQuery.of(context).size.width * 0.11 : null,
|
width: isDesktop ? MediaQuery.of(context).size.width * 0.16 : null,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
@ -982,7 +1012,8 @@ class _InsuranceScreenState extends State<InsuranceScreen> {
|
|||||||
errorMessages["end_date"]!,
|
errorMessages["end_date"]!,
|
||||||
style: const TextStyle(color: Colors.red, fontSize: 12),
|
style: const TextStyle(color: Colors.red, fontSize: 12),
|
||||||
maxLines: 2, // Allow it to wrap onto two lines
|
maxLines: 2, // Allow it to wrap onto two lines
|
||||||
overflow: TextOverflow.ellipsis, // Add ellipsis if it still overflows
|
overflow:
|
||||||
|
TextOverflow.ellipsis, // Add ellipsis if it still overflows
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
@ -991,6 +1022,229 @@ class _InsuranceScreenState extends State<InsuranceScreen> {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<Widget> _buildSecondSubRow(bool isDesktop) {
|
||||||
|
List<dynamic> purposeList =
|
||||||
|
widget.apiData?['insurance_type_of_insurance'] ?? [];
|
||||||
|
// selectedInsuranceType = purposeList.isNotEmpty ? purposeList.first['dropdown_value'] : null;
|
||||||
|
|
||||||
|
List<DropdownMenuItem<String>> dropdownItems =
|
||||||
|
purposeList
|
||||||
|
.map(
|
||||||
|
(item) => DropdownMenuItem<String>(
|
||||||
|
value: item['dropdown_key'],
|
||||||
|
child: Text(item['dropdown_value']),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
if (dropdownItems.isEmpty) {
|
||||||
|
dropdownItems.add(
|
||||||
|
DropdownMenuItem<String>(
|
||||||
|
value: null,
|
||||||
|
child: Text(
|
||||||
|
"No options available",
|
||||||
|
style: TextStyle(color: Colors.grey),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default selected value
|
||||||
|
selectedInsuranceType ??=
|
||||||
|
dropdownItems.isNotEmpty ? dropdownItems.first.value : null;
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------
|
||||||
|
|
||||||
|
DateTime? _selectedCheckDOBDate;
|
||||||
|
|
||||||
|
Future<void> _selectCheckDOBOutDate(BuildContext context) async {
|
||||||
|
DateTime now = DateTime.now();
|
||||||
|
DateTime today = DateTime(now.year, now.month, now.day);
|
||||||
|
|
||||||
|
// Parse date from notifier if available, else use today
|
||||||
|
DateTime initialDate;
|
||||||
|
|
||||||
|
initialDate = today;
|
||||||
|
|
||||||
|
final pickedDate = await showDatePicker(
|
||||||
|
context: context,
|
||||||
|
initialDate: initialDate,
|
||||||
|
firstDate: DateTime(1900),
|
||||||
|
lastDate: today,
|
||||||
|
initialEntryMode: DatePickerEntryMode.calendarOnly,
|
||||||
|
);
|
||||||
|
|
||||||
|
// DateTime? pickedDate = await showDatePicker(
|
||||||
|
// context: context,
|
||||||
|
// initialDate: _selectedCheckOutDate != null &&
|
||||||
|
// _selectedCheckOutDate!.isAfter(today)
|
||||||
|
// ? _selectedCheckOutDate!
|
||||||
|
// : today,
|
||||||
|
// firstDate: today,
|
||||||
|
// lastDate: DateTime(2100),
|
||||||
|
// );
|
||||||
|
|
||||||
|
if (pickedDate != null && pickedDate != _selectedCheckDOBDate) {
|
||||||
|
setState(() {
|
||||||
|
_selectedCheckDOBDate = pickedDate;
|
||||||
|
_dateOfBirthController.text = DateFormat(
|
||||||
|
'dd-MM-yyyy',
|
||||||
|
).format(pickedDate);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Nominee*",
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: 5),
|
||||||
|
CustomTextFieldWrapper(
|
||||||
|
isFocused: _nomineeFocus,
|
||||||
|
isDesktop: isDesktop,
|
||||||
|
// width: isDesktop ? MediaQuery.of(context).size.width * 0.15 : null,
|
||||||
|
width: isDesktop ? MediaQuery.of(context).size.width * 0.31 : null,
|
||||||
|
// width: isDesktop ? MediaQuery.of(context).size.width * 0.34 : null,
|
||||||
|
child: SizedBox(
|
||||||
|
height: 40,
|
||||||
|
child: TextField(
|
||||||
|
focusNode: _nomineeFocusNode,
|
||||||
|
controller: _nomineeController,
|
||||||
|
style: TextStyle(fontSize: 12),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
labelText: "Nominee",
|
||||||
|
labelStyle: TextStyle(fontSize: 12, color: Colors.grey),
|
||||||
|
floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||||
|
border: InputBorder.none,
|
||||||
|
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
||||||
|
// contentPadding: EdgeInsets.symmetric(horizontal: 1,vertical: 1),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (errorMessages["nominee_name"] != null) ...[
|
||||||
|
SizedBox(height: 5), // Space before error message
|
||||||
|
Text("Required", style: TextStyle(color: Colors.red, fontSize: 12)),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
),
|
||||||
|
if (isDesktop) Spacer() else SizedBox(height: 8),
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Date of Birth*",
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: 5),
|
||||||
|
CustomTextFieldWrapper(
|
||||||
|
isFocused: _startDateFocus,
|
||||||
|
isDesktop: isDesktop,
|
||||||
|
width: isDesktop ? MediaQuery.of(context).size.width * 0.16 : null,
|
||||||
|
// width: isDesktop ? MediaQuery.of(context).size.width * 0.11 : null,
|
||||||
|
child: SizedBox(
|
||||||
|
height: 40,
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () async {
|
||||||
|
await _selectCheckDOBOutDate(context);
|
||||||
|
// await _selectDateOfBirth(context);
|
||||||
|
if (_dateOfBirthController.text.isNotEmpty) {
|
||||||
|
setState(() {
|
||||||
|
errorMessages.remove(
|
||||||
|
"nominee_dob",
|
||||||
|
); // Removes the key completely
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: AbsorbPointer(
|
||||||
|
child: TextField(
|
||||||
|
focusNode: _startDateFocusNode,
|
||||||
|
controller: _dateOfBirthController,
|
||||||
|
readOnly: true,
|
||||||
|
style: const TextStyle(fontSize: 12),
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
labelText: "Select ",
|
||||||
|
labelStyle: TextStyle(fontSize: 12, color: Colors.grey),
|
||||||
|
floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||||
|
border: InputBorder.none,
|
||||||
|
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
||||||
|
suffixIcon: Icon(
|
||||||
|
Icons.calendar_today,
|
||||||
|
size: 16,
|
||||||
|
color: Colors.grey,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (errorMessages["nominee_dob"] != null) ...[
|
||||||
|
SizedBox(height: 5), // Space before error message
|
||||||
|
Text("Required", style: TextStyle(color: Colors.red, fontSize: 12)),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
),
|
||||||
|
if (isDesktop) Spacer() else SizedBox(height: 8),
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Relationship*",
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: 5),
|
||||||
|
|
||||||
|
//
|
||||||
|
CustomTextFieldWrapper(
|
||||||
|
isFocused: false,
|
||||||
|
isDesktop: isDesktop,
|
||||||
|
width: isDesktop ? MediaQuery.of(context).size.width * 0.16 : null,
|
||||||
|
// width: isDesktop ? MediaQuery.of(context).size.width * 0.31 : null,
|
||||||
|
// width: isDesktop ? MediaQuery.of(context).size.width * 0.34 : null,
|
||||||
|
child: SizedBox(
|
||||||
|
height: 40,
|
||||||
|
child: TextField(
|
||||||
|
// focusNode: _nomineeFocusNode,
|
||||||
|
controller: _nomineerelationController,
|
||||||
|
style: TextStyle(fontSize: 12),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
labelText: "Nominee Relationship",
|
||||||
|
labelStyle: TextStyle(fontSize: 12, color: Colors.grey),
|
||||||
|
floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||||
|
border: InputBorder.none,
|
||||||
|
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
||||||
|
// contentPadding: EdgeInsets.symmetric(horizontal: 1,vertical: 1),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (errorMessages["nominee_relationship"] != null) ...[
|
||||||
|
SizedBox(height: 5), // Space before error message
|
||||||
|
Text("Required", style: TextStyle(color: Colors.red, fontSize: 12)),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
),
|
||||||
|
if (isDesktop) Spacer() else SizedBox(height: 8),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
List<Widget> _buildThirdRow(bool isDesktop) {
|
List<Widget> _buildThirdRow(bool isDesktop) {
|
||||||
return [
|
return [
|
||||||
Column(
|
Column(
|
||||||
|
|||||||
@ -51,10 +51,15 @@ class _FlightListWidgetState extends State<FlightListWidget> {
|
|||||||
Map<String, String> tempCountryMap = {};
|
Map<String, String> tempCountryMap = {};
|
||||||
|
|
||||||
for (var country in result) {
|
for (var country in result) {
|
||||||
String city = country['City'] ?? '';
|
// String city = country['City'] ?? '';
|
||||||
String airport = country['Airport'] ?? '';
|
// String airport = country['Airport'] ?? '';
|
||||||
String displayName = '${country['City']} - ${country['Airport']}';
|
// String displayName = '${country['City']} - ${country['Airport']}';
|
||||||
// String displayName = '${country['City']} | ${country['Airport']}';
|
// // String displayName = '${country['City']} | ${country['Airport']}';
|
||||||
|
|
||||||
|
final code = country['Code'] ?? '';
|
||||||
|
final city = country['City'] ?? '';
|
||||||
|
final airport = country['Airport'] ?? '';
|
||||||
|
final displayName = '$city ($code)\n$airport';
|
||||||
|
|
||||||
tempCountryMap[country['Code']] = displayName;
|
tempCountryMap[country['Code']] = displayName;
|
||||||
}
|
}
|
||||||
@ -346,7 +351,7 @@ class _FlightListWidgetState extends State<FlightListWidget> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 4,
|
flex: 5,
|
||||||
child: Text(
|
child: Text(
|
||||||
"Sector",
|
"Sector",
|
||||||
style: GoogleFonts.poppins(fontSize: 11),
|
style: GoogleFonts.poppins(fontSize: 11),
|
||||||
@ -374,13 +379,38 @@ class _FlightListWidgetState extends State<FlightListWidget> {
|
|||||||
if (isDesktop)
|
if (isDesktop)
|
||||||
if (item["trips"] != null && item["trips"].isNotEmpty)
|
if (item["trips"] != null && item["trips"].isNotEmpty)
|
||||||
...item["trips"].map<Widget>((trip) {
|
...item["trips"].map<Widget>((trip) {
|
||||||
|
print("werewrewrTrip - $trip");
|
||||||
|
|
||||||
String fromPlaceCountry =
|
String fromPlaceCountry =
|
||||||
countryMap[trip["from_place"]?.toString()] ??
|
countryMap[trip["from_place"]?.toString()] ??
|
||||||
"Unknown Country";
|
"Unknown Country";
|
||||||
|
|
||||||
|
final parts = fromPlaceCountry.split('\n');
|
||||||
|
final cityAndCode = parts[0];
|
||||||
|
final fromairport = parts.length > 1 ? parts[1] : '';
|
||||||
|
|
||||||
|
// Extract city and code from "City (CODE)"
|
||||||
|
final cityMatch = RegExp(
|
||||||
|
r'^(.*)\s+\(([^)]+)\)$',
|
||||||
|
).firstMatch(cityAndCode);
|
||||||
|
final fromcity = cityMatch?.group(1) ?? '';
|
||||||
|
final fromcode = cityMatch?.group(2) ?? '';
|
||||||
|
|
||||||
String toPlaceCountry =
|
String toPlaceCountry =
|
||||||
countryMap[trip["to_place"]?.toString()] ??
|
countryMap[trip["to_place"]?.toString()] ??
|
||||||
"Unknown Country";
|
"Unknown Country";
|
||||||
|
|
||||||
|
final toparts = toPlaceCountry.split('\n');
|
||||||
|
final tocityAndCode = toparts[0];
|
||||||
|
final toairport = toparts.length > 1 ? toparts[1] : '';
|
||||||
|
|
||||||
|
// Extract city and code from "City (CODE)"
|
||||||
|
final tocityMatch = RegExp(
|
||||||
|
r'^(.*)\s+\(([^)]+)\)$',
|
||||||
|
).firstMatch(tocityAndCode);
|
||||||
|
final tocity = tocityMatch?.group(1) ?? '';
|
||||||
|
final tocode = tocityMatch?.group(2) ?? '';
|
||||||
|
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 4.0),
|
padding: const EdgeInsets.symmetric(vertical: 4.0),
|
||||||
child: Row(
|
child: Row(
|
||||||
@ -398,36 +428,74 @@ class _FlightListWidgetState extends State<FlightListWidget> {
|
|||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 4,
|
flex: 4,
|
||||||
child: Column(
|
child: Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
flex: 1,
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment:
|
||||||
|
CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"$fromPlaceCountry",
|
"$fromcity ($fromcode)",
|
||||||
// "${trip["from_place"]?.toString()} - ${trip["to_place"]?.toString()}",
|
// "${trip["from_place"]?.toString()} - ${trip["to_place"]?.toString()}",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w700,
|
fontWeight: FontWeight.w700,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(left: 10),
|
|
||||||
child: Image.asset(
|
|
||||||
'assets/images/IconsImg/alternate.png',
|
|
||||||
width: 20,
|
|
||||||
height: 20,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Text(
|
Text(
|
||||||
"$toPlaceCountry",
|
"$fromairport",
|
||||||
// "${trip["from_place"]?.toString()} - ${trip["to_place"]?.toString()}",
|
// "${trip["from_place"]?.toString()} - ${trip["to_place"]?.toString()}",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 10,
|
||||||
fontWeight: FontWeight.w700,
|
fontWeight: FontWeight.w400,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
Expanded(
|
||||||
|
flex: 1,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 10),
|
||||||
|
child: Image.asset(
|
||||||
|
'assets/images/IconsImg/Frame.png',
|
||||||
|
width: 20,
|
||||||
|
height: 20,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
flex: 1,
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment:
|
||||||
|
CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"$tocity ($tocode)",
|
||||||
|
// "${trip["from_place"]?.toString()} - ${trip["to_place"]?.toString()}",
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
"$toairport",
|
||||||
|
// "${trip["from_place"]?.toString()} - ${trip["to_place"]?.toString()}",
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 10,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Spacer(),
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 2,
|
flex: 2,
|
||||||
child: Text(
|
child: Text(
|
||||||
@ -478,6 +546,7 @@ class _FlightListWidgetState extends State<FlightListWidget> {
|
|||||||
"Sector",
|
"Sector",
|
||||||
"${trip["from_place"] ?? "N/A"} - ${trip["to_place"] ?? "N/A"}",
|
"${trip["from_place"] ?? "N/A"} - ${trip["to_place"] ?? "N/A"}",
|
||||||
),
|
),
|
||||||
|
|
||||||
_buildKeyValueRow(
|
_buildKeyValueRow(
|
||||||
"Date",
|
"Date",
|
||||||
formatDate(trip["date"] ?? ""),
|
formatDate(trip["date"] ?? ""),
|
||||||
|
|||||||
@ -54,7 +54,8 @@ class _TrainListWidgetState extends State<TrainListWidget> {
|
|||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
title: const Text('Select Trip Type'),
|
title: const Text('Select Trip Type'),
|
||||||
content: const Text(
|
content: const Text(
|
||||||
'Please select a trip type before adding a Train.'),
|
'Please select a trip type before adding a Train.',
|
||||||
|
),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Navigator.of(context).pop(),
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
@ -109,16 +110,19 @@ class _TrainListWidgetState extends State<TrainListWidget> {
|
|||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
MouseRegion(
|
MouseRegion(
|
||||||
cursor: widget.isViewMode
|
cursor:
|
||||||
|
widget.isViewMode
|
||||||
? SystemMouseCursors.forbidden
|
? SystemMouseCursors.forbidden
|
||||||
: SystemMouseCursors.click,
|
: SystemMouseCursors.click,
|
||||||
child: MouseRegion(
|
child: MouseRegion(
|
||||||
cursor: widget.isViewMode
|
cursor:
|
||||||
|
widget.isViewMode
|
||||||
? SystemMouseCursors.forbidden
|
? SystemMouseCursors.forbidden
|
||||||
: SystemMouseCursors.click,
|
: SystemMouseCursors.click,
|
||||||
|
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: widget.isViewMode
|
onTap:
|
||||||
|
widget.isViewMode
|
||||||
? null
|
? null
|
||||||
: () {
|
: () {
|
||||||
print("New data");
|
print("New data");
|
||||||
@ -137,7 +141,7 @@ class _TrainListWidgetState extends State<TrainListWidget> {
|
|||||||
Icons.add_circle_sharp,
|
Icons.add_circle_sharp,
|
||||||
size: 30,
|
size: 30,
|
||||||
color: Color(0xFF114D8B),
|
color: Color(0xFF114D8B),
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -193,9 +197,9 @@ class _TrainListWidgetState extends State<TrainListWidget> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
// Scroll behavior based on device
|
|
||||||
|
|
||||||
_buildData(context, isDesktop)
|
// Scroll behavior based on device
|
||||||
|
_buildData(context, isDesktop),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -268,8 +272,11 @@ class _TrainListWidgetState extends State<TrainListWidget> {
|
|||||||
|
|
||||||
if (hour == 24 && minute == 0) {
|
if (hour == 24 && minute == 0) {
|
||||||
// 24:00 is treated as 00:00 on the next day
|
// 24:00 is treated as 00:00 on the next day
|
||||||
dateTime = DateTime(now.year, now.month, now.day)
|
dateTime = DateTime(
|
||||||
.add(const Duration(days: 1));
|
now.year,
|
||||||
|
now.month,
|
||||||
|
now.day,
|
||||||
|
).add(const Duration(days: 1));
|
||||||
} else {
|
} else {
|
||||||
if (hour < 0 || hour > 23 || minute < 0 || minute > 59) {
|
if (hour < 0 || hour > 23 || minute < 0 || minute > 59) {
|
||||||
throw FormatException("Invalid hour or minute");
|
throw FormatException("Invalid hour or minute");
|
||||||
@ -356,9 +363,7 @@ class _TrainListWidgetState extends State<TrainListWidget> {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Divider(
|
Divider(color: Colors.blueGrey.shade50),
|
||||||
color: Colors.blueGrey.shade50,
|
|
||||||
),
|
|
||||||
SizedBox(height: 4),
|
SizedBox(height: 4),
|
||||||
isDesktop
|
isDesktop
|
||||||
? Row(
|
? Row(
|
||||||
@ -367,34 +372,30 @@ class _TrainListWidgetState extends State<TrainListWidget> {
|
|||||||
flex: 2,
|
flex: 2,
|
||||||
child: Text(
|
child: Text(
|
||||||
" Class",
|
" Class",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(fontSize: 11),
|
||||||
fontSize: 11,
|
),
|
||||||
),
|
),
|
||||||
)),
|
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 2,
|
flex: 4,
|
||||||
child: Text(
|
child: Text(
|
||||||
" Planned Trips",
|
" Planned Trips",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(fontSize: 11),
|
||||||
fontSize: 11,
|
),
|
||||||
),
|
),
|
||||||
)),
|
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 2,
|
flex: 2,
|
||||||
child: Text(
|
child: Text(
|
||||||
" Date",
|
" Date",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(fontSize: 11),
|
||||||
fontSize: 11,
|
),
|
||||||
),
|
),
|
||||||
)),
|
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 2,
|
flex: 2,
|
||||||
child: Text(
|
child: Text(
|
||||||
" Comments",
|
" Comments",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(fontSize: 11),
|
||||||
fontSize: 11,
|
),
|
||||||
),
|
),
|
||||||
)),
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
: SizedBox.shrink(),
|
: SizedBox.shrink(),
|
||||||
@ -410,20 +411,103 @@ class _TrainListWidgetState extends State<TrainListWidget> {
|
|||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
),
|
),
|
||||||
)),
|
),
|
||||||
|
),
|
||||||
SizedBox(width: 10),
|
SizedBox(width: 10),
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 2,
|
flex: 3,
|
||||||
child: Text(
|
|
||||||
"$fromPlaceCountry - $toPlaceCountry",
|
// child: Column(
|
||||||
|
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
// children: [
|
||||||
|
// Expanded(
|
||||||
|
// flex: 1,
|
||||||
|
// child: Text(
|
||||||
|
// "$fromPlaceCountry",
|
||||||
|
// // "${trip["from_place"]?.toString()} - ${trip["to_place"]?.toString()}",
|
||||||
|
// style: GoogleFonts.poppins(
|
||||||
|
// fontSize: 12,
|
||||||
|
// fontWeight: FontWeight.w700,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// Expanded(
|
||||||
|
// flex: 1,
|
||||||
|
// child: Padding(
|
||||||
|
// padding: const EdgeInsets.only(left: 10),
|
||||||
|
// child: Image.asset(
|
||||||
|
// 'assets/images/IconsImg/Frame.png',
|
||||||
|
// width: 20,
|
||||||
|
// height: 20,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// Expanded(
|
||||||
|
// flex: 1,
|
||||||
|
// child: Text(
|
||||||
|
// "$toPlaceCountry",
|
||||||
|
// // "${trip["from_place"]?.toString()} - ${trip["to_place"]?.toString()}",
|
||||||
|
// style: GoogleFonts.poppins(
|
||||||
|
// fontSize: 12,
|
||||||
|
// fontWeight: FontWeight.w700,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
flex: 1,
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"$fromPlaceCountry ",
|
||||||
|
|
||||||
// "${item["from_station"]!} - ${(item["to_station"])}",
|
// "${item["from_station"]!} - ${(item["to_station"])}",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
),
|
),
|
||||||
)),
|
),
|
||||||
SizedBox(width: 10),
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
flex: 1,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 10),
|
||||||
|
child: Image.asset(
|
||||||
|
'assets/images/IconsImg/Frame.png',
|
||||||
|
width: 20,
|
||||||
|
height: 20,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
flex: 1,
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"$toPlaceCountry",
|
||||||
|
|
||||||
|
// "$fromPlaceCountry - $toPlaceCountry",
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Spacer(),
|
||||||
|
// SizedBox(width: 10),
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 2,
|
flex: 2,
|
||||||
child: Text(
|
child: Text(
|
||||||
@ -438,7 +522,9 @@ class _TrainListWidgetState extends State<TrainListWidget> {
|
|||||||
Expanded(
|
Expanded(
|
||||||
flex: 2,
|
flex: 2,
|
||||||
child: _buildComments(
|
child: _buildComments(
|
||||||
"Comments:", item["comments"] ?? "N/A"),
|
"Comments:",
|
||||||
|
item["comments"] ?? "N/A",
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@ -447,8 +533,8 @@ class _TrainListWidgetState extends State<TrainListWidget> {
|
|||||||
children: [
|
children: [
|
||||||
_buildRow(
|
_buildRow(
|
||||||
"Class:",
|
"Class:",
|
||||||
getRequestForTrainClass(
|
getRequestForTrainClass(item["class"]!.toString()),
|
||||||
item["class"]!.toString())),
|
),
|
||||||
_buildRow("From:", item["from_station"]!),
|
_buildRow("From:", item["from_station"]!),
|
||||||
_buildRow("To:", item["to_station"]!),
|
_buildRow("To:", item["to_station"]!),
|
||||||
_buildDateTimeRow(
|
_buildDateTimeRow(
|
||||||
@ -458,7 +544,7 @@ class _TrainListWidgetState extends State<TrainListWidget> {
|
|||||||
),
|
),
|
||||||
_buildRow("Comments:", item["comments"] ?? "N/A"),
|
_buildRow("Comments:", item["comments"] ?? "N/A"),
|
||||||
],
|
],
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -487,30 +573,36 @@ class _TrainListWidgetState extends State<TrainListWidget> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: exceedsLimit
|
child:
|
||||||
|
exceedsLimit
|
||||||
? Tooltip(
|
? Tooltip(
|
||||||
message: wrapText(value, 50),
|
message: wrapText(value, 50),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.grey.shade200, // Black background
|
color: Colors.grey.shade200, // Black background
|
||||||
borderRadius: BorderRadius.circular(6),
|
borderRadius: BorderRadius.circular(6),
|
||||||
),
|
),
|
||||||
textStyle:
|
textStyle: TextStyle(
|
||||||
TextStyle(color: Colors.black), // Tooltip text color
|
color: Colors.black,
|
||||||
|
), // Tooltip text color
|
||||||
padding: EdgeInsets.all(8),
|
padding: EdgeInsets.all(8),
|
||||||
preferBelow: false,
|
preferBelow: false,
|
||||||
child: Text(value.substring(0, limit) + "...",
|
child: Text(
|
||||||
|
value.substring(0, limit) + "...",
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
fontFamily: "Archivo"),
|
fontFamily: "Archivo",
|
||||||
overflow: TextOverflow.ellipsis),
|
),
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
: Text(
|
: Text(
|
||||||
value,
|
value,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
fontFamily: "Archivo"),
|
fontFamily: "Archivo",
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -538,36 +630,30 @@ class _TrainListWidgetState extends State<TrainListWidget> {
|
|||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
title,
|
title,
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(fontSize: 12, fontWeight: FontWeight.w600),
|
||||||
fontSize: 12,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
SizedBox(width: 8),
|
SizedBox(width: 8),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: exceedsLimit
|
child:
|
||||||
|
exceedsLimit
|
||||||
? Tooltip(
|
? Tooltip(
|
||||||
message: wrapText(value, 50),
|
message: wrapText(value, 50),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.grey.shade200, // Black background
|
color: Colors.grey.shade200, // Black background
|
||||||
borderRadius: BorderRadius.circular(6),
|
borderRadius: BorderRadius.circular(6),
|
||||||
),
|
),
|
||||||
textStyle:
|
textStyle: TextStyle(
|
||||||
TextStyle(color: Colors.black), // Tooltip text color
|
color: Colors.black,
|
||||||
|
), // Tooltip text color
|
||||||
padding: EdgeInsets.all(8),
|
padding: EdgeInsets.all(8),
|
||||||
preferBelow: false,
|
preferBelow: false,
|
||||||
child: Text(value.substring(0, limit) + "...",
|
child: Text(
|
||||||
style: GoogleFonts.poppins(
|
value.substring(0, limit) + "...",
|
||||||
fontSize: 12,
|
style: GoogleFonts.poppins(fontSize: 12),
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
overflow: TextOverflow.ellipsis),
|
|
||||||
)
|
)
|
||||||
: Text(
|
: Text(value, style: GoogleFonts.poppins(fontSize: 12)),
|
||||||
value,
|
|
||||||
style: GoogleFonts.poppins(
|
|
||||||
fontSize: 12,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@ -579,18 +665,10 @@ class _TrainListWidgetState extends State<TrainListWidget> {
|
|||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
title,
|
title,
|
||||||
style: TextStyle(
|
style: TextStyle(fontWeight: FontWeight.w600, fontSize: 12),
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
fontSize: 12,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
SizedBox(width: 8),
|
SizedBox(width: 8),
|
||||||
Expanded(
|
Expanded(child: Text("$date, $time", style: TextStyle(fontSize: 12))),
|
||||||
child: Text(
|
|
||||||
"$date, $time",
|
|
||||||
style: TextStyle(fontSize: 12),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -282,6 +282,8 @@ class _CreatePlansState extends State<CreatePlan> {
|
|||||||
context.go('/listAllPlan');
|
context.go('/listAllPlan');
|
||||||
} else if (currentUri == "/createPlan") {
|
} else if (currentUri == "/createPlan") {
|
||||||
context.go('/listPlan');
|
context.go('/listPlan');
|
||||||
|
} else if (currentUri == "/approver/plans") {
|
||||||
|
context.go('/approvallist');
|
||||||
} else {
|
} else {
|
||||||
isApprover ? context.go('/approvallist') : context.go('/listPlan');
|
isApprover ? context.go('/approvallist') : context.go('/listPlan');
|
||||||
}
|
}
|
||||||
@ -1173,17 +1175,18 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
print("ViewAAA - $planData");
|
print("ViewAAA - $planData");
|
||||||
print("Call viewPlanForApprover");
|
print("Call viewPlanForApprover");
|
||||||
|
|
||||||
ApiService.viewPlanForApprover(
|
// ApiService.viewPlanForApprover(
|
||||||
context,
|
// context,
|
||||||
data['plan_id'],
|
// data['plan_id'],
|
||||||
data['approverId'],
|
// data['approverId'],
|
||||||
data['delegaterId'],
|
// data['delegaterId'],
|
||||||
data['approver_status'],
|
// data['approver_status'],
|
||||||
|
//
|
||||||
isViewMode: false,
|
// isViewMode: false,
|
||||||
isApprover: true,
|
// isApprover: true,
|
||||||
);
|
// );
|
||||||
|
// Close loading dialog (ONLY if still mounted)
|
||||||
|
if (mounted) Navigator.of(context, rootNavigator: true).pop();
|
||||||
context.go('/approvallist');
|
context.go('/approvallist');
|
||||||
} else {
|
} else {
|
||||||
print("$methodName failed. Status: ${response.statusCode}");
|
print("$methodName failed. Status: ${response.statusCode}");
|
||||||
@ -3172,6 +3175,11 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
statusValue = "Approved";
|
statusValue = "Approved";
|
||||||
});
|
});
|
||||||
callApproveAPI(selectedPlanId!, planData['user_id']);
|
callApproveAPI(selectedPlanId!, planData['user_id']);
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
barrierDismissible: false,
|
||||||
|
builder: (context) => const SavingLoader(),
|
||||||
|
);
|
||||||
} else if (result is String) {
|
} else if (result is String) {
|
||||||
// User rejected with remarks
|
// User rejected with remarks
|
||||||
_remarksController.text = result;
|
_remarksController.text = result;
|
||||||
|
|||||||
@ -153,7 +153,9 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
"address": controllers["address"]?.text,
|
"address": controllers["address"]?.text,
|
||||||
"gender": selectedGender,
|
"gender": selectedGender,
|
||||||
// "gender": personalDetailsKey.currentState?.selectedGender,
|
// "gender": personalDetailsKey.currentState?.selectedGender,
|
||||||
|
// "agent_supported_service_ids": selectedServiceIds,
|
||||||
"agent_supported_service_ids": selectedServiceIds,
|
"agent_supported_service_ids": selectedServiceIds,
|
||||||
|
|
||||||
"postal_code": controllers["postalCode"]?.text,
|
"postal_code": controllers["postalCode"]?.text,
|
||||||
"country_code": selectedCountry,
|
"country_code": selectedCountry,
|
||||||
"employee_code": controllers["employeeCode"]?.text,
|
"employee_code": controllers["employeeCode"]?.text,
|
||||||
@ -720,7 +722,7 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
if (start_Date != null &&
|
if (start_Date != null &&
|
||||||
end_Date != null &&
|
end_Date != null &&
|
||||||
end_Date.isBefore(start_Date)) {
|
end_Date.isBefore(start_Date)) {
|
||||||
print("End date cannot be earlier than start date");
|
print("Invalid Date Range");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -1420,6 +1422,7 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
disabledBackgroundColor:
|
disabledBackgroundColor:
|
||||||
layoutColor, // Ensure color remains when disabled
|
layoutColor, // Ensure color remains when disabled
|
||||||
disabledForegroundColor: Colors.white,
|
disabledForegroundColor: Colors.white,
|
||||||
|
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
side: BorderSide(color: layoutColor, width: 2),
|
side: BorderSide(color: layoutColor, width: 2),
|
||||||
@ -1482,9 +1485,10 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
disabledForegroundColor: Colors.white,
|
disabledForegroundColor: Colors.white,
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
side: BorderSide(color: Colors.white, width: 2),
|
side: BorderSide(color: layoutColor, width: 2),
|
||||||
),
|
),
|
||||||
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 18),
|
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 10),
|
||||||
),
|
),
|
||||||
onPressed: handleBack,
|
onPressed: handleBack,
|
||||||
// onPressed:
|
// onPressed:
|
||||||
|
|||||||
@ -457,7 +457,7 @@ class _OfficeDetailsState extends State<OfficeDetails> {
|
|||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
Text(
|
Text(
|
||||||
widget.errorMessages["employee_code"]!,
|
widget.errorMessages["employee_code"]!,
|
||||||
style: TextStyle(color: Colors.red, fontSize: 12),
|
style: GoogleFonts.poppins(color: Colors.red, fontSize: 12),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
|||||||
@ -314,8 +314,8 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
SizedBox(height: 20),
|
SizedBox(height: 20),
|
||||||
_buildPassportDataRow1(widget.isDesktop),
|
// _buildPassportDataRow1(widget.isDesktop),
|
||||||
SizedBox(height: 10),
|
// SizedBox(height: 10),
|
||||||
_buildFirstRow(widget.isDesktop),
|
_buildFirstRow(widget.isDesktop),
|
||||||
SizedBox(height: 10),
|
SizedBox(height: 10),
|
||||||
_buildSecondRow(widget.isDesktop),
|
_buildSecondRow(widget.isDesktop),
|
||||||
@ -451,7 +451,7 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
} else {
|
} else {
|
||||||
selectedServiceIds.add({"service_id": serviceId});
|
selectedServiceIds.add({"service_id": serviceId});
|
||||||
}
|
}
|
||||||
|
print("selectedServiceIdsUser --- $selectedServiceIds");
|
||||||
// Call the parent's callback
|
// Call the parent's callback
|
||||||
widget.onServiceIdsChanged!(selectedServiceIds);
|
widget.onServiceIdsChanged!(selectedServiceIds);
|
||||||
});
|
});
|
||||||
@ -802,7 +802,7 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
Text(
|
Text(
|
||||||
widget.errorMessages["first_name"]!,
|
widget.errorMessages["first_name"]!,
|
||||||
style: TextStyle(color: Colors.red, fontSize: 12),
|
style: GoogleFonts.poppins(color: Colors.red, fontSize: 12),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
@ -848,7 +848,7 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
Text(
|
Text(
|
||||||
widget.errorMessages["last_name"]!,
|
widget.errorMessages["last_name"]!,
|
||||||
style: TextStyle(color: Colors.red, fontSize: 12),
|
style: GoogleFonts.poppins(color: Colors.red, fontSize: 12),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
@ -1168,7 +1168,7 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
Text(
|
Text(
|
||||||
widget.errorMessages["email"]!,
|
widget.errorMessages["email"]!,
|
||||||
style: TextStyle(color: Colors.red, fontSize: 12),
|
style: GoogleFonts.poppins(color: Colors.red, fontSize: 12),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
@ -1229,7 +1229,7 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
Text(
|
Text(
|
||||||
widget.errorMessages["mobile_no"]!,
|
widget.errorMessages["mobile_no"]!,
|
||||||
style: TextStyle(color: Colors.red, fontSize: 12),
|
style: GoogleFonts.poppins(color: Colors.red, fontSize: 12),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
@ -1281,7 +1281,7 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
Text(
|
Text(
|
||||||
widget.errorMessages["alternate_mobile_no"]!,
|
widget.errorMessages["alternate_mobile_no"]!,
|
||||||
style: TextStyle(color: Colors.red, fontSize: 12),
|
style: GoogleFonts.poppins(color: Colors.red, fontSize: 12),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
@ -1612,7 +1612,7 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
Text(
|
Text(
|
||||||
widget.errorMessages["role_id"]!,
|
widget.errorMessages["role_id"]!,
|
||||||
style: TextStyle(color: Colors.red, fontSize: 12),
|
style: GoogleFonts.poppins(color: Colors.red, fontSize: 12),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
@ -1703,7 +1703,7 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
Text(
|
Text(
|
||||||
widget.errorMessages["password"]!,
|
widget.errorMessages["password"]!,
|
||||||
style: TextStyle(color: Colors.red, fontSize: 12),
|
style: GoogleFonts.poppins(color: Colors.red, fontSize: 12),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
|||||||
@ -195,7 +195,7 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
end_Date != null &&
|
end_Date != null &&
|
||||||
end_Date.isBefore(start_Date)) {
|
end_Date.isBefore(start_Date)) {
|
||||||
setState(() {
|
setState(() {
|
||||||
errorMessages["date_of_expiry"] = "End date cannot be earlier";
|
errorMessages["date_of_expiry"] = "Invalid Date Range";
|
||||||
});
|
});
|
||||||
print("End date cannot be earlier than start date");
|
print("End date cannot be earlier than start date");
|
||||||
}
|
}
|
||||||
@ -227,28 +227,44 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// valid_from: 20-06-2025, valid_upto: 19-06-2025
|
// ✅ Visa entries: Validate valid_from < valid_upto for each entry
|
||||||
// DateTime? valid_from = data?['valid_from'];
|
for (var entry in visaEntries) {
|
||||||
// DateTime? valid_upto = data?['valid_upto'];
|
final localId = entry["local_id"];
|
||||||
//
|
final fromText = entry["controller_valid_from"]?.text.trim();
|
||||||
// if (valid_from != null &&
|
final toText = entry["controller_valid_upto"]?.text.trim();
|
||||||
// valid_upto != null &&
|
|
||||||
// valid_from.toString().isNotEmpty &&
|
if (fromText != null &&
|
||||||
// valid_upto.toString().isNotEmpty) {
|
toText != null &&
|
||||||
// try {
|
fromText.isNotEmpty &&
|
||||||
// final format = DateFormat("dd-MM-yyyy");
|
toText.isNotEmpty) {
|
||||||
// final checkValidFrom = format.parse("$valid_from");
|
try {
|
||||||
// final checkValidUpto = format.parse("$valid_upto");
|
final fromDate = format.parseStrict(fromText);
|
||||||
//
|
final toDate = format.parseStrict(toText);
|
||||||
// if (checkValidUpto.isBefore(checkValidFrom)) {
|
|
||||||
// // return "valid upto cannot be earlier than valid from";
|
if (toDate.isBefore(fromDate)) {
|
||||||
// }
|
print("VisaErroer1");
|
||||||
// } catch (e) {
|
errorMessages["valid_upto${entry['local_id']}"] =
|
||||||
// // return "valid upto cannot be earlier than valid from";
|
"Invalid date range";
|
||||||
//
|
// errorMessages["valid_upto_$localId"] =
|
||||||
// // errorMessages["end_date"] = "Invalid date format";
|
// "Valid Upto can't be before Valid From";
|
||||||
// }
|
} else {
|
||||||
// }
|
print("VisaErroer2");
|
||||||
|
// errorMessages.remove("valid_upto$localId");
|
||||||
|
errorMessages.remove("valid_upto${entry['local_id']}");
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print("VisaErroer3");
|
||||||
|
errorMessages["valid_upto${entry['local_id']}"] =
|
||||||
|
"Invalid date format";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errorMessages.isNotEmpty) {
|
||||||
|
print("Validation failed with errors: $errorMessages");
|
||||||
|
setState(() {}); // Refresh UI to show errors
|
||||||
|
return false;
|
||||||
|
}
|
||||||
print("travel validation end");
|
print("travel validation end");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1379,7 +1395,7 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
Text(
|
Text(
|
||||||
errorMessages["passport_number"]!,
|
errorMessages["passport_number"]!,
|
||||||
style: TextStyle(color: Colors.red, fontSize: 12),
|
style: GoogleFonts.poppins(color: Colors.red, fontSize: 12),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
@ -1458,8 +1474,7 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
// Revalidate expiry
|
// Revalidate expiry
|
||||||
if (_selectedDateOfExpiry != null &&
|
if (_selectedDateOfExpiry != null &&
|
||||||
_selectedDateOfExpiry!.isBefore(_selectedDateOfIssue!)) {
|
_selectedDateOfExpiry!.isBefore(_selectedDateOfIssue!)) {
|
||||||
errorMessages["date_of_expiry"] =
|
errorMessages["date_of_expiry"] = "Invalid Date Range";
|
||||||
"Expiry date cannot be earlier than Issue date";
|
|
||||||
} else {
|
} else {
|
||||||
errorMessages.remove("date_of_expiry");
|
errorMessages.remove("date_of_expiry");
|
||||||
}
|
}
|
||||||
@ -1585,8 +1600,7 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
|
|
||||||
if (_selectedDateOfIssue != null &&
|
if (_selectedDateOfIssue != null &&
|
||||||
_selectedDateOfExpiry!.isBefore(_selectedDateOfIssue!)) {
|
_selectedDateOfExpiry!.isBefore(_selectedDateOfIssue!)) {
|
||||||
errorMessages["date_of_expiry"] =
|
errorMessages["date_of_expiry"] = "Invalid Date Range";
|
||||||
"Expiry date cannot be earlier than Issue date";
|
|
||||||
} else {
|
} else {
|
||||||
errorMessages.remove("date_of_expiry");
|
errorMessages.remove("date_of_expiry");
|
||||||
}
|
}
|
||||||
@ -1668,7 +1682,7 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
Text(
|
Text(
|
||||||
errorMessages["date_of_expiry"]!,
|
errorMessages["date_of_expiry"]!,
|
||||||
style: const TextStyle(color: Colors.red, fontSize: 10),
|
style: GoogleFonts.poppins(color: Colors.red, fontSize: 10),
|
||||||
maxLines: 2, // Allow it to wrap onto two lines
|
maxLines: 2, // Allow it to wrap onto two lines
|
||||||
overflow:
|
overflow:
|
||||||
TextOverflow.ellipsis, // Add ellipsis if it still overflows
|
TextOverflow.ellipsis, // Add ellipsis if it still overflows
|
||||||
@ -2202,7 +2216,7 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
vertical: 8,
|
vertical: 8,
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
item['dropdown_value'] ?? '',
|
item['dropdown_value'] ?? 'Select',
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
color: Colors.black,
|
color: Colors.black,
|
||||||
@ -2214,7 +2228,7 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
dropdownDecoratorProps: const DropDownDecoratorProps(
|
dropdownDecoratorProps: const DropDownDecoratorProps(
|
||||||
dropdownSearchDecoration: InputDecoration(
|
dropdownSearchDecoration: InputDecoration(
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
hintText: "Select Seat",
|
hintText: "Select",
|
||||||
contentPadding: EdgeInsets.symmetric(
|
contentPadding: EdgeInsets.symmetric(
|
||||||
horizontal: 10,
|
horizontal: 10,
|
||||||
vertical: 5,
|
vertical: 5,
|
||||||
@ -2227,7 +2241,7 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
dropdownBuilder: (context, selectedItem) {
|
dropdownBuilder: (context, selectedItem) {
|
||||||
if (selectedItem == null || selectedItem.isEmpty) {
|
if (selectedItem == null || selectedItem.isEmpty) {
|
||||||
return Text(
|
return Text(
|
||||||
"Select Seat", // fallback text
|
"Select ", // fallback text
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
color: Colors.grey,
|
color: Colors.grey,
|
||||||
@ -2235,7 +2249,7 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
return Text(
|
return Text(
|
||||||
selectedItem['dropdown_value'] ?? "Select Seat",
|
selectedItem['dropdown_value'] ?? "Select ",
|
||||||
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -2615,7 +2629,7 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
vertical: 8,
|
vertical: 8,
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
item['dropdown_value'] ?? '',
|
item['dropdown_value'] ?? 'Select Seat',
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
color: Colors.black,
|
color: Colors.black,
|
||||||
@ -2905,7 +2919,7 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
Text(
|
Text(
|
||||||
errorMessages["forex_pre_paid_card_number"]!,
|
errorMessages["forex_pre_paid_card_number"]!,
|
||||||
style: TextStyle(color: Colors.red, fontSize: 12),
|
style: GoogleFonts.poppins(color: Colors.red, fontSize: 12),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
@ -3642,8 +3656,17 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
.map((e) => _buildVisaDataRow1(e, isDesktop)),
|
.map((e) => _buildVisaDataRow1(e, isDesktop)),
|
||||||
|
|
||||||
// _buildVisaDataRow1(isDesktop),
|
// _buildVisaDataRow1(isDesktop),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
" * I confirm my passport is valid for next 6 months",
|
||||||
|
style: GoogleFonts.poppins(fontSize: 10),
|
||||||
|
),
|
||||||
IconForVisa(),
|
IconForVisa(),
|
||||||
],
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3663,6 +3686,7 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
buildVisaValidFrom(entry),
|
buildVisaValidFrom(entry),
|
||||||
SizedBox(width: 15),
|
SizedBox(width: 15),
|
||||||
buildVisaValidUpTo(entry),
|
buildVisaValidUpTo(entry),
|
||||||
|
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: 60,
|
height: 60,
|
||||||
child: Center(
|
child: Center(
|
||||||
@ -3699,6 +3723,7 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
buildVisaValidFrom(entry),
|
buildVisaValidFrom(entry),
|
||||||
SizedBox(height: 8),
|
SizedBox(height: 8),
|
||||||
buildVisaValidUpTo(entry),
|
buildVisaValidUpTo(entry),
|
||||||
|
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
Icons.remove_circle_sharp,
|
Icons.remove_circle_sharp,
|
||||||
@ -4165,6 +4190,9 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
initialEntryMode: DatePickerEntryMode.calendarOnly,
|
initialEntryMode: DatePickerEntryMode.calendarOnly,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
print("CheckOut - $_selectedCheckOutDate");
|
||||||
|
print("CheckIn - $_selectedCheckInDate");
|
||||||
|
|
||||||
if (pickedDate != null && pickedDate != _selectedCheckOutDate) {
|
if (pickedDate != null && pickedDate != _selectedCheckOutDate) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_selectedCheckInDate = pickedDate;
|
_selectedCheckInDate = pickedDate;
|
||||||
@ -4175,10 +4203,14 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
// Revalidate expiry
|
// Revalidate expiry
|
||||||
if (_selectedCheckOutDate != null &&
|
if (_selectedCheckOutDate != null &&
|
||||||
_selectedCheckOutDate!.isBefore(_selectedCheckInDate!)) {
|
_selectedCheckOutDate!.isBefore(_selectedCheckInDate!)) {
|
||||||
errorMessages["valid_upto"] =
|
print("Entry - $entry");
|
||||||
"valid upto cannot be earlier than valid from";
|
print("errorMessages - $errorMessages");
|
||||||
|
errorMessages["valid_upto${entry['local_id']}"] =
|
||||||
|
"Invalid Date Range";
|
||||||
|
// errorMessages["valid_upto"] = "Invalid Date Range";
|
||||||
} else {
|
} else {
|
||||||
errorMessages.remove("valid_upto");
|
errorMessages.remove("valid_upto${entry['local_id']}");
|
||||||
|
// errorMessages.remove("valid_upto");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -4293,10 +4325,10 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
|
|
||||||
if (_selectedCheckInDate != null &&
|
if (_selectedCheckInDate != null &&
|
||||||
_selectedCheckOutDate!.isBefore(_selectedCheckInDate!)) {
|
_selectedCheckOutDate!.isBefore(_selectedCheckInDate!)) {
|
||||||
errorMessages["valid_upto"] =
|
errorMessages["valid_upto${entry['local_id']}"] =
|
||||||
"valid upto cannot be earlier than valid from";
|
"Invalid Date Range";
|
||||||
} else {
|
} else {
|
||||||
errorMessages.remove("valid_upto");
|
errorMessages.remove("valid_upto${entry['local_id']}");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -4325,6 +4357,7 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
height: 40,
|
height: 40,
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
|
errorMessages.remove("valid_upto${entry['local_id']}");
|
||||||
await _selectValidUpToDate(context);
|
await _selectValidUpToDate(context);
|
||||||
},
|
},
|
||||||
child: AbsorbPointer(
|
child: AbsorbPointer(
|
||||||
@ -4351,11 +4384,11 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (errorMessages["valid_upto"] != null) ...[
|
if (errorMessages["valid_upto${entry['local_id']}"] != null) ...[
|
||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
Text(
|
Text(
|
||||||
errorMessages["valid_upto"]!,
|
errorMessages["valid_upto${entry['local_id']}"]!,
|
||||||
style: const TextStyle(color: Colors.red, fontSize: 10),
|
style: GoogleFonts.poppins(color: Colors.red, fontSize: 10),
|
||||||
maxLines: 2, // Allow it to wrap onto two lines
|
maxLines: 2, // Allow it to wrap onto two lines
|
||||||
overflow:
|
overflow:
|
||||||
TextOverflow.ellipsis, // Add ellipsis if it still overflows
|
TextOverflow.ellipsis, // Add ellipsis if it still overflows
|
||||||
|
|||||||
@ -111,7 +111,7 @@ class _UserListScreenState extends State<UserListScreen> {
|
|||||||
|
|
||||||
Future<List<dynamic>> fetchUsers() async {
|
Future<List<dynamic>> fetchUsers() async {
|
||||||
orgId = await getOrgId();
|
orgId = await getOrgId();
|
||||||
final String apiUrlData = '$apiUrl/api/users?org_id=$orgId';
|
final String apiUrlData = '$apiUrl/api/users?org_id=$orgId&for=table_view';
|
||||||
final String? token = await getToken();
|
final String? token = await getToken();
|
||||||
|
|
||||||
print("Fetch Users");
|
print("Fetch Users");
|
||||||
@ -294,7 +294,13 @@ class _UserListScreenState extends State<UserListScreen> {
|
|||||||
// Refresh user list after update
|
// Refresh user list after update
|
||||||
void refreshUserList() {
|
void refreshUserList() {
|
||||||
setState(() {
|
setState(() {
|
||||||
futureUsers = fetchUsers(); // Re-fetch users after status update
|
futureUsers = fetchUsers();
|
||||||
|
|
||||||
|
futureUsers.then((users) {
|
||||||
|
setState(() {
|
||||||
|
allUsers = users;
|
||||||
|
});
|
||||||
|
}); // Re-fetch users after status update
|
||||||
// Wait for futurePlans to be fetched and update allPlans
|
// Wait for futurePlans to be fetched and update allPlans
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -724,7 +730,9 @@ class _UserListScreenState extends State<UserListScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
DataCell(
|
DataCell(
|
||||||
GestureDetector(
|
MouseRegion(
|
||||||
|
cursor: SystemMouseCursors.click,
|
||||||
|
child: GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
handleToggleUserStatus(
|
handleToggleUserStatus(
|
||||||
user['user_id'],
|
user['user_id'],
|
||||||
@ -747,6 +755,7 @@ class _UserListScreenState extends State<UserListScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
DataCell(
|
DataCell(
|
||||||
UserActionsMenu(
|
UserActionsMenu(
|
||||||
user: user,
|
user: user,
|
||||||
@ -1146,7 +1155,6 @@ class _UserListScreenState extends State<UserListScreen> {
|
|||||||
// )
|
// )
|
||||||
// : buildMobileCardView(paginatedUser),
|
// : buildMobileCardView(paginatedUser),
|
||||||
// ),
|
// ),
|
||||||
|
|
||||||
Expanded(
|
Expanded(
|
||||||
child:
|
child:
|
||||||
isDesktop
|
isDesktop
|
||||||
|
|||||||
@ -15,6 +15,7 @@ class Plan {
|
|||||||
|
|
||||||
final String userName;
|
final String userName;
|
||||||
final String travellerName;
|
final String travellerName;
|
||||||
|
final String approverName;
|
||||||
final String statusValue;
|
final String statusValue;
|
||||||
final String createdOn;
|
final String createdOn;
|
||||||
final String? approverId;
|
final String? approverId;
|
||||||
@ -35,6 +36,7 @@ class Plan {
|
|||||||
required this.isBillable,
|
required this.isBillable,
|
||||||
required this.userName,
|
required this.userName,
|
||||||
required this.travellerName,
|
required this.travellerName,
|
||||||
|
required this.approverName,
|
||||||
required this.statusValue,
|
required this.statusValue,
|
||||||
required this.createdOn,
|
required this.createdOn,
|
||||||
this.approverId,
|
this.approverId,
|
||||||
@ -44,24 +46,36 @@ class Plan {
|
|||||||
factory Plan.fromJson(Map<String, dynamic> json) {
|
factory Plan.fromJson(Map<String, dynamic> json) {
|
||||||
print('Parsing Plan from JSON: $json');
|
print('Parsing Plan from JSON: $json');
|
||||||
return Plan(
|
return Plan(
|
||||||
planId: json['plan_id'],
|
planId: json['plan_id']!.toString(),
|
||||||
employeeCode: json['employee_code'],
|
employeeCode: json['employee_code']!.toString(),
|
||||||
tripTitle: json['trip_title'],
|
tripTitle: json['trip_title']!.toString(),
|
||||||
tripType: json['trip_type_value'],
|
tripType: json['trip_type_value']!.toString(),
|
||||||
approver_status: json['approver_status'],
|
approver_status:
|
||||||
|
json["approver_status"] == null
|
||||||
|
? ''
|
||||||
|
: json['approver_status']!.toString(),
|
||||||
status: json['status'] == "0" ? "Inactive" : "Active",
|
status: json['status'] == "0" ? "Inactive" : "Active",
|
||||||
costCenter: json['cost_center_value'] ?? '',
|
costCenter: json['cost_center_value']!.toString(),
|
||||||
functionalDepartment: json['functional_department_value'] ?? '',
|
functionalDepartment: json['functional_department_value']!.toString(),
|
||||||
purposeOfTravel: json['purpose_of_travel_value'] ?? '',
|
purposeOfTravel: json['purpose_of_travel_value']!.toString(),
|
||||||
soNumber: json['so_number'] ?? '',
|
soNumber: json['so_number']!.toString(),
|
||||||
description: json['description'] ?? '',
|
description: json['description']!.toString(),
|
||||||
isBillable: json['is_billable_value'] ?? '',
|
isBillable: json['is_billable_value']!.toString(),
|
||||||
userName: json["user_name"] ?? '',
|
userName: json["user_name"]!.toString(),
|
||||||
travellerName: json["traveller_name"] ?? '',
|
travellerName:
|
||||||
statusValue: json["status_value"] ?? '',
|
json["traveller_name"] == null
|
||||||
createdOn: json["created_on"] ?? '',
|
? ''
|
||||||
approverId: json['approver_id'],
|
: json["traveller_name"]!.toString(),
|
||||||
delegaterId: json['delegater_id'],
|
approverName:
|
||||||
|
json["approver_name"] == null
|
||||||
|
? ''
|
||||||
|
: json["approver_name"]!.toString(),
|
||||||
|
statusValue: json["status_value"]!.toString(),
|
||||||
|
createdOn: json["created_on"],
|
||||||
|
approverId:
|
||||||
|
json["approver_id"] == null ? '' : json['approver_id']!.toString(),
|
||||||
|
delegaterId:
|
||||||
|
json["delegater_id"] == null ? '' : json['delegater_id']!.toString(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -618,8 +618,8 @@ class ApiService {
|
|||||||
BuildContext context,
|
BuildContext context,
|
||||||
String planId,
|
String planId,
|
||||||
String? approverId,
|
String? approverId,
|
||||||
String? approver_status,
|
String? delegaterId,
|
||||||
String? delegaterId, {
|
String? approver_status, {
|
||||||
bool isViewMode = false,
|
bool isViewMode = false,
|
||||||
bool isApprover = true,
|
bool isApprover = true,
|
||||||
}) async {
|
}) async {
|
||||||
|
|||||||
@ -21,7 +21,6 @@ class PlanPopupMenu extends StatelessWidget {
|
|||||||
required this.layoutColor,
|
required this.layoutColor,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Align(
|
return Align(
|
||||||
@ -30,12 +29,9 @@ class PlanPopupMenu extends StatelessWidget {
|
|||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
padding: EdgeInsets.zero,
|
padding: EdgeInsets.zero,
|
||||||
offset: Offset(0, 30),
|
offset: Offset(0, 30),
|
||||||
icon: Icon(
|
icon: Icon(Icons.more_vert, color: Color(0xFF475569), size: 15),
|
||||||
Icons.more_vert,
|
itemBuilder:
|
||||||
color: Color(0xFF475569),
|
(context) => [
|
||||||
size: 15,
|
|
||||||
),
|
|
||||||
itemBuilder: (context) => [
|
|
||||||
CustomPopupMenuEntry(
|
CustomPopupMenuEntry(
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: EdgeInsets.symmetric(horizontal: 2, vertical: 4),
|
padding: EdgeInsets.symmetric(horizontal: 2, vertical: 4),
|
||||||
@ -48,8 +44,11 @@ class PlanPopupMenu extends StatelessWidget {
|
|||||||
icon: Icon(Icons.remove_red_eye, size: 18),
|
icon: Icon(Icons.remove_red_eye, size: 18),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
ApiService.viewPlan(context, plan.planId,
|
ApiService.viewPlan(
|
||||||
isViewMode: true);
|
context,
|
||||||
|
plan.planId,
|
||||||
|
isViewMode: true,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
||||||
@ -62,7 +61,6 @@ class PlanPopupMenu extends StatelessWidget {
|
|||||||
// isViewMode: false);
|
// isViewMode: false);
|
||||||
// },
|
// },
|
||||||
// ),
|
// ),
|
||||||
|
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.cancel_rounded, size: 18),
|
icon: Icon(Icons.cancel_rounded, size: 18),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
@ -71,8 +69,11 @@ class PlanPopupMenu extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.download,
|
icon: Icon(
|
||||||
color: Color(0xFF114D8B), size: 18),
|
Icons.download,
|
||||||
|
color: Color(0xFF114D8B),
|
||||||
|
size: 18,
|
||||||
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
apiService.getPdfDownload(plan.planId);
|
apiService.getPdfDownload(plan.planId);
|
||||||
@ -87,13 +88,16 @@ class PlanPopupMenu extends StatelessWidget {
|
|||||||
onPressed: () {
|
onPressed: () {
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => CommentModalList(
|
builder:
|
||||||
|
(context) => CommentModalList(
|
||||||
// planId: plan.planId,
|
// planId: plan.planId,
|
||||||
planId: plan.planId.toString(),
|
planId: plan.planId.toString(),
|
||||||
layoutColorForUser: layoutColor!,
|
layoutColorForUser: layoutColor!,
|
||||||
role: "User"),
|
role: "User",
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}),
|
},
|
||||||
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(
|
icon: const Icon(
|
||||||
Icons.comment,
|
Icons.comment,
|
||||||
@ -103,13 +107,16 @@ class PlanPopupMenu extends StatelessWidget {
|
|||||||
onPressed: () {
|
onPressed: () {
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => CommentModal(
|
builder:
|
||||||
|
(context) => CommentModal(
|
||||||
// planId: plan.planId,
|
// planId: plan.planId,
|
||||||
planId: plan.planId.toString(),
|
planId: plan.planId.toString(),
|
||||||
layoutColorForUser: layoutColor!,
|
layoutColorForUser: layoutColor!,
|
||||||
role: "Travel Agent"),
|
role: "Travel Agent",
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}),
|
},
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@ -101,6 +101,8 @@ flutter:
|
|||||||
- assets/images/login/microsoft.png
|
- assets/images/login/microsoft.png
|
||||||
- assets/images/IconsImg/path.png
|
- assets/images/IconsImg/path.png
|
||||||
- assets/images/IconsImg/alternate.png
|
- assets/images/IconsImg/alternate.png
|
||||||
|
- assets/images/IconsImg/ViceVersaArrow.png
|
||||||
|
- assets/images/IconsImg/Frame.png
|
||||||
- assets/images/IconsImg/delete.png
|
- assets/images/IconsImg/delete.png
|
||||||
- assets/images/IconsImg/edit.png
|
- assets/images/IconsImg/edit.png
|
||||||
- assets/images/IconsImg/planPdf_icon.png
|
- assets/images/IconsImg/planPdf_icon.png
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user