1495 lines
51 KiB
Dart
1495 lines
51 KiB
Dart
import 'dart:convert';
|
||
|
||
import 'package:dropdown_button2/dropdown_button2.dart';
|
||
import 'package:flutter/material.dart';
|
||
import 'package:flutter/services.dart';
|
||
import 'package:google_fonts/google_fonts.dart';
|
||
import 'package:intl/intl.dart';
|
||
|
||
import '../config/environment.dart';
|
||
import '../customAppBar/toastHelper.dart';
|
||
import '../responsive.dart';
|
||
import '../service/api_service.dart';
|
||
import '../service/file_upload_service.dart';
|
||
import 'package:http/http.dart' as http;
|
||
|
||
import 'package:file_picker/file_picker.dart';
|
||
|
||
import '../service/multi_file_upload_widget.dart';
|
||
import '../service/token_storage_service.dart';
|
||
import 'package:pdf/widgets.dart' as pw;
|
||
|
||
class RaiseClaimDialog extends StatefulWidget {
|
||
final BuildContext parentContext;
|
||
final VoidCallback onSuccess;
|
||
|
||
const RaiseClaimDialog({Key? key, required this.parentContext, required this.onSuccess,})
|
||
: super(key: key);
|
||
|
||
@override
|
||
State<RaiseClaimDialog> createState() => _RaiseClaimDialogState();
|
||
}
|
||
|
||
class _RaiseClaimDialogState extends State<RaiseClaimDialog> {
|
||
// const RaiseClaimDialog({super.key});
|
||
late ApiService apiService;
|
||
bool isLoading = false;
|
||
dynamic empPrimaryId;
|
||
dynamic empClientId;
|
||
dynamic empClientBranchId;
|
||
dynamic empHrId;
|
||
final tokenService = TokenStorageService();
|
||
String? _postPreToken = '';
|
||
List<Map<String, dynamic>> policyList = [];
|
||
dynamic policyDataIsEmpty = 1;
|
||
dynamic policyHeading;
|
||
dynamic policyName;
|
||
dynamic EmployeePolicy;
|
||
List<Map<String, String>> employeeDetails = [];
|
||
dynamic argumentsData;
|
||
dynamic claimsDetails;
|
||
int? fromClaimsPage;
|
||
dynamic decodedToken;
|
||
List<Map<String, dynamic>> departmentList = [];
|
||
List<Map<String, dynamic>> policyNumberList = [];
|
||
int? serviceId;
|
||
String? serviceName;
|
||
int? policyNumberId;
|
||
int? selectedMemberId;
|
||
String? selectedMemberName;
|
||
String? selectedServiceName;
|
||
String? selectedPolicyNo;
|
||
dynamic claimsDepartmentId;
|
||
dynamic claimSubject;
|
||
dynamic rawPolicyStartDate;
|
||
dynamic rawPolicyEndDate;
|
||
dynamic claimsPolicyNo;
|
||
dynamic client_branch_id;
|
||
dynamic mobileNo;
|
||
dynamic client_policy_id;
|
||
dynamic selfDetails;
|
||
dynamic emailId;
|
||
List<Map<String, dynamic>> employeePolicyList = [];
|
||
String? selectedFileNames;
|
||
// html.File? uploadedFile;
|
||
// List<html.File> uploadedFiles = [];
|
||
List<PlatformFile> uploadedFiles = [];
|
||
final fileService = FileUploadService();
|
||
bool isSubmitting = false;
|
||
dynamic getPostCardArrays = [];
|
||
List<Map<String, dynamic>> activePoliciesList = [];
|
||
int stausVal = 1;
|
||
Map<String, dynamic> getClaimPoliciesApi = {};
|
||
int? selectedPolicyTypeId;
|
||
int? selectedClientPolicyId;
|
||
|
||
Map<String, dynamic>? selectedMemberObject;
|
||
|
||
// Declare subjectController and bodyController as instance variables
|
||
late TextEditingController subjectController;
|
||
late TextEditingController messageController;
|
||
late TextEditingController accidentDetailsController;
|
||
late TextEditingController hospitalNameController;
|
||
late TextEditingController hospitalAddressController;
|
||
late TextEditingController hospitalCityController;
|
||
late TextEditingController hospitalStateController;
|
||
late TextEditingController hospitalPinCodeController;
|
||
late TextEditingController hospitalPhoneNoController;
|
||
late TextEditingController claimAmountController;
|
||
late TextEditingController sumInsuredController;
|
||
late TextEditingController admitDateController;
|
||
late TextEditingController dischargeDateController;
|
||
|
||
DateTime? accidentDate;
|
||
DateTime? deathDate;
|
||
DateTime? intimationDate;
|
||
DateTime? birthDate;
|
||
DateTime? admitDate;
|
||
DateTime? dischargeDate;
|
||
|
||
DateTime? parsedPolicyStartDate;
|
||
DateTime? parsedPolicyEndDate;
|
||
|
||
Map<String, DateTime?> selectedDates = {
|
||
"Accident Date": null,
|
||
"Date of Death": null,
|
||
};
|
||
|
||
final Map<int, List<int>> servicePolicyTypeMap = {
|
||
1: [2, 3, 4, 5],
|
||
2: [1],
|
||
3: [6],
|
||
4: [7],
|
||
};
|
||
|
||
List<Map<String, dynamic>> filteredPoliciesList = [];
|
||
|
||
// Create a unique form key for each accordion section
|
||
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
|
||
|
||
bool isServiceValid = true;
|
||
bool isPolicyValid = true;
|
||
bool isMemberValid = true;
|
||
bool isSubjectValid = true;
|
||
bool isHospitalNameValid = true;
|
||
bool isHospitalAddressValid = true;
|
||
bool isHospitalCityValid = true;
|
||
bool isHospitalStateValid = true;
|
||
bool isHospitalPincodeValid = true;
|
||
bool isHospitalPhoneNoValid = true;
|
||
bool isAdmitDischargeValid = true;
|
||
bool isClaimAmountValid = true;
|
||
bool isAccidentDateValid = true;
|
||
bool isIntimationDateValid = true;
|
||
bool isAdmitDateValid = true;
|
||
bool isDischargeDateValid = true;
|
||
|
||
@override
|
||
void initState() {
|
||
super.initState();
|
||
fileService.clearAll();
|
||
subjectController = TextEditingController();
|
||
messageController = TextEditingController();
|
||
accidentDetailsController = TextEditingController();
|
||
hospitalNameController = TextEditingController();
|
||
hospitalAddressController = TextEditingController();
|
||
hospitalCityController = TextEditingController();
|
||
hospitalStateController = TextEditingController();
|
||
hospitalPinCodeController = TextEditingController();
|
||
hospitalPhoneNoController = TextEditingController();
|
||
claimAmountController = TextEditingController();
|
||
sumInsuredController = TextEditingController();
|
||
admitDateController = TextEditingController();
|
||
dischargeDateController = TextEditingController();
|
||
apiService = ApiService(context); // Initialize ApiService here
|
||
_loadToken();
|
||
// Check if fromClaimsPage is 0 and set serviceId to 'Claims' (id is 2)
|
||
// if (fromClaimsPage == 0) {
|
||
// setInitialServiceId();
|
||
// }
|
||
}
|
||
|
||
@override
|
||
void dispose() {
|
||
// Dispose the controllers to avoid memory leaks
|
||
subjectController.dispose();
|
||
messageController.dispose();
|
||
accidentDetailsController.dispose();
|
||
hospitalNameController.dispose();
|
||
hospitalAddressController.dispose();
|
||
hospitalCityController.dispose();
|
||
hospitalStateController.dispose();
|
||
hospitalPinCodeController.dispose();
|
||
hospitalPhoneNoController.dispose();
|
||
claimAmountController.dispose();
|
||
sumInsuredController.dispose();
|
||
admitDateController.dispose();
|
||
dischargeDateController.dispose();
|
||
serviceId = null;
|
||
departmentList.clear();
|
||
super.dispose();
|
||
fileService.clearAll();
|
||
}
|
||
|
||
Future<void> _loadToken() async {
|
||
_postPreToken = tokenService.getCurrentToken();
|
||
empClientId = await tokenService.readValue('empClientId');
|
||
empClientBranchId = await tokenService.readValue('empClientBranchId');
|
||
empHrId = await tokenService.readValue('empHrId');
|
||
getClaimsPoliciesDetails();
|
||
await getPostCashDepositDetails(
|
||
empClientBranchId, empClientId, empHrId, _postPreToken);
|
||
}
|
||
|
||
Future<void> getClaimsPoliciesDetails() async {
|
||
print('9');
|
||
setState(() {
|
||
isLoading = true;
|
||
});
|
||
try {
|
||
print('10');
|
||
final response = await apiService.getClaimPoliciesToApi(_postPreToken!);
|
||
if (response['status'] == 'success') {
|
||
setState(() {
|
||
isLoading = false;
|
||
});
|
||
setState(() {
|
||
getClaimPoliciesApi = Map<String, dynamic>.from(response['data']);
|
||
departmentList = (getClaimPoliciesApi['ticket_type'] as List)
|
||
.map<Map<String, dynamic>>((item) => {
|
||
'id': int.parse(item['ticket_type'].toString()),
|
||
'name': item['type_name'].toString(),
|
||
})
|
||
.toList();
|
||
});
|
||
} else {
|
||
setState(() {
|
||
isLoading = false;
|
||
});
|
||
|
||
// ToastHelper.showWarningToast(
|
||
// context, 'Request failed with status: ${response.statusCode}');
|
||
print('Request failed with status: ${response['code']}');
|
||
}
|
||
} catch (e) {
|
||
setState(() {
|
||
// isLoading = false;
|
||
});
|
||
print('Exception occurred: $e');
|
||
} finally {
|
||
setState(() {
|
||
// _isLoading = false;
|
||
});
|
||
}
|
||
}
|
||
|
||
Future<void> getPostCashDepositDetails(
|
||
empClientBranchId, empClientId, empHrId, _postPreToken) async {
|
||
print('IN');
|
||
print("clintBranchId -$empClientBranchId");
|
||
print("clintID -$empClientId");
|
||
print("hr_id -$empHrId");
|
||
print("token -$_postPreToken");
|
||
|
||
isLoading = true;
|
||
// setState(() {
|
||
// _isLoading = true;
|
||
// });
|
||
try {
|
||
if (empClientBranchId == null || empClientId == null) {
|
||
return;
|
||
}
|
||
final response = await apiService.getActiveCashDepositDetailsToApi(
|
||
empClientId!, empClientBranchId!, empHrId, _postPreToken, stausVal);
|
||
|
||
// final response = await apiService.getCashDepositDetailsToApi(
|
||
// clintID!, clintBranchId!, hr_id, token);
|
||
print('IN1');
|
||
if (response['status'] == 'success') {
|
||
isLoading = false;
|
||
setState(() {
|
||
print('response');
|
||
print(response['data']);
|
||
getPostCardArrays = List<Map<String, dynamic>>.from(response['data']);
|
||
print('getPostCardArrays');
|
||
print(getPostCardArrays);
|
||
|
||
activePoliciesList = getPostCardArrays;
|
||
});
|
||
|
||
print('IN2');
|
||
} else {
|
||
isLoading = false;
|
||
print('API request failed with status');
|
||
setState(() {
|
||
activePoliciesList = [];
|
||
});
|
||
print('API request failed with status');
|
||
}
|
||
} catch (e) {
|
||
print('Exception occurred: $e');
|
||
}
|
||
}
|
||
|
||
void filterPoliciesByService(int serviceTicketType) {
|
||
final allowedPolicyTypes = servicePolicyTypeMap[serviceTicketType] ?? [];
|
||
|
||
final filtered = activePoliciesList.where((policy) {
|
||
final policyTypeId = int.tryParse(
|
||
policy['policy_type_id'].toString(),
|
||
);
|
||
return allowedPolicyTypes.contains(policyTypeId);
|
||
}).toList();
|
||
|
||
setState(() {
|
||
policyNumberId = null;
|
||
|
||
policyNumberList = filtered.map<Map<String, dynamic>>((policy) {
|
||
return {
|
||
// ✅ VALUE (what gets sent)
|
||
'id': int.parse(policy['client_policy_id'].toString()),
|
||
|
||
// ✅ DISPLAY (what user sees)
|
||
'label': '${policy['type']} - ${policy['policy_no']}',
|
||
|
||
// keep extras if needed
|
||
'policy_type_id': int.parse(policy['policy_type_id'].toString()),
|
||
};
|
||
}).toList();
|
||
|
||
|
||
isPolicyValid = true;
|
||
});
|
||
}
|
||
|
||
Future<void> getCDPoliciesDetails() async {
|
||
print('9');
|
||
setState(() {
|
||
isLoading = true;
|
||
});
|
||
try {
|
||
print('10');
|
||
|
||
final response = await apiService.getEmployeeAndDependenceToApi(
|
||
empClientId, selectedClientPolicyId, empClientBranchId, _postPreToken!);
|
||
|
||
if (response['status'] == 'success') {
|
||
final List<Map<String, dynamic>> members =
|
||
List<Map<String, dynamic>>.from(response['data']);
|
||
|
||
setState(() {
|
||
employeePolicyList = members.map((m) {
|
||
return {
|
||
'id': int.parse(m['id'].toString()), // ✅ UNIQUE
|
||
'name': m['name'], // ✅ DISPLAY
|
||
'client_policy_id': m['client_policy_id'] ?? '',
|
||
'emp_id': m['self_employee_id'] ?? '',
|
||
'insured_emp_id': m['employee_id'] ?? '',
|
||
'emp_code': m['emp_code'] ?? '',
|
||
'mobile': m['mobile'] ?? ' ',
|
||
'empEmailCorporate': m['email_corporate'] ?? '',
|
||
'relationship': m['relationship'],
|
||
'gender': m['gender'],
|
||
'dob': m['dob'],
|
||
'policy_name': serviceId == 1
|
||
? null
|
||
: m['policy_name'],
|
||
};
|
||
}).toList();
|
||
});
|
||
}
|
||
} catch (e) {
|
||
setState(() {
|
||
isLoading = false;
|
||
});
|
||
print('Exception occurred: $e');
|
||
} finally {
|
||
setState(() {
|
||
isLoading = false;
|
||
});
|
||
}
|
||
}
|
||
|
||
Future<void> sendFormDataToApi() async {
|
||
|
||
setState(() {
|
||
isServiceValid = serviceId != null;
|
||
isPolicyValid = selectedClientPolicyId != null;
|
||
isMemberValid = selectedMemberId != null;
|
||
// isSubjectValid = subjectController.text.trim().isNotEmpty;
|
||
// 🏥 GMC / Topup
|
||
final isGmc = serviceId == 1 || serviceId == 4;
|
||
isHospitalNameValid = !isGmc || hospitalNameController.text.trim().isNotEmpty;
|
||
isHospitalAddressValid = !isGmc || hospitalAddressController.text.trim().isNotEmpty;
|
||
isHospitalCityValid = !isGmc || hospitalCityController.text.trim().isNotEmpty;
|
||
isHospitalStateValid = !isGmc || hospitalStateController.text.trim().isNotEmpty;
|
||
isHospitalPincodeValid = !isGmc || hospitalPinCodeController.text.trim().isNotEmpty;
|
||
isHospitalPhoneNoValid = !isGmc || hospitalPhoneNoController.text.trim().isNotEmpty;
|
||
|
||
isAdmitDateValid = !isGmc || admitDate != null;
|
||
isDischargeDateValid = !isGmc || dischargeDate != null;
|
||
|
||
isClaimAmountValid = !isGmc || claimAmountController.text.trim().isNotEmpty;
|
||
|
||
// ☠ Accident / Death
|
||
final isAccident = [2, 3, 4].contains(serviceId);
|
||
|
||
isAccidentDateValid = !isAccident || accidentDate != null;
|
||
isIntimationDateValid = !isAccident || intimationDate != null;
|
||
});
|
||
|
||
if (isServiceValid &&
|
||
isPolicyValid &&
|
||
isMemberValid &&
|
||
// isSubjectValid &&
|
||
isHospitalNameValid &&
|
||
isHospitalAddressValid &&
|
||
isHospitalStateValid &&
|
||
isHospitalCityValid &&
|
||
isHospitalPincodeValid &&
|
||
isHospitalPhoneNoValid &&
|
||
isAdmitDateValid &&
|
||
isDischargeDateValid &&
|
||
isClaimAmountValid &&
|
||
isAccidentDateValid &&
|
||
isIntimationDateValid) {
|
||
if (FileUploadService().files.isEmpty) {
|
||
setState(() {
|
||
MultiFileUploadWidget.hasFiles = false;
|
||
});
|
||
ToastHelper.showErrorToast(context, 'Please upload at least one document');
|
||
return;
|
||
}
|
||
// Proceed to submit
|
||
} else {
|
||
ToastHelper.showErrorToast(context, 'Please Fill Required Fields');
|
||
return;
|
||
}
|
||
setState(() => isSubmitting = true); // 🔥 start loader
|
||
setState(() {
|
||
isLoading = true;
|
||
});
|
||
|
||
try {
|
||
print('Check One');
|
||
Map<String, dynamic> fields = {
|
||
'client_policy_id': selectedClientPolicyId,
|
||
// 'policy_type_id': selectedPolicyTypeId,
|
||
|
||
'emp_id': selectedMemberObject?['emp_id'],
|
||
'ticket_type_id': serviceId,
|
||
'subject': serviceName,
|
||
'message': messageController.text,
|
||
|
||
'emp_code': selectedMemberObject?['emp_code'] ?? '',
|
||
'mobile_number': selectedMemberObject?['mobile'] ?? ' ',
|
||
'email': selectedMemberObject?['empEmailCorporate'] ?? '',
|
||
'fullname': selectedMemberObject?['name'] ?? '',
|
||
'client_id': empClientId,
|
||
'relationship': selectedMemberObject?['relationship'],
|
||
'gender': selectedMemberObject?['gender'],
|
||
'age': selectedMemberObject?['dob'],
|
||
'policy_name': serviceId == 1
|
||
? null
|
||
: selectedMemberObject?['policy_name'],
|
||
|
||
};
|
||
|
||
|
||
if (serviceId == 1 || serviceId == 72) {
|
||
String formattedAdmitDate = DateFormat('yyyy-MM-dd').format(admitDate!);
|
||
String formattedDischargeDate = DateFormat('yyyy-MM-dd').format(dischargeDate!);
|
||
fields['hospital_name'] = hospitalNameController.text;
|
||
fields['hospital_address'] = hospitalAddressController.text;
|
||
fields['hospital_city'] = hospitalCityController.text;
|
||
fields['hospital_state'] = hospitalStateController.text;
|
||
fields['hospital_pin_code'] = hospitalPinCodeController.text;
|
||
fields['hospital_phone_no'] = hospitalPhoneNoController.text;
|
||
fields['doa'] = formattedAdmitDate;
|
||
fields['dod'] = formattedDischargeDate;
|
||
fields['claim_amount'] = claimAmountController.text;
|
||
fields['policyholder_name'] = employeePolicyList[0]['name'];
|
||
fields['member_name'] = selectedMemberObject?['name'];
|
||
fields['insured_emp_id'] = selectedMemberObject?['insured_emp_id'];
|
||
} else {
|
||
String formattedAccidentDate =
|
||
DateFormat('yyyy-MM-dd').format(accidentDate!);
|
||
String formattedDeathDate = DateFormat('yyyy-MM-dd').format(deathDate!);
|
||
String formattedBirthDate = DateFormat('yyyy-MM-dd').format(birthDate!);
|
||
String formattedIntimationDate =
|
||
DateFormat('yyyy-MM-dd').format(intimationDate!);
|
||
fields['date_of_accident'] = formattedAccidentDate;
|
||
fields['dob'] = formattedBirthDate;
|
||
fields['date_of_intimat'] = formattedIntimationDate;
|
||
fields['date_of_death'] = formattedDeathDate;
|
||
fields['si_amt'] = sumInsuredController.text;
|
||
fields['policyholder_name'] = employeePolicyList[0]['name'];
|
||
fields['member_name'] = selectedMemberName;
|
||
fields['insured_emp_id'] = selectedMemberObject?['insured_emp_id'];
|
||
}
|
||
|
||
|
||
final request = http.MultipartRequest('POST', Uri.parse('${Environment.apiUrlPost}initiateClaim'));
|
||
request.headers['Authorization'] = 'Bearer $_postPreToken';
|
||
request.headers['APP-SIGNATURE'] = 'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y';
|
||
final stringFields = fields.map((key, value) => MapEntry(key, value?.toString() ?? ''));
|
||
request.fields.addAll(stringFields);
|
||
|
||
// get uploaded files
|
||
final uploadedFiles = FileUploadService().files;
|
||
print("📁 Total uploaded files: ${uploadedFiles.length}");
|
||
print("📂 File list (original names): ${uploadedFiles.map((f) => f.file.name).toList()}");
|
||
|
||
// Validate all labels present (optional but recommended)
|
||
for (final uf in uploadedFiles) {
|
||
print("📝 Checking label for file: ${uf.file.name}, current label: '${uf.label}'");
|
||
if ((uf.label ?? '').trim().isEmpty) {
|
||
ToastHelper.showErrorToast(context, 'Please enter name for all uploaded documents');
|
||
setState(() => isLoading = false);
|
||
return;
|
||
}
|
||
}
|
||
|
||
// ✅ NEW VALIDATION: At least one PDF must be uploaded
|
||
// bool hasPdf = uploadedFiles.any((uf) {
|
||
// final ext = uf.file.extension?.toLowerCase() ?? '';
|
||
// return ext == 'pdf';
|
||
// });
|
||
//
|
||
// if (!hasPdf) {
|
||
// ToastHelper.showErrorToast(context, 'Please upload at least one PDF document');
|
||
// setState(() => isLoading = false);
|
||
// return;
|
||
// }
|
||
|
||
// Add files
|
||
// for (var uf in uploadedFiles) {
|
||
// final pf = uf.file;
|
||
// if (pf.bytes != null) {
|
||
// request.files.add(http.MultipartFile.fromBytes(
|
||
// 'claim_docs[]',
|
||
// pf.bytes!,
|
||
// filename: pf.name,
|
||
// ));
|
||
// }
|
||
// }
|
||
|
||
// Add files — convert images to PDF if needed
|
||
for (var uf in uploadedFiles) {
|
||
final pf = uf.file;
|
||
final ext = pf.extension?.toLowerCase() ?? '';
|
||
|
||
if (pf.bytes != null) {
|
||
Uint8List fileBytes = pf.bytes!;
|
||
|
||
if (['jpg', 'jpeg', 'png', 'heic'].contains(ext)) {
|
||
// ✅ Convert image → PDF
|
||
final pdf = pw.Document();
|
||
final image = pw.MemoryImage(fileBytes);
|
||
|
||
pdf.addPage(
|
||
pw.Page(
|
||
build: (pw.Context context) => pw.Center(
|
||
child: pw.Image(image, fit: pw.BoxFit.contain),
|
||
),
|
||
),
|
||
);
|
||
|
||
fileBytes = await pdf.save(); // converted PDF bytes
|
||
|
||
// replace file name with .pdf extension
|
||
final pdfFileName = pf.name.replaceAll(RegExp(r'\.\w+$'), '.pdf');
|
||
|
||
print('📄 Converted image ${pf.name} → PDF ($pdfFileName)');
|
||
request.files.add(http.MultipartFile.fromBytes(
|
||
'claim_docs[]',
|
||
fileBytes,
|
||
filename: pdfFileName,
|
||
));
|
||
} else {
|
||
// ✅ Already a PDF
|
||
request.files.add(http.MultipartFile.fromBytes(
|
||
'claim_docs[]',
|
||
fileBytes,
|
||
filename: pf.name,
|
||
));
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
// ✅ Combine all names into a JSON array string
|
||
final claimDocNames = uploadedFiles.map((uf) => uf.label.trim()).toList();
|
||
final encodedNames = jsonEncode(claimDocNames);
|
||
request.fields['claim_doc_names'] = encodedNames;
|
||
|
||
// ✅ Debug print
|
||
print("Payload being sent:");
|
||
print("Files: ${uploadedFiles.map((f) => f.file.name).toList()}");
|
||
print("Names (JSON): $encodedNames");
|
||
|
||
|
||
final response = await request.send();
|
||
final responseBody = await response.stream.bytesToString();
|
||
|
||
final decoded = jsonDecode(responseBody);
|
||
if (decoded['status'] == true) {
|
||
// 1️⃣ Close dialog first
|
||
Navigator.pop(context);
|
||
|
||
// 2️⃣ Call parent page function
|
||
widget.onSuccess();
|
||
|
||
ToastHelper.showSuccessToast(context, decoded['message']);
|
||
serviceId = null;
|
||
departmentList.clear();
|
||
setState(() {
|
||
isLoading = false;
|
||
});
|
||
// context.go('/claims', extra: 2);
|
||
print('Form data submitted successfully');
|
||
fileService.clearAll();
|
||
} else {
|
||
setState(() {
|
||
isLoading = false;
|
||
});
|
||
Navigator.pop(context);
|
||
ToastHelper.showErrorToast(context, "Failed: ${decoded['message']}");
|
||
}
|
||
|
||
|
||
} catch (e) {
|
||
setState(() {
|
||
isLoading = false;
|
||
});
|
||
print('Error submitting form data: $e');
|
||
} finally {
|
||
setState(() => isSubmitting = false); // 🔥 stop loader
|
||
}
|
||
}
|
||
|
||
Future<void> _pickDate(BuildContext context, String label) async {
|
||
final DateTime? pickedDate = await showDatePicker(
|
||
context: context,
|
||
initialDate: selectedDates[label] ?? DateTime.now(),
|
||
firstDate: DateTime(2000),
|
||
lastDate: DateTime.now(),
|
||
);
|
||
|
||
if (pickedDate != null && pickedDate != selectedDates[label]) {
|
||
setState(() {
|
||
selectedDates[label] = pickedDate;
|
||
});
|
||
}
|
||
}
|
||
|
||
Future<void> _pickFromToDate(BuildContext context) async {
|
||
// Define the policy date range
|
||
final DateTime policyStartDate =
|
||
DateFormat('dd-MMM-yyyy').parse(rawPolicyStartDate);
|
||
final DateTime policyEndDate =
|
||
DateFormat('dd-MMM-yyyy').parse(rawPolicyEndDate);
|
||
|
||
// Show the date range picker within the policy date limits
|
||
final DateTimeRange? pickedDateRange = await showDateRangePicker(
|
||
context: context,
|
||
firstDate: policyStartDate,
|
||
lastDate: policyEndDate,
|
||
initialDateRange: admitDate != null && dischargeDate != null
|
||
? DateTimeRange(start: admitDate!, end: dischargeDate!)
|
||
: null,
|
||
);
|
||
|
||
// Update values if a valid date range is picked
|
||
if (pickedDateRange != null) {
|
||
setState(() {
|
||
admitDate = pickedDateRange.start;
|
||
dischargeDate = pickedDateRange.end;
|
||
admitDateController.text = DateFormat('dd-MM-yyyy').format(admitDate!);
|
||
dischargeDateController.text =
|
||
DateFormat('dd-MM-yyyy').format(dischargeDate!);
|
||
});
|
||
}
|
||
}
|
||
|
||
// Future<void> _pickFromToDate(BuildContext context) async {
|
||
// final DateTimeRange? pickedDateRange = await showDateRangePicker(
|
||
// context: context,
|
||
// firstDate: DateTime(2000),
|
||
// lastDate: DateTime(2100),
|
||
// initialDateRange: admitDate != null && dischargeDate != null
|
||
// ? DateTimeRange(start: admitDate!, end: dischargeDate!)
|
||
// : null,
|
||
// );
|
||
//
|
||
// if (pickedDateRange != null) {
|
||
// setState(() {
|
||
// admitDate = pickedDateRange.start;
|
||
// dischargeDate = pickedDateRange.end;
|
||
// admitDateController.text = DateFormat('yyyy-MM-dd').format(admitDate!);
|
||
// dischargeDateController.text =
|
||
// DateFormat('yyyy-MM-dd').format(dischargeDate!);
|
||
// });
|
||
// }
|
||
// }
|
||
|
||
int calculateAge(String dob) {
|
||
DateTime birthDate = DateTime.parse(dob); // Parse the dob string
|
||
DateTime currentDate = DateTime.now();
|
||
|
||
int age = currentDate.year - birthDate.year;
|
||
|
||
// Adjust age if the birthday has not occurred yet this year
|
||
if (currentDate.month < birthDate.month ||
|
||
(currentDate.month == birthDate.month &&
|
||
currentDate.day < birthDate.day)) {
|
||
age--;
|
||
}
|
||
|
||
return age;
|
||
}
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return Dialog(
|
||
backgroundColor: Colors.white, // ✅ PURE WHITE popup
|
||
insetPadding: const EdgeInsets.all(20),
|
||
shape: RoundedRectangleBorder(
|
||
borderRadius: BorderRadius.circular(16),
|
||
),
|
||
child: ClipRRect(
|
||
borderRadius: BorderRadius.circular(16),
|
||
child: SizedBox(
|
||
width: MediaQuery.of(context).size.width * 0.75, // Desktop popup width
|
||
// height: MediaQuery.of(context).size.height * 0.85,
|
||
child: Stack(
|
||
children: [
|
||
/// MAIN CONTENT (YOUR EXISTING UI)
|
||
SingleChildScrollView(
|
||
child: Container(
|
||
padding: EdgeInsets.all(20),
|
||
color: Colors.white,
|
||
child: Column(
|
||
children: [
|
||
/// 🔹 HEADER ROW (Title + Close)
|
||
Row(
|
||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||
children: [
|
||
Text(
|
||
"Raise Insurance Claim",
|
||
style: GoogleFonts.poppins(
|
||
fontSize: 20,
|
||
fontWeight: FontWeight.w600,
|
||
),
|
||
),
|
||
IconButton(
|
||
icon: const Icon(Icons.close),
|
||
onPressed: () => Navigator.pop(context),
|
||
),
|
||
],
|
||
),
|
||
|
||
const SizedBox(height: 16),
|
||
|
||
Form(
|
||
key: formKey,
|
||
child: Column(
|
||
children: [
|
||
_row([
|
||
buildDropdownField(
|
||
'Service',
|
||
(value) {
|
||
final selectedItem = departmentList.firstWhere(
|
||
(item) => item['id'] == value,
|
||
orElse: () => {},
|
||
);
|
||
setState(() {
|
||
serviceId = value;
|
||
serviceName = selectedItem['name'];
|
||
policyNumberId = null;
|
||
isServiceValid = true;
|
||
});
|
||
print('🔥 serviceId set to $serviceId');
|
||
filterPoliciesByService(value!);
|
||
},
|
||
departmentList,
|
||
'name',
|
||
serviceId,
|
||
),
|
||
buildDropdownField(
|
||
'Select Policy',
|
||
(value) {
|
||
final selectedPolicy =
|
||
policyNumberList.firstWhere((p) => p['id'] == value);
|
||
|
||
setState(() {
|
||
// ✅ THIS is what you send to API
|
||
selectedClientPolicyId = selectedPolicy['id'];
|
||
|
||
// optional
|
||
selectedPolicyTypeId = selectedPolicy['policy_type_id'];
|
||
policyNumberId = value;
|
||
|
||
isPolicyValid = true;
|
||
});
|
||
|
||
getCDPoliciesDetails();
|
||
},
|
||
policyNumberList,
|
||
'label', // 👈 DISPLAY FIELD
|
||
policyNumberId,
|
||
),
|
||
|
||
buildDropdownFieldSearch(
|
||
'Member Name',
|
||
(value) {
|
||
final member = employeePolicyList.firstWhere(
|
||
(m) => m['id'] == value,
|
||
);
|
||
|
||
setState(() {
|
||
selectedMemberId = value;
|
||
selectedMemberObject = member; // ✅ FULL OBJECT
|
||
selectedMemberName = member['name'];
|
||
isMemberValid = true;
|
||
print('selectedMemberObject $selectedMemberObject');
|
||
});
|
||
},
|
||
employeePolicyList,
|
||
'name',
|
||
selectedMemberId,
|
||
),
|
||
|
||
]),
|
||
_row([
|
||
buildTextField('Message', messageController),
|
||
if (serviceId == 1 || serviceId == 72)...[
|
||
buildTextField('Hospital Name', hospitalNameController),
|
||
buildTextField('Hospital Address', hospitalAddressController),
|
||
]
|
||
]),
|
||
|
||
if (serviceId == 1 || serviceId == 72)
|
||
_row([
|
||
buildTextField('Hospital City', hospitalCityController),
|
||
buildTextField('Hospital State', hospitalStateController),
|
||
buildTextField(
|
||
'Hospital Pincode',
|
||
hospitalPinCodeController,
|
||
keyboardType: TextInputType.number,
|
||
inputFormatters: [
|
||
FilteringTextInputFormatter.digitsOnly,
|
||
LengthLimitingTextInputFormatter(6),
|
||
],
|
||
),
|
||
]),
|
||
if (serviceId == 1 || serviceId == 72)
|
||
_row([
|
||
buildTextField(
|
||
'Hospital Phone No',
|
||
hospitalPhoneNoController,
|
||
keyboardType: TextInputType.number,
|
||
inputFormatters: [
|
||
FilteringTextInputFormatter.digitsOnly,
|
||
LengthLimitingTextInputFormatter(10),
|
||
],
|
||
),
|
||
buildDatePickerField(
|
||
label: 'Admit Date',
|
||
selectedDate: admitDate,
|
||
allowFuture: false,
|
||
onDateSelected: (d) {
|
||
setState(() {
|
||
admitDate = d;
|
||
dischargeDate = null;
|
||
});
|
||
},
|
||
),
|
||
buildDatePickerField(
|
||
label: 'Discharge Date',
|
||
selectedDate: dischargeDate,
|
||
allowFuture: true,
|
||
minDate: admitDate?.add(const Duration(days: 1)),
|
||
onDateSelected: (d) => setState(() => dischargeDate = d),
|
||
),
|
||
buildTextField(
|
||
'Claims Amount',
|
||
claimAmountController,
|
||
keyboardType: TextInputType.number,
|
||
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
|
||
),
|
||
]),
|
||
|
||
if ([2, 3, 4].contains(serviceId))
|
||
_row([
|
||
buildDatePickerField(
|
||
label: 'Date of Birth',
|
||
selectedDate: birthDate,
|
||
allowFuture: false,
|
||
onDateSelected: (d) => setState(() => birthDate = d),
|
||
),
|
||
buildDatePickerField(
|
||
label: 'Accident Date',
|
||
selectedDate: accidentDate,
|
||
allowFuture: false,
|
||
onDateSelected: (d) {
|
||
setState(() {
|
||
accidentDate = d;
|
||
deathDate = null;
|
||
intimationDate = null;
|
||
});
|
||
},
|
||
),
|
||
buildDatePickerField(
|
||
label: 'Date of Death',
|
||
selectedDate: deathDate,
|
||
allowFuture: false,
|
||
onDateSelected: (d) => setState(() => deathDate = d),
|
||
),
|
||
]),
|
||
if ([2, 3, 4].contains(serviceId))
|
||
_row([
|
||
buildDatePickerField(
|
||
label: 'Date of Intimation',
|
||
selectedDate: intimationDate,
|
||
allowFuture: false,
|
||
onDateSelected: (d) => setState(() => intimationDate = d),
|
||
),
|
||
buildTextField(
|
||
'Sum Insured',
|
||
sumInsuredController,
|
||
keyboardType: TextInputType.number,
|
||
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
|
||
),
|
||
const SizedBox(),
|
||
]),
|
||
|
||
_row([
|
||
MultiFileUploadWidget(),
|
||
]),
|
||
Align(
|
||
alignment: Alignment.centerRight,
|
||
child: SizedBox(
|
||
width: 120,
|
||
height: 42,
|
||
child: ElevatedButton(
|
||
onPressed: isSubmitting ? null : sendFormDataToApi,
|
||
style: ElevatedButton.styleFrom(
|
||
backgroundColor: const Color(0xFFE26728),
|
||
shape: RoundedRectangleBorder(
|
||
borderRadius: BorderRadius.circular(10),
|
||
),
|
||
),
|
||
child: isSubmitting
|
||
? const SizedBox(
|
||
height: 18,
|
||
width: 18,
|
||
child: CircularProgressIndicator(
|
||
strokeWidth: 2,
|
||
color: Colors.white,
|
||
),
|
||
)
|
||
: const Text(
|
||
'Send',
|
||
style: TextStyle(color: Colors.white,
|
||
fontWeight: FontWeight.w600),
|
||
),
|
||
),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
),
|
||
|
||
/// 🔄 LOADER OVERLAY (UNCHANGED)
|
||
if (isLoading)
|
||
Container(
|
||
color: const Color(0x98FFFCE5),
|
||
child: Center(
|
||
child: Image.asset(
|
||
'assets/nhance-loader.gif',
|
||
height: 60,
|
||
width: 60,
|
||
),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
)
|
||
|
||
);
|
||
}
|
||
|
||
/// ---------- HELPERS ----------
|
||
|
||
Widget _row(List<Widget> children) {
|
||
return Padding(
|
||
padding: const EdgeInsets.only(bottom: 14),
|
||
child: Row(
|
||
children: children
|
||
.map((e) => Expanded(
|
||
child: Padding(
|
||
padding: const EdgeInsets.only(right: 12),
|
||
child: e,
|
||
)))
|
||
.toList(),
|
||
),
|
||
);
|
||
}
|
||
|
||
Widget buildTextField(
|
||
String label,
|
||
TextEditingController controller, {
|
||
TextInputType keyboardType = TextInputType.text,
|
||
List<TextInputFormatter>? inputFormatters,
|
||
}) {
|
||
return Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
fieldLabel(label),
|
||
formBox(
|
||
child: TextField(
|
||
controller: controller,
|
||
keyboardType: keyboardType,
|
||
inputFormatters: inputFormatters,
|
||
decoration: const InputDecoration(
|
||
isDense: true,
|
||
border: InputBorder.none,
|
||
),
|
||
),
|
||
),
|
||
],
|
||
);
|
||
}
|
||
|
||
Widget buildTextAreaField(String label, TextEditingController controller) {
|
||
return Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
fieldLabel(label),
|
||
Container(
|
||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
||
decoration: BoxDecoration(
|
||
color: const Color(0xFFF1F1F1),
|
||
borderRadius: BorderRadius.circular(8),
|
||
),
|
||
child: TextField(
|
||
controller: controller,
|
||
maxLines: 3,
|
||
decoration: const InputDecoration(
|
||
isDense: true,
|
||
border: InputBorder.none,
|
||
),
|
||
),
|
||
),
|
||
],
|
||
);
|
||
}
|
||
|
||
Widget buildDropdownField(
|
||
String label,
|
||
void Function(int?) onChanged,
|
||
List<Map<String, dynamic>> itemsList,
|
||
String displayField,
|
||
int? selectedValue,
|
||
) {
|
||
return Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
fieldLabel(label),
|
||
formBox(
|
||
child: DropdownButtonHideUnderline(
|
||
child: DropdownButton<int>(
|
||
isExpanded: true,
|
||
value: selectedValue,
|
||
hint: const Text('Select'),
|
||
icon: const Icon(Icons.keyboard_arrow_down),
|
||
items: itemsList.map<DropdownMenuItem<int>>((item) {
|
||
return DropdownMenuItem<int>(
|
||
value: item['id'],
|
||
child: Text(item[displayField]),
|
||
);
|
||
}).toList(),
|
||
onChanged: onChanged,
|
||
),
|
||
),
|
||
),
|
||
],
|
||
);
|
||
}
|
||
|
||
|
||
Widget buildDropdownFieldSearch(
|
||
String label,
|
||
void Function(int?) onChanged,
|
||
List<Map<String, dynamic>> itemsList,
|
||
String displayField,
|
||
int? selectedValue,
|
||
) {
|
||
final TextEditingController searchController = TextEditingController();
|
||
|
||
return Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
fieldLabel(label),
|
||
formBox(
|
||
child: DropdownButtonHideUnderline(
|
||
child: DropdownButton2<int>(
|
||
isExpanded: true,
|
||
value: selectedValue,
|
||
hint: const Text('Select'),
|
||
iconStyleData: const IconStyleData(
|
||
icon: Icon(Icons.keyboard_arrow_down),
|
||
),
|
||
|
||
// 🔹 SEARCH CONFIG
|
||
dropdownSearchData: DropdownSearchData(
|
||
searchController: searchController,
|
||
searchInnerWidgetHeight: 50,
|
||
searchInnerWidget: Padding(
|
||
padding: const EdgeInsets.all(8),
|
||
child: TextField(
|
||
controller: searchController,
|
||
decoration: InputDecoration(
|
||
hintText: 'Search...',
|
||
border: OutlineInputBorder(
|
||
borderRadius: BorderRadius.circular(8),
|
||
),
|
||
isDense: true,
|
||
),
|
||
),
|
||
),
|
||
searchMatchFn: (item, searchValue) {
|
||
return item.value
|
||
.toString()
|
||
.toLowerCase()
|
||
.contains(searchValue.toLowerCase()) ||
|
||
item.child
|
||
.toString()
|
||
.toLowerCase()
|
||
.contains(searchValue.toLowerCase());
|
||
},
|
||
),
|
||
|
||
// 🔹 CLEAR SEARCH WHEN CLOSED
|
||
onMenuStateChange: (isOpen) {
|
||
if (!isOpen) searchController.clear();
|
||
},
|
||
|
||
items: itemsList.map((item) {
|
||
return DropdownMenuItem<int>(
|
||
value: item['id'],
|
||
child: Text(
|
||
item[displayField],
|
||
overflow: TextOverflow.ellipsis,
|
||
),
|
||
);
|
||
}).toList(),
|
||
|
||
onChanged: onChanged,
|
||
),
|
||
),
|
||
),
|
||
],
|
||
);
|
||
}
|
||
|
||
|
||
Widget buildDatePickerField({
|
||
required String label,
|
||
required DateTime? selectedDate,
|
||
required bool allowFuture,
|
||
required ValueChanged<DateTime?> onDateSelected,
|
||
DateTime? minDate,
|
||
DateTime? maxDate,
|
||
}) {
|
||
return Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
fieldLabel(label),
|
||
formBox(
|
||
child: InkWell(
|
||
onTap: () async {
|
||
final DateTime now = DateTime.now();
|
||
final DateTime first = minDate ?? DateTime(1980);
|
||
final DateTime last =
|
||
allowFuture ? (maxDate ?? DateTime(2100)) : now;
|
||
|
||
final DateTime initialDate =
|
||
selectedDate ?? (first.isAfter(now) ? first : now);
|
||
|
||
final picked = await showDatePicker(
|
||
context: context,
|
||
initialDate: initialDate,
|
||
firstDate: first,
|
||
lastDate: last,
|
||
);
|
||
|
||
if (picked != null) {
|
||
onDateSelected(picked);
|
||
}
|
||
},
|
||
child: Row(
|
||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||
children: [
|
||
Text(
|
||
selectedDate != null
|
||
? DateFormat('dd-MM-yyyy').format(selectedDate)
|
||
: 'Select',
|
||
style: const TextStyle(color: Colors.black),
|
||
),
|
||
const Icon(Icons.calendar_today, size: 18),
|
||
],
|
||
),
|
||
),
|
||
),
|
||
],
|
||
);
|
||
}
|
||
|
||
// Widget uploadBox() {
|
||
// return Column(
|
||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||
// children: [
|
||
// fieldLabel('Upload Documents'),
|
||
// Container(
|
||
// height: 120,
|
||
// width: double.infinity,
|
||
// decoration: BoxDecoration(
|
||
// color: const Color(0xFFF9F9F9),
|
||
// borderRadius: BorderRadius.circular(10),
|
||
// border: Border.all(
|
||
// color: const Color(0xFF00A6A6),
|
||
// width: 1,
|
||
// ),
|
||
// ),
|
||
// child: const MultiFileUploadWidget(),
|
||
// ),
|
||
// ],
|
||
// );
|
||
// }
|
||
|
||
Widget formBox({required Widget child}) {
|
||
return Container(
|
||
height: 42,
|
||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||
decoration: BoxDecoration(
|
||
color: const Color(0xFFF1F1F1), // 👈 light grey
|
||
borderRadius: BorderRadius.circular(8),
|
||
),
|
||
child: Center(child: child),
|
||
);
|
||
}
|
||
|
||
Widget fieldLabel(String text) {
|
||
return Padding(
|
||
padding: const EdgeInsets.only(bottom: 6),
|
||
child: Text(
|
||
text,
|
||
style: GoogleFonts.poppins(
|
||
fontSize: 12,
|
||
fontWeight: FontWeight.w500,
|
||
color: Colors.black,
|
||
),
|
||
),
|
||
);
|
||
}
|
||
}
|
||
|
||
// class RaiseClaimDialog extends StatelessWidget {
|
||
// const RaiseClaimDialog({super.key});
|
||
//
|
||
// @override
|
||
// Widget build(BuildContext context) {
|
||
// return Dialog(
|
||
// backgroundColor: Colors.white, // 👈 THIS
|
||
// insetPadding: const EdgeInsets.all(24),
|
||
// shape: RoundedRectangleBorder(
|
||
// borderRadius: BorderRadius.circular(16),
|
||
// ),
|
||
// child: Container(
|
||
// width: MediaQuery.of(context).size.width * 0.75,
|
||
// padding: const EdgeInsets.all(24),
|
||
// child: Column(
|
||
// mainAxisSize: MainAxisSize.min,
|
||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||
// children: [
|
||
// /// HEADER
|
||
// Row(
|
||
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||
// children: [
|
||
// Text(
|
||
// 'Raise Insurance Claim',
|
||
// style: GoogleFonts.poppins(
|
||
// fontSize: 20,
|
||
// fontWeight: FontWeight.w600,
|
||
// ),
|
||
// ),
|
||
// IconButton(
|
||
// icon: const Icon(Icons.close),
|
||
// onPressed: () => Navigator.pop(context),
|
||
// ),
|
||
// ],
|
||
// ),
|
||
//
|
||
// const SizedBox(height: 20),
|
||
//
|
||
// /// FORM
|
||
// Expanded(
|
||
// child: SingleChildScrollView(
|
||
// child: Column(
|
||
// children: [
|
||
// _row([
|
||
// _dropdown('Select Policy*'),
|
||
// _dropdown('Member Name'),
|
||
// _input('Hospital Name'),
|
||
// ]),
|
||
// _row([
|
||
// _input('Hospital Address'),
|
||
// _input('Hospital City'),
|
||
// _input('Hospital State'),
|
||
// ]),
|
||
// _row([
|
||
// _input('Hospital Pincode'),
|
||
// _input('Hospital Phone Number'),
|
||
// _date('Admit Date'),
|
||
// ]),
|
||
// _row([
|
||
// _date('Discharge Date'),
|
||
// _input('Claim Amount'),
|
||
// _input('Message'),
|
||
// ]),
|
||
//
|
||
// const SizedBox(height: 20),
|
||
//
|
||
// /// UPLOAD
|
||
// _uploadBox(),
|
||
// ],
|
||
// ),
|
||
// ),
|
||
// ),
|
||
//
|
||
// const SizedBox(height: 20),
|
||
//
|
||
// /// FOOTER
|
||
// Align(
|
||
// alignment: Alignment.centerRight,
|
||
// child: SizedBox(
|
||
// width: 120,
|
||
// height: 42,
|
||
// child: ElevatedButton(
|
||
// onPressed: () {},
|
||
// style: ElevatedButton.styleFrom(
|
||
// backgroundColor: const Color(0xFFE26728),
|
||
// shape: RoundedRectangleBorder(
|
||
// borderRadius: BorderRadius.circular(10),
|
||
// ),
|
||
// ),
|
||
// child: const Text(
|
||
// 'Send',
|
||
// style: TextStyle(fontWeight: FontWeight.w600),
|
||
// ),
|
||
// ),
|
||
// ),
|
||
// ),
|
||
// ],
|
||
// ),
|
||
// ),
|
||
// );
|
||
// }
|
||
//
|
||
// /// ---------- HELPERS ----------
|
||
//
|
||
// Widget _row(List<Widget> children) {
|
||
// return Padding(
|
||
// padding: const EdgeInsets.only(bottom: 14),
|
||
// child: Row(
|
||
// children: children
|
||
// .map((e) => Expanded(child: Padding(
|
||
// padding: const EdgeInsets.only(right: 12),
|
||
// child: e,
|
||
// )))
|
||
// .toList(),
|
||
// ),
|
||
// );
|
||
// }
|
||
//
|
||
// Widget _input(String label) {
|
||
// return Column(
|
||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||
// children: [
|
||
// Text(label, style: _labelStyle),
|
||
// const SizedBox(height: 6),
|
||
// _box(
|
||
// TextField(
|
||
// decoration: const InputDecoration(
|
||
// border: InputBorder.none,
|
||
// ),
|
||
// ),
|
||
// ),
|
||
// ],
|
||
// );
|
||
// }
|
||
//
|
||
// Widget _dropdown(String label) {
|
||
// return Column(
|
||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||
// children: [
|
||
// Text(label, style: _labelStyle),
|
||
// const SizedBox(height: 6),
|
||
// _box(
|
||
// DropdownButtonHideUnderline(
|
||
// child: DropdownButton<String>(
|
||
// isExpanded: true,
|
||
// hint: const Text('Select'),
|
||
// items: const [],
|
||
// onChanged: (_) {},
|
||
// ),
|
||
// ),
|
||
// ),
|
||
// ],
|
||
// );
|
||
// }
|
||
//
|
||
// Widget _date(String label) {
|
||
// return Column(
|
||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||
// children: [
|
||
// Text(label, style: _labelStyle),
|
||
// const SizedBox(height: 6),
|
||
// _box(
|
||
// TextField(
|
||
// readOnly: true,
|
||
// decoration: const InputDecoration(
|
||
// suffixIcon: Icon(Icons.calendar_today, size: 18),
|
||
// border: InputBorder.none,
|
||
// ),
|
||
// ),
|
||
// ),
|
||
// ],
|
||
// );
|
||
// }
|
||
//
|
||
// Widget _box(Widget child) {
|
||
// return Container(
|
||
// height: 42,
|
||
// padding: const EdgeInsets.symmetric(horizontal: 12),
|
||
// decoration: BoxDecoration(
|
||
// color: const Color(0xFFF1F1F1),
|
||
// borderRadius: BorderRadius.circular(8),
|
||
// ),
|
||
// child: Center(child: child),
|
||
// );
|
||
// }
|
||
//
|
||
// Widget _uploadBox() {
|
||
// return Column(
|
||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||
// children: [
|
||
// Text('Upload Documents', style: _labelStyle),
|
||
// const SizedBox(height: 8),
|
||
// Container(
|
||
// height: 120,
|
||
// width: double.infinity,
|
||
// decoration: BoxDecoration(
|
||
// borderRadius: BorderRadius.circular(10),
|
||
// border: Border.all(
|
||
// color: const Color(0xFF00A6A6),
|
||
// style: BorderStyle.solid,
|
||
// ),
|
||
// color: const Color(0xFFF9F9F9),
|
||
// ),
|
||
// child: Column(
|
||
// mainAxisAlignment: MainAxisAlignment.center,
|
||
// children: const [
|
||
// Icon(Icons.insert_drive_file,
|
||
// size: 36, color: Color(0xFF00A6A6)),
|
||
// SizedBox(height: 6),
|
||
// Text(
|
||
// 'Sample_file.PDF',
|
||
// style: TextStyle(fontWeight: FontWeight.w500),
|
||
// ),
|
||
// SizedBox(height: 4),
|
||
// Text(
|
||
// '(Supported formats: PDF, PNG, JPG, JPEG, HEIC)',
|
||
// style: TextStyle(fontSize: 11, color: Colors.grey),
|
||
// ),
|
||
// ],
|
||
// ),
|
||
// ),
|
||
// ],
|
||
// );
|
||
// }
|
||
// }
|
||
|
||
/// ---------- STYLES ----------
|
||
final _labelStyle = GoogleFonts.poppins(
|
||
fontSize: 12,
|
||
fontWeight: FontWeight.w500,
|
||
);
|