july 1 to july 15
This commit is contained in:
parent
3be15a71ef
commit
35229fa755
BIN
assets/images/IconsImg/Domestic.png
Normal file
BIN
assets/images/IconsImg/Domestic.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.0 KiB |
BIN
assets/images/IconsImg/Domestic_new.png
Normal file
BIN
assets/images/IconsImg/Domestic_new.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.1 KiB |
BIN
assets/images/IconsImg/Domestic_old.png
Normal file
BIN
assets/images/IconsImg/Domestic_old.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
BIN
assets/images/IconsImg/International.png
Normal file
BIN
assets/images/IconsImg/International.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.9 KiB |
BIN
assets/images/IconsImg/International_new.png
Normal file
BIN
assets/images/IconsImg/International_new.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.9 KiB |
BIN
assets/images/IconsImg/International_old.png
Normal file
BIN
assets/images/IconsImg/International_old.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
@ -723,12 +723,12 @@ class _ListAllPlansState extends State<ListAllPlans> {
|
|||||||
// ),
|
// ),
|
||||||
SizedBox(height: adjHgt / 4),
|
SizedBox(height: adjHgt / 4),
|
||||||
Text(
|
Text(
|
||||||
" No Trips Found",
|
" No Data Found",
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.bold,
|
||||||
color: Colors.black54,
|
color: Colors.grey,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -1187,11 +1187,156 @@ class _ListAllPlansState extends State<ListAllPlans> {
|
|||||||
),
|
),
|
||||||
Column(
|
Column(
|
||||||
children: [
|
children: [
|
||||||
PlanPopupMenu(
|
// PlanPopupMenu(
|
||||||
plan: plan,
|
// plan: plan,
|
||||||
deletePlan: deletePlan,
|
// deletePlan: deletePlan,
|
||||||
apiService: apiService,
|
// apiService: apiService,
|
||||||
layoutColor: layoutColor,
|
// layoutColor: layoutColor,
|
||||||
|
// ),
|
||||||
|
PopupMenuButton<int>(
|
||||||
|
color: Colors.white,
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
offset: Offset(0, 30),
|
||||||
|
icon: Icon(
|
||||||
|
Icons.more_vert,
|
||||||
|
color: Color(0xFF475569),
|
||||||
|
size: 14,
|
||||||
|
),
|
||||||
|
itemBuilder:
|
||||||
|
(context) => [
|
||||||
|
CustomPopupMenuEntry(
|
||||||
|
child: Container(
|
||||||
|
padding:
|
||||||
|
EdgeInsets.symmetric(
|
||||||
|
horizontal: 8,
|
||||||
|
vertical: 8,
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize:
|
||||||
|
MainAxisSize.min,
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment
|
||||||
|
.center,
|
||||||
|
children: [
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(
|
||||||
|
Icons
|
||||||
|
.remove_red_eye,
|
||||||
|
color: Color(
|
||||||
|
0xFF475569,
|
||||||
|
),
|
||||||
|
size: 18,
|
||||||
|
),
|
||||||
|
tooltip:
|
||||||
|
'View The Trip Details',
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(
|
||||||
|
context,
|
||||||
|
); // Close popup manually
|
||||||
|
ApiService.viewPlan(
|
||||||
|
context,
|
||||||
|
plan.planId,
|
||||||
|
isViewMode:
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
if (plan.statusValue ==
|
||||||
|
"Pending Approval" ||
|
||||||
|
plan.statusValue ==
|
||||||
|
"Partially Approved")
|
||||||
|
IconButton(
|
||||||
|
icon: Image.asset(
|
||||||
|
'assets/images/IconsImg/edit.png',
|
||||||
|
width: 20,
|
||||||
|
height: 15,
|
||||||
|
),
|
||||||
|
tooltip:
|
||||||
|
'Edit The Trip Details',
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(
|
||||||
|
context,
|
||||||
|
);
|
||||||
|
ApiService.viewPlan(
|
||||||
|
context,
|
||||||
|
plan.planId,
|
||||||
|
isViewMode:
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(
|
||||||
|
Icons
|
||||||
|
.cancel_rounded,
|
||||||
|
size: 18,
|
||||||
|
),
|
||||||
|
tooltip:
|
||||||
|
'Cancellation The Trip Details',
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(
|
||||||
|
context,
|
||||||
|
);
|
||||||
|
deletePlan(
|
||||||
|
plan.planId,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(
|
||||||
|
Icons.download,
|
||||||
|
color: Color(
|
||||||
|
0xFF114D8B,
|
||||||
|
),
|
||||||
|
size: 18,
|
||||||
|
),
|
||||||
|
tooltip:
|
||||||
|
'Download The PDF',
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(
|
||||||
|
context,
|
||||||
|
);
|
||||||
|
apiService
|
||||||
|
.getPdfDownload(
|
||||||
|
plan.planId,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(
|
||||||
|
Icons.comment,
|
||||||
|
color: Color(
|
||||||
|
0xFF475569,
|
||||||
|
),
|
||||||
|
size: 11,
|
||||||
|
),
|
||||||
|
tooltip:
|
||||||
|
'Trip Comments',
|
||||||
|
onPressed: () {
|
||||||
|
showDialog(
|
||||||
|
context:
|
||||||
|
context,
|
||||||
|
builder:
|
||||||
|
(
|
||||||
|
context,
|
||||||
|
) => CommentModalList(
|
||||||
|
// planId: plan.planId,
|
||||||
|
planId:
|
||||||
|
plan.planId
|
||||||
|
.toString(),
|
||||||
|
layoutColorForUser:
|
||||||
|
layoutColor!,
|
||||||
|
role:
|
||||||
|
"Admin",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -1311,7 +1456,7 @@ class _ListAllPlansState extends State<ListAllPlans> {
|
|||||||
filteredPlans.isEmpty
|
filteredPlans.isEmpty
|
||||||
? Center(
|
? Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
"No matches found",
|
"No Matches Found",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: Colors.grey,
|
color: Colors.grey,
|
||||||
@ -1326,7 +1471,7 @@ class _ListAllPlansState extends State<ListAllPlans> {
|
|||||||
filteredPlans.isEmpty
|
filteredPlans.isEmpty
|
||||||
? Center(
|
? Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
"No matches found",
|
"No Matches Found",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: Colors.grey,
|
color: Colors.grey,
|
||||||
|
|||||||
@ -858,15 +858,12 @@ class _ApprovalListState extends State<ApprovalList> {
|
|||||||
// fontWeight: FontWeight.bold,
|
// fontWeight: FontWeight.bold,
|
||||||
// color: Colors.redAccent)),
|
// color: Colors.redAccent)),
|
||||||
SizedBox(height: adjHgt / 4),
|
SizedBox(height: adjHgt / 4),
|
||||||
Text(
|
Text("No Data Found",
|
||||||
" No Trips Pending For Your Approvals",
|
|
||||||
|
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
// fontFamily: "Inter",
|
fontWeight: FontWeight.bold,
|
||||||
fontWeight: FontWeight.w500,
|
color: Colors.grey,
|
||||||
color: Colors.black54,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -1688,7 +1685,7 @@ class _ApprovalListState extends State<ApprovalList> {
|
|||||||
filteredPlans.isEmpty
|
filteredPlans.isEmpty
|
||||||
? Center(
|
? Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
"No matches found",
|
"No Matches Found",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: Colors.grey,
|
color: Colors.grey,
|
||||||
@ -1703,7 +1700,7 @@ class _ApprovalListState extends State<ApprovalList> {
|
|||||||
filteredPlans.isEmpty
|
filteredPlans.isEmpty
|
||||||
? Center(
|
? Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
"No matches found",
|
"No Matches Found",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: Colors.grey,
|
color: Colors.grey,
|
||||||
|
|||||||
@ -50,6 +50,7 @@ class CostCenterDataState extends State<CostCenterData> {
|
|||||||
String? userId;
|
String? userId;
|
||||||
int? costcenterDataId;
|
int? costcenterDataId;
|
||||||
late String isActive = "1";
|
late String isActive = "1";
|
||||||
|
bool isDisable = false;
|
||||||
|
|
||||||
List<String> dataHeader = ["name", "description"];
|
List<String> dataHeader = ["name", "description"];
|
||||||
|
|
||||||
@ -163,9 +164,12 @@ class CostCenterDataState extends State<CostCenterData> {
|
|||||||
userId = await getUserId();
|
userId = await getUserId();
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
|
isDisable = true;
|
||||||
// This triggers UI rebuild with error messages
|
// This triggers UI rebuild with error messages
|
||||||
if (validateData()) {
|
if (validateData()) {
|
||||||
postCostCenterData();
|
postCostCenterData();
|
||||||
|
}else{
|
||||||
|
isDisable = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -221,22 +225,38 @@ class CostCenterDataState extends State<CostCenterData> {
|
|||||||
print("Update - Response: ${response.body}");
|
print("Update - Response: ${response.body}");
|
||||||
_clearError();
|
_clearError();
|
||||||
widget.fetchGetCostCenter();
|
widget.fetchGetCostCenter();
|
||||||
Navigator.of(context).pop();
|
if (context.mounted) {
|
||||||
|
Navigator.of(context).pop(); // Close modal only if mounted
|
||||||
|
}
|
||||||
|
setState(() {
|
||||||
|
isDisable = false;
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 201:
|
case 201:
|
||||||
print("Save - Response: ${response.body}");
|
print("Save - Response: ${response.body}");
|
||||||
_clearError();
|
_clearError();
|
||||||
await widget.fetchGetCostCenter();
|
await widget.fetchGetCostCenter();
|
||||||
Navigator.of(context).pop();
|
if (context.mounted) {
|
||||||
|
Navigator.of(context).pop(); // Close modal only if mounted
|
||||||
|
}
|
||||||
|
setState(() {
|
||||||
|
isDisable = false;
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
print("Failed to submit costcenter. Status: ${response.statusCode}");
|
print("Failed to submit costcenter. Status: ${response.statusCode}");
|
||||||
print("Error: ${response.body}");
|
print("Error: ${response.body}");
|
||||||
|
setState(() {
|
||||||
|
isDisable = false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(" Error submitting plan: $e");
|
print(" Error submitting plan: $e");
|
||||||
|
setState(() {
|
||||||
|
isDisable = false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -406,11 +426,27 @@ class CostCenterDataState extends State<CostCenterData> {
|
|||||||
// ),
|
// ),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: isDisable
|
||||||
handleSubmit();
|
? null
|
||||||
|
: () async {
|
||||||
|
setState(() {
|
||||||
|
isDisable = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
await handleSubmit();
|
||||||
// You can get text from commentController.text
|
// You can get text from commentController.text
|
||||||
// Navigator.of(context).pop(); // Close the modal
|
// Navigator.of(context).pop(); // Close the modal
|
||||||
|
|
||||||
|
// Optional: re-enable only on error
|
||||||
|
// setState(() {
|
||||||
|
// isDisable = false;
|
||||||
|
// });
|
||||||
},
|
},
|
||||||
|
// onPressed: () {
|
||||||
|
// handleSubmit();
|
||||||
|
// // You can get text from commentController.text
|
||||||
|
// // Navigator.of(context).pop(); // Close the modal
|
||||||
|
// },
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: widget.layoutColor,
|
backgroundColor: widget.layoutColor,
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
|
|||||||
@ -132,6 +132,7 @@ class CostCenterListState extends State<CostCenterList> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<List<dynamic>> fetchGetCostCenter() async {
|
Future<List<dynamic>> fetchGetCostCenter() async {
|
||||||
|
// return [];
|
||||||
final String apiUrlData = '$apiUrl/api/getCostCenterMaster?for=table_view';
|
final String apiUrlData = '$apiUrl/api/getCostCenterMaster?for=table_view';
|
||||||
|
|
||||||
final String? token = await getToken();
|
final String? token = await getToken();
|
||||||
@ -285,7 +286,7 @@ class CostCenterListState extends State<CostCenterList> {
|
|||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
breadcrumbItems: [
|
breadcrumbItems: [
|
||||||
BreadcrumbItem(
|
BreadcrumbItem(
|
||||||
title: 'Organization Settings',
|
title: 'Org Settings',
|
||||||
tooltip: 'Go To Organization Settings',
|
tooltip: 'Go To Organization Settings',
|
||||||
onTap: (context) {
|
onTap: (context) {
|
||||||
context.go("/OrganizationSettings");
|
context.go("/OrganizationSettings");
|
||||||
@ -455,6 +456,7 @@ class CostCenterListState extends State<CostCenterList> {
|
|||||||
FutureBuilder<List<dynamic>>(
|
FutureBuilder<List<dynamic>>(
|
||||||
future: futureCostCenter,
|
future: futureCostCenter,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
|
final adjHgt = MediaQuery.of(context).size.height;
|
||||||
if (futureCostCenter == null) {
|
if (futureCostCenter == null) {
|
||||||
return CircularProgressIndicator();
|
return CircularProgressIndicator();
|
||||||
}
|
}
|
||||||
@ -480,9 +482,9 @@ class CostCenterListState extends State<CostCenterList> {
|
|||||||
// fontWeight: FontWeight.bold,
|
// fontWeight: FontWeight.bold,
|
||||||
// color: Colors.redAccent),
|
// color: Colors.redAccent),
|
||||||
// ),
|
// ),
|
||||||
const SizedBox(height: 8),
|
SizedBox(height: adjHgt / 4),
|
||||||
Text(
|
Text(
|
||||||
"No CostCenter Available ",
|
"No Data Found ",
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
@ -491,15 +493,15 @@ class CostCenterListState extends State<CostCenterList> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
Text(
|
// Text(
|
||||||
"Please Create CostCenter Details",
|
// "Please Create CostCenter Details",
|
||||||
textAlign: TextAlign.center,
|
// textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
// style: GoogleFonts.poppins(
|
||||||
fontSize: 16,
|
// fontSize: 16,
|
||||||
color: Colors.grey,
|
// color: Colors.grey,
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
const SizedBox(height: 20),
|
// const SizedBox(height: 20),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -906,7 +908,7 @@ class CostCenterListState extends State<CostCenterList> {
|
|||||||
filteredCostCenter.isEmpty
|
filteredCostCenter.isEmpty
|
||||||
? Center(
|
? Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
"No matches found",
|
"No Matches Found",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: Colors.grey,
|
color: Colors.grey,
|
||||||
@ -921,7 +923,7 @@ class CostCenterListState extends State<CostCenterList> {
|
|||||||
filteredCostCenter.isEmpty
|
filteredCostCenter.isEmpty
|
||||||
? Center(
|
? Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
"No matches found",
|
"No Matches Found",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: Colors.grey,
|
color: Colors.grey,
|
||||||
|
|||||||
423
lib/Screens/dashboard/status_dashboard (copy).dart
Normal file
423
lib/Screens/dashboard/status_dashboard (copy).dart
Normal file
@ -0,0 +1,423 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:io';
|
||||||
|
import 'dart:html' as html;
|
||||||
|
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:frontend/routes/custom_router.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
|
import 'package:http/http.dart' as http;
|
||||||
|
import 'package:responsive_builder/responsive_builder.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
|
import '../../config/apiUrl.dart';
|
||||||
|
import '../../routes/custom_appBar.dart';
|
||||||
|
import '../../routes/custom_drawer.dart';
|
||||||
|
import '../../services/apiService.dart';
|
||||||
|
import '../../utils/auth_utils.dart';
|
||||||
|
import '../../utils/pagination.dart';
|
||||||
|
|
||||||
|
class StatusDashboard extends StatefulWidget {
|
||||||
|
const StatusDashboard({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
StatusDashboardState createState() => StatusDashboardState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class StatusDashboardState extends State<StatusDashboard> {
|
||||||
|
Map<String, dynamic>? apiData;
|
||||||
|
String? organizationId;
|
||||||
|
late bool _dialogShown = false;
|
||||||
|
late StreamSubscription<html.PopStateEvent> _popStateListener;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_checkAuthAndLoadData();
|
||||||
|
|
||||||
|
checkbackbutton();
|
||||||
|
|
||||||
|
// loadDashboardData();
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkbackbutton() async {
|
||||||
|
// Push a dummy state so back button triggers popstate instead of navigating
|
||||||
|
html.window.history.pushState(null, 'home', html.window.location.href);
|
||||||
|
|
||||||
|
_popStateListener = html.window.onPopState.listen((event) {
|
||||||
|
if (!_dialogShown && mounted) {
|
||||||
|
_showBackConfirmationDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Re-push to prevent leaving
|
||||||
|
html.window.history.pushState(null, 'home', html.window.location.href);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_popStateListener.cancel(); // ✅ Remove the browser popstate listener
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _showBackConfirmationDialog() {
|
||||||
|
if (!mounted) return;
|
||||||
|
|
||||||
|
_dialogShown = true;
|
||||||
|
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder:
|
||||||
|
(context) => AlertDialog(
|
||||||
|
title: Text("Confirm"),
|
||||||
|
content: Text("Do you want to logout?"),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context); // Close dialog
|
||||||
|
_dialogShown = false;
|
||||||
|
},
|
||||||
|
child: Text("Cancel"),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () async {
|
||||||
|
Navigator.pop(context); // Close dialog
|
||||||
|
_dialogShown = false;
|
||||||
|
await _logoutAndRedirect(context);
|
||||||
|
},
|
||||||
|
child: Text("Logout"),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _logoutAndRedirect(BuildContext context) async {
|
||||||
|
print("logue 0");
|
||||||
|
|
||||||
|
// Example: clear session or shared preferences
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
await prefs.clear();
|
||||||
|
|
||||||
|
context.go("/");
|
||||||
|
|
||||||
|
print("logue 1");
|
||||||
|
}
|
||||||
|
|
||||||
|
void _checkAuthAndLoadData() async {
|
||||||
|
final String? token = await getToken(); // Your async function to get token
|
||||||
|
|
||||||
|
if (token == null || token.isEmpty) {
|
||||||
|
// Token doesn't exist → redirect to login
|
||||||
|
context.go(
|
||||||
|
"/",
|
||||||
|
); // or use: router.go("/") if you're using `GoRouter` directly
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
checkbackbutton();
|
||||||
|
});
|
||||||
|
// If token exists, load the dashboard data
|
||||||
|
loadDashboardData();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> loadDashboardData() async {
|
||||||
|
try {
|
||||||
|
final data = await fetchStatusDashboard();
|
||||||
|
setState(() {
|
||||||
|
apiData = data;
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
print("Error loading dashboard: $e");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<String?> getToken() async {
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
return prefs.getString('auth_token');
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<String?> getOrgId() async {
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
final String? userDataString = prefs.getString('user_data');
|
||||||
|
|
||||||
|
if (userDataString != null) {
|
||||||
|
try {
|
||||||
|
final Map<String, dynamic> userData = jsonDecode(userDataString);
|
||||||
|
return userData["org_id"]?.toString();
|
||||||
|
} catch (e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Map<String, dynamic>> fetchStatusDashboard() async {
|
||||||
|
organizationId = await getOrgId();
|
||||||
|
|
||||||
|
final String apiUrlData =
|
||||||
|
'$apiUrl/api/plans/statusDashboard?org_id=$organizationId';
|
||||||
|
final String? token = await getToken();
|
||||||
|
|
||||||
|
print("Fetch StatusDashboard -- 2KN Here : $token");
|
||||||
|
|
||||||
|
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',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
print("called api : $apiUrlData");
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
final apiData = json.decode(response.body);
|
||||||
|
print("Fetch StatusDashboard -- Reponse Here : $apiData");
|
||||||
|
return apiData; // Returning raw JSON list
|
||||||
|
} else {
|
||||||
|
throw Exception('Failed to load users');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Color getStatusColor(String status) {
|
||||||
|
if (status == "Domestic") return Colors.white;
|
||||||
|
if (status == "International") return Colors.white;
|
||||||
|
if (status == "Partially Approved") return Colors.yellow.shade100;
|
||||||
|
if (status == "Pending Approval") return Colors.greenAccent.shade100;
|
||||||
|
if (status == "Approved") return Colors.green.shade100;
|
||||||
|
if (status == "Completed") return Colors.green.shade500;
|
||||||
|
if (status == "Rejected") return Colors.red.shade100;
|
||||||
|
if (status == "Cancelled") return Colors.red.shade200;
|
||||||
|
return Colors.grey.shade100;
|
||||||
|
}
|
||||||
|
|
||||||
|
IconData getStatusIcon(String title) {
|
||||||
|
switch (title) {
|
||||||
|
case "Domestic":
|
||||||
|
return Icons.directions_bus_filled_outlined;
|
||||||
|
case "International":
|
||||||
|
return Icons.airplanemode_active;
|
||||||
|
case "Partially Approved":
|
||||||
|
return Icons.pending;
|
||||||
|
case "Approved":
|
||||||
|
return Icons.check_circle_outline;
|
||||||
|
case "Completed":
|
||||||
|
return Icons.done_all;
|
||||||
|
case "Rejected":
|
||||||
|
return Icons.cancel_outlined;
|
||||||
|
case "Cancelled":
|
||||||
|
return Icons.cancel_schedule_send_outlined;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return Icons.info_outline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final typeBasedCount = List<Map<String, dynamic>>.from(
|
||||||
|
(apiData?['data']?['typeBasedCount']) ?? [],
|
||||||
|
);
|
||||||
|
|
||||||
|
print("apiData - => $apiData");
|
||||||
|
print("typeBasedCount => $typeBasedCount");
|
||||||
|
|
||||||
|
final statusBasedCount = List<Map<String, dynamic>>.from(
|
||||||
|
(apiData?['data']?['statusBasedCount']) ?? [],
|
||||||
|
);
|
||||||
|
print("statusBasedCount - => $statusBasedCount");
|
||||||
|
// 👇 Local function to create the card widget
|
||||||
|
Widget buildInfoCard(String title, int count, double width) {
|
||||||
|
print('title $title');
|
||||||
|
final color = getStatusColor(title);
|
||||||
|
final icon = getStatusIcon(title);
|
||||||
|
return Card(
|
||||||
|
elevation: 3,
|
||||||
|
color: color,
|
||||||
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
|
||||||
|
child: Container(
|
||||||
|
width: width,
|
||||||
|
padding: const EdgeInsets.all(12),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
icon,
|
||||||
|
size: 32,
|
||||||
|
color:
|
||||||
|
(title == 'Domestic' || title == 'International')
|
||||||
|
? Colors.green
|
||||||
|
: Colors.black54,
|
||||||
|
), // 👈 Add Icon here
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
Text(
|
||||||
|
title,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
fontSize:
|
||||||
|
(title == 'Domestic' || title == 'International')
|
||||||
|
? 16
|
||||||
|
: 14,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
Text(
|
||||||
|
count.toString(),
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 22,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
// color: Colors.blue,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _handleBackButton() {
|
||||||
|
final location = GoRouterState.of(context).uri.toString();
|
||||||
|
|
||||||
|
print("location - $location");
|
||||||
|
if (location.contains('/StatusDashboard')) {
|
||||||
|
// Do nothing or show "Press again to exit" toast
|
||||||
|
print("Blocked back on dashboard");
|
||||||
|
} else {
|
||||||
|
print("dashboard ..");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResponsiveBuilder(
|
||||||
|
builder: (context, sizingInfo) {
|
||||||
|
bool isDesktop =
|
||||||
|
sizingInfo.deviceScreenType == DeviceScreenType.desktop;
|
||||||
|
|
||||||
|
return PopScope(
|
||||||
|
canPop: false, // Allow back navigation only if not login screen
|
||||||
|
onPopInvokedWithResult: (didPop, result) {
|
||||||
|
if (didPop) return;
|
||||||
|
_handleBackButton(); // Show exit confirmation dialog
|
||||||
|
},
|
||||||
|
child: Scaffold(
|
||||||
|
backgroundColor: const Color(0xFFf5f5f5),
|
||||||
|
appBar: CustomAppBar(isDesktop: isDesktop),
|
||||||
|
drawer: CustomDrawer(isDesktop: false),
|
||||||
|
body: Padding(
|
||||||
|
padding:
|
||||||
|
isDesktop
|
||||||
|
? EdgeInsets.symmetric(
|
||||||
|
horizontal:
|
||||||
|
MediaQuery.of(context).size.width *
|
||||||
|
0.1, // 30% of screen width as horizontal padding
|
||||||
|
vertical: 10, // 5% of screen height as vertical padding
|
||||||
|
)
|
||||||
|
: EdgeInsets.all(0),
|
||||||
|
child: LayoutBuilder(
|
||||||
|
builder: (context, constraints) {
|
||||||
|
return SingleChildScrollView(
|
||||||
|
child: ConstrainedBox(
|
||||||
|
constraints: BoxConstraints(
|
||||||
|
minHeight: constraints.maxHeight,
|
||||||
|
),
|
||||||
|
child: IntrinsicHeight(
|
||||||
|
// Only needed if child layout depends on height
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color:
|
||||||
|
isDesktop
|
||||||
|
? Colors.white
|
||||||
|
: const Color(0xFFFCFCFC),
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(30.0),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment:
|
||||||
|
CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Wrap(
|
||||||
|
spacing: 10,
|
||||||
|
runSpacing: 10,
|
||||||
|
children:
|
||||||
|
typeBasedCount.map((item) {
|
||||||
|
double cardWidth =
|
||||||
|
isDesktop
|
||||||
|
? (MediaQuery.of(
|
||||||
|
context,
|
||||||
|
).size.width *
|
||||||
|
0.75 -
|
||||||
|
10) /
|
||||||
|
2 // 80% width padding adjusted
|
||||||
|
: MediaQuery.of(
|
||||||
|
context,
|
||||||
|
).size.width -
|
||||||
|
24; // full width with padding
|
||||||
|
|
||||||
|
return SizedBox(
|
||||||
|
width: cardWidth,
|
||||||
|
child: buildInfoCard(
|
||||||
|
item['value'],
|
||||||
|
item['count'],
|
||||||
|
cardWidth,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
Wrap(
|
||||||
|
spacing: 10,
|
||||||
|
runSpacing: 10,
|
||||||
|
children:
|
||||||
|
statusBasedCount.map((item) {
|
||||||
|
double cardWidth =
|
||||||
|
isDesktop
|
||||||
|
? (MediaQuery.of(
|
||||||
|
context,
|
||||||
|
).size.width *
|
||||||
|
0.90 -
|
||||||
|
50) /
|
||||||
|
6 // desktop layout: 6 cards per row
|
||||||
|
: MediaQuery.of(
|
||||||
|
context,
|
||||||
|
).size.width -
|
||||||
|
24; // mobile: full width
|
||||||
|
|
||||||
|
return SizedBox(
|
||||||
|
width: cardWidth,
|
||||||
|
child: buildInfoCard(
|
||||||
|
item['value'],
|
||||||
|
item['count'],
|
||||||
|
cardWidth,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -31,6 +31,34 @@ class StatusDashboardState extends State<StatusDashboard> {
|
|||||||
String? organizationId;
|
String? organizationId;
|
||||||
late bool _dialogShown = false;
|
late bool _dialogShown = false;
|
||||||
late StreamSubscription<html.PopStateEvent> _popStateListener;
|
late StreamSubscription<html.PopStateEvent> _popStateListener;
|
||||||
|
String selectedView = 'Today';
|
||||||
|
String AccessKeyFlag = "Both";
|
||||||
|
Map<String, dynamic>? currentData;
|
||||||
|
List typeData = [];
|
||||||
|
List statusData = [];
|
||||||
|
List<int> flightData = [];
|
||||||
|
List<int> accommodationData = [];
|
||||||
|
List<int> forexData = [];
|
||||||
|
|
||||||
|
final categoryIcons = {
|
||||||
|
"flight": Icons.flight,
|
||||||
|
"accommodation": Icons.hotel_outlined,
|
||||||
|
"forex": Icons.attach_money,
|
||||||
|
};
|
||||||
|
|
||||||
|
List<String> statusLabels = [
|
||||||
|
"Pending Approval",
|
||||||
|
"Partially Approved",
|
||||||
|
"Approved",
|
||||||
|
"Rejected",
|
||||||
|
"Cancelled"
|
||||||
|
];
|
||||||
|
|
||||||
|
// Extract counts for "Both" section
|
||||||
|
List<int> getStatusValues(Map<String, dynamic> serviceData) {
|
||||||
|
final both = serviceData['Both'] ?? {};
|
||||||
|
return statusLabels.map((label) => (both[label] ?? 0) as int).toList();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@ -231,7 +259,82 @@ class StatusDashboardState extends State<StatusDashboard> {
|
|||||||
final statusBasedCount = List<Map<String, dynamic>>.from(
|
final statusBasedCount = List<Map<String, dynamic>>.from(
|
||||||
(apiData?['data']?['statusBasedCount']) ?? [],
|
(apiData?['data']?['statusBasedCount']) ?? [],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
final statusBasedTodayCount = List<Map<String, dynamic>>.from(
|
||||||
|
(apiData?['data']?['statusBasedTodayCount']) ?? [],
|
||||||
|
);
|
||||||
|
|
||||||
|
final statusBasedWeeklyCount = List<Map<String, dynamic>>.from(
|
||||||
|
(apiData?['data']?['statusBasedWeeklyCount']) ?? [],
|
||||||
|
);
|
||||||
|
|
||||||
|
final typeBasedTodayCount = List<Map<String, dynamic>>.from(
|
||||||
|
(apiData?['data']?['typeBasedTodayCount']) ?? [],
|
||||||
|
);
|
||||||
|
|
||||||
|
final typeBasedWeeklyCount = List<Map<String, dynamic>>.from(
|
||||||
|
(apiData?['data']?['typeBasedWeeklyCount']) ?? [],
|
||||||
|
);
|
||||||
|
|
||||||
|
final typeTodayBasedCount = List<Map<String, dynamic>>.from(
|
||||||
|
(apiData?['data']?['typeTodayBasedCount']) ?? [],
|
||||||
|
);
|
||||||
|
|
||||||
|
final typeWeeklyBasedCount = List<Map<String, dynamic>>.from(
|
||||||
|
(apiData?['data']?['typeWeeklyBasedCount']) ?? [],
|
||||||
|
);
|
||||||
|
|
||||||
|
final statusTodayBasedCount = List<Map<String, dynamic>>.from(
|
||||||
|
(apiData?['data']?['statusTodayBasedCount']) ?? [],
|
||||||
|
);
|
||||||
|
|
||||||
|
final statusWeeklyBasedCount = List<Map<String, dynamic>>.from(
|
||||||
|
(apiData?['data']?['statusWeeklyBasedCount']) ?? [],
|
||||||
|
);
|
||||||
|
|
||||||
|
final List todayList = List<Map<String, dynamic>>.from(
|
||||||
|
apiData?['data']?['todayTripCounts'] ?? [],
|
||||||
|
);
|
||||||
|
|
||||||
|
final List weekList = List<Map<String, dynamic>>.from(
|
||||||
|
apiData?['data']?['weekTripCounts'] ?? [],
|
||||||
|
);
|
||||||
|
|
||||||
|
// Merge all maps in the list into one map
|
||||||
|
Map<String, dynamic> todayBasedCount = {};
|
||||||
|
Map<String, dynamic> weekBasedCount = {};
|
||||||
|
|
||||||
|
for (final item in todayList) {
|
||||||
|
todayBasedCount.addAll(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (final item in weekList) {
|
||||||
|
weekBasedCount.addAll(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
// currentData = selectedView == "Today" ? todayBasedCount : weekBasedCount;
|
||||||
|
typeData = selectedView == "Today"
|
||||||
|
? typeBasedTodayCount
|
||||||
|
: typeBasedWeeklyCount ;
|
||||||
|
statusData = selectedView == "Today"
|
||||||
|
? statusBasedTodayCount
|
||||||
|
: statusBasedWeeklyCount ;
|
||||||
|
|
||||||
|
flightData = selectedView == "Today"
|
||||||
|
? getStatusValues(todayBasedCount['flight'] ?? {})
|
||||||
|
: getStatusValues(weekBasedCount['flight'] ?? {});
|
||||||
|
accommodationData = selectedView == "Today"
|
||||||
|
? getStatusValues(todayBasedCount['acomodation'] ?? {})
|
||||||
|
: getStatusValues(weekBasedCount['acomodation'] ?? {});
|
||||||
|
forexData = selectedView == "Today"
|
||||||
|
? getStatusValues(todayBasedCount['forex'] ?? {})
|
||||||
|
: getStatusValues(weekBasedCount['forex'] ?? {});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
print("statusBasedCount - => $statusBasedCount");
|
print("statusBasedCount - => $statusBasedCount");
|
||||||
|
print("Current Data - => $currentData");
|
||||||
// 👇 Local function to create the card widget
|
// 👇 Local function to create the card widget
|
||||||
Widget buildInfoCard(String title, int count, double width) {
|
Widget buildInfoCard(String title, int count, double width) {
|
||||||
print('title $title');
|
print('title $title');
|
||||||
@ -265,6 +368,7 @@ class StatusDashboardState extends State<StatusDashboard> {
|
|||||||
(title == 'Domestic' || title == 'International')
|
(title == 'Domestic' || title == 'International')
|
||||||
? 16
|
? 16
|
||||||
: 14,
|
: 14,
|
||||||
|
color: Colors.black87,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
@ -293,6 +397,317 @@ class StatusDashboardState extends State<StatusDashboard> {
|
|||||||
print("dashboard ..");
|
print("dashboard ..");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
String capitalize(String s) => s[0].toUpperCase() + s.substring(1);
|
||||||
|
|
||||||
|
Widget toggleChip(String label) {
|
||||||
|
bool isSelected = selectedView == label;
|
||||||
|
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
setState(() {
|
||||||
|
selectedView = label;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: isSelected ? const Color(0xFF003A78) : Colors.transparent,
|
||||||
|
borderRadius: BorderRadius.circular(20),
|
||||||
|
),
|
||||||
|
alignment: Alignment.center,
|
||||||
|
height: 36,
|
||||||
|
child: Text(
|
||||||
|
label,
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 10,
|
||||||
|
color: isSelected ? Colors.white : Colors.black,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget buildTopCard({
|
||||||
|
// required IconData icon,
|
||||||
|
required Color color,
|
||||||
|
required String label,
|
||||||
|
required int count,
|
||||||
|
required Color bgColor,
|
||||||
|
}) {
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.all(1),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(1),
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Tooltip(
|
||||||
|
message: label ,
|
||||||
|
child: Image.asset(
|
||||||
|
label == 'Domestic'
|
||||||
|
? 'assets/images/IconsImg/Domestic_new.png'
|
||||||
|
: 'assets/images/IconsImg/International_new.png',
|
||||||
|
// width: 65,
|
||||||
|
// height: label == 'Domestic' ? 37 : 40,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// Icon(icon, color: color, size: 40),
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
Text(
|
||||||
|
count.toString(),
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 28,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 5),
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: bgColor,
|
||||||
|
borderRadius: BorderRadius.circular(20),
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
label,
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 10,
|
||||||
|
color: color,
|
||||||
|
// color: const Color(0xFFEAF3FB),
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget statusCard(String label, int count) {
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 15),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: const Color(0xFFEAF3FB),
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
count.toString(),
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 18,
|
||||||
|
color: Colors.black87,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 5),
|
||||||
|
Text(
|
||||||
|
label,
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 12,
|
||||||
|
color: Colors.black87,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget buildCategoryCard(String title, IconData icon, List<String> statusLabels,List<int> values) {
|
||||||
|
|
||||||
|
final statusIcons = [
|
||||||
|
Icons.calendar_today,
|
||||||
|
Icons.assignment,
|
||||||
|
Icons.verified,
|
||||||
|
Icons.block,
|
||||||
|
Icons.cancel,
|
||||||
|
];
|
||||||
|
|
||||||
|
final statusColors = [
|
||||||
|
Color(0xFFFBFFCA),
|
||||||
|
Color(0xFFFFF1CD),// Colors.yellow.shade100, // Color(0xFFCAE77B),
|
||||||
|
Color(0xFFDAFFE8),// Colors.green.shade100, // Color(0xFF72D480),
|
||||||
|
Color(0xFFFFD6D3),// Colors.red.shade100, // Color(0xFFF88C8C),
|
||||||
|
Color(0xFFFFA8A8), // Colors.red.shade200, // Color(0xFFE94B4B),
|
||||||
|
];
|
||||||
|
|
||||||
|
final statusIconColors = [
|
||||||
|
Color(0xFFB1BC1A),
|
||||||
|
Color(0xFFCC9300),
|
||||||
|
Color(0xFF509269),
|
||||||
|
Color(0xFFD25E55),
|
||||||
|
Color(0xFFAE0303),
|
||||||
|
];
|
||||||
|
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
// decoration: BoxDecoration(
|
||||||
|
// color: Colors.white,
|
||||||
|
// borderRadius: BorderRadius.circular(12),
|
||||||
|
// ),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.blueGrey,
|
||||||
|
blurRadius: 5,
|
||||||
|
offset: Offset(0, 2),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.all(8),
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
// color: Colors.blue,
|
||||||
|
color: Color(0xFF004A8E),
|
||||||
|
shape: BoxShape.circle,
|
||||||
|
),
|
||||||
|
child: Icon(
|
||||||
|
icon,
|
||||||
|
color: Colors.white,
|
||||||
|
size: 20,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 10),
|
||||||
|
Text(title, style: GoogleFonts.poppins(
|
||||||
|
color: Colors.black87,
|
||||||
|
fontWeight: FontWeight.bold
|
||||||
|
),),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
...List.generate(values.length, (index) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
// Icon(statusIcons[index], size: 15, color: statusIconColors[index]),
|
||||||
|
Container(
|
||||||
|
width: 28,
|
||||||
|
height: 28,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: statusColors[index], // background color
|
||||||
|
borderRadius: BorderRadius.circular(4), // square with slight rounding
|
||||||
|
),
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: Icon(
|
||||||
|
statusIcons[index],
|
||||||
|
size: 15,
|
||||||
|
color: statusIconColors[index], // icon color
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 6),
|
||||||
|
Text(statusLabels[index], style: GoogleFonts.poppins(
|
||||||
|
color: Colors.black87,
|
||||||
|
),),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Text(values[index].toString(), style: GoogleFonts.poppins(
|
||||||
|
fontSize: 10,
|
||||||
|
color: Colors.black87,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Widget buildCategoryCard(String title, IconData icon,statusLabels,statusvalue) {
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// return Container(
|
||||||
|
// padding: const EdgeInsets.all(16),
|
||||||
|
// // decoration: BoxDecoration(
|
||||||
|
// // color: Colors.white,
|
||||||
|
// // borderRadius: BorderRadius.circular(12),
|
||||||
|
// // ),
|
||||||
|
//
|
||||||
|
// child: Column(
|
||||||
|
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
// children: [
|
||||||
|
// Row(
|
||||||
|
// children: [
|
||||||
|
// Container(
|
||||||
|
// padding: const EdgeInsets.all(8),
|
||||||
|
// decoration: const BoxDecoration(
|
||||||
|
// color: Colors.blue,
|
||||||
|
// shape: BoxShape.circle,
|
||||||
|
// ),
|
||||||
|
// child: Icon(
|
||||||
|
// icon,
|
||||||
|
// color: Colors.white,
|
||||||
|
// size: 20,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// const SizedBox(width: 10),
|
||||||
|
// Text(title, style: GoogleFonts.poppins(
|
||||||
|
// color: Colors.black87,
|
||||||
|
// fontWeight: FontWeight.bold
|
||||||
|
// ),),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
// const SizedBox(height: 12),
|
||||||
|
// ...List.generate(statusvalue.length, (index) {
|
||||||
|
// return Padding(
|
||||||
|
// padding: const EdgeInsets.symmetric(vertical: 10),
|
||||||
|
// child: Row(
|
||||||
|
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
// children: [
|
||||||
|
// Row(
|
||||||
|
// children: [
|
||||||
|
// // Icon(statusIcons[index], size: 20, color: statusColors[index]),
|
||||||
|
// Container(
|
||||||
|
// padding: const EdgeInsets.all(8),
|
||||||
|
// decoration: BoxDecoration(
|
||||||
|
// color: statusColors[index], // Background color behind the icon
|
||||||
|
// borderRadius: BorderRadius.circular(10), // Rounded square
|
||||||
|
// boxShadow: [
|
||||||
|
// BoxShadow(
|
||||||
|
// color: Colors.grey, // Shadow color
|
||||||
|
// spreadRadius: 1,
|
||||||
|
// blurRadius: 5,
|
||||||
|
// offset: const Offset(0, 2), // Shadow position
|
||||||
|
// ),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
// child: Icon(
|
||||||
|
// statusIcons[index],
|
||||||
|
// color: statusIconColors[index],
|
||||||
|
// size: 20,
|
||||||
|
// // color: statusColors[index],
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// const SizedBox(width: 6),
|
||||||
|
// Text(statusLabels[index]),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
//
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
// );
|
||||||
|
// }),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
return ResponsiveBuilder(
|
return ResponsiveBuilder(
|
||||||
builder: (context, sizingInfo) {
|
builder: (context, sizingInfo) {
|
||||||
@ -322,85 +737,116 @@ class StatusDashboardState extends State<StatusDashboard> {
|
|||||||
child: LayoutBuilder(
|
child: LayoutBuilder(
|
||||||
builder: (context, constraints) {
|
builder: (context, constraints) {
|
||||||
return SingleChildScrollView(
|
return SingleChildScrollView(
|
||||||
child: ConstrainedBox(
|
// child: ConstrainedBox(
|
||||||
constraints: BoxConstraints(
|
// constraints: BoxConstraints(
|
||||||
minHeight: constraints.maxHeight,
|
// minHeight: constraints.maxHeight,
|
||||||
),
|
// ),
|
||||||
child: IntrinsicHeight(
|
// ),
|
||||||
// Only needed if child layout depends on height
|
child: Column(
|
||||||
child: Container(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
// First Row: Toggle Buttons Row
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
height: 36,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color:
|
color: const Color(0xFFEAEAEA),
|
||||||
isDesktop
|
borderRadius: BorderRadius.circular(20),
|
||||||
? Colors.white
|
|
||||||
: const Color(0xFFFCFCFC),
|
|
||||||
borderRadius: BorderRadius.circular(12),
|
|
||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
toggleChip("Today"),
|
||||||
child: Padding(
|
toggleChip("This Week"),
|
||||||
padding: const EdgeInsets.all(30.0),
|
],
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment:
|
|
||||||
CrossAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
Wrap(
|
|
||||||
spacing: 10,
|
|
||||||
runSpacing: 10,
|
|
||||||
children:
|
|
||||||
typeBasedCount.map((item) {
|
|
||||||
double cardWidth =
|
|
||||||
isDesktop
|
|
||||||
? (MediaQuery.of(
|
|
||||||
context,
|
|
||||||
).size.width *
|
|
||||||
0.75 -
|
|
||||||
10) /
|
|
||||||
2 // 80% width padding adjusted
|
|
||||||
: MediaQuery.of(
|
|
||||||
context,
|
|
||||||
).size.width -
|
|
||||||
24; // full width with padding
|
|
||||||
|
|
||||||
return SizedBox(
|
|
||||||
width: cardWidth,
|
|
||||||
child: buildInfoCard(
|
|
||||||
item['value'],
|
|
||||||
item['count'],
|
|
||||||
cardWidth,
|
|
||||||
),
|
),
|
||||||
);
|
),
|
||||||
}).toList(),
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
Wrap(
|
|
||||||
spacing: 10,
|
|
||||||
runSpacing: 10,
|
|
||||||
children:
|
|
||||||
statusBasedCount.map((item) {
|
|
||||||
double cardWidth =
|
|
||||||
isDesktop
|
|
||||||
? (MediaQuery.of(
|
|
||||||
context,
|
|
||||||
).size.width *
|
|
||||||
0.90 -
|
|
||||||
50) /
|
|
||||||
6 // desktop layout: 6 cards per row
|
|
||||||
: MediaQuery.of(
|
|
||||||
context,
|
|
||||||
).size.width -
|
|
||||||
24; // mobile: full width
|
|
||||||
|
|
||||||
return SizedBox(
|
// Second Row: Domestic & International and Status
|
||||||
width: cardWidth,
|
Row(
|
||||||
child: buildInfoCard(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
item['value'],
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
item['count'],
|
children: [
|
||||||
cardWidth,
|
// LEFT SIDE
|
||||||
|
Expanded(
|
||||||
|
flex: 2,
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.blueGrey,
|
||||||
|
blurRadius: 5,
|
||||||
|
offset: Offset(0, 2),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
padding: const EdgeInsets.all(15),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
...typeData.map((item) {
|
||||||
|
return Expanded(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
buildTopCard(
|
||||||
|
// icon: item['value'] == "Domestic"
|
||||||
|
// ? Icons.home
|
||||||
|
// : Icons.travel_explore,
|
||||||
|
color: item['value'] == "Domestic"
|
||||||
|
? Color(0xFF0DB04B)
|
||||||
|
: Color(0xFF004A8E),
|
||||||
|
label: item['value'],
|
||||||
|
count: item['count'],
|
||||||
|
bgColor: item['value'] == "Domestic"
|
||||||
|
? const Color(0xFFD6FBE4)
|
||||||
|
: const Color(0xFFD9E8FF),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}).toList(),
|
}).toList(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 20),
|
||||||
|
// RIGHT SIDE
|
||||||
|
Expanded(
|
||||||
|
flex: 3,
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.blueGrey,
|
||||||
|
blurRadius: 5,
|
||||||
|
offset: Offset(0, 2),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
padding: const EdgeInsets.all(15),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text("Status",
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 19,
|
||||||
|
color: Colors.black87,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 23),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
|
children: [
|
||||||
|
...statusData.map((item) => statusCard(item['value'], item['count'])).toList(),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -408,8 +854,20 @@ class StatusDashboardState extends State<StatusDashboard> {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
|
||||||
|
// Third Row: Flight, Accommodation, Forex
|
||||||
|
Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Expanded(child: buildCategoryCard("Flight", Icons.flight,statusLabels,flightData)),
|
||||||
|
const SizedBox(width: 10),
|
||||||
|
Expanded(child: buildCategoryCard("Accomodation", Icons.hotel_outlined,statusLabels,accommodationData)),
|
||||||
|
const SizedBox(width: 10),
|
||||||
|
Expanded(child: buildCategoryCard("Forex", Icons.attach_money,statusLabels,forexData)),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@ -50,6 +50,7 @@ class DepartmentDataState extends State<DepartmentData> {
|
|||||||
String? userId;
|
String? userId;
|
||||||
int? departmentDataId;
|
int? departmentDataId;
|
||||||
late String isActive = "1";
|
late String isActive = "1";
|
||||||
|
bool isDisable = false;
|
||||||
|
|
||||||
List<String> dataHeader = ["dropdown_value", "description"];
|
List<String> dataHeader = ["dropdown_value", "description"];
|
||||||
|
|
||||||
@ -163,9 +164,12 @@ class DepartmentDataState extends State<DepartmentData> {
|
|||||||
userId = await getUserId();
|
userId = await getUserId();
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
|
isDisable = true;
|
||||||
// This triggers UI rebuild with error messages
|
// This triggers UI rebuild with error messages
|
||||||
if (validateData()) {
|
if (validateData()) {
|
||||||
postDepartmentData();
|
postDepartmentData();
|
||||||
|
}else{
|
||||||
|
isDisable = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -222,11 +226,20 @@ class DepartmentDataState extends State<DepartmentData> {
|
|||||||
_clearError();
|
_clearError();
|
||||||
widget.fetchGetDepartment();
|
widget.fetchGetDepartment();
|
||||||
// dispose();
|
// dispose();
|
||||||
Navigator.of(context).pop();
|
if (context.mounted) {
|
||||||
|
Navigator.of(context).pop(); // Close modal only if mounted
|
||||||
|
}
|
||||||
|
setState(() {
|
||||||
|
isDisable = false;
|
||||||
|
});
|
||||||
} else if (response.statusCode == 404) {
|
} else if (response.statusCode == 404) {
|
||||||
|
if (context.mounted) {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
|
}
|
||||||
final message = jsonDecode(response.body)['message'] ?? 'Unknown error';
|
final message = jsonDecode(response.body)['message'] ?? 'Unknown error';
|
||||||
|
setState(() {
|
||||||
|
isDisable = false;
|
||||||
|
});
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(
|
SnackBar(
|
||||||
content: Text(message),
|
content: Text(message),
|
||||||
@ -237,9 +250,15 @@ class DepartmentDataState extends State<DepartmentData> {
|
|||||||
} else {
|
} else {
|
||||||
print("Failed to submit. Status: ${response.statusCode}");
|
print("Failed to submit. Status: ${response.statusCode}");
|
||||||
print("Error: ${response.body}");
|
print("Error: ${response.body}");
|
||||||
|
setState(() {
|
||||||
|
isDisable = false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(" Error submitting plan: $e");
|
print(" Error submitting plan: $e");
|
||||||
|
setState(() {
|
||||||
|
isDisable = false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -409,10 +428,21 @@ class DepartmentDataState extends State<DepartmentData> {
|
|||||||
// ),
|
// ),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: isDisable
|
||||||
handleSubmit();
|
? null
|
||||||
|
: () async {
|
||||||
|
setState(() {
|
||||||
|
isDisable = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
await handleSubmit();
|
||||||
// You can get text from commentController.text
|
// You can get text from commentController.text
|
||||||
// Navigator.of(context).pop(); // Close the modal
|
// Navigator.of(context).pop(); // Close the modal
|
||||||
|
|
||||||
|
// Optional: re-enable only on error
|
||||||
|
// setState(() {
|
||||||
|
// isDisable = false;
|
||||||
|
// });
|
||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: widget.layoutColor,
|
backgroundColor: widget.layoutColor,
|
||||||
|
|||||||
@ -132,6 +132,7 @@ class DepartmentListState extends State<DepartmentList> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<List<dynamic>> fetchGetDepartment() async {
|
Future<List<dynamic>> fetchGetDepartment() async {
|
||||||
|
// return [];
|
||||||
final String apiUrlData = '$apiUrl/api/getDepartmentList?for=table_view';
|
final String apiUrlData = '$apiUrl/api/getDepartmentList?for=table_view';
|
||||||
|
|
||||||
final String? token = await getToken();
|
final String? token = await getToken();
|
||||||
@ -284,7 +285,7 @@ class DepartmentListState extends State<DepartmentList> {
|
|||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
breadcrumbItems: [
|
breadcrumbItems: [
|
||||||
BreadcrumbItem(
|
BreadcrumbItem(
|
||||||
title: 'Organization Settings',
|
title: 'Org Settings',
|
||||||
tooltip: 'Go To Organization Settings',
|
tooltip: 'Go To Organization Settings',
|
||||||
onTap: (context) {
|
onTap: (context) {
|
||||||
context.go("/OrganizationSettings");
|
context.go("/OrganizationSettings");
|
||||||
@ -454,6 +455,7 @@ class DepartmentListState extends State<DepartmentList> {
|
|||||||
FutureBuilder<List<dynamic>>(
|
FutureBuilder<List<dynamic>>(
|
||||||
future: futureDepartment,
|
future: futureDepartment,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
|
final adjHgt = MediaQuery.of(context).size.height;
|
||||||
if (futureDepartment == null) {
|
if (futureDepartment == null) {
|
||||||
CircularProgressIndicator();
|
CircularProgressIndicator();
|
||||||
}
|
}
|
||||||
@ -479,9 +481,9 @@ class DepartmentListState extends State<DepartmentList> {
|
|||||||
// fontWeight: FontWeight.bold,
|
// fontWeight: FontWeight.bold,
|
||||||
// color: Colors.redAccent),
|
// color: Colors.redAccent),
|
||||||
// ),
|
// ),
|
||||||
const SizedBox(height: 8),
|
SizedBox(height: adjHgt / 4),
|
||||||
Text(
|
Text(
|
||||||
"No Department Available ",
|
"No Data Found ",
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
@ -490,15 +492,15 @@ class DepartmentListState extends State<DepartmentList> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
Text(
|
// Text(
|
||||||
"Please Create Department Details",
|
// "Please Create Department Details",
|
||||||
textAlign: TextAlign.center,
|
// textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
// style: GoogleFonts.poppins(
|
||||||
fontSize: 16,
|
// fontSize: 16,
|
||||||
color: Colors.grey,
|
// color: Colors.grey,
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
const SizedBox(height: 20),
|
// const SizedBox(height: 20),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -905,7 +907,7 @@ class DepartmentListState extends State<DepartmentList> {
|
|||||||
filteredDepartment.isEmpty
|
filteredDepartment.isEmpty
|
||||||
? Center(
|
? Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
"No matches found",
|
"No Matches Found",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: Colors.grey,
|
color: Colors.grey,
|
||||||
@ -920,7 +922,7 @@ class DepartmentListState extends State<DepartmentList> {
|
|||||||
filteredDepartment.isEmpty
|
filteredDepartment.isEmpty
|
||||||
? Center(
|
? Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
"No matches found",
|
"No Matches Found",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: Colors.grey,
|
color: Colors.grey,
|
||||||
|
|||||||
@ -66,6 +66,7 @@ class GroupDataState extends State<GroupData> {
|
|||||||
int? groupDataId;
|
int? groupDataId;
|
||||||
|
|
||||||
late String isActive = "1";
|
late String isActive = "1";
|
||||||
|
bool isDisable = false;
|
||||||
|
|
||||||
List<String> dataHeader = [
|
List<String> dataHeader = [
|
||||||
"name",
|
"name",
|
||||||
@ -227,9 +228,12 @@ class GroupDataState extends State<GroupData> {
|
|||||||
userId = await getUserId();
|
userId = await getUserId();
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
|
isDisable = true;
|
||||||
// This triggers UI rebuild with error messages
|
// This triggers UI rebuild with error messages
|
||||||
if (validateData()) {
|
if (validateData()) {
|
||||||
postGroupData();
|
postGroupData();
|
||||||
|
}else{
|
||||||
|
isDisable = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -280,11 +284,21 @@ class GroupDataState extends State<GroupData> {
|
|||||||
// _clearError();
|
// _clearError();
|
||||||
_clearError();
|
_clearError();
|
||||||
await widget.fetchGetGroup();
|
await widget.fetchGetGroup();
|
||||||
|
if (context.mounted) {
|
||||||
|
Navigator.of(context).pop(); // Close modal only if mounted
|
||||||
|
}
|
||||||
|
setState(() {
|
||||||
|
isDisable = false;
|
||||||
|
});
|
||||||
|
|
||||||
// dispose();
|
// dispose();
|
||||||
Navigator.of(context).pop();
|
|
||||||
} else if (response.statusCode == 404) {
|
} else if (response.statusCode == 404) {
|
||||||
|
if (context.mounted) {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
|
}
|
||||||
|
setState(() {
|
||||||
|
isDisable = false;
|
||||||
|
});
|
||||||
final message = jsonDecode(response.body)['message'] ?? 'Unknown error';
|
final message = jsonDecode(response.body)['message'] ?? 'Unknown error';
|
||||||
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
@ -294,12 +308,33 @@ class GroupDataState extends State<GroupData> {
|
|||||||
behavior: SnackBarBehavior.floating,
|
behavior: SnackBarBehavior.floating,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} 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}");
|
||||||
|
final message = jsonDecode(response.body);
|
||||||
|
final errorMessage = message['messages']?['error'] ?? 'Unknown error occurred';
|
||||||
|
|
||||||
|
if (errorMessage.contains("Duplicate entry")) {
|
||||||
|
_clearError();
|
||||||
|
await widget.fetchGetGroup();
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(
|
||||||
|
content: Text("Group Already Exists!"),
|
||||||
|
backgroundColor: Colors.orange,
|
||||||
|
behavior: SnackBarBehavior.floating,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
setState(() {
|
||||||
|
isDisable = false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(" Error submitting plan: $e");
|
print(" Error submitting plan: $e");
|
||||||
|
setState(() {
|
||||||
|
isDisable = false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -377,7 +412,6 @@ class GroupDataState extends State<GroupData> {
|
|||||||
CustomTextFieldForexWrapper(
|
CustomTextFieldForexWrapper(
|
||||||
// isFocused: false,
|
// isFocused: false,
|
||||||
isFocused: focusStates["nameFocused"] ?? false,
|
isFocused: focusStates["nameFocused"] ?? false,
|
||||||
|
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
@ -444,6 +478,7 @@ class GroupDataState extends State<GroupData> {
|
|||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldForexWrapper(
|
CustomTextFieldForexWrapper(
|
||||||
isFocused: focusStates["domestic_policy_nameFocused"] ?? false,
|
isFocused: focusStates["domestic_policy_nameFocused"] ?? false,
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 0),
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
@ -498,7 +533,7 @@ class GroupDataState extends State<GroupData> {
|
|||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
color:
|
color:
|
||||||
(focusStates["country_codeFocused"] ?? false)
|
(focusStates["domestic_policy_nameFocused"] ?? false)
|
||||||
? widget.layoutColor!
|
? widget.layoutColor!
|
||||||
: Colors.white,
|
: Colors.white,
|
||||||
// width: 0.5,
|
// width: 0.5,
|
||||||
@ -507,7 +542,7 @@ class GroupDataState extends State<GroupData> {
|
|||||||
enabledBorder: OutlineInputBorder(
|
enabledBorder: OutlineInputBorder(
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
color:
|
color:
|
||||||
(focusStates["country_codeFocused"] ?? false)
|
(focusStates["domestic_policy_nameFocused"] ?? false)
|
||||||
? widget.layoutColor!
|
? widget.layoutColor!
|
||||||
: Colors.white,
|
: Colors.white,
|
||||||
// : const Color(0xFFD6D5E6),
|
// : const Color(0xFFD6D5E6),
|
||||||
@ -518,9 +553,8 @@ class GroupDataState extends State<GroupData> {
|
|||||||
focusedBorder: OutlineInputBorder(
|
focusedBorder: OutlineInputBorder(
|
||||||
borderSide: BorderSide(color: widget.layoutColor!, width: 1),
|
borderSide: BorderSide(color: widget.layoutColor!, width: 1),
|
||||||
),
|
),
|
||||||
contentPadding: EdgeInsets.symmetric(
|
contentPadding: EdgeInsets.symmetric(horizontal: 10.0,
|
||||||
horizontal: 8,
|
vertical: 8.0,),
|
||||||
)
|
|
||||||
// contentPadding: EdgeInsets.symmetric(horizontal: 1),
|
// contentPadding: EdgeInsets.symmetric(horizontal: 1),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -583,7 +617,7 @@ class GroupDataState extends State<GroupData> {
|
|||||||
CustomTextFieldForexWrapper(
|
CustomTextFieldForexWrapper(
|
||||||
isFocused:
|
isFocused:
|
||||||
focusStates["international_policy_nameFocused"] ?? false,
|
focusStates["international_policy_nameFocused"] ?? false,
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 0),
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
@ -639,20 +673,20 @@ class GroupDataState extends State<GroupData> {
|
|||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
color:
|
color:
|
||||||
(focusStates["country_codeFocused"] ?? false)
|
(focusStates["international_policy_nameFocused"] ?? false)
|
||||||
? widget.layoutColor!
|
? widget.layoutColor!
|
||||||
: Colors.white,
|
: Colors.white,
|
||||||
// width: 0.5,
|
width: 0.5,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
enabledBorder: OutlineInputBorder(
|
enabledBorder: OutlineInputBorder(
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
color:
|
color:
|
||||||
(focusStates["country_codeFocused"] ?? false)
|
(focusStates["international_policy_nameFocused"] ?? false)
|
||||||
? widget.layoutColor!
|
? widget.layoutColor!
|
||||||
: Colors.white,
|
: Colors.white,
|
||||||
// : const Color(0xFFD6D5E6),
|
// : const Color(0xFFD6D5E6),
|
||||||
// width: 0.5,
|
width: 0.5,
|
||||||
// const Color(0xFFD6D5E6),
|
// const Color(0xFFD6D5E6),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -794,10 +828,25 @@ class GroupDataState extends State<GroupData> {
|
|||||||
// ),
|
// ),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
onPressed: () {
|
// onPressed: () {
|
||||||
handleSubmit();
|
// handleSubmit();
|
||||||
|
// // You can get text from commentController.text
|
||||||
|
// // Navigator.of(context).pop(); // Close the modal
|
||||||
|
// },
|
||||||
|
onPressed: isDisable
|
||||||
|
? null
|
||||||
|
: () async {
|
||||||
|
setState(() {
|
||||||
|
isDisable = true;
|
||||||
|
});
|
||||||
|
await handleSubmit();
|
||||||
// You can get text from commentController.text
|
// You can get text from commentController.text
|
||||||
// Navigator.of(context).pop(); // Close the modal
|
// Navigator.of(context).pop(); // Close the modal
|
||||||
|
|
||||||
|
// Optional: re-enable only on error
|
||||||
|
// setState(() {
|
||||||
|
// isDisable = false;
|
||||||
|
// });
|
||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: widget.layoutColor,
|
backgroundColor: widget.layoutColor,
|
||||||
|
|||||||
@ -117,6 +117,7 @@ class _GroupListState extends State<GroupList> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<List<dynamic>> fetchGroups() async {
|
Future<List<dynamic>> fetchGroups() async {
|
||||||
|
// return [];
|
||||||
final result = await apiService.fetchAllGroup();
|
final result = await apiService.fetchAllGroup();
|
||||||
return result; // Returning raw JSON list
|
return result; // Returning raw JSON list
|
||||||
}
|
}
|
||||||
@ -303,7 +304,7 @@ class _GroupListState extends State<GroupList> {
|
|||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
breadcrumbItems: [
|
breadcrumbItems: [
|
||||||
BreadcrumbItem(
|
BreadcrumbItem(
|
||||||
title: 'Organization Settings',
|
title: 'Org Settings',
|
||||||
tooltip: 'Go To Organization Settings',
|
tooltip: 'Go To Organization Settings',
|
||||||
onTap: (context) {
|
onTap: (context) {
|
||||||
context.go("/OrganizationSettings");
|
context.go("/OrganizationSettings");
|
||||||
@ -475,6 +476,7 @@ class _GroupListState extends State<GroupList> {
|
|||||||
FutureBuilder<List<dynamic>>(
|
FutureBuilder<List<dynamic>>(
|
||||||
future: futureGroups,
|
future: futureGroups,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
|
final adjHgt = MediaQuery.of(context).size.height;
|
||||||
if (futureGroups == null) {
|
if (futureGroups == null) {
|
||||||
return const CircularProgressIndicator();
|
return const CircularProgressIndicator();
|
||||||
}
|
}
|
||||||
@ -490,9 +492,9 @@ class _GroupListState extends State<GroupList> {
|
|||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
const SizedBox(height: 8),
|
SizedBox(height: adjHgt / 4),
|
||||||
Text(
|
Text(
|
||||||
"No Group Found",
|
"No Data Found",
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
@ -501,15 +503,15 @@ class _GroupListState extends State<GroupList> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
Text(
|
// Text(
|
||||||
"Please Create Group",
|
// "Please Create Group",
|
||||||
textAlign: TextAlign.center,
|
// textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
// style: GoogleFonts.poppins(
|
||||||
fontSize: 16,
|
// fontSize: 16,
|
||||||
color: Colors.grey,
|
// color: Colors.grey,
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
const SizedBox(height: 20),
|
// const SizedBox(height: 20),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -612,13 +614,28 @@ class _GroupListState extends State<GroupList> {
|
|||||||
|
|
||||||
return DataRow(
|
return DataRow(
|
||||||
cells: [
|
cells: [
|
||||||
|
// DataCell(
|
||||||
|
// Text(
|
||||||
|
// "${group['name'] ?? ''}",
|
||||||
|
// style: TextStyle(
|
||||||
|
// fontSize: 13,
|
||||||
|
// fontFamily: "Inter",
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
DataCell(
|
DataCell(
|
||||||
Text(
|
ConstrainedBox(
|
||||||
|
constraints: BoxConstraints(maxWidth: 200), // limit description width
|
||||||
|
child: Text(
|
||||||
"${group['name'] ?? ''}",
|
"${group['name'] ?? ''}",
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
fontFamily: "Inter",
|
fontFamily: "Inter",
|
||||||
),
|
),
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
maxLines: 1, // optional: show only 1 line
|
||||||
|
softWrap: false,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
DataCell(
|
DataCell(
|
||||||
@ -639,13 +656,28 @@ class _GroupListState extends State<GroupList> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
// DataCell(
|
||||||
|
// Text(
|
||||||
|
// "${group['description'] ?? 'N/A'}",
|
||||||
|
// style: TextStyle(
|
||||||
|
// fontSize: 13,
|
||||||
|
// fontFamily: "Inter",
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
DataCell(
|
DataCell(
|
||||||
Text(
|
ConstrainedBox(
|
||||||
|
constraints: BoxConstraints(maxWidth: 200), // limit description width
|
||||||
|
child: Text(
|
||||||
"${group['description'] ?? 'N/A'}",
|
"${group['description'] ?? 'N/A'}",
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
fontFamily: "Inter",
|
fontFamily: "Inter",
|
||||||
),
|
),
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
maxLines: 1,
|
||||||
|
softWrap: false,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
DataCell(
|
DataCell(
|
||||||
@ -984,7 +1016,7 @@ class _GroupListState extends State<GroupList> {
|
|||||||
filteredGroups.isEmpty
|
filteredGroups.isEmpty
|
||||||
? Center(
|
? Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
"No matches found",
|
"No Matches Found",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: Colors.grey,
|
color: Colors.grey,
|
||||||
@ -999,7 +1031,7 @@ class _GroupListState extends State<GroupList> {
|
|||||||
paginatedGroup.isEmpty
|
paginatedGroup.isEmpty
|
||||||
? Center(
|
? Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
"No matches found",
|
"No Matches Found",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: Colors.grey,
|
color: Colors.grey,
|
||||||
|
|||||||
@ -54,6 +54,7 @@ class HotelsDataState extends State<HotelsData> {
|
|||||||
String? userId;
|
String? userId;
|
||||||
int? hotelsDataId;
|
int? hotelsDataId;
|
||||||
late String isActive = "1";
|
late String isActive = "1";
|
||||||
|
bool isDisable = false;
|
||||||
|
|
||||||
List<String> dataHeader = [
|
List<String> dataHeader = [
|
||||||
"hotel_name",
|
"hotel_name",
|
||||||
@ -196,9 +197,12 @@ class HotelsDataState extends State<HotelsData> {
|
|||||||
userId = await getUserId();
|
userId = await getUserId();
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
|
isDisable = true;
|
||||||
// This triggers UI rebuild with error messages
|
// This triggers UI rebuild with error messages
|
||||||
if (validateData()) {
|
if (validateData()) {
|
||||||
postHotelsData();
|
postHotelsData();
|
||||||
|
}else{
|
||||||
|
isDisable = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -250,20 +254,24 @@ class HotelsDataState extends State<HotelsData> {
|
|||||||
hotelsDataId != null
|
hotelsDataId != null
|
||||||
? 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);
|
||||||
|
|
||||||
if (response.statusCode == 200 || response.statusCode == 201) {
|
if (response.statusCode == 200 || response.statusCode == 201) {
|
||||||
print("Hotels Details Created successfully!");
|
print("Hotels Details Created successfully!");
|
||||||
print("Response: ${response.body}");
|
print("Response: ${response.body}");
|
||||||
// _clearError();
|
|
||||||
_clearError();
|
_clearError();
|
||||||
await widget.fetchGetHotels();
|
await widget.fetchGetHotels();
|
||||||
|
|
||||||
// dispose();
|
if (context.mounted) {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop(); // Close modal only if mounted
|
||||||
|
}
|
||||||
|
setState(() {
|
||||||
|
isDisable = false;
|
||||||
|
});
|
||||||
|
// Do NOT re-enable here if success
|
||||||
} else if (response.statusCode == 404) {
|
} else if (response.statusCode == 404) {
|
||||||
|
if (context.mounted) {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
|
}
|
||||||
final message = jsonDecode(response.body)['message'] ?? 'Unknown error';
|
final message = jsonDecode(response.body)['message'] ?? 'Unknown error';
|
||||||
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(
|
SnackBar(
|
||||||
content: Text(message),
|
content: Text(message),
|
||||||
@ -271,13 +279,26 @@ class HotelsDataState extends State<HotelsData> {
|
|||||||
behavior: SnackBarBehavior.floating,
|
behavior: SnackBarBehavior.floating,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
setState(() {
|
||||||
|
isDisable = false;
|
||||||
|
});
|
||||||
|
|
||||||
} 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}");
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
isDisable = false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} catch (e) {
|
}
|
||||||
|
catch (e) {
|
||||||
print("Error submitting plan: $e");
|
print("Error submitting plan: $e");
|
||||||
|
setState(() {
|
||||||
|
isDisable = false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -691,10 +712,21 @@ class HotelsDataState extends State<HotelsData> {
|
|||||||
// ),
|
// ),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: isDisable
|
||||||
handleSubmit();
|
? null
|
||||||
|
: () async {
|
||||||
|
setState(() {
|
||||||
|
isDisable = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
await handleSubmit();
|
||||||
// You can get text from commentController.text
|
// You can get text from commentController.text
|
||||||
// Navigator.of(context).pop(); // Close the modal
|
// Navigator.of(context).pop(); // Close the modal
|
||||||
|
|
||||||
|
// Optional: re-enable only on error
|
||||||
|
// setState(() {
|
||||||
|
// isDisable = false;
|
||||||
|
// });
|
||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: widget.layoutColor,
|
backgroundColor: widget.layoutColor,
|
||||||
|
|||||||
@ -135,6 +135,7 @@ class HotelsDataListState extends State<HotelsDataList> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<List<dynamic>> fetchGetHotels() async {
|
Future<List<dynamic>> fetchGetHotels() async {
|
||||||
|
// return [];
|
||||||
orgId = await getOrgId();
|
orgId = await getOrgId();
|
||||||
final String apiUrlData = '$apiUrl/api/getHotels?for=table_view';
|
final String apiUrlData = '$apiUrl/api/getHotels?for=table_view';
|
||||||
|
|
||||||
@ -335,7 +336,7 @@ class HotelsDataListState extends State<HotelsDataList> {
|
|||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
breadcrumbItems: [
|
breadcrumbItems: [
|
||||||
BreadcrumbItem(
|
BreadcrumbItem(
|
||||||
title: 'Organization Settings',
|
title: 'Org Settings',
|
||||||
tooltip: 'Go To Organization Settings',
|
tooltip: 'Go To Organization Settings',
|
||||||
onTap: (context) {
|
onTap: (context) {
|
||||||
context.go("/OrganizationSettings");
|
context.go("/OrganizationSettings");
|
||||||
@ -503,6 +504,7 @@ class HotelsDataListState extends State<HotelsDataList> {
|
|||||||
FutureBuilder<List<dynamic>>(
|
FutureBuilder<List<dynamic>>(
|
||||||
future: futureHotels,
|
future: futureHotels,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
|
final adjHgt = MediaQuery.of(context).size.height;
|
||||||
if (futureHotels == null) {
|
if (futureHotels == null) {
|
||||||
return CircularProgressIndicator();
|
return CircularProgressIndicator();
|
||||||
}
|
}
|
||||||
@ -528,9 +530,9 @@ class HotelsDataListState extends State<HotelsDataList> {
|
|||||||
// fontWeight: FontWeight.bold,
|
// fontWeight: FontWeight.bold,
|
||||||
// color: Colors.redAccent),
|
// color: Colors.redAccent),
|
||||||
// ),
|
// ),
|
||||||
const SizedBox(height: 8),
|
SizedBox(height: adjHgt / 4),
|
||||||
Text(
|
Text(
|
||||||
"No Hotels Available ",
|
"No Data Found ",
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
@ -539,15 +541,15 @@ class HotelsDataListState extends State<HotelsDataList> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
Text(
|
// Text(
|
||||||
"Please Create Hotels",
|
// "Please Create Hotels",
|
||||||
textAlign: TextAlign.center,
|
// textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
// style: GoogleFonts.poppins(
|
||||||
fontSize: 16,
|
// fontSize: 16,
|
||||||
color: Colors.grey,
|
// color: Colors.grey,
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
const SizedBox(height: 20),
|
// const SizedBox(height: 20),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -922,7 +924,7 @@ class HotelsDataListState extends State<HotelsDataList> {
|
|||||||
filteredHotels.isEmpty
|
filteredHotels.isEmpty
|
||||||
? Center(
|
? Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
"No matches found",
|
"No Matches Found",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: Colors.grey,
|
color: Colors.grey,
|
||||||
@ -937,7 +939,7 @@ class HotelsDataListState extends State<HotelsDataList> {
|
|||||||
filteredHotels.isEmpty
|
filteredHotels.isEmpty
|
||||||
? Center(
|
? Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
"No matches found",
|
"No Matches Found",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: Colors.grey,
|
color: Colors.grey,
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import 'package:intl/intl.dart';
|
|||||||
import 'package:responsive_builder/responsive_builder.dart';
|
import 'package:responsive_builder/responsive_builder.dart';
|
||||||
|
|
||||||
import '../../services/apiService.dart';
|
import '../../services/apiService.dart';
|
||||||
|
import '../../utils/auth_utils.dart';
|
||||||
import '../../widgets/custom_confirmation_dialog.dart';
|
import '../../widgets/custom_confirmation_dialog.dart';
|
||||||
import '../../widgets/custom_text_field.dart';
|
import '../../widgets/custom_text_field.dart';
|
||||||
import '../../widgets/custom_text_itnerary_sub.dart';
|
import '../../widgets/custom_text_itnerary_sub.dart';
|
||||||
@ -76,6 +77,8 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
bool _checkOutTimeFocus = false;
|
bool _checkOutTimeFocus = false;
|
||||||
bool _commentsFocus = false;
|
bool _commentsFocus = false;
|
||||||
|
|
||||||
|
Color layoutColor = Colors.grey;
|
||||||
|
|
||||||
void _addFocusListener(FocusNode node, Function(bool) onFocusChange) {
|
void _addFocusListener(FocusNode node, Function(bool) onFocusChange) {
|
||||||
node.addListener(() {
|
node.addListener(() {
|
||||||
setState(() {
|
setState(() {
|
||||||
@ -100,6 +103,9 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
"created_by": widget.loginUser,
|
"created_by": widget.loginUser,
|
||||||
"updated_by": widget.loginUser,
|
"updated_by": widget.loginUser,
|
||||||
};
|
};
|
||||||
|
print(":(");
|
||||||
|
print(_checkInController.text);
|
||||||
|
print(_checkInTimeController.text);
|
||||||
|
|
||||||
if (widget.selectedItem != null) {
|
if (widget.selectedItem != null) {
|
||||||
if (widget.selectedItem?["indx"] != null &&
|
if (widget.selectedItem?["indx"] != null &&
|
||||||
@ -120,7 +126,9 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
loadInitialData();
|
||||||
|
});
|
||||||
_addFocusListener(
|
_addFocusListener(
|
||||||
_destinationFocusNode,
|
_destinationFocusNode,
|
||||||
(focus) => _destinationFocused = focus,
|
(focus) => _destinationFocused = focus,
|
||||||
@ -129,6 +137,7 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
_hotelNameFocusNode,
|
_hotelNameFocusNode,
|
||||||
(focus) => _isHotelNameFocused = focus,
|
(focus) => _isHotelNameFocused = focus,
|
||||||
);
|
);
|
||||||
|
_addFocusListener( _CategoryFocusNode, (focus) => _CategoryFocused = focus);
|
||||||
_addFocusListener(_checkInFocusNode, (focus) => _checkInFocus = focus);
|
_addFocusListener(_checkInFocusNode, (focus) => _checkInFocus = focus);
|
||||||
_addFocusListener(
|
_addFocusListener(
|
||||||
_checkInTimeFocusNode,
|
_checkInTimeFocusNode,
|
||||||
@ -160,6 +169,14 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
flightLastTripDateNotifier = ValueNotifier<String?>(null);
|
flightLastTripDateNotifier = ValueNotifier<String?>(null);
|
||||||
flightFirstToDestinationNotifier = ValueNotifier<String?>(null);
|
flightFirstToDestinationNotifier = ValueNotifier<String?>(null);
|
||||||
|
|
||||||
|
// // ✅ Check and set default times if empty
|
||||||
|
// if (_checkInTimeController.text.isEmpty) {
|
||||||
|
// _checkInTimeController.text = '14:00'; // 2 PM
|
||||||
|
// }
|
||||||
|
// if (_checkOutTimeController.text.isEmpty) {
|
||||||
|
// _checkOutTimeController.text = '12:00'; // 12 PM
|
||||||
|
// }
|
||||||
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
loadCountryList();
|
loadCountryList();
|
||||||
|
|
||||||
@ -176,12 +193,23 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
widget.selectedItem?["destination_city"] ??
|
widget.selectedItem?["destination_city"] ??
|
||||||
result['firstToDestination'];
|
result['firstToDestination'];
|
||||||
|
|
||||||
|
// if (checkinDate != null) {
|
||||||
|
// flightFirstTripDateNotifier.value = checkinDate;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (checkoutDate != null) {
|
||||||
|
// flightLastTripDateNotifier.value = checkoutDate;
|
||||||
|
// }
|
||||||
|
|
||||||
|
final tripType = result['tripType'] ;
|
||||||
|
|
||||||
if (checkinDate != null) {
|
if (checkinDate != null) {
|
||||||
flightFirstTripDateNotifier.value = checkinDate;
|
flightFirstTripDateNotifier.value = checkinDate;
|
||||||
|
if (tripType == "Oneway") {
|
||||||
|
flightLastTripDateNotifier.value = checkinDate;
|
||||||
|
} else {
|
||||||
|
flightLastTripDateNotifier.value = checkoutDate ?? checkinDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (checkoutDate != null) {
|
|
||||||
flightLastTripDateNotifier.value = checkoutDate;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (destinationCity != null) {
|
if (destinationCity != null) {
|
||||||
@ -199,24 +227,25 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
|
|
||||||
// ✅ 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(
|
final checkInDateInput = flightFirstTripDateNotifier.value;
|
||||||
"dd-MM-yyyy",
|
if (checkInDateInput != null && checkInDateInput.isNotEmpty) {
|
||||||
).parse(flightFirstTripDateNotifier.value ?? '');
|
try {
|
||||||
if (parsedDate != null) {
|
final parsedDate = DateFormat("dd-MM-yyyy").parseStrict(checkInDateInput);
|
||||||
_checkInController.text = DateFormat('dd-MM-yyyy').format(parsedDate);
|
_checkInController.text = DateFormat("dd-MM-yyyy").format(parsedDate);
|
||||||
|
} catch (e) {
|
||||||
|
_checkInController.text = '';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// final parsedEndDate = DateTime.tryParse(flightLastTripDateNotifier.value ?? '');
|
// final parsedEndDate = DateTime.tryParse(flightLastTripDateNotifier.value ?? '');
|
||||||
final parsedEndDate = DateFormat(
|
final checkOutDateInput = flightLastTripDateNotifier.value;
|
||||||
"dd-MM-yyyy",
|
if (checkOutDateInput != null && checkOutDateInput.isNotEmpty) {
|
||||||
).parse(flightLastTripDateNotifier.value ?? '');
|
try {
|
||||||
|
final parsedDate = DateFormat("dd-MM-yyyy").parseStrict(checkOutDateInput);
|
||||||
if (parsedEndDate != null) {
|
_checkOutController.text = DateFormat("dd-MM-yyyy").format(parsedDate);
|
||||||
// _checkOutController.text = DateFormat('dd-MM-yyyy').format(parsedEndDate);
|
} catch (e) {
|
||||||
|
_checkOutController.text = '';
|
||||||
_checkOutController.text = DateFormat(
|
}
|
||||||
'dd-MM-yyyy',
|
|
||||||
).format(parsedEndDate);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ✅ Check and set default times if empty
|
// ✅ Check and set default times if empty
|
||||||
@ -239,6 +268,24 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void loadInitialData() async {
|
||||||
|
String? layoutString = await getLayoutColor();
|
||||||
|
|
||||||
|
// setState(() {
|
||||||
|
// layoutColor =
|
||||||
|
// layoutString != null
|
||||||
|
// ? Color(int.parse(layoutString))
|
||||||
|
// : Colors.redAccent;
|
||||||
|
// });
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
layoutColor =
|
||||||
|
layoutString != null
|
||||||
|
? Color(int.parse(layoutString))
|
||||||
|
: Colors.redAccent;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_destinationFocusNode.dispose();
|
_destinationFocusNode.dispose();
|
||||||
@ -272,8 +319,13 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
Map<String, String?> getFlightTripDateRange(
|
Map<String, String?> getFlightTripDateRange(
|
||||||
List<Map<String, dynamic>> flightData,
|
List<Map<String, dynamic>> flightData,
|
||||||
) {
|
) {
|
||||||
print("FlightDAta - ${widget.flightData}");
|
String tt = "";
|
||||||
|
if (widget.flightData.isNotEmpty) {
|
||||||
|
print("Trip Type - ${widget.flightData[0]['trip_type']}");
|
||||||
|
tt = widget.flightData[0]['trip_type'];
|
||||||
|
} else {
|
||||||
|
print("No flight data available");
|
||||||
|
}
|
||||||
final allTrips =
|
final allTrips =
|
||||||
flightData
|
flightData
|
||||||
.expand((flight) => flight['trips'] ?? [])
|
.expand((flight) => flight['trips'] ?? [])
|
||||||
@ -298,6 +350,7 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
|
|
||||||
print("res1 - ${firstTrip['date']},");
|
print("res1 - ${firstTrip['date']},");
|
||||||
print("res11 - $firstTripDate");
|
print("res11 - $firstTripDate");
|
||||||
|
print("res22 - $tt");
|
||||||
|
|
||||||
// Use `List.where` instead of `firstWhere` so you can handle an empty result
|
// Use `List.where` instead of `firstWhere` so you can handle an empty result
|
||||||
|
|
||||||
@ -319,6 +372,7 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
// 'lastTripDate': nextTrip['date'],
|
// 'lastTripDate': nextTrip['date'],
|
||||||
// 'lastTripDate': lastTrip['date'],
|
// 'lastTripDate': lastTrip['date'],
|
||||||
'firstToDestination': firstTripToDestination['to_place'],
|
'firstToDestination': firstTripToDestination['to_place'],
|
||||||
|
'tripType': tt, // trip_type: Oneway
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -503,6 +557,8 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
|
|
||||||
List<Widget> _buildFirstRow(isDesktop) {
|
List<Widget> _buildFirstRow(isDesktop) {
|
||||||
List<dynamic> purposeList = widget.apiDataForClass?['hotel_class'] ?? [];
|
List<dynamic> purposeList = widget.apiDataForClass?['hotel_class'] ?? [];
|
||||||
|
print("hotel_classhotel_class");
|
||||||
|
print(purposeList);
|
||||||
|
|
||||||
List<DropdownMenuItem<String>> dropdownItems =
|
List<DropdownMenuItem<String>> dropdownItems =
|
||||||
purposeList
|
purposeList
|
||||||
@ -655,6 +711,20 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
|
child: Focus(
|
||||||
|
focusNode: _CategoryFocusNode,
|
||||||
|
|
||||||
|
onFocusChange: (hasFocus) {
|
||||||
|
setState(() {
|
||||||
|
_CategoryFocused = hasFocus;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: GestureDetector(
|
||||||
|
//
|
||||||
|
onTap: () {
|
||||||
|
// Request focus when user taps
|
||||||
|
_CategoryFocusNode?.requestFocus();
|
||||||
|
},
|
||||||
child: DropdownSearch<Map<String, dynamic>>(
|
child: DropdownSearch<Map<String, dynamic>>(
|
||||||
key:
|
key:
|
||||||
selectedClass == null
|
selectedClass == null
|
||||||
@ -697,10 +767,34 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
dropdownDecoratorProps: const DropDownDecoratorProps(
|
dropdownDecoratorProps: DropDownDecoratorProps(
|
||||||
dropdownSearchDecoration: InputDecoration(
|
dropdownSearchDecoration: InputDecoration(
|
||||||
border: InputBorder.none,
|
// border: InputBorder.none,
|
||||||
contentPadding: EdgeInsets.symmetric(
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(5),
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(_CategoryFocused ?? false)
|
||||||
|
? layoutColor!
|
||||||
|
: Colors.white,
|
||||||
|
width: 1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(_CategoryFocused ?? false)
|
||||||
|
? layoutColor
|
||||||
|
: Colors.white,
|
||||||
|
// : const Color(0xFFD6D5E6),
|
||||||
|
width: 1,
|
||||||
|
// const Color(0xFFD6D5E6),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(color: layoutColor, width: 1),
|
||||||
|
),
|
||||||
|
contentPadding: const EdgeInsets.symmetric(
|
||||||
horizontal: 10,
|
horizontal: 10,
|
||||||
vertical: 10,
|
vertical: 10,
|
||||||
),
|
),
|
||||||
@ -764,7 +858,7 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
),
|
),),),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (errorMessages["class"] != null) ...[
|
if (errorMessages["class"] != null) ...[
|
||||||
|
|||||||
@ -113,7 +113,7 @@ class _BusScreenState extends State<BusScreen> {
|
|||||||
});
|
});
|
||||||
_dateFocusNode.addListener(() {
|
_dateFocusNode.addListener(() {
|
||||||
setState(() {
|
setState(() {
|
||||||
_dateFocus = _fromFocusNode.hasFocus;
|
_dateFocus = _dateFocusNode.hasFocus;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -144,6 +144,9 @@ class _BusScreenState extends State<BusScreen> {
|
|||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_tripTypeFocusNode.dispose();
|
_tripTypeFocusNode.dispose();
|
||||||
|
_dateFocusNode.dispose();
|
||||||
|
_timeFocusNode.dispose();
|
||||||
|
|
||||||
_tripTypeController.dispose();
|
_tripTypeController.dispose();
|
||||||
_hotelNameController.dispose();
|
_hotelNameController.dispose();
|
||||||
_fromController.dispose();
|
_fromController.dispose();
|
||||||
@ -536,7 +539,11 @@ class _BusScreenState extends State<BusScreen> {
|
|||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: () => _selectCheckOutDate(context),
|
// onTap: () => _selectCheckOutDate(context),
|
||||||
|
onTap: () {
|
||||||
|
_dateFocusNode.requestFocus();
|
||||||
|
_selectCheckOutDate(context);
|
||||||
|
},
|
||||||
child: AbsorbPointer(
|
child: AbsorbPointer(
|
||||||
child: TextField(
|
child: TextField(
|
||||||
focusNode: _dateFocusNode,
|
focusNode: _dateFocusNode,
|
||||||
@ -588,6 +595,7 @@ class _BusScreenState extends State<BusScreen> {
|
|||||||
onTap: () {
|
onTap: () {
|
||||||
// _selectedCheckOutTime = null; // ✅ Reset time variable
|
// _selectedCheckOutTime = null; // ✅ Reset time variable
|
||||||
_timeController.text = ""; // ✅ Clear text field
|
_timeController.text = ""; // ✅ Clear text field
|
||||||
|
_timeFocusNode.requestFocus();
|
||||||
_selectCheckOutTime(context);
|
_selectCheckOutTime(context);
|
||||||
},
|
},
|
||||||
child: AbsorbPointer(
|
child: AbsorbPointer(
|
||||||
|
|||||||
@ -279,7 +279,7 @@ class _ForexScreenState extends State<ForexScreen> {
|
|||||||
if (cardNumber.length < 15) {
|
if (cardNumber.length < 15) {
|
||||||
// Show error or return false
|
// Show error or return false
|
||||||
print("Card number must be 15 digits");
|
print("Card number must be 15 digits");
|
||||||
errorMessages["card_number"] = "Card number must be atleat 15 digits";
|
errorMessages["card_number"] = "Card number must be atleast 15 digits";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1091,8 +1091,8 @@ class _ForexScreenState extends State<ForexScreen> {
|
|||||||
//
|
//
|
||||||
// },
|
// },
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
|
focusNodes["_forexStartDate"]?.requestFocus();
|
||||||
await _selectCheckOutDate(context);
|
await _selectCheckOutDate(context);
|
||||||
|
|
||||||
if (textControllers["_forexEndDate"]!.text.isNotEmpty) {
|
if (textControllers["_forexEndDate"]!.text.isNotEmpty) {
|
||||||
DateTime? startDate = _parseDate(
|
DateTime? startDate = _parseDate(
|
||||||
textControllers["_forexStartDate"]!.text,
|
textControllers["_forexStartDate"]!.text,
|
||||||
@ -1189,6 +1189,7 @@ class _ForexScreenState extends State<ForexScreen> {
|
|||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
// onTap: () => _selectForexEndDate(context),
|
// onTap: () => _selectForexEndDate(context),
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
|
focusNodes["_forexEndDate"]?.requestFocus();
|
||||||
await _selectForexEndDate(context);
|
await _selectForexEndDate(context);
|
||||||
|
|
||||||
if (textControllers["_forexEndDate"]!.text.isNotEmpty) {
|
if (textControllers["_forexEndDate"]!.text.isNotEmpty) {
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import 'package:google_fonts/google_fonts.dart';
|
|||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import 'package:responsive_builder/responsive_builder.dart';
|
import 'package:responsive_builder/responsive_builder.dart';
|
||||||
|
|
||||||
|
import '../../utils/auth_utils.dart';
|
||||||
import '../../widgets/custom_text_field.dart';
|
import '../../widgets/custom_text_field.dart';
|
||||||
import '../../widgets/custom_text_itnerary_sub.dart';
|
import '../../widgets/custom_text_itnerary_sub.dart';
|
||||||
|
|
||||||
@ -44,10 +45,10 @@ class _MiscellaneousScreenState extends State<MiscellaneousScreen> {
|
|||||||
|
|
||||||
late TextEditingController _commentsController = TextEditingController();
|
late TextEditingController _commentsController = TextEditingController();
|
||||||
|
|
||||||
bool _isHotelNameFocused = false;
|
bool _hotelNameFocused = false;
|
||||||
bool _commentsFocus = false;
|
bool _commentsFocus = false;
|
||||||
String? selectedSpecialType;
|
String? selectedSpecialType;
|
||||||
|
Color layoutColor = Colors.grey;
|
||||||
Map<String, String> errorMessages = {};
|
Map<String, String> errorMessages = {};
|
||||||
|
|
||||||
Map<String, dynamic> get miscellaneousData {
|
Map<String, dynamic> get miscellaneousData {
|
||||||
@ -77,10 +78,12 @@ class _MiscellaneousScreenState extends State<MiscellaneousScreen> {
|
|||||||
if (widget.selectedItem == null) {
|
if (widget.selectedItem == null) {
|
||||||
_commentsController.clear();
|
_commentsController.clear();
|
||||||
}
|
}
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
loadInitialData();
|
||||||
|
});
|
||||||
_hotelNameFocusNode.addListener(() {
|
_hotelNameFocusNode.addListener(() {
|
||||||
setState(() {
|
setState(() {
|
||||||
_isHotelNameFocused = _hotelNameFocusNode.hasFocus;
|
_hotelNameFocused = _hotelNameFocusNode.hasFocus;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -104,11 +107,30 @@ class _MiscellaneousScreenState extends State<MiscellaneousScreen> {
|
|||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_tripTypeFocusNode.dispose();
|
_tripTypeFocusNode.dispose();
|
||||||
|
_hotelNameFocusNode.dispose();
|
||||||
_tripTypeController.dispose();
|
_tripTypeController.dispose();
|
||||||
_commentsController.dispose();
|
_commentsController.dispose();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void loadInitialData() async {
|
||||||
|
String? layoutString = await getLayoutColor();
|
||||||
|
|
||||||
|
// setState(() {
|
||||||
|
// layoutColor =
|
||||||
|
// layoutString != null
|
||||||
|
// ? Color(int.parse(layoutString))
|
||||||
|
// : Colors.redAccent;
|
||||||
|
// });
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
layoutColor =
|
||||||
|
layoutString != null
|
||||||
|
? Color(int.parse(layoutString))
|
||||||
|
: Colors.redAccent;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
bool isValidData(Map<String, dynamic> data) {
|
bool isValidData(Map<String, dynamic> data) {
|
||||||
errorMessages.clear(); // Reset errors
|
errorMessages.clear(); // Reset errors
|
||||||
|
|
||||||
@ -281,8 +303,9 @@ class _MiscellaneousScreenState extends State<MiscellaneousScreen> {
|
|||||||
// ),
|
// ),
|
||||||
// ),
|
// ),
|
||||||
CustomTextFieldItnerarySubWrapper(
|
CustomTextFieldItnerarySubWrapper(
|
||||||
isFocused: _isHotelNameFocused,
|
isFocused: _hotelNameFocused,
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 0),
|
||||||
width:
|
width:
|
||||||
isDesktop
|
isDesktop
|
||||||
? MediaQuery.of(context).size.width * 0.34
|
? MediaQuery.of(context).size.width * 0.34
|
||||||
@ -290,6 +313,19 @@ class _MiscellaneousScreenState extends State<MiscellaneousScreen> {
|
|||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
|
child: Focus(
|
||||||
|
focusNode: _hotelNameFocusNode,
|
||||||
|
onFocusChange: (hasFocus) {
|
||||||
|
setState(() {
|
||||||
|
_hotelNameFocused = hasFocus;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: GestureDetector(
|
||||||
|
//
|
||||||
|
onTap: () {
|
||||||
|
// Request focus when user taps
|
||||||
|
_hotelNameFocusNode?.requestFocus();
|
||||||
|
},
|
||||||
child: DropdownSearch<Map<String, dynamic>>(
|
child: DropdownSearch<Map<String, dynamic>>(
|
||||||
// focusNode: _taxiReqFocusNode,
|
// focusNode: _taxiReqFocusNode,
|
||||||
items: purposeList.cast<Map<String, dynamic>>(),
|
items: purposeList.cast<Map<String, dynamic>>(),
|
||||||
@ -318,9 +354,33 @@ class _MiscellaneousScreenState extends State<MiscellaneousScreen> {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
dropdownDecoratorProps: const DropDownDecoratorProps(
|
dropdownDecoratorProps: DropDownDecoratorProps(
|
||||||
dropdownSearchDecoration: InputDecoration(
|
dropdownSearchDecoration: InputDecoration(
|
||||||
border: InputBorder.none,
|
// border: InputBorder.none,
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(4),
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(_hotelNameFocused ?? false)
|
||||||
|
? layoutColor!
|
||||||
|
: Colors.white,
|
||||||
|
width: 0.5,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(_hotelNameFocused ?? false)
|
||||||
|
? layoutColor
|
||||||
|
: Colors.white,
|
||||||
|
// : const Color(0xFFD6D5E6),
|
||||||
|
width: 0.5,
|
||||||
|
// const Color(0xFFD6D5E6),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(color: layoutColor, width: 0.5),
|
||||||
|
),
|
||||||
contentPadding: EdgeInsets.symmetric(
|
contentPadding: EdgeInsets.symmetric(
|
||||||
horizontal: 10,
|
horizontal: 10,
|
||||||
vertical: 10,
|
vertical: 10,
|
||||||
@ -348,7 +408,7 @@ class _MiscellaneousScreenState extends State<MiscellaneousScreen> {
|
|||||||
print("Updating form data: -> ${newValue ?? ""}");
|
print("Updating form data: -> ${newValue ?? ""}");
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
),
|
),),)
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (errorMessages["special_request"] != null) ...[
|
if (errorMessages["special_request"] != null) ...[
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import 'package:google_fonts/google_fonts.dart';
|
|||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import 'package:responsive_builder/responsive_builder.dart';
|
import 'package:responsive_builder/responsive_builder.dart';
|
||||||
|
|
||||||
|
import '../../utils/auth_utils.dart';
|
||||||
import '../../widgets/custom_text_field.dart';
|
import '../../widgets/custom_text_field.dart';
|
||||||
import '../../widgets/custom_text_itnerary_sub.dart';
|
import '../../widgets/custom_text_itnerary_sub.dart';
|
||||||
|
|
||||||
@ -41,6 +42,7 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
final FocusNode _timeFocusNode = FocusNode();
|
final FocusNode _timeFocusNode = FocusNode();
|
||||||
final FocusNode _numPassengerFocusNode = FocusNode();
|
final FocusNode _numPassengerFocusNode = FocusNode();
|
||||||
final FocusNode _commentsFocusNode = FocusNode();
|
final FocusNode _commentsFocusNode = FocusNode();
|
||||||
|
final FocusNode _carTypeFocusNode = FocusNode();
|
||||||
|
|
||||||
late TextEditingController _destinationController = TextEditingController();
|
late TextEditingController _destinationController = TextEditingController();
|
||||||
late TextEditingController _locationController = TextEditingController();
|
late TextEditingController _locationController = TextEditingController();
|
||||||
@ -54,12 +56,14 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
bool _toFocus = false;
|
bool _toFocus = false;
|
||||||
bool _dateFocus = false;
|
bool _dateFocus = false;
|
||||||
bool _taxiReqFocused = false;
|
bool _taxiReqFocused = false;
|
||||||
|
bool _carTypeFocused = false;
|
||||||
bool _numPassengerFocus = false;
|
bool _numPassengerFocus = false;
|
||||||
bool _timeFocus = false;
|
bool _timeFocus = false;
|
||||||
bool _commentsFocus = false;
|
bool _commentsFocus = false;
|
||||||
|
|
||||||
String? selectedReqTaxi;
|
String? selectedReqTaxi;
|
||||||
String? selectedCarType;
|
String? selectedCarType;
|
||||||
|
Color layoutColor = Colors.grey;
|
||||||
|
|
||||||
Map<String, dynamic> get taxiData {
|
Map<String, dynamic> get taxiData {
|
||||||
Map<String, dynamic> data = {
|
Map<String, dynamic> data = {
|
||||||
@ -98,6 +102,10 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
loadInitialData();
|
||||||
|
});
|
||||||
|
|
||||||
_addFocusListener(
|
_addFocusListener(
|
||||||
_destinationFocusNode,
|
_destinationFocusNode,
|
||||||
(focus) => _destinationFocus = focus,
|
(focus) => _destinationFocus = focus,
|
||||||
@ -106,6 +114,7 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
_addFocusListener(_dateFocusNode, (focus) => _dateFocus = focus);
|
_addFocusListener(_dateFocusNode, (focus) => _dateFocus = focus);
|
||||||
_addFocusListener(_timeFocusNode, (focus) => _timeFocus = focus);
|
_addFocusListener(_timeFocusNode, (focus) => _timeFocus = focus);
|
||||||
_addFocusListener(_taxiReqFocusNode, (focus) => _taxiReqFocused = focus);
|
_addFocusListener(_taxiReqFocusNode, (focus) => _taxiReqFocused = focus);
|
||||||
|
_addFocusListener(_carTypeFocusNode, (focus) => _carTypeFocused = focus);
|
||||||
_addFocusListener(
|
_addFocusListener(
|
||||||
_numPassengerFocusNode,
|
_numPassengerFocusNode,
|
||||||
(focus) => _numPassengerFocus = focus,
|
(focus) => _numPassengerFocus = focus,
|
||||||
@ -146,10 +155,22 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void loadInitialData() async {
|
||||||
|
String? layoutString = await getLayoutColor();
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
layoutColor =
|
||||||
|
layoutString != null
|
||||||
|
? Color(int.parse(layoutString))
|
||||||
|
: Colors.redAccent;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_destinationFocusNode.dispose();
|
_destinationFocusNode.dispose();
|
||||||
_locationFocusNode.dispose();
|
_locationFocusNode.dispose();
|
||||||
|
_carTypeFocusNode.dispose();
|
||||||
_destinationController.dispose();
|
_destinationController.dispose();
|
||||||
_dateController.dispose();
|
_dateController.dispose();
|
||||||
_timeController.dispose();
|
_timeController.dispose();
|
||||||
@ -397,9 +418,22 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
CustomTextFieldItnerarySubWrapper(
|
CustomTextFieldItnerarySubWrapper(
|
||||||
isFocused: _toFocus,
|
isFocused: _toFocus,
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 0),
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
|
child: Focus(
|
||||||
|
focusNode: _carTypeFocusNode,
|
||||||
|
onFocusChange: (hasFocus) {
|
||||||
|
setState(() {
|
||||||
|
_carTypeFocused = hasFocus;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
// Request focus when user taps
|
||||||
|
_carTypeFocusNode?.requestFocus();
|
||||||
|
},
|
||||||
child: DropdownSearch<Map<String, dynamic>>(
|
child: DropdownSearch<Map<String, dynamic>>(
|
||||||
// focusNode: _taxiReqFocusNode,
|
// focusNode: _taxiReqFocusNode,
|
||||||
items: purposeList.cast<Map<String, dynamic>>(),
|
items: purposeList.cast<Map<String, dynamic>>(),
|
||||||
@ -428,9 +462,33 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
dropdownDecoratorProps: const DropDownDecoratorProps(
|
dropdownDecoratorProps: DropDownDecoratorProps(
|
||||||
dropdownSearchDecoration: InputDecoration(
|
dropdownSearchDecoration: InputDecoration(
|
||||||
border: InputBorder.none,
|
// border: InputBorder.none,
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(5),
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(_carTypeFocused ?? false)
|
||||||
|
? layoutColor!
|
||||||
|
: Colors.white,
|
||||||
|
width: 1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(_carTypeFocused ?? false)
|
||||||
|
? layoutColor
|
||||||
|
: Colors.white,
|
||||||
|
// : const Color(0xFFD6D5E6),
|
||||||
|
width: 1,
|
||||||
|
// const Color(0xFFD6D5E6),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(color: layoutColor, width: 1),
|
||||||
|
),
|
||||||
contentPadding: EdgeInsets.symmetric(
|
contentPadding: EdgeInsets.symmetric(
|
||||||
horizontal: 10,
|
horizontal: 10,
|
||||||
vertical: 10,
|
vertical: 10,
|
||||||
@ -464,7 +522,7 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
print("Updating form data: -> ${newValue ?? ""}");
|
print("Updating form data: -> ${newValue ?? ""}");
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
),
|
),),),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -541,6 +599,7 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
CustomTextFieldItnerarySubWrapper(
|
CustomTextFieldItnerarySubWrapper(
|
||||||
isFocused: _taxiReqFocused,
|
isFocused: _taxiReqFocused,
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 0),
|
||||||
width:
|
width:
|
||||||
isDesktop
|
isDesktop
|
||||||
? MediaQuery.of(context).size.width * 0.34
|
? MediaQuery.of(context).size.width * 0.34
|
||||||
@ -548,6 +607,17 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
|
child: Focus(
|
||||||
|
focusNode: _taxiReqFocusNode,
|
||||||
|
onFocusChange: (hasFocus) {
|
||||||
|
setState(() {
|
||||||
|
_taxiReqFocused = hasFocus;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
_taxiReqFocusNode?.requestFocus();
|
||||||
|
},
|
||||||
child: DropdownSearch<Map<String, dynamic>>(
|
child: DropdownSearch<Map<String, dynamic>>(
|
||||||
// focusNode: _taxiReqFocusNode,
|
// focusNode: _taxiReqFocusNode,
|
||||||
items: purposeList.cast<Map<String, dynamic>>(),
|
items: purposeList.cast<Map<String, dynamic>>(),
|
||||||
@ -576,12 +646,36 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
dropdownDecoratorProps: const DropDownDecoratorProps(
|
dropdownDecoratorProps: DropDownDecoratorProps(
|
||||||
dropdownSearchDecoration: InputDecoration(
|
dropdownSearchDecoration: InputDecoration(
|
||||||
border: InputBorder.none,
|
// border: InputBorder.none,
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(5),
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(_taxiReqFocused ?? false)
|
||||||
|
? layoutColor!
|
||||||
|
: Colors.white,
|
||||||
|
width: 1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(_taxiReqFocused ?? false)
|
||||||
|
? layoutColor
|
||||||
|
: Colors.white,
|
||||||
|
// : const Color(0xFFD6D5E6),
|
||||||
|
width: 1,
|
||||||
|
// const Color(0xFFD6D5E6),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(color: layoutColor, width: 1),
|
||||||
|
),
|
||||||
contentPadding: EdgeInsets.symmetric(
|
contentPadding: EdgeInsets.symmetric(
|
||||||
horizontal: 10,
|
horizontal: 10,
|
||||||
vertical: 10,
|
vertical: 1,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -606,7 +700,7 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
print("Updating form data: -> ${newValue ?? ""}");
|
print("Updating form data: -> ${newValue ?? ""}");
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
),
|
),),),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
@ -817,7 +911,11 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: () => _selectCheckOutDate(context),
|
// onTap: () => _selectCheckOutDate(context),
|
||||||
|
onTap: () {
|
||||||
|
_dateFocusNode.requestFocus();
|
||||||
|
_selectCheckOutDate(context);
|
||||||
|
},
|
||||||
child: AbsorbPointer(
|
child: AbsorbPointer(
|
||||||
child: TextField(
|
child: TextField(
|
||||||
focusNode: _dateFocusNode,
|
focusNode: _dateFocusNode,
|
||||||
@ -868,6 +966,7 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
_timeController.text = "";
|
_timeController.text = "";
|
||||||
|
_timeFocusNode.requestFocus();
|
||||||
_selectCheckOutTime(context);
|
_selectCheckOutTime(context);
|
||||||
},
|
},
|
||||||
child: AbsorbPointer(
|
child: AbsorbPointer(
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import 'package:intl/intl.dart';
|
|||||||
import 'package:responsive_builder/responsive_builder.dart';
|
import 'package:responsive_builder/responsive_builder.dart';
|
||||||
|
|
||||||
import '../../services/apiService.dart';
|
import '../../services/apiService.dart';
|
||||||
|
import '../../utils/auth_utils.dart';
|
||||||
import '../../widgets/custom_confirmation_dialog.dart';
|
import '../../widgets/custom_confirmation_dialog.dart';
|
||||||
import '../../widgets/custom_text_field.dart';
|
import '../../widgets/custom_text_field.dart';
|
||||||
import '../../widgets/custom_text_itnerary_sub.dart';
|
import '../../widgets/custom_text_itnerary_sub.dart';
|
||||||
@ -44,7 +45,7 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
Map<String, String?> selectedValues = {};
|
Map<String, String?> selectedValues = {};
|
||||||
|
|
||||||
final FocusNode _trainNoFocusNode = FocusNode();
|
final FocusNode _trainNoFocusNode = FocusNode();
|
||||||
final FocusNode _hotelNameFocusNode = FocusNode();
|
final FocusNode _typeOfClassFocusNode = FocusNode();
|
||||||
final FocusNode _fromFocusNode = FocusNode();
|
final FocusNode _fromFocusNode = FocusNode();
|
||||||
final FocusNode _toFocusNode = FocusNode();
|
final FocusNode _toFocusNode = FocusNode();
|
||||||
final FocusNode _dateFocusNode = FocusNode();
|
final FocusNode _dateFocusNode = FocusNode();
|
||||||
@ -60,7 +61,7 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
late TextEditingController _trainCommentsController = TextEditingController();
|
late TextEditingController _trainCommentsController = TextEditingController();
|
||||||
|
|
||||||
bool _trainNoFocused = false;
|
bool _trainNoFocused = false;
|
||||||
bool _isHotelNameFocused = false;
|
bool _typeOfClassFocus = false;
|
||||||
bool _fromFocus = false;
|
bool _fromFocus = false;
|
||||||
bool _toFocus = false;
|
bool _toFocus = false;
|
||||||
bool _dateFocus = false;
|
bool _dateFocus = false;
|
||||||
@ -71,6 +72,7 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
String? exceptionalClass = "0";
|
String? exceptionalClass = "0";
|
||||||
String? selectedFrom;
|
String? selectedFrom;
|
||||||
String? selectedTo;
|
String? selectedTo;
|
||||||
|
Color layoutColor = Colors.grey;
|
||||||
|
|
||||||
Map<String, String> errorMessages = {};
|
Map<String, String> errorMessages = {};
|
||||||
|
|
||||||
@ -110,15 +112,17 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
loadInitialData();
|
||||||
|
});
|
||||||
_trainNoFocusNode.addListener(() {
|
_trainNoFocusNode.addListener(() {
|
||||||
setState(() {
|
setState(() {
|
||||||
_trainNoFocused = _trainNoFocusNode.hasFocus;
|
_trainNoFocused = _trainNoFocusNode.hasFocus;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
_hotelNameFocusNode.addListener(() {
|
_typeOfClassFocusNode.addListener(() {
|
||||||
setState(() {
|
setState(() {
|
||||||
_isHotelNameFocused = _hotelNameFocusNode.hasFocus;
|
_typeOfClassFocus = _typeOfClassFocusNode.hasFocus;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
_fromFocusNode.addListener(() {
|
_fromFocusNode.addListener(() {
|
||||||
@ -133,7 +137,7 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
});
|
});
|
||||||
_dateFocusNode.addListener(() {
|
_dateFocusNode.addListener(() {
|
||||||
setState(() {
|
setState(() {
|
||||||
_dateFocus = _fromFocusNode.hasFocus;
|
_dateFocus = _dateFocusNode.hasFocus;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
_timeFocusNode.addListener(() {
|
_timeFocusNode.addListener(() {
|
||||||
@ -213,6 +217,13 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_trainNoFocusNode.dispose();
|
_trainNoFocusNode.dispose();
|
||||||
|
_dateFocusNode.dispose();
|
||||||
|
_timeFocusNode.dispose();
|
||||||
|
_typeOfClassFocusNode.dispose();
|
||||||
|
_fromFocusNode.dispose();
|
||||||
|
_toFocusNode.dispose();
|
||||||
|
_commentsFocusNode.dispose();
|
||||||
|
|
||||||
_trainNoController.dispose();
|
_trainNoController.dispose();
|
||||||
_hotelNameController.dispose();
|
_hotelNameController.dispose();
|
||||||
_fromController.dispose();
|
_fromController.dispose();
|
||||||
@ -223,6 +234,17 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void loadInitialData() async {
|
||||||
|
String? layoutString = await getLayoutColor();
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
layoutColor =
|
||||||
|
layoutString != null
|
||||||
|
? Color(int.parse(layoutString))
|
||||||
|
: Colors.redAccent;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void _clearError(String field) {
|
void _clearError(String field) {
|
||||||
if (mounted && errorMessages.containsKey(field)) {
|
if (mounted && errorMessages.containsKey(field)) {
|
||||||
setState(() {
|
setState(() {
|
||||||
@ -632,12 +654,24 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
// ),
|
// ),
|
||||||
// ),
|
// ),
|
||||||
CustomTextFieldWrapper(
|
CustomTextFieldWrapper(
|
||||||
isFocused: _isHotelNameFocused,
|
isFocused: _typeOfClassFocus,
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 0),
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
width: isDesktop ? MediaQuery.of(context).size.width * 0.15 : null,
|
width: isDesktop ? MediaQuery.of(context).size.width * 0.15 : null,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
|
child: Focus(
|
||||||
|
focusNode: _typeOfClassFocusNode,
|
||||||
|
onFocusChange: (hasFocus) {
|
||||||
|
setState(() {
|
||||||
|
_typeOfClassFocus = hasFocus;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
_typeOfClassFocusNode?.requestFocus();
|
||||||
|
},
|
||||||
child: DropdownSearch<Map<String, dynamic>>(
|
child: DropdownSearch<Map<String, dynamic>>(
|
||||||
key:
|
key:
|
||||||
selectedClass == null
|
selectedClass == null
|
||||||
@ -678,9 +712,33 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
dropdownDecoratorProps: const DropDownDecoratorProps(
|
dropdownDecoratorProps: DropDownDecoratorProps(
|
||||||
dropdownSearchDecoration: InputDecoration(
|
dropdownSearchDecoration: InputDecoration(
|
||||||
border: InputBorder.none,
|
// border: InputBorder.none,
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(5),
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(_typeOfClassFocus ?? false)
|
||||||
|
? layoutColor!
|
||||||
|
: Colors.white,
|
||||||
|
width: 1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(_typeOfClassFocus ?? false)
|
||||||
|
? layoutColor
|
||||||
|
: Colors.white,
|
||||||
|
// : const Color(0xFFD6D5E6),
|
||||||
|
width: 1,
|
||||||
|
// const Color(0xFFD6D5E6),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(color: layoutColor, width: 1),
|
||||||
|
),
|
||||||
contentPadding: EdgeInsets.symmetric(
|
contentPadding: EdgeInsets.symmetric(
|
||||||
horizontal: 10,
|
horizontal: 10,
|
||||||
vertical: 10,
|
vertical: 10,
|
||||||
@ -759,7 +817,7 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
),
|
),),)
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (errorMessages["class"] != null) ...[
|
if (errorMessages["class"] != null) ...[
|
||||||
@ -874,15 +932,27 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
// ),
|
// ),
|
||||||
CustomTextFieldItnerarySubWrapper(
|
CustomTextFieldItnerarySubWrapper(
|
||||||
isFocused: _fromFocus ?? false,
|
isFocused: _fromFocus ?? false,
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 0),
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
|
child: Focus(
|
||||||
|
focusNode: _fromFocusNode,
|
||||||
|
onFocusChange: (hasFocus) {
|
||||||
|
setState(() {
|
||||||
|
_fromFocus = hasFocus;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
_fromFocusNode?.requestFocus();
|
||||||
|
},
|
||||||
child: DropdownSearch<String>(
|
child: DropdownSearch<String>(
|
||||||
selectedItem: countryMap[selectedFrom],
|
selectedItem: countryMap[selectedFrom],
|
||||||
popupProps: PopupProps.menu(
|
popupProps: PopupProps.menu(
|
||||||
showSearchBox: true,
|
showSearchBox: true,
|
||||||
fit: FlexFit.loose,
|
fit: FlexFit.loose,
|
||||||
constraints: BoxConstraints(maxHeight: 250),
|
constraints: BoxConstraints(maxHeight: 150),// maxHeight: 250
|
||||||
menuProps: const MenuProps(backgroundColor: Colors.white),
|
menuProps: const MenuProps(backgroundColor: Colors.white),
|
||||||
itemBuilder:
|
itemBuilder:
|
||||||
(context, item, isSelected) => Container(
|
(context, item, isSelected) => Container(
|
||||||
@ -906,8 +976,32 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
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(horizontal: 1),
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(5),
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(_fromFocus ?? false)
|
||||||
|
? layoutColor!
|
||||||
|
: Colors.white,
|
||||||
|
width: 1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(_fromFocus ?? false)
|
||||||
|
? layoutColor
|
||||||
|
: Colors.white,
|
||||||
|
// : const Color(0xFFD6D5E6),
|
||||||
|
width: 1,
|
||||||
|
// const Color(0xFFD6D5E6),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(color: layoutColor, width: 1),
|
||||||
|
),
|
||||||
|
contentPadding: EdgeInsets.symmetric(horizontal: 10),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
dropdownBuilder:
|
dropdownBuilder:
|
||||||
@ -929,7 +1023,7 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
.key;
|
.key;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
),
|
),),)
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (errorMessages["from_station"] != null) ...[
|
if (errorMessages["from_station"] != null) ...[
|
||||||
@ -1008,14 +1102,26 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
CustomTextFieldItnerarySubWrapper(
|
CustomTextFieldItnerarySubWrapper(
|
||||||
isFocused: _toFocus ?? false,
|
isFocused: _toFocus ?? false,
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 0),
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
|
child: Focus(
|
||||||
|
focusNode: _toFocusNode,
|
||||||
|
onFocusChange: (hasFocus) {
|
||||||
|
setState(() {
|
||||||
|
_toFocus = hasFocus;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
_toFocusNode?.requestFocus();
|
||||||
|
},
|
||||||
child: DropdownSearch<String>(
|
child: DropdownSearch<String>(
|
||||||
selectedItem: countryMap[selectedTo],
|
selectedItem: countryMap[selectedTo],
|
||||||
popupProps: PopupProps.menu(
|
popupProps: PopupProps.menu(
|
||||||
showSearchBox: true,
|
showSearchBox: true,
|
||||||
fit: FlexFit.loose,
|
fit: FlexFit.loose,
|
||||||
constraints: BoxConstraints(maxHeight: 250),
|
constraints: BoxConstraints(maxHeight: 150),
|
||||||
menuProps: const MenuProps(backgroundColor: Colors.white),
|
menuProps: const MenuProps(backgroundColor: Colors.white),
|
||||||
itemBuilder:
|
itemBuilder:
|
||||||
(context, item, isSelected) => Container(
|
(context, item, isSelected) => Container(
|
||||||
@ -1039,8 +1145,32 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
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(horizontal: 1),
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(5),
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(_toFocus ?? false)
|
||||||
|
? layoutColor!
|
||||||
|
: Colors.white,
|
||||||
|
width: 1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(_toFocus ?? false)
|
||||||
|
? layoutColor
|
||||||
|
: Colors.white,
|
||||||
|
// : const Color(0xFFD6D5E6),
|
||||||
|
width: 1,
|
||||||
|
// const Color(0xFFD6D5E6),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(color: layoutColor, width: 1),
|
||||||
|
),
|
||||||
|
contentPadding: EdgeInsets.symmetric(horizontal: 10),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
dropdownBuilder:
|
dropdownBuilder:
|
||||||
@ -1062,7 +1192,7 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
.key;
|
.key;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
),
|
),),),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (errorMessages["to_station"] != null) ...[
|
if (errorMessages["to_station"] != null) ...[
|
||||||
@ -1094,7 +1224,11 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: () => _selectCheckOutDate(context),
|
// onTap: () => _selectCheckOutDate(context),
|
||||||
|
onTap: () {
|
||||||
|
_dateFocusNode.requestFocus();
|
||||||
|
_selectCheckOutDate(context);
|
||||||
|
},
|
||||||
child: AbsorbPointer(
|
child: AbsorbPointer(
|
||||||
child: TextField(
|
child: TextField(
|
||||||
focusNode: _dateFocusNode,
|
focusNode: _dateFocusNode,
|
||||||
@ -1146,6 +1280,7 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
_timeController.text = "";
|
_timeController.text = "";
|
||||||
|
_timeFocusNode.requestFocus();
|
||||||
_selectCheckOutTime(context);
|
_selectCheckOutTime(context);
|
||||||
},
|
},
|
||||||
child: AbsorbPointer(
|
child: AbsorbPointer(
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import 'package:intl/intl.dart';
|
|||||||
import 'package:responsive_builder/responsive_builder.dart';
|
import 'package:responsive_builder/responsive_builder.dart';
|
||||||
|
|
||||||
import '../../services/apiService.dart';
|
import '../../services/apiService.dart';
|
||||||
|
import '../../utils/auth_utils.dart';
|
||||||
import '../../widgets/custom_text_field.dart';
|
import '../../widgets/custom_text_field.dart';
|
||||||
import '../../widgets/custom_text_itnerary_sub.dart';
|
import '../../widgets/custom_text_itnerary_sub.dart';
|
||||||
|
|
||||||
@ -49,6 +50,7 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
List<dynamic> countryList = [];
|
List<dynamic> countryList = [];
|
||||||
|
|
||||||
final FocusNode _tripTypeFocusNode = FocusNode();
|
final FocusNode _tripTypeFocusNode = FocusNode();
|
||||||
|
final FocusNode _countryFocusNode = FocusNode();
|
||||||
final FocusNode _hotelNameFocusNode = FocusNode();
|
final FocusNode _hotelNameFocusNode = FocusNode();
|
||||||
final FocusNode _dateFocusNode = FocusNode();
|
final FocusNode _dateFocusNode = FocusNode();
|
||||||
final FocusNode _commentsFocusNode = FocusNode();
|
final FocusNode _commentsFocusNode = FocusNode();
|
||||||
@ -62,12 +64,14 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
late TextEditingController _visaCommentsController = TextEditingController();
|
late TextEditingController _visaCommentsController = TextEditingController();
|
||||||
|
|
||||||
bool _tripTypeFocused = false;
|
bool _tripTypeFocused = false;
|
||||||
|
bool _countryFocused = false;
|
||||||
bool _isHotelNameFocused = false;
|
bool _isHotelNameFocused = false;
|
||||||
bool _dateFocus = false;
|
bool _dateFocus = false;
|
||||||
bool _commentsFocus = false;
|
bool _commentsFocus = false;
|
||||||
|
|
||||||
String? selectedPurpose;
|
String? selectedPurpose;
|
||||||
String? selectedCountry;
|
String? selectedCountry;
|
||||||
|
Color layoutColor = Colors.grey;
|
||||||
|
|
||||||
Map<String, String> errorMessages = {};
|
Map<String, String> errorMessages = {};
|
||||||
|
|
||||||
@ -97,8 +101,11 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
loadInitialData();
|
||||||
|
});
|
||||||
_addFocusListener(_tripTypeFocusNode, (focus) => _tripTypeFocused = focus);
|
_addFocusListener(_tripTypeFocusNode, (focus) => _tripTypeFocused = focus);
|
||||||
|
_addFocusListener(_countryFocusNode, (focus) => _countryFocused = focus);
|
||||||
_addFocusListener(
|
_addFocusListener(
|
||||||
_hotelNameFocusNode,
|
_hotelNameFocusNode,
|
||||||
(focus) => _isHotelNameFocused = focus,
|
(focus) => _isHotelNameFocused = focus,
|
||||||
@ -144,6 +151,24 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void loadInitialData() async {
|
||||||
|
String? layoutString = await getLayoutColor();
|
||||||
|
|
||||||
|
// setState(() {
|
||||||
|
// layoutColor =
|
||||||
|
// layoutString != null
|
||||||
|
// ? Color(int.parse(layoutString))
|
||||||
|
// : Colors.redAccent;
|
||||||
|
// });
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
layoutColor =
|
||||||
|
layoutString != null
|
||||||
|
? Color(int.parse(layoutString))
|
||||||
|
: Colors.redAccent;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void _addFocusListener(FocusNode node, Function(bool) updateState) {
|
void _addFocusListener(FocusNode node, Function(bool) updateState) {
|
||||||
node.addListener(() {
|
node.addListener(() {
|
||||||
setState(() {
|
setState(() {
|
||||||
@ -217,6 +242,7 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_tripTypeFocusNode.dispose();
|
_tripTypeFocusNode.dispose();
|
||||||
|
_countryFocusNode.dispose();
|
||||||
_tripTypeController.dispose();
|
_tripTypeController.dispose();
|
||||||
_hotelNameController.dispose();
|
_hotelNameController.dispose();
|
||||||
_fromController.dispose();
|
_fromController.dispose();
|
||||||
@ -519,12 +545,27 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
CustomTextFieldItnerarySubWrapper(
|
CustomTextFieldItnerarySubWrapper(
|
||||||
isFocused: _isHotelNameFocused,
|
isFocused: _isHotelNameFocused,
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 0),
|
||||||
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: Focus(
|
||||||
|
focusNode: _countryFocusNode,
|
||||||
|
|
||||||
|
onFocusChange: (hasFocus) {
|
||||||
|
setState(() {
|
||||||
|
_countryFocused = hasFocus;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: GestureDetector(
|
||||||
|
//
|
||||||
|
onTap: () {
|
||||||
|
// Request focus when user taps
|
||||||
|
_countryFocusNode?.requestFocus();
|
||||||
|
},
|
||||||
child: DropdownSearch<String>(
|
child: DropdownSearch<String>(
|
||||||
selectedItem: countryMap[selectedCountry],
|
selectedItem: countryMap[selectedCountry],
|
||||||
popupProps: PopupProps.menu(
|
popupProps: PopupProps.menu(
|
||||||
@ -575,8 +616,32 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
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(horizontal: 1),
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(5),
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(_countryFocused ?? false)
|
||||||
|
? layoutColor!
|
||||||
|
: Colors.white,
|
||||||
|
width: 1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(_countryFocused ?? false)
|
||||||
|
? layoutColor
|
||||||
|
: Colors.white,
|
||||||
|
// : const Color(0xFFD6D5E6),
|
||||||
|
width: 1,
|
||||||
|
// const Color(0xFFD6D5E6),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(color: layoutColor, width: 1),
|
||||||
|
),
|
||||||
|
contentPadding: EdgeInsets.symmetric(horizontal: 10),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
dropdownBuilder:
|
dropdownBuilder:
|
||||||
@ -598,7 +663,7 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
.key;
|
.key;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
),
|
),),),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (errorMessages["country_code"] != null) ...[
|
if (errorMessages["country_code"] != null) ...[
|
||||||
@ -659,10 +724,24 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
CustomTextFieldWrapper(
|
CustomTextFieldWrapper(
|
||||||
isFocused: _tripTypeFocused,
|
isFocused: _tripTypeFocused,
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 0),
|
||||||
width: isDesktop ? MediaQuery.of(context).size.width * 0.15 : null,
|
width: isDesktop ? MediaQuery.of(context).size.width * 0.15 : null,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
|
child: Focus(
|
||||||
|
focusNode: _tripTypeFocusNode,
|
||||||
|
onFocusChange: (hasFocus) {
|
||||||
|
setState(() {
|
||||||
|
_tripTypeFocused = hasFocus;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: GestureDetector(
|
||||||
|
//
|
||||||
|
onTap: () {
|
||||||
|
// Request focus when user taps
|
||||||
|
_tripTypeFocusNode?.requestFocus();
|
||||||
|
},
|
||||||
child: DropdownSearch<Map<String, dynamic>>(
|
child: DropdownSearch<Map<String, dynamic>>(
|
||||||
items: purposeList.cast<Map<String, dynamic>>(),
|
items: purposeList.cast<Map<String, dynamic>>(),
|
||||||
selectedItem: purposeList.firstWhere(
|
selectedItem: purposeList.firstWhere(
|
||||||
@ -690,9 +769,33 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
dropdownDecoratorProps: const DropDownDecoratorProps(
|
dropdownDecoratorProps: DropDownDecoratorProps(
|
||||||
dropdownSearchDecoration: InputDecoration(
|
dropdownSearchDecoration: InputDecoration(
|
||||||
border: InputBorder.none,
|
// border: InputBorder.none,
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(5),
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(_tripTypeFocused ?? false)
|
||||||
|
? layoutColor!
|
||||||
|
: Colors.white,
|
||||||
|
width: 0.5,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(_tripTypeFocused ?? false)
|
||||||
|
? layoutColor
|
||||||
|
: Colors.white,
|
||||||
|
// : const Color(0xFFD6D5E6),
|
||||||
|
width: 0.5,
|
||||||
|
// const Color(0xFFD6D5E6),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(color: layoutColor, width: 0.5),
|
||||||
|
),
|
||||||
contentPadding: EdgeInsets.symmetric(
|
contentPadding: EdgeInsets.symmetric(
|
||||||
horizontal: 10,
|
horizontal: 10,
|
||||||
vertical: 10,
|
vertical: 10,
|
||||||
@ -734,7 +837,7 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
),
|
),),),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (errorMessages["type_of_visa"] != null) ...[
|
if (errorMessages["type_of_visa"] != null) ...[
|
||||||
@ -764,6 +867,7 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
height: 40,
|
height: 40,
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
|
_dateFocusNode.requestFocus();
|
||||||
await _selectCheckOutDate(context);
|
await _selectCheckOutDate(context);
|
||||||
if (_dateController.text.isNotEmpty) {
|
if (_dateController.text.isNotEmpty) {
|
||||||
setState(() {
|
setState(() {
|
||||||
|
|||||||
@ -34,6 +34,7 @@ import '../../routes/custom_drawer.dart';
|
|||||||
import '../../services/apiService.dart';
|
import '../../services/apiService.dart';
|
||||||
import '../../utils/auth_utils.dart';
|
import '../../utils/auth_utils.dart';
|
||||||
import '../../widgets/custom_breadcrumb_navigation.dart';
|
import '../../widgets/custom_breadcrumb_navigation.dart';
|
||||||
|
import '../../widgets/custom_user_form.dart';
|
||||||
import '../../widgets/custom_user_travel.dart';
|
import '../../widgets/custom_user_travel.dart';
|
||||||
import 'dialog_placeholders.dart';
|
import 'dialog_placeholders.dart';
|
||||||
|
|
||||||
@ -63,6 +64,8 @@ class TemplateState extends State<Template> {
|
|||||||
List<String> placeholders = [];
|
List<String> placeholders = [];
|
||||||
Map<String, FocusNode> focusNodes = {};
|
Map<String, FocusNode> focusNodes = {};
|
||||||
Map<String, bool> focusStates = {};
|
Map<String, bool> focusStates = {};
|
||||||
|
bool isDisable = false;
|
||||||
|
|
||||||
|
|
||||||
late QuillController _controller = QuillController.basic();
|
late QuillController _controller = QuillController.basic();
|
||||||
final FocusNode _focusNode = FocusNode();
|
final FocusNode _focusNode = FocusNode();
|
||||||
@ -449,6 +452,7 @@ class TemplateState extends State<Template> {
|
|||||||
// print('doc $doc');
|
// print('doc $doc');
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
|
isDisable = true;
|
||||||
updateTemplateData(data);
|
updateTemplateData(data);
|
||||||
// This triggers UI rebuild with error messages
|
// This triggers UI rebuild with error messages
|
||||||
// if (validateData()) {
|
// if (validateData()) {
|
||||||
@ -478,14 +482,19 @@ class TemplateState extends State<Template> {
|
|||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
print("policyData submitted successfully!");
|
print("policyData submitted successfully!");
|
||||||
print("Response: ${response.body}");
|
print("Response: ${response.body}");
|
||||||
|
setState(() {
|
||||||
|
isDisable = false; });
|
||||||
context.go('/templateList');
|
context.go('/templateList');
|
||||||
} else {
|
} else {
|
||||||
print("Failed to submit policyData. Status: ${response.statusCode}");
|
print("Failed to submit policyData. Status: ${response.statusCode}");
|
||||||
print("Error: ${response.body}");
|
print("Error: ${response.body}");
|
||||||
|
setState(() {
|
||||||
|
isDisable = false; });
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(" Error submitting policyData: $e");
|
print(" Error submitting policyData: $e");
|
||||||
|
setState(() {
|
||||||
|
isDisable = false; });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -562,7 +571,7 @@ class TemplateState extends State<Template> {
|
|||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
breadcrumbItems: [
|
breadcrumbItems: [
|
||||||
BreadcrumbItem(
|
BreadcrumbItem(
|
||||||
title: 'Organization Settings',
|
title: 'Org Settings',
|
||||||
tooltip: 'Go To Organization Settings',
|
tooltip: 'Go To Organization Settings',
|
||||||
onTap: (context) {
|
onTap: (context) {
|
||||||
context.go("/OrganizationSettings");
|
context.go("/OrganizationSettings");
|
||||||
@ -608,7 +617,7 @@ class TemplateState extends State<Template> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldUserTravellerWrapper(
|
CustomTextFieldUserWrapper(
|
||||||
// isFocused: false,
|
// isFocused: false,
|
||||||
isFocused: focusStates["subjectFocused"] ?? false,
|
isFocused: focusStates["subjectFocused"] ?? false,
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
@ -618,7 +627,7 @@ class TemplateState extends State<Template> {
|
|||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
||||||
focusNode: focusNodes["subjectNode"],
|
focusNode: focusNodes["subjectFocusNode"],
|
||||||
controller: controllers["subject"],
|
controller: controllers["subject"],
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
// _clearError("local_id_num");
|
// _clearError("local_id_num");
|
||||||
@ -762,8 +771,14 @@ class TemplateState extends State<Template> {
|
|||||||
SizedBox(width: 10),
|
SizedBox(width: 10),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: isDisable
|
||||||
handleSubmit();
|
? null
|
||||||
|
: () async {
|
||||||
|
setState(() {
|
||||||
|
isDisable = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
await handleSubmit();
|
||||||
// You can get text from commentController.text
|
// You can get text from commentController.text
|
||||||
// Navigator.of(context).pop(); // Close the modal
|
// Navigator.of(context).pop(); // Close the modal
|
||||||
},
|
},
|
||||||
|
|||||||
@ -74,6 +74,10 @@ class TemplateForexState extends State<TemplateForex> {
|
|||||||
late int templateId = 0;
|
late int templateId = 0;
|
||||||
late String templateName = "";
|
late String templateName = "";
|
||||||
late List<Map<String, dynamic>> placeholderList = [];
|
late List<Map<String, dynamic>> placeholderList = [];
|
||||||
|
bool isDisable = false;
|
||||||
|
|
||||||
|
Map<String, FocusNode> focusNodes = {};
|
||||||
|
Map<String, bool> focusStates = {};
|
||||||
|
|
||||||
Map<String, dynamic> get TemplateData {
|
Map<String, dynamic> get TemplateData {
|
||||||
final data = {
|
final data = {
|
||||||
@ -118,6 +122,18 @@ class TemplateForexState extends State<TemplateForex> {
|
|||||||
// updateData();
|
// updateData();
|
||||||
// loadinitializeData();
|
// loadinitializeData();
|
||||||
// loadInitialData();
|
// loadInitialData();
|
||||||
|
for (var field in dataHeader) {
|
||||||
|
focusNodes["${field}FocusNode"] = FocusNode();
|
||||||
|
focusStates["${field}Focused"] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var key in focusNodes.keys) {
|
||||||
|
_addFocusListener(focusNodes[key]!, (focus) {
|
||||||
|
setState(() {
|
||||||
|
focusStates[key.replaceFirst("FocusNode", "Focused")] = focus;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _checkAuthAndLoadData() async {
|
void _checkAuthAndLoadData() async {
|
||||||
@ -151,6 +167,22 @@ class TemplateForexState extends State<TemplateForex> {
|
|||||||
// _editorFocusNode.dispose();
|
// _editorFocusNode.dispose();
|
||||||
// super.dispose();
|
// super.dispose();
|
||||||
// }
|
// }
|
||||||
|
void dispose() {
|
||||||
|
for (var node in focusNodes.values) {
|
||||||
|
node.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _addFocusListener(FocusNode node, Function(bool) updateState) {
|
||||||
|
node.addListener(() {
|
||||||
|
setState(() {
|
||||||
|
updateState(node.hasFocus);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void loadinitializeData() async {
|
void loadinitializeData() async {
|
||||||
orgId = await getOrgId();
|
orgId = await getOrgId();
|
||||||
userId = await getUserId();
|
userId = await getUserId();
|
||||||
@ -437,6 +469,7 @@ class TemplateForexState extends State<TemplateForex> {
|
|||||||
// print('doc $doc');
|
// print('doc $doc');
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
|
isDisable = true;
|
||||||
updateTemplateData(data);
|
updateTemplateData(data);
|
||||||
// This triggers UI rebuild with error messages
|
// This triggers UI rebuild with error messages
|
||||||
// if (validateData()) {
|
// if (validateData()) {
|
||||||
@ -466,14 +499,23 @@ class TemplateForexState extends State<TemplateForex> {
|
|||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
print("policyData submitted successfully!");
|
print("policyData submitted successfully!");
|
||||||
print("Response: ${response.body}");
|
print("Response: ${response.body}");
|
||||||
|
// context.go('/templateList');
|
||||||
context.go('/templateList');
|
context.go('/OrganizationSettings');
|
||||||
|
setState(() {
|
||||||
|
isDisable = false;
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
print("Failed to submit policyData. Status: ${response.statusCode}");
|
print("Failed to submit policyData. Status: ${response.statusCode}");
|
||||||
print("Error: ${response.body}");
|
print("Error: ${response.body}");
|
||||||
|
setState(() {
|
||||||
|
isDisable = false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(" Error submitting policyData: $e");
|
print(" Error submitting policyData: $e");
|
||||||
|
setState(() {
|
||||||
|
isDisable = false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -545,7 +587,7 @@ class TemplateForexState extends State<TemplateForex> {
|
|||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
breadcrumbItems: [
|
breadcrumbItems: [
|
||||||
BreadcrumbItem(
|
BreadcrumbItem(
|
||||||
title: 'Organization Settings',
|
title: 'Org Settings',
|
||||||
tooltip: 'Go To Organization Settings',
|
tooltip: 'Go To Organization Settings',
|
||||||
onTap: (context) {
|
onTap: (context) {
|
||||||
context.go("/OrganizationSettings");
|
context.go("/OrganizationSettings");
|
||||||
@ -596,7 +638,8 @@ class TemplateForexState extends State<TemplateForex> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldUserTravellerWrapper(
|
CustomTextFieldUserTravellerWrapper(
|
||||||
isFocused: false,
|
// isFocused: false,
|
||||||
|
isFocused: focusStates["subjectFocused"] ?? false,
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
width: isDesktop ? MediaQuery.of(context).size.width * 0.8 : null,
|
width: isDesktop ? MediaQuery.of(context).size.width * 0.8 : null,
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
@ -604,6 +647,7 @@ class TemplateForexState extends State<TemplateForex> {
|
|||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
||||||
|
focusNode: focusNodes["subjectFocusNode"],
|
||||||
controller: controllers["subject"],
|
controller: controllers["subject"],
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
// _clearError("local_id_num");
|
// _clearError("local_id_num");
|
||||||
@ -818,8 +862,14 @@ class TemplateForexState extends State<TemplateForex> {
|
|||||||
SizedBox(width: 10),
|
SizedBox(width: 10),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: isDisable
|
||||||
handleSubmit();
|
? null
|
||||||
|
: () async {
|
||||||
|
setState(() {
|
||||||
|
isDisable = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
await handleSubmit();
|
||||||
// You can get text from commentController.text
|
// You can get text from commentController.text
|
||||||
// Navigator.of(context).pop(); // Close the modal
|
// Navigator.of(context).pop(); // Close the modal
|
||||||
},
|
},
|
||||||
|
|||||||
@ -159,6 +159,7 @@ class TemplatesListState extends State<TemplatesList> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<List<dynamic>> fetchGetForex() async {
|
Future<List<dynamic>> fetchGetForex() async {
|
||||||
|
// return [];
|
||||||
orgId = await getOrgId();
|
orgId = await getOrgId();
|
||||||
// final String apiUrlData = '$apiUrl/api/getForexPerdiemList';
|
// final String apiUrlData = '$apiUrl/api/getForexPerdiemList';
|
||||||
final String apiUrlData = '$apiUrl/api/template?org_id=${orgId}';
|
final String apiUrlData = '$apiUrl/api/template?org_id=${orgId}';
|
||||||
@ -446,7 +447,7 @@ class TemplatesListState extends State<TemplatesList> {
|
|||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
breadcrumbItems: [
|
breadcrumbItems: [
|
||||||
BreadcrumbItem(
|
BreadcrumbItem(
|
||||||
title: 'Organization Settings',
|
title: 'Org Settings',
|
||||||
tooltip: 'Go To Organization Settings',
|
tooltip: 'Go To Organization Settings',
|
||||||
onTap: (context) {
|
onTap: (context) {
|
||||||
context.go("/OrganizationSettings");
|
context.go("/OrganizationSettings");
|
||||||
@ -594,6 +595,7 @@ class TemplatesListState extends State<TemplatesList> {
|
|||||||
FutureBuilder<List<dynamic>>(
|
FutureBuilder<List<dynamic>>(
|
||||||
future: futureTemplates,
|
future: futureTemplates,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
|
final adjHgt = MediaQuery.of(context).size.height;
|
||||||
if (futureTemplates == null) {
|
if (futureTemplates == null) {
|
||||||
return CircularProgressIndicator();
|
return CircularProgressIndicator();
|
||||||
}
|
}
|
||||||
@ -618,9 +620,9 @@ class TemplatesListState extends State<TemplatesList> {
|
|||||||
// fontWeight: FontWeight.bold,
|
// fontWeight: FontWeight.bold,
|
||||||
// color: Colors.redAccent),
|
// color: Colors.redAccent),
|
||||||
// ),
|
// ),
|
||||||
const SizedBox(height: 8),
|
SizedBox(height: adjHgt / 4),
|
||||||
Text(
|
Text(
|
||||||
"No Templates Available ",
|
"No Data Found ",
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
@ -629,15 +631,15 @@ class TemplatesListState extends State<TemplatesList> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
Text(
|
// Text(
|
||||||
"Please Create Templates",
|
// "Please Create Templates",
|
||||||
textAlign: TextAlign.center,
|
// textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
// style: GoogleFonts.poppins(
|
||||||
fontSize: 16,
|
// fontSize: 16,
|
||||||
color: Colors.grey,
|
// color: Colors.grey,
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
const SizedBox(height: 20),
|
// const SizedBox(height: 20),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@ -30,6 +30,8 @@ class _MailSettingState extends State<MailSetting> {
|
|||||||
Map<String, String> errorMessages = {};
|
Map<String, String> errorMessages = {};
|
||||||
final Map<String, TextEditingController> controllers = {};
|
final Map<String, TextEditingController> controllers = {};
|
||||||
bool _obscurePassword = true;
|
bool _obscurePassword = true;
|
||||||
|
Map<String, FocusNode> focusNodes = {};
|
||||||
|
Map<String, bool> focusStates = {};
|
||||||
|
|
||||||
List<String> dataHeader = [
|
List<String> dataHeader = [
|
||||||
"host",
|
"host",
|
||||||
@ -40,6 +42,14 @@ class _MailSettingState extends State<MailSetting> {
|
|||||||
"toEmail",
|
"toEmail",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
for (var node in focusNodes.values) {
|
||||||
|
node.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
Map<String, dynamic> getMailData() => mailData;
|
Map<String, dynamic> getMailData() => mailData;
|
||||||
|
|
||||||
Map<String, dynamic> get mailData {
|
Map<String, dynamic> get mailData {
|
||||||
@ -70,6 +80,18 @@ class _MailSettingState extends State<MailSetting> {
|
|||||||
widget.onMailDataChanged(mailData); // Notify parent
|
widget.onMailDataChanged(mailData); // Notify parent
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
for (var field in dataHeader) {
|
||||||
|
focusNodes["${field}FocusNode"] = FocusNode();
|
||||||
|
focusStates["${field}Focused"] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var key in focusNodes.keys) {
|
||||||
|
_addFocusListener(focusNodes[key]!, (focus) {
|
||||||
|
setState(() {
|
||||||
|
focusStates[key.replaceFirst("FocusNode", "Focused")] = focus;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -105,6 +127,14 @@ class _MailSettingState extends State<MailSetting> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _addFocusListener(FocusNode node, Function(bool) updateState) {
|
||||||
|
node.addListener(() {
|
||||||
|
setState(() {
|
||||||
|
updateState(node.hasFocus);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void handleTestMailSubmit() {
|
void handleTestMailSubmit() {
|
||||||
print("TEStMailData- $mailData");
|
print("TEStMailData- $mailData");
|
||||||
|
|
||||||
@ -285,7 +315,7 @@ class _MailSettingState extends State<MailSetting> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldWrapper(
|
CustomTextFieldWrapper(
|
||||||
isFocused: false,
|
isFocused: focusStates["userNameFocused"] ?? false,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
width:
|
width:
|
||||||
widget.isDesktop
|
widget.isDesktop
|
||||||
@ -295,6 +325,7 @@ class _MailSettingState extends State<MailSetting> {
|
|||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
// focusNode: _destinationFocusNode,
|
// focusNode: _destinationFocusNode,
|
||||||
|
focusNode: focusNodes["userNameFocusNode"],
|
||||||
controller: controllers["userName"],
|
controller: controllers["userName"],
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
_clearError("mail_user_name");
|
_clearError("mail_user_name");
|
||||||
@ -337,7 +368,7 @@ class _MailSettingState extends State<MailSetting> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldWrapper(
|
CustomTextFieldWrapper(
|
||||||
isFocused: false,
|
isFocused: focusStates["mail_passwordFocused"] ?? false,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
width:
|
width:
|
||||||
widget.isDesktop
|
widget.isDesktop
|
||||||
@ -347,6 +378,7 @@ class _MailSettingState extends State<MailSetting> {
|
|||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
// focusNode: _destinationFocusNode,
|
// focusNode: _destinationFocusNode,
|
||||||
|
focusNode: focusNodes["mail_passwordFocusNode"],
|
||||||
controller: controllers["mail_password"],
|
controller: controllers["mail_password"],
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
_clearError("mail_password");
|
_clearError("mail_password");
|
||||||
@ -412,7 +444,7 @@ class _MailSettingState extends State<MailSetting> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldWrapper(
|
CustomTextFieldWrapper(
|
||||||
isFocused: false,
|
isFocused: focusStates["senderEmailFocused"] ?? false,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
width:
|
width:
|
||||||
widget.isDesktop
|
widget.isDesktop
|
||||||
@ -422,6 +454,7 @@ class _MailSettingState extends State<MailSetting> {
|
|||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
// focusNode: _destinationFocusNode,
|
// focusNode: _destinationFocusNode,
|
||||||
|
focusNode: focusNodes["senderEmailFocusNode"],
|
||||||
controller: controllers["senderEmail"],
|
controller: controllers["senderEmail"],
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
_clearError("sender_email");
|
_clearError("sender_email");
|
||||||
@ -474,7 +507,7 @@ class _MailSettingState extends State<MailSetting> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldWrapper(
|
CustomTextFieldWrapper(
|
||||||
isFocused: false,
|
isFocused: focusStates["hostFocused"] ?? false,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
width:
|
width:
|
||||||
widget.isDesktop
|
widget.isDesktop
|
||||||
@ -484,6 +517,7 @@ class _MailSettingState extends State<MailSetting> {
|
|||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
// focusNode: _destinationFocusNode,
|
// focusNode: _destinationFocusNode,
|
||||||
|
focusNode: focusNodes["hostFocusNode"],
|
||||||
controller: controllers["host"],
|
controller: controllers["host"],
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
_clearError("mail_host");
|
_clearError("mail_host");
|
||||||
@ -526,7 +560,7 @@ class _MailSettingState extends State<MailSetting> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldWrapper(
|
CustomTextFieldWrapper(
|
||||||
isFocused: false,
|
isFocused: focusStates["portFocused"] ?? false,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
width:
|
width:
|
||||||
widget.isDesktop
|
widget.isDesktop
|
||||||
@ -536,6 +570,7 @@ class _MailSettingState extends State<MailSetting> {
|
|||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
// focusNode: _destinationFocusNode,
|
// focusNode: _destinationFocusNode,
|
||||||
|
focusNode: focusNodes["portFocusNode"],
|
||||||
controller: controllers["port"],
|
controller: controllers["port"],
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
_clearError("mail_port");
|
_clearError("mail_port");
|
||||||
@ -581,7 +616,7 @@ class _MailSettingState extends State<MailSetting> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldWrapper(
|
CustomTextFieldWrapper(
|
||||||
isFocused: false,
|
isFocused: focusStates["toEmailFocused"] ?? false,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
width:
|
width:
|
||||||
widget.isDesktop
|
widget.isDesktop
|
||||||
@ -591,6 +626,7 @@ class _MailSettingState extends State<MailSetting> {
|
|||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
// focusNode: _destinationFocusNode,
|
// focusNode: _destinationFocusNode,
|
||||||
|
focusNode: focusNodes["toEmailFocusNode"],
|
||||||
controller: controllers["toEmail"],
|
controller: controllers["toEmail"],
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
_clearError("to_mail");
|
_clearError("to_mail");
|
||||||
|
|||||||
@ -591,7 +591,7 @@ class _OrgSetUpState extends State<OrgSetUp> {
|
|||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
breadcrumbItems: [
|
breadcrumbItems: [
|
||||||
BreadcrumbItem(
|
BreadcrumbItem(
|
||||||
title: 'Organization Settings',
|
title: 'Org Settings',
|
||||||
tooltip: 'Go To Organization Settings',
|
tooltip: 'Go To Organization Settings',
|
||||||
onTap: (context) {
|
onTap: (context) {
|
||||||
context.go("/OrganizationSettings");
|
context.go("/OrganizationSettings");
|
||||||
|
|||||||
@ -150,7 +150,7 @@ class _OrganizationListState extends State<OrganizationList> {
|
|||||||
|
|
||||||
Widget buildGroupListView(bool isDesktop) {
|
Widget buildGroupListView(bool isDesktop) {
|
||||||
if (apiAllOrganization == null || apiAllOrganization!.isEmpty) {
|
if (apiAllOrganization == null || apiAllOrganization!.isEmpty) {
|
||||||
return Center(child: Text("No groups found."));
|
return Center(child: Text("No Data Found."));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ListView.builder(
|
return ListView.builder(
|
||||||
|
|||||||
@ -54,6 +54,7 @@ class ForexDataState extends State<ForexData> {
|
|||||||
String? userId;
|
String? userId;
|
||||||
int? forexDataId;
|
int? forexDataId;
|
||||||
late String isActive = "1";
|
late String isActive = "1";
|
||||||
|
bool isDisable = false;
|
||||||
|
|
||||||
bool isCashEditing = false;
|
bool isCashEditing = false;
|
||||||
bool isCardEditing = false;
|
bool isCardEditing = false;
|
||||||
@ -242,9 +243,12 @@ class ForexDataState extends State<ForexData> {
|
|||||||
userId = await getUserId();
|
userId = await getUserId();
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
|
isDisable = true;
|
||||||
// This triggers UI rebuild with error messages
|
// This triggers UI rebuild with error messages
|
||||||
if (validateData()) {
|
if (validateData()) {
|
||||||
postForexData();
|
postForexData();
|
||||||
|
}else{
|
||||||
|
isDisable = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -252,6 +256,7 @@ class ForexDataState extends State<ForexData> {
|
|||||||
print("ForexDAta - $forexData1");
|
print("ForexDAta - $forexData1");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Future<void> postForexData({int isActive = 1}) async {
|
Future<void> postForexData({int isActive = 1}) async {
|
||||||
// final remarksData = getData();
|
// final remarksData = getData();
|
||||||
|
|
||||||
@ -316,9 +321,19 @@ class ForexDataState extends State<ForexData> {
|
|||||||
await widget.fetchGetForex();
|
await widget.fetchGetForex();
|
||||||
|
|
||||||
// dispose();
|
// dispose();
|
||||||
Navigator.of(context).pop();
|
if (context.mounted) {
|
||||||
|
Navigator.of(context).pop(); // Close modal only if mounted
|
||||||
|
}
|
||||||
|
setState(() {
|
||||||
|
isDisable = false;
|
||||||
|
});
|
||||||
} else if (response.statusCode == 404) {
|
} else if (response.statusCode == 404) {
|
||||||
|
if (context.mounted) {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
|
}
|
||||||
|
setState(() {
|
||||||
|
isDisable = false;
|
||||||
|
});
|
||||||
final message = jsonDecode(response.body)['message'] ?? 'Unknown error';
|
final message = jsonDecode(response.body)['message'] ?? 'Unknown error';
|
||||||
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
@ -331,9 +346,15 @@ class ForexDataState extends State<ForexData> {
|
|||||||
} 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}");
|
||||||
|
setState(() {
|
||||||
|
isDisable = false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(" Error submitting plan: $e");
|
print(" Error submitting plan: $e");
|
||||||
|
setState(() {
|
||||||
|
isDisable = false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -887,10 +908,26 @@ class ForexDataState extends State<ForexData> {
|
|||||||
// ),
|
// ),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
onPressed: () {
|
// onPressed: () {
|
||||||
handleSubmit();
|
// handleSubmit();
|
||||||
|
// // You can get text from commentController.text
|
||||||
|
// // Navigator.of(context).pop(); // Close the modal
|
||||||
|
// },
|
||||||
|
onPressed: isDisable
|
||||||
|
? null
|
||||||
|
: () async {
|
||||||
|
setState(() {
|
||||||
|
isDisable = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
await handleSubmit();
|
||||||
// You can get text from commentController.text
|
// You can get text from commentController.text
|
||||||
// Navigator.of(context).pop(); // Close the modal
|
// Navigator.of(context).pop(); // Close the modal
|
||||||
|
|
||||||
|
// Optional: re-enable only on error
|
||||||
|
// setState(() {
|
||||||
|
// isDisable = false;
|
||||||
|
// });
|
||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: widget.layoutColor,
|
backgroundColor: widget.layoutColor,
|
||||||
|
|||||||
@ -364,6 +364,16 @@ class ForexDataListState extends State<ForexDataList> {
|
|||||||
print("filteredForex: $filteredForex");
|
print("filteredForex: $filteredForex");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String toTitleCase(String input) {
|
||||||
|
return input
|
||||||
|
.toLowerCase()
|
||||||
|
.split(' ')
|
||||||
|
.map((word) => word.isNotEmpty
|
||||||
|
? word[0].toUpperCase() + word.substring(1)
|
||||||
|
: '')
|
||||||
|
.join(' ');
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ResponsiveBuilder(
|
return ResponsiveBuilder(
|
||||||
@ -454,7 +464,7 @@ class ForexDataListState extends State<ForexDataList> {
|
|||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
breadcrumbItems: [
|
breadcrumbItems: [
|
||||||
BreadcrumbItem(
|
BreadcrumbItem(
|
||||||
title: 'Organization Settings',
|
title: 'Org Settings',
|
||||||
tooltip: 'Go To Organization Settings',
|
tooltip: 'Go To Organization Settings',
|
||||||
onTap: (context) {
|
onTap: (context) {
|
||||||
context.go("/OrganizationSettings");
|
context.go("/OrganizationSettings");
|
||||||
@ -649,7 +659,7 @@ class ForexDataListState extends State<ForexDataList> {
|
|||||||
// ),
|
// ),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
Text(
|
Text(
|
||||||
"No Perdiem Available ",
|
"No Data Found ",
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
@ -658,15 +668,15 @@ class ForexDataListState extends State<ForexDataList> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
Text(
|
// Text(
|
||||||
"Please Create Perdiem Amount",
|
// "Please Create Perdiem Amount",
|
||||||
textAlign: TextAlign.center,
|
// textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
// style: GoogleFonts.poppins(
|
||||||
fontSize: 16,
|
// fontSize: 16,
|
||||||
color: Colors.grey,
|
// color: Colors.grey,
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
const SizedBox(height: 20),
|
// const SizedBox(height: 20),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -780,7 +790,7 @@ class ForexDataListState extends State<ForexDataList> {
|
|||||||
),
|
),
|
||||||
DataCell(
|
DataCell(
|
||||||
Text(
|
Text(
|
||||||
forex['country_name'] ?? '',
|
toTitleCase(forex['country_name']) ?? '',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
fontFamily: "Inter",
|
fontFamily: "Inter",
|
||||||
@ -911,7 +921,7 @@ class ForexDataListState extends State<ForexDataList> {
|
|||||||
MainAxisAlignment.spaceBetween,
|
MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
forex['country_name'] ?? 'N/A',
|
toTitleCase(forex['country_name']) ?? 'N/A',
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 10,
|
fontSize: 10,
|
||||||
color: Colors.black87,
|
color: Colors.black87,
|
||||||
@ -1113,7 +1123,7 @@ class ForexDataListState extends State<ForexDataList> {
|
|||||||
filteredForex.isEmpty
|
filteredForex.isEmpty
|
||||||
? Center(
|
? Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
"No matches found",
|
"No Matches Found",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: Colors.grey,
|
color: Colors.grey,
|
||||||
@ -1128,7 +1138,7 @@ class ForexDataListState extends State<ForexDataList> {
|
|||||||
filteredForex.isEmpty
|
filteredForex.isEmpty
|
||||||
? Center(
|
? Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
"No matches found",
|
"No Matches Found",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: Colors.grey,
|
color: Colors.grey,
|
||||||
|
|||||||
@ -44,6 +44,7 @@ class _CreatePlansState extends State<CreatePlan> {
|
|||||||
|
|
||||||
final FocusNode focusNode = FocusNode();
|
final FocusNode focusNode = FocusNode();
|
||||||
bool isFocused = false;
|
bool isFocused = false;
|
||||||
|
late FocusNode _tripTitleFocusNode;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@ -571,6 +572,10 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
focusStates["${field}Focused"] = false;
|
focusStates["${field}Focused"] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// trip_titleFocusNode.addListener(() {
|
||||||
|
// setState(() {}); // Rebuild when focus changes
|
||||||
|
// });
|
||||||
|
|
||||||
print("Focus Nodes KeysII: ${focusNodes.keys.toList()}");
|
print("Focus Nodes KeysII: ${focusNodes.keys.toList()}");
|
||||||
print("Focus States KeysII: ${focusStates.keys.toList()}");
|
print("Focus States KeysII: ${focusStates.keys.toList()}");
|
||||||
|
|
||||||
@ -1356,9 +1361,10 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
print("hasExceptionalClass: $hasExceptionalClass");
|
print("hasExceptionalClass: $hasExceptionalClass");
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleSubmit() {
|
void handleSubmit() async {
|
||||||
setState(() async {
|
await checkExceptionalClass(); // Do async work first
|
||||||
await checkExceptionalClass();
|
setState(() {
|
||||||
|
// await checkExceptionalClass();
|
||||||
|
|
||||||
print("Handle Submit....after check");
|
print("Handle Submit....after check");
|
||||||
|
|
||||||
@ -3719,7 +3725,7 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildTripName(bool isDesktop) {
|
Widget _buildTN(bool isDesktop) {
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
width: isDesktop ? MediaQuery.of(context).size.width * 0.7443333 : 180,
|
width: isDesktop ? MediaQuery.of(context).size.width * 0.7443333 : 180,
|
||||||
height: 35,
|
height: 35,
|
||||||
@ -3751,6 +3757,49 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _buildTripName(bool isDesktop) {
|
||||||
|
return SizedBox(
|
||||||
|
width: isDesktop ? MediaQuery.of(context).size.width * 0.5 : 180,
|
||||||
|
height: 35,
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
scrollDirection: Axis.horizontal,
|
||||||
|
reverse: false, // show right-end on overflow
|
||||||
|
physics: BouncingScrollPhysics(),
|
||||||
|
child: ConstrainedBox(
|
||||||
|
constraints: BoxConstraints(minWidth: isDesktop ? MediaQuery.of(context).size.width * 0.5 : 180),
|
||||||
|
child: IntrinsicWidth(
|
||||||
|
child: TextField(
|
||||||
|
controller: _tripTitleController,
|
||||||
|
maxLines: 1,
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: isDesktop ? 16 : 14,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
enabled: !widget.isViewMode,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
labelText: "Trip Name *",
|
||||||
|
labelStyle: GoogleFonts.poppins(
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: Colors.grey,
|
||||||
|
),
|
||||||
|
floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||||
|
border: InputBorder.none,
|
||||||
|
contentPadding: EdgeInsets.symmetric(horizontal: 1, vertical: 16),
|
||||||
|
errorText: validationErrors["trip_title"],
|
||||||
|
errorStyle: GoogleFonts.poppins(fontSize: 12, color: Colors.red),
|
||||||
|
),
|
||||||
|
keyboardType: TextInputType.text,
|
||||||
|
scrollPhysics: BouncingScrollPhysics(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Widget _buildApprovalItem(String title, String name) {
|
Widget _buildApprovalItem(String title, String name) {
|
||||||
return Row(
|
return Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
|||||||
@ -278,6 +278,7 @@ class _ListPlansState extends State<ListPlans> {
|
|||||||
|
|
||||||
// Fetch API Data
|
// Fetch API Data
|
||||||
Future<List<Plan>> fetchPlans() async {
|
Future<List<Plan>> fetchPlans() async {
|
||||||
|
// return [];
|
||||||
// final String apiUrldata = '$apiUrl/api/plans';
|
// final String apiUrldata = '$apiUrl/api/plans';
|
||||||
// final String apiUrldata = '$apiUrl/api/plans?user_id=$userId';
|
// final String apiUrldata = '$apiUrl/api/plans?user_id=$userId';
|
||||||
// final String apiUrldata = '$apiUrl/api/plans?user_id=$userId';
|
// final String apiUrldata = '$apiUrl/api/plans?user_id=$userId';
|
||||||
@ -871,22 +872,27 @@ class _ListPlansState extends State<ListPlans> {
|
|||||||
Text(
|
Text(
|
||||||
" No Trips Found",
|
" No Trips Found",
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
|
// style: GoogleFonts.poppins(
|
||||||
|
// fontSize: 20,
|
||||||
|
// fontWeight: FontWeight.w500,
|
||||||
|
// color: Colors.black54,
|
||||||
|
// ),
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.bold,
|
||||||
color: Colors.black54,
|
color: Colors.grey,
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 10),
|
|
||||||
Text(
|
|
||||||
"Please Create Trip",
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
style: GoogleFonts.poppins(
|
|
||||||
fontSize: 12,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
color: Colors.black54,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
// const SizedBox(height: 10),
|
||||||
|
// Text(
|
||||||
|
// "Please Create Trip",
|
||||||
|
// textAlign: TextAlign.center,
|
||||||
|
// style: GoogleFonts.poppins(
|
||||||
|
// fontSize: 12,
|
||||||
|
// fontWeight: FontWeight.w500,
|
||||||
|
// color: Colors.black54,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -1627,7 +1633,7 @@ class _ListPlansState extends State<ListPlans> {
|
|||||||
filteredPlans.isEmpty
|
filteredPlans.isEmpty
|
||||||
? Center(
|
? Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
"No matches found",
|
"No Matches Found",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: Colors.grey,
|
color: Colors.grey,
|
||||||
@ -1642,7 +1648,7 @@ class _ListPlansState extends State<ListPlans> {
|
|||||||
filteredPlans.isEmpty
|
filteredPlans.isEmpty
|
||||||
? Center(
|
? Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
"No matches found",
|
"No Matches Found",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: Colors.grey,
|
color: Colors.grey,
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import 'dart:ui' as html;
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:html' as html;
|
import 'dart:html' as html;
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
import 'dart:html' as html;
|
import 'package:fluttertoast/fluttertoast.dart';
|
||||||
import 'dart:ui' as web;
|
import 'dart:ui' as web;
|
||||||
|
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
@ -50,12 +50,14 @@ class _PolicyState extends State<Policy> {
|
|||||||
Color? layoutColor;
|
Color? layoutColor;
|
||||||
Color? bodyColor;
|
Color? bodyColor;
|
||||||
late String policyType = "domestic";
|
late String policyType = "domestic";
|
||||||
// int? selectedServiceIndex = 1;
|
String selectedServiceDBValue = '1';
|
||||||
ValueNotifier<String> selectedServiceIndex = ValueNotifier("1");
|
ValueNotifier<String> selectedServiceIndex = ValueNotifier("1");
|
||||||
ValueNotifier<String> selectedServicePriorityIndex = ValueNotifier("1");
|
ValueNotifier<String> selectedServicePriorityIndex = ValueNotifier("1");
|
||||||
String selectedService = "train";
|
String selectedService = "train";
|
||||||
// ValueNotifier<String> selectedService = ValueNotifier("Train");
|
// ValueNotifier<String> selectedService = ValueNotifier("Train");
|
||||||
bool isViewMode = false;
|
bool isViewMode = false;
|
||||||
|
bool isDisable = false;
|
||||||
|
bool isSubmitting = false;
|
||||||
|
|
||||||
Map<String, FocusNode> focusNodes = {};
|
Map<String, FocusNode> focusNodes = {};
|
||||||
Map<String, bool> focusStates = {};
|
Map<String, bool> focusStates = {};
|
||||||
@ -118,6 +120,15 @@ class _PolicyState extends State<Policy> {
|
|||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_checkAuthAndLoadData();
|
_checkAuthAndLoadData();
|
||||||
|
focusNodes["policyFocusNode"] = FocusNode();
|
||||||
|
focusStates["policyFocused"] = false;
|
||||||
|
for (var key in focusNodes.keys) {
|
||||||
|
_addFocusListener(focusNodes[key]!, (focus) {
|
||||||
|
setState(() {
|
||||||
|
focusStates[key.replaceFirst("FocusNode", "Focused")] = focus;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
// for (var field in dataHeader) {
|
// for (var field in dataHeader) {
|
||||||
// focusNodes["${field}FocusNode"] = FocusNode();
|
// focusNodes["${field}FocusNode"] = FocusNode();
|
||||||
// focusStates["${field}Focused"] = false;
|
// focusStates["${field}Focused"] = false;
|
||||||
@ -142,7 +153,13 @@ class _PolicyState extends State<Policy> {
|
|||||||
// }
|
// }
|
||||||
// });
|
// });
|
||||||
}
|
}
|
||||||
|
void _addFocusListener(FocusNode node, Function(bool) updateState) {
|
||||||
|
node.addListener(() {
|
||||||
|
setState(() {
|
||||||
|
updateState(node.hasFocus);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
void _checkAuthAndLoadData() async {
|
void _checkAuthAndLoadData() async {
|
||||||
final String? token = await getToken(); // Your async function to get token
|
final String? token = await getToken(); // Your async function to get token
|
||||||
|
|
||||||
@ -366,9 +383,38 @@ class _PolicyState extends State<Policy> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// void handleSubmit() async {
|
||||||
|
// setState(() { isDisable = true; });
|
||||||
|
// print("Services - $services");
|
||||||
|
// print("USR Detail Submit - $policyData");
|
||||||
|
//
|
||||||
|
// policyCriteriaKey.currentState?.saveCurrentPolicy(services);
|
||||||
|
//
|
||||||
|
// // Now the full data is ready in policyDataFromChild
|
||||||
|
// print("Submitting full policyData: $policyData");
|
||||||
|
//
|
||||||
|
// Map<String, dynamic> data = policyData;
|
||||||
|
//
|
||||||
|
// if (!isValidData(data)) {
|
||||||
|
// print("USERDETAILS : $policyData");
|
||||||
|
// print("Validation Failed: Required fields are missing.");
|
||||||
|
// setState(() { isDisable = false; });
|
||||||
|
// return; // Stop execution if validation fails
|
||||||
|
// } else {
|
||||||
|
// // print("USERDETAILS : $policyData");
|
||||||
|
// // orgId = await getOrgId();
|
||||||
|
//
|
||||||
|
// if(isDisable == true){ createPolicyData(data); }
|
||||||
|
// setState(() { isDisable = false; });
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
void handleSubmit() async {
|
void handleSubmit() async {
|
||||||
print("Services - $services");
|
if (isSubmitting || isDisable) return;
|
||||||
print("USR Detail Submit - $policyData");
|
isSubmitting = true;
|
||||||
|
setState(() {
|
||||||
|
isDisable = true;
|
||||||
|
});
|
||||||
|
|
||||||
policyCriteriaKey.currentState?.saveCurrentPolicy(services);
|
policyCriteriaKey.currentState?.saveCurrentPolicy(services);
|
||||||
|
|
||||||
@ -378,18 +424,44 @@ class _PolicyState extends State<Policy> {
|
|||||||
Map<String, dynamic> data = policyData;
|
Map<String, dynamic> data = policyData;
|
||||||
|
|
||||||
if (!isValidData(data)) {
|
if (!isValidData(data)) {
|
||||||
print("USERDETAILS : $policyData");
|
print("Validation Failed");
|
||||||
print("Validation Failed: Required fields are missing.");
|
isSubmitting = false;
|
||||||
setState(() {});
|
setState(() => isDisable = false);
|
||||||
return; // Stop execution if validation fails
|
return;
|
||||||
} else {
|
}
|
||||||
// print("USERDETAILS : $policyData");
|
|
||||||
// orgId = await getOrgId();
|
|
||||||
|
|
||||||
createPolicyData(data);
|
bool result = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
result = await createPolicyData(data);
|
||||||
|
} catch (e) {
|
||||||
|
print("Unexpected error during policy creation: $e");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (result) {
|
||||||
|
// ✅ Only navigate on success
|
||||||
|
context.go('/PolicyList');
|
||||||
|
} else {
|
||||||
|
// ❌ Show error, allow retry
|
||||||
|
Fluttertoast.showToast(
|
||||||
|
msg: "Failed to submit policy. Please try again.",
|
||||||
|
toastLength: Toast.LENGTH_SHORT,
|
||||||
|
gravity: ToastGravity.CENTER,
|
||||||
|
timeInSecForIosWeb: 2,
|
||||||
|
backgroundColor: Colors.redAccent,
|
||||||
|
textColor: Colors.white,
|
||||||
|
fontSize: 18.0,
|
||||||
|
webBgColor: "linear-gradient(to right, #28a745, #28a745)",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isSubmitting = false;
|
||||||
|
setState(() {
|
||||||
|
isDisable = false; // Allow retry
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool isValidData(Map<String, dynamic> data) {
|
bool isValidData(Map<String, dynamic> data) {
|
||||||
errorMessages.clear(); // Reset previous errors
|
errorMessages.clear(); // Reset previous errors
|
||||||
|
|
||||||
@ -444,12 +516,14 @@ class _PolicyState extends State<Policy> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> createPolicyData(Map<String, dynamic> policyData) async {
|
Future<bool> createPolicyData(Map<String, dynamic> policyData) async {
|
||||||
final String apiUrldata = '$apiUrl/api/policy/createOrUpdate';
|
final String apiUrldata = '$apiUrl/api/policy/createOrUpdate';
|
||||||
final token = await getToken(); // Fetch token
|
final token = await getToken(); // Fetch token
|
||||||
|
|
||||||
if (token == null) {
|
if (token == null) {
|
||||||
throw Exception('Token not found. Please log in.');
|
print('Token not found. Please log in.');
|
||||||
|
// throw Exception('Token not found. Please log in.');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
final int? policyId;
|
final int? policyId;
|
||||||
@ -472,14 +546,15 @@ class _PolicyState extends State<Policy> {
|
|||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
print("policyData submitted successfully!");
|
print("policyData submitted successfully!");
|
||||||
print("Response: ${response.body}");
|
print("Response: ${response.body}");
|
||||||
|
return true;
|
||||||
context.go('/PolicyList');
|
|
||||||
} else {
|
} else {
|
||||||
print("Failed to submit policyData. Status: ${response.statusCode}");
|
print("Failed to submit policyData. Status: ${response.statusCode}");
|
||||||
print("Error: ${response.body}");
|
print("Error: ${response.body}");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(" Error submitting policyData: $e");
|
print(" Error submitting policyData: $e");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -792,12 +867,13 @@ class _PolicyState extends State<Policy> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldUserWrapper(
|
CustomTextFieldUserWrapper(
|
||||||
isFocused: false,
|
isFocused: focusStates["policyFocused"] ?? false,
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
style: GoogleFonts.poppins(fontSize: 12),
|
style: GoogleFonts.poppins(fontSize: 12),
|
||||||
|
focusNode: focusNodes["policyFocusNode"],
|
||||||
controller: _policyController,
|
controller: _policyController,
|
||||||
onChanged: (value) => _clearError("name"),
|
onChanged: (value) => _clearError("name"),
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
@ -1073,6 +1149,13 @@ class _PolicyState extends State<Policy> {
|
|||||||
List<String> services =
|
List<String> services =
|
||||||
ServicesChoosed!.map((service) => service['name'].toString()).toList();
|
ServicesChoosed!.map((service) => service['name'].toString()).toList();
|
||||||
|
|
||||||
|
List<String> serviceDBvalue =
|
||||||
|
ServicesChoosed!.map((service) => service['service_id'].toString()).toList();
|
||||||
|
|
||||||
|
print("1093");
|
||||||
|
print(services);
|
||||||
|
print(serviceDBvalue);
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: Axis.horizontal,
|
||||||
@ -1102,12 +1185,17 @@ class _PolicyState extends State<Policy> {
|
|||||||
print("Selected Services - $service - $index");
|
print("Selected Services - $service - $index");
|
||||||
setState(() {
|
setState(() {
|
||||||
selectedServiceIndex.value = index.toString();
|
selectedServiceIndex.value = index.toString();
|
||||||
|
selectedServiceDBValue = serviceDBvalue[entry.key];
|
||||||
selectedService = service;
|
selectedService = service;
|
||||||
|
|
||||||
print(
|
print(
|
||||||
" selectedServiceIndex.value - ${selectedServiceIndex.value}",
|
" selectedServiceIndex.value - ${selectedServiceIndex.value}",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
print(
|
||||||
|
" selectedServiceDBValue.value - ${selectedServiceDBValue}",
|
||||||
|
);
|
||||||
|
|
||||||
// policyCriteriaKey.currentState?.fieldForPolicy();
|
// policyCriteriaKey.currentState?.fieldForPolicy();
|
||||||
// policyCriteriaKey.currentState
|
// policyCriteriaKey.currentState
|
||||||
// ?.addOrUpdatePolicy(selectedServiceIndex.value);
|
// ?.addOrUpdatePolicy(selectedServiceIndex.value);
|
||||||
@ -1308,6 +1396,7 @@ class _PolicyState extends State<Policy> {
|
|||||||
isCost: showCost,
|
isCost: showCost,
|
||||||
selectedTabNotifier: selectedServiceIndex,
|
selectedTabNotifier: selectedServiceIndex,
|
||||||
selectedService: selectedService,
|
selectedService: selectedService,
|
||||||
|
selectedServiceDBValue: selectedServiceDBValue,
|
||||||
userId: userId,
|
userId: userId,
|
||||||
onPolicyDataChanged: (List<Map<String, dynamic>>? policyData) {
|
onPolicyDataChanged: (List<Map<String, dynamic>>? policyData) {
|
||||||
print("🟢 policyData received from child: $policyData");
|
print("🟢 policyData received from child: $policyData");
|
||||||
@ -1493,7 +1582,8 @@ class _PolicyState extends State<Policy> {
|
|||||||
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
|
||||||
|
isViewMode || isDisable ? null : handleSubmit,
|
||||||
child: Text("Submit", style: GoogleFonts.poppins(fontSize: 10)),
|
child: Text("Submit", style: GoogleFonts.poppins(fontSize: 10)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import '../../widgets/custom_user_form.dart';
|
|||||||
class PolicyCriteria extends StatefulWidget {
|
class PolicyCriteria extends StatefulWidget {
|
||||||
bool isDesktop;
|
bool isDesktop;
|
||||||
String selectedService;
|
String selectedService;
|
||||||
|
String selectedServiceDBValue;
|
||||||
final ValueNotifier<String> selectedTabNotifier;
|
final ValueNotifier<String> selectedTabNotifier;
|
||||||
String? userId;
|
String? userId;
|
||||||
bool isClass = true;
|
bool isClass = true;
|
||||||
@ -26,6 +27,7 @@ class PolicyCriteria extends StatefulWidget {
|
|||||||
required this.isDesktop,
|
required this.isDesktop,
|
||||||
required this.selectedService,
|
required this.selectedService,
|
||||||
required this.selectedTabNotifier,
|
required this.selectedTabNotifier,
|
||||||
|
required this.selectedServiceDBValue,
|
||||||
required this.userId,
|
required this.userId,
|
||||||
required this.isClass,
|
required this.isClass,
|
||||||
required this.isCost,
|
required this.isCost,
|
||||||
@ -149,7 +151,7 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
|
|||||||
|
|
||||||
// Step 4: Initialize any missing controllers or data
|
// Step 4: Initialize any missing controllers or data
|
||||||
costController.putIfAbsent(id, () => TextEditingController());
|
costController.putIfAbsent(id, () => TextEditingController());
|
||||||
classAction.putIfAbsent(id, () => "1");
|
classAction.putIfAbsent(id, () => "1"); // working fine
|
||||||
FirstApproverAction.putIfAbsent(id, () => "None");
|
FirstApproverAction.putIfAbsent(id, () => "None");
|
||||||
SecondApproverAction.putIfAbsent(id, () => "None");
|
SecondApproverAction.putIfAbsent(id, () => "None");
|
||||||
ThirdApproverAction.putIfAbsent(id, () => "None");
|
ThirdApproverAction.putIfAbsent(id, () => "None");
|
||||||
@ -170,7 +172,7 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
|
|||||||
policyData?.add({
|
policyData?.add({
|
||||||
"service_id": int.parse(id),
|
"service_id": int.parse(id),
|
||||||
"cost": "",
|
"cost": "",
|
||||||
"class": classAction[id],
|
"class": classAction[id], // working fine
|
||||||
"a1_action": FirstApproverAction[id],
|
"a1_action": FirstApproverAction[id],
|
||||||
"a2_action": SecondApproverAction[id],
|
"a2_action": SecondApproverAction[id],
|
||||||
"a3_action": ThirdApproverAction[id],
|
"a3_action": ThirdApproverAction[id],
|
||||||
@ -204,7 +206,7 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
|
|||||||
|
|
||||||
// classAction[serviceId] = classAction[serviceId]?.toString();
|
// classAction[serviceId] = classAction[serviceId]?.toString();
|
||||||
|
|
||||||
classAction[serviceId] = item['class']?.toString() ?? '';
|
classAction[serviceId] = item['class']?.toString() ?? ''; // working fine
|
||||||
|
|
||||||
FirstApproverAction[serviceId] = item['a1_action']?.toString();
|
FirstApproverAction[serviceId] = item['a1_action']?.toString();
|
||||||
SecondApproverAction[serviceId] = item['a2_action']?.toString();
|
SecondApproverAction[serviceId] = item['a2_action']?.toString();
|
||||||
@ -266,7 +268,7 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
|
|||||||
"service_id": serviceId,
|
"service_id": serviceId,
|
||||||
"cost": costController[serviceId]?.text,
|
"cost": costController[serviceId]?.text,
|
||||||
// "class": classController[serviceId]?.text,
|
// "class": classController[serviceId]?.text,
|
||||||
"class": classAction[serviceId] ?? "",
|
"class": classAction[serviceId] ?? "", // working fine
|
||||||
"a1_action": FirstApproverAction[serviceId],
|
"a1_action": FirstApproverAction[serviceId],
|
||||||
"a2_action": SecondApproverAction[serviceId],
|
"a2_action": SecondApproverAction[serviceId],
|
||||||
"a3_action": ThirdApproverAction[serviceId],
|
"a3_action": ThirdApproverAction[serviceId],
|
||||||
@ -288,7 +290,7 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
|
|||||||
final cost = costController[serviceId]?.text ?? "";
|
final cost = costController[serviceId]?.text ?? "";
|
||||||
|
|
||||||
// final travelClass = classController[serviceId]?.text ?? "";
|
// final travelClass = classController[serviceId]?.text ?? "";
|
||||||
final travelClass = classAction[serviceId];
|
final travelClass = classAction[serviceId]; // working fine
|
||||||
final a1 = FirstApproverAction[serviceId];
|
final a1 = FirstApproverAction[serviceId];
|
||||||
final a2 = SecondApproverAction[serviceId];
|
final a2 = SecondApproverAction[serviceId];
|
||||||
final a3 = ThirdApproverAction[serviceId];
|
final a3 = ThirdApproverAction[serviceId];
|
||||||
@ -456,10 +458,11 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
|
|||||||
); // 👈 Save current values for existing service
|
); // 👈 Save current values for existing service
|
||||||
}
|
}
|
||||||
setState(() {
|
setState(() {
|
||||||
ServiceId = widget.selectedTabNotifier.value ?? "1";
|
// ServiceId = widget.selectedTabNotifier.value ?? "1";
|
||||||
|
ServiceId = widget.selectedServiceDBValue;
|
||||||
// Initialize controllers and variables if not present
|
// Initialize controllers and variables if not present
|
||||||
costController.putIfAbsent(ServiceId!, () => TextEditingController());
|
costController.putIfAbsent(ServiceId!, () => TextEditingController());
|
||||||
classAction.putIfAbsent(ServiceId!, () => "1");
|
classAction.putIfAbsent((widget.selectedServiceDBValue), () => "1");
|
||||||
// classController.putIfAbsent(ServiceId!, () => TextEditingController());
|
// classController.putIfAbsent(ServiceId!, () => TextEditingController());
|
||||||
|
|
||||||
FirstApproverAction.putIfAbsent(ServiceId!, () => "None");
|
FirstApproverAction.putIfAbsent(ServiceId!, () => "None");
|
||||||
@ -2370,6 +2373,7 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
|
|||||||
|
|
||||||
Widget buildClassWidget(isDesktop) {
|
Widget buildClassWidget(isDesktop) {
|
||||||
List<dynamic> purposeList = [];
|
List<dynamic> purposeList = [];
|
||||||
|
String textLabel = "Class";
|
||||||
// if (ServiceId != null) {
|
// if (ServiceId != null) {
|
||||||
// purposeList = (ServiceId == "1")
|
// purposeList = (ServiceId == "1")
|
||||||
// ? (apiDataForClass?['flight_class'] ?? [])
|
// ? (apiDataForClass?['flight_class'] ?? [])
|
||||||
@ -2377,20 +2381,33 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
if (ServiceIndxId != null) {
|
if (ServiceIndxId != null) {
|
||||||
purposeList =
|
switch (ServiceIndxId) {
|
||||||
(ServiceIndxId == "1")
|
case "1":
|
||||||
? (apiDataForClass?['flight_class'] ?? [])
|
textLabel = "Class";
|
||||||
: (ServiceIndxId == "2")
|
purposeList = apiDataForClass?['flight_class'] ?? [];
|
||||||
? (apiDataForClass?['hotel_class'] ?? [])
|
break;
|
||||||
: (apiDataForClass?['train_class'] ?? []);
|
|
||||||
|
case "2":
|
||||||
|
textLabel = "Category";
|
||||||
|
purposeList = apiDataForClass?['hotel_class'] ?? [];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "9":
|
||||||
|
textLabel = "Class";
|
||||||
|
purposeList = apiDataForClass?['train_class'] ?? [];
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
textLabel = "Class";
|
||||||
|
purposeList = [];
|
||||||
}
|
}
|
||||||
String textLabel = "Class";
|
|
||||||
if (ServiceIndxId != null) {
|
|
||||||
textLabel = (ServiceIndxId == "2") ? "Category" : "Class";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
print("CLASSServiceId- $ServiceId");
|
print("CLASS-ServiceId- $ServiceId");
|
||||||
print("CLASSpurposeList - $purposeList");
|
print("CLASS-ServiceIndxId- $ServiceIndxId");
|
||||||
|
print("CLASS-purposeList - $purposeList");
|
||||||
|
print("CLASS-DB Service Id - ${widget.selectedServiceDBValue}");
|
||||||
|
print("CLASS-Action - ${classAction[widget.selectedServiceDBValue]}");
|
||||||
|
|
||||||
// ✅ Sort by dropdown_key
|
// ✅ Sort by dropdown_key
|
||||||
purposeList.sort((a, b) {
|
purposeList.sort((a, b) {
|
||||||
@ -2409,7 +2426,6 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
|
|||||||
)
|
)
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
print("CLASS 2 - ");
|
|
||||||
|
|
||||||
if (dropdownItems.isEmpty) {
|
if (dropdownItems.isEmpty) {
|
||||||
dropdownItems.add(
|
dropdownItems.add(
|
||||||
@ -2436,13 +2452,13 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
// 1. First, when dropdownItems are ready, assign default value:
|
// 1. First, when dropdownItems are ready, assign default value:
|
||||||
if (ServiceId != null &&
|
if ((widget.selectedServiceDBValue) != null &&
|
||||||
classAction[ServiceId!] == null &&
|
classAction[(widget.selectedServiceDBValue)] == null &&
|
||||||
dropdownItems.isNotEmpty) {
|
dropdownItems.isNotEmpty) {
|
||||||
// Important to wrap inside setState if async
|
// Important to wrap inside setState if async
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
setState(() {
|
setState(() {
|
||||||
classAction[ServiceId!] = dropdownItems.first.value!;
|
classAction[(widget.selectedServiceDBValue)] = dropdownItems.first.value!;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -2502,13 +2518,13 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
|
|||||||
height: 40,
|
height: 40,
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
child:
|
child:
|
||||||
ServiceId != null && (isLoading || dropdownItems.isEmpty)
|
(widget.selectedServiceDBValue) != null && (isLoading || dropdownItems.isEmpty)
|
||||||
? const Center(child: CircularProgressIndicator())
|
? const Center(child: CircularProgressIndicator())
|
||||||
: DropdownSearch<Map<String, dynamic>>(
|
: DropdownSearch<Map<String, dynamic>>(
|
||||||
key:
|
key:
|
||||||
classAction[ServiceId!] == null
|
classAction[(widget.selectedServiceDBValue)] == null
|
||||||
? UniqueKey()
|
? UniqueKey()
|
||||||
: ValueKey(classAction[ServiceId!]),
|
: ValueKey(classAction[(widget.selectedServiceDBValue)]),
|
||||||
items: purposeList.cast<Map<String, dynamic>>(),
|
items: purposeList.cast<Map<String, dynamic>>(),
|
||||||
|
|
||||||
// selectedItem: purposeList.firstWhere(
|
// selectedItem: purposeList.firstWhere(
|
||||||
@ -2516,11 +2532,11 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
|
|||||||
// orElse: () => {},
|
// orElse: () => {},
|
||||||
// ),
|
// ),
|
||||||
selectedItem:
|
selectedItem:
|
||||||
classAction[ServiceId!] != null
|
classAction[(widget.selectedServiceDBValue)] != null
|
||||||
? purposeList.firstWhere(
|
? purposeList.firstWhere(
|
||||||
(item) =>
|
(item) =>
|
||||||
item['dropdown_key'] ==
|
item['dropdown_key'] ==
|
||||||
classAction[ServiceId!],
|
classAction[(widget.selectedServiceDBValue)],
|
||||||
orElse: () => {},
|
orElse: () => {},
|
||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
@ -2583,10 +2599,10 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
|
|||||||
purposeList.isNotEmpty
|
purposeList.isNotEmpty
|
||||||
? (Map<String, dynamic>? newValue) async {
|
? (Map<String, dynamic>? newValue) async {
|
||||||
setState(() {
|
setState(() {
|
||||||
classAction[ServiceId!] =
|
classAction[(widget.selectedServiceDBValue)] =
|
||||||
newValue?['dropdown_key'];
|
newValue?['dropdown_key'];
|
||||||
print(
|
print(
|
||||||
"Selected Purpose: ${classAction[ServiceId!]}",
|
"Selected Purpose: ${classAction[(widget.selectedServiceDBValue)]}",
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -133,17 +133,16 @@ class _PolicyListState extends State<PolicyList> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void filterPolicy(String query) {
|
void filterPolicy(String query) {
|
||||||
|
print("all before filtering: $query");
|
||||||
final lowerQuery = query.toLowerCase();
|
final lowerQuery = query.toLowerCase();
|
||||||
setState(() {
|
setState(() {
|
||||||
filteredPolicy =
|
filteredPolicy =
|
||||||
allPolicy.where((object) {
|
allPolicy.where((object) {
|
||||||
final isActiveStatus =
|
final isActiveStatus =
|
||||||
object['is_active'] == "1" ? "active" : "inactive";
|
object['is_active'] == "1" ? "active" : "inactive";
|
||||||
return (object['policy_id']?.toLowerCase().contains(lowerQuery) ??
|
return (object['policy_id']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||||
false) ||
|
|
||||||
(object['name']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
(object['name']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||||
(object['policy_type']?.toLowerCase().contains(lowerQuery) ??
|
(object['policy_type']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||||
false) ||
|
|
||||||
(isActiveStatus.contains(lowerQuery));
|
(isActiveStatus.contains(lowerQuery));
|
||||||
}).toList();
|
}).toList();
|
||||||
currentPage = 0;
|
currentPage = 0;
|
||||||
@ -340,7 +339,7 @@ class _PolicyListState extends State<PolicyList> {
|
|||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
breadcrumbItems: [
|
breadcrumbItems: [
|
||||||
BreadcrumbItem(
|
BreadcrumbItem(
|
||||||
title: 'Organization Settings',
|
title: 'Org Settings',
|
||||||
tooltip: 'Go To Organization Settings',
|
tooltip: 'Go To Organization Settings',
|
||||||
onTap: (context) {
|
onTap: (context) {
|
||||||
context.go("/OrganizationSettings");
|
context.go("/OrganizationSettings");
|
||||||
@ -504,6 +503,7 @@ class _PolicyListState extends State<PolicyList> {
|
|||||||
FutureBuilder<List<dynamic>>(
|
FutureBuilder<List<dynamic>>(
|
||||||
future: futurePolicy,
|
future: futurePolicy,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
|
final adjHgt = MediaQuery.of(context).size.height;
|
||||||
if (futurePolicy == null) {
|
if (futurePolicy == null) {
|
||||||
return const CircularProgressIndicator();
|
return const CircularProgressIndicator();
|
||||||
}
|
}
|
||||||
@ -519,9 +519,9 @@ class _PolicyListState extends State<PolicyList> {
|
|||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
const SizedBox(height: 8),
|
SizedBox(height: adjHgt / 4),
|
||||||
Text(
|
Text(
|
||||||
"No Policy Found",
|
"No Data Found",
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
@ -530,15 +530,15 @@ class _PolicyListState extends State<PolicyList> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
Text(
|
// Text(
|
||||||
"Please Create Policy",
|
// "Please Create Policy",
|
||||||
textAlign: TextAlign.center,
|
// textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
// style: GoogleFonts.poppins(
|
||||||
fontSize: 16,
|
// fontSize: 16,
|
||||||
color: Colors.grey,
|
// color: Colors.grey,
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
const SizedBox(height: 20),
|
// const SizedBox(height: 20),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -1030,11 +1030,31 @@ class _PolicyListState extends State<PolicyList> {
|
|||||||
Expanded(
|
Expanded(
|
||||||
child:
|
child:
|
||||||
isDesktop
|
isDesktop
|
||||||
? SingleChildScrollView(
|
? (searchController.text.isNotEmpty && filteredPolicy.isEmpty
|
||||||
scrollDirection: Axis.vertical,
|
? Center(
|
||||||
child: table, // <-- your existing table
|
child: Text( "No Matches Found",
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 14,
|
||||||
|
color: Colors.grey,
|
||||||
|
),),
|
||||||
)
|
)
|
||||||
: buildMobileCardView(paginatedUser),
|
: SingleChildScrollView(
|
||||||
|
scrollDirection: Axis.vertical,
|
||||||
|
child: table,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
: (searchController.text.isNotEmpty && filteredPolicy.isEmpty
|
||||||
|
? Center(
|
||||||
|
child: Text(
|
||||||
|
"No Matches Found",
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 14,
|
||||||
|
color: Colors.grey,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: buildMobileCardView(paginatedUser)
|
||||||
|
),
|
||||||
),
|
),
|
||||||
PaginationControls(
|
PaginationControls(
|
||||||
currentPage: currentPage,
|
currentPage: currentPage,
|
||||||
|
|||||||
@ -50,6 +50,7 @@ class PurposeOfTravelDataState extends State<PurposeOfTravelData> {
|
|||||||
String? userId;
|
String? userId;
|
||||||
int? purposeOfTravelDataId;
|
int? purposeOfTravelDataId;
|
||||||
late String isActive = "1";
|
late String isActive = "1";
|
||||||
|
bool isDisable = false;
|
||||||
|
|
||||||
List<String> dataHeader = ["dropdown_value", "description"];
|
List<String> dataHeader = ["dropdown_value", "description"];
|
||||||
|
|
||||||
@ -163,9 +164,12 @@ class PurposeOfTravelDataState extends State<PurposeOfTravelData> {
|
|||||||
userId = await getUserId();
|
userId = await getUserId();
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
|
isDisable = true;
|
||||||
// This triggers UI rebuild with error messages
|
// This triggers UI rebuild with error messages
|
||||||
if (validateData()) {
|
if (validateData()) {
|
||||||
postPurposeOfTravelData();
|
postPurposeOfTravelData();
|
||||||
|
}else{
|
||||||
|
isDisable = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -222,9 +226,19 @@ class PurposeOfTravelDataState extends State<PurposeOfTravelData> {
|
|||||||
_clearError();
|
_clearError();
|
||||||
widget.fetchGetPurposeOfTravel();
|
widget.fetchGetPurposeOfTravel();
|
||||||
// dispose();
|
// dispose();
|
||||||
Navigator.of(context).pop();
|
if (context.mounted) {
|
||||||
|
Navigator.of(context).pop(); // Close modal only if mounted
|
||||||
|
}
|
||||||
|
setState(() {
|
||||||
|
isDisable = false;
|
||||||
|
});
|
||||||
} else if (response.statusCode == 404) {
|
} else if (response.statusCode == 404) {
|
||||||
Navigator.of(context).pop();
|
if (context.mounted) {
|
||||||
|
Navigator.of(context).pop(); // Close modal only if mounted
|
||||||
|
}
|
||||||
|
setState(() {
|
||||||
|
isDisable = false;
|
||||||
|
});
|
||||||
final message = jsonDecode(response.body)['message'] ?? 'Unknown error';
|
final message = jsonDecode(response.body)['message'] ?? 'Unknown error';
|
||||||
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
@ -237,9 +251,15 @@ class PurposeOfTravelDataState extends State<PurposeOfTravelData> {
|
|||||||
} else {
|
} else {
|
||||||
print("Failed to submit. Status: ${response.statusCode}");
|
print("Failed to submit. Status: ${response.statusCode}");
|
||||||
print("Error: ${response.body}");
|
print("Error: ${response.body}");
|
||||||
|
setState(() {
|
||||||
|
isDisable = false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(" Error submitting plan: $e");
|
print(" Error submitting plan: $e");
|
||||||
|
setState(() {
|
||||||
|
isDisable = false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -409,10 +429,21 @@ class PurposeOfTravelDataState extends State<PurposeOfTravelData> {
|
|||||||
// ),
|
// ),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: isDisable
|
||||||
handleSubmit();
|
? null
|
||||||
|
: () async {
|
||||||
|
setState(() {
|
||||||
|
isDisable = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
await handleSubmit();
|
||||||
// You can get text from commentController.text
|
// You can get text from commentController.text
|
||||||
// Navigator.of(context).pop(); // Close the modal
|
// Navigator.of(context).pop(); // Close the modal
|
||||||
|
|
||||||
|
// Optional: re-enable only on error
|
||||||
|
// setState(() {
|
||||||
|
// isDisable = false;
|
||||||
|
// });
|
||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: widget.layoutColor,
|
backgroundColor: widget.layoutColor,
|
||||||
|
|||||||
@ -284,7 +284,7 @@ class PurposeOfTravelListState extends State<PurposeOfTravelList> {
|
|||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
breadcrumbItems: [
|
breadcrumbItems: [
|
||||||
BreadcrumbItem(
|
BreadcrumbItem(
|
||||||
title: 'Organization Settings',
|
title: 'Org Settings',
|
||||||
tooltip: 'Go To Organization Settings',
|
tooltip: 'Go To Organization Settings',
|
||||||
onTap: (context) {
|
onTap: (context) {
|
||||||
context.go("/OrganizationSettings");
|
context.go("/OrganizationSettings");
|
||||||
@ -454,6 +454,7 @@ class PurposeOfTravelListState extends State<PurposeOfTravelList> {
|
|||||||
FutureBuilder<List<dynamic>>(
|
FutureBuilder<List<dynamic>>(
|
||||||
future: futurePurposeOfTravel,
|
future: futurePurposeOfTravel,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
|
final adjHgt = MediaQuery.of(context).size.height;
|
||||||
if (futurePurposeOfTravel == null) {
|
if (futurePurposeOfTravel == null) {
|
||||||
CircularProgressIndicator();
|
CircularProgressIndicator();
|
||||||
}
|
}
|
||||||
@ -479,9 +480,9 @@ class PurposeOfTravelListState extends State<PurposeOfTravelList> {
|
|||||||
// fontWeight: FontWeight.bold,
|
// fontWeight: FontWeight.bold,
|
||||||
// color: Colors.redAccent),
|
// color: Colors.redAccent),
|
||||||
// ),
|
// ),
|
||||||
const SizedBox(height: 8),
|
SizedBox(height: adjHgt / 4),
|
||||||
Text(
|
Text(
|
||||||
"No Purpose Of Travel Available ",
|
"No Data Found ",
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
@ -490,15 +491,15 @@ class PurposeOfTravelListState extends State<PurposeOfTravelList> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
Text(
|
// Text(
|
||||||
"Please Create Purpose Of Travel Details",
|
// "Please Create Purpose Of Travel Details",
|
||||||
textAlign: TextAlign.center,
|
// textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
// style: GoogleFonts.poppins(
|
||||||
fontSize: 16,
|
// fontSize: 16,
|
||||||
color: Colors.grey,
|
// color: Colors.grey,
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
const SizedBox(height: 20),
|
// const SizedBox(height: 20),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -797,7 +798,7 @@ class PurposeOfTravelListState extends State<PurposeOfTravelList> {
|
|||||||
filteredPurposeOfTravel.isEmpty
|
filteredPurposeOfTravel.isEmpty
|
||||||
? Center(
|
? Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
"No matches found",
|
"No Matches Found",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: Colors.grey,
|
color: Colors.grey,
|
||||||
@ -812,7 +813,7 @@ class PurposeOfTravelListState extends State<PurposeOfTravelList> {
|
|||||||
filteredPurposeOfTravel.isEmpty
|
filteredPurposeOfTravel.isEmpty
|
||||||
? Center(
|
? Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
"No matches found",
|
"No Matches Found",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: Colors.grey,
|
color: Colors.grey,
|
||||||
|
|||||||
@ -449,8 +449,9 @@ class _AdvancePurchaseState extends State<AdvancePurchase>
|
|||||||
false) ||
|
false) ||
|
||||||
(object['Service']?.toLowerCase().contains(lowerQuery) ??
|
(object['Service']?.toLowerCase().contains(lowerQuery) ??
|
||||||
false) ||
|
false) ||
|
||||||
(newFromDate.toLowerCase().contains(lowerQuery)) ||
|
(object['created_on']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||||
(newToDate.toLowerCase().contains(lowerQuery)) ||
|
(object['created_time']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||||
|
(object['FirstTravelDt']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||||
(object['AdvPurch']?.toLowerCase().contains(lowerQuery));
|
(object['AdvPurch']?.toLowerCase().contains(lowerQuery));
|
||||||
}).toList();
|
}).toList();
|
||||||
currentPage1 = 0;
|
currentPage1 = 0;
|
||||||
@ -505,8 +506,9 @@ class _AdvancePurchaseState extends State<AdvancePurchase>
|
|||||||
false) ||
|
false) ||
|
||||||
(object['Service']?.toLowerCase().contains(lowerQuery) ??
|
(object['Service']?.toLowerCase().contains(lowerQuery) ??
|
||||||
false) ||
|
false) ||
|
||||||
(newFromDate.toLowerCase().contains(lowerQuery)) ||
|
(object['created_on']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||||
(newToDate.toLowerCase().contains(lowerQuery)) ||
|
(object['created_time']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||||
|
(object['FirstTravelDt']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||||
(object['AdvPurch']?.toLowerCase().contains(lowerQuery));
|
(object['AdvPurch']?.toLowerCase().contains(lowerQuery));
|
||||||
}).toList();
|
}).toList();
|
||||||
currentPage2 = 0;
|
currentPage2 = 0;
|
||||||
@ -662,24 +664,24 @@ class _AdvancePurchaseState extends State<AdvancePurchase>
|
|||||||
MediaQuery.of(context).size.height / 4,
|
MediaQuery.of(context).size.height / 4,
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
"No Records Found",
|
"No Data Found",
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.bold,
|
||||||
color: Colors.black54,
|
color: Colors.grey,
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 10),
|
|
||||||
Text(
|
|
||||||
"Please ensure the selected dates contain report data.",
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
style: GoogleFonts.poppins(
|
|
||||||
fontSize: 12,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
color: Colors.black54,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
// const SizedBox(height: 10),
|
||||||
|
// Text(
|
||||||
|
// "Please ensure the selected dates contain report data.",
|
||||||
|
// textAlign: TextAlign.center,
|
||||||
|
// style: GoogleFonts.poppins(
|
||||||
|
// fontSize: 12,
|
||||||
|
// fontWeight: FontWeight.w500,
|
||||||
|
// color: Colors.black54,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -895,7 +897,7 @@ class _AdvancePurchaseState extends State<AdvancePurchase>
|
|||||||
4,
|
4,
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
"No Records Found",
|
"No Matches Found",
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
@ -903,16 +905,16 @@ class _AdvancePurchaseState extends State<AdvancePurchase>
|
|||||||
color: Colors.black54,
|
color: Colors.black54,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 10),
|
// const SizedBox(height: 10),
|
||||||
Text(
|
// Text(
|
||||||
"Please ensure the selected dates contain report data.",
|
// "Please ensure the selected dates contain report data.",
|
||||||
textAlign: TextAlign.center,
|
// textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
// style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
// fontSize: 12,
|
||||||
fontWeight: FontWeight.w500,
|
// fontWeight: FontWeight.w500,
|
||||||
color: Colors.black54,
|
// color: Colors.black54,
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -1031,6 +1033,18 @@ class _AdvancePurchaseState extends State<AdvancePurchase>
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
DataColumn(
|
||||||
|
label: Text(
|
||||||
|
'Created Time',
|
||||||
|
style:
|
||||||
|
GoogleFonts.poppins(
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight:
|
||||||
|
FontWeight
|
||||||
|
.w600,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
DataColumn(
|
DataColumn(
|
||||||
label: Text(
|
label: Text(
|
||||||
'First Travel Date',
|
'First Travel Date',
|
||||||
@ -1060,22 +1074,8 @@ class _AdvancePurchaseState extends State<AdvancePurchase>
|
|||||||
paginatedDomestic.map((
|
paginatedDomestic.map((
|
||||||
entry,
|
entry,
|
||||||
) {
|
) {
|
||||||
final FromDate =
|
final FromDate = entry['created_on'];
|
||||||
DateFormat(
|
final ToDate = entry['FirstTravelDt'];
|
||||||
'dd-MM-yyyy',
|
|
||||||
).format(
|
|
||||||
DateTime.parse(
|
|
||||||
entry['created_on'],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
final ToDate =
|
|
||||||
DateFormat(
|
|
||||||
'dd-MM-yyyy',
|
|
||||||
).format(
|
|
||||||
DateTime.parse(
|
|
||||||
entry['FirstTravelDt'],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
return DataRow(
|
return DataRow(
|
||||||
cells: [
|
cells: [
|
||||||
DataCell(
|
DataCell(
|
||||||
@ -1142,6 +1142,15 @@ class _AdvancePurchaseState extends State<AdvancePurchase>
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
DataCell(
|
||||||
|
Text(
|
||||||
|
'${entry['created_time']}',
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize:
|
||||||
|
12,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
DataCell(
|
DataCell(
|
||||||
Text(
|
Text(
|
||||||
// '${entry['FirstTravelDt']}',
|
// '${entry['FirstTravelDt']}',
|
||||||
@ -1210,7 +1219,7 @@ class _AdvancePurchaseState extends State<AdvancePurchase>
|
|||||||
MediaQuery.of(context).size.height / 4,
|
MediaQuery.of(context).size.height / 4,
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
"No Records Found",
|
"No Data Found",
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
@ -1219,15 +1228,15 @@ class _AdvancePurchaseState extends State<AdvancePurchase>
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
Text(
|
// Text(
|
||||||
"Please ensure the selected dates contain report data.",
|
// "Please ensure the selected dates contain report data.",
|
||||||
textAlign: TextAlign.center,
|
// textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
// style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
// fontSize: 12,
|
||||||
fontWeight: FontWeight.w500,
|
// fontWeight: FontWeight.w500,
|
||||||
color: Colors.black54,
|
// color: Colors.black54,
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -1473,7 +1482,7 @@ class _AdvancePurchaseState extends State<AdvancePurchase>
|
|||||||
4,
|
4,
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
"No Records Found",
|
"No Matches Found",
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
@ -1482,15 +1491,15 @@ class _AdvancePurchaseState extends State<AdvancePurchase>
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
Text(
|
// Text(
|
||||||
"Please ensure the selected dates contain report data.",
|
// "Please ensure the selected dates contain report data.",
|
||||||
textAlign: TextAlign.center,
|
// textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
// style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
// fontSize: 12,
|
||||||
fontWeight: FontWeight.w500,
|
// fontWeight: FontWeight.w500,
|
||||||
color: Colors.black54,
|
// color: Colors.black54,
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -1638,22 +1647,8 @@ class _AdvancePurchaseState extends State<AdvancePurchase>
|
|||||||
paginatedInternational.map((
|
paginatedInternational.map((
|
||||||
entry,
|
entry,
|
||||||
) {
|
) {
|
||||||
final FromDate =
|
final FromDate = entry['created_on'];
|
||||||
DateFormat(
|
final ToDate = entry['FirstTravelDt'];
|
||||||
'dd-MM-yyyy',
|
|
||||||
).format(
|
|
||||||
DateTime.parse(
|
|
||||||
entry['created_on'],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
final ToDate =
|
|
||||||
DateFormat(
|
|
||||||
'dd-MM-yyyy',
|
|
||||||
).format(
|
|
||||||
DateTime.parse(
|
|
||||||
entry['FirstTravelDt'],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
return DataRow(
|
return DataRow(
|
||||||
cells: [
|
cells: [
|
||||||
DataCell(
|
DataCell(
|
||||||
@ -1786,10 +1781,30 @@ class _AdvancePurchaseState extends State<AdvancePurchase>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Widget buildTitle(bool isDesktop) {
|
||||||
|
// return // Left side: Breadcrumb inside a Container (optional)
|
||||||
|
// Container(
|
||||||
|
// child: BreadcrumbNavigation(
|
||||||
|
// isDesktop: isDesktop,
|
||||||
|
// breadcrumbItems: [
|
||||||
|
// BreadcrumbItem(
|
||||||
|
// title: 'Report List',
|
||||||
|
// tooltip: 'Go To Report List',
|
||||||
|
// onTap: (context) {
|
||||||
|
// // Navigator.pushNamed(context, '/report');
|
||||||
|
// context.go("/report");
|
||||||
|
// },
|
||||||
|
// ),
|
||||||
|
// BreadcrumbItem(title: 'Advance Purchase'),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
Widget buildTitle(bool isDesktop) {
|
Widget buildTitle(bool isDesktop) {
|
||||||
return // Left side: Breadcrumb inside a Container (optional)
|
return Row(
|
||||||
Container(
|
children: [
|
||||||
child: BreadcrumbNavigation(
|
BreadcrumbNavigation(
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
breadcrumbItems: [
|
breadcrumbItems: [
|
||||||
BreadcrumbItem(
|
BreadcrumbItem(
|
||||||
@ -1803,6 +1818,7 @@ class _AdvancePurchaseState extends State<AdvancePurchase>
|
|||||||
BreadcrumbItem(title: 'Advance Purchase'),
|
BreadcrumbItem(title: 'Advance Purchase'),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -420,7 +420,7 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
|||||||
false) ||
|
false) ||
|
||||||
(object['flight_class']?.toLowerCase().contains(lowerQuery) ??
|
(object['flight_class']?.toLowerCase().contains(lowerQuery) ??
|
||||||
false) ||
|
false) ||
|
||||||
(formattedDate.toLowerCase().contains(lowerQuery)) ||
|
(object['flight_travel_date']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||||
(object['sector']?.toLowerCase().contains(lowerQuery));
|
(object['sector']?.toLowerCase().contains(lowerQuery));
|
||||||
}).toList();
|
}).toList();
|
||||||
currentPage1 = 0;
|
currentPage1 = 0;
|
||||||
@ -469,7 +469,7 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
|||||||
false) ||
|
false) ||
|
||||||
(object['flight_class']?.toLowerCase().contains(lowerQuery) ??
|
(object['flight_class']?.toLowerCase().contains(lowerQuery) ??
|
||||||
false) ||
|
false) ||
|
||||||
(formattedDate.toLowerCase().contains(lowerQuery)) ||
|
(object['flight_travel_date']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||||
(object['sector']?.toLowerCase().contains(lowerQuery));
|
(object['sector']?.toLowerCase().contains(lowerQuery));
|
||||||
}).toList();
|
}).toList();
|
||||||
currentPage2 = 0;
|
currentPage2 = 0;
|
||||||
@ -626,24 +626,24 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
|||||||
MediaQuery.of(context).size.height / 4,
|
MediaQuery.of(context).size.height / 4,
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
"No Records Found",
|
"No Data Found",
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.bold,
|
||||||
color: Colors.black54,
|
color: Colors.grey,
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 10),
|
|
||||||
Text(
|
|
||||||
"Please ensure the selected dates contain report data.",
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
style: GoogleFonts.poppins(
|
|
||||||
fontSize: 12,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
color: Colors.black54,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
// const SizedBox(height: 10),
|
||||||
|
// Text(
|
||||||
|
// "Please ensure the selected dates contain report data.",
|
||||||
|
// textAlign: TextAlign.center,
|
||||||
|
// style: GoogleFonts.poppins(
|
||||||
|
// fontSize: 12,
|
||||||
|
// fontWeight: FontWeight.w500,
|
||||||
|
// color: Colors.black54,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -859,7 +859,7 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
|||||||
4,
|
4,
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
"No Records Found",
|
"No Matches Found",
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
@ -868,15 +868,15 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
Text(
|
// Text(
|
||||||
"Please ensure the selected dates contain report data.",
|
// "Please ensure the selected dates contain report data.",
|
||||||
textAlign: TextAlign.center,
|
// textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
// style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
// fontSize: 12,
|
||||||
fontWeight: FontWeight.w500,
|
// fontWeight: FontWeight.w500,
|
||||||
color: Colors.black54,
|
// color: Colors.black54,
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -1024,14 +1024,7 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
|||||||
paginatedDomestic.map((
|
paginatedDomestic.map((
|
||||||
entry,
|
entry,
|
||||||
) {
|
) {
|
||||||
final TravelDate =
|
final TravelDate = entry['flight_travel_date'];
|
||||||
DateFormat(
|
|
||||||
'dd-MM-yyyy',
|
|
||||||
).format(
|
|
||||||
DateTime.parse(
|
|
||||||
entry['flight_travel_date'],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
return DataRow(
|
return DataRow(
|
||||||
cells: [
|
cells: [
|
||||||
DataCell(
|
DataCell(
|
||||||
@ -1394,7 +1387,7 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
|||||||
filteredInternational.isEmpty)
|
filteredInternational.isEmpty)
|
||||||
? Center(
|
? Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
"No data found",
|
"No Matches Found",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
@ -1544,14 +1537,7 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
|||||||
paginatedInternational.map((
|
paginatedInternational.map((
|
||||||
entry,
|
entry,
|
||||||
) {
|
) {
|
||||||
final TravelDate =
|
final TravelDate = entry['flight_travel_date'];
|
||||||
DateFormat(
|
|
||||||
'dd-MM-yyyy',
|
|
||||||
).format(
|
|
||||||
DateTime.parse(
|
|
||||||
entry['flight_travel_date'],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
return DataRow(
|
return DataRow(
|
||||||
cells: [
|
cells: [
|
||||||
DataCell(
|
DataCell(
|
||||||
@ -1682,10 +1668,30 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Widget buildTitle(bool isDesktop) {
|
||||||
|
// return // Left side: Breadcrumb inside a Container (optional)
|
||||||
|
// Container(
|
||||||
|
// child: BreadcrumbNavigation(
|
||||||
|
// isDesktop: isDesktop,
|
||||||
|
// breadcrumbItems: [
|
||||||
|
// BreadcrumbItem(
|
||||||
|
// title: 'Report List',
|
||||||
|
// tooltip: 'Go To Report List',
|
||||||
|
// onTap: (context) {
|
||||||
|
// // Navigator.pushNamed(context, '/report');
|
||||||
|
// context.go("/report");
|
||||||
|
// },
|
||||||
|
// ),
|
||||||
|
// BreadcrumbItem(title: 'MIS Air Report '),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
Widget buildTitle(bool isDesktop) {
|
Widget buildTitle(bool isDesktop) {
|
||||||
return // Left side: Breadcrumb inside a Container (optional)
|
return Row(
|
||||||
Container(
|
children: [
|
||||||
child: BreadcrumbNavigation(
|
BreadcrumbNavigation(
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
breadcrumbItems: [
|
breadcrumbItems: [
|
||||||
BreadcrumbItem(
|
BreadcrumbItem(
|
||||||
@ -1699,6 +1705,7 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
|||||||
BreadcrumbItem(title: 'MIS Air Report '),
|
BreadcrumbItem(title: 'MIS Air Report '),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -518,24 +518,24 @@ class _MISforexState extends State<MISforex>
|
|||||||
MediaQuery.of(context).size.height / 4,
|
MediaQuery.of(context).size.height / 4,
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
"No Records Found",
|
"No Data Found",
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.bold,
|
||||||
color: Colors.black54,
|
color: Colors.grey,
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 10),
|
|
||||||
Text(
|
|
||||||
"Please ensure the selected dates contain report data.",
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
style: GoogleFonts.poppins(
|
|
||||||
fontSize: 12,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
color: Colors.black54,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
// const SizedBox(height: 10),
|
||||||
|
// Text(
|
||||||
|
// "Please ensure the selected dates contain report data.",
|
||||||
|
// textAlign: TextAlign.center,
|
||||||
|
// style: GoogleFonts.poppins(
|
||||||
|
// fontSize: 12,
|
||||||
|
// fontWeight: FontWeight.w500,
|
||||||
|
// color: Colors.black54,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -660,7 +660,7 @@ class _MISforexState extends State<MISforex>
|
|||||||
4,
|
4,
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
"No Records Found",
|
"No Matches Found",
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
@ -669,15 +669,15 @@ class _MISforexState extends State<MISforex>
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
Text(
|
// Text(
|
||||||
"Please ensure the selected dates contain report data.",
|
// "Please ensure the selected dates contain report data.",
|
||||||
textAlign: TextAlign.center,
|
// textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
// style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
// fontSize: 12,
|
||||||
fontWeight: FontWeight.w500,
|
// fontWeight: FontWeight.w500,
|
||||||
color: Colors.black54,
|
// color: Colors.black54,
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -822,22 +822,22 @@ class _MISforexState extends State<MISforex>
|
|||||||
paginatedInternational.map((
|
paginatedInternational.map((
|
||||||
entry,
|
entry,
|
||||||
) {
|
) {
|
||||||
final forexFromDate =
|
final forexFromDate = entry['forex_from_date'];
|
||||||
DateFormat(
|
// DateFormat(
|
||||||
'dd-MM-yyyy',
|
// 'dd-MM-yyyy',
|
||||||
).format(
|
// ).format(
|
||||||
DateTime.parse(
|
// DateTime.parse(
|
||||||
entry['forex_from_date'],
|
// entry['forex_from_date'],
|
||||||
),
|
// ),
|
||||||
);
|
// );
|
||||||
final forexToDate =
|
final forexToDate = entry['forex_to_date'];
|
||||||
DateFormat(
|
// DateFormat(
|
||||||
'dd-MM-yyyy',
|
// 'dd-MM-yyyy',
|
||||||
).format(
|
// ).format(
|
||||||
DateTime.parse(
|
// DateTime.parse(
|
||||||
entry['forex_to_date'],
|
// entry['forex_to_date'],
|
||||||
),
|
// ),
|
||||||
);
|
// );
|
||||||
return DataRow(
|
return DataRow(
|
||||||
cells: [
|
cells: [
|
||||||
DataCell(
|
DataCell(
|
||||||
@ -973,9 +973,9 @@ class _MISforexState extends State<MISforex>
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget buildTitle(bool isDesktop) {
|
Widget buildTitle(bool isDesktop) {
|
||||||
return // Left side: Breadcrumb inside a Container (optional)
|
return Row(
|
||||||
Container(
|
children: [
|
||||||
child: BreadcrumbNavigation(
|
BreadcrumbNavigation(
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
breadcrumbItems: [
|
breadcrumbItems: [
|
||||||
BreadcrumbItem(
|
BreadcrumbItem(
|
||||||
@ -989,6 +989,7 @@ class _MISforexState extends State<MISforex>
|
|||||||
BreadcrumbItem(title: 'MIS Forex Report '),
|
BreadcrumbItem(title: 'MIS Forex Report '),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -429,8 +429,8 @@ class _MIShotelState extends State<MIShotel>
|
|||||||
false) ||
|
false) ||
|
||||||
(object['hotel_name']?.toLowerCase().contains(lowerQuery) ??
|
(object['hotel_name']?.toLowerCase().contains(lowerQuery) ??
|
||||||
false) ||
|
false) ||
|
||||||
(newFromDate.toLowerCase().contains(lowerQuery)) ||
|
(object['check_in_date'].toLowerCase().contains(lowerQuery) ?? false) ||
|
||||||
(newToDate.toLowerCase().contains(lowerQuery)) ||
|
(object['check_out_date'].toLowerCase().contains(lowerQuery) ?? false) ||
|
||||||
(object['hotel_city']?.toLowerCase().contains(lowerQuery));
|
(object['hotel_city']?.toLowerCase().contains(lowerQuery));
|
||||||
}).toList();
|
}).toList();
|
||||||
currentPage1 = 0;
|
currentPage1 = 0;
|
||||||
@ -487,8 +487,8 @@ class _MIShotelState extends State<MIShotel>
|
|||||||
false) ||
|
false) ||
|
||||||
(object['hotel_name']?.toLowerCase().contains(lowerQuery) ??
|
(object['hotel_name']?.toLowerCase().contains(lowerQuery) ??
|
||||||
false) ||
|
false) ||
|
||||||
(newFromDate.toLowerCase().contains(lowerQuery)) ||
|
(object['check_in_date']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||||
(newToDate.toLowerCase().contains(lowerQuery)) ||
|
(object['check_out_date'].toLowerCase().contains(lowerQuery) ?? false) ||
|
||||||
(object['hotel_city']?.toLowerCase().contains(lowerQuery));
|
(object['hotel_city']?.toLowerCase().contains(lowerQuery));
|
||||||
}).toList();
|
}).toList();
|
||||||
currentPage2 = 0;
|
currentPage2 = 0;
|
||||||
@ -644,24 +644,24 @@ class _MIShotelState extends State<MIShotel>
|
|||||||
MediaQuery.of(context).size.height / 4,
|
MediaQuery.of(context).size.height / 4,
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
"No Records Found",
|
"No Data Found",
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.bold,
|
||||||
color: Colors.black54,
|
color: Colors.grey,
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 10),
|
|
||||||
Text(
|
|
||||||
"Please ensure the selected dates contain report data.",
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
style: GoogleFonts.poppins(
|
|
||||||
fontSize: 12,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
color: Colors.black54,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
// const SizedBox(height: 10),
|
||||||
|
// Text(
|
||||||
|
// "Please ensure the selected dates contain report data.",
|
||||||
|
// textAlign: TextAlign.center,
|
||||||
|
// style: GoogleFonts.poppins(
|
||||||
|
// fontSize: 12,
|
||||||
|
// fontWeight: FontWeight.w500,
|
||||||
|
// color: Colors.black54,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -877,7 +877,7 @@ class _MIShotelState extends State<MIShotel>
|
|||||||
4,
|
4,
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
"No Records Found",
|
"No Matches Found",
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
@ -886,15 +886,15 @@ class _MIShotelState extends State<MIShotel>
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
Text(
|
// Text(
|
||||||
"Please ensure the selected dates contain report data.",
|
// "Please ensure the selected dates contain report data.",
|
||||||
textAlign: TextAlign.center,
|
// textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
// style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
// fontSize: 12,
|
||||||
fontWeight: FontWeight.w500,
|
// fontWeight: FontWeight.w500,
|
||||||
color: Colors.black54,
|
// color: Colors.black54,
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -1002,18 +1002,18 @@ class _MIShotelState extends State<MIShotel>
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
DataColumn(
|
// DataColumn(
|
||||||
label: Text(
|
// label: Text(
|
||||||
'Sector',
|
// 'Sector',
|
||||||
style:
|
// style:
|
||||||
GoogleFonts.poppins(
|
// GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
// fontSize: 12,
|
||||||
fontWeight:
|
// fontWeight:
|
||||||
FontWeight
|
// FontWeight
|
||||||
.w600,
|
// .w600,
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
DataColumn(
|
DataColumn(
|
||||||
label: Text(
|
label: Text(
|
||||||
'Hotel Name',
|
'Hotel Name',
|
||||||
@ -1067,22 +1067,9 @@ class _MIShotelState extends State<MIShotel>
|
|||||||
paginatedDomestic.map((
|
paginatedDomestic.map((
|
||||||
entry,
|
entry,
|
||||||
) {
|
) {
|
||||||
final checkInDate =
|
final checkInDate = entry['check_in_date'];
|
||||||
DateFormat(
|
|
||||||
'dd-MM-yyyy',
|
final checkOutDate = entry['check_out_date'];
|
||||||
).format(
|
|
||||||
DateTime.parse(
|
|
||||||
entry['check_in_date'],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
final checkOutDate =
|
|
||||||
DateFormat(
|
|
||||||
'dd-MM-yyyy',
|
|
||||||
).format(
|
|
||||||
DateTime.parse(
|
|
||||||
entry['check_out_date'],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
return DataRow(
|
return DataRow(
|
||||||
cells: [
|
cells: [
|
||||||
@ -1140,15 +1127,15 @@ class _MIShotelState extends State<MIShotel>
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
DataCell(
|
// DataCell(
|
||||||
Text(
|
// Text(
|
||||||
'${entry['sector']}',
|
// '${entry['sector']}',
|
||||||
style: GoogleFonts.poppins(
|
// style: GoogleFonts.poppins(
|
||||||
fontSize:
|
// fontSize:
|
||||||
12,
|
// 12,
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
DataCell(
|
DataCell(
|
||||||
Text(
|
Text(
|
||||||
'${entry['hotel_name']}',
|
'${entry['hotel_name']}',
|
||||||
@ -1234,7 +1221,7 @@ class _MIShotelState extends State<MIShotel>
|
|||||||
MediaQuery.of(context).size.height / 4,
|
MediaQuery.of(context).size.height / 4,
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
"No Records Found",
|
"No Data Found",
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
@ -1243,15 +1230,15 @@ class _MIShotelState extends State<MIShotel>
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
Text(
|
// Text(
|
||||||
"Please ensure the selected dates contain report data.",
|
// "Please ensure the selected dates contain report data.",
|
||||||
textAlign: TextAlign.center,
|
// textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
// style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
// fontSize: 12,
|
||||||
fontWeight: FontWeight.w500,
|
// fontWeight: FontWeight.w500,
|
||||||
color: Colors.black54,
|
// color: Colors.black54,
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -1497,7 +1484,7 @@ class _MIShotelState extends State<MIShotel>
|
|||||||
4,
|
4,
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
"No Records Found",
|
"No Matches Found",
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
@ -1506,15 +1493,15 @@ class _MIShotelState extends State<MIShotel>
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
Text(
|
// Text(
|
||||||
"Please ensure the selected dates contain report data.",
|
// "Please ensure the selected dates contain report data.",
|
||||||
textAlign: TextAlign.center,
|
// textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
// style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
// fontSize: 12,
|
||||||
fontWeight: FontWeight.w500,
|
// fontWeight: FontWeight.w500,
|
||||||
color: Colors.black54,
|
// color: Colors.black54,
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -1622,18 +1609,18 @@ class _MIShotelState extends State<MIShotel>
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
DataColumn(
|
// DataColumn(
|
||||||
label: Text(
|
// label: Text(
|
||||||
'Sector',
|
// 'Sector',
|
||||||
style:
|
// style:
|
||||||
GoogleFonts.poppins(
|
// GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
// fontSize: 12,
|
||||||
fontWeight:
|
// fontWeight:
|
||||||
FontWeight
|
// FontWeight
|
||||||
.w600,
|
// .w600,
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
DataColumn(
|
DataColumn(
|
||||||
label: Text(
|
label: Text(
|
||||||
'Hotel Name',
|
'Hotel Name',
|
||||||
@ -1687,22 +1674,22 @@ class _MIShotelState extends State<MIShotel>
|
|||||||
paginatedInternational.map((
|
paginatedInternational.map((
|
||||||
entry,
|
entry,
|
||||||
) {
|
) {
|
||||||
final checkInDate =
|
final checkInDate = entry['check_in_date'];
|
||||||
DateFormat(
|
// DateFormat(
|
||||||
'dd-MM-yyyy',
|
// 'dd-MM-yyyy',
|
||||||
).format(
|
// ).format(
|
||||||
DateTime.parse(
|
// DateTime.parse(
|
||||||
entry['check_in_date'],
|
// entry['check_in_date'],
|
||||||
),
|
// ),
|
||||||
);
|
// );
|
||||||
final checkOutDate =
|
final checkOutDate = entry['check_out_date'];
|
||||||
DateFormat(
|
// DateFormat(
|
||||||
'dd-MM-yyyy',
|
// 'dd-MM-yyyy',
|
||||||
).format(
|
// ).format(
|
||||||
DateTime.parse(
|
// DateTime.parse(
|
||||||
entry['check_out_date'],
|
// entry['check_out_date'],
|
||||||
),
|
// ),
|
||||||
);
|
// );
|
||||||
return DataRow(
|
return DataRow(
|
||||||
cells: [
|
cells: [
|
||||||
DataCell(
|
DataCell(
|
||||||
@ -1759,15 +1746,15 @@ class _MIShotelState extends State<MIShotel>
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
DataCell(
|
// DataCell(
|
||||||
Text(
|
// Text(
|
||||||
'${entry['sector']}',
|
// '${entry['sector']}',
|
||||||
style: GoogleFonts.poppins(
|
// style: GoogleFonts.poppins(
|
||||||
fontSize:
|
// fontSize:
|
||||||
12,
|
// 12,
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
DataCell(
|
DataCell(
|
||||||
Text(
|
Text(
|
||||||
'${entry['hotel_name']}',
|
'${entry['hotel_name']}',
|
||||||
@ -1853,8 +1840,9 @@ class _MIShotelState extends State<MIShotel>
|
|||||||
|
|
||||||
Widget buildTitle(bool isDesktop) {
|
Widget buildTitle(bool isDesktop) {
|
||||||
return // Left side: Breadcrumb inside a Container (optional)
|
return // Left side: Breadcrumb inside a Container (optional)
|
||||||
Container(
|
Row(
|
||||||
child: BreadcrumbNavigation(
|
children: [
|
||||||
|
BreadcrumbNavigation(
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
breadcrumbItems: [
|
breadcrumbItems: [
|
||||||
BreadcrumbItem(
|
BreadcrumbItem(
|
||||||
@ -1868,6 +1856,7 @@ class _MIShotelState extends State<MIShotel>
|
|||||||
BreadcrumbItem(title: 'MIS Hotel Report '),
|
BreadcrumbItem(title: 'MIS Hotel Report '),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -567,24 +567,24 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
|||||||
MediaQuery.of(context).size.height / 4,
|
MediaQuery.of(context).size.height / 4,
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
"No Records Found",
|
"No Data Found",
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.bold,
|
||||||
color: Colors.black54,
|
color: Colors.grey,
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 10),
|
|
||||||
Text(
|
|
||||||
"Please ensure the selected dates contain report data.",
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
style: GoogleFonts.poppins(
|
|
||||||
fontSize: 12,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
color: Colors.black54,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
// const SizedBox(height: 10),
|
||||||
|
// Text(
|
||||||
|
// "Please ensure the selected dates contain report data.",
|
||||||
|
// textAlign: TextAlign.center,
|
||||||
|
// style: GoogleFonts.poppins(
|
||||||
|
// fontSize: 12,
|
||||||
|
// fontWeight: FontWeight.w500,
|
||||||
|
// color: Colors.black54,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -800,7 +800,7 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
|||||||
4,
|
4,
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
"No Records Found",
|
"No Matches Found",
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
@ -809,15 +809,15 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
Text(
|
// Text(
|
||||||
"Please ensure the selected dates contain report data.",
|
// "Please ensure the selected dates contain report data.",
|
||||||
textAlign: TextAlign.center,
|
// textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
// style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
// fontSize: 12,
|
||||||
fontWeight: FontWeight.w500,
|
// fontWeight: FontWeight.w500,
|
||||||
color: Colors.black54,
|
// color: Colors.black54,
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -971,7 +971,7 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
|||||||
MediaQuery.of(context).size.height / 4,
|
MediaQuery.of(context).size.height / 4,
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
"No Records Found",
|
"No Data Found",
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
@ -980,15 +980,15 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
Text(
|
// Text(
|
||||||
"Please ensure the selected dates contain report data.",
|
// "Please ensure the selected dates contain report data.",
|
||||||
textAlign: TextAlign.center,
|
// textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
// style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
// fontSize: 12,
|
||||||
fontWeight: FontWeight.w500,
|
// fontWeight: FontWeight.w500,
|
||||||
color: Colors.black54,
|
// color: Colors.black54,
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -1234,7 +1234,7 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
|||||||
4,
|
4,
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
"No Records Found",
|
"No Matches Found",
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
@ -1243,15 +1243,15 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
Text(
|
// Text(
|
||||||
"Please ensure the selected dates contain report data.",
|
// "Please ensure the selected dates contain report data.",
|
||||||
textAlign: TextAlign.center,
|
// textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
// style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
// fontSize: 12,
|
||||||
fontWeight: FontWeight.w500,
|
// fontWeight: FontWeight.w500,
|
||||||
color: Colors.black54,
|
// color: Colors.black54,
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -1403,10 +1403,30 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Widget buildTitle(bool isDesktop) {
|
||||||
|
// return // Left side: Breadcrumb inside a Container (optional)
|
||||||
|
// Container(
|
||||||
|
// child: BreadcrumbNavigation(
|
||||||
|
// isDesktop: isDesktop,
|
||||||
|
// breadcrumbItems: [
|
||||||
|
// BreadcrumbItem(
|
||||||
|
// title: 'Report List',
|
||||||
|
// tooltip: 'Go To Report List',
|
||||||
|
// onTap: (context) {
|
||||||
|
// // Navigator.pushNamed(context, '/report');
|
||||||
|
// context.go("/report");
|
||||||
|
// },
|
||||||
|
// ),
|
||||||
|
// BreadcrumbItem(title: 'Service Analysis Report'),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
Widget buildTitle(bool isDesktop) {
|
Widget buildTitle(bool isDesktop) {
|
||||||
return // Left side: Breadcrumb inside a Container (optional)
|
return Row(
|
||||||
Container(
|
children: [
|
||||||
child: BreadcrumbNavigation(
|
BreadcrumbNavigation(
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
breadcrumbItems: [
|
breadcrumbItems: [
|
||||||
BreadcrumbItem(
|
BreadcrumbItem(
|
||||||
@ -1420,6 +1440,7 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
|||||||
BreadcrumbItem(title: 'Service Analysis Report'),
|
BreadcrumbItem(title: 'Service Analysis Report'),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -50,6 +50,7 @@ class TravellerDataState extends State<TravellerData> {
|
|||||||
String? userId;
|
String? userId;
|
||||||
int? travellerDataId;
|
int? travellerDataId;
|
||||||
late String isActive = "1";
|
late String isActive = "1";
|
||||||
|
bool isDisable = false;
|
||||||
|
|
||||||
List<String> dataHeader = ["first_name", "last_name", "email", "mobile"];
|
List<String> dataHeader = ["first_name", "last_name", "email", "mobile"];
|
||||||
|
|
||||||
@ -183,9 +184,12 @@ class TravellerDataState extends State<TravellerData> {
|
|||||||
userId = await getUserId();
|
userId = await getUserId();
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
|
isDisable = true;
|
||||||
// This triggers UI rebuild with error messages
|
// This triggers UI rebuild with error messages
|
||||||
if (validateData()) {
|
if (validateData()) {
|
||||||
postTravellerData();
|
postTravellerData();
|
||||||
|
}else{
|
||||||
|
isDisable = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -244,22 +248,38 @@ class TravellerDataState extends State<TravellerData> {
|
|||||||
print("Update - Response: ${response.body}");
|
print("Update - Response: ${response.body}");
|
||||||
_clearError();
|
_clearError();
|
||||||
widget.fetchGetTraveller();
|
widget.fetchGetTraveller();
|
||||||
Navigator.of(context).pop();
|
if (context.mounted) {
|
||||||
|
Navigator.of(context).pop(); // Close modal only if mounted
|
||||||
|
}
|
||||||
|
setState(() {
|
||||||
|
isDisable = false;
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 201:
|
case 201:
|
||||||
print("Save - Response: ${response.body}");
|
print("Save - Response: ${response.body}");
|
||||||
_clearError();
|
_clearError();
|
||||||
await widget.fetchGetTraveller();
|
await widget.fetchGetTraveller();
|
||||||
Navigator.of(context).pop();
|
if (context.mounted) {
|
||||||
|
Navigator.of(context).pop(); // Close modal only if mounted
|
||||||
|
}
|
||||||
|
setState(() {
|
||||||
|
isDisable = false;
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
print("Failed to submit traveller. Status: ${response.statusCode}");
|
print("Failed to submit traveller. Status: ${response.statusCode}");
|
||||||
print("Error: ${response.body}");
|
print("Error: ${response.body}");
|
||||||
|
setState(() {
|
||||||
|
isDisable = false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(" Error submitting plan: $e");
|
print(" Error submitting plan: $e");
|
||||||
|
setState(() {
|
||||||
|
isDisable = false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -530,10 +550,21 @@ class TravellerDataState extends State<TravellerData> {
|
|||||||
// ),
|
// ),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: isDisable
|
||||||
handleSubmit();
|
? null
|
||||||
|
: () async {
|
||||||
|
setState(() {
|
||||||
|
isDisable = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
await handleSubmit();
|
||||||
// You can get text from commentController.text
|
// You can get text from commentController.text
|
||||||
// Navigator.of(context).pop(); // Close the modal
|
// Navigator.of(context).pop(); // Close the modal
|
||||||
|
|
||||||
|
// Optional: re-enable only on error
|
||||||
|
// setState(() {
|
||||||
|
// isDisable = false;
|
||||||
|
// });
|
||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: widget.layoutColor,
|
backgroundColor: widget.layoutColor,
|
||||||
|
|||||||
@ -132,6 +132,7 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<List<dynamic>> fetchGetTraveller() async {
|
Future<List<dynamic>> fetchGetTraveller() async {
|
||||||
|
// return [];
|
||||||
String? ordId = await getOrgId();
|
String? ordId = await getOrgId();
|
||||||
final String apiUrlData =
|
final String apiUrlData =
|
||||||
'$apiUrl/api/travellers?for=table_view&org_id=$ordId';
|
'$apiUrl/api/travellers?for=table_view&org_id=$ordId';
|
||||||
@ -293,7 +294,7 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
breadcrumbItems: [
|
breadcrumbItems: [
|
||||||
BreadcrumbItem(
|
BreadcrumbItem(
|
||||||
title: 'Organization Settings',
|
title: 'Org Settings',
|
||||||
tooltip: 'Go To Organization Settings',
|
tooltip: 'Go To Organization Settings',
|
||||||
onTap: (context) {
|
onTap: (context) {
|
||||||
context.go("/OrganizationSettings");
|
context.go("/OrganizationSettings");
|
||||||
@ -463,6 +464,7 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
FutureBuilder<List<dynamic>>(
|
FutureBuilder<List<dynamic>>(
|
||||||
future: futureTraveller,
|
future: futureTraveller,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
|
final adjHgt = MediaQuery.of(context).size.height;
|
||||||
if (futureTraveller == null) {
|
if (futureTraveller == null) {
|
||||||
return CircularProgressIndicator();
|
return CircularProgressIndicator();
|
||||||
}
|
}
|
||||||
@ -478,9 +480,9 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
const SizedBox(height: 8),
|
SizedBox(height: adjHgt / 4),
|
||||||
Text(
|
Text(
|
||||||
"No Traveller Available ",
|
"No Data Found ",
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
@ -489,15 +491,15 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
Text(
|
// Text(
|
||||||
"Please Create Traveller Details",
|
// "Please Create Traveller Details",
|
||||||
textAlign: TextAlign.center,
|
// textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
// style: GoogleFonts.poppins(
|
||||||
fontSize: 16,
|
// fontSize: 16,
|
||||||
color: Colors.grey,
|
// color: Colors.grey,
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
const SizedBox(height: 20),
|
// const SizedBox(height: 20),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -840,7 +842,7 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
filteredTraveller.isEmpty
|
filteredTraveller.isEmpty
|
||||||
? Center(
|
? Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
"No matches found",
|
"No Matches Found",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: Colors.grey,
|
color: Colors.grey,
|
||||||
@ -855,7 +857,7 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
filteredTraveller.isEmpty
|
filteredTraveller.isEmpty
|
||||||
? Center(
|
? Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
"No matches found",
|
"No Matches Found",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: Colors.grey,
|
color: Colors.grey,
|
||||||
|
|||||||
@ -112,6 +112,7 @@ class _CreateTravelAgentFormDetialsState
|
|||||||
List<String> dataHeader = [
|
List<String> dataHeader = [
|
||||||
"Fname",
|
"Fname",
|
||||||
"Lname",
|
"Lname",
|
||||||
|
"Cname",
|
||||||
"email",
|
"email",
|
||||||
"password",
|
"password",
|
||||||
"dob",
|
"dob",
|
||||||
@ -148,6 +149,7 @@ class _CreateTravelAgentFormDetialsState
|
|||||||
Map<String, dynamic> data = {
|
Map<String, dynamic> data = {
|
||||||
"first_name": controllers["Fname"]?.text,
|
"first_name": controllers["Fname"]?.text,
|
||||||
"last_name": controllers["Lname"]?.text,
|
"last_name": controllers["Lname"]?.text,
|
||||||
|
"company_name": controllers["Cname"]?.text,
|
||||||
"email": controllers["email"]?.text,
|
"email": controllers["email"]?.text,
|
||||||
"password": controllers["password"]?.text,
|
"password": controllers["password"]?.text,
|
||||||
"mobile_no": controllers["mobileNumber"]?.text,
|
"mobile_no": controllers["mobileNumber"]?.text,
|
||||||
@ -212,6 +214,7 @@ class _CreateTravelAgentFormDetialsState
|
|||||||
userIdApi = apiselectedUser?["user_id"] ?? "";
|
userIdApi = apiselectedUser?["user_id"] ?? "";
|
||||||
controllers["Fname"]?.text = apiselectedUser?["first_name"] ?? "";
|
controllers["Fname"]?.text = apiselectedUser?["first_name"] ?? "";
|
||||||
controllers["Lname"]?.text = apiselectedUser?["last_name"] ?? "";
|
controllers["Lname"]?.text = apiselectedUser?["last_name"] ?? "";
|
||||||
|
controllers["Cname"]?.text = apiselectedUser?["company_name"] ?? "";
|
||||||
controllers["email"]?.text = apiselectedUser?["email"] ?? "";
|
controllers["email"]?.text = apiselectedUser?["email"] ?? "";
|
||||||
controllers["password"]?.text = "";
|
controllers["password"]?.text = "";
|
||||||
// controllers["password"]?.text = apiselectedUser?["password"] ?? "";
|
// controllers["password"]?.text = apiselectedUser?["password"] ?? "";
|
||||||
@ -1251,7 +1254,7 @@ class _CreateTravelAgentFormDetialsState
|
|||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
breadcrumbItems: [
|
breadcrumbItems: [
|
||||||
BreadcrumbItem(
|
BreadcrumbItem(
|
||||||
title: 'Organization Settings',
|
title: 'Org Settings',
|
||||||
tooltip: 'Go To Organization Settings',
|
tooltip: 'Go To Organization Settings',
|
||||||
onTap: (context) {
|
onTap: (context) {
|
||||||
context.go("/OrganizationSettings");
|
context.go("/OrganizationSettings");
|
||||||
|
|||||||
@ -142,6 +142,7 @@ class _TravelAgentListScreenState extends State<TravelAgentListScreen> {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
Future<List<dynamic>> fetchUsers() async {
|
Future<List<dynamic>> fetchUsers() async {
|
||||||
|
// return [];
|
||||||
orgId = await getOrgId();
|
orgId = await getOrgId();
|
||||||
final String apiUrlData = '$apiUrl/api/agentList?org_id=$orgId&for=table_view';
|
final String apiUrlData = '$apiUrl/api/agentList?org_id=$orgId&for=table_view';
|
||||||
final String? token = await getToken();
|
final String? token = await getToken();
|
||||||
@ -355,6 +356,8 @@ class _TravelAgentListScreenState extends State<TravelAgentListScreen> {
|
|||||||
false) ||
|
false) ||
|
||||||
(user['last_name']?.toLowerCase().contains(lowerQuery) ??
|
(user['last_name']?.toLowerCase().contains(lowerQuery) ??
|
||||||
false) ||
|
false) ||
|
||||||
|
(user['company_name']?.toLowerCase().contains(lowerQuery) ??
|
||||||
|
false) ||
|
||||||
(user['email']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
(user['email']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||||
(user['role_value']?.toLowerCase().contains(lowerQuery) ??
|
(user['role_value']?.toLowerCase().contains(lowerQuery) ??
|
||||||
false);
|
false);
|
||||||
@ -456,7 +459,7 @@ class _TravelAgentListScreenState extends State<TravelAgentListScreen> {
|
|||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
breadcrumbItems: [
|
breadcrumbItems: [
|
||||||
BreadcrumbItem(
|
BreadcrumbItem(
|
||||||
title: 'Organization Settings',
|
title: 'Org Settings',
|
||||||
tooltip: 'Go To Organization Settings',
|
tooltip: 'Go To Organization Settings',
|
||||||
onTap: (context) {
|
onTap: (context) {
|
||||||
context.go("/OrganizationSettings");
|
context.go("/OrganizationSettings");
|
||||||
@ -490,7 +493,7 @@ class _TravelAgentListScreenState extends State<TravelAgentListScreen> {
|
|||||||
controller: searchController,
|
controller: searchController,
|
||||||
onChanged: filterUsers,
|
onChanged: filterUsers,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: "Search for a Travel Agent",
|
hintText: "Search ...",
|
||||||
hintStyle: TextStyle(
|
hintStyle: TextStyle(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
color: Color(0xFF9E9DBD),
|
color: Color(0xFF9E9DBD),
|
||||||
@ -626,6 +629,10 @@ class _TravelAgentListScreenState extends State<TravelAgentListScreen> {
|
|||||||
FutureBuilder<List<dynamic>>(
|
FutureBuilder<List<dynamic>>(
|
||||||
future: futureUsers,
|
future: futureUsers,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
|
final adjHgt = MediaQuery.of(context).size.height;
|
||||||
|
if (futureUsers == null) {
|
||||||
|
return CircularProgressIndicator();
|
||||||
|
}
|
||||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||||
return const Center(child: CircularProgressIndicator());
|
return const Center(child: CircularProgressIndicator());
|
||||||
} else if (snapshot.hasError ||
|
} else if (snapshot.hasError ||
|
||||||
@ -647,7 +654,7 @@ class _TravelAgentListScreenState extends State<TravelAgentListScreen> {
|
|||||||
// fontWeight: FontWeight.bold,
|
// fontWeight: FontWeight.bold,
|
||||||
// color: Colors.redAccent),
|
// color: Colors.redAccent),
|
||||||
// ),
|
// ),
|
||||||
const SizedBox(height: 8),
|
SizedBox(height: adjHgt / 4),
|
||||||
Text(
|
Text(
|
||||||
"No Travel Agent Found",
|
"No Travel Agent Found",
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
@ -658,15 +665,15 @@ class _TravelAgentListScreenState extends State<TravelAgentListScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
Text(
|
// Text(
|
||||||
"Please Create Travel Agent",
|
// "Please Create Travel Agent",
|
||||||
textAlign: TextAlign.center,
|
// textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
// style: GoogleFonts.poppins(
|
||||||
fontSize: 16,
|
// fontSize: 16,
|
||||||
color: Colors.grey,
|
// color: Colors.grey,
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
const SizedBox(height: 20),
|
// const SizedBox(height: 20),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -714,6 +721,15 @@ class _TravelAgentListScreenState extends State<TravelAgentListScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
DataColumn(
|
||||||
|
label: Text(
|
||||||
|
'Company Name',
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 13,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
DataColumn(
|
DataColumn(
|
||||||
label: Text(
|
label: Text(
|
||||||
'Email ID',
|
'Email ID',
|
||||||
@ -768,6 +784,15 @@ class _TravelAgentListScreenState extends State<TravelAgentListScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
DataCell(
|
||||||
|
Text(
|
||||||
|
user['company_name'] ?? '',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 13,
|
||||||
|
fontFamily: "Inter",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
DataCell(
|
DataCell(
|
||||||
Text(
|
Text(
|
||||||
user['email'] ?? '',
|
user['email'] ?? '',
|
||||||
@ -1014,6 +1039,25 @@ class _TravelAgentListScreenState extends State<TravelAgentListScreen> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(height: 2),
|
SizedBox(height: 2),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment:
|
||||||
|
CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"${user['company_name'] ?? ''}",
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 12,
|
||||||
|
color: Colors.black87,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SizedBox(height: 2),
|
||||||
|
|
||||||
// Name
|
// Name
|
||||||
Row(
|
Row(
|
||||||
@ -1093,7 +1137,7 @@ class _TravelAgentListScreenState extends State<TravelAgentListScreen> {
|
|||||||
filteredUsers.isEmpty
|
filteredUsers.isEmpty
|
||||||
? Center(
|
? Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
"No Travel Agents found",
|
"No Travel Agents Found",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: Colors.grey,
|
color: Colors.grey,
|
||||||
@ -1108,7 +1152,7 @@ class _TravelAgentListScreenState extends State<TravelAgentListScreen> {
|
|||||||
filteredUsers.isEmpty
|
filteredUsers.isEmpty
|
||||||
? Center(
|
? Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
"No Travel Agents found",
|
"No Data Found",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: Colors.grey,
|
color: Colors.grey,
|
||||||
|
|||||||
@ -104,6 +104,7 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
List<String> dataHeader = [
|
List<String> dataHeader = [
|
||||||
"Fname",
|
"Fname",
|
||||||
"Lname",
|
"Lname",
|
||||||
|
"Cname",
|
||||||
"email",
|
"email",
|
||||||
"password",
|
"password",
|
||||||
"dob",
|
"dob",
|
||||||
@ -351,8 +352,8 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
SizedBox(height: 10),
|
SizedBox(height: 10),
|
||||||
_buildFirstRow(widget.isDesktop),
|
_buildFirstRow(widget.isDesktop),
|
||||||
SizedBox(height: 10),
|
SizedBox(height: 10),
|
||||||
_buildSecondRow(widget.isDesktop),
|
// _buildSecondRow(widget.isDesktop),
|
||||||
SizedBox(height: 10),
|
// SizedBox(height: 10),
|
||||||
_buildThirdRow(widget.isDesktop),
|
_buildThirdRow(widget.isDesktop),
|
||||||
SizedBox(height: 10),
|
SizedBox(height: 10),
|
||||||
_buildForthRow(widget.isDesktop),
|
_buildForthRow(widget.isDesktop),
|
||||||
@ -586,6 +587,8 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
Spacer(),
|
Spacer(),
|
||||||
buildLastNameField(),
|
buildLastNameField(),
|
||||||
Spacer(), // Space after Last Name
|
Spacer(), // Space after Last Name
|
||||||
|
buildCompanyNameField(),
|
||||||
|
Spacer(),
|
||||||
// buildGenderField(),
|
// buildGenderField(),
|
||||||
// SizedBox(width: 15),
|
// SizedBox(width: 15),
|
||||||
// buildDobField(),
|
// buildDobField(),
|
||||||
@ -601,6 +604,8 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
SizedBox(height: 8), // Vertical space
|
SizedBox(height: 8), // Vertical space
|
||||||
buildLastNameField(),
|
buildLastNameField(),
|
||||||
SizedBox(height: 8),
|
SizedBox(height: 8),
|
||||||
|
buildCompanyNameField(),
|
||||||
|
SizedBox(height: 8),
|
||||||
// buildGenderField(),
|
// buildGenderField(),
|
||||||
// SizedBox(height: 8),
|
// SizedBox(height: 8),
|
||||||
// buildDobField(),
|
// buildDobField(),
|
||||||
@ -612,33 +617,33 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildSecondRow(bool isDesktop) {
|
// Widget _buildSecondRow(bool isDesktop) {
|
||||||
return Container(
|
// return Container(
|
||||||
color: Colors.white,
|
// color: Colors.white,
|
||||||
child:
|
// child:
|
||||||
widget.isDesktop
|
// widget.isDesktop
|
||||||
? Row(
|
// ? Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
// children: [
|
||||||
// buildEmailField(),
|
// // buildEmailField(),
|
||||||
// Spacer(),
|
// // Spacer(),
|
||||||
// buildMobileField(),
|
// // buildMobileField(),
|
||||||
// Spacer(), // Space after Last Name
|
// // Spacer(), // Space after Last Name
|
||||||
// buildAlternateMobileField(),
|
// // buildAlternateMobileField(),
|
||||||
],
|
// ],
|
||||||
)
|
// )
|
||||||
: Column(
|
// : Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
// children: [
|
||||||
// buildMobileField(),
|
// // buildMobileField(),
|
||||||
// SizedBox(height: 8), // Vertical space
|
// // SizedBox(height: 8), // Vertical space
|
||||||
// buildAlternateMobileField(),
|
// // buildAlternateMobileField(),
|
||||||
// SizedBox(height: 8),
|
// // SizedBox(height: 8),
|
||||||
// buildEmailField(),
|
// // buildEmailField(),
|
||||||
],
|
// ],
|
||||||
),
|
// ),
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
|
|
||||||
Widget _buildThirdRow(bool isDesktop) {
|
Widget _buildThirdRow(bool isDesktop) {
|
||||||
void _openPopup() {
|
void _openPopup() {
|
||||||
@ -668,11 +673,15 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
children: [
|
children: [
|
||||||
if (!widget.apiselectedUser) ...[
|
if (!widget.apiselectedUser) ...[
|
||||||
buildEmailField(),
|
buildEmailField(),
|
||||||
|
// SizedBox(
|
||||||
|
// width: MediaQuery.of(context).size.width * 0.014,
|
||||||
|
// ),
|
||||||
Spacer(),
|
Spacer(),
|
||||||
buildPassword(),
|
buildPassword(),
|
||||||
SizedBox(
|
// SizedBox(
|
||||||
width: MediaQuery.of(context).size.width * 0.015,
|
// width: MediaQuery.of(context).size.width * 0.015,
|
||||||
),
|
// ),
|
||||||
|
Spacer(),
|
||||||
buildRole(),
|
buildRole(),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
@ -797,6 +806,7 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
CustomTextFieldUserWrapper(
|
CustomTextFieldUserWrapper(
|
||||||
isFocused: focusStates["FnameFocused"] ?? false,
|
isFocused: focusStates["FnameFocused"] ?? false,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
|
width: MediaQuery.of(context).size.width * 0.12,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
@ -848,6 +858,7 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
CustomTextFieldUserWrapper(
|
CustomTextFieldUserWrapper(
|
||||||
isFocused: focusStates["LnameFocused"] ?? false,
|
isFocused: focusStates["LnameFocused"] ?? false,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
|
width: MediaQuery.of(context).size.width * 0.12,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
@ -879,6 +890,43 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget buildCompanyNameField() {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Company Name",
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: 5),
|
||||||
|
CustomTextFieldUserWrapper(
|
||||||
|
isFocused: focusStates["CnameFocused"] ?? false,
|
||||||
|
isDesktop: widget.isDesktop,
|
||||||
|
child: SizedBox(
|
||||||
|
height: 40,
|
||||||
|
child: TextField(
|
||||||
|
style: TextStyle(fontSize: 12, color: Colors.black),
|
||||||
|
focusNode: focusNodes["CnameFocusNode"],
|
||||||
|
controller: widget.controllers["Cname"],
|
||||||
|
enabled: !widget.isViewMode,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
labelText: "CompanyName",
|
||||||
|
labelStyle: TextStyle(fontSize: 12, color: Colors.grey),
|
||||||
|
floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||||
|
border: InputBorder.none,
|
||||||
|
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Widget buildGenderField() {
|
Widget buildGenderField() {
|
||||||
List<String> genderOptions = ["Male", "Female"];
|
List<String> genderOptions = ["Male", "Female"];
|
||||||
|
|
||||||
@ -1109,11 +1157,12 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldUserWrapper(
|
CustomTextFieldUserWrapper(
|
||||||
isFocused: false,
|
isFocused: focusStates["emailFocused"] ?? false,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
|
focusNode: focusNodes["emailFocusNode"],
|
||||||
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
||||||
controller: widget.controllers["email"],
|
controller: widget.controllers["email"],
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
@ -1159,13 +1208,14 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldUserWrapper(
|
CustomTextFieldUserWrapper(
|
||||||
isFocused: false,
|
isFocused: focusStates["mobileNumberFocused"] ?? false,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
width: MediaQuery.of(context).size.width * 0.12,
|
width: MediaQuery.of(context).size.width * 0.12,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
||||||
|
focusNode: focusNodes["mobileNumberFocusNode"],
|
||||||
controller: widget.controllers["mobileNumber"],
|
controller: widget.controllers["mobileNumber"],
|
||||||
enabled: !widget.isViewMode,
|
enabled: !widget.isViewMode,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
@ -1221,12 +1271,14 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldUserWrapper(
|
CustomTextFieldUserWrapper(
|
||||||
isFocused: false,
|
// isFocused: false,
|
||||||
|
isFocused: focusStates["alternateMobileFocused"] ?? false,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
width: MediaQuery.of(context).size.width * 0.12,
|
width: MediaQuery.of(context).size.width * 0.12,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
|
focusNode: focusNodes["alternateMobileFocusNode"],
|
||||||
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
||||||
controller: widget.controllers["alternateMobile"],
|
controller: widget.controllers["alternateMobile"],
|
||||||
enabled: !widget.isViewMode,
|
enabled: !widget.isViewMode,
|
||||||
@ -1297,10 +1349,24 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldUserWrapper(
|
CustomTextFieldUserWrapper(
|
||||||
isFocused: false,
|
isFocused: focusStates["countryFocusNode"] ?? false,
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 0),
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
|
width: double.infinity,
|
||||||
|
child: Focus(
|
||||||
|
focusNode: focusNodes["countryFocusNode"],
|
||||||
|
onFocusChange: (hasFocus) {
|
||||||
|
setState(() {
|
||||||
|
focusStates["countryFocused"] = hasFocus;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
// Request focus when user taps
|
||||||
|
focusNodes["countryFocusNode"]?.requestFocus();
|
||||||
|
},
|
||||||
child: DropdownSearch<String>(
|
child: DropdownSearch<String>(
|
||||||
selectedItem: countryMap[selectedCountry],
|
selectedItem: countryMap[selectedCountry],
|
||||||
enabled: !widget.isViewMode,
|
enabled: !widget.isViewMode,
|
||||||
@ -1365,8 +1431,33 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
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(horizontal: 1),
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(focusStates["countryFocused"] ?? false)
|
||||||
|
? (layoutColor ?? Colors.blue)
|
||||||
|
: Colors.white,
|
||||||
|
// width: 0.5,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(focusStates["countryFocused"] ?? false)
|
||||||
|
? (layoutColor ?? Colors.blue)
|
||||||
|
: Colors.white,
|
||||||
|
// width: 0.5,
|
||||||
|
// const Color(0xFFD6D5E6),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color : (layoutColor ?? Colors.grey), width: 1),
|
||||||
|
),
|
||||||
|
contentPadding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 8.0,),
|
||||||
|
// contentPadding: EdgeInsets.symmetric(horizontal: 1),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
dropdownBuilder:
|
dropdownBuilder:
|
||||||
@ -1416,7 +1507,7 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
countryCode,
|
countryCode,
|
||||||
); // ✅ send code not name
|
); // ✅ send code not name
|
||||||
},
|
},
|
||||||
),
|
),),),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -1437,11 +1528,12 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldUserWrapper(
|
CustomTextFieldUserWrapper(
|
||||||
isFocused: false,
|
isFocused: focusStates["postalCodeFocused"] ?? false,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
|
focusNode: focusNodes["postalCodeFocusNode"],
|
||||||
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
||||||
controller: widget.controllers["postalCode"],
|
controller: widget.controllers["postalCode"],
|
||||||
enabled: !widget.isViewMode,
|
enabled: !widget.isViewMode,
|
||||||
@ -1586,11 +1678,12 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldUserWrapper(
|
CustomTextFieldUserWrapper(
|
||||||
isFocused: false,
|
isFocused: focusStates["addressFocused"] ?? false,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 80,
|
height: 80,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
|
focusNode: focusNodes["addressFocusNode"],
|
||||||
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
||||||
controller: widget.controllers["address"],
|
controller: widget.controllers["address"],
|
||||||
enabled: !widget.isViewMode,
|
enabled: !widget.isViewMode,
|
||||||
@ -1628,11 +1721,12 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldUserWrapper(
|
CustomTextFieldUserWrapper(
|
||||||
isFocused: false,
|
isFocused: focusStates["passwordFocused"] ?? false,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
|
focusNode: focusNodes["passwordFocusNode"],
|
||||||
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
||||||
controller: widget.controllers["password"],
|
controller: widget.controllers["password"],
|
||||||
enabled: !widget.isViewMode,
|
enabled: !widget.isViewMode,
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:html' as html;
|
|
||||||
import 'dart:typed_data'; // Import for Uint8List
|
import 'dart:typed_data'; // Import for Uint8List
|
||||||
|
|
||||||
import 'package:bcrypt/bcrypt.dart';
|
import 'package:bcrypt/bcrypt.dart';
|
||||||
@ -59,6 +58,7 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
String? userIdApi;
|
String? userIdApi;
|
||||||
|
|
||||||
bool isCheckingToken = false;
|
bool isCheckingToken = false;
|
||||||
|
bool isDisable = false;
|
||||||
|
|
||||||
String? token;
|
String? token;
|
||||||
|
|
||||||
@ -912,17 +912,17 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
// valid_from: 20-06-2025, valid_upto: 19-06-2025
|
// valid_from: 20-06-2025, valid_upto: 19-06-2025
|
||||||
DateTime? valid_from = data?['valid_from'];
|
DateTime? validFrom = data['valid_from'];
|
||||||
DateTime? valid_upto = data?['valid_upto'];
|
DateTime? validUpto = data['valid_upto'];
|
||||||
|
|
||||||
if (valid_from != null &&
|
if (validFrom != null &&
|
||||||
valid_upto != null &&
|
validUpto != null &&
|
||||||
valid_from.toString().isNotEmpty &&
|
validFrom.toString().isNotEmpty &&
|
||||||
valid_upto.toString().isNotEmpty) {
|
validUpto.toString().isNotEmpty) {
|
||||||
try {
|
try {
|
||||||
final format = DateFormat("dd-MM-yyyy");
|
final format = DateFormat("dd-MM-yyyy");
|
||||||
final checkValidFrom = format.parse("$valid_from");
|
final checkValidFrom = format.parse("$validFrom");
|
||||||
final checkValidUpto = format.parse("$valid_upto");
|
final checkValidUpto = format.parse("$validUpto");
|
||||||
|
|
||||||
if (checkValidUpto.isBefore(checkValidFrom)) {
|
if (checkValidUpto.isBefore(checkValidFrom)) {
|
||||||
// return "valid upto cannot be earlier than valid from";
|
// return "valid upto cannot be earlier than valid from";
|
||||||
@ -1157,7 +1157,7 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
print("Response body: ${response.body}");
|
print("Response body: ${response.body}");
|
||||||
|
|
||||||
if (response.statusCode == 200 || response.statusCode == 201) {
|
if (response.statusCode == 200 || response.statusCode == 201) {
|
||||||
dispose();
|
// dispose();
|
||||||
print("✅ User submitted successfully!");
|
print("✅ User submitted successfully!");
|
||||||
|
|
||||||
print("📨 Response: ${response.body}");
|
print("📨 Response: ${response.body}");
|
||||||
@ -1334,32 +1334,6 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
apiselectedUser != null
|
|
||||||
? Text(
|
|
||||||
"Profile",
|
|
||||||
style: GoogleFonts.poppins(
|
|
||||||
fontSize: isDesktop ? 15 : 12,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
color: Colors.black,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: Container(
|
|
||||||
child: BreadcrumbNavigation(
|
|
||||||
isDesktop: isDesktop,
|
|
||||||
breadcrumbItems: [
|
|
||||||
BreadcrumbItem(
|
|
||||||
title: 'Users',
|
|
||||||
tooltip: 'Go To Users',
|
|
||||||
onTap: (context) {
|
|
||||||
context.go("/listUser");
|
|
||||||
},
|
|
||||||
),
|
|
||||||
BreadcrumbItem(title: 'Create New User'),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
// Text(
|
// Text(
|
||||||
// apiselectedUser != null ? "Profile" : "Create New User",
|
// apiselectedUser != null ? "Profile" : "Create New User",
|
||||||
// style: GoogleFonts.poppins(
|
// style: GoogleFonts.poppins(
|
||||||
@ -1367,7 +1341,8 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
// fontWeight: FontWeight.w600,
|
// fontWeight: FontWeight.w600,
|
||||||
// color: Colors.black,
|
// color: Colors.black,
|
||||||
// ),
|
// ),
|
||||||
// ),
|
// ), //old very first
|
||||||
|
|
||||||
// if (isEditProfile)
|
// if (isEditProfile)
|
||||||
// IconButton(
|
// IconButton(
|
||||||
// icon: Icon(
|
// icon: Icon(
|
||||||
@ -1380,6 +1355,44 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
// isViewMode = !isViewMode;
|
// isViewMode = !isViewMode;
|
||||||
// });
|
// });
|
||||||
// })
|
// })
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
if (apiselectedUser != null)
|
||||||
|
isEditProfile
|
||||||
|
? Text( "Profile",
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: isDesktop ? 15 : 12,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: BreadcrumbNavigation(
|
||||||
|
isDesktop: isDesktop,
|
||||||
|
breadcrumbItems: [
|
||||||
|
BreadcrumbItem(
|
||||||
|
title: 'Users',
|
||||||
|
tooltip: 'Go To Users',
|
||||||
|
onTap: (context) {
|
||||||
|
context.go("/listUser");
|
||||||
|
},
|
||||||
|
),
|
||||||
|
BreadcrumbItem(title: 'Edit User'),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
else
|
||||||
|
BreadcrumbNavigation(
|
||||||
|
isDesktop: isDesktop,
|
||||||
|
breadcrumbItems: [
|
||||||
|
BreadcrumbItem(
|
||||||
|
title: 'Users',
|
||||||
|
tooltip: 'Go To Users',
|
||||||
|
onTap: (context) {
|
||||||
|
context.go("/listUser");
|
||||||
|
},
|
||||||
|
),
|
||||||
|
BreadcrumbItem(title: 'Create User'),
|
||||||
|
],
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(height: 18),
|
SizedBox(height: 18),
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import 'package:google_fonts/google_fonts.dart';
|
|||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
import '../../../services/apiService.dart';
|
import '../../../services/apiService.dart';
|
||||||
|
import '../../../utils/auth_utils.dart';
|
||||||
import '../../../widgets/custom_user_form.dart';
|
import '../../../widgets/custom_user_form.dart';
|
||||||
|
|
||||||
class OfficeDetails extends StatefulWidget {
|
class OfficeDetails extends StatefulWidget {
|
||||||
@ -108,6 +109,28 @@ class _OfficeDetailsState extends State<OfficeDetails> {
|
|||||||
DateTime? _selectedEndDate;
|
DateTime? _selectedEndDate;
|
||||||
html.File? passportFile;
|
html.File? passportFile;
|
||||||
|
|
||||||
|
final FocusNode _employeeCodeFocusNode = FocusNode();
|
||||||
|
final FocusNode _departmentFocusNode = FocusNode();
|
||||||
|
final FocusNode _groupFocusNode = FocusNode();
|
||||||
|
final FocusNode _firstApprovalFocusNode = FocusNode();
|
||||||
|
final FocusNode _secondApprovalFocusNode = FocusNode();
|
||||||
|
final FocusNode _thirdApprovalFocusNode = FocusNode();
|
||||||
|
final FocusNode _exceptionalApprovalFocusNode = FocusNode();
|
||||||
|
final FocusNode _delegateFocusNode = FocusNode();
|
||||||
|
final FocusNode _startDateFocusNode = FocusNode();
|
||||||
|
final FocusNode _endDateFocusNode = FocusNode();
|
||||||
|
|
||||||
|
bool _employeeCodeFocus = false;
|
||||||
|
bool _departmentFocus = false;
|
||||||
|
bool _groupFocus = false;
|
||||||
|
bool _firstApprovalFocus = false;
|
||||||
|
bool _secondApprovalFocus = false;
|
||||||
|
bool _thirdApprovalFocus = false;
|
||||||
|
bool _exceptionalApprovalFocus = false;
|
||||||
|
bool _delegateFocus = false;
|
||||||
|
bool _startDateFocus = false;
|
||||||
|
bool _endDateFocus = false;
|
||||||
|
|
||||||
List<String> dataHeader = [
|
List<String> dataHeader = [
|
||||||
"Fname",
|
"Fname",
|
||||||
"Lname",
|
"Lname",
|
||||||
@ -137,12 +160,16 @@ class _OfficeDetailsState extends State<OfficeDetails> {
|
|||||||
"changePassword",
|
"changePassword",
|
||||||
];
|
];
|
||||||
|
|
||||||
Color? layoutColor;
|
// Color? layoutColor;
|
||||||
|
Color layoutColor = Colors.grey;
|
||||||
Color? bodyColor;
|
Color? bodyColor;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
loadInitialData();
|
||||||
|
});
|
||||||
apiCountryData = null;
|
apiCountryData = null;
|
||||||
apiUserData = null;
|
apiUserData = null;
|
||||||
apiCostData = null;
|
apiCostData = null;
|
||||||
@ -162,6 +189,44 @@ class _OfficeDetailsState extends State<OfficeDetails> {
|
|||||||
fetchDepartment();
|
fetchDepartment();
|
||||||
fetchUsers();
|
fetchUsers();
|
||||||
fetchFindGroup();
|
fetchFindGroup();
|
||||||
|
|
||||||
|
|
||||||
|
_addFocusListener(_employeeCodeFocusNode, (focus) => _employeeCodeFocus = focus);
|
||||||
|
_addFocusListener(_departmentFocusNode, (focus) => _departmentFocus = focus);
|
||||||
|
_addFocusListener(_groupFocusNode, (focus) => _groupFocus = focus);
|
||||||
|
_addFocusListener(_firstApprovalFocusNode, (focus) => _firstApprovalFocus = focus);
|
||||||
|
_addFocusListener(_secondApprovalFocusNode, (focus) => _secondApprovalFocus = focus);
|
||||||
|
_addFocusListener(_thirdApprovalFocusNode, (focus) => _thirdApprovalFocus = focus);
|
||||||
|
_addFocusListener(_exceptionalApprovalFocusNode, (focus) => _exceptionalApprovalFocus = focus);
|
||||||
|
_addFocusListener(_delegateFocusNode, (focus) => _delegateFocus = focus);
|
||||||
|
_addFocusListener(_startDateFocusNode, (focus) => _startDateFocus = focus);
|
||||||
|
_addFocusListener(_endDateFocusNode, (focus) => _endDateFocus = focus);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void _addFocusListener(FocusNode node, Function(bool) updateState) {
|
||||||
|
node.addListener(() {
|
||||||
|
setState(() {
|
||||||
|
updateState(node.hasFocus);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void loadInitialData() async {
|
||||||
|
String? layoutString = await getLayoutColor();
|
||||||
|
String? bodyStringColor = await getBodyColor();
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
layoutColor =
|
||||||
|
layoutString != null
|
||||||
|
? Color(int.parse(layoutString))
|
||||||
|
: Colors.redAccent;
|
||||||
|
|
||||||
|
bodyColor =
|
||||||
|
bodyStringColor != null
|
||||||
|
? Color(int.parse(bodyStringColor))
|
||||||
|
: Colors.white;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> apiCheckDuplicate(
|
Future<void> apiCheckDuplicate(
|
||||||
@ -459,14 +524,14 @@ class _OfficeDetailsState extends State<OfficeDetails> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldUserWrapper(
|
CustomTextFieldUserWrapper(
|
||||||
isFocused: false,
|
isFocused: _employeeCodeFocus,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
||||||
|
focusNode: _employeeCodeFocusNode,
|
||||||
controller: widget.controllers["employeeCode"],
|
controller: widget.controllers["employeeCode"],
|
||||||
|
|
||||||
enabled: !widget.isViewMode,
|
enabled: !widget.isViewMode,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
_clearError("employee_code");
|
_clearError("employee_code");
|
||||||
@ -585,10 +650,24 @@ class _OfficeDetailsState extends State<OfficeDetails> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldUserWrapper(
|
CustomTextFieldUserWrapper(
|
||||||
isFocused: false,
|
isFocused: _departmentFocus,
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 0),
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
|
width: double.infinity,
|
||||||
|
child: Focus(
|
||||||
|
focusNode: _departmentFocusNode,
|
||||||
|
onFocusChange: (hasFocus) {
|
||||||
|
setState(() {
|
||||||
|
_departmentFocus = hasFocus;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
// Request focus when user taps
|
||||||
|
_departmentFocusNode?.requestFocus();
|
||||||
|
},
|
||||||
child: DropdownSearch<String>(
|
child: DropdownSearch<String>(
|
||||||
selectedItem: departmentMap[selectedDepartment],
|
selectedItem: departmentMap[selectedDepartment],
|
||||||
enabled: !widget.isViewMode,
|
enabled: !widget.isViewMode,
|
||||||
@ -619,8 +698,32 @@ class _OfficeDetailsState extends State<OfficeDetails> {
|
|||||||
|
|
||||||
dropdownDecoratorProps: DropDownDecoratorProps(
|
dropdownDecoratorProps: DropDownDecoratorProps(
|
||||||
dropdownSearchDecoration: InputDecoration(
|
dropdownSearchDecoration: InputDecoration(
|
||||||
border: InputBorder.none,
|
border: OutlineInputBorder(
|
||||||
contentPadding: EdgeInsets.symmetric(horizontal: 1),
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(_departmentFocus ?? false)
|
||||||
|
? (layoutColor ?? Colors.white)
|
||||||
|
: Colors.white,
|
||||||
|
width: 0.5,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(_departmentFocus ?? false)
|
||||||
|
? (layoutColor ?? Colors.white)
|
||||||
|
: Colors.white,
|
||||||
|
width: 0.5,
|
||||||
|
// const Color(0xFFD6D5E6),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color : (layoutColor ?? Colors.grey), width: 0.5),
|
||||||
|
),
|
||||||
|
contentPadding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 8.0),
|
||||||
|
// contentPadding: EdgeInsets.symmetric(horizontal: 1),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
dropdownBuilder:
|
dropdownBuilder:
|
||||||
@ -653,7 +756,7 @@ class _OfficeDetailsState extends State<OfficeDetails> {
|
|||||||
departmentId,
|
departmentId,
|
||||||
); // Send department_id
|
); // Send department_id
|
||||||
},
|
},
|
||||||
),
|
),),),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -718,10 +821,24 @@ class _OfficeDetailsState extends State<OfficeDetails> {
|
|||||||
// ),
|
// ),
|
||||||
// ),
|
// ),
|
||||||
CustomTextFieldUserWrapper(
|
CustomTextFieldUserWrapper(
|
||||||
isFocused: false,
|
isFocused: _groupFocus,
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 0),
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
|
width: double.infinity,
|
||||||
|
child: Focus(
|
||||||
|
focusNode: _groupFocusNode,
|
||||||
|
onFocusChange: (hasFocus) {
|
||||||
|
setState(() {
|
||||||
|
_groupFocus = hasFocus;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
// Request focus when user taps
|
||||||
|
_groupFocusNode?.requestFocus();
|
||||||
|
},
|
||||||
child:
|
child:
|
||||||
apiAllGroups == null
|
apiAllGroups == null
|
||||||
? Center(
|
? Center(
|
||||||
@ -774,8 +891,31 @@ class _OfficeDetailsState extends State<OfficeDetails> {
|
|||||||
|
|
||||||
dropdownDecoratorProps: DropDownDecoratorProps(
|
dropdownDecoratorProps: DropDownDecoratorProps(
|
||||||
dropdownSearchDecoration: InputDecoration(
|
dropdownSearchDecoration: InputDecoration(
|
||||||
border: InputBorder.none,
|
border: OutlineInputBorder(
|
||||||
contentPadding: EdgeInsets.symmetric(horizontal: 1),
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(_groupFocus ?? false)
|
||||||
|
? (layoutColor ?? Colors.white)
|
||||||
|
: Colors.white,
|
||||||
|
width: 0.5,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(_groupFocus ?? false)
|
||||||
|
? (layoutColor ?? Colors.white)
|
||||||
|
: Colors.white,
|
||||||
|
width: 0.5,
|
||||||
|
// const Color(0xFFD6D5E6),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color : (layoutColor ?? Colors.grey), width: 0.5),
|
||||||
|
),
|
||||||
|
contentPadding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 8.0),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
dropdownBuilder:
|
dropdownBuilder:
|
||||||
@ -805,6 +945,7 @@ class _OfficeDetailsState extends State<OfficeDetails> {
|
|||||||
); // ✅ pass the ID not the name
|
); // ✅ pass the ID not the name
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
),),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -834,10 +975,24 @@ class _OfficeDetailsState extends State<OfficeDetails> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldUserWrapper(
|
CustomTextFieldUserWrapper(
|
||||||
isFocused: false,
|
isFocused: _firstApprovalFocus,
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 0),
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
|
width: double.infinity,
|
||||||
|
child: Focus(
|
||||||
|
focusNode: _firstApprovalFocusNode,
|
||||||
|
onFocusChange: (hasFocus) {
|
||||||
|
setState(() {
|
||||||
|
_firstApprovalFocus= hasFocus;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
// Request focus when user taps
|
||||||
|
_firstApprovalFocusNode?.requestFocus();
|
||||||
|
},
|
||||||
child:
|
child:
|
||||||
apiUserData == null
|
apiUserData == null
|
||||||
? Center(
|
? Center(
|
||||||
@ -884,11 +1039,32 @@ class _OfficeDetailsState extends State<OfficeDetails> {
|
|||||||
}).toList(),
|
}).toList(),
|
||||||
dropdownDecoratorProps: DropDownDecoratorProps(
|
dropdownDecoratorProps: DropDownDecoratorProps(
|
||||||
dropdownSearchDecoration: InputDecoration(
|
dropdownSearchDecoration: InputDecoration(
|
||||||
border: InputBorder.none,
|
border: OutlineInputBorder(
|
||||||
contentPadding: EdgeInsets.symmetric(
|
borderRadius: BorderRadius.circular(8),
|
||||||
horizontal: 1,
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(_firstApprovalFocus ?? false)
|
||||||
|
? (layoutColor ?? Colors.white)
|
||||||
|
: Colors.white,
|
||||||
|
width: 0.5,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(_firstApprovalFocus ?? false)
|
||||||
|
? (layoutColor ?? Colors.white)
|
||||||
|
: Colors.white,
|
||||||
|
width: 0.5,
|
||||||
|
// const Color(0xFFD6D5E6),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color : (layoutColor ?? Colors.grey), width: 0.5),
|
||||||
|
),
|
||||||
|
contentPadding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 8.0),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
dropdownBuilder:
|
dropdownBuilder:
|
||||||
(context, selectedItem) => Align(
|
(context, selectedItem) => Align(
|
||||||
@ -934,6 +1110,7 @@ class _OfficeDetailsState extends State<OfficeDetails> {
|
|||||||
); // ✅ not newValue, but approverId
|
); // ✅ not newValue, but approverId
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
),),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -970,10 +1147,24 @@ class _OfficeDetailsState extends State<OfficeDetails> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldUserWrapper(
|
CustomTextFieldUserWrapper(
|
||||||
isFocused: false,
|
isFocused: _secondApprovalFocus,
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 0),
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
|
width: double.infinity,
|
||||||
|
child: Focus(
|
||||||
|
focusNode: _secondApprovalFocusNode,
|
||||||
|
onFocusChange: (hasFocus) {
|
||||||
|
setState(() {
|
||||||
|
_secondApprovalFocus = hasFocus;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
// Request focus when user taps
|
||||||
|
_secondApprovalFocusNode?.requestFocus();
|
||||||
|
},
|
||||||
child:
|
child:
|
||||||
apiUserData == null
|
apiUserData == null
|
||||||
? Center(
|
? Center(
|
||||||
@ -1020,11 +1211,32 @@ class _OfficeDetailsState extends State<OfficeDetails> {
|
|||||||
}).toList(),
|
}).toList(),
|
||||||
dropdownDecoratorProps: DropDownDecoratorProps(
|
dropdownDecoratorProps: DropDownDecoratorProps(
|
||||||
dropdownSearchDecoration: InputDecoration(
|
dropdownSearchDecoration: InputDecoration(
|
||||||
border: InputBorder.none,
|
border: OutlineInputBorder(
|
||||||
contentPadding: EdgeInsets.symmetric(
|
borderRadius: BorderRadius.circular(8),
|
||||||
horizontal: 1,
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(_secondApprovalFocus ?? false)
|
||||||
|
? (layoutColor ?? Colors.white)
|
||||||
|
: Colors.white,
|
||||||
|
width: 0.5,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(_secondApprovalFocus ?? false)
|
||||||
|
? (layoutColor ?? Colors.white)
|
||||||
|
: Colors.white,
|
||||||
|
width: 0.5,
|
||||||
|
// const Color(0xFFD6D5E6),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color : (layoutColor ?? Colors.grey), width: 0.5),
|
||||||
|
),
|
||||||
|
contentPadding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 8.0),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
dropdownBuilder:
|
dropdownBuilder:
|
||||||
(context, selectedItem) => Align(
|
(context, selectedItem) => Align(
|
||||||
@ -1069,6 +1281,7 @@ class _OfficeDetailsState extends State<OfficeDetails> {
|
|||||||
// });
|
// });
|
||||||
// },
|
// },
|
||||||
),
|
),
|
||||||
|
),),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -1105,10 +1318,24 @@ class _OfficeDetailsState extends State<OfficeDetails> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldUserWrapper(
|
CustomTextFieldUserWrapper(
|
||||||
isFocused: false,
|
isFocused: _thirdApprovalFocus,
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 0),
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
|
width: double.infinity,
|
||||||
|
child: Focus(
|
||||||
|
focusNode: _thirdApprovalFocusNode,
|
||||||
|
onFocusChange: (hasFocus) {
|
||||||
|
setState(() {
|
||||||
|
_thirdApprovalFocus = hasFocus;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
// Request focus when user taps
|
||||||
|
_thirdApprovalFocusNode?.requestFocus();
|
||||||
|
},
|
||||||
child:
|
child:
|
||||||
apiUserData == null
|
apiUserData == null
|
||||||
? Center(
|
? Center(
|
||||||
@ -1155,11 +1382,32 @@ class _OfficeDetailsState extends State<OfficeDetails> {
|
|||||||
}).toList(),
|
}).toList(),
|
||||||
dropdownDecoratorProps: DropDownDecoratorProps(
|
dropdownDecoratorProps: DropDownDecoratorProps(
|
||||||
dropdownSearchDecoration: InputDecoration(
|
dropdownSearchDecoration: InputDecoration(
|
||||||
border: InputBorder.none,
|
border: OutlineInputBorder(
|
||||||
contentPadding: EdgeInsets.symmetric(
|
borderRadius: BorderRadius.circular(8),
|
||||||
horizontal: 1,
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(_thirdApprovalFocus ?? false)
|
||||||
|
? (layoutColor ?? Colors.white)
|
||||||
|
: Colors.white,
|
||||||
|
width: 0.5,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(_thirdApprovalFocus ?? false)
|
||||||
|
? (layoutColor ?? Colors.white)
|
||||||
|
: Colors.white,
|
||||||
|
width: 0.5,
|
||||||
|
// const Color(0xFFD6D5E6),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color : (layoutColor ?? Colors.grey), width: 0.5),
|
||||||
|
),
|
||||||
|
contentPadding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 8.0),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
dropdownBuilder:
|
dropdownBuilder:
|
||||||
(context, selectedItem) => Align(
|
(context, selectedItem) => Align(
|
||||||
@ -1203,6 +1451,7 @@ class _OfficeDetailsState extends State<OfficeDetails> {
|
|||||||
// });
|
// });
|
||||||
// },
|
// },
|
||||||
),
|
),
|
||||||
|
),),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -1239,10 +1488,24 @@ class _OfficeDetailsState extends State<OfficeDetails> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldUserWrapper(
|
CustomTextFieldUserWrapper(
|
||||||
isFocused: false,
|
isFocused: _exceptionalApprovalFocus,
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 0),
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
|
width: double.infinity,
|
||||||
|
child: Focus(
|
||||||
|
focusNode: _exceptionalApprovalFocusNode,
|
||||||
|
onFocusChange: (hasFocus) {
|
||||||
|
setState(() {
|
||||||
|
_exceptionalApprovalFocus = hasFocus;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
// Request focus when user taps
|
||||||
|
_exceptionalApprovalFocusNode?.requestFocus();
|
||||||
|
},
|
||||||
child:
|
child:
|
||||||
apiUserData == null
|
apiUserData == null
|
||||||
? Center(
|
? Center(
|
||||||
@ -1289,11 +1552,32 @@ class _OfficeDetailsState extends State<OfficeDetails> {
|
|||||||
}).toList(),
|
}).toList(),
|
||||||
dropdownDecoratorProps: DropDownDecoratorProps(
|
dropdownDecoratorProps: DropDownDecoratorProps(
|
||||||
dropdownSearchDecoration: InputDecoration(
|
dropdownSearchDecoration: InputDecoration(
|
||||||
border: InputBorder.none,
|
border: OutlineInputBorder(
|
||||||
contentPadding: EdgeInsets.symmetric(
|
borderRadius: BorderRadius.circular(8),
|
||||||
horizontal: 1,
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(_exceptionalApprovalFocus ?? false)
|
||||||
|
? (layoutColor ?? Colors.white)
|
||||||
|
: Colors.white,
|
||||||
|
width: 0.5,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(_exceptionalApprovalFocus ?? false)
|
||||||
|
? (layoutColor ?? Colors.white)
|
||||||
|
: Colors.white,
|
||||||
|
width: 0.5,
|
||||||
|
// const Color(0xFFD6D5E6),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color : (layoutColor ?? Colors.white), width: 0.5),
|
||||||
|
),
|
||||||
|
contentPadding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 8.0),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
dropdownBuilder:
|
dropdownBuilder:
|
||||||
(context, selectedItem) => Align(
|
(context, selectedItem) => Align(
|
||||||
@ -1326,6 +1610,7 @@ class _OfficeDetailsState extends State<OfficeDetails> {
|
|||||||
); // ✅ not newValue, but approverId
|
); // ✅ not newValue, but approverId
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
),),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -1363,10 +1648,23 @@ class _OfficeDetailsState extends State<OfficeDetails> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldUserWrapper(
|
CustomTextFieldUserWrapper(
|
||||||
isFocused: false,
|
isFocused: _delegateFocus,
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 0),
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
|
width: double.infinity,
|
||||||
|
child: Focus(
|
||||||
|
focusNode: _delegateFocusNode,
|
||||||
|
onFocusChange: (hasFocus) {
|
||||||
|
setState(() {
|
||||||
|
_delegateFocus = hasFocus;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
_delegateFocusNode?.requestFocus();
|
||||||
|
},
|
||||||
child:
|
child:
|
||||||
apiUserData == null
|
apiUserData == null
|
||||||
? Center(
|
? Center(
|
||||||
@ -1417,11 +1715,32 @@ class _OfficeDetailsState extends State<OfficeDetails> {
|
|||||||
}).toList(),
|
}).toList(),
|
||||||
dropdownDecoratorProps: DropDownDecoratorProps(
|
dropdownDecoratorProps: DropDownDecoratorProps(
|
||||||
dropdownSearchDecoration: InputDecoration(
|
dropdownSearchDecoration: InputDecoration(
|
||||||
border: InputBorder.none,
|
border: OutlineInputBorder(
|
||||||
contentPadding: EdgeInsets.symmetric(
|
borderRadius: BorderRadius.circular(8),
|
||||||
horizontal: 1,
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(_delegateFocus ?? false)
|
||||||
|
? (layoutColor ?? Colors.white)
|
||||||
|
: Colors.white,
|
||||||
|
width: 0.5,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(_delegateFocus ?? false)
|
||||||
|
? (layoutColor ?? Colors.white)
|
||||||
|
: Colors.white,
|
||||||
|
width: 0.5,
|
||||||
|
// const Color(0xFFD6D5E6),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color : (layoutColor ?? Colors.grey), width: 0.5),
|
||||||
|
),
|
||||||
|
contentPadding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 8.0),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
dropdownBuilder:
|
dropdownBuilder:
|
||||||
(context, selectedItem) => Align(
|
(context, selectedItem) => Align(
|
||||||
@ -1467,6 +1786,7 @@ class _OfficeDetailsState extends State<OfficeDetails> {
|
|||||||
); // ✅ not newValue, but approverId
|
); // ✅ not newValue, but approverId
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
),),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -1544,7 +1864,7 @@ class _OfficeDetailsState extends State<OfficeDetails> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldUserWrapper(
|
CustomTextFieldUserWrapper(
|
||||||
isFocused: false,
|
isFocused: _startDateFocus,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
@ -1554,10 +1874,12 @@ class _OfficeDetailsState extends State<OfficeDetails> {
|
|||||||
//
|
//
|
||||||
// },
|
// },
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
|
_startDateFocusNode?.requestFocus();
|
||||||
await _selectCheckOutDate(context);
|
await _selectCheckOutDate(context);
|
||||||
},
|
},
|
||||||
child: AbsorbPointer(
|
child: AbsorbPointer(
|
||||||
child: TextField(
|
child: TextField(
|
||||||
|
focusNode: _startDateFocusNode,
|
||||||
controller: widget.controllers["delegationStartDate"],
|
controller: widget.controllers["delegationStartDate"],
|
||||||
readOnly: true,
|
readOnly: true,
|
||||||
style: const TextStyle(fontSize: 12),
|
style: const TextStyle(fontSize: 12),
|
||||||
@ -1649,7 +1971,7 @@ class _OfficeDetailsState extends State<OfficeDetails> {
|
|||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldUserWrapper(
|
CustomTextFieldUserWrapper(
|
||||||
width: isDesktop ? MediaQuery.of(context).size.width * 0.2 : null,
|
width: isDesktop ? MediaQuery.of(context).size.width * 0.2 : null,
|
||||||
isFocused: false,
|
isFocused: _endDateFocus,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
@ -1659,10 +1981,12 @@ class _OfficeDetailsState extends State<OfficeDetails> {
|
|||||||
//
|
//
|
||||||
// },
|
// },
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
|
_endDateFocusNode?.requestFocus();
|
||||||
await _selectForexEndDate(context);
|
await _selectForexEndDate(context);
|
||||||
},
|
},
|
||||||
child: AbsorbPointer(
|
child: AbsorbPointer(
|
||||||
child: TextField(
|
child: TextField(
|
||||||
|
focusNode: _endDateFocusNode,
|
||||||
controller: widget.controllers["delegationEndDate"],
|
controller: widget.controllers["delegationEndDate"],
|
||||||
readOnly: true,
|
readOnly: true,
|
||||||
style: const TextStyle(fontSize: 12),
|
style: const TextStyle(fontSize: 12),
|
||||||
|
|||||||
@ -75,6 +75,8 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
String? get selectedGenderValue => selectedGender;
|
String? get selectedGenderValue => selectedGender;
|
||||||
String? get selectedCountryValue => selectedCountry;
|
String? get selectedCountryValue => selectedCountry;
|
||||||
String? get selectedRoleValue => selectedRole;
|
String? get selectedRoleValue => selectedRole;
|
||||||
|
Map<String, FocusNode> focusNodes = {};
|
||||||
|
Map<String, bool> focusStates = {};
|
||||||
|
|
||||||
late bool isTravelAgent = false;
|
late bool isTravelAgent = false;
|
||||||
|
|
||||||
@ -135,7 +137,9 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
loadInitialData();
|
||||||
|
});
|
||||||
apiCountryData = null;
|
apiCountryData = null;
|
||||||
|
|
||||||
apiRoleData = null;
|
apiRoleData = null;
|
||||||
@ -150,6 +154,19 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
|
|
||||||
print("selectedServiceIdsAPI - $selectedServiceIds");
|
print("selectedServiceIdsAPI - $selectedServiceIds");
|
||||||
|
|
||||||
|
for (var field in dataHeader) {
|
||||||
|
focusNodes["${field}FocusNode"] = FocusNode();
|
||||||
|
focusStates["${field}Focused"] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var key in focusNodes.keys) {
|
||||||
|
_addFocusListener(focusNodes[key]!, (focus) {
|
||||||
|
setState(() {
|
||||||
|
focusStates[key.replaceFirst("FocusNode", "Focused")] = focus;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
loadAllServices();
|
loadAllServices();
|
||||||
getOrganizationData();
|
getOrganizationData();
|
||||||
@ -157,6 +174,14 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _addFocusListener(FocusNode node, Function(bool) updateState) {
|
||||||
|
node.addListener(() {
|
||||||
|
setState(() {
|
||||||
|
updateState(node.hasFocus);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> apiCheckDuplicate(
|
Future<void> apiCheckDuplicate(
|
||||||
String label,
|
String label,
|
||||||
String field,
|
String field,
|
||||||
@ -777,13 +802,15 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldUserWrapper(
|
CustomTextFieldUserWrapper(
|
||||||
isFocused: false,
|
isFocused: focusStates["FnameFocused"] ?? false,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
||||||
|
focusNode: focusNodes["FnameFocusNode"],
|
||||||
controller: widget.controllers["Fname"],
|
controller: widget.controllers["Fname"],
|
||||||
|
autofocus: true,
|
||||||
enabled: !widget.isViewMode,
|
enabled: !widget.isViewMode,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
_clearError("first_name");
|
_clearError("first_name");
|
||||||
@ -827,12 +854,14 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldUserWrapper(
|
CustomTextFieldUserWrapper(
|
||||||
isFocused: false,
|
isFocused: focusStates["LnameFocused"] ?? false,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
style: TextStyle(fontSize: 12, color: Colors.black),
|
style: TextStyle(fontSize: 12, color: Colors.black),
|
||||||
|
focusNode: focusNodes["LnameFocusNode"],
|
||||||
|
autofocus: true,
|
||||||
controller: widget.controllers["Lname"],
|
controller: widget.controllers["Lname"],
|
||||||
enabled: !widget.isViewMode,
|
enabled: !widget.isViewMode,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
@ -977,10 +1006,22 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
widget.isDesktop
|
widget.isDesktop
|
||||||
? MediaQuery.of(context).size.width * 0.12
|
? MediaQuery.of(context).size.width * 0.12
|
||||||
: null,
|
: null,
|
||||||
isFocused: false,
|
isFocused: focusStates["genderFocused"] ?? false,
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 0),
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
|
child: Focus(
|
||||||
|
focusNode: focusNodes["genderFocusNode"],
|
||||||
|
onFocusChange: (hasFocus) {
|
||||||
|
setState(() {
|
||||||
|
focusStates["genderFocused"] = hasFocus;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
focusNodes["genderFocusNode"]?.requestFocus();
|
||||||
|
},
|
||||||
child: DropdownSearch<String>(
|
child: DropdownSearch<String>(
|
||||||
selectedItem: selectedGender,
|
selectedItem: selectedGender,
|
||||||
enabled: !widget.isViewMode,
|
enabled: !widget.isViewMode,
|
||||||
@ -990,51 +1031,51 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
fit: FlexFit.loose,
|
fit: FlexFit.loose,
|
||||||
constraints: BoxConstraints(maxHeight: 200),
|
constraints: BoxConstraints(maxHeight: 200),
|
||||||
itemBuilder:
|
itemBuilder:
|
||||||
// (context, item, isSelected) => Container(
|
(context, item, isSelected) => Container(
|
||||||
// color: Colors.white,
|
color: Colors.white,
|
||||||
// padding: EdgeInsets.symmetric(
|
padding: EdgeInsets.symmetric(
|
||||||
// horizontal: 10,
|
horizontal: 10,
|
||||||
// vertical: 6,
|
vertical: 6,
|
||||||
// ),
|
|
||||||
// child: Text(
|
|
||||||
// item,
|
|
||||||
// style: GoogleFonts.poppins(fontSize: 11.5),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
(context, item, isSelected) {
|
|
||||||
print("contryItem - $item");
|
|
||||||
final match = RegExp(r'^(.*)\s\((.*)\)$',).firstMatch(item);
|
|
||||||
final countryName = match?.group(1) ?? '';
|
|
||||||
final countryCode = match?.group(2) ?? '';
|
|
||||||
return Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
horizontal: 8.0,
|
|
||||||
vertical: 6.0,
|
|
||||||
),
|
),
|
||||||
child: Padding(
|
child: Text(
|
||||||
padding: const EdgeInsets.all(8.0),
|
item,
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
countryName,
|
|
||||||
style: GoogleFonts.poppins(fontSize: 11.5),
|
style: GoogleFonts.poppins(fontSize: 11.5),
|
||||||
),
|
),
|
||||||
Text(
|
|
||||||
countryCode,
|
|
||||||
style: GoogleFonts.poppins(fontSize: 11.5,color:Colors.grey),
|
|
||||||
|
|
||||||
),
|
),
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);},
|
|
||||||
),
|
),
|
||||||
items: genderOptions,
|
items: genderOptions,
|
||||||
dropdownDecoratorProps: DropDownDecoratorProps(
|
dropdownDecoratorProps: DropDownDecoratorProps(
|
||||||
dropdownSearchDecoration: InputDecoration(
|
dropdownSearchDecoration: InputDecoration(
|
||||||
border: InputBorder.none,
|
// border: InputBorder.none,
|
||||||
contentPadding: EdgeInsets.symmetric(horizontal: 1),
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(5),
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(focusStates["genderFocused"] ?? false)
|
||||||
|
? (layoutColor ?? Colors.blue)
|
||||||
|
: Colors.white,
|
||||||
|
width: 0.5,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(focusStates["genderFocused"] ?? false)
|
||||||
|
? (layoutColor ?? Colors.blue)
|
||||||
|
: Colors.white,
|
||||||
|
// : const Color(0xFFD6D5E6),
|
||||||
|
width: 0.5,
|
||||||
|
// const Color(0xFFD6D5E6),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(color : (layoutColor ?? Colors.grey), width: 0.5),
|
||||||
|
),
|
||||||
|
contentPadding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 10,
|
||||||
|
// vertical: 1,
|
||||||
|
),
|
||||||
|
// contentPadding: EdgeInsets.symmetric(horizontal: 1),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
dropdownBuilder:
|
dropdownBuilder:
|
||||||
@ -1058,7 +1099,7 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
});
|
});
|
||||||
widget.onGenderChanged?.call(newValue);
|
widget.onGenderChanged?.call(newValue);
|
||||||
},
|
},
|
||||||
),
|
),),),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -1111,7 +1152,7 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
widget.isDesktop
|
widget.isDesktop
|
||||||
? MediaQuery.of(context).size.width * 0.12
|
? MediaQuery.of(context).size.width * 0.12
|
||||||
: null,
|
: null,
|
||||||
isFocused: false,
|
isFocused: focusStates["dobFocused"] ?? false,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
@ -1125,11 +1166,16 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
setState(() {
|
setState(() {
|
||||||
// errorMessages.remove("start_date");
|
// errorMessages.remove("start_date");
|
||||||
});
|
});
|
||||||
|
// Delay re-focusing the DOB field slightly
|
||||||
|
Future.delayed(Duration(milliseconds: 100), () {
|
||||||
|
focusNodes["dobFocusNode"]?.requestFocus();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: AbsorbPointer(
|
child: AbsorbPointer(
|
||||||
child: TextField(
|
child: TextField(
|
||||||
controller: widget.controllers["dob"],
|
controller: widget.controllers["dob"],
|
||||||
|
focusNode: focusNodes["dobFocusNode"],
|
||||||
readOnly: true,
|
readOnly: true,
|
||||||
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
@ -1171,12 +1217,14 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldUserWrapper(
|
CustomTextFieldUserWrapper(
|
||||||
isFocused: false,
|
isFocused: focusStates["emailFocused"] ?? false,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
||||||
|
focusNode: focusNodes["emailFocusNode"],
|
||||||
|
autofocus: true,
|
||||||
controller: widget.controllers["email"],
|
controller: widget.controllers["email"],
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
_clearError("email");
|
_clearError("email");
|
||||||
@ -1221,12 +1269,14 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldUserWrapper(
|
CustomTextFieldUserWrapper(
|
||||||
isFocused: false,
|
isFocused: focusStates["mobileNumberFocused"] ?? false,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
||||||
|
focusNode: focusNodes["mobileNumberFocusNode"],
|
||||||
|
autofocus: true,
|
||||||
controller: widget.controllers["mobileNumber"],
|
controller: widget.controllers["mobileNumber"],
|
||||||
enabled: !widget.isViewMode,
|
enabled: !widget.isViewMode,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
@ -1282,12 +1332,14 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldUserWrapper(
|
CustomTextFieldUserWrapper(
|
||||||
isFocused: false,
|
isFocused: focusStates["alternateMobileFocused"] ?? false,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
||||||
|
focusNode: focusNodes["alternateMobileFocusNode"],
|
||||||
|
autofocus: true,
|
||||||
controller: widget.controllers["alternateMobile"],
|
controller: widget.controllers["alternateMobile"],
|
||||||
enabled: !widget.isViewMode,
|
enabled: !widget.isViewMode,
|
||||||
keyboardType: TextInputType.numberWithOptions(decimal: true),
|
keyboardType: TextInputType.numberWithOptions(decimal: true),
|
||||||
@ -1356,10 +1408,24 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldUserWrapper(
|
CustomTextFieldUserWrapper(
|
||||||
isFocused: false,
|
isFocused: focusStates["countryFocused"] ?? false,
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 0),
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
|
width: double.infinity,
|
||||||
|
child: Focus(
|
||||||
|
focusNode: focusNodes["countryFocusNode"],
|
||||||
|
onFocusChange: (hasFocus) {
|
||||||
|
setState(() {
|
||||||
|
focusStates["countryFocused"] = hasFocus;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
// Request focus when user taps
|
||||||
|
focusNodes["countryFocusNode"]?.requestFocus();
|
||||||
|
},
|
||||||
child: DropdownSearch<String>(
|
child: DropdownSearch<String>(
|
||||||
selectedItem: countryMap[selectedCountry],
|
selectedItem: countryMap[selectedCountry],
|
||||||
enabled: !widget.isViewMode,
|
enabled: !widget.isViewMode,
|
||||||
@ -1389,8 +1455,33 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
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(horizontal: 1),
|
// contentPadding: EdgeInsets.symmetric(horizontal: 1),
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(focusStates["countryFocused"] ?? false)
|
||||||
|
? (layoutColor ?? Colors.blue)
|
||||||
|
: Colors.white,
|
||||||
|
width: 0.5,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(focusStates["countryFocused"] ?? false)
|
||||||
|
? (layoutColor ?? Colors.blue)
|
||||||
|
: Colors.white,
|
||||||
|
width: 0.5,
|
||||||
|
// const Color(0xFFD6D5E6),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color : (layoutColor ?? Colors.grey), width: 0.5),
|
||||||
|
),
|
||||||
|
contentPadding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 8.0),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
dropdownBuilder:
|
dropdownBuilder:
|
||||||
@ -1440,7 +1531,7 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
countryCode,
|
countryCode,
|
||||||
); // ✅ send code not name
|
); // ✅ send code not name
|
||||||
},
|
},
|
||||||
),
|
),),)
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -1461,12 +1552,14 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldUserWrapper(
|
CustomTextFieldUserWrapper(
|
||||||
isFocused: false,
|
isFocused: focusStates["postalCodeFocused"] ?? false,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
|
autofocus: true,
|
||||||
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
||||||
|
focusNode: focusNodes["postalCodeFocusNode"],
|
||||||
controller: widget.controllers["postalCode"],
|
controller: widget.controllers["postalCode"],
|
||||||
enabled: !widget.isViewMode,
|
enabled: !widget.isViewMode,
|
||||||
keyboardType: TextInputType.numberWithOptions(decimal: true),
|
keyboardType: TextInputType.numberWithOptions(decimal: true),
|
||||||
@ -1579,10 +1672,24 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldUserWrapper(
|
CustomTextFieldUserWrapper(
|
||||||
isFocused: false,
|
// isFocused: false,
|
||||||
|
isFocused: focusStates["roleIdFocusNode"] ?? false,
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 0),
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
|
child: Focus(
|
||||||
|
focusNode: focusNodes["roleIdFocusNode"],
|
||||||
|
onFocusChange: (hasFocus) {
|
||||||
|
setState(() {
|
||||||
|
focusStates["roleIdFocused"] = hasFocus;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
// Request focus when user taps
|
||||||
|
focusNodes["roleIdFocusNode"]?.requestFocus();
|
||||||
|
},
|
||||||
child: DropdownSearch<String>(
|
child: DropdownSearch<String>(
|
||||||
selectedItem: selectedRole != null ? roleMap[selectedRole] : null,
|
selectedItem: selectedRole != null ? roleMap[selectedRole] : null,
|
||||||
enabled: !widget.isViewMode,
|
enabled: !widget.isViewMode,
|
||||||
@ -1613,8 +1720,36 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
items: roleNames,
|
items: roleNames,
|
||||||
dropdownDecoratorProps: DropDownDecoratorProps(
|
dropdownDecoratorProps: DropDownDecoratorProps(
|
||||||
dropdownSearchDecoration: InputDecoration(
|
dropdownSearchDecoration: InputDecoration(
|
||||||
border: InputBorder.none,
|
// border: InputBorder.none,
|
||||||
contentPadding: EdgeInsets.symmetric(horizontal: 1),
|
// contentPadding: EdgeInsets.symmetric(horizontal: 1),
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(5),
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(focusStates["roleIdFocused"] ?? false)
|
||||||
|
? (layoutColor ?? Colors.blue)
|
||||||
|
: Colors.white,
|
||||||
|
width: 0.5,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(focusStates["roleIdFocused"] ?? false)
|
||||||
|
? (layoutColor ?? Colors.blue)
|
||||||
|
: Colors.white,
|
||||||
|
// : const Color(0xFFD6D5E6),
|
||||||
|
width: 0.5,
|
||||||
|
// const Color(0xFFD6D5E6),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(color : (layoutColor ?? Colors.grey), width: 0.5),
|
||||||
|
),
|
||||||
|
contentPadding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 8,
|
||||||
|
vertical: 1,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
dropdownBuilder:
|
dropdownBuilder:
|
||||||
@ -1647,7 +1782,7 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
widget.onUserTypeChanged?.call(isTravelAgent);
|
widget.onUserTypeChanged?.call(isTravelAgent);
|
||||||
widget.onRoleChanged?.call(selectedKey);
|
widget.onRoleChanged?.call(selectedKey);
|
||||||
},
|
},
|
||||||
),
|
),),),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (widget.errorMessages["role_id"] != null) ...[
|
if (widget.errorMessages["role_id"] != null) ...[
|
||||||
@ -1675,12 +1810,14 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldUserWrapper(
|
CustomTextFieldUserWrapper(
|
||||||
isFocused: false,
|
isFocused: focusStates["addressFocused"] ?? false,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 80,
|
height: 80,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
|
autofocus: true,
|
||||||
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
||||||
|
focusNode: focusNodes["addressFocusNode"],
|
||||||
controller: widget.controllers["address"],
|
controller: widget.controllers["address"],
|
||||||
enabled: !widget.isViewMode,
|
enabled: !widget.isViewMode,
|
||||||
maxLines: 2,
|
maxLines: 2,
|
||||||
@ -1717,12 +1854,14 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldUserWrapper(
|
CustomTextFieldUserWrapper(
|
||||||
isFocused: false,
|
isFocused: focusStates["passwordFocused"] ?? false,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
||||||
|
focusNode: focusNodes["passwordFocusNode"],
|
||||||
|
autofocus: true,
|
||||||
controller: widget.controllers["password"],
|
controller: widget.controllers["password"],
|
||||||
enabled: !widget.isViewMode,
|
enabled: !widget.isViewMode,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
|
|||||||
@ -91,6 +91,14 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
late List<dynamic>? apiAirlineCountryData;
|
late List<dynamic>? apiAirlineCountryData;
|
||||||
Map<String, dynamic>? apiData;
|
Map<String, dynamic>? apiData;
|
||||||
final Map<String, TextEditingController> controllers = {};
|
final Map<String, TextEditingController> controllers = {};
|
||||||
|
Map<String, FocusNode> focusNodes = {};
|
||||||
|
Map<String, bool> focusStates = {};
|
||||||
|
|
||||||
|
bool _iSeatPrefFocus = false;
|
||||||
|
bool _dSeatPrefFocus = false;
|
||||||
|
|
||||||
|
final FocusNode _iSeatPrefFocusNode = FocusNode();
|
||||||
|
final FocusNode _dSeatPrefFocusNode = FocusNode();
|
||||||
|
|
||||||
final List<String> headers = [
|
final List<String> headers = [
|
||||||
"Passport Details",
|
"Passport Details",
|
||||||
@ -126,6 +134,11 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
"forex_expiry_date",
|
"forex_expiry_date",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// Color? layoutColor;
|
||||||
|
Color layoutColor = Colors.grey;
|
||||||
|
Color? bodyColor;
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
@ -138,7 +151,18 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
apiData = null;
|
apiData = null;
|
||||||
for (var field in dataHeader) {
|
for (var field in dataHeader) {
|
||||||
controllers[field] = TextEditingController();
|
controllers[field] = TextEditingController();
|
||||||
|
focusNodes["${field}FocusNode"] = FocusNode();
|
||||||
|
focusStates["${field}Focused"] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (var key in focusNodes.keys) {
|
||||||
|
_addFocusListener(focusNodes[key]!, (focus) {
|
||||||
|
setState(() {
|
||||||
|
focusStates[key.replaceFirst("FocusNode", "Focused")] = focus;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
fetchCountries();
|
fetchCountries();
|
||||||
fetchHotels();
|
fetchHotels();
|
||||||
loadCountryList();
|
loadCountryList();
|
||||||
@ -149,9 +173,46 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
addHotelLoyaltyEntry();
|
addHotelLoyaltyEntry();
|
||||||
addFrequentFlierEntry();
|
addFrequentFlierEntry();
|
||||||
addVisaEntry();
|
addVisaEntry();
|
||||||
|
loadInitialData();
|
||||||
});
|
});
|
||||||
updateTravel();
|
updateTravel();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
_addFocusListener(_iSeatPrefFocusNode, (focus) => _iSeatPrefFocus = focus);
|
||||||
|
_addFocusListener(_dSeatPrefFocusNode, (focus) => _dSeatPrefFocus = focus);
|
||||||
|
// _addFocusListener(_groupFocusNode, (focus) => _groupFocus = focus);
|
||||||
|
// _addFocusListener(_firstApprovalFocusNode, (focus) => _firstApprovalFocus = focus);
|
||||||
|
// _addFocusListener(_secondApprovalFocusNode, (focus) => _secondApprovalFocus = focus);
|
||||||
|
// _addFocusListener(_thirdApprovalFocusNode, (focus) => _thirdApprovalFocus = focus);
|
||||||
|
// _addFocusListener(_exceptionalApprovalFocusNode, (focus) => _exceptionalApprovalFocus = focus);
|
||||||
|
// _addFocusListener(_delegateFocusNode, (focus) => _delegateFocus = focus);
|
||||||
|
// _addFocusListener(_startDateFocusNode, (focus) => _startDateFocus = focus);
|
||||||
|
// _addFocusListener(_endDateFocusNode, (focus) => _endDateFocus = focus);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _addFocusListener(FocusNode node, Function(bool) updateState) {
|
||||||
|
node.addListener(() {
|
||||||
|
setState(() {
|
||||||
|
updateState(node.hasFocus);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void loadInitialData() async {
|
||||||
|
String? layoutString = await getLayoutColor();
|
||||||
|
String? bodyStringColor = await getBodyColor();
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
layoutColor =
|
||||||
|
layoutString != null
|
||||||
|
? Color(int.parse(layoutString))
|
||||||
|
: Colors.redAccent;
|
||||||
|
|
||||||
|
bodyColor =
|
||||||
|
bodyStringColor != null
|
||||||
|
? Color(int.parse(bodyStringColor))
|
||||||
|
: Colors.white;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool boolValidation() {
|
bool boolValidation() {
|
||||||
@ -1145,12 +1206,14 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldUserTravellerWrapper(
|
CustomTextFieldUserTravellerWrapper(
|
||||||
isFocused: false,
|
// isFocused: false,
|
||||||
|
isFocused: focusStates["FnameFocused"] ?? false,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
||||||
|
focusNode: focusNodes["FnameFocusNode"],
|
||||||
controller: controllers["Fname"],
|
controller: controllers["Fname"],
|
||||||
enabled: !widget.isViewMode,
|
enabled: !widget.isViewMode,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
@ -1187,12 +1250,13 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldUserTravellerWrapper(
|
CustomTextFieldUserTravellerWrapper(
|
||||||
isFocused: false,
|
isFocused: focusStates["MnameFocused"] ?? false,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
||||||
|
focusNode: focusNodes["MnameFocusNode"],
|
||||||
controller: controllers["Mname"],
|
controller: controllers["Mname"],
|
||||||
enabled: !widget.isViewMode,
|
enabled: !widget.isViewMode,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
@ -1229,7 +1293,7 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldUserTravellerWrapper(
|
CustomTextFieldUserTravellerWrapper(
|
||||||
isFocused: false,
|
isFocused: focusStates["LnameFocused"] ?? false,
|
||||||
width:
|
width:
|
||||||
widget.isDesktop
|
widget.isDesktop
|
||||||
? MediaQuery.of(context).size.width * 0.13
|
? MediaQuery.of(context).size.width * 0.13
|
||||||
@ -1239,6 +1303,7 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
||||||
|
focusNode: focusNodes["LnameFocusNode"],
|
||||||
controller: controllers["Lname"],
|
controller: controllers["Lname"],
|
||||||
enabled: !widget.isViewMode,
|
enabled: !widget.isViewMode,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
@ -1280,7 +1345,9 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldUserTravellerWrapper(
|
CustomTextFieldUserTravellerWrapper(
|
||||||
isFocused: false,
|
// isFocused: false,
|
||||||
|
isFocused: focusStates["nationality"] ?? false,
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 0),
|
||||||
width:
|
width:
|
||||||
widget.isDesktop
|
widget.isDesktop
|
||||||
? MediaQuery.of(context).size.width * 0.13
|
? MediaQuery.of(context).size.width * 0.13
|
||||||
@ -1288,6 +1355,18 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
|
child: Focus(
|
||||||
|
focusNode: focusNodes["nationalityFocusNode"],
|
||||||
|
onFocusChange: (hasFocus) {
|
||||||
|
setState(() {
|
||||||
|
focusStates["nationalityFocused"] = hasFocus;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
// Request focus when user taps
|
||||||
|
focusNodes["nationalityFocusNode"]?.requestFocus();
|
||||||
|
},
|
||||||
child: DropdownSearch<String>(
|
child: DropdownSearch<String>(
|
||||||
selectedItem: _selectedTripType,
|
selectedItem: _selectedTripType,
|
||||||
enabled: !widget.isViewMode,
|
enabled: !widget.isViewMode,
|
||||||
@ -1312,8 +1391,36 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
items: nationalityOptions,
|
items: nationalityOptions,
|
||||||
dropdownDecoratorProps: DropDownDecoratorProps(
|
dropdownDecoratorProps: DropDownDecoratorProps(
|
||||||
dropdownSearchDecoration: InputDecoration(
|
dropdownSearchDecoration: InputDecoration(
|
||||||
border: InputBorder.none,
|
// border: InputBorder.none,
|
||||||
contentPadding: EdgeInsets.symmetric(horizontal: 1),
|
// contentPadding: EdgeInsets.symmetric(horizontal: 1),
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(1),
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(focusStates["nationalityFocused"] ?? false)
|
||||||
|
? (layoutColor)
|
||||||
|
: Colors.white,
|
||||||
|
width: 1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(focusStates["nationalityFocused"] ?? false)
|
||||||
|
? (layoutColor)
|
||||||
|
: Colors.white,
|
||||||
|
// : const Color(0xFFD6D5E6),
|
||||||
|
width: 1,
|
||||||
|
// const Color(0xFFD6D5E6),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(color : (layoutColor), width: 0.5),
|
||||||
|
),
|
||||||
|
contentPadding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 8,
|
||||||
|
vertical: 1,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
dropdownBuilder:
|
dropdownBuilder:
|
||||||
@ -1337,7 +1444,7 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
print("_selectedTripType - $_selectedTripType");
|
print("_selectedTripType - $_selectedTripType");
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
),
|
),),),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -1358,12 +1465,13 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldUserTravellerWrapper(
|
CustomTextFieldUserTravellerWrapper(
|
||||||
isFocused: false,
|
isFocused: focusStates["passportNumberFocused"] ?? false,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
||||||
|
focusNode: focusNodes["passportNumberFocusNode"],
|
||||||
controller: controllers["passportNumber"],
|
controller: controllers["passportNumber"],
|
||||||
enabled: !widget.isViewMode,
|
enabled: !widget.isViewMode,
|
||||||
inputFormatters: [
|
inputFormatters: [
|
||||||
@ -1421,12 +1529,13 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldUserTravellerWrapper(
|
CustomTextFieldUserTravellerWrapper(
|
||||||
isFocused: false,
|
isFocused: focusStates["placeOfIssueFocused"] ?? false,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
||||||
|
focusNode: focusNodes["placeOfIssueFocusNode"],
|
||||||
controller: controllers["placeOfIssue"],
|
controller: controllers["placeOfIssue"],
|
||||||
enabled: !widget.isViewMode,
|
enabled: !widget.isViewMode,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
@ -1504,7 +1613,8 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
widget.isDesktop
|
widget.isDesktop
|
||||||
? MediaQuery.of(context).size.width * 0.13
|
? MediaQuery.of(context).size.width * 0.13
|
||||||
: null,
|
: null,
|
||||||
isFocused: false,
|
isFocused: focusStates["dateOfIssueFocused"] ?? false,
|
||||||
|
// isFocused: false,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
@ -1519,10 +1629,12 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
// errorMessages.remove("start_date");
|
// errorMessages.remove("start_date");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
focusNodes["dateOfIssueFocusNode"]?.requestFocus();
|
||||||
},
|
},
|
||||||
child: AbsorbPointer(
|
child: AbsorbPointer(
|
||||||
child: TextField(
|
child: TextField(
|
||||||
controller: controllers["dateOfIssue"],
|
controller: controllers["dateOfIssue"],
|
||||||
|
focusNode: focusNodes["dateOfIssueFocusNode"],
|
||||||
readOnly: true,
|
readOnly: true,
|
||||||
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
@ -1638,7 +1750,8 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldUserTravellerWrapper(
|
CustomTextFieldUserTravellerWrapper(
|
||||||
isFocused: false,
|
// isFocused: false,
|
||||||
|
isFocused: focusStates["dateOfExpiryFocused"] ?? false,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
width:
|
width:
|
||||||
widget.isDesktop
|
widget.isDesktop
|
||||||
@ -1657,10 +1770,12 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
// errorMessages.remove("start_date");
|
// errorMessages.remove("start_date");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
focusNodes["dateOfExpiryFocusNode"]?.requestFocus();
|
||||||
},
|
},
|
||||||
child: AbsorbPointer(
|
child: AbsorbPointer(
|
||||||
child: TextField(
|
child: TextField(
|
||||||
controller: controllers["dateOfExpiry"],
|
controller: controllers["dateOfExpiry"],
|
||||||
|
focusNode: focusNodes["dateOfExpiryFocusNode"],
|
||||||
readOnly: true,
|
readOnly: true,
|
||||||
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
@ -2388,11 +2503,24 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
widget.isDesktop
|
widget.isDesktop
|
||||||
? MediaQuery.of(context).size.width * 0.15
|
? MediaQuery.of(context).size.width * 0.15
|
||||||
: null,
|
: null,
|
||||||
isFocused: false,
|
isFocused: _dSeatPrefFocus,
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 0),
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 35,
|
height: 35,
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
|
child: Focus(
|
||||||
|
focusNode: _dSeatPrefFocusNode,
|
||||||
|
onFocusChange: (hasFocus) {
|
||||||
|
setState(() {
|
||||||
|
_dSeatPrefFocus = hasFocus;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
// Request focus when user taps
|
||||||
|
_dSeatPrefFocusNode.requestFocus();
|
||||||
|
},
|
||||||
child: DropdownSearch<Map<String, dynamic>>(
|
child: DropdownSearch<Map<String, dynamic>>(
|
||||||
popupProps: PopupProps.menu(
|
popupProps: PopupProps.menu(
|
||||||
showSearchBox: false,
|
showSearchBox: false,
|
||||||
@ -2416,7 +2544,31 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
),
|
),
|
||||||
dropdownDecoratorProps: DropDownDecoratorProps(
|
dropdownDecoratorProps: DropDownDecoratorProps(
|
||||||
dropdownSearchDecoration: InputDecoration(
|
dropdownSearchDecoration: InputDecoration(
|
||||||
border: InputBorder.none,
|
// border: InputBorder.none,
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(_dSeatPrefFocus)
|
||||||
|
? (layoutColor)
|
||||||
|
: Colors.white,
|
||||||
|
width: 0.5,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(_dSeatPrefFocus)
|
||||||
|
? (layoutColor)
|
||||||
|
: Colors.white,
|
||||||
|
width: 0.5,
|
||||||
|
// const Color(0xFFD6D5E6),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color : (layoutColor), width: 0.5),
|
||||||
|
),
|
||||||
hintText: "Select Seat",
|
hintText: "Select Seat",
|
||||||
hintStyle: GoogleFonts.poppins(
|
hintStyle: GoogleFonts.poppins(
|
||||||
fontSize: 11.5,
|
fontSize: 11.5,
|
||||||
@ -2463,7 +2615,7 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),),),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -2488,12 +2640,13 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
widget.isDesktop
|
widget.isDesktop
|
||||||
? MediaQuery.of(context).size.width * 0.15
|
? MediaQuery.of(context).size.width * 0.15
|
||||||
: null,
|
: null,
|
||||||
isFocused: false,
|
isFocused: focusStates["d_meal_prefFocused"] ?? false,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
||||||
|
focusNode: focusNodes["d_meal_prefFocusNode"],
|
||||||
controller: controllers["d_meal_pref"],
|
controller: controllers["d_meal_pref"],
|
||||||
enabled: !widget.isViewMode,
|
enabled: !widget.isViewMode,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
@ -2532,13 +2685,14 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
CustomTextFieldUserTravellerWrapper(
|
CustomTextFieldUserTravellerWrapper(
|
||||||
width:
|
width:
|
||||||
widget.isDesktop ? MediaQuery.of(context).size.width * 0.4 : null,
|
widget.isDesktop ? MediaQuery.of(context).size.width * 0.4 : null,
|
||||||
isFocused: false,
|
isFocused: focusStates["d_additonal_InfoFocused"] ?? false,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
||||||
controller: controllers["d_additonal_Info"],
|
controller: controllers["d_additonal_Info"],
|
||||||
|
focusNode: focusNodes["d_additonal_InfoFocusNode"],
|
||||||
enabled: !widget.isViewMode,
|
enabled: !widget.isViewMode,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
_clearError("d_additonal_Info");
|
_clearError("d_additonal_Info");
|
||||||
@ -2625,11 +2779,23 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
widget.isDesktop
|
widget.isDesktop
|
||||||
? MediaQuery.of(context).size.width * 0.15
|
? MediaQuery.of(context).size.width * 0.15
|
||||||
: null,
|
: null,
|
||||||
isFocused: false,
|
isFocused: _iSeatPrefFocus,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 35,
|
height: 35,
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
|
child: Focus(
|
||||||
|
focusNode: _iSeatPrefFocusNode,
|
||||||
|
onFocusChange: (hasFocus) {
|
||||||
|
setState(() {
|
||||||
|
_iSeatPrefFocus = hasFocus;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
// Request focus when user taps
|
||||||
|
_iSeatPrefFocusNode.requestFocus();
|
||||||
|
},
|
||||||
child: DropdownSearch<Map<String, dynamic>>(
|
child: DropdownSearch<Map<String, dynamic>>(
|
||||||
popupProps: PopupProps.menu(
|
popupProps: PopupProps.menu(
|
||||||
showSearchBox: false,
|
showSearchBox: false,
|
||||||
@ -2651,12 +2817,36 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
dropdownDecoratorProps: const DropDownDecoratorProps(
|
dropdownDecoratorProps: DropDownDecoratorProps(
|
||||||
dropdownSearchDecoration: InputDecoration(
|
dropdownSearchDecoration: InputDecoration(
|
||||||
border: InputBorder.none,
|
// border: InputBorder.none,
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(_iSeatPrefFocus)
|
||||||
|
? (layoutColor)
|
||||||
|
: Colors.white,
|
||||||
|
width: 0.5,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(_iSeatPrefFocus)
|
||||||
|
? (layoutColor)
|
||||||
|
: Colors.white,
|
||||||
|
width: 0.5,
|
||||||
|
// const Color(0xFFD6D5E6),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color : (layoutColor), width: 0.5),
|
||||||
|
),
|
||||||
contentPadding: EdgeInsets.symmetric(
|
contentPadding: EdgeInsets.symmetric(
|
||||||
horizontal: 10,
|
horizontal: 10,
|
||||||
vertical: 5,
|
vertical: 1,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -2701,7 +2891,7 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),),),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -2726,13 +2916,14 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
widget.isDesktop
|
widget.isDesktop
|
||||||
? MediaQuery.of(context).size.width * 0.15
|
? MediaQuery.of(context).size.width * 0.15
|
||||||
: null,
|
: null,
|
||||||
isFocused: false,
|
isFocused: focusStates["i_meal_prefFocused"] ?? false,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
||||||
controller: controllers["i_meal_pref"],
|
controller: controllers["i_meal_pref"],
|
||||||
|
focusNode: focusNodes["i_meal_prefFocusNode"],
|
||||||
enabled: !widget.isViewMode,
|
enabled: !widget.isViewMode,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
_clearError("i_meal_pref");
|
_clearError("i_meal_pref");
|
||||||
@ -2770,13 +2961,14 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
CustomTextFieldUserTravellerWrapper(
|
CustomTextFieldUserTravellerWrapper(
|
||||||
width:
|
width:
|
||||||
widget.isDesktop ? MediaQuery.of(context).size.width * 0.4 : null,
|
widget.isDesktop ? MediaQuery.of(context).size.width * 0.4 : null,
|
||||||
isFocused: false,
|
isFocused: focusStates["i_additonal_InfoFocused"] ?? false,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
||||||
controller: controllers["i_additonal_Info"],
|
controller: controllers["i_additonal_Info"],
|
||||||
|
focusNode: focusNodes["i_additonal_InfoFocusNode"],
|
||||||
enabled: !widget.isViewMode,
|
enabled: !widget.isViewMode,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
_clearError("i_additonal_Info");
|
_clearError("i_additonal_Info");
|
||||||
@ -2821,13 +3013,15 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldUserTravellerWrapper(
|
CustomTextFieldUserTravellerWrapper(
|
||||||
isFocused: false,
|
// isFocused: false,
|
||||||
|
isFocused: focusStates["emergency_contactFocused"] ?? false,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
||||||
controller: controllers["emergency_contact"],
|
controller: controllers["emergency_contact"],
|
||||||
|
focusNode: focusNodes["emergency_contactFocusNode"],
|
||||||
inputFormatters: [
|
inputFormatters: [
|
||||||
FilteringTextInputFormatter.allow(RegExp(r'[0-9\s]')),
|
FilteringTextInputFormatter.allow(RegExp(r'[0-9\s]')),
|
||||||
],
|
],
|
||||||
@ -2900,13 +3094,14 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldUserTravellerWrapper(
|
CustomTextFieldUserTravellerWrapper(
|
||||||
isFocused: false,
|
isFocused: focusStates["forex_card_numFocused"] ?? false,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
||||||
controller: controllers["forex_card_num"],
|
controller: controllers["forex_card_num"],
|
||||||
|
focusNode: focusNodes["forex_card_numFocusNode"],
|
||||||
inputFormatters: [
|
inputFormatters: [
|
||||||
FilteringTextInputFormatter.allow(RegExp(r'[0-9\s]')),
|
FilteringTextInputFormatter.allow(RegExp(r'[0-9\s]')),
|
||||||
LengthLimitingTextInputFormatter(16),
|
LengthLimitingTextInputFormatter(16),
|
||||||
@ -2988,7 +3183,7 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldUserTravellerWrapper(
|
CustomTextFieldUserTravellerWrapper(
|
||||||
isFocused: false,
|
isFocused: focusStates["forex_expiry_dateFocused"] ?? false,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
@ -2997,11 +3192,13 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
widget.isViewMode
|
widget.isViewMode
|
||||||
? null
|
? null
|
||||||
: () async {
|
: () async {
|
||||||
|
focusNodes["forex_expiry_dateFocusNode"]?.requestFocus();
|
||||||
await _selectExpiryDate(context);
|
await _selectExpiryDate(context);
|
||||||
},
|
},
|
||||||
child: AbsorbPointer(
|
child: AbsorbPointer(
|
||||||
child: TextField(
|
child: TextField(
|
||||||
controller: controllers["forex_expiry_date"],
|
controller: controllers["forex_expiry_date"],
|
||||||
|
focusNode: focusNodes["forex_expiry_dateFocusNode"],
|
||||||
readOnly: true,
|
readOnly: true,
|
||||||
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
|
|||||||
@ -144,6 +144,7 @@ class _UserListScreenState extends State<UserListScreen> {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
Future<List<dynamic>> fetchUsers() async {
|
Future<List<dynamic>> fetchUsers() async {
|
||||||
|
// return [];
|
||||||
orgId = await getOrgId();
|
orgId = await getOrgId();
|
||||||
final String apiUrlData = '$apiUrl/api/users?org_id=$orgId&for=table_view';
|
final String apiUrlData = '$apiUrl/api/users?org_id=$orgId&for=table_view';
|
||||||
final String? token = await getToken();
|
final String? token = await getToken();
|
||||||
@ -767,7 +768,8 @@ class _UserListScreenState extends State<UserListScreen> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ResponsiveBuilder(
|
return
|
||||||
|
ResponsiveBuilder(
|
||||||
builder: (context, sizingInfo) {
|
builder: (context, sizingInfo) {
|
||||||
bool isDesktop =
|
bool isDesktop =
|
||||||
sizingInfo.deviceScreenType == DeviceScreenType.desktop;
|
sizingInfo.deviceScreenType == DeviceScreenType.desktop;
|
||||||
@ -795,6 +797,7 @@ class _UserListScreenState extends State<UserListScreen> {
|
|||||||
// if (isDesktop) CustomDrawer(isDesktop: true),
|
// if (isDesktop) CustomDrawer(isDesktop: true),
|
||||||
// const Expanded(child: Center(child: Text("User Page Content"))),
|
// const Expanded(child: Center(child: Text("User Page Content"))),
|
||||||
Expanded(child: buildGroupList(isDesktop)),
|
Expanded(child: buildGroupList(isDesktop)),
|
||||||
|
// child: buildGroupList(isDesktop),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -872,7 +875,7 @@ class _UserListScreenState extends State<UserListScreen> {
|
|||||||
controller: searchController,
|
controller: searchController,
|
||||||
onChanged: filterUsers,
|
onChanged: filterUsers,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: "Search for a User",
|
hintText: "Search ...",
|
||||||
hintStyle: TextStyle(
|
hintStyle: TextStyle(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
color: Color(0xFF9E9DBD),
|
color: Color(0xFF9E9DBD),
|
||||||
@ -896,6 +899,7 @@ class _UserListScreenState extends State<UserListScreen> {
|
|||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
color: Colors.grey.shade300,
|
color: Colors.grey.shade300,
|
||||||
|
// color: layoutColor!,
|
||||||
width: 1,
|
width: 1,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -1085,6 +1089,7 @@ class _UserListScreenState extends State<UserListScreen> {
|
|||||||
FutureBuilder<List<dynamic>>(
|
FutureBuilder<List<dynamic>>(
|
||||||
future: futureUsers,
|
future: futureUsers,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
|
final adjHgt = MediaQuery.of(context).size.height;
|
||||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||||
return const Center(child: CircularProgressIndicator());
|
return const Center(child: CircularProgressIndicator());
|
||||||
} else if (snapshot.hasError ||
|
} else if (snapshot.hasError ||
|
||||||
@ -1106,9 +1111,10 @@ class _UserListScreenState extends State<UserListScreen> {
|
|||||||
// fontWeight: FontWeight.bold,
|
// fontWeight: FontWeight.bold,
|
||||||
// color: Colors.redAccent),
|
// color: Colors.redAccent),
|
||||||
// ),
|
// ),
|
||||||
const SizedBox(height: 8),
|
// const SizedBox(height: 8),
|
||||||
|
SizedBox(height: adjHgt / 4),
|
||||||
Text(
|
Text(
|
||||||
"No User Found",
|
"No Data Found",
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
@ -1117,15 +1123,15 @@ class _UserListScreenState extends State<UserListScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
Text(
|
// Text(
|
||||||
"Please Create User",
|
// "Please Create User",
|
||||||
textAlign: TextAlign.center,
|
// textAlign: TextAlign.center,
|
||||||
style: GoogleFonts.poppins(
|
// style: GoogleFonts.poppins(
|
||||||
fontSize: 16,
|
// fontSize: 16,
|
||||||
color: Colors.grey,
|
// color: Colors.grey,
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
const SizedBox(height: 20),
|
// const SizedBox(height: 20),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -1732,7 +1738,7 @@ class _UserListScreenState extends State<UserListScreen> {
|
|||||||
filteredUsers.isEmpty
|
filteredUsers.isEmpty
|
||||||
? Center(
|
? Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
"No users found",
|
"No Matches Found",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: Colors.grey,
|
color: Colors.grey,
|
||||||
@ -1747,7 +1753,7 @@ class _UserListScreenState extends State<UserListScreen> {
|
|||||||
filteredUsers.isEmpty
|
filteredUsers.isEmpty
|
||||||
? Center(
|
? Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
"No users found",
|
"No Matches Found",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: Colors.grey,
|
color: Colors.grey,
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import 'dart:convert';
|
|||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
// import 'package:flutter/rendering.dart';
|
import 'package:flutter/rendering.dart';
|
||||||
import 'dart:html' as html;
|
import 'dart:html' as html;
|
||||||
import 'package:frontend/config/apiUrl.dart'; // 1 newly added
|
import 'package:frontend/config/apiUrl.dart'; // 1 newly added
|
||||||
import 'package:frontend/services/apiService.dart';
|
import 'package:frontend/services/apiService.dart';
|
||||||
@ -31,7 +31,7 @@ class _MyAppState extends State<MyApp> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
// SemanticsBinding.instance.ensureSemantics(); // ✅ Safe here
|
SemanticsBinding.instance.ensureSemantics(); // ✅ Safe here - for testing uncomment this
|
||||||
if (kIsWeb) {
|
if (kIsWeb) {
|
||||||
final uri = Uri.parse(html.window.location.href);
|
final uri = Uri.parse(html.window.location.href);
|
||||||
print("URI - $uri");
|
print("URI - $uri");
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
//api url
|
//api url
|
||||||
const String apiUrl = 'http://apitest.tripapprovaltool.com/tstat_be';
|
// const String apiUrl = 'http://localhost/tstat_be';
|
||||||
// const String apiUrl = 'https://uat.tripapprovaltool.com/tstat_be';
|
// const String apiUrl = 'https://uat.tripapprovaltool.com/tstat_be';
|
||||||
|
const String apiUrl = 'http://apitest.tripapprovaltool.com/tstat_be'; // look at this
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import '../utils/auth_utils.dart';
|
||||||
|
|
||||||
class CustomTextFieldUserWrapper extends StatefulWidget {
|
class CustomTextFieldUserWrapper extends StatefulWidget {
|
||||||
final Widget child;
|
final Widget child;
|
||||||
@ -27,6 +28,28 @@ class CustomTextFieldUserWrapper extends StatefulWidget {
|
|||||||
|
|
||||||
class _CustomTextFieldUserWrapperState
|
class _CustomTextFieldUserWrapperState
|
||||||
extends State<CustomTextFieldUserWrapper> {
|
extends State<CustomTextFieldUserWrapper> {
|
||||||
|
Color? layoutColor;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
loadInitialData();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void loadInitialData() async {
|
||||||
|
String? layoutString = await getLayoutColor();
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
layoutColor =
|
||||||
|
layoutString != null
|
||||||
|
? Color(int.parse(layoutString))
|
||||||
|
: Colors.redAccent;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return Container(
|
||||||
@ -41,9 +64,9 @@ class _CustomTextFieldUserWrapperState
|
|||||||
// color: Color(0xFFF7F7FB),
|
// color: Color(0xFFF7F7FB),
|
||||||
borderRadius: BorderRadius.circular(10),
|
borderRadius: BorderRadius.circular(10),
|
||||||
border: Border.all(
|
border: Border.all(
|
||||||
color: widget.isFocused ? Color(0xFF78B4FC) : Color(0xFFD6D5E6),
|
color: widget.isFocused ? layoutColor! : Color(0xFFD6D5E6),
|
||||||
// color: widget.isFocused ? Color(0xFF78B4FC) : Color(0xFFD6D5E6),
|
// color: widget.isFocused ? Color(0xFF78B4FC) : Color(0xFFD6D5E6),
|
||||||
width: widget.isFocused ? 2.0 : 0.5,
|
width: widget.isFocused ? 1.0 : 0.5,
|
||||||
),
|
),
|
||||||
// boxShadow:
|
// boxShadow:
|
||||||
// widget.isFocused
|
// widget.isFocused
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import '../utils/auth_utils.dart';
|
||||||
|
|
||||||
class CustomTextFieldUserTravellerWrapper extends StatefulWidget {
|
class CustomTextFieldUserTravellerWrapper extends StatefulWidget {
|
||||||
final Widget child;
|
final Widget child;
|
||||||
@ -27,6 +28,27 @@ class CustomTextFieldUserTravellerWrapper extends StatefulWidget {
|
|||||||
|
|
||||||
class _CustomTextFieldUserTravellerWrapperState
|
class _CustomTextFieldUserTravellerWrapperState
|
||||||
extends State<CustomTextFieldUserTravellerWrapper> {
|
extends State<CustomTextFieldUserTravellerWrapper> {
|
||||||
|
Color? layoutColor;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
loadInitialData();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void loadInitialData() async {
|
||||||
|
String? layoutString = await getLayoutColor();
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
layoutColor =
|
||||||
|
layoutString != null
|
||||||
|
? Color(int.parse(layoutString))
|
||||||
|
: Colors.redAccent;
|
||||||
|
});
|
||||||
|
}
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return Container(
|
||||||
@ -40,20 +62,21 @@ class _CustomTextFieldUserTravellerWrapperState
|
|||||||
// color: Color(0xFFF7F7FB),
|
// color: Color(0xFFF7F7FB),
|
||||||
borderRadius: BorderRadius.circular(10),
|
borderRadius: BorderRadius.circular(10),
|
||||||
border: Border.all(
|
border: Border.all(
|
||||||
color: widget.isFocused ? Color(0xFF78B4FC) : Color(0xFFD6D5E6),
|
color: widget.isFocused ? layoutColor! : Color(0xFFD6D5E6),
|
||||||
// color: widget.isFocused ? Color(0xFF78B4FC) : Color(0xFFD6D5E6),
|
// color: widget.isFocused ? Color(0xFF78B4FC) : Color(0xFFD6D5E6),
|
||||||
width: widget.isFocused ? 2.0 : 0.5,
|
// color: widget.isFocused ? Color(0xFF78B4FC) : Color(0xFFD6D5E6),
|
||||||
|
width: widget.isFocused ? 1.0 : 0.5,
|
||||||
),
|
),
|
||||||
boxShadow: widget.isFocused
|
// boxShadow: widget.isFocused
|
||||||
? [
|
// ? [
|
||||||
BoxShadow(
|
// BoxShadow(
|
||||||
color: Color.fromRGBO(120, 180, 252, 0.3),
|
// color: Color.fromRGBO(120, 180, 252, 0.3),
|
||||||
blurRadius: 10,
|
// blurRadius: 10,
|
||||||
spreadRadius: 2,
|
// spreadRadius: 2,
|
||||||
offset: Offset(0, 4),
|
// offset: Offset(0, 4),
|
||||||
),
|
// ),
|
||||||
]
|
// ]
|
||||||
: [],
|
// : [],
|
||||||
),
|
),
|
||||||
child: widget.child,
|
child: widget.child,
|
||||||
);
|
);
|
||||||
|
|||||||
@ -110,6 +110,13 @@ flutter:
|
|||||||
- assets/images/IconsImg/upload.png
|
- assets/images/IconsImg/upload.png
|
||||||
- assets/images/IconsImg/download.png
|
- assets/images/IconsImg/download.png
|
||||||
- assets/images/IconsImg/planPdf_icon.png
|
- assets/images/IconsImg/planPdf_icon.png
|
||||||
|
- assets/images/IconsImg/Domestic.png
|
||||||
|
- assets/images/IconsImg/Domestic_old.png
|
||||||
|
- assets/images/IconsImg/Domestic_new.png
|
||||||
|
- assets/images/IconsImg/International.png
|
||||||
|
- assets/images/IconsImg/International_old.png
|
||||||
|
- assets/images/IconsImg/International_new.png
|
||||||
|
|
||||||
|
|
||||||
flutter_icons:
|
flutter_icons:
|
||||||
android: true
|
android: true
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user