nhance_partner/lib/presentation/screens/Enquiry/enquiry/policy_tab.dart
2026-04-03 15:04:34 +05:30

871 lines
31 KiB
Dart

import 'package:dropdown_search/dropdown_search.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:nhance_partner/presentation/screens/Enquiry/enquiry/policy_popup.dart';
import '../../../../core/services/api_service.dart';
import '../../../../data/services/auth_service.dart';
import '../../../../data/utils/Pagination.dart';
import '../../../../data/utils/validators.dart';
import '../../../layouts/main_layout.dart';
import '../../../layouts/responsive_layout.dart';
import '../../../providers/manager_provider.dart';
import '../../../themes/indicators/export_btn.dart';
import '../../../themes/indicators/search_field_theme.dart';
import '../../../themes/indicators/text_field_theme.dart';
import '../../../widgets/custom_action_popup.dart';
import '../policy_claims_endros/sub_claims.dart';
import '../policy_claims_endros/sub_endrosment.dart';
class PolicyTab extends ConsumerStatefulWidget {
final List<Map<String, dynamic>>? data;
dynamic id;
// const PolicyTab({super.key});
PolicyTab({super.key, this.data, this.id});
@override
ConsumerState<PolicyTab> createState() => PolicyTabState();
}
class PolicyTabState extends ConsumerState<PolicyTab> {
final GlobalKey<ClaimsSubListState> claimsKey =
GlobalKey<ClaimsSubListState>();
final GlobalKey<EndrosmentSubListState> enrollKey =
GlobalKey<EndrosmentSubListState>();
List<Map<String, dynamic>> dataVal = [];
final TextEditingController _searchController = TextEditingController();
List<Map<String, dynamic>> getQuotationData = [];
List<Map<String, dynamic>> originalData = [];
List<Map<String, dynamic>> filteredData = [];
late ApiService apiService;
final _formKey = GlobalKey<FormState>();
bool isLoading = false;
List<String> tabHeader = [
'regNum',
'insurer',
'idv',
'insurerName',
'policyNo',
'paymentMode',
'premAmount',
'planType',
];
Map<String, TextEditingController> controllers = {};
String? _token;
dynamic userId;
dynamic managerId;
dynamic selectedPolicyNumber;
@override
void initState() {
super.initState();
apiService = ApiService();
print("PolicyTab - Called");
for (String field in tabHeader) {
controllers[field] = TextEditingController();
}
// updateData();
_initializeToken();
Future.microtask(() {
managerId = ref.watch(managerIdProvider);
userId = ref.watch(userIdProvider);
getPolicyList(managerId);
});
}
@override
void dispose() {
// Dispose all TextEditingControllers
for (var controller in controllers.values) {
controller.dispose();
}
super.dispose();
}
Future<void> _initializeToken() async {
_token = await AuthService.getToken();
print("APISERTOKEN - $_token");
}
Future<void> getPolicyList(int managerId) async {
print('getPolicyList called MagId - $managerId');
setState(() {
isLoading = true;
});
try {
// final response = await apiService.fetchQuotationList(managerId);
if (widget.data != null) {
// final data = List<Map<String, dynamic>>.from(widget.data as Iterable);
List<Map<String, dynamic>> data;
if (widget.data is List) {
data = List<Map<String, dynamic>>.from(widget.data as List);
} else if (widget.data is Map) {
data = [Map<String, dynamic>.from(widget.data as Map)];
} else {
data = [];
}
print('policyListData - ${widget.data}');
setState(() {
getQuotationData = data;
// getQuotationData = List<Map<String, dynamic>>.from(response['data']);
originalData = getQuotationData;
filteredData = List.from(originalData);
// print('originalData - $getClaimPolicies');
updateData(filteredData);
});
} else {
getQuotationData = [];
originalData = [];
filteredData = [];
}
} catch (e) {
print('Exception occurred: $e');
} finally {
setState(() {
isLoading = false;
});
}
}
void updateData(data) {
if (data != null && data is List && data.isNotEmpty) {
final record = data[0]; // get the first map
print('UPDID - $record');
setState(() {
selectedPolicyNumber = record['policy_number']?.toString() ?? '';
controllers['regNum']?.text = record['reg_no']?.toString() ?? '';
controllers['insurer']?.text = record['insurer_name']?.toString() ?? '';
controllers['idv']?.text =
record['insured_declared_value']?.toString() ?? '';
controllers['insurerName']?.text =
record['insured_name']?.toString() ?? '';
controllers['policyNo']?.text =
record['policy_number']?.toString() ?? '';
controllers['paymentMode']?.text =
record['payment_mode_value']?.toString() ?? '';
controllers['premAmount']?.text =
record['premium_amount']?.toString() ?? '';
controllers['planType']?.text =
record['insurance_plan_type']?.toString() ?? '';
});
}
}
@override
Widget build(BuildContext context) {
final isMobile = ResponsiveLayout.isMobile(context);
return isLoading
? CircularProgressIndicator()
: SelectionArea(
child: Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: filteredData.isNotEmpty
? SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Column(
children: [
Container(
// color: Colors.green,
decoration: BoxDecoration(
color: Color(0xffEDF6F5),
borderRadius: BorderRadius.circular(10.0),
),
width: MediaQuery.of(context).size.width,
// height: MediaQuery.of(context).size.height * 0.8,
padding: isMobile
? EdgeInsets.all(10.0)
: EdgeInsets.all(16.0),
child: Column(
children: [
if (!ResponsiveLayout.isMobile(context)) ...[
Container(
child: Row(
children: [
Text(
'Policy Details',
style: GoogleFonts.inter(
fontWeight: FontWeight.bold,
fontSize: 16,
),
),
if (!ResponsiveLayout.isMobile(
context,
)) ...[
Spacer(),
buildDocPolicy(context, isMobile),
SizedBox(width: 15),
buildDocReciept(context, isMobile),
],
// GestureDetector(
// onTap: () {
// print("Upload ${widget.id}");
// final selectedId = widget.id;
// // final path =
// // 'agent/downloadAgentIncentiveFile?id=$selectedId';
// final path =
// 'policy/downloadPolicyFile?policy_id=$selectedId&file_type=policy_payment_receipt';
// apiService.getPdfDownload(path, selectedId);
// },
// child: Container(
// padding: const EdgeInsets.all(8),
// decoration: BoxDecoration(
// borderRadius: BorderRadius.circular(5),
// color: const Color(0xFF425B5B),
// ),
// child: Row(
// children: const [
// Text(
// "Download Receipt",
// style: TextStyle(
// fontSize: 12,
// fontWeight: FontWeight.w200,
// color: Colors.white,
// ),
// ),
// SizedBox(width: 15),
// Icon(
// Icons.file_download_outlined,
// size: 16,
// color: Colors.white,
// ),
// ],
// ),
// ),
// ),
],
),
),
const SizedBox(height: 20),
],
SingleChildScrollView(
child: buildFormFields(context),
),
isMobile
? SizedBox(height: 5)
: SizedBox(height: 20),
],
),
),
isMobile ? SizedBox(height: 5) : SizedBox(height: 20),
Container(
// color: Colors.green,
decoration: BoxDecoration(
color: Color(0xffEDF6F5),
borderRadius: BorderRadius.circular(10.0),
),
width: MediaQuery.of(context).size.width,
// height: MediaQuery.of(context).size.height * 0.8,
padding: EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'More Information (optional)',
style: GoogleFonts.inter(
fontWeight: FontWeight.bold,
fontSize: 16,
),
),
if (!ResponsiveLayout.isMobile(context)) ...[
SizedBox(height: 10),
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
width: 100,
child: Text('Claim', style: _headerStyle),
),
SizedBox(width: 20),
Expanded(
child: buildMoreInfoSetClaims(context),
),
],
),
],
if (ResponsiveLayout.isMobile(context))
Container(
padding: EdgeInsets.all(6.0),
decoration: BoxDecoration(
color: Color(0xFFF6FEFD),
// color: Color(0xFFCBE6E2),
borderRadius: BorderRadius.circular(10.0),
),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
SizedBox(
width: 100,
child: Text(
'Claim',
style: _headerStyle,
),
),
_actionClaims(context),
],
),
SizedBox(width: 20),
buildMoreInfoSetClaims(context),
],
),
),
SizedBox(height: 10),
if (!ResponsiveLayout.isMobile(context))
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
width: 100,
child: Text(
'Endorsement',
style: _headerStyle,
),
),
SizedBox(width: 20),
Expanded(
child: buildMoreInfoSetEndrosment(
context,
),
),
],
),
if (ResponsiveLayout.isMobile(context))
Container(
padding: EdgeInsets.all(6.0),
decoration: BoxDecoration(
color: Color(0xFFF6FEFD),
// color: Color(0xFFCBE6E2),
borderRadius: BorderRadius.circular(10.0),
),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
SizedBox(
width: 100,
child: Text(
'Endorsement',
style: _headerStyle,
),
),
_actionEnroll(context),
],
),
SizedBox(width: 20),
buildMoreInfoSetEndrosment(context),
],
),
),
// SizedBox(height: 10),
// Row(
// mainAxisAlignment: MainAxisAlignment.end,
// children: [
// GestureDetector(
// onTap: () {
// // handleSave();
// },
// child: Container(
// padding: EdgeInsets.symmetric(
// horizontal: 45.0,
// vertical: 8,
// ),
//
// decoration: BoxDecoration(
// borderRadius: BorderRadius.circular(
// 8.0,
// ),
// color: Color(0xFF425B5B),
// ),
// child: Text(
// 'Save',
// style: TextStyle(color: Colors.white),
// ),
// ),
// ),
// ],
// ),
// SizedBox(height: 30),
// _buildDataTable(context),
],
),
),
],
),
)
: Center(child: Text('No Available Data')),
) );
}
Widget buildDocPolicy(BuildContext context, bool isMobile) {
return GestureDetector(
onTap: () {
print("Upload ${widget.id}");
final selectedId = widget.id;
// final path =
// 'agent/downloadAgentIncentiveFile?id=$selectedId';
final path =
'policy/downloadPolicyFile?policy_id=$selectedId&file_type=policy_pdf';
apiService.getPdfDownload(path, selectedId);
},
child: Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
color: const Color(0xFF425B5B),
),
child: Row(
children: [
const Text(
"Download Policy",
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w200,
color: Colors.white,
),
),
isMobile ? const Spacer() : const SizedBox(width: 15),
const Icon(
Icons.file_download_outlined,
size: 16,
color: Colors.white,
),
],
),
),
);
}
Widget buildDocReciept(BuildContext context, bool isMobile) {
return GestureDetector(
onTap: () {
print("Upload ${widget.id}");
final selectedId = widget.id;
// final path =
// 'agent/downloadAgentIncentiveFile?id=$selectedId';
final path =
'policy/downloadPolicyFile?policy_id=$selectedId&file_type=policy_payment_receipt';
apiService.getPdfDownload(path, selectedId);
},
child: Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
color: const Color(0xFF425B5B),
),
child: Row(
children: [
Text(
"Download Receipt",
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w200,
color: Colors.white,
),
),
isMobile ? const Spacer() : const SizedBox(width: 15),
Icon(Icons.file_download_outlined, size: 16, color: Colors.white),
],
),
),
);
}
Widget buildMoreInfoSetClaims(BuildContext context) {
if (selectedPolicyNumber == null || selectedPolicyNumber!.isEmpty) {
// return const Center(child: CircularProgressIndicator()); // or placeholder
return const Center(
child: Text( 'No records available', textAlign: TextAlign.center,),
);
}
return Container(
padding: ResponsiveLayout.isMobile(context) ? null : EdgeInsets.all(6.0),
decoration: ResponsiveLayout.isMobile(context)
? null
: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10.0),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: ClaimsSubList(
key: claimsKey,
policyNumber: selectedPolicyNumber,
),
),
if (!ResponsiveLayout.isMobile(context)) _actionClaims(context),
],
),
);
}
Widget buildMoreInfoSetEndrosment(BuildContext context) {
if (selectedPolicyNumber == null || selectedPolicyNumber!.isEmpty) {
// return const Center(child: CircularProgressIndicator()); // or placeholder
return const Center(
child: Text( 'No records available', textAlign: TextAlign.center,),
);
}
return Container(
// padding: EdgeInsets.all(8.0),
// decoration: BoxDecoration(
// color: Colors.white,
// borderRadius: BorderRadius.circular(6.0),
// ),
padding: ResponsiveLayout.isMobile(context) ? null : EdgeInsets.all(6.0),
decoration: ResponsiveLayout.isMobile(context)
? null
: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10.0),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: EndrosmentSubList(
key: enrollKey,
policyNumber: selectedPolicyNumber,
),
),
if (!ResponsiveLayout.isMobile(context)) _actionEnroll(context),
],
),
);
}
Widget _actionEnroll(BuildContext context) {
return Tooltip(
message: 'Add Endorsement',
child: IconButton(
onPressed: () {
showDialog(
context: context,
builder: (ctx) => AddDialog(
userId: userId,
role: null,
managerId: null,
title: "Endorsement",
// policyNumber: selectedPolicyNumber,
onSubmit: (value) {
debugPrint("New Endorsement: $value");
enrollKey.currentState?.getEndrosmentList(selectedPolicyNumber);
// Update claim list or call API
},
),
);
},
icon: Icon(Icons.add),
),
);
}
Widget _actionClaims(BuildContext context) {
return Tooltip(
message: 'Add Claim',
child: IconButton(
onPressed: () {
showDialog(
context: context,
builder: (ctx) => AddDialog(
userId: userId,
title: "Claims",
role: null,
managerId: null,
// policyNumber: selectedPolicyNumber,
onSubmit: (value) {
debugPrint("New Claim: $value");
claimsKey.currentState?.getClaimsList(selectedPolicyNumber);
// Update claim list or call API
},
),
);
},
icon: Icon(Icons.add),
),
);
}
Widget buildFormFields(BuildContext context) {
final isMobile = ResponsiveLayout.isMobile(context);
return Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildResponsiveRow(
context,
buildName(context),
buildInsusrer(context),
),
isMobile ? SizedBox(height: 5) : SizedBox(height: 10),
_buildResponsiveRow(
context,
buildIdv(context),
buildInsurdName(context),
),
isMobile ? SizedBox(height: 5) : SizedBox(height: 10),
_buildResponsiveRow(
context,
buildPolicyNum(context),
buildPaymentMode(context),
),
isMobile ? SizedBox(height: 5) : SizedBox(height: 10),
_buildResponsiveRow(
context,
buildPlanType(context),
buildPremiumAmount(context),
),
isMobile ? SizedBox(height: 5) : SizedBox(height: 10),
if (ResponsiveLayout.isMobile(context))
_buildResponsiveRow(
context,
buildDocPolicy(context, isMobile),
buildDocReciept(context, isMobile),
),
],
),
);
}
Widget _buildResponsiveRow(
BuildContext context,
Widget first,
Widget second,
) {
if (ResponsiveLayout.isMobile(context)) {
// Stack vertically
return Column(children: [first, const SizedBox(height: 4), second]);
} else {
// Place side by side
return Row(
children: [
Expanded(child: first),
const SizedBox(width: 25),
Expanded(child: second),
],
);
}
}
Widget buildResponsiveField({required String label, required Widget field}) {
final isMobile = ResponsiveLayout.isMobile(context);
if (isMobile) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(label, style: _textStyle),
const SizedBox(height: 8),
field,
const SizedBox(height: 16),
],
);
} else {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(child: Text(label, style: _textStyle)),
const SizedBox(width: 10),
field,
],
);
}
}
Widget buildName(BuildContext context) {
return buildResponsiveField(
label: "Vehicle Number",
field: ThemedFormField(
controller: controllers['regNum']!,
readOnly: true,
// validator: (value) => Validators.requiredField(value, "name"),
txtwidth: ResponsiveLayout.isMobile(context)
? null
: MediaQuery.of(context).size.width * 0.26,
),
);
}
Widget buildInsusrer(BuildContext context) {
return buildResponsiveField(
label: "Insurer",
field: ThemedFormField(
controller: controllers['insurer']!,
readOnly: true,
txtwidth: ResponsiveLayout.isMobile(context)
? null
: MediaQuery.of(context).size.width * 0.26,
),
);
}
Widget buildIdv(BuildContext context) {
return buildResponsiveField(
label: "IDV",
field: ThemedFormField(
controller: controllers['idv']!,
readOnly: true,
// validator: (value) => Validators.phone(value, "phNumber"),
txtwidth: ResponsiveLayout.isMobile(context)
? null
: MediaQuery.of(context).size.width * 0.26,
),
);
}
Widget buildInsurdName(BuildContext context) {
return buildResponsiveField(
label: "Insured Name",
field: ThemedFormField(
controller: controllers['insurerName']!,
readOnly: true,
// validator: (value) => Validators.phone(value, "phNumber"),
txtwidth: ResponsiveLayout.isMobile(context)
? null
: MediaQuery.of(context).size.width * 0.26,
),
);
}
Widget buildPolicyNum(BuildContext context) {
return buildResponsiveField(
label: "Policy Number",
field: ThemedFormField(
controller: controllers['policyNo']!,
readOnly: true,
// validator: (value) => Validators.phone(value, "phNumber"),
txtwidth: ResponsiveLayout.isMobile(context)
? null
: MediaQuery.of(context).size.width * 0.26,
),
);
}
Widget buildPaymentMode(BuildContext context) {
return buildResponsiveField(
label: "Payment Mode",
field: ThemedFormField(
readOnly: true,
controller: controllers['paymentMode']!,
txtwidth: ResponsiveLayout.isMobile(context)
? null
: MediaQuery.of(context).size.width * 0.26,
),
);
}
Widget buildPlanType(BuildContext context) {
return buildResponsiveField(
label: "Plan Type",
field: ThemedFormField(
controller: controllers['planType']!,
readOnly: true,
// validator: (value) => Validators.phone(value, "phNumber"),
txtwidth: ResponsiveLayout.isMobile(context)
? null
: MediaQuery.of(context).size.width * 0.26,
),
);
}
Widget buildPremiumAmount(BuildContext context) {
return buildResponsiveField(
label: "Premium Amount",
field: ThemedFormField(
controller: controllers['premAmount']!,
readOnly: true,
// validator: (value) => Validators.phone(value, "phNumber"),
txtwidth: ResponsiveLayout.isMobile(context)
? null
: MediaQuery.of(context).size.width * 0.26,
),
);
}
static const _headerStyle = TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
);
static const _textStyle = TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
);
static final _dataBold = TextStyle(
fontSize: 14,
fontWeight: FontWeight.w400,
color: Color(0xFF000000),
);
static final _dataSub = TextStyle(
fontSize: 10,
fontWeight: FontWeight.w300,
color: Color(0xFF585757),
);
static const _cardheaderStyle = TextStyle(
color: Colors.black,
fontWeight: FontWeight.w600,
fontSize: 12,
);
static const _cardBodyStyle = TextStyle(
color: Color(0xFF545454),
fontWeight: FontWeight.w400,
fontSize: 12,
);
}