merge
This commit is contained in:
parent
cf15771518
commit
335fbacede
@ -287,7 +287,9 @@ class _ApprovalListState extends State<ApprovalList> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void viewPlanforApprover(
|
void viewPlanforApprover(
|
||||||
String planId, {
|
String planId,
|
||||||
|
String? approverId,
|
||||||
|
String? delegaterId, {
|
||||||
bool isViewMode = false,
|
bool isViewMode = false,
|
||||||
bool isApprover = true,
|
bool isApprover = true,
|
||||||
}) async {
|
}) async {
|
||||||
@ -295,14 +297,26 @@ class _ApprovalListState extends State<ApprovalList> {
|
|||||||
Map<String, dynamic> planData = await getViewPlan(planId);
|
Map<String, dynamic> planData = await getViewPlan(planId);
|
||||||
|
|
||||||
print("ViewAAA - $planData");
|
print("ViewAAA - $planData");
|
||||||
context.go(
|
|
||||||
'/createPlan',
|
context.replace(
|
||||||
|
'/approver/plans',
|
||||||
extra: {
|
extra: {
|
||||||
'planData': planData,
|
'planData': planData,
|
||||||
|
'approverId': approverId,
|
||||||
|
'delegaterId': delegaterId,
|
||||||
'isViewMode': isViewMode,
|
'isViewMode': isViewMode,
|
||||||
'isApprover': isApprover,
|
'isApprover': isApprover,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// context.go(
|
||||||
|
// '/createPlan',
|
||||||
|
// extra: {
|
||||||
|
// 'planData': planData,
|
||||||
|
// 'isViewMode': isViewMode,
|
||||||
|
// 'isApprover': isApprover,
|
||||||
|
// },
|
||||||
|
// );
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print("Error fetching plan: $e");
|
print("Error fetching plan: $e");
|
||||||
}
|
}
|
||||||
@ -854,6 +868,8 @@ class _ApprovalListState extends State<ApprovalList> {
|
|||||||
); // Close popup manually
|
); // Close popup manually
|
||||||
viewPlanforApprover(
|
viewPlanforApprover(
|
||||||
plan.planId,
|
plan.planId,
|
||||||
|
plan.approverId,
|
||||||
|
plan.delegaterId,
|
||||||
isViewMode:
|
isViewMode:
|
||||||
true,
|
true,
|
||||||
isApprover:
|
isApprover:
|
||||||
@ -1108,6 +1124,8 @@ class _ApprovalListState extends State<ApprovalList> {
|
|||||||
); // Close popup manually
|
); // Close popup manually
|
||||||
viewPlanforApprover(
|
viewPlanforApprover(
|
||||||
plan.planId,
|
plan.planId,
|
||||||
|
plan.approverId,
|
||||||
|
plan.delegaterId,
|
||||||
isViewMode: true,
|
isViewMode: true,
|
||||||
isApprover: true,
|
isApprover: true,
|
||||||
);
|
);
|
||||||
|
|||||||
@ -472,6 +472,40 @@ class _LoginWidgetState extends State<LoginWidget> {
|
|||||||
|
|
||||||
/// **Password Field**
|
/// **Password Field**
|
||||||
_buildLabel("Password"),
|
_buildLabel("Password"),
|
||||||
|
// TextFormField(
|
||||||
|
// controller: _passwordController,
|
||||||
|
// style: GoogleFonts.poppins(
|
||||||
|
// fontWeight: FontWeight.w600,
|
||||||
|
// fontSize: 11,
|
||||||
|
// ),
|
||||||
|
// obscureText: _obscureText,
|
||||||
|
//
|
||||||
|
// decoration: _inputDecoration(
|
||||||
|
// "Enter your password",
|
||||||
|
// ).copyWith(
|
||||||
|
// prefixIcon: Icon(Icons.key, size: 16),
|
||||||
|
// suffixIcon: IconButton(
|
||||||
|
// icon: Icon(
|
||||||
|
// _obscureText
|
||||||
|
// ? Icons.visibility_off
|
||||||
|
// : Icons.visibility,
|
||||||
|
// color: Color(0xFF12B24B),
|
||||||
|
// size: 16,
|
||||||
|
// ),
|
||||||
|
//
|
||||||
|
// onPressed:
|
||||||
|
// () => setState(
|
||||||
|
// () => _obscureText = !_obscureText,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
//
|
||||||
|
// validator:
|
||||||
|
// (value) =>
|
||||||
|
// value == null || value.isEmpty
|
||||||
|
// ? 'Required Password'
|
||||||
|
// : null,
|
||||||
|
// ),
|
||||||
TextFormField(
|
TextFormField(
|
||||||
controller: _passwordController,
|
controller: _passwordController,
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
@ -479,6 +513,7 @@ class _LoginWidgetState extends State<LoginWidget> {
|
|||||||
fontSize: 11,
|
fontSize: 11,
|
||||||
),
|
),
|
||||||
obscureText: _obscureText,
|
obscureText: _obscureText,
|
||||||
|
textInputAction: TextInputAction.done,
|
||||||
decoration: _inputDecoration(
|
decoration: _inputDecoration(
|
||||||
"Enter your password",
|
"Enter your password",
|
||||||
).copyWith(
|
).copyWith(
|
||||||
@ -497,13 +532,17 @@ class _LoginWidgetState extends State<LoginWidget> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
onFieldSubmitted: (_) {
|
||||||
|
if (_formKey.currentState!.validate()) {
|
||||||
|
_login(context);
|
||||||
|
}
|
||||||
|
},
|
||||||
validator:
|
validator:
|
||||||
(value) =>
|
(value) =>
|
||||||
value == null || value.isEmpty
|
value == null || value.isEmpty
|
||||||
? 'Required Password'
|
? 'Required Password'
|
||||||
: null,
|
: null,
|
||||||
),
|
),
|
||||||
|
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
|
|
||||||
/// **Login Button**
|
/// **Login Button**
|
||||||
|
|||||||
@ -19,13 +19,14 @@ class CostCenterData extends StatefulWidget {
|
|||||||
final int? costcenterId; // <-- Add this
|
final int? costcenterId; // <-- Add this
|
||||||
final Map<String, dynamic>? costcenterData;
|
final Map<String, dynamic>? costcenterData;
|
||||||
|
|
||||||
const CostCenterData(
|
const CostCenterData({
|
||||||
{super.key,
|
super.key,
|
||||||
required this.isDesktop,
|
required this.isDesktop,
|
||||||
this.layoutColor,
|
this.layoutColor,
|
||||||
required this.fetchGetCostCenter,
|
required this.fetchGetCostCenter,
|
||||||
this.costcenterId,
|
this.costcenterId,
|
||||||
this.costcenterData});
|
this.costcenterData,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
CostCenterDataState createState() => CostCenterDataState();
|
CostCenterDataState createState() => CostCenterDataState();
|
||||||
@ -49,10 +50,7 @@ class CostCenterDataState extends State<CostCenterData> {
|
|||||||
int? costcenterDataId;
|
int? costcenterDataId;
|
||||||
late String isActive = "1";
|
late String isActive = "1";
|
||||||
|
|
||||||
List<String> dataHeader = [
|
List<String> dataHeader = ["name", "description"];
|
||||||
"name",
|
|
||||||
"description",
|
|
||||||
];
|
|
||||||
|
|
||||||
Map<String, dynamic> costcenterDetails() {
|
Map<String, dynamic> costcenterDetails() {
|
||||||
final data = {
|
final data = {
|
||||||
@ -69,7 +67,6 @@ class CostCenterDataState extends State<CostCenterData> {
|
|||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
|
|
||||||
apiData = null;
|
apiData = null;
|
||||||
for (var field in dataHeader) {
|
for (var field in dataHeader) {
|
||||||
controllers[field] = TextEditingController();
|
controllers[field] = TextEditingController();
|
||||||
@ -110,7 +107,6 @@ class CostCenterDataState extends State<CostCenterData> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void toggleStatus() {
|
void toggleStatus() {
|
||||||
setState(() {
|
setState(() {
|
||||||
isActive = isActive == "1" ? "0" : "1";
|
isActive = isActive == "1" ? "0" : "1";
|
||||||
@ -171,7 +167,9 @@ class CostCenterDataState extends State<CostCenterData> {
|
|||||||
apiUrldata = '$apiUrl/api/updateCostCenter/$costcenterDataId';
|
apiUrldata = '$apiUrl/api/updateCostCenter/$costcenterDataId';
|
||||||
costcenterData["cost_center_id"] = costcenterDataId.toString();
|
costcenterData["cost_center_id"] = costcenterDataId.toString();
|
||||||
costcenterData["updated_by"] = userId;
|
costcenterData["updated_by"] = userId;
|
||||||
(costcenterData.containsKey("created_by")) ? costcenterData.remove("created_by") : '' ;
|
(costcenterData.containsKey("created_by"))
|
||||||
|
? costcenterData.remove("created_by")
|
||||||
|
: '';
|
||||||
} else {
|
} else {
|
||||||
print("for add CostCenter id - null");
|
print("for add CostCenter id - null");
|
||||||
apiUrldata = '$apiUrl/api/createCostCenter';
|
apiUrldata = '$apiUrl/api/createCostCenter';
|
||||||
@ -193,11 +191,11 @@ class CostCenterDataState extends State<CostCenterData> {
|
|||||||
};
|
};
|
||||||
final body = jsonEncode(costcenterData);
|
final body = jsonEncode(costcenterData);
|
||||||
|
|
||||||
final response = costcenterDataId != null
|
final response =
|
||||||
|
costcenterDataId != 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);
|
||||||
|
|
||||||
|
|
||||||
switch (response.statusCode) {
|
switch (response.statusCode) {
|
||||||
case 200:
|
case 200:
|
||||||
print("Update - Response: ${response.body}");
|
print("Update - Response: ${response.body}");
|
||||||
@ -217,7 +215,6 @@ class CostCenterDataState extends State<CostCenterData> {
|
|||||||
print("Failed to submit costcenter. Status: ${response.statusCode}");
|
print("Failed to submit costcenter. Status: ${response.statusCode}");
|
||||||
print("Error: ${response.body}");
|
print("Error: ${response.body}");
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(" Error submitting plan: $e");
|
print(" Error submitting plan: $e");
|
||||||
}
|
}
|
||||||
@ -225,7 +222,6 @@ class CostCenterDataState extends State<CostCenterData> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|
||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
backgroundColor: Colors.white,
|
backgroundColor: Colors.white,
|
||||||
contentPadding: const EdgeInsets.fromLTRB(34, 30, 34, 30),
|
contentPadding: const EdgeInsets.fromLTRB(34, 30, 34, 30),
|
||||||
@ -238,27 +234,27 @@ class CostCenterDataState extends State<CostCenterData> {
|
|||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
(costcenterDataId != null) ? 'Edit CostCenter' : 'Create CostCenter',
|
(costcenterDataId != null)
|
||||||
|
? 'Edit CostCenter'
|
||||||
|
: 'Create CostCenter',
|
||||||
style: GoogleFonts.poppins(fontSize: 15, color: Colors.black),
|
style: GoogleFonts.poppins(fontSize: 15, color: Colors.black),
|
||||||
),
|
),
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 2),
|
const SizedBox(height: 2),
|
||||||
Divider(
|
Divider(thickness: 0.2, color: Colors.blueGrey.shade100),
|
||||||
thickness: 0.2,
|
|
||||||
color: Colors.blueGrey.shade100,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 5),
|
const SizedBox(height: 5),
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Name",
|
"Name *",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldForexWrapper(
|
CustomTextFieldForexWrapper(
|
||||||
@ -278,7 +274,8 @@ class CostCenterDataState extends State<CostCenterData> {
|
|||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
||||||
),
|
),
|
||||||
)),
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
if (errorMessages["name"] != null) ...[
|
if (errorMessages["name"] != null) ...[
|
||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
@ -289,18 +286,17 @@ class CostCenterDataState extends State<CostCenterData> {
|
|||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(height: 15),
|
||||||
height: 15,
|
|
||||||
),
|
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Description",
|
"Description *",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldForexWrapper(
|
CustomTextFieldForexWrapper(
|
||||||
@ -334,9 +330,7 @@ class CostCenterDataState extends State<CostCenterData> {
|
|||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(height: 15),
|
||||||
height: 15,
|
|
||||||
),
|
|
||||||
if (costcenterDataId != null)
|
if (costcenterDataId != null)
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
@ -346,7 +340,8 @@ class CostCenterDataState extends State<CostCenterData> {
|
|||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
Tooltip(
|
Tooltip(
|
||||||
message:
|
message:
|
||||||
@ -358,17 +353,14 @@ class CostCenterDataState extends State<CostCenterData> {
|
|||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
fontFamily: "Inter",
|
fontFamily: "Inter",
|
||||||
color: isActive == "1" ? Colors.green : Colors.red,
|
color: isActive == "1" ? Colors.green : Colors.grey,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (costcenterDataId != null)
|
if (costcenterDataId != null) SizedBox(height: 15),
|
||||||
SizedBox(
|
|
||||||
height: 15,
|
|
||||||
),
|
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
@ -405,13 +397,17 @@ class CostCenterDataState extends State<CostCenterData> {
|
|||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: Text('Save',
|
child: Text(
|
||||||
|
'Save',
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 11, color: Colors.white)),
|
fontSize: 11,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
),
|
||||||
// : SizedBox.shrink(),
|
// : SizedBox.shrink(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@ -99,7 +99,7 @@ class CostCenterListState extends State<CostCenterList> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<List<dynamic>> fetchGetCostCenter() async {
|
Future<List<dynamic>> fetchGetCostCenter() async {
|
||||||
final String apiUrlData = '$apiUrl/api/getCostCenterMaster';
|
final String apiUrlData = '$apiUrl/api/getCostCenterMaster?for=table_view';
|
||||||
|
|
||||||
final String? token = await getToken();
|
final String? token = await getToken();
|
||||||
|
|
||||||
@ -566,7 +566,7 @@ class CostCenterListState extends State<CostCenterList> {
|
|||||||
color:
|
color:
|
||||||
tableObject['is_active'] == "1"
|
tableObject['is_active'] == "1"
|
||||||
? Colors.green
|
? Colors.green
|
||||||
: Colors.red,
|
: Colors.grey,
|
||||||
),
|
),
|
||||||
softWrap: true,
|
softWrap: true,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
|
|||||||
@ -19,13 +19,14 @@ class DepartmentData extends StatefulWidget {
|
|||||||
final int? departmentId; // <-- Add this
|
final int? departmentId; // <-- Add this
|
||||||
final Map<String, dynamic>? departmentData;
|
final Map<String, dynamic>? departmentData;
|
||||||
|
|
||||||
const DepartmentData(
|
const DepartmentData({
|
||||||
{super.key,
|
super.key,
|
||||||
required this.isDesktop,
|
required this.isDesktop,
|
||||||
this.layoutColor,
|
this.layoutColor,
|
||||||
required this.fetchGetDepartment,
|
required this.fetchGetDepartment,
|
||||||
this.departmentId,
|
this.departmentId,
|
||||||
this.departmentData});
|
this.departmentData,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
DepartmentDataState createState() => DepartmentDataState();
|
DepartmentDataState createState() => DepartmentDataState();
|
||||||
@ -49,10 +50,7 @@ class DepartmentDataState extends State<DepartmentData> {
|
|||||||
int? departmentDataId;
|
int? departmentDataId;
|
||||||
late String isActive = "1";
|
late String isActive = "1";
|
||||||
|
|
||||||
List<String> dataHeader = [
|
List<String> dataHeader = ["name", "description"];
|
||||||
"name",
|
|
||||||
"description",
|
|
||||||
];
|
|
||||||
|
|
||||||
Map<String, dynamic> departmentDetails() {
|
Map<String, dynamic> departmentDetails() {
|
||||||
final data = {
|
final data = {
|
||||||
@ -69,7 +67,6 @@ class DepartmentDataState extends State<DepartmentData> {
|
|||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
|
|
||||||
apiData = null;
|
apiData = null;
|
||||||
for (var field in dataHeader) {
|
for (var field in dataHeader) {
|
||||||
controllers[field] = TextEditingController();
|
controllers[field] = TextEditingController();
|
||||||
@ -110,7 +107,6 @@ class DepartmentDataState extends State<DepartmentData> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void toggleStatus() {
|
void toggleStatus() {
|
||||||
setState(() {
|
setState(() {
|
||||||
isActive = isActive == "1" ? "0" : "1";
|
isActive = isActive == "1" ? "0" : "1";
|
||||||
@ -171,7 +167,9 @@ class DepartmentDataState extends State<DepartmentData> {
|
|||||||
apiUrldata = '$apiUrl/api/updateDepartment/$departmentDataId';
|
apiUrldata = '$apiUrl/api/updateDepartment/$departmentDataId';
|
||||||
departmentData["department_id"] = departmentDataId.toString();
|
departmentData["department_id"] = departmentDataId.toString();
|
||||||
departmentData["updated_by"] = userId;
|
departmentData["updated_by"] = userId;
|
||||||
(departmentData.containsKey("created_by")) ? departmentData.remove("created_by") : '' ;
|
(departmentData.containsKey("created_by"))
|
||||||
|
? departmentData.remove("created_by")
|
||||||
|
: '';
|
||||||
} else {
|
} else {
|
||||||
print("for add Department id - null");
|
print("for add Department id - null");
|
||||||
apiUrldata = '$apiUrl/api/createDepartment';
|
apiUrldata = '$apiUrl/api/createDepartment';
|
||||||
@ -193,11 +191,11 @@ class DepartmentDataState extends State<DepartmentData> {
|
|||||||
};
|
};
|
||||||
final body = jsonEncode(departmentData);
|
final body = jsonEncode(departmentData);
|
||||||
|
|
||||||
final response = departmentDataId != null
|
final response =
|
||||||
|
departmentDataId != 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);
|
||||||
|
|
||||||
|
|
||||||
switch (response.statusCode) {
|
switch (response.statusCode) {
|
||||||
case 200:
|
case 200:
|
||||||
print("Update - Response: ${response.body}");
|
print("Update - Response: ${response.body}");
|
||||||
@ -217,7 +215,6 @@ class DepartmentDataState extends State<DepartmentData> {
|
|||||||
print("Failed to submit department. Status: ${response.statusCode}");
|
print("Failed to submit department. Status: ${response.statusCode}");
|
||||||
print("Error: ${response.body}");
|
print("Error: ${response.body}");
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(" Error submitting plan: $e");
|
print(" Error submitting plan: $e");
|
||||||
}
|
}
|
||||||
@ -225,7 +222,6 @@ class DepartmentDataState extends State<DepartmentData> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|
||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
backgroundColor: Colors.white,
|
backgroundColor: Colors.white,
|
||||||
contentPadding: const EdgeInsets.fromLTRB(34, 30, 34, 30),
|
contentPadding: const EdgeInsets.fromLTRB(34, 30, 34, 30),
|
||||||
@ -238,27 +234,27 @@ class DepartmentDataState extends State<DepartmentData> {
|
|||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
(departmentDataId != null) ? 'Edit Department' : 'Create Department',
|
(departmentDataId != null)
|
||||||
|
? 'Edit Department'
|
||||||
|
: 'Create Department',
|
||||||
style: GoogleFonts.poppins(fontSize: 15, color: Colors.black),
|
style: GoogleFonts.poppins(fontSize: 15, color: Colors.black),
|
||||||
),
|
),
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 2),
|
const SizedBox(height: 2),
|
||||||
Divider(
|
Divider(thickness: 0.2, color: Colors.blueGrey.shade100),
|
||||||
thickness: 0.2,
|
|
||||||
color: Colors.blueGrey.shade100,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 5),
|
const SizedBox(height: 5),
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Name",
|
"Name *",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldForexWrapper(
|
CustomTextFieldForexWrapper(
|
||||||
@ -278,7 +274,8 @@ class DepartmentDataState extends State<DepartmentData> {
|
|||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
||||||
),
|
),
|
||||||
)),
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
if (errorMessages["name"] != null) ...[
|
if (errorMessages["name"] != null) ...[
|
||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
@ -289,18 +286,17 @@ class DepartmentDataState extends State<DepartmentData> {
|
|||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(height: 15),
|
||||||
height: 15,
|
|
||||||
),
|
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Description",
|
"Description *",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldForexWrapper(
|
CustomTextFieldForexWrapper(
|
||||||
@ -334,9 +330,7 @@ class DepartmentDataState extends State<DepartmentData> {
|
|||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(height: 15),
|
||||||
height: 15,
|
|
||||||
),
|
|
||||||
if (departmentDataId != null)
|
if (departmentDataId != null)
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
@ -346,7 +340,8 @@ class DepartmentDataState extends State<DepartmentData> {
|
|||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
Tooltip(
|
Tooltip(
|
||||||
message:
|
message:
|
||||||
@ -362,13 +357,10 @@ class DepartmentDataState extends State<DepartmentData> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (departmentDataId != null)
|
if (departmentDataId != null) SizedBox(height: 15),
|
||||||
SizedBox(
|
|
||||||
height: 15,
|
|
||||||
),
|
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
@ -405,13 +397,17 @@ class DepartmentDataState extends State<DepartmentData> {
|
|||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: Text('Save',
|
child: Text(
|
||||||
|
'Save',
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 11, color: Colors.white)),
|
fontSize: 11,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
),
|
||||||
// : SizedBox.shrink(),
|
// : SizedBox.shrink(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@ -99,7 +99,7 @@ class DepartmentListState extends State<DepartmentList> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<List<dynamic>> fetchGetDepartment() async {
|
Future<List<dynamic>> fetchGetDepartment() async {
|
||||||
final String apiUrlData = '$apiUrl/api/getDepartmentList';
|
final String apiUrlData = '$apiUrl/api/getDepartmentList?for=table_view';
|
||||||
|
|
||||||
final String? token = await getToken();
|
final String? token = await getToken();
|
||||||
|
|
||||||
@ -565,7 +565,7 @@ class DepartmentListState extends State<DepartmentList> {
|
|||||||
color:
|
color:
|
||||||
tableObject['is_active'] == "1"
|
tableObject['is_active'] == "1"
|
||||||
? Colors.green
|
? Colors.green
|
||||||
: Colors.red,
|
: Colors.grey,
|
||||||
),
|
),
|
||||||
softWrap: true,
|
softWrap: true,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
|
|||||||
@ -100,11 +100,13 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw Exception(
|
throw Exception(
|
||||||
"Unexpected response format: Expected a List but got ${responseBody.runtimeType}");
|
"Unexpected response format: Expected a List but got ${responseBody.runtimeType}",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw Exception(
|
throw Exception(
|
||||||
'Failed to load users. Status Code: ${response.statusCode}');
|
'Failed to load users. Status Code: ${response.statusCode}',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print("Error fetching users: $e");
|
print("Error fetching users: $e");
|
||||||
@ -138,7 +140,8 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
|||||||
List<dynamic> travellerList = responseBody['data'];
|
List<dynamic> travellerList = responseBody['data'];
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
_traveller = travellerList
|
_traveller =
|
||||||
|
travellerList
|
||||||
.map((user) => SearchTraveler.fromJson(user))
|
.map((user) => SearchTraveler.fromJson(user))
|
||||||
.toList();
|
.toList();
|
||||||
_filteredTraveller = List.from(_traveller);
|
_filteredTraveller = List.from(_traveller);
|
||||||
@ -147,47 +150,53 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
|||||||
print("Users fetched: ${_users.length}");
|
print("Users fetched: ${_users.length}");
|
||||||
for (var travvelr in _traveller) {
|
for (var travvelr in _traveller) {
|
||||||
print(
|
print(
|
||||||
"${travvelr.firstName} ${travvelr.lastName} ${travvelr.mobileNo}");
|
"${travvelr.firstName} ${travvelr.lastName} ${travvelr.mobileNo}",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw Exception(
|
throw Exception(
|
||||||
"Unexpected response format: Expected a List but got ${responseBody.runtimeType}");
|
"Unexpected response format: Expected a List but got ${responseBody.runtimeType}",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw Exception(
|
throw Exception(
|
||||||
'Failed to load users. Status Code: ${response.statusCode}');
|
'Failed to load users. Status Code: ${response.statusCode}',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print("Error fetching traveller: $e");
|
print("Error fetching traveller: $e");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _filterUsers1(String query) {
|
// void _filterUsers1(String query) {
|
||||||
print("Filtering users...");
|
// print("Filtering users...");
|
||||||
setState(() {
|
// setState(() {
|
||||||
if (query.isEmpty) {
|
// if (query.isEmpty) {
|
||||||
_filteredUsers = List.from(_users);
|
// _filteredUsers = List.from(_users);
|
||||||
} else {
|
// } else {
|
||||||
_filteredUsers = _users.where((user) {
|
// _filteredUsers =
|
||||||
List<String> searchFields = [
|
// _users.where((user) {
|
||||||
"${user.firstName} ${user.lastName}".toLowerCase(),
|
// List<String> searchFields = [
|
||||||
user.email.toLowerCase() ?? "",
|
// "${user.firstName} ${user.lastName}".toLowerCase(),
|
||||||
user.userId.toLowerCase() ?? "",
|
// user.email.toLowerCase() ?? "",
|
||||||
user.mobileNo ?? "",
|
// user.empCode?.toLowerCase() ?? "",
|
||||||
user.alternateMobileNo ?? ""
|
// user.userId.toLowerCase() ?? "",
|
||||||
];
|
// user.mobileNo ?? "",
|
||||||
|
// user.alternateMobileNo ?? "",
|
||||||
return searchFields
|
// ];
|
||||||
.any((field) => field.contains(query.toLowerCase()));
|
//
|
||||||
}).toList();
|
// return searchFields.any(
|
||||||
}
|
// (field) => field.contains(query.toLowerCase()),
|
||||||
});
|
// );
|
||||||
|
// }).toList();
|
||||||
print("Filtered Users:");
|
// }
|
||||||
for (var user in _filteredUsers) {
|
// });
|
||||||
print("${user.firstName} ${user.lastName}");
|
//
|
||||||
}
|
// print("Filtered Users:");
|
||||||
}
|
// for (var user in _filteredUsers) {
|
||||||
|
// print("${user.firstName} ${user.lastName}");
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
void _filterUsers(String query) {
|
void _filterUsers(String query) {
|
||||||
print("Filtering _filterUsersTravellers...");
|
print("Filtering _filterUsersTravellers...");
|
||||||
@ -200,7 +209,8 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
|||||||
];
|
];
|
||||||
} else {
|
} else {
|
||||||
_filteredList = [
|
_filteredList = [
|
||||||
..._users.where((user) {
|
..._users
|
||||||
|
.where((user) {
|
||||||
print("usersLLL : ${user}");
|
print("usersLLL : ${user}");
|
||||||
|
|
||||||
List<String> searchFields = [
|
List<String> searchFields = [
|
||||||
@ -208,11 +218,14 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
|||||||
user.email.toLowerCase() ?? "",
|
user.email.toLowerCase() ?? "",
|
||||||
user.userId.toLowerCase() ?? "",
|
user.userId.toLowerCase() ?? "",
|
||||||
user.mobileNo ?? "",
|
user.mobileNo ?? "",
|
||||||
user.alternateMobileNo ?? ""
|
user.alternateMobileNo ?? "",
|
||||||
|
user.empCode?.toLowerCase() ?? "",
|
||||||
];
|
];
|
||||||
return searchFields
|
return searchFields.any(
|
||||||
.any((field) => field.contains(query.toLowerCase()));
|
(field) => field.contains(query.toLowerCase()),
|
||||||
}).map((user) => {"type": "user", "data": user}),
|
);
|
||||||
|
})
|
||||||
|
.map((user) => {"type": "user", "data": user}),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -221,7 +234,8 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
|||||||
for (var item in _filteredList) {
|
for (var item in _filteredList) {
|
||||||
var user = item["data"];
|
var user = item["data"];
|
||||||
print(
|
print(
|
||||||
"${item["type"].toUpperCase()} - ${user.firstName} ${user.lastName}");
|
"${item["type"].toUpperCase()} - ${user.firstName} ${user.lastName}",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,16 +250,19 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
|||||||
];
|
];
|
||||||
} else {
|
} else {
|
||||||
_filteredList = [
|
_filteredList = [
|
||||||
..._traveller.where((traveller) {
|
..._traveller
|
||||||
|
.where((traveller) {
|
||||||
List<String> searchFields = [
|
List<String> searchFields = [
|
||||||
"${traveller.firstName} ${traveller.lastName}".toLowerCase(),
|
"${traveller.firstName} ${traveller.lastName}".toLowerCase(),
|
||||||
traveller.email.toLowerCase() ?? "",
|
traveller.email.toLowerCase() ?? "",
|
||||||
traveller.travellerId.toLowerCase() ?? "",
|
traveller.travellerId.toLowerCase() ?? "",
|
||||||
traveller.mobileNo ?? "",
|
traveller.mobileNo ?? "",
|
||||||
];
|
];
|
||||||
return searchFields
|
return searchFields.any(
|
||||||
.any((field) => field.contains(query.toLowerCase()));
|
(field) => field.contains(query.toLowerCase()),
|
||||||
}).map((traveller) => {"type": "traveller", "data": traveller}),
|
);
|
||||||
|
})
|
||||||
|
.map((traveller) => {"type": "traveller", "data": traveller}),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -254,7 +271,8 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
|||||||
for (var item in _filteredList) {
|
for (var item in _filteredList) {
|
||||||
var user = item["data"];
|
var user = item["data"];
|
||||||
print(
|
print(
|
||||||
"${item["type"].toUpperCase()} - ${user.firstName} ${user.lastName}");
|
"${item["type"].toUpperCase()} - ${user.firstName} ${user.lastName}",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -266,32 +284,39 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
|||||||
if (query.isEmpty) {
|
if (query.isEmpty) {
|
||||||
_filteredList = [
|
_filteredList = [
|
||||||
..._users.map((user) => {"type": "user", "data": user}),
|
..._users.map((user) => {"type": "user", "data": user}),
|
||||||
..._traveller
|
..._traveller.map(
|
||||||
.map((traveller) => {"type": "traveller", "data": traveller}),
|
(traveller) => {"type": "traveller", "data": traveller},
|
||||||
|
),
|
||||||
];
|
];
|
||||||
} else {
|
} else {
|
||||||
_filteredList = [
|
_filteredList = [
|
||||||
..._users.where((user) {
|
..._users
|
||||||
|
.where((user) {
|
||||||
List<String> searchFields = [
|
List<String> searchFields = [
|
||||||
"${user.firstName} ${user.lastName}".toLowerCase(),
|
"${user.firstName} ${user.lastName}".toLowerCase(),
|
||||||
user.email.toLowerCase() ?? "",
|
user.email.toLowerCase() ?? "",
|
||||||
user.userId.toLowerCase() ?? "",
|
user.userId.toLowerCase() ?? "",
|
||||||
user.mobileNo ?? "",
|
user.mobileNo ?? "",
|
||||||
user.alternateMobileNo ?? ""
|
user.alternateMobileNo ?? "",
|
||||||
];
|
];
|
||||||
return searchFields
|
return searchFields.any(
|
||||||
.any((field) => field.contains(query.toLowerCase()));
|
(field) => field.contains(query.toLowerCase()),
|
||||||
}).map((user) => {"type": "user", "data": user}),
|
);
|
||||||
..._traveller.where((traveller) {
|
})
|
||||||
|
.map((user) => {"type": "user", "data": user}),
|
||||||
|
..._traveller
|
||||||
|
.where((traveller) {
|
||||||
List<String> searchFields = [
|
List<String> searchFields = [
|
||||||
"${traveller.firstName} ${traveller.lastName}".toLowerCase(),
|
"${traveller.firstName} ${traveller.lastName}".toLowerCase(),
|
||||||
traveller.email.toLowerCase() ?? "",
|
traveller.email.toLowerCase() ?? "",
|
||||||
traveller.travellerId.toLowerCase() ?? "",
|
traveller.travellerId.toLowerCase() ?? "",
|
||||||
traveller.mobileNo ?? "",
|
traveller.mobileNo ?? "",
|
||||||
];
|
];
|
||||||
return searchFields
|
return searchFields.any(
|
||||||
.any((field) => field.contains(query.toLowerCase()));
|
(field) => field.contains(query.toLowerCase()),
|
||||||
}).map((traveller) => {"type": "traveller", "data": traveller}),
|
);
|
||||||
|
})
|
||||||
|
.map((traveller) => {"type": "traveller", "data": traveller}),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -300,7 +325,8 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
|||||||
for (var item in _filteredList) {
|
for (var item in _filteredList) {
|
||||||
var user = item["data"];
|
var user = item["data"];
|
||||||
print(
|
print(
|
||||||
"${item["type"].toUpperCase()} - ${user.firstName} ${user.lastName}");
|
"${item["type"].toUpperCase()} - ${user.firstName} ${user.lastName}",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -324,10 +350,14 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
|||||||
MainAxisSize.min, // Ensures content doesn't expand unnecessarily
|
MainAxisSize.min, // Ensures content doesn't expand unnecessarily
|
||||||
children: [
|
children: [
|
||||||
widget.title == "Others"
|
widget.title == "Others"
|
||||||
? Text("Please Select Other User",
|
? Text(
|
||||||
style: GoogleFonts.poppins(fontSize: 14))
|
"Please Select Other User",
|
||||||
: Text("Please Select Other Employee",
|
style: GoogleFonts.poppins(fontSize: 14),
|
||||||
style: GoogleFonts.poppins(fontSize: 14)),
|
)
|
||||||
|
: Text(
|
||||||
|
"Please Select Other Employee",
|
||||||
|
style: GoogleFonts.poppins(fontSize: 14),
|
||||||
|
),
|
||||||
SizedBox(height: 10),
|
SizedBox(height: 10),
|
||||||
|
|
||||||
// Search Field
|
// Search Field
|
||||||
@ -344,11 +374,14 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
|||||||
style: GoogleFonts.poppins(fontSize: 12),
|
style: GoogleFonts.poppins(fontSize: 12),
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: "Search for a user",
|
hintText: "Search for a user",
|
||||||
hintStyle:
|
hintStyle: GoogleFonts.poppins(
|
||||||
GoogleFonts.poppins(fontSize: 14, color: Colors.grey),
|
fontSize: 14,
|
||||||
|
color: Colors.grey,
|
||||||
|
),
|
||||||
prefixIcon: Icon(Icons.search),
|
prefixIcon: Icon(Icons.search),
|
||||||
border:
|
border: OutlineInputBorder(
|
||||||
OutlineInputBorder(borderRadius: BorderRadius.circular(8)),
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
),
|
||||||
enabledBorder: OutlineInputBorder(
|
enabledBorder: OutlineInputBorder(
|
||||||
borderSide: BorderSide(color: Colors.grey.shade200, width: 1),
|
borderSide: BorderSide(color: Colors.grey.shade200, width: 1),
|
||||||
// borderSide: BorderSide(color: Color(0xFFF5F5F5), width: 2),
|
// borderSide: BorderSide(color: Color(0xFFF5F5F5), width: 2),
|
||||||
@ -366,9 +399,13 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
|||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Text("or create a new traveler",
|
Text(
|
||||||
|
"or create a new traveler",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 14, color: Color(0xFF575A74))),
|
fontSize: 14,
|
||||||
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
@ -376,9 +413,13 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
|||||||
_searchController.clear();
|
_searchController.clear();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
child: Text("Create",
|
child: Text(
|
||||||
|
"Create",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 14, color: widget.layoutColorForUser)),
|
fontSize: 14,
|
||||||
|
color: widget.layoutColorForUser,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -391,12 +432,15 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
|||||||
? SizedBox(
|
? SizedBox(
|
||||||
height: 300, // Limit height to avoid overflow
|
height: 300, // Limit height to avoid overflow
|
||||||
// child: _filteredUsers.isEmpty
|
// child: _filteredUsers.isEmpty
|
||||||
child: _filteredList.isEmpty
|
child:
|
||||||
|
_filteredList.isEmpty
|
||||||
? Center(
|
? Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
"No users found",
|
"No users found",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 14, color: Colors.grey),
|
fontSize: 14,
|
||||||
|
color: Colors.grey,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: ListView.builder(
|
: ListView.builder(
|
||||||
@ -411,7 +455,8 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
|||||||
item["type"]; // "user" or "traveller"
|
item["type"]; // "user" or "traveller"
|
||||||
if (user is Map<String, dynamic>) {
|
if (user is Map<String, dynamic>) {
|
||||||
print(
|
print(
|
||||||
"userLsirer - ${jsonEncode(user)}"); // pretty JSON-like string
|
"userLsirer - ${jsonEncode(user)}",
|
||||||
|
); // pretty JSON-like string
|
||||||
} else {
|
} else {
|
||||||
print("userLsirer - $user"); // fallback
|
print("userLsirer - $user"); // fallback
|
||||||
}
|
}
|
||||||
@ -420,32 +465,37 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
|||||||
"${user.firstName ?? "Unknown"} ${user.lastName ?? ""}",
|
"${user.firstName ?? "Unknown"} ${user.lastName ?? ""}",
|
||||||
style: GoogleFonts.poppins(fontSize: 11),
|
style: GoogleFonts.poppins(fontSize: 11),
|
||||||
),
|
),
|
||||||
subtitle: userType == "user"
|
subtitle:
|
||||||
|
userType == "user"
|
||||||
? Text(
|
? Text(
|
||||||
"Employee ID: ${user.empCode ?? ""} ",
|
"Employee ID: ${user.empCode ?? ""} ",
|
||||||
// "Employee ID: ${userType == "user" ? user.userId : user.travellerId}",
|
// "Employee ID: ${userType == "user" ? user.userId : user.travellerId}",
|
||||||
style:
|
style: GoogleFonts.poppins(
|
||||||
GoogleFonts.poppins(fontSize: 10),
|
fontSize: 10,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
: Text(
|
: Text(
|
||||||
"Mobile : ${user.mobileNo ?? ""} ",
|
"Mobile : ${user.mobileNo ?? ""} ",
|
||||||
// "Employee ID: ${userType == "user" ? user.userId : user.travellerId}",
|
// "Employee ID: ${userType == "user" ? user.userId : user.travellerId}",
|
||||||
style:
|
style: GoogleFonts.poppins(
|
||||||
GoogleFonts.poppins(fontSize: 10),
|
fontSize: 10,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
String selectedUser =
|
String selectedUser =
|
||||||
"${user.firstName ?? "Unknown"} ${user.lastName ?? ""}";
|
"${user.firstName ?? "Unknown"} ${user.lastName ?? ""}";
|
||||||
setState(() {
|
setState(() {
|
||||||
_searchController.text = selectedUser;
|
_searchController.text = selectedUser;
|
||||||
userIdSelected = userType == "user"
|
userIdSelected =
|
||||||
|
userType == "user"
|
||||||
? user.userId
|
? user.userId
|
||||||
: user.travellerId;
|
: user.travellerId;
|
||||||
isTraveller = userType == "traveller";
|
isTraveller = userType == "traveller";
|
||||||
});
|
});
|
||||||
print(
|
print(
|
||||||
"Selected: $selectedUser, ID: ${userType == "user" ? user.userId : user.travellerId},"
|
"Selected: $selectedUser, ID: ${userType == "user" ? user.userId : user.travellerId},"
|
||||||
" isTraveller: $userIdSelected");
|
" isTraveller: $userIdSelected",
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -462,10 +512,16 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
|||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
child: TravelerForm(
|
child: TravelerForm(
|
||||||
formKey: _formKey,
|
formKey: _formKey,
|
||||||
onSubmit: (String fullName, String travellerId,
|
onSubmit: (
|
||||||
bool isTraveller) {
|
String fullName,
|
||||||
widget.onSubmit(fullName, travellerId,
|
String travellerId,
|
||||||
isTraveller); // Pass the data up
|
bool isTraveller,
|
||||||
|
) {
|
||||||
|
widget.onSubmit(
|
||||||
|
fullName,
|
||||||
|
travellerId,
|
||||||
|
isTraveller,
|
||||||
|
); // Pass the data up
|
||||||
},
|
},
|
||||||
firstNameController: TextEditingController(),
|
firstNameController: TextEditingController(),
|
||||||
lastNameController: TextEditingController(),
|
lastNameController: TextEditingController(),
|
||||||
@ -487,7 +543,9 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
|||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
side: BorderSide(
|
side: BorderSide(
|
||||||
color: widget.layoutColorForUser, width: 2),
|
color: widget.layoutColorForUser,
|
||||||
|
width: 2,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
||||||
),
|
),
|
||||||
@ -508,15 +566,21 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
|||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
side: BorderSide(
|
side: BorderSide(
|
||||||
color: widget.layoutColorForUser, width: 2),
|
color: widget.layoutColorForUser,
|
||||||
|
width: 2,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
||||||
),
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
print(
|
print(
|
||||||
"Submitting: ${_searchController.text}, ID: $userIdSelected");
|
"Submitting: ${_searchController.text}, ID: $userIdSelected",
|
||||||
|
);
|
||||||
widget.onSubmit(
|
widget.onSubmit(
|
||||||
_searchController.text, userIdSelected, isTraveller);
|
_searchController.text,
|
||||||
|
userIdSelected,
|
||||||
|
isTraveller,
|
||||||
|
);
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
@ -542,14 +606,15 @@ class TravelerForm extends StatefulWidget {
|
|||||||
final GlobalKey<FormState> formKey;
|
final GlobalKey<FormState> formKey;
|
||||||
final void Function(String, String, bool) onSubmit;
|
final void Function(String, String, bool) onSubmit;
|
||||||
|
|
||||||
TravelerForm(
|
TravelerForm({
|
||||||
{required this.formKey,
|
required this.formKey,
|
||||||
required this.orgId,
|
required this.orgId,
|
||||||
required this.firstNameController,
|
required this.firstNameController,
|
||||||
required this.lastNameController,
|
required this.lastNameController,
|
||||||
required this.emailController,
|
required this.emailController,
|
||||||
required this.mobileController,
|
required this.mobileController,
|
||||||
required this.onSubmit});
|
required this.onSubmit,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_TravelerFormState createState() => _TravelerFormState();
|
_TravelerFormState createState() => _TravelerFormState();
|
||||||
@ -582,8 +647,9 @@ class _TravelerFormState extends State<TravelerForm> {
|
|||||||
if (value == null || value.isEmpty) {
|
if (value == null || value.isEmpty) {
|
||||||
return 'Email is required';
|
return 'Email is required';
|
||||||
}
|
}
|
||||||
if (!RegExp(r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$')
|
if (!RegExp(
|
||||||
.hasMatch(value)) {
|
r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$',
|
||||||
|
).hasMatch(value)) {
|
||||||
return 'Enter a valid email address';
|
return 'Enter a valid email address';
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -642,7 +708,8 @@ class _TravelerFormState extends State<TravelerForm> {
|
|||||||
String lastName = travellerData["last_name"];
|
String lastName = travellerData["last_name"];
|
||||||
|
|
||||||
print(
|
print(
|
||||||
"Traveller Added: ID: $travellerId, Name: $firstName $lastName");
|
"Traveller Added: ID: $travellerId, Name: $firstName $lastName",
|
||||||
|
);
|
||||||
|
|
||||||
// // Pass data to callback
|
// // Pass data to callback
|
||||||
// widget.onSubmit("$firstName $lastName", travellerId, true);
|
// widget.onSubmit("$firstName $lastName", travellerId, true);
|
||||||
@ -658,21 +725,22 @@ class _TravelerFormState extends State<TravelerForm> {
|
|||||||
SnackBar(
|
SnackBar(
|
||||||
content: Text(
|
content: Text(
|
||||||
"Traveller added successfully!",
|
"Traveller added successfully!",
|
||||||
style:
|
style: GoogleFonts.poppins(
|
||||||
GoogleFonts.poppins(color: Colors.white), // ✅ Set text color
|
color: Colors.white,
|
||||||
|
), // ✅ Set text color
|
||||||
),
|
),
|
||||||
backgroundColor: Colors.green,
|
backgroundColor: Colors.green,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(
|
||||||
SnackBar(content: Text("Error: ${response.body}")),
|
context,
|
||||||
);
|
).showSnackBar(SnackBar(content: Text("Error: ${response.body}")));
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(
|
||||||
SnackBar(content: Text("Failed to connect to server.")),
|
context,
|
||||||
);
|
).showSnackBar(SnackBar(content: Text("Failed to connect to server.")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -697,8 +765,10 @@ class _TravelerFormState extends State<TravelerForm> {
|
|||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Text("Create Traveler",
|
Text(
|
||||||
style: GoogleFonts.poppins(color: Colors.black54)),
|
"Create Traveler",
|
||||||
|
style: GoogleFonts.poppins(color: Colors.black54),
|
||||||
|
),
|
||||||
SizedBox(height: 7),
|
SizedBox(height: 7),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
@ -714,13 +784,17 @@ class _TravelerFormState extends State<TravelerForm> {
|
|||||||
onPressed: () {
|
onPressed: () {
|
||||||
widget.formKey.currentState?.reset();
|
widget.formKey.currentState?.reset();
|
||||||
},
|
},
|
||||||
child: Text("Clear",
|
child: Text(
|
||||||
style: GoogleFonts.poppins(color: Colors.grey)),
|
"Clear",
|
||||||
|
style: GoogleFonts.poppins(color: Colors.grey),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => _onSubmit(context),
|
onPressed: () => _onSubmit(context),
|
||||||
child: Text("Add",
|
child: Text(
|
||||||
style: GoogleFonts.poppins(color: Color(0xFF114D8B))),
|
"Add",
|
||||||
|
style: GoogleFonts.poppins(color: Color(0xFF114D8B)),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@ -21,13 +21,14 @@ class ForexData extends StatefulWidget {
|
|||||||
final int? forexId; // <-- Add this
|
final int? forexId; // <-- Add this
|
||||||
final Map<String, dynamic>? forexData;
|
final Map<String, dynamic>? forexData;
|
||||||
|
|
||||||
const ForexData(
|
const ForexData({
|
||||||
{super.key,
|
super.key,
|
||||||
required this.isDesktop,
|
required this.isDesktop,
|
||||||
this.layoutColor,
|
this.layoutColor,
|
||||||
required this.fetchGetForex,
|
required this.fetchGetForex,
|
||||||
this.forexId,
|
this.forexId,
|
||||||
this.forexData});
|
this.forexData,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ForexDataState createState() => ForexDataState();
|
ForexDataState createState() => ForexDataState();
|
||||||
@ -61,7 +62,7 @@ class ForexDataState extends State<ForexData> {
|
|||||||
"currency",
|
"currency",
|
||||||
"perdiemAmount",
|
"perdiemAmount",
|
||||||
"cash",
|
"cash",
|
||||||
"card"
|
"card",
|
||||||
];
|
];
|
||||||
|
|
||||||
Map<String, dynamic> forex_Detials() {
|
Map<String, dynamic> forex_Detials() {
|
||||||
@ -197,7 +198,7 @@ class ForexDataState extends State<ForexData> {
|
|||||||
"currency",
|
"currency",
|
||||||
"perdiemAmount",
|
"perdiemAmount",
|
||||||
"cash_percentage",
|
"cash_percentage",
|
||||||
"card_percentage"
|
"card_percentage",
|
||||||
];
|
];
|
||||||
|
|
||||||
// Check validation for each field
|
// Check validation for each field
|
||||||
@ -273,7 +274,8 @@ class ForexDataState extends State<ForexData> {
|
|||||||
};
|
};
|
||||||
final body = jsonEncode(forexData);
|
final body = jsonEncode(forexData);
|
||||||
|
|
||||||
final response = forexDataId != null
|
final response =
|
||||||
|
forexDataId != 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);
|
||||||
|
|
||||||
@ -326,7 +328,7 @@ class ForexDataState extends State<ForexData> {
|
|||||||
// Map country codes to country names
|
// Map country codes to country names
|
||||||
countryMap = {
|
countryMap = {
|
||||||
for (var item in countryList)
|
for (var item in countryList)
|
||||||
item['country_code'] as String: item['country_name'] as String
|
item['country_code'] as String: item['country_name'] as String,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Extract only country codes for processing
|
// Extract only country codes for processing
|
||||||
@ -355,21 +357,19 @@ class ForexDataState extends State<ForexData> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 2),
|
const SizedBox(height: 2),
|
||||||
Divider(
|
Divider(thickness: 0.2, color: Colors.blueGrey.shade100),
|
||||||
thickness: 0.2,
|
|
||||||
color: Colors.blueGrey.shade100,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 5),
|
const SizedBox(height: 5),
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Country",
|
"Country *",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldForexWrapper(
|
CustomTextFieldForexWrapper(
|
||||||
@ -381,13 +381,14 @@ class ForexDataState extends State<ForexData> {
|
|||||||
selectedItem: countryMap[selectedCountry],
|
selectedItem: countryMap[selectedCountry],
|
||||||
popupProps: PopupProps.menu(
|
popupProps: PopupProps.menu(
|
||||||
showSearchBox: true, // Enables search functionality
|
showSearchBox: true, // Enables search functionality
|
||||||
menuProps: const MenuProps(
|
menuProps: const MenuProps(backgroundColor: Colors.white),
|
||||||
backgroundColor: Colors.white,
|
|
||||||
),
|
|
||||||
constraints: BoxConstraints(maxHeight: 250),
|
constraints: BoxConstraints(maxHeight: 250),
|
||||||
itemBuilder: (context, item, isSelected) => Padding(
|
itemBuilder:
|
||||||
|
(context, item, isSelected) => Padding(
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(
|
||||||
horizontal: 8.0, vertical: 6.0),
|
horizontal: 8.0,
|
||||||
|
vertical: 6.0,
|
||||||
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
item,
|
item,
|
||||||
style: GoogleFonts.poppins(fontSize: 11.5),
|
style: GoogleFonts.poppins(fontSize: 11.5),
|
||||||
@ -405,12 +406,11 @@ class ForexDataState extends State<ForexData> {
|
|||||||
dropdownDecoratorProps: DropDownDecoratorProps(
|
dropdownDecoratorProps: DropDownDecoratorProps(
|
||||||
dropdownSearchDecoration: InputDecoration(
|
dropdownSearchDecoration: InputDecoration(
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding: EdgeInsets.symmetric(
|
contentPadding: EdgeInsets.symmetric(horizontal: 1),
|
||||||
horizontal: 1,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
dropdownBuilder:
|
||||||
dropdownBuilder: (context, selectedItem) => Align(
|
(context, selectedItem) => Align(
|
||||||
// Center-align selected item
|
// Center-align selected item
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: Text(
|
child: Text(
|
||||||
@ -421,7 +421,8 @@ class ForexDataState extends State<ForexData> {
|
|||||||
onChanged: (String? newValue) {
|
onChanged: (String? newValue) {
|
||||||
setState(() {
|
setState(() {
|
||||||
// Find the country_code based on selected country_name
|
// Find the country_code based on selected country_name
|
||||||
selectedCountry = countryMap.entries
|
selectedCountry =
|
||||||
|
countryMap.entries
|
||||||
.firstWhere((entry) => entry.value == newValue)
|
.firstWhere((entry) => entry.value == newValue)
|
||||||
.key;
|
.key;
|
||||||
selectedCountryName = newValue;
|
selectedCountryName = newValue;
|
||||||
@ -444,11 +445,12 @@ class ForexDataState extends State<ForexData> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Currency",
|
"Currency *",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldForexWrapper(
|
CustomTextFieldForexWrapper(
|
||||||
@ -470,7 +472,8 @@ class ForexDataState extends State<ForexData> {
|
|||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
||||||
),
|
),
|
||||||
)),
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
if (errorMessages["currency"] != null) ...[
|
if (errorMessages["currency"] != null) ...[
|
||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
@ -481,11 +484,9 @@ class ForexDataState extends State<ForexData> {
|
|||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
// if (isDesktop)SizedBox(width: 8,) else SizedBox(height: 8,),
|
|
||||||
|
|
||||||
SizedBox(
|
// if (isDesktop)SizedBox(width: 8,) else SizedBox(height: 8,),
|
||||||
height: 10,
|
SizedBox(height: 10),
|
||||||
),
|
|
||||||
Row(
|
Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
@ -493,18 +494,20 @@ class ForexDataState extends State<ForexData> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Cash (%)",
|
"Cash (%) *",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldForexWrapper(
|
CustomTextFieldForexWrapper(
|
||||||
isFocused: false,
|
isFocused: false,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
width: widget.isDesktop
|
width:
|
||||||
|
widget.isDesktop
|
||||||
? MediaQuery.of(context).size.width * 0.09
|
? MediaQuery.of(context).size.width * 0.09
|
||||||
: MediaQuery.of(context).size.width * 0.66,
|
: MediaQuery.of(context).size.width * 0.66,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
@ -518,13 +521,16 @@ class ForexDataState extends State<ForexData> {
|
|||||||
style: const TextStyle(fontSize: 12),
|
style: const TextStyle(fontSize: 12),
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
labelText: "Cash",
|
labelText: "Cash",
|
||||||
labelStyle:
|
labelStyle: TextStyle(
|
||||||
TextStyle(fontSize: 11, color: Colors.grey),
|
fontSize: 11,
|
||||||
|
color: Colors.grey,
|
||||||
|
),
|
||||||
floatingLabelBehavior: FloatingLabelBehavior.never,
|
floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
||||||
),
|
),
|
||||||
)),
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
if (errorMessages["cash_percentage"] != null) ...[
|
if (errorMessages["cash_percentage"] != null) ...[
|
||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
@ -540,18 +546,20 @@ class ForexDataState extends State<ForexData> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Card (%)",
|
"Card (%) *",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldForexWrapper(
|
CustomTextFieldForexWrapper(
|
||||||
isFocused: false,
|
isFocused: false,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
width: widget.isDesktop
|
width:
|
||||||
|
widget.isDesktop
|
||||||
? MediaQuery.of(context).size.width * 0.09
|
? MediaQuery.of(context).size.width * 0.09
|
||||||
: MediaQuery.of(context).size.width * 0.66,
|
: MediaQuery.of(context).size.width * 0.66,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
@ -565,13 +573,16 @@ class ForexDataState extends State<ForexData> {
|
|||||||
style: const TextStyle(fontSize: 12),
|
style: const TextStyle(fontSize: 12),
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
labelText: "Card",
|
labelText: "Card",
|
||||||
labelStyle:
|
labelStyle: TextStyle(
|
||||||
TextStyle(fontSize: 11, color: Colors.grey),
|
fontSize: 11,
|
||||||
|
color: Colors.grey,
|
||||||
|
),
|
||||||
floatingLabelBehavior: FloatingLabelBehavior.never,
|
floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
||||||
),
|
),
|
||||||
)),
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
if (errorMessages["card_percentage"] != null) ...[
|
if (errorMessages["card_percentage"] != null) ...[
|
||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
@ -581,21 +592,20 @@ class ForexDataState extends State<ForexData> {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(height: 10),
|
||||||
height: 10,
|
|
||||||
),
|
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Perdiem Amount",
|
"Perdiem Amount *",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldForexWrapper(
|
CustomTextFieldForexWrapper(
|
||||||
@ -614,7 +624,8 @@ class ForexDataState extends State<ForexData> {
|
|||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
||||||
),
|
),
|
||||||
)),
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
if (errorMessages["perdiemAmount"] != null) ...[
|
if (errorMessages["perdiemAmount"] != null) ...[
|
||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
@ -625,9 +636,7 @@ class ForexDataState extends State<ForexData> {
|
|||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(height: 15),
|
||||||
height: 15,
|
|
||||||
),
|
|
||||||
|
|
||||||
if (forexDataId != null)
|
if (forexDataId != null)
|
||||||
Row(
|
Row(
|
||||||
@ -638,7 +647,8 @@ class ForexDataState extends State<ForexData> {
|
|||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
Tooltip(
|
Tooltip(
|
||||||
message:
|
message:
|
||||||
@ -654,13 +664,10 @@ class ForexDataState extends State<ForexData> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (forexDataId != null)
|
if (forexDataId != null) SizedBox(height: 15),
|
||||||
SizedBox(
|
|
||||||
height: 15,
|
|
||||||
),
|
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
@ -697,13 +704,17 @@ class ForexDataState extends State<ForexData> {
|
|||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: Text('Save',
|
child: Text(
|
||||||
|
'Save',
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 11, color: Colors.white)),
|
fontSize: 11,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
),
|
||||||
// : SizedBox.shrink(),
|
// : SizedBox.shrink(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@ -102,7 +102,7 @@ class ForexDataListState extends State<ForexDataList> {
|
|||||||
|
|
||||||
Future<List<dynamic>> fetchGetForex() async {
|
Future<List<dynamic>> fetchGetForex() async {
|
||||||
orgId = await getOrgId();
|
orgId = await getOrgId();
|
||||||
final String apiUrlData = '$apiUrl/api/getForexPerdiemList';
|
final String apiUrlData = '$apiUrl/api/getForexPerdiemList?for=table_view';
|
||||||
|
|
||||||
final String? token = await getToken();
|
final String? token = await getToken();
|
||||||
|
|
||||||
|
|||||||
@ -21,13 +21,14 @@ class GroupData extends StatefulWidget {
|
|||||||
final int? groupId; // <-- Add this
|
final int? groupId; // <-- Add this
|
||||||
final Map<String, dynamic>? groupData;
|
final Map<String, dynamic>? groupData;
|
||||||
|
|
||||||
const GroupData(
|
const GroupData({
|
||||||
{super.key,
|
super.key,
|
||||||
required this.isDesktop,
|
required this.isDesktop,
|
||||||
this.layoutColor,
|
this.layoutColor,
|
||||||
required this.fetchGetGroup,
|
required this.fetchGetGroup,
|
||||||
this.groupId,
|
this.groupId,
|
||||||
this.groupData});
|
this.groupData,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
GroupDataState createState() => GroupDataState();
|
GroupDataState createState() => GroupDataState();
|
||||||
@ -46,7 +47,6 @@ class GroupDataState extends State<GroupData> {
|
|||||||
final Map<String, TextEditingController> controllers = {};
|
final Map<String, TextEditingController> controllers = {};
|
||||||
Map<String, String> errorMessages = {};
|
Map<String, String> errorMessages = {};
|
||||||
|
|
||||||
|
|
||||||
List<dynamic> domesticList = [];
|
List<dynamic> domesticList = [];
|
||||||
List<dynamic> internationalList = [];
|
List<dynamic> internationalList = [];
|
||||||
|
|
||||||
@ -166,7 +166,6 @@ class GroupDataState extends State<GroupData> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool validateData() {
|
bool validateData() {
|
||||||
errorMessages.clear();
|
errorMessages.clear();
|
||||||
|
|
||||||
@ -179,10 +178,7 @@ class GroupDataState extends State<GroupData> {
|
|||||||
"international_policy_name": selectedInternationalPolicyName,
|
"international_policy_name": selectedInternationalPolicyName,
|
||||||
};
|
};
|
||||||
|
|
||||||
final requiredFields = [
|
final requiredFields = ["name", "description"];
|
||||||
"name",
|
|
||||||
"description",
|
|
||||||
];
|
|
||||||
|
|
||||||
// Check validation for each field
|
// Check validation for each field
|
||||||
for (String field in requiredFields) {
|
for (String field in requiredFields) {
|
||||||
@ -240,7 +236,8 @@ class GroupDataState extends State<GroupData> {
|
|||||||
};
|
};
|
||||||
final body = jsonEncode(groupData);
|
final body = jsonEncode(groupData);
|
||||||
|
|
||||||
final response = groupDataId != null
|
final response =
|
||||||
|
groupDataId != 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);
|
||||||
|
|
||||||
@ -288,7 +285,7 @@ class GroupDataState extends State<GroupData> {
|
|||||||
// Map id to names
|
// Map id to names
|
||||||
DomesticMap = {
|
DomesticMap = {
|
||||||
for (var object in domesticList)
|
for (var object in domesticList)
|
||||||
object['policy_id'] as String: object['name'] as String
|
object['policy_id'] as String: object['name'] as String,
|
||||||
};
|
};
|
||||||
|
|
||||||
// print("domestic -- map--$DomesticMap");
|
// print("domestic -- map--$DomesticMap");
|
||||||
@ -302,7 +299,7 @@ class GroupDataState extends State<GroupData> {
|
|||||||
|
|
||||||
InternationalMap = {
|
InternationalMap = {
|
||||||
for (var item in internationalList)
|
for (var item in internationalList)
|
||||||
item['policy_id'] as String: item['name'] as String
|
item['policy_id'] as String: item['name'] as String,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Extract only id for processing
|
// Extract only id for processing
|
||||||
@ -330,20 +327,18 @@ class GroupDataState extends State<GroupData> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 2),
|
const SizedBox(height: 2),
|
||||||
Divider(
|
Divider(thickness: 0.2, color: Colors.blueGrey.shade100),
|
||||||
thickness: 0.2,
|
|
||||||
color: Colors.blueGrey.shade100,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 5),
|
const SizedBox(height: 5),
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Name",
|
"Name *",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldForexWrapper(
|
CustomTextFieldForexWrapper(
|
||||||
@ -362,7 +357,8 @@ class GroupDataState extends State<GroupData> {
|
|||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
||||||
),
|
),
|
||||||
)),
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
if (errorMessages["name"] != null) ...[
|
if (errorMessages["name"] != null) ...[
|
||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
@ -382,7 +378,8 @@ class GroupDataState extends State<GroupData> {
|
|||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldForexWrapper(
|
CustomTextFieldForexWrapper(
|
||||||
@ -391,16 +388,18 @@ class GroupDataState extends State<GroupData> {
|
|||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: DropdownSearch<String>(
|
child: DropdownSearch<String>(
|
||||||
selectedItem: InternationalMap[selectedInternationalPolicyID],
|
selectedItem:
|
||||||
|
InternationalMap[selectedInternationalPolicyID],
|
||||||
popupProps: PopupProps.menu(
|
popupProps: PopupProps.menu(
|
||||||
showSearchBox: true, // Enables search functionality
|
showSearchBox: true, // Enables search functionality
|
||||||
menuProps: const MenuProps(
|
menuProps: const MenuProps(backgroundColor: Colors.white),
|
||||||
backgroundColor: Colors.white,
|
|
||||||
),
|
|
||||||
constraints: BoxConstraints(maxHeight: 250),
|
constraints: BoxConstraints(maxHeight: 250),
|
||||||
itemBuilder: (context, item, isSelected) => Padding(
|
itemBuilder:
|
||||||
|
(context, item, isSelected) => Padding(
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(
|
||||||
horizontal: 8.0, vertical: 6.0),
|
horizontal: 8.0,
|
||||||
|
vertical: 6.0,
|
||||||
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
item,
|
item,
|
||||||
style: GoogleFonts.poppins(fontSize: 11.5),
|
style: GoogleFonts.poppins(fontSize: 11.5),
|
||||||
@ -418,12 +417,11 @@ class GroupDataState extends State<GroupData> {
|
|||||||
dropdownDecoratorProps: DropDownDecoratorProps(
|
dropdownDecoratorProps: DropDownDecoratorProps(
|
||||||
dropdownSearchDecoration: InputDecoration(
|
dropdownSearchDecoration: InputDecoration(
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding: EdgeInsets.symmetric(
|
contentPadding: EdgeInsets.symmetric(horizontal: 1),
|
||||||
horizontal: 1,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
dropdownBuilder:
|
||||||
dropdownBuilder: (context, selectedItem) => Align(
|
(context, selectedItem) => Align(
|
||||||
// Center-align selected item
|
// Center-align selected item
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: Text(
|
child: Text(
|
||||||
@ -434,7 +432,8 @@ class GroupDataState extends State<GroupData> {
|
|||||||
onChanged: (String? newValue) {
|
onChanged: (String? newValue) {
|
||||||
setState(() {
|
setState(() {
|
||||||
// Find the country_code based on selected country_name
|
// Find the country_code based on selected country_name
|
||||||
selectedInternationalPolicyID = InternationalMap.entries
|
selectedInternationalPolicyID =
|
||||||
|
InternationalMap.entries
|
||||||
.firstWhere((entry) => entry.value == newValue)
|
.firstWhere((entry) => entry.value == newValue)
|
||||||
.key;
|
.key;
|
||||||
selectedInternationalPolicyName = newValue;
|
selectedInternationalPolicyName = newValue;
|
||||||
@ -454,7 +453,8 @@ class GroupDataState extends State<GroupData> {
|
|||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldForexWrapper(
|
CustomTextFieldForexWrapper(
|
||||||
@ -466,13 +466,14 @@ class GroupDataState extends State<GroupData> {
|
|||||||
selectedItem: DomesticMap[selectedDomesticPolicyID],
|
selectedItem: DomesticMap[selectedDomesticPolicyID],
|
||||||
popupProps: PopupProps.menu(
|
popupProps: PopupProps.menu(
|
||||||
showSearchBox: true, // Enables search functionality
|
showSearchBox: true, // Enables search functionality
|
||||||
menuProps: const MenuProps(
|
menuProps: const MenuProps(backgroundColor: Colors.white),
|
||||||
backgroundColor: Colors.white,
|
|
||||||
),
|
|
||||||
constraints: BoxConstraints(maxHeight: 250),
|
constraints: BoxConstraints(maxHeight: 250),
|
||||||
itemBuilder: (context, object, isSelected) => Padding(
|
itemBuilder:
|
||||||
|
(context, object, isSelected) => Padding(
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(
|
||||||
horizontal: 8.0, vertical: 6.0),
|
horizontal: 8.0,
|
||||||
|
vertical: 6.0,
|
||||||
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
object,
|
object,
|
||||||
style: GoogleFonts.poppins(fontSize: 11.5),
|
style: GoogleFonts.poppins(fontSize: 11.5),
|
||||||
@ -490,12 +491,11 @@ class GroupDataState extends State<GroupData> {
|
|||||||
dropdownDecoratorProps: DropDownDecoratorProps(
|
dropdownDecoratorProps: DropDownDecoratorProps(
|
||||||
dropdownSearchDecoration: InputDecoration(
|
dropdownSearchDecoration: InputDecoration(
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding: EdgeInsets.symmetric(
|
contentPadding: EdgeInsets.symmetric(horizontal: 1),
|
||||||
horizontal: 1,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
dropdownBuilder:
|
||||||
dropdownBuilder: (context, selectedItem) => Align(
|
(context, selectedItem) => Align(
|
||||||
// Center-align selected item
|
// Center-align selected item
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: Text(
|
child: Text(
|
||||||
@ -506,7 +506,8 @@ class GroupDataState extends State<GroupData> {
|
|||||||
onChanged: (String? newValue) {
|
onChanged: (String? newValue) {
|
||||||
setState(() {
|
setState(() {
|
||||||
// Find the country_code based on selected country_name
|
// Find the country_code based on selected country_name
|
||||||
selectedDomesticPolicyID = DomesticMap.entries
|
selectedDomesticPolicyID =
|
||||||
|
DomesticMap.entries
|
||||||
.firstWhere((entry) => entry.value == newValue)
|
.firstWhere((entry) => entry.value == newValue)
|
||||||
.key;
|
.key;
|
||||||
selectedDomesticPolicyName = newValue;
|
selectedDomesticPolicyName = newValue;
|
||||||
@ -522,11 +523,12 @@ class GroupDataState extends State<GroupData> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Description",
|
"Description *",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldForexWrapper(
|
CustomTextFieldForexWrapper(
|
||||||
@ -559,9 +561,7 @@ class GroupDataState extends State<GroupData> {
|
|||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(height: 15),
|
||||||
height: 15,
|
|
||||||
),
|
|
||||||
if (groupDataId != null)
|
if (groupDataId != null)
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
@ -571,7 +571,8 @@ class GroupDataState extends State<GroupData> {
|
|||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
Tooltip(
|
Tooltip(
|
||||||
message:
|
message:
|
||||||
@ -587,13 +588,10 @@ class GroupDataState extends State<GroupData> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (groupDataId != null)
|
if (groupDataId != null) SizedBox(height: 15),
|
||||||
SizedBox(
|
|
||||||
height: 15,
|
|
||||||
),
|
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
@ -630,13 +628,17 @@ class GroupDataState extends State<GroupData> {
|
|||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: Text('Save',
|
child: Text(
|
||||||
|
'Save',
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 11, color: Colors.white)),
|
fontSize: 11,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
),
|
||||||
// : SizedBox.shrink(),
|
// : SizedBox.shrink(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@ -102,32 +102,30 @@ class _GroupListState extends State<GroupList> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void filterGroups(String query) {
|
void filterGroups(String query) {
|
||||||
print("allGroups before filtering: $query");
|
|
||||||
final lowerQuery = query.toLowerCase();
|
final lowerQuery = query.toLowerCase();
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
filteredGroups =
|
filteredGroups =
|
||||||
allGroups.where((group) {
|
allGroups.where((object) {
|
||||||
return (group['name']?.toLowerCase().contains(lowerQuery) ??
|
final isActiveStatus =
|
||||||
|
object['is_active'] == "1" ? "active" : "inactive";
|
||||||
|
return (object['group_id']?.toLowerCase().contains(lowerQuery) ??
|
||||||
false) ||
|
false) ||
|
||||||
(group['domestic_policy_name']?.toLowerCase().contains(
|
(object['name']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||||
|
(object['domestic_policy_name']?.toLowerCase().contains(
|
||||||
lowerQuery,
|
lowerQuery,
|
||||||
) ??
|
) ??
|
||||||
false)(
|
false) ||
|
||||||
group['international_policy_name']?.toLowerCase().contains(
|
(object['international_policy_name']?.toLowerCase().contains(
|
||||||
lowerQuery,
|
lowerQuery,
|
||||||
) ??
|
) ??
|
||||||
false,
|
|
||||||
) ||
|
|
||||||
(group['description']?.toLowerCase().contains(lowerQuery) ??
|
|
||||||
false) ||
|
false) ||
|
||||||
(group['is_active']?.toLowerCase().contains(lowerQuery) ??
|
(object['description']?.toLowerCase().contains(lowerQuery) ??
|
||||||
false);
|
false) ||
|
||||||
|
(isActiveStatus.contains(lowerQuery));
|
||||||
}).toList();
|
}).toList();
|
||||||
currentPage = 0;
|
currentPage = 0;
|
||||||
});
|
});
|
||||||
|
print("filteredGroups: $filteredGroups");
|
||||||
print("filtered: $filteredGroups");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleActiveStatus(
|
void handleActiveStatus(
|
||||||
@ -287,7 +285,7 @@ class _GroupListState extends State<GroupList> {
|
|||||||
controller: searchController,
|
controller: searchController,
|
||||||
onChanged: filterGroups,
|
onChanged: filterGroups,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: "Search for a Group",
|
hintText: "Search ...",
|
||||||
hintStyle: TextStyle(
|
hintStyle: TextStyle(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
color: Color(0xFF9E9DBD),
|
color: Color(0xFF9E9DBD),
|
||||||
@ -385,7 +383,7 @@ class _GroupListState extends State<GroupList> {
|
|||||||
controller: searchController,
|
controller: searchController,
|
||||||
onChanged: filterGroups,
|
onChanged: filterGroups,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: "Search for a Group",
|
hintText: "Search ...",
|
||||||
hintStyle: TextStyle(
|
hintStyle: TextStyle(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
color: Color(0xFF9E9DBD),
|
color: Color(0xFF9E9DBD),
|
||||||
@ -924,12 +922,35 @@ class _GroupListState extends State<GroupList> {
|
|||||||
Expanded(
|
Expanded(
|
||||||
child:
|
child:
|
||||||
isDesktop
|
isDesktop
|
||||||
? SingleChildScrollView(
|
? (searchController.text.isNotEmpty &&
|
||||||
scrollDirection: Axis.vertical,
|
filteredGroups.isEmpty
|
||||||
child: table, // <-- your existing table
|
? Center(
|
||||||
)
|
child: Text(
|
||||||
: buildMobileCardView(paginatedGroup),
|
"No matches found",
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 14,
|
||||||
|
color: Colors.grey,
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: SingleChildScrollView(
|
||||||
|
scrollDirection: Axis.vertical,
|
||||||
|
child: table,
|
||||||
|
))
|
||||||
|
: (searchController.text.isNotEmpty &&
|
||||||
|
paginatedGroup.isEmpty
|
||||||
|
? Center(
|
||||||
|
child: Text(
|
||||||
|
"No matches found",
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 14,
|
||||||
|
color: Colors.grey,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: buildMobileCardView(paginatedGroup)),
|
||||||
|
),
|
||||||
|
|
||||||
PaginationControls(
|
PaginationControls(
|
||||||
currentPage: currentPage,
|
currentPage: currentPage,
|
||||||
itemsPerPage: itemsPerPage,
|
itemsPerPage: itemsPerPage,
|
||||||
|
|||||||
@ -20,13 +20,14 @@ class HotelsData extends StatefulWidget {
|
|||||||
final int? hotelsId; // <-- Add this
|
final int? hotelsId; // <-- Add this
|
||||||
final Map<String, dynamic>? hotelsData;
|
final Map<String, dynamic>? hotelsData;
|
||||||
|
|
||||||
const HotelsData(
|
const HotelsData({
|
||||||
{super.key,
|
super.key,
|
||||||
required this.isDesktop,
|
required this.isDesktop,
|
||||||
this.layoutColor,
|
this.layoutColor,
|
||||||
required this.fetchGetHotels,
|
required this.fetchGetHotels,
|
||||||
this.hotelsId,
|
this.hotelsId,
|
||||||
this.hotelsData});
|
this.hotelsData,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
HotelsDataState createState() => HotelsDataState();
|
HotelsDataState createState() => HotelsDataState();
|
||||||
@ -110,7 +111,8 @@ class HotelsDataState extends State<HotelsData> {
|
|||||||
if (data == null) return;
|
if (data == null) return;
|
||||||
setState(() {
|
setState(() {
|
||||||
selectedCountry = data['country_code']; // For dropdown
|
selectedCountry = data['country_code']; // For dropdown
|
||||||
selectedCountryName = data['country_name']; // For dropdown label or display
|
selectedCountryName =
|
||||||
|
data['country_name']; // For dropdown label or display
|
||||||
controllers['city']?.text = data['city'] ?? '';
|
controllers['city']?.text = data['city'] ?? '';
|
||||||
controllers['hotel_chain']?.text = data['hotel_chain'] ?? '';
|
controllers['hotel_chain']?.text = data['hotel_chain'] ?? '';
|
||||||
controllers['hotel_name']?.text = data['hotel_name'] ?? '';
|
controllers['hotel_name']?.text = data['hotel_name'] ?? '';
|
||||||
@ -148,7 +150,12 @@ class HotelsDataState extends State<HotelsData> {
|
|||||||
"city": controllers["city"]?.text,
|
"city": controllers["city"]?.text,
|
||||||
};
|
};
|
||||||
|
|
||||||
final requiredFields = ["hotel_name","hotel_chain","country_code","city"];
|
final requiredFields = [
|
||||||
|
"hotel_name",
|
||||||
|
"hotel_chain",
|
||||||
|
"country_code",
|
||||||
|
"city",
|
||||||
|
];
|
||||||
|
|
||||||
// Check validation for each field
|
// Check validation for each field
|
||||||
for (String field in requiredFields) {
|
for (String field in requiredFields) {
|
||||||
@ -174,7 +181,6 @@ class HotelsDataState extends State<HotelsData> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> postHotelsData({int isActive = 1}) async {
|
Future<void> postHotelsData({int isActive = 1}) async {
|
||||||
|
|
||||||
final hotelsData = hotels_Details();
|
final hotelsData = hotels_Details();
|
||||||
|
|
||||||
final String apiUrldata;
|
final String apiUrldata;
|
||||||
@ -184,16 +190,20 @@ class HotelsDataState extends State<HotelsData> {
|
|||||||
apiUrldata = '$apiUrl/api/updateHotels/$hotelsDataId';
|
apiUrldata = '$apiUrl/api/updateHotels/$hotelsDataId';
|
||||||
hotelsData["hotel_id"] = hotelsDataId.toString();
|
hotelsData["hotel_id"] = hotelsDataId.toString();
|
||||||
hotelsData["updated_by"] = userId;
|
hotelsData["updated_by"] = userId;
|
||||||
(hotelsData.containsKey("created_by")) ? hotelsData.remove("created_by") : '' ;
|
(hotelsData.containsKey("created_by"))
|
||||||
(hotelsData.containsKey("country_name")) ? hotelsData.remove("country_name") : '' ;
|
? hotelsData.remove("created_by")
|
||||||
|
: '';
|
||||||
|
(hotelsData.containsKey("country_name"))
|
||||||
|
? hotelsData.remove("country_name")
|
||||||
|
: '';
|
||||||
} else {
|
} else {
|
||||||
print("for add Hotel id - null");
|
print("for add Hotel id - null");
|
||||||
apiUrldata = '$apiUrl/api/createHotels';
|
apiUrldata = '$apiUrl/api/createHotels';
|
||||||
print("called apiUrl - $apiUrldata");
|
print("called apiUrl - $apiUrldata");
|
||||||
hotelsData["created_by"] = userId;
|
hotelsData["created_by"] = userId;
|
||||||
(hotelsData.containsKey("country_name")) ? hotelsData.remove("country_name") : '' ;
|
(hotelsData.containsKey("country_name"))
|
||||||
|
? hotelsData.remove("country_name")
|
||||||
|
: '';
|
||||||
}
|
}
|
||||||
|
|
||||||
final token = await getToken(); // Fetch token
|
final token = await getToken(); // Fetch token
|
||||||
@ -210,7 +220,8 @@ class HotelsDataState extends State<HotelsData> {
|
|||||||
};
|
};
|
||||||
final body = jsonEncode(hotelsData);
|
final body = jsonEncode(hotelsData);
|
||||||
|
|
||||||
final response = hotelsDataId != null
|
final response =
|
||||||
|
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);
|
||||||
|
|
||||||
@ -254,7 +265,7 @@ class HotelsDataState extends State<HotelsData> {
|
|||||||
// Map country codes to country names
|
// Map country codes to country names
|
||||||
countryMap = {
|
countryMap = {
|
||||||
for (var item in countryList)
|
for (var item in countryList)
|
||||||
item['country_code'] as String: item['country_name'] as String
|
item['country_code'] as String: item['country_name'] as String,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Extract only country codes for processing
|
// Extract only country codes for processing
|
||||||
@ -281,20 +292,18 @@ class HotelsDataState extends State<HotelsData> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 2),
|
const SizedBox(height: 2),
|
||||||
Divider(
|
Divider(thickness: 0.2, color: Colors.blueGrey.shade100),
|
||||||
thickness: 0.2,
|
|
||||||
color: Colors.blueGrey.shade100,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Hotel Name",
|
"Hotel Name *",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldForexWrapper(
|
CustomTextFieldForexWrapper(
|
||||||
@ -313,7 +322,8 @@ class HotelsDataState extends State<HotelsData> {
|
|||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
||||||
),
|
),
|
||||||
)),
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
if (errorMessages["hotel_name"] != null) ...[
|
if (errorMessages["hotel_name"] != null) ...[
|
||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
@ -329,11 +339,12 @@ class HotelsDataState extends State<HotelsData> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Hotel Chain",
|
"Hotel Chain *",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldForexWrapper(
|
CustomTextFieldForexWrapper(
|
||||||
@ -352,7 +363,8 @@ class HotelsDataState extends State<HotelsData> {
|
|||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
||||||
),
|
),
|
||||||
)),
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
if (errorMessages["hotel_chain"] != null) ...[
|
if (errorMessages["hotel_chain"] != null) ...[
|
||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
@ -363,16 +375,104 @@ class HotelsDataState extends State<HotelsData> {
|
|||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(height: 10),
|
|
||||||
|
// - It has been observed that many of the dropdowns have overlapping issues, causing label names to be hidden - just copied searchable dropdown - still not completed (user mangement screen only ) master page except policy - my trips - flight taxi train insurance, visa misscenllo color white size padding data
|
||||||
|
// - Delete option is not working in the policy list page - completed
|
||||||
|
// - Label Names for all the modules should be set bold as it is looking like normal text in user management compared to trips page - completed
|
||||||
|
// - In the masters org mangement search option not working for traveller - particular 4 master page - - issues occur - commpleted - email master working fine, traveller master working fine, amount master working fine, group - completed
|
||||||
|
// - QC- Authentication - - completed - ask to check
|
||||||
|
const SizedBox(height: 10),
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"City",
|
"Country *",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: 5),
|
||||||
|
CustomTextFieldForexWrapper(
|
||||||
|
isFocused: false,
|
||||||
|
isDesktop: widget.isDesktop,
|
||||||
|
child: SizedBox(
|
||||||
|
height: 40,
|
||||||
|
child: DropdownSearch<String>(
|
||||||
|
selectedItem: countryMap[selectedCountry],
|
||||||
|
popupProps: PopupProps.menu(
|
||||||
|
showSearchBox: true, // Enables search functionality
|
||||||
|
menuProps: const MenuProps(backgroundColor: Colors.white),
|
||||||
|
constraints: BoxConstraints(maxHeight: 250),
|
||||||
|
itemBuilder:
|
||||||
|
(context, item, isSelected) => Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 8.0,
|
||||||
|
vertical: 6.0,
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
item,
|
||||||
|
style: GoogleFonts.poppins(fontSize: 11.5),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
searchFieldProps: TextFieldProps(
|
||||||
|
decoration: InputDecoration(
|
||||||
|
hintText: "Search Country...",
|
||||||
|
hintStyle: GoogleFonts.poppins(fontSize: 11),
|
||||||
|
contentPadding: EdgeInsets.symmetric(horizontal: 4),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
items: countryMap.values.toList(),
|
||||||
|
dropdownDecoratorProps: DropDownDecoratorProps(
|
||||||
|
dropdownSearchDecoration: InputDecoration(
|
||||||
|
border: InputBorder.none,
|
||||||
|
contentPadding: EdgeInsets.symmetric(horizontal: 1),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
dropdownBuilder:
|
||||||
|
(context, selectedItem) => Align(
|
||||||
|
// Center-align selected item
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
child: Text(
|
||||||
|
selectedItem ?? "Select Country",
|
||||||
|
style: GoogleFonts.poppins(fontSize: 11),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onChanged: (String? newValue) {
|
||||||
|
setState(() {
|
||||||
|
// Find the country_code based on selected country_name
|
||||||
|
selectedCountry =
|
||||||
|
countryMap.entries
|
||||||
|
.firstWhere((entry) => entry.value == newValue)
|
||||||
|
.key;
|
||||||
|
selectedCountryName = newValue;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (errorMessages["country_code"] != null) ...[
|
||||||
|
SizedBox(height: 5), // Space before error message
|
||||||
|
Text(
|
||||||
|
errorMessages["country_code"]!,
|
||||||
|
style: TextStyle(color: Colors.red, fontSize: 12),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"City *",
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldForexWrapper(
|
CustomTextFieldForexWrapper(
|
||||||
@ -391,7 +491,8 @@ class HotelsDataState extends State<HotelsData> {
|
|||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
||||||
),
|
),
|
||||||
)),
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
if (errorMessages["city"] != null) ...[
|
if (errorMessages["city"] != null) ...[
|
||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
@ -402,86 +503,7 @@ class HotelsDataState extends State<HotelsData> {
|
|||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 10),
|
SizedBox(height: 10),
|
||||||
Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
"Country",
|
|
||||||
style: GoogleFonts.poppins(
|
|
||||||
fontSize: 12,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
color: Color(0xFF575A74)),
|
|
||||||
),
|
|
||||||
SizedBox(height: 5),
|
|
||||||
CustomTextFieldForexWrapper(
|
|
||||||
isFocused: false,
|
|
||||||
isDesktop: widget.isDesktop,
|
|
||||||
child: SizedBox(
|
|
||||||
height: 40,
|
|
||||||
child: DropdownSearch<String>(
|
|
||||||
selectedItem: countryMap[selectedCountry],
|
|
||||||
popupProps: PopupProps.menu(
|
|
||||||
showSearchBox: true, // Enables search functionality
|
|
||||||
menuProps: const MenuProps(
|
|
||||||
backgroundColor: Colors.white,
|
|
||||||
),
|
|
||||||
constraints: BoxConstraints(maxHeight: 250),
|
|
||||||
itemBuilder: (context, item, isSelected) => Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
horizontal: 8.0, vertical: 6.0),
|
|
||||||
child: Text(
|
|
||||||
item,
|
|
||||||
style: GoogleFonts.poppins(fontSize: 11.5),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
searchFieldProps: TextFieldProps(
|
|
||||||
decoration: InputDecoration(
|
|
||||||
hintText: "Search Country...",
|
|
||||||
hintStyle: GoogleFonts.poppins(fontSize: 11),
|
|
||||||
contentPadding: EdgeInsets.symmetric(horizontal: 4),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
items: countryMap.values.toList(),
|
|
||||||
dropdownDecoratorProps: DropDownDecoratorProps(
|
|
||||||
dropdownSearchDecoration: InputDecoration(
|
|
||||||
border: InputBorder.none,
|
|
||||||
contentPadding: EdgeInsets.symmetric(
|
|
||||||
horizontal: 1,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
dropdownBuilder: (context, selectedItem) => Align(
|
|
||||||
// Center-align selected item
|
|
||||||
alignment: Alignment.centerLeft,
|
|
||||||
child: Text(
|
|
||||||
selectedItem ?? "Select Country",
|
|
||||||
style: GoogleFonts.poppins(fontSize: 11),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
onChanged: (String? newValue) {
|
|
||||||
setState(() {
|
|
||||||
// Find the country_code based on selected country_name
|
|
||||||
selectedCountry = countryMap.entries
|
|
||||||
.firstWhere((entry) => entry.value == newValue)
|
|
||||||
.key;
|
|
||||||
selectedCountryName = newValue;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (errorMessages["country_code"] != null) ...[
|
|
||||||
SizedBox(height: 5), // Space before error message
|
|
||||||
Text(
|
|
||||||
errorMessages["country_code"]!,
|
|
||||||
style: TextStyle(color: Colors.red, fontSize: 12),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
],
|
|
||||||
),
|
|
||||||
SizedBox( height: 15 ),
|
|
||||||
// if (isDesktop)SizedBox(width: 8,) else SizedBox(height: 8,),
|
// if (isDesktop)SizedBox(width: 8,) else SizedBox(height: 8,),
|
||||||
if (hotelsDataId != null)
|
if (hotelsDataId != null)
|
||||||
Row(
|
Row(
|
||||||
@ -492,7 +514,8 @@ class HotelsDataState extends State<HotelsData> {
|
|||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
Tooltip(
|
Tooltip(
|
||||||
message:
|
message:
|
||||||
@ -508,13 +531,10 @@ class HotelsDataState extends State<HotelsData> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (hotelsDataId != null)
|
if (hotelsDataId != null) SizedBox(height: 15),
|
||||||
SizedBox(
|
|
||||||
height: 15,
|
|
||||||
),
|
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
@ -551,13 +571,17 @@ class HotelsDataState extends State<HotelsData> {
|
|||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: Text('Save',
|
child: Text(
|
||||||
|
'Save',
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 11, color: Colors.white)),
|
fontSize: 11,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
),
|
||||||
// : SizedBox.shrink(),
|
// : SizedBox.shrink(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@ -102,7 +102,7 @@ class HotelsDataListState extends State<HotelsDataList> {
|
|||||||
|
|
||||||
Future<List<dynamic>> fetchGetHotels() async {
|
Future<List<dynamic>> fetchGetHotels() async {
|
||||||
orgId = await getOrgId();
|
orgId = await getOrgId();
|
||||||
final String apiUrlData = '$apiUrl/api/getHotels';
|
final String apiUrlData = '$apiUrl/api/getHotels?for=table_view';
|
||||||
|
|
||||||
final String? token = await getToken();
|
final String? token = await getToken();
|
||||||
|
|
||||||
@ -646,7 +646,7 @@ class HotelsDataListState extends State<HotelsDataList> {
|
|||||||
color:
|
color:
|
||||||
hotels['is_active'] == "1"
|
hotels['is_active'] == "1"
|
||||||
? Colors.green
|
? Colors.green
|
||||||
: Colors.red,
|
: Colors.grey,
|
||||||
),
|
),
|
||||||
softWrap: true,
|
softWrap: true,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
|
|||||||
@ -21,8 +21,8 @@ class FlightScreen extends StatefulWidget {
|
|||||||
final Map<String, dynamic>? selectedItem;
|
final Map<String, dynamic>? selectedItem;
|
||||||
final ValueNotifier<String?> tripTypeNotifier;
|
final ValueNotifier<String?> tripTypeNotifier;
|
||||||
|
|
||||||
FlightScreen(
|
FlightScreen({
|
||||||
{Key? key,
|
Key? key,
|
||||||
required this.apiData,
|
required this.apiData,
|
||||||
required this.loginUser,
|
required this.loginUser,
|
||||||
required this.onClose,
|
required this.onClose,
|
||||||
@ -32,8 +32,8 @@ class FlightScreen extends StatefulWidget {
|
|||||||
required this.hasAction,
|
required this.hasAction,
|
||||||
this.tripType,
|
this.tripType,
|
||||||
required this.tripTypeNotifier,
|
required this.tripTypeNotifier,
|
||||||
this.apiDataForClass})
|
this.apiDataForClass,
|
||||||
: super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FlightScreenState createState() => FlightScreenState();
|
FlightScreenState createState() => FlightScreenState();
|
||||||
@ -70,7 +70,7 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
"_date",
|
"_date",
|
||||||
"_visa",
|
"_visa",
|
||||||
"_time",
|
"_time",
|
||||||
"_comments"
|
"_comments",
|
||||||
];
|
];
|
||||||
|
|
||||||
Map<String, FocusNode> focusNodes = {};
|
Map<String, FocusNode> focusNodes = {};
|
||||||
@ -148,14 +148,18 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
|
|
||||||
// Loop through each row and add listeners to clear errors
|
// Loop through each row and add listeners to clear errors
|
||||||
for (int i = 1; i <= rowCount; i++) {
|
for (int i = 1; i <= rowCount; i++) {
|
||||||
textControllers["_from${i}Controller"]
|
textControllers["_from${i}Controller"]?.addListener(
|
||||||
?.addListener(() => _clearError("from_place_$i"));
|
() => _clearError("from_place_$i"),
|
||||||
textControllers["_to${i}Controller"]
|
);
|
||||||
?.addListener(() => _clearError("to_place_$i"));
|
textControllers["_to${i}Controller"]?.addListener(
|
||||||
textControllers["_date${i}Controller"]
|
() => _clearError("to_place_$i"),
|
||||||
?.addListener(() => _clearError("date_$i"));
|
);
|
||||||
textControllers["_time${i}Controller"]
|
textControllers["_date${i}Controller"]?.addListener(
|
||||||
?.addListener(() => _clearError("time_$i"));
|
() => _clearError("date_$i"),
|
||||||
|
);
|
||||||
|
textControllers["_time${i}Controller"]?.addListener(
|
||||||
|
() => _clearError("time_$i"),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
// loadCountryList();
|
// loadCountryList();
|
||||||
|
|
||||||
@ -178,17 +182,16 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Map<String, String?> getFlightTripDateRange(
|
Map<String, String?> getFlightTripDateRange(
|
||||||
List<Map<String, dynamic>> flightData) {
|
List<Map<String, dynamic>> flightData,
|
||||||
final allTrips = flightData
|
) {
|
||||||
|
final allTrips =
|
||||||
|
flightData
|
||||||
.expand((flight) => flight['trips'] ?? [])
|
.expand((flight) => flight['trips'] ?? [])
|
||||||
.whereType<Map<String, dynamic>>()
|
.whereType<Map<String, dynamic>>()
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
if (allTrips.isEmpty) {
|
if (allTrips.isEmpty) {
|
||||||
return {
|
return {'firstTripDate': null, 'lastTripDate': null};
|
||||||
'firstTripDate': null,
|
|
||||||
'lastTripDate': null,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
allTrips.sort((a, b) {
|
allTrips.sort((a, b) {
|
||||||
@ -293,7 +296,8 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
print("Text Controllers KeysII: ${textControllers.keys.toList()}");
|
print("Text Controllers KeysII: ${textControllers.keys.toList()}");
|
||||||
|
|
||||||
// Determine the row count based on selectedTripType
|
// Determine the row count based on selectedTripType
|
||||||
int rowCount = selectedTripType == "Roundtrip"
|
int rowCount =
|
||||||
|
selectedTripType == "Roundtrip"
|
||||||
? 2
|
? 2
|
||||||
: selectedTripType == "Multitrip"
|
: selectedTripType == "Multitrip"
|
||||||
? multiTripRowCount
|
? multiTripRowCount
|
||||||
@ -476,10 +480,12 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
// TextEditingController(text: trip["from_place"]);
|
// TextEditingController(text: trip["from_place"]);
|
||||||
// textControllers["_to${index}Controller"] =
|
// textControllers["_to${index}Controller"] =
|
||||||
// TextEditingController(text: trip["to_place"]);
|
// TextEditingController(text: trip["to_place"]);
|
||||||
textControllers["_date${index}Controller"] =
|
textControllers["_date${index}Controller"] = TextEditingController(
|
||||||
TextEditingController(text: trip["date"]);
|
text: trip["date"],
|
||||||
textControllers["_time${index}Controller"] =
|
);
|
||||||
TextEditingController(text: trip["time"]);
|
textControllers["_time${index}Controller"] = TextEditingController(
|
||||||
|
text: trip["time"],
|
||||||
|
);
|
||||||
|
|
||||||
// Check if editing and flight_trip_id exists for this trip
|
// Check if editing and flight_trip_id exists for this trip
|
||||||
if (widget.selectedItem != null &&
|
if (widget.selectedItem != null &&
|
||||||
@ -541,10 +547,9 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
final currDateTime = format.parse("$currDateStr $currTimeStr");
|
final currDateTime = format.parse("$currDateStr $currTimeStr");
|
||||||
|
|
||||||
if (!currDateTime.isAfter(prevDateTime)) {
|
if (!currDateTime.isAfter(prevDateTime)) {
|
||||||
errorMessages["time_$index"] = "Must be after previous time";
|
errorMessages["time_$index"] = "30 mins gap required";
|
||||||
} else if (currDateTime.difference(prevDateTime).inMinutes < 30) {
|
} else if (currDateTime.difference(prevDateTime).inMinutes < 30) {
|
||||||
errorMessages["time_$index"] =
|
errorMessages["time_$index"] = "30 mins gap required";
|
||||||
"Must be least 30 mins after previous time";
|
|
||||||
} else {
|
} else {
|
||||||
errorMessages.remove("time_$index");
|
errorMessages.remove("time_$index");
|
||||||
}
|
}
|
||||||
@ -665,14 +670,15 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ResponsiveBuilder(builder: (context, sizingInfo) {
|
return ResponsiveBuilder(
|
||||||
|
builder: (context, sizingInfo) {
|
||||||
bool isMobile = sizingInfo.isMobile;
|
bool isMobile = sizingInfo.isMobile;
|
||||||
bool isDesktop = sizingInfo.deviceScreenType == DeviceScreenType.desktop;
|
bool isDesktop =
|
||||||
|
sizingInfo.deviceScreenType == DeviceScreenType.desktop;
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
// color: Color(0xFFF4F4FB),
|
// color: Color(0xFFF4F4FB),
|
||||||
// color: Color(0xFFF9F9F9), // Slightly lighter than white
|
// color: Color(0xFFF9F9F9), // Slightly lighter than white
|
||||||
|
|
||||||
child: Form(
|
child: Form(
|
||||||
key: _formKey,
|
key: _formKey,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
@ -684,13 +690,14 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
child: Center(
|
child: Center(
|
||||||
child: Column(children: _buildAccomadtionForm(isDesktop)),
|
child: Column(children: _buildAccomadtionForm(isDesktop)),
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
});
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> _buildAccomadtionForm(bool isDesktop) {
|
List<Widget> _buildAccomadtionForm(bool isDesktop) {
|
||||||
@ -703,14 +710,14 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
|
|
||||||
List<List<Widget>> rowBuilders = [
|
List<List<Widget>> rowBuilders = [
|
||||||
// _builClassType(isDesktop, 1),
|
// _builClassType(isDesktop, 1),
|
||||||
_buildSecondRow(isDesktop, 1)
|
_buildSecondRow(isDesktop, 1),
|
||||||
];
|
];
|
||||||
|
|
||||||
List<List<Widget>> rowRoundBuilders = [
|
List<List<Widget>> rowRoundBuilders = [
|
||||||
// _builClassType(isDesktop, 1),
|
// _builClassType(isDesktop, 1),
|
||||||
_buildSecondRow(isDesktop, 1),
|
_buildSecondRow(isDesktop, 1),
|
||||||
// _builClassType(isDesktop, 2),
|
// _builClassType(isDesktop, 2),
|
||||||
_buildSecondRow(isDesktop, 2)
|
_buildSecondRow(isDesktop, 2),
|
||||||
];
|
];
|
||||||
|
|
||||||
print("Trip Type Selected: $selectedTripType");
|
print("Trip Type Selected: $selectedTripType");
|
||||||
@ -740,7 +747,6 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
// ...List.generate(multiTripRowCount, (index) =>
|
// ...List.generate(multiTripRowCount, (index) =>
|
||||||
// buildResponsiveRow(_builClassType(isDesktop, index + 1) + _buildSecondRow(isDesktop, index + 1))
|
// buildResponsiveRow(_builClassType(isDesktop, index + 1) + _buildSecondRow(isDesktop, index + 1))
|
||||||
// ).expand((row) => row),
|
// ).expand((row) => row),
|
||||||
|
|
||||||
if (selectedTripType == "Multitrip")
|
if (selectedTripType == "Multitrip")
|
||||||
Align(
|
Align(
|
||||||
alignment: Alignment.centerRight,
|
alignment: Alignment.centerRight,
|
||||||
@ -811,39 +817,40 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
isDesktop
|
isDesktop
|
||||||
? Row(children: _buildTripType(isDesktop))
|
? Row(children: _buildTripType(isDesktop))
|
||||||
: Column(children: _buildTripType(isDesktop))
|
: Column(children: _buildTripType(isDesktop)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (isDesktop)
|
if (isDesktop) Spacer() else SizedBox(height: 8),
|
||||||
Spacer()
|
|
||||||
else
|
|
||||||
SizedBox(
|
|
||||||
height: 8,
|
|
||||||
),
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> _buildTripType(bool isDesktop) {
|
List<Widget> _buildTripType(bool isDesktop) {
|
||||||
List<dynamic> purposeList = widget.apiData?['flight_trip_type'] ?? [];
|
List<dynamic> purposeList = widget.apiData?['flight_trip_type'] ?? [];
|
||||||
|
|
||||||
List<DropdownMenuItem<String>> dropdownItems = purposeList
|
List<DropdownMenuItem<String>> dropdownItems =
|
||||||
.map((item) => DropdownMenuItem<String>(
|
purposeList
|
||||||
|
.map(
|
||||||
|
(item) => DropdownMenuItem<String>(
|
||||||
value: item['dropdown_value'],
|
value: item['dropdown_value'],
|
||||||
child: Text(item['dropdown_value']),
|
child: Text(item['dropdown_value']),
|
||||||
))
|
),
|
||||||
|
)
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
if (dropdownItems.isEmpty) {
|
if (dropdownItems.isEmpty) {
|
||||||
dropdownItems.add(
|
dropdownItems.add(
|
||||||
DropdownMenuItem<String>(
|
DropdownMenuItem<String>(
|
||||||
value: null,
|
value: null,
|
||||||
child: Text("No options available",
|
child: Text(
|
||||||
style: TextStyle(color: Colors.grey)),
|
"No options available",
|
||||||
|
style: TextStyle(color: Colors.grey),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -858,7 +865,8 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
height: 40,
|
height: 40,
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
child: DropdownSearch<String>(
|
child: DropdownSearch<String>(
|
||||||
items: purposeList
|
items:
|
||||||
|
purposeList
|
||||||
.map((item) => item['dropdown_value'] as String)
|
.map((item) => item['dropdown_value'] as String)
|
||||||
.toList(),
|
.toList(),
|
||||||
dropdownDecoratorProps: DropDownDecoratorProps(
|
dropdownDecoratorProps: DropDownDecoratorProps(
|
||||||
@ -876,11 +884,13 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
errorMessages.clear();
|
errorMessages.clear();
|
||||||
});
|
});
|
||||||
print(
|
print(
|
||||||
"Updating form data: Flight -> trip_type -> $selectedTripType");
|
"Updating form data: Flight -> trip_type -> $selectedTripType",
|
||||||
|
);
|
||||||
_initializeFields();
|
_initializeFields();
|
||||||
},
|
},
|
||||||
selectedItem: selectedTripType,
|
selectedItem: selectedTripType,
|
||||||
dropdownBuilder: (context, selectedItem) => Align(
|
dropdownBuilder:
|
||||||
|
(context, selectedItem) => Align(
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: Text(
|
child: Text(
|
||||||
selectedItem ?? "Select",
|
selectedItem ?? "Select",
|
||||||
@ -890,13 +900,17 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
popupProps: PopupProps.menu(
|
popupProps: PopupProps.menu(
|
||||||
constraints: BoxConstraints(maxHeight: 100),
|
constraints: BoxConstraints(maxHeight: 100),
|
||||||
menuProps: MenuProps(backgroundColor: Colors.white),
|
menuProps: MenuProps(backgroundColor: Colors.white),
|
||||||
itemBuilder: (context, item, isSelected) => Padding(
|
itemBuilder:
|
||||||
padding:
|
(context, item, isSelected) => Padding(
|
||||||
const EdgeInsets.symmetric(horizontal: 8.0, vertical: 6.0),
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 8.0,
|
||||||
|
vertical: 6.0,
|
||||||
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
item,
|
item,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 13), // Custom text size for dropdown items
|
fontSize: 13,
|
||||||
|
), // Custom text size for dropdown items
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -999,9 +1013,9 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
return [
|
return [
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.all(10),
|
padding: const EdgeInsets.all(10),
|
||||||
|
|
||||||
// padding: const EdgeInsets.only(left: 10, right: 10),
|
// padding: const EdgeInsets.only(left: 10, right: 10),
|
||||||
// color: Colors.white,
|
// color: Colors.white,
|
||||||
|
|
||||||
child: Text(
|
child: Text(
|
||||||
"Trip ${index}",
|
"Trip ${index}",
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
@ -1012,17 +1026,14 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: isDesktop
|
width:
|
||||||
|
isDesktop
|
||||||
? MediaQuery.of(context).size.width * 0.58
|
? MediaQuery.of(context).size.width * 0.58
|
||||||
: 80, // Ensure full width
|
: 80, // Ensure full width
|
||||||
child: Stack(
|
child: Stack(
|
||||||
alignment: Alignment.center, // Centers the icon
|
alignment: Alignment.center, // Centers the icon
|
||||||
children: [
|
children: [
|
||||||
Divider(
|
Divider(color: Color(0xFF8B8FB2), thickness: 0.5, height: 20),
|
||||||
color: Color(0xFF8B8FB2),
|
|
||||||
thickness: 0.5,
|
|
||||||
height: 20,
|
|
||||||
),
|
|
||||||
Container(
|
Container(
|
||||||
// padding: EdgeInsets.all(4),
|
// padding: EdgeInsets.all(4),
|
||||||
color: Colors.white, // Background to avoid overlapping
|
color: Colors.white, // Background to avoid overlapping
|
||||||
@ -1064,7 +1075,6 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
// ],
|
// ],
|
||||||
// ),
|
// ),
|
||||||
// ),
|
// ),
|
||||||
|
|
||||||
Container(
|
Container(
|
||||||
// color: Colors.white,
|
// color: Colors.white,
|
||||||
// padding: const EdgeInsets.only(left: 10, right: 10),
|
// padding: const EdgeInsets.only(left: 10, right: 10),
|
||||||
@ -1076,7 +1086,7 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
color: Colors.blueAccent,
|
color: Colors.blueAccent,
|
||||||
iconSize: 20,
|
iconSize: 20,
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1085,19 +1095,24 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
|
|
||||||
List<dynamic> purposeList = widget.apiDataForClass?['flight_class'] ?? [];
|
List<dynamic> purposeList = widget.apiDataForClass?['flight_class'] ?? [];
|
||||||
|
|
||||||
List<DropdownMenuItem<String>> dropdownItems = purposeList
|
List<DropdownMenuItem<String>> dropdownItems =
|
||||||
.map((item) => DropdownMenuItem<String>(
|
purposeList
|
||||||
|
.map(
|
||||||
|
(item) => DropdownMenuItem<String>(
|
||||||
value: item['dropdown_key'],
|
value: item['dropdown_key'],
|
||||||
child: Text(item['dropdown_value']),
|
child: Text(item['dropdown_value']),
|
||||||
))
|
),
|
||||||
|
)
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
if (dropdownItems.isEmpty) {
|
if (dropdownItems.isEmpty) {
|
||||||
dropdownItems.add(
|
dropdownItems.add(
|
||||||
DropdownMenuItem<String>(
|
DropdownMenuItem<String>(
|
||||||
value: null,
|
value: null,
|
||||||
child: Text("No options available",
|
child: Text(
|
||||||
style: TextStyle(color: Colors.grey)),
|
"No options available",
|
||||||
|
style: TextStyle(color: Colors.grey),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1120,8 +1135,9 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
flightLastTripDateNotifier.value != null &&
|
flightLastTripDateNotifier.value != null &&
|
||||||
flightLastTripDateNotifier.value!.isNotEmpty) {
|
flightLastTripDateNotifier.value!.isNotEmpty) {
|
||||||
try {
|
try {
|
||||||
final tripDate = DateFormat('dd-MM-yyyy')
|
final tripDate = DateFormat(
|
||||||
.parseStrict(flightLastTripDateNotifier.value!);
|
'dd-MM-yyyy',
|
||||||
|
).parseStrict(flightLastTripDateNotifier.value!);
|
||||||
if (tripDate.isAfter(today)) {
|
if (tripDate.isAfter(today)) {
|
||||||
firstDate = tripDate;
|
firstDate = tripDate;
|
||||||
}
|
}
|
||||||
@ -1133,8 +1149,9 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
textControllers["_date${index - 1}Controller"]?.text;
|
textControllers["_date${index - 1}Controller"]?.text;
|
||||||
if (previousDateString != null && previousDateString.isNotEmpty) {
|
if (previousDateString != null && previousDateString.isNotEmpty) {
|
||||||
try {
|
try {
|
||||||
final previousDate =
|
final previousDate = DateFormat(
|
||||||
DateFormat('dd-MM-yyyy').parseStrict(previousDateString);
|
'dd-MM-yyyy',
|
||||||
|
).parseStrict(previousDateString);
|
||||||
if (previousDate.isAfter(today)) {
|
if (previousDate.isAfter(today)) {
|
||||||
firstDate = previousDate;
|
firstDate = previousDate;
|
||||||
}
|
}
|
||||||
@ -1144,7 +1161,8 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DateTime initialDate = _selectedCheckOutDate != null &&
|
DateTime initialDate =
|
||||||
|
_selectedCheckOutDate != null &&
|
||||||
_selectedCheckOutDate!.isAfter(firstDate)
|
_selectedCheckOutDate!.isAfter(firstDate)
|
||||||
? _selectedCheckOutDate!
|
? _selectedCheckOutDate!
|
||||||
: firstDate;
|
: firstDate;
|
||||||
@ -1160,14 +1178,18 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
setState(() {
|
setState(() {
|
||||||
_selectedCheckOutDate = pickedDate;
|
_selectedCheckOutDate = pickedDate;
|
||||||
// _dateController.text = DateFormat('yyyy-MM-dd').format(pickedDate);
|
// _dateController.text = DateFormat('yyyy-MM-dd').format(pickedDate);
|
||||||
textControllers["_date${index}Controller"]?.text =
|
textControllers["_date${index}Controller"]?.text = DateFormat(
|
||||||
DateFormat('dd-MM-yyyy').format(pickedDate);
|
'dd-MM-yyyy',
|
||||||
|
).format(pickedDate);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _selectCheckOutTime(
|
Future<void> _selectCheckOutTime(
|
||||||
BuildContext context, int index, VoidCallback onPicked) async {
|
BuildContext context,
|
||||||
|
int index,
|
||||||
|
VoidCallback onPicked,
|
||||||
|
) async {
|
||||||
TimeOfDay? pickedTime = await showTimePicker(
|
TimeOfDay? pickedTime = await showTimePicker(
|
||||||
context: context,
|
context: context,
|
||||||
initialTime: _selectedCheckOutTime ?? TimeOfDay.now(),
|
initialTime: _selectedCheckOutTime ?? TimeOfDay.now(),
|
||||||
@ -1179,8 +1201,13 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
// Formatting time to HH:mm (24-hour format)
|
// Formatting time to HH:mm (24-hour format)
|
||||||
final now = DateTime.now();
|
final now = DateTime.now();
|
||||||
final formattedTime = DateFormat('HH:mm').format(
|
final formattedTime = DateFormat('HH:mm').format(
|
||||||
DateTime(now.year, now.month, now.day, pickedTime.hour,
|
DateTime(
|
||||||
pickedTime.minute),
|
now.year,
|
||||||
|
now.month,
|
||||||
|
now.day,
|
||||||
|
pickedTime.hour,
|
||||||
|
pickedTime.minute,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
// _timeController.text = formattedTime;
|
// _timeController.text = formattedTime;
|
||||||
textControllers["_time${index}Controller"]?.text = formattedTime;
|
textControllers["_time${index}Controller"]?.text = formattedTime;
|
||||||
@ -1208,11 +1235,12 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"From",
|
"From*",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldItnerarySubWrapper(
|
CustomTextFieldItnerarySubWrapper(
|
||||||
@ -1222,10 +1250,12 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: isCountryLoading
|
child:
|
||||||
|
isCountryLoading
|
||||||
? Center(child: CircularProgressIndicator())
|
? Center(child: CircularProgressIndicator())
|
||||||
: DropdownSearch<String>(
|
: DropdownSearch<String>(
|
||||||
selectedItem: selectedFrom[index] != null
|
selectedItem:
|
||||||
|
selectedFrom[index] != null
|
||||||
? countryMap[selectedFrom[index]]
|
? countryMap[selectedFrom[index]]
|
||||||
: null,
|
: null,
|
||||||
popupProps: PopupProps.menu(
|
popupProps: PopupProps.menu(
|
||||||
@ -1236,20 +1266,24 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: "Search...",
|
hintText: "Search...",
|
||||||
contentPadding: EdgeInsets.symmetric(
|
contentPadding: EdgeInsets.symmetric(
|
||||||
horizontal: 10, vertical: 1),
|
horizontal: 10,
|
||||||
|
vertical: 1,
|
||||||
),
|
),
|
||||||
style: TextStyle(fontSize: 12)),
|
|
||||||
menuProps: MenuProps(
|
|
||||||
backgroundColor: Colors.white,
|
|
||||||
),
|
),
|
||||||
itemBuilder: (context, item, isSelected) => Padding(
|
style: TextStyle(fontSize: 12),
|
||||||
|
),
|
||||||
|
menuProps: MenuProps(backgroundColor: Colors.white),
|
||||||
|
itemBuilder:
|
||||||
|
(context, item, isSelected) => Padding(
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(
|
||||||
horizontal: 8.0, vertical: 6.0),
|
horizontal: 8.0,
|
||||||
|
vertical: 6.0,
|
||||||
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
item,
|
item,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize:
|
fontSize: 13,
|
||||||
13), // 👈 Set your desired text size here
|
), // 👈 Set your desired text size here
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -1260,7 +1294,8 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
contentPadding: EdgeInsets.symmetric(horizontal: 1),
|
contentPadding: EdgeInsets.symmetric(horizontal: 1),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
dropdownBuilder: (context, selectedItem) => Align(
|
dropdownBuilder:
|
||||||
|
(context, selectedItem) => Align(
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: Text(
|
child: Text(
|
||||||
selectedItem ?? "Select",
|
selectedItem ?? "Select",
|
||||||
@ -1273,15 +1308,18 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
// .firstWhere((entry) => entry.value == newValue)
|
// .firstWhere((entry) => entry.value == newValue)
|
||||||
// .key;
|
// .key;
|
||||||
|
|
||||||
selectedFrom[index] = countryMap.entries
|
selectedFrom[index] =
|
||||||
.firstWhere((entry) => entry.value == newValue)
|
countryMap.entries
|
||||||
|
.firstWhere(
|
||||||
|
(entry) => entry.value == newValue,
|
||||||
|
)
|
||||||
.key;
|
.key;
|
||||||
|
|
||||||
print(selectedFrom[index]);
|
print(selectedFrom[index]);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
|
|
||||||
// child: SizedBox(
|
// child: SizedBox(
|
||||||
// height: 40,
|
// height: 40,
|
||||||
@ -1302,30 +1340,21 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
),
|
),
|
||||||
if (errorMessages["from_place_$index"] != null) ...[
|
if (errorMessages["from_place_$index"] != null) ...[
|
||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
Text(
|
Text("Required", style: TextStyle(color: Colors.red, fontSize: 12)),
|
||||||
"Required",
|
|
||||||
style: TextStyle(color: Colors.red, fontSize: 12),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (isDesktop)
|
if (isDesktop) SizedBox(width: 20) else SizedBox(height: 8),
|
||||||
SizedBox(
|
|
||||||
width: 20,
|
|
||||||
)
|
|
||||||
else
|
|
||||||
SizedBox(
|
|
||||||
height: 8,
|
|
||||||
),
|
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"To",
|
"To*",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldItnerarySubWrapper(
|
CustomTextFieldItnerarySubWrapper(
|
||||||
@ -1333,10 +1362,12 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: isCountryLoading
|
child:
|
||||||
|
isCountryLoading
|
||||||
? Center(child: CircularProgressIndicator())
|
? Center(child: CircularProgressIndicator())
|
||||||
: DropdownSearch<String>(
|
: DropdownSearch<String>(
|
||||||
selectedItem: selectedTo[index] != null
|
selectedItem:
|
||||||
|
selectedTo[index] != null
|
||||||
? countryMap[selectedTo[index]]
|
? countryMap[selectedTo[index]]
|
||||||
: null,
|
: null,
|
||||||
popupProps: PopupProps.menu(
|
popupProps: PopupProps.menu(
|
||||||
@ -1347,20 +1378,24 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: "Search...",
|
hintText: "Search...",
|
||||||
contentPadding: EdgeInsets.symmetric(
|
contentPadding: EdgeInsets.symmetric(
|
||||||
horizontal: 10, vertical: 1),
|
horizontal: 10,
|
||||||
|
vertical: 1,
|
||||||
),
|
),
|
||||||
style: TextStyle(fontSize: 12)),
|
|
||||||
menuProps: MenuProps(
|
|
||||||
backgroundColor: Colors.white,
|
|
||||||
),
|
),
|
||||||
itemBuilder: (context, item, isSelected) => Padding(
|
style: TextStyle(fontSize: 12),
|
||||||
|
),
|
||||||
|
menuProps: MenuProps(backgroundColor: Colors.white),
|
||||||
|
itemBuilder:
|
||||||
|
(context, item, isSelected) => Padding(
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(
|
||||||
horizontal: 8.0, vertical: 6.0),
|
horizontal: 8.0,
|
||||||
|
vertical: 6.0,
|
||||||
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
item,
|
item,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize:
|
fontSize: 13,
|
||||||
13), // 👈 Set your desired text size here
|
), // 👈 Set your desired text size here
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -1371,7 +1406,8 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
contentPadding: EdgeInsets.symmetric(horizontal: 1),
|
contentPadding: EdgeInsets.symmetric(horizontal: 1),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
dropdownBuilder: (context, selectedItem) => Align(
|
dropdownBuilder:
|
||||||
|
(context, selectedItem) => Align(
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: Text(
|
child: Text(
|
||||||
selectedItem ?? "Select Country",
|
selectedItem ?? "Select Country",
|
||||||
@ -1380,30 +1416,26 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
),
|
),
|
||||||
onChanged: (String? newValue) {
|
onChanged: (String? newValue) {
|
||||||
setState(() {
|
setState(() {
|
||||||
selectedTo[index] = countryMap.entries
|
selectedTo[index] =
|
||||||
.firstWhere((entry) => entry.value == newValue)
|
countryMap.entries
|
||||||
|
.firstWhere(
|
||||||
|
(entry) => entry.value == newValue,
|
||||||
|
)
|
||||||
.key;
|
.key;
|
||||||
|
|
||||||
print(selectedTo[index]);
|
print(selectedTo[index]);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
)),
|
),
|
||||||
|
),
|
||||||
if (errorMessages["to_place_$index"] != null) ...[
|
if (errorMessages["to_place_$index"] != null) ...[
|
||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
Text(
|
Text("Required", style: TextStyle(color: Colors.red, fontSize: 12)),
|
||||||
"Required",
|
|
||||||
style: TextStyle(color: Colors.red, fontSize: 12),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (isDesktop)
|
if (isDesktop) Spacer() else SizedBox(height: 8),
|
||||||
Spacer()
|
|
||||||
else
|
|
||||||
SizedBox(
|
|
||||||
height: 8,
|
|
||||||
),
|
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
@ -1412,7 +1444,8 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldItnerarySubWrapper(
|
CustomTextFieldItnerarySubWrapper(
|
||||||
@ -1423,7 +1456,8 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
// : MediaQuery.of(context).size.width * 0.66,
|
// : MediaQuery.of(context).size.width * 0.66,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: isFlightClassLoading
|
child:
|
||||||
|
isFlightClassLoading
|
||||||
? const Center(child: CircularProgressIndicator())
|
? const Center(child: CircularProgressIndicator())
|
||||||
: DropdownButtonFormField<String>(
|
: DropdownButtonFormField<String>(
|
||||||
focusNode: focusNodes["_class${index}FocusNode"],
|
focusNode: focusNodes["_class${index}FocusNode"],
|
||||||
@ -1435,9 +1469,11 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding: EdgeInsets.symmetric(
|
contentPadding: EdgeInsets.symmetric(
|
||||||
horizontal: 10), // Proper padding
|
horizontal: 10,
|
||||||
|
), // Proper padding
|
||||||
),
|
),
|
||||||
onChanged: purposeList.isNotEmpty
|
onChanged:
|
||||||
|
purposeList.isNotEmpty
|
||||||
? (newValue) {
|
? (newValue) {
|
||||||
setState(() {
|
setState(() {
|
||||||
selectedClasses[index] = newValue;
|
selectedClasses[index] = newValue;
|
||||||
@ -1452,21 +1488,17 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (isDesktop)
|
if (isDesktop) Spacer() else SizedBox(height: 8),
|
||||||
Spacer()
|
|
||||||
else
|
|
||||||
SizedBox(
|
|
||||||
height: 8,
|
|
||||||
),
|
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Date",
|
"Date*",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldItnerarySubWrapper(
|
CustomTextFieldItnerarySubWrapper(
|
||||||
@ -1489,8 +1521,11 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
floatingLabelBehavior: FloatingLabelBehavior.never,
|
floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
||||||
suffixIcon: Icon(Icons.calendar_today,
|
suffixIcon: Icon(
|
||||||
size: 16, color: Colors.grey),
|
Icons.calendar_today,
|
||||||
|
size: 16,
|
||||||
|
color: Colors.grey,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -1499,28 +1534,21 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
),
|
),
|
||||||
if (errorMessages["date_$index"] != null) ...[
|
if (errorMessages["date_$index"] != null) ...[
|
||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
Text(
|
Text("Required", style: TextStyle(color: Colors.red, fontSize: 12)),
|
||||||
"Required",
|
|
||||||
style: TextStyle(color: Colors.red, fontSize: 12),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (isDesktop)
|
if (isDesktop) Spacer() else SizedBox(height: 8),
|
||||||
Spacer()
|
|
||||||
else
|
|
||||||
SizedBox(
|
|
||||||
height: 8,
|
|
||||||
),
|
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Time",
|
"Time*",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldItnerarySubWrapper(
|
CustomTextFieldItnerarySubWrapper(
|
||||||
@ -1538,7 +1566,8 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
_selectCheckOutTime(context, index, () {
|
_selectCheckOutTime(context, index, () {
|
||||||
validateTimeDifference(index);
|
validateTimeDifference(index);
|
||||||
setState(
|
setState(
|
||||||
() {}); // ✅ Force rebuild to show the error immediately
|
() {},
|
||||||
|
); // ✅ Force rebuild to show the error immediately
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
child: AbsorbPointer(
|
child: AbsorbPointer(
|
||||||
@ -1554,8 +1583,11 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
floatingLabelBehavior: FloatingLabelBehavior.never,
|
floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
||||||
suffixIcon:
|
suffixIcon: Icon(
|
||||||
Icon(Icons.access_time, size: 16, color: Colors.grey),
|
Icons.access_time,
|
||||||
|
size: 16,
|
||||||
|
color: Colors.grey,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -1579,13 +1611,9 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
onPressed: () {
|
onPressed: () {
|
||||||
removeTrip(index);
|
removeTrip(index);
|
||||||
},
|
},
|
||||||
icon: Icon(
|
icon: Icon(Icons.close, color: Colors.redAccent, size: 20),
|
||||||
Icons.close,
|
|
||||||
color: Colors.redAccent,
|
|
||||||
size: 20,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1594,11 +1622,14 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
widget.apiData?['flight_visa_available'] ?? [];
|
widget.apiData?['flight_visa_available'] ?? [];
|
||||||
// Default selected value
|
// Default selected value
|
||||||
|
|
||||||
List<DropdownMenuItem<String>> dropdownItems = visa_available
|
List<DropdownMenuItem<String>> dropdownItems =
|
||||||
.map((item) => DropdownMenuItem<String>(
|
visa_available
|
||||||
|
.map(
|
||||||
|
(item) => DropdownMenuItem<String>(
|
||||||
value: item['dropdown_key'],
|
value: item['dropdown_key'],
|
||||||
child: Text(item['dropdown_value']),
|
child: Text(item['dropdown_value']),
|
||||||
))
|
),
|
||||||
|
)
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
selectedvisa_available ??=
|
selectedvisa_available ??=
|
||||||
@ -1608,8 +1639,10 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
dropdownItems.add(
|
dropdownItems.add(
|
||||||
DropdownMenuItem<String>(
|
DropdownMenuItem<String>(
|
||||||
value: null,
|
value: null,
|
||||||
child: Text("No options available",
|
child: Text(
|
||||||
style: TextStyle(color: Colors.grey)),
|
"No options available",
|
||||||
|
style: TextStyle(color: Colors.grey),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1622,7 +1655,8 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldItnerarySubWrapper(
|
CustomTextFieldItnerarySubWrapper(
|
||||||
@ -1641,10 +1675,12 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
style: TextStyle(fontSize: 12),
|
style: TextStyle(fontSize: 12),
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding:
|
contentPadding: EdgeInsets.symmetric(
|
||||||
EdgeInsets.symmetric(horizontal: 10), // Proper padding
|
horizontal: 10,
|
||||||
|
), // Proper padding
|
||||||
),
|
),
|
||||||
onChanged: visa_available.isNotEmpty
|
onChanged:
|
||||||
|
visa_available.isNotEmpty
|
||||||
? (newValue) {
|
? (newValue) {
|
||||||
setState(() {
|
setState(() {
|
||||||
selectedvisa_available = newValue;
|
selectedvisa_available = newValue;
|
||||||
@ -1652,7 +1688,8 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
// Reset `multiTripRowCount` when switching away from Multitrip
|
// Reset `multiTripRowCount` when switching away from Multitrip
|
||||||
});
|
});
|
||||||
print(
|
print(
|
||||||
"Updating form data: Flight -> trip_type -> $selectedvisa_available");
|
"Updating form data: Flight -> trip_type -> $selectedvisa_available",
|
||||||
|
);
|
||||||
|
|
||||||
// _initializeRows();
|
// _initializeRows();
|
||||||
}
|
}
|
||||||
@ -1664,13 +1701,8 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (isDesktop)
|
if (isDesktop) SizedBox(width: 20),
|
||||||
SizedBox(
|
SizedBox(height: 5),
|
||||||
width: 20,
|
|
||||||
),
|
|
||||||
SizedBox(
|
|
||||||
height: 5,
|
|
||||||
),
|
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
@ -1679,7 +1711,8 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldWrapper(
|
CustomTextFieldWrapper(
|
||||||
@ -1705,9 +1738,7 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (isDesktop) Spacer(),
|
if (isDesktop) Spacer(),
|
||||||
SizedBox(
|
SizedBox(height: 5),
|
||||||
height: 5,
|
|
||||||
),
|
|
||||||
Column(
|
Column(
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
@ -1724,11 +1755,14 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
widget.apiData?['flight_visa_available'] ?? [];
|
widget.apiData?['flight_visa_available'] ?? [];
|
||||||
// Default selected value
|
// Default selected value
|
||||||
|
|
||||||
List<DropdownMenuItem<String>> dropdownItems = visa_available
|
List<DropdownMenuItem<String>> dropdownItems =
|
||||||
.map((item) => DropdownMenuItem<String>(
|
visa_available
|
||||||
|
.map(
|
||||||
|
(item) => DropdownMenuItem<String>(
|
||||||
value: item['dropdown_key'],
|
value: item['dropdown_key'],
|
||||||
child: Text(item['dropdown_value']),
|
child: Text(item['dropdown_value']),
|
||||||
))
|
),
|
||||||
|
)
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
selectedvisa_available ??=
|
selectedvisa_available ??=
|
||||||
@ -1738,8 +1772,10 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
dropdownItems.add(
|
dropdownItems.add(
|
||||||
DropdownMenuItem<String>(
|
DropdownMenuItem<String>(
|
||||||
value: null,
|
value: null,
|
||||||
child: Text("No options available",
|
child: Text(
|
||||||
style: TextStyle(color: Colors.grey)),
|
"No options available",
|
||||||
|
style: TextStyle(color: Colors.grey),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1753,14 +1789,16 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldWrapper(
|
CustomTextFieldWrapper(
|
||||||
// isFocused: _tripTypeFocused,
|
// isFocused: _tripTypeFocused,
|
||||||
isFocused: focusStates["_visa1Focused"] ?? false,
|
isFocused: focusStates["_visa1Focused"] ?? false,
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
width: isDesktop
|
width:
|
||||||
|
isDesktop
|
||||||
? MediaQuery.of(context).size.width * 0.34
|
? MediaQuery.of(context).size.width * 0.34
|
||||||
: MediaQuery.of(context).size.width * 0.66,
|
: MediaQuery.of(context).size.width * 0.66,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
@ -1772,10 +1810,12 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
style: TextStyle(fontSize: 12),
|
style: TextStyle(fontSize: 12),
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding:
|
contentPadding: EdgeInsets.symmetric(
|
||||||
EdgeInsets.symmetric(horizontal: 10), // Proper padding
|
horizontal: 10,
|
||||||
|
), // Proper padding
|
||||||
),
|
),
|
||||||
onChanged: visa_available.isNotEmpty
|
onChanged:
|
||||||
|
visa_available.isNotEmpty
|
||||||
? (newValue) {
|
? (newValue) {
|
||||||
setState(() {
|
setState(() {
|
||||||
selectedvisa_available = newValue;
|
selectedvisa_available = newValue;
|
||||||
@ -1783,7 +1823,8 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
// Reset `multiTripRowCount` when switching away from Multitrip
|
// Reset `multiTripRowCount` when switching away from Multitrip
|
||||||
});
|
});
|
||||||
print(
|
print(
|
||||||
"Updating form data: Flight -> trip_type -> $selectedvisa_available");
|
"Updating form data: Flight -> trip_type -> $selectedvisa_available",
|
||||||
|
);
|
||||||
|
|
||||||
// _initializeRows();
|
// _initializeRows();
|
||||||
}
|
}
|
||||||
@ -1807,9 +1848,7 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Colors.grey[400], // Light grey color
|
backgroundColor: Colors.grey[400], // Light grey color
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
|
||||||
borderRadius: BorderRadius.circular(8),
|
|
||||||
),
|
|
||||||
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
@ -1818,7 +1857,6 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(width: 10), // Space between buttons
|
SizedBox(width: 10), // Space between buttons
|
||||||
|
|
||||||
// Save Changes Button
|
// Save Changes Button
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
@ -1826,9 +1864,7 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Color(0xFF114D8B), // Primary color for save
|
backgroundColor: Color(0xFF114D8B), // Primary color for save
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
|
||||||
borderRadius: BorderRadius.circular(8),
|
|
||||||
),
|
|
||||||
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
|
|||||||
@ -223,8 +223,6 @@ class _ForexScreenState extends State<ForexScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool isValidForexData(Map<String, dynamic> data) {
|
bool isValidForexData(Map<String, dynamic> data) {
|
||||||
errorMessages.clear(); // Reset errors
|
|
||||||
|
|
||||||
// Required fields that must not be empty
|
// Required fields that must not be empty
|
||||||
List<String> requiredFields = [
|
List<String> requiredFields = [
|
||||||
"start_date",
|
"start_date",
|
||||||
@ -232,7 +230,7 @@ class _ForexScreenState extends State<ForexScreen> {
|
|||||||
"country_code",
|
"country_code",
|
||||||
"deposit_on_card",
|
"deposit_on_card",
|
||||||
"deposit_on_cash",
|
"deposit_on_cash",
|
||||||
// "card_number"
|
// "card_number",
|
||||||
];
|
];
|
||||||
|
|
||||||
// If have_card is "1", then delivery_location is required
|
// If have_card is "1", then delivery_location is required
|
||||||
@ -246,11 +244,17 @@ class _ForexScreenState extends State<ForexScreen> {
|
|||||||
// Check validation for each field
|
// Check validation for each field
|
||||||
for (String field in requiredFields) {
|
for (String field in requiredFields) {
|
||||||
if (data[field] == null || data[field].toString().trim().isEmpty) {
|
if (data[field] == null || data[field].toString().trim().isEmpty) {
|
||||||
errorMessages[field] = "This field is required";
|
errorMessages[field] = "Required";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return errorMessages.isEmpty; // Valid if there are no errors
|
return errorMessages.values.every((msg) => msg.trim().isEmpty);
|
||||||
|
|
||||||
|
// if (hasErrors) {
|
||||||
|
// print("At least one error message is present.");
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return errorMessages.isEmpty; // Valid if there are no errors
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, String?> getFlightTripDateRange(
|
Map<String, String?> getFlightTripDateRange(
|
||||||
@ -286,7 +290,7 @@ class _ForexScreenState extends State<ForexScreen> {
|
|||||||
|
|
||||||
Map<String, dynamic> data = forexData;
|
Map<String, dynamic> data = forexData;
|
||||||
|
|
||||||
if (!isValidForexData(data)) {
|
if (!isValidForexData(data) && errorMessages.isNotEmpty) {
|
||||||
print("Validation Failed: Required fields are missing.");
|
print("Validation Failed: Required fields are missing.");
|
||||||
setState(() {});
|
setState(() {});
|
||||||
return; // Stop execution if validation fails
|
return; // Stop execution if validation fails
|
||||||
@ -613,7 +617,7 @@ class _ForexScreenState extends State<ForexScreen> {
|
|||||||
errorMessages["deposit_on_card"] =
|
errorMessages["deposit_on_card"] =
|
||||||
"Enter Valid Amount"; // Clear error if valid
|
"Enter Valid Amount"; // Clear error if valid
|
||||||
} else {
|
} else {
|
||||||
errorMessages["deposit_on_card"] = ""; // Clear error if valid
|
errorMessages.remove("deposit_on_card"); // Clear error if valid
|
||||||
}
|
}
|
||||||
|
|
||||||
// Refresh UI if using StatefulWidget
|
// Refresh UI if using StatefulWidget
|
||||||
@ -621,7 +625,8 @@ class _ForexScreenState extends State<ForexScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _validateCashAmount(String value) {
|
void _validateCashAmount(String value) {
|
||||||
errorMessages["deposit_on_card"] = " ";
|
// errorMessages["deposit_on_card"] = " ";
|
||||||
|
errorMessages.remove("deposit_on_cash");
|
||||||
print("_validateCashAmount - $value - $fifteenPercent");
|
print("_validateCashAmount - $value - $fifteenPercent");
|
||||||
|
|
||||||
int? enteredAmount = int.tryParse(value);
|
int? enteredAmount = int.tryParse(value);
|
||||||
@ -642,11 +647,18 @@ class _ForexScreenState extends State<ForexScreen> {
|
|||||||
textControllers["_card"]?.text = difference.toString();
|
textControllers["_card"]?.text = difference.toString();
|
||||||
|
|
||||||
if (enteredAmount > fifteenPercent) {
|
if (enteredAmount > fifteenPercent) {
|
||||||
|
if (checkValidAmount > 0) {
|
||||||
|
textControllers["_card"]?.text = "0";
|
||||||
|
errorMessages["deposit_on_card"] =
|
||||||
|
"Enter Valid Amount"; // Clear error if valid
|
||||||
|
}
|
||||||
errorMessages["deposit_on_cash"] = "Amount cannot exceed $fifteenPercent";
|
errorMessages["deposit_on_cash"] = "Amount cannot exceed $fifteenPercent";
|
||||||
} else if (checkValidAmount == quotedAmount) {
|
} else if (checkValidAmount == quotedAmount) {
|
||||||
errorMessages["deposit_on_card"] = " "; // Clear error if valid
|
errorMessages.remove("deposit_on_cash");
|
||||||
|
// errorMessages["deposit_on_card"] = " "; // Clear error if valid
|
||||||
} else {
|
} else {
|
||||||
errorMessages["deposit_on_cash"] = ""; // Clear error if valid
|
// errorMessages["deposit_on_cash"] = ""; // Clear error if valid
|
||||||
|
errorMessages.remove("deposit_on_cash");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Refresh UI if using StatefulWidget
|
// Refresh UI if using StatefulWidget
|
||||||
@ -887,7 +899,7 @@ class _ForexScreenState extends State<ForexScreen> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Start Date",
|
"Start Date *",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
@ -958,7 +970,7 @@ class _ForexScreenState extends State<ForexScreen> {
|
|||||||
if (errorMessages["start_date"] != null) ...[
|
if (errorMessages["start_date"] != null) ...[
|
||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
Text(
|
Text(
|
||||||
"Select Start Date",
|
errorMessages["start_date"]!,
|
||||||
style: TextStyle(color: Colors.red, fontSize: 12),
|
style: TextStyle(color: Colors.red, fontSize: 12),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -969,7 +981,7 @@ class _ForexScreenState extends State<ForexScreen> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"End Date",
|
"End Date *",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
@ -1123,7 +1135,7 @@ class _ForexScreenState extends State<ForexScreen> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Country",
|
"Country*",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
@ -1179,7 +1191,7 @@ class _ForexScreenState extends State<ForexScreen> {
|
|||||||
if (errorMessages["country_code"] != null) ...[
|
if (errorMessages["country_code"] != null) ...[
|
||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
Text(
|
Text(
|
||||||
"Select Country",
|
errorMessages["country_code"]!,
|
||||||
style: TextStyle(color: Colors.red, fontSize: 12),
|
style: TextStyle(color: Colors.red, fontSize: 12),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -1600,8 +1612,12 @@ class _ForexScreenState extends State<ForexScreen> {
|
|||||||
child: TextField(
|
child: TextField(
|
||||||
focusNode: focusNodes["_cash"],
|
focusNode: focusNodes["_cash"],
|
||||||
controller: textControllers["_cash"],
|
controller: textControllers["_cash"],
|
||||||
style: const TextStyle(fontSize: 12),
|
|
||||||
keyboardType: TextInputType.number,
|
keyboardType: TextInputType.number,
|
||||||
|
inputFormatters: [
|
||||||
|
FilteringTextInputFormatter.digitsOnly, // ✅ Only allow digits
|
||||||
|
],
|
||||||
|
style: const TextStyle(fontSize: 12),
|
||||||
|
// keyboardType: TextInputType.number,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
// errorMessages["deposit_on_cash"] = "";
|
// errorMessages["deposit_on_cash"] = "";
|
||||||
_validateCashAmount(
|
_validateCashAmount(
|
||||||
@ -1653,6 +1669,9 @@ class _ForexScreenState extends State<ForexScreen> {
|
|||||||
controller: textControllers["_card"],
|
controller: textControllers["_card"],
|
||||||
style: const TextStyle(fontSize: 12),
|
style: const TextStyle(fontSize: 12),
|
||||||
keyboardType: TextInputType.number,
|
keyboardType: TextInputType.number,
|
||||||
|
inputFormatters: [
|
||||||
|
FilteringTextInputFormatter.digitsOnly, // ✅ Only allow digits
|
||||||
|
],
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
_validateCardAmount(
|
_validateCardAmount(
|
||||||
value,
|
value,
|
||||||
@ -1884,7 +1903,7 @@ class _ForexScreenState extends State<ForexScreen> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Card Number",
|
"Card Number*",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
|
|||||||
@ -17,14 +17,15 @@ class TrainScreen extends StatefulWidget {
|
|||||||
final String? loginUser;
|
final String? loginUser;
|
||||||
final String? tripType;
|
final String? tripType;
|
||||||
|
|
||||||
TrainScreen(
|
TrainScreen({
|
||||||
{required this.onClose,
|
required this.onClose,
|
||||||
this.apiData,
|
this.apiData,
|
||||||
required this.onSavetrain,
|
required this.onSavetrain,
|
||||||
required this.selectedItem,
|
required this.selectedItem,
|
||||||
required this.loginUser,
|
required this.loginUser,
|
||||||
this.apiDataForClass,
|
this.apiDataForClass,
|
||||||
this.tripType});
|
this.tripType,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_TrainScreenState createState() => _TrainScreenState();
|
_TrainScreenState createState() => _TrainScreenState();
|
||||||
@ -232,7 +233,7 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
"from_station",
|
"from_station",
|
||||||
"to_station",
|
"to_station",
|
||||||
"date",
|
"date",
|
||||||
"time"
|
"time",
|
||||||
];
|
];
|
||||||
|
|
||||||
// Check validation for each field
|
// Check validation for each field
|
||||||
@ -287,9 +288,11 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ResponsiveBuilder(builder: (context, sizingInfo) {
|
return ResponsiveBuilder(
|
||||||
|
builder: (context, sizingInfo) {
|
||||||
bool isMobile = sizingInfo.isMobile;
|
bool isMobile = sizingInfo.isMobile;
|
||||||
bool isDesktop = sizingInfo.deviceScreenType == DeviceScreenType.desktop;
|
bool isDesktop =
|
||||||
|
sizingInfo.deviceScreenType == DeviceScreenType.desktop;
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
// color: Color(0xFFF4F4FB),
|
// color: Color(0xFFF4F4FB),
|
||||||
@ -325,13 +328,14 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
child: Center(
|
child: Center(
|
||||||
child: Column(children: _buildAccomadtionForm(isDesktop)),
|
child: Column(children: _buildAccomadtionForm(isDesktop)),
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
});
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> _buildAccomadtionForm(bool isDesktop) {
|
List<Widget> _buildAccomadtionForm(bool isDesktop) {
|
||||||
@ -344,7 +348,7 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
|
|
||||||
List<List<Widget>> rowBuilders = [
|
List<List<Widget>> rowBuilders = [
|
||||||
_builClassType(isDesktop),
|
_builClassType(isDesktop),
|
||||||
_buildSecondRow(isDesktop)
|
_buildSecondRow(isDesktop),
|
||||||
];
|
];
|
||||||
|
|
||||||
return [
|
return [
|
||||||
@ -369,7 +373,8 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
isDesktop
|
isDesktop
|
||||||
@ -377,38 +382,35 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
: Column(children: _buildTripType(isDesktop)),
|
: Column(children: _buildTripType(isDesktop)),
|
||||||
if (errorMessages["train_no"] != null) ...[
|
if (errorMessages["train_no"] != null) ...[
|
||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
Text(
|
Text("Required", style: TextStyle(color: Colors.red, fontSize: 12)),
|
||||||
"Required",
|
|
||||||
style: TextStyle(color: Colors.red, fontSize: 12),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (isDesktop)
|
if (isDesktop) Spacer() else SizedBox(height: 8),
|
||||||
Spacer()
|
|
||||||
else
|
|
||||||
SizedBox(
|
|
||||||
height: 8,
|
|
||||||
),
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> _buildTripType(bool isDesktop) {
|
List<Widget> _buildTripType(bool isDesktop) {
|
||||||
List<dynamic> purposeList = widget.apiData?['flight_trip_type'] ?? [];
|
List<dynamic> purposeList = widget.apiData?['flight_trip_type'] ?? [];
|
||||||
|
|
||||||
List<DropdownMenuItem<String>> dropdownItems = purposeList
|
List<DropdownMenuItem<String>> dropdownItems =
|
||||||
.map((item) => DropdownMenuItem<String>(
|
purposeList
|
||||||
|
.map(
|
||||||
|
(item) => DropdownMenuItem<String>(
|
||||||
value: item['dropdown_value'],
|
value: item['dropdown_value'],
|
||||||
child: Text(item['dropdown_value']),
|
child: Text(item['dropdown_value']),
|
||||||
))
|
),
|
||||||
|
)
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
if (dropdownItems.isEmpty) {
|
if (dropdownItems.isEmpty) {
|
||||||
dropdownItems.add(
|
dropdownItems.add(
|
||||||
DropdownMenuItem<String>(
|
DropdownMenuItem<String>(
|
||||||
value: null,
|
value: null,
|
||||||
child: Text("No options available",
|
child: Text(
|
||||||
style: TextStyle(color: Colors.grey)),
|
"No options available",
|
||||||
|
style: TextStyle(color: Colors.grey),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -455,7 +457,8 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
|
|
||||||
DateTime? pickedDate = await showDatePicker(
|
DateTime? pickedDate = await showDatePicker(
|
||||||
context: context,
|
context: context,
|
||||||
initialDate: _selectedCheckOutDate != null &&
|
initialDate:
|
||||||
|
_selectedCheckOutDate != null &&
|
||||||
_selectedCheckOutDate!.isAfter(today)
|
_selectedCheckOutDate!.isAfter(today)
|
||||||
? _selectedCheckOutDate!
|
? _selectedCheckOutDate!
|
||||||
: today,
|
: today,
|
||||||
@ -483,8 +486,13 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
// Formatting time to HH:mm (24-hour format)
|
// Formatting time to HH:mm (24-hour format)
|
||||||
final now = DateTime.now();
|
final now = DateTime.now();
|
||||||
final formattedTime = DateFormat('HH:mm').format(
|
final formattedTime = DateFormat('HH:mm').format(
|
||||||
DateTime(now.year, now.month, now.day, pickedTime.hour,
|
DateTime(
|
||||||
pickedTime.minute),
|
now.year,
|
||||||
|
now.month,
|
||||||
|
now.day,
|
||||||
|
pickedTime.hour,
|
||||||
|
pickedTime.minute,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
_timeController.text = formattedTime;
|
_timeController.text = formattedTime;
|
||||||
});
|
});
|
||||||
@ -495,19 +503,24 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
|
|
||||||
List<dynamic> purposeList = widget.apiDataForClass?['train_class'] ?? [];
|
List<dynamic> purposeList = widget.apiDataForClass?['train_class'] ?? [];
|
||||||
|
|
||||||
List<DropdownMenuItem<String>> dropdownItems = purposeList
|
List<DropdownMenuItem<String>> dropdownItems =
|
||||||
.map((item) => DropdownMenuItem<String>(
|
purposeList
|
||||||
|
.map(
|
||||||
|
(item) => DropdownMenuItem<String>(
|
||||||
value: item['dropdown_key'],
|
value: item['dropdown_key'],
|
||||||
child: Text(item['dropdown_value']),
|
child: Text(item['dropdown_value']),
|
||||||
))
|
),
|
||||||
|
)
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
if (dropdownItems.isEmpty) {
|
if (dropdownItems.isEmpty) {
|
||||||
dropdownItems.add(
|
dropdownItems.add(
|
||||||
DropdownMenuItem<String>(
|
DropdownMenuItem<String>(
|
||||||
value: null,
|
value: null,
|
||||||
child: Text("No options available",
|
child: Text(
|
||||||
style: TextStyle(color: Colors.grey)),
|
"No options available",
|
||||||
|
style: TextStyle(color: Colors.grey),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -525,7 +538,8 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldItnerarySubWrapper(
|
CustomTextFieldItnerarySubWrapper(
|
||||||
@ -543,10 +557,12 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
style: TextStyle(fontSize: 12),
|
style: TextStyle(fontSize: 12),
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding:
|
contentPadding: EdgeInsets.symmetric(
|
||||||
EdgeInsets.symmetric(horizontal: 10), // Proper padding
|
horizontal: 10,
|
||||||
|
), // Proper padding
|
||||||
),
|
),
|
||||||
onChanged: purposeList.isNotEmpty
|
onChanged:
|
||||||
|
purposeList.isNotEmpty
|
||||||
? (newValue) {
|
? (newValue) {
|
||||||
setState(() {
|
setState(() {
|
||||||
selectedClass = newValue;
|
selectedClass = newValue;
|
||||||
@ -559,19 +575,11 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
),
|
),
|
||||||
if (errorMessages["class"] != null) ...[
|
if (errorMessages["class"] != null) ...[
|
||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
Text(
|
Text("Required", style: TextStyle(color: Colors.red, fontSize: 12)),
|
||||||
"Required",
|
|
||||||
style: TextStyle(color: Colors.red, fontSize: 12),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (isDesktop)
|
if (isDesktop) Spacer() else SizedBox(height: 8),
|
||||||
Spacer()
|
|
||||||
else
|
|
||||||
SizedBox(
|
|
||||||
height: 8,
|
|
||||||
),
|
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
@ -580,7 +588,8 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldItnerarySubWrapper(
|
CustomTextFieldItnerarySubWrapper(
|
||||||
@ -588,41 +597,51 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: isCountryLoading
|
child:
|
||||||
|
isCountryLoading
|
||||||
? Center(child: CircularProgressIndicator())
|
? Center(child: CircularProgressIndicator())
|
||||||
: DropdownSearch<String>(
|
: DropdownSearch<String>(
|
||||||
// selectedItem: selectedFrom != null
|
// selectedItem: selectedFrom != null
|
||||||
// ? countryMap[selectedFrom]
|
// ? countryMap[selectedFrom]
|
||||||
// : null,
|
// : null,
|
||||||
|
selectedItem:
|
||||||
selectedItem: selectedFrom != null
|
selectedFrom != null
|
||||||
? countryMap[
|
? countryMap[selectedFrom] // get the display value from code
|
||||||
selectedFrom] // get the display value from code
|
|
||||||
: null,
|
: null,
|
||||||
popupProps: PopupProps.menu(
|
popupProps: PopupProps.menu(
|
||||||
|
menuProps: MenuProps(backgroundColor: Colors.white),
|
||||||
|
constraints: BoxConstraints(maxHeight: 230),
|
||||||
showSearchBox: true,
|
showSearchBox: true,
|
||||||
searchFieldProps: TextFieldProps(
|
searchFieldProps: TextFieldProps(
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: "Search ...",
|
hintText: "Search ...",
|
||||||
contentPadding:
|
contentPadding: EdgeInsets.symmetric(
|
||||||
EdgeInsets.symmetric(horizontal: 10),
|
horizontal: 10,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
|
||||||
items: countryMap.values.toList(),
|
items: countryMap.values.toList(),
|
||||||
|
|
||||||
dropdownDecoratorProps: DropDownDecoratorProps(
|
dropdownDecoratorProps: DropDownDecoratorProps(
|
||||||
dropdownSearchDecoration: InputDecoration(
|
dropdownSearchDecoration: InputDecoration(
|
||||||
|
contentPadding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 10,
|
||||||
|
vertical: 5,
|
||||||
|
),
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding: EdgeInsets.symmetric(horizontal: 1),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
dropdownBuilder: (context, selectedItem) => Align(
|
dropdownBuilder:
|
||||||
|
(context, selectedItem) => Align(
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: Text(
|
child: Text(
|
||||||
selectedItem ?? "Select",
|
selectedItem ?? "Select",
|
||||||
style: TextStyle(fontSize: 12),
|
style: TextStyle(fontSize: 12),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
// onChanged: (String? newValue) {
|
// onChanged: (String? newValue) {
|
||||||
// setState(() {
|
// setState(() {
|
||||||
// // selectedFrom[index] = countryMap.entries
|
// // selectedFrom[index] = countryMap.entries
|
||||||
@ -636,16 +655,18 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
// print(selectedFrom);
|
// print(selectedFrom);
|
||||||
// });
|
// });
|
||||||
// },
|
// },
|
||||||
|
|
||||||
onChanged: (String? newValue) {
|
onChanged: (String? newValue) {
|
||||||
setState(() {
|
setState(() {
|
||||||
selectedFrom = countryMap.entries
|
selectedFrom =
|
||||||
.firstWhere((entry) => entry.value == newValue)
|
countryMap.entries
|
||||||
|
.firstWhere(
|
||||||
|
(entry) => entry.value == newValue,
|
||||||
|
)
|
||||||
.key;
|
.key;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
// child: SizedBox(
|
// child: SizedBox(
|
||||||
// height: 40,
|
// height: 40,
|
||||||
// child: TextField(
|
// child: TextField(
|
||||||
@ -664,19 +685,11 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
),
|
),
|
||||||
if (errorMessages["from_station"] != null) ...[
|
if (errorMessages["from_station"] != null) ...[
|
||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
Text(
|
Text("Required", style: TextStyle(color: Colors.red, fontSize: 12)),
|
||||||
"Required",
|
|
||||||
style: TextStyle(color: Colors.red, fontSize: 12),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (isDesktop)
|
if (isDesktop) Spacer() else SizedBox(height: 8),
|
||||||
Spacer()
|
|
||||||
else
|
|
||||||
SizedBox(
|
|
||||||
height: 8,
|
|
||||||
),
|
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
@ -685,7 +698,8 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldItnerarySubWrapper(
|
CustomTextFieldItnerarySubWrapper(
|
||||||
@ -693,20 +707,24 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: isCountryLoading
|
child:
|
||||||
|
isCountryLoading
|
||||||
? Center(child: CircularProgressIndicator())
|
? Center(child: CircularProgressIndicator())
|
||||||
: DropdownSearch<String>(
|
: DropdownSearch<String>(
|
||||||
selectedItem: selectedTo != null
|
selectedItem:
|
||||||
? countryMap[
|
selectedTo != null
|
||||||
selectedTo] // get the display value from code
|
? countryMap[selectedTo] // get the display value from code
|
||||||
: null,
|
: null,
|
||||||
popupProps: PopupProps.menu(
|
popupProps: PopupProps.menu(
|
||||||
|
menuProps: MenuProps(backgroundColor: Colors.white),
|
||||||
|
constraints: BoxConstraints(maxHeight: 230),
|
||||||
showSearchBox: true,
|
showSearchBox: true,
|
||||||
searchFieldProps: TextFieldProps(
|
searchFieldProps: TextFieldProps(
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: "Search ...",
|
hintText: "Search ...",
|
||||||
contentPadding:
|
contentPadding: EdgeInsets.symmetric(
|
||||||
EdgeInsets.symmetric(horizontal: 10),
|
horizontal: 10,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -717,7 +735,8 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
contentPadding: EdgeInsets.symmetric(horizontal: 1),
|
contentPadding: EdgeInsets.symmetric(horizontal: 1),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
dropdownBuilder: (context, selectedItem) => Align(
|
dropdownBuilder:
|
||||||
|
(context, selectedItem) => Align(
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: Text(
|
child: Text(
|
||||||
selectedItem ?? "Select",
|
selectedItem ?? "Select",
|
||||||
@ -726,8 +745,11 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
),
|
),
|
||||||
onChanged: (String? newValue) {
|
onChanged: (String? newValue) {
|
||||||
setState(() {
|
setState(() {
|
||||||
selectedTo = countryMap.entries
|
selectedTo =
|
||||||
.firstWhere((entry) => entry.value == newValue)
|
countryMap.entries
|
||||||
|
.firstWhere(
|
||||||
|
(entry) => entry.value == newValue,
|
||||||
|
)
|
||||||
.key;
|
.key;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@ -736,19 +758,11 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
),
|
),
|
||||||
if (errorMessages["to_station"] != null) ...[
|
if (errorMessages["to_station"] != null) ...[
|
||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
Text(
|
Text("Required", style: TextStyle(color: Colors.red, fontSize: 12)),
|
||||||
"Required",
|
|
||||||
style: TextStyle(color: Colors.red, fontSize: 12),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (isDesktop)
|
if (isDesktop) Spacer() else SizedBox(height: 8),
|
||||||
Spacer()
|
|
||||||
else
|
|
||||||
SizedBox(
|
|
||||||
height: 8,
|
|
||||||
),
|
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
@ -757,7 +771,8 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldItnerarySubWrapper(
|
CustomTextFieldItnerarySubWrapper(
|
||||||
@ -779,8 +794,11 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
floatingLabelBehavior: FloatingLabelBehavior.never,
|
floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
||||||
suffixIcon: Icon(Icons.calendar_today,
|
suffixIcon: Icon(
|
||||||
size: 16, color: Colors.grey),
|
Icons.calendar_today,
|
||||||
|
size: 16,
|
||||||
|
color: Colors.grey,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -789,19 +807,11 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
),
|
),
|
||||||
if (errorMessages["date"] != null) ...[
|
if (errorMessages["date"] != null) ...[
|
||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
Text(
|
Text("Required", style: TextStyle(color: Colors.red, fontSize: 12)),
|
||||||
"Required",
|
|
||||||
style: TextStyle(color: Colors.red, fontSize: 12),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (isDesktop)
|
if (isDesktop) Spacer() else SizedBox(height: 8),
|
||||||
Spacer()
|
|
||||||
else
|
|
||||||
SizedBox(
|
|
||||||
height: 8,
|
|
||||||
),
|
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
@ -810,7 +820,8 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldItnerarySubWrapper(
|
CustomTextFieldItnerarySubWrapper(
|
||||||
@ -832,8 +843,11 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
floatingLabelBehavior: FloatingLabelBehavior.never,
|
floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
||||||
suffixIcon:
|
suffixIcon: Icon(
|
||||||
Icon(Icons.access_time, size: 16, color: Colors.grey),
|
Icons.access_time,
|
||||||
|
size: 16,
|
||||||
|
color: Colors.grey,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -842,10 +856,7 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
),
|
),
|
||||||
if (errorMessages["time"] != null) ...[
|
if (errorMessages["time"] != null) ...[
|
||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
Text(
|
Text("Required", style: TextStyle(color: Colors.red, fontSize: 12)),
|
||||||
"Required",
|
|
||||||
style: TextStyle(color: Colors.red, fontSize: 12),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -862,7 +873,8 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldWrapper(
|
CustomTextFieldWrapper(
|
||||||
@ -890,9 +902,7 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (isDesktop) Spacer(),
|
if (isDesktop) Spacer(),
|
||||||
SizedBox(
|
SizedBox(height: 5),
|
||||||
height: 5,
|
|
||||||
),
|
|
||||||
Column(
|
Column(
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
@ -900,7 +910,7 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
children: _handleAction(isDesktop),
|
children: _handleAction(isDesktop),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -913,9 +923,7 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Colors.grey[400], // Light grey color
|
backgroundColor: Colors.grey[400], // Light grey color
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
|
||||||
borderRadius: BorderRadius.circular(8),
|
|
||||||
),
|
|
||||||
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
@ -924,7 +932,6 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(width: 10), // Space between buttons
|
SizedBox(width: 10), // Space between buttons
|
||||||
|
|
||||||
// Save Changes Button
|
// Save Changes Button
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
@ -932,9 +939,7 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Color(0xFF114D8B), // Primary color for save
|
backgroundColor: Color(0xFF114D8B), // Primary color for save
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
|
||||||
borderRadius: BorderRadius.circular(8),
|
|
||||||
),
|
|
||||||
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
|
|||||||
@ -23,6 +23,7 @@ import '../../routes/custom_drawer.dart';
|
|||||||
import '../../services/apiService.dart';
|
import '../../services/apiService.dart';
|
||||||
import '../../widgets/custom_radio_button.dart';
|
import '../../widgets/custom_radio_button.dart';
|
||||||
import '../../widgets/custom_text_field.dart';
|
import '../../widgets/custom_text_field.dart';
|
||||||
|
import '../../widgets/saving_loader.dart';
|
||||||
import '../approvals/approval_dialogs.dart';
|
import '../approvals/approval_dialogs.dart';
|
||||||
import '../dialog/user_selection_dialog.dart';
|
import '../dialog/user_selection_dialog.dart';
|
||||||
import '../itnerary/flights.dart';
|
import '../itnerary/flights.dart';
|
||||||
@ -909,8 +910,8 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
costCenterIds = costCenterMap.keys.toList();
|
costCenterIds = costCenterMap.keys.toList();
|
||||||
|
|
||||||
// Optionally auto-select the first item if not already selected
|
// Optionally auto-select the first item if not already selected
|
||||||
selectedCostCenterId ??=
|
// selectedCostCenterId ??=
|
||||||
costCenterIds.isNotEmpty ? costCenterIds.first : null;
|
// costCenterIds.isNotEmpty ? costCenterIds.first : null;
|
||||||
});
|
});
|
||||||
|
|
||||||
print('plansJSON');
|
print('plansJSON');
|
||||||
@ -1069,11 +1070,16 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
miscellaneousList,
|
miscellaneousList,
|
||||||
];
|
];
|
||||||
|
|
||||||
bool anyServiceSelected = serviceLists.any(
|
// bool anyServiceSelected = serviceLists.any(
|
||||||
(list) => list != null && list.isNotEmpty,
|
// (list) => list != null && list.isNotEmpty,
|
||||||
);
|
// );
|
||||||
|
bool anyServiceSelected = serviceLists.any((list) {
|
||||||
|
return list != null &&
|
||||||
|
list.any((entry) => entry['is_active'].toString() == "1");
|
||||||
|
});
|
||||||
|
|
||||||
if (!anyServiceSelected) {
|
if (!anyServiceSelected) {
|
||||||
// validationErrors["services"] = "Please select at least one service";
|
validationErrors["services"] = "Please select at least one service";
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
temporaryMessage = "Please select at least one service";
|
temporaryMessage = "Please select at least one service";
|
||||||
@ -1172,7 +1178,7 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void handleSubmit() {
|
void handleSubmit() {
|
||||||
setState(() {
|
setState(() async {
|
||||||
if (validateForm() && temporaryMessage == null) {
|
if (validateForm() && temporaryMessage == null) {
|
||||||
// if (selectedPlanId != null && selectedPlanId!.isNotEmpty) {
|
// if (selectedPlanId != null && selectedPlanId!.isNotEmpty) {
|
||||||
// planData['plan_id'] = selectedPlanId; // Add plan_id for update
|
// planData['plan_id'] = selectedPlanId; // Add plan_id for update
|
||||||
@ -1183,24 +1189,17 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
// "${planData['traveller_id']},"
|
// "${planData['traveller_id']},"
|
||||||
// " ${selectedPlanId}, "
|
// " ${selectedPlanId}, "
|
||||||
// " ");
|
// " ");
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
barrierDismissible: false,
|
||||||
|
builder: (context) => const SavingLoader(),
|
||||||
|
);
|
||||||
|
// postPlanData(planData);
|
||||||
|
|
||||||
postPlanData(planData);
|
await postPlanData(planData);
|
||||||
|
|
||||||
final currentUri =
|
// Close loading dialog (ONLY if still mounted)
|
||||||
GoRouterState.of(
|
if (mounted) Navigator.of(context, rootNavigator: true).pop();
|
||||||
context,
|
|
||||||
).uri.toString(); // ✅ safer than `.location`
|
|
||||||
print("currentUri - $currentUri");
|
|
||||||
|
|
||||||
if (currentUri == "/allTrips/trips") {
|
|
||||||
context.go('/listAllPlan');
|
|
||||||
} else if (currentUri == "/createPlan") {
|
|
||||||
context.go('/listPlan');
|
|
||||||
} else {
|
|
||||||
widget.isApprover
|
|
||||||
? context.go('/approvallist')
|
|
||||||
: context.go('/listPlan');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -1233,6 +1232,22 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
print("Plan submitted successfully!");
|
print("Plan submitted successfully!");
|
||||||
print("Response: ${response.body}");
|
print("Response: ${response.body}");
|
||||||
|
|
||||||
|
final currentUri =
|
||||||
|
GoRouterState.of(
|
||||||
|
context,
|
||||||
|
).uri.toString(); // ✅ safer than `.location`
|
||||||
|
print("currentUri - $currentUri");
|
||||||
|
|
||||||
|
if (currentUri == "/allTrips/trips") {
|
||||||
|
context.go('/listAllPlan');
|
||||||
|
} else if (currentUri == "/createPlan") {
|
||||||
|
context.go('/listPlan');
|
||||||
|
} else {
|
||||||
|
widget.isApprover
|
||||||
|
? context.go('/approvallist')
|
||||||
|
: context.go('/listPlan');
|
||||||
|
}
|
||||||
} 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}");
|
||||||
@ -2184,6 +2199,14 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
// ),
|
// ),
|
||||||
// ),
|
// ),
|
||||||
),
|
),
|
||||||
|
if (validationErrors["cost_center_id"] != null)
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(top: 4),
|
||||||
|
child: Text(
|
||||||
|
validationErrors["cost_center_id"]!,
|
||||||
|
style: GoogleFonts.poppins(fontSize: 12, color: Colors.red),
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(width: 25, height: 5),
|
SizedBox(width: 25, height: 5),
|
||||||
@ -2307,6 +2330,14 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
if (validationErrors["purpose_of_travel"] != null)
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(top: 4),
|
||||||
|
child: Text(
|
||||||
|
validationErrors["purpose_of_travel"]!,
|
||||||
|
style: GoogleFonts.poppins(fontSize: 12, color: Colors.red),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
// CustomTextFieldWrapper(
|
// CustomTextFieldWrapper(
|
||||||
// isFocused: false, // Dropdown doesn't use focus
|
// isFocused: false, // Dropdown doesn't use focus
|
||||||
@ -2466,6 +2497,14 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
if (validationErrors["functional_department"] != null)
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(top: 4),
|
||||||
|
child: Text(
|
||||||
|
validationErrors["functional_department"]!,
|
||||||
|
style: GoogleFonts.poppins(fontSize: 12, color: Colors.red),
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
@ -2475,7 +2514,7 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
List<Map<String, String>> options = [
|
List<Map<String, String>> options = [
|
||||||
{"title": "Self", "value": "Option 1"},
|
{"title": "Self", "value": "Option 1"},
|
||||||
{"title": "Other Employee", "value": "Option 2"},
|
{"title": "Other Employee", "value": "Option 2"},
|
||||||
{"title": "Others", "value": "Option 3"},
|
{"title": "Others (Non Employee)", "value": "Option 3"},
|
||||||
];
|
];
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
|||||||
@ -39,8 +39,8 @@ class DynamicItinerary extends StatefulWidget {
|
|||||||
final GlobalKey<FlightScreenState> flightScreenKey;
|
final GlobalKey<FlightScreenState> flightScreenKey;
|
||||||
final ValueNotifier<String?> tripTypeNotifier;
|
final ValueNotifier<String?> tripTypeNotifier;
|
||||||
|
|
||||||
const DynamicItinerary(
|
const DynamicItinerary({
|
||||||
{super.key,
|
super.key,
|
||||||
required this.apiData,
|
required this.apiData,
|
||||||
required this.onItineraryUpdate,
|
required this.onItineraryUpdate,
|
||||||
required this.apiCountryData,
|
required this.apiCountryData,
|
||||||
@ -51,7 +51,8 @@ class DynamicItinerary extends StatefulWidget {
|
|||||||
this.tripType,
|
this.tripType,
|
||||||
this.apiDataForClass,
|
this.apiDataForClass,
|
||||||
required this.tripTypeNotifier,
|
required this.tripTypeNotifier,
|
||||||
required this.flightScreenKey});
|
required this.flightScreenKey,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
DynamicItineraryState createState() => DynamicItineraryState();
|
DynamicItineraryState createState() => DynamicItineraryState();
|
||||||
@ -135,7 +136,8 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
|||||||
if (rawServices != null && rawServices is String) {
|
if (rawServices != null && rawServices is String) {
|
||||||
try {
|
try {
|
||||||
List<dynamic> decoded = json.decode(rawServices);
|
List<dynamic> decoded = json.decode(rawServices);
|
||||||
List<Map<String, String>> formatted = decoded
|
List<Map<String, String>> formatted =
|
||||||
|
decoded
|
||||||
.map((e) => {"service_id": e['service_id'].toString()})
|
.map((e) => {"service_id": e['service_id'].toString()})
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
@ -168,7 +170,7 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
|||||||
"insurance",
|
"insurance",
|
||||||
"visa",
|
"visa",
|
||||||
"miscellaneous",
|
"miscellaneous",
|
||||||
"taxi"
|
"taxi",
|
||||||
];
|
];
|
||||||
} else {
|
} else {
|
||||||
// tripType is null or not 1/2, allow everything
|
// tripType is null or not 1/2, allow everything
|
||||||
@ -242,21 +244,25 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
|||||||
final selectedIds =
|
final selectedIds =
|
||||||
selectedOrgServiceIds.map((e) => e['service_id']).toSet();
|
selectedOrgServiceIds.map((e) => e['service_id']).toSet();
|
||||||
|
|
||||||
final additionalServices = selectedAllServices!.where((service) {
|
final additionalServices =
|
||||||
|
selectedAllServices!.where((service) {
|
||||||
final name = (service['name'] ?? "").toString().toLowerCase();
|
final name = (service['name'] ?? "").toString().toLowerCase();
|
||||||
final id = service['service_id'].toString();
|
final id = service['service_id'].toString();
|
||||||
final isNameAllowed =
|
final isNameAllowed =
|
||||||
allowedServiceNames.isEmpty || allowedServiceNames.contains(name);
|
allowedServiceNames.isEmpty ||
|
||||||
|
allowedServiceNames.contains(name);
|
||||||
return filledItineraryKeys.contains(name) &&
|
return filledItineraryKeys.contains(name) &&
|
||||||
!selectedIds.contains(id) &&
|
!selectedIds.contains(id) &&
|
||||||
isNameAllowed;
|
isNameAllowed;
|
||||||
}).toList();
|
}).toList();
|
||||||
|
|
||||||
final originalFiltered = selectedAllServices!.where((service) {
|
final originalFiltered =
|
||||||
|
selectedAllServices!.where((service) {
|
||||||
final name = (service['name'] ?? "").toString().toLowerCase();
|
final name = (service['name'] ?? "").toString().toLowerCase();
|
||||||
final id = service['service_id'].toString();
|
final id = service['service_id'].toString();
|
||||||
final isNameAllowed =
|
final isNameAllowed =
|
||||||
allowedServiceNames.isEmpty || allowedServiceNames.contains(name);
|
allowedServiceNames.isEmpty ||
|
||||||
|
allowedServiceNames.contains(name);
|
||||||
return selectedIds.contains(id) && isNameAllowed;
|
return selectedIds.contains(id) && isNameAllowed;
|
||||||
}).toList();
|
}).toList();
|
||||||
|
|
||||||
@ -266,21 +272,25 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
print(
|
print(
|
||||||
"Services chosen based on filled keys + selected: $ServicesChoosed");
|
"Services chosen based on filled keys + selected: $ServicesChoosed",
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
final selectedIds =
|
final selectedIds =
|
||||||
selectedOrgServiceIds.map((e) => e['service_id']).toSet();
|
selectedOrgServiceIds.map((e) => e['service_id']).toSet();
|
||||||
|
|
||||||
final filtered = selectedAllServices!.where((service) {
|
final filtered =
|
||||||
|
selectedAllServices!.where((service) {
|
||||||
final name = (service['name'] ?? "").toString().toLowerCase();
|
final name = (service['name'] ?? "").toString().toLowerCase();
|
||||||
final isNameAllowed =
|
final isNameAllowed =
|
||||||
allowedServiceNames.isEmpty || allowedServiceNames.contains(name);
|
allowedServiceNames.isEmpty ||
|
||||||
|
allowedServiceNames.contains(name);
|
||||||
return selectedIds.contains(service['service_id'].toString()) &&
|
return selectedIds.contains(service['service_id'].toString()) &&
|
||||||
isNameAllowed;
|
isNameAllowed;
|
||||||
}).toList();
|
}).toList();
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
ServicesChoosed = filtered
|
ServicesChoosed =
|
||||||
|
filtered
|
||||||
..sort((a, b) => (a['order'] ?? 0).compareTo(b['order'] ?? 0));
|
..sort((a, b) => (a['order'] ?? 0).compareTo(b['order'] ?? 0));
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -296,23 +306,32 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
|||||||
setState(() {
|
setState(() {
|
||||||
itineraryData = {
|
itineraryData = {
|
||||||
"Train": List<Map<String, dynamic>>.from(
|
"Train": List<Map<String, dynamic>>.from(
|
||||||
widget.selectedPlanData['train'] ?? []),
|
widget.selectedPlanData['train'] ?? [],
|
||||||
|
),
|
||||||
"Bus": List<Map<String, dynamic>>.from(
|
"Bus": List<Map<String, dynamic>>.from(
|
||||||
widget.selectedPlanData['bus'] ?? []),
|
widget.selectedPlanData['bus'] ?? [],
|
||||||
|
),
|
||||||
"Taxi": List<Map<String, dynamic>>.from(
|
"Taxi": List<Map<String, dynamic>>.from(
|
||||||
widget.selectedPlanData['taxi'] ?? []),
|
widget.selectedPlanData['taxi'] ?? [],
|
||||||
|
),
|
||||||
"Miscellaneous": List<Map<String, dynamic>>.from(
|
"Miscellaneous": List<Map<String, dynamic>>.from(
|
||||||
widget.selectedPlanData['miscellaneous'] ?? []),
|
widget.selectedPlanData['miscellaneous'] ?? [],
|
||||||
|
),
|
||||||
"Flight": List<Map<String, dynamic>>.from(
|
"Flight": List<Map<String, dynamic>>.from(
|
||||||
widget.selectedPlanData['flight'] ?? []),
|
widget.selectedPlanData['flight'] ?? [],
|
||||||
|
),
|
||||||
"Accomodation": List<Map<String, dynamic>>.from(
|
"Accomodation": List<Map<String, dynamic>>.from(
|
||||||
widget.selectedPlanData['accomodation'] ?? []),
|
widget.selectedPlanData['accomodation'] ?? [],
|
||||||
|
),
|
||||||
"Insurance": List<Map<String, dynamic>>.from(
|
"Insurance": List<Map<String, dynamic>>.from(
|
||||||
widget.selectedPlanData['insurance'] ?? []),
|
widget.selectedPlanData['insurance'] ?? [],
|
||||||
|
),
|
||||||
"Visa": List<Map<String, dynamic>>.from(
|
"Visa": List<Map<String, dynamic>>.from(
|
||||||
widget.selectedPlanData['visa'] ?? []),
|
widget.selectedPlanData['visa'] ?? [],
|
||||||
|
),
|
||||||
"Forex": List<Map<String, dynamic>>.from(
|
"Forex": List<Map<String, dynamic>>.from(
|
||||||
widget.selectedPlanData['forex'] ?? []),
|
widget.selectedPlanData['forex'] ?? [],
|
||||||
|
),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@ -330,7 +349,7 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
|||||||
"accomodation",
|
"accomodation",
|
||||||
"insurance",
|
"insurance",
|
||||||
"visa",
|
"visa",
|
||||||
"forex"
|
"forex",
|
||||||
];
|
];
|
||||||
|
|
||||||
// for (String key in keys) {
|
// for (String key in keys) {
|
||||||
@ -416,7 +435,8 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
|||||||
if (existingId != null && existingId != 0) {
|
if (existingId != null && existingId != 0) {
|
||||||
// int itemId = itemList.indexWhere((item) => item["id"] == existingId);
|
// int itemId = itemList.indexWhere((item) => item["id"] == existingId);
|
||||||
int itemId = itemList.indexWhere(
|
int itemId = itemList.indexWhere(
|
||||||
(item) => item[idKey]?.toString() == existingId.toString());
|
(item) => item[idKey]?.toString() == existingId.toString(),
|
||||||
|
);
|
||||||
|
|
||||||
if (itemId != -1) {
|
if (itemId != -1) {
|
||||||
print(" Updating existing item with id: $existingId");
|
print(" Updating existing item with id: $existingId");
|
||||||
@ -428,8 +448,9 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
|||||||
|
|
||||||
// CASE 1: Update if indx exists in list
|
// CASE 1: Update if indx exists in list
|
||||||
if (existingIndex != null && existingIndex != 0) {
|
if (existingIndex != null && existingIndex != 0) {
|
||||||
int itemIndex =
|
int itemIndex = itemList.indexWhere(
|
||||||
itemList.indexWhere((item) => item["indx"] == existingIndex);
|
(item) => item["indx"] == existingIndex,
|
||||||
|
);
|
||||||
if (itemIndex != -1) {
|
if (itemIndex != -1) {
|
||||||
print("Updating existing item with indx: $existingIndex");
|
print("Updating existing item with indx: $existingIndex");
|
||||||
newData["is_active"] = "1";
|
newData["is_active"] = "1";
|
||||||
@ -494,6 +515,7 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
|||||||
});
|
});
|
||||||
print(" onItineraryUpdate - $type - ${itineraryData[type]!} ");
|
print(" onItineraryUpdate - $type - ${itineraryData[type]!} ");
|
||||||
widget.onItineraryUpdate(type, itineraryData[type]!); // Notify parent
|
widget.onItineraryUpdate(type, itineraryData[type]!); // Notify parent
|
||||||
|
print("ItienreayDATE - $itineraryData");
|
||||||
}
|
}
|
||||||
|
|
||||||
// void handleItineraryUpdate(String type, Map<String, dynamic> newData) {
|
// void handleItineraryUpdate(String type, Map<String, dynamic> newData) {
|
||||||
@ -583,8 +605,8 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
|||||||
onOpen: handleEdit,
|
onOpen: handleEdit,
|
||||||
onAddNew: handlecreateNewPlan,
|
onAddNew: handlecreateNewPlan,
|
||||||
isViewMode: widget.isViewMode,
|
isViewMode: widget.isViewMode,
|
||||||
onDeleteAccommodation: (data) =>
|
onDeleteAccommodation:
|
||||||
handleItinerarydelete("Accomodation", data),
|
(data) => handleItinerarydelete("Accomodation", data),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case "Miscellaneous":
|
case "Miscellaneous":
|
||||||
@ -594,8 +616,8 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
|||||||
isViewMode: widget.isViewMode,
|
isViewMode: widget.isViewMode,
|
||||||
onAddNew: handlecreateNewPlan,
|
onAddNew: handlecreateNewPlan,
|
||||||
apiData: widget.apiData,
|
apiData: widget.apiData,
|
||||||
onDeleteMiscellaneous: (data) =>
|
onDeleteMiscellaneous:
|
||||||
handleItinerarydelete("Miscellaneous", data),
|
(data) => handleItinerarydelete("Miscellaneous", data),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case "Flight":
|
case "Flight":
|
||||||
@ -608,7 +630,8 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
|||||||
onAddNew: handlecreateNewPlan,
|
onAddNew: handlecreateNewPlan,
|
||||||
isViewMode: widget.isViewMode,
|
isViewMode: widget.isViewMode,
|
||||||
apiData: widget.apiData,
|
apiData: widget.apiData,
|
||||||
onDeleteFlight: (data) => handleItinerarydelete("Flight", data));
|
onDeleteFlight: (data) => handleItinerarydelete("Flight", data),
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -621,7 +644,8 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
|||||||
loginUser: widget.loginUser,
|
loginUser: widget.loginUser,
|
||||||
onSavetrain: (data) => handleItineraryUpdate("Train", data),
|
onSavetrain: (data) => handleItineraryUpdate("Train", data),
|
||||||
tripType: widget.tripType,
|
tripType: widget.tripType,
|
||||||
selectedItem: selectedItem);
|
selectedItem: selectedItem,
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
case "Taxi":
|
case "Taxi":
|
||||||
selectedWidget = TaxiScreen(
|
selectedWidget = TaxiScreen(
|
||||||
@ -629,7 +653,8 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
|||||||
apiData: widget.apiData,
|
apiData: widget.apiData,
|
||||||
loginUser: widget.loginUser,
|
loginUser: widget.loginUser,
|
||||||
onSavetaxi: (data) => handleItineraryUpdate("Taxi", data),
|
onSavetaxi: (data) => handleItineraryUpdate("Taxi", data),
|
||||||
selectedItem: selectedItem);
|
selectedItem: selectedItem,
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
case "Bus":
|
case "Bus":
|
||||||
selectedWidget = BusScreen(
|
selectedWidget = BusScreen(
|
||||||
@ -637,7 +662,8 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
|||||||
apiData: widget.apiData,
|
apiData: widget.apiData,
|
||||||
loginUser: widget.loginUser,
|
loginUser: widget.loginUser,
|
||||||
onSaveBus: (data) => handleItineraryUpdate("Bus", data),
|
onSaveBus: (data) => handleItineraryUpdate("Bus", data),
|
||||||
selectedItem: selectedItem);
|
selectedItem: selectedItem,
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
case "Insurance":
|
case "Insurance":
|
||||||
selectedWidget = InsuranceScreen(
|
selectedWidget = InsuranceScreen(
|
||||||
@ -666,8 +692,8 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
|||||||
onClose: handleClose,
|
onClose: handleClose,
|
||||||
apiData: widget.apiData,
|
apiData: widget.apiData,
|
||||||
loginUser: widget.loginUser,
|
loginUser: widget.loginUser,
|
||||||
onSaveMiscellaneous: (data) =>
|
onSaveMiscellaneous:
|
||||||
handleItineraryUpdate("Miscellaneous", data),
|
(data) => handleItineraryUpdate("Miscellaneous", data),
|
||||||
selectedItem: selectedItem,
|
selectedItem: selectedItem,
|
||||||
selectedIndex: selectedIndex,
|
selectedIndex: selectedIndex,
|
||||||
);
|
);
|
||||||
@ -676,8 +702,8 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
|||||||
selectedWidget = AccomodationScreen(
|
selectedWidget = AccomodationScreen(
|
||||||
onClose: handleClose,
|
onClose: handleClose,
|
||||||
loginUser: widget.loginUser,
|
loginUser: widget.loginUser,
|
||||||
onSaveAccomadation: (data) =>
|
onSaveAccomadation:
|
||||||
handleItineraryUpdate("Accomodation", data),
|
(data) => handleItineraryUpdate("Accomodation", data),
|
||||||
selectedItem: selectedItem,
|
selectedItem: selectedItem,
|
||||||
flightData: itineraryData["Flight"]!,
|
flightData: itineraryData["Flight"]!,
|
||||||
);
|
);
|
||||||
@ -776,7 +802,8 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
|||||||
// );
|
// );
|
||||||
// });
|
// });
|
||||||
|
|
||||||
return ResponsiveBuilder(builder: (context, sizingInfo) {
|
return ResponsiveBuilder(
|
||||||
|
builder: (context, sizingInfo) {
|
||||||
bool isMobile = sizingInfo.isMobile;
|
bool isMobile = sizingInfo.isMobile;
|
||||||
|
|
||||||
return Stack(
|
return Stack(
|
||||||
@ -785,7 +812,8 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
|||||||
// Second container (yellow box)
|
// Second container (yellow box)
|
||||||
Container(
|
Container(
|
||||||
margin: EdgeInsets.only(
|
margin: EdgeInsets.only(
|
||||||
top: 40), // Push it down to make room for the tab bar
|
top: 40,
|
||||||
|
), // Push it down to make room for the tab bar
|
||||||
padding: EdgeInsets.all(12),
|
padding: EdgeInsets.all(12),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.white, // Card background
|
color: Colors.white, // Card background
|
||||||
@ -835,12 +863,11 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
child: isMobile
|
child:
|
||||||
|
isMobile
|
||||||
? SingleChildScrollView(
|
? SingleChildScrollView(
|
||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: Axis.horizontal,
|
||||||
child: Row(
|
child: Row(children: _buildOptions()),
|
||||||
children: _buildOptions(),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
: Row(
|
: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
@ -850,11 +877,31 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
});
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasValidItineraryEntries() {
|
||||||
|
if (ServicesChoosed == null || ServicesChoosed!.isEmpty) return false;
|
||||||
|
|
||||||
|
for (var service in ServicesChoosed!) {
|
||||||
|
final serviceName = service['name'];
|
||||||
|
final entries = itineraryData[serviceName];
|
||||||
|
|
||||||
|
// Check if there is at least one active entry (is_active == 1)
|
||||||
|
final hasActive =
|
||||||
|
entries?.any((entry) => entry['is_active'] == 1) ?? false;
|
||||||
|
|
||||||
|
if (!hasActive) {
|
||||||
|
return false; // Fail fast if any one service has no active entries
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true; // All selected services have at least one active entry
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> _buildOptions() {
|
List<Widget> _buildOptions() {
|
||||||
if (ServicesChoosed == null) return [];
|
if (ServicesChoosed == null && !hasValidItineraryEntries()) return [];
|
||||||
|
|
||||||
if (ServicesChoosed != null &&
|
if (ServicesChoosed != null &&
|
||||||
ServicesChoosed!.isNotEmpty &&
|
ServicesChoosed!.isNotEmpty &&
|
||||||
@ -875,18 +922,28 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
return ServicesChoosed!.map((service) {
|
return ServicesChoosed!.map((service) {
|
||||||
|
final serviceName = service['name'];
|
||||||
|
final serviceEntries = itineraryData[serviceName];
|
||||||
|
|
||||||
|
final hasActive =
|
||||||
|
serviceEntries?.any((entry) => entry['is_active'] == "1") ?? false;
|
||||||
|
|
||||||
|
print("Service1: $serviceName");
|
||||||
|
print("Entries1: $serviceEntries");
|
||||||
|
print("Has Active1: $hasActive");
|
||||||
|
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.only(right: 20.0),
|
padding: const EdgeInsets.only(right: 20.0),
|
||||||
child: _buildOption(
|
child: _buildOption(
|
||||||
service, itineraryData[service['name']]?.isNotEmpty ?? false),
|
service,
|
||||||
|
hasActive,
|
||||||
|
// itineraryData[service['name']]?.isNotEmpty ?? false,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}).toList();
|
}).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildOption(
|
Widget _buildOption(Map<String, dynamic> service, bool hasData) {
|
||||||
Map<String, dynamic> service,
|
|
||||||
bool hasData,
|
|
||||||
) {
|
|
||||||
String name = service['name'];
|
String name = service['name'];
|
||||||
String iconUrl = service['icon']; // Can be empty string
|
String iconUrl = service['icon']; // Can be empty string
|
||||||
IconData fallbackIcon = _getLocalIconForService(name);
|
IconData fallbackIcon = _getLocalIconForService(name);
|
||||||
@ -921,7 +978,8 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
|||||||
return Icon(
|
return Icon(
|
||||||
fallbackIcon,
|
fallbackIcon,
|
||||||
size: 25,
|
size: 25,
|
||||||
color: isOptionSelected
|
color:
|
||||||
|
isOptionSelected
|
||||||
? Color(0xFF114D8B)
|
? Color(0xFF114D8B)
|
||||||
: Color(0xFF475569),
|
: Color(0xFF475569),
|
||||||
);
|
);
|
||||||
@ -930,9 +988,8 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
|||||||
: Icon(
|
: Icon(
|
||||||
fallbackIcon,
|
fallbackIcon,
|
||||||
size: 25,
|
size: 25,
|
||||||
color: isOptionSelected
|
color:
|
||||||
? Color(0xFF114D8B)
|
isOptionSelected ? Color(0xFF114D8B) : Color(0xFF475569),
|
||||||
: Color(0xFF475569),
|
|
||||||
),
|
),
|
||||||
SizedBox(height: 2),
|
SizedBox(height: 2),
|
||||||
Row(
|
Row(
|
||||||
@ -943,10 +1000,10 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
|||||||
// style: GoogleFonts.poppins( fontSize: 12,
|
// style: GoogleFonts.poppins( fontSize: 12,
|
||||||
// fontWeight: FontWeight.w600,
|
// fontWeight: FontWeight.w600,
|
||||||
// color: Color(0xFF575A74))
|
// color: Color(0xFF575A74))
|
||||||
|
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: isOptionSelected
|
color:
|
||||||
|
isOptionSelected
|
||||||
? Color(0xFF114D8B)
|
? Color(0xFF114D8B)
|
||||||
: Color(0xFF475569),
|
: Color(0xFF475569),
|
||||||
fontFamily: "Inter",
|
fontFamily: "Inter",
|
||||||
@ -964,86 +1021,87 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildOption1(
|
// Widget _buildOption1(
|
||||||
Map<String, dynamic> service,
|
// Map<String, dynamic> service,
|
||||||
bool hasData,
|
// bool hasData,
|
||||||
) {
|
// )
|
||||||
String name = service['name'];
|
// {
|
||||||
String iconUrl = service['icon']; // Can be empty string
|
// String name = service['name'];
|
||||||
// Optional: define local icon fallback if iconUrl is empty
|
// String iconUrl = service['icon']; // Can be empty string
|
||||||
IconData fallbackIcon = _getLocalIconForService(name);
|
// // Optional: define local icon fallback if iconUrl is empty
|
||||||
// final idMap = {"service_id": service['service_id'].toString()};
|
// IconData fallbackIcon = _getLocalIconForService(name);
|
||||||
// final isSelected = selectedServiceIds.contains(idMap);
|
// // final idMap = {"service_id": service['service_id'].toString()};
|
||||||
|
// // final isSelected = selectedServiceIds.contains(idMap);
|
||||||
String serviceId = service['service_id'].toString();
|
//
|
||||||
// bool isSelected = selectedServiceIds.contains(serviceId);
|
// String serviceId = service['service_id'].toString();
|
||||||
// bool isSelected =
|
// // bool isSelected = selectedServiceIds.contains(serviceId);
|
||||||
// selectedServiceIds.any((item) => item["service_id"] == serviceId);
|
// // bool isSelected =
|
||||||
|
// // selectedServiceIds.any((item) => item["service_id"] == serviceId);
|
||||||
return GestureDetector(
|
//
|
||||||
onTap: () {
|
// return GestureDetector(
|
||||||
setState(() {
|
// onTap: () {
|
||||||
selectedListOption = name;
|
// setState(() {
|
||||||
isSelected = false;
|
// selectedListOption = name;
|
||||||
});
|
// isSelected = false;
|
||||||
},
|
// });
|
||||||
child: Row(children: [
|
// },
|
||||||
iconUrl.isNotEmpty
|
// child: Row(children: [
|
||||||
? Image.network(
|
// iconUrl.isNotEmpty
|
||||||
iconUrl,
|
// ? Image.network(
|
||||||
width: 18,
|
// iconUrl,
|
||||||
height: 18,
|
// width: 18,
|
||||||
errorBuilder: (context, error, stackTrace) {
|
// height: 18,
|
||||||
return Icon(
|
// errorBuilder: (context, error, stackTrace) {
|
||||||
fallbackIcon,
|
// return Icon(
|
||||||
size: 18,
|
// fallbackIcon,
|
||||||
color: selectedListOption == name
|
// size: 18,
|
||||||
? Color(0xFF114D8B)
|
// color: selectedListOption == name
|
||||||
: Color(0xFF475569),
|
// ? Color(0xFF114D8B)
|
||||||
);
|
// : Color(0xFF475569),
|
||||||
},
|
// );
|
||||||
)
|
// },
|
||||||
: Icon(
|
// )
|
||||||
fallbackIcon,
|
// : Icon(
|
||||||
size: 18,
|
// fallbackIcon,
|
||||||
color: selectedListOption == name
|
// size: 18,
|
||||||
? Color(0xFF114D8B)
|
// color: selectedListOption == name
|
||||||
: Color(0xFF475569),
|
// ? Color(0xFF114D8B)
|
||||||
),
|
// : Color(0xFF475569),
|
||||||
|
// ),
|
||||||
SizedBox(width: 2),
|
//
|
||||||
Text(
|
// SizedBox(width: 2),
|
||||||
name,
|
// Text(
|
||||||
style: TextStyle(
|
// name,
|
||||||
fontSize: 14,
|
// style: TextStyle(
|
||||||
// color: selectedListOption == title ? Colors.blueAccent : Color(0xFF575A74),
|
// fontSize: 14,
|
||||||
color: selectedListOption == name
|
// // color: selectedListOption == title ? Colors.blueAccent : Color(0xFF575A74),
|
||||||
? Color(0xFF114D8B)
|
// color: selectedListOption == name
|
||||||
: Color(0xFF475569),
|
// ? Color(0xFF114D8B)
|
||||||
fontFamily: "Archivo",
|
// : Color(0xFF475569),
|
||||||
fontWeight: selectedListOption == name
|
// fontFamily: "Archivo",
|
||||||
? FontWeight.bold
|
// fontWeight: selectedListOption == name
|
||||||
: FontWeight.w500),
|
// ? FontWeight.bold
|
||||||
// fontWeight: selectedListOption == title ? FontWeight.bold : FontWeight.normal,)),
|
// : FontWeight.w500),
|
||||||
),
|
// // fontWeight: selectedListOption == title ? FontWeight.bold : FontWeight.normal,)),
|
||||||
|
// ),
|
||||||
SizedBox(width: 2),
|
//
|
||||||
// if (selectedListOption == title && widget.isViewMode == false)
|
// SizedBox(width: 2),
|
||||||
if (hasData)
|
// // if (selectedListOption == title && widget.isViewMode == false)
|
||||||
Icon(Icons.circle, size: 8, color: Colors.green
|
// if (hasData)
|
||||||
// color: Colors.grey,
|
// Icon(Icons.circle, size: 8, color: Colors.green
|
||||||
)
|
// // color: Colors.grey,
|
||||||
// Container(
|
// )
|
||||||
// height: 10,
|
// // Container(
|
||||||
// width: 10,
|
// // height: 10,
|
||||||
// // decoration: BoxDecoration(
|
// // width: 10,
|
||||||
// // shape: BoxShape.circle,
|
// // // decoration: BoxDecoration(
|
||||||
// // border: Border.all(color: Colors.green, width: 1.5),
|
// // // shape: BoxShape.circle,
|
||||||
// // ),
|
// // // border: Border.all(color: Colors.green, width: 1.5),
|
||||||
// child:),
|
// // // ),
|
||||||
]),
|
// // child:),
|
||||||
);
|
// ]),
|
||||||
}
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
IconData _getLocalIconForService(String name) {
|
IconData _getLocalIconForService(String name) {
|
||||||
switch (name.toLowerCase()) {
|
switch (name.toLowerCase()) {
|
||||||
|
|||||||
@ -79,14 +79,15 @@ class _PolicyState extends State<Policy> {
|
|||||||
List<Map<String, dynamic>>? policy_details = [];
|
List<Map<String, dynamic>>? policy_details = [];
|
||||||
|
|
||||||
Map<String, dynamic> get policyData {
|
Map<String, dynamic> get policyData {
|
||||||
List<Map<String, dynamic>> policyDetails = policy_details!.where((service) {
|
List<Map<String, dynamic>> policyDetails =
|
||||||
|
policy_details!.where((service) {
|
||||||
// Only check these specific fields for emptiness
|
// Only check these specific fields for emptiness
|
||||||
final fieldsToCheck = [
|
final fieldsToCheck = [
|
||||||
'cost',
|
'cost',
|
||||||
'class',
|
'class',
|
||||||
'a1_action',
|
'a1_action',
|
||||||
'a2_action',
|
'a2_action',
|
||||||
'a3_action'
|
'a3_action',
|
||||||
];
|
];
|
||||||
|
|
||||||
// If any of the important fields has a value, keep it
|
// If any of the important fields has a value, keep it
|
||||||
@ -124,8 +125,9 @@ class _PolicyState extends State<Policy> {
|
|||||||
loadInitialData();
|
loadInitialData();
|
||||||
|
|
||||||
if (widget.policy != null) {
|
if (widget.policy != null) {
|
||||||
final details =
|
final details = List<Map<String, dynamic>>.from(
|
||||||
List<Map<String, dynamic>>.from(widget.policy!['policy_details']);
|
widget.policy!['policy_details'],
|
||||||
|
);
|
||||||
policyCriteriaKey.currentState?.loadPolicyDetails(details);
|
policyCriteriaKey.currentState?.loadPolicyDetails(details);
|
||||||
|
|
||||||
policyCriteriaKey.currentState?.fetchTrainFlightClass();
|
policyCriteriaKey.currentState?.fetchTrainFlightClass();
|
||||||
@ -138,11 +140,13 @@ class _PolicyState extends State<Policy> {
|
|||||||
String? bodyStringColor = await getBodyColor();
|
String? bodyStringColor = await getBodyColor();
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
layoutColor = layoutString != null
|
layoutColor =
|
||||||
|
layoutString != null
|
||||||
? Color(int.parse(layoutString))
|
? Color(int.parse(layoutString))
|
||||||
: Colors.redAccent;
|
: Colors.redAccent;
|
||||||
|
|
||||||
bodyColor = bodyStringColor != null
|
bodyColor =
|
||||||
|
bodyStringColor != null
|
||||||
? Color(int.parse(bodyStringColor))
|
? Color(int.parse(bodyStringColor))
|
||||||
: Colors.white;
|
: Colors.white;
|
||||||
});
|
});
|
||||||
@ -175,7 +179,8 @@ class _PolicyState extends State<Policy> {
|
|||||||
if (rawServices != null && rawServices is String) {
|
if (rawServices != null && rawServices is String) {
|
||||||
try {
|
try {
|
||||||
List<dynamic> decoded = json.decode(rawServices);
|
List<dynamic> decoded = json.decode(rawServices);
|
||||||
List<Map<String, String>> formatted = decoded
|
List<Map<String, String>> formatted =
|
||||||
|
decoded
|
||||||
.map((e) => {"service_id": e['service_id'].toString()})
|
.map((e) => {"service_id": e['service_id'].toString()})
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
@ -205,16 +210,21 @@ class _PolicyState extends State<Policy> {
|
|||||||
selectedOrgServiceIds.map((e) => e['service_id']).toSet();
|
selectedOrgServiceIds.map((e) => e['service_id']).toSet();
|
||||||
|
|
||||||
if (widget.policy != null) {
|
if (widget.policy != null) {
|
||||||
final details =
|
final details = List<Map<String, dynamic>>.from(
|
||||||
List<Map<String, dynamic>>.from(widget.policy!['policy_details']);
|
widget.policy!['policy_details'],
|
||||||
|
);
|
||||||
|
|
||||||
print(
|
print(
|
||||||
"UUFiltered Selected Services - ${widget.policy!['services_ids']} ");
|
"UUFiltered Selected Services - ${widget.policy!['services_ids']} ",
|
||||||
|
);
|
||||||
// pr int("UUFiltered Selected Services - $details");
|
// pr int("UUFiltered Selected Services - $details");
|
||||||
|
|
||||||
final filtered = selectedAllServices!
|
final filtered =
|
||||||
.where((service) =>
|
selectedAllServices!
|
||||||
selectedIds.contains(service['service_id'].toString()))
|
.where(
|
||||||
|
(service) =>
|
||||||
|
selectedIds.contains(service['service_id'].toString()),
|
||||||
|
)
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
@ -236,12 +246,15 @@ class _PolicyState extends State<Policy> {
|
|||||||
final decoded = jsonDecode(widget.policy!['services_ids']);
|
final decoded = jsonDecode(widget.policy!['services_ids']);
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
services = List<Map<String, dynamic>>.from(decoded)
|
services =
|
||||||
.map((service) => {
|
List<Map<String, dynamic>>.from(decoded)
|
||||||
|
.map(
|
||||||
|
(service) => {
|
||||||
'service_id': service['service_id'].toString(),
|
'service_id': service['service_id'].toString(),
|
||||||
'name': service['name'].toString(),
|
'name': service['name'].toString(),
|
||||||
'order': service['order'].toString(),
|
'order': service['order'].toString(),
|
||||||
})
|
},
|
||||||
|
)
|
||||||
.toList();
|
.toList();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -250,9 +263,12 @@ class _PolicyState extends State<Policy> {
|
|||||||
|
|
||||||
print("Filtered Selected Services Added to Policy: $ServicesChoosed");
|
print("Filtered Selected Services Added to Policy: $ServicesChoosed");
|
||||||
} else {
|
} else {
|
||||||
final filtered = selectedAllServices!
|
final filtered =
|
||||||
.where((service) =>
|
selectedAllServices!
|
||||||
selectedIds.contains(service['service_id'].toString()))
|
.where(
|
||||||
|
(service) =>
|
||||||
|
selectedIds.contains(service['service_id'].toString()),
|
||||||
|
)
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
print("ServicesChoosedYY: $ServicesChoosed");
|
print("ServicesChoosedYY: $ServicesChoosed");
|
||||||
@ -264,13 +280,16 @@ class _PolicyState extends State<Policy> {
|
|||||||
|
|
||||||
// ServicesChoosed = filtered;
|
// ServicesChoosed = filtered;
|
||||||
|
|
||||||
services = ServicesChoosed!
|
services =
|
||||||
.map((service) => {
|
ServicesChoosed!
|
||||||
|
.map(
|
||||||
|
(service) => {
|
||||||
'service_id': service['service_id'].toString(),
|
'service_id': service['service_id'].toString(),
|
||||||
'name':
|
'name':
|
||||||
service['name'].toString(), // ✅ no space before 'name'
|
service['name'].toString(), // ✅ no space before 'name'
|
||||||
'order': service['order'].toString(),
|
'order': service['order'].toString(),
|
||||||
})
|
},
|
||||||
|
)
|
||||||
.toList();
|
.toList();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -336,7 +355,7 @@ class _PolicyState extends State<Policy> {
|
|||||||
|
|
||||||
// Validate required fields
|
// Validate required fields
|
||||||
if (data["name"] == null || data["name"].toString().trim().isEmpty) {
|
if (data["name"] == null || data["name"].toString().trim().isEmpty) {
|
||||||
errorMessages["name"] = "Policy name is required.";
|
errorMessages["name"] = "Required"; // "Policy name is required.";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate that either domestic or international is selected
|
// Validate that either domestic or international is selected
|
||||||
@ -344,10 +363,12 @@ class _PolicyState extends State<Policy> {
|
|||||||
final international = data["international"]?.toString() ?? "0";
|
final international = data["international"]?.toString() ?? "0";
|
||||||
|
|
||||||
print(
|
print(
|
||||||
"domestic: ${data["domestic"]}, international: ${data["international"]}");
|
"domestic: ${data["domestic"]}, international: ${data["international"]}",
|
||||||
|
);
|
||||||
|
|
||||||
if (domestic != "1" && international != "1") {
|
if (domestic != "1" && international != "1") {
|
||||||
errorMessages["trip_type"] = "Please select Domestic or International.";
|
errorMessages["trip_type"] =
|
||||||
|
"Required"; // "Please select Domestic or International.";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate at least one policy_detail with valid content
|
// Validate at least one policy_detail with valid content
|
||||||
@ -359,7 +380,7 @@ class _PolicyState extends State<Policy> {
|
|||||||
'class',
|
'class',
|
||||||
'a1_action',
|
'a1_action',
|
||||||
'a2_action',
|
'a2_action',
|
||||||
'a3_action'
|
'a3_action',
|
||||||
];
|
];
|
||||||
return fieldsToCheck.any((field) {
|
return fieldsToCheck.any((field) {
|
||||||
final value = service[field];
|
final value = service[field];
|
||||||
@ -369,7 +390,7 @@ class _PolicyState extends State<Policy> {
|
|||||||
|
|
||||||
if (!hasAtLeastOneDetail) {
|
if (!hasAtLeastOneDetail) {
|
||||||
errorMessages["policy_details"] =
|
errorMessages["policy_details"] =
|
||||||
"At least one valid policy detail is required.";
|
"Required"; // "At least one valid policy detail is required.";
|
||||||
}
|
}
|
||||||
|
|
||||||
return errorMessages.isEmpty;
|
return errorMessages.isEmpty;
|
||||||
@ -424,19 +445,24 @@ class _PolicyState extends State<Policy> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ResponsiveBuilder(builder: (context, sizingInfo) {
|
return ResponsiveBuilder(
|
||||||
bool isDesktop = sizingInfo.deviceScreenType == DeviceScreenType.desktop;
|
builder: (context, sizingInfo) {
|
||||||
|
bool isDesktop =
|
||||||
|
sizingInfo.deviceScreenType == DeviceScreenType.desktop;
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: Color(0xFFf5f5f5),
|
backgroundColor: Color(0xFFf5f5f5),
|
||||||
appBar: CustomAppBar(isDesktop: isDesktop),
|
appBar: CustomAppBar(isDesktop: isDesktop),
|
||||||
drawer: CustomDrawer(isDesktop: false),
|
drawer: CustomDrawer(isDesktop: false),
|
||||||
body: Padding(
|
body: Padding(
|
||||||
padding: isDesktop
|
padding:
|
||||||
|
isDesktop
|
||||||
? EdgeInsets.symmetric(
|
? EdgeInsets.symmetric(
|
||||||
horizontal: MediaQuery.of(context).size.width *
|
horizontal:
|
||||||
|
MediaQuery.of(context).size.width *
|
||||||
0.1, // 30% of screen width as horizontal padding
|
0.1, // 30% of screen width as horizontal padding
|
||||||
vertical: MediaQuery.of(context).size.height *
|
vertical:
|
||||||
|
MediaQuery.of(context).size.height *
|
||||||
0, // 5% of screen height as vertical padding
|
0, // 5% of screen height as vertical padding
|
||||||
)
|
)
|
||||||
: EdgeInsets.all(8),
|
: EdgeInsets.all(8),
|
||||||
@ -446,7 +472,6 @@ class _PolicyState extends State<Policy> {
|
|||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
// if (isDesktop) CustomDrawer(isDesktop: true),
|
// if (isDesktop) CustomDrawer(isDesktop: true),
|
||||||
|
|
||||||
Expanded(child: buildData(isDesktop, context)),
|
Expanded(child: buildData(isDesktop, context)),
|
||||||
// Expanded(
|
// Expanded(
|
||||||
// child: Container(
|
// child: Container(
|
||||||
@ -493,7 +518,8 @@ class _PolicyState extends State<Policy> {
|
|||||||
// ],
|
// ],
|
||||||
// ),
|
// ),
|
||||||
);
|
);
|
||||||
});
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildData(bool isDesktop, context) {
|
Widget buildData(bool isDesktop, context) {
|
||||||
@ -524,7 +550,8 @@ class _PolicyState extends State<Policy> {
|
|||||||
Container(
|
Container(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
child: isDesktop
|
child:
|
||||||
|
isDesktop
|
||||||
? Row(
|
? Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
children: _buildSubmit(isDesktop),
|
children: _buildSubmit(isDesktop),
|
||||||
@ -544,7 +571,8 @@ class _PolicyState extends State<Policy> {
|
|||||||
// margin: isDesktop
|
// margin: isDesktop
|
||||||
// ? EdgeInsets.all(10.0)
|
// ? EdgeInsets.all(10.0)
|
||||||
// : EdgeInsets.only(left: 20.0, bottom: 20.0, top: 10.0, right: 20.0),
|
// : EdgeInsets.only(left: 20.0, bottom: 20.0, top: 10.0, right: 20.0),
|
||||||
height: isDesktop
|
height:
|
||||||
|
isDesktop
|
||||||
? MediaQuery.of(context).size.height * 0.98
|
? MediaQuery.of(context).size.height * 0.98
|
||||||
: MediaQuery.of(context).size.height,
|
: MediaQuery.of(context).size.height,
|
||||||
// decoration: BoxDecoration(
|
// decoration: BoxDecoration(
|
||||||
@ -582,7 +610,8 @@ class _PolicyState extends State<Policy> {
|
|||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -593,7 +622,8 @@ class _PolicyState extends State<Policy> {
|
|||||||
isDesktop ? SizedBox(height: 0) : SizedBox(height: 5),
|
isDesktop ? SizedBox(height: 0) : SizedBox(height: 5),
|
||||||
Container(
|
Container(
|
||||||
padding: isDesktop ? const EdgeInsets.only(left: 35) : null,
|
padding: isDesktop ? const EdgeInsets.only(left: 35) : null,
|
||||||
child: isDesktop
|
child:
|
||||||
|
isDesktop
|
||||||
? Row(
|
? Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
@ -611,18 +641,13 @@ class _PolicyState extends State<Policy> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(height: 10),
|
||||||
height: 10,
|
Divider(thickness: 0.1, color: Colors.grey),
|
||||||
),
|
|
||||||
Divider(
|
|
||||||
thickness: 0.1,
|
|
||||||
color: Colors.grey,
|
|
||||||
),
|
|
||||||
if (errorMessages["policy_details"] != null) ...[
|
if (errorMessages["policy_details"] != null) ...[
|
||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
Text(
|
Text(
|
||||||
errorMessages["policy_details"]!,
|
errorMessages["policy_details"]!,
|
||||||
style: GoogleFonts.poppins(color: Colors.red, fontSize: 10),
|
style: GoogleFonts.poppins(color: Colors.red, fontSize: 12),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
isDesktop
|
isDesktop
|
||||||
@ -636,15 +661,17 @@ class _PolicyState extends State<Policy> {
|
|||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
"Service Priority",
|
"Service Priority",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
)
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@ -666,11 +693,7 @@ class _PolicyState extends State<Policy> {
|
|||||||
_buildPolicyCategory(isDesktop),
|
_buildPolicyCategory(isDesktop),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Column(
|
Column(children: [_buildPolicyCategoryList(isDesktop)]),
|
||||||
children: [
|
|
||||||
_buildPolicyCategoryList(isDesktop),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -719,11 +742,14 @@ class _PolicyState extends State<Policy> {
|
|||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text("Policy Name",
|
Text(
|
||||||
|
"Policy Name *",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF575A74))),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldUserWrapper(
|
CustomTextFieldUserWrapper(
|
||||||
isFocused: false,
|
isFocused: false,
|
||||||
@ -736,8 +762,10 @@ class _PolicyState extends State<Policy> {
|
|||||||
onChanged: (value) => _clearError("name"),
|
onChanged: (value) => _clearError("name"),
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: "Policy Name",
|
labelText: "Policy Name",
|
||||||
labelStyle:
|
labelStyle: GoogleFonts.poppins(
|
||||||
GoogleFonts.poppins(fontSize: 12, color: Colors.grey),
|
fontSize: 12,
|
||||||
|
color: Colors.grey,
|
||||||
|
),
|
||||||
floatingLabelBehavior: FloatingLabelBehavior.never,
|
floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
||||||
@ -747,8 +775,10 @@ class _PolicyState extends State<Policy> {
|
|||||||
),
|
),
|
||||||
if (errorMessages["name"] != null) ...[
|
if (errorMessages["name"] != null) ...[
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
Text(errorMessages["name"]!,
|
Text(
|
||||||
style: GoogleFonts.poppins(color: Colors.red, fontSize: 10)),
|
errorMessages["name"]!,
|
||||||
|
style: GoogleFonts.poppins(color: Colors.red, fontSize: 12),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@ -758,11 +788,14 @@ class _PolicyState extends State<Policy> {
|
|||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text("Policy Type",
|
Text(
|
||||||
|
"Policy Type *",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF575A74))),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
@ -770,8 +803,10 @@ class _PolicyState extends State<Policy> {
|
|||||||
),
|
),
|
||||||
if (errorMessages["trip_type"] != null) ...[
|
if (errorMessages["trip_type"] != null) ...[
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
Text(errorMessages["trip_type"]!,
|
Text(
|
||||||
style: GoogleFonts.poppins(color: Colors.red, fontSize: 10)),
|
errorMessages["trip_type"]!,
|
||||||
|
style: GoogleFonts.poppins(color: Colors.red, fontSize: 12),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@ -786,8 +821,10 @@ class _PolicyState extends State<Policy> {
|
|||||||
// color: Colors.blueGrey.shade200,
|
// color: Colors.blueGrey.shade200,
|
||||||
width: isDesktop ? MediaQuery.of(context).size.width * 0.15 : null,
|
width: isDesktop ? MediaQuery.of(context).size.width * 0.15 : null,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
border: Border.all(color: Colors.blueGrey.shade100, width: 0.35)),
|
border: Border.all(color: Colors.blueGrey.shade100, width: 0.35),
|
||||||
child: isDesktop
|
),
|
||||||
|
child:
|
||||||
|
isDesktop
|
||||||
? Padding(
|
? Padding(
|
||||||
padding: const EdgeInsets.all(10.0),
|
padding: const EdgeInsets.all(10.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
@ -900,16 +937,13 @@ class _PolicyState extends State<Policy> {
|
|||||||
color: Colors.grey.withOpacity(0.3),
|
color: Colors.grey.withOpacity(0.3),
|
||||||
blurRadius: 2,
|
blurRadius: 2,
|
||||||
offset: const Offset(0, 1),
|
offset: const Offset(0, 1),
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
child: Text(
|
child: Text(
|
||||||
name,
|
name,
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(color: Colors.black, fontSize: 12),
|
||||||
color: Colors.black,
|
|
||||||
fontSize: 12,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -942,7 +976,7 @@ class _PolicyState extends State<Policy> {
|
|||||||
color: Colors.grey.withOpacity(0.3),
|
color: Colors.grey.withOpacity(0.3),
|
||||||
blurRadius: 2,
|
blurRadius: 2,
|
||||||
offset: const Offset(0, 1),
|
offset: const Offset(0, 1),
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
@ -967,10 +1001,10 @@ class _PolicyState extends State<Policy> {
|
|||||||
padding: isDesktop ? const EdgeInsets.only(left: 30, top: 8) : null,
|
padding: isDesktop ? const EdgeInsets.only(left: 30, top: 8) : null,
|
||||||
width: isDesktop ? MediaQuery.of(context).size.width * 0.62 : null,
|
width: isDesktop ? MediaQuery.of(context).size.width * 0.62 : null,
|
||||||
// width: isDesktop ? MediaQuery.of(context).size.width * 0.75 : null,
|
// width: isDesktop ? MediaQuery.of(context).size.width * 0.75 : null,
|
||||||
child: isDesktop
|
child:
|
||||||
|
isDesktop
|
||||||
? Container(
|
? Container(
|
||||||
// color: Colors.amber,
|
// color: Colors.amber,
|
||||||
|
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [_buildPolicyServiceOrdering(isDesktop)],
|
children: [_buildPolicyServiceOrdering(isDesktop)],
|
||||||
@ -992,8 +1026,9 @@ class _PolicyState extends State<Policy> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Sort services by 'order'
|
// Sort services by 'order'
|
||||||
ServicesChoosed!
|
ServicesChoosed!.sort(
|
||||||
.sort((a, b) => (a['order'] ?? 0).compareTo(b['order'] ?? 0));
|
(a, b) => (a['order'] ?? 0).compareTo(b['order'] ?? 0),
|
||||||
|
);
|
||||||
|
|
||||||
List<String> services =
|
List<String> services =
|
||||||
ServicesChoosed!.map((service) => service['name'].toString()).toList();
|
ServicesChoosed!.map((service) => service['name'].toString()).toList();
|
||||||
@ -1003,16 +1038,22 @@ class _PolicyState extends State<Policy> {
|
|||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: Axis.horizontal,
|
||||||
child: Flex(
|
child: Flex(
|
||||||
direction: Axis.horizontal,
|
direction: Axis.horizontal,
|
||||||
children: services.asMap().entries.map((entry) {
|
children:
|
||||||
|
services.asMap().entries.map((entry) {
|
||||||
int index = entry.key + 1;
|
int index = entry.key + 1;
|
||||||
String service = entry.value;
|
String service = entry.value;
|
||||||
String serviceId = index.toString();
|
String serviceId = index.toString();
|
||||||
bool isSelected = selectedServiceIndex.value == index.toString();
|
bool isSelected =
|
||||||
|
selectedServiceIndex.value == index.toString();
|
||||||
|
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
// width: isDesktop ? 40 : null,
|
// width: isDesktop ? 40 : null,
|
||||||
height: isDesktop
|
height:
|
||||||
? max((MediaQuery.of(context).size.height * 0.075), 10)
|
isDesktop
|
||||||
|
? max(
|
||||||
|
(MediaQuery.of(context).size.height * 0.075),
|
||||||
|
10,
|
||||||
|
)
|
||||||
: 45,
|
: 45,
|
||||||
|
|
||||||
// max((MediaQuery.of(context).size.height * 0.09), 10)
|
// max((MediaQuery.of(context).size.height * 0.09), 10)
|
||||||
@ -1024,7 +1065,8 @@ class _PolicyState extends State<Policy> {
|
|||||||
selectedService = service;
|
selectedService = service;
|
||||||
|
|
||||||
print(
|
print(
|
||||||
" selectedServiceIndex.value - ${selectedServiceIndex.value}");
|
" selectedServiceIndex.value - ${selectedServiceIndex.value}",
|
||||||
|
);
|
||||||
|
|
||||||
// policyCriteriaKey.currentState?.fieldForPolicy();
|
// policyCriteriaKey.currentState?.fieldForPolicy();
|
||||||
// policyCriteriaKey.currentState
|
// policyCriteriaKey.currentState
|
||||||
@ -1035,7 +1077,8 @@ class _PolicyState extends State<Policy> {
|
|||||||
showCost = true;
|
showCost = true;
|
||||||
int serviceCode = selectedService == "Flight" ? 1 : 2;
|
int serviceCode = selectedService == "Flight" ? 1 : 2;
|
||||||
|
|
||||||
policyCriteriaKey.currentState?.fetchTrainFlightClass();
|
policyCriteriaKey.currentState
|
||||||
|
?.fetchTrainFlightClass();
|
||||||
} else if (selectedService == "Accommodation") {
|
} else if (selectedService == "Accommodation") {
|
||||||
showClass = true;
|
showClass = true;
|
||||||
showCost = false;
|
showCost = false;
|
||||||
@ -1047,10 +1090,13 @@ class _PolicyState extends State<Policy> {
|
|||||||
},
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
margin: const EdgeInsets.all(5),
|
margin: const EdgeInsets.all(5),
|
||||||
padding: isDesktop
|
padding:
|
||||||
|
isDesktop
|
||||||
? const EdgeInsets.all(8)
|
? const EdgeInsets.all(8)
|
||||||
: const EdgeInsets.symmetric(
|
: const EdgeInsets.symmetric(
|
||||||
horizontal: 8, vertical: 3),
|
horizontal: 8,
|
||||||
|
vertical: 3,
|
||||||
|
),
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
@ -1058,19 +1104,24 @@ class _PolicyState extends State<Policy> {
|
|||||||
Text(
|
Text(
|
||||||
service,
|
service,
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
color: isSelected
|
color:
|
||||||
|
isSelected
|
||||||
? const Color(0xFF114D8B)
|
? const Color(0xFF114D8B)
|
||||||
: Colors.black87,
|
: Colors.black87,
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
fontWeight:
|
fontWeight:
|
||||||
isSelected ? FontWeight.bold : FontWeight.w500,
|
isSelected
|
||||||
decoration: TextDecoration
|
? FontWeight.bold
|
||||||
|
: FontWeight.w500,
|
||||||
|
decoration:
|
||||||
|
TextDecoration
|
||||||
.none, // remove built-in underline
|
.none, // remove built-in underline
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (isSelected)
|
if (isSelected)
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 1), // spacing between text and underline
|
height: 1,
|
||||||
|
), // spacing between text and underline
|
||||||
if (isSelected)
|
if (isSelected)
|
||||||
Container(
|
Container(
|
||||||
height: 2,
|
height: 2,
|
||||||
@ -1080,7 +1131,8 @@ class _PolicyState extends State<Policy> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
));
|
),
|
||||||
|
);
|
||||||
}).toList(),
|
}).toList(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -1112,15 +1164,21 @@ class _PolicyState extends State<Policy> {
|
|||||||
scrollDirection: isDesktop ? Axis.vertical : Axis.horizontal,
|
scrollDirection: isDesktop ? Axis.vertical : Axis.horizontal,
|
||||||
child: Flex(
|
child: Flex(
|
||||||
direction: isDesktop ? Axis.vertical : Axis.horizontal,
|
direction: isDesktop ? Axis.vertical : Axis.horizontal,
|
||||||
children: services.asMap().entries.map((entry) {
|
children:
|
||||||
|
services.asMap().entries.map((entry) {
|
||||||
int index = entry.key + 1;
|
int index = entry.key + 1;
|
||||||
String service = entry.value;
|
String service = entry.value;
|
||||||
bool isSelected = selectedServiceIndex.value == index.toString();
|
bool isSelected =
|
||||||
|
selectedServiceIndex.value == index.toString();
|
||||||
|
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
width: isDesktop ? 180 : null,
|
width: isDesktop ? 180 : null,
|
||||||
height: isDesktop
|
height:
|
||||||
? max((MediaQuery.of(context).size.height * 0.075), 10)
|
isDesktop
|
||||||
|
? max(
|
||||||
|
(MediaQuery.of(context).size.height * 0.075),
|
||||||
|
10,
|
||||||
|
)
|
||||||
: 45,
|
: 45,
|
||||||
|
|
||||||
// max((MediaQuery.of(context).size.height * 0.09), 10)
|
// max((MediaQuery.of(context).size.height * 0.09), 10)
|
||||||
@ -1148,9 +1206,15 @@ class _PolicyState extends State<Policy> {
|
|||||||
},
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
margin: EdgeInsets.all(5),
|
margin: EdgeInsets.all(5),
|
||||||
padding: isDesktop
|
padding:
|
||||||
|
isDesktop
|
||||||
? EdgeInsets.all(8)
|
? EdgeInsets.all(8)
|
||||||
: EdgeInsets.only(top: 3, bottom: 3, left: 8, right: 8),
|
: EdgeInsets.only(
|
||||||
|
top: 3,
|
||||||
|
bottom: 3,
|
||||||
|
left: 8,
|
||||||
|
right: 8,
|
||||||
|
),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
// color: Colors.blue,
|
// color: Colors.blue,
|
||||||
color: isSelected ? Color(0xFF114D8B) : Colors.white,
|
color: isSelected ? Color(0xFF114D8B) : Colors.white,
|
||||||
@ -1176,10 +1240,12 @@ class _PolicyState extends State<Policy> {
|
|||||||
color: isSelected ? Colors.white : Colors.black87,
|
color: isSelected ? Colors.white : Colors.black87,
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
fontWeight:
|
fontWeight:
|
||||||
isSelected ? FontWeight.bold : FontWeight.w100),
|
isSelected ? FontWeight.bold : FontWeight.w100,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
));
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
}).toList(),
|
}).toList(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -1210,7 +1276,8 @@ class _PolicyState extends State<Policy> {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
));
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> _buildTripType(bool isDesktop) {
|
List<Widget> _buildTripType(bool isDesktop) {
|
||||||
@ -1232,7 +1299,8 @@ class _PolicyState extends State<Policy> {
|
|||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
color: _selectedTripType == "1" ? Colors.white : Colors.black,
|
color: _selectedTripType == "1" ? Colors.white : Colors.black,
|
||||||
fontWeight: _selectedTripType == "1" ? FontWeight.w600 : null,
|
fontWeight: _selectedTripType == "1" ? FontWeight.w600 : null,
|
||||||
fontSize: 13),
|
fontSize: 13,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
@ -1259,11 +1327,12 @@ class _PolicyState extends State<Policy> {
|
|||||||
width: _selectedTripType == "1" ? 2 : 1,
|
width: _selectedTripType == "1" ? 2 : 1,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: _selectedTripType == "1"
|
child:
|
||||||
|
_selectedTripType == "1"
|
||||||
? Icon(Icons.rectangle, size: 8, color: Colors.white)
|
? Icon(Icons.rectangle, size: 8, color: Colors.white)
|
||||||
: null, // Add checkmark if selected
|
: null, // Add checkmark if selected
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -1314,11 +1383,12 @@ class _PolicyState extends State<Policy> {
|
|||||||
width: _selectedTripType == "2" ? 2 : 1,
|
width: _selectedTripType == "2" ? 2 : 1,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: _selectedTripType == "2"
|
child:
|
||||||
|
_selectedTripType == "2"
|
||||||
? Icon(Icons.rectangle, size: 8, color: Colors.white)
|
? Icon(Icons.rectangle, size: 8, color: Colors.white)
|
||||||
: null, // Add checkmark if selected
|
: null, // Add checkmark if selected
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
||||||
@ -1356,15 +1426,12 @@ class _PolicyState extends State<Policy> {
|
|||||||
onPressed: () {
|
onPressed: () {
|
||||||
context.go('/PolicyList');
|
context.go('/PolicyList');
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text("Cancel", style: GoogleFonts.poppins(fontSize: 10)),
|
||||||
"Cancel",
|
|
||||||
style: GoogleFonts.poppins(fontSize: 10),
|
|
||||||
)),
|
|
||||||
SizedBox(
|
|
||||||
width: 20,
|
|
||||||
),
|
),
|
||||||
|
SizedBox(width: 20),
|
||||||
MouseRegion(
|
MouseRegion(
|
||||||
cursor: isViewMode
|
cursor:
|
||||||
|
isViewMode
|
||||||
? SystemMouseCursors.forbidden
|
? SystemMouseCursors.forbidden
|
||||||
: SystemMouseCursors.click,
|
: SystemMouseCursors.click,
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
@ -1384,12 +1451,9 @@ class _PolicyState extends State<Policy> {
|
|||||||
),
|
),
|
||||||
onPressed:
|
onPressed:
|
||||||
isViewMode ? null : handleSubmit, // Disable when in view mode
|
isViewMode ? null : handleSubmit, // Disable when in view mode
|
||||||
child: Text(
|
child: Text("Submit", style: GoogleFonts.poppins(fontSize: 10)),
|
||||||
"Submit",
|
|
||||||
style: GoogleFonts.poppins(fontSize: 10),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1410,10 +1474,7 @@ class _PolicyState extends State<Policy> {
|
|||||||
contentPadding: EdgeInsets.zero,
|
contentPadding: EdgeInsets.zero,
|
||||||
visualDensity: VisualDensity.compact,
|
visualDensity: VisualDensity.compact,
|
||||||
dense: true,
|
dense: true,
|
||||||
title: Text(
|
title: Text("Domestic", style: GoogleFonts.poppins(fontSize: 12)),
|
||||||
"Domestic",
|
|
||||||
style: GoogleFonts.poppins(fontSize: 12),
|
|
||||||
),
|
|
||||||
value: "1",
|
value: "1",
|
||||||
groupValue: _selectedTripType,
|
groupValue: _selectedTripType,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
|
|||||||
@ -14,14 +14,12 @@ import '../../services/apiService.dart';
|
|||||||
import '../../utils/auth_utils.dart';
|
import '../../utils/auth_utils.dart';
|
||||||
import '../../utils/pagination.dart';
|
import '../../utils/pagination.dart';
|
||||||
|
|
||||||
|
|
||||||
class PolicyList extends StatefulWidget {
|
class PolicyList extends StatefulWidget {
|
||||||
@override
|
@override
|
||||||
_PolicyListState createState() => _PolicyListState();
|
_PolicyListState createState() => _PolicyListState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _PolicyListState extends State<PolicyList> {
|
class _PolicyListState extends State<PolicyList> {
|
||||||
|
|
||||||
final ApiService apiService = ApiService();
|
final ApiService apiService = ApiService();
|
||||||
late Future<List<dynamic>> futurePolicy;
|
late Future<List<dynamic>> futurePolicy;
|
||||||
|
|
||||||
@ -37,7 +35,6 @@ class _PolicyListState extends State<PolicyList> {
|
|||||||
List filteredPolicy = [];
|
List filteredPolicy = [];
|
||||||
TextEditingController searchController = TextEditingController();
|
TextEditingController searchController = TextEditingController();
|
||||||
|
|
||||||
|
|
||||||
int currentPage = 0;
|
int currentPage = 0;
|
||||||
int itemsPerPage = 10;
|
int itemsPerPage = 10;
|
||||||
|
|
||||||
@ -84,8 +81,6 @@ class _PolicyListState extends State<PolicyList> {
|
|||||||
return prefs.getString('auth_token');
|
return prefs.getString('auth_token');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Future<List<dynamic>> fetchPolicy() async {
|
Future<List<dynamic>> fetchPolicy() async {
|
||||||
final data = await apiService.fetchAllPolicy();
|
final data = await apiService.fetchAllPolicy();
|
||||||
return data; // Returning raw JSON list
|
return data; // Returning raw JSON list
|
||||||
@ -95,28 +90,35 @@ class _PolicyListState extends State<PolicyList> {
|
|||||||
void refreshPolicyList() {
|
void refreshPolicyList() {
|
||||||
setState(() {
|
setState(() {
|
||||||
futurePolicy = fetchPolicy(); // Re-fetch users after status update
|
futurePolicy = fetchPolicy(); // Re-fetch users after status update
|
||||||
|
|
||||||
|
futurePolicy.then((object) {
|
||||||
|
setState(() {
|
||||||
|
allPolicy = object;
|
||||||
|
});
|
||||||
|
});
|
||||||
// Wait for futurePlans to be fetched and update allPlans
|
// Wait for futurePlans to be fetched and update allPlans
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void filterPolicy(String query) {
|
void filterPolicy(String query) {
|
||||||
print("allPolicy before filtering: $query");
|
|
||||||
final lowerQuery = query.toLowerCase();
|
final lowerQuery = query.toLowerCase();
|
||||||
setState(() {
|
setState(() {
|
||||||
filteredPolicy =
|
filteredPolicy =
|
||||||
allPolicy.where((object) {
|
allPolicy.where((object) {
|
||||||
return (object['name']?.toLowerCase().contains(lowerQuery) ??
|
final isActiveStatus =
|
||||||
|
object['is_active'] == "1" ? "active" : "inactive";
|
||||||
|
return (object['policy_id']?.toLowerCase().contains(lowerQuery) ??
|
||||||
false) ||
|
false) ||
|
||||||
|
(object['name']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||||
(object['policy_type']?.toLowerCase().contains(lowerQuery) ??
|
(object['policy_type']?.toLowerCase().contains(lowerQuery) ??
|
||||||
false) ||
|
false) ||
|
||||||
(object['is_active']?.toLowerCase().contains(lowerQuery) ?? false);}).toList();
|
(isActiveStatus.contains(lowerQuery));
|
||||||
|
}).toList();
|
||||||
currentPage = 0;
|
currentPage = 0;
|
||||||
});
|
});
|
||||||
print("filtered: $filteredPolicy");
|
print("filteredPolicy: $filteredPolicy");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void handleActiveStatus(
|
void handleActiveStatus(
|
||||||
Map<String, dynamic> policyData,
|
Map<String, dynamic> policyData,
|
||||||
String policyId,
|
String policyId,
|
||||||
@ -159,7 +161,6 @@ class _PolicyListState extends State<PolicyList> {
|
|||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
print("policyData submitted successfully!");
|
print("policyData submitted successfully!");
|
||||||
print("Response: ${response.body}");
|
print("Response: ${response.body}");
|
||||||
|
|
||||||
loadAllGroups();
|
loadAllGroups();
|
||||||
} else {
|
} else {
|
||||||
print("Failed to submit policyData. Status: ${response.statusCode}");
|
print("Failed to submit policyData. Status: ${response.statusCode}");
|
||||||
@ -175,31 +176,45 @@ class _PolicyListState extends State<PolicyList> {
|
|||||||
print("policystatus: $status");
|
print("policystatus: $status");
|
||||||
print("policysData: $policydata");
|
print("policysData: $policydata");
|
||||||
|
|
||||||
// handleActiveStatus(groupdata, groupId, status);
|
|
||||||
print("Calling handleActiveStatus with: id=$policyId, status=$status");
|
|
||||||
handleActiveStatus(policydata, policyId.toString(), status.toString());
|
handleActiveStatus(policydata, policyId.toString(), status.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> refreshData() async {
|
||||||
|
loadAllGroups();
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> loadAllGroups() async {
|
Future<void> loadAllGroups() async {
|
||||||
try {
|
try {
|
||||||
final result = await apiService.fetchAllPolicy();
|
final result = await apiService.fetchAllPolicy();
|
||||||
|
|
||||||
// Sort by policy_id descending (latest first)
|
|
||||||
result.sort((a, b) {
|
|
||||||
int idA = int.tryParse(a['policy_id'].toString()) ?? 0;
|
|
||||||
int idB = int.tryParse(b['policy_id'].toString()) ?? 0;
|
|
||||||
return idB.compareTo(idA); // latest first
|
|
||||||
});
|
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
futurePolicy = result as Future<List>;
|
allPolicy = result;
|
||||||
});
|
});
|
||||||
print("Fetched services: $futurePolicy");
|
print("Fetched services: $allPolicy");
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('Error fetching role list: $e');
|
print('Error fetching role list: $e');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Future<void> loadAllGroups_old() async {
|
||||||
|
// try {
|
||||||
|
// final result = await apiService.fetchAllPolicy();
|
||||||
|
//
|
||||||
|
// // Sort by policy_id descending (latest first)
|
||||||
|
// result.sort((a, b) {
|
||||||
|
// int idA = int.tryParse(a['policy_id'].toString()) ?? 0;
|
||||||
|
// int idB = int.tryParse(b['policy_id'].toString()) ?? 0;
|
||||||
|
// return idB.compareTo(idA); // latest first
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// setState(() {
|
||||||
|
// futurePolicy = result as Future<List>;
|
||||||
|
// });
|
||||||
|
// print("Fetched services: $futurePolicy");
|
||||||
|
// refreshPolicyList();
|
||||||
|
// } catch (e) {
|
||||||
|
// print('Error fetching role list: $e');
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -362,7 +377,6 @@ class _PolicyListState extends State<PolicyList> {
|
|||||||
// Print the resolved value
|
// Print the resolved value
|
||||||
print("CREATELIAS - $policyData");
|
print("CREATELIAS - $policyData");
|
||||||
context.go('/Policy');
|
context.go('/Policy');
|
||||||
|
|
||||||
},
|
},
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisSize:
|
mainAxisSize:
|
||||||
@ -546,7 +560,8 @@ class _PolicyListState extends State<PolicyList> {
|
|||||||
rows:
|
rows:
|
||||||
paginatedUser.map((policy) {
|
paginatedUser.map((policy) {
|
||||||
String policyId =
|
String policyId =
|
||||||
policy['policy_id'].toString(); // Get policy ID
|
policy['policy_id']
|
||||||
|
.toString(); // Get policy ID
|
||||||
bool isSelected = selectedPolicyId == policyId;
|
bool isSelected = selectedPolicyId == policyId;
|
||||||
|
|
||||||
return DataRow(
|
return DataRow(
|
||||||
@ -588,7 +603,8 @@ class _PolicyListState extends State<PolicyList> {
|
|||||||
),
|
),
|
||||||
DataCell(
|
DataCell(
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
@ -596,14 +612,23 @@ class _PolicyListState extends State<PolicyList> {
|
|||||||
final intPolicyId =
|
final intPolicyId =
|
||||||
rawId is int
|
rawId is int
|
||||||
? rawId
|
? rawId
|
||||||
: int.tryParse(rawId.toString()) ?? 0;
|
: int.tryParse(
|
||||||
|
rawId.toString(),
|
||||||
|
) ??
|
||||||
|
0;
|
||||||
|
|
||||||
Map<String, dynamic> policyData = await apiService
|
Map<String, dynamic> policyData =
|
||||||
.getSinglePolicy(intPolicyId);
|
await apiService
|
||||||
|
.getSinglePolicy(
|
||||||
|
intPolicyId,
|
||||||
|
);
|
||||||
|
|
||||||
print("PolicyDATa: $policyData");
|
print("PolicyDATa: $policyData");
|
||||||
|
|
||||||
context.go("/Policy", extra: policyData);
|
context.go(
|
||||||
|
"/Policy",
|
||||||
|
extra: policyData,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
child: Tooltip(
|
child: Tooltip(
|
||||||
message: 'Edit Policy Details',
|
message: 'Edit Policy Details',
|
||||||
@ -618,13 +643,16 @@ class _PolicyListState extends State<PolicyList> {
|
|||||||
GestureDetector(
|
GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
final idStr = policy['policy_id'];
|
final idStr = policy['policy_id'];
|
||||||
final id = int.tryParse(idStr.toString());
|
final id = int.tryParse(
|
||||||
|
idStr.toString(),
|
||||||
|
);
|
||||||
|
|
||||||
if (id == null) {
|
if (id == null) {
|
||||||
print("group_id is null");
|
print("group_id is null");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final status = policy['is_active'];
|
final status =
|
||||||
|
policy['is_active'];
|
||||||
|
|
||||||
deletePolicy(policy, id, status);
|
deletePolicy(policy, id, status);
|
||||||
},
|
},
|
||||||
@ -635,7 +663,8 @@ class _PolicyListState extends State<PolicyList> {
|
|||||||
width: 20,
|
width: 20,
|
||||||
height: 15,
|
height: 15,
|
||||||
),
|
),
|
||||||
),),
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -654,7 +683,10 @@ class _PolicyListState extends State<PolicyList> {
|
|||||||
|
|
||||||
return Card(
|
return Card(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
margin: EdgeInsets.symmetric(horizontal: 12, vertical: 6),
|
margin: EdgeInsets.symmetric(
|
||||||
|
horizontal: 12,
|
||||||
|
vertical: 6,
|
||||||
|
),
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
),
|
),
|
||||||
@ -666,7 +698,8 @@ class _PolicyListState extends State<PolicyList> {
|
|||||||
children: [
|
children: [
|
||||||
// Row 1: Policy Name and Actions
|
// Row 1: Policy Name and Actions
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: RichText(
|
child: RichText(
|
||||||
@ -684,11 +717,12 @@ class _PolicyListState extends State<PolicyList> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: "${object['name'] ?? 'N/A'}",
|
text:
|
||||||
|
"${object['name'] ?? 'N/A'}",
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
fontFamily: "Inter",
|
fontFamily: "Inter",
|
||||||
fontWeight: FontWeight.normal
|
fontWeight: FontWeight.normal,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -701,16 +735,26 @@ class _PolicyListState extends State<PolicyList> {
|
|||||||
GestureDetector(
|
GestureDetector(
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
final rawId = object['policy_id'];
|
final rawId = object['policy_id'];
|
||||||
final intPolicyId = rawId is int
|
final intPolicyId =
|
||||||
|
rawId is int
|
||||||
? rawId
|
? rawId
|
||||||
: int.tryParse(rawId.toString()) ?? 0;
|
: int.tryParse(
|
||||||
|
rawId.toString(),
|
||||||
|
) ??
|
||||||
|
0;
|
||||||
|
|
||||||
Map<String, dynamic> policyData =
|
Map<String, dynamic> policyData =
|
||||||
await apiService.getSinglePolicy(intPolicyId);
|
await apiService
|
||||||
|
.getSinglePolicy(
|
||||||
|
intPolicyId,
|
||||||
|
);
|
||||||
|
|
||||||
print("PolicyDATa: $policyData");
|
print("PolicyDATa: $policyData");
|
||||||
|
|
||||||
context.go("/Policy", extra: policyData);
|
context.go(
|
||||||
|
"/Policy",
|
||||||
|
extra: policyData,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
child: Tooltip(
|
child: Tooltip(
|
||||||
message: 'Edit Policy Details',
|
message: 'Edit Policy Details',
|
||||||
@ -725,7 +769,9 @@ class _PolicyListState extends State<PolicyList> {
|
|||||||
GestureDetector(
|
GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
final idStr = object['policy_id'];
|
final idStr = object['policy_id'];
|
||||||
final id = int.tryParse(idStr.toString());
|
final id = int.tryParse(
|
||||||
|
idStr.toString(),
|
||||||
|
);
|
||||||
|
|
||||||
if (id == null) {
|
if (id == null) {
|
||||||
print("policy_id is null");
|
print("policy_id is null");
|
||||||
@ -750,7 +796,6 @@ class _PolicyListState extends State<PolicyList> {
|
|||||||
),
|
),
|
||||||
|
|
||||||
SizedBox(height: 8), // Spacing
|
SizedBox(height: 8), // Spacing
|
||||||
|
|
||||||
// Row 2: Policy Type
|
// Row 2: Policy Type
|
||||||
RichText(
|
RichText(
|
||||||
text: TextSpan(
|
text: TextSpan(
|
||||||
@ -767,13 +812,14 @@ class _PolicyListState extends State<PolicyList> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: object['domestic'] == "1"
|
text:
|
||||||
|
object['domestic'] == "1"
|
||||||
? "Domestic"
|
? "Domestic"
|
||||||
: "International",
|
: "International",
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
fontFamily: "Inter",
|
fontFamily: "Inter",
|
||||||
fontWeight: FontWeight.normal
|
fontWeight: FontWeight.normal,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -787,7 +833,6 @@ class _PolicyListState extends State<PolicyList> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Widget buildMobileCardView2(List<dynamic> paginatedUser) {
|
Widget buildMobileCardView2(List<dynamic> paginatedUser) {
|
||||||
return ListView.builder(
|
return ListView.builder(
|
||||||
itemCount: paginatedUser.length,
|
itemCount: paginatedUser.length,
|
||||||
@ -810,7 +855,6 @@ class _PolicyListState extends State<PolicyList> {
|
|||||||
children: [
|
children: [
|
||||||
Column(
|
Column(
|
||||||
children: [
|
children: [
|
||||||
|
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 1,
|
flex: 1,
|
||||||
child: Text(
|
child: Text(
|
||||||
@ -861,14 +905,22 @@ class _PolicyListState extends State<PolicyList> {
|
|||||||
final intPolicyId =
|
final intPolicyId =
|
||||||
rawId is int
|
rawId is int
|
||||||
? rawId
|
? rawId
|
||||||
: int.tryParse(rawId.toString()) ?? 0;
|
: int.tryParse(
|
||||||
|
rawId.toString(),
|
||||||
|
) ??
|
||||||
|
0;
|
||||||
|
|
||||||
Map<String, dynamic> policyData = await apiService
|
Map<String, dynamic> policyData =
|
||||||
.getSinglePolicy(intPolicyId);
|
await apiService.getSinglePolicy(
|
||||||
|
intPolicyId,
|
||||||
|
);
|
||||||
|
|
||||||
print("PolicyDATa: $policyData");
|
print("PolicyDATa: $policyData");
|
||||||
|
|
||||||
context.go("/Policy", extra: policyData);
|
context.go(
|
||||||
|
"/Policy",
|
||||||
|
extra: policyData,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
child: Tooltip(
|
child: Tooltip(
|
||||||
message: 'Edit Policy Details',
|
message: 'Edit Policy Details',
|
||||||
@ -876,13 +928,16 @@ class _PolicyListState extends State<PolicyList> {
|
|||||||
'assets/images/IconsImg/edit.png',
|
'assets/images/IconsImg/edit.png',
|
||||||
width: 20,
|
width: 20,
|
||||||
height: 15,
|
height: 15,
|
||||||
),),
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(width: 5),
|
SizedBox(width: 5),
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
final idStr = object['policy_id'];
|
final idStr = object['policy_id'];
|
||||||
final id = int.tryParse(idStr.toString());
|
final id = int.tryParse(
|
||||||
|
idStr.toString(),
|
||||||
|
);
|
||||||
|
|
||||||
if (id == null) {
|
if (id == null) {
|
||||||
print("group_id is null");
|
print("group_id is null");
|
||||||
@ -898,7 +953,8 @@ class _PolicyListState extends State<PolicyList> {
|
|||||||
'assets/images/IconsImg/delete.png',
|
'assets/images/IconsImg/delete.png',
|
||||||
width: 20,
|
width: 20,
|
||||||
height: 15,
|
height: 15,
|
||||||
),),
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@ -19,13 +19,14 @@ class TravellerData extends StatefulWidget {
|
|||||||
final int? travellerId; // <-- Add this
|
final int? travellerId; // <-- Add this
|
||||||
final Map<String, dynamic>? travellerData;
|
final Map<String, dynamic>? travellerData;
|
||||||
|
|
||||||
const TravellerData(
|
const TravellerData({
|
||||||
{super.key,
|
super.key,
|
||||||
required this.isDesktop,
|
required this.isDesktop,
|
||||||
this.layoutColor,
|
this.layoutColor,
|
||||||
required this.fetchGetTraveller,
|
required this.fetchGetTraveller,
|
||||||
this.travellerId,
|
this.travellerId,
|
||||||
this.travellerData});
|
this.travellerData,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
TravellerDataState createState() => TravellerDataState();
|
TravellerDataState createState() => TravellerDataState();
|
||||||
@ -49,12 +50,7 @@ class TravellerDataState extends State<TravellerData> {
|
|||||||
int? travellerDataId;
|
int? travellerDataId;
|
||||||
late String isActive = "1";
|
late String isActive = "1";
|
||||||
|
|
||||||
List<String> dataHeader = [
|
List<String> dataHeader = ["first_name", "last_name", "email", "mobile"];
|
||||||
"first_name",
|
|
||||||
"last_name",
|
|
||||||
"email",
|
|
||||||
"mobile",
|
|
||||||
];
|
|
||||||
|
|
||||||
Map<String, dynamic> travellerDetails() {
|
Map<String, dynamic> travellerDetails() {
|
||||||
final data = {
|
final data = {
|
||||||
@ -72,7 +68,6 @@ class TravellerDataState extends State<TravellerData> {
|
|||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
|
|
||||||
apiData = null;
|
apiData = null;
|
||||||
for (var field in dataHeader) {
|
for (var field in dataHeader) {
|
||||||
controllers[field] = TextEditingController();
|
controllers[field] = TextEditingController();
|
||||||
@ -115,7 +110,6 @@ class TravellerDataState extends State<TravellerData> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void toggleStatus() {
|
void toggleStatus() {
|
||||||
setState(() {
|
setState(() {
|
||||||
isActive = isActive == "1" ? "0" : "1";
|
isActive = isActive == "1" ? "0" : "1";
|
||||||
@ -155,8 +149,9 @@ class TravellerDataState extends State<TravellerData> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (data["email"] != null && data["email"].toString().isNotEmpty) {
|
if (data["email"] != null && data["email"].toString().isNotEmpty) {
|
||||||
if (!RegExp(r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$")
|
if (!RegExp(
|
||||||
.hasMatch(data["email"].toString())) {
|
r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$",
|
||||||
|
).hasMatch(data["email"].toString())) {
|
||||||
errorMessages["email"] = "Invalid email format"; // Invalid email format
|
errorMessages["email"] = "Invalid email format"; // Invalid email format
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -195,7 +190,9 @@ class TravellerDataState extends State<TravellerData> {
|
|||||||
apiUrldata = '$apiUrl/api/travellers/update/$travellerDataId';
|
apiUrldata = '$apiUrl/api/travellers/update/$travellerDataId';
|
||||||
travellerData["traveller_id"] = travellerDataId.toString();
|
travellerData["traveller_id"] = travellerDataId.toString();
|
||||||
travellerData["updated_by"] = userId;
|
travellerData["updated_by"] = userId;
|
||||||
(travellerData.containsKey("created_by")) ? travellerData.remove("created_by") : '' ;
|
(travellerData.containsKey("created_by"))
|
||||||
|
? travellerData.remove("created_by")
|
||||||
|
: '';
|
||||||
} else {
|
} else {
|
||||||
print("for add Traveller id - null");
|
print("for add Traveller id - null");
|
||||||
apiUrldata = '$apiUrl/api/travellers/create';
|
apiUrldata = '$apiUrl/api/travellers/create';
|
||||||
@ -217,11 +214,11 @@ class TravellerDataState extends State<TravellerData> {
|
|||||||
};
|
};
|
||||||
final body = jsonEncode(travellerData);
|
final body = jsonEncode(travellerData);
|
||||||
|
|
||||||
final response = travellerDataId != null
|
final response =
|
||||||
|
travellerDataId != 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);
|
||||||
|
|
||||||
|
|
||||||
switch (response.statusCode) {
|
switch (response.statusCode) {
|
||||||
case 200:
|
case 200:
|
||||||
print("Update - Response: ${response.body}");
|
print("Update - Response: ${response.body}");
|
||||||
@ -241,7 +238,6 @@ class TravellerDataState extends State<TravellerData> {
|
|||||||
print("Failed to submit traveller. Status: ${response.statusCode}");
|
print("Failed to submit traveller. Status: ${response.statusCode}");
|
||||||
print("Error: ${response.body}");
|
print("Error: ${response.body}");
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(" Error submitting plan: $e");
|
print(" Error submitting plan: $e");
|
||||||
}
|
}
|
||||||
@ -249,7 +245,6 @@ class TravellerDataState extends State<TravellerData> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|
||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
backgroundColor: Colors.white,
|
backgroundColor: Colors.white,
|
||||||
contentPadding: const EdgeInsets.fromLTRB(34, 30, 34, 30),
|
contentPadding: const EdgeInsets.fromLTRB(34, 30, 34, 30),
|
||||||
@ -264,27 +259,30 @@ class TravellerDataState extends State<TravellerData> {
|
|||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
(travellerDataId != null) ? 'Edit Traveller' : 'Create Traveller',
|
(travellerDataId != null)
|
||||||
style: GoogleFonts.poppins(fontSize: 15, color: Colors.black),
|
? 'Edit Traveller'
|
||||||
|
: 'Create Traveller',
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 15,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 2),
|
const SizedBox(height: 2),
|
||||||
Divider(
|
Divider(thickness: 0.2, color: Colors.blueGrey.shade100),
|
||||||
thickness: 0.2,
|
|
||||||
color: Colors.blueGrey.shade100,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 5),
|
const SizedBox(height: 5),
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"First Name",
|
"First Name *",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldForexWrapper(
|
CustomTextFieldForexWrapper(
|
||||||
@ -299,12 +297,16 @@ class TravellerDataState extends State<TravellerData> {
|
|||||||
style: const TextStyle(fontSize: 12),
|
style: const TextStyle(fontSize: 12),
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
labelText: "First Name",
|
labelText: "First Name",
|
||||||
labelStyle: TextStyle(fontSize: 11, color: Colors.grey),
|
labelStyle: TextStyle(
|
||||||
|
fontSize: 11,
|
||||||
|
color: Colors.grey,
|
||||||
|
),
|
||||||
floatingLabelBehavior: FloatingLabelBehavior.never,
|
floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
||||||
),
|
),
|
||||||
)),
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
if (errorMessages["first_name"] != null) ...[
|
if (errorMessages["first_name"] != null) ...[
|
||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
@ -315,18 +317,17 @@ class TravellerDataState extends State<TravellerData> {
|
|||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(height: 15),
|
||||||
height: 15,
|
|
||||||
),
|
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Last Name",
|
"Last Name *",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldForexWrapper(
|
CustomTextFieldForexWrapper(
|
||||||
@ -341,12 +342,16 @@ class TravellerDataState extends State<TravellerData> {
|
|||||||
style: const TextStyle(fontSize: 12),
|
style: const TextStyle(fontSize: 12),
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
labelText: "Last Name",
|
labelText: "Last Name",
|
||||||
labelStyle: TextStyle(fontSize: 11, color: Colors.grey),
|
labelStyle: TextStyle(
|
||||||
|
fontSize: 11,
|
||||||
|
color: Colors.grey,
|
||||||
|
),
|
||||||
floatingLabelBehavior: FloatingLabelBehavior.never,
|
floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
||||||
),
|
),
|
||||||
)),
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
if (errorMessages["last_name"] != null) ...[
|
if (errorMessages["last_name"] != null) ...[
|
||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
@ -357,18 +362,17 @@ class TravellerDataState extends State<TravellerData> {
|
|||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(height: 15),
|
||||||
height: 15,
|
|
||||||
),
|
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Email",
|
"Email *",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldForexWrapper(
|
CustomTextFieldForexWrapper(
|
||||||
@ -383,12 +387,16 @@ class TravellerDataState extends State<TravellerData> {
|
|||||||
style: const TextStyle(fontSize: 12),
|
style: const TextStyle(fontSize: 12),
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
labelText: "Email",
|
labelText: "Email",
|
||||||
labelStyle: TextStyle(fontSize: 11, color: Colors.grey),
|
labelStyle: TextStyle(
|
||||||
|
fontSize: 11,
|
||||||
|
color: Colors.grey,
|
||||||
|
),
|
||||||
floatingLabelBehavior: FloatingLabelBehavior.never,
|
floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
||||||
),
|
),
|
||||||
)),
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
if (errorMessages["email"] != null) ...[
|
if (errorMessages["email"] != null) ...[
|
||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
@ -399,18 +407,17 @@ class TravellerDataState extends State<TravellerData> {
|
|||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(height: 15),
|
||||||
height: 15,
|
|
||||||
),
|
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Mobile",
|
"Mobile *",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldForexWrapper(
|
CustomTextFieldForexWrapper(
|
||||||
@ -425,12 +432,16 @@ class TravellerDataState extends State<TravellerData> {
|
|||||||
style: const TextStyle(fontSize: 12),
|
style: const TextStyle(fontSize: 12),
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
labelText: "Mobile",
|
labelText: "Mobile",
|
||||||
labelStyle: TextStyle(fontSize: 11, color: Colors.grey),
|
labelStyle: TextStyle(
|
||||||
|
fontSize: 11,
|
||||||
|
color: Colors.grey,
|
||||||
|
),
|
||||||
floatingLabelBehavior: FloatingLabelBehavior.never,
|
floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
||||||
),
|
),
|
||||||
)),
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
if (errorMessages["mobile"] != null) ...[
|
if (errorMessages["mobile"] != null) ...[
|
||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
@ -441,9 +452,7 @@ class TravellerDataState extends State<TravellerData> {
|
|||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(height: 15),
|
||||||
height: 15,
|
|
||||||
),
|
|
||||||
if (travellerDataId != null)
|
if (travellerDataId != null)
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
@ -453,11 +462,14 @@ class TravellerDataState extends State<TravellerData> {
|
|||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
Tooltip(
|
Tooltip(
|
||||||
message:
|
message:
|
||||||
isActive == "1" ? "Tap to deactivate" : "Tap to activate",
|
isActive == "1"
|
||||||
|
? "Tap to deactivate"
|
||||||
|
: "Tap to activate",
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: toggleStatus,
|
onTap: toggleStatus,
|
||||||
child: Text(
|
child: Text(
|
||||||
@ -469,13 +481,10 @@ class TravellerDataState extends State<TravellerData> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (travellerDataId != null)
|
if (travellerDataId != null) SizedBox(height: 15),
|
||||||
SizedBox(
|
|
||||||
height: 15,
|
|
||||||
),
|
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
@ -512,18 +521,22 @@ class TravellerDataState extends State<TravellerData> {
|
|||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: Text('Save',
|
child: Text(
|
||||||
|
'Save',
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 11, color: Colors.white)),
|
fontSize: 11,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
),
|
||||||
// : SizedBox.shrink(),
|
// : SizedBox.shrink(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -67,11 +67,13 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
String? bodyStringColor = await getBodyColor();
|
String? bodyStringColor = await getBodyColor();
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
layoutColor = layoutString != null
|
layoutColor =
|
||||||
|
layoutString != null
|
||||||
? Color(int.parse(layoutString))
|
? Color(int.parse(layoutString))
|
||||||
: Colors.redAccent;
|
: Colors.redAccent;
|
||||||
|
|
||||||
bodyColor = bodyStringColor != null
|
bodyColor =
|
||||||
|
bodyStringColor != null
|
||||||
? Color(int.parse(bodyStringColor))
|
? Color(int.parse(bodyStringColor))
|
||||||
: Colors.white;
|
: Colors.white;
|
||||||
});
|
});
|
||||||
@ -98,8 +100,8 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
|
|
||||||
Future<List<dynamic>> fetchGetTraveller() async {
|
Future<List<dynamic>> fetchGetTraveller() async {
|
||||||
String? ordId = await getOrgId();
|
String? ordId = await getOrgId();
|
||||||
final String apiUrlData = '$apiUrl/api/travellers?org_id=$ordId';
|
final String apiUrlData =
|
||||||
|
'$apiUrl/api/travellers?for=table_view&org_id=$ordId';
|
||||||
|
|
||||||
final String? token = await getToken();
|
final String? token = await getToken();
|
||||||
|
|
||||||
@ -143,13 +145,21 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
print("all before filtering: $query");
|
print("all before filtering: $query");
|
||||||
final lowerQuery = query.toLowerCase();
|
final lowerQuery = query.toLowerCase();
|
||||||
setState(() {
|
setState(() {
|
||||||
filteredTraveller = allTraveller.where((object) {
|
filteredTraveller =
|
||||||
|
allTraveller.where((object) {
|
||||||
final isActiveStatus =
|
final isActiveStatus =
|
||||||
object['is_active'] == "1" ? "active" : "inactive";
|
object['is_active'] == "1" ? "active" : "inactive";
|
||||||
return (object['traveller_id']?.toLowerCase().contains(lowerQuery) ??
|
return (object['traveller_id']?.toLowerCase().contains(
|
||||||
|
lowerQuery,
|
||||||
|
) ??
|
||||||
false) ||
|
false) ||
|
||||||
(object['name']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
(object['first_name']?.toLowerCase().contains(lowerQuery) ??
|
||||||
(object['description']?.toLowerCase().contains(lowerQuery) ??
|
false) ||
|
||||||
|
(object['last_name']?.toLowerCase().contains(lowerQuery) ??
|
||||||
|
false) ||
|
||||||
|
(object['mobile']?.toLowerCase().contains(lowerQuery) ??
|
||||||
|
false) ||
|
||||||
|
(object['email']?.toLowerCase().contains(lowerQuery) ??
|
||||||
false) ||
|
false) ||
|
||||||
(isActiveStatus.contains(lowerQuery));
|
(isActiveStatus.contains(lowerQuery));
|
||||||
}).toList();
|
}).toList();
|
||||||
@ -160,8 +170,10 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ResponsiveBuilder(builder: (context, sizingInfo) {
|
return ResponsiveBuilder(
|
||||||
bool isDesktop = sizingInfo.deviceScreenType == DeviceScreenType.desktop;
|
builder: (context, sizingInfo) {
|
||||||
|
bool isDesktop =
|
||||||
|
sizingInfo.deviceScreenType == DeviceScreenType.desktop;
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: Color(0xFFf5f5f5),
|
backgroundColor: Color(0xFFf5f5f5),
|
||||||
@ -170,11 +182,14 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
appBar: CustomAppBar(isDesktop: isDesktop),
|
appBar: CustomAppBar(isDesktop: isDesktop),
|
||||||
drawer: CustomDrawer(isDesktop: false),
|
drawer: CustomDrawer(isDesktop: false),
|
||||||
body: Padding(
|
body: Padding(
|
||||||
padding: isDesktop
|
padding:
|
||||||
|
isDesktop
|
||||||
? EdgeInsets.symmetric(
|
? EdgeInsets.symmetric(
|
||||||
horizontal: MediaQuery.of(context).size.width *
|
horizontal:
|
||||||
|
MediaQuery.of(context).size.width *
|
||||||
0.1, // 30% of screen width as horizontal padding
|
0.1, // 30% of screen width as horizontal padding
|
||||||
vertical: MediaQuery.of(context).size.height *
|
vertical:
|
||||||
|
MediaQuery.of(context).size.height *
|
||||||
0, // 5% of screen height as vertical padding
|
0, // 5% of screen height as vertical padding
|
||||||
)
|
)
|
||||||
: EdgeInsets.all(0),
|
: EdgeInsets.all(0),
|
||||||
@ -187,7 +202,8 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
});
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildGroupList(bool isDesktop) {
|
Widget buildGroupList(bool isDesktop) {
|
||||||
@ -215,7 +231,8 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
// ? EdgeInsets.all(10.0)
|
// ? EdgeInsets.all(10.0)
|
||||||
// : EdgeInsets.only(left: 20.0, bottom: 20.0, top: 10.0, right: 20.0),
|
// : EdgeInsets.only(left: 20.0, bottom: 20.0, top: 10.0, right: 20.0),
|
||||||
// padding: const EdgeInsets.all(10),
|
// padding: const EdgeInsets.all(10),
|
||||||
height: isDesktop
|
height:
|
||||||
|
isDesktop
|
||||||
? MediaQuery.of(context).size.height * 0.98
|
? MediaQuery.of(context).size.height * 0.98
|
||||||
: MediaQuery.of(context).size.height,
|
: MediaQuery.of(context).size.height,
|
||||||
|
|
||||||
@ -247,9 +264,7 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (isDesktop)
|
if (isDesktop)
|
||||||
SizedBox(
|
SizedBox(width: MediaQuery.of(context).size.width * 0.16),
|
||||||
width: MediaQuery.of(context).size.width * 0.16,
|
|
||||||
),
|
|
||||||
|
|
||||||
if (isDesktop)
|
if (isDesktop)
|
||||||
Container(
|
Container(
|
||||||
@ -261,7 +276,9 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: "Search ...",
|
hintText: "Search ...",
|
||||||
hintStyle: TextStyle(
|
hintStyle: TextStyle(
|
||||||
fontSize: 12, color: Color(0xFF9E9DBD)),
|
fontSize: 12,
|
||||||
|
color: Color(0xFF9E9DBD),
|
||||||
|
),
|
||||||
prefixIcon: Icon(
|
prefixIcon: Icon(
|
||||||
Icons.search,
|
Icons.search,
|
||||||
color: Color(0xFF9E9DBD),
|
color: Color(0xFF9E9DBD),
|
||||||
@ -273,17 +290,19 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
enabledBorder: OutlineInputBorder(
|
enabledBorder: OutlineInputBorder(
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
color: Colors.grey.shade200, width: 0.5),
|
color: Colors.grey.shade200,
|
||||||
|
width: 0.5,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
focusedBorder: OutlineInputBorder(
|
focusedBorder: OutlineInputBorder(
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
color: Colors.grey.shade300, width: 1),
|
color: Colors.grey.shade300,
|
||||||
|
width: 1,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
style: GoogleFonts.poppins(
|
|
||||||
fontSize: 12,
|
|
||||||
),
|
),
|
||||||
|
style: GoogleFonts.poppins(fontSize: 12),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
// SizedBox(width: 16),
|
// SizedBox(width: 16),
|
||||||
@ -297,16 +316,18 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
disabledForegroundColor: Colors.white,
|
disabledForegroundColor: Colors.white,
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
side:
|
side: BorderSide(color: Color(0xFF114D8B), width: 2),
|
||||||
BorderSide(color: Color(0xFF114D8B), width: 2),
|
|
||||||
),
|
),
|
||||||
padding: EdgeInsets.symmetric(
|
padding: EdgeInsets.symmetric(
|
||||||
horizontal: 20, vertical: 12),
|
horizontal: 20,
|
||||||
|
vertical: 12,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => TravellerData(
|
builder:
|
||||||
|
(context) => TravellerData(
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
layoutColor: layoutColor!,
|
layoutColor: layoutColor!,
|
||||||
fetchGetTraveller: refreshData,
|
fetchGetTraveller: refreshData,
|
||||||
@ -338,10 +359,7 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
||||||
if (!isDesktop)
|
if (!isDesktop) SizedBox(height: 5),
|
||||||
SizedBox(
|
|
||||||
height: 5,
|
|
||||||
),
|
|
||||||
isDesktop
|
isDesktop
|
||||||
? SizedBox.shrink()
|
? SizedBox.shrink()
|
||||||
: Row(
|
: Row(
|
||||||
@ -356,7 +374,9 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: "Search ...",
|
hintText: "Search ...",
|
||||||
hintStyle: TextStyle(
|
hintStyle: TextStyle(
|
||||||
fontSize: 12, color: Color(0xFF9E9DBD)),
|
fontSize: 12,
|
||||||
|
color: Color(0xFF9E9DBD),
|
||||||
|
),
|
||||||
prefixIcon: Icon(
|
prefixIcon: Icon(
|
||||||
Icons.search,
|
Icons.search,
|
||||||
color: Color(0xFF9E9DBD),
|
color: Color(0xFF9E9DBD),
|
||||||
@ -369,17 +389,18 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
color: Colors.grey.shade200,
|
color: Colors.grey.shade200,
|
||||||
width: 0.5),
|
width: 0.5,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
focusedBorder: OutlineInputBorder(
|
focusedBorder: OutlineInputBorder(
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
color: Colors.grey.shade300, width: 1),
|
color: Colors.grey.shade300,
|
||||||
|
width: 1,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
style: GoogleFonts.poppins(
|
|
||||||
fontSize: 12,
|
|
||||||
),
|
),
|
||||||
|
style: GoogleFonts.poppins(fontSize: 12),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
// SizedBox(width: 16),
|
// SizedBox(width: 16),
|
||||||
@ -400,16 +421,6 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
// const Icon(Icons.error_outline,
|
|
||||||
// color: Colors.redAccent, size: 60),
|
|
||||||
// const SizedBox(height: 16),
|
|
||||||
// Text(
|
|
||||||
// "Oops!",
|
|
||||||
// style: GoogleFonts.poppins(
|
|
||||||
// fontSize: 20,
|
|
||||||
// fontWeight: FontWeight.bold,
|
|
||||||
// color: Colors.redAccent),
|
|
||||||
// ),
|
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
Text(
|
Text(
|
||||||
"No Traveller Available ",
|
"No Traveller Available ",
|
||||||
@ -417,14 +428,17 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
color: Colors.grey),
|
color: Colors.grey,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
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, color: Colors.grey),
|
fontSize: 16,
|
||||||
|
color: Colors.grey,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
],
|
],
|
||||||
@ -433,7 +447,8 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
/* Here collect the list to displayed the data in table or card Used */
|
/* Here collect the list to displayed the data in table or card Used */
|
||||||
List<dynamic> object = filteredTraveller.isNotEmpty
|
List<dynamic> object =
|
||||||
|
filteredTraveller.isNotEmpty
|
||||||
? filteredTraveller
|
? filteredTraveller
|
||||||
: allTraveller;
|
: allTraveller;
|
||||||
|
|
||||||
@ -442,12 +457,12 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
DateTime dateA = DateTime.parse(a['created_on']);
|
DateTime dateA = DateTime.parse(a['created_on']);
|
||||||
DateTime dateB = DateTime.parse(b['created_on']);
|
DateTime dateB = DateTime.parse(b['created_on']);
|
||||||
|
|
||||||
return dateB
|
return dateB.compareTo(dateA); // Descending: newest first
|
||||||
.compareTo(dateA); // Descending: newest first
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/* For pagination for list ... */
|
/* For pagination for list ... */
|
||||||
List paginatedTraveller = object
|
List paginatedTraveller =
|
||||||
|
object
|
||||||
.skip(currentPage * itemsPerPage)
|
.skip(currentPage * itemsPerPage)
|
||||||
.take(itemsPerPage)
|
.take(itemsPerPage)
|
||||||
.toList();
|
.toList();
|
||||||
@ -455,8 +470,7 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
/* Table ... */
|
/* Table ... */
|
||||||
Widget table = LayoutBuilder(
|
Widget table = LayoutBuilder(
|
||||||
builder: (context, constraints) {
|
builder: (context, constraints) {
|
||||||
double minWidth =
|
double minWidth = isDesktop ? constraints.maxWidth : 1300;
|
||||||
isDesktop ? constraints.maxWidth : 1300;
|
|
||||||
|
|
||||||
return ConstrainedBox(
|
return ConstrainedBox(
|
||||||
constraints: BoxConstraints(minWidth: minWidth),
|
constraints: BoxConstraints(minWidth: minWidth),
|
||||||
@ -465,7 +479,9 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
columnSpacing: isDesktop ? 24.0 : 16.0,
|
columnSpacing: isDesktop ? 24.0 : 16.0,
|
||||||
border: TableBorder(
|
border: TableBorder(
|
||||||
horizontalInside: BorderSide(
|
horizontalInside: BorderSide(
|
||||||
width: 0.5, color: Colors.grey.shade200),
|
width: 0.5,
|
||||||
|
color: Colors.grey.shade200,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
columns: [
|
columns: [
|
||||||
DataColumn(
|
DataColumn(
|
||||||
@ -473,67 +489,90 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
'Name',
|
'Name',
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
fontWeight: FontWeight.w600),
|
fontWeight: FontWeight.w600,
|
||||||
)),
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
DataColumn(
|
DataColumn(
|
||||||
label: Text(
|
label: Text(
|
||||||
'Email',
|
'Email',
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
fontWeight: FontWeight.w600),
|
fontWeight: FontWeight.w600,
|
||||||
)),
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
DataColumn(
|
DataColumn(
|
||||||
label: Text(
|
label: Text(
|
||||||
'Mobile',
|
'Mobile',
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
fontWeight: FontWeight.w600),
|
fontWeight: FontWeight.w600,
|
||||||
)),
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
DataColumn(
|
DataColumn(
|
||||||
label: Text(
|
label: Text(
|
||||||
'Status',
|
'Status',
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
fontWeight: FontWeight.w600),
|
fontWeight: FontWeight.w600,
|
||||||
)),
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
DataColumn(
|
DataColumn(
|
||||||
label: Text(
|
label: Text(
|
||||||
'Actions',
|
'Actions',
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
fontWeight: FontWeight.w600),
|
fontWeight: FontWeight.w600,
|
||||||
)),
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
rows: paginatedTraveller.map((tableObject) {
|
rows:
|
||||||
String fullName = '${tableObject['first_name'] ?? ''} ${tableObject['last_name'] ?? ''}';
|
paginatedTraveller.map((tableObject) {
|
||||||
|
String fullName =
|
||||||
|
'${tableObject['first_name'] ?? ''} ${tableObject['last_name'] ?? ''}';
|
||||||
String travellerId =
|
String travellerId =
|
||||||
tableObject['traveller_id']
|
tableObject['traveller_id']
|
||||||
.toString(); // Get user ID
|
.toString(); // Get user ID
|
||||||
bool isSelected =
|
bool isSelected =
|
||||||
selectedTravellerId == travellerId;
|
selectedTravellerId == travellerId;
|
||||||
|
|
||||||
return DataRow(cells: [
|
return DataRow(
|
||||||
DataCell(Text(fullName ?? 'N/A',
|
cells: [
|
||||||
|
DataCell(
|
||||||
|
Text(
|
||||||
|
fullName ?? 'N/A',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
fontFamily: "Inter",
|
fontFamily: "Inter",
|
||||||
))),
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
DataCell(
|
DataCell(
|
||||||
Text(tableObject['email'] ?? 'N/A',
|
Text(
|
||||||
|
tableObject['email'] ?? 'N/A',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
fontFamily: "Inter",
|
fontFamily: "Inter",
|
||||||
),
|
),
|
||||||
softWrap: true,
|
softWrap: true,
|
||||||
overflow: TextOverflow.ellipsis)),
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
DataCell(
|
DataCell(
|
||||||
Text(tableObject['mobile'] ?? 'N/A',
|
Text(
|
||||||
|
tableObject['mobile'] ?? 'N/A',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
fontFamily: "Inter",
|
fontFamily: "Inter",
|
||||||
),
|
),
|
||||||
softWrap: true,
|
softWrap: true,
|
||||||
overflow: TextOverflow.ellipsis)),
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
DataCell(
|
DataCell(
|
||||||
Text(
|
Text(
|
||||||
tableObject['is_active'] == "1"
|
tableObject['is_active'] == "1"
|
||||||
@ -542,52 +581,52 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
fontFamily: "Inter",
|
fontFamily: "Inter",
|
||||||
color: tableObject['is_active'] == "1"
|
color:
|
||||||
|
tableObject['is_active'] == "1"
|
||||||
? Colors.green
|
? Colors.green
|
||||||
: Colors.red,
|
: Colors.grey,
|
||||||
),
|
),
|
||||||
softWrap: true,
|
softWrap: true,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
DataCell(
|
DataCell(
|
||||||
// UserActionsMenu(
|
|
||||||
// user: forex,
|
|
||||||
// getUserDetails: (id) =>
|
|
||||||
// apiService.getSingleUser(id),
|
|
||||||
// ),
|
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
child: Image.asset(
|
child: Image.asset(
|
||||||
'assets/images/IconsImg/edit.png',
|
'assets/images/IconsImg/edit.png',
|
||||||
width: 20,
|
width: 20,
|
||||||
height: 15),
|
height: 15,
|
||||||
|
),
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
// final userId = getUserId(user['user_id']);
|
// final userId = getUserId(user['user_id']);
|
||||||
// final usersData = await getUserDetails(userId);
|
// final usersData = await getUserDetails(userId);
|
||||||
//
|
//
|
||||||
final travellerId = int.tryParse(
|
final travellerId = int.tryParse(
|
||||||
tableObject['traveller_id']
|
tableObject['traveller_id']
|
||||||
.toString());
|
.toString(),
|
||||||
|
);
|
||||||
|
|
||||||
if (travellerId != null) {
|
if (travellerId != null) {
|
||||||
print(
|
print(
|
||||||
"Table cell - traveller Id -- $travellerId");
|
"Table cell - traveller Id -- $travellerId",
|
||||||
|
);
|
||||||
final data = await apiService
|
final data = await apiService
|
||||||
.getTravellerDetailsFind(
|
.getTravellerDetailsFind(
|
||||||
travellerId);
|
travellerId,
|
||||||
|
);
|
||||||
print("TravellerId -- $data");
|
print("TravellerId -- $data");
|
||||||
|
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) =>
|
builder:
|
||||||
TravellerData(
|
(context) => TravellerData(
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
travellerId:
|
travellerId:
|
||||||
travellerId, // Pass the ID
|
travellerId, // Pass the ID
|
||||||
travellerData: data,
|
travellerData: data,
|
||||||
layoutColor: layoutColor!,
|
layoutColor: layoutColor!,
|
||||||
// fetchGetForex: fetchGetForex,
|
fetchGetTraveller:
|
||||||
fetchGetTraveller: refreshData,
|
refreshData,
|
||||||
// role:
|
// role:
|
||||||
// "Travel Agent"
|
// "Travel Agent"
|
||||||
),
|
),
|
||||||
@ -598,7 +637,8 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
]);
|
],
|
||||||
|
);
|
||||||
}).toList(),
|
}).toList(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -611,11 +651,14 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
itemCount: paginatedUser.length,
|
itemCount: paginatedUser.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final cardObject = paginatedUser[index];
|
final cardObject = paginatedUser[index];
|
||||||
String fullName = '${cardObject['first_name'] ?? ''} ${cardObject['last_name'] ?? ''}';
|
String fullName =
|
||||||
|
'${cardObject['first_name'] ?? ''} ${cardObject['last_name'] ?? ''}';
|
||||||
return Card(
|
return Card(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
margin: EdgeInsets.symmetric(
|
margin: EdgeInsets.symmetric(
|
||||||
horizontal: 12, vertical: 6),
|
horizontal: 12,
|
||||||
|
vertical: 6,
|
||||||
|
),
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
),
|
),
|
||||||
@ -635,34 +678,36 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 10,
|
fontSize: 10,
|
||||||
color: Colors.black87,
|
color: Colors.black87,
|
||||||
fontWeight: FontWeight.w700),
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
child: Image.asset(
|
child: Image.asset(
|
||||||
'assets/images/IconsImg/edit.png',
|
'assets/images/IconsImg/edit.png',
|
||||||
width: 20,
|
width: 20,
|
||||||
height: 15),
|
height: 15,
|
||||||
|
),
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
// final userId = getUserId(user['user_id']);
|
// final userId = getUserId(user['user_id']);
|
||||||
// final usersData = await getUserDetails(userId);
|
// final usersData = await getUserDetails(userId);
|
||||||
//
|
//
|
||||||
final travellerId = int.tryParse(
|
final travellerId = int.tryParse(
|
||||||
cardObject['traveller_id']
|
cardObject['traveller_id'].toString(),
|
||||||
.toString());
|
);
|
||||||
|
|
||||||
if (travellerId != null) {
|
if (travellerId != null) {
|
||||||
print(
|
print("travellerId -- $travellerId");
|
||||||
"travellerId -- $travellerId");
|
|
||||||
final data = await apiService
|
final data = await apiService
|
||||||
.getTravellerDetailsFind(
|
.getTravellerDetailsFind(
|
||||||
travellerId);
|
travellerId,
|
||||||
|
);
|
||||||
print("TravellerId -- $data");
|
print("TravellerId -- $data");
|
||||||
|
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) =>
|
builder:
|
||||||
TravellerData(
|
(context) => TravellerData(
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
travellerId:
|
travellerId:
|
||||||
travellerId, // Pass the ID
|
travellerId, // Pass the ID
|
||||||
@ -680,79 +725,6 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
// 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),
|
|
||||||
// onPressed: () {
|
|
||||||
// print(
|
|
||||||
// "USerDAta - $user");
|
|
||||||
// // dynamic usersData = apiService
|
|
||||||
// // .getSingleUser(user[
|
|
||||||
// // 'user_id']
|
|
||||||
// // is String
|
|
||||||
// // ? int.parse(user[
|
|
||||||
// // 'user_id'])
|
|
||||||
// // : user[
|
|
||||||
// // 'user_id']);
|
|
||||||
// //
|
|
||||||
// // print(
|
|
||||||
// // "USerDAta - $usersData");
|
|
||||||
//
|
|
||||||
// context.go(
|
|
||||||
// "/CreateUserDetails",
|
|
||||||
// extra: {
|
|
||||||
// "selectedUser":
|
|
||||||
// user,
|
|
||||||
// "isViewMode": true
|
|
||||||
// },
|
|
||||||
// );
|
|
||||||
// }),
|
|
||||||
// IconButton(
|
|
||||||
// icon: Image.asset(
|
|
||||||
// 'assets/images/IconsImg/edit.png',
|
|
||||||
// width: 20,
|
|
||||||
// height: 15),
|
|
||||||
// onPressed: () {
|
|
||||||
// context.go(
|
|
||||||
// "/CreateUserDetails",
|
|
||||||
// extra: {
|
|
||||||
// "selectedUser":
|
|
||||||
// user,
|
|
||||||
// "isViewMode": false
|
|
||||||
// },
|
|
||||||
// );
|
|
||||||
// },
|
|
||||||
// ),
|
|
||||||
// ],
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ],
|
|
||||||
// ),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
||||||
@ -766,25 +738,25 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
CrossAxisAlignment.start,
|
CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
cardObject['email'] ?? '',
|
'${cardObject['email'] ?? 'N/A'}',
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 10,
|
fontSize: 10,
|
||||||
color: Colors.black87),
|
color: Colors.black87,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(width: 10),
|
||||||
width: 10,
|
|
||||||
),
|
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment:
|
crossAxisAlignment:
|
||||||
CrossAxisAlignment.start,
|
CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
cardObject['mobile'] ?? '',
|
'${cardObject['mobile'] ?? 'N/A'}',
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 10,
|
fontSize: 10,
|
||||||
color: Colors.black87),
|
color: Colors.black87,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -805,7 +777,8 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: isDesktop
|
child:
|
||||||
|
isDesktop
|
||||||
? (searchController.text.isNotEmpty &&
|
? (searchController.text.isNotEmpty &&
|
||||||
filteredTraveller.isEmpty
|
filteredTraveller.isEmpty
|
||||||
? Center(
|
? Center(
|
||||||
@ -813,7 +786,8 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
"No matches found",
|
"No matches found",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: Colors.grey),
|
color: Colors.grey,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: SingleChildScrollView(
|
: SingleChildScrollView(
|
||||||
@ -827,11 +801,13 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
"No matches found",
|
"No matches found",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: Colors.grey),
|
color: Colors.grey,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: buildMobileCardView(
|
: buildMobileCardView(
|
||||||
paginatedTraveller)),
|
paginatedTraveller,
|
||||||
|
)),
|
||||||
),
|
),
|
||||||
// Expanded(
|
// Expanded(
|
||||||
// child: isDesktop
|
// child: isDesktop
|
||||||
@ -862,9 +838,11 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
)
|
),
|
||||||
]),
|
],
|
||||||
)),
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -663,6 +663,7 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
"last_name",
|
"last_name",
|
||||||
"email",
|
"email",
|
||||||
"mobile_no",
|
"mobile_no",
|
||||||
|
"role_id",
|
||||||
// "employeeCode",
|
// "employeeCode",
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -1125,6 +1126,9 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
case "travel":
|
case "travel":
|
||||||
|
final fullName =
|
||||||
|
"${controllers["Fname"]?.text ?? ""} ${controllers["Lname"]?.text ?? ""}"
|
||||||
|
.trim();
|
||||||
return TravellerDetails(
|
return TravellerDetails(
|
||||||
key: travellerDetailsKey,
|
key: travellerDetailsKey,
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
@ -1134,6 +1138,7 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
travelDetails: travelDetailsDataFromAPI, // 👈 Pass this down
|
travelDetails: travelDetailsDataFromAPI, // 👈 Pass this down
|
||||||
passportFileUrlFromApi: passportFileUrlFromApi,
|
passportFileUrlFromApi: passportFileUrlFromApi,
|
||||||
userIdApi: userIdApi,
|
userIdApi: userIdApi,
|
||||||
|
fullName: fullName,
|
||||||
);
|
);
|
||||||
default:
|
default:
|
||||||
return PersonalDetails(
|
return PersonalDetails(
|
||||||
|
|||||||
@ -314,6 +314,8 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
SizedBox(height: 20),
|
SizedBox(height: 20),
|
||||||
|
_buildPassportDataRow1(widget.isDesktop),
|
||||||
|
SizedBox(height: 10),
|
||||||
_buildFirstRow(widget.isDesktop),
|
_buildFirstRow(widget.isDesktop),
|
||||||
SizedBox(height: 10),
|
SizedBox(height: 10),
|
||||||
_buildSecondRow(widget.isDesktop),
|
_buildSecondRow(widget.isDesktop),
|
||||||
@ -329,6 +331,25 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _buildPassportDataRow1(bool isDesktop) {
|
||||||
|
return Container(
|
||||||
|
color: Colors.white,
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"* Please fill name details as per in passport *",
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 10,
|
||||||
|
color: Colors.black87,
|
||||||
|
fontStyle: FontStyle.italic,
|
||||||
|
letterSpacing: 0.5,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> loadAllServices() async {
|
Future<void> loadAllServices() async {
|
||||||
try {
|
try {
|
||||||
final result = await apiService.fetchAllServices();
|
final result = await apiService.fetchAllServices();
|
||||||
@ -1500,7 +1521,7 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Role",
|
"Role*",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
@ -1579,6 +1600,13 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
if (widget.errorMessages["role_id"] != null) ...[
|
||||||
|
SizedBox(height: 5), // Space before error message
|
||||||
|
Text(
|
||||||
|
widget.errorMessages["role_id"]!,
|
||||||
|
style: TextStyle(color: Colors.red, fontSize: 12),
|
||||||
|
),
|
||||||
|
],
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,6 +32,7 @@ class TravellerDetails extends StatefulWidget {
|
|||||||
final Map<String, dynamic>? travelDetails;
|
final Map<String, dynamic>? travelDetails;
|
||||||
final String? passportFileUrlFromApi;
|
final String? passportFileUrlFromApi;
|
||||||
final String? userIdApi;
|
final String? userIdApi;
|
||||||
|
final String fullName;
|
||||||
|
|
||||||
const TravellerDetails({
|
const TravellerDetails({
|
||||||
Key? key,
|
Key? key,
|
||||||
@ -42,6 +43,7 @@ class TravellerDetails extends StatefulWidget {
|
|||||||
this.travelDetails,
|
this.travelDetails,
|
||||||
this.passportFileUrlFromApi,
|
this.passportFileUrlFromApi,
|
||||||
this.userIdApi,
|
this.userIdApi,
|
||||||
|
required this.fullName,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
@override
|
@override
|
||||||
TravellerDetailsState createState() => TravellerDetailsState();
|
TravellerDetailsState createState() => TravellerDetailsState();
|
||||||
@ -54,6 +56,8 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
int? expandedIndex;
|
int? expandedIndex;
|
||||||
bool isCountryLoading = true;
|
bool isCountryLoading = true;
|
||||||
|
|
||||||
|
Map<String, String> errorMessages = {};
|
||||||
|
|
||||||
late final userId;
|
late final userId;
|
||||||
String? selectedFileNames;
|
String? selectedFileNames;
|
||||||
Uint8List? passportDocumentBytes;
|
Uint8List? passportDocumentBytes;
|
||||||
@ -154,18 +158,16 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
String value,
|
String value,
|
||||||
String? userId,
|
String? userId,
|
||||||
) async {
|
) async {
|
||||||
var newField = "";
|
|
||||||
try {
|
try {
|
||||||
final response = await apiService.CheckDuplicate(
|
final response = await apiService.CheckDuplicate(
|
||||||
label,
|
label,
|
||||||
newField,
|
field,
|
||||||
value,
|
value,
|
||||||
userId,
|
userId,
|
||||||
);
|
);
|
||||||
if (response.isNotEmpty) {
|
if (response.isNotEmpty) {
|
||||||
_clearError(field);
|
_clearError(field);
|
||||||
widget.errorMessages[field] =
|
errorMessages[field] = response['message'] ?? "$label Already Exists";
|
||||||
response['message'] ?? "$label already exists";
|
|
||||||
print("Duplicate found: ${response['message']}");
|
print("Duplicate found: ${response['message']}");
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
@ -177,9 +179,37 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Future<void> apiCheckDuplicate(
|
||||||
|
// String label,
|
||||||
|
// String field,
|
||||||
|
// String value,
|
||||||
|
// String? userId,
|
||||||
|
// ) async {
|
||||||
|
// var newField = "";
|
||||||
|
// try {
|
||||||
|
// final response = await apiService.CheckDuplicate(
|
||||||
|
// label,
|
||||||
|
// newField,
|
||||||
|
// value,
|
||||||
|
// userId,
|
||||||
|
// );
|
||||||
|
// if (response.isNotEmpty) {
|
||||||
|
// _clearError(field);
|
||||||
|
// errorMessages[field] = response['message'] ?? "$label already exists";
|
||||||
|
// print("Duplicate found: ${response['message']}");
|
||||||
|
// return;
|
||||||
|
// } else {
|
||||||
|
// _clearError(field);
|
||||||
|
// print("No duplicates found.");
|
||||||
|
// }
|
||||||
|
// } catch (e) {
|
||||||
|
// print("Error in checkDuplicate: $e");
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
void _clearError(String field) {
|
void _clearError(String field) {
|
||||||
setState(() {
|
setState(() {
|
||||||
widget.errorMessages.remove(field);
|
errorMessages.remove(field);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -858,7 +888,7 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
// SizedBox(
|
// SizedBox(
|
||||||
// height: 10,
|
// height: 10,
|
||||||
// ),
|
// ),
|
||||||
// _buildPassportDataRow1(widget.isDesktop),
|
_buildPassportDataRow1(widget.isDesktop),
|
||||||
SizedBox(height: 10),
|
SizedBox(height: 10),
|
||||||
_buildPassportDataRow2(widget.isDesktop),
|
_buildPassportDataRow2(widget.isDesktop),
|
||||||
SizedBox(height: 10),
|
SizedBox(height: 10),
|
||||||
@ -870,28 +900,49 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
Widget _buildPassportDataRow1(bool isDesktop) {
|
Widget _buildPassportDataRow1(bool isDesktop) {
|
||||||
return Container(
|
return Container(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
child:
|
child: Row(
|
||||||
widget.isDesktop
|
|
||||||
? Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
children: [
|
||||||
buildFirstNameField(),
|
Text(
|
||||||
Spacer(),
|
"Name as per passport : ",
|
||||||
buildLastNameField(),
|
style: GoogleFonts.poppins(
|
||||||
Spacer(), // Space after Last Name
|
fontSize: 11,
|
||||||
buildNationality(),
|
fontStyle: FontStyle.italic,
|
||||||
],
|
letterSpacing: 0.5,
|
||||||
)
|
),
|
||||||
: Column(
|
),
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
Text(
|
||||||
children: [
|
"${widget.fullName} ",
|
||||||
buildFirstNameField(),
|
style: GoogleFonts.poppins(
|
||||||
SizedBox(height: 8), // Vertical space
|
fontSize: 10,
|
||||||
buildLastNameField(),
|
fontWeight: FontWeight.w600,
|
||||||
SizedBox(height: 8),
|
letterSpacing: 0.5,
|
||||||
buildNationality(),
|
color: Colors.black87,
|
||||||
|
// fontStyle: FontStyle.italic,
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
// child: widget.isDesktop
|
||||||
|
// ? Row(
|
||||||
|
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
// children: [
|
||||||
|
// buildFirstNameField(),
|
||||||
|
// Spacer(),
|
||||||
|
// buildLastNameField(),
|
||||||
|
// Spacer(), // Space after Last Name
|
||||||
|
// buildNationality(),
|
||||||
|
// ],
|
||||||
|
// )
|
||||||
|
// : Column(
|
||||||
|
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
// children: [
|
||||||
|
// buildFirstNameField(),
|
||||||
|
// SizedBox(height: 8), // Vertical space
|
||||||
|
// buildLastNameField(),
|
||||||
|
// SizedBox(height: 8),
|
||||||
|
// buildNationality(),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -984,13 +1035,6 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (widget.errorMessages["first_name"] != null) ...[
|
|
||||||
SizedBox(height: 5), // Space before error message
|
|
||||||
Text(
|
|
||||||
widget.errorMessages["first_name"]!,
|
|
||||||
style: TextStyle(color: Colors.red, fontSize: 12),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1033,13 +1077,6 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (widget.errorMessages["last_name"] != null) ...[
|
|
||||||
SizedBox(height: 5), // Space before error message
|
|
||||||
Text(
|
|
||||||
widget.errorMessages["last_name"]!,
|
|
||||||
style: TextStyle(color: Colors.red, fontSize: 12),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1082,13 +1119,6 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (widget.errorMessages["last_name"] != null) ...[
|
|
||||||
SizedBox(height: 5), // Space before error message
|
|
||||||
Text(
|
|
||||||
widget.errorMessages["last_name"]!,
|
|
||||||
style: TextStyle(color: Colors.red, fontSize: 12),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1137,10 +1167,10 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (widget.errorMessages["passport_number"] != null) ...[
|
if (errorMessages["passport_number"] != null) ...[
|
||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
Text(
|
Text(
|
||||||
widget.errorMessages["passport_number"]!,
|
errorMessages["passport_number"]!,
|
||||||
style: TextStyle(color: Colors.red, fontSize: 12),
|
style: TextStyle(color: Colors.red, fontSize: 12),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -2375,6 +2405,13 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
if (errorMessages["forex_pre_paid_card_number"] != null) ...[
|
||||||
|
SizedBox(height: 5), // Space before error message
|
||||||
|
Text(
|
||||||
|
errorMessages["forex_pre_paid_card_number"]!,
|
||||||
|
style: TextStyle(color: Colors.red, fontSize: 12),
|
||||||
|
),
|
||||||
|
],
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,3 @@
|
|||||||
//api url
|
//api url
|
||||||
const String apiUrl = 'http://apitest.tripapprovaltool.com/tstat_be';
|
const String apiUrl = 'http://apitest.tripapprovaltool.com/tstat_be';
|
||||||
// const String apiUrl = 'https://uat.tripapprovaltool.com';
|
// const String apiUrl = 'https://uat.tripapprovaltool.com/tstat_be';
|
||||||
|
|||||||
@ -143,7 +143,7 @@ class OrganizationSettingState extends State<OrganizationSetting> {
|
|||||||
{
|
{
|
||||||
'value': '/traveller',
|
'value': '/traveller',
|
||||||
'icon': Icons.travel_explore,
|
'icon': Icons.travel_explore,
|
||||||
'label': 'Traveller',
|
'label': 'Traveller (Non Employee)',
|
||||||
'description': 'Create and Edit Traveller',
|
'description': 'Create and Edit Traveller',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
@ -318,7 +318,7 @@ class ApiService {
|
|||||||
Future<List<dynamic>> fetchAllGroup() async {
|
Future<List<dynamic>> fetchAllGroup() async {
|
||||||
String? orgId = await getOrgId();
|
String? orgId = await getOrgId();
|
||||||
|
|
||||||
final String apiUrldata = '$apiUrl/api/groups?org_id=$orgId';
|
final String apiUrldata = '$apiUrl/api/groups?for=table_view&org_id=$orgId';
|
||||||
|
|
||||||
final token = await getToken();
|
final token = await getToken();
|
||||||
|
|
||||||
@ -392,7 +392,7 @@ class ApiService {
|
|||||||
Future<List<dynamic>> fetchAllPolicy() async {
|
Future<List<dynamic>> fetchAllPolicy() async {
|
||||||
String? orgId = await getOrgId();
|
String? orgId = await getOrgId();
|
||||||
|
|
||||||
final String apiUrldata = '$apiUrl/api/policy?org_id=$orgId';
|
final String apiUrldata = '$apiUrl/api/policy?for=table_view&org_id=$orgId';
|
||||||
|
|
||||||
final token = await getToken();
|
final token = await getToken();
|
||||||
|
|
||||||
|
|||||||
35
lib/widgets/saving_loader.dart
Normal file
35
lib/widgets/saving_loader.dart
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
// saving_loader.dart
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class SavingLoader extends StatelessWidget {
|
||||||
|
const SavingLoader({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Dialog(
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(24.0),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
const SizedBox(
|
||||||
|
width: 80,
|
||||||
|
height: 10,
|
||||||
|
child: LinearProgressIndicator(
|
||||||
|
backgroundColor: Colors.green,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
const Text(
|
||||||
|
"Your changes are being saved.",
|
||||||
|
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user