UI_ENQ_AGENT
This commit is contained in:
parent
720a27985a
commit
9c83ab630d
@ -91,13 +91,15 @@ class ApiService {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> getPdfDownload(path, id) async {
|
||||
Future<void> getPdfDownload1(path, id) async {
|
||||
// final url = Uri.parse(
|
||||
// 'https://venbait.in/nhance/partner/dev/api/agent/downloadAgentCertificateFile?agent_id=1',
|
||||
// );
|
||||
final url = Uri.parse('https://venbait.in/nhance/partner/dev/$path');
|
||||
|
||||
// final token = await getToken();
|
||||
print('GetDownload');
|
||||
final url = Uri.parse('https://venbait.in/nhance/partner/dev/$path');
|
||||
print('GetDownload - $url');
|
||||
await _initializeToken();
|
||||
|
||||
if (_token == null) {
|
||||
throw Exception('Token not found. Please log in.');
|
||||
@ -130,28 +132,84 @@ class ApiService {
|
||||
throw Exception('Error parsing response: $e');
|
||||
}
|
||||
} else if (response.statusCode == 404) {
|
||||
// showDialog(
|
||||
// context: context,
|
||||
// builder: (BuildContext context) {
|
||||
// return AlertDialog(
|
||||
// title: Text('File not found.'),
|
||||
// // content: Text('File not found.'),
|
||||
// actions: [
|
||||
// TextButton(
|
||||
// child: Text('OK'),
|
||||
// onPressed: () {
|
||||
// Navigator.of(context).pop(); // Close the dialog
|
||||
// },
|
||||
// ),
|
||||
// ],
|
||||
// );
|
||||
// },
|
||||
// );
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: Text('File not found.'),
|
||||
// content: Text('File not found.'),
|
||||
actions: [
|
||||
TextButton(
|
||||
child: Text('OK'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(); // Close the dialog
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
} else {
|
||||
throw Exception('Failed to load plans');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> getPdfDownload(String path, String id) async {
|
||||
print('getPdfDownload 1');
|
||||
final url = Uri.parse('https://venbait.in/nhance/partner/dev/$path');
|
||||
await _initializeToken();
|
||||
print('getPdfDownload 2');
|
||||
if (_token == null) throw Exception('Token not found. Please log in.');
|
||||
|
||||
final headers = {
|
||||
'Authorization': 'Bearer $_token',
|
||||
'App-Signature': 'nhance-partner-2025-signature-35468846JRhH551HK',
|
||||
};
|
||||
|
||||
final response = await _makeGethttpRequest(url, headers);
|
||||
print('getPdfDownload 3');
|
||||
if (response.statusCode == 200) {
|
||||
final blob = html.Blob([response.bodyBytes]);
|
||||
final blobUrl = html.Url.createObjectUrlFromBlob(blob);
|
||||
print('getPdfDownload $blobUrl');
|
||||
// --- filename resolution ---
|
||||
String fileName = 'download_$id';
|
||||
print('getPdfDownloadfileName $fileName');
|
||||
final contentDisp = response.headers['content-disposition'];
|
||||
print('getPdfDownloadcontentDisp $contentDisp');
|
||||
if (contentDisp != null && contentDisp.contains('filename=')) {
|
||||
print('getPdfDownloadcontentDisp..1');
|
||||
fileName = contentDisp.split('filename=')[1].replaceAll('"', '');
|
||||
print('getPdfDownloadcontentDisp..2');
|
||||
} else {
|
||||
print('getPdfDownloadcontentDisp..3');
|
||||
// fallback: URL or id
|
||||
fileName = path.split('/').last;
|
||||
if (id != null) fileName = '${id}_$fileName';
|
||||
}
|
||||
final anchor = html.AnchorElement(href: blobUrl)
|
||||
..setAttribute('download', fileName)
|
||||
..click();
|
||||
print('getPdfDownloadcontentDisp..4');
|
||||
html.Url.revokeObjectUrl(blobUrl);
|
||||
} else if (response.statusCode == 404) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: const Text('File not found.'),
|
||||
actions: [
|
||||
TextButton(
|
||||
child: const Text('OK'),
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
} else {
|
||||
throw Exception('Failed to download file');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> downloadFile({
|
||||
required String? apiUrl,
|
||||
required PlatformFile? localFile,
|
||||
@ -176,7 +234,8 @@ class ApiService {
|
||||
}
|
||||
} else if (apiUrl != null) {
|
||||
print("Download from API: $apiUrl");
|
||||
await getPdfDownload(apiUrl, apiId);
|
||||
print("Download from API: $apiId!");
|
||||
await getPdfDownload(apiUrl, apiId!);
|
||||
} else {
|
||||
print("⚠️ No file available to download");
|
||||
}
|
||||
@ -516,6 +575,21 @@ class ApiService {
|
||||
return response;
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> findSingleClaimData(id) async {
|
||||
// print(_token);
|
||||
if (_token == null) {
|
||||
await _initializeToken();
|
||||
}
|
||||
final url = Uri.parse('${Env.apiUrl}claim/ClaimList?policy_number=$id');
|
||||
|
||||
final headers = {
|
||||
'Authorization': 'Bearer $_token' ?? '',
|
||||
'App-Signature': 'nhance-partner-2025-signature-35468846JRhH551HK',
|
||||
};
|
||||
final response = await _makeGetRequest(url, headers);
|
||||
return response;
|
||||
}
|
||||
|
||||
// ----------------------------------- ENDORSEMENT -------------------------------------------------
|
||||
|
||||
Future<Map<String, dynamic>> fetchEndorsementList(int id, role) async {
|
||||
@ -549,6 +623,23 @@ class ApiService {
|
||||
return response;
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> findSingleEnrosmentData(id) async {
|
||||
// print(_token);
|
||||
if (_token == null) {
|
||||
await _initializeToken();
|
||||
}
|
||||
final url = Uri.parse(
|
||||
'${Env.apiUrl}endorsement/endorsementList?policy_number=$id',
|
||||
);
|
||||
|
||||
final headers = {
|
||||
'Authorization': 'Bearer $_token' ?? '',
|
||||
'App-Signature': 'nhance-partner-2025-signature-35468846JRhH551HK',
|
||||
};
|
||||
final response = await _makeGetRequest(url, headers);
|
||||
return response;
|
||||
}
|
||||
|
||||
// --------------------------------- MASTER DATA ----------------------------------------------
|
||||
|
||||
Future<Map<String, dynamic>> fetchMasterDropDown(String val) async {
|
||||
|
||||
@ -3,7 +3,8 @@ import 'package:flutter/cupertino.dart';
|
||||
class Validators {
|
||||
static String? requiredField(String? value, String label) {
|
||||
if (value == null || value.trim().isEmpty) {
|
||||
return "$label is required";
|
||||
return "Required";
|
||||
// return "$label is required";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:http/http.dart' as ref;
|
||||
import 'package:nhance_partner/core/routing/routes.dart';
|
||||
import 'package:nhance_partner/data/services/auth_service.dart';
|
||||
import '../providers/manager_provider.dart';
|
||||
import '../screens/UserManagement/Profile/profile_web.dart';
|
||||
import '../widgets/custom_action_popup.dart';
|
||||
import '../widgets/topbar.dart';
|
||||
@ -26,7 +28,7 @@ class MainLayout extends StatelessWidget {
|
||||
title: title,
|
||||
isMobile: true,
|
||||
onBack: () {
|
||||
Navigator.pop(context);
|
||||
// Navigator.pop(context);
|
||||
},
|
||||
onNotifications: () {
|
||||
debugPrint("Notifications tapped");
|
||||
@ -42,7 +44,8 @@ class MainLayout extends StatelessWidget {
|
||||
} else if (index == 1) {
|
||||
context.go(AppRoutes.profile);
|
||||
} else if (index == 2) {
|
||||
context.go(AppRoutes.tabEnquiry);
|
||||
// ref.read(enquiryIdProvider.notifier).state = null;
|
||||
context.go(AppRoutes.enquiryLst);
|
||||
}
|
||||
},
|
||||
),
|
||||
|
||||
@ -65,6 +65,8 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
String? selectedIdProof;
|
||||
String? selectedPrevPolicy;
|
||||
|
||||
String? selectedRCFileName;
|
||||
|
||||
String? rcFileUrlFromApi;
|
||||
String? idProofFileUrlFromApi;
|
||||
String? prevPolicyFileUrlFromApi;
|
||||
@ -73,7 +75,7 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
bool isLoading = false;
|
||||
|
||||
String? selectedVehicleType;
|
||||
int? selectedVehicleTypeId;
|
||||
// int? selectedVehicleTypeId;
|
||||
String? selectedInsurer;
|
||||
|
||||
Map<String, TextEditingController> controllers = {};
|
||||
@ -222,13 +224,17 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
selectedVehicleType = data['vehicle_type_id'] ?? '';
|
||||
selectedInsurer = data['insurer_id'] ?? '';
|
||||
|
||||
String? apiDocPath = data["certificate_file_name"];
|
||||
|
||||
// RC FILE
|
||||
String? rcPath = data["rc_file_name"];
|
||||
if (rcPath != null && rcPath.isNotEmpty) {
|
||||
selectedRCFile = rcPath.split('/').last; // UI filename
|
||||
selectedRCFileName = rcPath.split('/').last;
|
||||
rcFileUrlFromApi = rcPath; // API download URL
|
||||
docUploadedRCFile =
|
||||
rcFileUrlFromApi as PlatformFile?; // user has not re-uploaded yet
|
||||
docUploadedRCFile = null;
|
||||
// docUploadedRCFile =
|
||||
// rcFileUrlFromApi as PlatformFile?; // user has not re-uploaded yet
|
||||
} else {
|
||||
selectedRCFile = null; // no UI file shown
|
||||
rcFileUrlFromApi = null;
|
||||
@ -240,7 +246,8 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
if (idProofPath != null && idProofPath.isNotEmpty) {
|
||||
selectedIdProof = idProofPath.split('/').last;
|
||||
idProofFileUrlFromApi = idProofPath; // ✅ FIXED → correct variable
|
||||
docUploadedIDProof = idProofFileUrlFromApi as PlatformFile?;
|
||||
docUploadedIDProof = null;
|
||||
// docUploadedIDProof = idProofFileUrlFromApi as PlatformFile?;
|
||||
} else {
|
||||
selectedIdProof = null;
|
||||
idProofFileUrlFromApi = null;
|
||||
@ -253,7 +260,8 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
selectedPrevPolicy = prevPolicyPath.split('/').last;
|
||||
prevPolicyFileUrlFromApi =
|
||||
prevPolicyPath; // ✅ FIXED → correct variable
|
||||
docUploadedPrevPolicy = prevPolicyFileUrlFromApi as PlatformFile?;
|
||||
docUploadedPrevPolicy = null;
|
||||
// docUploadedPrevPolicy = prevPolicyFileUrlFromApi as PlatformFile?;
|
||||
} else {
|
||||
selectedPrevPolicy = null;
|
||||
prevPolicyFileUrlFromApi = null;
|
||||
@ -271,6 +279,22 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
final dataSet = dataDetails();
|
||||
print("dataSetAgent - $dataSet");
|
||||
print("managerId - $managerId ,userId - $userId ");
|
||||
|
||||
if ((docUploadedRCFile == null ||
|
||||
(docUploadedRCFile?.bytes == null &&
|
||||
docUploadedRCFile?.path == null)) &&
|
||||
(rcFileUrlFromApi == null || rcFileUrlFromApi!.isEmpty)) {
|
||||
ToastHelper.showErrorToast(context, "Please upload RC Document");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((docUploadedIDProof == null ||
|
||||
(docUploadedIDProof?.bytes == null &&
|
||||
docUploadedIDProof?.path == null)) &&
|
||||
(idProofFileUrlFromApi == null || idProofFileUrlFromApi!.isEmpty)) {
|
||||
ToastHelper.showErrorToast(context, "Please upload ID Proof");
|
||||
return;
|
||||
}
|
||||
createUserData(dataSet);
|
||||
} else {
|
||||
// isDisable = false;
|
||||
@ -331,36 +355,6 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> attachFiles1(http.MultipartRequest request) async {
|
||||
Future<void> addFile(PlatformFile? file, String fieldName) async {
|
||||
if (file == null) return;
|
||||
try {
|
||||
if (file.bytes != null) {
|
||||
final multipartFile = http.MultipartFile.fromBytes(
|
||||
fieldName,
|
||||
file.bytes!,
|
||||
filename: file.name,
|
||||
);
|
||||
request.files.add(multipartFile);
|
||||
} else if (file.path != null) {
|
||||
final multipartFile = await http.MultipartFile.fromPath(
|
||||
fieldName,
|
||||
file.path!,
|
||||
filename: file.name,
|
||||
);
|
||||
request.files.add(multipartFile);
|
||||
}
|
||||
print("📎 File attached: ${file.name} → $fieldName");
|
||||
} catch (e) {
|
||||
print("❌ Failed to attach $fieldName: $e");
|
||||
}
|
||||
}
|
||||
|
||||
await addFile(docUploadedRCFile, 'rc_file_name');
|
||||
await addFile(docUploadedIDProof, 'id_proof_file_name');
|
||||
await addFile(docUploadedPrevPolicy, 'previous_policy_file_name');
|
||||
}
|
||||
|
||||
Future<void> createUserData(Map<String, dynamic> userData) async {
|
||||
final bool isUpdating =
|
||||
widget.data != null && widget.id != 'tab' && widget.id != 'null';
|
||||
@ -397,16 +391,17 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
// request.fields[key] = value.toString();
|
||||
// print("✅ Encoded travel_details2: ${request.fields[key]}");
|
||||
// });
|
||||
|
||||
await attachFiles(request);
|
||||
userData.forEach((key, value) {
|
||||
if (key != 'certificate_file_name') {
|
||||
if (key != 'rc_file_name' && key != 'id_proof_file_name') {
|
||||
request.fields[key] = value.toString();
|
||||
print("✅ Encoded $key: ${request.fields[key]}");
|
||||
} else {
|
||||
print('Something Missing..');
|
||||
}
|
||||
});
|
||||
|
||||
// attach files
|
||||
await attachFiles(request);
|
||||
|
||||
// request.fields['agent_id'] = selectedId.toString();
|
||||
|
||||
@ -423,7 +418,13 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
print("✅ Agent submitted successfully!");
|
||||
ToastHelper.showSuccessToast(context, 'Saved Enquiry');
|
||||
print("Response: ${response.body}");
|
||||
context.go(AppRoutes.tabEnquiry);
|
||||
|
||||
if (isUpdating) {
|
||||
context.go(AppRoutes.tabEnquiry);
|
||||
} else {
|
||||
ref.read(enquiryIdProvider.notifier).state = null;
|
||||
context.go(AppRoutes.enquiryLst);
|
||||
}
|
||||
} else {
|
||||
print("❌ Submission failed. Status: ${response.statusCode}");
|
||||
print("Body: ${response.body}");
|
||||
@ -432,9 +433,9 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: Text("Agent Creation Failed"),
|
||||
title: Text("Enquiry Creation Failed"),
|
||||
content: Text(
|
||||
"There was a problem in creating user. Please try again.",
|
||||
"There was a problem in creating enquiry. Please try again.",
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
@ -455,6 +456,7 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
bool isMobile = ResponsiveLayout.isMobile(context);
|
||||
return Container(
|
||||
// color: Colors.green,
|
||||
decoration: BoxDecoration(
|
||||
@ -463,14 +465,16 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
),
|
||||
width: MediaQuery.of(context).size.width,
|
||||
// height: MediaQuery.of(context).size.height * 0.8,
|
||||
padding: EdgeInsets.all(26.0),
|
||||
padding: isMobile
|
||||
? EdgeInsets.only(left: 14.0, right: 14.0)
|
||||
: EdgeInsets.all(26.0),
|
||||
child: Column(
|
||||
children: [
|
||||
// Row(children: [Expanded(child: buildFormFields(context))]),
|
||||
Expanded(
|
||||
child: SingleChildScrollView(child: buildFormFields(context)),
|
||||
),
|
||||
|
||||
isMobile
|
||||
? Row(children: [Expanded(child: buildFormFields(context))])
|
||||
: Expanded(
|
||||
child: SingleChildScrollView(child: buildFormFields(context)),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
|
||||
Row(
|
||||
@ -499,27 +503,29 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
}
|
||||
|
||||
Widget buildFormFields(BuildContext context) {
|
||||
bool isMobile = ResponsiveLayout.isMobile(context);
|
||||
return Form(
|
||||
key: _formKey,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_buildResponsiveRow(context, buildName(context), buildEmail(context)),
|
||||
if (!ResponsiveLayout.isMobile(context)) const SizedBox(height: 20),
|
||||
|
||||
isMobile ? SizedBox(height: 5) : SizedBox(height: 20),
|
||||
|
||||
_buildResponsiveRow(
|
||||
context,
|
||||
buildPhNumber(context),
|
||||
buildId(context),
|
||||
),
|
||||
if (!ResponsiveLayout.isMobile(context)) const SizedBox(height: 20),
|
||||
isMobile ? SizedBox(height: 5) : SizedBox(height: 20),
|
||||
|
||||
_buildResponsiveRow(
|
||||
context,
|
||||
buildVehicleType(context),
|
||||
buildInsurer(context),
|
||||
),
|
||||
if (!ResponsiveLayout.isMobile(context)) const SizedBox(height: 20),
|
||||
isMobile ? SizedBox(height: 5) : SizedBox(height: 20),
|
||||
|
||||
_buildResponsiveRow(
|
||||
context,
|
||||
@ -527,7 +533,7 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
buildUploadIDDocument(context),
|
||||
),
|
||||
|
||||
if (!ResponsiveLayout.isMobile(context)) const SizedBox(height: 20),
|
||||
isMobile ? SizedBox(height: 5) : SizedBox(height: 20),
|
||||
_buildResponsiveRow(
|
||||
context,
|
||||
buildUploadPolicyDocument(context),
|
||||
@ -621,9 +627,10 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
|
||||
Widget buildName(BuildContext context) {
|
||||
return buildResponsiveField(
|
||||
label: "Full Name ",
|
||||
label: "Full Name *",
|
||||
field: ThemedFormField(
|
||||
controller: controllers['name']!,
|
||||
|
||||
validator: (value) => Validators.requiredField(value, "name"),
|
||||
txtwidth: ResponsiveLayout.isMobile(context)
|
||||
? null
|
||||
@ -634,7 +641,7 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
|
||||
Widget buildEmail(BuildContext context) {
|
||||
return buildResponsiveField(
|
||||
label: "Email",
|
||||
label: "Email *",
|
||||
field: ThemedFormField(
|
||||
controller: controllers['email']!,
|
||||
validator: (value) => Validators.email(value, "email"),
|
||||
@ -647,7 +654,7 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
|
||||
Widget buildPhNumber(BuildContext context) {
|
||||
return buildResponsiveField(
|
||||
label: "Phone Number",
|
||||
label: "Phone Number *",
|
||||
field: ThemedFormField(
|
||||
controller: controllers['mobile']!,
|
||||
validator: (value) => Validators.phone(value, "phNumber"),
|
||||
@ -660,7 +667,7 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
|
||||
Widget buildId(BuildContext context) {
|
||||
return buildResponsiveField(
|
||||
label: "Registration Number",
|
||||
label: "Registration Number *",
|
||||
field: ThemedFormField(
|
||||
controller: controllers['regNo']!,
|
||||
validator: (value) => Validators.requiredField(value, "regNo"),
|
||||
@ -680,9 +687,12 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
);
|
||||
|
||||
return buildResponsiveField(
|
||||
label: "Vehicle Type",
|
||||
label: "Vehicle Type *",
|
||||
field: Container(
|
||||
color: Colors.white,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(10.0),
|
||||
),
|
||||
width: ResponsiveLayout.isMobile(context)
|
||||
? null
|
||||
: MediaQuery.of(context).size.width * 0.26,
|
||||
@ -693,6 +703,12 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
items: (filter, infiniteScrollProps) {
|
||||
return filteredVechicleData;
|
||||
},
|
||||
validator: (val) {
|
||||
if (val == null) {
|
||||
return "Required"; // ✅ error message
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
itemAsString: (val) => val['vehicle_type'].toString(),
|
||||
compareFn: (item, selectedItem) =>
|
||||
@ -756,9 +772,12 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
orElse: () => {},
|
||||
);
|
||||
return buildResponsiveField(
|
||||
label: "Insurer",
|
||||
label: "Insurer *",
|
||||
field: Container(
|
||||
color: Colors.white,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(10.0),
|
||||
),
|
||||
width: ResponsiveLayout.isMobile(context)
|
||||
? null
|
||||
: MediaQuery.of(context).size.width * 0.26,
|
||||
@ -773,6 +792,12 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
itemAsString: (val) => val['name'].toString(), // what to show
|
||||
compareFn: (item, selectedItem) =>
|
||||
item['id'] == selectedItem['id'], // ✅ compare by id
|
||||
validator: (val) {
|
||||
if (val == null) {
|
||||
return "Required"; // ✅ error message
|
||||
}
|
||||
return null;
|
||||
},
|
||||
decoratorProps: DropDownDecoratorProps(
|
||||
decoration:
|
||||
AppInputDecorations.dropdownDecoration(
|
||||
@ -860,14 +885,14 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
padding: const EdgeInsets.only(top: 5),
|
||||
child: Row(
|
||||
children: [
|
||||
IconButton(
|
||||
onPressed: onRemove,
|
||||
icon: const Icon(
|
||||
Icons.remove_circle_outline_rounded,
|
||||
color: Colors.redAccent,
|
||||
),
|
||||
tooltip: 'Remove Upload',
|
||||
),
|
||||
// IconButton(
|
||||
// onPressed: onRemove,
|
||||
// icon: const Icon(
|
||||
// Icons.remove_circle_outline_rounded,
|
||||
// color: Colors.redAccent,
|
||||
// ),
|
||||
// tooltip: 'Remove Upload',
|
||||
// ),
|
||||
GestureDetector(
|
||||
onTap: onDownload,
|
||||
child: Container(
|
||||
@ -904,7 +929,10 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
Text(label, style: _textStyle),
|
||||
const SizedBox(height: 8),
|
||||
uploadWidget,
|
||||
downloadRow,
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [downloadRow],
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
],
|
||||
);
|
||||
@ -931,12 +959,12 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
|
||||
Widget buildUploadRCDocument(BuildContext context) {
|
||||
return buildResponsiveUploadField(
|
||||
label: "Upload RC Document",
|
||||
label: "Upload RC Document *",
|
||||
hintText: selectedRCFile,
|
||||
onFileSelected: (fileName, file) {
|
||||
setState(() {
|
||||
docUploadedRCFile = file;
|
||||
// selectedFileNames = fileName;
|
||||
selectedRCFileName = fileName;
|
||||
});
|
||||
},
|
||||
showDownload: docUploadedRCFile != null || rcFileUrlFromApi != null,
|
||||
@ -944,7 +972,7 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
setState(() {
|
||||
docUploadedRCFile = null;
|
||||
rcFileUrlFromApi = null;
|
||||
// selectedFileNames = null;
|
||||
selectedRCFileName = null;
|
||||
});
|
||||
},
|
||||
onDownload: () => apiService.downloadFile(
|
||||
@ -952,29 +980,17 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
apiUrl:
|
||||
'api/enquiry/downloadEnquiryFile?enquiry_id=$selectedId&file_type=rc',
|
||||
|
||||
apiId: null,
|
||||
apiId: selectedId.toString(),
|
||||
|
||||
localFile: docUploadedRCFile,
|
||||
fileName: 'RC',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Widget buildUploadIDDocument(BuildContext context) {
|
||||
// return buildResponsiveUploadField(
|
||||
// label: "Upload ID Proof",
|
||||
// hintText: selectedIdProof,
|
||||
// onFileSelected: (fileName, file) {
|
||||
// print("File picked: $fileName");
|
||||
// setState(() {
|
||||
// docUploadedIDProof = file;
|
||||
// });
|
||||
// },
|
||||
// );
|
||||
// }
|
||||
|
||||
Widget buildUploadIDDocument(BuildContext context) {
|
||||
return buildResponsiveUploadField(
|
||||
label: "Upload ID Proof",
|
||||
label: "Upload ID Proof *",
|
||||
hintText: selectedIdProof,
|
||||
onFileSelected: (fileName, file) {
|
||||
setState(() {
|
||||
@ -995,26 +1011,13 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
apiUrl:
|
||||
'api/enquiry/downloadEnquiryFile?enquiry_id=$selectedId&file_type=id_proof',
|
||||
|
||||
apiId: null,
|
||||
localFile: docUploadedRCFile,
|
||||
apiId: selectedId.toString(),
|
||||
localFile: docUploadedIDProof,
|
||||
fileName: 'Id_Proof',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Widget buildUploadPolicyDocument(BuildContext context) {
|
||||
// return buildResponsiveUploadField(
|
||||
// label: "Upload Previous Policy",
|
||||
// hintText: selectedPrevPolicy,
|
||||
// onFileSelected: (fileName, file) {
|
||||
// print("File picked: $fileName");
|
||||
// setState(() {
|
||||
// docUploadedPrevPolicy = file;
|
||||
// });
|
||||
// },
|
||||
// );
|
||||
// }
|
||||
|
||||
Widget buildUploadPolicyDocument(BuildContext context) {
|
||||
return buildResponsiveUploadField(
|
||||
label: "Upload Previous Policy",
|
||||
@ -1039,7 +1042,7 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
apiUrl:
|
||||
'api/enquiry/downloadEnquiryFile?enquiry_id=$selectedId&file_type=previous_policy',
|
||||
|
||||
apiId: null,
|
||||
apiId: selectedId.toString(),
|
||||
localFile: docUploadedPrevPolicy,
|
||||
fileName: 'Previous_Policy',
|
||||
),
|
||||
@ -1052,6 +1055,7 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
field: ThemedFormField(
|
||||
maxLength: 500,
|
||||
controller: controllers['remarks']!,
|
||||
keyboardType: TextInputType.multiline,
|
||||
txtwidth: ResponsiveLayout.isMobile(context)
|
||||
? null
|
||||
: MediaQuery.of(context).size.width * 0.26,
|
||||
|
||||
@ -1,52 +1,588 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:dropdown_search/dropdown_search.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:toastification/toastification.dart';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../../../core/config/env.dart';
|
||||
import '../../../../core/services/api_service.dart';
|
||||
import '../../../../data/services/auth_service.dart';
|
||||
import '../../../../data/utils/toastNotification.dart';
|
||||
import '../../../../data/utils/validators.dart';
|
||||
import '../../../layouts/responsive_layout.dart';
|
||||
import '../../../themes/indicators/input_field_decoration.dart';
|
||||
import '../../../themes/indicators/text_field_theme.dart';
|
||||
|
||||
Future<void> showAddDialog({
|
||||
required BuildContext context,
|
||||
required String title,
|
||||
required void Function(String value) onSubmit,
|
||||
}) async {
|
||||
final TextEditingController controller = TextEditingController();
|
||||
// 🔹 Custom Dialog Widget
|
||||
class AddDialog extends StatefulWidget {
|
||||
final String title;
|
||||
final dynamic userId;
|
||||
final void Function(String value) onSubmit;
|
||||
final dynamic policyNumber;
|
||||
const AddDialog({
|
||||
super.key,
|
||||
required this.title,
|
||||
required this.onSubmit,
|
||||
required this.userId,
|
||||
this.policyNumber,
|
||||
});
|
||||
|
||||
await showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
title: Text(title),
|
||||
content: title == 'Claim'
|
||||
? claims()
|
||||
: endorsement(), // 👈 conditional content
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: const Text("Cancel"),
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
onSubmit(controller.text.trim());
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: const Text("Save"),
|
||||
),
|
||||
],
|
||||
@override
|
||||
State<AddDialog> createState() => _AddDialogState();
|
||||
}
|
||||
|
||||
class _AddDialogState extends State<AddDialog> {
|
||||
late ApiService apiService;
|
||||
String? _token;
|
||||
|
||||
bool isLoading = false;
|
||||
late TextEditingController controller;
|
||||
Map<String, TextEditingController> controllers = {};
|
||||
|
||||
final _formKeyClaims = GlobalKey<FormState>();
|
||||
final _formKeyEndrosment = GlobalKey<FormState>();
|
||||
final GlobalKey<DropdownSearchState<Map<String, dynamic>>> dropDownKey =
|
||||
GlobalKey<DropdownSearchState<Map<String, dynamic>>>();
|
||||
final GlobalKey<DropdownSearchState<Map<String, dynamic>>>
|
||||
dropDownKeyEndorsement =
|
||||
GlobalKey<DropdownSearchState<Map<String, dynamic>>>();
|
||||
|
||||
List<String> tabHeader = ['policyNum', 'claimsDesc', 'remarks'];
|
||||
|
||||
List<Map<String, dynamic>> getClaimsTypeData = [];
|
||||
List<Map<String, dynamic>> filteredClaimsData = [];
|
||||
|
||||
List<Map<String, dynamic>> getEndrosmentType = [];
|
||||
List<Map<String, dynamic>> filteredEndrosmentData = [];
|
||||
|
||||
String? selectedClaimsType;
|
||||
String? selectedEndorsement;
|
||||
|
||||
Map<String, dynamic> claimsDetails() {
|
||||
final data = {
|
||||
"policy_number": controllers["policyNum"]?.text,
|
||||
"claim_description": controllers["claimsDesc"]?.text,
|
||||
"claim_type": selectedClaimsType,
|
||||
// "manager_id": managerId,
|
||||
"created_by": widget.userId,
|
||||
};
|
||||
return data;
|
||||
}
|
||||
|
||||
Map<String, dynamic> endrosmentDetails() {
|
||||
final data = {
|
||||
"policy_number": controllers["policyNum"]?.text,
|
||||
"endorsement_description": controllers["remarks"]?.text,
|
||||
"endorsement_type": selectedEndorsement,
|
||||
// "manager_id": managerId,
|
||||
"created_by": widget.userId,
|
||||
};
|
||||
return data;
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
apiService = ApiService();
|
||||
for (String field in tabHeader) {
|
||||
controllers[field] = TextEditingController();
|
||||
}
|
||||
|
||||
controllers["policyNum"]?.text = widget.policyNumber;
|
||||
// 🔹 Init logic here (API calls, token fetch, etc.)
|
||||
_initializeToken();
|
||||
getClaimsType();
|
||||
getEnroementType();
|
||||
}
|
||||
|
||||
Future<void> _initializeToken() async {
|
||||
_token = await AuthService.getToken();
|
||||
print("APISERTOKEN - $_token");
|
||||
}
|
||||
|
||||
Future<void> getClaimsType() async {
|
||||
print('getClaimList called');
|
||||
setState(() {
|
||||
isLoading = true;
|
||||
});
|
||||
|
||||
try {
|
||||
final response = await apiService.fetchMasterDropDown('Claim');
|
||||
|
||||
if (response['status'] == 200) {
|
||||
print('getClaimsTypeData - ${response['data']}');
|
||||
setState(() {
|
||||
getClaimsTypeData = List<Map<String, dynamic>>.from(response['data']);
|
||||
print('API Data - $getClaimsTypeData');
|
||||
|
||||
filteredClaimsData = List.from(getClaimsTypeData);
|
||||
print('originalData - $filteredClaimsData');
|
||||
});
|
||||
} else {
|
||||
getClaimsTypeData = [];
|
||||
filteredClaimsData = [];
|
||||
}
|
||||
} catch (e) {
|
||||
print('Exception occurred: $e');
|
||||
} finally {
|
||||
setState(() {
|
||||
isLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> getEnroementType() async {
|
||||
print('Insurers called');
|
||||
setState(() {
|
||||
isLoading = true;
|
||||
});
|
||||
|
||||
try {
|
||||
final response = await apiService.fetchMasterDropDown('Endorsement');
|
||||
|
||||
if (response['status'] == 200) {
|
||||
print('getEnroementType - ${response['data']}');
|
||||
setState(() {
|
||||
getEndrosmentType = List<Map<String, dynamic>>.from(response['data']);
|
||||
print('API Data - $getEndrosmentType');
|
||||
|
||||
filteredEndrosmentData = List.from(getEndrosmentType);
|
||||
print('originalData - $filteredEndrosmentData');
|
||||
});
|
||||
} else {
|
||||
getEndrosmentType = [];
|
||||
filteredEndrosmentData = [];
|
||||
}
|
||||
} catch (e) {
|
||||
print('Exception occurred: $e');
|
||||
} finally {
|
||||
setState(() {
|
||||
isLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void handleDone(val) {
|
||||
print('val - $val');
|
||||
if (val == 'Claims') {
|
||||
if (!_formKeyClaims.currentState!.validate()) return;
|
||||
setState(() {
|
||||
if (_formKeyClaims.currentState!.validate()) {
|
||||
claimsDetails();
|
||||
final dataSet = claimsDetails();
|
||||
print("dataSetAgent - $dataSet");
|
||||
// print("managerId - $managerId ,userId - $userId ");
|
||||
createUserData(dataSet, val);
|
||||
} else {
|
||||
// isDi sable = false;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (!_formKeyEndrosment.currentState!.validate()) return;
|
||||
setState(() {
|
||||
if (_formKeyEndrosment.currentState!.validate()) {
|
||||
endrosmentDetails();
|
||||
final dataSet = endrosmentDetails();
|
||||
print("dataSetAgent - $dataSet");
|
||||
// print("managerId - $managerId ,userId - $userId ");
|
||||
createUserData(dataSet, val);
|
||||
} else {
|
||||
// isDisable = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> createUserData(data, val) async {
|
||||
// final bool isUpdating = widget.id != null && widget.id != 'create';
|
||||
final String apiUrldata;
|
||||
|
||||
apiUrldata = (val == 'Claims')
|
||||
? '${Env.apiUrl}claim/createClaim'
|
||||
: '${Env.apiUrl}endorsement/createEndorsement';
|
||||
|
||||
// final token = await getToken(); // Fetch token
|
||||
|
||||
if (_token == null) {
|
||||
throw Exception('Token not found. Please log in.');
|
||||
}
|
||||
|
||||
print("data------- $data}");
|
||||
|
||||
try {
|
||||
final response = await http.post(
|
||||
Uri.parse(apiUrldata),
|
||||
headers: {
|
||||
'Authorization': 'Bearer $_token',
|
||||
'Content-Type': 'application/json',
|
||||
'app-signature': 'nhance-partner-2025-signature-35468846JRhH551HK',
|
||||
},
|
||||
body: jsonEncode(data), // Convert map to JSON
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget claims() {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
color: Colors.redAccent,
|
||||
child: const Text('Claims', style: TextStyle(color: Colors.white)),
|
||||
);
|
||||
}
|
||||
if (response.statusCode == 200) {
|
||||
print("Staff submitted successfully!");
|
||||
print("Response: ${response.body}");
|
||||
ToastHelper.showSuccessToast(context, 'Saved Successfully');
|
||||
Navigator.of(context).pop();
|
||||
|
||||
Widget endorsement() {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
color: Colors.yellow,
|
||||
child: const Text('Endorsement', style: TextStyle(color: Colors.black)),
|
||||
widget.onSubmit("success");
|
||||
// context.go(AppRoutes.staffLst);
|
||||
} else {
|
||||
final responseBody = jsonDecode(response.body);
|
||||
dynamic msg = responseBody['data'];
|
||||
|
||||
print("Failed to submit plan. Status: ${response.statusCode}");
|
||||
print("Error: ${response.body}");
|
||||
|
||||
ToastHelper.showErrorToast(context, 'Failed To Save');
|
||||
}
|
||||
} catch (e) {
|
||||
print(" Error submitting Staff: $e");
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
// controllers.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AlertDialog(
|
||||
backgroundColor: Colors.white,
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
// Header row
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
widget.title,
|
||||
style: GoogleFonts.inter(
|
||||
color: const Color(0xFF374141),
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () => Navigator.pop(context),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(5.0),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFFF1F1F1),
|
||||
borderRadius: BorderRadius.circular(5.0),
|
||||
),
|
||||
child: const Icon(Icons.close, size: 18),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
const SizedBox(height: 16),
|
||||
|
||||
// 🔹 Switch content dynamically
|
||||
widget.title == 'Claims' ? claims(context) : endorsement(context),
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
Center(
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
handleDone(widget.title);
|
||||
// widget.onSubmit(controller.text.trim());
|
||||
// Navigator.of(context).pop();
|
||||
},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 25.0,
|
||||
vertical: 8,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(8.0),
|
||||
color: const Color(0xFF425B5B),
|
||||
),
|
||||
child: const Text('Done', style: TextStyle(color: Colors.white)),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// 🔹 Example: Claims widget
|
||||
Widget claims(BuildContext context) {
|
||||
return Form(
|
||||
key: _formKeyClaims,
|
||||
child: Column(
|
||||
children: [
|
||||
buildClaimType(context),
|
||||
buildPolicyNumber(context),
|
||||
buildClaimsDesc(context),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// 🔹 Example: Endorsement widget
|
||||
Widget endorsement(BuildContext context) {
|
||||
return Form(
|
||||
key: _formKeyEndrosment,
|
||||
child: Column(
|
||||
children: [buildEndrosType(context), buildEndrosRemarks(context)],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// ------------------------- Claims Part -----------------------------------
|
||||
Widget buildPolicyNumber(context) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text("Policy Number", style: _textStyle),
|
||||
SizedBox(height: 10),
|
||||
ThemedFormField(
|
||||
controller: controllers['policyNum']!,
|
||||
backgroundColor: Color(0xFFEDF6F5),
|
||||
validator: (value) => Validators.requiredField(value, "name"),
|
||||
txtwidth: ResponsiveLayout.isMobile(context)
|
||||
? null
|
||||
: MediaQuery.of(context).size.width * 0.26,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildClaimsDesc(context) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text("Claims Description", style: _textStyle),
|
||||
SizedBox(height: 10),
|
||||
ThemedFormField(
|
||||
backgroundColor: Color(0xFFEDF6F5),
|
||||
controller: controllers['claimsDesc']!,
|
||||
validator: (value) => Validators.requiredField(value, "claimsDesc"),
|
||||
txtwidth: ResponsiveLayout.isMobile(context)
|
||||
? null
|
||||
: MediaQuery.of(context).size.width * 0.26,
|
||||
keyboardType: TextInputType.multiline,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildClaimType(context) {
|
||||
Map<String, dynamic>? selectedVehicle = filteredClaimsData.firstWhere(
|
||||
(item) => item['id'].toString() == selectedClaimsType,
|
||||
orElse: () => {},
|
||||
);
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text("Claims Type", style: _textStyle),
|
||||
SizedBox(height: 10),
|
||||
Container(
|
||||
color: Colors.white,
|
||||
width: ResponsiveLayout.isMobile(context)
|
||||
? null
|
||||
: MediaQuery.of(context).size.width * 0.26,
|
||||
// height: 40,
|
||||
child: DropdownSearch<Map<String, dynamic>>(
|
||||
key: dropDownKey,
|
||||
selectedItem: selectedVehicle.isNotEmpty ? selectedVehicle : null,
|
||||
items: (filter, infiniteScrollProps) {
|
||||
return filteredClaimsData;
|
||||
},
|
||||
|
||||
itemAsString: (val) => val['claim_type'].toString(),
|
||||
compareFn: (item, selectedItem) =>
|
||||
item['id'] == selectedItem['id'], // ✅ compare by id
|
||||
validator: (val) {
|
||||
if (val == null) {
|
||||
return "Required"; // ✅ error message
|
||||
}
|
||||
return null;
|
||||
},
|
||||
decoratorProps: DropDownDecoratorProps(
|
||||
decoration:
|
||||
AppInputDecorations.dropdownDecoration(
|
||||
label: "Select Claims Type",
|
||||
).copyWith(
|
||||
filled: true,
|
||||
fillColor: Color(
|
||||
0xFFEDF6F5,
|
||||
), // 👈 makes the dropdown input white
|
||||
),
|
||||
),
|
||||
|
||||
popupProps: PopupProps.menu(
|
||||
fit: FlexFit.loose,
|
||||
constraints: BoxConstraints(maxHeight: 250),
|
||||
menuProps: MenuProps(
|
||||
backgroundColor:
|
||||
Colors.white, // 👈 sets dropdown background to white
|
||||
),
|
||||
showSearchBox: true,
|
||||
searchFieldProps: TextFieldProps(
|
||||
decoration: InputDecoration(
|
||||
filled: true,
|
||||
fillColor: Colors.white,
|
||||
hintText: "Search Claims Type...",
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Colors.white,
|
||||
), // 👈 Normal border
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Colors.white,
|
||||
width: 1.5,
|
||||
), // 👈 Focused border
|
||||
),
|
||||
),
|
||||
),
|
||||
// constraints: BoxConstraints(),
|
||||
),
|
||||
|
||||
onChanged: (val) {
|
||||
if (val != null) {
|
||||
print("Selected ClaimsType : ${val['claim_type']}");
|
||||
print("Id: ${val['id']}");
|
||||
selectedClaimsType = val['id'];
|
||||
// controllers['agentId']?.text = val['agent_code'];
|
||||
// agentId = agent['id'];
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// ------------------------- Endrosment Part -----------------------------------
|
||||
|
||||
Widget buildEndrosType(context) {
|
||||
Map<String, dynamic>? selectedEndorsementd = filteredEndrosmentData
|
||||
.firstWhere(
|
||||
(item) => item['id'].toString() == selectedEndorsement,
|
||||
orElse: () => {},
|
||||
);
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text("Endorsement Type", style: _textStyle),
|
||||
SizedBox(height: 10),
|
||||
Container(
|
||||
color: Colors.white,
|
||||
width: ResponsiveLayout.isMobile(context)
|
||||
? null
|
||||
: MediaQuery.of(context).size.width * 0.26,
|
||||
// height: 40,
|
||||
child: DropdownSearch<Map<String, dynamic>>(
|
||||
key: dropDownKeyEndorsement,
|
||||
selectedItem: selectedEndorsementd.isNotEmpty
|
||||
? selectedEndorsementd
|
||||
: null,
|
||||
items: (filter, infiniteScrollProps) {
|
||||
return filteredEndrosmentData;
|
||||
},
|
||||
|
||||
itemAsString: (val) =>
|
||||
val['endorsement_type'].toString(), // what to show
|
||||
compareFn: (item, selectedItem) =>
|
||||
item['id'] == selectedItem['id'], // ✅ compare by id
|
||||
validator: (val) {
|
||||
if (val == null) {
|
||||
return "Required"; // ✅ error message
|
||||
}
|
||||
return null;
|
||||
},
|
||||
decoratorProps: DropDownDecoratorProps(
|
||||
decoration:
|
||||
AppInputDecorations.dropdownDecoration(
|
||||
label: "Select Endorsement Type",
|
||||
).copyWith(
|
||||
filled: true,
|
||||
fillColor: Color(
|
||||
0xFFEDF6F5,
|
||||
), // 👈 makes the dropdown input white
|
||||
),
|
||||
),
|
||||
|
||||
popupProps: PopupProps.menu(
|
||||
fit: FlexFit.loose,
|
||||
constraints: BoxConstraints(maxHeight: 250),
|
||||
menuProps: MenuProps(
|
||||
backgroundColor:
|
||||
Colors.white, // 👈 sets dropdown background to white
|
||||
),
|
||||
showSearchBox: true,
|
||||
searchFieldProps: TextFieldProps(
|
||||
decoration: InputDecoration(
|
||||
filled: true,
|
||||
fillColor: Colors.white,
|
||||
hintText: "Search Endorsement Type...",
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Colors.white,
|
||||
), // 👈 Normal border
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Colors.white,
|
||||
width: 1.5,
|
||||
), // 👈 Focused border
|
||||
),
|
||||
),
|
||||
),
|
||||
// constraints: BoxConstraints(),
|
||||
),
|
||||
|
||||
onChanged: (val) {
|
||||
if (val != null) {
|
||||
print("Selected Endorsement : ${val['endorsement_type']}");
|
||||
print("Id: ${val['id']}");
|
||||
selectedEndorsement = val['id'];
|
||||
// controllers['agentId']?.text = val['agent_code'];
|
||||
// agentId = agent['id'];
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildEndrosRemarks(context) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text("Remarks", style: _textStyle),
|
||||
SizedBox(height: 10),
|
||||
ThemedFormField(
|
||||
backgroundColor: Color(0xFFEDF6F5),
|
||||
controller: controllers['remarks']!,
|
||||
validator: (value) => Validators.requiredField(value, "remarks"),
|
||||
txtwidth: ResponsiveLayout.isMobile(context)
|
||||
? null
|
||||
: MediaQuery.of(context).size.width * 0.26,
|
||||
keyboardType: TextInputType.multiline,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// ------------------- STyle ---------------------------------
|
||||
|
||||
static final TextStyle _textStyle = TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
);
|
||||
}
|
||||
|
||||
@ -15,16 +15,26 @@ 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});
|
||||
const PolicyTab({super.key, this.data});
|
||||
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();
|
||||
@ -38,13 +48,6 @@ class PolicyTabState extends ConsumerState<PolicyTab> {
|
||||
bool isLoading = false;
|
||||
|
||||
List<String> tabHeader = [
|
||||
'name',
|
||||
'email',
|
||||
'mobile',
|
||||
'code',
|
||||
'address',
|
||||
'regNo',
|
||||
|
||||
'regNum',
|
||||
'insurer',
|
||||
'idv',
|
||||
@ -59,7 +62,7 @@ class PolicyTabState extends ConsumerState<PolicyTab> {
|
||||
String? _token;
|
||||
dynamic userId;
|
||||
dynamic managerId;
|
||||
|
||||
dynamic selectedPolicyNumber;
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
@ -74,7 +77,7 @@ class PolicyTabState extends ConsumerState<PolicyTab> {
|
||||
managerId = ref.watch(managerIdProvider);
|
||||
userId = ref.watch(userIdProvider);
|
||||
|
||||
getQuotationList(managerId);
|
||||
getPolicyList(managerId);
|
||||
});
|
||||
}
|
||||
|
||||
@ -83,8 +86,8 @@ class PolicyTabState extends ConsumerState<PolicyTab> {
|
||||
print("APISERTOKEN - $_token");
|
||||
}
|
||||
|
||||
Future<void> getQuotationList(int managerId) async {
|
||||
print('getClaimList called MagId - $managerId');
|
||||
Future<void> getPolicyList(int managerId) async {
|
||||
print('getPolicyList called MagId - $managerId');
|
||||
setState(() {
|
||||
isLoading = true;
|
||||
});
|
||||
@ -101,11 +104,14 @@ class PolicyTabState extends ConsumerState<PolicyTab> {
|
||||
// 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');
|
||||
@ -116,228 +122,329 @@ class PolicyTabState extends ConsumerState<PolicyTab> {
|
||||
}
|
||||
}
|
||||
|
||||
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']?.toString() ?? '';
|
||||
controllers['premAmount']?.text =
|
||||
record['premium_amount']?.toString() ?? '';
|
||||
controllers['planType']?.text =
|
||||
record['insurance_plan_type']?.toString() ?? '';
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
height: MediaQuery.of(context).size.height,
|
||||
width: MediaQuery.of(context).size.width,
|
||||
child: 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: EdgeInsets.all(26.0),
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
child: Row(
|
||||
final isMobile = ResponsiveLayout.isMobile(context);
|
||||
return isLoading
|
||||
? CircularProgressIndicator()
|
||||
: Container(
|
||||
height: MediaQuery.of(context).size.height,
|
||||
width: MediaQuery.of(context).size.width,
|
||||
child: filteredData.isNotEmpty
|
||||
? SingleChildScrollView(
|
||||
scrollDirection: Axis.vertical,
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
'Policy Details',
|
||||
style: GoogleFonts.inter(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 16,
|
||||
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),
|
||||
|
||||
Spacer(),
|
||||
GestureDetector(
|
||||
onTap: () {},
|
||||
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,
|
||||
SizedBox(width: 15),
|
||||
buildDocReciept(context, isMobile),
|
||||
],
|
||||
// GestureDetector(
|
||||
// onTap: () {
|
||||
// print("Upload ${widget.id}");
|
||||
// final selectedId = widget.id;
|
||||
// // final path =
|
||||
// // 'api/agent/downloadAgentIncentiveFile?id=$selectedId';
|
||||
// final path =
|
||||
// 'api/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,
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
],
|
||||
),
|
||||
),
|
||||
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),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
SizedBox(width: 15),
|
||||
GestureDetector(
|
||||
onTap: () {},
|
||||
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,
|
||||
),
|
||||
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,
|
||||
),
|
||||
SizedBox(width: 15),
|
||||
Icon(
|
||||
Icons.file_download_outlined,
|
||||
size: 16,
|
||||
color: Colors.white,
|
||||
),
|
||||
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),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
SingleChildScrollView(child: buildFormFields(context)),
|
||||
)
|
||||
: Center(child: Text('No Available Data')),
|
||||
);
|
||||
}
|
||||
|
||||
const SizedBox(height: 20),
|
||||
],
|
||||
Widget buildDocPolicy(BuildContext context, bool isMobile) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
print("Upload ${widget.id}");
|
||||
final selectedId = widget.id;
|
||||
// final path =
|
||||
// 'api/agent/downloadAgentIncentiveFile?id=$selectedId';
|
||||
final path =
|
||||
'api/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,
|
||||
),
|
||||
),
|
||||
const 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', style: _headerStyle),
|
||||
Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 100,
|
||||
child: Text('Claim', style: _headerStyle),
|
||||
),
|
||||
SizedBox(width: 20),
|
||||
Expanded(
|
||||
child: Container(
|
||||
padding: EdgeInsets.all(6.0),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(10.0),
|
||||
),
|
||||
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Container(child: buildClaimTable()),
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
showAddDialog(
|
||||
context: context,
|
||||
title: "Claim",
|
||||
onSubmit: (value) {
|
||||
print("New Claim: $value");
|
||||
// update claim list here
|
||||
},
|
||||
);
|
||||
},
|
||||
icon: Icon(Icons.add),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 100,
|
||||
child: Text('Endorsement', style: _headerStyle),
|
||||
),
|
||||
SizedBox(width: 20),
|
||||
Expanded(
|
||||
child: Container(
|
||||
padding: EdgeInsets.all(8.0),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(6.0),
|
||||
),
|
||||
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Container(child: buildEndrosmentTable()),
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
showAddDialog(
|
||||
context: context,
|
||||
title: "Endorsement",
|
||||
onSubmit: (value) {
|
||||
print("New Claim: $value");
|
||||
// update claim list here
|
||||
},
|
||||
);
|
||||
},
|
||||
icon: Icon(Icons.add),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
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),
|
||||
],
|
||||
),
|
||||
isMobile ? const Spacer() : const SizedBox(width: 15),
|
||||
const Icon(
|
||||
Icons.file_download_outlined,
|
||||
size: 16,
|
||||
color: Colors.white,
|
||||
),
|
||||
],
|
||||
),
|
||||
@ -345,7 +452,149 @@ class PolicyTabState extends ConsumerState<PolicyTab> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildDocReciept(BuildContext context, bool isMobile) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
print("Upload ${widget.id}");
|
||||
final selectedId = widget.id;
|
||||
// final path =
|
||||
// 'api/agent/downloadAgentIncentiveFile?id=$selectedId';
|
||||
final path =
|
||||
'api/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 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 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 IconButton(
|
||||
onPressed: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (ctx) => AddDialog(
|
||||
userId: userId,
|
||||
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 IconButton(
|
||||
onPressed: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (ctx) => AddDialog(
|
||||
userId: userId,
|
||||
title: "Claims",
|
||||
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(
|
||||
@ -356,28 +605,36 @@ class PolicyTabState extends ConsumerState<PolicyTab> {
|
||||
buildName(context),
|
||||
buildInsusrer(context),
|
||||
),
|
||||
if (!ResponsiveLayout.isMobile(context)) const SizedBox(height: 10),
|
||||
|
||||
isMobile ? SizedBox(height: 5) : SizedBox(height: 10),
|
||||
_buildResponsiveRow(
|
||||
context,
|
||||
buildIdv(context),
|
||||
buildInsurdName(context),
|
||||
),
|
||||
if (!ResponsiveLayout.isMobile(context)) const SizedBox(height: 10),
|
||||
|
||||
isMobile ? SizedBox(height: 5) : SizedBox(height: 10),
|
||||
_buildResponsiveRow(
|
||||
context,
|
||||
buildPolicyNum(context),
|
||||
buildPaymentMode(context),
|
||||
),
|
||||
|
||||
if (!ResponsiveLayout.isMobile(context)) const SizedBox(height: 10),
|
||||
|
||||
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),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
@ -390,7 +647,7 @@ class PolicyTabState extends ConsumerState<PolicyTab> {
|
||||
) {
|
||||
if (ResponsiveLayout.isMobile(context)) {
|
||||
// Stack vertically
|
||||
return Column(children: [first, const SizedBox(height: 2), second]);
|
||||
return Column(children: [first, const SizedBox(height: 4), second]);
|
||||
} else {
|
||||
// Place side by side
|
||||
return Row(
|
||||
@ -432,8 +689,8 @@ class PolicyTabState extends ConsumerState<PolicyTab> {
|
||||
return buildResponsiveField(
|
||||
label: "Registration Number",
|
||||
field: ThemedFormField(
|
||||
controller: controllers['name']!,
|
||||
validator: (value) => Validators.requiredField(value, "name"),
|
||||
controller: controllers['regNum']!,
|
||||
// validator: (value) => Validators.requiredField(value, "name"),
|
||||
txtwidth: ResponsiveLayout.isMobile(context)
|
||||
? null
|
||||
: MediaQuery.of(context).size.width * 0.26,
|
||||
@ -445,8 +702,7 @@ class PolicyTabState extends ConsumerState<PolicyTab> {
|
||||
return buildResponsiveField(
|
||||
label: "Insusrer",
|
||||
field: ThemedFormField(
|
||||
controller: controllers['email']!,
|
||||
validator: (value) => Validators.email(value, "email"),
|
||||
controller: controllers['insurer']!,
|
||||
txtwidth: ResponsiveLayout.isMobile(context)
|
||||
? null
|
||||
: MediaQuery.of(context).size.width * 0.26,
|
||||
@ -458,7 +714,7 @@ class PolicyTabState extends ConsumerState<PolicyTab> {
|
||||
return buildResponsiveField(
|
||||
label: "IDV",
|
||||
field: ThemedFormField(
|
||||
controller: controllers['mobile']!,
|
||||
controller: controllers['idv']!,
|
||||
validator: (value) => Validators.phone(value, "phNumber"),
|
||||
txtwidth: ResponsiveLayout.isMobile(context)
|
||||
? null
|
||||
@ -471,8 +727,8 @@ class PolicyTabState extends ConsumerState<PolicyTab> {
|
||||
return buildResponsiveField(
|
||||
label: "Insured Name",
|
||||
field: ThemedFormField(
|
||||
controller: controllers['mobile']!,
|
||||
validator: (value) => Validators.phone(value, "phNumber"),
|
||||
controller: controllers['insurerName']!,
|
||||
// validator: (value) => Validators.phone(value, "phNumber"),
|
||||
txtwidth: ResponsiveLayout.isMobile(context)
|
||||
? null
|
||||
: MediaQuery.of(context).size.width * 0.26,
|
||||
@ -484,8 +740,8 @@ class PolicyTabState extends ConsumerState<PolicyTab> {
|
||||
return buildResponsiveField(
|
||||
label: "Policy Number",
|
||||
field: ThemedFormField(
|
||||
controller: controllers['mobile']!,
|
||||
validator: (value) => Validators.phone(value, "phNumber"),
|
||||
controller: controllers['policyNo']!,
|
||||
// validator: (value) => Validators.phone(value, "phNumber"),
|
||||
txtwidth: ResponsiveLayout.isMobile(context)
|
||||
? null
|
||||
: MediaQuery.of(context).size.width * 0.26,
|
||||
@ -497,8 +753,7 @@ class PolicyTabState extends ConsumerState<PolicyTab> {
|
||||
return buildResponsiveField(
|
||||
label: "Payment Mode",
|
||||
field: ThemedFormField(
|
||||
controller: controllers['mobile']!,
|
||||
validator: (value) => Validators.phone(value, "phNumber"),
|
||||
controller: controllers['paymentMode']!,
|
||||
txtwidth: ResponsiveLayout.isMobile(context)
|
||||
? null
|
||||
: MediaQuery.of(context).size.width * 0.26,
|
||||
@ -510,7 +765,7 @@ class PolicyTabState extends ConsumerState<PolicyTab> {
|
||||
return buildResponsiveField(
|
||||
label: "Plan Type",
|
||||
field: ThemedFormField(
|
||||
controller: controllers['mobile']!,
|
||||
controller: controllers['planType']!,
|
||||
validator: (value) => Validators.phone(value, "phNumber"),
|
||||
txtwidth: ResponsiveLayout.isMobile(context)
|
||||
? null
|
||||
@ -523,7 +778,7 @@ class PolicyTabState extends ConsumerState<PolicyTab> {
|
||||
return buildResponsiveField(
|
||||
label: "Premium Amount",
|
||||
field: ThemedFormField(
|
||||
controller: controllers['mobile']!,
|
||||
controller: controllers['premAmount']!,
|
||||
validator: (value) => Validators.phone(value, "phNumber"),
|
||||
txtwidth: ResponsiveLayout.isMobile(context)
|
||||
? null
|
||||
@ -532,14 +787,6 @@ class PolicyTabState extends ConsumerState<PolicyTab> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildClaimTable() {
|
||||
return Text('data');
|
||||
}
|
||||
|
||||
Widget buildEndrosmentTable() {
|
||||
return Text('data');
|
||||
}
|
||||
|
||||
static const _headerStyle = TextStyle(
|
||||
color: Colors.black,
|
||||
fontWeight: FontWeight.bold,
|
||||
@ -549,4 +796,29 @@ class PolicyTabState extends ConsumerState<PolicyTab> {
|
||||
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,
|
||||
);
|
||||
}
|
||||
|
||||
@ -45,6 +45,7 @@ class QuotationTabState extends ConsumerState<QuotationTab> {
|
||||
'regNum',
|
||||
'insurer',
|
||||
'idv',
|
||||
'insuranceId',
|
||||
'premAmount',
|
||||
'planType',
|
||||
'addit_doc',
|
||||
@ -64,6 +65,7 @@ class QuotationTabState extends ConsumerState<QuotationTab> {
|
||||
String? selectedId;
|
||||
bool isLoading = false;
|
||||
bool isquotation = false;
|
||||
bool showAction = false;
|
||||
|
||||
Map<String, TextEditingController> controllers = {};
|
||||
String? _token;
|
||||
@ -78,13 +80,12 @@ class QuotationTabState extends ConsumerState<QuotationTab> {
|
||||
|
||||
Map<String, dynamic> dataDetails() {
|
||||
final data = {
|
||||
"regNum": controllers["regNum"]?.text,
|
||||
"insurer": controllers["insurer"]?.text,
|
||||
"mobile": controllers["mobile"]?.text,
|
||||
"address": controllers["address"]?.text,
|
||||
"agent_code": controllers["code"]?.text,
|
||||
"is_active": isActive,
|
||||
"manager_id": managerId,
|
||||
"id": selectedId,
|
||||
"enquiry_id": widget.id,
|
||||
"insured_declared_value": controllers["idv"]?.text,
|
||||
"premium_amount": controllers["premAmount"]?.text,
|
||||
"insurance_plan_type_id": controllers["insuranceId"]?.text,
|
||||
"updated_by": userId,
|
||||
};
|
||||
return data;
|
||||
}
|
||||
@ -129,42 +130,42 @@ class QuotationTabState extends ConsumerState<QuotationTab> {
|
||||
});
|
||||
|
||||
try {
|
||||
// if (widget.data != null) {
|
||||
// final data = List<Map<String, dynamic>>.from(widget.data as Iterable);
|
||||
//
|
||||
// print('quoationListData - ${widget.data}');
|
||||
// setState(() {
|
||||
// getQuotationData = data;
|
||||
// // getQuotationData = List<Map<String, dynamic>>.from(response['data']);
|
||||
// originalData = getQuotationData;
|
||||
// filteredData = List.from(originalData);
|
||||
// // print('originalData - $getClaimPolicies');
|
||||
// });
|
||||
// }
|
||||
final response;
|
||||
|
||||
final response = await apiService.findSingleQuotationData(managerId);
|
||||
if (widget.data != null && widget.id != null) {
|
||||
final data = List<Map<String, dynamic>>.from(widget.data as Iterable);
|
||||
response = await apiService.findSingleQuotationData(widget.id);
|
||||
// print('quoationListData - ${widget.data}');
|
||||
// setState(() {
|
||||
// getQuotationData = data;
|
||||
// // getQuotationData = List<Map<String, dynamic>>.from(response['data']);
|
||||
// originalData = getQuotationData;
|
||||
// filteredData = List.from(originalData);
|
||||
// // print('originalData - $getClaimPolicies');
|
||||
// });
|
||||
|
||||
if (response['status'] == 'success') {
|
||||
final rawData = response['data'];
|
||||
print('quoationListData1 - ${response['data']}');
|
||||
setState(() {
|
||||
if (rawData is List) {
|
||||
// already a list
|
||||
getQuotationData = List<Map<String, dynamic>>.from(rawData);
|
||||
} else if (rawData is Map) {
|
||||
// single object, wrap into a list
|
||||
getQuotationData = [Map<String, dynamic>.from(rawData)];
|
||||
} else {
|
||||
getQuotationData = [];
|
||||
}
|
||||
// getQuotationData = List<Map<String, dynamic>>.from(response['data']);
|
||||
originalData = getQuotationData;
|
||||
filteredData = List.from(originalData);
|
||||
// print('originalData - $getClaimPolicies');
|
||||
});
|
||||
} else {
|
||||
getQuotationData = [];
|
||||
originalData = [];
|
||||
if (response['status'] == 'success') {
|
||||
final rawData = response['data'];
|
||||
print('quoationListData1 - ${response['data']}');
|
||||
setState(() {
|
||||
if (rawData is List) {
|
||||
// already a list
|
||||
getQuotationData = List<Map<String, dynamic>>.from(rawData);
|
||||
} else if (rawData is Map) {
|
||||
// single object, wrap into a list
|
||||
getQuotationData = [Map<String, dynamic>.from(rawData)];
|
||||
} else {
|
||||
getQuotationData = [];
|
||||
}
|
||||
// getQuotationData = List<Map<String, dynamic>>.from(response['data']);
|
||||
originalData = getQuotationData;
|
||||
filteredData = List.from(originalData);
|
||||
// print('originalData - $getClaimPolicies');
|
||||
});
|
||||
} else {
|
||||
getQuotationData = [];
|
||||
originalData = [];
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
print('Exception occurred: $e');
|
||||
@ -203,11 +204,33 @@ class QuotationTabState extends ConsumerState<QuotationTab> {
|
||||
data['insured_declared_value']?.toString() ?? '';
|
||||
controllers['premAmount']?.text =
|
||||
data['premium_amount']?.toString() ?? '';
|
||||
controllers['planType']?.text =
|
||||
|
||||
controllers['insuranceId']?.text =
|
||||
data['insurance_plan_type_id']?.toString() ?? '';
|
||||
controllers['addit_doc']?.text =
|
||||
data['additional_uploaded_file_name']?.toString() ?? '';
|
||||
controllers['planType']?.text =
|
||||
data['insurance_plan_type']?.toString() ?? '';
|
||||
|
||||
controllers['remarks']?.text = data['reject_reason']?.toString() ?? '';
|
||||
|
||||
String? status = data['status']?.toString() ?? '';
|
||||
if (status == 'Pending') {
|
||||
print('status - $status');
|
||||
showAction = true;
|
||||
}
|
||||
|
||||
String? apiDocPath = data["additional_uploaded_file_name"];
|
||||
if (apiDocPath != null && apiDocPath.isNotEmpty) {
|
||||
print('apiDocPath - $apiDocPath');
|
||||
selectedFileNames = apiDocPath.split('/').last;
|
||||
print('selectedFileNames - $selectedFileNames');
|
||||
docUploadedFileFromApi = apiDocPath;
|
||||
print('docUploadedFileFromApi - $docUploadedFileFromApi');
|
||||
docUploadedFile = null;
|
||||
} else {
|
||||
selectedFileNames = null;
|
||||
docUploadedFile = null;
|
||||
docUploadedFileFromApi = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -266,101 +289,205 @@ class QuotationTabState extends ConsumerState<QuotationTab> {
|
||||
}
|
||||
}
|
||||
|
||||
void UpdataDocuments() {
|
||||
final dataSet = dataDetails();
|
||||
print('UpdataDocuments - $dataSet}');
|
||||
createDocumentData(dataSet);
|
||||
}
|
||||
|
||||
Future<void> createDocumentData(Map<String, dynamic> userData) async {
|
||||
final id = widget.id;
|
||||
final uri = Uri.parse('${Env.apiUrl}quotation/updateQuotation');
|
||||
if (_token == null) {
|
||||
throw Exception('Token not found. Please log in.');
|
||||
}
|
||||
|
||||
// Use MultipartRequest (POST only)
|
||||
final request = http.MultipartRequest('POST', uri);
|
||||
request.headers['Authorization'] = 'Bearer $_token';
|
||||
request.headers['app-signature'] =
|
||||
'nhance-partner-2025-signature-35468846JRhH551HK';
|
||||
|
||||
print("USerDAta - $userData");
|
||||
|
||||
// userData.forEach((key, value) {
|
||||
// request.fields[key] = value.toString();
|
||||
// print("✅ Encoded travel_details2: ${request.fields[key]}");
|
||||
// });
|
||||
|
||||
userData.forEach((key, value) {
|
||||
if (key != 'additional_uploaded_file_name') {
|
||||
request.fields[key] = value.toString();
|
||||
print("✅ Encoded $key: ${request.fields[key]}");
|
||||
}
|
||||
});
|
||||
|
||||
// Attach file if selected
|
||||
if (docUploadedFile != null) {
|
||||
try {
|
||||
if (docUploadedFile!.bytes != null) {
|
||||
final multipartFile = http.MultipartFile.fromBytes(
|
||||
'additional_uploaded_file_name',
|
||||
docUploadedFile!.bytes!,
|
||||
filename: docUploadedFile!.name,
|
||||
);
|
||||
request.files.add(multipartFile);
|
||||
} else if (docUploadedFile!.path != null) {
|
||||
final multipartFile = await http.MultipartFile.fromPath(
|
||||
'additional_uploaded_file_name',
|
||||
docUploadedFile!.path!,
|
||||
filename: docUploadedFile!.name,
|
||||
);
|
||||
request.files.add(multipartFile);
|
||||
}
|
||||
print("📎 File attached: ${docUploadedFile!.name}");
|
||||
} catch (e) {
|
||||
print("❌ Failed to attach file: $e");
|
||||
}
|
||||
}
|
||||
|
||||
print(" Sending request with fields: ${request.fields}");
|
||||
|
||||
try {
|
||||
final streamedResponse = await request.send();
|
||||
final response = await http.Response.fromStream(streamedResponse);
|
||||
print("Response status: ${response.statusCode}");
|
||||
print("Response body: ${response.body}");
|
||||
|
||||
if (response.statusCode == 200 || response.statusCode == 201) {
|
||||
// dispose();
|
||||
|
||||
ToastHelper.showSuccessToast(context, 'Document Uploaded');
|
||||
print("Response: ${response.body}");
|
||||
// context.go(AppRoutes.agentLst);
|
||||
} else {
|
||||
final responseBody = jsonDecode(response.body);
|
||||
dynamic msg = responseBody['data'];
|
||||
print("❌ Submission failed. Status: ${response.statusCode}");
|
||||
print("Body: ${response.body}");
|
||||
ToastHelper.showErrorToast(context, 'Document Upload Failed');
|
||||
}
|
||||
} catch (e) {
|
||||
print("🔥 Error submitting user: $e");
|
||||
}
|
||||
}
|
||||
|
||||
Color _getStatusColor(String? status) {
|
||||
switch (status) {
|
||||
case 'Accepted':
|
||||
return Colors.green;
|
||||
case 'Rejected':
|
||||
return Colors.red;
|
||||
default:
|
||||
return Colors.grey;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
bool isMobile = ResponsiveLayout.isMobile(context);
|
||||
return Container(
|
||||
height: MediaQuery.of(context).size.height,
|
||||
width: MediaQuery.of(context).size.width,
|
||||
child: 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: EdgeInsets.all(16.0),
|
||||
child: filteredData.isNotEmpty
|
||||
? SingleChildScrollView(
|
||||
scrollDirection: Axis.vertical,
|
||||
child: Column(
|
||||
children: [
|
||||
// Text('datta')
|
||||
_buildDataTable(context),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
const SizedBox(height: 20),
|
||||
if (isquotation)
|
||||
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(26.0),
|
||||
child: Column(
|
||||
children: [
|
||||
SingleChildScrollView(child: buildFormFields(context)),
|
||||
|
||||
const SizedBox(height: 20),
|
||||
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
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(6.0)
|
||||
: EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
handleActions('Rejected');
|
||||
},
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 45.0,
|
||||
vertical: 8,
|
||||
),
|
||||
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(8.0),
|
||||
color: Color(0xFF425B5B),
|
||||
),
|
||||
child: Text(
|
||||
'Reject',
|
||||
style: TextStyle(color: Colors.white),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
handleActions('Accepted');
|
||||
},
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 45.0,
|
||||
vertical: 8,
|
||||
),
|
||||
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(8.0),
|
||||
color: Color(0xFF425B5B),
|
||||
),
|
||||
child: Text(
|
||||
'Accept',
|
||||
style: TextStyle(color: Colors.white),
|
||||
),
|
||||
),
|
||||
),
|
||||
// Text('datta')
|
||||
_buildDataTable(context),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
const SizedBox(height: 20),
|
||||
if (isquotation)
|
||||
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.only(left: 14.0, right: 14.0)
|
||||
: EdgeInsets.all(26.0),
|
||||
child: Column(
|
||||
children: [
|
||||
SingleChildScrollView(
|
||||
child: buildFormFields(context),
|
||||
),
|
||||
|
||||
const SizedBox(height: 20),
|
||||
|
||||
if (showAction)
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
handleActions('Rejected');
|
||||
},
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 45.0,
|
||||
vertical: 8,
|
||||
),
|
||||
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(8.0),
|
||||
color: Color(0xFF425B5B),
|
||||
),
|
||||
child: Text(
|
||||
'Reject',
|
||||
style: TextStyle(color: Colors.white),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
handleActions('Accepted');
|
||||
},
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 45.0,
|
||||
vertical: 8,
|
||||
),
|
||||
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(8.0),
|
||||
color: Color(0xFF425B5B),
|
||||
),
|
||||
child: Text(
|
||||
'Accept',
|
||||
style: TextStyle(color: Colors.white),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
: Center(child: Text('No Available Data')),
|
||||
);
|
||||
}
|
||||
|
||||
@ -531,12 +658,14 @@ class QuotationTabState extends ConsumerState<QuotationTab> {
|
||||
|
||||
Widget buildDocuments(BuildContext context) {
|
||||
return buildResponsiveUploadField(
|
||||
label: "Passport File",
|
||||
label: 'Quotation Documents',
|
||||
hintText: selectedFileNames,
|
||||
onFileSelected: (fileName, file) {
|
||||
setState(() {
|
||||
docUploadedFile = file;
|
||||
selectedFileNames = fileName;
|
||||
|
||||
UpdataDocuments();
|
||||
});
|
||||
},
|
||||
showDownload: docUploadedFile != null || docUploadedFileFromApi != null,
|
||||
@ -548,8 +677,8 @@ class QuotationTabState extends ConsumerState<QuotationTab> {
|
||||
});
|
||||
},
|
||||
onDownload: () => apiService.downloadFile(
|
||||
apiUrl: 'api/agent/downloadAgentCertificateFile?agent_id=$selectedId',
|
||||
apiId: null,
|
||||
apiUrl: 'api/quotation/downloadAdditionalUploadedFile?id=$selectedId',
|
||||
apiId: selectedId,
|
||||
localFile: docUploadedFile,
|
||||
fileName: selectedFileNames,
|
||||
),
|
||||
@ -664,14 +793,14 @@ class QuotationTabState extends ConsumerState<QuotationTab> {
|
||||
padding: const EdgeInsets.only(top: 5),
|
||||
child: Row(
|
||||
children: [
|
||||
IconButton(
|
||||
onPressed: onRemove,
|
||||
icon: const Icon(
|
||||
Icons.remove_circle_outline_rounded,
|
||||
color: Colors.redAccent,
|
||||
),
|
||||
tooltip: 'Remove Upload',
|
||||
),
|
||||
// IconButton(
|
||||
// onPressed: onRemove,
|
||||
// icon: const Icon(
|
||||
// Icons.remove_circle_outline_rounded,
|
||||
// color: Colors.redAccent,
|
||||
// ),
|
||||
// tooltip: 'Remove Upload',
|
||||
// ),
|
||||
GestureDetector(
|
||||
onTap: onDownload,
|
||||
child: Container(
|
||||
@ -788,6 +917,7 @@ class QuotationTabState extends ConsumerState<QuotationTab> {
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Checkbox(
|
||||
activeColor: Colors.black,
|
||||
value: selectedId == item['id'], // only selected row is checked
|
||||
onChanged: (val) {
|
||||
setState(() {
|
||||
@ -823,10 +953,7 @@ class QuotationTabState extends ConsumerState<QuotationTab> {
|
||||
),
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Text(
|
||||
item['insurance_plan_type_id'] ?? '-',
|
||||
style: _dataBold,
|
||||
),
|
||||
child: Text(item['insurance_plan_type'] ?? '-', style: _dataBold),
|
||||
),
|
||||
Expanded(
|
||||
flex: 1,
|
||||
@ -851,10 +978,11 @@ class QuotationTabState extends ConsumerState<QuotationTab> {
|
||||
|
||||
Widget _buildDataCard(Map<String, dynamic> item, int sno) {
|
||||
return Container(
|
||||
margin: const EdgeInsets.symmetric(vertical: 6, horizontal: 8),
|
||||
// margin: const EdgeInsets.symmetric(vertical: 6, horizontal: 8),
|
||||
padding: const EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFFF6FEFD),
|
||||
color: const Color(0xFFFFFFFF),
|
||||
// color: const Color(0xFFF6FEFD),
|
||||
borderRadius: BorderRadius.circular(8.0),
|
||||
border: Border.all(color: const Color(0xffD9EBE8)),
|
||||
),
|
||||
@ -864,6 +992,7 @@ class QuotationTabState extends ConsumerState<QuotationTab> {
|
||||
children: [
|
||||
// ✅ Single-select checkbox
|
||||
Checkbox(
|
||||
activeColor: Colors.black,
|
||||
value: selectedId == item['id'], // only selected row is checked
|
||||
onChanged: (val) {
|
||||
setState(() {
|
||||
@ -886,56 +1015,69 @@ class QuotationTabState extends ConsumerState<QuotationTab> {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Company + Vehicle Reg No
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// flex: 2,
|
||||
child: Text(
|
||||
item['insurer_name'] ?? '-',
|
||||
style: _cardRow1BodyStyle,
|
||||
),
|
||||
),
|
||||
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
Expanded(
|
||||
// flex: 2,
|
||||
child: Text(
|
||||
item['insurance_plan_type'] ?? '-',
|
||||
style: _cardRow1BodyStyle,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
// "TN64V3456",
|
||||
item['reg_no'] ?? '-',
|
||||
style: _cardheaderStyle,
|
||||
),
|
||||
Text(
|
||||
'IDV: ${item['insured_declared_value']}' ?? '-',
|
||||
style: _cardRow2BodyStyle,
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
RichText(
|
||||
text: TextSpan(
|
||||
children: [
|
||||
Text(
|
||||
item['insurer_name'] ?? '-',
|
||||
|
||||
style: _cardBodyStyle,
|
||||
TextSpan(
|
||||
text: 'Status : ', // key
|
||||
style: TextStyle(
|
||||
color: Colors.black,
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 11,
|
||||
), // key color
|
||||
),
|
||||
Text(
|
||||
// "TN64V3456",
|
||||
item['reg_no'] ?? '-',
|
||||
|
||||
style: _cardheaderStyle,
|
||||
),
|
||||
Text(
|
||||
'Status : ${item['status']}' ?? '-',
|
||||
|
||||
style: _cardBodyStyle,
|
||||
TextSpan(
|
||||
text: '${item['status'] ?? '-'}', // value
|
||||
style: TextStyle(
|
||||
color: _getStatusColor(item['status']),
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 11,
|
||||
), // value color
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(width: 5),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
item['insurance_plan_type_id'] ?? '-',
|
||||
style: _cardBodyStyle,
|
||||
),
|
||||
Text(
|
||||
item['insured_declared_value'] ?? '-',
|
||||
style: _cardBodyStyle,
|
||||
),
|
||||
Text(
|
||||
'Premium Amount - ${item['premium_amount']}' ?? '-',
|
||||
style: _cardheaderStyle,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Text(
|
||||
'${item['premium_amount']}' ?? '-',
|
||||
style: _cardheaderStyle,
|
||||
),
|
||||
],
|
||||
),
|
||||
@ -977,8 +1119,21 @@ class QuotationTabState extends ConsumerState<QuotationTab> {
|
||||
);
|
||||
|
||||
static const _cardBodyStyle = TextStyle(
|
||||
// color: Color(0xFF545454),
|
||||
color: Colors.black,
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 12,
|
||||
);
|
||||
static const _cardRow1BodyStyle = TextStyle(
|
||||
// color: Color(0xFF545454),
|
||||
color: Colors.black,
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: 12,
|
||||
);
|
||||
static const _cardRow2BodyStyle = TextStyle(
|
||||
color: Color(0xFF545454),
|
||||
fontWeight: FontWeight.w400,
|
||||
// color: Colors.black,
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: 12,
|
||||
);
|
||||
}
|
||||
|
||||
@ -19,12 +19,13 @@ class TabEnquiryList extends ConsumerStatefulWidget {
|
||||
}
|
||||
|
||||
class TabEnquiryListState extends ConsumerState<TabEnquiryList> {
|
||||
int? expandedIndex;
|
||||
int selectedIndex = 0;
|
||||
List<TabItem> tabs = [];
|
||||
Map<String, dynamic>? enquiryData;
|
||||
bool isLoading = true;
|
||||
late ApiService apiService;
|
||||
|
||||
ScrollController _scrollController = ScrollController();
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
@ -76,6 +77,7 @@ class TabEnquiryListState extends ConsumerState<TabEnquiryList> {
|
||||
data: (enquiryData?["policies"] as List<dynamic>?)!
|
||||
.map((e) => Map<String, dynamic>.from(e as Map))
|
||||
.toList(),
|
||||
id: id ?? "",
|
||||
),
|
||||
),
|
||||
|
||||
@ -103,6 +105,7 @@ class TabEnquiryListState extends ConsumerState<TabEnquiryList> {
|
||||
|
||||
return MainLayout(
|
||||
title: "Enquiry",
|
||||
|
||||
body: SafeArea(
|
||||
child: isLoading
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
@ -118,22 +121,55 @@ class TabEnquiryListState extends ConsumerState<TabEnquiryList> {
|
||||
itemCount: tabs.length,
|
||||
padding: const EdgeInsets.all(16),
|
||||
itemBuilder: (context, index) {
|
||||
final isExpanded = expandedIndex == index;
|
||||
|
||||
return Card(
|
||||
margin: const EdgeInsets.only(bottom: 12),
|
||||
color: const Color(0xFF425B5B),
|
||||
color: isExpanded ? const Color(0xFFEDF6F5) : const Color(0xFF425B5B),
|
||||
// color: Color(0xFFEDF6F5),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
side: BorderSide(
|
||||
color: isExpanded ? Color(0xFF425B5B) : Color(0xFF425B5B),
|
||||
// color: isExpanded ? Color(0xFFEDF6F5) : Color(0xFFEDF6F5),
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
child: ExpansionTile(
|
||||
collapsedIconColor: Colors.white,
|
||||
iconColor: Colors.white,
|
||||
collapsedIconColor: isExpanded ? Colors.black : Colors.white,
|
||||
iconColor: isExpanded ? Colors.black : Colors.white,
|
||||
initiallyExpanded: isExpanded,
|
||||
onExpansionChanged: (expanded) {
|
||||
setState(() {
|
||||
if (expanded) {
|
||||
expandedIndex = index;
|
||||
// Scroll to make the expanded tile visible
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
RenderBox box = context.findRenderObject() as RenderBox;
|
||||
double yPos = box.localToGlobal(Offset.zero).dy;
|
||||
_scrollController.animateTo(
|
||||
_scrollController.offset +
|
||||
yPos -
|
||||
100, // adjust 100 if needed
|
||||
duration: const Duration(milliseconds: 300),
|
||||
curve: Curves.easeInOut,
|
||||
);
|
||||
});
|
||||
} else {
|
||||
expandedIndex = null;
|
||||
}
|
||||
});
|
||||
},
|
||||
title: Text(
|
||||
tabs[index].title,
|
||||
style: GoogleFonts.inter(
|
||||
color: Colors.white,
|
||||
color: isExpanded ? Colors.black : Colors.white,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.all(12),
|
||||
// padding: const EdgeInsets.all(12),
|
||||
child: tabs[index].widget,
|
||||
),
|
||||
],
|
||||
@ -150,7 +186,9 @@ class TabEnquiryListState extends ConsumerState<TabEnquiryList> {
|
||||
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
context.go(AppRoutes.dashboard);
|
||||
// context.go(AppRoutes.dashboard);
|
||||
ref.read(enquiryIdProvider.notifier).state = null;
|
||||
context.go(AppRoutes.enquiryLst);
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
@ -213,424 +251,3 @@ class TabItem {
|
||||
final Widget widget;
|
||||
TabItem(this.title, this.widget);
|
||||
}
|
||||
|
||||
// class TabEnquiryListState extends ConsumerState<TabEnquiryList> {
|
||||
// int selectedIndex = 0; // 0 = Enquiry, 1 = Quotation, 2 = Policy
|
||||
//
|
||||
// // final List<String> tabs = ["Enquiry", "Quotation", "Policy"];
|
||||
// // final List<Widget> tabWidgets = [EnquiryTab(), QuotationTab(), PolicyTab()];
|
||||
// // late List<Widget> tabWidgets;
|
||||
//
|
||||
// late List<Map<String, dynamic>> tabs;
|
||||
//
|
||||
// Map<String, dynamic>? enquiryData;
|
||||
// bool isLoading = true;
|
||||
// late ApiService apiService;
|
||||
//
|
||||
// @override
|
||||
// void initState() {
|
||||
// super.initState();
|
||||
// apiService = ApiService();
|
||||
// _loadData();
|
||||
// }
|
||||
//
|
||||
// Future<void> _loadData() async {
|
||||
// final id = ref.read(enquiryIdProvider);
|
||||
// if (id != null && id.isNotEmpty) {
|
||||
// setState(() => isLoading = true);
|
||||
// final response = await apiService.findEnqQuotePolicyView(id);
|
||||
// setState(() {
|
||||
// enquiryData = response["data"];
|
||||
// isLoading = false;
|
||||
// tabs = [
|
||||
// TabItem("Enquiry", EnquiryTab(data: enquiryData?["enquiry"])),
|
||||
// TabItem("Quotation", QuotationTab(id: id)),
|
||||
// TabItem("Policy", PolicyTab()),
|
||||
// ];
|
||||
// });
|
||||
// } else {
|
||||
// setState(() {
|
||||
// isLoading = false;
|
||||
// tabs = [
|
||||
// TabItem("Enquiry", EnquiryTab()),
|
||||
// TabItem("Quotation", QuotationTab(id: "")),
|
||||
// TabItem("Policy", PolicyTab()),
|
||||
// ];
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // Future<void> _fetchData() async {
|
||||
// // final id = ref.read(enquiryIdProvider);
|
||||
// // if (id != null && id.isNotEmpty) {
|
||||
// // setState(() {
|
||||
// // isLoading = true;
|
||||
// // });
|
||||
// //
|
||||
// // final response = await apiService.findEnqQuotePolicyView(id);
|
||||
// //
|
||||
// // setState(() {
|
||||
// // enquiryData = response["data"];
|
||||
// // tabs = [
|
||||
// // TabItem("Enquiry", EnquiryTab(data: enquiryData?["enquiry"])),
|
||||
// // TabItem("Quotation", QuotationTab(id: id)),
|
||||
// // TabItem("Policy", PolicyTab()),
|
||||
// // ];
|
||||
// // isLoading = false;
|
||||
// // });
|
||||
// // } else {
|
||||
// // setState(() {
|
||||
// // tabs = [
|
||||
// // TabItem("Enquiry", EnquiryTab()),
|
||||
// // TabItem("Quotation", QuotationTab(id: "")),
|
||||
// // TabItem("Policy", PolicyTab()),
|
||||
// // ];
|
||||
// // isLoading = false;
|
||||
// // });
|
||||
// // }
|
||||
// // }
|
||||
//
|
||||
// // Future<void> _fetchData() async {
|
||||
// // final id = ref.read(enquiryIdProvider);
|
||||
// // if (id != null && id.isNotEmpty) {
|
||||
// // final response = await apiService.findEnqQuotePolicyView(id);
|
||||
// // setState(() {
|
||||
// // enquiryData = response["data"];
|
||||
// // isLoading = false;
|
||||
// // });
|
||||
// // }
|
||||
// // }
|
||||
//
|
||||
// // @override
|
||||
// // Widget build(BuildContext context) {
|
||||
// // final bool isMobile = MediaQuery.of(context).size.width < 600;
|
||||
// // final id = ref.watch(enquiryIdProvider); // listen to provider
|
||||
// //
|
||||
// // print('ENQID: $id');
|
||||
// // // final tabs = [
|
||||
// // // TabItem("Enquiry", EnquiryTab(id: id ?? "")),
|
||||
// // // TabItem("Quotation", QuotationTab(id: id ?? "")),
|
||||
// // // TabItem("Policy", PolicyTab()),
|
||||
// // // ];
|
||||
// // final tabs;
|
||||
// // if (id != null) {
|
||||
// // print('HASENQID: $id');
|
||||
// // setState(() {
|
||||
// // isLoading = true;
|
||||
// // });
|
||||
// //
|
||||
// // _fetchData();
|
||||
// //
|
||||
// // setState(() {
|
||||
// // isLoading = false;
|
||||
// // });
|
||||
// //
|
||||
// // tabs = [
|
||||
// // TabItem("Enquiry", EnquiryTab(data: enquiryData?["enquiry"])),
|
||||
// //
|
||||
// // // TabItem("Quotation", QuotationTab(data: enquiryData?["quotations"])),
|
||||
// // // TabItem("Policy", PolicyTab(data: enquiryData?["policies"])),
|
||||
// // TabItem("Quotation", QuotationTab(id: id ?? "")),
|
||||
// // TabItem("Policy", PolicyTab()),
|
||||
// // ];
|
||||
// // } else {
|
||||
// // setState(() {
|
||||
// // isLoading = false;
|
||||
// // });
|
||||
// //
|
||||
// // print('HASENQIDNot');
|
||||
// // tabs = [
|
||||
// // TabItem("Enquiry", EnquiryTab()),
|
||||
// //
|
||||
// // // TabItem("Quotation", QuotationTab(data: enquiryData?["quotations"])),
|
||||
// // // TabItem("Policy", PolicyTab(data: enquiryData?["policies"])),
|
||||
// // TabItem("Quotation", QuotationTab(id: id ?? "")),
|
||||
// // TabItem("Policy", PolicyTab()),
|
||||
// // ];
|
||||
// // }
|
||||
// //
|
||||
// // return MainLayout(
|
||||
// // title: "Enquiry",
|
||||
// // body: SafeArea(
|
||||
// // child: isLoading
|
||||
// // ? const Center(
|
||||
// // child: CircularProgressIndicator(), // 👈 loader inside SafeArea
|
||||
// // )
|
||||
// // : isMobile
|
||||
// // ? ListView.builder(
|
||||
// // itemCount: tabs.length,
|
||||
// // padding: const EdgeInsets.all(16),
|
||||
// // itemBuilder: (context, index) {
|
||||
// // return Card(
|
||||
// // shape: RoundedRectangleBorder(
|
||||
// // borderRadius: BorderRadius.circular(8),
|
||||
// // ),
|
||||
// // margin: const EdgeInsets.only(bottom: 12),
|
||||
// // color: const Color(0xFF425B5B), // Header background
|
||||
// // child: Theme(
|
||||
// // data: Theme.of(context).copyWith(
|
||||
// // dividerColor:
|
||||
// // Colors.transparent, // remove default divider
|
||||
// // ),
|
||||
// // child: ExpansionTile(
|
||||
// // collapsedIconColor: Colors.white,
|
||||
// // iconColor: Colors.white,
|
||||
// // title: Text(
|
||||
// // // tabs[index]["title"],
|
||||
// // tabs[index].title,
|
||||
// // style: GoogleFonts.inter(
|
||||
// // color: Colors.white,
|
||||
// // fontWeight: FontWeight.w600,
|
||||
// // ),
|
||||
// // ),
|
||||
// // children: [
|
||||
// // Container(
|
||||
// // width: double.infinity,
|
||||
// // decoration: BoxDecoration(
|
||||
// // color: const Color(0xFFEAF6F4),
|
||||
// // borderRadius: BorderRadius.circular(8),
|
||||
// // border: Border.all(
|
||||
// // color: const Color(0xFFB0CFCB),
|
||||
// // width: 1,
|
||||
// // ),
|
||||
// // ),
|
||||
// // padding: const EdgeInsets.all(12),
|
||||
// // child: SizedBox(
|
||||
// // height: MediaQuery.of(context).size.height,
|
||||
// // child: tabs[selectedIndex].widget,
|
||||
// // // child: tabs[index]["widget"] as Widget,
|
||||
// // ), // ✅ directly, no SizedBox height
|
||||
// // ),
|
||||
// // // Container(
|
||||
// // // width: double.infinity,
|
||||
// // //
|
||||
// // // decoration: BoxDecoration(
|
||||
// // // color: const Color(0xFFEAF6F4), // light teal bg like screenshot
|
||||
// // // borderRadius: BorderRadius.circular(8),
|
||||
// // // border: Border.all(
|
||||
// // // color: const Color(0xFFB0CFCB), // soft border color
|
||||
// // // width: 1,
|
||||
// // // ),
|
||||
// // // ),
|
||||
// // // padding: const EdgeInsets.all(12),
|
||||
// // // child: SizedBox(
|
||||
// // // height: MediaQuery.of(context).size.height,
|
||||
// // // // mainAxisSize: MainAxisSize.min, // 👈 prevents collapse
|
||||
// // // // children: [
|
||||
// // // child: tabs[index]["widget"] as Widget, // ✅ actual tab widget
|
||||
// // // // ],
|
||||
// // // ),
|
||||
// // // ),
|
||||
// // ],
|
||||
// // ),
|
||||
// // ),
|
||||
// // );
|
||||
// // },
|
||||
// // )
|
||||
// // : Column(
|
||||
// // crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// // children: [
|
||||
// // // Back Button + Title
|
||||
// // Padding(
|
||||
// // padding: const EdgeInsets.symmetric(
|
||||
// // horizontal: 6,
|
||||
// // vertical: 2,
|
||||
// // ),
|
||||
// // child: GestureDetector(
|
||||
// // onTap: () {
|
||||
// // context.go(AppRoutes.dashboard);
|
||||
// // },
|
||||
// // child: Row(
|
||||
// // children: [
|
||||
// // const Icon(
|
||||
// // Icons.arrow_left_sharp,
|
||||
// // size: 35,
|
||||
// // color: Color(0xFF425B5B),
|
||||
// // ),
|
||||
// // const SizedBox(width: 8),
|
||||
// // Text(
|
||||
// // "Enquiry",
|
||||
// // style: GoogleFonts.inter(
|
||||
// // fontSize: 18,
|
||||
// // fontWeight: FontWeight.w700,
|
||||
// // color: Colors.black87,
|
||||
// // ),
|
||||
// // ),
|
||||
// // ],
|
||||
// // ),
|
||||
// // ),
|
||||
// // ),
|
||||
// //
|
||||
// // const SizedBox(height: 10),
|
||||
// //
|
||||
// // // Tabs
|
||||
// // Padding(
|
||||
// // padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
// // child: Row(
|
||||
// // children: List.generate(tabs.length, (index) {
|
||||
// // final bool isSelected = selectedIndex == index;
|
||||
// // return Padding(
|
||||
// // padding: const EdgeInsets.only(right: 12),
|
||||
// // child: ElevatedButton(
|
||||
// // style: ElevatedButton.styleFrom(
|
||||
// // elevation: 2,
|
||||
// // backgroundColor: isSelected
|
||||
// // ? const Color(0xFF425B5B)
|
||||
// // : const Color(0xFFEDFFFC),
|
||||
// // foregroundColor: isSelected
|
||||
// // ? Colors.white
|
||||
// // : Colors.black87,
|
||||
// // shape: RoundedRectangleBorder(
|
||||
// // borderRadius: BorderRadius.circular(6),
|
||||
// // ),
|
||||
// // padding: const EdgeInsets.symmetric(
|
||||
// // horizontal: 24,
|
||||
// // vertical: 12,
|
||||
// // ),
|
||||
// // ),
|
||||
// // onPressed: () {
|
||||
// // setState(() {
|
||||
// // selectedIndex = index;
|
||||
// // });
|
||||
// // },
|
||||
// // child: Text(
|
||||
// // // tabs[index]["title"],
|
||||
// // tabs[index].title,
|
||||
// // style: GoogleFonts.inter(
|
||||
// // fontWeight: isSelected
|
||||
// // ? FontWeight.w600
|
||||
// // : FontWeight.w500,
|
||||
// // fontSize: 15,
|
||||
// // ),
|
||||
// // ),
|
||||
// // ),
|
||||
// // );
|
||||
// // }),
|
||||
// // ),
|
||||
// // ),
|
||||
// //
|
||||
// // const SizedBox(height: 16),
|
||||
// //
|
||||
// // // Tab Content
|
||||
// // Expanded(
|
||||
// // child: Padding(
|
||||
// // padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
// // child: tabs[selectedIndex].widget,
|
||||
// // // child: tabs[selectedIndex]["widget"],
|
||||
// // ),
|
||||
// // ),
|
||||
// // ],
|
||||
// // ),
|
||||
// // ),
|
||||
// // );
|
||||
// // }
|
||||
//
|
||||
// // Widget build(BuildContext context) {
|
||||
// // return MainLayout(
|
||||
// // title: "Enquiry",
|
||||
// // body: SafeArea(
|
||||
// // child: Column(
|
||||
// // crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// // mainAxisAlignment: MainAxisAlignment.start,
|
||||
// // children: [
|
||||
// // // Header
|
||||
// // Padding(
|
||||
// // padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
|
||||
// // child: GestureDetector(
|
||||
// // onTap: () {
|
||||
// // context.go(AppRoutes.dashboard);
|
||||
// // },
|
||||
// // child: Row(
|
||||
// // children: [
|
||||
// // const Icon(
|
||||
// // Icons.arrow_left_sharp,
|
||||
// // size: 35,
|
||||
// // color: Color(0xFF425B5B),
|
||||
// // ),
|
||||
// // const SizedBox(width: 8),
|
||||
// // Text(
|
||||
// // "Enquiry",
|
||||
// // style: GoogleFonts.inter(
|
||||
// // fontSize: 18,
|
||||
// // fontWeight: FontWeight.w700,
|
||||
// // color: Colors.black87,
|
||||
// // ),
|
||||
// // ),
|
||||
// // ],
|
||||
// // ),
|
||||
// // ),
|
||||
// // ),
|
||||
// //
|
||||
// // const SizedBox(height: 10),
|
||||
// //
|
||||
// // // Tab Buttons
|
||||
// // Padding(
|
||||
// // padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
// // child: Row(
|
||||
// // children: List.generate(tabs.length, (index) {
|
||||
// // final bool isSelected = selectedIndex == index;
|
||||
// // return Padding(
|
||||
// // padding: const EdgeInsets.only(right: 12),
|
||||
// // child: ElevatedButton(
|
||||
// // style: ElevatedButton.styleFrom(
|
||||
// // elevation: 2,
|
||||
// // backgroundColor: isSelected
|
||||
// // ? const Color(0xFF425B5B) // selected dark green
|
||||
// // : const Color(0xFFEDFFFC), // light teal
|
||||
// // foregroundColor: isSelected
|
||||
// // ? Colors.white
|
||||
// // : Colors.black87,
|
||||
// // side: BorderSide(
|
||||
// // color: isSelected
|
||||
// // ? const Color(0xFF425B5B)
|
||||
// // : const Color(0xFFEDFFFC),
|
||||
// // ),
|
||||
// // shape: RoundedRectangleBorder(
|
||||
// // borderRadius: BorderRadius.circular(6),
|
||||
// // ),
|
||||
// // padding: const EdgeInsets.symmetric(
|
||||
// // horizontal: 24,
|
||||
// // vertical: 12,
|
||||
// // ),
|
||||
// // ),
|
||||
// // onPressed: () {
|
||||
// // setState(() {
|
||||
// // selectedIndex = index;
|
||||
// // });
|
||||
// // },
|
||||
// // child: Text(
|
||||
// // tabs[index],
|
||||
// // style: GoogleFonts.inter(
|
||||
// // fontWeight: isSelected
|
||||
// // ? FontWeight.w600
|
||||
// // : FontWeight.w500,
|
||||
// // fontSize: 15,
|
||||
// // ),
|
||||
// // ),
|
||||
// // ),
|
||||
// // );
|
||||
// // }),
|
||||
// // ),
|
||||
// // ),
|
||||
// //
|
||||
// // const SizedBox(height: 16),
|
||||
// //
|
||||
// // // Tab content
|
||||
// // Expanded(
|
||||
// // child: Padding(
|
||||
// // padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
// // child: tabWidgets[selectedIndex],
|
||||
// // ),
|
||||
// // ),
|
||||
// // ],
|
||||
// // ),
|
||||
// // ),
|
||||
// // );
|
||||
// // }
|
||||
// }
|
||||
|
||||
// class TabItem {
|
||||
// final String title;
|
||||
// final Widget widget;
|
||||
// TabItem(this.title, this.widget);
|
||||
// }
|
||||
|
||||
@ -249,6 +249,8 @@ class EnquiryListState extends ConsumerState<EnquiryList> {
|
||||
SizedBox(width: 10),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
ref.read(enquiryIdProvider.notifier).state = null;
|
||||
context.go(AppRoutes.tabEnquiry);
|
||||
// print('Export');
|
||||
},
|
||||
child: Container(
|
||||
@ -264,21 +266,33 @@ class EnquiryListState extends ConsumerState<EnquiryList> {
|
||||
|
||||
if (!ResponsiveLayout.isMobile(context)) ...[
|
||||
SizedBox(width: 10),
|
||||
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
// context.go(AppRoutes.agent / create);
|
||||
context.go('/tabEnquiry/tab');
|
||||
},
|
||||
child: Text(
|
||||
'Create New Enquiry',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 14,
|
||||
),
|
||||
Text(
|
||||
'Create New Enquiry',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 14,
|
||||
),
|
||||
),
|
||||
// GestureDetector(
|
||||
// onTap: () {
|
||||
// ref
|
||||
// .read(
|
||||
// enquiryIdProvider.notifier,
|
||||
// )
|
||||
// .state =
|
||||
// null;
|
||||
// context.go(AppRoutes.tabEnquiry);
|
||||
// },
|
||||
// child: Text(
|
||||
// 'Create New Enquiry',
|
||||
// style: TextStyle(
|
||||
// color: Colors.white,
|
||||
// fontWeight: FontWeight.w600,
|
||||
// fontSize: 14,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
],
|
||||
],
|
||||
),
|
||||
@ -288,51 +302,53 @@ class EnquiryListState extends ConsumerState<EnquiryList> {
|
||||
),
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Color(0xFFEDF6F5),
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 12,
|
||||
horizontal: 16,
|
||||
),
|
||||
child: const Row(
|
||||
children: [
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Text('S.No.', style: _headerStyle),
|
||||
),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text(
|
||||
'Received Date & Time',
|
||||
style: _headerStyle,
|
||||
|
||||
if (!ResponsiveLayout.isMobile(context))
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Color(0xFFEDF6F5),
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 12,
|
||||
horizontal: 16,
|
||||
),
|
||||
child: const Row(
|
||||
children: [
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Text('S.No.', style: _headerStyle),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Text('Reg.No.', style: _headerStyle),
|
||||
),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text('Company', style: _headerStyle),
|
||||
),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text('Status', style: _headerStyle),
|
||||
),
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Text('Remarks', style: _headerStyle),
|
||||
),
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Text('Action', style: _headerStyle),
|
||||
),
|
||||
],
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text(
|
||||
'Received Date & Time',
|
||||
style: _headerStyle,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Text('Reg.No.', style: _headerStyle),
|
||||
),
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: Text('Company', style: _headerStyle),
|
||||
),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text('Status', style: _headerStyle),
|
||||
),
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Text('Remarks', style: _headerStyle),
|
||||
),
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Text('Action', style: _headerStyle),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(child: _buildDataTable(context)),
|
||||
],
|
||||
),
|
||||
@ -430,7 +446,7 @@ class EnquiryListState extends ConsumerState<EnquiryList> {
|
||||
child: Text(item['reg_no'] ?? '-', style: _dataBold),
|
||||
),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
flex: 3,
|
||||
child: Text(
|
||||
item['insurer_name'] ?? '-',
|
||||
style: _dataBold,
|
||||
|
||||
@ -0,0 +1,701 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:nhance_partner/presentation/providers/userRoleProvider.dart';
|
||||
import '../../../../core/routing/routes.dart';
|
||||
import '../../../../core/services/api_service.dart';
|
||||
import '../../../../data/utils/Pagination.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 '../../../widgets/custom_action_popup.dart';
|
||||
|
||||
// class claimList extends ConsumerStatefulWidget {
|
||||
// const claimList({super.key});
|
||||
// @override
|
||||
// ConsumerState<claimList> createState() => claimListState();
|
||||
// }
|
||||
//
|
||||
// class claimListState extends ConsumerState<claimList> {
|
||||
// late ApiService apiService;
|
||||
// List<Map<String, dynamic>> getClaimsHistoryList = [];
|
||||
// List<String> stepKeys = [];
|
||||
// late Map<String, dynamic> stepMap;
|
||||
// int _index = 4;
|
||||
// bool isLoading = false;
|
||||
//
|
||||
// @override
|
||||
// void initState() {
|
||||
// super.initState();
|
||||
//
|
||||
// apiService = ApiService();
|
||||
// // print(widget.postToken);
|
||||
// print("CLAIMHISTORY");
|
||||
// print(widget.claimAmount);
|
||||
// print(widget.claimNo);
|
||||
// print(widget.clientPolicyNo);
|
||||
// print(widget.empCode);
|
||||
// print(widget.policyType);
|
||||
// print(widget.ticket_id);
|
||||
// getClaimsHistoryDetails();
|
||||
// }
|
||||
//
|
||||
// @override
|
||||
// void dispose() {
|
||||
// super.dispose();
|
||||
// }
|
||||
//
|
||||
// Future<void> getClaimsHistoryDetails() async {
|
||||
// setState(() {
|
||||
// isLoading = true;
|
||||
// });
|
||||
// try {
|
||||
// print('10');
|
||||
// // final ticketID = widget.ticket_id;
|
||||
// // if (ticketID != '' || ticketID != null) {
|
||||
// // return;
|
||||
// // }
|
||||
// final response = await apiService.getClaimsHistoryToApi(widget.ticket_id);
|
||||
// if (response['status'] == 'success') {
|
||||
// setState(() {
|
||||
// isLoading = false;
|
||||
// print('Claims History List1');
|
||||
// // final List<dynamic> ticketDataList = response['data']['ticket_data'];
|
||||
// // final Map<String, dynamic> ticketDataMap =
|
||||
// // response['data']['ticket_data'];
|
||||
// // print('Claims History List12');
|
||||
// // print('Claims History List1- $ticketDataMap');
|
||||
//
|
||||
// // getClaimsHistoryList = ticketDataList
|
||||
// // .map((item) => Map<String, dynamic>.from(item))
|
||||
// // .toList();
|
||||
//
|
||||
// // getClaimsHistoryList = ticketDataMap.entries.map((entry) {
|
||||
// // return {
|
||||
// // 'status': entry.key,
|
||||
// // ...Map<String, dynamic>.from(entry.value),
|
||||
// // };
|
||||
// // }).toList();
|
||||
// //
|
||||
// // getClaimsHistoryList = ticketDataMap.entries.map((entry) {
|
||||
// // return {
|
||||
// // 'status': entry.key,
|
||||
// // ...Map<String, dynamic>.from(entry.value),
|
||||
// // };
|
||||
// // }).toList();
|
||||
//
|
||||
// // if (getClaimsHistoryList.isNotEmpty) {
|
||||
// // stepMap = getClaimsHistoryList[0];
|
||||
// // stepKeys = stepMap.keys.toList();
|
||||
// // }
|
||||
//
|
||||
// print('Claims History List: $getClaimsHistoryList');
|
||||
//
|
||||
// getClaimsHistoryList = [
|
||||
// Map<String, dynamic>.from(response['data']['ticket_data']),
|
||||
// ];
|
||||
// stepMap = getClaimsHistoryList[0];
|
||||
// stepKeys = stepMap.keys.toList();
|
||||
//
|
||||
// // originalData = getCDPolicies;
|
||||
// // filteredData = List.from(originalData);
|
||||
// // print('filteredData');
|
||||
// // print(filteredData);
|
||||
// });
|
||||
// } else {
|
||||
// setState(() {
|
||||
// isLoading = false;
|
||||
// });
|
||||
//
|
||||
// // ToastHelper.showWarningToast(
|
||||
// // context, 'Request failed with status: ${response.statusCode}');
|
||||
// print('Request failed with status: ${response['code']}');
|
||||
// }
|
||||
// } catch (e) {
|
||||
// setState(() {
|
||||
// isLoading = false;
|
||||
// });
|
||||
// print('Exception occurred: $e');
|
||||
// } finally {
|
||||
// setState(() {
|
||||
// // _isLoading = false;
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @override
|
||||
// Widget build(BuildContext context) {
|
||||
// // if (getClaimsHistoryList.isEmpty) {
|
||||
// // return SizedBox(
|
||||
// // height: 50,
|
||||
// // child: Center(child: Text('No available Claims')),
|
||||
// // );
|
||||
// // }
|
||||
// final keyValueWidgets = [
|
||||
// _buildKeyValue(
|
||||
// 'Name',
|
||||
// '${widget.empName ?? ''} (${widget.empCode ?? ''})',
|
||||
// ),
|
||||
// SizedBox(
|
||||
// width: Responsive.isDesktop(context) ? 16 : 0,
|
||||
// height: Responsive.isDesktop(context) ? 0 : 8,
|
||||
// ),
|
||||
// _buildKeyValue(
|
||||
// 'Policy Name',
|
||||
// '${widget.policyType ?? ''} - ${widget.clientPolicyNo ?? ''}',
|
||||
// ),
|
||||
// ];
|
||||
//
|
||||
// final keyValueWidgetRow = [
|
||||
// _buildKeyValue(
|
||||
// 'Claim Amount',
|
||||
// widget.claimAmount == null || widget.claimAmount!.trim().isEmpty
|
||||
// ? 'N/A'
|
||||
// : '₹${widget.claimAmount}',
|
||||
// ),
|
||||
// SizedBox(
|
||||
// width: Responsive.isDesktop(context) ? 16 : 0,
|
||||
// height: Responsive.isDesktop(context) ? 0 : 8,
|
||||
// ),
|
||||
// _buildKeyValue(
|
||||
// 'Claim Number',
|
||||
// widget.claimNo == null || widget.claimNo!.trim().isEmpty
|
||||
// ? 'N/A'
|
||||
// : widget.claimNo!,
|
||||
// ),
|
||||
// ];
|
||||
//
|
||||
// return Container(
|
||||
// constraints: BoxConstraints(maxWidth: 800, maxHeight: 800),
|
||||
// padding: EdgeInsets.all(20),
|
||||
// decoration: BoxDecoration(
|
||||
// color: Colors.white,
|
||||
// borderRadius: BorderRadius.circular(12),
|
||||
// ),
|
||||
// child: SingleChildScrollView(
|
||||
// child: Column(
|
||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// children: [
|
||||
// Row(
|
||||
// children: [
|
||||
// Expanded(
|
||||
// child: Align(
|
||||
// alignment: Alignment.centerLeft,
|
||||
// child: Text(
|
||||
// 'Claim History',
|
||||
// style: GoogleFonts.poppins(
|
||||
// fontSize: Responsive.isDesktop(context) ? 20 : 16,
|
||||
// fontWeight: FontWeight.w500,
|
||||
// color: Color(0xFF101010),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// MouseRegion(
|
||||
// cursor: SystemMouseCursors.click, // Show pointer cursor
|
||||
// child: GestureDetector(
|
||||
// onTap: () => Navigator.of(context).pop(),
|
||||
// child: Container(
|
||||
// height: 30,
|
||||
// width: 30,
|
||||
// decoration: BoxDecoration(
|
||||
// color: Colors.white,
|
||||
// border: Border.all(color: Color(0xFFBCBCBC)),
|
||||
// borderRadius: BorderRadius.circular(6),
|
||||
// ),
|
||||
// child: Icon(
|
||||
// Icons.close,
|
||||
// size: 25,
|
||||
// color: Color(0xFFBCBCBC),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// SizedBox(height: Responsive.isDesktop(context) ? 10 : 5),
|
||||
// Container(
|
||||
// margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 20),
|
||||
// decoration: BoxDecoration(
|
||||
// color: Color(0xFFFFFFFF), // White background
|
||||
// borderRadius: BorderRadius.circular(12),
|
||||
// boxShadow: [
|
||||
// BoxShadow(
|
||||
// color: Color(0xFFEBEBEB), // Shadow color
|
||||
// blurRadius: 14, // How soft the shadow is
|
||||
// spreadRadius: 2, // How much it spreads
|
||||
// offset: Offset(0, 1), // X and Y offset
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// padding: const EdgeInsets.all(16),
|
||||
// child: Center(
|
||||
// child: Column(
|
||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// children: [
|
||||
// Responsive.isDesktop(context)
|
||||
// ? Row(
|
||||
// children: keyValueWidgets
|
||||
// .map((w) => Expanded(child: w))
|
||||
// .toList(),
|
||||
// )
|
||||
// : Container(
|
||||
// width: MediaQuery.of(context).size.width,
|
||||
// child: Column(
|
||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// children: keyValueWidgets,
|
||||
// ),
|
||||
// ),
|
||||
// // Row(
|
||||
// // children: [
|
||||
// // Expanded(
|
||||
// // child: _buildKeyValue('Name',
|
||||
// // '${widget.empName ?? ''} (${widget.empCode ?? ''})'),
|
||||
// // ),
|
||||
// // SizedBox(width: 16),
|
||||
// // Expanded(
|
||||
// // child: _buildKeyValue('Policy Name',
|
||||
// // '${widget.policyType ?? ''} - ${widget.clientPolicyNo ?? ''}')),
|
||||
// // ],
|
||||
// // ),
|
||||
// SizedBox(height: Responsive.isDesktop(context) ? 16 : 8),
|
||||
// Responsive.isDesktop(context)
|
||||
// ? Row(
|
||||
// children: keyValueWidgetRow
|
||||
// .map((w) => Expanded(child: w))
|
||||
// .toList(),
|
||||
// )
|
||||
// : Container(
|
||||
// width: MediaQuery.of(context).size.width,
|
||||
// child: Column(
|
||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// children: keyValueWidgetRow,
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// SizedBox(height: 10),
|
||||
//
|
||||
// // Container(
|
||||
// // padding: const EdgeInsets.all(16),
|
||||
// // child: Stepper(
|
||||
// // currentStep: _index,
|
||||
// // onStepCancel: () {
|
||||
// // if (_index > 0) {
|
||||
// // setState(() {
|
||||
// // _index -= 1;
|
||||
// // });
|
||||
// // }
|
||||
// // },
|
||||
// // onStepContinue: () {
|
||||
// // if (_index < 4) {
|
||||
// // setState(() {
|
||||
// // _index += 1;
|
||||
// // });
|
||||
// // }
|
||||
// // },
|
||||
// // onStepTapped: (int index) {
|
||||
// // setState(() {
|
||||
// // _index = index;
|
||||
// // });
|
||||
// // },
|
||||
// // steps: <Step>[
|
||||
// // Step(
|
||||
// // title: Text('Step 1: PAYMENT INITIATED'),
|
||||
// // content: Text('Pay Initiate Date: 05-05-2025'),
|
||||
// // isActive: true,
|
||||
// // state: StepState.complete,
|
||||
// // ),
|
||||
// // Step(
|
||||
// // title: Text('Step 2: INFORMATION REQUIRED'),
|
||||
// // content: Text('Raised Date: 05-05-2025'),
|
||||
// // isActive: true,
|
||||
// // state: StepState.complete,
|
||||
// // ),
|
||||
// // Step(
|
||||
// // title: Text('Step 3: CLAIM NO. UPDATION'),
|
||||
// // content: Column(
|
||||
// // crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// // children: [
|
||||
// // Text('Claim Number: 4315440'),
|
||||
// // Text('Registration Date: 05-05-2025'),
|
||||
// // ],
|
||||
// // ),
|
||||
// // isActive: true,
|
||||
// // state: StepState.complete,
|
||||
// // ),
|
||||
// // Step(
|
||||
// // title: Text('Step 4: QUERY DOCUMENT REQUIRED'),
|
||||
// // content: Text('Query Received Date: 05-05-2025'),
|
||||
// // isActive: true,
|
||||
// // state: StepState.complete,
|
||||
// // ),
|
||||
// // Step(
|
||||
// // title: Text('Step 5: APPROVED'),
|
||||
// // content: Column(
|
||||
// // crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// // children: [
|
||||
// // Text('Approved Amount: 4315440'),
|
||||
// // Text('Approved Date: 05-05-2025'),
|
||||
// // Text('Approved Letter: Lorem ipsum...'),
|
||||
// // Text('Description: Lorem ipsum...'),
|
||||
// // ],
|
||||
// // ),
|
||||
// // isActive: true,
|
||||
// // state: StepState.complete,
|
||||
// // ),
|
||||
// // ],
|
||||
// // ),
|
||||
// // )
|
||||
// // Column(
|
||||
// // crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// // children: List.generate(5, (index) {
|
||||
// // return _buildStep(
|
||||
// // stepNumber: index + 1,
|
||||
// // title: _getStepTitle(index),
|
||||
// // content: _getStepContent(index),
|
||||
// // isLast: index == 4,
|
||||
// // );
|
||||
// // }),
|
||||
// // )
|
||||
// isLoading
|
||||
// ? Container(
|
||||
// // color: Color(0x98FFFCE5), // Semi-transparent background
|
||||
// child: Center(
|
||||
// child: // Your GIF loader widget
|
||||
// Image.asset(
|
||||
// height: 60,
|
||||
// width: 60,
|
||||
// 'assets/nhance-loader.gif',
|
||||
// ), // Adjust path to your GIF loader
|
||||
// ),
|
||||
// )
|
||||
// : Container(
|
||||
// child: getClaimsHistoryList.isNotEmpty
|
||||
// ? Column(
|
||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// children: List.generate(stepKeys.length, (index) {
|
||||
// String stepTitleKey = stepKeys[index];
|
||||
// Map<String, dynamic> stepData =
|
||||
// stepMap[stepTitleKey];
|
||||
//
|
||||
// print('stepTitleKey');
|
||||
// print(stepTitleKey);
|
||||
// print('stepData');
|
||||
// print(stepData);
|
||||
//
|
||||
// Widget content = _getStepContentFromApi(stepData);
|
||||
//
|
||||
// return _buildStep(
|
||||
// stepNumber: index + 1,
|
||||
// title: _getStepTitleFromApi(
|
||||
// stepTitleKey,
|
||||
// stepData,
|
||||
// ),
|
||||
// content: content,
|
||||
// // content: _getStepContentFromApi(stepData),
|
||||
// isLast: index == stepKeys.length - 1,
|
||||
// );
|
||||
// }),
|
||||
// )
|
||||
// : Container(
|
||||
// height: MediaQuery.of(context).size.height * 0.4,
|
||||
// // color: Colors.red,
|
||||
// child: Center(
|
||||
// child: Column(
|
||||
// children: [
|
||||
// Image.asset(
|
||||
// 'assets/searchData.jpg', // Replace 'default_image.png' with your default image asset path
|
||||
// width: 200,
|
||||
// height: 200,
|
||||
// fit: BoxFit.cover,
|
||||
// ),
|
||||
// Text(
|
||||
// 'No Claim History',
|
||||
// style: TextStyle(
|
||||
// fontWeight: FontWeight.w500,
|
||||
// fontSize: 15,
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// Widget _buildStep({
|
||||
// required int stepNumber,
|
||||
// // required String title,
|
||||
// required Widget title,
|
||||
// required Widget content,
|
||||
// bool isLast = false,
|
||||
// }) {
|
||||
// print(title);
|
||||
// final noContent;
|
||||
// if ((content as Column).children.isEmpty) {
|
||||
// noContent = 0;
|
||||
// } else {
|
||||
// noContent = 1;
|
||||
// }
|
||||
//
|
||||
// return Row(
|
||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// children: [
|
||||
// // Left Column with circle + line
|
||||
// Column(
|
||||
// children: [
|
||||
// // Add top spacing before circle
|
||||
// SizedBox(height: stepNumber == 1 ? 0 : 4),
|
||||
//
|
||||
// // Step number circle
|
||||
// Container(
|
||||
// height: 28,
|
||||
// width: 28,
|
||||
// decoration: BoxDecoration(
|
||||
// color: Color(0xFF00A5A8),
|
||||
// shape: BoxShape.circle,
|
||||
// ),
|
||||
// alignment: Alignment.center,
|
||||
// child: Text(
|
||||
// '$stepNumber',
|
||||
// style: TextStyle(
|
||||
// color: Colors.white,
|
||||
// fontSize: Responsive.isDesktop(context) ? 13 : 12,
|
||||
// fontWeight: FontWeight.w600,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
//
|
||||
// // Dotted line below circle (except for last step)
|
||||
// if (!isLast)
|
||||
// Container(
|
||||
// height: noContent == 1 ? 50 : 20,
|
||||
// // increase to extend line
|
||||
// width: 2,
|
||||
// margin: EdgeInsets.only(top: 4, bottom: 4),
|
||||
// child: CustomPaint(painter: DottedLinePainter()),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
//
|
||||
// SizedBox(width: 12),
|
||||
//
|
||||
// // Right Side: Step title and content
|
||||
// Expanded(
|
||||
// child: Column(
|
||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// children: [
|
||||
// title,
|
||||
// if (noContent == 1) SizedBox(height: noContent == 0 ? 0 : 8),
|
||||
// if (noContent == 1)
|
||||
// Container(
|
||||
// width: double.infinity,
|
||||
// padding: EdgeInsets.all(12),
|
||||
// decoration: BoxDecoration(
|
||||
// color: Color(0xFFF7F7F7),
|
||||
// borderRadius: BorderRadius.circular(8),
|
||||
// border: Border.all(color: Color(0xFFE0E0E0)),
|
||||
// ),
|
||||
// child: content,
|
||||
// ),
|
||||
// if (noContent == 1) SizedBox(height: isLast ? 0 : 16),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// // String _getStepTitleFromApi(String status, Map<String, dynamic> data) {
|
||||
// // final modifiedBy = data['modified_by'] ?? '';
|
||||
// // final modifiedAt = data['modified_at'] ?? '';
|
||||
// // return '$status ($modifiedBy – $modifiedAt)';
|
||||
// // }
|
||||
//
|
||||
// Widget _getStepTitleFromApi(String status, Map<String, dynamic> data) {
|
||||
// final modifiedBy = data['modified_by'] ?? '';
|
||||
// final modifiedAt = data['modified_at'] ?? '';
|
||||
// final isDesktop = Responsive.isDesktop(context);
|
||||
//
|
||||
// return RichText(
|
||||
// text: TextSpan(
|
||||
// children: [
|
||||
// TextSpan(
|
||||
// text: status + (isDesktop ? ' ' : '\n'),
|
||||
// style: GoogleFonts.poppins(
|
||||
// fontSize: Responsive.isDesktop(context) ? 15 : 11,
|
||||
// fontWeight: FontWeight.w500,
|
||||
// color: Color(0xFF212120), // Status color
|
||||
// ),
|
||||
// ),
|
||||
// TextSpan(
|
||||
// text: ' ($modifiedBy – $modifiedAt)',
|
||||
// style: GoogleFonts.poppins(
|
||||
// fontSize: Responsive.isDesktop(context) ? 14 : 11,
|
||||
// fontWeight: FontWeight.w400,
|
||||
// color: Color(0xFF565656), // Subtitle color
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// Widget _getStepContentFromApi(Map<String, dynamic> data) {
|
||||
// List<Widget> rows = [];
|
||||
//
|
||||
// data.forEach((key, value) {
|
||||
// // Skip metadata fields
|
||||
// if (key == 'modified_by' || key == 'modified_at') return;
|
||||
//
|
||||
// String displayName = value['display_name'] ?? key;
|
||||
// String displayValue = value['display_value'] ?? 'N/A';
|
||||
//
|
||||
// rows.add(_buildHistoryListData(displayName, displayValue));
|
||||
// rows.add(SizedBox(height: 1));
|
||||
// });
|
||||
//
|
||||
// return Column(crossAxisAlignment: CrossAxisAlignment.start, children: rows);
|
||||
// }
|
||||
//
|
||||
// Widget _buildKeyValue(String title, String value) {
|
||||
// final displayValue = (value == null || value.trim().isEmpty)
|
||||
// ? 'N/A'
|
||||
// : value;
|
||||
// return Column(
|
||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// children: [
|
||||
// Text(
|
||||
// title,
|
||||
// style: GoogleFonts.poppins(
|
||||
// color: Color(0xFF747474),
|
||||
// fontWeight: FontWeight.w400,
|
||||
// fontSize: Responsive.isDesktop(context) ? 16 : 13,
|
||||
// ),
|
||||
// ),
|
||||
// SizedBox(height: 4),
|
||||
// Text(
|
||||
// displayValue,
|
||||
// style: GoogleFonts.poppins(
|
||||
// color: Color(0xFF000000),
|
||||
// fontWeight: FontWeight.w500,
|
||||
// fontSize: Responsive.isDesktop(context) ? 16 : 13,
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// Widget _buildHistoryListData(String title, String value) {
|
||||
// final displayValue = (value == null || value.trim().isEmpty)
|
||||
// ? 'N/A'
|
||||
// : value;
|
||||
//
|
||||
// final titleText = Text(
|
||||
// title,
|
||||
// style: GoogleFonts.poppins(
|
||||
// color: const Color(0xFF747474),
|
||||
// fontWeight: FontWeight.w400,
|
||||
// fontSize: Responsive.isDesktop(context) ? 14 : 12,
|
||||
// ),
|
||||
// );
|
||||
//
|
||||
// final valueText = Text(
|
||||
// displayValue,
|
||||
// style: GoogleFonts.poppins(
|
||||
// color: const Color(0xFF000000),
|
||||
// fontWeight: FontWeight.w400,
|
||||
// fontSize: Responsive.isDesktop(context) ? 14 : 12,
|
||||
// ),
|
||||
// textAlign: TextAlign.right,
|
||||
// );
|
||||
//
|
||||
// return Padding(
|
||||
// padding: const EdgeInsets.symmetric(vertical: 1), // optional spacing
|
||||
// child: Responsive.isDesktop(context)
|
||||
// ? Row(
|
||||
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
// crossAxisAlignment: CrossAxisAlignment.center,
|
||||
// children: [
|
||||
// Expanded(
|
||||
// child: Align(
|
||||
// alignment: Alignment.centerLeft,
|
||||
// child: titleText,
|
||||
// ),
|
||||
// ),
|
||||
// Expanded(
|
||||
// child: Align(
|
||||
// alignment: Alignment.centerRight,
|
||||
// child: valueText,
|
||||
// ),
|
||||
// ),
|
||||
//
|
||||
// // Title - Align to center left
|
||||
// // Expanded(
|
||||
// // child: Align(
|
||||
// // alignment: Alignment.centerLeft,
|
||||
// // child: Text(
|
||||
// // title,
|
||||
// // style: GoogleFonts.poppins(
|
||||
// // color: const Color(0xFF747474),
|
||||
// // fontWeight: FontWeight.w400,
|
||||
// // fontSize: 14,
|
||||
// // ),
|
||||
// // ),
|
||||
// // ),
|
||||
// // ),
|
||||
//
|
||||
// // Value - Align to center right
|
||||
// // Expanded(
|
||||
// // child: Align(
|
||||
// // alignment: Alignment.centerRight,
|
||||
// // child: Text(
|
||||
// // displayValue,
|
||||
// // style: GoogleFonts.poppins(
|
||||
// // color: const Color(0xFF000000),
|
||||
// // fontWeight: FontWeight.w400,
|
||||
// // fontSize: 14,
|
||||
// // ),
|
||||
// // ),
|
||||
// // ),
|
||||
// // ),
|
||||
// ],
|
||||
// )
|
||||
// : Column(
|
||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// children: [titleText, SizedBox(height: 4), valueText],
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// class DottedLinePainter extends CustomPainter {
|
||||
// @override
|
||||
// void paint(Canvas canvas, Size size) {
|
||||
// const dashHeight = 2.0;
|
||||
// const dashSpace = 3.0;
|
||||
// double startY = 0;
|
||||
// final paint = Paint()
|
||||
// ..color = Colors.grey.shade400
|
||||
// ..strokeWidth = 1;
|
||||
//
|
||||
// while (startY < size.height) {
|
||||
// canvas.drawLine(Offset(0, startY), Offset(0, startY + dashHeight), paint);
|
||||
// startY += dashHeight + dashSpace;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @override
|
||||
// bool shouldRepaint(CustomPainter oldDelegate) => false;
|
||||
// }
|
||||
@ -0,0 +1,431 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:http/http.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:nhance_partner/presentation/providers/userRoleProvider.dart';
|
||||
import '../../../../core/routing/routes.dart';
|
||||
import '../../../../core/services/api_service.dart';
|
||||
import '../../../../data/utils/Pagination.dart';
|
||||
import '../../../layouts/responsive_layout.dart';
|
||||
import '../../../providers/manager_provider.dart';
|
||||
import '../../../widgets/custom_action_popup.dart';
|
||||
|
||||
class ClaimsSubList extends ConsumerStatefulWidget {
|
||||
final dynamic policyNumber;
|
||||
ClaimsSubList({super.key, this.policyNumber});
|
||||
@override
|
||||
ConsumerState<ClaimsSubList> createState() => ClaimsSubListState();
|
||||
}
|
||||
|
||||
class ClaimsSubListState extends ConsumerState<ClaimsSubList> {
|
||||
int currentPage = 1;
|
||||
int itemsPerPage = 10;
|
||||
late ApiService apiService;
|
||||
|
||||
// List<Map<String, dynamic>> dataVal = [];
|
||||
List<Map<String, dynamic>> getStaffData = [];
|
||||
List<Map<String, dynamic>> originalData = [];
|
||||
List<Map<String, dynamic>> filteredData = [];
|
||||
bool isLoading = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
apiService = ApiService();
|
||||
|
||||
if (widget.policyNumber != null) {
|
||||
getClaimsList(widget.policyNumber);
|
||||
}
|
||||
// Future.microtask(() {
|
||||
// // final id = ref.read(managerIdProvider);
|
||||
// // final roleId = ref.read(userRoleProvider);
|
||||
//
|
||||
// // print("ENQroleId - $roleId");
|
||||
//
|
||||
// });
|
||||
}
|
||||
|
||||
Future<void> getClaimsList(id) async {
|
||||
// print('getClaimList called MagId - $managerId - $role');
|
||||
setState(() {
|
||||
isLoading = true;
|
||||
});
|
||||
// dynamic id = widget.policyNumber;
|
||||
print('POLID - $id');
|
||||
try {
|
||||
final response = await apiService.findSingleClaimData(id);
|
||||
|
||||
if (response['status'] == 'success') {
|
||||
final data = response['data'];
|
||||
print('getClaimsListData - ${response['data']}');
|
||||
setState(() {
|
||||
if (data is List) {
|
||||
// Already a list of maps
|
||||
getStaffData = List<Map<String, dynamic>>.from(data);
|
||||
} else if (data is Map) {
|
||||
// Single object, wrap in a list
|
||||
getStaffData = [Map<String, dynamic>.from(data)];
|
||||
} else {
|
||||
getStaffData = [];
|
||||
}
|
||||
// getStaffData = List<Map<String, dynamic>>.from(response['data']);
|
||||
originalData = getStaffData;
|
||||
filteredData = List.from(originalData);
|
||||
// print('originalData - $getClaimPolicies');
|
||||
});
|
||||
} else {
|
||||
getStaffData = [];
|
||||
originalData = [];
|
||||
}
|
||||
} catch (e) {
|
||||
print('Exception occurred: $e');
|
||||
} finally {
|
||||
setState(() {
|
||||
isLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
final TextEditingController _searchStaffController = TextEditingController();
|
||||
|
||||
String _formatDate(String rawDate) {
|
||||
try {
|
||||
final dateTime = DateTime.parse(rawDate);
|
||||
return DateFormat('dd/MM/yyyy HH:mm').format(dateTime); // 24-hour format
|
||||
} catch (e) {
|
||||
return rawDate; // fallback if parsing fails
|
||||
}
|
||||
}
|
||||
|
||||
List<Widget> _buildPopupMenuActions(BuildContext context, dynamic data) {
|
||||
return [
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
print('EDITStaff - ${data['id']}');
|
||||
// dynamic id = data['id'];
|
||||
// context.go('/tabEnquiry/$id');
|
||||
|
||||
// update provider
|
||||
final id = data['id'].toString();
|
||||
ref.read(enquiryIdProvider.notifier).state = id;
|
||||
context.go(AppRoutes.tabEnquiry);
|
||||
},
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(Icons.edit_sharp, color: Color(0xFF319718), size: 18),
|
||||
SizedBox(width: 10),
|
||||
Text('Edit'),
|
||||
],
|
||||
),
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
// color: Colors.yellow.shade50,
|
||||
width: MediaQuery.of(context).size.width * 0.6,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
// color: Colors.green,
|
||||
// color: Colors.green.shade50,
|
||||
width: MediaQuery.of(context).size.width,
|
||||
|
||||
padding: EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
children: [
|
||||
if (!ResponsiveLayout.isMobile(context))
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 12,
|
||||
horizontal: 16,
|
||||
),
|
||||
child: const Row(
|
||||
children: [
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text('Claim Type', style: _headerStyle),
|
||||
),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text('Claim Amount', style: _headerStyle),
|
||||
),
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: Text('Remarks', style: _headerStyle),
|
||||
),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text('Status', style: _headerStyle),
|
||||
),
|
||||
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Text('Action', style: _headerStyle),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
_buildDataTable(context),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildDataTable1(BuildContext context) {
|
||||
if (filteredData.isEmpty) {
|
||||
return const SizedBox(
|
||||
height: 50,
|
||||
child: Center(child: Text('No available data')),
|
||||
);
|
||||
}
|
||||
|
||||
final sortedData = [...filteredData];
|
||||
return ListView.builder(
|
||||
itemCount: ResponsiveLayout.isMobile(context)
|
||||
? sortedData
|
||||
.length // only cards for mobile
|
||||
: sortedData.length + 1, // +1 for header in desktop
|
||||
itemBuilder: (context, index) {
|
||||
if (!ResponsiveLayout.isMobile(context) && index == 0) {
|
||||
return _buildHeader();
|
||||
}
|
||||
|
||||
final startIndex = (currentPage - 1) * itemsPerPage;
|
||||
final item =
|
||||
sortedData[index - (ResponsiveLayout.isMobile(context) ? 0 : 1)];
|
||||
final sno = startIndex + index;
|
||||
|
||||
return !ResponsiveLayout.isMobile(context)
|
||||
? _buildDataRow(item, sno)
|
||||
: _buildDataCard(item, sno);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildDataTable(BuildContext context) {
|
||||
print('DATA -1');
|
||||
if (filteredData.isEmpty) {
|
||||
return const SizedBox(
|
||||
height: 50,
|
||||
child: Center(child: Text('No available data')),
|
||||
);
|
||||
}
|
||||
print('DATA -2');
|
||||
|
||||
final sortedData = [...filteredData];
|
||||
print('DATA -$sortedData');
|
||||
|
||||
return ListView.builder(
|
||||
shrinkWrap: true, // 👈 important when inside Column
|
||||
physics: const NeverScrollableScrollPhysics(), // let parent scroll
|
||||
itemCount: sortedData.length,
|
||||
itemBuilder: (context, index) {
|
||||
print('DAta Itembuilder 1');
|
||||
final startIndex = (currentPage - 1) * itemsPerPage;
|
||||
final item = sortedData[index];
|
||||
final sno = startIndex + index + 1;
|
||||
|
||||
print('DAta Itembuilder 2');
|
||||
return !ResponsiveLayout.isMobile(context)
|
||||
? _buildDataRow(item, sno)
|
||||
: _buildDataCard(item, sno);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildHeader() {
|
||||
return SizedBox.shrink();
|
||||
}
|
||||
|
||||
Widget _buildDataRow(Map<String, dynamic> item, sno) {
|
||||
print('Build - $item'); // Debug: check data
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 16),
|
||||
decoration: BoxDecoration(
|
||||
color: Color(0xFFEDF6F5),
|
||||
border: const Border(
|
||||
bottom: BorderSide(color: Color(0xFFEAEAEA), width: 1),
|
||||
),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text(item['claim_type_value'] ?? '-', style: _dataBold),
|
||||
),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text(item['claim_amount'] ?? '-', style: _dataBold),
|
||||
),
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: Text(item['claim_description'] ?? '-', style: _dataBold),
|
||||
),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text(item['claim_status_value'] ?? '-', style: _dataBold),
|
||||
),
|
||||
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Row(
|
||||
children: [
|
||||
PopupMenuButton<int>(
|
||||
color: Colors.white,
|
||||
padding: EdgeInsets.zero,
|
||||
offset: Offset(0, 30),
|
||||
icon: Icon(
|
||||
Icons.more_vert,
|
||||
color: Color(0xFF475569),
|
||||
size: 14,
|
||||
),
|
||||
itemBuilder: (context) => [
|
||||
CustomPopupMenuEntry(
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 8,
|
||||
vertical: 8,
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: _buildPopupMenuActions(context, item),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildDataCard(Map<String, dynamic> item, int sno) {
|
||||
return Container(
|
||||
margin: const EdgeInsets.symmetric(vertical: 6, horizontal: 8),
|
||||
padding: const EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(
|
||||
// color: const Color(0xFFF6FEFD),
|
||||
color: const Color(0xFFFFFFFF),
|
||||
borderRadius: BorderRadius.circular(8.0),
|
||||
border: Border.all(color: const Color(0xffD9EBE8)),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Title + menu
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
item['claim_type_value'] ?? '-',
|
||||
style: _headerStyle,
|
||||
),
|
||||
),
|
||||
PopupMenuButton<int>(
|
||||
color: Colors.white,
|
||||
padding: EdgeInsets.zero,
|
||||
offset: const Offset(0, 30),
|
||||
icon: const Icon(
|
||||
Icons.more_vert,
|
||||
color: Color(0xFF475569),
|
||||
size: 16,
|
||||
),
|
||||
itemBuilder: (context) => [
|
||||
PopupMenuItem<int>(
|
||||
value: 1,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: _buildPopupMenuActions(context, item),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
// Description
|
||||
Text(
|
||||
item['claim_description'] ?? '-',
|
||||
style: _cardBodyStyle,
|
||||
maxLines: 3,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
// Status
|
||||
Row(
|
||||
children: [
|
||||
const Text(
|
||||
"Status: ",
|
||||
style: TextStyle(
|
||||
color: Colors.green,
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
item['claim_status_value'] ?? '-',
|
||||
style: TextStyle(
|
||||
// color: (item['status'] == "Completed")
|
||||
// ? Colors.green
|
||||
// : Colors.orange,
|
||||
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 _headerStyle = TextStyle(
|
||||
color: Colors.black,
|
||||
fontWeight: FontWeight.bold,
|
||||
);
|
||||
static const _cardheaderStyle = TextStyle(
|
||||
color: Colors.black,
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 12,
|
||||
);
|
||||
|
||||
static const _cardBodyStyle = TextStyle(
|
||||
color: Color(0xFF545454),
|
||||
fontWeight: FontWeight.w400,
|
||||
fontSize: 12,
|
||||
);
|
||||
}
|
||||
@ -0,0 +1,464 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:http/http.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:nhance_partner/presentation/providers/userRoleProvider.dart';
|
||||
import '../../../../core/routing/routes.dart';
|
||||
import '../../../../core/services/api_service.dart';
|
||||
import '../../../../data/utils/Pagination.dart';
|
||||
import '../../../layouts/responsive_layout.dart';
|
||||
import '../../../providers/manager_provider.dart';
|
||||
import '../../../widgets/custom_action_popup.dart';
|
||||
|
||||
class EndrosmentSubList extends ConsumerStatefulWidget {
|
||||
final dynamic policyNumber;
|
||||
const EndrosmentSubList({super.key, this.policyNumber});
|
||||
@override
|
||||
ConsumerState<EndrosmentSubList> createState() => EndrosmentSubListState();
|
||||
}
|
||||
|
||||
class EndrosmentSubListState extends ConsumerState<EndrosmentSubList> {
|
||||
int currentPage = 1;
|
||||
int itemsPerPage = 10;
|
||||
late ApiService apiService;
|
||||
|
||||
// List<Map<String, dynamic>> dataVal = [];
|
||||
List<Map<String, dynamic>> getStaffData = [];
|
||||
List<Map<String, dynamic>> originalData = [];
|
||||
List<Map<String, dynamic>> filteredData = [];
|
||||
bool isLoading = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
apiService = ApiService();
|
||||
if (widget.policyNumber != null) {
|
||||
getEndrosmentList(widget.policyNumber);
|
||||
}
|
||||
// Future.microtask(() {
|
||||
// // final id = ref.read(managerIdProvider);
|
||||
// // final roleId = ref.read(userRoleProvider);
|
||||
//
|
||||
// });
|
||||
}
|
||||
|
||||
Future<void> getEndrosmentList(id) async {
|
||||
print('POLID - $id');
|
||||
// print('getClaimList called MagId - $managerId - $role');
|
||||
setState(() {
|
||||
isLoading = true;
|
||||
});
|
||||
// dynamic id = widget.policyNumber;
|
||||
try {
|
||||
final response = await apiService.findSingleEnrosmentData(id);
|
||||
|
||||
if (response['status'] == 'success') {
|
||||
final data = response['data'];
|
||||
print('getEndrosmentData - ${response['data']}');
|
||||
setState(() {
|
||||
if (data is List) {
|
||||
print('getEndrosmentData 1');
|
||||
// Already a list of maps
|
||||
getStaffData = List<Map<String, dynamic>>.from(data);
|
||||
} else if (data is Map) {
|
||||
print('getEndrosmentData 2 ');
|
||||
// Single object, wrap in a list
|
||||
|
||||
getStaffData = [Map<String, dynamic>.from(data)];
|
||||
|
||||
print('getEndrosmentData 2 - $getStaffData');
|
||||
} else {
|
||||
print('getEndrosmentData 3');
|
||||
getStaffData = [];
|
||||
}
|
||||
// getStaffData = List<Map<String, dynamic>>.from(response['data']);
|
||||
originalData = getStaffData;
|
||||
filteredData = List.from(originalData);
|
||||
// print('originalData - $getClaimPolicies');
|
||||
});
|
||||
} else {
|
||||
getStaffData = [];
|
||||
originalData = [];
|
||||
}
|
||||
} catch (e) {
|
||||
print('Exception occurred: $e');
|
||||
} finally {
|
||||
setState(() {
|
||||
isLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
final TextEditingController _searchStaffController = TextEditingController();
|
||||
|
||||
String _formatDate(String rawDate) {
|
||||
try {
|
||||
final dateTime = DateTime.parse(rawDate);
|
||||
return DateFormat('dd/MM/yyyy HH:mm').format(dateTime); // 24-hour format
|
||||
} catch (e) {
|
||||
return rawDate; // fallback if parsing fails
|
||||
}
|
||||
}
|
||||
|
||||
List<dynamic> get _paginatedData {
|
||||
// Sort descending by id first
|
||||
final sortedData = [...filteredData]
|
||||
..sort((a, b) => int.parse(b['id']) - int.parse(a['id']));
|
||||
|
||||
final startIndex = (currentPage - 1) * itemsPerPage;
|
||||
final endIndex = (currentPage * itemsPerPage).clamp(0, sortedData.length);
|
||||
|
||||
return sortedData.sublist(startIndex, endIndex);
|
||||
}
|
||||
|
||||
List<Widget> _buildPopupMenuActions(BuildContext context, dynamic data) {
|
||||
return [
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
print('EDITStaff - ${data['id']}');
|
||||
// dynamic id = data['id'];
|
||||
// context.go('/tabEnquiry/$id');
|
||||
|
||||
// update provider
|
||||
final id = data['id'].toString();
|
||||
ref.read(enquiryIdProvider.notifier).state = id;
|
||||
context.go(AppRoutes.tabEnquiry);
|
||||
},
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(Icons.edit_sharp, color: Color(0xFF319718), size: 18),
|
||||
SizedBox(width: 10),
|
||||
Text('Edit'),
|
||||
],
|
||||
),
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
// color: Colors.yellow.shade50,
|
||||
width: MediaQuery.of(context).size.width * 0.6,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
// color: Colors.green,
|
||||
// color: Colors.green.shade50,
|
||||
width: MediaQuery.of(context).size.width,
|
||||
|
||||
padding: EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
children: [
|
||||
if (!ResponsiveLayout.isMobile(context))
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
// color: Color(0xFFEDF6F5),
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 12,
|
||||
horizontal: 16,
|
||||
),
|
||||
child: const Row(
|
||||
children: [
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text('Endorsement Type', style: _headerStyle),
|
||||
),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text(
|
||||
'Endorsement Number',
|
||||
style: _headerStyle,
|
||||
),
|
||||
),
|
||||
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: Text('Remarks', style: _headerStyle),
|
||||
),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text('Status', style: _headerStyle),
|
||||
),
|
||||
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Text('Action', style: _headerStyle),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
_buildDataTable(context),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildDataTable1(BuildContext context) {
|
||||
print('DATA -1');
|
||||
if (filteredData.isEmpty) {
|
||||
return const SizedBox(
|
||||
height: 50,
|
||||
child: Center(child: Text('No available data')),
|
||||
);
|
||||
}
|
||||
print('DATA -2');
|
||||
// final sortedData = [..._paginatedData];
|
||||
final sortedData = [...filteredData];
|
||||
print('DATA -$sortedData');
|
||||
return ListView.builder(
|
||||
itemCount: ResponsiveLayout.isMobile(context)
|
||||
? sortedData
|
||||
.length // only cards for mobile
|
||||
: sortedData.length + 1, // +1 for header in desktop
|
||||
// itemCount: sortedData.length,
|
||||
itemBuilder: (context, index) {
|
||||
print('DAta Itembuilder');
|
||||
if (!ResponsiveLayout.isMobile(context) && index == 0) {
|
||||
return _buildHeader();
|
||||
}
|
||||
print('DAta Itembuilder 1');
|
||||
final startIndex = (currentPage - 1) * itemsPerPage;
|
||||
print('DAta Itembuilder 2');
|
||||
final item =
|
||||
sortedData[index - (ResponsiveLayout.isMobile(context) ? 0 : 1)];
|
||||
final sno = startIndex + index;
|
||||
|
||||
print('DAta Itembuilder 3');
|
||||
// return _buildDataRow(item, sno);
|
||||
|
||||
return !ResponsiveLayout.isMobile(context)
|
||||
? _buildDataRow(item, sno)
|
||||
: _buildDataCard(item, sno);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildDataTable(BuildContext context) {
|
||||
print('DATA -1');
|
||||
if (filteredData.isEmpty) {
|
||||
return const SizedBox(
|
||||
height: 50,
|
||||
child: Center(child: Text('No available data')),
|
||||
);
|
||||
}
|
||||
print('DATA -2');
|
||||
|
||||
final sortedData = [...filteredData];
|
||||
print('DATA -$sortedData');
|
||||
|
||||
return ListView.builder(
|
||||
shrinkWrap: true, // 👈 important when inside Column
|
||||
physics: const NeverScrollableScrollPhysics(), // let parent scroll
|
||||
itemCount: sortedData.length,
|
||||
itemBuilder: (context, index) {
|
||||
print('DAta Itembuilder 1');
|
||||
final startIndex = (currentPage - 1) * itemsPerPage;
|
||||
final item = sortedData[index];
|
||||
final sno = startIndex + index + 1;
|
||||
|
||||
print('DAta Itembuilder 2');
|
||||
return !ResponsiveLayout.isMobile(context)
|
||||
? _buildDataRow(item, sno)
|
||||
: _buildDataCard(item, sno);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildHeader() {
|
||||
return SizedBox.shrink();
|
||||
}
|
||||
|
||||
Widget _buildDataRow(Map<String, dynamic> item, sno) {
|
||||
print('Build - $item'); // Debug: check data
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 16),
|
||||
decoration: BoxDecoration(
|
||||
color: Color(0xFFEDF6F5),
|
||||
border: const Border(
|
||||
bottom: BorderSide(color: Color(0xFFEAEAEA), width: 1),
|
||||
),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text(
|
||||
item['endorsement_type_value'] ?? '-',
|
||||
style: _dataBold,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text(item['endorsement_no'] ?? '-', style: _dataBold),
|
||||
),
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: Text(
|
||||
item['endorsement_description'] ?? '-',
|
||||
style: _dataBold,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text(item['status'] ?? '-', style: _dataBold),
|
||||
),
|
||||
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Row(
|
||||
children: [
|
||||
PopupMenuButton<int>(
|
||||
color: Colors.white,
|
||||
padding: EdgeInsets.zero,
|
||||
offset: Offset(0, 30),
|
||||
icon: Icon(
|
||||
Icons.more_vert,
|
||||
color: Color(0xFF475569),
|
||||
size: 14,
|
||||
),
|
||||
itemBuilder: (context) => [
|
||||
CustomPopupMenuEntry(
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 8,
|
||||
vertical: 8,
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: _buildPopupMenuActions(context, item),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildDataCard(Map<String, dynamic> item, int sno) {
|
||||
return Container(
|
||||
margin: const EdgeInsets.symmetric(vertical: 6, horizontal: 8),
|
||||
padding: const EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFFFFFFFF),
|
||||
borderRadius: BorderRadius.circular(8.0),
|
||||
border: Border.all(color: const Color(0xffD9EBE8)),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Title + menu
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
item['endorsement_type_value'] ?? '-',
|
||||
style: _headerStyle,
|
||||
),
|
||||
),
|
||||
PopupMenuButton<int>(
|
||||
color: Colors.white,
|
||||
padding: EdgeInsets.zero,
|
||||
offset: const Offset(0, 30),
|
||||
icon: const Icon(
|
||||
Icons.more_vert,
|
||||
color: Color(0xFF475569),
|
||||
size: 16,
|
||||
),
|
||||
itemBuilder: (context) => [
|
||||
PopupMenuItem<int>(
|
||||
value: 1,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: _buildPopupMenuActions(context, item),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
// Description
|
||||
Text(
|
||||
item['endorsement_description'] ?? '-',
|
||||
style: _cardBodyStyle,
|
||||
maxLines: 3,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
// Status
|
||||
Row(
|
||||
children: [
|
||||
const Text(
|
||||
"Status: ",
|
||||
style: TextStyle(
|
||||
color: Colors.green,
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
item['status'] ?? '-',
|
||||
style: TextStyle(
|
||||
// color: (item['status'] == "Completed")
|
||||
// ? Colors.green
|
||||
// : Colors.orange,
|
||||
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 _headerStyle = TextStyle(
|
||||
color: Colors.black,
|
||||
fontWeight: FontWeight.bold,
|
||||
);
|
||||
static const _cardheaderStyle = TextStyle(
|
||||
color: Colors.black,
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 12,
|
||||
);
|
||||
|
||||
static const _cardBodyStyle = TextStyle(
|
||||
color: Color(0xFF545454),
|
||||
fontWeight: FontWeight.w400,
|
||||
fontSize: 12,
|
||||
);
|
||||
}
|
||||
@ -547,25 +547,25 @@ class AgentState extends ConsumerState<Agent> {
|
||||
// color: Colors.white,
|
||||
child: Row(
|
||||
children: [
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
docUploadedFile = null;
|
||||
passportFileUrlFromApi = null;
|
||||
selectedFileNames = null;
|
||||
});
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.remove_circle_outline_rounded,
|
||||
color: Colors.redAccent,
|
||||
),
|
||||
tooltip: 'To Remove Upload',
|
||||
),
|
||||
// IconButton(
|
||||
// onPressed: () {
|
||||
// setState(() {
|
||||
// docUploadedFile = null;
|
||||
// passportFileUrlFromApi = null;
|
||||
// selectedFileNames = null;
|
||||
// });
|
||||
// },
|
||||
// icon: Icon(
|
||||
// Icons.remove_circle_outline_rounded,
|
||||
// color: Colors.redAccent,
|
||||
// ),
|
||||
// tooltip: 'To Remove Upload',
|
||||
// ),
|
||||
GestureDetector(
|
||||
onTap: () => apiService.downloadFile(
|
||||
apiUrl:
|
||||
'api/agent/downloadAgentCertificateFile?agent_id=$selectedId',
|
||||
apiId: null,
|
||||
apiId: selectedId,
|
||||
localFile: docUploadedFile,
|
||||
fileName: selectedFileNames,
|
||||
),
|
||||
|
||||
@ -13,6 +13,7 @@ class AppInputDecorations {
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
borderSide: const BorderSide(color: Color(0xFFFFFFFF)),
|
||||
),
|
||||
errorStyle: const TextStyle(color: Colors.red, fontSize: 12),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
borderSide: const BorderSide(color: Color(0xFFFFFFFF)),
|
||||
@ -21,6 +22,15 @@ class AppInputDecorations {
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
borderSide: const BorderSide(color: Color(0xFF50A398), width: 2),
|
||||
),
|
||||
|
||||
errorBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
borderSide: const BorderSide(color: Color(0xFFD83731), width: 1),
|
||||
),
|
||||
focusedErrorBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
borderSide: const BorderSide(color: Color(0xFFD83731), width: 2),
|
||||
),
|
||||
floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||
);
|
||||
}
|
||||
|
||||
@ -136,6 +136,9 @@ class ThemedFormField extends HookWidget {
|
||||
keyboardType: keyboardType, // ✅ e.g. TextInputType.number
|
||||
maxLength: maxLength, // ✅ max length
|
||||
inputFormatters: inputFormatters,
|
||||
// ✅ allow multiline if user sets maxLines / minLines
|
||||
minLines: (keyboardType == TextInputType.multiline) ? 3 : 1,
|
||||
maxLines: (keyboardType == TextInputType.multiline) ? null : 1,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@ -83,19 +83,19 @@ class DrawerMenuState extends ConsumerState<DrawerMenu> {
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
context.go(AppRoutes.enquiryLst);
|
||||
},
|
||||
child: const Text(
|
||||
"Enquiries",
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
// const SizedBox(height: 5),
|
||||
// GestureDetector(
|
||||
// onTap: () {
|
||||
// context.go(AppRoutes.enquiryLst);
|
||||
// },
|
||||
// child: const Text(
|
||||
// "Enquiries",
|
||||
// style: TextStyle(
|
||||
// fontSize: 16,
|
||||
// fontWeight: FontWeight.w400,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
const SizedBox(height: 5),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
@ -230,8 +230,12 @@ class DrawerMenuState extends ConsumerState<DrawerMenu> {
|
||||
builder: (context, ref, _) {
|
||||
return IconButton(
|
||||
onPressed: () {
|
||||
ref.read(enquiryIdProvider.notifier).state = null;
|
||||
context.go(AppRoutes.tabEnquiry);
|
||||
if (roleId == 'manager') {
|
||||
} else if (roleId == 'agent') {
|
||||
context.go(AppRoutes.enquiryLst);
|
||||
}
|
||||
// ref.read(enquiryIdProvider.notifier).state = null;
|
||||
// context.go(AppRoutes.tabEnquiry);
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.list_alt_rounded,
|
||||
|
||||
@ -39,15 +39,15 @@ class TopBar extends StatelessWidget implements PreferredSizeWidget {
|
||||
width: 120,
|
||||
),
|
||||
if (isMobile) ...[
|
||||
IconButton(
|
||||
icon: const Icon(
|
||||
Icons.arrow_back_ios,
|
||||
color: Colors.black87,
|
||||
size: 18,
|
||||
),
|
||||
onPressed: onBack ?? () => Navigator.pop(context),
|
||||
),
|
||||
|
||||
// IconButton(
|
||||
// icon: const Icon(
|
||||
// Icons.arrow_back_ios,
|
||||
// color: Colors.black87,
|
||||
// size: 18,
|
||||
// ),
|
||||
// onPressed: onBack ?? () => Navigator.pop(context),
|
||||
// ),
|
||||
SizedBox(width: 5),
|
||||
Expanded(
|
||||
child: Text(
|
||||
title,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user