diff --git a/.env b/.env
index 5f1f339..3c01a91 100644
--- a/.env
+++ b/.env
@@ -1,6 +1,6 @@
-API_URL=https://venbait.in/nhance/dev/employeeRest/
-chatbot_Url=https://venbait.in/nhance/dev/chatbot
-API_URL_Enrollment=https://venbait.in/enrollment/employeeRest/
-TICKET_API_URL=https://venbait.in/nhance/dev/api
-BASE_HREF=/nhance/app/dev/
-ENV=development
+API_URL=https://app.nhanceindia.in/zenith/employeeRest/
+API_URL_Enrollment=https://app.nhanceindia.in/enrolment/employeeRest/
+TICKET_API_URL=https://app.nhanceindia.in/zenith/api
+chatbot_Url=https://app.nhanceindia.in/zenith/chatbot
+BASE_HREF=/app/
+ENV=production
\ No newline at end of file
diff --git a/.env.development b/.env.development
index 5f1f339..3c01a91 100644
--- a/.env.development
+++ b/.env.development
@@ -1,6 +1,6 @@
-API_URL=https://venbait.in/nhance/dev/employeeRest/
-chatbot_Url=https://venbait.in/nhance/dev/chatbot
-API_URL_Enrollment=https://venbait.in/enrollment/employeeRest/
-TICKET_API_URL=https://venbait.in/nhance/dev/api
-BASE_HREF=/nhance/app/dev/
-ENV=development
+API_URL=https://app.nhanceindia.in/zenith/employeeRest/
+API_URL_Enrollment=https://app.nhanceindia.in/enrolment/employeeRest/
+TICKET_API_URL=https://app.nhanceindia.in/zenith/api
+chatbot_Url=https://app.nhanceindia.in/zenith/chatbot
+BASE_HREF=/app/
+ENV=production
\ No newline at end of file
diff --git a/assets/nhance_client_logo.png b/assets/nhance_client_logo.png
old mode 100755
new mode 100644
diff --git a/assets/nhance_client_logo.svg b/assets/nhance_client_logo.svg
new file mode 100644
index 0000000..1b3df04
--- /dev/null
+++ b/assets/nhance_client_logo.svg
@@ -0,0 +1,11 @@
+
diff --git a/assets/nhance_logo.png b/assets/nhance_logo.png
new file mode 100644
index 0000000..26029eb
Binary files /dev/null and b/assets/nhance_logo.png differ
diff --git a/lib/customAppBar/customAppBar.dart b/lib/customAppBar/customAppBar.dart
index 30fa214..52d14e4 100755
--- a/lib/customAppBar/customAppBar.dart
+++ b/lib/customAppBar/customAppBar.dart
@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:adaptive_navbar/adaptive_navbar.dart';
+import 'package:flutter_svg/svg.dart';
import 'package:go_router/go_router.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:nhance_app_pwa/customAppBar/responsive.dart';
@@ -59,14 +60,18 @@ class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
.start, // Adjust the alignment as needed
children: [
Container(
- margin: EdgeInsets.only(
- top: 10, bottom: 10, left: 10, right: 10),
- width: Responsive.isDesktop(context) ? 150 : 130,
- height: Responsive.isDesktop(context) ? 150 : 130,
- child: Image.asset(
- 'assets/nhance_client_logo.png',
- fit: BoxFit.contain, // Adjust the fit as needed
+ // margin: EdgeInsets.only(
+ // top: 10, bottom: 10, left: 10, right: 10),
+ // width: Responsive.isDesktop(context) ? 150 : 130,
+ // height: Responsive.isDesktop(context) ? 31 : 130,
+ child: SvgPicture.asset(
+ 'assets/nhance_client_logo.svg',
+ width: 150,
),
+ // child: Image.asset(
+ // 'assets/nhance_logo.png',
+ // width: 250,
+ // ),
),
],
),
diff --git a/lib/pages/enrollment/addons.dart b/lib/pages/enrollment/addons.dart
index dc99640..42e8674 100755
--- a/lib/pages/enrollment/addons.dart
+++ b/lib/pages/enrollment/addons.dart
@@ -85,6 +85,8 @@ class _addOnsDetailsState extends State {
dynamic gmcTypeName;
dynamic clientName;
dynamic clientLogo;
+ bool gpahasPremiumSummary = false;
+ bool gmchasPremiumSummary = false;
dynamic addon_subheading;
dynamic topUpECardDownload;
dynamic topUpMappedFamilyFloatersSi;
@@ -332,6 +334,10 @@ class _addOnsDetailsState extends State {
setState(() {
gpaPolicies = response['data'];
for (var item in gpaPolicies) {
+ if (item['is_premium_summery'] == "1") {
+ gpahasPremiumSummary = true;
+ break;
+ }
// Extract disclaimer value from each object
if (item['OpenForEnrollment'] == '1') {
dynamic disclaimer = item['disclaimer'];
@@ -408,6 +414,13 @@ class _addOnsDetailsState extends State {
// setState(() {
gmcPolicies = response['data'];
for (var item in gmcPolicies) {
+ print('checking is_premium_summery ${item['is_premium_summery']}');
+ if (item['is_premium_summery'] == "1") {
+ print('checking is_premium_summery ${item['is_premium_summery']}');
+ gmchasPremiumSummary = true;
+ print('gmchasPremiumSummary ${gmchasPremiumSummary}');
+ break;
+ }
if (item['OpenForEnrollment'] == '1') {
dynamic disclaimer = item['disclaimer'];
if (disclaimer != null && disclaimer.isNotEmpty) {
@@ -4056,217 +4069,220 @@ class _addOnsDetailsState extends State {
: EdgeInsets.all(10),
child: Column(
children: [
-
- Container(
- child: Row(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Expanded(
- flex: 12,
- child: Container(
- alignment: Alignment.centerLeft,
- child: Column(
- mainAxisAlignment:
- MainAxisAlignment.start,
- crossAxisAlignment:
- CrossAxisAlignment.start,
- children: [
- Text(
- 'Premium Summary',
- textAlign: TextAlign.left,
- style: GoogleFonts.poppins(
- fontSize:
- Responsive.isDesktop(
- context)
- ? 18
- : 16,
- color: Color(0xFF181818),
- fontWeight: FontWeight.w600,
- ),
- ),
- ],
- ))),
- ],
- ),
- ),
- SizedBox(height: 15),
- Container(
- child: Row(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Expanded(
- flex: 12,
- child: Container(
- alignment: Alignment
- .centerLeft, // Adjust padding as needed
- child: Table(
- columnWidths: {
- 0: FlexColumnWidth(
- 2), // Adjust column width as needed
- 1: FlexColumnWidth(2),
- 2: FlexColumnWidth(
- 2), // Adjust column width as needed
- 3: FlexColumnWidth(2),
- },
- children: [
- TableRow(
+ if(gpahasPremiumSummary == true || gmchasPremiumSummary == true)...[
+ Container(
+ child: Row(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Expanded(
+ flex: 12,
+ child: Container(
+ alignment: Alignment.centerLeft,
+ child: Column(
+ mainAxisAlignment:
+ MainAxisAlignment.start,
+ crossAxisAlignment:
+ CrossAxisAlignment.start,
children: [
- TableCell(
- child: Padding(
- padding:
- EdgeInsets.all(8.0),
- child: Text(
- 'Policy ',
- textAlign:
- TextAlign.start,
- style: GoogleFonts.poppins(
- fontSize: Responsive
- .isDesktop(
- context)
- ? 16
- : 13,
- fontWeight:
- FontWeight
- .bold),
- ),
- ),
- ),
- TableCell(
- child: Padding(
- padding:
- EdgeInsets.all(8.0),
- child: Text(
- 'Additional Premium',
- textAlign:
- TextAlign.start,
- style: GoogleFonts.poppins(
- fontSize: Responsive
- .isDesktop(
- context)
- ? 16
- : 13,
- fontWeight:
- FontWeight
- .bold),
- ),
- ),
- ),
- TableCell(
- child: Padding(
- padding:
- EdgeInsets.all(8.0),
- child: Text(
- 'GST',
- textAlign:
- TextAlign.start,
- style: GoogleFonts.poppins(
- fontSize: Responsive
- .isDesktop(
- context)
- ? 16
- : 13,
- fontWeight:
- FontWeight
- .bold),
- ),
- ),
- ),
- TableCell(
- child: Padding(
- padding:
- EdgeInsets.all(8.0),
- child: Text(
- 'Total',
- textAlign:
- TextAlign.start,
- style: GoogleFonts.poppins(
- fontSize: Responsive
- .isDesktop(
- context)
- ? 16
- : 13,
- fontWeight:
- FontWeight
- .bold),
- ),
+ Text(
+ 'Premium Summary',
+ textAlign: TextAlign.left,
+ style: GoogleFonts.poppins(
+ fontSize:
+ Responsive.isDesktop(
+ context)
+ ? 18
+ : 16,
+ color: Color(0xFF181818),
+ fontWeight: FontWeight.w600,
),
),
],
+ ))),
+ ],
+ ),
+ ),
+ SizedBox(height: 15),
+ if(gpahasPremiumSummary == true || gmchasPremiumSummary == true)
+ Container(
+ child: Row(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Expanded(
+ flex: 12,
+ child: Container(
+ alignment: Alignment
+ .centerLeft, // Adjust padding as needed
+ child: Table(
+ columnWidths: {
+ 0: FlexColumnWidth(
+ 2), // Adjust column width as needed
+ 1: FlexColumnWidth(2),
+ 2: FlexColumnWidth(
+ 2), // Adjust column width as needed
+ 3: FlexColumnWidth(2),
+ },
+ children: [
+ TableRow(
+ children: [
+ TableCell(
+ child: Padding(
+ padding:
+ EdgeInsets.all(8.0),
+ child: Text(
+ 'Policy ',
+ textAlign:
+ TextAlign.start,
+ style: GoogleFonts.poppins(
+ fontSize: Responsive
+ .isDesktop(
+ context)
+ ? 16
+ : 13,
+ fontWeight:
+ FontWeight
+ .bold),
+ ),
+ ),
+ ),
+ TableCell(
+ child: Padding(
+ padding:
+ EdgeInsets.all(8.0),
+ child: Text(
+ 'Additional Premium',
+ textAlign:
+ TextAlign.start,
+ style: GoogleFonts.poppins(
+ fontSize: Responsive
+ .isDesktop(
+ context)
+ ? 16
+ : 13,
+ fontWeight:
+ FontWeight
+ .bold),
+ ),
+ ),
+ ),
+ TableCell(
+ child: Padding(
+ padding:
+ EdgeInsets.all(8.0),
+ child: Text(
+ 'GST',
+ textAlign:
+ TextAlign.start,
+ style: GoogleFonts.poppins(
+ fontSize: Responsive
+ .isDesktop(
+ context)
+ ? 16
+ : 13,
+ fontWeight:
+ FontWeight
+ .bold),
+ ),
+ ),
+ ),
+ TableCell(
+ child: Padding(
+ padding:
+ EdgeInsets.all(8.0),
+ child: Text(
+ 'Total',
+ textAlign:
+ TextAlign.start,
+ style: GoogleFonts.poppins(
+ fontSize: Responsive
+ .isDesktop(
+ context)
+ ? 16
+ : 13,
+ fontWeight:
+ FontWeight
+ .bold),
+ ),
+ ),
+ ),
+ ],
+ ),
+ if (gpaPolicies != null &&
+ gpaPolicies.length > 0)
+ ...gpaBuildPolicyRows(
+ gpaPolicies, context),
+ if (gmcPolicies != null &&
+ gmcPolicies.length > 0)
+ ...gmcBuildPolicyRows(
+ gmcPolicies, context),
+ ],
),
- if (gpaPolicies != null &&
- gpaPolicies.length > 0)
- ...gpaBuildPolicyRows(
- gpaPolicies, context),
- if (gmcPolicies != null &&
- gmcPolicies.length > 0)
- ...gmcBuildPolicyRows(
- gmcPolicies, context),
- ],
- ),
- ))
- ],
- ),
- ),
- SizedBox(height: 10),
- Container(
- child: Row(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Expanded(
- flex: 6,
- child: Container(
- alignment: Alignment.centerLeft,
- child: Column(
- mainAxisAlignment:
- MainAxisAlignment.start,
- crossAxisAlignment:
- CrossAxisAlignment.start,
- children: [
- Text(
- 'Total Payable',
- textAlign: TextAlign.left,
- style: GoogleFonts.poppins(
- fontSize:
- Responsive.isDesktop(
- context)
- ? 20
- : 16,
- color: Color(0xFF181818),
- fontWeight: FontWeight.w600,
+ ))
+ ],
+ ),
+ ),
+ SizedBox(height: 10),
+ Container(
+ child: Row(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Expanded(
+ flex: 6,
+ child: Container(
+ alignment: Alignment.centerLeft,
+ child: Column(
+ mainAxisAlignment:
+ MainAxisAlignment.start,
+ crossAxisAlignment:
+ CrossAxisAlignment.start,
+ children: [
+ Text(
+ 'Total Payable',
+ textAlign: TextAlign.left,
+ style: GoogleFonts.poppins(
+ fontSize:
+ Responsive.isDesktop(
+ context)
+ ? 20
+ : 16,
+ color: Color(0xFF181818),
+ fontWeight: FontWeight.w600,
+ ),
),
- ),
- ],
- ))),
- Expanded(
- flex: 6,
- child: Container(
- alignment: Alignment.centerRight,
- child: Column(
- mainAxisAlignment:
- MainAxisAlignment.end,
- crossAxisAlignment:
- CrossAxisAlignment.end,
- children: [
- Text(
- '₹${allTotalSum()}/Year',
- textAlign: TextAlign.right,
- style: GoogleFonts.poppins(
- fontSize:
- Responsive.isDesktop(
- context)
- ? 18
- : 16,
- color: Color(0xFFE26728),
- fontWeight: FontWeight.w500,
+ ],
+ ))),
+ Expanded(
+ flex: 6,
+ child: Container(
+ alignment: Alignment.centerRight,
+ child: Column(
+ mainAxisAlignment:
+ MainAxisAlignment.end,
+ crossAxisAlignment:
+ CrossAxisAlignment.end,
+ children: [
+ Text(
+ '₹${allTotalSum()}/Year',
+ textAlign: TextAlign.right,
+ style: GoogleFonts.poppins(
+ fontSize:
+ Responsive.isDesktop(
+ context)
+ ? 18
+ : 16,
+ color: Color(0xFFE26728),
+ fontWeight: FontWeight.w500,
+ ),
),
- ),
- ],
- )))
- ],
+ ],
+ )))
+ ],
+ ),
),
- ),
- SizedBox(height: 10),
+ SizedBox(height: 10),
+ ],
+
Container(
alignment: Alignment.topLeft,
child: Row(
diff --git a/lib/pages/enrollment/empReview.dart b/lib/pages/enrollment/empReview.dart
index f0e4aea..1c86992 100755
--- a/lib/pages/enrollment/empReview.dart
+++ b/lib/pages/enrollment/empReview.dart
@@ -510,8 +510,11 @@ class _empReviewDetailsState extends State {
print('gmcPolicies $gmcPolicies');
for (var policy in gmcPolicies) {
+ print('checking is_premium_summery ${policy['is_premium_summery']}');
if (policy['is_premium_summery'] == "1") {
+ print('checking is_premium_summery ${policy['is_premium_summery']}');
gmchasPremiumSummary = true;
+ print('gmchasPremiumSummary ${gmchasPremiumSummary}');
break;
}
}
diff --git a/lib/pages/postEnrollment/planclaimsform.dart b/lib/pages/postEnrollment/planclaimsform.dart
index 8bee409..313a39c 100755
--- a/lib/pages/postEnrollment/planclaimsform.dart
+++ b/lib/pages/postEnrollment/planclaimsform.dart
@@ -115,6 +115,8 @@ class _planclaimsformState extends State {
bool isClaimAmountValid = true;
bool isAccidentDateValid = true;
bool isIntimationDateValid = true;
+ bool isAdmitDateValid = true;
+ bool isDischargeDateValid = true;
final session = SessionManager();
@@ -516,7 +518,9 @@ class _planclaimsformState extends State {
isMemberValid = selectedMemberId != null;
isSubjectValid = subjectController.text.trim().isNotEmpty;
isHospitalNameValid = policyTypeCondition != 1 || hospitalNameController.text.trim().isNotEmpty;
- isAdmitDischargeValid = policyTypeCondition != 1 || (admitDate != null && dischargeDate != null);
+ // isAdmitDischargeValid = policyTypeCondition != 1 || (admitDate != null && dischargeDate != null);
+ isAdmitDateValid = policyTypeCondition != 1 || admitDate != null;
+ isDischargeDateValid = policyTypeCondition != 1 || dischargeDate != null;
isClaimAmountValid = serviceId != 1 || claimAmountController.text.trim().isNotEmpty;
isAccidentDateValid = (serviceId == 2 || serviceId == 3 || serviceId == 4) ? accidentDate != null : true;
isIntimationDateValid = (serviceId == 2 || serviceId == 3 || serviceId == 4) ? intimationDate != null : true;
@@ -527,10 +531,18 @@ class _planclaimsformState extends State {
isMemberValid &&
isSubjectValid &&
isHospitalNameValid &&
- isAdmitDischargeValid &&
+ 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');
@@ -544,20 +556,17 @@ class _planclaimsformState extends State {
final SharedPreferences prefs = await SharedPreferences.getInstance();
final String? emp_id = session.empPrimaryId;
print('Check One $client_policy_id');
- // print(employeePolicyList[0]['name']);
- // print('Help $filteredPoliciesList');
+
try {
print('Check One');
Map fields = {
- // 'opener': 'user',
+
'emp_id': emp_id,
'client_policy_id': client_policy_id,
'ticket_type_id': serviceId,
'subject': subjectController.text,
'message': messageController.text,
- // 'policy_id': fromClaimsPage == 0
- // ? claimsDetails['client_policy_id']
- // : policyNumberId,
+
'emp_code': empCodeString ?? ' ',
'mobile_number': mobileNo ?? '',
'email': session.empEmailCorporate ?? '',
@@ -571,35 +580,16 @@ class _planclaimsformState extends State {
: (fromClaimsPage == 0
? claimsDetails['policy_name']
: filteredPoliciesList[0]['policy_name']),
- // 'tpa': serviceId == 1
- // ? null
- // : (fromClaimsPage == 0
- // ? claimsDetails['tpa_name']
- // : filteredPoliciesList[0]['tpa_name']),
- // 'insurer': serviceId == 1
- // ? null
- // : (fromClaimsPage == 0
- // ? claimsDetails['insurer_name']
- // : filteredPoliciesList[0]['insurer_name']),
+
};
- // Conditionally add fields based on the first word in policy_type
- // if (policyTypeCondition == 3) {
- // String formattedAccidentDate =
- // DateFormat('yyyy-MM-dd').format(accidentDate!);
- // // formData['accident_details'] = accidentDetailsController.text;
- // formData['accident_details'] = messageController.text;
- // formData['accident_date'] = formattedAccidentDate;
- // formData['claim_amount'] = claimAmountController.text;
- // formData['policyholder_name'] = employeePolicyList[0]['name'];
- // formData['member_name'] = selectedMemberName;
- // formData['emp_policy_id'] = selectedMemberId;
- // } else
if (policyTypeCondition == 1) {
+ String formattedAdmitDate = DateFormat('yyyy-MM-dd').format(admitDate!);
+ String formattedDischargeDate = DateFormat('yyyy-MM-dd').format(dischargeDate!);
fields['hospital_name'] = hospitalNameController.text;
- fields['doa'] = admitDateController.text;
- fields['dod'] = dischargeDateController.text;
+ fields['doa'] = formattedAdmitDate;
+ fields['dod'] = formattedDischargeDate;
fields['claim_amount'] = claimAmountController.text;
fields['policyholder_name'] = employeePolicyList[0]['name'];
fields['member_name'] = selectedMemberName;
@@ -611,8 +601,6 @@ class _planclaimsformState extends State {
String formattedBirthDate = DateFormat('yyyy-MM-dd').format(birthDate!);
String formattedIntimationDate =
DateFormat('yyyy-MM-dd').format(intimationDate!);
- // formData['accident_details'] = accidentDetailsController.text;
- // formData['accident_details'] = messageController.text;
fields['date_of_accident'] = formattedAccidentDate;
fields['dob'] = formattedBirthDate;
fields['date_of_intimat'] = formattedIntimationDate;
@@ -623,26 +611,6 @@ class _planclaimsformState extends State {
fields['insured_emp_id'] = selectedMemberId;
}
- // Multipart request
-
- // final request = http.MultipartRequest('POST', Uri.parse('${Environment.apiUrl}/initiateClaim'));
- // request.headers['Authorization'] = 'Bearer $_token';
- // final stringFields = fields.map((key, value) => MapEntry(key, value?.toString() ?? ''));
- // request.fields.addAll(stringFields);
- //
- // if (uploadedFile != null) {
- // final reader = html.FileReader();
- // reader.readAsArrayBuffer(uploadedFile!);
- // await reader.onLoad.first;
- //
- // final data = reader.result as Uint8List;
- //
- // request.files.add(http.MultipartFile.fromBytes(
- // 'claim_docs',
- // data,
- // filename: uploadedFile!.name,
- // ));
- // }
_token = await TokenService.getPostToken();
final request = http.MultipartRequest('POST', Uri.parse('${Environment.apiUrl}/initiateClaim'));
@@ -650,31 +618,44 @@ class _planclaimsformState extends State {
final stringFields = fields.map((key, value) => MapEntry(key, value?.toString() ?? ''));
request.fields.addAll(stringFields);
- // 🔥 Loop through multiple files
- // for (var file in uploadedFiles) {
- // final reader = html.FileReader();
- // reader.readAsArrayBuffer(file);
- // await reader.onLoad.first;
- // final data = reader.result as Uint8List;
- //
- // request.files.add(http.MultipartFile.fromBytes(
- // 'claim_docs[]', // 👈 if backend expects array
- // data,
- // filename: file.name,
- // ));
- // }
- uploadedFiles = FileUploadService().files;
- print("Files available globally: ${uploadedFiles.map((f) => f.name).toList()}");
- for (var file in uploadedFiles) {
- if (file.bytes != null) {
+ // 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;
+ }
+ }
+
+ // Add files
+ for (var uf in uploadedFiles) {
+ final pf = uf.file;
+ if (pf.bytes != null) {
request.files.add(http.MultipartFile.fromBytes(
'claim_docs[]',
- file.bytes!,
- filename: file.name,
+ pf.bytes!,
+ 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();
@@ -1199,25 +1180,42 @@ SizedBox(height: 15),
// accidentDetailsController),
// SizedBox(height: 15),
if (policyTypeCondition == 1) ...[
- InkWell(
- onTap: () => _pickFromToDate(context),
- child: InputDecorator(
- decoration: InputDecoration(
- labelText: 'Admit Date - Discharge Date',
- border: OutlineInputBorder(),
- ),
- child: Text(
- admitDate != null && dischargeDate != null
- ? '${admitDateController.text} to ${dischargeDateController.text}'
- : 'Select Admit and Discharge Dates',
- style: TextStyle(color: Colors.black),
- ),
- ),
+ // 🟡 Admit Date — no future allowed
+ buildDatePickerField(
+ label: 'Admit Date',
+ selectedDate: admitDate,
+ allowFuture: false,
+ onDateSelected: (selectedDate) {
+ setState(() {
+ admitDate = selectedDate;
+ dischargeDate = null; // reset discharge when admit changes
+ });
+ },
),
- if (!isAdmitDischargeValid)
- Text('Please select Admit and Discharge Dates', style: TextStyle(color: Colors.red)),
+ if (!isAdmitDateValid)
+ const Text('Please select the Admit Date', style: TextStyle(color: Colors.red)),
+ const SizedBox(height: 20),
+
+ // 🟢 Discharge Date — must be after Admit Date
+ buildDatePickerField(
+ label: 'Discharge Date',
+ selectedDate: dischargeDate,
+ allowFuture: true,
+ minDate: admitDate != null
+ ? admitDate!.add(const Duration(days: 1))
+ : DateTime.now().add(const Duration(days: 1)),
+ maxDate: null,
+ onDateSelected: (selectedDate) {
+ setState(() {
+ dischargeDate = selectedDate;
+ });
+ },
+ ),
+ if (!isDischargeDateValid)
+ const Text('Please select the Discharge Date', style: TextStyle(color: Colors.red)),
],
+
SizedBox(height: 15),
if (serviceId == 1) ...[
buildTextField('Claims Amount', claimAmountController, TextInputType.number),
@@ -1421,14 +1419,42 @@ SizedBox(height: 15),
return InkWell(
onTap: () async {
final DateTime now = DateTime.now();
- final DateTime first = minDate ?? DateTime(2000);
- final DateTime last = allowFuture ? (maxDate ?? DateTime(2100)) : now;
+
+ // 👇 Special rules only for Admit & Discharge
+ DateTime first;
+ DateTime last;
+
+ if (label == 'Admit Date') {
+ // ❌ Admit date cannot be future
+ first = minDate ?? DateTime(2000);
+ last = now;
+ } else if (label == 'Discharge Date') {
+ // ✅ Discharge date must be AFTER admit date, future allowed
+ first = minDate ?? now.add(const Duration(days: 1));
+ last = maxDate ?? DateTime(2100);
+ } else {
+ // All other date pickers keep original behavior
+ first = minDate ?? DateTime(1980);
+ last = allowFuture ? (maxDate ?? DateTime(2100)) : now;
+ }
+
+ // final DateTime? pickedDate = await showDatePicker(
+ // context: context,
+ // initialDate: selectedDate ?? now,
+ // firstDate: label == "Date of Birth" ? DateTime(1900) : first,
+ // lastDate: label == "Date of Birth" ? now : last,
+ // );
+
+ // ✅ Fix: Ensure initialDate always within valid range
+ DateTime initialDate = selectedDate ?? now;
+ if (initialDate.isBefore(first)) initialDate = first;
+ if (initialDate.isAfter(last)) initialDate = last;
final DateTime? pickedDate = await showDatePicker(
context: context,
- initialDate: selectedDate ?? now,
- firstDate: label == "Date of Birth" ? DateTime(1900) : first,
- lastDate: label == "Date of Birth" ? now : last,
+ initialDate: initialDate,
+ firstDate: first,
+ lastDate: last,
);
if (pickedDate != null) {
@@ -1438,18 +1464,19 @@ SizedBox(height: 15),
child: InputDecorator(
decoration: InputDecoration(
labelText: label,
- border: OutlineInputBorder(),
+ border: const OutlineInputBorder(),
),
child: Text(
selectedDate != null
? DateFormat('dd-MM-yyyy').format(selectedDate)
: 'Select $label',
- style: TextStyle(color: Colors.black),
+ style: const TextStyle(color: Colors.black),
),
),
);
}
+
Widget buildDropdownField(
String label,
void Function(int?) onChanged,
diff --git a/lib/pages/postEnrollment/service/file_upload_service.dart b/lib/pages/postEnrollment/service/file_upload_service.dart
index ea1da68..643d002 100644
--- a/lib/pages/postEnrollment/service/file_upload_service.dart
+++ b/lib/pages/postEnrollment/service/file_upload_service.dart
@@ -1,16 +1,31 @@
import 'package:file_picker/file_picker.dart';
+import 'package:flutter/widgets.dart';
+
+class UploadedFile {
+ final PlatformFile file;
+ final TextEditingController controller;
+ UploadedFile({required this.file})
+ : controller = TextEditingController(
+ text: file.extension != null
+ ? file.name.replaceAll('.${file.extension}', '')
+ : file.name);
+
+ String get label => controller.text;
+ void dispose() => controller.dispose();
+}
class FileUploadService {
FileUploadService._();
static final FileUploadService _instance = FileUploadService._();
factory FileUploadService() => _instance;
- final List _files = [];
+ final List _files = [];
- List get files => List.unmodifiable(_files);
+ // Expose as unmodifiable but containing UploadedFile objects
+ List get files => List.unmodifiable(_files);
// Allowed extensions
- static const allowedExtensions = ['pdf', 'png', 'jpg', 'jpeg','heic'];
+ static const allowedExtensions = ['pdf', 'png', 'jpg', 'jpeg', 'heic'];
Future pickFiles({int maxFileSizeInMB = 3}) async {
final result = await FilePicker.platform.pickFiles(
@@ -21,26 +36,35 @@ class FileUploadService {
);
if (result != null) {
- for (final file in result.files) {
- final ext = file.extension?.toLowerCase() ?? '';
- final sizeInMB = (file.size / (1024 * 1024));
+ for (final pf in result.files) {
+ final ext = pf.extension?.toLowerCase() ?? '';
+ final sizeInMB = (pf.size / (1024 * 1024));
if (!allowedExtensions.contains(ext)) {
- return "Unsupported file format: ${file.name}";
+ return "Unsupported file format: ${pf.name}";
}
if (sizeInMB > maxFileSizeInMB) {
- return "File too large (${file.name}). Max $maxFileSizeInMB MB allowed.";
+ return "File too large (${pf.name}). Max $maxFileSizeInMB MB allowed.";
}
- }
- _files.addAll(result.files);
+ // Wrap PlatformFile in our UploadedFile model
+ _files.add(UploadedFile(file: pf));
+ }
}
- return null; // success
+ return null;
}
void removeFileAt(int index) {
- if (index >= 0 && index < _files.length) _files.removeAt(index);
+ if (index >= 0 && index < _files.length) {
+ _files[index].dispose();
+ _files.removeAt(index);
+ }
}
- void clearAll() => _files.clear();
+ void clearAll() {
+ for (final f in _files) {
+ f.dispose();
+ }
+ _files.clear();
+ }
}
diff --git a/lib/pages/postEnrollment/service/multi_file_upload_widget.dart b/lib/pages/postEnrollment/service/multi_file_upload_widget.dart
index 3f3dc3b..7ae2df4 100644
--- a/lib/pages/postEnrollment/service/multi_file_upload_widget.dart
+++ b/lib/pages/postEnrollment/service/multi_file_upload_widget.dart
@@ -7,6 +7,8 @@ class MultiFileUploadWidget extends StatefulWidget {
@override
State createState() => _MultiFileUploadWidgetState();
+
+ static bool hasFiles = false; // ✅ Static variable to check from parent
}
class _MultiFileUploadWidgetState extends State {
@@ -39,13 +41,16 @@ class _MultiFileUploadWidgetState extends State {
} else {
setState(() {
errorMessage = null;
+ MultiFileUploadWidget.hasFiles = fileService.files.isNotEmpty;
});
}
}
void _removeFile(int index) {
fileService.removeFileAt(index);
- setState(() {});
+ setState(() {
+ MultiFileUploadWidget.hasFiles = fileService.files.isNotEmpty;
+ });
}
@override
@@ -108,6 +113,14 @@ class _MultiFileUploadWidgetState extends State {
),
],
+ if (fileService.files.isEmpty && errorMessage == null) ...[
+ const SizedBox(height: 4),
+ const Text(
+ "Required",
+ style: TextStyle(color: Colors.red, fontSize: 12),
+ ),
+ ],
+
if (errorMessage != null) ...[
const SizedBox(height: 4),
Text(
@@ -117,18 +130,34 @@ class _MultiFileUploadWidgetState extends State {
],
const SizedBox(height: 8),
- ...files.asMap().entries.map((entry) {
+ ...fileService.files.asMap().entries.map((entry) {
final index = entry.key;
- final file = entry.value;
+ final uploaded = entry.value; // UploadedFile
- return ListTile(
- dense: true,
- contentPadding: EdgeInsets.zero,
- title: Text(file.name, style: const TextStyle(fontSize: 14)),
- trailing: IconButton(
- icon: const Icon(Icons.close, color: Colors.red),
- onPressed: () => _removeFile(index),
- ),
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ ListTile(
+ dense: true,
+ contentPadding: EdgeInsets.zero,
+ title: Text(uploaded.file.name, style: const TextStyle(fontSize: 14)),
+ trailing: IconButton(
+ icon: const Icon(Icons.close, color: Colors.red),
+ onPressed: () => _removeFile(index),
+ ),
+ ),
+ Padding(
+ padding: const EdgeInsets.only(left: 8.0, bottom: 8.0, right: 8.0),
+ child: TextField(
+ controller: uploaded.controller,
+ decoration: const InputDecoration(
+ labelText: 'Enter document name',
+ border: OutlineInputBorder(),
+ isDense: true,
+ ),
+ ),
+ ),
+ ],
);
}),
],
diff --git a/lib/pages/service/popup_helper.dart b/lib/pages/service/popup_helper.dart
index f5067d5..7d86132 100644
--- a/lib/pages/service/popup_helper.dart
+++ b/lib/pages/service/popup_helper.dart
@@ -56,6 +56,19 @@ class PopupHelper {
final double dialogHeight =
isMobile ? MediaQuery.of(context).size.height * 0.17 : 150;
+ // Auto close after 3 seconds and redirect
+ Future.delayed(const Duration(seconds: 2), () {
+ if (Navigator.of(dialogContext).canPop()) {
+ Navigator.of(dialogContext).pop();
+ }
+
+ if (wellnessURL != null) {
+ launchURL(wellnessURL, context);
+ } else {
+ ToastHelper.showInfoToast(context, 'Invalid link or unavailable');
+ }
+ });
+
return Dialog(
insetPadding: EdgeInsets.symmetric(horizontal: isMobile ? 40 : 0),
shape: RoundedRectangleBorder(
@@ -67,10 +80,12 @@ class PopupHelper {
height: dialogHeight,
padding: const EdgeInsets.all(20),
child: Column(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ mainAxisAlignment: MainAxisAlignment.center,
+ crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
- 'You are being redirected out of this app. Click Proceed to Continue',
+ 'You are being redirected out of this app.',
+ // 'You are being redirected out of this app. Click Proceed to Continue',
textAlign: TextAlign.center,
style: GoogleFonts.poppins(
fontSize: isMobile ? 14 : 16,
@@ -78,65 +93,65 @@ class PopupHelper {
color: const Color(0xFF777777),
),
),
- const SizedBox(height: 20),
- Row(
- mainAxisAlignment: MainAxisAlignment.spaceEvenly,
- children: [
- Expanded(
- child: OutlinedButton(
- onPressed: () => Navigator.pop(dialogContext),
- style: OutlinedButton.styleFrom(
- side: const BorderSide(color: Color(0xFFE26728)),
- shape: RoundedRectangleBorder(
- borderRadius: BorderRadius.circular(10),
- ),
- padding: const EdgeInsets.symmetric(vertical: 12),
- ),
- child: FittedBox(
- fit: BoxFit.scaleDown,
- child: Text(
- 'Cancel',
- style: GoogleFonts.poppins(
- color: const Color(0xFFE26728),
- fontSize: isMobile ? 14 : 16,
- ),
- ),
- ),
- ),
- ),
- const SizedBox(width: 15),
- Expanded(
- child: ElevatedButton(
- onPressed: () {
- Navigator.of(dialogContext).pop();
- if (wellnessURL != null) {
- launchURL(wellnessURL, context);
- } else {
- ToastHelper.showInfoToast(
- context, 'Invalid link or unavailable');
- }
- },
- style: ElevatedButton.styleFrom(
- backgroundColor: const Color(0xFFE26728),
- shape: RoundedRectangleBorder(
- borderRadius: BorderRadius.circular(10),
- ),
- padding: const EdgeInsets.symmetric(vertical: 12),
- ),
- child: FittedBox(
- fit: BoxFit.scaleDown,
- child: Text(
- 'Proceed',
- style: GoogleFonts.poppins(
- color: Colors.white,
- fontSize: isMobile ? 14 : 16,
- ),
- ),
- ),
- ),
- ),
- ],
- ),
+ // const SizedBox(height: 20),
+ // Row(
+ // mainAxisAlignment: MainAxisAlignment.spaceEvenly,
+ // children: [
+ // Expanded(
+ // child: OutlinedButton(
+ // onPressed: () => Navigator.pop(dialogContext),
+ // style: OutlinedButton.styleFrom(
+ // side: const BorderSide(color: Color(0xFFE26728)),
+ // shape: RoundedRectangleBorder(
+ // borderRadius: BorderRadius.circular(10),
+ // ),
+ // padding: const EdgeInsets.symmetric(vertical: 12),
+ // ),
+ // child: FittedBox(
+ // fit: BoxFit.scaleDown,
+ // child: Text(
+ // 'Cancel',
+ // style: GoogleFonts.poppins(
+ // color: const Color(0xFFE26728),
+ // fontSize: isMobile ? 14 : 16,
+ // ),
+ // ),
+ // ),
+ // ),
+ // ),
+ // const SizedBox(width: 15),
+ // Expanded(
+ // child: ElevatedButton(
+ // onPressed: () {
+ // Navigator.of(dialogContext).pop();
+ // if (wellnessURL != null) {
+ // launchURL(wellnessURL, context);
+ // } else {
+ // ToastHelper.showInfoToast(
+ // context, 'Invalid link or unavailable');
+ // }
+ // },
+ // style: ElevatedButton.styleFrom(
+ // backgroundColor: const Color(0xFFE26728),
+ // shape: RoundedRectangleBorder(
+ // borderRadius: BorderRadius.circular(10),
+ // ),
+ // padding: const EdgeInsets.symmetric(vertical: 12),
+ // ),
+ // child: FittedBox(
+ // fit: BoxFit.scaleDown,
+ // child: Text(
+ // 'Proceed',
+ // style: GoogleFonts.poppins(
+ // color: Colors.white,
+ // fontSize: isMobile ? 14 : 16,
+ // ),
+ // ),
+ // ),
+ // ),
+ // ),
+ // ],
+ // ),
],
),
),
@@ -206,4 +221,4 @@ class PopupHelper {
},
);
}
-}
+}
\ No newline at end of file