claim upload name added and permium hide content

This commit is contained in:
Surendiran 2025-11-03 17:30:35 +05:30
parent 34048148ed
commit 96297a0104
12 changed files with 533 additions and 403 deletions

12
.env
View File

@ -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

View File

@ -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

0
assets/nhance_client_logo.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 145 KiB

After

Width:  |  Height:  |  Size: 145 KiB

View File

@ -0,0 +1,11 @@
<svg width="150" height="31" viewBox="0 0 150 31" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M61.8514 16.2325C62.2354 16.141 62.6195 16.3605 62.7475 16.7263C63.0767 17.6408 63.4242 18.5186 63.7717 19.4148C64.0095 19.9818 63.6437 20.1098 63.2779 20.311C61.7599 21.1706 61.2661 22.3228 61.7416 23.8408C62.0342 24.8101 62.7109 25.3405 63.6437 25.5051C66.7712 26.1087 69.3865 24.0603 69.4962 20.8779C69.5511 18.4272 69.4962 15.9764 69.4597 13.5257C69.4414 12.6478 69.039 11.9894 68.1611 11.7333C66.0579 11.1481 64.0278 11.1115 62.272 12.7758C61.8148 13.2148 61.0832 13.5623 60.4614 13.6171C59.2543 13.7269 58.0472 13.672 56.7487 13.6537C56.3097 13.6537 55.9988 13.2331 56.1268 12.8124C57.2608 9.28258 59.6018 7.12446 63.3145 6.72209C65.8567 6.42947 68.4172 6.52091 70.8862 7.32564C73.337 8.11207 75.0013 9.72153 75.1293 12.3552C75.2756 15.6289 75.3122 18.9027 75.0927 22.1765C74.7635 26.9134 71.7641 29.1447 67.5759 29.986C65.1251 30.4615 62.6561 30.5895 60.2419 29.6751C57.7546 28.7423 56.1451 26.5842 56.0171 23.9505C55.7428 19.6343 57.6083 17.1469 61.8514 16.2325Z" fill="#00989E"/>
<path d="M62.7292 13.7817C64.7045 14.4219 66.4602 14.9888 68.216 15.6107C68.5086 15.7204 68.6366 16.0313 68.5086 16.3056C67.8136 17.8419 66.4237 20.6036 65.8201 21.6644C65.7104 21.8473 65.436 21.829 65.3629 21.6278C64.4301 19.2136 63.4608 16.7629 62.4183 14.1109C62.3452 13.9098 62.5281 13.7269 62.7292 13.7817Z" fill="#E26727"/>
<path d="M95.4669 30.242C93.2905 30.242 91.5165 28.468 91.5165 26.2916V16.141C91.5165 14.3853 90.8398 13.3245 89.4864 12.9404C87.1819 12.3186 84.9323 14.1475 84.9323 16.5251V29.8579C84.9323 30.0408 84.7677 30.2054 84.5848 30.2054H79.0981C78.3299 30.2054 77.7081 29.5836 77.7081 28.8155V17.3115C77.5984 10.2519 81.0916 6.72209 88.2061 6.72209C95.3206 6.72209 98.8687 10.2519 98.8687 17.3115V29.0715C98.8687 29.6933 98.3749 30.2237 97.7165 30.2237H95.4669V30.242Z" fill="#00989E"/>
<path d="M122.864 22.085C123.267 22.085 123.541 22.4691 123.413 22.8349C121.73 27.7913 118.109 30.2969 112.531 30.3335C109.038 30.3335 106.349 29.2727 104.429 27.1329C102.508 24.8284 101.521 21.9387 101.484 18.4455C101.374 14.9522 102.325 12.1174 104.337 9.92271C106.203 7.728 108.891 6.63065 112.439 6.63065C115.987 6.52091 118.767 7.59998 120.797 9.83126C121.986 11.0566 122.809 12.5198 123.248 14.2207L123.267 14.2755C123.358 14.623 123.084 14.9888 122.7 14.9888H116.646C116.408 14.9888 116.207 14.8425 116.115 14.6413C115.548 13.3062 114.378 12.6295 112.622 12.6295C110.153 12.6295 108.891 14.5682 108.818 18.4638C108.818 22.2679 110.135 24.2614 112.75 24.4626H112.842C114.122 24.4078 115.073 24.042 115.75 23.3836C116.426 22.5423 117.359 22.1033 118.53 22.1033L122.864 22.085Z" fill="#00989E"/>
<path d="M42.6294 6.68552C44.4217 6.44776 46.1775 6.59407 47.915 7.12446C51.9386 8.33155 54.0236 11.6053 54.1333 16.9823V28.9252C54.1333 29.6385 53.5481 30.2237 52.8348 30.2237H48.0796C47.3114 30.2237 46.6896 29.6019 46.6896 28.8337V18.0248C46.6896 14.7511 45.2447 13.105 42.3733 13.105C39.5019 13.105 38.0754 14.7511 38.1302 18.0248V28.6509C38.1302 29.5105 37.4353 30.1872 36.594 30.1872H32.1497C31.3632 30.1872 30.7048 29.547 30.7048 28.7423V1.25362C30.7048 0.631787 31.2352 0.1014 31.857 0.1014H34.509C36.5208 0.1014 38.1485 1.72914 38.1485 3.74095V8.34983C38.1485 8.51444 38.3314 8.60588 38.4595 8.49615C39.5568 7.59998 40.9651 6.99643 42.6294 6.68552Z" fill="#00989E"/>
<path d="M141.007 13.1599C141.629 12.6844 140.221 11.9162 139.891 11.7333C137.934 10.7091 135.502 11.2761 133.746 12.4649C129.869 15.1168 130.107 22.3594 134.606 24.2432C137.971 25.6697 142.415 24.2066 143.641 20.5853C143.75 20.2927 143.842 20.0001 143.933 19.6891C143.981 19.5392 144.071 19.413 144.191 19.327C144.356 19.2081 144.535 19.199 144.61 19.1953C145.526 19.1588 145.985 19.1405 147 19.1679C147.339 19.177 149.084 19.2081 149.605 19.4057C149.665 19.4276 149.811 19.4861 149.905 19.627C149.905 19.627 150.027 19.7714 149.994 19.9854C149.799 21.2565 149.217 23.8335 147.209 26.2422C145.709 28.0418 144.067 28.9618 143.5 29.2599C142.119 29.9841 140.897 30.2786 140.255 30.4048C138.812 30.6864 137.695 30.6243 136.855 30.5731C135.829 30.509 134.225 30.3957 132.311 29.6184C130.101 28.7204 128.731 27.4456 128.387 27.1164C127.83 26.5823 126.613 25.4027 125.79 23.4403C125.223 22.0869 124.949 20.5871 124.949 18.9045C124.949 17.2219 125.187 15.6125 125.662 14.2774C126.12 12.9423 126.833 11.7717 127.766 10.8024C128.698 9.83309 129.686 9.02836 130.729 8.40653C132.172 7.54511 133.443 7.18847 133.966 7.05313C134.884 6.81537 135.615 6.74038 136.131 6.68917C137.501 6.55383 138.567 6.62516 139.003 6.66174C139.807 6.72941 140.916 6.83 142.287 7.30735C143.765 7.82128 144.835 8.49981 145.36 8.9168C146.256 9.63008 147.097 10.4348 147.829 11.3127C148.012 11.5504 148.213 11.7699 148.396 12.026C149.219 13.0867 148.89 14.623 147.701 15.2632L136.673 21.1523C136.362 21.3169 134.46 21.9936 133.435 20.6585C132.32 19.2319 132.85 17.8785 133.874 17.2933C133.783 17.275 141.007 13.1599 141.007 13.1599Z" fill="#00989E"/>
<path d="M24.1207 0.00995388C21.8528 -0.00833533 20.3897 -0.00833516 20.4446 2.8082V14.3304C20.4446 14.4767 20.4994 14.623 20.6458 14.7511L26.3703 19.7074C26.8641 20.1464 27.8334 19.872 27.8334 19.2868V2.71676C27.8151 -0.392409 26.4252 0.0282431 24.1207 0.00995388Z" fill="#E26727"/>
<path d="M15.0493 12.0077L4.69757 0.759812C4.16718 0.174557 3.52706 0.119689 2.79549 0.119689C1.29577 0.137978 -0.167363 -0.428988 0.0155289 3.02767L0.143553 5.3504C0.161843 5.6979 0.308156 6.06368 0.564205 6.33802L16.2563 22.9812L22.4381 29.7482C22.6393 30.0043 22.9319 30.1506 23.2611 30.1506C24.0293 30.1689 25.0535 30.1506 25.6204 30.1506C27.1201 30.1323 27.8883 30.0957 27.8883 28.3399L27.742 25.9806C27.7237 25.6331 27.5774 25.2674 27.3213 25.0113L15.0493 12.0077Z" fill="#00989E"/>
<path d="M0.45447 28.6509C0.45447 29.8397 1.13117 30.4249 4.24034 30.2969C7.27635 30.1689 7.91647 29.8579 7.91647 28.7606V17.3481C7.91647 17.0738 7.78844 16.8177 7.56897 16.6348L3.06983 12.7758C2.17366 12.0077 0.472759 12.4832 0.472759 13.4891V28.6509H0.45447Z" fill="#E26727"/>
</svg>

