nhance_partner/lib/presentation/screens/staff/policy/policy_validation_old.dart
2025-12-19 18:42:42 +05:30

1356 lines
60 KiB
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' as http;
import 'package:pdf_render/pdf_render_widgets.dart';
import 'package:syncfusion_flutter_pdfviewer/pdfviewer.dart';
import '../../../../core/config/env.dart';
import '../../../../core/services/api_service.dart';
import '../../../../data/utils/toastNotification.dart';
import '../../../providers/manager_provider.dart';
import 'loadNetworkPdfBytes.dart';
import 'dart:typed_data';
// /// Represents Homepage for Navigation
// class policyValidation extends ConsumerStatefulWidget {
// final dynamic item;
// const policyValidation({Key? key, this.item}) : super(key: key);
//
// @override
// ConsumerState<policyValidation> createState() => _policyValidationState();
// }
//
// class _policyValidationState extends ConsumerState<policyValidation> {
// final GlobalKey<SfPdfViewerState> _pdfViewerKey = GlobalKey();
//
// @override
// void initState() {
// super.initState();
// }
//
// @override
// Widget build(BuildContext context) {
// return Scaffold(
// appBar: AppBar(
// title: const Text('Syncfusion Flutter PDF Viewer'),
// actions: <Widget>[
// IconButton(
// icon: const Icon(
// Icons.bookmark,
// color: Colors.white,
// semanticLabel: 'Bookmark',
// ),
// onPressed: () {
// _pdfViewerKey.currentState?.openBookmarkView();
// },
// ),
// ],
// ),
// body: SfPdfViewer.asset(
// 'assets/pdfs/sample.pdf',
// key: _pdfViewerKey,
// )
// );
// }
// }
import 'package:flutter/services.dart';
final digitsOnlyFormatter = [FilteringTextInputFormatter.digitsOnly];
final decimalFormatter = [
FilteringTextInputFormatter.allow(RegExp(r'^\d*\.?\d{0,2}$')),
];
class policyValidation extends ConsumerStatefulWidget {
final dynamic item;
const policyValidation({Key? key, this.item}) : super(key: key);
@override
ConsumerState<policyValidation> createState() => _policyValidationState();
}
class _policyValidationState extends ConsumerState<policyValidation> {
// --- Api / state
late ApiService apiService;
bool isLoading = false;
dynamic managerId;
dynamic userId;
String? pdfUrl; // full file path from API
// --- Controllers (all editable fields)
late TextEditingController policyNumberController;
late TextEditingController insuredNameController;
late TextEditingController premiumController;
late TextEditingController remarksController;
late TextEditingController rcNoController;
late TextEditingController issuedDateController;
late TextEditingController startDateController;
late TextEditingController endDateController;
late TextEditingController tpController;
late TextEditingController odController;
late TextEditingController paController;
late TextEditingController cgstController;
late TextEditingController sgstController;
late TextEditingController igstController;
late TextEditingController rtoStateCodeController;
late TextEditingController rtoCityCodeController;
late TextEditingController weightController;
late TextEditingController fuelTypeController;
late TextEditingController registrationDateController;
late TextEditingController yomController;
late TextEditingController engineNoController;
late TextEditingController chassisNoController;
late TextEditingController makeController;
late TextEditingController modelController;
late TextEditingController cubicCapacityController;
late TextEditingController vehicleTypeController;
late TextEditingController brokerNameController;
late TextEditingController commissionAmountController;
final GlobalKey<SfPdfViewerState> _pdfViewerKey = GlobalKey();
final _formKey = GlobalKey<FormState>();
@override
void initState() {
super.initState();
apiService = ApiService();
// instantiate controllers with defaults
policyNumberController = TextEditingController();
insuredNameController = TextEditingController();
premiumController = TextEditingController();
remarksController = TextEditingController();
rcNoController = TextEditingController();
issuedDateController = TextEditingController();
startDateController = TextEditingController();
endDateController = TextEditingController();
tpController = TextEditingController();
odController = TextEditingController();
paController = TextEditingController();
cgstController = TextEditingController();
sgstController = TextEditingController();
igstController = TextEditingController();
rtoStateCodeController = TextEditingController();
rtoCityCodeController = TextEditingController();
weightController = TextEditingController();
fuelTypeController = TextEditingController();
registrationDateController = TextEditingController();
yomController = TextEditingController();
engineNoController = TextEditingController();
chassisNoController = TextEditingController();
makeController = TextEditingController();
modelController = TextEditingController();
cubicCapacityController = TextEditingController();
vehicleTypeController = TextEditingController();
brokerNameController = TextEditingController();
commissionAmountController = TextEditingController();
// Pre-fill controllers from initial `widget.item` (if available)
final item = widget.item as Map<String, dynamic>? ?? {};
policyNumberController.text = item['policy_number']?.toString() ?? '';
insuredNameController.text = item['insured_name']?.toString() ?? '';
premiumController.text = item['premium_amount']?.toString() ?? '';
remarksController.text = item['remarks']?.toString() ?? '';
rcNoController.text = item['rc_no']?.toString() ?? '';
issuedDateController.text = item['issued_date']?.toString() ?? '';
startDateController.text = item['start_date']?.toString() ?? '';
endDateController.text = item['end_date']?.toString() ?? '';
tpController.text = item['tp']?.toString() ?? '';
odController.text = item['od']?.toString() ?? '';
paController.text = item['pa']?.toString() ?? '';
cgstController.text = item['cgst']?.toString() ?? '';
sgstController.text = item['sgst']?.toString() ?? '';
igstController.text = item['igst']?.toString() ?? '';
rtoStateCodeController.text = item['rto_state_code']?.toString() ?? '';
rtoCityCodeController.text = item['rto_city_code']?.toString() ?? '';
weightController.text = item['weight']?.toString() ?? '';
fuelTypeController.text = item['fuel_type']?.toString() ?? '';
registrationDateController.text =
item['date_of_registration']?.toString() ?? '';
yomController.text = item['year_of_manufacture']?.toString() ?? '';
engineNoController.text = item['engine_no']?.toString() ?? '';
chassisNoController.text = item['chassis_no']?.toString() ?? '';
makeController.text = item['make']?.toString() ?? '';
modelController.text = item['model']?.toString() ?? '';
cubicCapacityController.text = item['cubic_capacity']?.toString() ?? '';
vehicleTypeController.text = item['vehicle_type']?.toString() ?? '';
brokerNameController.text = item['broker_name']?.toString() ?? '';
commissionAmountController.text =
item['commission_amount']?.toString() ?? '';
// read providers + call APIs
Future.microtask(() {
try {
managerId = ref.read(managerIdProvider);
} catch (e) {
managerId = null;
}
try {
userId = ref.read(userIdProvider);
} catch (e) {
userId = null;
}
getFindPolicy();
getPolicyFilePath();
});
}
@override
void dispose() {
policyNumberController.dispose();
insuredNameController.dispose();
premiumController.dispose();
remarksController.dispose();
rcNoController.dispose();
issuedDateController.dispose();
startDateController.dispose();
endDateController.dispose();
tpController.dispose();
odController.dispose();
paController.dispose();
cgstController.dispose();
sgstController.dispose();
igstController.dispose();
rtoStateCodeController.dispose();
rtoCityCodeController.dispose();
weightController.dispose();
fuelTypeController.dispose();
registrationDateController.dispose();
yomController.dispose();
engineNoController.dispose();
chassisNoController.dispose();
makeController.dispose();
modelController.dispose();
cubicCapacityController.dispose();
vehicleTypeController.dispose();
brokerNameController.dispose();
commissionAmountController.dispose();
super.dispose();
}
Future<void> getPolicyFilePath() async {
_pdfViewerKey.currentState?.openBookmarkView();
final policyId = widget.item?['policy_id'];
if (policyId == null) {
debugPrint('policyValidation: policy id is null, skipping API call');
return;
}
if (!mounted) return;
setState(() => isLoading = true);
try {
final url = Uri.parse(
'${Env.apiUrl}policy/PolicyFilePath?policy_id=$policyId&file_type=policy_pdf',
);
setState(() {
pdfUrl = "$url";
});
print("FINAL PDF URL -> $pdfUrl");
} catch (e, st) {
print('Exception in getPolicyFilePath: $e\n$st');
} finally {
if (!mounted) return;
setState(() => isLoading = false);
}
}
Future<void> getFindPolicy() async {
final policyId = widget.item?['policy_id'];
if (policyId == null) {
debugPrint('policyValidation: policy id is null, skipping API call');
return;
}
if (!mounted) return;
setState(() => isLoading = true);
try {
final response = await apiService.findPolicyApi(policyId);
debugPrint('findPolicyApi response: $response');
if (response != null && response['status'] == 'success') {
final data = (response['data'] ?? {}) as Map<String, dynamic>;
if (!mounted) return;
setState(() {
// update controllers (overwrite with authoritative API values)
policyNumberController.text =
data['policy_number']?.toString() ?? policyNumberController.text;
insuredNameController.text =
data['insured_name']?.toString() ?? insuredNameController.text;
premiumController.text =
data['premium_amount']?.toString() ?? premiumController.text;
remarksController.text =
data['remarks']?.toString() ?? remarksController.text;
rcNoController.text =
data['rc_no']?.toString() ?? rcNoController.text;
issuedDateController.text =
data['issued_date']?.toString() ?? issuedDateController.text;
startDateController.text =
data['start_date']?.toString() ?? startDateController.text;
endDateController.text =
data['end_date']?.toString() ?? endDateController.text;
tpController.text = data['tp']?.toString() ?? tpController.text;
odController.text = data['od']?.toString() ?? odController.text;
paController.text = data['pa']?.toString() ?? paController.text;
cgstController.text = data['cgst']?.toString() ?? cgstController.text;
sgstController.text = data['sgst']?.toString() ?? sgstController.text;
igstController.text = data['igst']?.toString() ?? igstController.text;
rtoStateCodeController.text =
data['rto_state_code']?.toString() ?? rtoStateCodeController.text;
rtoCityCodeController.text =
data['rto_city_code']?.toString() ?? rtoCityCodeController.text;
weightController.text =
data['weight']?.toString() ?? weightController.text;
fuelTypeController.text =
data['fuel_type']?.toString() ?? fuelTypeController.text;
registrationDateController.text =
data['date_of_registration']?.toString() ??
registrationDateController.text;
yomController.text =
data['year_of_manufacture']?.toString() ?? yomController.text;
engineNoController.text =
data['engine_no']?.toString() ?? engineNoController.text;
chassisNoController.text =
data['chassis_no']?.toString() ?? chassisNoController.text;
makeController.text = data['make']?.toString() ?? makeController.text;
modelController.text =
data['model']?.toString() ?? modelController.text;
cubicCapacityController.text =
data['cubic_capacity']?.toString() ??
cubicCapacityController.text;
vehicleTypeController.text =
data['vehicle_type']?.toString() ?? vehicleTypeController.text;
brokerNameController.text =
data['broker_name']?.toString() ?? brokerNameController.text;
commissionAmountController.text =
data['commission_amount']?.toString() ??
commissionAmountController.text;
});
} else {
debugPrint(
'findPolicyApi returned error: ${response?['message'] ?? 'unknown'}',
);
}
} catch (e, st) {
debugPrint('Exception in getFindPolicy: $e\n$st');
} finally {
if (!mounted) return;
setState(() => isLoading = false);
}
}
Future<void> _pickDate(
TextEditingController controller,
BuildContext context,
) async {
DateTime initial = DateTime.now();
try {
if (controller.text.isNotEmpty) {
// try parse dd-MM-yyyy
final parts = controller.text.split('-');
if (parts.length == 3) {
final d = int.tryParse(parts[0]) ?? initial.day;
final m = int.tryParse(parts[1]) ?? initial.month;
final y = int.tryParse(parts[2]) ?? initial.year;
initial = DateTime(y, m, d);
}
}
} catch (_) {}
final picked = await showDatePicker(
context: context,
initialDate: initial,
firstDate: DateTime(1900),
lastDate: DateTime(2100),
);
if (picked != null) {
controller.text =
"${picked.day.toString().padLeft(2, '0')}-${picked.month.toString().padLeft(2, '0')}-${picked.year}";
}
}
Future<void> _save() async {
final policyId = widget.item?['policy_id'];
if (policyId == null) {
ToastHelper.showWarningToast(context, 'Missing policy id');
return;
}
if (!_formKey.currentState!.validate()) {
ToastHelper.showWarningToast(context, "Please fill all required fields");
return;
}
if (widget.item?['is_data_accuracy_checked'] == "1") {
ToastHelper.showWarningToast(context, "Data already confirmed");
return;
}
final payload = {
"id": policyId,
"rc_no": rcNoController.text,
"insured_name": insuredNameController.text,
"issued_date": issuedDateController.text,
"start_date": startDateController.text,
"end_date": endDateController.text,
"premium_amount": premiumController.text,
"policy_number": policyNumberController.text,
"tp": tpController.text.isEmpty ? null : tpController.text,
"od": odController.text.isEmpty ? null : odController.text,
"pa": paController.text.isEmpty ? null : paController.text,
"cgst": cgstController.text.isEmpty ? null : cgstController.text,
"sgst": sgstController.text.isEmpty ? null : sgstController.text,
"igst": igstController.text.isEmpty ? null : igstController.text,
"rto_state_code": rtoStateCodeController.text.isEmpty
? null
: rtoStateCodeController.text,
"rto_city_code": rtoCityCodeController.text.isEmpty
? null
: rtoCityCodeController.text,
"weight": weightController.text.isEmpty ? null : weightController.text,
"fuel_type": fuelTypeController.text.isEmpty
? null
: fuelTypeController.text,
"date_of_registration": registrationDateController.text.isEmpty
? null
: registrationDateController.text,
"year_of_manufacture": yomController.text.isEmpty
? null
: yomController.text,
"engine_no": engineNoController.text.isEmpty
? null
: engineNoController.text,
"chassis_no": chassisNoController.text.isEmpty
? null
: chassisNoController.text,
"make": makeController.text.isEmpty ? null : makeController.text,
"model": modelController.text.isEmpty ? null : modelController.text,
"cubic_capacity": cubicCapacityController.text.isEmpty
? null
: cubicCapacityController.text,
"vehicle_type": vehicleTypeController.text.isEmpty
? null
: vehicleTypeController.text,
"broker_name": brokerNameController.text.isEmpty
? null
: brokerNameController.text,
"commission_amount": commissionAmountController.text.isEmpty
? null
: commissionAmountController.text,
"updated_by": userId,
};
if (!mounted) return;
setState(() => isLoading = true);
try {
debugPrint('FINAL SAVE PAYLOAD => $payload');
final result = await apiService.updatePolicyApi(payload);
debugPrint('updatePolicy result => $result');
if (result != null && result['status'] == 'success') {
if (!mounted) return;
setState(() => isLoading = false);
context.pop();
ToastHelper.showSuccessToast(context, "Policy updated successfully");
WidgetsBinding.instance.addPostFrameCallback((_) {
// Now safe to do navigation + provider updates
final container = ProviderScope.containerOf(context);
container.read(policyDataAcurancyRefreshProvider.notifier).state =
true;
});
} else {
if (!mounted) return;
setState(() => isLoading = false);
ToastHelper.showErrorToast(
context,
result?['message']?.toString() ?? 'Error updating policy',
);
}
} catch (e, st) {
debugPrint('Exception in updatePolicy: $e\n$st');
if (!mounted) return;
setState(() => isLoading = false);
ToastHelper.showWarningToast(context, 'Exception: $e');
}
}
Future<void> _fetchCommision() async {
final policyId = widget.item?['policy_id'];
if (policyId == null) {
ToastHelper.showWarningToast(context, 'Missing policy id');
return;
}
if (!_formKey.currentState!.validate()) {
ToastHelper.showWarningToast(context, "Please fill all required fields");
return;
}
// if (widget.item?['is_data_accuracy_checked'] == "1") {
// ToastHelper.showWarningToast(context, "Data already confirmed");
// return;
// }
final payload = {
"id": policyId,
"rc_no": rcNoController.text,
"insured_name": insuredNameController.text,
"issued_date": issuedDateController.text,
"start_date": startDateController.text,
"end_date": endDateController.text,
"premium_amount": premiumController.text,
"policy_number": policyNumberController.text,
"tp": tpController.text.isEmpty ? null : tpController.text,
"od": odController.text.isEmpty ? null : odController.text,
"pa": paController.text.isEmpty ? null : paController.text,
"cgst": cgstController.text.isEmpty ? null : cgstController.text,
"sgst": sgstController.text.isEmpty ? null : sgstController.text,
"igst": igstController.text.isEmpty ? null : igstController.text,
"rto_state_code": rtoStateCodeController.text.isEmpty
? null
: rtoStateCodeController.text,
"rto_city_code": rtoCityCodeController.text.isEmpty
? null
: rtoCityCodeController.text,
"weight": weightController.text.isEmpty ? null : weightController.text,
"fuel_type": fuelTypeController.text.isEmpty
? null
: fuelTypeController.text,
"date_of_registration": registrationDateController.text.isEmpty
? null
: registrationDateController.text,
"year_of_manufacture": yomController.text.isEmpty
? null
: yomController.text,
"engine_no": engineNoController.text.isEmpty
? null
: engineNoController.text,
"chassis_no": chassisNoController.text.isEmpty
? null
: chassisNoController.text,
"make": makeController.text.isEmpty ? null : makeController.text,
"model": modelController.text.isEmpty ? null : modelController.text,
"cubic_capacity": cubicCapacityController.text.isEmpty
? null
: cubicCapacityController.text,
"vehicle_type": vehicleTypeController.text.isEmpty
? null
: vehicleTypeController.text,
"broker_name": brokerNameController.text.isEmpty
? null
: brokerNameController.text,
// "commission_amount": commissionAmountController.text.isEmpty
// ? null
// : commissionAmountController.text,
"updated_by": userId,
// "insurance_plan_type":
};
if (!mounted) return;
setState(() => isLoading = true);
try {
debugPrint('FINAL SAVE PAYLOAD => $payload');
final result = await apiService.calculateCommissionRequest(payload);
debugPrint('updatePolicy result => $result');
if (result != null && result['status'] == 'success') {
if (!mounted) return;
setState(() => isLoading = false);
// context.pop();
ToastHelper.showSuccessToast(context, "Policy updated successfully");
// WidgetsBinding.instance.addPostFrameCallback((_) {
// // Now safe to do navigation + provider updates
// final container = ProviderScope.containerOf(context);
// container.read(policyDataAcurancyRefreshProvider.notifier).state =
// true;
// });
} else {
if (!mounted) return;
setState(() => isLoading = false);
ToastHelper.showErrorToast(
context,
result?['message']?.toString() ?? 'Error updating policy',
);
}
} catch (e, st) {
debugPrint('Exception in updatePolicy: $e\n$st');
if (!mounted) return;
setState(() => isLoading = false);
ToastHelper.showWarningToast(context, 'Exception: $e');
}
}
Widget _sectionHeader(String title, {IconData icon = Icons.info}) {
return Container(
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 12),
decoration: BoxDecoration(
color: Color(0xFFE3F9F8),
borderRadius: BorderRadius.circular(6),
),
child: Row(
children: [
Container(
padding: const EdgeInsets.all(6),
decoration: const BoxDecoration(
color: Color(0xFF2E7D6E),
shape: BoxShape.circle,
),
child: Icon(icon, size: 16, color: Colors.white),
),
const SizedBox(width: 10),
Text(
title,
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600),
),
],
),
);
}
Widget _buildInput(
String label,
TextEditingController controller, {
TextInputType keyboardType = TextInputType.text,
bool readOnly = false,
VoidCallback? onTap,
bool required = false,
List<TextInputFormatter>? inputFormatters, // 👈 ADD THIS
}) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(label, style: const TextStyle(fontWeight: FontWeight.w500)),
const SizedBox(height: 6),
TextFormField(
controller: controller,
keyboardType: keyboardType,
readOnly: readOnly,
onTap: onTap,
inputFormatters: inputFormatters, // 👈 USE HERE
validator: (value) {
if (required && (value == null || value.trim().isEmpty)) {
return "$label is required";
}
return null;
},
decoration: InputDecoration(
border: OutlineInputBorder(borderRadius: BorderRadius.circular(6)),
isDense: true,
// alignment fix
helperText: ' ',
helperStyle: const TextStyle(height: 1),
errorMaxLines: 2,
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(6),
borderSide: const BorderSide(color: Colors.red),
),
focusedErrorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(6),
borderSide: const BorderSide(color: Colors.red),
),
contentPadding: const EdgeInsets.all(10),
),
),
],
);
}
@override
Widget build(BuildContext context) {
// Ensure global AppHeader remains visible by pushing content down by 64px
return SafeArea(
child: Scaffold(
backgroundColor: Color(0xffD9EBE8),
// ⭐ FIXED BUTTON FOOTER
bottomNavigationBar: Container(
padding: const EdgeInsets.all(16),
color: const Color(0xFFF7FBFA),
child: Row(
mainAxisAlignment: MainAxisAlignment.end, // 👉 move button to right
children: [
ElevatedButton(
onPressed: _fetchCommision,
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF2E7D6E),
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(
vertical: 10,
horizontal: 20, // 👉 smaller width
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
),
child: const Text(
'Fetch Commission',
style: TextStyle(fontSize: 14, fontWeight: FontWeight.w600),
),
),
SizedBox(width: 10),
ElevatedButton(
onPressed: widget.item?['is_data_accuracy_checked'] == '1'
? null
: _save,
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF2E7D6E),
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(
vertical: 10,
horizontal: 20, // 👉 smaller width
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
),
child: const Text(
'Confirm Data Accuracy',
style: TextStyle(fontSize: 14, fontWeight: FontWeight.w600),
),
),
],
),
),
body: Container(
// margin: const EdgeInsets.only(top: 64), // <-- keeps popup under global AppHeader
width: double.infinity,
// height: MediaQuery.of(context).size.height - 64,
color: const Color(0xFFF7FBFA),
child: Column(
children: [
// In-body header
Container(
height: 56,
color: Color(0xFFE3F9F8),
padding: const EdgeInsets.symmetric(horizontal: 12),
child: Row(
children: [
IconButton(
icon: const Icon(Icons.file_open),
onPressed: () => context.pop(),
),
const Expanded(
child: Text(
'Insurance Policy Review',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w600,
),
),
),
if (isLoading)
const SizedBox(
width: 12,
height: 12,
child: CircularProgressIndicator(strokeWidth: 2),
),
const SizedBox(width: 8),
IconButton(
icon: const Icon(Icons.close),
onPressed: () => context.pop(),
),
],
),
),
// Body: left PDF preview + right grouped form
Expanded(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Row(
children: [
// LEFT - PDF placeholder
Expanded(
flex: 1,
child: Container(
margin: const EdgeInsets.only(right: 12),
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
border: Border.all(color: Colors.grey.shade200),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Text(
'Original Policy Document',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
),
),
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,
),
);
},
);
},
);
},
),
),
// 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,
// )
// )
// )
// ),
// )
// )
],
),
),
),
// RIGHT - Grouped Form
Expanded(
flex: 1,
child: SingleChildScrollView(
child: Form(
key: _formKey,
autovalidateMode:
AutovalidateMode.onUserInteraction,
child: Card(
elevation: 2,
color: Colors.white,
margin: EdgeInsets.zero,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.stretch,
children: [
// Policy Details
Card(
elevation: 5,
color: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.stretch,
children: [
_sectionHeader(
'Policy Details',
icon: Icons.policy,
),
SizedBox(height: 10),
Row(
children: [
Expanded(
child: _buildInput(
'Policy Number',
policyNumberController,
required: true,
),
),
const SizedBox(width: 8),
Expanded(
child: _buildInput(
'Insured Name',
insuredNameController,
required: true,
),
),
],
),
Row(
children: [
Expanded(
child: _buildInput(
'Issued Date',
issuedDateController,
readOnly: true,
required: true,
onTap: () => _pickDate(
issuedDateController,
context,
),
),
),
const SizedBox(width: 8),
Expanded(
child: _buildInput(
'Start Date',
startDateController,
readOnly: true,
required: true,
onTap: () => _pickDate(
startDateController,
context,
),
),
),
const SizedBox(width: 8),
Expanded(
child: _buildInput(
'End Date',
endDateController,
readOnly: true,
required: true,
onTap: () => _pickDate(
endDateController,
context,
),
),
),
],
),
Row(
children: [
Expanded(
child: _buildInput(
'Premium Amount',
premiumController,
required: true,
keyboardType:
TextInputType.numberWithOptions(
decimal: true,
),
inputFormatters:
decimalFormatter,
),
),
const SizedBox(width: 8),
Expanded(
child: _buildInput(
'Remarks',
remarksController,
required: false,
),
),
],
),
],
),
),
),
const SizedBox(height: 12),
// Tax Details
Card(
elevation: 5,
color: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.stretch,
children: [
_sectionHeader(
'Tax / Cover Details',
icon: Icons.attach_money,
),
SizedBox(height: 10),
Row(
children: [
Expanded(
child: _buildInput(
'TP',
tpController,
required: true,
keyboardType:
TextInputType.numberWithOptions(
decimal: true,
),
inputFormatters:
decimalFormatter,
),
),
const SizedBox(width: 8),
Expanded(
child: _buildInput(
'OD',
odController,
required: true,
keyboardType:
TextInputType.numberWithOptions(
decimal: true,
),
inputFormatters:
decimalFormatter,
),
),
const SizedBox(width: 8),
Expanded(
child: _buildInput(
'PA',
paController,
required: true,
keyboardType:
TextInputType.numberWithOptions(
decimal: true,
),
inputFormatters:
decimalFormatter,
),
),
],
),
Row(
children: [
Expanded(
child: _buildInput(
'CGST',
cgstController,
required: true,
keyboardType:
TextInputType.numberWithOptions(
decimal: true,
),
inputFormatters:
decimalFormatter,
),
),
const SizedBox(width: 8),
Expanded(
child: _buildInput(
'SGST',
sgstController,
required: true,
keyboardType:
TextInputType.numberWithOptions(
decimal: true,
),
inputFormatters:
decimalFormatter,
),
),
const SizedBox(width: 8),
Expanded(
child: _buildInput(
'IGST',
igstController,
required: true,
keyboardType:
TextInputType.numberWithOptions(
decimal: true,
),
inputFormatters:
decimalFormatter,
),
),
],
),
],
),
),
),
const SizedBox(height: 12),
// Vehicle Details
Card(
elevation: 5,
color: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.stretch,
children: [
_sectionHeader(
'Vehicle Details',
icon: Icons.directions_car,
),
SizedBox(height: 10),
Row(
children: [
Expanded(
child: _buildInput(
'RTO State Name',
rtoStateCodeController,
required: false,
),
),
const SizedBox(width: 8),
Expanded(
child: _buildInput(
'RTO City Code',
rtoCityCodeController,
required: false,
keyboardType:
TextInputType.number,
inputFormatters:
digitsOnlyFormatter,
),
),
const SizedBox(width: 8),
Expanded(
child: _buildInput(
'Weight',
weightController,
required: false,
keyboardType:
TextInputType.number,
inputFormatters:
digitsOnlyFormatter,
),
),
],
),
Row(
children: [
Expanded(
child: _buildInput(
'Fuel Type',
fuelTypeController,
required: false,
),
),
const SizedBox(width: 8),
Expanded(
child: _buildInput(
'Date of Registration',
registrationDateController,
required: false,
readOnly: true,
onTap: () => _pickDate(
registrationDateController,
context,
),
),
),
const SizedBox(width: 8),
Expanded(
child: _buildInput(
'Year of Manufacture',
yomController,
required: false,
keyboardType:
TextInputType.number,
inputFormatters:
digitsOnlyFormatter,
),
),
],
),
Row(
children: [
Expanded(
child: _buildInput(
'Engine No',
engineNoController,
required: false,
),
),
const SizedBox(width: 8),
Expanded(
child: _buildInput(
'Chassis No',
chassisNoController,
required: false,
),
),
const SizedBox(width: 8),
Expanded(
child: Expanded(
child: _buildInput(
'Make',
makeController,
required: false,
),
),
),
],
),
Row(
children: [
Expanded(
child: _buildInput(
'Model',
modelController,
required: false,
),
),
const SizedBox(width: 8),
Expanded(
child: _buildInput(
'Cubic Capacity',
cubicCapacityController,
required: false,
keyboardType:
TextInputType.numberWithOptions(
decimal: true,
),
inputFormatters:
decimalFormatter,
),
),
const SizedBox(width: 8),
Expanded(
child: _buildInput(
'Vehicle Type',
vehicleTypeController,
required: false,
),
),
],
),
],
),
),
),
const SizedBox(height: 12),
// Broker Details
Card(
elevation: 5,
color: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.stretch,
children: [
_sectionHeader(
'Broker / Commission',
icon: Icons.person,
),
SizedBox(height: 10),
Row(
children: [
Expanded(
child: _buildInput(
'Broker Name',
brokerNameController,
required: false,
),
),
const SizedBox(width: 8),
Expanded(
child: _buildInput(
'Commission Amount',
commissionAmountController,
required: false,
keyboardType:
TextInputType.numberWithOptions(
decimal: true,
),
inputFormatters:
decimalFormatter,
),
),
],
),
],
),
),
),
const SizedBox(
height: 20,
), // spacing above fixed button
],
),
),
),
),
),
),
],
),
),
),
],
),
),
),
);
}
}