policy tracker fix

This commit is contained in:
venbaittech 2025-12-24 17:46:51 +05:30
parent 10e5751367
commit 7a6ec262b7
5 changed files with 327 additions and 99 deletions

View File

@ -527,7 +527,7 @@ class _DateFilterRowState extends ConsumerState<DateFilterRowPayout> {
SizedBox(height: 5),
SizedBox(
height: 35,
width: MediaQuery.of(context).size.width * 0.42,
width: MediaQuery.of(context).size.width * 0.4,
child: DropdownSearch<Map<String, dynamic>>.multiSelection(
key: dropDownKeyPartner,
@ -567,7 +567,7 @@ class _DateFilterRowState extends ConsumerState<DateFilterRowPayout> {
decoratorProps: DropDownDecoratorProps(
decoration:
AppInputDecorations.dropdownDecoration(
label: "Select Partner",
label: "Select Referer",
).copyWith(
hintStyle: GoogleFonts.inter(
fontSize: 12,
@ -608,7 +608,7 @@ class _DateFilterRowState extends ConsumerState<DateFilterRowPayout> {
decoration: InputDecoration(
filled: true,
fillColor: Colors.white,
hintText: "Search Partner...",
hintText: "Search Referer...",
hintStyle: GoogleFonts.inter(
fontSize: 11,
color: Colors.black,

View File

@ -15,6 +15,7 @@ import '../../layouts/responsive_layout.dart';
import '../../providers/manager_provider.dart';
import '../../providers/userRoleProvider.dart';
import '../../themes/indicators/input_field_decoration.dart';
import '../../themes/indicators/search_field_theme.dart';
import 'FormFieldBox.dart';
import 'custom_dateRange.dart';
@ -44,6 +45,10 @@ class _PayOutScreenState extends ConsumerState<PayOutScreen> {
dynamic totalCommission = '0';
bool isEdit = false;
List<Map<String, dynamic>> masterPolicies = [];
final TextEditingController _searchStaffController = TextEditingController();
final GlobalKey<DropdownSearchState<Map<String, dynamic>>> dropDownKeyPOS =
GlobalKey<DropdownSearchState<Map<String, dynamic>>>();
@ -136,6 +141,45 @@ class _PayOutScreenState extends ConsumerState<PayOutScreen> {
}
}
void filterPolicyData(String query) {
final lowerQuery = query.toLowerCase();
print('filterPolicyData - $lowerQuery');
print('filteredPolicies1 - $filteredPolicies');
setState(() {
if (query.trim().isEmpty) {
print('filteredPolicies2');
filteredPolicies = List.from(masterPolicies);
return;
}
print('filteredPolicies3');
filteredPolicies = masterPolicies.where((item) {
return (item['policy_no'] ?? '').toString().toLowerCase().contains(
lowerQuery,
) ||
(item['customer_name'] ?? '').toString().toLowerCase().contains(
lowerQuery,
) ||
(item['agent_name'] ?? '').toString().toLowerCase().contains(
lowerQuery,
) ||
(item['insurer_name'] ?? '').toString().toLowerCase().contains(
lowerQuery,
) ||
(item['premium_amount'] ?? '').toString().toLowerCase().contains(
lowerQuery,
) ||
(item['commission_amount'] ?? '').toString().toLowerCase().contains(
lowerQuery,
) ||
(_formatDate(item['issued_date']) ?? '').toLowerCase().contains(
lowerQuery,
);
}).toList();
});
}
Future<void> getPosList(int id) async {
print('E104 => Fns called => $id');
@ -224,6 +268,7 @@ class _PayOutScreenState extends ConsumerState<PayOutScreen> {
.map((e) => Map<String, dynamic>.from(e))
.toList();
masterPolicies = List<Map<String, dynamic>>.from(response['data']);
filteredPolicies = List<Map<String, dynamic>>.from(response['data']);
print("selectedPolicies → $filteredPolicies ");
@ -678,7 +723,8 @@ class _PayOutScreenState extends ConsumerState<PayOutScreen> {
),
),
// SizedBox(width: 10),
Spacer(),
// Spacer(),
SizedBox(width: 10),
Text(
'Status: ${isPending ? 'Pending' : 'Completed'}',
style: GoogleFonts.inter(
@ -690,6 +736,22 @@ class _PayOutScreenState extends ConsumerState<PayOutScreen> {
// : const Color(0xFF047857),
),
),
Spacer(),
ThemedSearchField(
hintText: 'Search',
// backgroundColor: Color(0xFFF6F8F8),
onChanged: filterPolicyData,
controller: _searchStaffController,
backgroundColor: Color(0xFFFFFFFF),
txtHeight: 30,
txtwidth: ResponsiveLayout.isMobile(context)
? MediaQuery.of(context).size.width * 0.7
: MediaQuery.of(context).size.width * 0.15,
),
],
if (!isEdit) ...[

View File

@ -0,0 +1,92 @@
import 'package:dropdown_search/dropdown_search.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:http/http.dart' as http;
import 'package:intl/intl.dart';
import 'package:pdf_render/pdf_render_widgets.dart';
import 'dart:typed_data';
import 'package:flutter/services.dart';
// ============= KEY FIX: Separate PDF Viewer Widget =============
class PolicyPdfViewer extends StatefulWidget {
final String? pdfUrl;
const PolicyPdfViewer({Key? key, this.pdfUrl}) : super(key: key);
@override
State<PolicyPdfViewer> createState() => _PolicyPdfViewerState();
}
class _PolicyPdfViewerState extends State<PolicyPdfViewer>
with AutomaticKeepAliveClientMixin {
@override
bool get wantKeepAlive => true; // Prevents rebuilding
// Cache the loaded PDF bytes
Uint8List? _cachedPdfBytes;
String? _lastLoadedUrl;
Future<Uint8List> _loadPdf() async {
// Return cached bytes if URL hasn't changed
if (_cachedPdfBytes != null && _lastLoadedUrl == widget.pdfUrl) {
return _cachedPdfBytes!;
}
// Load new PDF
final response = await http.get(Uri.parse(widget.pdfUrl!));
if (response.statusCode == 200) {
_cachedPdfBytes = response.bodyBytes;
_lastLoadedUrl = widget.pdfUrl;
return _cachedPdfBytes!;
} else {
throw Exception('Failed to load PDF: ${response.statusCode}');
}
}
@override
Widget build(BuildContext context) {
super.build(context); // Required for AutomaticKeepAliveClientMixin
if (widget.pdfUrl == null) {
return const Center(child: CircularProgressIndicator());
}
return FutureBuilder<Uint8List>(
key: ValueKey(widget.pdfUrl), // Only rebuild if URL changes
future: _loadPdf(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(child: CircularProgressIndicator());
}
if (snapshot.hasError) {
return Center(child: Text('Error: ${snapshot.error}'));
}
if (!snapshot.hasData) {
return const Center(child: CircularProgressIndicator());
}
return PdfDocumentLoader.openData(
snapshot.data!,
documentBuilder: (context, pdfDocument, pageCount) {
return ListView.builder(
itemCount: pageCount,
itemBuilder: (context, index) {
return Container(
color: Colors.black12,
child: PdfPageView(
pdfDocument: pdfDocument,
pageNumber: index + 1,
),
);
},
);
},
);
},
);
}
}

View File

@ -866,7 +866,7 @@ class policylistState extends ConsumerState<policylist> {
? 'Verified'
: 'To Verify',
child: Container(
width: 80, // FIXED WIDTH Equal in both states
width: 30, // FIXED WIDTH Equal in both states
padding: const EdgeInsets.symmetric(
horizontal: 8,
vertical: 4,

View File

@ -4,6 +4,8 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:http/http.dart' as http;
import 'package:intl/intl.dart';
import 'package:nhance_partner/presentation/screens/staff/policy/policyPdf.dart';
import 'package:pdf_render/pdf_render_widgets.dart';
import 'package:syncfusion_flutter_pdfviewer/pdfviewer.dart';
@ -41,6 +43,7 @@ class _policyValidationState extends ConsumerState<policyValidation> {
dynamic managerId;
dynamic userId;
String? _cachedPdfUrl;
String? pdfUrl; // full file path from API
// --- Controllers (all editable fields)
@ -110,6 +113,8 @@ class _policyValidationState extends ConsumerState<policyValidation> {
final GlobalKey<DropdownSearchState<Map<String, dynamic>>> dropDownKeyFuel =
GlobalKey<DropdownSearchState<Map<String, dynamic>>>();
bool _hasLoadedInitialData = false;
Map<String, dynamic> dataDetails() {
return {
"rc_no": controllers["rcNo"]?.text,
@ -244,28 +249,50 @@ class _policyValidationState extends ConsumerState<policyValidation> {
for (final key in controllerKeys) key: TextEditingController(),
};
update();
_loadInitialData();
// read providers + call APIs
Future.microtask(() {
try {
managerId = ref.read(managerIdProvider);
} catch (e) {
managerId = null;
}
try {
userId = ref.read(userIdProvider);
} catch (e) {
userId = null;
}
// Future.microtask(() {
// try {
// managerId = ref.read(managerIdProvider);
// } catch (e) {
// managerId = null;
// }
// try {
// userId = ref.read(userIdProvider);
// } catch (e) {
// userId = null;
// }
//
// getVehicleType();
// getFuelType();
// getFindPolicy();
// getPolicyFilePath();
// });
getFindPolicy();
getVehicleType();
getFuelType();
getPolicyFilePath();
});
// controllers['commission_amount']?.addListener(() {
// setState(() {});
// });
}
controllers['commission_amount']?.addListener(() {
setState(() {});
});
Future<void> _loadInitialData() async {
print('_loadInitialData');
try {
managerId = ref.read(managerIdProvider);
} catch (e) {
managerId = null;
}
try {
userId = ref.read(userIdProvider);
} catch (e) {
userId = null;
}
await Future.wait([
getFindPolicy(),
getVehicleType(),
getFuelType(),
getPolicyFilePath(),
]);
}
@override
@ -361,6 +388,7 @@ class _policyValidationState extends ConsumerState<policyValidation> {
setState(() {
pdfUrl = "$url";
_cachedPdfUrl = pdfUrl;
});
print("FINAL PDF URL -> $pdfUrl");
} catch (e, st) {
@ -416,7 +444,7 @@ class _policyValidationState extends ConsumerState<policyValidation> {
// controllers["startDate"]!.text = safeText(data['start_date']);
// controllers["endDate"]!.text = safeText(data['end_date']);
controllers["issueDate"]?.text = fixInvalidDate(data['issued_date']);
controllers["issuedDate"]?.text = fixInvalidDate(data['issued_date']);
controllers["startDate"]?.text = fixInvalidDate(data['start_date']);
controllers["endDate"]?.text = fixInvalidDate(data['end_date']);
@ -451,6 +479,10 @@ class _policyValidationState extends ConsumerState<policyValidation> {
selectedInsuranceId = safeText(data['insurer_id']);
selectedAgentRentionRate = safeText(data['agent_retention_rate']);
selectedManagerRentionRate = safeText(data['manager_retention_rate']);
controllers["commission_amount"]?.text = safeText(
data['commission_amount'],
);
});
debugPrint('findPolicyApi response3:');
@ -553,6 +585,15 @@ class _policyValidationState extends ConsumerState<policyValidation> {
}
}
DateTime? parseDate(String? value) {
if (value == null || value.isEmpty) return null;
try {
return DateFormat('dd-MM-yyyy').parse(value); // change format if required
} catch (_) {
return null;
}
}
Future<void> _fetchCommision() async {
print('_fetchCommision IN');
final policyId = widget.item?['policy_id'];
@ -562,6 +603,17 @@ class _policyValidationState extends ConsumerState<policyValidation> {
return;
}
final startDate = parseDate(controllers["startDate"]?.text);
final endDate = parseDate(controllers["endDate"]?.text);
if (startDate != null && endDate != null && startDate.isAfter(endDate)) {
ToastHelper.showWarningToast(
context,
'Start Date cannot be greater than End Date',
);
return;
}
if (!_formKey.currentState!.validate()) {
ToastHelper.showWarningToast(context, "Please fill all required fields");
return;
@ -822,11 +874,11 @@ class _policyValidationState extends ConsumerState<policyValidation> {
onChanged: (val) {
if (val != null) {
setState(() {
selectedVehicleType = val;
controllers['vehicleType']?.text = val;
});
// setState(() {
selectedVehicleType = val;
controllers['vehicleType']?.text = val;
// });
setState(() {});
print("Selected Vehicle Type: $val");
}
},
@ -927,11 +979,11 @@ class _policyValidationState extends ConsumerState<policyValidation> {
onChanged: (val) {
if (val != null) {
setState(() {
selectedFuelType = val;
controllers['fuelType']?.text = val;
});
// setState(() {
selectedFuelType = val;
controllers['fuelType']?.text = val;
// });
setState(() {});
print("Selected Fuel Type: $val");
}
},
@ -1187,60 +1239,62 @@ class _policyValidationState extends ConsumerState<policyValidation> {
),
),
const SizedBox(height: 8),
Expanded(
child: FutureBuilder<Uint8List>(
future: loadNetworkPdfBytes(pdfUrl!),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return const Center(
child: CircularProgressIndicator(),
);
}
final pdfBytes = snapshot.data!;
return PdfDocumentLoader.openData(
pdfBytes,
documentBuilder:
(context, pdfDocument, pageCount) {
return ListView.builder(
itemCount: pageCount,
itemBuilder: (context, index) {
return Container(
color: Colors.black12,
child: PdfPageView(
pdfDocument: pdfDocument,
pageNumber: index + 1,
),
);
},
);
},
);
},
),
child: PolicyPdfViewer(
pdfUrl: pdfUrl,
), // 👈 Use separate widget
),
// Expanded(
// child: PdfDocumentLoader.openAsset(
// 'assets/pdfs/sample.pdf',
// documentBuilder: (context, pdfDocument, pageCount) => LayoutBuilder(
// builder: (context, constraints) => ListView.builder(
// itemCount: pageCount,
// itemBuilder: (context, index) => Container(
// // margin: EdgeInsets.all(margin),
// // padding: EdgeInsets.all(padding),
// color: Colors.black12,
// child: PdfPageView(
// pdfDocument: pdfDocument,
// pageNumber: index + 1,
// )
// )
// )
// ),
// )
// )
// child: pdfUrl == null
// ? Center(child: CircularProgressIndicator())
// : FutureBuilder<Uint8List>(
// key: ValueKey(
// _cachedPdfUrl,
// ), // 👈 Add this key
// future: loadNetworkPdfBytes(
// _cachedPdfUrl!,
// ),
// // future: loadNetworkPdfBytes(pdfUrl!),
// builder: (context, snapshot) {
// if (!snapshot.hasData) {
// return const Center(
// child:
// CircularProgressIndicator(),
// );
// }
//
// final pdfBytes = snapshot.data!;
//
// return PdfDocumentLoader.openData(
// pdfBytes,
// documentBuilder:
// (
// context,
// pdfDocument,
// pageCount,
// ) {
// return ListView.builder(
// itemCount: pageCount,
// itemBuilder:
// (context, index) {
// return Container(
// color:
// Colors.black12,
// child: PdfPageView(
// pdfDocument:
// pdfDocument,
// pageNumber:
// index + 1,
// ),
// );
// },
// );
// },
// );
// },
// ),
// ),
],
),
),
@ -1344,10 +1398,7 @@ class _policyValidationState extends ConsumerState<policyValidation> {
),
),
),
],
),
Row(
children: [
const SizedBox(width: 8),
Expanded(
child: _buildInput(
'Premium Amount *',
@ -1362,16 +1413,34 @@ class _policyValidationState extends ConsumerState<policyValidation> {
decimalFormatter,
),
),
const SizedBox(width: 8),
Expanded(
child: _buildInput(
'Remarks *',
required: false,
controllers['remarks']!,
),
),
],
),
// Row(
// children: [
// Expanded(
// child: _buildInput(
// 'Premium Amount *',
// controllers['premiumAmount']!,
//
// required: true,
// keyboardType:
// TextInputType.numberWithOptions(
// decimal: true,
// ),
// inputFormatters:
// decimalFormatter,
// ),
// ),
// const SizedBox(width: 8),
// // Expanded(
// // child: _buildInput(
// // 'Remarks *',
// // required: false,
// // controllers['remarks']!,
// // ),
// // ),
// ],
// ),
],
),
),
@ -1579,8 +1648,13 @@ class _policyValidationState extends ConsumerState<policyValidation> {
required: true,
keyboardType:
TextInputType.number,
inputFormatters:
digitsOnlyFormatter,
inputFormatters: [
FilteringTextInputFormatter
.digitsOnly, // only numbers
LengthLimitingTextInputFormatter(
4,
), // max 4 digits
],
),
),
],