1731 lines
55 KiB
Dart
1731 lines
55 KiB
Dart
import 'dart:convert';
|
|
import 'dart:math';
|
|
import 'dart:ui' as html;
|
|
|
|
import 'dart:async';
|
|
import 'dart:html' as html;
|
|
import 'dart:typed_data';
|
|
import 'package:fluttertoast/fluttertoast.dart';
|
|
import 'dart:ui' as web;
|
|
|
|
import 'package:google_fonts/google_fonts.dart';
|
|
import 'package:reorderables/reorderables.dart';
|
|
import 'package:web/web.dart' as web;
|
|
|
|
import 'package:flutter/material.dart';
|
|
import 'package:frontend/Screens/policy/policyCriteria.dart';
|
|
import 'package:go_router/go_router.dart';
|
|
import 'package:http/http.dart' as http;
|
|
import 'package:responsive_builder/responsive_builder.dart';
|
|
|
|
import '../../config/apiUrl.dart';
|
|
import '../../routes/custom_appBar.dart';
|
|
import '../../routes/custom_drawer.dart';
|
|
import '../../services/apiService.dart';
|
|
import '../../utils/auth_utils.dart';
|
|
import '../../widgets/custom_text_field.dart';
|
|
import '../../widgets/custom_user_form.dart';
|
|
|
|
class Policy extends StatefulWidget {
|
|
final Map<String, dynamic>? policy;
|
|
const Policy({super.key, required this.policy});
|
|
|
|
static Policy fromState(GoRouterState state) {
|
|
return Policy(policy: state.extra as Map<String, dynamic>?);
|
|
}
|
|
|
|
@override
|
|
_PolicyState createState() => _PolicyState();
|
|
}
|
|
|
|
class _PolicyState extends State<Policy> {
|
|
final GlobalKey<PolicyCriteriaState> policyCriteriaKey =
|
|
GlobalKey<PolicyCriteriaState>();
|
|
|
|
final ApiService apiService = ApiService();
|
|
|
|
// List<String> services = [];
|
|
List<Map<String, dynamic>> services = [];
|
|
String? servicesJson;
|
|
Color? layoutColor;
|
|
Color? bodyColor;
|
|
late String policyType = "domestic";
|
|
// String selectedServiceDBValue = '1';
|
|
List<int> serviceDBValueList = [];
|
|
ValueNotifier<String> selectedServiceIndex = ValueNotifier("1");
|
|
ValueNotifier<String> selectedServicePriorityIndex = ValueNotifier("1");
|
|
ValueNotifier<String> selectedServiceDBValue = ValueNotifier("0");
|
|
String? selectedService;
|
|
// ValueNotifier<String> selectedService = ValueNotifier("Train");
|
|
bool isViewMode = false;
|
|
bool isDisable = false;
|
|
bool isSubmitting = false;
|
|
|
|
Map<String, FocusNode> focusNodes = {};
|
|
Map<String, bool> focusStates = {};
|
|
Map<String, String> errorMessages = {};
|
|
|
|
String? selectedPolicyId;
|
|
String? _selectedTripType;
|
|
String? PolicyName;
|
|
String? SelectedDomestic = "0";
|
|
String? SelectedInternational = "0";
|
|
String? orgId;
|
|
String? userId;
|
|
|
|
bool showClass = true;
|
|
bool showCost = false; // bool showCost = true; // on 21st june
|
|
|
|
List<dynamic>? selectedAllServices;
|
|
List<Map<String, String>> selectedOrgServiceIds = [];
|
|
List<dynamic>? ServicesChoosed;
|
|
List<String> filledItineraryKeys = [];
|
|
|
|
TextEditingController _policyController = TextEditingController();
|
|
List<Map<String, dynamic>>? policy_details = [];
|
|
|
|
Map<String, dynamic> get policyData {
|
|
List<Map<String, dynamic>> policyDetails =
|
|
policy_details!.where((service) {
|
|
// Only check these specific fields for emptiness
|
|
final fieldsToCheck = [
|
|
'cost',
|
|
'class',
|
|
'a1_action',
|
|
'a2_action',
|
|
'a3_action',
|
|
];
|
|
|
|
// If any of the important fields has a value, keep it
|
|
return fieldsToCheck.any((field) {
|
|
final value = service[field];
|
|
return value != null && value.toString().trim().isNotEmpty;
|
|
});
|
|
}).toList();
|
|
|
|
|
|
Map<String, dynamic> data = {
|
|
"name": _policyController.text,
|
|
"domestic": SelectedDomestic,
|
|
"international": SelectedInternational,
|
|
"services_ids": services,
|
|
"is_active": "1",
|
|
"org_id": orgId,
|
|
"created_by": userId,
|
|
"policy_details": policyDetails,
|
|
};
|
|
|
|
return data;
|
|
}
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_checkAuthAndLoadData();
|
|
focusNodes["policyFocusNode"] = FocusNode();
|
|
focusStates["policyFocused"] = false;
|
|
for (var key in focusNodes.keys) {
|
|
_addFocusListener(focusNodes[key]!, (focus) {
|
|
setState(() {
|
|
focusStates[key.replaceFirst("FocusNode", "Focused")] = focus;
|
|
});
|
|
});
|
|
}
|
|
// for (var field in dataHeader) {
|
|
// focusNodes["${field}FocusNode"] = FocusNode();
|
|
// focusStates["${field}Focused"] = false;
|
|
// }
|
|
// WidgetsFlutterBinding.ensureInitialized();
|
|
|
|
// WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
// loadinitializeData();
|
|
//
|
|
// updateSelectedServices();
|
|
// updateData();
|
|
//
|
|
// loadInitialData();
|
|
//
|
|
// if (widget.policy != null) {
|
|
// final details = List<Map<String, dynamic>>.from(
|
|
// widget.policy!['policy_details'],
|
|
// );
|
|
// policyCriteriaKey.currentState?.loadPolicyDetails(details);
|
|
//
|
|
// policyCriteriaKey.currentState?.fetchTrainFlightClass();
|
|
// }
|
|
// });
|
|
}
|
|
void _addFocusListener(FocusNode node, Function(bool) updateState) {
|
|
node.addListener(() {
|
|
setState(() {
|
|
updateState(node.hasFocus);
|
|
});
|
|
});
|
|
}
|
|
void _checkAuthAndLoadData() async {
|
|
final String? token = await getToken(); // Your async function to get token
|
|
|
|
if (token == null || token.isEmpty) {
|
|
// Token doesn't exist → redirect to login
|
|
context.go(
|
|
"/",
|
|
); // or use: router.go("/") if you're using `GoRouter` directly
|
|
return;
|
|
}
|
|
if (!mounted) return;
|
|
try {
|
|
loadinitializeData();
|
|
|
|
await updateSelectedServices();
|
|
updateData();
|
|
|
|
loadInitialData();
|
|
|
|
|
|
|
|
|
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
if (widget.policy != null) {
|
|
final details = List<Map<String, dynamic>>.from(
|
|
widget.policy!['policy_details'],
|
|
);
|
|
policyCriteriaKey.currentState?.loadPolicyDetails(details);
|
|
}
|
|
});
|
|
|
|
|
|
// if (widget.policy != null) {
|
|
// print("185");
|
|
// final details = List<Map<String, dynamic>>.from(
|
|
// widget.policy!['policy_details'],
|
|
// );
|
|
// policyCriteriaKey.currentState?.loadPolicyDetails(details);
|
|
//
|
|
// policyCriteriaKey.currentState?.fetchTrainFlightClass();
|
|
// }
|
|
} catch (e) {
|
|
print("group : $e");
|
|
}
|
|
}
|
|
|
|
void loadInitialData() async {
|
|
String? layoutString = await getLayoutColor();
|
|
String? bodyStringColor = await getBodyColor();
|
|
|
|
setState(() {
|
|
layoutColor =
|
|
layoutString != null
|
|
? Color(int.parse(layoutString))
|
|
: Colors.redAccent;
|
|
|
|
bodyColor =
|
|
bodyStringColor != null
|
|
? Color(int.parse(bodyStringColor))
|
|
: Colors.white;
|
|
});
|
|
}
|
|
|
|
void loadinitializeData() async {
|
|
orgId = await getOrgId();
|
|
userId = await getUserId();
|
|
}
|
|
|
|
Future<void> loadAllServices() async {
|
|
try {
|
|
final result = await apiService.fetchAllServices();
|
|
setState(() {
|
|
selectedAllServices = result;
|
|
});
|
|
print("Fetched services: $selectedAllServices");
|
|
} catch (e) {
|
|
print('Error fetching role list: $e');
|
|
}
|
|
}
|
|
|
|
Future<void> loadOrgSelectedAlServices() async {
|
|
try {
|
|
final result = await apiService.fetchOrganization();
|
|
|
|
if (result != null && result is Map<String, dynamic>) {
|
|
final rawServices = result['services_ids'];
|
|
|
|
if (rawServices != null && rawServices is String) {
|
|
try {
|
|
List<dynamic> decoded = json.decode(rawServices);
|
|
List<Map<String, String>> formatted =
|
|
decoded
|
|
.map((e) => {"service_id": e['service_id'].toString()})
|
|
.toList();
|
|
|
|
setState(() {
|
|
selectedOrgServiceIds = formatted;
|
|
});
|
|
print("selectedOrgServiceIds: ${selectedOrgServiceIds}");
|
|
|
|
for (var service in selectedOrgServiceIds) {
|
|
print("service_id: ${service['service_id']}");
|
|
}
|
|
} catch (e) {
|
|
print("Failed to decode services_ids: $e");
|
|
}
|
|
}
|
|
}
|
|
} catch (e) {
|
|
print('Error fetching role list: $e');
|
|
}
|
|
}
|
|
|
|
Future<void> updateSelectedServices() async {
|
|
print("started");
|
|
await loadAllServices();
|
|
await loadOrgSelectedAlServices();
|
|
print("III-end");
|
|
final selectedIds =
|
|
selectedOrgServiceIds.map((e) => e['service_id']).toSet();
|
|
|
|
if (widget.policy != null) {
|
|
print("inside if");
|
|
print(widget.policy);
|
|
final details = List<Map<String, dynamic>>.from(
|
|
widget.policy!['policy_details'],
|
|
);
|
|
print("****details-$details");
|
|
|
|
print(
|
|
"UUFiltered Selected Services - ${widget.policy!['services_ids']} ",
|
|
);
|
|
|
|
final exisitingService = List<Map<String, dynamic>>.from(
|
|
jsonDecode(widget.policy!['services_ids']),
|
|
);
|
|
print("exisitingService ${exisitingService}");
|
|
|
|
final filtered =
|
|
exisitingService!
|
|
.where(
|
|
(service) =>
|
|
selectedIds.contains(service['service_id'].toString()),
|
|
)
|
|
.toList();
|
|
|
|
setState(() {
|
|
ServicesChoosed = filtered;
|
|
});
|
|
print("298 ServicesChoosed ${ServicesChoosed}");
|
|
|
|
|
|
|
|
if (ServicesChoosed!.isNotEmpty) {
|
|
print("Filtered Selected Services ChooesedIpfa1: $ServicesChoosed");
|
|
|
|
|
|
ServicesChoosed!.sort(
|
|
(a, b) => (a['order'] ?? 0).compareTo(b['order'] ?? 0),
|
|
);
|
|
String firstServiceName = ServicesChoosed?.first['name'];
|
|
String firstServiceId = ServicesChoosed?.first['service_id'];
|
|
|
|
print("✅ 306 First service name selected for filter: $firstServiceName - $firstServiceId");
|
|
selectedService = firstServiceName;
|
|
if (selectedServiceDBValue.value == "0") {
|
|
setState(() {
|
|
selectedServiceDBValue.value = firstServiceId.toString();
|
|
});
|
|
}
|
|
List<int> serviceDBvalue = ServicesChoosed!
|
|
.map((item) => int.parse(item['service_id'].toString()))
|
|
.toList();
|
|
serviceDBValueList = serviceDBvalue;
|
|
|
|
}
|
|
print(widget.policy);
|
|
// updateData();
|
|
if (widget.policy != null && widget.policy!['services_ids'] != null) {
|
|
final decoded = jsonDecode(widget.policy!['services_ids']);
|
|
|
|
setState(() {
|
|
services =
|
|
List<Map<String, dynamic>>.from(decoded)
|
|
.map(
|
|
(service) => {
|
|
'service_id': service['service_id'].toString(),
|
|
'name': service['name'].toString(),
|
|
'order': service['order'].toString(),
|
|
},
|
|
)
|
|
.toList();
|
|
});
|
|
|
|
print("✅ Loaded services from policy (decoded): $services");
|
|
|
|
|
|
}
|
|
|
|
print("Filtered Selected Services Added to Policy: $ServicesChoosed");
|
|
|
|
}
|
|
else {
|
|
final filtered =
|
|
selectedAllServices!
|
|
.where(
|
|
(service) =>
|
|
selectedIds.contains(service['service_id'].toString()),
|
|
)
|
|
.toList();
|
|
|
|
print("ServicesChoosedYY: $ServicesChoosed");
|
|
setState(() {
|
|
ServicesChoosed = filtered;
|
|
// services = ServicesChoosed!
|
|
// .map((service) => service['name'].toString())
|
|
// .toList();
|
|
|
|
// ServicesChoosed = filtered;
|
|
|
|
services =
|
|
ServicesChoosed!
|
|
.map(
|
|
(service) => {
|
|
'service_id': service['service_id'].toString(),
|
|
'name':
|
|
service['name'].toString(), // ✅ no space before 'name'
|
|
'order': service['order'].toString(),
|
|
},
|
|
)
|
|
.toList();
|
|
});
|
|
|
|
print("Filtered Selected Services Chooesed1: $ServicesChoosed");
|
|
|
|
if (ServicesChoosed!.isNotEmpty) {
|
|
policyCriteriaKey.currentState?.fetchTrainFlightClass();
|
|
ServicesChoosed!.sort(
|
|
(a, b) => (a['order'] ?? 0).compareTo(b['order'] ?? 0),
|
|
);
|
|
String firstServiceName = ServicesChoosed?.first['name'];
|
|
String firstServiceId = ServicesChoosed?.first['service_id'];
|
|
print("✅ 363 First service name selected for filter: $firstServiceName - $firstServiceId");
|
|
selectedService = firstServiceName;
|
|
if (selectedServiceDBValue.value == "0") {
|
|
setState(() {
|
|
selectedServiceDBValue.value = firstServiceId.toString();
|
|
});
|
|
}
|
|
|
|
List<int> serviceDBvalue = ServicesChoosed!
|
|
.map((item) => int.parse(item['service_id'].toString()))
|
|
.toList();
|
|
serviceDBValueList = serviceDBvalue;
|
|
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
void updateData() {
|
|
print("updateData");
|
|
// if (widget.policy != null && selectedService != null && selectedServiceDBValue.value != "0") {
|
|
if (widget.policy != null) {
|
|
setState(() {
|
|
selectedPolicyId = widget.policy?["policy_id"] ?? "";
|
|
_policyController.text = widget.policy?["name"] ?? "";
|
|
SelectedDomestic = widget.policy?["domestic"] ?? "";
|
|
SelectedInternational = widget.policy?["international"] ?? "";
|
|
|
|
if (SelectedDomestic == "1") {
|
|
_selectedTripType = "1";
|
|
} else if (SelectedInternational == "1") {
|
|
_selectedTripType = "2";
|
|
}
|
|
|
|
/// ✅ Load policy_details list safely
|
|
policy_details = List<Map<String, dynamic>>.from(
|
|
widget.policy?["policy_details"] ?? [],
|
|
);
|
|
// print("policy_details ${policy_details}");
|
|
});
|
|
}
|
|
}
|
|
|
|
// void handleSubmit() async {
|
|
// setState(() { isDisable = true; });
|
|
// print("Services - $services");
|
|
// print("USR Detail Submit - $policyData");
|
|
//
|
|
// policyCriteriaKey.currentState?.saveCurrentPolicy(services);
|
|
//
|
|
// // Now the full data is ready in policyDataFromChild
|
|
// print("Submitting full policyData: $policyData");
|
|
//
|
|
// Map<String, dynamic> data = policyData;
|
|
//
|
|
// if (!isValidData(data)) {
|
|
// print("USERDETAILS : $policyData");
|
|
// print("Validation Failed: Required fields are missing.");
|
|
// setState(() { isDisable = false; });
|
|
// return; // Stop execution if validation fails
|
|
// } else {
|
|
// // print("USERDETAILS : $policyData");
|
|
// // orgId = await getOrgId();
|
|
//
|
|
// if(isDisable == true){ createPolicyData(data); }
|
|
// setState(() { isDisable = false; });
|
|
// }
|
|
// }
|
|
|
|
void handleSubmit() async {
|
|
if (isSubmitting || isDisable) return;
|
|
isSubmitting = true;
|
|
setState(() {
|
|
isDisable = true;
|
|
});
|
|
|
|
policyCriteriaKey.currentState?.saveCurrentPolicy(services);
|
|
|
|
// Now the full data is ready in policyDataFromChild
|
|
print("Submitting full policyData: $policyData");
|
|
|
|
Map<String, dynamic> data = policyData;
|
|
|
|
if (!isValidData(data)) {
|
|
print("Validation Failed");
|
|
isSubmitting = false;
|
|
setState(() => isDisable = false);
|
|
return;
|
|
}
|
|
|
|
bool result = false;
|
|
|
|
try {
|
|
result = await createPolicyData(data);
|
|
} catch (e) {
|
|
print("Unexpected error during policy creation: $e");
|
|
}
|
|
|
|
if (result) {
|
|
// ✅ Only navigate on success
|
|
context.go('/PolicyList');
|
|
} else {
|
|
// ❌ Show error, allow retry
|
|
Fluttertoast.showToast(
|
|
msg: "Failed to submit policy. Please try again.",
|
|
toastLength: Toast.LENGTH_SHORT,
|
|
gravity: ToastGravity.CENTER,
|
|
timeInSecForIosWeb: 2,
|
|
backgroundColor: Colors.redAccent,
|
|
textColor: Colors.white,
|
|
fontSize: 18.0,
|
|
webBgColor: "linear-gradient(to right, #28a745, #28a745)",
|
|
);
|
|
}
|
|
|
|
isSubmitting = false;
|
|
setState(() {
|
|
isDisable = false; // Allow retry
|
|
});
|
|
}
|
|
|
|
|
|
bool isValidData(Map<String, dynamic> data) {
|
|
errorMessages.clear(); // Reset previous errors
|
|
|
|
// Validate required fields
|
|
if (data["name"] == null || data["name"].toString().trim().isEmpty) {
|
|
errorMessages["name"] = "Required"; // "Policy name is required.";
|
|
}
|
|
|
|
// Validate that either domestic or international is selected
|
|
final domestic = data["domestic"]?.toString() ?? "0";
|
|
final international = data["international"]?.toString() ?? "0";
|
|
|
|
print(
|
|
"domestic: ${data["domestic"]}, international: ${data["international"]}",
|
|
);
|
|
|
|
if (domestic != "1" && international != "1") {
|
|
errorMessages["trip_type"] =
|
|
"Required"; // "Please select Domestic or International.";
|
|
}
|
|
|
|
// Validate at least one policy_detail with valid content
|
|
final policyDetails = data["policy_details"] as List<Map<String, dynamic>>;
|
|
|
|
bool hasAtLeastOneDetail = policyDetails.any((service) {
|
|
final fieldsToCheck = [
|
|
'cost',
|
|
'class',
|
|
'a1_action',
|
|
'a2_action',
|
|
'a3_action',
|
|
];
|
|
return fieldsToCheck.any((field) {
|
|
final value = service[field];
|
|
return value != null && value.toString().trim().isNotEmpty;
|
|
});
|
|
});
|
|
|
|
if (!hasAtLeastOneDetail) {
|
|
errorMessages["policy_details"] =
|
|
"Required"; // "At least one valid policy detail is required.";
|
|
}
|
|
|
|
return errorMessages.isEmpty;
|
|
}
|
|
|
|
void _clearError(String field) {
|
|
if (mounted && errorMessages.containsKey(field)) {
|
|
setState(() {
|
|
errorMessages.remove(field);
|
|
});
|
|
}
|
|
}
|
|
|
|
Future<bool> createPolicyData(Map<String, dynamic> policyData) async {
|
|
final String apiUrldata = '$apiUrl/api/policy/createOrUpdate';
|
|
final token = await getToken(); // Fetch token
|
|
|
|
if (token == null) {
|
|
print('Token not found. Please log in.');
|
|
// throw Exception('Token not found. Please log in.');
|
|
return false;
|
|
}
|
|
|
|
final int? policyId;
|
|
|
|
if (selectedPolicyId != null && selectedPolicyId!.isNotEmpty) {
|
|
policyId = int.tryParse(selectedPolicyId!);
|
|
policyData['policy_id'] = policyId; // Add only if updating
|
|
}
|
|
|
|
try {
|
|
final response = await http.post(
|
|
Uri.parse(apiUrldata),
|
|
headers: {
|
|
'Authorization': 'Bearer $token',
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: jsonEncode(policyData), // Convert map to JSON
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
print("policyData submitted successfully!");
|
|
print("Response: ${response.body}");
|
|
return true;
|
|
} else {
|
|
print("Failed to submit policyData. Status: ${response.statusCode}");
|
|
print("Error: ${response.body}");
|
|
return false;
|
|
}
|
|
} catch (e) {
|
|
print(" Error submitting policyData: $e");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return ResponsiveBuilder(
|
|
builder: (context, sizingInfo) {
|
|
bool isDesktop =
|
|
sizingInfo.deviceScreenType == DeviceScreenType.desktop;
|
|
|
|
return Scaffold(
|
|
backgroundColor: Color(0xFFf5f5f5),
|
|
appBar: CustomAppBar(isDesktop: isDesktop),
|
|
drawer: CustomDrawer(isDesktop: false),
|
|
body: Padding(
|
|
padding:
|
|
isDesktop
|
|
? EdgeInsets.symmetric(
|
|
horizontal:
|
|
MediaQuery.of(context).size.width *
|
|
0.1, // 30% of screen width as horizontal padding
|
|
vertical:
|
|
MediaQuery.of(context).size.height *
|
|
0, // 5% of screen height as vertical padding
|
|
)
|
|
: EdgeInsets.all(8),
|
|
child: Column(
|
|
children: [
|
|
Expanded(
|
|
child: Row(
|
|
children: [
|
|
// if (isDesktop) CustomDrawer(isDesktop: true),
|
|
Expanded(child: buildData(isDesktop, context)),
|
|
// Expanded(
|
|
// child: Container(
|
|
// color: bodyColor,
|
|
// child: buildPolicyLayout(isDesktop),
|
|
// ),
|
|
// ),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
|
|
// Row(
|
|
// children: [
|
|
// if (isDesktop) CustomDrawer(isDesktop: true),
|
|
// Expanded(
|
|
// child: Column(
|
|
// children: [
|
|
// Expanded(
|
|
// child: Container(
|
|
// // height: MediaQuery.of(context).size.height * 0.8,
|
|
// color: bodyColor,
|
|
// child: buildPolicyLayout(isDesktop)),
|
|
// ),
|
|
// ],
|
|
// ),
|
|
// ),
|
|
// Container(
|
|
// color: Colors.white,
|
|
// child: Padding(
|
|
// padding: const EdgeInsets.all(8.0),
|
|
// child: isDesktop
|
|
// ? Row(
|
|
// mainAxisAlignment: MainAxisAlignment.end,
|
|
// children: _buildSubmit(isDesktop),
|
|
// )
|
|
// : Row(
|
|
// mainAxisAlignment: MainAxisAlignment.center,
|
|
// children: _buildSubmit(isDesktop),
|
|
// )),
|
|
// )
|
|
// ],
|
|
// ),
|
|
);
|
|
},
|
|
);
|
|
}
|
|
|
|
Widget buildData(bool isDesktop, context) {
|
|
return Container(
|
|
margin: isDesktop ? const EdgeInsets.only(top: 10.0, bottom: 10.0) : null,
|
|
padding: const EdgeInsets.all(8),
|
|
decoration: BoxDecoration(
|
|
color: isDesktop ? Colors.white : Color(0xFFFCFCFC),
|
|
),
|
|
// margin: const EdgeInsets.only(left: 10.0, right: 15.0, top: 10.0, bottom: 10.0),
|
|
// decoration: BoxDecoration(
|
|
// color: Color(0xFFE1F5FE),
|
|
// // color: bodyColor,
|
|
// border: Border.all(
|
|
// color: Colors.white,
|
|
// // color: Color(0xFFF7F7FB),
|
|
//
|
|
// width: 3.5)),
|
|
child: Column(
|
|
children: [
|
|
Expanded(
|
|
child: Container(
|
|
// color: bodyColor,
|
|
// color: Color(0xFFE1F5FE),
|
|
child: buildPolicyLayout(isDesktop),
|
|
),
|
|
),
|
|
Container(
|
|
color: Colors.white,
|
|
padding: const EdgeInsets.all(8.0),
|
|
child:
|
|
isDesktop
|
|
? Row(
|
|
mainAxisAlignment: MainAxisAlignment.end,
|
|
children: _buildSubmit(isDesktop),
|
|
)
|
|
: Row(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: _buildSubmit(isDesktop),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget buildPolicyLayout(bool isDesktop) {
|
|
return Container(
|
|
// margin: isDesktop
|
|
// ? EdgeInsets.all(10.0)
|
|
// : EdgeInsets.only(left: 20.0, bottom: 20.0, top: 10.0, right: 20.0),
|
|
height:
|
|
isDesktop
|
|
? MediaQuery.of(context).size.height * 0.98
|
|
: MediaQuery.of(context).size.height,
|
|
// decoration: BoxDecoration(
|
|
// border: isDesktop
|
|
// ? Border.all(
|
|
// width: 2,
|
|
// color: Colors.white,
|
|
// // color: Color(0xFFF7F7FB),
|
|
// )
|
|
// : null,
|
|
// color: Colors.white,
|
|
// // color: Color(0xFFF7F7FB),
|
|
//
|
|
// // color: Colors.amber,
|
|
// ),
|
|
child: Column(
|
|
mainAxisAlignment: MainAxisAlignment.start,
|
|
children: [
|
|
Container(
|
|
// color: Color(0xFFF7F7FB),
|
|
child: Column(
|
|
mainAxisAlignment: MainAxisAlignment.start,
|
|
children: [
|
|
Container(
|
|
padding: isDesktop ? EdgeInsets.all(6) : EdgeInsets.all(3),
|
|
// color: Colors.white, // Background to avoid overlapping
|
|
color: Colors.white,
|
|
// color: isDesktop ? Color(0xFFF7F7FB) : Colors.white,
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
crossAxisAlignment: CrossAxisAlignment.end,
|
|
// children: [
|
|
// Text(
|
|
// "Choose Policy Type",
|
|
// style: GoogleFonts.poppins(
|
|
// fontSize: 12,
|
|
// fontWeight: FontWeight.w600,
|
|
// color: Color(0xFF575A74),
|
|
// ),
|
|
// ),
|
|
// ],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
isDesktop ? SizedBox(height: 0) : SizedBox(height: 5),
|
|
Container(
|
|
padding: isDesktop ? const EdgeInsets.only(left: 35) : null,
|
|
child:
|
|
isDesktop
|
|
? Row(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Expanded(child: _buildPolicyNameField(isDesktop)),
|
|
Spacer(),
|
|
Expanded(child: _buildPolicyTypeField(isDesktop)),
|
|
],
|
|
)
|
|
: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
_buildPolicyNameField(isDesktop),
|
|
SizedBox(height: 20),
|
|
_buildPolicyTypeField(isDesktop),
|
|
],
|
|
),
|
|
),
|
|
SizedBox(height: 10),
|
|
Divider(thickness: 0.1, color: Colors.grey),
|
|
if (errorMessages["policy_details"] != null) ...[
|
|
SizedBox(height: 5), // Space before error message
|
|
Text(
|
|
errorMessages["policy_details"]!,
|
|
style: GoogleFonts.poppins(color: Colors.red, fontSize: 12),
|
|
),
|
|
],
|
|
isDesktop
|
|
? Padding(
|
|
padding: const EdgeInsets.only(left: 30.0, right: 98.0),
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Text(
|
|
"Approval Criteria",
|
|
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(),
|
|
|
|
isDesktop
|
|
? Container(
|
|
// color: Colors.yellow.shade50,
|
|
height: MediaQuery.of(context).size.height * 0.54,
|
|
child: SingleChildScrollView(
|
|
scrollDirection: Axis.vertical,
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.start,
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Column(
|
|
children: [
|
|
_buildPolicyOrdering(isDesktop),
|
|
_buildPolicyCategory(isDesktop),
|
|
],
|
|
),
|
|
Column(children: [_buildPolicyCategoryList(isDesktop)]),
|
|
],
|
|
),
|
|
),
|
|
)
|
|
: Expanded(
|
|
child: Container(
|
|
child: SingleChildScrollView(
|
|
scrollDirection: Axis.vertical,
|
|
child: Column(
|
|
children: [
|
|
_buildPolicyCategoryList(isDesktop),
|
|
_buildPolicyOrdering(isDesktop),
|
|
_buildPolicyCategory(isDesktop),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
// isDesktop
|
|
// ? Expanded(
|
|
// child: Row(
|
|
// children: [
|
|
// _buildPolicyCategory(isDesktop),
|
|
// _buildPolicyCategoryList(isDesktop),
|
|
// ],
|
|
// ),
|
|
// )
|
|
// : Expanded(
|
|
// child: Column(
|
|
// children: [
|
|
// _buildPolicyCategoryList(isDesktop),
|
|
// _buildPolicyCategory(isDesktop),
|
|
// ],
|
|
// ),
|
|
// ),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
// Widget _buildServiceSelect(bool isDesktop){
|
|
// return [];
|
|
// }
|
|
|
|
Widget _buildPolicyNameField(bool isDesktop) {
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
"Policy Name *",
|
|
style: GoogleFonts.poppins(
|
|
fontSize: 12,
|
|
fontWeight: FontWeight.w600,
|
|
color: Color(0xFF575A74),
|
|
),
|
|
),
|
|
SizedBox(height: 5),
|
|
CustomTextFieldUserWrapper(
|
|
isFocused: focusStates["policyFocused"] ?? false,
|
|
isDesktop: isDesktop,
|
|
child: SizedBox(
|
|
height: 40,
|
|
child: TextField(
|
|
style: GoogleFonts.poppins(fontSize: 12),
|
|
focusNode: focusNodes["policyFocusNode"],
|
|
controller: _policyController,
|
|
onChanged: (value) => _clearError("name"),
|
|
decoration: InputDecoration(
|
|
labelText: "Policy Name",
|
|
labelStyle: GoogleFonts.poppins(
|
|
fontSize: 12,
|
|
color: Colors.grey,
|
|
),
|
|
floatingLabelBehavior: FloatingLabelBehavior.never,
|
|
border: InputBorder.none,
|
|
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
if (errorMessages["name"] != null) ...[
|
|
SizedBox(height: 5),
|
|
Text(
|
|
errorMessages["name"]!,
|
|
style: GoogleFonts.poppins(color: Colors.red, fontSize: 12),
|
|
),
|
|
],
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget _buildPolicyTypeField(bool isDesktop) {
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
"Policy Type *",
|
|
style: GoogleFonts.poppins(
|
|
fontSize: 12,
|
|
fontWeight: FontWeight.w600,
|
|
color: Color(0xFF575A74),
|
|
),
|
|
),
|
|
SizedBox(height: 5),
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.start,
|
|
children: _buildTripType(isDesktop),
|
|
),
|
|
if (errorMessages["trip_type"] != null) ...[
|
|
SizedBox(height: 5),
|
|
Text(
|
|
errorMessages["trip_type"]!,
|
|
style: GoogleFonts.poppins(color: Colors.red, fontSize: 12),
|
|
),
|
|
],
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget _buildPolicyCategoryList(bool isDesktop) {
|
|
return Container(
|
|
margin: const EdgeInsets.only(top: 8.0),
|
|
// color: Colors.white,
|
|
height: isDesktop ? 350 : null,
|
|
// height: isDesktop ? MediaQuery.of(context).size.height * 0.55 : null,
|
|
// color: Colors.blueGrey.shade200,
|
|
width: isDesktop ? MediaQuery.of(context).size.width * 0.15 : null,
|
|
decoration: BoxDecoration(
|
|
border: Border.all(color: Colors.blueGrey.shade100, width: 0.35),
|
|
),
|
|
child:
|
|
isDesktop
|
|
? Padding(
|
|
padding: const EdgeInsets.all(10.0),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.center,
|
|
mainAxisAlignment: MainAxisAlignment.start,
|
|
children: [_buildPolicySubCategoryList(isDesktop)],
|
|
),
|
|
)
|
|
: Column(
|
|
children: [
|
|
Container(
|
|
// color: Colors.amber,
|
|
child: _buildPolicySubCategoryList(isDesktop),
|
|
// child: Text("FAta"),
|
|
// child: Row(
|
|
// mainAxisAlignment: MainAxisAlignment.start,
|
|
// children: [_buildPolicySubCategoryList(isDesktop)],
|
|
// ),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildPolicySubCategoryList(bool isDesktop) {
|
|
if (services.isEmpty) {
|
|
return const Center(child: CircularProgressIndicator());
|
|
}
|
|
|
|
if (isDesktop) {
|
|
// 🖥 Desktop (vertical ReorderableListView)
|
|
return Expanded(
|
|
child: ReorderableListView(
|
|
onReorder: (oldIndex, newIndex) {
|
|
setState(() {
|
|
if (newIndex > oldIndex) newIndex -= 1;
|
|
final item = services.removeAt(oldIndex);
|
|
services.insert(newIndex, item);
|
|
});
|
|
},
|
|
children: List.generate(services.length, (i) {
|
|
return SizedBox(
|
|
key: ValueKey(services[i]['service_id']),
|
|
width: 185,
|
|
height: 35,
|
|
// height: MediaQuery.of(context).size.height * 0.025,
|
|
child: _buildServiceTile(services[i], i.toString()),
|
|
);
|
|
}),
|
|
),
|
|
);
|
|
} else {
|
|
// 📱 Mobile (horizontal ReorderableWrap)
|
|
return Container(
|
|
// color: Colors.red,
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text("Service Ordering"),
|
|
SingleChildScrollView(
|
|
scrollDirection: Axis.horizontal,
|
|
child: ReorderableWrap(
|
|
spacing: 8,
|
|
runSpacing: 8,
|
|
direction: Axis.horizontal,
|
|
needsLongPressDraggable: true,
|
|
onReorder: (oldIndex, newIndex) {
|
|
setState(() {
|
|
final item = services.removeAt(oldIndex);
|
|
services.insert(newIndex, item);
|
|
});
|
|
},
|
|
children: List.generate(services.length, (i) {
|
|
return SizedBox(
|
|
key: ValueKey(services[i]),
|
|
height: isDesktop ? 10 : 45,
|
|
// child: _buildServiceTile(services[i]['service_id'], i.toString()),
|
|
child: _buildServiceTile(services[i], i.toString()),
|
|
);
|
|
}),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
Widget _buildServiceTile(Map<String, dynamic> service, String index) {
|
|
// bool isSelected = selectedServiceIndex.value == index;
|
|
bool isSelected = selectedServicePriorityIndex.value == index;
|
|
String name = service['name']; // or 'service_id', as needed
|
|
|
|
return GestureDetector(
|
|
onTap: () {
|
|
setState(() {
|
|
// selectedServiceIndex.value = index;
|
|
selectedServicePriorityIndex.value = index;
|
|
});
|
|
},
|
|
child: Container(
|
|
margin: const EdgeInsets.all(5),
|
|
decoration: BoxDecoration(
|
|
// color: Colors.yellow.shade50,
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.circular(8),
|
|
border: Border.all(color: Colors.white),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.grey.withOpacity(0.3),
|
|
blurRadius: 2,
|
|
offset: const Offset(0, 1),
|
|
),
|
|
],
|
|
),
|
|
alignment: Alignment.center,
|
|
child: Text(
|
|
name,
|
|
style: GoogleFonts.poppins(color: Colors.black, fontSize: 12),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildServiceTile1(Map<String, dynamic> service, String index) {
|
|
// bool isSelected = selectedServiceIndex.value == index;
|
|
// bool isSelected = selectedServiceIndex.value == index;
|
|
// String name = service['service_id']
|
|
bool isSelected = selectedServiceIndex.value == index;
|
|
String name = service['name'];
|
|
|
|
return GestureDetector(
|
|
onTap: () {
|
|
setState(() {
|
|
selectedServiceIndex.value = index;
|
|
});
|
|
},
|
|
child: Container(
|
|
height: 5,
|
|
// padding: const EdgeInsets.symmetric(horizontal: 1, vertical: 2),
|
|
margin: const EdgeInsets.all(1),
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
// color: isSelected ? const Color(0xFF114D8B) : Colors.white,
|
|
borderRadius: BorderRadius.circular(8),
|
|
border: Border.all(color: Colors.white),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.grey.withOpacity(0.3),
|
|
blurRadius: 2,
|
|
offset: const Offset(0, 1),
|
|
),
|
|
],
|
|
),
|
|
alignment: Alignment.center,
|
|
child: Text(
|
|
name,
|
|
style: GoogleFonts.poppins(
|
|
color: Colors.black,
|
|
// color: isSelected ? Colors.white : Colors.black87,
|
|
fontSize: 12,
|
|
// fontWeight: FontWeight.w100,
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildPolicyOrdering(bool isDesktop) {
|
|
return Container(
|
|
// height: 50,
|
|
// color: Colors.white,
|
|
// color: Colors.yellow.shade200,
|
|
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.75 : null,
|
|
child:
|
|
isDesktop
|
|
? Container(
|
|
// color: Colors.amber,
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [_buildPolicyServiceOrdering(isDesktop)],
|
|
),
|
|
)
|
|
: Container(
|
|
// color: Colors.amber,
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.start,
|
|
children: [_buildPolicyServiceOrdering(isDesktop)],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildPolicyServiceOrdering(bool isDesktop) {
|
|
if (ServicesChoosed == null) {
|
|
return const Center(child: CircularProgressIndicator());
|
|
}
|
|
|
|
// Sort services by 'order'
|
|
ServicesChoosed!.sort(
|
|
(a, b) => (a['order'] ?? 0).compareTo(b['order'] ?? 0),
|
|
);
|
|
|
|
List<String> services =
|
|
ServicesChoosed!.map((service) => service['name'].toString()).toList();
|
|
|
|
// List<int> serviceDBvalue =
|
|
// ServicesChoosed!.map((service) => int.parse(service['service_id'].toString())).toList();
|
|
List<int> serviceDBvalue = ServicesChoosed!
|
|
.map((item) => int.parse(item['service_id'].toString()))
|
|
.toList();
|
|
|
|
|
|
print("1093");
|
|
print(services);
|
|
print(serviceDBvalue);
|
|
|
|
return Container(
|
|
child: SingleChildScrollView(
|
|
scrollDirection: Axis.horizontal,
|
|
child: Flex(
|
|
direction: Axis.horizontal,
|
|
children:
|
|
services.asMap().entries.map((entry) {
|
|
print("1182 ${entry}");
|
|
int i = entry.key;
|
|
int index = i + 1;
|
|
String service = entry.value;
|
|
int serviceId = serviceDBvalue[i];
|
|
|
|
bool isSelected =
|
|
selectedServiceIndex.value == index.toString();
|
|
|
|
return SizedBox(
|
|
// width: isDesktop ? 40 : null,
|
|
height:
|
|
isDesktop
|
|
? max(
|
|
(MediaQuery.of(context).size.height * 0.075),
|
|
10,
|
|
)
|
|
: 45,
|
|
|
|
// max((MediaQuery.of(context).size.height * 0.09), 10)
|
|
child: GestureDetector(
|
|
onTap: () {
|
|
print("1201 Selected Services - $service - Tab Index - $index Service Id- $serviceId");
|
|
setState(() {
|
|
selectedServiceIndex.value = index.toString();
|
|
selectedServiceDBValue.value = serviceId.toString();
|
|
selectedService = service;
|
|
|
|
print(
|
|
" selectedServiceIndex.value - ${selectedServiceIndex.value}",
|
|
);
|
|
|
|
|
|
// policyCriteriaKey.currentState?.fieldForPolicy();
|
|
// policyCriteriaKey.currentState
|
|
// ?.addOrUpdatePolicy(selectedServiceIndex.value);
|
|
print("policyselectedService - $selectedService");
|
|
if (selectedService == "Flight" ||
|
|
selectedService == "Train" || selectedService == "Accomodation") {
|
|
showClass = true;
|
|
showCost = false;
|
|
// int serviceCode = selectedService == "Flight" ? 1 : 2;
|
|
print("policyselectedService1 - $selectedService");
|
|
policyCriteriaKey.currentState
|
|
?.fetchTrainFlightClass();
|
|
}
|
|
// else if (selectedService == "Accommodation") {
|
|
// showClass = true;
|
|
// showCost = false;
|
|
// }
|
|
else {
|
|
showClass = false;
|
|
showCost = false;
|
|
}
|
|
});
|
|
},
|
|
child: Container(
|
|
margin: const EdgeInsets.all(5),
|
|
padding:
|
|
isDesktop
|
|
? const EdgeInsets.all(8)
|
|
: const EdgeInsets.symmetric(
|
|
horizontal: 8,
|
|
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),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}).toList(),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildPolicySubCategoryList1(bool isDesktop) {
|
|
// List<String> services = [
|
|
// "Flight",
|
|
// "Train",
|
|
// "Bus",
|
|
// "Taxi",
|
|
// "Forex",
|
|
// "Accommodation",
|
|
// "Insurance",
|
|
// "Visa",
|
|
// "Miscellaneous"
|
|
// ];
|
|
|
|
if (ServicesChoosed == null) {
|
|
return const Center(child: CircularProgressIndicator());
|
|
}
|
|
|
|
List<String> services =
|
|
ServicesChoosed!.map((service) => service['name'].toString()).toList();
|
|
|
|
return Expanded(
|
|
child: SingleChildScrollView(
|
|
scrollDirection: isDesktop ? Axis.vertical : Axis.horizontal,
|
|
child: Flex(
|
|
direction: isDesktop ? Axis.vertical : Axis.horizontal,
|
|
children:
|
|
services.asMap().entries.map((entry) {
|
|
int index = entry.key + 1;
|
|
String service = entry.value;
|
|
bool isSelected =
|
|
selectedServiceIndex.value == index.toString();
|
|
|
|
return SizedBox(
|
|
width: isDesktop ? 180 : null,
|
|
height:
|
|
isDesktop
|
|
? max(
|
|
(MediaQuery.of(context).size.height * 0.075),
|
|
10,
|
|
)
|
|
: 45,
|
|
|
|
// max((MediaQuery.of(context).size.height * 0.09), 10)
|
|
child: GestureDetector(
|
|
onTap: () {
|
|
print("Selected Services - $service - $index");
|
|
setState(() {
|
|
// selectedServiceIndex.value = index.toString();
|
|
// selectedService = service;
|
|
//
|
|
// if (selectedService == "Flight" ||
|
|
// selectedService == "Train") {
|
|
// showClass = true;
|
|
// showCost = true;
|
|
// int serviceCode = selectedService == "Flight" ? 1 : 2;
|
|
// policyCriteriaKey.currentState?.fetchTrainFlightClass();
|
|
// } else if (selectedService == "Accommodation") {
|
|
// showClass = true;
|
|
// showCost = false;
|
|
// } else {
|
|
// showClass = false;
|
|
// showCost = false;
|
|
// }
|
|
});
|
|
},
|
|
child: Container(
|
|
margin: EdgeInsets.all(5),
|
|
padding:
|
|
isDesktop
|
|
? EdgeInsets.all(8)
|
|
: EdgeInsets.only(
|
|
top: 3,
|
|
bottom: 3,
|
|
left: 8,
|
|
right: 8,
|
|
),
|
|
decoration: BoxDecoration(
|
|
// color: Colors.blue,
|
|
color: isSelected ? Color(0xFF114D8B) : Colors.white,
|
|
// : Color(0xFFEBEBF7),
|
|
borderRadius: BorderRadius.circular(8),
|
|
border: Border.all(
|
|
color: Colors.white, // Light grey border
|
|
width: 1,
|
|
),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.grey.withAlpha(90), // Shadow color
|
|
blurRadius: 1, // Blur radius
|
|
spreadRadius: 1, // Spread radius
|
|
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,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}).toList(),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildPolicyCategory(bool isDesktop) {
|
|
print("1408 $selectedServiceIndex");
|
|
print("1409 $selectedService");
|
|
print("1410 ${selectedServiceDBValue.value}");
|
|
return Container(
|
|
margin: isDesktop ? EdgeInsets.all(5) : null,
|
|
// color: Colors.brown.shade100,
|
|
// child: Text("data"),
|
|
// color: Colors.white60,
|
|
child: (selectedService != null && selectedServiceDBValue.value != "0")
|
|
? PolicyCriteria(
|
|
key: policyCriteriaKey,
|
|
isDesktop: isDesktop,
|
|
isClass: showClass,
|
|
isCost: showCost,
|
|
selectedTabNotifier: selectedServiceIndex,
|
|
selectedIdNotifier: selectedServiceDBValue,
|
|
selectedService: selectedService!,
|
|
serviceDBValueList: serviceDBValueList, // 👈 Pass the array here
|
|
userId: userId,
|
|
onPolicyDataChanged: (List<Map<String, dynamic>>? policyData) {
|
|
print("🟢 policyData received from child: $policyData");
|
|
|
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
setState(() {
|
|
policy_details = policyData;
|
|
_clearError("policy_details");
|
|
});
|
|
});
|
|
},
|
|
) : const Center(child: CircularProgressIndicator()),
|
|
);
|
|
}
|
|
|
|
List<Widget> _buildTripType(bool isDesktop) {
|
|
return [
|
|
CustomTextFieldWrapper(
|
|
color: Color(0xFFF4F4FB),
|
|
layoutColor: layoutColor,
|
|
borderRadius: BorderRadius.circular(25),
|
|
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
|
|
width: 130,
|
|
isFocused: _selectedTripType == "1",
|
|
isDesktop: isDesktop,
|
|
child: Row(
|
|
mainAxisSize: MainAxisSize.min,
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Text(
|
|
"Domestic",
|
|
style: GoogleFonts.poppins(
|
|
color: _selectedTripType == "1" ? Colors.black : Colors.black,
|
|
fontWeight: _selectedTripType == "1" ? FontWeight.w600 : null,
|
|
fontSize: 13,
|
|
),
|
|
),
|
|
GestureDetector(
|
|
onTap: () {
|
|
setState(() {
|
|
_clearError("trip_type");
|
|
_selectedTripType = "1";
|
|
PolicyName = "Domestic Policy";
|
|
SelectedDomestic = "1";
|
|
SelectedInternational = "0";
|
|
});
|
|
},
|
|
child: Container(
|
|
width: 15,
|
|
height: 15,
|
|
decoration: BoxDecoration(
|
|
shape: BoxShape.rectangle,
|
|
// color: _selectedOption == option["value"]
|
|
// ? Colors.blueAccent
|
|
// : Colors.transparent,
|
|
borderRadius: BorderRadius.circular(4), // Rounded rectangle
|
|
border: Border.all(
|
|
color:
|
|
_selectedTripType == "1" ? Colors.green : Colors.black,
|
|
width: _selectedTripType == "1" ? 2 : 1,
|
|
),
|
|
),
|
|
child:
|
|
_selectedTripType == "1"
|
|
? Icon(Icons.rectangle, size: 8, color: Colors.green)
|
|
: null, // Add checkmark if selected
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
SizedBox(width: 20),
|
|
CustomTextFieldWrapper(
|
|
color: Color(0xFFF4F4FB),
|
|
layoutColor: layoutColor,
|
|
borderRadius: BorderRadius.circular(25),
|
|
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
|
|
width: 150,
|
|
// padding: EdgeInsets.symmetric(horizontal: 5, vertical: 2),
|
|
isFocused: _selectedTripType == "2",
|
|
isDesktop: isDesktop,
|
|
child: Row(
|
|
mainAxisSize: MainAxisSize.min,
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Text(
|
|
"International",
|
|
style: GoogleFonts.poppins(
|
|
fontSize: 13,
|
|
color: _selectedTripType == "2" ? Colors.black : Colors.black,
|
|
fontWeight: _selectedTripType == "2" ? FontWeight.w600 : null,
|
|
),
|
|
),
|
|
GestureDetector(
|
|
onTap: () {
|
|
setState(() {
|
|
_clearError("trip_type");
|
|
_selectedTripType = "2";
|
|
PolicyName = "International Policy";
|
|
SelectedDomestic = "0";
|
|
SelectedInternational = "1";
|
|
});
|
|
},
|
|
child: Container(
|
|
width: 15,
|
|
height: 15,
|
|
decoration: BoxDecoration(
|
|
shape: BoxShape.rectangle,
|
|
// color: _selectedOption == option["value"]
|
|
// ? Colors.blueAccent
|
|
// : Colors.transparent,
|
|
borderRadius: BorderRadius.circular(4), // Rounded rectangle
|
|
border: Border.all(
|
|
color:
|
|
_selectedTripType == "2" ? Colors.green : Colors.black,
|
|
width: _selectedTripType == "2" ? 2 : 1,
|
|
),
|
|
),
|
|
child:
|
|
_selectedTripType == "2"
|
|
? Icon(Icons.rectangle, size: 8, color: Colors.green)
|
|
: null, // Add checkmark if selected
|
|
),
|
|
),
|
|
],
|
|
),
|
|
|
|
// RadioListTile<String>(
|
|
// activeColor: Colors.blueAccent,
|
|
// contentPadding: EdgeInsets.zero,
|
|
// dense: true,
|
|
// title: Text("International"),
|
|
// value: "2",
|
|
// groupValue: _selectedTripType,
|
|
// onChanged: widget.isViewMode
|
|
// ? null
|
|
// : (value) {
|
|
// setState(() {
|
|
// _selectedTripType = value!;
|
|
// });
|
|
// },
|
|
// ),
|
|
),
|
|
];
|
|
}
|
|
|
|
List<Widget> _buildSubmit(isDesktop) {
|
|
return [
|
|
ElevatedButton(
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: Colors.white,
|
|
foregroundColor: layoutColor,
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(8),
|
|
side: BorderSide(color: layoutColor ?? Colors.grey, width: 2),
|
|
),
|
|
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
|
),
|
|
onPressed: () {
|
|
context.go('/PolicyList');
|
|
},
|
|
child: Text("Cancel", style: GoogleFonts.poppins(fontSize: 10)),
|
|
),
|
|
SizedBox(width: 20),
|
|
MouseRegion(
|
|
cursor:
|
|
isViewMode
|
|
? SystemMouseCursors.forbidden
|
|
: SystemMouseCursors.click,
|
|
child: ElevatedButton(
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor:
|
|
isViewMode ? layoutColor : layoutColor, // Keep original color
|
|
foregroundColor:
|
|
isViewMode ? Colors.white : Colors.white, // Keep original color
|
|
disabledBackgroundColor:
|
|
layoutColor, // Ensure color remains when disabled
|
|
disabledForegroundColor: Colors.white,
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(8),
|
|
side: BorderSide(color: layoutColor ?? Colors.grey, width: 2),
|
|
),
|
|
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
|
),
|
|
onPressed:
|
|
// isViewMode ? null : handleSubmit, // Disable when in view mode
|
|
isViewMode || isDisable ? null : handleSubmit,
|
|
child: Text("Submit", style: GoogleFonts.poppins(fontSize: 10)),
|
|
),
|
|
),
|
|
];
|
|
}
|
|
|
|
List<Widget> _buildTripType1(bool isDesktop) {
|
|
return [
|
|
CustomTextFieldWrapper(
|
|
color: Color(0xFFF4F4FB),
|
|
padding: EdgeInsets.symmetric(horizontal: 6, vertical: 2),
|
|
width: isDesktop ? 170 : 140,
|
|
isFocused: _selectedTripType == "1",
|
|
isDesktop: isDesktop,
|
|
child: SizedBox(
|
|
height: 35,
|
|
child: Material(
|
|
color: Colors.transparent,
|
|
child: RadioListTile<String>(
|
|
activeColor: Colors.blueAccent,
|
|
contentPadding: EdgeInsets.zero,
|
|
visualDensity: VisualDensity.compact,
|
|
dense: true,
|
|
title: Text("Domestic", style: GoogleFonts.poppins(fontSize: 12)),
|
|
value: "1",
|
|
groupValue: _selectedTripType,
|
|
onChanged: (value) {
|
|
setState(() {
|
|
_selectedTripType = value!;
|
|
PolicyName = "Domestic Policy";
|
|
SelectedDomestic = "1";
|
|
SelectedInternational = "0";
|
|
});
|
|
},
|
|
),
|
|
),
|
|
),
|
|
),
|
|
isDesktop ? SizedBox(width: 28) : SizedBox(width: 15),
|
|
CustomTextFieldWrapper(
|
|
color: Color(0xFFF4F4FB),
|
|
padding: EdgeInsets.symmetric(horizontal: 6, vertical: 2),
|
|
width: isDesktop ? 180 : 180,
|
|
isFocused: _selectedTripType == "2",
|
|
isDesktop: isDesktop,
|
|
child: SizedBox(
|
|
height: 35,
|
|
child: Material(
|
|
color: Colors.transparent,
|
|
child: RadioListTile<String>(
|
|
activeColor: Colors.blueAccent,
|
|
contentPadding: EdgeInsets.zero,
|
|
visualDensity: VisualDensity.compact,
|
|
dense: true,
|
|
title: Text("International"),
|
|
value: "2",
|
|
groupValue: _selectedTripType,
|
|
onChanged: (value) {
|
|
setState(() {
|
|
_selectedTripType = value!;
|
|
PolicyName = "International Policy";
|
|
SelectedDomestic = "0";
|
|
SelectedInternational = "1";
|
|
});
|
|
},
|
|
),
|
|
),
|
|
),
|
|
),
|
|
];
|
|
}
|
|
} |