latest commit 10-06-2025
This commit is contained in:
commit
036d0704fd
BIN
assets/images/IconsImg/alternate.png
Normal file
BIN
assets/images/IconsImg/alternate.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 78 KiB |
BIN
assets/images/IconsImg/path.png
Normal file
BIN
assets/images/IconsImg/path.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.6 KiB |
@ -913,7 +913,7 @@ class _ListAllPlansState extends State<ListAllPlans> {
|
|||||||
size: 18,
|
size: 18,
|
||||||
),
|
),
|
||||||
tooltip:
|
tooltip:
|
||||||
'Download The Trip Details',
|
'Download The PDF',
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.pop(
|
Navigator.pop(
|
||||||
context,
|
context,
|
||||||
|
|||||||
@ -931,7 +931,7 @@ class _ApprovalListState extends State<ApprovalList> {
|
|||||||
size: 18,
|
size: 18,
|
||||||
),
|
),
|
||||||
tooltip:
|
tooltip:
|
||||||
'Download The Trip Details',
|
'Download The PDF',
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.pop(
|
Navigator.pop(
|
||||||
context,
|
context,
|
||||||
@ -1170,7 +1170,7 @@ class _ApprovalListState extends State<ApprovalList> {
|
|||||||
size: 18,
|
size: 18,
|
||||||
),
|
),
|
||||||
tooltip:
|
tooltip:
|
||||||
'Download The Trip Details',
|
'Download The PDF',
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
apiService
|
apiService
|
||||||
|
|||||||
@ -336,7 +336,7 @@ class CostCenterListState extends State<CostCenterList> {
|
|||||||
MainAxisSize.min, // Ensures content fits nicely
|
MainAxisSize.min, // Ensures content fits nicely
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Add CostCenter",
|
"Add Cost Center",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: isDesktop ? 13 : 11,
|
fontSize: isDesktop ? 13 : 11,
|
||||||
),
|
),
|
||||||
|
|||||||
@ -196,24 +196,27 @@ class DepartmentDataState extends State<DepartmentData> {
|
|||||||
? await http.put(uri, headers: headers, body: body)
|
? await http.put(uri, headers: headers, body: body)
|
||||||
: await http.post(uri, headers: headers, body: body);
|
: await http.post(uri, headers: headers, body: body);
|
||||||
|
|
||||||
switch (response.statusCode) {
|
if (response.statusCode == 200 || response.statusCode == 201) {
|
||||||
case 200:
|
print("successfully!");
|
||||||
print("Update - Response: ${response.body}");
|
print("Response: ${response.body}");
|
||||||
_clearError();
|
_clearError();
|
||||||
widget.fetchGetDepartment();
|
widget.fetchGetDepartment();
|
||||||
Navigator.of(context).pop();
|
// dispose();
|
||||||
break;
|
Navigator.of(context).pop();
|
||||||
|
} else if (response.statusCode == 404) {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
final message = jsonDecode(response.body)['message'] ?? 'Unknown error';
|
||||||
|
|
||||||
case 201:
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
print("Save - Response: ${response.body}");
|
SnackBar(
|
||||||
_clearError();
|
content: Text(message),
|
||||||
await widget.fetchGetDepartment();
|
backgroundColor: Colors.redAccent,
|
||||||
Navigator.of(context).pop();
|
behavior: SnackBarBehavior.floating,
|
||||||
break;
|
),
|
||||||
|
);
|
||||||
default:
|
} else {
|
||||||
print("Failed to submit department. Status: ${response.statusCode}");
|
print("Failed to submit. Status: ${response.statusCode}");
|
||||||
print("Error: ${response.body}");
|
print("Error: ${response.body}");
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(" Error submitting plan: $e");
|
print(" Error submitting plan: $e");
|
||||||
|
|||||||
@ -349,7 +349,7 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
|||||||
mainAxisSize:
|
mainAxisSize:
|
||||||
MainAxisSize.min, // Ensures content doesn't expand unnecessarily
|
MainAxisSize.min, // Ensures content doesn't expand unnecessarily
|
||||||
children: [
|
children: [
|
||||||
widget.title == "Others"
|
widget.title == "Others (Non Employee)"
|
||||||
? Text(
|
? Text(
|
||||||
"Please Select Other User",
|
"Please Select Other User",
|
||||||
style: GoogleFonts.poppins(fontSize: 14),
|
style: GoogleFonts.poppins(fontSize: 14),
|
||||||
@ -367,7 +367,7 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
|||||||
setState(() {
|
setState(() {
|
||||||
_showTravellerForm = false;
|
_showTravellerForm = false;
|
||||||
});
|
});
|
||||||
widget.title == "Others"
|
widget.title == "Others (Non Employee)"
|
||||||
? _filterTravellers(query)
|
? _filterTravellers(query)
|
||||||
: _filterUsers(query);
|
: _filterUsers(query);
|
||||||
},
|
},
|
||||||
@ -395,7 +395,7 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
|||||||
|
|
||||||
SizedBox(height: 10),
|
SizedBox(height: 10),
|
||||||
|
|
||||||
if (widget.title == "Others") ...[
|
if (widget.title == "Others (Non Employee)") ...[
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
|
|||||||
@ -396,7 +396,7 @@ class ForexDataState extends State<ForexData> {
|
|||||||
),
|
),
|
||||||
searchFieldProps: TextFieldProps(
|
searchFieldProps: TextFieldProps(
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: "Search Country...",
|
hintText: "Search ...",
|
||||||
hintStyle: GoogleFonts.poppins(fontSize: 11),
|
hintStyle: GoogleFonts.poppins(fontSize: 11),
|
||||||
contentPadding: EdgeInsets.symmetric(horizontal: 4),
|
contentPadding: EdgeInsets.symmetric(horizontal: 4),
|
||||||
),
|
),
|
||||||
@ -414,7 +414,7 @@ class ForexDataState extends State<ForexData> {
|
|||||||
// Center-align selected item
|
// Center-align selected item
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: Text(
|
child: Text(
|
||||||
selectedItem ?? "Select Country",
|
selectedItem ?? "Select ",
|
||||||
style: GoogleFonts.poppins(fontSize: 11),
|
style: GoogleFonts.poppins(fontSize: 11),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@ -746,9 +746,9 @@ class ForexDataListState extends State<ForexDataList> {
|
|||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
fontFamily: "Inter",
|
fontFamily: "Inter",
|
||||||
// color: forex['is_active'] == "1"
|
color: forex['is_active'] == "1"
|
||||||
// ? Colors.green
|
? Colors.green
|
||||||
// : Colors.grey,
|
: Colors.grey,
|
||||||
),
|
),
|
||||||
softWrap: true,
|
softWrap: true,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
|
|||||||
@ -93,13 +93,15 @@ class _groupState extends State<Group> {
|
|||||||
String? bodyStringColor = await getBodyColor();
|
String? bodyStringColor = await getBodyColor();
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
layoutColor = layoutString != null
|
layoutColor =
|
||||||
? Color(int.parse(layoutString))
|
layoutString != null
|
||||||
: Colors.redAccent;
|
? Color(int.parse(layoutString))
|
||||||
|
: Colors.redAccent;
|
||||||
|
|
||||||
bodyColor = bodyStringColor != null
|
bodyColor =
|
||||||
? Color(int.parse(bodyStringColor))
|
bodyStringColor != null
|
||||||
: Colors.white;
|
? Color(int.parse(bodyStringColor))
|
||||||
|
: Colors.white;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,10 +156,7 @@ class _groupState extends State<Group> {
|
|||||||
errorMessages.clear(); // Reset errors
|
errorMessages.clear(); // Reset errors
|
||||||
|
|
||||||
// Required fields that must not be empty
|
// Required fields that must not be empty
|
||||||
List<String> requiredFields = [
|
List<String> requiredFields = ["name", "description"];
|
||||||
"name",
|
|
||||||
"description",
|
|
||||||
];
|
|
||||||
|
|
||||||
// Check validation for each field
|
// Check validation for each field
|
||||||
for (String field in requiredFields) {
|
for (String field in requiredFields) {
|
||||||
@ -165,6 +164,14 @@ class _groupState extends State<Group> {
|
|||||||
errorMessages[field] = "Required";
|
errorMessages[field] = "Required";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// ✅ At least one of the two policies must be selected
|
||||||
|
if ((selectedDomestic == null || selectedDomestic!.isEmpty) &&
|
||||||
|
(selectedInternational == null || selectedInternational!.isEmpty)) {
|
||||||
|
errorMessages["domestic_policy_id"] = "Select at least one policy";
|
||||||
|
errorMessages["international_policy_id"] = "Select at least one policy";
|
||||||
|
}
|
||||||
|
|
||||||
|
return errorMessages.isEmpty;
|
||||||
|
|
||||||
return errorMessages.isEmpty; // Valid if there are no errors
|
return errorMessages.isEmpty; // Valid if there are no errors
|
||||||
}
|
}
|
||||||
@ -223,23 +230,24 @@ class _groupState extends State<Group> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final response = await (isEdit
|
final response =
|
||||||
? http.put(
|
await (isEdit
|
||||||
Uri.parse(apiUrlData),
|
? http.put(
|
||||||
headers: {
|
Uri.parse(apiUrlData),
|
||||||
'Authorization': 'Bearer $token',
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Authorization': 'Bearer $token',
|
||||||
},
|
'Content-Type': 'application/json',
|
||||||
body: jsonEncode(groupData),
|
},
|
||||||
)
|
body: jsonEncode(groupData),
|
||||||
: http.post(
|
)
|
||||||
Uri.parse(apiUrlData),
|
: http.post(
|
||||||
headers: {
|
Uri.parse(apiUrlData),
|
||||||
'Authorization': 'Bearer $token',
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Authorization': 'Bearer $token',
|
||||||
},
|
'Content-Type': 'application/json',
|
||||||
body: jsonEncode(groupData),
|
},
|
||||||
));
|
body: jsonEncode(groupData),
|
||||||
|
));
|
||||||
|
|
||||||
if (response.statusCode == 200 || response.statusCode == 201) {
|
if (response.statusCode == 200 || response.statusCode == 201) {
|
||||||
print("Group submitted successfully!");
|
print("Group submitted successfully!");
|
||||||
@ -320,32 +328,38 @@ class _groupState extends State<Group> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ResponsiveBuilder(builder: (context, sizingInfo) {
|
return ResponsiveBuilder(
|
||||||
bool isDesktop = sizingInfo.deviceScreenType == DeviceScreenType.desktop;
|
builder: (context, sizingInfo) {
|
||||||
|
bool isDesktop =
|
||||||
|
sizingInfo.deviceScreenType == DeviceScreenType.desktop;
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
// backgroundColor: Colors.white,
|
// backgroundColor: Colors.white,
|
||||||
backgroundColor: Color(0xFFf5f5f5),
|
backgroundColor: Color(0xFFf5f5f5),
|
||||||
appBar: CustomAppBar(isDesktop: isDesktop),
|
appBar: CustomAppBar(isDesktop: isDesktop),
|
||||||
drawer: CustomDrawer(isDesktop: false),
|
drawer: CustomDrawer(isDesktop: false),
|
||||||
body: Padding(
|
body: Padding(
|
||||||
padding: isDesktop
|
padding:
|
||||||
? EdgeInsets.symmetric(
|
isDesktop
|
||||||
horizontal: MediaQuery.of(context).size.width *
|
? EdgeInsets.symmetric(
|
||||||
0.1, // 30% of screen width as horizontal padding
|
horizontal:
|
||||||
vertical: MediaQuery.of(context).size.height *
|
MediaQuery.of(context).size.width *
|
||||||
0, // 5% of screen height as vertical padding
|
0.1, // 30% of screen width as horizontal padding
|
||||||
)
|
vertical:
|
||||||
: EdgeInsets.all(8),
|
MediaQuery.of(context).size.height *
|
||||||
child: Row(
|
0, // 5% of screen height as vertical padding
|
||||||
children: [
|
)
|
||||||
// if (isDesktop) CustomDrawer(isDesktop: true),
|
: EdgeInsets.all(8),
|
||||||
Expanded(child: buildData(isDesktop, context))
|
child: Row(
|
||||||
],
|
children: [
|
||||||
|
// if (isDesktop) CustomDrawer(isDesktop: true),
|
||||||
|
Expanded(child: buildData(isDesktop, context)),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
);
|
},
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildData(bool isDesktop, context) {
|
Widget buildData(bool isDesktop, context) {
|
||||||
@ -367,15 +381,16 @@ class _groupState extends State<Group> {
|
|||||||
Container(
|
Container(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
child: isDesktop
|
child:
|
||||||
? Row(
|
isDesktop
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
? Row(
|
||||||
children: _buildSubmit(isDesktop),
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
)
|
children: _buildSubmit(isDesktop),
|
||||||
: Row(
|
)
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
: Row(
|
||||||
children: _buildSubmit(isDesktop),
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
),
|
children: _buildSubmit(isDesktop),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -387,9 +402,10 @@ class _groupState extends State<Group> {
|
|||||||
// margin: isDesktop
|
// margin: isDesktop
|
||||||
// ? EdgeInsets.all(10.0)
|
// ? EdgeInsets.all(10.0)
|
||||||
// : EdgeInsets.only(left: 20.0, bottom: 20.0, top: 10.0, right: 20.0),
|
// : EdgeInsets.only(left: 20.0, bottom: 20.0, top: 10.0, right: 20.0),
|
||||||
height: isDesktop
|
height:
|
||||||
? MediaQuery.of(context).size.height * 0.98
|
isDesktop
|
||||||
: MediaQuery.of(context).size.height,
|
? MediaQuery.of(context).size.height * 0.98
|
||||||
|
: MediaQuery.of(context).size.height,
|
||||||
// decoration: BoxDecoration(
|
// decoration: BoxDecoration(
|
||||||
// border: isDesktop
|
// border: isDesktop
|
||||||
// ? Border.all(
|
// ? Border.all(
|
||||||
@ -414,10 +430,7 @@ class _groupState extends State<Group> {
|
|||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text("Create Group", style: GoogleFonts.poppins(fontSize: 18)),
|
||||||
"Create Group",
|
|
||||||
style: GoogleFonts.poppins(fontSize: 18),
|
|
||||||
),
|
|
||||||
// Container(
|
// Container(
|
||||||
// color: Color(0xFFE9EBF6),
|
// color: Color(0xFFE9EBF6),
|
||||||
// child: IconButton(
|
// child: IconButton(
|
||||||
@ -436,53 +449,52 @@ class _groupState extends State<Group> {
|
|||||||
// height: 5,
|
// height: 5,
|
||||||
// ),
|
// ),
|
||||||
Container(
|
Container(
|
||||||
margin: const EdgeInsets.all(10),
|
margin: const EdgeInsets.all(10),
|
||||||
padding: const EdgeInsets.all(20),
|
padding: const EdgeInsets.all(20),
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
height: MediaQuery.of(context).size.height * 0.6,
|
height: MediaQuery.of(context).size.height * 0.6,
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
// Row(
|
// Row(
|
||||||
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
// children: [
|
// children: [
|
||||||
// Text(
|
// Text(
|
||||||
// "Mail Settings",
|
// "Mail Settings",
|
||||||
// style: TextStyle(color: Colors.blueAccent),
|
// style: TextStyle(color: Colors.blueAccent),
|
||||||
// ),
|
// ),
|
||||||
// Icon(
|
// Icon(
|
||||||
// Icons.keyboard_arrow_down_outlined,
|
// Icons.keyboard_arrow_down_outlined,
|
||||||
// color: Colors.blueAccent,
|
// color: Colors.blueAccent,
|
||||||
// size: 30,
|
// size: 30,
|
||||||
// ),
|
// ),
|
||||||
// ],
|
// ],
|
||||||
// ),
|
// ),
|
||||||
isDesktop
|
isDesktop
|
||||||
? Row(
|
? Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: _buildFirstRow(isDesktop),
|
children: _buildFirstRow(isDesktop),
|
||||||
)
|
)
|
||||||
: Column(
|
: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
children: _buildFirstRow(isDesktop),
|
children: _buildFirstRow(isDesktop),
|
||||||
),
|
),
|
||||||
|
|
||||||
SizedBox(
|
SizedBox(height: 10),
|
||||||
height: 10,
|
|
||||||
),
|
|
||||||
|
|
||||||
isDesktop
|
isDesktop
|
||||||
? Row(
|
? Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: _buildSecondRow(isDesktop),
|
children: _buildSecondRow(isDesktop),
|
||||||
)
|
)
|
||||||
: Column(
|
: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
children: _buildSecondRow(isDesktop),
|
children: _buildSecondRow(isDesktop),
|
||||||
),
|
),
|
||||||
|
|
||||||
// SizedBox(height: 15),
|
// SizedBox(height: 15),
|
||||||
],
|
],
|
||||||
)),
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -496,17 +508,19 @@ class _groupState extends State<Group> {
|
|||||||
Text(
|
Text(
|
||||||
"Group Name",
|
"Group Name",
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
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: false,
|
isFocused: false,
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
width: isDesktop
|
width:
|
||||||
? MediaQuery.of(context).size.width * 0.34
|
isDesktop
|
||||||
: MediaQuery.of(context).size.width * 0.85,
|
? MediaQuery.of(context).size.width * 0.34
|
||||||
|
: MediaQuery.of(context).size.width * 0.85,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
@ -540,17 +554,19 @@ class _groupState extends State<Group> {
|
|||||||
Text(
|
Text(
|
||||||
"Description",
|
"Description",
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
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: false,
|
isFocused: false,
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
width: isDesktop
|
width:
|
||||||
? MediaQuery.of(context).size.width * 0.34
|
isDesktop
|
||||||
: MediaQuery.of(context).size.width * 0.85,
|
? MediaQuery.of(context).size.width * 0.34
|
||||||
|
: MediaQuery.of(context).size.width * 0.85,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
@ -589,72 +605,82 @@ class _groupState extends State<Group> {
|
|||||||
Text(
|
Text(
|
||||||
"Select Policy For Domestic",
|
"Select Policy For Domestic",
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
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: false,
|
isFocused: false,
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
width: isDesktop
|
width:
|
||||||
? MediaQuery.of(context).size.width * 0.34
|
isDesktop
|
||||||
: MediaQuery.of(context).size.width * 0.85,
|
? MediaQuery.of(context).size.width * 0.34
|
||||||
|
: MediaQuery.of(context).size.width * 0.85,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: apiForDomestic == null
|
child:
|
||||||
? Center(
|
apiForDomestic == null
|
||||||
child: Transform.scale(
|
? Center(
|
||||||
scale: 0.5,
|
child: Transform.scale(
|
||||||
child: CircularProgressIndicator(),
|
scale: 0.5,
|
||||||
),
|
child: CircularProgressIndicator(),
|
||||||
)
|
),
|
||||||
: DropdownSearch<String>(
|
)
|
||||||
selectedItem: selectedDomestic == null
|
: DropdownSearch<String>(
|
||||||
? null
|
selectedItem:
|
||||||
: apiForDomestic!
|
selectedDomestic == null
|
||||||
.firstWhere((policy) =>
|
? null
|
||||||
policy['policy_id'] ==
|
: apiForDomestic!
|
||||||
selectedDomestic)['name']
|
.firstWhere(
|
||||||
.toString(),
|
(policy) =>
|
||||||
popupProps: PopupProps.menu(
|
policy['policy_id'] ==
|
||||||
showSearchBox: true,
|
selectedDomestic,
|
||||||
fit: FlexFit.loose,
|
)['name']
|
||||||
constraints: BoxConstraints(maxHeight: 250),
|
.toString(),
|
||||||
searchFieldProps: TextFieldProps(
|
popupProps: PopupProps.menu(
|
||||||
decoration: InputDecoration(
|
showSearchBox: true,
|
||||||
hintText: "Search Policy...",
|
fit: FlexFit.loose,
|
||||||
contentPadding:
|
constraints: BoxConstraints(maxHeight: 250),
|
||||||
EdgeInsets.symmetric(horizontal: 10),
|
searchFieldProps: TextFieldProps(
|
||||||
|
decoration: InputDecoration(
|
||||||
|
hintText: "Search Policy...",
|
||||||
|
contentPadding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 10,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
items:
|
||||||
items: apiForDomestic!
|
apiForDomestic!
|
||||||
.map((policy) => policy['name'].toString())
|
.map((policy) => policy['name'].toString())
|
||||||
.toList(),
|
.toList(),
|
||||||
dropdownDecoratorProps: DropDownDecoratorProps(
|
dropdownDecoratorProps: DropDownDecoratorProps(
|
||||||
dropdownSearchDecoration: InputDecoration(
|
dropdownSearchDecoration: InputDecoration(
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding: EdgeInsets.symmetric(horizontal: 1),
|
contentPadding: EdgeInsets.symmetric(horizontal: 1),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
|
dropdownBuilder:
|
||||||
|
(context, selectedItem) => Align(
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
child: Text(
|
||||||
|
selectedItem ?? "Select",
|
||||||
|
style: TextStyle(fontSize: 12),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onChanged: (String? newValue) {
|
||||||
|
setState(() {
|
||||||
|
selectedDomestic =
|
||||||
|
apiForDomestic!.firstWhere(
|
||||||
|
(policy) => policy['name'] == newValue,
|
||||||
|
)['policy_id'];
|
||||||
|
});
|
||||||
|
},
|
||||||
),
|
),
|
||||||
dropdownBuilder: (context, selectedItem) => Align(
|
|
||||||
alignment: Alignment.centerLeft,
|
|
||||||
child: Text(
|
|
||||||
selectedItem ?? "Select",
|
|
||||||
style: TextStyle(fontSize: 12),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
onChanged: (String? newValue) {
|
|
||||||
setState(() {
|
|
||||||
selectedDomestic = apiForDomestic!.firstWhere(
|
|
||||||
(policy) =>
|
|
||||||
policy['name'] == newValue)['policy_id'];
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Column(
|
Column(
|
||||||
@ -663,72 +689,82 @@ class _groupState extends State<Group> {
|
|||||||
Text(
|
Text(
|
||||||
"Select Policy For International",
|
"Select Policy For International",
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
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: false,
|
isFocused: false,
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
width: isDesktop
|
width:
|
||||||
? MediaQuery.of(context).size.width * 0.34
|
isDesktop
|
||||||
: MediaQuery.of(context).size.width * 0.85,
|
? MediaQuery.of(context).size.width * 0.34
|
||||||
|
: MediaQuery.of(context).size.width * 0.85,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: apiForInternational == null
|
child:
|
||||||
? Center(
|
apiForInternational == null
|
||||||
child: Transform.scale(
|
? Center(
|
||||||
scale: 0.5,
|
child: Transform.scale(
|
||||||
child: CircularProgressIndicator(),
|
scale: 0.5,
|
||||||
),
|
child: CircularProgressIndicator(),
|
||||||
)
|
),
|
||||||
: DropdownSearch<String>(
|
)
|
||||||
selectedItem: selectedInternational == null
|
: DropdownSearch<String>(
|
||||||
? null
|
selectedItem:
|
||||||
: apiForInternational!
|
selectedInternational == null
|
||||||
.firstWhere((policy) =>
|
? null
|
||||||
policy['policy_id'] ==
|
: apiForInternational!
|
||||||
selectedInternational)['name']
|
.firstWhere(
|
||||||
.toString(),
|
(policy) =>
|
||||||
popupProps: PopupProps.menu(
|
policy['policy_id'] ==
|
||||||
showSearchBox: true,
|
selectedInternational,
|
||||||
fit: FlexFit.loose,
|
)['name']
|
||||||
constraints: BoxConstraints(maxHeight: 250),
|
.toString(),
|
||||||
searchFieldProps: TextFieldProps(
|
popupProps: PopupProps.menu(
|
||||||
decoration: InputDecoration(
|
showSearchBox: true,
|
||||||
hintText: "Search Policy...",
|
fit: FlexFit.loose,
|
||||||
contentPadding:
|
constraints: BoxConstraints(maxHeight: 250),
|
||||||
EdgeInsets.symmetric(horizontal: 10),
|
searchFieldProps: TextFieldProps(
|
||||||
|
decoration: InputDecoration(
|
||||||
|
hintText: "Search Policy...",
|
||||||
|
contentPadding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 10,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
items:
|
||||||
items: apiForInternational!
|
apiForInternational!
|
||||||
.map((policy) => policy['name'].toString())
|
.map((policy) => policy['name'].toString())
|
||||||
.toList(),
|
.toList(),
|
||||||
dropdownDecoratorProps: DropDownDecoratorProps(
|
dropdownDecoratorProps: DropDownDecoratorProps(
|
||||||
dropdownSearchDecoration: InputDecoration(
|
dropdownSearchDecoration: InputDecoration(
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding: EdgeInsets.symmetric(horizontal: 1),
|
contentPadding: EdgeInsets.symmetric(horizontal: 1),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
|
dropdownBuilder:
|
||||||
|
(context, selectedItem) => Align(
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
child: Text(
|
||||||
|
selectedItem ?? "Select",
|
||||||
|
style: TextStyle(fontSize: 12),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onChanged: (String? newValue) {
|
||||||
|
setState(() {
|
||||||
|
selectedInternational =
|
||||||
|
apiForInternational!.firstWhere(
|
||||||
|
(policy) => policy['name'] == newValue,
|
||||||
|
)['policy_id'];
|
||||||
|
});
|
||||||
|
},
|
||||||
),
|
),
|
||||||
dropdownBuilder: (context, selectedItem) => Align(
|
|
||||||
alignment: Alignment.centerLeft,
|
|
||||||
child: Text(
|
|
||||||
selectedItem ?? "Select",
|
|
||||||
style: TextStyle(fontSize: 12),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
onChanged: (String? newValue) {
|
|
||||||
setState(() {
|
|
||||||
selectedInternational = apiForInternational!
|
|
||||||
.firstWhere((policy) =>
|
|
||||||
policy['name'] == newValue)['policy_id'];
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
@ -737,22 +773,21 @@ class _groupState extends State<Group> {
|
|||||||
List<Widget> _buildSubmit(isDesktop) {
|
List<Widget> _buildSubmit(isDesktop) {
|
||||||
return [
|
return [
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Colors.white,
|
backgroundColor: Colors.white,
|
||||||
foregroundColor: layoutColor,
|
foregroundColor: layoutColor,
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
side: BorderSide(color: layoutColor ?? Colors.green, width: 2),
|
side: BorderSide(color: layoutColor ?? Colors.green, width: 2),
|
||||||
),
|
|
||||||
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
|
||||||
),
|
),
|
||||||
onPressed: () {
|
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
||||||
context.go('/group');
|
),
|
||||||
},
|
onPressed: () {
|
||||||
child: Text("Cancel")),
|
context.go('/group');
|
||||||
SizedBox(
|
},
|
||||||
width: 20,
|
child: Text("Cancel"),
|
||||||
),
|
),
|
||||||
|
SizedBox(width: 20),
|
||||||
MouseRegion(
|
MouseRegion(
|
||||||
// cursor: widget.isViewMode
|
// cursor: widget.isViewMode
|
||||||
// ? SystemMouseCursors.forbidden
|
// ? SystemMouseCursors.forbidden
|
||||||
@ -773,7 +808,7 @@ class _groupState extends State<Group> {
|
|||||||
onPressed: handleSubmit, // Disable when in view mode
|
onPressed: handleSubmit, // Disable when in view mode
|
||||||
child: Text("Submit"),
|
child: Text("Submit"),
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -407,7 +407,7 @@ class GroupDataState extends State<GroupData> {
|
|||||||
),
|
),
|
||||||
searchFieldProps: TextFieldProps(
|
searchFieldProps: TextFieldProps(
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: "Select Policy For International",
|
hintText: "Search ...",
|
||||||
hintStyle: GoogleFonts.poppins(fontSize: 11),
|
hintStyle: GoogleFonts.poppins(fontSize: 11),
|
||||||
contentPadding: EdgeInsets.symmetric(horizontal: 4),
|
contentPadding: EdgeInsets.symmetric(horizontal: 4),
|
||||||
),
|
),
|
||||||
@ -425,7 +425,7 @@ class GroupDataState extends State<GroupData> {
|
|||||||
// Center-align selected item
|
// Center-align selected item
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: Text(
|
child: Text(
|
||||||
selectedItem ?? "Select Policy For International",
|
selectedItem ?? "Select",
|
||||||
style: GoogleFonts.poppins(fontSize: 11),
|
style: GoogleFonts.poppins(fontSize: 11),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -481,7 +481,7 @@ class GroupDataState extends State<GroupData> {
|
|||||||
),
|
),
|
||||||
searchFieldProps: TextFieldProps(
|
searchFieldProps: TextFieldProps(
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: "Select Policy For Domestic...",
|
hintText: "Search ...",
|
||||||
hintStyle: GoogleFonts.poppins(fontSize: 11),
|
hintStyle: GoogleFonts.poppins(fontSize: 11),
|
||||||
contentPadding: EdgeInsets.symmetric(horizontal: 4),
|
contentPadding: EdgeInsets.symmetric(horizontal: 4),
|
||||||
),
|
),
|
||||||
@ -499,7 +499,7 @@ class GroupDataState extends State<GroupData> {
|
|||||||
// Center-align selected item
|
// Center-align selected item
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: Text(
|
child: Text(
|
||||||
selectedItem ?? "Select Policy For Domestic",
|
selectedItem ?? "Select ",
|
||||||
style: GoogleFonts.poppins(fontSize: 11),
|
style: GoogleFonts.poppins(fontSize: 11),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@ -353,7 +353,7 @@ class _GroupListState extends State<GroupList> {
|
|||||||
MainAxisSize.min, // Ensures content fits nicely
|
MainAxisSize.min, // Ensures content fits nicely
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Add New Group",
|
"Add Group",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: isDesktop ? 13 : 11,
|
fontSize: isDesktop ? 13 : 11,
|
||||||
),
|
),
|
||||||
|
|||||||
@ -418,7 +418,7 @@ class HotelsDataState extends State<HotelsData> {
|
|||||||
),
|
),
|
||||||
searchFieldProps: TextFieldProps(
|
searchFieldProps: TextFieldProps(
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: "Search Country...",
|
hintText: "Search ...",
|
||||||
hintStyle: GoogleFonts.poppins(fontSize: 11),
|
hintStyle: GoogleFonts.poppins(fontSize: 11),
|
||||||
contentPadding: EdgeInsets.symmetric(horizontal: 4),
|
contentPadding: EdgeInsets.symmetric(horizontal: 4),
|
||||||
),
|
),
|
||||||
@ -436,7 +436,7 @@ class HotelsDataState extends State<HotelsData> {
|
|||||||
// Center-align selected item
|
// Center-align selected item
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: Text(
|
child: Text(
|
||||||
selectedItem ?? "Select Country",
|
selectedItem ?? "Select ",
|
||||||
style: GoogleFonts.poppins(fontSize: 11),
|
style: GoogleFonts.poppins(fontSize: 11),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@ -15,13 +15,14 @@ class AccomodationScreen extends StatefulWidget {
|
|||||||
final String? loginUser;
|
final String? loginUser;
|
||||||
final String? tripType;
|
final String? tripType;
|
||||||
|
|
||||||
AccomodationScreen(
|
AccomodationScreen({
|
||||||
{required this.onClose,
|
required this.onClose,
|
||||||
required this.onSaveAccomadation,
|
required this.onSaveAccomadation,
|
||||||
required this.selectedItem,
|
required this.selectedItem,
|
||||||
required this.loginUser,
|
required this.loginUser,
|
||||||
required this.flightData,
|
required this.flightData,
|
||||||
this.tripType});
|
this.tripType,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_AccomodationScreenState createState() => _AccomodationScreenState();
|
_AccomodationScreenState createState() => _AccomodationScreenState();
|
||||||
@ -107,15 +108,23 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
_addFocusListener(
|
_addFocusListener(
|
||||||
_destinationFocusNode, (focus) => _destinationFocused = focus);
|
_destinationFocusNode,
|
||||||
|
(focus) => _destinationFocused = focus,
|
||||||
|
);
|
||||||
_addFocusListener(
|
_addFocusListener(
|
||||||
_hotelNameFocusNode, (focus) => _isHotelNameFocused = focus);
|
_hotelNameFocusNode,
|
||||||
|
(focus) => _isHotelNameFocused = focus,
|
||||||
|
);
|
||||||
_addFocusListener(_checkInFocusNode, (focus) => _checkInFocus = focus);
|
_addFocusListener(_checkInFocusNode, (focus) => _checkInFocus = focus);
|
||||||
_addFocusListener(
|
_addFocusListener(
|
||||||
_checkInTimeFocusNode, (focus) => _checkInTimeFocus = focus);
|
_checkInTimeFocusNode,
|
||||||
|
(focus) => _checkInTimeFocus = focus,
|
||||||
|
);
|
||||||
_addFocusListener(_checkOutFocusNode, (focus) => _checkOutFocus = focus);
|
_addFocusListener(_checkOutFocusNode, (focus) => _checkOutFocus = focus);
|
||||||
_addFocusListener(
|
_addFocusListener(
|
||||||
_checkOutTimeFocusNode, (focus) => _checkOutTimeFocus = focus);
|
_checkOutTimeFocusNode,
|
||||||
|
(focus) => _checkOutTimeFocus = focus,
|
||||||
|
);
|
||||||
_addFocusListener(_commentsFocusNode, (focus) => _commentsFocus = focus);
|
_addFocusListener(_commentsFocusNode, (focus) => _commentsFocus = focus);
|
||||||
|
|
||||||
_destinationController = initController("destination_city");
|
_destinationController = initController("destination_city");
|
||||||
@ -149,25 +158,29 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
flightFirstToDestinationNotifier.value = result['firstToDestination'];
|
flightFirstToDestinationNotifier.value = result['firstToDestination'];
|
||||||
|
|
||||||
print(
|
print(
|
||||||
"flightfirstToDestinationNotifier: $flightFirstToDestinationNotifier.value ");
|
"flightfirstToDestinationNotifier: $flightFirstToDestinationNotifier.value ",
|
||||||
|
);
|
||||||
|
|
||||||
// ✅ Only set controller after value is updated
|
// ✅ Only set controller after value is updated
|
||||||
// final parsedDate = DateTime.tryParse(flightFirstTripDateNotifier.value ?? '');
|
// final parsedDate = DateTime.tryParse(flightFirstTripDateNotifier.value ?? '');
|
||||||
final parsedDate = DateFormat("dd-MM-yyyy")
|
final parsedDate = DateFormat(
|
||||||
.parse(flightFirstTripDateNotifier.value ?? '');
|
"dd-MM-yyyy",
|
||||||
|
).parse(flightFirstTripDateNotifier.value ?? '');
|
||||||
if (parsedDate != null) {
|
if (parsedDate != null) {
|
||||||
_checkInController.text = DateFormat('dd-MM-yyyy').format(parsedDate);
|
_checkInController.text = DateFormat('dd-MM-yyyy').format(parsedDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
// final parsedEndDate = DateTime.tryParse(flightLastTripDateNotifier.value ?? '');
|
// final parsedEndDate = DateTime.tryParse(flightLastTripDateNotifier.value ?? '');
|
||||||
final parsedEndDate = DateFormat("dd-MM-yyyy")
|
final parsedEndDate = DateFormat(
|
||||||
.parse(flightLastTripDateNotifier.value ?? '');
|
"dd-MM-yyyy",
|
||||||
|
).parse(flightLastTripDateNotifier.value ?? '');
|
||||||
|
|
||||||
if (parsedEndDate != null) {
|
if (parsedEndDate != null) {
|
||||||
// _checkOutController.text = DateFormat('dd-MM-yyyy').format(parsedEndDate);
|
// _checkOutController.text = DateFormat('dd-MM-yyyy').format(parsedEndDate);
|
||||||
|
|
||||||
_checkOutController.text =
|
_checkOutController.text = DateFormat(
|
||||||
DateFormat('dd-MM-yyyy').format(parsedEndDate);
|
'dd-MM-yyyy',
|
||||||
|
).format(parsedEndDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ✅ Check and set default times if empty
|
// ✅ Check and set default times if empty
|
||||||
@ -202,17 +215,16 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Map<String, String?> getFlightTripDateRange(
|
Map<String, String?> getFlightTripDateRange(
|
||||||
List<Map<String, dynamic>> flightData) {
|
List<Map<String, dynamic>> flightData,
|
||||||
final allTrips = flightData
|
) {
|
||||||
.expand((flight) => flight['trips'] ?? [])
|
final allTrips =
|
||||||
.whereType<Map<String, dynamic>>()
|
flightData
|
||||||
.toList();
|
.expand((flight) => flight['trips'] ?? [])
|
||||||
|
.whereType<Map<String, dynamic>>()
|
||||||
|
.toList();
|
||||||
|
|
||||||
if (allTrips.isEmpty) {
|
if (allTrips.isEmpty) {
|
||||||
return {
|
return {'firstTripDate': null, 'lastTripDate': null};
|
||||||
'firstTripDate': null,
|
|
||||||
'lastTripDate': null,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
allTrips.sort((a, b) {
|
allTrips.sort((a, b) {
|
||||||
@ -230,7 +242,7 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
return {
|
return {
|
||||||
'firstTripDate': firstTrip['date'],
|
'firstTripDate': firstTrip['date'],
|
||||||
'lastTripDate': lastTrip['date'],
|
'lastTripDate': lastTrip['date'],
|
||||||
'firstToDestination': firstTripToDestination['to_place']
|
'firstToDestination': firstTripToDestination['to_place'],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,7 +256,7 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
"checkin_date",
|
"checkin_date",
|
||||||
"checkin_time",
|
"checkin_time",
|
||||||
"checkout_date",
|
"checkout_date",
|
||||||
"checkout_time"
|
"checkout_time",
|
||||||
];
|
];
|
||||||
|
|
||||||
// Check validation for each field
|
// Check validation for each field
|
||||||
@ -284,8 +296,9 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
checkOutTime.toString().isNotEmpty) {
|
checkOutTime.toString().isNotEmpty) {
|
||||||
try {
|
try {
|
||||||
final checkInDateTime = formatTime.parse("$checkIn $checkInTime");
|
final checkInDateTime = formatTime.parse("$checkIn $checkInTime");
|
||||||
final checkOutDateTime =
|
final checkOutDateTime = formatTime.parse(
|
||||||
formatTime.parse("$checkOut $checkOutTime");
|
"$checkOut $checkOutTime",
|
||||||
|
);
|
||||||
|
|
||||||
if (!checkOutDateTime.isAfter(checkInDateTime)) {
|
if (!checkOutDateTime.isAfter(checkInDateTime)) {
|
||||||
errorMessages["checkout_time"] =
|
errorMessages["checkout_time"] =
|
||||||
@ -359,60 +372,51 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ResponsiveBuilder(builder: (context, sizingInfo) {
|
return ResponsiveBuilder(
|
||||||
bool isMobile = sizingInfo.isMobile;
|
builder: (context, sizingInfo) {
|
||||||
bool isDesktop = sizingInfo.deviceScreenType == DeviceScreenType.desktop;
|
bool isMobile = sizingInfo.isMobile;
|
||||||
|
bool isDesktop =
|
||||||
|
sizingInfo.deviceScreenType == DeviceScreenType.desktop;
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
// color: Color(0xFFF4F4FB),
|
// color: Color(0xFFF4F4FB),
|
||||||
child: Form(
|
child: Form(
|
||||||
key: _formKey,
|
key: _formKey,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(28.0),
|
padding: const EdgeInsets.only(top: 30.0),
|
||||||
child: Center(
|
child: Center(
|
||||||
child: Column(children: _buildAccomadtionForm(isDesktop)),
|
child: Column(children: _buildAccomadtionForm(isDesktop)),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
)
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
);
|
},
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> _buildAccomadtionForm(isDesktop) {
|
List<Widget> _buildAccomadtionForm(isDesktop) {
|
||||||
return [
|
return [
|
||||||
isDesktop
|
isDesktop
|
||||||
? Row(
|
? Row(children: _buildFirstRow(isDesktop))
|
||||||
children: _buildFirstRow(isDesktop),
|
: Column(children: _buildFirstRow(isDesktop)),
|
||||||
)
|
|
||||||
: Column(
|
|
||||||
children: _buildFirstRow(isDesktop),
|
|
||||||
),
|
|
||||||
|
|
||||||
SizedBox(height: 10), // Spacing between first and second row
|
SizedBox(height: 10), // Spacing between first and second row
|
||||||
isDesktop
|
isDesktop
|
||||||
? Row(
|
? Row(children: _buildSecondRow(isDesktop))
|
||||||
children: _buildSecondRow(isDesktop),
|
: Column(children: _buildSecondRow(isDesktop)),
|
||||||
)
|
|
||||||
: Column(
|
|
||||||
children: _buildSecondRow(isDesktop),
|
|
||||||
),
|
|
||||||
|
|
||||||
SizedBox(height: 10),
|
SizedBox(height: 10),
|
||||||
|
|
||||||
isDesktop
|
isDesktop
|
||||||
? Row(
|
? Row(children: _buildThirdRow(isDesktop))
|
||||||
children: _buildThirdRow(isDesktop),
|
: Column(children: _buildThirdRow(isDesktop)),
|
||||||
)
|
|
||||||
: Column(
|
|
||||||
children: _buildThirdRow(isDesktop),
|
|
||||||
),
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -432,24 +436,25 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
// ),
|
// ),
|
||||||
// ],
|
// ],
|
||||||
// ),
|
// ),
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Destination",
|
"Destination *",
|
||||||
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: _destinationFocused,
|
isFocused: _destinationFocused,
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
width: isDesktop
|
width:
|
||||||
? MediaQuery.of(context).size.width * 0.34
|
isDesktop
|
||||||
: MediaQuery.of(context).size.width * 0.66,
|
? MediaQuery.of(context).size.width * 0.34
|
||||||
|
: MediaQuery.of(context).size.width * 0.66,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
@ -475,29 +480,26 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (isDesktop)
|
if (isDesktop) Spacer() else SizedBox(height: 8),
|
||||||
Spacer()
|
|
||||||
else
|
|
||||||
SizedBox(
|
|
||||||
height: 8,
|
|
||||||
),
|
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Hotel Name",
|
"Hotel Name *",
|
||||||
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: _isHotelNameFocused,
|
isFocused: _isHotelNameFocused,
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
width: isDesktop
|
width:
|
||||||
? MediaQuery.of(context).size.width * 0.34
|
isDesktop
|
||||||
: MediaQuery.of(context).size.width * 0.66,
|
? MediaQuery.of(context).size.width * 0.34
|
||||||
|
: MediaQuery.of(context).size.width * 0.66,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
@ -557,6 +559,7 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
initialDate: initialDate,
|
initialDate: initialDate,
|
||||||
firstDate: initialDate,
|
firstDate: initialDate,
|
||||||
lastDate: DateTime(2100),
|
lastDate: DateTime(2100),
|
||||||
|
initialEntryMode: DatePickerEntryMode.calendarOnly,
|
||||||
);
|
);
|
||||||
|
|
||||||
// DateTime? pickedDate = await showDatePicker(
|
// DateTime? pickedDate = await showDatePicker(
|
||||||
@ -583,18 +586,61 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
initialTime: _selectedCheckInTime ?? TimeOfDay.now(),
|
initialTime: _selectedCheckInTime ?? TimeOfDay.now(),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (pickedTime != null && pickedTime != _selectedCheckInTime) {
|
if (pickedTime != null) {
|
||||||
|
final now = DateTime.now();
|
||||||
|
|
||||||
|
// Parse the selected date
|
||||||
|
final dateText = _checkInController.text ?? "";
|
||||||
|
final selectedDate = DateFormat(
|
||||||
|
'dd-MM-yyyy',
|
||||||
|
).parse(dateText); // or 'yyyy-MM-dd' depending on your format
|
||||||
|
|
||||||
|
final selectedDateTime = DateTime(
|
||||||
|
selectedDate.year,
|
||||||
|
selectedDate.month,
|
||||||
|
selectedDate.day,
|
||||||
|
pickedTime.hour,
|
||||||
|
pickedTime.minute,
|
||||||
|
);
|
||||||
|
|
||||||
|
// ✅ Only validate past time if date is today
|
||||||
|
final isToday =
|
||||||
|
selectedDate.year == now.year &&
|
||||||
|
selectedDate.month == now.month &&
|
||||||
|
selectedDate.day == now.day;
|
||||||
|
|
||||||
|
bool isPastTime = selectedDateTime.isBefore(now);
|
||||||
|
|
||||||
|
if (isToday && isPastTime) {
|
||||||
|
setState(() {
|
||||||
|
errorMessages["checkin_time"] = "You can't select a past time.";
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ✅ Valid time selection
|
||||||
setState(() {
|
setState(() {
|
||||||
_selectedCheckInTime = pickedTime;
|
_selectedCheckInTime = pickedTime;
|
||||||
// Formatting time to HH:mm (24-hour format)
|
|
||||||
final now = DateTime.now();
|
final formattedTime = DateFormat('HH:mm').format(selectedDateTime);
|
||||||
final formattedTime = DateFormat('HH:mm').format(
|
|
||||||
DateTime(now.year, now.month, now.day, pickedTime.hour,
|
|
||||||
pickedTime.minute),
|
|
||||||
);
|
|
||||||
_checkInTimeController.text = formattedTime;
|
_checkInTimeController.text = formattedTime;
|
||||||
|
// errorMessages["time_$index"] = ""; // clear previous error
|
||||||
|
errorMessages.remove("checkin_time");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if (pickedTime != null && pickedTime != _selectedCheckInTime) {
|
||||||
|
// setState(() {
|
||||||
|
// _selectedCheckInTime = pickedTime;
|
||||||
|
// // Formatting time to HH:mm (24-hour format)
|
||||||
|
// final now = DateTime.now();
|
||||||
|
// final formattedTime = DateFormat('HH:mm').format(
|
||||||
|
// DateTime(now.year, now.month, now.day, pickedTime.hour,
|
||||||
|
// pickedTime.minute),
|
||||||
|
// );
|
||||||
|
// _checkInTimeController.text = formattedTime;
|
||||||
|
// });
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
//-------------------------------Check-In End
|
//-------------------------------Check-In End
|
||||||
|
|
||||||
@ -647,23 +693,26 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
// : firstDate;
|
// : firstDate;
|
||||||
|
|
||||||
DateTime firstDate = checkInDate;
|
DateTime firstDate = checkInDate;
|
||||||
DateTime initialDate = _selectedCheckOutDate != null &&
|
DateTime initialDate =
|
||||||
_selectedCheckOutDate!.isAfter(firstDate)
|
_selectedCheckOutDate != null &&
|
||||||
? _selectedCheckOutDate!
|
_selectedCheckOutDate!.isAfter(firstDate)
|
||||||
: firstDate;
|
? _selectedCheckOutDate!
|
||||||
|
: firstDate;
|
||||||
|
|
||||||
final pickedDate = await showDatePicker(
|
final pickedDate = await showDatePicker(
|
||||||
context: context,
|
context: context,
|
||||||
initialDate: initialDate,
|
initialDate: initialDate,
|
||||||
firstDate: firstDate,
|
firstDate: firstDate,
|
||||||
lastDate: DateTime(2100),
|
lastDate: DateTime(2100),
|
||||||
|
initialEntryMode: DatePickerEntryMode.calendarOnly,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (pickedDate != null && pickedDate != _selectedCheckOutDate) {
|
if (pickedDate != null && pickedDate != _selectedCheckOutDate) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_selectedCheckOutDate = pickedDate;
|
_selectedCheckOutDate = pickedDate;
|
||||||
_checkOutController.text =
|
_checkOutController.text = DateFormat(
|
||||||
DateFormat('dd-MM-yyyy').format(pickedDate);
|
'dd-MM-yyyy',
|
||||||
|
).format(pickedDate);
|
||||||
errorMessages.remove("checkout_date");
|
errorMessages.remove("checkout_date");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -681,8 +730,13 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
// Formatting time to HH:mm (24-hour format)
|
// Formatting time to HH:mm (24-hour format)
|
||||||
final now = DateTime.now();
|
final now = DateTime.now();
|
||||||
final formattedTime = DateFormat('HH:mm').format(
|
final formattedTime = DateFormat('HH:mm').format(
|
||||||
DateTime(now.year, now.month, now.day, pickedTime.hour,
|
DateTime(
|
||||||
pickedTime.minute),
|
now.year,
|
||||||
|
now.month,
|
||||||
|
now.day,
|
||||||
|
pickedTime.hour,
|
||||||
|
pickedTime.minute,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
_checkOutTimeController.text = formattedTime;
|
_checkOutTimeController.text = formattedTime;
|
||||||
errorMessages.remove("checkout_time");
|
errorMessages.remove("checkout_time");
|
||||||
@ -695,11 +749,12 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Check-in*",
|
"Check-in *",
|
||||||
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),
|
||||||
CustomTextFieldItnerarySubWrapper(
|
CustomTextFieldItnerarySubWrapper(
|
||||||
@ -720,8 +775,11 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
floatingLabelBehavior: FloatingLabelBehavior.never,
|
floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
||||||
suffixIcon: Icon(Icons.calendar_today,
|
suffixIcon: Icon(
|
||||||
size: 16, color: Colors.grey),
|
Icons.calendar_today,
|
||||||
|
size: 16,
|
||||||
|
color: Colors.grey,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -737,21 +795,17 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (isDesktop)
|
if (isDesktop) Spacer() else SizedBox(height: 8),
|
||||||
Spacer()
|
|
||||||
else
|
|
||||||
SizedBox(
|
|
||||||
height: 8,
|
|
||||||
),
|
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Time (Check-in)",
|
"Time (Check-in) *",
|
||||||
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),
|
||||||
CustomTextFieldItnerarySubWrapper(
|
CustomTextFieldItnerarySubWrapper(
|
||||||
@ -760,7 +814,10 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: () => _selectCheckInTime(context),
|
onTap: () {
|
||||||
|
_checkInTimeController.text = "";
|
||||||
|
_selectCheckInTime(context);
|
||||||
|
},
|
||||||
child: AbsorbPointer(
|
child: AbsorbPointer(
|
||||||
child: TextField(
|
child: TextField(
|
||||||
focusNode: _checkInTimeFocusNode,
|
focusNode: _checkInTimeFocusNode,
|
||||||
@ -772,8 +829,11 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
floatingLabelBehavior: FloatingLabelBehavior.never,
|
floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
||||||
suffixIcon:
|
suffixIcon: Icon(
|
||||||
Icon(Icons.access_time, size: 16, color: Colors.grey),
|
Icons.access_time,
|
||||||
|
size: 16,
|
||||||
|
color: Colors.grey,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -789,21 +849,17 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (isDesktop)
|
if (isDesktop) Spacer() else SizedBox(height: 8),
|
||||||
Spacer()
|
|
||||||
else
|
|
||||||
SizedBox(
|
|
||||||
height: 8,
|
|
||||||
),
|
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Check-out*",
|
"Check-out*",
|
||||||
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),
|
||||||
CustomTextFieldItnerarySubWrapper(
|
CustomTextFieldItnerarySubWrapper(
|
||||||
@ -817,15 +873,18 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
child: TextField(
|
child: TextField(
|
||||||
focusNode: _checkOutFocusNode,
|
focusNode: _checkOutFocusNode,
|
||||||
controller: _checkOutController,
|
controller: _checkOutController,
|
||||||
style: const TextStyle(fontSize: 12),
|
style: const TextStyle(fontSize: 12, color: Colors.black),
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
labelText: "Select Date",
|
labelText: "Select Date",
|
||||||
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),
|
||||||
suffixIcon: Icon(Icons.calendar_today,
|
suffixIcon: Icon(
|
||||||
size: 16, color: Colors.grey),
|
Icons.calendar_today,
|
||||||
|
size: 16,
|
||||||
|
color: Colors.grey,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -841,21 +900,17 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (isDesktop)
|
if (isDesktop) Spacer() else SizedBox(height: 8),
|
||||||
Spacer()
|
|
||||||
else
|
|
||||||
SizedBox(
|
|
||||||
height: 8,
|
|
||||||
),
|
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Time (Check-out)",
|
"Time (Check-out) *",
|
||||||
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),
|
||||||
CustomTextFieldItnerarySubWrapper(
|
CustomTextFieldItnerarySubWrapper(
|
||||||
@ -876,8 +931,11 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
floatingLabelBehavior: FloatingLabelBehavior.never,
|
floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
||||||
suffixIcon:
|
suffixIcon: Icon(
|
||||||
Icon(Icons.access_time, size: 16, color: Colors.grey),
|
Icons.access_time,
|
||||||
|
size: 16,
|
||||||
|
color: Colors.grey,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -904,17 +962,19 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
Text(
|
Text(
|
||||||
"Comments",
|
"Comments",
|
||||||
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: _commentsFocus, // Dropdown doesn't use focus
|
isFocused: _commentsFocus, // Dropdown doesn't use focus
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
width: isDesktop
|
width:
|
||||||
? MediaQuery.of(context).size.width * 0.34
|
isDesktop
|
||||||
: MediaQuery.of(context).size.width * 0.66,
|
? MediaQuery.of(context).size.width * 0.34
|
||||||
|
: MediaQuery.of(context).size.width * 0.66,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
@ -934,9 +994,7 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (isDesktop) Spacer(),
|
if (isDesktop) Spacer(),
|
||||||
SizedBox(
|
SizedBox(height: 5),
|
||||||
height: 5,
|
|
||||||
),
|
|
||||||
Column(
|
Column(
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
@ -957,9 +1015,7 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Colors.grey[400], // Light grey color
|
backgroundColor: Colors.grey[400], // Light grey color
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
|
||||||
borderRadius: BorderRadius.circular(8),
|
|
||||||
),
|
|
||||||
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
@ -968,7 +1024,6 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(width: 10), // Space between buttons
|
SizedBox(width: 10), // Space between buttons
|
||||||
|
|
||||||
// Save Changes Button
|
// Save Changes Button
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
@ -976,9 +1031,7 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Color(0xFF114D8B), // Primary color for save
|
backgroundColor: Color(0xFF114D8B), // Primary color for save
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
|
||||||
borderRadius: BorderRadius.circular(8),
|
|
||||||
),
|
|
||||||
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
|
|||||||
@ -13,12 +13,13 @@ class BusScreen extends StatefulWidget {
|
|||||||
final Map<String, dynamic>? selectedItem;
|
final Map<String, dynamic>? selectedItem;
|
||||||
final String? loginUser;
|
final String? loginUser;
|
||||||
|
|
||||||
BusScreen(
|
BusScreen({
|
||||||
{required this.onClose,
|
required this.onClose,
|
||||||
this.apiData,
|
this.apiData,
|
||||||
required this.onSaveBus,
|
required this.onSaveBus,
|
||||||
required this.selectedItem,
|
required this.selectedItem,
|
||||||
required this.loginUser});
|
required this.loginUser,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_BusScreenState createState() => _BusScreenState();
|
_BusScreenState createState() => _BusScreenState();
|
||||||
@ -195,51 +196,54 @@ class _BusScreenState extends State<BusScreen> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ResponsiveBuilder(builder: (context, sizingInfo) {
|
return ResponsiveBuilder(
|
||||||
bool isMobile = sizingInfo.isMobile;
|
builder: (context, sizingInfo) {
|
||||||
bool isDesktop = sizingInfo.deviceScreenType == DeviceScreenType.desktop;
|
bool isMobile = sizingInfo.isMobile;
|
||||||
|
bool isDesktop =
|
||||||
|
sizingInfo.deviceScreenType == DeviceScreenType.desktop;
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
// color: Colors.white,
|
// color: Colors.white,
|
||||||
child: Form(
|
child: Form(
|
||||||
key: _formKey,
|
key: _formKey,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
// Align(
|
// Align(
|
||||||
// alignment: Alignment.centerRight,
|
// alignment: Alignment.centerRight,
|
||||||
// child: InkWell(
|
// child: InkWell(
|
||||||
// onTap: () {
|
// onTap: () {
|
||||||
// widget.onClose(false);
|
// widget.onClose(false);
|
||||||
// },
|
// },
|
||||||
// child: Icon(
|
// child: Icon(
|
||||||
// Icons.close,
|
// Icons.close,
|
||||||
// size: 18,
|
// size: 18,
|
||||||
// color: Color(0xFF575A74),
|
// color: Color(0xFF575A74),
|
||||||
// ),
|
// ),
|
||||||
// ),
|
// ),
|
||||||
// ),
|
// ),
|
||||||
// Text("Bus Booking List",
|
// Text("Bus Booking List",
|
||||||
// style: TextStyle(
|
// style: TextStyle(
|
||||||
// fontSize: 18,
|
// fontSize: 18,
|
||||||
// fontWeight: FontWeight.bold,
|
// fontWeight: FontWeight.bold,
|
||||||
// color: Color(0xFF575A74))),
|
// color: Color(0xFF575A74))),
|
||||||
// SizedBox(
|
// SizedBox(
|
||||||
// height: 6,
|
// height: 6,
|
||||||
// ),
|
// ),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(28.0),
|
padding: const EdgeInsets.only(top: 30.0),
|
||||||
child: Center(
|
child: Center(
|
||||||
child: Column(children: _buildAccomadtionForm(isDesktop)),
|
child: Column(children: _buildAccomadtionForm(isDesktop)),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
)
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
);
|
},
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> _buildAccomadtionForm(bool isDesktop) {
|
List<Widget> _buildAccomadtionForm(bool isDesktop) {
|
||||||
@ -252,7 +256,7 @@ class _BusScreenState extends State<BusScreen> {
|
|||||||
|
|
||||||
List<List<Widget>> rowBuilders = [
|
List<List<Widget>> rowBuilders = [
|
||||||
// _builClassType(isDesktop),
|
// _builClassType(isDesktop),
|
||||||
_buildSecondRow(isDesktop)
|
_buildSecondRow(isDesktop),
|
||||||
];
|
];
|
||||||
|
|
||||||
return [
|
return [
|
||||||
@ -275,41 +279,42 @@ class _BusScreenState extends State<BusScreen> {
|
|||||||
Text(
|
Text(
|
||||||
"Trip Type",
|
"Trip Type",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
isDesktop
|
isDesktop
|
||||||
? Row(children: _buildTripType(isDesktop))
|
? Row(children: _buildTripType(isDesktop))
|
||||||
: Column(children: _buildTripType(isDesktop))
|
: Column(children: _buildTripType(isDesktop)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (isDesktop)
|
if (isDesktop) Spacer() else SizedBox(height: 8),
|
||||||
Spacer()
|
|
||||||
else
|
|
||||||
SizedBox(
|
|
||||||
height: 8,
|
|
||||||
),
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> _buildTripType(bool isDesktop) {
|
List<Widget> _buildTripType(bool isDesktop) {
|
||||||
List<dynamic> purposeList = widget.apiData?['flight_trip_type'] ?? [];
|
List<dynamic> purposeList = widget.apiData?['flight_trip_type'] ?? [];
|
||||||
|
|
||||||
List<DropdownMenuItem<String>> dropdownItems = purposeList
|
List<DropdownMenuItem<String>> dropdownItems =
|
||||||
.map((item) => DropdownMenuItem<String>(
|
purposeList
|
||||||
value: item['dropdown_key'],
|
.map(
|
||||||
child: Text(item['dropdown_value']),
|
(item) => DropdownMenuItem<String>(
|
||||||
))
|
value: item['dropdown_key'],
|
||||||
.toList();
|
child: Text(item['dropdown_value']),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList();
|
||||||
|
|
||||||
if (dropdownItems.isEmpty) {
|
if (dropdownItems.isEmpty) {
|
||||||
dropdownItems.add(
|
dropdownItems.add(
|
||||||
DropdownMenuItem<String>(
|
DropdownMenuItem<String>(
|
||||||
value: null,
|
value: null,
|
||||||
child: Text("No options available",
|
child: Text(
|
||||||
style: TextStyle(color: Colors.grey)),
|
"No options available",
|
||||||
|
style: TextStyle(color: Colors.grey),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -327,21 +332,25 @@ class _BusScreenState extends State<BusScreen> {
|
|||||||
child: DropdownButtonFormField<String>(
|
child: DropdownButtonFormField<String>(
|
||||||
focusNode: _tripTypeFocusNode, // Assign the correct focus node
|
focusNode: _tripTypeFocusNode, // Assign the correct focus node
|
||||||
value: selectedPurpose,
|
value: selectedPurpose,
|
||||||
style: TextStyle(fontSize: 12),
|
// style: TextStyle(fontSize: 12),
|
||||||
|
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding:
|
contentPadding: EdgeInsets.symmetric(
|
||||||
EdgeInsets.symmetric(horizontal: 10), // Proper padding
|
horizontal: 10,
|
||||||
|
), // Proper padding
|
||||||
),
|
),
|
||||||
onChanged: purposeList.isNotEmpty
|
onChanged:
|
||||||
? (newValue) {
|
purposeList.isNotEmpty
|
||||||
setState(() {
|
? (newValue) {
|
||||||
selectedPurpose = newValue;
|
setState(() {
|
||||||
});
|
selectedPurpose = newValue;
|
||||||
print(
|
});
|
||||||
"Updating form data: Flight -> trip_type -> ${newValue ?? ""}");
|
print(
|
||||||
}
|
"Updating form data: Flight -> trip_type -> ${newValue ?? ""}",
|
||||||
: null,
|
);
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
|
||||||
items: dropdownItems,
|
items: dropdownItems,
|
||||||
),
|
),
|
||||||
@ -360,12 +369,14 @@ class _BusScreenState extends State<BusScreen> {
|
|||||||
|
|
||||||
DateTime? pickedDate = await showDatePicker(
|
DateTime? pickedDate = await showDatePicker(
|
||||||
context: context,
|
context: context,
|
||||||
initialDate: _selectedCheckOutDate != null &&
|
initialDate:
|
||||||
_selectedCheckOutDate!.isAfter(today)
|
_selectedCheckOutDate != null &&
|
||||||
? _selectedCheckOutDate!
|
_selectedCheckOutDate!.isAfter(today)
|
||||||
: today,
|
? _selectedCheckOutDate!
|
||||||
|
: today,
|
||||||
firstDate: today,
|
firstDate: today,
|
||||||
lastDate: DateTime(2100),
|
lastDate: DateTime(2100),
|
||||||
|
initialEntryMode: DatePickerEntryMode.calendarOnly,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (pickedDate != null && pickedDate != _selectedCheckOutDate) {
|
if (pickedDate != null && pickedDate != _selectedCheckOutDate) {
|
||||||
@ -383,16 +394,50 @@ class _BusScreenState extends State<BusScreen> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (pickedTime != null && pickedTime != _selectedCheckOutTime) {
|
if (pickedTime != null && pickedTime != _selectedCheckOutTime) {
|
||||||
setState(() {
|
// Parse the selected date
|
||||||
_selectedCheckOutTime = pickedTime;
|
final dateText = _dateController.text ?? "";
|
||||||
// Formatting time to HH:mm (24-hour format)
|
final selectedDate = DateFormat(
|
||||||
final now = DateTime.now();
|
'dd-MM-yyyy',
|
||||||
final formattedTime = DateFormat('HH:mm').format(
|
).parse(dateText); // or 'yyyy-MM-dd' depending on your format
|
||||||
DateTime(now.year, now.month, now.day, pickedTime.hour,
|
final now = DateTime.now();
|
||||||
pickedTime.minute),
|
|
||||||
);
|
final selectedDateTime = DateTime(
|
||||||
_timeController.text = formattedTime;
|
selectedDate.year,
|
||||||
});
|
selectedDate.month,
|
||||||
|
selectedDate.day,
|
||||||
|
pickedTime.hour,
|
||||||
|
pickedTime.minute,
|
||||||
|
);
|
||||||
|
|
||||||
|
final isToday =
|
||||||
|
selectedDate.year == now.year &&
|
||||||
|
selectedDate.month == now.month &&
|
||||||
|
selectedDate.day == now.day;
|
||||||
|
|
||||||
|
bool isPastTime = selectedDateTime.isBefore(now);
|
||||||
|
|
||||||
|
if (isToday && isPastTime) {
|
||||||
|
setState(() {
|
||||||
|
errorMessages["time"] = "You can't select a past time.";
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
setState(() {
|
||||||
|
_selectedCheckOutTime = pickedTime;
|
||||||
|
// Formatting time to HH:mm (24-hour format)
|
||||||
|
final now = DateTime.now();
|
||||||
|
final formattedTime = DateFormat('HH:mm').format(
|
||||||
|
DateTime(
|
||||||
|
now.year,
|
||||||
|
now.month,
|
||||||
|
now.day,
|
||||||
|
pickedTime.hour,
|
||||||
|
pickedTime.minute,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
_timeController.text = formattedTime;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -401,11 +446,12 @@ class _BusScreenState extends State<BusScreen> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"From",
|
"From *",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldItnerarySubWrapper(
|
CustomTextFieldItnerarySubWrapper(
|
||||||
@ -429,28 +475,21 @@ class _BusScreenState extends State<BusScreen> {
|
|||||||
),
|
),
|
||||||
if (errorMessages["from"] != null) ...[
|
if (errorMessages["from"] != null) ...[
|
||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
Text(
|
Text("Required", style: TextStyle(color: Colors.red, fontSize: 12)),
|
||||||
"Required",
|
|
||||||
style: TextStyle(color: Colors.red, fontSize: 12),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (isDesktop)
|
if (isDesktop) Spacer() else SizedBox(height: 8),
|
||||||
Spacer()
|
|
||||||
else
|
|
||||||
SizedBox(
|
|
||||||
height: 8,
|
|
||||||
),
|
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"To",
|
"To *",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldItnerarySubWrapper(
|
CustomTextFieldItnerarySubWrapper(
|
||||||
@ -474,28 +513,21 @@ class _BusScreenState extends State<BusScreen> {
|
|||||||
),
|
),
|
||||||
if (errorMessages["to"] != null) ...[
|
if (errorMessages["to"] != null) ...[
|
||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
Text(
|
Text("Required", style: TextStyle(color: Colors.red, fontSize: 12)),
|
||||||
"Required",
|
|
||||||
style: TextStyle(color: Colors.red, fontSize: 12),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (isDesktop)
|
if (isDesktop) Spacer() else SizedBox(height: 8),
|
||||||
Spacer()
|
|
||||||
else
|
|
||||||
SizedBox(
|
|
||||||
height: 8,
|
|
||||||
),
|
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Date",
|
"Date *",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldItnerarySubWrapper(
|
CustomTextFieldItnerarySubWrapper(
|
||||||
@ -516,8 +548,11 @@ class _BusScreenState extends State<BusScreen> {
|
|||||||
floatingLabelBehavior: FloatingLabelBehavior.never,
|
floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
||||||
suffixIcon: Icon(Icons.calendar_today,
|
suffixIcon: Icon(
|
||||||
size: 16, color: Colors.grey),
|
Icons.calendar_today,
|
||||||
|
size: 16,
|
||||||
|
color: Colors.grey,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -526,28 +561,21 @@ class _BusScreenState extends State<BusScreen> {
|
|||||||
),
|
),
|
||||||
if (errorMessages["date"] != null) ...[
|
if (errorMessages["date"] != null) ...[
|
||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
Text(
|
Text("Required", style: TextStyle(color: Colors.red, fontSize: 12)),
|
||||||
"Required",
|
|
||||||
style: TextStyle(color: Colors.red, fontSize: 12),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (isDesktop)
|
if (isDesktop) Spacer() else SizedBox(height: 8),
|
||||||
Spacer()
|
|
||||||
else
|
|
||||||
SizedBox(
|
|
||||||
height: 8,
|
|
||||||
),
|
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Time",
|
"Time *",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldItnerarySubWrapper(
|
CustomTextFieldItnerarySubWrapper(
|
||||||
@ -556,20 +584,27 @@ class _BusScreenState extends State<BusScreen> {
|
|||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: () => _selectCheckOutTime(context),
|
onTap: () {
|
||||||
|
// _selectedCheckOutTime = null; // ✅ Reset time variable
|
||||||
|
_timeController.text = ""; // ✅ Clear text field
|
||||||
|
_selectCheckOutTime(context);
|
||||||
|
},
|
||||||
child: AbsorbPointer(
|
child: AbsorbPointer(
|
||||||
child: TextField(
|
child: TextField(
|
||||||
focusNode: _timeFocusNode,
|
focusNode: _timeFocusNode,
|
||||||
controller: _timeController,
|
controller: _timeController,
|
||||||
style: const TextStyle(fontSize: 12),
|
style: const TextStyle(fontSize: 12, color: Colors.black),
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
labelText: "Select Time",
|
labelText: "Select Time",
|
||||||
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),
|
||||||
suffixIcon:
|
suffixIcon: Icon(
|
||||||
Icon(Icons.access_time, size: 16, color: Colors.grey),
|
Icons.access_time,
|
||||||
|
size: 16,
|
||||||
|
color: Colors.grey,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -579,7 +614,7 @@ class _BusScreenState extends State<BusScreen> {
|
|||||||
if (errorMessages["time"] != null) ...[
|
if (errorMessages["time"] != null) ...[
|
||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
Text(
|
Text(
|
||||||
"Required",
|
errorMessages["time"]!,
|
||||||
style: TextStyle(color: Colors.red, fontSize: 12),
|
style: TextStyle(color: Colors.red, fontSize: 12),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -596,9 +631,10 @@ class _BusScreenState extends State<BusScreen> {
|
|||||||
Text(
|
Text(
|
||||||
"Comments",
|
"Comments",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldWrapper(
|
CustomTextFieldWrapper(
|
||||||
@ -644,9 +680,7 @@ class _BusScreenState extends State<BusScreen> {
|
|||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Colors.grey[400], // Light grey color
|
backgroundColor: Colors.grey[400], // Light grey color
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
|
||||||
borderRadius: BorderRadius.circular(8),
|
|
||||||
),
|
|
||||||
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
@ -655,7 +689,6 @@ class _BusScreenState extends State<BusScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(width: 10), // Space between buttons
|
SizedBox(width: 10), // Space between buttons
|
||||||
|
|
||||||
// Save Changes Button
|
// Save Changes Button
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
@ -663,9 +696,7 @@ class _BusScreenState extends State<BusScreen> {
|
|||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Color(0xFF114D8B), // Primary color for save
|
backgroundColor: Color(0xFF114D8B), // Primary color for save
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
|
||||||
borderRadius: BorderRadius.circular(8),
|
|
||||||
),
|
|
||||||
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -53,6 +53,7 @@ class _ForexScreenState extends State<ForexScreen> {
|
|||||||
|
|
||||||
int fifteenPercent = 0;
|
int fifteenPercent = 0;
|
||||||
int remainingAmount = 0;
|
int remainingAmount = 0;
|
||||||
|
bool isWidget = false;
|
||||||
|
|
||||||
Map<String, FocusNode> focusNodes = {};
|
Map<String, FocusNode> focusNodes = {};
|
||||||
Map<String, bool> focusStates = {};
|
Map<String, bool> focusStates = {};
|
||||||
@ -248,6 +249,31 @@ class _ForexScreenState extends State<ForexScreen> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Additional validation starts
|
||||||
|
final start_Date = data["start_date"];
|
||||||
|
final end_Date = data["end_date"];
|
||||||
|
|
||||||
|
if (start_Date != null &&
|
||||||
|
end_Date != null &&
|
||||||
|
start_Date.toString().isNotEmpty &&
|
||||||
|
end_Date.toString().isNotEmpty) {
|
||||||
|
try {
|
||||||
|
final format = DateFormat("dd-MM-yyyy");
|
||||||
|
|
||||||
|
final checkStartDate = format.parse("$start_Date");
|
||||||
|
final checkEndDate = format.parse("$end_Date");
|
||||||
|
|
||||||
|
if (checkEndDate.isBefore(checkStartDate)) {
|
||||||
|
errorMessages["end_date"] =
|
||||||
|
"End date cannot be earlier than start date";
|
||||||
|
;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
errorMessages["end_date"] = "Invalid date format";
|
||||||
|
}
|
||||||
|
return errorMessages.isEmpty;
|
||||||
|
}
|
||||||
|
// Additional validation ends
|
||||||
return errorMessages.values.every((msg) => msg.trim().isEmpty);
|
return errorMessages.values.every((msg) => msg.trim().isEmpty);
|
||||||
|
|
||||||
// if (hasErrors) {
|
// if (hasErrors) {
|
||||||
@ -290,7 +316,13 @@ class _ForexScreenState extends State<ForexScreen> {
|
|||||||
|
|
||||||
Map<String, dynamic> data = forexData;
|
Map<String, dynamic> data = forexData;
|
||||||
|
|
||||||
if (!isValidForexData(data) && errorMessages.isNotEmpty) {
|
final card = data["deposit_on_card"];
|
||||||
|
final cash = data["deposit_on_cash"];
|
||||||
|
print("card - $card");
|
||||||
|
print("cash - $cash");
|
||||||
|
|
||||||
|
if (!isValidForexData(data)) {
|
||||||
|
// && errorMessages.isNotEmpty) {
|
||||||
print("Validation Failed: Required fields are missing.");
|
print("Validation Failed: Required fields are missing.");
|
||||||
setState(() {});
|
setState(() {});
|
||||||
return; // Stop execution if validation fails
|
return; // Stop execution if validation fails
|
||||||
@ -419,12 +451,16 @@ class _ForexScreenState extends State<ForexScreen> {
|
|||||||
selectedCashPercent = int.tryParse(
|
selectedCashPercent = int.tryParse(
|
||||||
widget.selectedItem!["cash_percentage"]?.toString() ?? "",
|
widget.selectedItem!["cash_percentage"]?.toString() ?? "",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
print("selectedCashPercentUPdae - $selectedCashPercent");
|
||||||
selectedPerdiemAmount = widget.selectedItem!["perdiem_amount"] as String?;
|
selectedPerdiemAmount = widget.selectedItem!["perdiem_amount"] as String?;
|
||||||
isChecked =
|
isChecked =
|
||||||
widget.selectedItem!["have_card"] == "1"; // Convert string to bool
|
widget.selectedItem!["have_card"] == "1"; // Convert string to bool
|
||||||
textControllers["_cardNumber"]?.text =
|
textControllers["_cardNumber"]?.text =
|
||||||
widget.selectedItem!["card_number"]?.toString() ?? "";
|
widget.selectedItem!["card_number"]?.toString() ?? "";
|
||||||
|
|
||||||
|
isWidget = true;
|
||||||
|
|
||||||
// if (textControllers["_cardNumber"] != null) {
|
// if (textControllers["_cardNumber"] != null) {
|
||||||
// print("userCardNumber11 - $userCardNumber");
|
// print("userCardNumber11 - $userCardNumber");
|
||||||
// textControllers["_cardNumber"]!.text = userCardNumber ?? '';
|
// textControllers["_cardNumber"]!.text = userCardNumber ?? '';
|
||||||
@ -548,6 +584,13 @@ class _ForexScreenState extends State<ForexScreen> {
|
|||||||
|
|
||||||
selectedQuotedAmount =
|
selectedQuotedAmount =
|
||||||
((perdiemAmount + calclateVal).toString() ?? 0) as String?;
|
((perdiemAmount + calclateVal).toString() ?? 0) as String?;
|
||||||
|
|
||||||
|
if (isWidget) {
|
||||||
|
print("IsWidget Update");
|
||||||
|
|
||||||
|
int? quotedAmount = int.tryParse(selectedQuotedAmount!);
|
||||||
|
fifteenPercent = (quotedAmount! * selectedCashPercent!) ~/ 100;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (userEdited) {
|
if (userEdited) {
|
||||||
@ -612,7 +655,8 @@ class _ForexScreenState extends State<ForexScreen> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (enteredAmount == null || calculateAmnt > qouteAmount!) {
|
if (enteredAmount == null || calculateAmnt > qouteAmount!) {
|
||||||
errorMessages["deposit_on_card"] = "Amount cannot exceed $qouteAmount";
|
errorMessages["deposit_on_card"] =
|
||||||
|
"Sum of cash card cannot exceed $qouteAmount";
|
||||||
} else if (checkValidAmount < qouteAmount) {
|
} else if (checkValidAmount < qouteAmount) {
|
||||||
errorMessages["deposit_on_card"] =
|
errorMessages["deposit_on_card"] =
|
||||||
"Enter Valid Amount"; // Clear error if valid
|
"Enter Valid Amount"; // Clear error if valid
|
||||||
@ -627,6 +671,7 @@ class _ForexScreenState extends State<ForexScreen> {
|
|||||||
void _validateCashAmount(String value) {
|
void _validateCashAmount(String value) {
|
||||||
// errorMessages["deposit_on_card"] = " ";
|
// errorMessages["deposit_on_card"] = " ";
|
||||||
errorMessages.remove("deposit_on_cash");
|
errorMessages.remove("deposit_on_cash");
|
||||||
|
|
||||||
print("_validateCashAmount - $value - $fifteenPercent");
|
print("_validateCashAmount - $value - $fifteenPercent");
|
||||||
|
|
||||||
int? enteredAmount = int.tryParse(value);
|
int? enteredAmount = int.tryParse(value);
|
||||||
@ -652,6 +697,7 @@ class _ForexScreenState extends State<ForexScreen> {
|
|||||||
errorMessages["deposit_on_card"] =
|
errorMessages["deposit_on_card"] =
|
||||||
"Enter Valid Amount"; // Clear error if valid
|
"Enter Valid Amount"; // Clear error if valid
|
||||||
}
|
}
|
||||||
|
print("CASHfifteenPercent - $fifteenPercent");
|
||||||
errorMessages["deposit_on_cash"] = "Amount cannot exceed $fifteenPercent";
|
errorMessages["deposit_on_cash"] = "Amount cannot exceed $fifteenPercent";
|
||||||
} else if (checkValidAmount == quotedAmount) {
|
} else if (checkValidAmount == quotedAmount) {
|
||||||
errorMessages.remove("deposit_on_cash");
|
errorMessages.remove("deposit_on_cash");
|
||||||
@ -819,6 +865,7 @@ class _ForexScreenState extends State<ForexScreen> {
|
|||||||
initialDate: initialDate,
|
initialDate: initialDate,
|
||||||
firstDate: initialDate,
|
firstDate: initialDate,
|
||||||
lastDate: DateTime(2100),
|
lastDate: DateTime(2100),
|
||||||
|
initialEntryMode: DatePickerEntryMode.calendarOnly,
|
||||||
);
|
);
|
||||||
|
|
||||||
// DateTime? pickedDate = await showDatePicker(
|
// DateTime? pickedDate = await showDatePicker(
|
||||||
@ -870,6 +917,7 @@ class _ForexScreenState extends State<ForexScreen> {
|
|||||||
initialDate: initialDate,
|
initialDate: initialDate,
|
||||||
firstDate: initialDate,
|
firstDate: initialDate,
|
||||||
lastDate: DateTime(2100),
|
lastDate: DateTime(2100),
|
||||||
|
initialEntryMode: DatePickerEntryMode.calendarOnly,
|
||||||
);
|
);
|
||||||
|
|
||||||
// DateTime? pickedDate = await showDatePicker(
|
// DateTime? pickedDate = await showDatePicker(
|
||||||
@ -1048,8 +1096,9 @@ class _ForexScreenState extends State<ForexScreen> {
|
|||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
Text(
|
Text(
|
||||||
errorMessages["end_date"]!,
|
errorMessages["end_date"]!,
|
||||||
// "Select End Date",
|
style: const TextStyle(color: Colors.red, fontSize: 12),
|
||||||
style: TextStyle(color: Colors.red, fontSize: 12),
|
maxLines: 2, // Allow it to wrap onto two lines
|
||||||
|
overflow: TextOverflow.ellipsis, // Add ellipsis if it still overflows
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
@ -1143,6 +1192,51 @@ class _ForexScreenState extends State<ForexScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
|
// CustomTextFieldForexWrapper(
|
||||||
|
// isFocused: focusStates["_countries"] ?? false,
|
||||||
|
// isDesktop: isDesktop,
|
||||||
|
// child: SizedBox(
|
||||||
|
// height: 40,
|
||||||
|
// child: DropdownSearch<String>(
|
||||||
|
// selectedItem: countryMap[selectedCountry],
|
||||||
|
// popupProps: PopupProps.menu(
|
||||||
|
// showSearchBox: true, // Enables search functionality
|
||||||
|
// searchFieldProps: TextFieldProps(
|
||||||
|
// decoration: InputDecoration(
|
||||||
|
// hintText: "Search ...",
|
||||||
|
// contentPadding: EdgeInsets.symmetric(horizontal: 10),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// items: countryMap.values.toList(),
|
||||||
|
// dropdownDecoratorProps: DropDownDecoratorProps(
|
||||||
|
// dropdownSearchDecoration: InputDecoration(
|
||||||
|
// border: InputBorder.none,
|
||||||
|
// contentPadding: EdgeInsets.symmetric(horizontal: 1),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// dropdownBuilder:
|
||||||
|
// (context, selectedItem) => Align(
|
||||||
|
// // Center-align selected item
|
||||||
|
// alignment: Alignment.centerLeft,
|
||||||
|
// child: Text(
|
||||||
|
// selectedItem ?? "Select ",
|
||||||
|
// style: TextStyle(fontSize: 12),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// onChanged: (String? newValue) {
|
||||||
|
// setState(() {
|
||||||
|
// // Find the country_code based on selected country_name
|
||||||
|
// selectedCountry =
|
||||||
|
// countryMap.entries
|
||||||
|
// .firstWhere((entry) => entry.value == newValue)
|
||||||
|
// .key;
|
||||||
|
// _onCountryChanged(selectedCountry);
|
||||||
|
// });
|
||||||
|
// },
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
CustomTextFieldForexWrapper(
|
CustomTextFieldForexWrapper(
|
||||||
isFocused: focusStates["_countries"] ?? false,
|
isFocused: focusStates["_countries"] ?? false,
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
@ -1151,10 +1245,25 @@ class _ForexScreenState extends State<ForexScreen> {
|
|||||||
child: DropdownSearch<String>(
|
child: DropdownSearch<String>(
|
||||||
selectedItem: countryMap[selectedCountry],
|
selectedItem: countryMap[selectedCountry],
|
||||||
popupProps: PopupProps.menu(
|
popupProps: PopupProps.menu(
|
||||||
showSearchBox: true, // Enables search functionality
|
showSearchBox: true,
|
||||||
|
fit: FlexFit.loose,
|
||||||
|
constraints: BoxConstraints(maxHeight: 250),
|
||||||
|
menuProps: const MenuProps(backgroundColor: Colors.white),
|
||||||
|
itemBuilder:
|
||||||
|
(context, item, isSelected) => Container(
|
||||||
|
color: Colors.white,
|
||||||
|
padding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 10,
|
||||||
|
vertical: 6,
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
item,
|
||||||
|
style: GoogleFonts.poppins(fontSize: 11.5),
|
||||||
|
),
|
||||||
|
),
|
||||||
searchFieldProps: TextFieldProps(
|
searchFieldProps: TextFieldProps(
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: "Search Country...",
|
hintText: "Search ...",
|
||||||
contentPadding: EdgeInsets.symmetric(horizontal: 10),
|
contentPadding: EdgeInsets.symmetric(horizontal: 10),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -1168,11 +1277,13 @@ class _ForexScreenState extends State<ForexScreen> {
|
|||||||
),
|
),
|
||||||
dropdownBuilder:
|
dropdownBuilder:
|
||||||
(context, selectedItem) => Align(
|
(context, selectedItem) => Align(
|
||||||
// Center-align selected item
|
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: Text(
|
child: Text(
|
||||||
selectedItem ?? "Select Country",
|
selectedItem ?? "Select ",
|
||||||
style: TextStyle(fontSize: 12),
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 12,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
onChanged: (String? newValue) {
|
onChanged: (String? newValue) {
|
||||||
@ -1203,7 +1314,8 @@ class _ForexScreenState extends State<ForexScreen> {
|
|||||||
// height: 8,
|
// height: 8,
|
||||||
// ),
|
// ),
|
||||||
if (isDesktop)
|
if (isDesktop)
|
||||||
SizedBox(width: MediaQuery.of(context).size.width * 0.048)
|
Spacer()
|
||||||
|
// SizedBox(width: MediaQuery.of(context).size.width * 0.048)
|
||||||
else
|
else
|
||||||
SizedBox(height: 8),
|
SizedBox(height: 8),
|
||||||
Column(
|
Column(
|
||||||
@ -1620,6 +1732,12 @@ class _ForexScreenState extends State<ForexScreen> {
|
|||||||
// keyboardType: TextInputType.number,
|
// keyboardType: TextInputType.number,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
// errorMessages["deposit_on_cash"] = "";
|
// errorMessages["deposit_on_cash"] = "";
|
||||||
|
errorMessages.remove("deposit_on_cash");
|
||||||
|
errorMessages.remove("deposit_on_card");
|
||||||
|
// errorMessages["deposit_on_card"] = "";
|
||||||
|
setState(() {
|
||||||
|
userEdited = true;
|
||||||
|
});
|
||||||
_validateCashAmount(
|
_validateCashAmount(
|
||||||
value,
|
value,
|
||||||
); // Call validation when text changes
|
); // Call validation when text changes
|
||||||
@ -1673,6 +1791,9 @@ class _ForexScreenState extends State<ForexScreen> {
|
|||||||
FilteringTextInputFormatter.digitsOnly, // ✅ Only allow digits
|
FilteringTextInputFormatter.digitsOnly, // ✅ Only allow digits
|
||||||
],
|
],
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
|
errorMessages.remove("deposit_on_cash");
|
||||||
|
errorMessages.remove("deposit_on_card");
|
||||||
|
userEdited = true;
|
||||||
_validateCardAmount(
|
_validateCardAmount(
|
||||||
value,
|
value,
|
||||||
); // Call validation when text changes
|
); // Call validation when text changes
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -1,3 +1,4 @@
|
|||||||
|
import 'package:dropdown_search/dropdown_search.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
@ -14,13 +15,14 @@ class MiscellaneousScreen extends StatefulWidget {
|
|||||||
final int? selectedIndex;
|
final int? selectedIndex;
|
||||||
final String? loginUser;
|
final String? loginUser;
|
||||||
|
|
||||||
MiscellaneousScreen(
|
MiscellaneousScreen({
|
||||||
{required this.onClose,
|
required this.onClose,
|
||||||
required this.apiData,
|
required this.apiData,
|
||||||
required this.onSaveMiscellaneous,
|
required this.onSaveMiscellaneous,
|
||||||
this.selectedItem,
|
this.selectedItem,
|
||||||
this.selectedIndex,
|
this.selectedIndex,
|
||||||
required this.loginUser});
|
required this.loginUser,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_MiscellaneousScreenState createState() => _MiscellaneousScreenState();
|
_MiscellaneousScreenState createState() => _MiscellaneousScreenState();
|
||||||
@ -87,8 +89,9 @@ class _MiscellaneousScreenState extends State<MiscellaneousScreen> {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
_commentsController =
|
_commentsController = TextEditingController(
|
||||||
TextEditingController(text: widget.selectedItem?["comments"] ?? "");
|
text: widget.selectedItem?["comments"] ?? "",
|
||||||
|
);
|
||||||
|
|
||||||
// Set the selected value if available
|
// Set the selected value if available
|
||||||
if (widget.selectedItem != null &&
|
if (widget.selectedItem != null &&
|
||||||
@ -114,7 +117,7 @@ class _MiscellaneousScreenState extends State<MiscellaneousScreen> {
|
|||||||
// Check validation for each field
|
// Check validation for each field
|
||||||
for (String field in requiredFields) {
|
for (String field in requiredFields) {
|
||||||
if (data[field] == null || data[field].toString().trim().isEmpty) {
|
if (data[field] == null || data[field].toString().trim().isEmpty) {
|
||||||
errorMessages[field] = "This field is required";
|
errorMessages[field] = "Required";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,29 +146,32 @@ class _MiscellaneousScreenState extends State<MiscellaneousScreen> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ResponsiveBuilder(builder: (context, sizingInfo) {
|
return ResponsiveBuilder(
|
||||||
bool isMobile = sizingInfo.isMobile;
|
builder: (context, sizingInfo) {
|
||||||
bool isDesktop = sizingInfo.deviceScreenType == DeviceScreenType.desktop;
|
bool isMobile = sizingInfo.isMobile;
|
||||||
|
bool isDesktop =
|
||||||
|
sizingInfo.deviceScreenType == DeviceScreenType.desktop;
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
child: Form(
|
child: Form(
|
||||||
key: _formKey,
|
key: _formKey,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(28.0),
|
padding: const EdgeInsets.only(top: 30.0),
|
||||||
child: Center(
|
child: Center(
|
||||||
child: Column(children: _buildAccomadtionForm(isDesktop)),
|
child: Column(children: _buildAccomadtionForm(isDesktop)),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
)
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
);
|
},
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> _buildAccomadtionForm(bool isDesktop) {
|
List<Widget> _buildAccomadtionForm(bool isDesktop) {
|
||||||
@ -191,16 +197,17 @@ class _MiscellaneousScreenState extends State<MiscellaneousScreen> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Special Type",
|
"Special Type *",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
isDesktop
|
isDesktop
|
||||||
? Row(children: _buildTripType(isDesktop))
|
? Row(children: _buildTripType(isDesktop))
|
||||||
: Column(children: _buildTripType(isDesktop))
|
: Column(children: _buildTripType(isDesktop)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
@ -211,19 +218,24 @@ class _MiscellaneousScreenState extends State<MiscellaneousScreen> {
|
|||||||
widget.apiData?['miscellaneous_special_request'] ?? [];
|
widget.apiData?['miscellaneous_special_request'] ?? [];
|
||||||
// selectedInsuranceType = purposeList.isNotEmpty ? purposeList.first['dropdown_value'] : null;
|
// selectedInsuranceType = purposeList.isNotEmpty ? purposeList.first['dropdown_value'] : null;
|
||||||
|
|
||||||
List<DropdownMenuItem<String>> dropdownItems = purposeList
|
List<DropdownMenuItem<String>> dropdownItems =
|
||||||
.map((item) => DropdownMenuItem<String>(
|
purposeList
|
||||||
value: item['dropdown_key'],
|
.map(
|
||||||
child: Text(item['dropdown_value']),
|
(item) => DropdownMenuItem<String>(
|
||||||
))
|
value: item['dropdown_key'],
|
||||||
.toList();
|
child: Text(item['dropdown_value']),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList();
|
||||||
|
|
||||||
if (dropdownItems.isEmpty) {
|
if (dropdownItems.isEmpty) {
|
||||||
dropdownItems.add(
|
dropdownItems.add(
|
||||||
DropdownMenuItem<String>(
|
DropdownMenuItem<String>(
|
||||||
value: null,
|
value: null,
|
||||||
child: Text("No options available",
|
child: Text(
|
||||||
style: TextStyle(color: Colors.grey)),
|
"No options available",
|
||||||
|
style: TextStyle(color: Colors.grey),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -233,7 +245,40 @@ class _MiscellaneousScreenState extends State<MiscellaneousScreen> {
|
|||||||
dropdownItems.isNotEmpty ? dropdownItems.first.value : "No options";
|
dropdownItems.isNotEmpty ? dropdownItems.first.value : "No options";
|
||||||
|
|
||||||
return [
|
return [
|
||||||
CustomTextFieldWrapper(
|
// CustomTextFieldWrapper(
|
||||||
|
// isFocused: _isHotelNameFocused,
|
||||||
|
// isDesktop: isDesktop,
|
||||||
|
// width:
|
||||||
|
// isDesktop
|
||||||
|
// ? MediaQuery.of(context).size.width * 0.34
|
||||||
|
// : MediaQuery.of(context).size.width * 0.66,
|
||||||
|
// child: SizedBox(
|
||||||
|
// height: 40,
|
||||||
|
// child: DropdownButtonFormField<String>(
|
||||||
|
// focusNode: _tripTypeFocusNode, // Assign the correct focus node
|
||||||
|
// value: selectedSpecialType,
|
||||||
|
// style: TextStyle(fontSize: 12),
|
||||||
|
// decoration: InputDecoration(
|
||||||
|
// border: InputBorder.none,
|
||||||
|
// contentPadding: EdgeInsets.symmetric(
|
||||||
|
// horizontal: 10,
|
||||||
|
// ), // Proper padding
|
||||||
|
// ),
|
||||||
|
// onChanged:
|
||||||
|
// purposeList.isNotEmpty
|
||||||
|
// ? (newValue) {
|
||||||
|
// setState(() {
|
||||||
|
// selectedSpecialType = newValue;
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// print(selectedSpecialType);
|
||||||
|
// }
|
||||||
|
// : null,
|
||||||
|
// items: dropdownItems,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
CustomTextFieldItnerarySubWrapper(
|
||||||
isFocused: _isHotelNameFocused,
|
isFocused: _isHotelNameFocused,
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
width: isDesktop
|
width: isDesktop
|
||||||
@ -241,34 +286,79 @@ class _MiscellaneousScreenState extends State<MiscellaneousScreen> {
|
|||||||
: MediaQuery.of(context).size.width * 0.66,
|
: MediaQuery.of(context).size.width * 0.66,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: DropdownButtonFormField<String>(
|
width: double.infinity,
|
||||||
focusNode: _tripTypeFocusNode, // Assign the correct focus node
|
child: DropdownSearch<Map<String, dynamic>>(
|
||||||
value: selectedSpecialType,
|
// focusNode: _taxiReqFocusNode,
|
||||||
style: TextStyle(fontSize: 12),
|
items: purposeList.cast<Map<String, dynamic>>(),
|
||||||
decoration: InputDecoration(
|
selectedItem: purposeList.firstWhere(
|
||||||
border: InputBorder.none,
|
(item) => item['dropdown_key'] == selectedSpecialType,
|
||||||
contentPadding:
|
orElse: () => {},
|
||||||
EdgeInsets.symmetric(horizontal: 10), // Proper padding
|
|
||||||
),
|
),
|
||||||
onChanged: purposeList.isNotEmpty
|
itemAsString: (item) => item['dropdown_value'] ?? '',
|
||||||
|
popupProps: PopupProps.menu(
|
||||||
|
showSearchBox: false,
|
||||||
|
fit: FlexFit.loose,
|
||||||
|
menuProps: const MenuProps(backgroundColor: Colors.white),
|
||||||
|
itemBuilder: (context, item, isSelected) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 10,
|
||||||
|
vertical: 5,
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
item['dropdown_value'] ?? '',
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 12,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
dropdownDecoratorProps: const DropDownDecoratorProps(
|
||||||
|
dropdownSearchDecoration: InputDecoration(
|
||||||
|
border: InputBorder.none,
|
||||||
|
contentPadding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 10,
|
||||||
|
vertical: 10,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
dropdownBuilder: (context, selectedItem) {
|
||||||
|
if (selectedItem == null || selectedItem.isEmpty) {
|
||||||
|
return Text(
|
||||||
|
"Select ",
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
color: Colors.grey,
|
||||||
|
fontSize: 13,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Text(
|
||||||
|
selectedItem['dropdown_value'] ?? '',
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 12,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
onChanged:
|
||||||
|
purposeList.isNotEmpty
|
||||||
? (newValue) {
|
? (newValue) {
|
||||||
setState(() {
|
setState(() {
|
||||||
selectedSpecialType = newValue;
|
selectedSpecialType = newValue as String?;
|
||||||
});
|
});
|
||||||
|
print(
|
||||||
print(selectedSpecialType);
|
"Updating form data: -> ${newValue ?? ""}",
|
||||||
}
|
);
|
||||||
|
}
|
||||||
: null,
|
: null,
|
||||||
items: dropdownItems,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (errorMessages["special_request"] != null) ...[
|
if (errorMessages["special_request"] != null) ...[
|
||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
Text(
|
Text("Required", style: TextStyle(color: Colors.red, fontSize: 12)),
|
||||||
"Select Type",
|
|
||||||
style: TextStyle(color: Colors.red, fontSize: 12),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -279,19 +369,21 @@ class _MiscellaneousScreenState extends State<MiscellaneousScreen> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Comments",
|
"Comments *",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldWrapper(
|
CustomTextFieldWrapper(
|
||||||
isFocused: _commentsFocus, // Dropdown doesn't use focus
|
isFocused: _commentsFocus, // Dropdown doesn't use focus
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
width: isDesktop
|
width:
|
||||||
? MediaQuery.of(context).size.width * 0.34
|
isDesktop
|
||||||
: MediaQuery.of(context).size.width * 0.66,
|
? MediaQuery.of(context).size.width * 0.34
|
||||||
|
: MediaQuery.of(context).size.width * 0.66,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
@ -310,17 +402,12 @@ class _MiscellaneousScreenState extends State<MiscellaneousScreen> {
|
|||||||
),
|
),
|
||||||
if (errorMessages["comments"] != null) ...[
|
if (errorMessages["comments"] != null) ...[
|
||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
Text(
|
Text("Required", style: TextStyle(color: Colors.red, fontSize: 12)),
|
||||||
"Required",
|
|
||||||
style: TextStyle(color: Colors.red, fontSize: 12),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (isDesktop) Spacer(),
|
if (isDesktop) Spacer(),
|
||||||
SizedBox(
|
SizedBox(height: 5),
|
||||||
height: 5,
|
|
||||||
),
|
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
children: _handleAction(isDesktop),
|
children: _handleAction(isDesktop),
|
||||||
@ -338,9 +425,7 @@ class _MiscellaneousScreenState extends State<MiscellaneousScreen> {
|
|||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Colors.grey[400], // Light grey color
|
backgroundColor: Colors.grey[400], // Light grey color
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
|
||||||
borderRadius: BorderRadius.circular(8),
|
|
||||||
),
|
|
||||||
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
@ -349,7 +434,6 @@ class _MiscellaneousScreenState extends State<MiscellaneousScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(width: 10), // Space between buttons
|
SizedBox(width: 10), // Space between buttons
|
||||||
|
|
||||||
// Save Changes Button
|
// Save Changes Button
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
@ -357,9 +441,7 @@ class _MiscellaneousScreenState extends State<MiscellaneousScreen> {
|
|||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Color(0xFF114D8B), // Primary color for save
|
backgroundColor: Color(0xFF114D8B), // Primary color for save
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
|
||||||
borderRadius: BorderRadius.circular(8),
|
|
||||||
),
|
|
||||||
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import 'package:dropdown_search/dropdown_search.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
@ -219,7 +220,7 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(28.0),
|
padding: const EdgeInsets.only(top: 30.0),
|
||||||
child: Center(
|
child: Center(
|
||||||
child: Column(children: _buildAccomadtionForm(isDesktop)),
|
child: Column(children: _buildAccomadtionForm(isDesktop)),
|
||||||
),
|
),
|
||||||
@ -362,34 +363,109 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
|
// CustomTextFieldItnerarySubWrapper(
|
||||||
|
// isFocused: _toFocus,
|
||||||
|
// isDesktop: isDesktop,
|
||||||
|
// child: SizedBox(
|
||||||
|
// height: 40,
|
||||||
|
// child: DropdownButtonFormField<String>(
|
||||||
|
// focusNode: _toFocusNode, // Assign the correct focus node
|
||||||
|
// value: selectedCarType,
|
||||||
|
// style: TextStyle(fontSize: 12),
|
||||||
|
// decoration: InputDecoration(
|
||||||
|
// border: InputBorder.none,
|
||||||
|
// contentPadding: EdgeInsets.symmetric(
|
||||||
|
// horizontal: 10,
|
||||||
|
// ), // Proper padding
|
||||||
|
// ),
|
||||||
|
// onChanged:
|
||||||
|
// purposeList.isNotEmpty
|
||||||
|
// ? (newValue) {
|
||||||
|
// setState(() {
|
||||||
|
// selectedCarType = newValue;
|
||||||
|
// });
|
||||||
|
// print(
|
||||||
|
// "Updating form data: Flight -> trip_type -> ${newValue ?? ""}",
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// : null,
|
||||||
|
//
|
||||||
|
// items: dropdownItems,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
CustomTextFieldItnerarySubWrapper(
|
CustomTextFieldItnerarySubWrapper(
|
||||||
isFocused: _toFocus,
|
isFocused: _toFocus,
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: DropdownButtonFormField<String>(
|
width: double.infinity,
|
||||||
focusNode: _toFocusNode, // Assign the correct focus node
|
child: DropdownSearch<Map<String, dynamic>>(
|
||||||
value: selectedCarType,
|
// focusNode: _taxiReqFocusNode,
|
||||||
style: TextStyle(fontSize: 12),
|
items: purposeList.cast<Map<String, dynamic>>(),
|
||||||
decoration: InputDecoration(
|
selectedItem: purposeList.firstWhere(
|
||||||
border: InputBorder.none,
|
(item) => item['dropdown_key'] == selectedCarType,
|
||||||
contentPadding: EdgeInsets.symmetric(
|
orElse: () => {},
|
||||||
horizontal: 10,
|
|
||||||
), // Proper padding
|
|
||||||
),
|
),
|
||||||
|
itemAsString: (item) => item['dropdown_value'] ?? '',
|
||||||
|
popupProps: PopupProps.menu(
|
||||||
|
showSearchBox: false,
|
||||||
|
fit: FlexFit.loose,
|
||||||
|
menuProps: const MenuProps(backgroundColor: Colors.white),
|
||||||
|
itemBuilder: (context, item, isSelected) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 10,
|
||||||
|
vertical: 5,
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
item['dropdown_value'] ?? '',
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 12,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
dropdownDecoratorProps: const DropDownDecoratorProps(
|
||||||
|
dropdownSearchDecoration: InputDecoration(
|
||||||
|
border: InputBorder.none,
|
||||||
|
contentPadding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 10,
|
||||||
|
vertical: 10,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
dropdownBuilder: (context, selectedItem) {
|
||||||
|
if (selectedItem == null || selectedItem.isEmpty) {
|
||||||
|
return Text(
|
||||||
|
"Select ",
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
color: Colors.grey,
|
||||||
|
fontSize: 13,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Text(
|
||||||
|
selectedItem['dropdown_value'] ?? '',
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 12,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
onChanged:
|
onChanged:
|
||||||
purposeList.isNotEmpty
|
purposeList.isNotEmpty
|
||||||
? (newValue) {
|
? (newValue) {
|
||||||
setState(() {
|
setState(() {
|
||||||
selectedCarType = newValue;
|
selectedCarType = newValue as String?;
|
||||||
});
|
});
|
||||||
print(
|
print(
|
||||||
"Updating form data: Flight -> trip_type -> ${newValue ?? ""}",
|
"Updating form data: -> ${newValue ?? ""}",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
|
|
||||||
items: dropdownItems,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -429,38 +505,117 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
dropdownItems.isNotEmpty ? dropdownItems.first.value : null;
|
dropdownItems.isNotEmpty ? dropdownItems.first.value : null;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
CustomTextFieldWrapper(
|
// CustomTextFieldWrapper(
|
||||||
|
// isFocused: _taxiReqFocused,
|
||||||
|
// isDesktop: isDesktop,
|
||||||
|
// width:
|
||||||
|
// isDesktop
|
||||||
|
// ? MediaQuery.of(context).size.width * 0.34
|
||||||
|
// : MediaQuery.of(context).size.width * 0.66,
|
||||||
|
// child: SizedBox(
|
||||||
|
// height: 40,
|
||||||
|
// child: DropdownButtonFormField<String>(
|
||||||
|
// focusNode: _taxiReqFocusNode, // Assign the correct focus node
|
||||||
|
// value: selectedReqTaxi,
|
||||||
|
// style: TextStyle(fontSize: 12),
|
||||||
|
// decoration: InputDecoration(
|
||||||
|
// border: InputBorder.none,
|
||||||
|
// contentPadding: EdgeInsets.symmetric(
|
||||||
|
// horizontal: 10,
|
||||||
|
// ), // Proper padding
|
||||||
|
// ),
|
||||||
|
// onChanged:
|
||||||
|
// purposeList.isNotEmpty
|
||||||
|
// ? (newValue) {
|
||||||
|
// setState(() {
|
||||||
|
// selectedReqTaxi = newValue;
|
||||||
|
// });
|
||||||
|
// print(
|
||||||
|
// "Updating form data: Flight -> trip_type -> ${newValue ?? ""}",
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// : null,
|
||||||
|
//
|
||||||
|
// items: dropdownItems,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
CustomTextFieldItnerarySubWrapper(
|
||||||
isFocused: _taxiReqFocused,
|
isFocused: _taxiReqFocused,
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
width:
|
width:
|
||||||
isDesktop
|
isDesktop
|
||||||
? MediaQuery.of(context).size.width * 0.34
|
? MediaQuery.of(context).size.width * 0.34
|
||||||
: MediaQuery.of(context).size.width * 0.66,
|
: MediaQuery.of(context).size.width * 0.66,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: DropdownButtonFormField<String>(
|
width: double.infinity,
|
||||||
focusNode: _taxiReqFocusNode, // Assign the correct focus node
|
child: DropdownSearch<Map<String, dynamic>>(
|
||||||
value: selectedReqTaxi,
|
// focusNode: _taxiReqFocusNode,
|
||||||
style: TextStyle(fontSize: 12),
|
items: purposeList.cast<Map<String, dynamic>>(),
|
||||||
decoration: InputDecoration(
|
selectedItem: purposeList.firstWhere(
|
||||||
border: InputBorder.none,
|
(item) => item['dropdown_key'] == selectedReqTaxi,
|
||||||
contentPadding: EdgeInsets.symmetric(
|
orElse: () => {},
|
||||||
horizontal: 10,
|
|
||||||
), // Proper padding
|
|
||||||
),
|
),
|
||||||
|
itemAsString: (item) => item['dropdown_value'] ?? '',
|
||||||
|
popupProps: PopupProps.menu(
|
||||||
|
showSearchBox: false,
|
||||||
|
fit: FlexFit.loose,
|
||||||
|
menuProps: const MenuProps(backgroundColor: Colors.white),
|
||||||
|
itemBuilder: (context, item, isSelected) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 10,
|
||||||
|
vertical: 5,
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
item['dropdown_value'] ?? '',
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 12,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
dropdownDecoratorProps: const DropDownDecoratorProps(
|
||||||
|
dropdownSearchDecoration: InputDecoration(
|
||||||
|
border: InputBorder.none,
|
||||||
|
contentPadding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 10,
|
||||||
|
vertical: 10,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
dropdownBuilder: (context, selectedItem) {
|
||||||
|
if (selectedItem == null || selectedItem.isEmpty) {
|
||||||
|
return Text(
|
||||||
|
"Select ",
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
color: Colors.grey,
|
||||||
|
fontSize: 13,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Text(
|
||||||
|
selectedItem['dropdown_value'] ?? '',
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 12,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
onChanged:
|
onChanged:
|
||||||
purposeList.isNotEmpty
|
purposeList.isNotEmpty
|
||||||
? (newValue) {
|
? (newValue) {
|
||||||
setState(() {
|
setState(() {
|
||||||
selectedReqTaxi = newValue;
|
selectedReqTaxi = newValue as String?;
|
||||||
});
|
});
|
||||||
print(
|
print(
|
||||||
"Updating form data: Flight -> trip_type -> ${newValue ?? ""}",
|
"Updating form data: -> ${newValue ?? ""}",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
|
|
||||||
items: dropdownItems,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -484,6 +639,7 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
: today,
|
: today,
|
||||||
firstDate: today,
|
firstDate: today,
|
||||||
lastDate: DateTime(2100),
|
lastDate: DateTime(2100),
|
||||||
|
initialEntryMode: DatePickerEntryMode.calendarOnly,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (pickedDate != null && pickedDate != _selectedCheckOutDate) {
|
if (pickedDate != null && pickedDate != _selectedCheckOutDate) {
|
||||||
@ -501,30 +657,87 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (pickedTime != null && pickedTime != _selectedCheckOutTime) {
|
if (pickedTime != null && pickedTime != _selectedCheckOutTime) {
|
||||||
setState(() {
|
// Parse the selected date
|
||||||
_selectedCheckOutTime = pickedTime;
|
final dateText = _dateController.text ?? "";
|
||||||
// Formatting time to HH:mm (24-hour format)
|
final selectedDate = DateFormat(
|
||||||
final now = DateTime.now();
|
'dd-MM-yyyy',
|
||||||
final formattedTime = DateFormat('HH:mm').format(
|
).parse(dateText); // or 'yyyy-MM-dd' depending on your format
|
||||||
DateTime(
|
final now = DateTime.now();
|
||||||
now.year,
|
|
||||||
now.month,
|
final selectedDateTime = DateTime(
|
||||||
now.day,
|
selectedDate.year,
|
||||||
pickedTime.hour,
|
selectedDate.month,
|
||||||
pickedTime.minute,
|
selectedDate.day,
|
||||||
),
|
pickedTime.hour,
|
||||||
);
|
pickedTime.minute,
|
||||||
_timeController.text = formattedTime;
|
);
|
||||||
});
|
|
||||||
|
final isToday =
|
||||||
|
selectedDate.year == now.year &&
|
||||||
|
selectedDate.month == now.month &&
|
||||||
|
selectedDate.day == now.day;
|
||||||
|
|
||||||
|
bool isPastTime = selectedDateTime.isBefore(now);
|
||||||
|
|
||||||
|
if (isToday && isPastTime) {
|
||||||
|
setState(() {
|
||||||
|
errorMessages["time"] = "You can't select a past time.";
|
||||||
|
_selectedCheckOutTime = null; // ✅ Reset time variable
|
||||||
|
_timeController.text = ""; // ✅ Clear text field
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
setState(() {
|
||||||
|
_selectedCheckOutTime = pickedTime;
|
||||||
|
// Formatting time to HH:mm (24-hour format)
|
||||||
|
final now = DateTime.now();
|
||||||
|
final formattedTime = DateFormat('HH:mm').format(
|
||||||
|
DateTime(
|
||||||
|
now.year,
|
||||||
|
now.month,
|
||||||
|
now.day,
|
||||||
|
pickedTime.hour,
|
||||||
|
pickedTime.minute,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
errorMessages["time"] = "";
|
||||||
|
_timeController.text = formattedTime;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Future<void> _selectCheckOutTime(BuildContext context) async {
|
||||||
|
// TimeOfDay? pickedTime = await showTimePicker(
|
||||||
|
// context: context,
|
||||||
|
// initialTime: _selectedCheckOutTime ?? TimeOfDay.now(),
|
||||||
|
// );
|
||||||
|
//
|
||||||
|
// if (pickedTime != null && pickedTime != _selectedCheckOutTime) {
|
||||||
|
// setState(() {
|
||||||
|
// _selectedCheckOutTime = pickedTime;
|
||||||
|
// // Formatting time to HH:mm (24-hour format)
|
||||||
|
// final now = DateTime.now();
|
||||||
|
// final formattedTime = DateFormat('HH:mm').format(
|
||||||
|
// DateTime(
|
||||||
|
// now.year,
|
||||||
|
// now.month,
|
||||||
|
// now.day,
|
||||||
|
// pickedTime.hour,
|
||||||
|
// pickedTime.minute,
|
||||||
|
// ),
|
||||||
|
// );
|
||||||
|
// _timeController.text = formattedTime;
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
return [
|
return [
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"City",
|
"City *",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
@ -562,7 +775,7 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Pickup Location",
|
"Pickup Location *",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
@ -600,7 +813,7 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Date",
|
"Date *",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
@ -648,7 +861,7 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Time",
|
"Time *",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
@ -662,7 +875,10 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: () => _selectCheckOutTime(context),
|
onTap: () {
|
||||||
|
_timeController.text = "";
|
||||||
|
_selectCheckOutTime(context);
|
||||||
|
},
|
||||||
child: AbsorbPointer(
|
child: AbsorbPointer(
|
||||||
child: TextField(
|
child: TextField(
|
||||||
focusNode: _timeFocusNode,
|
focusNode: _timeFocusNode,
|
||||||
@ -687,7 +903,11 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
),
|
),
|
||||||
if (errorMessages["time"] != null) ...[
|
if (errorMessages["time"] != null) ...[
|
||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
Text("Required", style: TextStyle(color: Colors.red, fontSize: 12)),
|
// Text("Required", style: TextStyle(color: Colors.red, fontSize: 12)),
|
||||||
|
Text(
|
||||||
|
errorMessages["time"]!,
|
||||||
|
style: TextStyle(color: Colors.red, fontSize: 12),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@ -243,6 +243,12 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (selectedFrom == selectedTo) {
|
||||||
|
errorMessages["to_station"] = "Change Destination";
|
||||||
|
}
|
||||||
|
|
||||||
|
print("Error: to_place -> Change Destination (selectedFrom == selectedTo)");
|
||||||
|
|
||||||
return errorMessages.isEmpty; // Valid if there are no errors
|
return errorMessages.isEmpty; // Valid if there are no errors
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -324,7 +330,7 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
// height: 6,
|
// height: 6,
|
||||||
// ),
|
// ),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(28.0),
|
padding: const EdgeInsets.only(top: 30.0),
|
||||||
child: Center(
|
child: Center(
|
||||||
child: Column(children: _buildAccomadtionForm(isDesktop)),
|
child: Column(children: _buildAccomadtionForm(isDesktop)),
|
||||||
),
|
),
|
||||||
@ -369,7 +375,7 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Train Number",
|
"Train Number *",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
@ -464,6 +470,7 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
: today,
|
: today,
|
||||||
firstDate: today,
|
firstDate: today,
|
||||||
lastDate: DateTime(2100),
|
lastDate: DateTime(2100),
|
||||||
|
initialEntryMode: DatePickerEntryMode.calendarOnly,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (pickedDate != null && pickedDate != _selectedCheckOutDate) {
|
if (pickedDate != null && pickedDate != _selectedCheckOutDate) {
|
||||||
@ -480,23 +487,66 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
initialTime: _selectedCheckOutTime ?? TimeOfDay.now(),
|
initialTime: _selectedCheckOutTime ?? TimeOfDay.now(),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (pickedTime != null && pickedTime != _selectedCheckOutTime) {
|
if (pickedTime != null) {
|
||||||
|
final now = DateTime.now();
|
||||||
|
|
||||||
|
// Parse the selected date
|
||||||
|
final dateText = _dateController.text ?? "";
|
||||||
|
final selectedDate = DateFormat(
|
||||||
|
'dd-MM-yyyy',
|
||||||
|
).parse(dateText); // or 'yyyy-MM-dd' depending on your format
|
||||||
|
|
||||||
|
final selectedDateTime = DateTime(
|
||||||
|
selectedDate.year,
|
||||||
|
selectedDate.month,
|
||||||
|
selectedDate.day,
|
||||||
|
pickedTime.hour,
|
||||||
|
pickedTime.minute,
|
||||||
|
);
|
||||||
|
|
||||||
|
// ✅ Only validate past time if date is today
|
||||||
|
final isToday =
|
||||||
|
selectedDate.year == now.year &&
|
||||||
|
selectedDate.month == now.month &&
|
||||||
|
selectedDate.day == now.day;
|
||||||
|
|
||||||
|
bool isPastTime = selectedDateTime.isBefore(now);
|
||||||
|
|
||||||
|
if (isToday && isPastTime) {
|
||||||
|
setState(() {
|
||||||
|
errorMessages["time"] = "You can't select a past time.";
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ✅ Valid time selection
|
||||||
setState(() {
|
setState(() {
|
||||||
_selectedCheckOutTime = pickedTime;
|
_selectedCheckOutTime = pickedTime;
|
||||||
// Formatting time to HH:mm (24-hour format)
|
|
||||||
final now = DateTime.now();
|
final formattedTime = DateFormat('HH:mm').format(selectedDateTime);
|
||||||
final formattedTime = DateFormat('HH:mm').format(
|
|
||||||
DateTime(
|
|
||||||
now.year,
|
|
||||||
now.month,
|
|
||||||
now.day,
|
|
||||||
pickedTime.hour,
|
|
||||||
pickedTime.minute,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
_timeController.text = formattedTime;
|
_timeController.text = formattedTime;
|
||||||
|
// errorMessages["time_$index"] = ""; // clear previous error
|
||||||
|
errorMessages.remove("time");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if (pickedTime != null && pickedTime != _selectedCheckOutTime) {
|
||||||
|
// setState(() {
|
||||||
|
// _selectedCheckOutTime = pickedTime;
|
||||||
|
// // Formatting time to HH:mm (24-hour format)
|
||||||
|
// final now = DateTime.now();
|
||||||
|
// final formattedTime = DateFormat('HH:mm').format(
|
||||||
|
// DateTime(
|
||||||
|
// now.year,
|
||||||
|
// now.month,
|
||||||
|
// now.day,
|
||||||
|
// pickedTime.hour,
|
||||||
|
// pickedTime.minute,
|
||||||
|
// ),
|
||||||
|
// );
|
||||||
|
// _timeController.text = formattedTime;
|
||||||
|
// });
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------
|
//----------------------------------------------
|
||||||
@ -542,34 +592,104 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldItnerarySubWrapper(
|
// CustomTextFieldItnerarySubWrapper(
|
||||||
|
// isFocused: _isHotelNameFocused,
|
||||||
|
// isDesktop: isDesktop,
|
||||||
|
// // width: isDesktop
|
||||||
|
// // ? MediaQuery.of(context).size.width * 0.34
|
||||||
|
// // : MediaQuery.of(context).size.width * 0.66,
|
||||||
|
// child: SizedBox(
|
||||||
|
// height: 40,
|
||||||
|
// child: DropdownButtonFormField<String>(
|
||||||
|
// focusNode: _hotelNameFocusNode, // Assign the correct focus node
|
||||||
|
// // controller: _hotelNameController,
|
||||||
|
// value: selectedClass,
|
||||||
|
// style: TextStyle(fontSize: 12),
|
||||||
|
// decoration: InputDecoration(
|
||||||
|
// border: InputBorder.none,
|
||||||
|
// contentPadding: EdgeInsets.symmetric(
|
||||||
|
// horizontal: 10,
|
||||||
|
// ), // Proper padding
|
||||||
|
// ),
|
||||||
|
// onChanged:
|
||||||
|
// purposeList.isNotEmpty
|
||||||
|
// ? (newValue) {
|
||||||
|
// setState(() {
|
||||||
|
// selectedClass = newValue;
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// : null,
|
||||||
|
// items: dropdownItems,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
CustomTextFieldWrapper(
|
||||||
isFocused: _isHotelNameFocused,
|
isFocused: _isHotelNameFocused,
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
// width: isDesktop
|
width: isDesktop ? MediaQuery.of(context).size.width * 0.15 : null,
|
||||||
// ? MediaQuery.of(context).size.width * 0.34
|
|
||||||
// : MediaQuery.of(context).size.width * 0.66,
|
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: DropdownButtonFormField<String>(
|
width: double.infinity,
|
||||||
focusNode: _hotelNameFocusNode, // Assign the correct focus node
|
child: DropdownSearch<Map<String, dynamic>>(
|
||||||
// controller: _hotelNameController,
|
items: purposeList.cast<Map<String, dynamic>>(),
|
||||||
value: selectedClass,
|
selectedItem: purposeList.firstWhere(
|
||||||
style: TextStyle(fontSize: 12),
|
(item) => item['dropdown_key'] == selectedClass,
|
||||||
decoration: InputDecoration(
|
orElse: () => {},
|
||||||
border: InputBorder.none,
|
|
||||||
contentPadding: EdgeInsets.symmetric(
|
|
||||||
horizontal: 10,
|
|
||||||
), // Proper padding
|
|
||||||
),
|
),
|
||||||
|
itemAsString: (item) => item['dropdown_value'] ?? '',
|
||||||
|
popupProps: PopupProps.menu(
|
||||||
|
showSearchBox: false,
|
||||||
|
fit: FlexFit.loose,
|
||||||
|
menuProps: const MenuProps(backgroundColor: Colors.white),
|
||||||
|
itemBuilder: (context, item, isSelected) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 10,
|
||||||
|
vertical: 5,
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
item['dropdown_value'] ?? '',
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 12,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
dropdownDecoratorProps: const DropDownDecoratorProps(
|
||||||
|
dropdownSearchDecoration: InputDecoration(
|
||||||
|
border: InputBorder.none,
|
||||||
|
contentPadding: EdgeInsets.symmetric(horizontal: 10,vertical: 10,),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
dropdownBuilder: (context, selectedItem) {
|
||||||
|
if (selectedItem == null || selectedItem.isEmpty) {
|
||||||
|
return Text(
|
||||||
|
"Select ",
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
color: Colors.grey,
|
||||||
|
fontSize: 13,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Text(
|
||||||
|
selectedItem['dropdown_value'] ?? '',
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 12,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
onChanged:
|
onChanged:
|
||||||
purposeList.isNotEmpty
|
purposeList.isNotEmpty
|
||||||
? (newValue) {
|
? (Map<String, dynamic>? newValue) {
|
||||||
setState(() {
|
setState(() {
|
||||||
selectedClass = newValue;
|
selectedClass= newValue?['dropdown_key'];
|
||||||
});
|
print("Selected Purpose: ${selectedClass}");
|
||||||
}
|
});
|
||||||
: null,
|
}
|
||||||
items: dropdownItems,
|
: null,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -584,7 +704,7 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"From",
|
"From *",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
@ -592,96 +712,158 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
|
// CustomTextFieldItnerarySubWrapper(
|
||||||
|
// isFocused: _fromFocus,
|
||||||
|
// isDesktop: isDesktop,
|
||||||
|
// child: SizedBox(
|
||||||
|
// height: 40,
|
||||||
|
// child:
|
||||||
|
// isCountryLoading
|
||||||
|
// ? Center(child: CircularProgressIndicator())
|
||||||
|
// : DropdownSearch<String>(
|
||||||
|
// // selectedItem: selectedFrom != null
|
||||||
|
// // ? countryMap[selectedFrom]
|
||||||
|
// // : null,
|
||||||
|
// selectedItem:
|
||||||
|
// selectedFrom != null
|
||||||
|
// ? countryMap[selectedFrom] // get the display value from code
|
||||||
|
// : null,
|
||||||
|
// popupProps: PopupProps.menu(
|
||||||
|
// menuProps: MenuProps(backgroundColor: Colors.white),
|
||||||
|
// constraints: BoxConstraints(maxHeight: 230),
|
||||||
|
// showSearchBox: true,
|
||||||
|
// searchFieldProps: TextFieldProps(
|
||||||
|
// decoration: InputDecoration(
|
||||||
|
// hintText: "Search ...",
|
||||||
|
// contentPadding: EdgeInsets.symmetric(
|
||||||
|
// horizontal: 10,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
//
|
||||||
|
// items: countryMap.values.toList(),
|
||||||
|
//
|
||||||
|
// dropdownDecoratorProps: DropDownDecoratorProps(
|
||||||
|
// dropdownSearchDecoration: InputDecoration(
|
||||||
|
// contentPadding: EdgeInsets.symmetric(
|
||||||
|
// horizontal: 10,
|
||||||
|
// vertical: 5,
|
||||||
|
// ),
|
||||||
|
// border: InputBorder.none,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// dropdownBuilder:
|
||||||
|
// (context, selectedItem) => Align(
|
||||||
|
// alignment: Alignment.centerLeft,
|
||||||
|
// child: Text(
|
||||||
|
// selectedItem ?? "Select",
|
||||||
|
// style: TextStyle(fontSize: 12),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
//
|
||||||
|
// // onChanged: (String? newValue) {
|
||||||
|
// // setState(() {
|
||||||
|
// // // selectedFrom[index] = countryMap.entries
|
||||||
|
// // // .firstWhere((entry) => entry.value == newValue)
|
||||||
|
// // // .key;
|
||||||
|
// //
|
||||||
|
// // selectedFrom = countryMap.entries
|
||||||
|
// // .firstWhere((entry) => entry.value == newValue)
|
||||||
|
// // .key;
|
||||||
|
// //
|
||||||
|
// // print(selectedFrom);
|
||||||
|
// // });
|
||||||
|
// // },
|
||||||
|
// onChanged: (String? newValue) {
|
||||||
|
// setState(() {
|
||||||
|
// selectedFrom =
|
||||||
|
// countryMap.entries
|
||||||
|
// .firstWhere(
|
||||||
|
// (entry) => entry.value == newValue,
|
||||||
|
// )
|
||||||
|
// .key;
|
||||||
|
// });
|
||||||
|
// },
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// // child: SizedBox(
|
||||||
|
// // height: 40,
|
||||||
|
// // child: TextField(
|
||||||
|
// // focusNode: _fromFocusNode,
|
||||||
|
// // controller: _fromController,
|
||||||
|
// // style: const TextStyle(fontSize: 12),
|
||||||
|
// // decoration: const InputDecoration(
|
||||||
|
// // labelText: "From",
|
||||||
|
// // labelStyle: TextStyle(fontSize: 12, color: Colors.grey),
|
||||||
|
// // floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||||
|
// // border: InputBorder.none,
|
||||||
|
// // contentPadding: EdgeInsets.symmetric(vertical: 16),
|
||||||
|
// // ),
|
||||||
|
// // ),
|
||||||
|
// // ),
|
||||||
|
// ),
|
||||||
CustomTextFieldItnerarySubWrapper(
|
CustomTextFieldItnerarySubWrapper(
|
||||||
isFocused: _fromFocus,
|
isFocused: _fromFocus ?? false,
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child:
|
child: DropdownSearch<String>(
|
||||||
isCountryLoading
|
selectedItem: countryMap[selectedFrom],
|
||||||
? Center(child: CircularProgressIndicator())
|
popupProps: PopupProps.menu(
|
||||||
: DropdownSearch<String>(
|
showSearchBox: true,
|
||||||
// selectedItem: selectedFrom != null
|
fit: FlexFit.loose,
|
||||||
// ? countryMap[selectedFrom]
|
constraints: BoxConstraints(maxHeight: 250),
|
||||||
// : null,
|
menuProps: const MenuProps(backgroundColor: Colors.white),
|
||||||
selectedItem:
|
itemBuilder:
|
||||||
selectedFrom != null
|
(context, item, isSelected) => Container(
|
||||||
? countryMap[selectedFrom] // get the display value from code
|
color: Colors.white,
|
||||||
: null,
|
padding: EdgeInsets.symmetric(
|
||||||
popupProps: PopupProps.menu(
|
horizontal: 10,
|
||||||
menuProps: MenuProps(backgroundColor: Colors.white),
|
vertical: 6,
|
||||||
constraints: BoxConstraints(maxHeight: 230),
|
),
|
||||||
showSearchBox: true,
|
child: Text(
|
||||||
searchFieldProps: TextFieldProps(
|
item,
|
||||||
decoration: InputDecoration(
|
style: GoogleFonts.poppins(fontSize: 11.5),
|
||||||
hintText: "Search ...",
|
),
|
||||||
contentPadding: EdgeInsets.symmetric(
|
),
|
||||||
horizontal: 10,
|
searchFieldProps: TextFieldProps(
|
||||||
),
|
decoration: InputDecoration(
|
||||||
),
|
hintText: "Search ...",
|
||||||
),
|
contentPadding: EdgeInsets.symmetric(horizontal: 10),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
items: countryMap.values.toList(),
|
),
|
||||||
|
items: countryMap.values.toList(),
|
||||||
dropdownDecoratorProps: DropDownDecoratorProps(
|
dropdownDecoratorProps: DropDownDecoratorProps(
|
||||||
dropdownSearchDecoration: InputDecoration(
|
dropdownSearchDecoration: InputDecoration(
|
||||||
contentPadding: EdgeInsets.symmetric(
|
border: InputBorder.none,
|
||||||
horizontal: 10,
|
contentPadding: EdgeInsets.symmetric(horizontal: 1),
|
||||||
vertical: 5,
|
),
|
||||||
),
|
),
|
||||||
border: InputBorder.none,
|
dropdownBuilder:
|
||||||
),
|
(context, selectedItem) => Align(
|
||||||
),
|
alignment: Alignment.centerLeft,
|
||||||
dropdownBuilder:
|
child: Text(
|
||||||
(context, selectedItem) => Align(
|
selectedItem ?? "Select ",
|
||||||
alignment: Alignment.centerLeft,
|
style: GoogleFonts.poppins(
|
||||||
child: Text(
|
fontSize: 12,
|
||||||
selectedItem ?? "Select",
|
color: Colors.black,
|
||||||
style: TextStyle(fontSize: 12),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
onChanged: (String? newValue) {
|
||||||
// onChanged: (String? newValue) {
|
setState(() {
|
||||||
// setState(() {
|
selectedFrom =
|
||||||
// // selectedFrom[index] = countryMap.entries
|
countryMap.entries
|
||||||
// // .firstWhere((entry) => entry.value == newValue)
|
.firstWhere(
|
||||||
// // .key;
|
(entry) => entry.value == newValue,
|
||||||
//
|
)
|
||||||
// selectedFrom = countryMap.entries
|
.key;
|
||||||
// .firstWhere((entry) => entry.value == newValue)
|
});
|
||||||
// .key;
|
},
|
||||||
//
|
),
|
||||||
// print(selectedFrom);
|
|
||||||
// });
|
|
||||||
// },
|
|
||||||
onChanged: (String? newValue) {
|
|
||||||
setState(() {
|
|
||||||
selectedFrom =
|
|
||||||
countryMap.entries
|
|
||||||
.firstWhere(
|
|
||||||
(entry) => entry.value == newValue,
|
|
||||||
)
|
|
||||||
.key;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
// child: SizedBox(
|
|
||||||
// height: 40,
|
|
||||||
// child: TextField(
|
|
||||||
// focusNode: _fromFocusNode,
|
|
||||||
// controller: _fromController,
|
|
||||||
// style: const TextStyle(fontSize: 12),
|
|
||||||
// decoration: const InputDecoration(
|
|
||||||
// labelText: "From",
|
|
||||||
// labelStyle: TextStyle(fontSize: 12, color: Colors.grey),
|
|
||||||
// floatingLabelBehavior: FloatingLabelBehavior.never,
|
|
||||||
// border: InputBorder.none,
|
|
||||||
// contentPadding: EdgeInsets.symmetric(vertical: 16),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
),
|
),
|
||||||
if (errorMessages["from_station"] != null) ...[
|
if (errorMessages["from_station"] != null) ...[
|
||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
@ -694,7 +876,7 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"To",
|
"To *",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
@ -702,63 +884,128 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
|
// CustomTextFieldItnerarySubWrapper(
|
||||||
|
// isFocused: _toFocus,
|
||||||
|
// isDesktop: isDesktop,
|
||||||
|
// child: SizedBox(
|
||||||
|
// height: 40,
|
||||||
|
// child:
|
||||||
|
// isCountryLoading
|
||||||
|
// ? Center(child: CircularProgressIndicator())
|
||||||
|
// : DropdownSearch<String>(
|
||||||
|
// selectedItem:
|
||||||
|
// selectedTo != null
|
||||||
|
// ? countryMap[selectedTo] // get the display value from code
|
||||||
|
// : null,
|
||||||
|
// popupProps: PopupProps.menu(
|
||||||
|
// menuProps: MenuProps(backgroundColor: Colors.white),
|
||||||
|
// constraints: BoxConstraints(maxHeight: 230),
|
||||||
|
// showSearchBox: true,
|
||||||
|
// searchFieldProps: TextFieldProps(
|
||||||
|
// decoration: InputDecoration(
|
||||||
|
// hintText: "Search ...",
|
||||||
|
// contentPadding: EdgeInsets.symmetric(
|
||||||
|
// horizontal: 10,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// items: countryMap.values.toList(),
|
||||||
|
// dropdownDecoratorProps: DropDownDecoratorProps(
|
||||||
|
// dropdownSearchDecoration: InputDecoration(
|
||||||
|
// border: InputBorder.none,
|
||||||
|
// contentPadding: EdgeInsets.symmetric(horizontal: 1),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// dropdownBuilder:
|
||||||
|
// (context, selectedItem) => Align(
|
||||||
|
// alignment: Alignment.centerLeft,
|
||||||
|
// child: Text(
|
||||||
|
// selectedItem ?? "Select",
|
||||||
|
// style: TextStyle(fontSize: 12),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// onChanged: (String? newValue) {
|
||||||
|
// setState(() {
|
||||||
|
// selectedTo =
|
||||||
|
// countryMap.entries
|
||||||
|
// .firstWhere(
|
||||||
|
// (entry) => entry.value == newValue,
|
||||||
|
// )
|
||||||
|
// .key;
|
||||||
|
// });
|
||||||
|
// },
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
CustomTextFieldItnerarySubWrapper(
|
CustomTextFieldItnerarySubWrapper(
|
||||||
isFocused: _toFocus,
|
isFocused: _toFocus ?? false,
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child:
|
child: DropdownSearch<String>(
|
||||||
isCountryLoading
|
selectedItem: countryMap[selectedTo],
|
||||||
? Center(child: CircularProgressIndicator())
|
popupProps: PopupProps.menu(
|
||||||
: DropdownSearch<String>(
|
showSearchBox: true,
|
||||||
selectedItem:
|
fit: FlexFit.loose,
|
||||||
selectedTo != null
|
constraints: BoxConstraints(maxHeight: 250),
|
||||||
? countryMap[selectedTo] // get the display value from code
|
menuProps: const MenuProps(backgroundColor: Colors.white),
|
||||||
: null,
|
itemBuilder:
|
||||||
popupProps: PopupProps.menu(
|
(context, item, isSelected) => Container(
|
||||||
menuProps: MenuProps(backgroundColor: Colors.white),
|
color: Colors.white,
|
||||||
constraints: BoxConstraints(maxHeight: 230),
|
padding: EdgeInsets.symmetric(
|
||||||
showSearchBox: true,
|
horizontal: 10,
|
||||||
searchFieldProps: TextFieldProps(
|
vertical: 6,
|
||||||
decoration: InputDecoration(
|
),
|
||||||
hintText: "Search ...",
|
child: Text(
|
||||||
contentPadding: EdgeInsets.symmetric(
|
item,
|
||||||
horizontal: 10,
|
style: GoogleFonts.poppins(fontSize: 11.5),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
searchFieldProps: TextFieldProps(
|
||||||
),
|
decoration: InputDecoration(
|
||||||
items: countryMap.values.toList(),
|
hintText: "Search ...",
|
||||||
dropdownDecoratorProps: DropDownDecoratorProps(
|
contentPadding: EdgeInsets.symmetric(horizontal: 10),
|
||||||
dropdownSearchDecoration: InputDecoration(
|
),
|
||||||
border: InputBorder.none,
|
),
|
||||||
contentPadding: EdgeInsets.symmetric(horizontal: 1),
|
),
|
||||||
),
|
items: countryMap.values.toList(),
|
||||||
),
|
dropdownDecoratorProps: DropDownDecoratorProps(
|
||||||
dropdownBuilder:
|
dropdownSearchDecoration: InputDecoration(
|
||||||
(context, selectedItem) => Align(
|
border: InputBorder.none,
|
||||||
alignment: Alignment.centerLeft,
|
contentPadding: EdgeInsets.symmetric(horizontal: 1),
|
||||||
child: Text(
|
),
|
||||||
selectedItem ?? "Select",
|
),
|
||||||
style: TextStyle(fontSize: 12),
|
dropdownBuilder:
|
||||||
),
|
(context, selectedItem) => Align(
|
||||||
),
|
alignment: Alignment.centerLeft,
|
||||||
onChanged: (String? newValue) {
|
child: Text(
|
||||||
setState(() {
|
selectedItem ?? "Select ",
|
||||||
selectedTo =
|
style: GoogleFonts.poppins(
|
||||||
countryMap.entries
|
fontSize: 12,
|
||||||
.firstWhere(
|
color: Colors.black,
|
||||||
(entry) => entry.value == newValue,
|
),
|
||||||
)
|
),
|
||||||
.key;
|
),
|
||||||
});
|
onChanged: (String? newValue) {
|
||||||
},
|
setState(() {
|
||||||
),
|
selectedTo =
|
||||||
|
countryMap.entries
|
||||||
|
.firstWhere(
|
||||||
|
(entry) => entry.value == newValue,
|
||||||
|
)
|
||||||
|
.key;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (errorMessages["to_station"] != null) ...[
|
if (errorMessages["to_station"] != null) ...[
|
||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
Text("Required", style: TextStyle(color: Colors.red, fontSize: 12)),
|
Text(
|
||||||
|
errorMessages["to_station"]!,
|
||||||
|
style: TextStyle(color: Colors.red, fontSize: 12),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -767,7 +1014,7 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Date",
|
"Date *",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
@ -816,7 +1063,7 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Time",
|
"Time *",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
@ -831,7 +1078,10 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: () => _selectCheckOutTime(context),
|
onTap: () {
|
||||||
|
_timeController.text = "";
|
||||||
|
_selectCheckOutTime(context);
|
||||||
|
},
|
||||||
child: AbsorbPointer(
|
child: AbsorbPointer(
|
||||||
child: TextField(
|
child: TextField(
|
||||||
focusNode: _timeFocusNode,
|
focusNode: _timeFocusNode,
|
||||||
@ -856,7 +1106,10 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
),
|
),
|
||||||
if (errorMessages["time"] != null) ...[
|
if (errorMessages["time"] != null) ...[
|
||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
Text("Required", style: TextStyle(color: Colors.red, fontSize: 12)),
|
Text(
|
||||||
|
errorMessages["time"]!,
|
||||||
|
style: TextStyle(color: Colors.red, fontSize: 12),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@ -18,14 +18,15 @@ class VisaScreen extends StatefulWidget {
|
|||||||
final Map<String, dynamic>? selectedItem;
|
final Map<String, dynamic>? selectedItem;
|
||||||
final String? loginUser;
|
final String? loginUser;
|
||||||
|
|
||||||
VisaScreen(
|
VisaScreen({
|
||||||
{required this.onClose,
|
required this.onClose,
|
||||||
required this.onSaveVisa,
|
required this.onSaveVisa,
|
||||||
this.apiData,
|
this.apiData,
|
||||||
required this.selectedItem,
|
required this.selectedItem,
|
||||||
required this.apiCountryData,
|
required this.apiCountryData,
|
||||||
required this.loginUser,
|
required this.loginUser,
|
||||||
required this.flightData});
|
required this.flightData,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_VisaScreenState createState() => _VisaScreenState();
|
_VisaScreenState createState() => _VisaScreenState();
|
||||||
@ -99,14 +100,18 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
|
|
||||||
_addFocusListener(_tripTypeFocusNode, (focus) => _tripTypeFocused = focus);
|
_addFocusListener(_tripTypeFocusNode, (focus) => _tripTypeFocused = focus);
|
||||||
_addFocusListener(
|
_addFocusListener(
|
||||||
_hotelNameFocusNode, (focus) => _isHotelNameFocused = focus);
|
_hotelNameFocusNode,
|
||||||
|
(focus) => _isHotelNameFocused = focus,
|
||||||
|
);
|
||||||
_addFocusListener(_dateFocusNode, (focus) => _dateFocus = focus);
|
_addFocusListener(_dateFocusNode, (focus) => _dateFocus = focus);
|
||||||
_addFocusListener(_commentsFocusNode, (focus) => _commentsFocus = focus);
|
_addFocusListener(_commentsFocusNode, (focus) => _commentsFocus = focus);
|
||||||
|
|
||||||
_visaCommentsController =
|
_visaCommentsController = TextEditingController(
|
||||||
TextEditingController(text: widget.selectedItem?["comments"] ?? "");
|
text: widget.selectedItem?["comments"] ?? "",
|
||||||
_dateController =
|
);
|
||||||
TextEditingController(text: widget.selectedItem?["start_date"] ?? "");
|
_dateController = TextEditingController(
|
||||||
|
text: widget.selectedItem?["start_date"] ?? "",
|
||||||
|
);
|
||||||
|
|
||||||
// Set the selected value if available
|
// Set the selected value if available
|
||||||
if (widget.selectedItem != null &&
|
if (widget.selectedItem != null &&
|
||||||
@ -130,8 +135,9 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
// ✅ 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")
|
final parsedDate = DateFormat(
|
||||||
.parse(flightFirstTripDateNotifier.value ?? '');
|
"dd-MM-yyyy",
|
||||||
|
).parse(flightFirstTripDateNotifier.value ?? '');
|
||||||
if (parsedDate != null) {
|
if (parsedDate != null) {
|
||||||
_dateController.text = DateFormat('dd-MM-yyyy').format(parsedDate);
|
_dateController.text = DateFormat('dd-MM-yyyy').format(parsedDate);
|
||||||
}
|
}
|
||||||
@ -181,17 +187,16 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Map<String, String?> getFlightTripDateRange(
|
Map<String, String?> getFlightTripDateRange(
|
||||||
List<Map<String, dynamic>> flightData) {
|
List<Map<String, dynamic>> flightData,
|
||||||
final allTrips = flightData
|
) {
|
||||||
.expand((flight) => flight['trips'] ?? [])
|
final allTrips =
|
||||||
.whereType<Map<String, dynamic>>()
|
flightData
|
||||||
.toList();
|
.expand((flight) => flight['trips'] ?? [])
|
||||||
|
.whereType<Map<String, dynamic>>()
|
||||||
|
.toList();
|
||||||
|
|
||||||
if (allTrips.isEmpty) {
|
if (allTrips.isEmpty) {
|
||||||
return {
|
return {'firstTripDate': null, 'lastTripDate': null};
|
||||||
'firstTripDate': null,
|
|
||||||
'lastTripDate': null,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
allTrips.sort((a, b) {
|
allTrips.sort((a, b) {
|
||||||
@ -229,7 +234,7 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
List<String> requiredFields = [
|
List<String> requiredFields = [
|
||||||
"type_of_visa",
|
"type_of_visa",
|
||||||
"country_code",
|
"country_code",
|
||||||
"start_date"
|
"start_date",
|
||||||
];
|
];
|
||||||
|
|
||||||
// Check validation for each field
|
// Check validation for each field
|
||||||
@ -260,29 +265,32 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ResponsiveBuilder(builder: (context, sizingInfo) {
|
return ResponsiveBuilder(
|
||||||
bool isMobile = sizingInfo.isMobile;
|
builder: (context, sizingInfo) {
|
||||||
bool isDesktop = sizingInfo.deviceScreenType == DeviceScreenType.desktop;
|
bool isMobile = sizingInfo.isMobile;
|
||||||
|
bool isDesktop =
|
||||||
|
sizingInfo.deviceScreenType == DeviceScreenType.desktop;
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
child: Form(
|
child: Form(
|
||||||
key: _formKey,
|
key: _formKey,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(28.0),
|
padding: const EdgeInsets.only(top: 30.0),
|
||||||
child: Center(
|
child: Center(
|
||||||
child: Column(children: _buildAccomadtionForm(isDesktop)),
|
child: Column(children: _buildAccomadtionForm(isDesktop)),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
)
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
);
|
},
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> _buildAccomadtionForm(bool isDesktop) {
|
List<Widget> _buildAccomadtionForm(bool isDesktop) {
|
||||||
@ -308,14 +316,7 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> _buildFirstRow(isDesktop) {
|
List<Widget> _buildFirstRow(isDesktop) {
|
||||||
return [
|
return [if (isDesktop) Spacer() else SizedBox(height: 8)];
|
||||||
if (isDesktop)
|
|
||||||
Spacer()
|
|
||||||
else
|
|
||||||
SizedBox(
|
|
||||||
height: 8,
|
|
||||||
),
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> _buildTripType(bool isDesktop) {
|
List<Widget> _buildTripType(bool isDesktop) {
|
||||||
@ -354,7 +355,7 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
// Map country codes to country names
|
// Map country codes to country names
|
||||||
countryMap = {
|
countryMap = {
|
||||||
for (var item in countryList)
|
for (var item in countryList)
|
||||||
item['country_code'] as String: item['country_name'] as String
|
item['country_code'] as String: item['country_name'] as String,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Extract only country codes for processing
|
// Extract only country codes for processing
|
||||||
@ -393,6 +394,7 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
initialDate: initialDate,
|
initialDate: initialDate,
|
||||||
firstDate: initialDate,
|
firstDate: initialDate,
|
||||||
lastDate: DateTime(2100),
|
lastDate: DateTime(2100),
|
||||||
|
initialEntryMode: DatePickerEntryMode.calendarOnly,
|
||||||
);
|
);
|
||||||
|
|
||||||
// DateTime? pickedDate = await showDatePicker(
|
// DateTime? pickedDate = await showDatePicker(
|
||||||
@ -417,19 +419,24 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
|
|
||||||
List<dynamic> purposeList = widget.apiData?['visa_type_of_visa'] ?? [];
|
List<dynamic> purposeList = widget.apiData?['visa_type_of_visa'] ?? [];
|
||||||
|
|
||||||
List<DropdownMenuItem<String>> dropdownItems = purposeList
|
List<DropdownMenuItem<String>> dropdownItems =
|
||||||
.map((item) => DropdownMenuItem<String>(
|
purposeList
|
||||||
value: item['dropdown_key'],
|
.map(
|
||||||
child: Text(item['dropdown_value']),
|
(item) => DropdownMenuItem<String>(
|
||||||
))
|
value: item['dropdown_key'],
|
||||||
.toList();
|
child: Text(item['dropdown_value']),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList();
|
||||||
|
|
||||||
if (dropdownItems.isEmpty) {
|
if (dropdownItems.isEmpty) {
|
||||||
dropdownItems.add(
|
dropdownItems.add(
|
||||||
DropdownMenuItem<String>(
|
DropdownMenuItem<String>(
|
||||||
value: null,
|
value: null,
|
||||||
child: Text("No options available",
|
child: Text(
|
||||||
style: TextStyle(color: Colors.grey)),
|
"No options available",
|
||||||
|
style: TextStyle(color: Colors.grey),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -442,114 +449,115 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Type of Visa",
|
"Country *",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldWrapper(
|
// CustomTextFieldWrapper(
|
||||||
isFocused: _tripTypeFocused,
|
// isFocused: _isHotelNameFocused,
|
||||||
|
// isDesktop: isDesktop,
|
||||||
|
// // width: isDesktop ? MediaQuery.of(context).size.width * 0.15 : null,
|
||||||
|
// width:
|
||||||
|
// isDesktop
|
||||||
|
// ? MediaQuery.of(context).size.width * 0.34
|
||||||
|
// : MediaQuery.of(context).size.width * 0.66,
|
||||||
|
// child: SizedBox(
|
||||||
|
// height: 40,
|
||||||
|
// child: DropdownSearch<String>(
|
||||||
|
// selectedItem: countryMap[selectedCountry],
|
||||||
|
// popupProps: PopupProps.menu(
|
||||||
|
// showSearchBox: true, // Enables search functionality
|
||||||
|
// searchFieldProps: TextFieldProps(
|
||||||
|
// decoration: InputDecoration(
|
||||||
|
// hintText: "Search ...",
|
||||||
|
// contentPadding: EdgeInsets.symmetric(horizontal: 10),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// items: countryMap.values.toList(),
|
||||||
|
// dropdownDecoratorProps: DropDownDecoratorProps(
|
||||||
|
// dropdownSearchDecoration: InputDecoration(
|
||||||
|
// border: InputBorder.none,
|
||||||
|
// contentPadding: EdgeInsets.symmetric(horizontal: 1),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// dropdownBuilder:
|
||||||
|
// (context, selectedItem) => Align(
|
||||||
|
// // Center-align selected item
|
||||||
|
// alignment: Alignment.centerLeft,
|
||||||
|
// child: Text(
|
||||||
|
// selectedItem ?? "Select ",
|
||||||
|
// style: TextStyle(fontSize: 12),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// onChanged: (String? newValue) {
|
||||||
|
// setState(() {
|
||||||
|
// // Find the country_code based on selected country_name
|
||||||
|
// selectedCountry =
|
||||||
|
// countryMap.entries
|
||||||
|
// .firstWhere((entry) => entry.value == newValue)
|
||||||
|
// .key;
|
||||||
|
//
|
||||||
|
// if (selectedCountry!.isNotEmpty) {
|
||||||
|
// errorMessages.remove("country_code");
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// },
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
CustomTextFieldItnerarySubWrapper(
|
||||||
|
isFocused: _isHotelNameFocused,
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
width: isDesktop
|
width: isDesktop
|
||||||
? MediaQuery.of(context).size.width * 0.34
|
? MediaQuery.of(context).size.width * 0.34
|
||||||
: MediaQuery.of(context).size.width * 0.66,
|
: MediaQuery.of(context).size.width * 0.66,
|
||||||
child: SizedBox(
|
|
||||||
height: 40,
|
|
||||||
child: DropdownButtonFormField<String>(
|
|
||||||
focusNode: _tripTypeFocusNode, // Assign the correct focus node
|
|
||||||
value: selectedPurpose,
|
|
||||||
style: TextStyle(fontSize: 12),
|
|
||||||
decoration: InputDecoration(
|
|
||||||
border: InputBorder.none,
|
|
||||||
contentPadding:
|
|
||||||
EdgeInsets.symmetric(horizontal: 10), // Proper padding
|
|
||||||
),
|
|
||||||
onChanged: purposeList.isNotEmpty
|
|
||||||
? (newValue) {
|
|
||||||
setState(() {
|
|
||||||
selectedPurpose = newValue;
|
|
||||||
});
|
|
||||||
print(
|
|
||||||
"Updating form data: Flight -> trip_type -> ${newValue ?? ""}");
|
|
||||||
}
|
|
||||||
: null,
|
|
||||||
|
|
||||||
items: dropdownItems,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (errorMessages["type_of_visa"] != 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(
|
|
||||||
"Country",
|
|
||||||
style: GoogleFonts.poppins(
|
|
||||||
fontSize: 12,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
color: Color(0xFF575A74)),
|
|
||||||
),
|
|
||||||
SizedBox(height: 5),
|
|
||||||
CustomTextFieldWrapper(
|
|
||||||
isFocused: _isHotelNameFocused,
|
|
||||||
isDesktop: isDesktop,
|
|
||||||
width: isDesktop ? MediaQuery.of(context).size.width * 0.15 : null,
|
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: DropdownSearch<String>(
|
child: DropdownSearch<String>(
|
||||||
selectedItem: countryMap[selectedCountry],
|
selectedItem: countryMap[selectedCountry],
|
||||||
popupProps: PopupProps.menu(
|
popupProps: PopupProps.menu(
|
||||||
showSearchBox: true, // Enables search functionality
|
showSearchBox: true,
|
||||||
searchFieldProps: TextFieldProps(
|
searchFieldProps: TextFieldProps(
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: "Search Country...",
|
hintText: "Search ...",
|
||||||
contentPadding: EdgeInsets.symmetric(horizontal: 10),
|
contentPadding: EdgeInsets.symmetric(horizontal: 10),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
itemBuilder: (context, item, isSelected) {
|
||||||
|
return Container(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 4),
|
||||||
|
child: Text(
|
||||||
|
item,
|
||||||
|
style: TextStyle(fontSize: 12,color: Colors.black,),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
items: countryMap.values.toList(),
|
items: countryMap.values.toList(),
|
||||||
dropdownDecoratorProps: DropDownDecoratorProps(
|
dropdownDecoratorProps: DropDownDecoratorProps(
|
||||||
dropdownSearchDecoration: InputDecoration(
|
dropdownSearchDecoration: InputDecoration(
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding: EdgeInsets.symmetric(
|
contentPadding: EdgeInsets.symmetric(horizontal: 1),
|
||||||
horizontal: 1,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
dropdownBuilder: (context, selectedItem) => Align(
|
dropdownBuilder: (context, selectedItem) => Align(
|
||||||
// Center-align selected item
|
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: Text(
|
child: Text(
|
||||||
selectedItem ?? "Select Country",
|
selectedItem ?? "Select",
|
||||||
style: TextStyle(fontSize: 12),
|
style: TextStyle(fontSize: 12),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
onChanged: (String? newValue) {
|
onChanged: (String? newValue) {
|
||||||
setState(() {
|
setState(() {
|
||||||
// Find the country_code based on selected country_name
|
|
||||||
selectedCountry = countryMap.entries
|
selectedCountry = countryMap.entries
|
||||||
.firstWhere((entry) => entry.value == newValue)
|
.firstWhere((entry) => entry.value == newValue)
|
||||||
.key;
|
.key;
|
||||||
|
|
||||||
if (selectedCountry!.isNotEmpty) {
|
|
||||||
errorMessages.remove("country_code");
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -557,28 +565,154 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
),
|
),
|
||||||
if (errorMessages["country_code"] != null) ...[
|
if (errorMessages["country_code"] != null) ...[
|
||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
Text(
|
Text("Required", style: TextStyle(color: Colors.red, fontSize: 12)),
|
||||||
"Required",
|
|
||||||
style: TextStyle(color: Colors.red, fontSize: 12),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (isDesktop)
|
|
||||||
Spacer()
|
if (isDesktop) Spacer() else SizedBox(height: 8),
|
||||||
else
|
|
||||||
SizedBox(
|
|
||||||
height: 8,
|
|
||||||
),
|
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Start Date",
|
"Type of Visa",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: 5),
|
||||||
|
// CustomTextFieldWrapper(
|
||||||
|
// isFocused: _tripTypeFocused,
|
||||||
|
// isDesktop: isDesktop,
|
||||||
|
// width: isDesktop ? MediaQuery.of(context).size.width * 0.15 : null,
|
||||||
|
// // width: isDesktop
|
||||||
|
// // ? MediaQuery.of(context).size.width * 0.34
|
||||||
|
// // : MediaQuery.of(context).size.width * 0.66,
|
||||||
|
// child: SizedBox(
|
||||||
|
// height: 40,
|
||||||
|
// child: DropdownButtonFormField<String>(
|
||||||
|
// focusNode: _tripTypeFocusNode, // Assign the correct focus node
|
||||||
|
// value: selectedPurpose,
|
||||||
|
// style: TextStyle(fontSize: 12),
|
||||||
|
// decoration: InputDecoration(
|
||||||
|
// border: InputBorder.none,
|
||||||
|
// contentPadding: EdgeInsets.symmetric(
|
||||||
|
// horizontal: 10,
|
||||||
|
// ), // Proper padding
|
||||||
|
// ),
|
||||||
|
// onChanged:
|
||||||
|
// purposeList.isNotEmpty
|
||||||
|
// ? (newValue) {
|
||||||
|
// setState(() {
|
||||||
|
// selectedPurpose = newValue;
|
||||||
|
// });
|
||||||
|
// print(
|
||||||
|
// "Updating form data: Flight -> trip_type -> ${newValue ?? ""}",
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// : null,
|
||||||
|
//
|
||||||
|
// items: dropdownItems,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
CustomTextFieldWrapper(
|
||||||
|
isFocused: _tripTypeFocused,
|
||||||
|
isDesktop: isDesktop,
|
||||||
|
width: isDesktop ? MediaQuery.of(context).size.width * 0.15 : null,
|
||||||
|
child: SizedBox(
|
||||||
|
height: 40,
|
||||||
|
width: double.infinity,
|
||||||
|
child: DropdownSearch<Map<String, dynamic>>(
|
||||||
|
items: purposeList.cast<Map<String, dynamic>>(),
|
||||||
|
selectedItem: purposeList.firstWhere(
|
||||||
|
(item) => item['dropdown_key'] == selectedPurpose,
|
||||||
|
orElse: () => {},
|
||||||
|
),
|
||||||
|
itemAsString: (item) => item['dropdown_value'] ?? '',
|
||||||
|
popupProps: PopupProps.menu(
|
||||||
|
showSearchBox: false,
|
||||||
|
fit: FlexFit.loose,
|
||||||
|
menuProps: const MenuProps(backgroundColor: Colors.white),
|
||||||
|
itemBuilder: (context, item, isSelected) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 10,
|
||||||
|
vertical: 5,
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
item['dropdown_value'] ?? '',
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 12,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
dropdownDecoratorProps: const DropDownDecoratorProps(
|
||||||
|
dropdownSearchDecoration: InputDecoration(
|
||||||
|
border: InputBorder.none,
|
||||||
|
contentPadding: EdgeInsets.symmetric(horizontal: 10,vertical: 10,),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
dropdownBuilder: (context, selectedItem) {
|
||||||
|
if (selectedItem == null || selectedItem.isEmpty) {
|
||||||
|
return Text(
|
||||||
|
"Select ",
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
color: Colors.grey,
|
||||||
|
fontSize: 13,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Text(
|
||||||
|
selectedItem['dropdown_value'] ?? '',
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 12,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
// focusNode: _tripTypeFocusNode, // Assign the correct focus node
|
||||||
|
// value: selectedPurpose,
|
||||||
|
// style: TextStyle(fontSize: 12),
|
||||||
|
// decoration: InputDecoration(
|
||||||
|
// border: InputBorder.none,
|
||||||
|
// contentPadding:
|
||||||
|
// EdgeInsets.symmetric(horizontal: 10), // Proper padding
|
||||||
|
// ),
|
||||||
|
onChanged:
|
||||||
|
purposeList.isNotEmpty
|
||||||
|
? (Map<String, dynamic>? newValue) {
|
||||||
|
setState(() {
|
||||||
|
selectedPurpose= newValue?['dropdown_key'];
|
||||||
|
print("Selected Purpose: ${selectedPurpose}");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (errorMessages["type_of_visa"] != 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(
|
||||||
|
"Start Date *",
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldWrapper(
|
CustomTextFieldWrapper(
|
||||||
@ -607,8 +741,11 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
floatingLabelBehavior: FloatingLabelBehavior.never,
|
floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
||||||
suffixIcon: Icon(Icons.calendar_today,
|
suffixIcon: Icon(
|
||||||
size: 16, color: Colors.grey),
|
Icons.calendar_today,
|
||||||
|
size: 16,
|
||||||
|
color: Colors.grey,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -617,10 +754,7 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
),
|
),
|
||||||
if (errorMessages["start_date"] != null) ...[
|
if (errorMessages["start_date"] != null) ...[
|
||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
Text(
|
Text("Required", style: TextStyle(color: Colors.red, fontSize: 12)),
|
||||||
"Required",
|
|
||||||
style: TextStyle(color: Colors.red, fontSize: 12),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -635,17 +769,19 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
Text(
|
Text(
|
||||||
"Comments",
|
"Comments",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldWrapper(
|
CustomTextFieldWrapper(
|
||||||
isFocused: _commentsFocus, // Dropdown doesn't use focus
|
isFocused: _commentsFocus, // Dropdown doesn't use focus
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
width: isDesktop
|
width:
|
||||||
? MediaQuery.of(context).size.width * 0.34
|
isDesktop
|
||||||
: MediaQuery.of(context).size.width * 0.66,
|
? MediaQuery.of(context).size.width * 0.34
|
||||||
|
: MediaQuery.of(context).size.width * 0.66,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
@ -665,9 +801,7 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (isDesktop) Spacer(),
|
if (isDesktop) Spacer(),
|
||||||
SizedBox(
|
SizedBox(height: 5),
|
||||||
height: 5,
|
|
||||||
),
|
|
||||||
Column(
|
Column(
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
@ -688,9 +822,7 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Colors.grey[400], // Light grey color
|
backgroundColor: Colors.grey[400], // Light grey color
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
|
||||||
borderRadius: BorderRadius.circular(8),
|
|
||||||
),
|
|
||||||
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
@ -699,7 +831,6 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(width: 10), // Space between buttons
|
SizedBox(width: 10), // Space between buttons
|
||||||
|
|
||||||
// Save Changes Button
|
// Save Changes Button
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
@ -707,9 +838,7 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Color(0xFF114D8B), // Primary color for save
|
backgroundColor: Color(0xFF114D8B), // Primary color for save
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
|
||||||
borderRadius: BorderRadius.circular(8),
|
|
||||||
),
|
|
||||||
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
|
|||||||
@ -398,13 +398,34 @@ class _FlightListWidgetState extends State<FlightListWidget> {
|
|||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 4,
|
flex: 4,
|
||||||
child: Text(
|
child: Column(
|
||||||
"$fromPlaceCountry (From) - (To) $toPlaceCountry",
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
// "${trip["from_place"]?.toString()} - ${trip["to_place"]?.toString()}",
|
children: [
|
||||||
style: GoogleFonts.poppins(
|
Text(
|
||||||
fontSize: 12,
|
"$fromPlaceCountry",
|
||||||
fontWeight: FontWeight.w700,
|
// "${trip["from_place"]?.toString()} - ${trip["to_place"]?.toString()}",
|
||||||
),
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 10),
|
||||||
|
child: Image.asset(
|
||||||
|
'assets/images/IconsImg/alternate.png',
|
||||||
|
width: 20,
|
||||||
|
height: 20,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
"$toPlaceCountry",
|
||||||
|
// "${trip["from_place"]?.toString()} - ${trip["to_place"]?.toString()}",
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
|
|||||||
@ -334,7 +334,7 @@ class VisaListWidget extends StatelessWidget {
|
|||||||
Expanded(
|
Expanded(
|
||||||
flex: 2,
|
flex: 2,
|
||||||
child: Text(
|
child: Text(
|
||||||
" Visa Type",
|
" Country",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 11,
|
fontSize: 11,
|
||||||
),
|
),
|
||||||
@ -342,7 +342,7 @@ class VisaListWidget extends StatelessWidget {
|
|||||||
Expanded(
|
Expanded(
|
||||||
flex: 2,
|
flex: 2,
|
||||||
child: Text(
|
child: Text(
|
||||||
" Country",
|
" Visa Type",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 11,
|
fontSize: 11,
|
||||||
),
|
),
|
||||||
@ -372,8 +372,8 @@ class VisaListWidget extends StatelessWidget {
|
|||||||
Expanded(
|
Expanded(
|
||||||
flex: 2,
|
flex: 2,
|
||||||
child: Text(
|
child: Text(
|
||||||
getRequestForVisa(
|
getRequestForCountry(
|
||||||
item["type_of_visa"]!.toString()),
|
item["country_code"]!.toString()),
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
@ -384,8 +384,8 @@ class VisaListWidget extends StatelessWidget {
|
|||||||
Expanded(
|
Expanded(
|
||||||
flex: 2,
|
flex: 2,
|
||||||
child: Text(
|
child: Text(
|
||||||
getRequestForCountry(
|
getRequestForVisa(
|
||||||
item["country_code"]!.toString()),
|
item["type_of_visa"]!.toString()),
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
|
|||||||
@ -903,10 +903,15 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
apiCostData = plansJson;
|
apiCostData = plansJson;
|
||||||
|
|
||||||
|
print("apiCostData...1");
|
||||||
costCenterMap = {
|
costCenterMap = {
|
||||||
for (var item in apiCostData!)
|
for (var item in apiCostData!)
|
||||||
|
// item['department_id'].toString(): item['name'].toString(),
|
||||||
item['cost_center_id'].toString(): item['name'].toString(),
|
item['cost_center_id'].toString(): item['name'].toString(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
print("apiCostData...122");
|
||||||
costCenterIds = costCenterMap.keys.toList();
|
costCenterIds = costCenterMap.keys.toList();
|
||||||
|
|
||||||
// Optionally auto-select the first item if not already selected
|
// Optionally auto-select the first item if not already selected
|
||||||
@ -1030,8 +1035,9 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
// Handle Submit
|
// Handle Submit
|
||||||
|
|
||||||
bool validateForm() {
|
bool validateForm() {
|
||||||
|
print("validateForm");
|
||||||
validationErrors.clear(); // Clear previous errors
|
validationErrors.clear(); // Clear previous errors
|
||||||
|
print("validateForm.....1");
|
||||||
// Ensure either "user_id" or "traveller_id" is provided
|
// Ensure either "user_id" or "traveller_id" is provided
|
||||||
if ((planUsrId == null || planUsrId!.isEmpty) &&
|
if ((planUsrId == null || planUsrId!.isEmpty) &&
|
||||||
(planTravlrId == null || planTravlrId!.isEmpty)) {
|
(planTravlrId == null || planTravlrId!.isEmpty)) {
|
||||||
@ -1040,7 +1046,7 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
validationErrors["traveller_id"] =
|
validationErrors["traveller_id"] =
|
||||||
"Either User ID or Traveller ID is required";
|
"Either User ID or Traveller ID is required";
|
||||||
}
|
}
|
||||||
|
print("validateForm.....2");
|
||||||
final requiredFields = {
|
final requiredFields = {
|
||||||
if (TripPlanAction != "Plan Creation Not Allowed") //
|
if (TripPlanAction != "Plan Creation Not Allowed") //
|
||||||
"trip_type": _selectedTripType,
|
"trip_type": _selectedTripType,
|
||||||
@ -1049,14 +1055,14 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
"functional_department": selectedFuncDept,
|
"functional_department": selectedFuncDept,
|
||||||
"purpose_of_travel": selectedPurpose,
|
"purpose_of_travel": selectedPurpose,
|
||||||
};
|
};
|
||||||
|
print("validateForm.....3");
|
||||||
for (var entry in requiredFields.entries) {
|
for (var entry in requiredFields.entries) {
|
||||||
if (entry.value == null || entry.value!.isEmpty) {
|
if (entry.value == null || entry.value!.isEmpty) {
|
||||||
validationErrors[entry.key] = "Required";
|
validationErrors[entry.key] = "Required";
|
||||||
// "${entry.key.replaceAll('_', ' ').toUpperCase()} Required";
|
// "${entry.key.replaceAll('_', ' ').toUpperCase()} Required";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
print("validateForm.....1");
|
||||||
// Validate at least one service is selected
|
// Validate at least one service is selected
|
||||||
final serviceLists = [
|
final serviceLists = [
|
||||||
flightList,
|
flightList,
|
||||||
@ -1179,7 +1185,9 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
|
|
||||||
void handleSubmit() {
|
void handleSubmit() {
|
||||||
setState(() async {
|
setState(() async {
|
||||||
|
print("Hansle Submit....11");
|
||||||
if (validateForm() && temporaryMessage == null) {
|
if (validateForm() && temporaryMessage == null) {
|
||||||
|
print("Hansle Submit....11222");
|
||||||
// if (selectedPlanId != null && selectedPlanId!.isNotEmpty) {
|
// if (selectedPlanId != null && selectedPlanId!.isNotEmpty) {
|
||||||
// planData['plan_id'] = selectedPlanId; // Add plan_id for update
|
// planData['plan_id'] = selectedPlanId; // Add plan_id for update
|
||||||
// }
|
// }
|
||||||
@ -1251,6 +1259,26 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
} else {
|
} else {
|
||||||
print("Failed to submit plan. Status: ${response.statusCode}");
|
print("Failed to submit plan. Status: ${response.statusCode}");
|
||||||
print("Error: ${response.body}");
|
print("Error: ${response.body}");
|
||||||
|
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return AlertDialog(
|
||||||
|
title: Text("Trip Creation Failed"),
|
||||||
|
content: Text(
|
||||||
|
"There was a problem submitting your plan. Please try again.",
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
child: Text("OK"),
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(" Error submitting plan: $e");
|
print(" Error submitting plan: $e");
|
||||||
@ -2592,7 +2620,7 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
List<Map<String, String>> options = [
|
List<Map<String, String>> options = [
|
||||||
{"title": "Self", "value": "Option 1"},
|
{"title": "Self", "value": "Option 1"},
|
||||||
{"title": "Other Employee", "value": "Option 2"},
|
{"title": "Other Employee", "value": "Option 2"},
|
||||||
{"title": "Others", "value": "Option 3"},
|
{"title": "Others (Non Employee)", "value": "Option 3"},
|
||||||
];
|
];
|
||||||
|
|
||||||
print(" layoutColor: ${widget.layoutColor}");
|
print(" layoutColor: ${widget.layoutColor}");
|
||||||
@ -2908,8 +2936,8 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
// ),
|
// ),
|
||||||
// ),
|
// ),
|
||||||
CustomTextFieldWrapper(
|
CustomTextFieldWrapper(
|
||||||
isFocused: false,
|
// isFocused: false,
|
||||||
// isFocused: _isdescriptionFocused,
|
isFocused: _isdescriptionFocused,
|
||||||
// width: isDesktop
|
// width: isDesktop
|
||||||
// ? MediaQuery.of(context).size.width * 0.38
|
// ? MediaQuery.of(context).size.width * 0.38
|
||||||
// : MediaQuery.of(context).size.width * 0.85,
|
// : MediaQuery.of(context).size.width * 0.85,
|
||||||
@ -3017,8 +3045,9 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
labelText: "Trip Name *",
|
labelText: "Trip Name *",
|
||||||
labelStyle: GoogleFonts.poppins(
|
labelStyle: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w400,
|
||||||
color: Color(0xFF575A74),
|
color: Colors.grey,
|
||||||
|
// color: Color(0xFF575A74),
|
||||||
),
|
),
|
||||||
floatingLabelBehavior: FloatingLabelBehavior.never,
|
floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
|
|||||||
@ -101,6 +101,13 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
|||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
|
|
||||||
if (widget.tripType != _tripType) {
|
if (widget.tripType != _tripType) {
|
||||||
|
// setState(() {
|
||||||
|
// selectedOption = "";
|
||||||
|
// isSelected = false;
|
||||||
|
// selectedIndex = null;
|
||||||
|
// selectedItem = null;
|
||||||
|
// });
|
||||||
|
|
||||||
updateTripType(widget.tripType);
|
updateTripType(widget.tripType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -160,6 +167,20 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
List<String> getAllowedServiceNames() {
|
List<String> getAllowedServiceNames() {
|
||||||
|
print(
|
||||||
|
"DID Updatee changee - $selectedOption $selectedListOption $isSelected $selectedItem $selectedIndex",
|
||||||
|
);
|
||||||
|
setState(() {
|
||||||
|
selectedOption = "";
|
||||||
|
selectedListOption = "";
|
||||||
|
isSelected = false;
|
||||||
|
selectedIndex = null;
|
||||||
|
selectedItem = null;
|
||||||
|
});
|
||||||
|
print(
|
||||||
|
"DID Updatee changee - $selectedOption $isSelected $selectedItem $selectedIndex",
|
||||||
|
);
|
||||||
|
|
||||||
if (widget.tripType == "1") {
|
if (widget.tripType == "1") {
|
||||||
return ["flight", "accomodation", "train", "bus", "taxi"];
|
return ["flight", "accomodation", "train", "bus", "taxi"];
|
||||||
} else if (widget.tripType == "2") {
|
} else if (widget.tripType == "2") {
|
||||||
|
|||||||
@ -968,7 +968,7 @@ class _ListPlansState extends State<ListPlans> {
|
|||||||
height: 15,
|
height: 15,
|
||||||
),
|
),
|
||||||
tooltip:
|
tooltip:
|
||||||
'Edit Trip/Plans Details',
|
'Edit Trip Details',
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.pop(
|
Navigator.pop(
|
||||||
context,
|
context,
|
||||||
@ -1009,7 +1009,7 @@ class _ListPlansState extends State<ListPlans> {
|
|||||||
size: 18,
|
size: 18,
|
||||||
),
|
),
|
||||||
tooltip:
|
tooltip:
|
||||||
'Download The Trip Comments',
|
'Download The PDF',
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.pop(
|
Navigator.pop(
|
||||||
context,
|
context,
|
||||||
@ -1222,7 +1222,7 @@ class _ListPlansState extends State<ListPlans> {
|
|||||||
height: 15,
|
height: 15,
|
||||||
),
|
),
|
||||||
tooltip:
|
tooltip:
|
||||||
'Edit Trip/plan Details',
|
'Edit Trip Details',
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.pop(
|
Navigator.pop(
|
||||||
context,
|
context,
|
||||||
@ -1256,7 +1256,7 @@ class _ListPlansState extends State<ListPlans> {
|
|||||||
size: 18,
|
size: 18,
|
||||||
),
|
),
|
||||||
tooltip:
|
tooltip:
|
||||||
'Download The Trip Comments',
|
'Download The PDF',
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
apiService
|
apiService
|
||||||
|
|||||||
@ -322,7 +322,8 @@ class _PolicyListState extends State<PolicyList> {
|
|||||||
controller: searchController,
|
controller: searchController,
|
||||||
onChanged: filterPolicy,
|
onChanged: filterPolicy,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: "Search for a Policy",
|
hintText: "Search ...",
|
||||||
|
|
||||||
hintStyle: TextStyle(
|
hintStyle: TextStyle(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
color: Color(0xFF9E9DBD),
|
color: Color(0xFF9E9DBD),
|
||||||
@ -383,7 +384,7 @@ class _PolicyListState extends State<PolicyList> {
|
|||||||
MainAxisSize.min, // Ensures content fits nicely
|
MainAxisSize.min, // Ensures content fits nicely
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Add New Policy",
|
"Add Policy",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: isDesktop ? 13 : 11,
|
fontSize: isDesktop ? 13 : 11,
|
||||||
),
|
),
|
||||||
@ -413,7 +414,7 @@ class _PolicyListState extends State<PolicyList> {
|
|||||||
controller: searchController,
|
controller: searchController,
|
||||||
onChanged: filterPolicy,
|
onChanged: filterPolicy,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: "Search for a Policy",
|
hintText: "Search ...",
|
||||||
hintStyle: TextStyle(
|
hintStyle: TextStyle(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
color: Color(0xFF9E9DBD),
|
color: Color(0xFF9E9DBD),
|
||||||
|
|||||||
@ -42,14 +42,14 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
final ApiService apiService = ApiService();
|
final ApiService apiService = ApiService();
|
||||||
|
|
||||||
final GlobalKey<PersonalDetailsState> personalDetailsKey =
|
final GlobalKey<PersonalDetailsState> personalDetailsKey =
|
||||||
GlobalKey<PersonalDetailsState>();
|
GlobalKey<PersonalDetailsState>();
|
||||||
final GlobalKey<TravellerDetailsState> travellerDetailsKey =
|
final GlobalKey<TravellerDetailsState> travellerDetailsKey =
|
||||||
GlobalKey<TravellerDetailsState>();
|
GlobalKey<TravellerDetailsState>();
|
||||||
|
|
||||||
// late List<Map<String, dynamic>?> travelDetailsData;
|
// late List<Map<String, dynamic>?> travelDetailsData;
|
||||||
Map<String, dynamic>? travelDetailsData;
|
Map<String, dynamic>? travelDetailsData;
|
||||||
Map<String, dynamic>? travelDetailsDataFromAPI;
|
Map<String, dynamic>? travelDetailsDataFromAPI;
|
||||||
|
Map<String, String> errorMessagesTravel = {};
|
||||||
late TabController _tabController;
|
late TabController _tabController;
|
||||||
|
|
||||||
String? userId;
|
String? userId;
|
||||||
@ -299,7 +299,7 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
// Fix the invalid JSON (dangerous if the format changes)
|
// Fix the invalid JSON (dangerous if the format changes)
|
||||||
final fixedJson = raw.replaceAllMapped(
|
final fixedJson = raw.replaceAllMapped(
|
||||||
RegExp(r'(\w+):'), // matches `service_id:`
|
RegExp(r'(\w+):'), // matches `service_id:`
|
||||||
(match) => '"${match.group(1)}":',
|
(match) => '"${match.group(1)}":',
|
||||||
);
|
);
|
||||||
|
|
||||||
List<dynamic> decodedList = jsonDecode(fixedJson);
|
List<dynamic> decodedList = jsonDecode(fixedJson);
|
||||||
@ -363,7 +363,7 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
final extraData =
|
final extraData =
|
||||||
GoRouterState.of(context).extra as Map<String, dynamic>?;
|
GoRouterState.of(context).extra as Map<String, dynamic>?;
|
||||||
|
|
||||||
if (extraData != null) {
|
if (extraData != null) {
|
||||||
print("extraData: ${extraData['selectedUser']}");
|
print("extraData: ${extraData['selectedUser']}");
|
||||||
@ -381,8 +381,8 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
|
|
||||||
// Handle selectedUser as a Map (not a List)
|
// Handle selectedUser as a Map (not a List)
|
||||||
apiselectedUser =
|
apiselectedUser =
|
||||||
extraData['selectedUser']
|
extraData['selectedUser']
|
||||||
as Map<String, dynamic>?; // Cast it as a Map
|
as Map<String, dynamic>?; // Cast it as a Map
|
||||||
isViewMode = extraData['isViewMode'] ?? false;
|
isViewMode = extraData['isViewMode'] ?? false;
|
||||||
isEditProfile = extraData['isEditProfile'] ?? false;
|
isEditProfile = extraData['isEditProfile'] ?? false;
|
||||||
});
|
});
|
||||||
@ -444,7 +444,7 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
userMap = {
|
userMap = {
|
||||||
for (var user in userList)
|
for (var user in userList)
|
||||||
user['user_id'].toString():
|
user['user_id'].toString():
|
||||||
"${user['first_name']} ${user['last_name']}",
|
"${user['first_name']} ${user['last_name']}",
|
||||||
};
|
};
|
||||||
userIdsApi = userMap.keys.toList();
|
userIdsApi = userMap.keys.toList();
|
||||||
});
|
});
|
||||||
@ -483,14 +483,14 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
layoutColor =
|
layoutColor =
|
||||||
layoutString != null
|
layoutString != null
|
||||||
? Color(int.parse(layoutString))
|
? Color(int.parse(layoutString))
|
||||||
: Colors.redAccent;
|
: Colors.redAccent;
|
||||||
|
|
||||||
bodyColor =
|
bodyColor =
|
||||||
bodyStringColor != null
|
bodyStringColor != null
|
||||||
? Color(int.parse(bodyStringColor))
|
? Color(int.parse(bodyStringColor))
|
||||||
: Colors.white;
|
: Colors.white;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -546,6 +546,33 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
printFormData();
|
printFormData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void handleBack() async {
|
||||||
|
print("USR Detail back");
|
||||||
|
|
||||||
|
final tabs = {
|
||||||
|
"personal": "Personal Details",
|
||||||
|
"office": "Office Details",
|
||||||
|
"travel": "Travel Details",
|
||||||
|
};
|
||||||
|
|
||||||
|
final tabKeys = tabs.keys.toList(); // ["personal", "office", "travel"]
|
||||||
|
|
||||||
|
final currentIndex = tabKeys.indexOf(selectedTab ?? "travel");
|
||||||
|
|
||||||
|
print("currentIndex - $currentIndex");
|
||||||
|
|
||||||
|
if (currentIndex > 0) {
|
||||||
|
// Move to next tab
|
||||||
|
setState(() {
|
||||||
|
selectedTab = tabKeys[currentIndex - 1];
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Final step — submit or show done
|
||||||
|
print("All tabs completed!");
|
||||||
|
// Submit the full form here
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void handleNext() async {
|
void handleNext() async {
|
||||||
print("USR Detail Next");
|
print("USR Detail Next");
|
||||||
printFormData();
|
printFormData();
|
||||||
@ -553,6 +580,7 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
// travelDetailsData = [travellerDetailsKey.currentState?.travel_Detials];
|
// travelDetailsData = [travellerDetailsKey.currentState?.travel_Detials];
|
||||||
|
|
||||||
travelDetailsData = travellerDetailsKey.currentState?.travel_Detials;
|
travelDetailsData = travellerDetailsKey.currentState?.travel_Detials;
|
||||||
|
// errorMessagesTravel = travellerDetailsKey.currentState!.errorMessages;
|
||||||
|
|
||||||
print("TRAVEL DETAILS FROM CHILD: $travelDetailsData");
|
print("TRAVEL DETAILS FROM CHILD: $travelDetailsData");
|
||||||
|
|
||||||
@ -626,31 +654,106 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
void handleSubmit() async {
|
void handleSubmit() async {
|
||||||
print("USR Detail Submit");
|
print("USR Detail Submit");
|
||||||
// printFormData();
|
// printFormData();
|
||||||
travelDetailsData = travellerDetailsKey.currentState?.travel_Detials;
|
|
||||||
|
|
||||||
print("TRAVEL DETAILS FROM CHILD");
|
bool isValid = travellerDetailsKey.currentState?.boolValidation() ?? false;
|
||||||
// print("TRAVEL DETAILS FROM CHILD: $travelDetailsData");
|
if (selectedTab == "travel" ||
|
||||||
|
selectedRole == "5" ||
|
||||||
|
setSelectesUserType == true) {
|
||||||
|
print("NO validation");
|
||||||
|
|
||||||
passportFile = travellerDetailsKey.currentState?.passportFile;
|
Map<String, dynamic> data = userDetials;
|
||||||
|
|
||||||
print("passportFile : $passportFile");
|
if (!isValidData(data)) {
|
||||||
|
print("USERDETAILS : $userDetials");
|
||||||
|
print("Validation Failed: Required fields are missing.");
|
||||||
|
setState(() {});
|
||||||
|
return; // Stop execution if validation fails
|
||||||
|
} else {
|
||||||
|
print("USERDETAILS : $userDetials");
|
||||||
|
orgId = await getOrgId();
|
||||||
|
|
||||||
Map<String, dynamic> data = userDetials;
|
createUserData(userDetials);
|
||||||
|
}
|
||||||
print("USERDETAILS : $data");
|
|
||||||
|
|
||||||
// Map<String, dynamic> data = userDetials;
|
|
||||||
|
|
||||||
if (!isValidData(data) && isValidDataTwo(data)) {
|
|
||||||
print("USERDETAILS : $userDetials");
|
|
||||||
print("Validation Failed: Required fields are missing.");
|
|
||||||
setState(() {});
|
|
||||||
return; // Stop execution if validation fails
|
|
||||||
} else {
|
} else {
|
||||||
print("USERDETAILS : $userDetials");
|
print("isValid- $isValid");
|
||||||
orgId = await getOrgId();
|
if (!isValid) {
|
||||||
|
print("Validation failed. Please check the inputs.");
|
||||||
|
setState(() {});
|
||||||
|
return; // ❌ STOP execution here if not valid
|
||||||
|
}
|
||||||
|
|
||||||
createUserData(userDetials);
|
travelDetailsData = travellerDetailsKey.currentState?.travel_Detials;
|
||||||
|
|
||||||
|
print("travelDetailsData - $travelDetailsData");
|
||||||
|
|
||||||
|
print("travelDetailsData - $travelDetailsData");
|
||||||
|
// errorMessagesTravel = travellerDetailsKey.currentState!.errorMessages;
|
||||||
|
|
||||||
|
print("TRAVEL DETAILS FROM CHILD");
|
||||||
|
// print("TRAVEL DETAILS FROM CHILD: $travelDetailsData");
|
||||||
|
|
||||||
|
passportFile = travellerDetailsKey.currentState?.passportFile;
|
||||||
|
|
||||||
|
print("passportFile : $passportFile");
|
||||||
|
|
||||||
|
Map<String, dynamic> data = userDetials;
|
||||||
|
|
||||||
|
print("USERDETAILS : $data");
|
||||||
|
|
||||||
|
// block-submit-here
|
||||||
|
|
||||||
|
// Additional validation starts - travelDetailsData passport
|
||||||
|
DateTime? start_Date = travelDetailsData?['date_of_issue'];
|
||||||
|
DateTime? end_Date = travelDetailsData?['date_of_expiry'];
|
||||||
|
|
||||||
|
if (start_Date != null && end_Date != null && start_Date.toString().isNotEmpty && end_Date.toString().isNotEmpty) {
|
||||||
|
try {
|
||||||
|
final format = DateFormat("dd-MM-yyyy");
|
||||||
|
final checkStartDate = format.parse("$start_Date");
|
||||||
|
final checkEndDate = format.parse("$end_Date");
|
||||||
|
|
||||||
|
if (checkEndDate.isBefore(checkStartDate)) {
|
||||||
|
// return "End date cannot be earlier than start date";;
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
} catch (e) { // return "End date cannot be earlier than start date";
|
||||||
|
return ;
|
||||||
|
// errorMessages["end_date"] = "Invalid date format";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// valid_from: 20-06-2025, valid_upto: 19-06-2025
|
||||||
|
DateTime? valid_from = data?['valid_from'];
|
||||||
|
DateTime? valid_upto = data?['valid_upto'];
|
||||||
|
|
||||||
|
if (valid_from != null && valid_upto != null && valid_from.toString().isNotEmpty && valid_upto.toString().isNotEmpty) {
|
||||||
|
try {
|
||||||
|
final format = DateFormat("dd-MM-yyyy");
|
||||||
|
final checkValidFrom = format.parse("$valid_from");
|
||||||
|
final checkValidUpto = format.parse("$valid_upto");
|
||||||
|
|
||||||
|
if (checkValidUpto.isBefore(checkValidFrom)) {
|
||||||
|
// return "valid upto cannot be earlier than valid from";
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
} catch (e) { // return "valid upto cannot be earlier than valid from";
|
||||||
|
return ;
|
||||||
|
// errorMessages["end_date"] = "Invalid date format";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map<String, dynamic> data = userDetials;
|
||||||
|
|
||||||
|
if (!isValidData(data) && isValidDataTwo(data)) {
|
||||||
|
print("USERDETAILS : $userDetials");
|
||||||
|
print("Validation Failed: Required fields are missing.");
|
||||||
|
setState(() {});
|
||||||
|
return; // Stop execution if validation fails
|
||||||
|
} else {
|
||||||
|
print("USERDETAILS : $userDetials");
|
||||||
|
orgId = await getOrgId();
|
||||||
|
|
||||||
|
createUserData(userDetials);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -682,7 +785,7 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
if (data["mobile_no"] != null && data["mobile_no"].toString().isNotEmpty) {
|
if (data["mobile_no"] != null && data["mobile_no"].toString().isNotEmpty) {
|
||||||
if (!RegExp(r"^\d{10}$").hasMatch(data["mobile_no"].toString())) {
|
if (!RegExp(r"^\d{10}$").hasMatch(data["mobile_no"].toString())) {
|
||||||
errorMessages["mobile_no"] =
|
errorMessages["mobile_no"] =
|
||||||
"Enter 10 digits"; // Invalid mobile number format
|
"Enter 10 digits"; // Invalid mobile number format
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -692,7 +795,7 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
r"^\d{10}$",
|
r"^\d{10}$",
|
||||||
).hasMatch(data["alternate_mobile_no"].toString())) {
|
).hasMatch(data["alternate_mobile_no"].toString())) {
|
||||||
errorMessages["alternate_mobile_no"] =
|
errorMessages["alternate_mobile_no"] =
|
||||||
"Enter 10 digits"; // Invalid mobile number format
|
"Enter 10 digits"; // Invalid mobile number format
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -882,7 +985,7 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
// ✅ Ensure UI updates
|
// ✅ Ensure UI updates
|
||||||
if (isMatch) {
|
if (isMatch) {
|
||||||
errorMessages["password"] =
|
errorMessages["password"] =
|
||||||
"New password is not similar to old password";
|
"New password is not similar to old password";
|
||||||
print(" Password match!");
|
print(" Password match!");
|
||||||
} else {
|
} else {
|
||||||
print(" Password NOT match!");
|
print(" Password NOT match!");
|
||||||
@ -911,16 +1014,16 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
drawer: CustomDrawer(isDesktop: false),
|
drawer: CustomDrawer(isDesktop: false),
|
||||||
body: Padding(
|
body: Padding(
|
||||||
padding:
|
padding:
|
||||||
isDesktop
|
isDesktop
|
||||||
? EdgeInsets.symmetric(
|
? EdgeInsets.symmetric(
|
||||||
horizontal:
|
horizontal:
|
||||||
MediaQuery.of(context).size.width *
|
MediaQuery.of(context).size.width *
|
||||||
0.1, // 30% of screen width as horizontal padding
|
0.1, // 30% of screen width as horizontal padding
|
||||||
vertical:
|
vertical:
|
||||||
MediaQuery.of(context).size.height *
|
MediaQuery.of(context).size.height *
|
||||||
0, // 5% of screen height as vertical padding
|
0, // 5% of screen height as vertical padding
|
||||||
)
|
)
|
||||||
: EdgeInsets.all(0),
|
: EdgeInsets.all(0),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [Expanded(child: buildData(isDesktop, context))],
|
children: [Expanded(child: buildData(isDesktop, context))],
|
||||||
),
|
),
|
||||||
@ -942,9 +1045,9 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: Container(
|
child: Container(
|
||||||
height:
|
height:
|
||||||
isDesktop
|
isDesktop
|
||||||
? MediaQuery.of(context).size.height * 0.98
|
? MediaQuery.of(context).size.height * 0.98
|
||||||
: MediaQuery.of(context).size.height,
|
: MediaQuery.of(context).size.height,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: EdgeInsets.all(0.0),
|
padding: EdgeInsets.all(0.0),
|
||||||
child: _buildUserDetails(isDesktop),
|
child: _buildUserDetails(isDesktop),
|
||||||
@ -956,28 +1059,39 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
child:
|
child:
|
||||||
isDesktop
|
isDesktop
|
||||||
? Row(
|
? Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
children:
|
children: [
|
||||||
(selectedTab == "travel" ||
|
if (selectedTab != "personal")
|
||||||
selectedRole == "5" ||
|
..._buildBack(isDesktop, layoutColor!),
|
||||||
setSelectesUserType == true)
|
Spacer(), // spacing between buttons
|
||||||
? _buildSubmit(isDesktop, layoutColor!)
|
// Next or Submit based on role or user type
|
||||||
: _buildNext(
|
if (selectedTab == "travel" ||
|
||||||
isDesktop,
|
selectedRole == "5" ||
|
||||||
layoutColor!,
|
setSelectesUserType == true)
|
||||||
), // _buildGoBack(isDesktop, layoutColor!),
|
..._buildSubmit(isDesktop, layoutColor!)
|
||||||
)
|
else
|
||||||
: Row(
|
..._buildNext(isDesktop, layoutColor!),
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
// (selectedTab == "travel" ||
|
||||||
children:
|
// selectedRole == "5" ||
|
||||||
(selectedTab == "travel" ||
|
// setSelectesUserType == true)
|
||||||
selectedRole == "5" ||
|
// ? _buildSubmit(isDesktop, layoutColor!)
|
||||||
setSelectesUserType == true)
|
// : _buildNext(
|
||||||
? _buildSubmit(isDesktop, layoutColor!)
|
// isDesktop,
|
||||||
: _buildNext(isDesktop, layoutColor!),
|
// layoutColor!,
|
||||||
),
|
// ), // _buildGoBack(isDesktop, layoutColor!),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children:
|
||||||
|
(selectedTab == "travel" ||
|
||||||
|
selectedRole == "5" ||
|
||||||
|
setSelectesUserType == true)
|
||||||
|
? _buildSubmit(isDesktop, layoutColor!)
|
||||||
|
: _buildNext(isDesktop, layoutColor!),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -1022,9 +1136,9 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
isDesktop
|
isDesktop
|
||||||
? buildTabsForUser()
|
? buildTabsForUser()
|
||||||
: SingleChildScrollView(
|
: SingleChildScrollView(
|
||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: Axis.horizontal,
|
||||||
child: buildTabsForUser(),
|
child: buildTabsForUser(),
|
||||||
),
|
),
|
||||||
Container(
|
Container(
|
||||||
// color: Colors.yellow.shade50,
|
// color: Colors.yellow.shade50,
|
||||||
height: MediaQuery.of(context).size.height * 0.64,
|
height: MediaQuery.of(context).size.height * 0.64,
|
||||||
@ -1127,8 +1241,8 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
);
|
);
|
||||||
case "travel":
|
case "travel":
|
||||||
final fullName =
|
final fullName =
|
||||||
"${controllers["Fname"]?.text ?? ""} ${controllers["Lname"]?.text ?? ""}"
|
"${controllers["Fname"]?.text ?? ""} ${controllers["Lname"]?.text ?? ""}"
|
||||||
.trim();
|
.trim();
|
||||||
return TravellerDetails(
|
return TravellerDetails(
|
||||||
key: travellerDetailsKey,
|
key: travellerDetailsKey,
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
@ -1187,69 +1301,69 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
return Row(
|
return Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.end, // important
|
crossAxisAlignment: CrossAxisAlignment.end, // important
|
||||||
children:
|
children:
|
||||||
tabs.entries.map((entry) {
|
tabs.entries.map((entry) {
|
||||||
final targetTab = entry.key;
|
final targetTab = entry.key;
|
||||||
|
|
||||||
print("TargetsTAb: $targetTab");
|
print("TargetsTAb: $targetTab");
|
||||||
|
|
||||||
final isSelected = selectedTab == entry.key;
|
final isSelected = selectedTab == entry.key;
|
||||||
print("isSelected: $isSelected");
|
print("isSelected: $isSelected");
|
||||||
|
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
bool isValid = false;
|
bool isValid = false;
|
||||||
|
|
||||||
final currentTab = selectedTab;
|
final currentTab = selectedTab;
|
||||||
if (currentTab == "personal") {
|
if (currentTab == "personal") {
|
||||||
isValid = isValidData(userDetials);
|
isValid = isValidData(userDetials);
|
||||||
|
|
||||||
if (isValid) {
|
if (isValid) {
|
||||||
selectedTab = entry.key;
|
selectedTab = entry.key;
|
||||||
}
|
}
|
||||||
} else if (currentTab == "office" &&
|
} else if (currentTab == "office" &&
|
||||||
targetTab == "personal") {
|
targetTab == "personal") {
|
||||||
selectedTab = entry.key;
|
selectedTab = entry.key;
|
||||||
} else if (currentTab == "office") {
|
} else if (currentTab == "office") {
|
||||||
isValid = isValidDataTwo(userDetials);
|
isValid = isValidDataTwo(userDetials);
|
||||||
if (isValid) {
|
if (isValid) {
|
||||||
selectedTab = entry.key;
|
selectedTab = entry.key;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
isValid =
|
isValid =
|
||||||
true; // Travel tab might not need validation at this point
|
true; // Travel tab might not need validation at this point
|
||||||
selectedTab = entry.key;
|
selectedTab = entry.key;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.only(
|
padding: const EdgeInsets.only(
|
||||||
right: 24.0,
|
right: 24.0,
|
||||||
), // space between tabs
|
), // space between tabs
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
entry.value,
|
entry.value,
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color:
|
color:
|
||||||
isSelected ? Color(0xFF114D8B) : Color(0xFF475569),
|
isSelected ? Color(0xFF114D8B) : Color(0xFF475569),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
const SizedBox(height: 8),
|
|
||||||
AnimatedContainer(
|
|
||||||
duration: Duration(milliseconds: 300),
|
|
||||||
height: 2,
|
|
||||||
width: isSelected ? 50 : 0, // small line
|
|
||||||
color: Color(0xFF114D8B),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(height: 8),
|
||||||
);
|
AnimatedContainer(
|
||||||
}).toList(),
|
duration: Duration(milliseconds: 300),
|
||||||
|
height: 2,
|
||||||
|
width: isSelected ? 50 : 0, // small line
|
||||||
|
color: Color(0xFF114D8B),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1259,17 +1373,17 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
return [
|
return [
|
||||||
MouseRegion(
|
MouseRegion(
|
||||||
cursor:
|
cursor:
|
||||||
isViewMode
|
isViewMode
|
||||||
? SystemMouseCursors.forbidden
|
? SystemMouseCursors.forbidden
|
||||||
: SystemMouseCursors.click,
|
: SystemMouseCursors.click,
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
isViewMode ? layoutColor : layoutColor, // Keep original color
|
isViewMode ? layoutColor : layoutColor, // Keep original color
|
||||||
foregroundColor:
|
foregroundColor:
|
||||||
isViewMode ? Colors.white : Colors.white, // Keep original color
|
isViewMode ? Colors.white : Colors.white, // Keep original color
|
||||||
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),
|
||||||
@ -1288,17 +1402,17 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
return [
|
return [
|
||||||
MouseRegion(
|
MouseRegion(
|
||||||
cursor:
|
cursor:
|
||||||
isViewMode
|
isViewMode
|
||||||
? SystemMouseCursors.forbidden
|
? SystemMouseCursors.forbidden
|
||||||
: SystemMouseCursors.click,
|
: SystemMouseCursors.click,
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
isViewMode ? layoutColor : layoutColor, // Keep original color
|
isViewMode ? layoutColor : layoutColor, // Keep original color
|
||||||
foregroundColor:
|
foregroundColor:
|
||||||
isViewMode ? Colors.white : Colors.white, // Keep original color
|
isViewMode ? Colors.white : Colors.white, // Keep original color
|
||||||
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),
|
||||||
@ -1319,28 +1433,28 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
return [
|
return [
|
||||||
MouseRegion(
|
MouseRegion(
|
||||||
cursor:
|
cursor:
|
||||||
isViewMode
|
isViewMode
|
||||||
? SystemMouseCursors.forbidden
|
? SystemMouseCursors.forbidden
|
||||||
: SystemMouseCursors.click,
|
: SystemMouseCursors.click,
|
||||||
child: TextButton(
|
child: TextButton(
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
isViewMode ? layoutColor : layoutColor, // Keep original color
|
isViewMode ? Colors.white : Colors.white, // Keep original color
|
||||||
foregroundColor:
|
foregroundColor:
|
||||||
isViewMode ? Colors.white : Colors.red, // Keep original color
|
isViewMode ? layoutColor : layoutColor, // Keep original color
|
||||||
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: Colors.white, width: 2),
|
||||||
),
|
),
|
||||||
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 18),
|
||||||
),
|
),
|
||||||
onPressed: handleNext,
|
onPressed: handleBack,
|
||||||
// onPressed:
|
// onPressed:
|
||||||
// isViewMode ? null : handleNext, // Disable when in view mode
|
// isViewMode ? null : handleNext, // Disable when in view mode
|
||||||
child: Text("Next"),
|
child: Text("Back"),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
@ -1367,19 +1481,19 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
if (!isViewMode)
|
if (!isViewMode)
|
||||||
MouseRegion(
|
MouseRegion(
|
||||||
cursor:
|
cursor:
|
||||||
isViewMode
|
isViewMode
|
||||||
? SystemMouseCursors.forbidden
|
? SystemMouseCursors.forbidden
|
||||||
: SystemMouseCursors.click,
|
: SystemMouseCursors.click,
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
isViewMode ? layoutColor : layoutColor, // Keep original color
|
isViewMode ? layoutColor : layoutColor, // Keep original color
|
||||||
foregroundColor:
|
foregroundColor:
|
||||||
isViewMode
|
isViewMode
|
||||||
? Colors.white
|
? Colors.white
|
||||||
: Colors.white, // Keep original color
|
: Colors.white, // Keep original color
|
||||||
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),
|
||||||
@ -1388,7 +1502,7 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
||||||
),
|
),
|
||||||
onPressed:
|
onPressed:
|
||||||
isViewMode ? null : handleSubmit, // Disable when in view mode
|
isViewMode ? null : handleSubmit, // Disable when in view mode
|
||||||
child: Text("Submit"),
|
child: Text("Submit"),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@ -391,7 +391,7 @@ class _OfficeDetailsState extends State<OfficeDetails> {
|
|||||||
buildDelegationStartDateField(isDesktop),
|
buildDelegationStartDateField(isDesktop),
|
||||||
Spacer(), // Space after Last Name
|
Spacer(), // Space after Last Name
|
||||||
buildDelegationEndDateField(isDesktop),
|
buildDelegationEndDateField(isDesktop),
|
||||||
SizedBox(width: 15),
|
SizedBox(width: 16),
|
||||||
buildReset(isDesktop),
|
buildReset(isDesktop),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@ -692,6 +692,9 @@ class _OfficeDetailsState extends State<OfficeDetails> {
|
|||||||
enabled: !widget.isViewMode,
|
enabled: !widget.isViewMode,
|
||||||
|
|
||||||
popupProps: PopupProps.menu(
|
popupProps: PopupProps.menu(
|
||||||
|
menuProps: const MenuProps(
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
),
|
||||||
showSearchBox: true,
|
showSearchBox: true,
|
||||||
fit: FlexFit.loose, // Allows flexible height
|
fit: FlexFit.loose, // Allows flexible height
|
||||||
itemBuilder:
|
itemBuilder:
|
||||||
@ -1342,6 +1345,7 @@ class _OfficeDetailsState extends State<OfficeDetails> {
|
|||||||
: today,
|
: today,
|
||||||
firstDate: today,
|
firstDate: today,
|
||||||
lastDate: DateTime(2100),
|
lastDate: DateTime(2100),
|
||||||
|
initialEntryMode: DatePickerEntryMode.calendarOnly,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (pickedDate != null && pickedDate != _selectedCheckOutDate) {
|
if (pickedDate != null && pickedDate != _selectedCheckOutDate) {
|
||||||
@ -1450,6 +1454,7 @@ class _OfficeDetailsState extends State<OfficeDetails> {
|
|||||||
: minDate,
|
: minDate,
|
||||||
firstDate: minDate,
|
firstDate: minDate,
|
||||||
lastDate: DateTime(2100),
|
lastDate: DateTime(2100),
|
||||||
|
initialEntryMode: DatePickerEntryMode.calendarOnly,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (pickedDate != null && pickedDate != _selectedEndDate) {
|
if (pickedDate != null && pickedDate != _selectedEndDate) {
|
||||||
@ -1475,7 +1480,7 @@ class _OfficeDetailsState extends State<OfficeDetails> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldUserWrapper(
|
CustomTextFieldUserWrapper(
|
||||||
width: isDesktop ? MediaQuery.of(context).size.width * 0.18 : null,
|
width: isDesktop ? MediaQuery.of(context).size.width * 0.2 : null,
|
||||||
isFocused: false,
|
isFocused: false,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
|
|||||||
@ -639,7 +639,9 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
children: [
|
children: [
|
||||||
if (!widget.apiselectedUser) ...[
|
if (!widget.apiselectedUser) ...[
|
||||||
buildPassword(),
|
buildPassword(),
|
||||||
SizedBox(width: 15),
|
SizedBox(
|
||||||
|
width: MediaQuery.of(context).size.width * 0.015,
|
||||||
|
),
|
||||||
buildRole(),
|
buildRole(),
|
||||||
] else ...[
|
] else ...[
|
||||||
// TextButton(
|
// TextButton(
|
||||||
@ -736,9 +738,11 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
buildAddress(),
|
buildAddress(),
|
||||||
SizedBox(width: 15),
|
Spacer(),
|
||||||
|
// SizedBox(width: 15),
|
||||||
buildCountryField(),
|
buildCountryField(),
|
||||||
SizedBox(width: 15),
|
Spacer(),
|
||||||
|
// SizedBox(width: 15),
|
||||||
buildPostalCodeField(),
|
buildPostalCodeField(),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@ -1043,7 +1047,9 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
? _selectedDateOfBirth!
|
? _selectedDateOfBirth!
|
||||||
: today,
|
: today,
|
||||||
firstDate: DateTime(1900),
|
firstDate: DateTime(1900),
|
||||||
lastDate: DateTime(2100),
|
// lastDate: DateTime(2100),
|
||||||
|
lastDate: today,
|
||||||
|
initialEntryMode: DatePickerEntryMode.calendarOnly,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (pickedDate != null && pickedDate != _selectedDateOfBirth) {
|
if (pickedDate != null && pickedDate != _selectedDateOfBirth) {
|
||||||
@ -1583,6 +1589,7 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
widget.isViewMode
|
widget.isViewMode
|
||||||
? null
|
? null
|
||||||
: (String? newValue) {
|
: (String? newValue) {
|
||||||
|
widget.errorMessages.remove("role_id");
|
||||||
if (newValue == null) return;
|
if (newValue == null) return;
|
||||||
final selectedKey =
|
final selectedKey =
|
||||||
roleMap.entries
|
roleMap.entries
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -1137,15 +1137,54 @@ class _UserListScreenState extends State<UserListScreen> {
|
|||||||
child: Column(
|
child: Column(
|
||||||
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
|
// Expanded(
|
||||||
|
// child:
|
||||||
|
// isDesktop
|
||||||
|
// ? SingleChildScrollView(
|
||||||
|
// scrollDirection: Axis.vertical,
|
||||||
|
// child: table, // <-- your existing table
|
||||||
|
// )
|
||||||
|
// : buildMobileCardView(paginatedUser),
|
||||||
|
// ),
|
||||||
|
|
||||||
Expanded(
|
Expanded(
|
||||||
child:
|
child:
|
||||||
isDesktop
|
isDesktop
|
||||||
? SingleChildScrollView(
|
? (searchController.text.isNotEmpty &&
|
||||||
scrollDirection: Axis.vertical,
|
filteredUsers.isEmpty
|
||||||
child: table, // <-- your existing table
|
? Center(
|
||||||
)
|
child: Text(
|
||||||
: buildMobileCardView(paginatedUser),
|
"No users found",
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 14,
|
||||||
|
color: Colors.grey,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: SingleChildScrollView(
|
||||||
|
scrollDirection: Axis.vertical,
|
||||||
|
child: table,
|
||||||
|
))
|
||||||
|
: (searchController.text.isNotEmpty &&
|
||||||
|
filteredUsers.isEmpty
|
||||||
|
? Center(
|
||||||
|
child: Text(
|
||||||
|
"No users found",
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 14,
|
||||||
|
color: Colors.grey,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: buildMobileCardView(paginatedUser)),
|
||||||
|
// child: isDesktop
|
||||||
|
// ? SingleChildScrollView(
|
||||||
|
// scrollDirection: Axis.vertical,
|
||||||
|
// child: table, // <-- your existing table
|
||||||
|
// )
|
||||||
|
// : buildMobileCardView(paginatedPlans),
|
||||||
),
|
),
|
||||||
|
|
||||||
PaginationControls(
|
PaginationControls(
|
||||||
currentPage: currentPage,
|
currentPage: currentPage,
|
||||||
itemsPerPage: itemsPerPage,
|
itemsPerPage: itemsPerPage,
|
||||||
|
|||||||
@ -284,297 +284,298 @@ class _CustomAppBarState extends State<CustomAppBar> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return
|
return AppBar(
|
||||||
FocusTraversalGroup(
|
backgroundColor: Colors.white,
|
||||||
descendantsAreFocusable: false,
|
surfaceTintColor: Colors.white,
|
||||||
child:
|
// elevation: 3,
|
||||||
AppBar(
|
automaticallyImplyLeading: !widget.isDesktop,
|
||||||
backgroundColor: Colors.white,
|
iconTheme: IconThemeData(
|
||||||
surfaceTintColor: Colors.white,
|
color: layoutColor, // 👈 Set your desired icon color here
|
||||||
// elevation: 3,
|
),
|
||||||
automaticallyImplyLeading: !widget.isDesktop,
|
|
||||||
iconTheme: IconThemeData(
|
|
||||||
color: layoutColor, // 👈 Set your desired icon color here
|
|
||||||
),
|
|
||||||
|
|
||||||
titleSpacing: 0,
|
titleSpacing: 0,
|
||||||
|
|
||||||
title:
|
title:
|
||||||
!widget.isDesktop
|
!widget.isDesktop
|
||||||
? Text('')
|
? Text('')
|
||||||
: Padding(
|
: Padding(
|
||||||
padding: EdgeInsets.symmetric(
|
|
||||||
horizontal: MediaQuery.of(context).size.width * 0.05,
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(10),
|
|
||||||
|
|
||||||
// padding: const EdgeInsets.symmetric(horizontal: 40, vertical: 10),
|
|
||||||
child:
|
|
||||||
selectedOrg?['logo'] != null
|
|
||||||
? SizedBox(
|
|
||||||
height: 50,
|
|
||||||
child: ClipRect(
|
|
||||||
child: Image.network(
|
|
||||||
selectedOrg!['logo'],
|
|
||||||
width: 130, //130
|
|
||||||
height: 80, //80
|
|
||||||
fit: BoxFit.contain,
|
|
||||||
errorBuilder: (context, error, stackTrace) {
|
|
||||||
return const CircleAvatar(
|
|
||||||
radius: 20,
|
|
||||||
backgroundColor: Colors.redAccent,
|
|
||||||
child: Icon(Icons.error, size: 10),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: const CircleAvatar(
|
|
||||||
radius: 20,
|
|
||||||
// backgroundColor: Colors.white,
|
|
||||||
child: Icon(
|
|
||||||
Icons.add_a_photo,
|
|
||||||
size: 10,
|
|
||||||
color: Colors.grey,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(width: MediaQuery.of(context).size.width * 0.18),
|
|
||||||
Container(
|
|
||||||
width: MediaQuery.of(context).size.width * 0.35,
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
if (userData?["role"] == "Org Admin" ||
|
|
||||||
userData?["role"] == "Travel Admin")
|
|
||||||
buildNavItem(
|
|
||||||
"Dashboard",
|
|
||||||
() => handleTabChange(
|
|
||||||
TabSelection.dashboard,
|
|
||||||
'/StatusDashboard',
|
|
||||||
),
|
|
||||||
layoutColor!,
|
|
||||||
isSelected: selectedTab == TabSelection.dashboard,
|
|
||||||
icon: Icons.dashboard,
|
|
||||||
// icon: Icons.insights_outlined,
|
|
||||||
),
|
|
||||||
if (userData?["role"] == "Org Admin" ||
|
|
||||||
userData?["role"] == "Travel Admin")
|
|
||||||
const SizedBox(width: 20),
|
|
||||||
if (userData?["role"] == "Org Admin" ||
|
|
||||||
userData?["role"] == "Travel Admin")
|
|
||||||
buildNavItem(
|
|
||||||
"All Trips",
|
|
||||||
() => handleTabChange(
|
|
||||||
TabSelection.allTrips,
|
|
||||||
'/listAllPlan',
|
|
||||||
),
|
|
||||||
layoutColor!,
|
|
||||||
isSelected: selectedTab == TabSelection.allTrips,
|
|
||||||
icon: Icons.format_list_bulleted_rounded,
|
|
||||||
// icon: Icons.insights_outlined,
|
|
||||||
),
|
|
||||||
if (userDetails["role"] != "Travel Agent")
|
|
||||||
const SizedBox(width: 20),
|
|
||||||
if (userData?["role"] == "Travel Agent")
|
|
||||||
buildNavItem(
|
|
||||||
"Trips",
|
|
||||||
() => handleTabChange(
|
|
||||||
TabSelection.myTrips,
|
|
||||||
'/listTravelAgentPlan',
|
|
||||||
),
|
|
||||||
layoutColor!,
|
|
||||||
// () => context.go('/listTravelAgentPlan'),
|
|
||||||
isSelected: selectedTab == TabSelection.myTrips,
|
|
||||||
icon: Icons.shopping_bag_outlined,
|
|
||||||
// icon: Icons.request_page_outlined,
|
|
||||||
),
|
|
||||||
if (userData?["role"] != "Travel Agent") // for others
|
|
||||||
buildNavItem(
|
|
||||||
"My Trips",
|
|
||||||
() => handleTabChange(
|
|
||||||
TabSelection.myTrips,
|
|
||||||
'/listPlan',
|
|
||||||
),
|
|
||||||
layoutColor!,
|
|
||||||
// () => context.go('/listPlan'),
|
|
||||||
isSelected: selectedTab == TabSelection.myTrips,
|
|
||||||
icon: Icons.shopping_bag_outlined,
|
|
||||||
),
|
|
||||||
const SizedBox(width: 20),
|
|
||||||
if (userData?["role"] != "Travel Agent")
|
|
||||||
buildNavItem(
|
|
||||||
"My Approvals",
|
|
||||||
|
|
||||||
() => handleTabChange(
|
|
||||||
TabSelection.myApprovals,
|
|
||||||
'/ApprovalList',
|
|
||||||
),
|
|
||||||
layoutColor!,
|
|
||||||
// () => context.go('/ApprovalList'),
|
|
||||||
isSelected:
|
|
||||||
selectedTab == TabSelection.myApprovals,
|
|
||||||
icon: Icons.verified_outlined,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Spacer(),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
actions: [
|
|
||||||
Padding(
|
|
||||||
padding: EdgeInsets.symmetric(
|
padding: EdgeInsets.symmetric(
|
||||||
horizontal: MediaQuery.of(context).size.width * 0.05,
|
horizontal: MediaQuery.of(context).size.width * 0.05,
|
||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
// if (userData?["role"] != "User")
|
Padding(
|
||||||
Builder(
|
padding: const EdgeInsets.all(10),
|
||||||
builder:
|
|
||||||
(context) => PopupMenuButton<String>(
|
|
||||||
color: Colors.white,
|
|
||||||
padding: EdgeInsets.zero,
|
|
||||||
offset: const Offset(0, 50), // 👈 shift it 50 pixels down
|
|
||||||
onSelected: (String value) {
|
|
||||||
switch (value) {
|
|
||||||
case '/OrganizationSettings':
|
|
||||||
context.go('/OrganizationSettings');
|
|
||||||
break;
|
|
||||||
// case '/OrganizationSetup':
|
|
||||||
// context.go('/OrganizationSetup');
|
|
||||||
// break;
|
|
||||||
case '/listUser':
|
|
||||||
context.go('/listUser');
|
|
||||||
break;
|
|
||||||
// case '/group':
|
|
||||||
// context.go('/group');
|
|
||||||
// break;
|
|
||||||
// case '/department':
|
|
||||||
// context.go('/department');
|
|
||||||
// break;
|
|
||||||
// case '/PolicyList':
|
|
||||||
// context.go('/PolicyList');
|
|
||||||
// case '/getPerdiem':
|
|
||||||
// context.go('/getPerdiem');
|
|
||||||
// case '/templateList':
|
|
||||||
// context.go('/templateList');
|
|
||||||
// case '/template':
|
|
||||||
// context.go('/template');
|
|
||||||
|
|
||||||
case '/CreateUserDetails':
|
// padding: const EdgeInsets.symmetric(horizontal: 40, vertical: 10),
|
||||||
context.go(
|
child:
|
||||||
"/CreateUserDetails",
|
selectedOrg?['logo'] != null
|
||||||
extra: {
|
? SizedBox(
|
||||||
"selectedUser": profileUserDetails,
|
height: 50,
|
||||||
"isEditProfile": true,
|
child: ClipRect(
|
||||||
"isViewMode": false,
|
child: Image.network(
|
||||||
},
|
selectedOrg!['logo'],
|
||||||
);
|
width: 130, //130
|
||||||
case '/logout':
|
height: 80, //80
|
||||||
context.go('/');
|
fit: BoxFit.contain,
|
||||||
break;
|
errorBuilder: (context, error, stackTrace) {
|
||||||
}
|
return const CircleAvatar(
|
||||||
},
|
radius: 20,
|
||||||
|
child: Icon(
|
||||||
// itemBuilder: (BuildContext context) =>
|
Icons.add_a_photo,
|
||||||
// menuItems.map(buildMenuItem).toList(),
|
size: 10,
|
||||||
itemBuilder: (BuildContext context) {
|
color: Colors.grey,
|
||||||
// final isUser = userData?["role"] == "User";
|
|
||||||
final role = userData?["role"];
|
|
||||||
List<Map<String, dynamic>> filteredItems;
|
|
||||||
|
|
||||||
if (role == "User") {
|
|
||||||
filteredItems =
|
|
||||||
menuItems
|
|
||||||
.where(
|
|
||||||
(item) =>
|
|
||||||
item['value'] == '/CreateUserDetails' ||
|
|
||||||
item['value'] == '/logout',
|
|
||||||
)
|
|
||||||
.toList();
|
|
||||||
} else if (role == "Travel Agent") {
|
|
||||||
filteredItems =
|
|
||||||
menuItems
|
|
||||||
.where((item) => item['value'] == '/logout')
|
|
||||||
.toList();
|
|
||||||
} else {
|
|
||||||
filteredItems = menuItems;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a new list starting with role display and divider
|
|
||||||
return [
|
|
||||||
PopupMenuItem<String>(
|
|
||||||
enabled: false, // ❌ Not clickable
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
userData?["role"] ?? '',
|
|
||||||
style: GoogleFonts.poppins(
|
|
||||||
fontSize: 12,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: Colors.black,
|
|
||||||
),
|
),
|
||||||
),
|
// backgroundColor: Colors.redAccent,
|
||||||
const Divider(), // 👈 Divider after role
|
// child: Icon(Icons.error, size: 10),
|
||||||
],
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
...filteredItems
|
)
|
||||||
.map(buildMenuItem)
|
: const CircleAvatar(
|
||||||
.toList(), // 👈 then normal items
|
radius: 20,
|
||||||
];
|
// backgroundColor: Colors.white,
|
||||||
},
|
child: Icon(
|
||||||
|
Icons.add_a_photo,
|
||||||
child: MouseRegion(
|
size: 10,
|
||||||
cursor: SystemMouseCursors.click,
|
color: Colors.grey,
|
||||||
child: Row(
|
),
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
userData?["name"] ?? "N/A",
|
|
||||||
style: GoogleFonts.poppins(
|
|
||||||
fontSize: 14,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
color: Colors.black,
|
|
||||||
),
|
|
||||||
// style: const TextStyle(
|
|
||||||
// fontSize: 14,
|
|
||||||
// fontWeight: FontWeight.w500,
|
|
||||||
// fontFamily: "Roboto",
|
|
||||||
// color: Colors.black,
|
|
||||||
// ),
|
|
||||||
),
|
|
||||||
const Icon(
|
|
||||||
Icons.arrow_drop_down,
|
|
||||||
size: 20,
|
|
||||||
color: Colors.black87,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
SizedBox(width: MediaQuery.of(context).size.width * 0.18),
|
||||||
|
// Spacer(),
|
||||||
|
Container(
|
||||||
|
width: MediaQuery.of(context).size.width * 0.35,
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
if (userData?["role"] == "Org Admin" ||
|
||||||
|
userData?["role"] == "Travel Admin")
|
||||||
|
buildNavItem(
|
||||||
|
"Dashboard",
|
||||||
|
() => handleTabChange(
|
||||||
|
TabSelection.dashboard,
|
||||||
|
'/StatusDashboard',
|
||||||
|
),
|
||||||
|
layoutColor!,
|
||||||
|
isSelected: selectedTab == TabSelection.dashboard,
|
||||||
|
icon: Icons.dashboard,
|
||||||
|
// icon: Icons.insights_outlined,
|
||||||
|
),
|
||||||
|
if (userData?["role"] == "Org Admin" ||
|
||||||
|
userData?["role"] == "Travel Admin")
|
||||||
|
const SizedBox(width: 20),
|
||||||
|
if (userData?["role"] == "Org Admin" ||
|
||||||
|
userData?["role"] == "Travel Admin")
|
||||||
|
buildNavItem(
|
||||||
|
"All Trips",
|
||||||
|
() => handleTabChange(
|
||||||
|
TabSelection.allTrips,
|
||||||
|
'/listAllPlan',
|
||||||
|
),
|
||||||
|
layoutColor!,
|
||||||
|
isSelected: selectedTab == TabSelection.allTrips,
|
||||||
|
icon: Icons.format_list_bulleted_rounded,
|
||||||
|
// icon: Icons.insights_outlined,
|
||||||
|
),
|
||||||
|
if (userDetails["role"] != "Travel Agent")
|
||||||
|
const SizedBox(width: 20),
|
||||||
|
if (userData?["role"] == "Travel Agent")
|
||||||
|
buildNavItem(
|
||||||
|
"Trips",
|
||||||
|
() => handleTabChange(
|
||||||
|
TabSelection.myTrips,
|
||||||
|
'/listTravelAgentPlan',
|
||||||
|
),
|
||||||
|
layoutColor!,
|
||||||
|
// () => context.go('/listTravelAgentPlan'),
|
||||||
|
isSelected: selectedTab == TabSelection.myTrips,
|
||||||
|
icon: Icons.shopping_bag_outlined,
|
||||||
|
// icon: Icons.request_page_outlined,
|
||||||
|
),
|
||||||
|
if (userData?["role"] != "Travel Agent") // for others
|
||||||
|
buildNavItem(
|
||||||
|
"My Trips",
|
||||||
|
() => handleTabChange(
|
||||||
|
TabSelection.myTrips,
|
||||||
|
'/listPlan',
|
||||||
|
),
|
||||||
|
layoutColor!,
|
||||||
|
// () => context.go('/listPlan'),
|
||||||
|
isSelected: selectedTab == TabSelection.myTrips,
|
||||||
|
icon: Icons.shopping_bag_outlined,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 20),
|
||||||
|
if (userData?["role"] != "Travel Agent")
|
||||||
|
buildNavItem(
|
||||||
|
"My Approvals",
|
||||||
|
|
||||||
|
() => handleTabChange(
|
||||||
|
TabSelection.myApprovals,
|
||||||
|
'/ApprovalList',
|
||||||
|
),
|
||||||
|
layoutColor!,
|
||||||
|
// () => context.go('/ApprovalList'),
|
||||||
|
isSelected:
|
||||||
|
selectedTab == TabSelection.myApprovals,
|
||||||
|
icon: Icons.verified_outlined,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Spacer(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
actions: [
|
||||||
bottom: PreferredSize(
|
Padding(
|
||||||
preferredSize: Size.fromHeight(1),
|
padding: EdgeInsets.symmetric(
|
||||||
child: Container(
|
horizontal: MediaQuery.of(context).size.width * 0.05,
|
||||||
height: 1,
|
),
|
||||||
// color: Colors.grey.shade200, // Set the color of the bottom border
|
child: Row(
|
||||||
color: layoutColor, // Set the color of the bottom border
|
children: [
|
||||||
|
// if (userData?["role"] != "User")
|
||||||
|
Builder(
|
||||||
|
builder:
|
||||||
|
(context) => PopupMenuButton<String>(
|
||||||
|
color: Colors.white,
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
offset: const Offset(0, 50), // 👈 shift it 50 pixels down
|
||||||
|
onSelected: (String value) {
|
||||||
|
switch (value) {
|
||||||
|
case '/OrganizationSettings':
|
||||||
|
context.go('/OrganizationSettings');
|
||||||
|
break;
|
||||||
|
// case '/OrganizationSetup':
|
||||||
|
// context.go('/OrganizationSetup');
|
||||||
|
// break;
|
||||||
|
case '/listUser':
|
||||||
|
context.go('/listUser');
|
||||||
|
break;
|
||||||
|
// case '/group':
|
||||||
|
// context.go('/group');
|
||||||
|
// break;
|
||||||
|
// case '/department':
|
||||||
|
// context.go('/department');
|
||||||
|
// break;
|
||||||
|
// case '/PolicyList':
|
||||||
|
// context.go('/PolicyList');
|
||||||
|
// case '/getPerdiem':
|
||||||
|
// context.go('/getPerdiem');
|
||||||
|
// case '/templateList':
|
||||||
|
// context.go('/templateList');
|
||||||
|
// case '/template':
|
||||||
|
// context.go('/template');
|
||||||
|
|
||||||
|
case '/CreateUserDetails':
|
||||||
|
context.go(
|
||||||
|
"/CreateUserDetails",
|
||||||
|
extra: {
|
||||||
|
"selectedUser": profileUserDetails,
|
||||||
|
"isEditProfile": true,
|
||||||
|
"isViewMode": false,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
case '/logout':
|
||||||
|
context.go('/');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// itemBuilder: (BuildContext context) =>
|
||||||
|
// menuItems.map(buildMenuItem).toList(),
|
||||||
|
itemBuilder: (BuildContext context) {
|
||||||
|
// final isUser = userData?["role"] == "User";
|
||||||
|
final role = userData?["role"];
|
||||||
|
List<Map<String, dynamic>> filteredItems;
|
||||||
|
|
||||||
|
if (role == "User") {
|
||||||
|
filteredItems =
|
||||||
|
menuItems
|
||||||
|
.where(
|
||||||
|
(item) =>
|
||||||
|
item['value'] == '/CreateUserDetails' ||
|
||||||
|
item['value'] == '/logout',
|
||||||
|
)
|
||||||
|
.toList();
|
||||||
|
} else if (role == "Travel Agent") {
|
||||||
|
filteredItems =
|
||||||
|
menuItems
|
||||||
|
.where((item) => item['value'] == '/logout')
|
||||||
|
.toList();
|
||||||
|
} else {
|
||||||
|
filteredItems = menuItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new list starting with role display and divider
|
||||||
|
return [
|
||||||
|
PopupMenuItem<String>(
|
||||||
|
enabled: false, // ❌ Not clickable
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
userData?["role"] ?? '',
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Divider(), // 👈 Divider after role
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
...filteredItems
|
||||||
|
.map(buildMenuItem)
|
||||||
|
.toList(), // 👈 then normal items
|
||||||
|
];
|
||||||
|
},
|
||||||
|
|
||||||
|
child: MouseRegion(
|
||||||
|
cursor: SystemMouseCursors.click,
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
userData?["name"] ?? "N/A",
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
// style: const TextStyle(
|
||||||
|
// fontSize: 14,
|
||||||
|
// fontWeight: FontWeight.w500,
|
||||||
|
// fontFamily: "Roboto",
|
||||||
|
// color: Colors.black,
|
||||||
|
// ),
|
||||||
|
),
|
||||||
|
const Icon(
|
||||||
|
Icons.arrow_drop_down,
|
||||||
|
size: 20,
|
||||||
|
color: Colors.black87,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(width: 8),
|
||||||
)
|
],
|
||||||
);
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
bottom: PreferredSize(
|
||||||
|
preferredSize: Size.fromHeight(1),
|
||||||
|
child: Container(
|
||||||
|
height: 1,
|
||||||
|
// color: Colors.grey.shade200, // Set the color of the bottom border
|
||||||
|
color: layoutColor, // Set the color of the bottom border
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -701,4 +702,4 @@ Widget buildNavItem(
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -112,9 +112,9 @@ class OrganizationSettingState extends State<OrganizationSetting> {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
'value': '/forexTexmplate',
|
'value': '/forexTexmplate',
|
||||||
'icon': Icons.attach_money,
|
'icon': Icons.credit_card,
|
||||||
'label': 'Forex Template',
|
'label': 'Forex Documentation',
|
||||||
'description': 'Edit Template',
|
'description': 'Edit Document',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'value': '/templateList',
|
'value': '/templateList',
|
||||||
|
|||||||
@ -102,6 +102,41 @@ class ApiService {
|
|||||||
throw Exception('Failed to load country list');
|
throw Exception('Failed to load country list');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Future<List<dynamic>> fetchAirlineList() async {
|
||||||
|
final String apiUrldata = '$apiUrl/api/getAirlineMaster';
|
||||||
|
final token = await getToken();
|
||||||
|
|
||||||
|
if (token == null) {
|
||||||
|
throw Exception('Token not found. Please log in.');
|
||||||
|
}
|
||||||
|
|
||||||
|
final response = await http.get(
|
||||||
|
Uri.parse(apiUrldata),
|
||||||
|
headers: {
|
||||||
|
'Authorization': 'Bearer $token',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
try {
|
||||||
|
final data = json.decode(response.body);
|
||||||
|
print("Airline - $data");
|
||||||
|
|
||||||
|
if (!data.containsKey('data') || data['data'] is! List) {
|
||||||
|
throw Exception(
|
||||||
|
"Invalid response format: 'data' field is missing or not a List",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return data['data'];
|
||||||
|
} catch (e) {
|
||||||
|
throw Exception('Error parsing response: $e');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw Exception('Failed to load country list');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<List<dynamic>> fetchUsers() async {
|
Future<List<dynamic>> fetchUsers() async {
|
||||||
String? ordId = await getOrgId();
|
String? ordId = await getOrgId();
|
||||||
|
|||||||
@ -42,7 +42,7 @@ class UserActionsMenu extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
child: Tooltip(
|
child: Tooltip(
|
||||||
message: 'View User Details',
|
message: 'View Details',
|
||||||
child: Icon(Icons.remove_red_eye,
|
child: Icon(Icons.remove_red_eye,
|
||||||
color: Color(0xFF475569), size: 18)
|
color: Color(0xFF475569), size: 18)
|
||||||
),
|
),
|
||||||
@ -61,7 +61,7 @@ class UserActionsMenu extends StatelessWidget {
|
|||||||
SizedBox(width: 8),
|
SizedBox(width: 8),
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
child: Tooltip(
|
child: Tooltip(
|
||||||
message: 'Edit User Details',
|
message: 'Edit Details',
|
||||||
child: Image.asset(
|
child: Image.asset(
|
||||||
'assets/images/IconsImg/edit.png',
|
'assets/images/IconsImg/edit.png',
|
||||||
width: 20,
|
width: 20,
|
||||||
|
|||||||
@ -19,7 +19,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
|||||||
version: 1.0.0+1
|
version: 1.0.0+1
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
# sdk: ^3.6.1
|
# sdk: ^3.6.1
|
||||||
sdk: ^3.7.2
|
sdk: ^3.7.2
|
||||||
# Dependencies specify other packages that your package needs in order to work.
|
# Dependencies specify other packages that your package needs in order to work.
|
||||||
# To automatically upgrade your package dependencies to the latest versions
|
# To automatically upgrade your package dependencies to the latest versions
|
||||||
@ -99,6 +99,8 @@ flutter:
|
|||||||
- assets/images/login/VectorG.png
|
- assets/images/login/VectorG.png
|
||||||
- assets/images/login/logoNew.jpg
|
- assets/images/login/logoNew.jpg
|
||||||
- assets/images/login/microsoft.png
|
- assets/images/login/microsoft.png
|
||||||
|
- assets/images/IconsImg/path.png
|
||||||
|
- assets/images/IconsImg/alternate.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
|
||||||
@ -134,4 +136,4 @@ flutter:
|
|||||||
# weight: 700
|
# weight: 700
|
||||||
#
|
#
|
||||||
# For details regarding fonts from package dependencies,
|
# For details regarding fonts from package dependencies,
|
||||||
# see https://flutter.dev/to/font-from-package
|
# see https://flutter.dev/to/font-from-packagej
|
||||||
Loading…
Reference in New Issue
Block a user