FIX_Helpdesk Fixes
This commit is contained in:
parent
ae238f8812
commit
5d3bf2c917
File diff suppressed because one or more lines are too long
@ -5,8 +5,8 @@ class Env {
|
||||
);
|
||||
static const String apiUrl = String.fromEnvironment(
|
||||
'API_URL',
|
||||
// defaultValue: 'https://partner.nhanceindia.in/partner_api/api/',
|
||||
defaultValue: 'https://venbait.in/nhance/partner/dev/api/',
|
||||
// defaultValue: 'https://partner.nhanceindia.in/partner_api/api/', /* when test build uncomment this. but below line should in comment */
|
||||
defaultValue: 'https://venbait.in/nhance/partner/dev/api/', /* when live build uncomment . but above line should in comment */
|
||||
);
|
||||
// static const String baseUrl = String.fromEnvironment(
|
||||
// 'BASE_URL',
|
||||
|
||||
@ -440,33 +440,61 @@ class ApiService {
|
||||
print('getPdfDownload 1 - $path');
|
||||
|
||||
dynamic pathVal;
|
||||
// if (path == 'Insurer') {
|
||||
// pathVal =
|
||||
// 'dashboard/downloadInsurerPoliciesExcel?manager_id=$managerId&month=$month&insurer_id=$id';
|
||||
// } else if (path == 'Broker') {
|
||||
// pathVal =
|
||||
// 'dashboard/downloadBrokerPoliciesExcel?manager_id=$managerId&month=$month&broker_id=$id';
|
||||
// } else if (path == 'Product') {
|
||||
// pathVal =
|
||||
// 'dashboard/downloadProductPoliciesExcel?manager_id=$managerId&month=$month&vehicle_type=$id';
|
||||
// } else if (path == 'PerformingTop50') {
|
||||
// pathVal =
|
||||
// 'dashboard/downloadAgentMonthlyPoliciesExcel?manager_id=$managerId&agent_id=$id';
|
||||
// } else if (path == 'PerformingAgentAll50') {
|
||||
// pathVal = 'dashboard/downloadT50AgentPoliciesExcel?manager_id=$managerId';
|
||||
// } else if (path == 'NonPerformingBelow50K') {
|
||||
// pathVal = 'dashboard/downloadLowPremiumAgentExcel?manager_id=$managerId';
|
||||
// } else if (path == 'staff_pending_summary') {
|
||||
// pathVal = 'dashboard/downloadStaffPendingSummaryExcel?manager_id=$managerId';
|
||||
// } else if (path == 'staff_pending_summary_by_id') {
|
||||
// pathVal = 'dashboard/downloadStaffPendingSummaryExcelByID?manager_id=$managerId&staff_id=$id&status=$month';
|
||||
// } else {
|
||||
// //NoBusiness
|
||||
// pathVal =
|
||||
// 'dashboard/downloadAgentsWithoutPoliciesExcel?manager_id=$managerId';
|
||||
// }
|
||||
|
||||
if (path == 'Insurer') {
|
||||
pathVal =
|
||||
'dashboard/downloadInsurerPoliciesExcel?manager_id=$managerId&month=$month&insurer_id=$id';
|
||||
'dashboard/downloadExcelInsurer?manager_id=$managerId&month=$month&insurer_id=$id';
|
||||
} else if (path == 'Broker') {
|
||||
pathVal =
|
||||
'dashboard/downloadBrokerPoliciesExcel?manager_id=$managerId&month=$month&broker_id=$id';
|
||||
'dashboard/downloadExcelBroker?manager_id=$managerId&month=$month&broker_id=$id';
|
||||
} else if (path == 'Product') {
|
||||
pathVal =
|
||||
'dashboard/downloadProductPoliciesExcel?manager_id=$managerId&month=$month&vehicle_type=$id';
|
||||
'dashboard/downloadExcelProduct?manager_id=$managerId&month=$month&vehicle_type=$id';
|
||||
} else if (path == 'PerformingTop50') {
|
||||
pathVal = 'dashboard/downloadExcelPerformingAgentsTop50?manager_id=$managerId';
|
||||
} else if (path == 'PerformingAgentsByID') {
|
||||
pathVal =
|
||||
'dashboard/downloadAgentMonthlyPoliciesExcel?manager_id=$managerId&agent_id=$id';
|
||||
} else if (path == 'PerformingAgentAll50') {
|
||||
pathVal = 'dashboard/downloadT50AgentPoliciesExcel?manager_id=$managerId';
|
||||
'dashboard/downloadExcelPerformingAgentsByID?manager_id=$managerId&agent_id=$id';
|
||||
} else if (path == 'NonPerformingBelow50K') {
|
||||
pathVal = 'dashboard/downloadLowPremiumAgentExcel?manager_id=$managerId';
|
||||
pathVal = 'dashboard/downloadExcelLowPremium?manager_id=$managerId';
|
||||
} else if (path == 'staff_pending_summary') {
|
||||
pathVal = 'dashboard/downloadStaffPendingSummaryExcel?manager_id=$managerId';
|
||||
pathVal = 'dashboard/downloadExcelStaffPendingSummaryExcel?manager_id=$managerId';
|
||||
} else if (path == 'staff_pending_summary_by_id') {
|
||||
pathVal = 'dashboard/downloadStaffPendingSummaryExcelByID?manager_id=$managerId&staff_id=$id&status=$month';
|
||||
pathVal = 'dashboard/downloadExcelStaffPendingSummaryExcelByID?manager_id=$managerId&staff_id=$id&status=$month';
|
||||
} else {
|
||||
//NoBusiness
|
||||
//NoBusiness
|
||||
pathVal =
|
||||
'dashboard/downloadAgentsWithoutPoliciesExcel?manager_id=$managerId';
|
||||
'dashboard/downloadExcelWithoutPolicies?manager_id=$managerId';
|
||||
}
|
||||
|
||||
final url = Uri.parse('${Env.apiUrl}$pathVal');
|
||||
final url = Uri.parse('${Env.apiUrl}$pathVal'); // original
|
||||
// final url = Uri.parse('http://localhost/nhance_partner_be/$pathVal'); //LocalHost
|
||||
|
||||
// final url = 'http://localhost/nhance_partner_be/dashboard/downloadAgentsWithoutPoliciesExcel?manager_id=1';
|
||||
// final url = Uri.parse('https://venbait.in/nhance/partner/dev/$path');
|
||||
print('getPdfDownload 2 - $url');
|
||||
@ -781,6 +809,7 @@ class ApiService {
|
||||
}
|
||||
final url = Uri.parse(
|
||||
'${Env.apiUrl}dashboard/partnerDashboard?manager_id=$id',
|
||||
// 'http://localhost/nhance_partner_be/dashboard/partnerDashboard?manager_id=$id',
|
||||
);
|
||||
|
||||
final headers = {
|
||||
@ -1071,7 +1100,7 @@ class ApiService {
|
||||
// query = 'manager_id=$id';
|
||||
// }
|
||||
if (role == 'manager') {
|
||||
query = 'manager_id=$id';
|
||||
query = 'manager_id=$managerid';
|
||||
} else if (role == 'handler') {
|
||||
query = 'handler_id=$id';
|
||||
} else if (role == 'staff') {
|
||||
@ -1301,7 +1330,8 @@ class ApiService {
|
||||
String? selectedStatus,
|
||||
String? selectedStaffId,
|
||||
}) async {
|
||||
// print(_token);
|
||||
print("APISERV : A1304");
|
||||
print(_token);
|
||||
if (_token == null) {
|
||||
await _initializeToken();
|
||||
}
|
||||
@ -1982,6 +2012,76 @@ class ApiService {
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
Future<void> generateEndorsementExcel(managerId) async {
|
||||
final url = Uri.parse(
|
||||
'${Env.apiUrl}reports/endorsement-excel?manager_id=$managerId',
|
||||
);
|
||||
|
||||
print('getPdfDownload endorsement-excel - $url');
|
||||
await _initializeToken();
|
||||
|
||||
if (_token == null) throw Exception('Token not found. Please log in.');
|
||||
|
||||
final headers = {
|
||||
'Authorization': 'Bearer $_token',
|
||||
// 'App-Signature': Env.App_Signature,
|
||||
'app-signature': Env.App_Signature,
|
||||
};
|
||||
|
||||
final response = await _makeGethttpRequest(url, headers);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
final contentType = response.headers['content-type'] ?? '';
|
||||
if (contentType.contains('application/json')) {
|
||||
final jsonResponse = jsonDecode(response.body);
|
||||
if (jsonResponse['code'] == 404 || jsonResponse['code'] == 500) {
|
||||
ToastHelper.show('File Not Found', Colors.red);
|
||||
} else {
|
||||
ToastHelper.show('No File Found', Colors.red);
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
final blob = html.Blob([response.bodyBytes]);
|
||||
final blobUrl = html.Url.createObjectUrlFromBlob(blob);
|
||||
print('getPdfDownload $blobUrl');
|
||||
final contentDisp = response.headers['content-disposition'];
|
||||
print('getPdfDownloadcontentDisp $contentDisp');
|
||||
|
||||
String fileName = extractFileName(contentDisp, "policy_excel");
|
||||
print('Resolved fileName: $fileName');
|
||||
final anchor = html.AnchorElement(href: blobUrl)
|
||||
..setAttribute('download', fileName)
|
||||
..click();
|
||||
|
||||
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 if (response.statusCode == 403) {
|
||||
await clearLocalStorageAndRedirect();
|
||||
} else if (response.statusCode == 500) {
|
||||
ToastHelper.show('No File Found', Colors.red);
|
||||
} else if (response.statusCode == 302) {
|
||||
print('getPdfDownload 3-PP-302');
|
||||
ToastHelper.show('No File Found', Colors.red);
|
||||
} else {
|
||||
ToastHelper.show('No File Found', Colors.red);
|
||||
throw Exception('Failed to download file');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> generatePolicyExcel(managerId, fromDate, toDate) async {
|
||||
final url = Uri.parse(
|
||||
'${Env.apiUrl}reports/policy-excel?manager_id=$managerId&from_date=${fromDate ?? ''}&to_date=${toDate ?? ''}',
|
||||
|
||||
@ -83,6 +83,7 @@ class _AddDialogState extends State<AddDialog> {
|
||||
|
||||
String? selectedClaimsType;
|
||||
String? selectedEndorsement;
|
||||
String? selectedEndrosementPolicyFrom;
|
||||
|
||||
dynamic roleId;
|
||||
|
||||
@ -98,6 +99,11 @@ class _AddDialogState extends State<AddDialog> {
|
||||
List<Map<String, dynamic>> originalVehicleData = [];
|
||||
List<Map<String, dynamic>> filteredVehicleData = [];
|
||||
|
||||
final List<Map<String, dynamic>> policyFromOptions = [
|
||||
{"policy_from": "Internal"},
|
||||
{"policy_from": "External"},
|
||||
];
|
||||
|
||||
Map<String, dynamic> claimsDetails() {
|
||||
final data = {
|
||||
"policy_number": controllers["policyNum"]?.text,
|
||||
@ -114,8 +120,9 @@ class _AddDialogState extends State<AddDialog> {
|
||||
"policy_number": controllers["policyNum"]?.text,
|
||||
"endorsement_description": controllers["remarks"]?.text,
|
||||
"endorsement_type": selectedEndorsement,
|
||||
// "manager_id": managerId,
|
||||
"manager_id": widget.managerId,
|
||||
"created_by": widget.userId,
|
||||
"policy_from": selectedEndrosementPolicyFrom,
|
||||
};
|
||||
return data;
|
||||
}
|
||||
@ -424,7 +431,8 @@ class _AddDialogState extends State<AddDialog> {
|
||||
// isDi sable = false;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if (!_formKeyEndrosment.currentState!.validate()) return;
|
||||
setState(() {
|
||||
if (_formKeyEndrosment.currentState!.validate()) {
|
||||
@ -441,9 +449,15 @@ class _AddDialogState extends State<AddDialog> {
|
||||
}
|
||||
|
||||
Future<void> createUserData(data, val) async {
|
||||
final Uri uri = (val == 'Claims')
|
||||
? Uri.parse('${Env.apiUrl}claim/createClaim')
|
||||
: Uri.parse('${Env.apiUrl}endorsement/createEndorsement');
|
||||
|
||||
final endpoints = {
|
||||
'Claims': 'claim/createClaim',
|
||||
'Endorsement': 'endorsement/createEndorsement',
|
||||
};
|
||||
|
||||
final String? path = endpoints[val];
|
||||
|
||||
final Uri uri = Uri.parse('${Env.apiUrl}$path');
|
||||
|
||||
if (_token == null) {
|
||||
throw Exception('Token not found. Please log in.');
|
||||
@ -808,7 +822,7 @@ class _AddDialogState extends State<AddDialog> {
|
||||
children: [
|
||||
buildEndrosType(context),
|
||||
SizedBox(width: 15),
|
||||
buildPolicyNumber(context),
|
||||
buildEndrosPolicyFrom(context),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
@ -819,9 +833,19 @@ class _AddDialogState extends State<AddDialog> {
|
||||
children: [
|
||||
buildUploadDocumentClaims(context),
|
||||
SizedBox(width: 15),
|
||||
buildEndrosRemarks(context),
|
||||
buildPolicyNumber(context),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
buildEndrosRemarks(context),
|
||||
SizedBox(width: 15),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
@ -1132,6 +1156,94 @@ class _AddDialogState extends State<AddDialog> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildEndrosPolicyFrom(context) {
|
||||
// Find the selected item from the static list based on your variable
|
||||
Map<String, dynamic> selectedEndorsementPF = policyFromOptions.firstWhere(
|
||||
(item) => item['policy_from'].toString() == selectedEndrosementPolicyFrom,
|
||||
orElse: () => {},
|
||||
);
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text("Policy From *", style: _textStyle),
|
||||
const SizedBox(height: 10),
|
||||
Container(
|
||||
color: Colors.white,
|
||||
width: ResponsiveLayout.isMobile(context)
|
||||
? null
|
||||
: MediaQuery.of(context).size.width * 0.26,
|
||||
child: DropdownSearch<Map<String, dynamic>>(
|
||||
// Use a unique key for this dropdown
|
||||
key: const ValueKey("policyFromDropdown"),
|
||||
selectedItem: selectedEndorsementPF.isNotEmpty
|
||||
? selectedEndorsementPF
|
||||
: null,
|
||||
items: (filter, infiniteScrollProps) {
|
||||
return policyFromOptions; // Use the static list
|
||||
},
|
||||
itemAsString: (val) => val['policy_from'].toString(),
|
||||
compareFn: (item, selectedItem) =>
|
||||
item['policy_from'] == selectedItem['policy_from'],
|
||||
|
||||
// --- REQUIRED VALIDATOR ---
|
||||
validator: (val) {
|
||||
if (val == null || val.isEmpty) {
|
||||
return "Required";
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
decoratorProps: DropDownDecoratorProps(
|
||||
decoration: AppInputDecorations.dropdownDecoration(
|
||||
label: "Select Policy From",
|
||||
).copyWith(
|
||||
filled: true,
|
||||
fillColor: const Color(0xFFEDF6F5),
|
||||
),
|
||||
),
|
||||
|
||||
popupProps: PopupProps.menu(
|
||||
fit: FlexFit.loose,
|
||||
constraints: const BoxConstraints(maxHeight: 150), // Shorter for 2 items
|
||||
menuProps: const MenuProps(
|
||||
backgroundColor: Colors.white,
|
||||
),
|
||||
showSearchBox: true, // Disabled search as there are only 2 items
|
||||
searchFieldProps: TextFieldProps(
|
||||
decoration: InputDecoration(
|
||||
filled: true,
|
||||
fillColor: Colors.white,
|
||||
hintText: "Search Policy From...",
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Colors.white,
|
||||
), // 👈 Normal border
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Colors.white,
|
||||
width: 1.5,
|
||||
), // 👈 Focused border
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
onChanged: (val) {
|
||||
if (val != null) {
|
||||
setState(() {
|
||||
print("Selected Policy From: ${val['policy_from']}");
|
||||
selectedEndrosementPolicyFrom = val['policy_from'];
|
||||
});
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildEndrosRemarks(context) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
|
||||
@ -0,0 +1,712 @@
|
||||
import 'package:dropdown_search/dropdown_search.dart';
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:http/http.dart' as ref;
|
||||
import 'package:toastification/toastification.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/customizd_file_upload.dart';
|
||||
import '../../../themes/indicators/input_field_decoration.dart';
|
||||
import '../../../themes/indicators/search_field_theme.dart';
|
||||
import '../../../themes/indicators/text_field_theme.dart';
|
||||
import '../../../providers/manager_provider.dart';
|
||||
|
||||
|
||||
class UpdateEndorsementDialog extends StatefulWidget {
|
||||
final Map<String, dynamic> item;
|
||||
final dynamic userId;
|
||||
final dynamic managerId;
|
||||
final Function(String) onSubmit;
|
||||
|
||||
const UpdateEndorsementDialog({
|
||||
super.key,
|
||||
required this.item,
|
||||
required this.userId,
|
||||
required this.managerId,
|
||||
required this.onSubmit,
|
||||
});
|
||||
|
||||
@override
|
||||
State<UpdateEndorsementDialog> createState() => _UpdateEndorsementDialogState();
|
||||
}
|
||||
|
||||
class _UpdateEndorsementDialogState extends State<UpdateEndorsementDialog> {
|
||||
late ApiService apiService;
|
||||
String? _token;
|
||||
final _formKeyUpdate = GlobalKey<FormState>();
|
||||
Map<String, TextEditingController> controllers = {};
|
||||
List<Map<String, dynamic>> getEndrosmentType = [];
|
||||
List<Map<String, dynamic>> filteredEndrosmentData = [];
|
||||
String? selectedEndorsement;
|
||||
String? selectedPolicyFrom;
|
||||
String? selectedStatus; // "Pending" or "Completed"
|
||||
String? selectedFileNames;
|
||||
bool isLoading = false;
|
||||
PlatformFile? docUploadedFile;
|
||||
|
||||
final List<Map<String, dynamic>> statusOptions = [
|
||||
{"status_value": "Open"},
|
||||
{"status_value": "Pending"},
|
||||
{"status_value": "Completed"},
|
||||
];
|
||||
|
||||
final List<Map<String, dynamic>> policyFromOptions = [
|
||||
{"policy_from": "Internal"},
|
||||
{"policy_from": "External"},
|
||||
];
|
||||
|
||||
final GlobalKey<DropdownSearchState<Map<String, dynamic>>> dropDownKey =
|
||||
GlobalKey<DropdownSearchState<Map<String, dynamic>>>();
|
||||
final GlobalKey<DropdownSearchState<Map<String, dynamic>>>
|
||||
dropDownKeyEndorsement =
|
||||
GlobalKey<DropdownSearchState<Map<String, dynamic>>>();
|
||||
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
apiService = ApiService();
|
||||
super.initState();
|
||||
_initializeToken();
|
||||
|
||||
print("secondpage");
|
||||
// 1. Initialize Controllers
|
||||
controllers['endorsement_no'] = TextEditingController(text: widget.item['endorsement_no']);
|
||||
controllers['remarks'] = TextEditingController(text: widget.item['endorsement_description']);
|
||||
|
||||
selectedEndorsement = widget.item['endorsement_type']?.toString();
|
||||
selectedStatus = widget.item['status']?.toString();
|
||||
selectedFileNames = widget.item['endorsement_completion_file'];
|
||||
getEnroementType();
|
||||
|
||||
}
|
||||
|
||||
Future<void> _initializeToken() async {
|
||||
_token = await AuthService.getToken();
|
||||
print("APISERTOKEN - $_token");
|
||||
}
|
||||
|
||||
// API Call logic
|
||||
// Future<void> updateData() async {
|
||||
// if (!_formKeyUpdate.currentState!.validate()) return;
|
||||
//
|
||||
// // VALIDATION: If Status is Completed, File is Mandatory
|
||||
// if (selectedStatus == "Completed" && docUploadedFile == null) {
|
||||
// ToastHelper.showErrorToast(context,"Document is required for Completed status",);
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// setState(() => isLoading = true);
|
||||
//
|
||||
// try {
|
||||
// final Uri uri = Uri.parse('${Env.apiUrl}endorsement/updateEndorsement');
|
||||
//
|
||||
// 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'] = Env.App_Signature;
|
||||
//
|
||||
// // Mapping fields to API Table
|
||||
// request.fields['endorsement_type'] = selectedEndorsement ?? "";
|
||||
// request.fields['endorsement_description'] = controllers['remarks']?.text ?? "";
|
||||
// request.fields['endorsement_no'] = widget.item['endorsement_no'] ?? "";
|
||||
// // request.fields['updated_by'] = userId;
|
||||
// request.fields['status'] = selectedStatus ?? "";
|
||||
//
|
||||
// if (docUploadedFile != null) {
|
||||
// try {
|
||||
// if (docUploadedFile!.bytes != null) {
|
||||
// final multipartFile = http.MultipartFile.fromBytes(
|
||||
// 'endorsement_completion_file',
|
||||
// docUploadedFile!.bytes!,
|
||||
// filename: docUploadedFile!.name,
|
||||
// );
|
||||
// request.files.add(multipartFile);
|
||||
// }
|
||||
//
|
||||
// print("📎 File attached: ${docUploadedFile!.name}");
|
||||
// } catch (e) {
|
||||
// print("❌ Failed to attach file: $e");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// final response = await request.send();
|
||||
// if (response.statusCode == 200) {
|
||||
// ToastHelper.showSuccessToast(context, 'Updated Successfully');
|
||||
// Navigator.pop(context);
|
||||
// widget.onSubmit("success");
|
||||
// }
|
||||
// } catch (e) {
|
||||
// print("Error: $e");
|
||||
// } finally {
|
||||
// setState(() => isLoading = false);
|
||||
// }
|
||||
// }
|
||||
|
||||
Future<void> updateData() async {
|
||||
// 1. Basic Form Validation
|
||||
if (!_formKeyUpdate.currentState!.validate()) return;
|
||||
|
||||
// 2. Business Validation: File mandatory for 'Completed' status
|
||||
if (selectedStatus == "Completed" && docUploadedFile == null) {
|
||||
ToastHelper.showErrorToast(context, "Document is required for Completed status");
|
||||
return;
|
||||
}
|
||||
|
||||
setState(() => isLoading = true);
|
||||
|
||||
try {
|
||||
final Uri uri = Uri.parse('${Env.apiUrl}endorsement/updateEndorsement');
|
||||
|
||||
if (_token == null) throw Exception('Token not found. Please log in.');
|
||||
|
||||
// Create Multipart Request
|
||||
final request = http.MultipartRequest('POST', uri);
|
||||
request.headers['Authorization'] = 'Bearer $_token';
|
||||
request.headers['app-signature'] = Env.App_Signature;
|
||||
|
||||
// --- MAPPING FIELDS ---
|
||||
// Use widget.item['id'] to identify the unique record
|
||||
request.fields['id'] = widget.item['id'].toString();
|
||||
request.fields['endorsement_type'] = selectedEndorsement ?? "";
|
||||
request.fields['endorsement_description'] = controllers['remarks']?.text ?? "";
|
||||
request.fields['endorsement_no'] = controllers['endorsement_no']?.text ?? "";
|
||||
|
||||
// Set updated_by from the widget parameter
|
||||
request.fields['updated_by'] = widget.userId.toString();
|
||||
request.fields['status'] = selectedStatus ?? "";
|
||||
|
||||
// --- FILE UPLOAD LOGIC ---
|
||||
if (docUploadedFile != null) {
|
||||
if (docUploadedFile!.bytes != null) {
|
||||
// For Web/Bytes
|
||||
request.files.add(http.MultipartFile.fromBytes(
|
||||
'endorsement_completion_file', // Key must match Backend
|
||||
docUploadedFile!.bytes!,
|
||||
filename: docUploadedFile!.name,
|
||||
));
|
||||
} else if (docUploadedFile!.path != null) {
|
||||
// For Mobile/Desktop path
|
||||
request.files.add(await http.MultipartFile.fromPath(
|
||||
'endorsement_completion_file',
|
||||
docUploadedFile!.path!,
|
||||
filename: docUploadedFile!.name,
|
||||
));
|
||||
}
|
||||
print("📎 Attached: ${docUploadedFile!.name}");
|
||||
}
|
||||
|
||||
// 3. Send Request
|
||||
final response = await request.send();
|
||||
final responseData = await http.Response.fromStream(response);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
ToastHelper.showSuccessToast(context, 'Updated Successfully');
|
||||
Navigator.pop(context);
|
||||
widget.onSubmit("success");
|
||||
} else {
|
||||
print("Server Error: ${responseData.body}");
|
||||
ToastHelper.showErrorToast(context, "Update failed: ${response.statusCode}");
|
||||
}
|
||||
} catch (e) {
|
||||
print("Error during update: $e");
|
||||
ToastHelper.showErrorToast(context, "An error occurred");
|
||||
} finally {
|
||||
setState(() => isLoading = false);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AlertDialog(
|
||||
backgroundColor: Colors.white,
|
||||
// Add shape for a cleaner look
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
|
||||
content: SizedBox(
|
||||
// Set a width to prevent layout jumping
|
||||
width: MediaQuery.of(context).size.width * 0.6,
|
||||
child: SingleChildScrollView( // 👈 Fix 1: Prevent Overflow
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
// Header row
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
"Update Endorsement",
|
||||
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 Tooltip(
|
||||
message: 'Close',
|
||||
child: Icon(Icons.close, size: 18),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
// Your form content
|
||||
endorsement(context),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
// 👈 Fix 2: Remove "onPressed:" label. Just call the function.
|
||||
updateData();
|
||||
},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 25.0, vertical: 8),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(8.0),
|
||||
color: const Color(0xFF425B5B),
|
||||
),
|
||||
child: isLoading
|
||||
? const SizedBox(height: 15, width: 15, child: CircularProgressIndicator(color: Colors.white, strokeWidth: 2))
|
||||
: const Text('Save', style: TextStyle(color: Colors.white)),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget endorsement(BuildContext context) {
|
||||
return Form(
|
||||
key: _formKeyUpdate,
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
// Wrap children in Expanded so they know how much space to take in the Row
|
||||
Expanded(child: buildEndrosType(context)),
|
||||
const SizedBox(width: 15),
|
||||
Expanded(child: buildStatusDropdown(context)),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(child: buildPolicyNumber(context)),
|
||||
const SizedBox(width: 15),
|
||||
Expanded(child: buildUploadDocumentEndorsment(context)),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(child: buildEndrosRemarks(context)),
|
||||
const SizedBox(width: 15),
|
||||
const Spacer(), // Keeps the remark field to the left
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// --- Specialized Widgets ---
|
||||
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 buildPolicyNumber(context) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text("Endorsement Number *", style: _textStyle),
|
||||
SizedBox(height: 10),
|
||||
ThemedFormField(
|
||||
backgroundColor: Color(0xFFEDF6F5),
|
||||
controller: controllers['endorsement_no']!,
|
||||
validator: (value) => Validators.requiredField(value, "endorsement_no"),
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z0-9\-_]')),
|
||||
],
|
||||
txtwidth: ResponsiveLayout.isMobile(context)
|
||||
? null
|
||||
: MediaQuery.of(context).size.width * 0.26,
|
||||
// keyboardType: TextInputType.multiline,
|
||||
// txtheight: 45,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildStatusDropdown(context) {
|
||||
// Find the selected item from the static list based on your variable
|
||||
Map<String, dynamic> selectedEndorsementST = statusOptions.firstWhere(
|
||||
(item) => item['status_value'].toString() == selectedStatus,
|
||||
orElse: () => {},
|
||||
);
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text("Status *", style: _textStyle),
|
||||
const SizedBox(height: 10),
|
||||
Container(
|
||||
color: Colors.white,
|
||||
width: ResponsiveLayout.isMobile(context)
|
||||
? null
|
||||
: MediaQuery.of(context).size.width * 0.26,
|
||||
child: DropdownSearch<Map<String, dynamic>>(
|
||||
// Use a unique key for this dropdown
|
||||
key: const ValueKey("statusDropdown"),
|
||||
selectedItem: selectedEndorsementST.isNotEmpty
|
||||
? selectedEndorsementST
|
||||
: null,
|
||||
items: (filter, infiniteScrollProps) {
|
||||
return statusOptions; // Use the static list
|
||||
},
|
||||
itemAsString: (val) => val['status_value'].toString(),
|
||||
compareFn: (item, selectedItem) =>
|
||||
item['status_value'] == selectedItem['status_value'],
|
||||
|
||||
// --- REQUIRED VALIDATOR ---
|
||||
validator: (val) {
|
||||
if (val == null || val.isEmpty) {
|
||||
return "Required";
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
decoratorProps: DropDownDecoratorProps(
|
||||
decoration: AppInputDecorations.dropdownDecoration(
|
||||
label: "Select Status",
|
||||
).copyWith(
|
||||
filled: true,
|
||||
fillColor: const Color(0xFFEDF6F5),
|
||||
),
|
||||
),
|
||||
|
||||
popupProps: PopupProps.menu(
|
||||
fit: FlexFit.loose,
|
||||
constraints: const BoxConstraints(maxHeight: 150), // Shorter for 2 items
|
||||
menuProps: const MenuProps(
|
||||
backgroundColor: Colors.white,
|
||||
),
|
||||
showSearchBox: true, // Disabled search as there are only 2 items
|
||||
searchFieldProps: TextFieldProps(
|
||||
decoration: InputDecoration(
|
||||
filled: true,
|
||||
fillColor: Colors.white,
|
||||
hintText: "Search Status...",
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Colors.white,
|
||||
), // 👈 Normal border
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Colors.white,
|
||||
width: 1.5,
|
||||
), // 👈 Focused border
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
onChanged: (val) {
|
||||
if (val != null) {
|
||||
setState(() {
|
||||
print("Selected Status: ${val['status_value']}");
|
||||
selectedStatus = val['status_value'];
|
||||
});
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
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,
|
||||
// txtheight: 45,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildUploadDocumentEndorsment(context) {
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text("Upload Document", style: _textStyle),
|
||||
SizedBox(width: 10),
|
||||
ThemedUploadField(
|
||||
backgroundColor: Color(0xFFEDF6F5),
|
||||
hintText: selectedFileNames ?? "Upload Document",
|
||||
txtwidth: ResponsiveLayout.isMobile(context)
|
||||
? null
|
||||
: MediaQuery.of(context).size.width * 0.26,
|
||||
onFileSelected: (fileName, file) {
|
||||
setState(() {
|
||||
docUploadedFile = file; // This 'file' is a PlatformFile
|
||||
});
|
||||
},
|
||||
),
|
||||
// Column(
|
||||
// mainAxisAlignment: MainAxisAlignment.end,
|
||||
// crossAxisAlignment: CrossAxisAlignment.end,
|
||||
// children: [
|
||||
// ThemedUploadField(
|
||||
// hintText: selectedFileNames ?? "Upload Document",
|
||||
// txtwidth: MediaQuery.of(context).size.width * 0.26,
|
||||
// onFileSelected: (fileName, file) {
|
||||
// print("Picked file: $fileName (${file.size} bytes)");
|
||||
// setState(() {
|
||||
// docUploadedEndorsFile = file;
|
||||
// });
|
||||
// },
|
||||
// ),
|
||||
// // const SizedBox(height: 5),
|
||||
// //
|
||||
// // if (docUploadedFile != null || passportEndorsFileUrlFromApi != null)
|
||||
// // Container(
|
||||
// // // color: Colors.white,
|
||||
// // child: Row(
|
||||
// // children: [
|
||||
// //
|
||||
// // GestureDetector(
|
||||
// // onTap: () => apiService.downloadFile(
|
||||
// // apiUrl:
|
||||
// // 'api/agent/downloadAgentCertificateFile?agent_id=$selectedEndorsId',
|
||||
// // apiId: selectedEndorsId,
|
||||
// // localFile: docUploadedFile,
|
||||
// // fileName: selectedFileNames,
|
||||
// // ),
|
||||
// // child: Container(
|
||||
// // padding: const EdgeInsets.all(5),
|
||||
// // decoration: BoxDecoration(
|
||||
// // borderRadius: BorderRadius.circular(5),
|
||||
// // color: Color(0xFF425B5B),
|
||||
// // // color: Colors.green.shade300,
|
||||
// // ),
|
||||
// // child: Row(
|
||||
// // children: const [
|
||||
// // Text(
|
||||
// // "Download",
|
||||
// // style: TextStyle(
|
||||
// // fontSize: 12,
|
||||
// // fontWeight: FontWeight.w200,
|
||||
// // color: Colors.white,
|
||||
// // ),
|
||||
// // ),
|
||||
// // SizedBox(width: 5),
|
||||
// // Icon(Icons.download, size: 13, color: Colors.white),
|
||||
// // ],
|
||||
// // ),
|
||||
// // ),
|
||||
// // ),
|
||||
// // ],
|
||||
// // ),
|
||||
// // ),
|
||||
// ],
|
||||
// ),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
static final TextStyle _textStyle = TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w600,
|
||||
);
|
||||
static final TextStyle _textStyle1 = TextStyle(
|
||||
fontSize: 9,
|
||||
fontWeight: FontWeight.w400,
|
||||
);
|
||||
|
||||
static final _dataBold = GoogleFonts.inter(
|
||||
fontSize: 11,
|
||||
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Color(0xFF000000),
|
||||
);
|
||||
|
||||
static final _dataSub = GoogleFonts.inter(
|
||||
fontSize: 10,
|
||||
fontWeight: FontWeight.w300,
|
||||
color: Color(0xFF585757),
|
||||
);
|
||||
|
||||
static final _headerStyle = GoogleFonts.poppins(
|
||||
fontSize: 11.2,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Color(0xFF1E293B),
|
||||
);
|
||||
static final _cardheaderStyle = GoogleFonts.inter(
|
||||
color: Colors.black,
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 12,
|
||||
);
|
||||
|
||||
static final _cardBodyStyle = GoogleFonts.inter(
|
||||
color: const Color(0xFF545454),
|
||||
fontWeight: FontWeight.w400,
|
||||
fontSize: 12,
|
||||
);
|
||||
|
||||
}
|
||||
@ -15,6 +15,7 @@ import '../../../themes/indicators/export_btn.dart';
|
||||
import '../../../themes/indicators/search_field_theme.dart';
|
||||
import '../../../widgets/custom_action_popup.dart';
|
||||
import '../enquiry/policy_popup.dart';
|
||||
import '../enquiry/updateEndorsementDialog.dart';
|
||||
|
||||
class endosement extends ConsumerStatefulWidget {
|
||||
const endosement({super.key});
|
||||
@ -128,6 +129,12 @@ class endosementState extends ConsumerState<endosement> {
|
||||
return (item['reg_no'] ?? '-').toLowerCase().contains(
|
||||
query.toLowerCase(),
|
||||
) ||
|
||||
(item['policy_from'] ?? '-').toLowerCase().contains(
|
||||
query.toLowerCase(),
|
||||
) ||
|
||||
(item['status'] ?? '-').toLowerCase().contains(
|
||||
query.toLowerCase(),
|
||||
) ||
|
||||
(item['insurer_short_name'] ?? '-').toLowerCase().contains(
|
||||
query.toLowerCase(),
|
||||
) ||
|
||||
@ -176,6 +183,30 @@ class endosementState extends ConsumerState<endosement> {
|
||||
];
|
||||
}
|
||||
|
||||
Future<void> fetchEndorsementExcelReport() async {
|
||||
final response = await apiService.generateEndorsementExcel(managerId);
|
||||
// Map your controllers and IDs to the API parameters
|
||||
// final String fromDate = controllers['startDate']!.text; // "11-01-2025"
|
||||
// final String toDate = controllers['endDate']!.text; // "20-01-2025"
|
||||
// print("fetchPolicyExcelReport function called here.");
|
||||
//
|
||||
// try {
|
||||
// // Assuming you have a generic _makeGetRequest method
|
||||
// final response = await apiService.fetchPolicyExcel(managerId,fromDate,toDate);
|
||||
//
|
||||
// if (response != null && response['status'] == 200) {
|
||||
// setState(() {
|
||||
// // Store the list of data in your variable
|
||||
// excelResponseData = response['data'];
|
||||
// });
|
||||
// print("Data fetched. Ready to export.");
|
||||
// }
|
||||
// } catch (e) {
|
||||
// debugPrint("Export Error: $e");
|
||||
// print("Failed to fetch report data.");
|
||||
// }
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MainLayout(
|
||||
@ -266,31 +297,60 @@ class endosementState extends ConsumerState<endosement> {
|
||||
),
|
||||
|
||||
SizedBox(width: 10),
|
||||
|
||||
ExportBtn(
|
||||
sheetName: "Endorsement",
|
||||
fileName: "endorsement_list",
|
||||
data: filteredData,
|
||||
txt: !ResponsiveLayout.isMobile(context)
|
||||
? true
|
||||
: false,
|
||||
displayHeaders: [
|
||||
"S.No.",
|
||||
"Vehicle.No.",
|
||||
"Insurer",
|
||||
"Policy No.",
|
||||
"Endorsement Type",
|
||||
"Endorsement No.",
|
||||
],
|
||||
keys: [
|
||||
"sno", // handled internally as i + 1
|
||||
"reg_no",
|
||||
"insurer_short_name",
|
||||
"policy_number",
|
||||
"endorsement_type_value",
|
||||
"endorsement_no",
|
||||
],
|
||||
Tooltip(
|
||||
message: 'Export Excel',
|
||||
child: InkWell(
|
||||
onTap: () async {
|
||||
await fetchEndorsementExcelReport();
|
||||
},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(7.0),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFF2E7D6E),
|
||||
// color: const Color(0xFF425B5B),
|
||||
borderRadius: BorderRadius.circular(8.0),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Image.asset(
|
||||
"assets/miscellaneous/export.png",
|
||||
height: 13,
|
||||
width: 13,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
// ExportBtn(
|
||||
// sheetName: "Endorsement",
|
||||
// fileName: "endorsement_list",
|
||||
// data: filteredData,
|
||||
// txt: !ResponsiveLayout.isMobile(context)
|
||||
// ? true
|
||||
// : false,
|
||||
// displayHeaders: [
|
||||
// "S.No.",
|
||||
// "Policy From.",
|
||||
// "Status",
|
||||
// "Vehicle.No.",
|
||||
// "Insurer",
|
||||
// "Policy No.",
|
||||
// "Endorsement Type",
|
||||
// "Endorsement No.",
|
||||
// ],
|
||||
// keys: [
|
||||
// "sno", // handled internally as i + 1
|
||||
// "policy_from",
|
||||
// "status",
|
||||
// "reg_no",
|
||||
// "insurer_short_name",
|
||||
// "policy_number",
|
||||
// "endorsement_type_value",
|
||||
// "endorsement_no",
|
||||
// ],
|
||||
// ),
|
||||
SizedBox(width: 10),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
@ -392,6 +452,14 @@ class endosementState extends ConsumerState<endosement> {
|
||||
flex: 2,
|
||||
child: Text('S.No.', style: _headerStyle),
|
||||
),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text('Policy.From.', style: _headerStyle),
|
||||
),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text('Status.', style: _headerStyle),
|
||||
),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text('Vehicle.No.', style: _headerStyle),
|
||||
@ -418,10 +486,10 @@ class endosementState extends ConsumerState<endosement> {
|
||||
style: _headerStyle,
|
||||
),
|
||||
),
|
||||
// Expanded(
|
||||
// flex: 1,
|
||||
// child: Text('Action', style: _headerStyle),
|
||||
// ),
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Text('Action', style: _headerStyle),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -515,6 +583,20 @@ class endosementState extends ConsumerState<endosement> {
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(flex: 2, child: Text('$sno' ?? '-', style: _dataBold)),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text(
|
||||
item['policy_from'] ?? '-',
|
||||
style: _dataBold,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text(
|
||||
item['status'] ?? '-',
|
||||
style: _dataBold,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text(
|
||||
@ -522,6 +604,13 @@ class endosementState extends ConsumerState<endosement> {
|
||||
style: _dataBold,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text(
|
||||
item['endorsement_type_value'] ?? '-',
|
||||
style: _dataBold,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text(
|
||||
@ -545,6 +634,62 @@ class endosementState extends ConsumerState<endosement> {
|
||||
flex: 2,
|
||||
child: Text(item['endorsement_no'] ?? '-', style: _dataBold),
|
||||
),
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: item['is_active'] == "1"
|
||||
? Row(
|
||||
children: [
|
||||
Tooltip(
|
||||
message: 'Edit',
|
||||
child: IconButton(
|
||||
icon: Image.asset(
|
||||
"assets/miscellaneous/Edit.png",
|
||||
height: 12,
|
||||
width: 15,
|
||||
),
|
||||
// onPressed: () {
|
||||
// showDialog(
|
||||
// context: context,
|
||||
// builder: (context) => UpdateEndorsementDialog(
|
||||
// item: item, // Passing the whole row map
|
||||
// userId: userId,
|
||||
// onSubmit: (val) => refresh(),
|
||||
// ),
|
||||
// );
|
||||
// },
|
||||
onPressed: () {
|
||||
// Ensure we are using the correct context
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: true, // Allows clicking outside to close
|
||||
builder: (BuildContext dialogContext) {
|
||||
return UpdateEndorsementDialog(
|
||||
item: item,
|
||||
userId: userId,
|
||||
managerId: managerId,
|
||||
onSubmit: (val) => refresh(),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
splashRadius: 28,
|
||||
hoverColor: Colors.black12,
|
||||
padding: const EdgeInsets.all(8),
|
||||
constraints: const BoxConstraints(),
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
: Row(
|
||||
children: [
|
||||
Image.asset(
|
||||
"assets/miscellaneous/Edit_muted.png",
|
||||
height: 12,
|
||||
width: 15,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
// Expanded(
|
||||
// flex: 1,
|
||||
// child: Row(
|
||||
@ -621,6 +766,43 @@ class endosementState extends ConsumerState<endosement> {
|
||||
),
|
||||
const Divider(color: Color(0xffD9EBE8), thickness: 0.8),
|
||||
|
||||
// Policy From + Status
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
//date and time
|
||||
Text("policy From", style: _cardheaderStyle),
|
||||
Text(
|
||||
item['policy_from'] ?? '-',
|
||||
style: _cardBodyStyle,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(width: 5),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
//remarks
|
||||
Text("Status", style: _cardheaderStyle),
|
||||
Text(
|
||||
item['status'] ?? '-',
|
||||
style: _cardBodyStyle,
|
||||
maxLines: 3,
|
||||
softWrap: true,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
|
||||
// Company + Vehicle Reg No
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
|
||||
@ -86,31 +86,57 @@ class BrokerListState extends ConsumerState<BrokerList> {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void filterData(String query) {
|
||||
setState(() {
|
||||
final q = query.toLowerCase();
|
||||
final q = query.toLowerCase().trim();
|
||||
|
||||
if (q.isEmpty) {
|
||||
filteredData = getBrokerData;
|
||||
filteredData = List.from(getBrokerData);
|
||||
return;
|
||||
}
|
||||
|
||||
filteredData = getBrokerData.where((item) {
|
||||
final isActiveStatus = item['is_active'] == "1" ? "active" : "inactive";
|
||||
final name =
|
||||
(item['name'] ?? '').toString().toLowerCase();
|
||||
final code =
|
||||
(item['short_name'] ?? '').toString().toLowerCase();
|
||||
final status =
|
||||
item['is_active'] == "1" ? "active" : "inactive";
|
||||
|
||||
return (item['name'] ?? '').toString().toLowerCase().contains(q) ||
|
||||
(item['email'] ?? '').toString().toLowerCase().contains(q) ||
|
||||
(item['mobile'] ?? '').toString().toLowerCase().contains(q) ||
|
||||
(item['address'] ?? '').toString().toLowerCase().contains(q) ||
|
||||
(item['emp_id'] ?? item['agent_code'] ?? '')
|
||||
.toString()
|
||||
.toLowerCase()
|
||||
.contains(q) ||
|
||||
isActiveStatus.contains(q);
|
||||
return name.contains(q) ||
|
||||
code.contains(q) ||
|
||||
status.contains(q);
|
||||
}).toList();
|
||||
// currentPage = 1;
|
||||
});
|
||||
}
|
||||
|
||||
// void filterData(String query) {
|
||||
// setState(() {
|
||||
// final q = query.toLowerCase();
|
||||
//
|
||||
// if (q.isEmpty) {
|
||||
// filteredData = getBrokerData;
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// filteredData = getBrokerData.where((item) {
|
||||
// final isActiveStatus = item['is_active'] == "1" ? "active" : "inactive";
|
||||
//
|
||||
// return (item['name'] ?? '').toString().toLowerCase().contains(q) ||
|
||||
// (item['email'] ?? '').toString().toLowerCase().contains(q) ||
|
||||
// (item['mobile'] ?? '').toString().toLowerCase().contains(q) ||
|
||||
// (item['address'] ?? '').toString().toLowerCase().contains(q) ||
|
||||
// (item['emp_id'] ?? item['agent_code'] ?? '')
|
||||
// .toString()
|
||||
// .toLowerCase()
|
||||
// .contains(q) ||
|
||||
// isActiveStatus.contains(q);
|
||||
// }).toList();
|
||||
// });
|
||||
// }
|
||||
|
||||
final TextEditingController _searchStaffController = TextEditingController();
|
||||
|
||||
Future<void> getBroker() async {
|
||||
|
||||
@ -311,6 +311,28 @@ class EndorsementTypeState extends ConsumerState<EndorsementType> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildPolicyFrom() {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text("Policy Type *", style: _textStyle),
|
||||
SizedBox(width: 10),
|
||||
SizedBox(
|
||||
child: ThemedFormInlineField(
|
||||
controller: controllers['policy_from']!,
|
||||
validator: (value) => Validators.requiredField(value, "policy_from"),
|
||||
txtwidth: MediaQuery.of(context).size.width * 0.15,
|
||||
borderColor: Color(0xFFE2E8F0),
|
||||
highlightColor: Color(0xFF50A398),
|
||||
// txtheight: 30,
|
||||
isdense: true,
|
||||
errFieldHgt: 0,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
static final _textStyle = GoogleFonts.inter(
|
||||
fontSize: 11,
|
||||
fontWeight: FontWeight.w600,
|
||||
|
||||
@ -144,7 +144,7 @@ class AttendanceAllDetailsState extends ConsumerState<AttendanceAllDetails> {
|
||||
try {
|
||||
final response = await apiService.fetchAttndanceOFAllStaffList(
|
||||
month: monthForApi,
|
||||
mangerId: managerId,
|
||||
mangerId: ref.read(managerIdProvider),
|
||||
// toDate: controllers['endDate']?.text ?? '',
|
||||
);
|
||||
|
||||
|
||||
@ -71,7 +71,7 @@ class AgentState extends ConsumerState<Agent> {
|
||||
dynamic role;
|
||||
|
||||
bool isLoading = false;
|
||||
String? selectedSalesExectv;
|
||||
dynamic selectedSalesExectv;
|
||||
List<Map<String, dynamic>> filteredSalesExecutiveData = [];
|
||||
List<Map<String, dynamic>> getSalesExecutiveData = [];
|
||||
|
||||
@ -170,7 +170,10 @@ class AgentState extends ConsumerState<Agent> {
|
||||
controllers['address']?.text = data['address'] ?? '';
|
||||
controllers['retenRate']?.text = data['retention_rate'] ?? '';
|
||||
isActive = data["is_active"];
|
||||
selectedSalesExectv = data['sales_executive_id'] ?? '';
|
||||
selectedSalesExectv = data['sales_executive_id'] != null
|
||||
? int.parse(data['sales_executive_id'].toString())
|
||||
: null;
|
||||
|
||||
print('selectedSalesExectv - $selectedSalesExectv');
|
||||
|
||||
String? apiDocPath = data["certificate_file_name"];
|
||||
@ -205,9 +208,10 @@ class AgentState extends ConsumerState<Agent> {
|
||||
return;
|
||||
}
|
||||
|
||||
print("Debug: current selectedSalesExectv is $selectedSalesExectv");
|
||||
|
||||
setState(() {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
dataDetails();
|
||||
final dataSet = dataDetails();
|
||||
print("dataSetAgent - $dataSet");
|
||||
print("managerId - $managerId ,userId - $userId ");
|
||||
@ -602,6 +606,10 @@ class AgentState extends ConsumerState<Agent> {
|
||||
ThemedFormField(
|
||||
controller: controllers['name']!,
|
||||
validator: (value) => Validators.requiredField(value, "name"),
|
||||
inputFormatters: [
|
||||
// This line now allows letters, numbers, hyphens, and underscores
|
||||
FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z0-9\-_]')),
|
||||
],
|
||||
borderColor: Color(0xFFE2E8F0),
|
||||
highlightColor: Color(0xFF50A398),
|
||||
txtwidth: MediaQuery.of(context).size.width * 0.18,
|
||||
@ -872,18 +880,12 @@ class AgentState extends ConsumerState<Agent> {
|
||||
// constraints: BoxConstraints(),
|
||||
),
|
||||
|
||||
onChanged: widget.id != null
|
||||
? null
|
||||
: (val) {
|
||||
if (val != null) {
|
||||
print("Selected Role : ${val['role']}");
|
||||
print("Id: ${val['id']}");
|
||||
selectedSalesExectv = val['id'];
|
||||
}
|
||||
|
||||
// controllers['agentId']?.text = val['agent_code'];
|
||||
// agentId = agent['id'];
|
||||
},
|
||||
onChanged: (val) {
|
||||
setState(() {
|
||||
selectedSalesExectv = val?['id']?.toString();
|
||||
});
|
||||
print("UI Updated with ID: $selectedSalesExectv");
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@ -147,9 +147,9 @@ class _DashboardState extends ConsumerState<PartnerDashboard> {
|
||||
if (data is Map<String, dynamic>) {
|
||||
setState(() {
|
||||
// agents_performance Policy
|
||||
if (data['monthlyPolicyCount'] != null) {
|
||||
if (data['agentsPerformanceList'] != null) {
|
||||
agentsPerformanceList = List<Map<String, dynamic>>.from(
|
||||
(data['monthlyPolicyCount'] as List).map(
|
||||
(data['agentsPerformanceList'] as List).map(
|
||||
(item) => Map<String, dynamic>.from(item),
|
||||
),
|
||||
);
|
||||
@ -163,17 +163,17 @@ class _DashboardState extends ConsumerState<PartnerDashboard> {
|
||||
);
|
||||
}
|
||||
|
||||
if (data['noPolicyTimeRange'] != null) {
|
||||
if (data['nonAgentsPerformanceList'] != null) {
|
||||
nonAgentsPerformanceList = List<Map<String, dynamic>>.from(
|
||||
(data['noPolicyTimeRange'] as List).map(
|
||||
(data['nonAgentsPerformanceList'] as List).map(
|
||||
(item) => Map<String, dynamic>.from(item),
|
||||
),
|
||||
);
|
||||
} // agents_performance Premium
|
||||
|
||||
if (data['below50tPremiumTimeRange'] != null) {
|
||||
if (data['nonAgentsPerformanceListPremium'] != null) {
|
||||
nonAgentsPerformanceListPremium = List<Map<String, dynamic>>.from(
|
||||
(data['below50tPremiumTimeRange'] as List).map(
|
||||
(data['nonAgentsPerformanceListPremium'] as List).map(
|
||||
(item) => Map<String, dynamic>.from(item),
|
||||
),
|
||||
);
|
||||
@ -345,7 +345,7 @@ class _DashboardState extends ConsumerState<PartnerDashboard> {
|
||||
InkWell(
|
||||
onTap: () async {
|
||||
final path =
|
||||
"PerformingAgentAll50";
|
||||
"PerformingTop50";
|
||||
final id = '';
|
||||
final month = 'current';
|
||||
|
||||
@ -714,7 +714,7 @@ class _PerformanceState extends State<Performance> {
|
||||
if (widget.title == 'Performing Partner') ...[
|
||||
InkWell(
|
||||
onTap: () async {
|
||||
final path1 = 'PerformingTop50';
|
||||
final path1 = 'PerformingAgentsByID';
|
||||
final path2 = widget.isPerfomingAgntPolicy
|
||||
? "NoBusiness"
|
||||
: "NonPerformingBelow50K";
|
||||
|
||||
@ -190,7 +190,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||
"assigned_to": selectedStaff,
|
||||
"insurer_id": selectedInsurer,
|
||||
"broker_id": selectedBroker,
|
||||
"manager_id": managerId,
|
||||
"manager_id": ref.read(managerIdProvider),
|
||||
"created_by": userId,
|
||||
};
|
||||
|
||||
@ -610,10 +610,11 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||
String SelectedStatus = '',
|
||||
String SelectedStaffId = '',
|
||||
}) async {
|
||||
print('DAJJshA72 => Fns called => $managerId | $role');
|
||||
print('A613 => Fns called => $managerId | $role');
|
||||
setState(() {
|
||||
isLoadingStaffList = true;
|
||||
});
|
||||
print('A713 => Fns called => $managerId | $role');
|
||||
|
||||
dynamic fromDt;
|
||||
dynamic toDt;
|
||||
@ -625,7 +626,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||
if (dashboardKey == 'fromDashboard' && SelectedStatus == "PrevPending") {
|
||||
// For PREV PENDING → set date range until yesterday
|
||||
final today = DateTime.now();
|
||||
|
||||
print('A813 => Fns called => $managerId | $role');
|
||||
// Change to dd-MM-yyyy
|
||||
final dateFormat = DateFormat('dd-MM-yyyy');
|
||||
|
||||
@ -640,7 +641,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||
SelectedStatus != '') {
|
||||
// For PREV PENDING → set date range until yesterday
|
||||
final today = DateTime.now();
|
||||
|
||||
print('A913 => Fns called => $managerId | $role');
|
||||
// Change to dd-MM-yyyy
|
||||
final dateFormat = DateFormat('dd-MM-yyyy');
|
||||
|
||||
@ -652,6 +653,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||
fromDateVal == '' &&
|
||||
toDateVal == '') {
|
||||
print("ENQ LIST PAGE");
|
||||
print('A1013 => Fns called => $managerId | $role');
|
||||
|
||||
final today = DateTime.now();
|
||||
fromDt = dateFormat.format(today.subtract(Duration(days: 5)));
|
||||
@ -660,6 +662,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||
|
||||
print('Enq FROM TO - $fromDt - $toDt');
|
||||
} else {
|
||||
print('A1113 => Fns called => $managerId | $role');
|
||||
print('Enq 1- $fromDt - $toDt');
|
||||
fromDt = fromDateVal;
|
||||
toDt = toDateVal;
|
||||
@ -668,6 +671,8 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||
String finalStatus = SelectedStatus;
|
||||
print('finalStatus1 - $finalStatus');
|
||||
|
||||
print('A1213 => Fns called => $managerId | $role');
|
||||
|
||||
try {
|
||||
final response = await apiService.fetchEnquiryList(
|
||||
managerId,
|
||||
@ -692,6 +697,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||
|
||||
print('FromDate : $fromDate');
|
||||
print('ToDate : $toDate');
|
||||
print('A1213 => Fns called => $managerId | $role');
|
||||
|
||||
setState(() {
|
||||
controllers['startDate']?.text = fromDate;
|
||||
|
||||
@ -534,7 +534,7 @@ class policylistState extends ConsumerState<policylist> {
|
||||
await fetchPolicyExcelReport();
|
||||
},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(4.0),
|
||||
padding: const EdgeInsets.all(7.0),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFF2E7D6E),
|
||||
// color: const Color(0xFF425B5B),
|
||||
@ -545,8 +545,8 @@ class policylistState extends ConsumerState<policylist> {
|
||||
children: [
|
||||
Image.asset(
|
||||
"assets/miscellaneous/export.png",
|
||||
height: 15,
|
||||
width: 15,
|
||||
height: 13,
|
||||
width: 13,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Loading…
Reference in New Issue
Block a user