After

Width:  |  Height:  |  Size: 5.9 KiB

BIN
assets/nhance_logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -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,
// ),
),
],
),

View File

@ -85,6 +85,8 @@ class _addOnsDetailsState extends State<addOnsDetails> {
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<addOnsDetails> {
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<addOnsDetails> {
// 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<addOnsDetails> {
: 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(

View File

@ -510,8 +510,11 @@ class _empReviewDetailsState extends State<empReviewDetails> {
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;
}
}

View File

@ -115,6 +115,8 @@ class _planclaimsformState extends State<planclaimsform> {
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<planclaimsform> {
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<planclaimsform> {
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<planclaimsform> {
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<String, dynamic> 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<planclaimsform> {
: (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<planclaimsform> {
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<planclaimsform> {
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<planclaimsform> {
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,

View File

@ -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<PlatformFile> _files = [];
final List<UploadedFile> _files = [];
List<PlatformFile> get files => List.unmodifiable(_files);
// Expose as unmodifiable but containing UploadedFile objects
List<UploadedFile> get files => List.unmodifiable(_files);
// Allowed extensions
static const allowedExtensions = ['pdf', 'png', 'jpg', 'jpeg','heic'];
static const allowedExtensions = ['pdf', 'png', 'jpg', 'jpeg', 'heic'];
Future<String?> 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();
}
}

View File

@ -7,6 +7,8 @@ class MultiFileUploadWidget extends StatefulWidget {
@override
State<MultiFileUploadWidget> createState() => _MultiFileUploadWidgetState();
static bool hasFiles = false; // Static variable to check from parent
}
class _MultiFileUploadWidgetState extends State<MultiFileUploadWidget> {
@ -39,13 +41,16 @@ class _MultiFileUploadWidgetState extends State<MultiFileUploadWidget> {
} 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<MultiFileUploadWidget> {
),
],
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<MultiFileUploadWidget> {
],
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,
),
),
),
],
);
}),
],

View File

@ -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 {
},
);
}
}
}