This commit is contained in:
venba-Inspriron-3558 2025-06-30 18:23:02 +05:30
parent 12d11ed0d8
commit 3be15a71ef
5 changed files with 1393 additions and 1062 deletions

View File

@ -40,7 +40,7 @@ class Policy extends StatefulWidget {
class _PolicyState extends State<Policy> { class _PolicyState extends State<Policy> {
final GlobalKey<PolicyCriteriaState> policyCriteriaKey = final GlobalKey<PolicyCriteriaState> policyCriteriaKey =
GlobalKey<PolicyCriteriaState>(); GlobalKey<PolicyCriteriaState>();
final ApiService apiService = ApiService(); final ApiService apiService = ApiService();
@ -82,22 +82,22 @@ class _PolicyState extends State<Policy> {
Map<String, dynamic> get policyData { Map<String, dynamic> get policyData {
List<Map<String, dynamic>> policyDetails = List<Map<String, dynamic>> policyDetails =
policy_details!.where((service) { 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
return fieldsToCheck.any((field) { return fieldsToCheck.any((field) {
final value = service[field]; final value = service[field];
return value != null && value.toString().trim().isNotEmpty; return value != null && value.toString().trim().isNotEmpty;
}); });
}).toList(); }).toList();
Map<String, dynamic> data = { Map<String, dynamic> data = {
@ -181,14 +181,14 @@ class _PolicyState extends State<Policy> {
setState(() { setState(() {
layoutColor = layoutColor =
layoutString != null layoutString != null
? Color(int.parse(layoutString)) ? Color(int.parse(layoutString))
: Colors.redAccent; : Colors.redAccent;
bodyColor = bodyColor =
bodyStringColor != null bodyStringColor != null
? Color(int.parse(bodyStringColor)) ? Color(int.parse(bodyStringColor))
: Colors.white; : Colors.white;
}); });
} }
@ -220,9 +220,9 @@ class _PolicyState extends State<Policy> {
try { try {
List<dynamic> decoded = json.decode(rawServices); List<dynamic> decoded = json.decode(rawServices);
List<Map<String, String>> formatted = List<Map<String, String>> formatted =
decoded decoded
.map((e) => {"service_id": e['service_id'].toString()}) .map((e) => {"service_id": e['service_id'].toString()})
.toList(); .toList();
setState(() { setState(() {
selectedOrgServiceIds = formatted; selectedOrgServiceIds = formatted;
@ -247,7 +247,7 @@ class _PolicyState extends State<Policy> {
await loadOrgSelectedAlServices(); await loadOrgSelectedAlServices();
final selectedIds = final selectedIds =
selectedOrgServiceIds.map((e) => e['service_id']).toSet(); selectedOrgServiceIds.map((e) => e['service_id']).toSet();
if (widget.policy != null) { if (widget.policy != null) {
final details = List<Map<String, dynamic>>.from( final details = List<Map<String, dynamic>>.from(
@ -260,12 +260,12 @@ class _PolicyState extends State<Policy> {
// pr int("UUFiltered Selected Services - $details"); // pr int("UUFiltered Selected Services - $details");
final filtered = final filtered =
selectedAllServices! selectedAllServices!
.where( .where(
(service) => (service) =>
selectedIds.contains(service['service_id'].toString()), selectedIds.contains(service['service_id'].toString()),
) )
.toList(); .toList();
setState(() { setState(() {
ServicesChoosed = filtered; ServicesChoosed = filtered;
@ -290,11 +290,11 @@ class _PolicyState extends State<Policy> {
List<Map<String, dynamic>>.from(decoded) List<Map<String, dynamic>>.from(decoded)
.map( .map(
(service) => { (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();
}); });
@ -304,12 +304,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 = final filtered =
selectedAllServices! selectedAllServices!
.where( .where(
(service) => (service) =>
selectedIds.contains(service['service_id'].toString()), selectedIds.contains(service['service_id'].toString()),
) )
.toList(); .toList();
print("ServicesChoosedYY: $ServicesChoosed"); print("ServicesChoosedYY: $ServicesChoosed");
setState(() { setState(() {
@ -324,12 +324,12 @@ class _PolicyState extends State<Policy> {
ServicesChoosed! ServicesChoosed!
.map( .map(
(service) => { (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();
}); });
@ -408,7 +408,7 @@ class _PolicyState extends State<Policy> {
if (domestic != "1" && international != "1") { if (domestic != "1" && international != "1") {
errorMessages["trip_type"] = errorMessages["trip_type"] =
"Required"; // "Please select Domestic or International."; "Required"; // "Please select Domestic or International.";
} }
// Validate at least one policy_detail with valid content // Validate at least one policy_detail with valid content
@ -430,7 +430,7 @@ class _PolicyState extends State<Policy> {
if (!hasAtLeastOneDetail) { if (!hasAtLeastOneDetail) {
errorMessages["policy_details"] = errorMessages["policy_details"] =
"Required"; // "At least one valid policy detail is required."; "Required"; // "At least one valid policy detail is required.";
} }
return errorMessages.isEmpty; return errorMessages.isEmpty;
@ -496,16 +496,16 @@ class _PolicyState extends State<Policy> {
drawer: CustomDrawer(isDesktop: false), drawer: CustomDrawer(isDesktop: false),
body: Padding( body: Padding(
padding: padding:
isDesktop isDesktop
? EdgeInsets.symmetric( ? EdgeInsets.symmetric(
horizontal: horizontal:
MediaQuery.of(context).size.width * MediaQuery.of(context).size.width *
0.1, // 30% of screen width as horizontal padding 0.1, // 30% of screen width as horizontal padding
vertical: vertical:
MediaQuery.of(context).size.height * MediaQuery.of(context).size.height *
0, // 5% of screen height as vertical padding 0, // 5% of screen height as vertical padding
) )
: EdgeInsets.all(8), : EdgeInsets.all(8),
child: Column( child: Column(
children: [ children: [
Expanded( Expanded(
@ -591,15 +591,15 @@ class _PolicyState extends State<Policy> {
color: Colors.white, color: Colors.white,
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: child:
isDesktop isDesktop
? Row( ? Row(
mainAxisAlignment: MainAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end,
children: _buildSubmit(isDesktop), children: _buildSubmit(isDesktop),
) )
: Row( : Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: _buildSubmit(isDesktop), children: _buildSubmit(isDesktop),
), ),
), ),
], ],
), ),
@ -612,9 +612,9 @@ class _PolicyState extends State<Policy> {
// ? 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: height:
isDesktop isDesktop
? MediaQuery.of(context).size.height * 0.98 ? MediaQuery.of(context).size.height * 0.98
: MediaQuery.of(context).size.height, : MediaQuery.of(context).size.height,
// decoration: BoxDecoration( // decoration: BoxDecoration(
// border: isDesktop // border: isDesktop
// ? Border.all( // ? Border.all(
@ -663,23 +663,23 @@ class _PolicyState extends State<Policy> {
Container( Container(
padding: isDesktop ? const EdgeInsets.only(left: 35) : null, padding: isDesktop ? const EdgeInsets.only(left: 35) : null,
child: child:
isDesktop isDesktop
? Row( ? Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Expanded(child: _buildPolicyNameField(isDesktop)), Expanded(child: _buildPolicyNameField(isDesktop)),
Spacer(), Spacer(),
Expanded(child: _buildPolicyTypeField(isDesktop)), Expanded(child: _buildPolicyTypeField(isDesktop)),
], ],
) )
: Column( : Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
_buildPolicyNameField(isDesktop), _buildPolicyNameField(isDesktop),
SizedBox(height: 20), SizedBox(height: 20),
_buildPolicyTypeField(isDesktop), _buildPolicyTypeField(isDesktop),
], ],
), ),
), ),
SizedBox(height: 10), SizedBox(height: 10),
Divider(thickness: 0.1, color: Colors.grey), Divider(thickness: 0.1, color: Colors.grey),
@ -692,66 +692,66 @@ class _PolicyState extends State<Policy> {
], ],
isDesktop isDesktop
? Padding( ? Padding(
padding: const EdgeInsets.only(left: 30.0, right: 98.0), padding: const EdgeInsets.only(left: 30.0, right: 98.0),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Text( Text(
"Approval Criteria", "Approval Criteria",
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: Color(0xFF575A74), color: Color(0xFF575A74),
), ),
),
Text(
"Service Priority",
style: GoogleFonts.poppins(
fontSize: 12,
fontWeight: FontWeight.w600,
color: Color(0xFF575A74),
),
),
],
), ),
) Text(
"Service Priority",
style: GoogleFonts.poppins(
fontSize: 12,
fontWeight: FontWeight.w600,
color: Color(0xFF575A74),
),
),
],
),
)
: SizedBox.shrink(), : SizedBox.shrink(),
isDesktop isDesktop
? Container( ? Container(
// color: Colors.yellow.shade50, // color: Colors.yellow.shade50,
height: MediaQuery.of(context).size.height * 0.54, height: MediaQuery.of(context).size.height * 0.54,
child: SingleChildScrollView( child: SingleChildScrollView(
scrollDirection: Axis.vertical, scrollDirection: Axis.vertical,
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
children: [ children: [
Column( _buildPolicyOrdering(isDesktop),
children: [ _buildPolicyCategory(isDesktop),
_buildPolicyOrdering(isDesktop),
_buildPolicyCategory(isDesktop),
],
),
Column(children: [_buildPolicyCategoryList(isDesktop)]),
], ],
), ),
), Column(children: [_buildPolicyCategoryList(isDesktop)]),
) ],
),
),
)
: Expanded( : Expanded(
child: Container( child: Container(
child: SingleChildScrollView( child: SingleChildScrollView(
scrollDirection: Axis.vertical, scrollDirection: Axis.vertical,
child: Column( child: Column(
children: [ children: [
_buildPolicyCategoryList(isDesktop), _buildPolicyCategoryList(isDesktop),
_buildPolicyOrdering(isDesktop), _buildPolicyOrdering(isDesktop),
_buildPolicyCategory(isDesktop), _buildPolicyCategory(isDesktop),
], ],
),
),
), ),
), ),
),
),
// isDesktop // isDesktop
// ? Expanded( // ? Expanded(
// child: Row( // child: Row(
@ -864,28 +864,28 @@ class _PolicyState extends State<Policy> {
border: Border.all(color: Colors.blueGrey.shade100, width: 0.35), border: Border.all(color: Colors.blueGrey.shade100, width: 0.35),
), ),
child: child:
isDesktop isDesktop
? Padding( ? Padding(
padding: const EdgeInsets.all(10.0), padding: const EdgeInsets.all(10.0),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
children: [_buildPolicySubCategoryList(isDesktop)], children: [_buildPolicySubCategoryList(isDesktop)],
), ),
) )
: Column( : Column(
children: [ children: [
Container( Container(
// color: Colors.amber, // color: Colors.amber,
child: _buildPolicySubCategoryList(isDesktop), child: _buildPolicySubCategoryList(isDesktop),
// child: Text("FAta"), // child: Text("FAta"),
// child: Row( // child: Row(
// mainAxisAlignment: MainAxisAlignment.start, // mainAxisAlignment: MainAxisAlignment.start,
// children: [_buildPolicySubCategoryList(isDesktop)], // children: [_buildPolicySubCategoryList(isDesktop)],
// ), // ),
), ),
], ],
), ),
); );
} }
@ -1042,21 +1042,21 @@ class _PolicyState extends State<Policy> {
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: child:
isDesktop 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)],
), ),
) )
: Container( : Container(
// color: Colors.amber, // color: Colors.amber,
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
children: [_buildPolicyServiceOrdering(isDesktop)], children: [_buildPolicyServiceOrdering(isDesktop)],
), ),
), ),
); );
} }
@ -1067,11 +1067,11 @@ class _PolicyState extends State<Policy> {
// Sort services by 'order' // Sort services by 'order'
ServicesChoosed!.sort( ServicesChoosed!.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();
return Container( return Container(
child: SingleChildScrollView( child: SingleChildScrollView(
@ -1079,104 +1079,104 @@ class _PolicyState extends State<Policy> {
child: Flex( child: Flex(
direction: Axis.horizontal, direction: Axis.horizontal,
children: children:
services.asMap().entries.map((entry) { 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 = bool isSelected =
selectedServiceIndex.value == index.toString(); selectedServiceIndex.value == index.toString();
return SizedBox( return SizedBox(
// width: isDesktop ? 40 : null, // width: isDesktop ? 40 : null,
height: height:
isDesktop isDesktop
? max( ? max(
(MediaQuery.of(context).size.height * 0.075), (MediaQuery.of(context).size.height * 0.075),
10, 10,
) )
: 45, : 45,
// max((MediaQuery.of(context).size.height * 0.09), 10) // max((MediaQuery.of(context).size.height * 0.09), 10)
child: GestureDetector( child: GestureDetector(
onTap: () { onTap: () {
print("Selected Services - $service - $index"); print("Selected Services - $service - $index");
setState(() { setState(() {
selectedServiceIndex.value = index.toString(); selectedServiceIndex.value = index.toString();
selectedService = service; selectedService = service;
print( print(
" selectedServiceIndex.value - ${selectedServiceIndex.value}", " selectedServiceIndex.value - ${selectedServiceIndex.value}",
); );
// policyCriteriaKey.currentState?.fieldForPolicy(); // policyCriteriaKey.currentState?.fieldForPolicy();
// policyCriteriaKey.currentState // policyCriteriaKey.currentState
// ?.addOrUpdatePolicy(selectedServiceIndex.value); // ?.addOrUpdatePolicy(selectedServiceIndex.value);
print("policyselectedService - $selectedService"); print("policyselectedService - $selectedService");
if (selectedService == "Flight" || if (selectedService == "Flight" ||
selectedService == "Train" || selectedService == "Accomodation") { selectedService == "Train" || selectedService == "Accomodation") {
showClass = true; showClass = true;
showCost = false; showCost = false;
int serviceCode = selectedService == "Flight" ? 1 : 2; int serviceCode = selectedService == "Flight" ? 1 : 2;
print("policyselectedService1 - $selectedService"); print("policyselectedService1 - $selectedService");
policyCriteriaKey.currentState policyCriteriaKey.currentState
?.fetchTrainFlightClass(); ?.fetchTrainFlightClass();
} }
// else if (selectedService == "Accommodation") { // else if (selectedService == "Accommodation") {
// showClass = true; // showClass = true;
// showCost = false; // showCost = false;
// } // }
else { else {
showClass = false; showClass = false;
showCost = false; showCost = false;
} }
}); });
}, },
child: Container( child: Container(
margin: const EdgeInsets.all(5), margin: const EdgeInsets.all(5),
padding: padding:
isDesktop isDesktop
? const EdgeInsets.all(8) ? const EdgeInsets.all(8)
: const EdgeInsets.symmetric( : const EdgeInsets.symmetric(
horizontal: 8, horizontal: 8,
vertical: 3, vertical: 3,
),
alignment: Alignment.center,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
service,
style: GoogleFonts.poppins(
color:
isSelected
? const Color(0xFF114D8B)
: Colors.black87,
fontSize: 13,
fontWeight:
isSelected
? FontWeight.bold
: FontWeight.w500,
decoration:
TextDecoration
.none, // remove built-in underline
),
),
if (isSelected)
const SizedBox(
height: 1,
), // spacing between text and underline
if (isSelected)
Container(
height: 2,
width: 30, // or based on text width
color: const Color(0xFF114D8B),
),
],
),
),
), ),
); alignment: Alignment.center,
}).toList(), child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
service,
style: GoogleFonts.poppins(
color:
isSelected
? const Color(0xFF114D8B)
: Colors.black87,
fontSize: 13,
fontWeight:
isSelected
? FontWeight.bold
: FontWeight.w500,
decoration:
TextDecoration
.none, // remove built-in underline
),
),
if (isSelected)
const SizedBox(
height: 1,
), // spacing between text and underline
if (isSelected)
Container(
height: 2,
width: 30, // or based on text width
color: const Color(0xFF114D8B),
),
],
),
),
),
);
}).toList(),
), ),
), ),
); );
@ -1200,7 +1200,7 @@ class _PolicyState extends State<Policy> {
} }
List<String> services = List<String> services =
ServicesChoosed!.map((service) => service['name'].toString()).toList(); ServicesChoosed!.map((service) => service['name'].toString()).toList();
return Expanded( return Expanded(
child: SingleChildScrollView( child: SingleChildScrollView(
@ -1208,88 +1208,88 @@ class _PolicyState extends State<Policy> {
child: Flex( child: Flex(
direction: isDesktop ? Axis.vertical : Axis.horizontal, direction: isDesktop ? Axis.vertical : Axis.horizontal,
children: children:
services.asMap().entries.map((entry) { 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 = bool isSelected =
selectedServiceIndex.value == index.toString(); selectedServiceIndex.value == index.toString();
return SizedBox( return SizedBox(
width: isDesktop ? 180 : null, width: isDesktop ? 180 : null,
height: height:
isDesktop isDesktop
? max( ? max(
(MediaQuery.of(context).size.height * 0.075), (MediaQuery.of(context).size.height * 0.075),
10, 10,
) )
: 45, : 45,
// max((MediaQuery.of(context).size.height * 0.09), 10) // max((MediaQuery.of(context).size.height * 0.09), 10)
child: GestureDetector( child: GestureDetector(
onTap: () { onTap: () {
print("Selected Services - $service - $index"); print("Selected Services - $service - $index");
setState(() { setState(() {
// selectedServiceIndex.value = index.toString(); // selectedServiceIndex.value = index.toString();
// selectedService = service; // selectedService = service;
// //
// if (selectedService == "Flight" || // if (selectedService == "Flight" ||
// selectedService == "Train") { // selectedService == "Train") {
// showClass = true; // showClass = true;
// 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;
// } else { // } else {
// showClass = false; // showClass = false;
// showCost = false; // showCost = false;
// } // }
}); });
}, },
child: Container( child: Container(
margin: EdgeInsets.all(5), margin: EdgeInsets.all(5),
padding: padding:
isDesktop isDesktop
? EdgeInsets.all(8) ? EdgeInsets.all(8)
: EdgeInsets.only( : EdgeInsets.only(
top: 3, top: 3,
bottom: 3, bottom: 3,
left: 8, left: 8,
right: 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,
// : Color(0xFFEBEBF7), // : Color(0xFFEBEBF7),
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
border: Border.all( border: Border.all(
color: Colors.white, // Light grey border color: Colors.white, // Light grey border
width: 1, width: 1,
), ),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: Colors.grey.withAlpha(90), // Shadow color color: Colors.grey.withAlpha(90), // Shadow color
blurRadius: 1, // Blur radius blurRadius: 1, // Blur radius
spreadRadius: 1, // Spread radius spreadRadius: 1, // Spread radius
offset: Offset(0, 1), // Shadow position offset: Offset(0, 1), // Shadow position
),
],
),
alignment: Alignment.center,
child: Text(
service,
style: GoogleFonts.poppins(
color: isSelected ? Colors.white : Colors.black87,
fontSize: 13,
fontWeight:
isSelected ? FontWeight.bold : FontWeight.w100,
),
), ),
],
),
alignment: Alignment.center,
child: Text(
service,
style: GoogleFonts.poppins(
color: isSelected ? Colors.white : Colors.black87,
fontSize: 13,
fontWeight:
isSelected ? FontWeight.bold : FontWeight.w100,
), ),
), ),
); ),
}).toList(), ),
);
}).toList(),
), ),
), ),
); );
@ -1366,14 +1366,14 @@ class _PolicyState extends State<Policy> {
borderRadius: BorderRadius.circular(4), // Rounded rectangle borderRadius: BorderRadius.circular(4), // Rounded rectangle
border: Border.all( border: Border.all(
color: color:
_selectedTripType == "1" ? Colors.green : Colors.black, _selectedTripType == "1" ? Colors.green : Colors.black,
width: _selectedTripType == "1" ? 2 : 1, width: _selectedTripType == "1" ? 2 : 1,
), ),
), ),
child: child:
_selectedTripType == "1" _selectedTripType == "1"
? Icon(Icons.rectangle, size: 8, color: Colors.green) ? Icon(Icons.rectangle, size: 8, color: Colors.green)
: null, // Add checkmark if selected : null, // Add checkmark if selected
), ),
), ),
], ],
@ -1422,14 +1422,14 @@ class _PolicyState extends State<Policy> {
borderRadius: BorderRadius.circular(4), // Rounded rectangle borderRadius: BorderRadius.circular(4), // Rounded rectangle
border: Border.all( border: Border.all(
color: color:
_selectedTripType == "2" ? Colors.green : Colors.black, _selectedTripType == "2" ? Colors.green : Colors.black,
width: _selectedTripType == "2" ? 2 : 1, width: _selectedTripType == "2" ? 2 : 1,
), ),
), ),
child: child:
_selectedTripType == "2" _selectedTripType == "2"
? Icon(Icons.rectangle, size: 8, color: Colors.green) ? Icon(Icons.rectangle, size: 8, color: Colors.green)
: null, // Add checkmark if selected : null, // Add checkmark if selected
), ),
), ),
], ],
@ -1474,17 +1474,17 @@ class _PolicyState extends State<Policy> {
SizedBox(width: 20), SizedBox(width: 20),
MouseRegion( MouseRegion(
cursor: cursor:
isViewMode isViewMode
? SystemMouseCursors.forbidden ? SystemMouseCursors.forbidden
: SystemMouseCursors.click, : SystemMouseCursors.click,
child: ElevatedButton( child: ElevatedButton(
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: backgroundColor:
isViewMode ? layoutColor : layoutColor, // Keep original color isViewMode ? layoutColor : layoutColor, // Keep original color
foregroundColor: foregroundColor:
isViewMode ? Colors.white : Colors.white, // Keep original color isViewMode ? Colors.white : Colors.white, // Keep original color
disabledBackgroundColor: disabledBackgroundColor:
layoutColor, // Ensure color remains when disabled layoutColor, // Ensure color remains when disabled
disabledForegroundColor: Colors.white, disabledForegroundColor: Colors.white,
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
@ -1493,7 +1493,7 @@ class _PolicyState extends State<Policy> {
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12), padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
), ),
onPressed: onPressed:
isViewMode ? null : handleSubmit, // Disable when in view mode isViewMode ? null : handleSubmit, // Disable when in view mode
child: Text("Submit", style: GoogleFonts.poppins(fontSize: 10)), child: Text("Submit", style: GoogleFonts.poppins(fontSize: 10)),
), ),
), ),
@ -1565,4 +1565,4 @@ class _PolicyState extends State<Policy> {
), ),
]; ];
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -102,6 +102,7 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
String? selectedSecondApprover; String? selectedSecondApprover;
String? selectedThirdApprover; String? selectedThirdApprover;
String? selectedSubstituteApprover; String? selectedSubstituteApprover;
String? selectedExceptionalApprover;
String? selectedFileNames; String? selectedFileNames;
Uint8List? passportDocumentBytes; Uint8List? passportDocumentBytes;
@ -174,6 +175,7 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
"first_approver": selectedFirstApprover, "first_approver": selectedFirstApprover,
"second_approver": selectedSecondApprover, "second_approver": selectedSecondApprover,
"third_approver": selectedThirdApprover, "third_approver": selectedThirdApprover,
"exceptional_approver" : selectedExceptionalApprover,
"delegated_to_user_id": selectedSubstituteApprover, "delegated_to_user_id": selectedSubstituteApprover,
// "passport_number": controllers["passportNumber"]?.text, // "passport_number": controllers["passportNumber"]?.text,
// "place_of_issue": controllers["placeOfIssue"]?.text, // "place_of_issue": controllers["placeOfIssue"]?.text,
@ -292,6 +294,11 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
apiselectedUser?["third_approver"]?.toString() ?? ""; apiselectedUser?["third_approver"]?.toString() ?? "";
} }
if (apiselectedUser?["exceptional_approver"] != null) {
selectedExceptionalApprover =
apiselectedUser?["exceptional_approver"]?.toString() ?? "";
}
if (apiselectedUser?["delegated_to_user_id"] != null) { if (apiselectedUser?["delegated_to_user_id"] != null) {
print( print(
"UPDADele- ${apiselectedUser?["delegated_to_user_id"]?.toString()}", "UPDADele- ${apiselectedUser?["delegated_to_user_id"]?.toString()}",
@ -814,6 +821,7 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
Map<String, dynamic> data = userDetials; Map<String, dynamic> data = userDetials;
print("userDetials ====> $userDetials");
if (!isValidData(data)) { if (!isValidData(data)) {
print("USERDETAILS : $userDetials"); print("USERDETAILS : $userDetials");
print("Validation Failed: Required fields are missing."); print("Validation Failed: Required fields are missing.");
@ -1447,6 +1455,7 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
selectedFirstApprover: selectedFirstApprover, selectedFirstApprover: selectedFirstApprover,
selectedSecondApprover: selectedSecondApprover, selectedSecondApprover: selectedSecondApprover,
selectedThirdApprover: selectedThirdApprover, selectedThirdApprover: selectedThirdApprover,
selectedExceptionalApprover: selectedExceptionalApprover,
selectedSubstituteApprover: selectedSubstituteApprover, selectedSubstituteApprover: selectedSubstituteApprover,
onLevelChanged: (gender) { onLevelChanged: (gender) {
setState(() { setState(() {
@ -1473,6 +1482,11 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
selectedThirdApprover = role; selectedThirdApprover = role;
}); });
}, },
onExceptionalApproverChanged: (role) {
setState(() {
selectedExceptionalApprover = role;
});
},
onFirstSubsApproverChanged: (role) { onFirstSubsApproverChanged: (role) {
setState(() { setState(() {
selectedSubstituteApprover = role; selectedSubstituteApprover = role;

View File

@ -23,6 +23,7 @@ class OfficeDetails extends StatefulWidget {
final ValueChanged<String?>? onSecondApproverChanged; final ValueChanged<String?>? onSecondApproverChanged;
final ValueChanged<String?>? onThirdApproverChanged; final ValueChanged<String?>? onThirdApproverChanged;
final ValueChanged<String?>? onFirstSubsApproverChanged; final ValueChanged<String?>? onFirstSubsApproverChanged;
final ValueChanged<String?>? onExceptionalApproverChanged;
final String? selectedLevel; final String? selectedLevel;
final String? selectedDepartment; final String? selectedDepartment;
@ -30,6 +31,7 @@ class OfficeDetails extends StatefulWidget {
final String? selectedSecondApprover; final String? selectedSecondApprover;
final String? selectedThirdApprover; final String? selectedThirdApprover;
final String? selectedSubstituteApprover; final String? selectedSubstituteApprover;
final String? selectedExceptionalApprover;
const OfficeDetails({ const OfficeDetails({
Key? key, Key? key,
@ -48,6 +50,8 @@ class OfficeDetails extends StatefulWidget {
this.onSecondApproverChanged, this.onSecondApproverChanged,
this.onThirdApproverChanged, this.onThirdApproverChanged,
this.selectedSubstituteApprover, this.selectedSubstituteApprover,
this.selectedExceptionalApprover,
this.onExceptionalApproverChanged,
this.onFirstSubsApproverChanged, this.onFirstSubsApproverChanged,
this.userIdApi, this.userIdApi,
}) : super(key: key); }) : super(key: key);
@ -94,6 +98,7 @@ class _OfficeDetailsState extends State<OfficeDetails> {
String? selectedSecondApprover; String? selectedSecondApprover;
String? selectedThirdApprover; String? selectedThirdApprover;
String? selectedSubstituteApprover; String? selectedSubstituteApprover;
String? selectedExceptionalApprover;
String? selectedFileNames; String? selectedFileNames;
Uint8List? passportDocumentBytes; Uint8List? passportDocumentBytes;
@ -125,6 +130,7 @@ class _OfficeDetailsState extends State<OfficeDetails> {
"firstApproval", "firstApproval",
"secondApproval", "secondApproval",
"thirdApproval", "thirdApproval",
"exceptional_approver",
"employeeCode", "employeeCode",
"dateOfIssue", "dateOfIssue",
"dateOfExpiry", "dateOfExpiry",
@ -151,6 +157,7 @@ class _OfficeDetailsState extends State<OfficeDetails> {
selectedSecondApprover = widget.selectedSecondApprover; selectedSecondApprover = widget.selectedSecondApprover;
selectedThirdApprover = widget.selectedThirdApprover; selectedThirdApprover = widget.selectedThirdApprover;
selectedSubstituteApprover = widget.selectedSubstituteApprover; selectedSubstituteApprover = widget.selectedSubstituteApprover;
selectedExceptionalApprover = widget.selectedExceptionalApprover;
fetchDepartment(); fetchDepartment();
fetchUsers(); fetchUsers();
@ -307,6 +314,8 @@ class _OfficeDetailsState extends State<OfficeDetails> {
if (widget.isDesktop) SizedBox(height: 10), if (widget.isDesktop) SizedBox(height: 10),
_buildSecondRow(widget.isDesktop), _buildSecondRow(widget.isDesktop),
if (widget.isDesktop) SizedBox(height: 10), if (widget.isDesktop) SizedBox(height: 10),
_buildThirdRow(widget.isDesktop),
if (widget.isDesktop) SizedBox(height: 10),
Divider(thickness: 0.2, color: Colors.blueGrey.shade100), Divider(thickness: 0.2, color: Colors.blueGrey.shade100),
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
@ -321,7 +330,7 @@ class _OfficeDetailsState extends State<OfficeDetails> {
], ],
), ),
SizedBox(height: 15), SizedBox(height: 15),
_buildThirdRow(widget.isDesktop), _buildFourthRow(widget.isDesktop),
], ],
), ),
); );
@ -384,6 +393,28 @@ class _OfficeDetailsState extends State<OfficeDetails> {
} }
Widget _buildThirdRow(bool isDesktop) { Widget _buildThirdRow(bool isDesktop) {
return Container(
color: Colors.white,
child:
widget.isDesktop
? Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
buildExceptionApprover(isDesktop),
Spacer(),
],
)
: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
buildExceptionApprover(isDesktop),
SizedBox(height: 8), // Vertical space
],
),
);
}
Widget _buildFourthRow(bool isDesktop) {
return Container( return Container(
color: Colors.white, color: Colors.white,
child: child:
@ -1185,6 +1216,130 @@ class _OfficeDetailsState extends State<OfficeDetails> {
); );
} }
Widget buildExceptionApprover(bool isDesktop) {
return Container(
color: Colors.white,
// child: Expanded(
// Allow first column to take available space
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Exceptional Approver",
style: GoogleFonts.poppins(
fontSize: 12,
fontWeight: FontWeight.w600,
color: Color(0xFF575A74),
),
),
SizedBox(height: 5),
CustomTextFieldUserWrapper(
isFocused: false,
isDesktop: isDesktop,
child: SizedBox(
height: 40,
child:
apiUserData == null
? Center(
child: Transform.scale(
scale: 0.5,
child: CircularProgressIndicator(),
),
)
: DropdownSearch<String>(
selectedItem: userMap[selectedExceptionalApprover],
enabled: !widget.isViewMode,
popupProps: PopupProps.menu(
showSearchBox: true,
fit: FlexFit.loose, // Allows flexible height
menuProps: const MenuProps(
backgroundColor: Colors.white,
),
itemBuilder:
(context, item, isSelected) => Container(
padding: EdgeInsets.symmetric(
horizontal: 10,
vertical: 6,
),
child: Text(
item,
style: GoogleFonts.poppins(
fontSize: 11.5,
),
),
),
constraints: BoxConstraints(maxHeight: 250),
searchFieldProps: TextFieldProps(
decoration: InputDecoration(
hintText: "Search User...",
contentPadding: EdgeInsets.symmetric(
horizontal: 10,
),
),
),
),
items:
apiUserData!.map((user) {
return "${user['first_name']} ${user['last_name']}";
}).toList(),
dropdownDecoratorProps: DropDownDecoratorProps(
dropdownSearchDecoration: InputDecoration(
border: InputBorder.none,
contentPadding: EdgeInsets.symmetric(
horizontal: 1,
),
),
),
dropdownBuilder:
(context, selectedItem) => Align(
// Center-align selected item
alignment: Alignment.centerLeft,
child: Text(
selectedItem ?? "Select",
style: GoogleFonts.poppins(
fontSize: 12,
),
),
),
onChanged: (String? newValue) {
if (newValue == null) return;
final approverId =
userMap.entries
.firstWhere(
(entry) => entry.value == newValue,
)
.key;
setState(() {
selectedExceptionalApprover = approverId;
});
widget.onExceptionalApproverChanged?.call(
approverId,
); // not newValue, but approverId
},
),
),
),
],
),
],
),
],
),
// ),
);
}
Widget buildApproverSubstitute1(bool isDesktop) { Widget buildApproverSubstitute1(bool isDesktop) {
return Container( return Container(
color: Colors.white, color: Colors.white,
@ -1246,7 +1401,7 @@ class _OfficeDetailsState extends State<OfficeDetails> {
), ),
), ),
), ),
constraints: BoxConstraints(maxHeight: 250), constraints: BoxConstraints(maxHeight: 133),
searchFieldProps: TextFieldProps( searchFieldProps: TextFieldProps(
decoration: InputDecoration( decoration: InputDecoration(
hintText: "Search User...", hintText: "Search User...",

View File

@ -46,36 +46,36 @@ class Plan {
factory Plan.fromJson(Map<String, dynamic> json) { factory Plan.fromJson(Map<String, dynamic> json) {
print('Parsing Plan from JSON: $json'); print('Parsing Plan from JSON: $json');
return Plan( return Plan(
planId: json['plan_id']!.toString(), planId: json['plan_id']?.toString() ?? "",
employeeCode: json['employee_code']!.toString(), employeeCode: json['employee_code']?.toString() ?? "",
tripTitle: json['trip_title']!.toString(), tripTitle: json['trip_title']?.toString() ?? "",
tripType: json['trip_type_value']!.toString(), tripType: json['trip_type_value']?.toString() ?? "",
approver_status: approver_status:
json["approver_status"] == null json["approver_status"] == null
? '' ? ''
: json['approver_status']!.toString(), : json['approver_status']?.toString() ?? "",
status: json['status'] == "0" ? "Inactive" : "Active", status: json['status'] == "0" ? "Inactive" : "Active",
costCenter: json['cost_center_value']!.toString(), costCenter: json['cost_center_value']?.toString() ?? "" ,
functionalDepartment: json['functional_department_value']!.toString(), functionalDepartment: json['functional_department_value']?.toString() ?? "",
purposeOfTravel: json['purpose_of_travel_value']!.toString(), purposeOfTravel: json['purpose_of_travel_value']?.toString() ?? "",
soNumber: json['so_number']!.toString(), soNumber: json['so_number']?.toString() ?? "",
description: json['description']!.toString(), description: json['description']?.toString() ?? "",
isBillable: json['is_billable_value']!.toString(), isBillable: json['is_billable_value']?.toString() ?? "",
userName: json["user_name"]!.toString(), userName: json["user_name"]?.toString() ?? "",
travellerName: travellerName:
json["traveller_name"] == null json["traveller_name"] == null
? '' ? ''
: json["traveller_name"]!.toString(), : json["traveller_name"]?.toString() ?? "",
approverName: approverName:
json["approver_name"] == null json["approver_name"] == null
? '' ? ''
: json["approver_name"]!.toString(), : json["approver_name"]?.toString() ?? "",
statusValue: json["status_value"]!.toString(), statusValue: json["status_value"]?.toString() ?? "",
createdOn: json["created_on"], createdOn: json["created_on"]?.toString() ?? "",
approverId: approverId:
json["approver_id"] == null ? '' : json['approver_id']!.toString(), json["approver_id"] == null ? '' : json['approver_id']?.toString() ?? "",
delegaterId: delegaterId:
json["delegater_id"] == null ? '' : json['delegater_id']!.toString(), json["delegater_id"] == null ? '' : json['delegater_id']?.toString() ?? "",
); );
} }
} }