1050 lines
34 KiB
Dart
1050 lines
34 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 'dart:html' as html;
|
|
import 'dart:ui' as web;
|
|
|
|
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();
|
|
|
|
Color? layoutColor;
|
|
Color? bodyColor;
|
|
late String policyType = "domestic";
|
|
// int? selectedServiceIndex = 1;
|
|
ValueNotifier<String> selectedServiceIndex = ValueNotifier("1");
|
|
String selectedService = "train";
|
|
// ValueNotifier<String> selectedService = ValueNotifier("Train");
|
|
bool isViewMode = false;
|
|
|
|
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 = true;
|
|
|
|
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,
|
|
"is_active": "1",
|
|
"org_id": orgId,
|
|
"created_by": userId,
|
|
"policy_details": policyDetails,
|
|
};
|
|
|
|
return data;
|
|
}
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
// 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 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 {
|
|
await loadAllServices();
|
|
await loadOrgSelectedAlServices();
|
|
|
|
final selectedIds =
|
|
selectedOrgServiceIds.map((e) => e['service_id']).toSet();
|
|
|
|
if (widget.policy != null) {
|
|
final details =
|
|
List<Map<String, dynamic>>.from(widget.policy!['policy_details']);
|
|
|
|
print("Filtered Selected Services - $details");
|
|
|
|
final filtered = selectedAllServices!
|
|
.where((service) =>
|
|
selectedIds.contains(service['service_id'].toString()))
|
|
.toList();
|
|
|
|
setState(() {
|
|
ServicesChoosed = filtered;
|
|
});
|
|
|
|
print("Filtered Selected Services Chooesed1: $ServicesChoosed");
|
|
|
|
if (ServicesChoosed!.isNotEmpty) {
|
|
String firstServiceName = ServicesChoosed?.first['name'];
|
|
print("✅ First service name selected for filter: $firstServiceName");
|
|
selectedService = firstServiceName;
|
|
}
|
|
print("Filtered Selected Services Added to Policy: $ServicesChoosed");
|
|
} else {
|
|
final filtered = selectedAllServices!
|
|
.where((service) =>
|
|
selectedIds.contains(service['service_id'].toString()))
|
|
.toList();
|
|
|
|
setState(() {
|
|
ServicesChoosed = filtered;
|
|
});
|
|
|
|
print("Filtered Selected Services Chooesed1: $ServicesChoosed");
|
|
|
|
if (ServicesChoosed!.isNotEmpty) {
|
|
String firstServiceName = ServicesChoosed?.first['name'];
|
|
print("✅ First service name selected for filter: $firstServiceName");
|
|
selectedService = firstServiceName;
|
|
policyCriteriaKey.currentState?.fetchTrainFlightClass();
|
|
}
|
|
}
|
|
}
|
|
|
|
void updateData() {
|
|
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 = "1";
|
|
}
|
|
|
|
/// ✅ Load policy_details list safely
|
|
policy_details = List<Map<String, dynamic>>.from(
|
|
widget.policy?["policy_details"] ?? [],
|
|
);
|
|
});
|
|
}
|
|
}
|
|
|
|
void handleSubmit() async {
|
|
print("USR Detail Submit - $policyData");
|
|
|
|
policyCriteriaKey.currentState?.saveCurrentPolicy();
|
|
|
|
// 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(() {});
|
|
return; // Stop execution if validation fails
|
|
} else {
|
|
// print("USERDETAILS : $policyData");
|
|
// orgId = await getOrgId();
|
|
|
|
createPolicyData(data);
|
|
}
|
|
}
|
|
|
|
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"] = "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"] = "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"] =
|
|
"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<void> createPolicyData(Map<String, dynamic> policyData) async {
|
|
final String apiUrldata = '$apiUrl/api/policy/createOrUpdate';
|
|
final token = await getToken(); // Fetch token
|
|
|
|
if (token == null) {
|
|
throw Exception('Token not found. Please log in.');
|
|
}
|
|
|
|
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}");
|
|
|
|
context.go('/PolicyList');
|
|
} else {
|
|
print("Failed to submit policyData. Status: ${response.statusCode}");
|
|
print("Error: ${response.body}");
|
|
}
|
|
} catch (e) {
|
|
print(" Error submitting policyData: $e");
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return ResponsiveBuilder(builder: (context, sizingInfo) {
|
|
bool isDesktop = sizingInfo.deviceScreenType == DeviceScreenType.desktop;
|
|
|
|
return Scaffold(
|
|
backgroundColor: Colors.white,
|
|
appBar: const CustomAppBar(),
|
|
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: 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: TextStyle(
|
|
fontSize: 18,
|
|
color: Colors.black,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
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.2,
|
|
color: Colors.grey,
|
|
),
|
|
if (errorMessages["policy_details"] != null) ...[
|
|
SizedBox(height: 5), // Space before error message
|
|
Text(
|
|
errorMessages["policy_details"]!,
|
|
style: TextStyle(color: Colors.red, fontSize: 12),
|
|
),
|
|
],
|
|
isDesktop
|
|
? Expanded(
|
|
child: Row(
|
|
children: [
|
|
_buildPolicyCategoryList(isDesktop),
|
|
_buildPolicyCategory(isDesktop),
|
|
],
|
|
),
|
|
)
|
|
: Expanded(
|
|
child: Column(
|
|
children: [
|
|
_buildPolicyCategoryList(isDesktop),
|
|
_buildPolicyCategory(isDesktop),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildPolicyNameField(bool isDesktop) {
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text("Policy Name",
|
|
style: TextStyle(
|
|
fontSize: 12,
|
|
fontWeight: FontWeight.w200,
|
|
color: Colors.black)),
|
|
SizedBox(height: 5),
|
|
CustomTextFieldUserWrapper(
|
|
isFocused: false,
|
|
isDesktop: isDesktop,
|
|
child: SizedBox(
|
|
height: 40,
|
|
child: TextField(
|
|
style: TextStyle(fontSize: 12),
|
|
controller: _policyController,
|
|
onChanged: (value) => _clearError("name"),
|
|
decoration: InputDecoration(
|
|
labelText: "Policy Name",
|
|
labelStyle: TextStyle(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: TextStyle(color: Colors.red, fontSize: 12)),
|
|
],
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget _buildPolicyTypeField(bool isDesktop) {
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text("Policy Type",
|
|
style: TextStyle(
|
|
fontSize: 12,
|
|
fontWeight: FontWeight.w200,
|
|
color: Colors.black)),
|
|
SizedBox(height: 5),
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.start,
|
|
children: _buildTripType(isDesktop),
|
|
),
|
|
if (errorMessages["trip_type"] != null) ...[
|
|
SizedBox(height: 5),
|
|
Text(errorMessages["trip_type"]!,
|
|
style: TextStyle(color: Colors.red, fontSize: 12)),
|
|
],
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget _buildPolicyCategoryList(bool isDesktop) {
|
|
return Container(
|
|
color: Colors.white,
|
|
// color: Colors.blueGrey.shade200,
|
|
width: isDesktop ? MediaQuery.of(context).size.width * 0.15 : null,
|
|
child: isDesktop
|
|
? Column(
|
|
mainAxisAlignment: MainAxisAlignment.start,
|
|
children: [_buildPolicySubCategoryList(isDesktop)],
|
|
)
|
|
: Container(
|
|
// color: Colors.amber,
|
|
child: Expanded(
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.start,
|
|
children: [_buildPolicySubCategoryList(isDesktop)],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildPolicySubCategoryList(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: TextStyle(
|
|
color: isSelected ? Colors.white : Colors.black87,
|
|
fontSize: 13,
|
|
fontWeight:
|
|
isSelected ? FontWeight.bold : FontWeight.w100),
|
|
),
|
|
),
|
|
));
|
|
}).toList(),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildPolicyCategory(bool isDesktop) {
|
|
return Expanded(
|
|
child: Container(
|
|
margin: EdgeInsets.all(10),
|
|
// color: Colors.brown.shade100,
|
|
// color: Colors.white60,
|
|
child: PolicyCriteria(
|
|
key: policyCriteriaKey,
|
|
isDesktop: isDesktop,
|
|
isClass: showClass,
|
|
isCost: showCost,
|
|
selectedTabNotifier: selectedServiceIndex,
|
|
selectedService: selectedService,
|
|
userId: userId,
|
|
onPolicyDataChanged: (List<Map<String, dynamic>>? policyData) {
|
|
print("🟢 policyData received from child: $policyData");
|
|
|
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
setState(() {
|
|
policy_details = policyData;
|
|
_clearError("policy_details");
|
|
});
|
|
});
|
|
},
|
|
)),
|
|
);
|
|
}
|
|
|
|
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: TextStyle(
|
|
color: _selectedTripType == "1" ? Colors.white : 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.white : Colors.black,
|
|
width: _selectedTripType == "1" ? 2 : 1,
|
|
),
|
|
),
|
|
child: _selectedTripType == "1"
|
|
? Icon(Icons.rectangle, size: 8, color: Colors.white)
|
|
: 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: TextStyle(
|
|
fontSize: 13,
|
|
color: _selectedTripType == "2" ? Colors.white : 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.white : Colors.black,
|
|
width: _selectedTripType == "2" ? 2 : 1,
|
|
),
|
|
),
|
|
child: _selectedTripType == "2"
|
|
? Icon(Icons.rectangle, size: 8, color: Colors.white)
|
|
: 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")),
|
|
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
|
|
child: Text("Submit"),
|
|
),
|
|
)
|
|
];
|
|
}
|
|
|
|
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"),
|
|
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";
|
|
});
|
|
},
|
|
),
|
|
),
|
|
),
|
|
),
|
|
];
|
|
}
|
|
}
|