bug fix
This commit is contained in:
parent
ad396fefb0
commit
72b253918a
@ -220,7 +220,7 @@ class _NhanceSideBarState extends State<NhanceSideBar> {
|
||||
);
|
||||
}).toList(),
|
||||
|
||||
if(postModules.isNotEmpty)
|
||||
if(postModules.isNotEmpty && postModules.contains(5))
|
||||
_SideItem(
|
||||
// icon: Icons.dashboard,
|
||||
icon: SvgPicture.string(
|
||||
|
||||
@ -69,6 +69,7 @@ class _MyEmailVerifyState extends State<MyEmailVerify> {
|
||||
late String _verificationId;
|
||||
dynamic empMobileNo;
|
||||
dynamic empEmailid;
|
||||
final tokenService = TokenStorageService();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@ -225,12 +226,53 @@ class _MyEmailVerifyState extends State<MyEmailVerify> {
|
||||
// // Show a Snackbar if the OTP is invalid
|
||||
// print('Invalid OTP. Please try again');
|
||||
// }
|
||||
} else if (response.statusCode == 401) {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
await tokenService.clearAll(); // 🔐 clears flutter_secure_storage
|
||||
|
||||
ToastHelper.showErrorToast(context, 'Session Out');
|
||||
if (!context.mounted) return;
|
||||
Navigator.pushNamedAndRemoveUntil(
|
||||
context,
|
||||
'hrLogin',
|
||||
(route) => false,
|
||||
);
|
||||
|
||||
} else if (response.statusCode == 403) {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
await tokenService.clearAll(); // 🔐 clears flutter_secure_storage
|
||||
|
||||
ToastHelper.showErrorToast(context, 'Session Out');
|
||||
if (!context.mounted) return;
|
||||
Navigator.pushNamedAndRemoveUntil(
|
||||
context,
|
||||
'hrLogin',
|
||||
(route) => false,
|
||||
);
|
||||
|
||||
} else if (response.statusCode == 451) {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
final body = jsonDecode(response.body);
|
||||
final message = body['message'];
|
||||
ToastHelper.showWarningToast(context, message);
|
||||
} else if (response.statusCode == 429) {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
final body = jsonDecode(response.body);
|
||||
final message = body['message'];
|
||||
ToastHelper.showWarningToast(context, message);
|
||||
} else {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
ToastHelper.showWarningToast(context, 'Something went wrong');
|
||||
throw Exception('Failed to verify OTP');
|
||||
throw Exception('Failed to load data');
|
||||
}
|
||||
} catch (e) {
|
||||
setState(() {
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import 'package:firebase_auth/firebase_auth.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
@ -12,6 +13,7 @@ import 'package:nhancepolicy/responsive.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:flutter_animated_button/flutter_animated_button.dart';
|
||||
import 'package:nhancepolicy/service/token_storage_service.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
import 'config/environment.dart';
|
||||
import 'email_verify.dart';
|
||||
@ -517,28 +519,34 @@ class _MyPhoneState extends State<MyHrLogin> {
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
Container(
|
||||
width: double
|
||||
.infinity, // Make the footer full width
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
alignment: Alignment.bottomCenter,
|
||||
padding:
|
||||
EdgeInsets.symmetric(vertical: 8),
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
child: RichText(
|
||||
textAlign: TextAlign.center,
|
||||
text: TextSpan(
|
||||
text:
|
||||
'By continuing, you agree with our ',
|
||||
text: 'By continuing, you agree with our ',
|
||||
style: GoogleFonts.poppins(
|
||||
color: Colors.black,
|
||||
fontSize: 9,
|
||||
),
|
||||
children: <TextSpan>[
|
||||
children: [
|
||||
TextSpan(
|
||||
text: 'privacy policy ',
|
||||
style: GoogleFonts.poppins(
|
||||
color: Color(0xFFE26828),
|
||||
color: const Color(0xFFE26828),
|
||||
fontSize: 9,
|
||||
// decoration: TextDecoration.underline,
|
||||
),
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () async {
|
||||
final url = Uri.parse(
|
||||
'https://nhanceindia.in/privacy-policy/');
|
||||
if (await canLaunchUrl(url)) {
|
||||
await launchUrl(url,
|
||||
mode: LaunchMode.externalApplication);
|
||||
}
|
||||
},
|
||||
),
|
||||
TextSpan(
|
||||
text: 'and ',
|
||||
@ -550,15 +558,67 @@ class _MyPhoneState extends State<MyHrLogin> {
|
||||
TextSpan(
|
||||
text: 'terms of use',
|
||||
style: GoogleFonts.poppins(
|
||||
color: Color(0xFFE26828),
|
||||
color: const Color(0xFFE26828),
|
||||
fontSize: 9,
|
||||
// decoration: TextDecoration.underline,
|
||||
),
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () async {
|
||||
final url = Uri.parse(
|
||||
'https://nhanceindia.in/privacy-policy/');
|
||||
if (await canLaunchUrl(url)) {
|
||||
await launchUrl(url,
|
||||
mode: LaunchMode.externalApplication);
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
// Container(
|
||||
// width: double
|
||||
// .infinity, // Make the footer full width
|
||||
// child: Container(
|
||||
// alignment: Alignment.bottomCenter,
|
||||
// padding:
|
||||
// EdgeInsets.symmetric(vertical: 8),
|
||||
// child: RichText(
|
||||
// textAlign: TextAlign.center,
|
||||
// text: TextSpan(
|
||||
// text:
|
||||
// 'By continuing, you agree with our ',
|
||||
// style: GoogleFonts.poppins(
|
||||
// color: Colors.black,
|
||||
// fontSize: 9,
|
||||
// ),
|
||||
// children: <TextSpan>[
|
||||
// TextSpan(
|
||||
// text: 'privacy policy ',
|
||||
// style: GoogleFonts.poppins(
|
||||
// color: Color(0xFFE26828),
|
||||
// fontSize: 9,
|
||||
// ),
|
||||
// ),
|
||||
// TextSpan(
|
||||
// text: 'and ',
|
||||
// style: GoogleFonts.poppins(
|
||||
// color: Colors.black,
|
||||
// fontSize: 9,
|
||||
// ),
|
||||
// ),
|
||||
// TextSpan(
|
||||
// text: 'terms of use',
|
||||
// style: GoogleFonts.poppins(
|
||||
// color: Color(0xFFE26828),
|
||||
// fontSize: 9,
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
183
lib/main.dart
183
lib/main.dart
@ -62,25 +62,158 @@ Future<void> startApp() async {
|
||||
projectId: 'nhance-ee8d1'));
|
||||
// await dotenv.load(fileName: Environment.fileName);
|
||||
|
||||
runApp(MaterialApp(
|
||||
// runApp(MaterialApp(
|
||||
// title: 'Nhance HR',
|
||||
// onGenerateTitle: (context) => "Nhance HR",
|
||||
// initialRoute: 'hrLogin',
|
||||
// debugShowCheckedModeBanner: false,
|
||||
// theme: ThemeData(
|
||||
// primaryColor: Color(0xFF00999E), // Primary theme color
|
||||
// scaffoldBackgroundColor: Colors.white,
|
||||
// colorScheme: ColorScheme.fromSeed(
|
||||
// seedColor: Color(0xFF00999E),
|
||||
// ),
|
||||
// textTheme: GoogleFonts.poppinsTextTheme(),
|
||||
// elevatedButtonTheme: ElevatedButtonThemeData(
|
||||
// style: ElevatedButton.styleFrom(
|
||||
// backgroundColor: Color(0xFF00999E), // Button background
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// routes: {
|
||||
// 'phone': (context) => MyPhone(),
|
||||
// 'mailVerify': (context) => MyEmailVerify(
|
||||
// type: '',
|
||||
// value: '',
|
||||
//
|
||||
// ),
|
||||
// 'verify': (context) => MyVerify(
|
||||
// verificationId: '',
|
||||
// mobileNumber: '',
|
||||
// resendToken: null,
|
||||
// onResendCode: (String, int) {},
|
||||
// ),
|
||||
// 'home': (context) => MyApp(),
|
||||
// 'hrLogin': (context) => MyHrLogin(),
|
||||
// // 'hrVerify': (context) => MyHrVerify(
|
||||
// // verificationId: '',
|
||||
// // mobileNumber: '',
|
||||
// // resendToken: null,
|
||||
// // onResendCode: (String, int) {},
|
||||
// // ),
|
||||
// 'hrHome': (context) => MyHrHome(),
|
||||
// 'preFileUpload': (context) => const preFileUpload(
|
||||
// ClientId: '',
|
||||
// policyTypeId: '',
|
||||
// ClientPoliyId: '',
|
||||
// clientBranchId: '',
|
||||
// Token: '',
|
||||
// TokenType: '',
|
||||
// cardType: '',
|
||||
// cardPolicyNo: '',
|
||||
// cardInsurer_name: '',
|
||||
// cardPolicy_name: '',
|
||||
// cardPolicy_ExpDate: '',
|
||||
// total_premium: '',
|
||||
// ),
|
||||
// 'postFileUpload': (context) => const postFileUpload(
|
||||
// ClientId: '',
|
||||
// policyTypeId: '',
|
||||
// ClientPoliyId: '',
|
||||
// clientBranchId: '',
|
||||
// Token: '',
|
||||
// TokenType: '',
|
||||
// cardType: '',
|
||||
// cardPolicyNo: '',
|
||||
// cardInsurer_name: '',
|
||||
// cardPolicy_name: '',
|
||||
// cardPolicy_ExpDate: '',
|
||||
// total_premium: '',
|
||||
// ),
|
||||
// 'excelErrorScreen': (context) => const excelErrorScreen(
|
||||
// ClientId: '',
|
||||
// policy_no: '',
|
||||
// action: '',
|
||||
// created_at: '',
|
||||
// clientBranchId: '',
|
||||
// Token: '',
|
||||
// TokenType: '',
|
||||
// id: ''
|
||||
// ),
|
||||
// 'empDetails': (context) => empDetails(),
|
||||
// 'addOnsDetails': (context) => addOnsDetails(),
|
||||
// 'empReviewDetails': (context) => empReviewDetails(),
|
||||
// 'hrDashboard': (context) => hrDashboard(),
|
||||
// 'hrPolicyDetails': (context) => hrPolicyDetails(
|
||||
// ClientId: '',
|
||||
// policyTypeId: '',
|
||||
// ClientPoliyId: '',
|
||||
// clientBranchId: '',
|
||||
// Token: '',
|
||||
// TokenType: '',
|
||||
// cardType: '',
|
||||
// cardPolicyNo: '',
|
||||
// cardInsurer_name: '',
|
||||
// cardPolicy_name: '',
|
||||
// cardPolicy_ExpDate: '',
|
||||
// total_premium: '',
|
||||
// is_ecard_bulk_download_for_employee: 0,
|
||||
// ),
|
||||
// 'oldPolicy': (context) => oldPolicy(),
|
||||
// 'branchSelection': (context) => BranchSelectionPage(),
|
||||
// 'policies': (context) => policies(),
|
||||
// 'CdPoliciesList': (context) => CdPoliciesList(),
|
||||
// 'ClaimsPolicies': (context) => ClaimsPolicies(
|
||||
// empCode:'',
|
||||
// ),
|
||||
// 'cdTransactionDetails': (context) => cdTransactionDetails(
|
||||
// insurerName: '',
|
||||
// cdMasterAccountNo: '',
|
||||
// insurerId: '',
|
||||
// cd_ac_pk: '',
|
||||
// empClientId: '',
|
||||
// ),
|
||||
// },
|
||||
// ));
|
||||
|
||||
final tokenService = TokenStorageService();
|
||||
final token = await tokenService.getCurrentToken();
|
||||
|
||||
runApp(MyApp(initialToken: token));
|
||||
}
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
final String? initialToken;
|
||||
|
||||
const MyApp({super.key, this.initialToken});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
title: 'Nhance HR',
|
||||
onGenerateTitle: (context) => "Nhance HR",
|
||||
initialRoute: 'hrLogin',
|
||||
debugShowCheckedModeBanner: false,
|
||||
initialRoute: (initialToken == null || initialToken!.isEmpty)
|
||||
? 'hrLogin'
|
||||
: 'hrHome',
|
||||
theme: ThemeData(
|
||||
primaryColor: Color(0xFF00999E), // Primary theme color
|
||||
primaryColor: const Color(0xFF00999E),
|
||||
scaffoldBackgroundColor: Colors.white,
|
||||
colorScheme: ColorScheme.fromSeed(
|
||||
seedColor: Color(0xFF00999E),
|
||||
seedColor: const Color(0xFF00999E),
|
||||
),
|
||||
textTheme: GoogleFonts.poppinsTextTheme(),
|
||||
elevatedButtonTheme: ElevatedButtonThemeData(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Color(0xFF00999E), // Button background
|
||||
backgroundColor: const Color(0xFF00999E),
|
||||
),
|
||||
),
|
||||
),
|
||||
routes: {
|
||||
routes: appRoutes,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
final Map<String, WidgetBuilder> appRoutes = {
|
||||
'phone': (context) => MyPhone(),
|
||||
'mailVerify': (context) => MyEmailVerify(
|
||||
type: '',
|
||||
@ -173,6 +306,38 @@ Future<void> startApp() async {
|
||||
cd_ac_pk: '',
|
||||
empClientId: '',
|
||||
),
|
||||
},
|
||||
));
|
||||
};
|
||||
|
||||
/// 🔐 Global Auth Wrapper (Protects All Pages)
|
||||
class AuthWrapper extends StatefulWidget {
|
||||
final Widget child;
|
||||
|
||||
const AuthWrapper({super.key, required this.child});
|
||||
|
||||
@override
|
||||
State<AuthWrapper> createState() => _AuthWrapperState();
|
||||
}
|
||||
|
||||
class _AuthWrapperState extends State<AuthWrapper> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_checkLogin();
|
||||
}
|
||||
|
||||
void _checkLogin() {
|
||||
final token = TokenStorageService().getCurrentToken();
|
||||
|
||||
if (token == null || token.isEmpty) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
Navigator.pushNamedAndRemoveUntil(
|
||||
context, 'hrLogin', (route) => false);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return widget.child;
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,8 +23,11 @@ class RaiseClaimDialog extends StatefulWidget {
|
||||
final BuildContext parentContext;
|
||||
final VoidCallback onSuccess;
|
||||
|
||||
const RaiseClaimDialog({Key? key, required this.parentContext, required this.onSuccess,})
|
||||
: super(key: key);
|
||||
const RaiseClaimDialog({
|
||||
Key? key,
|
||||
required this.parentContext,
|
||||
required this.onSuccess,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<RaiseClaimDialog> createState() => _RaiseClaimDialogState();
|
||||
@ -32,6 +35,7 @@ class RaiseClaimDialog extends StatefulWidget {
|
||||
|
||||
class _RaiseClaimDialogState extends State<RaiseClaimDialog> {
|
||||
// const RaiseClaimDialog({super.key});
|
||||
bool hasSubmitted = false;
|
||||
late ApiService apiService;
|
||||
bool isLoading = false;
|
||||
dynamic empPrimaryId;
|
||||
@ -86,6 +90,11 @@ class _RaiseClaimDialogState extends State<RaiseClaimDialog> {
|
||||
Map<String, dynamic>? selectedMemberObject;
|
||||
TextEditingController searchController = TextEditingController();
|
||||
|
||||
Map<String, dynamic> claimTypeMap = {};
|
||||
List<Map<String, dynamic>> claimTypeList = [];
|
||||
int? claimTypeId;
|
||||
bool isClaimTypeValid = true;
|
||||
|
||||
// Declare subjectController and bodyController as instance variables
|
||||
late TextEditingController subjectController;
|
||||
late TextEditingController messageController;
|
||||
@ -145,6 +154,7 @@ class _RaiseClaimDialogState extends State<RaiseClaimDialog> {
|
||||
bool isAdmitDateValid = true;
|
||||
bool isDischargeDateValid = true;
|
||||
bool isAccidentService = false;
|
||||
bool isDeathDateValid = true;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@ -188,6 +198,7 @@ class _RaiseClaimDialogState extends State<RaiseClaimDialog> {
|
||||
admitDateController.dispose();
|
||||
dischargeDateController.dispose();
|
||||
serviceId = null;
|
||||
claimTypeId = null;
|
||||
departmentList.clear();
|
||||
super.dispose();
|
||||
fileService.clearAll();
|
||||
@ -210,7 +221,7 @@ class _RaiseClaimDialogState extends State<RaiseClaimDialog> {
|
||||
});
|
||||
try {
|
||||
print('10');
|
||||
final response = await apiService.getClaimPoliciesToApi(_postPreToken!);
|
||||
final response = await apiService.getClaimPoliciesToApi(_postPreToken!,empClientId);
|
||||
if (response['status'] == 'success') {
|
||||
setState(() {
|
||||
isLoading = false;
|
||||
@ -223,6 +234,9 @@ class _RaiseClaimDialogState extends State<RaiseClaimDialog> {
|
||||
'name': item['type_name'].toString(),
|
||||
})
|
||||
.toList();
|
||||
|
||||
claimTypeMap = Map<String, dynamic>.from(getClaimPoliciesApi['claim_type']);
|
||||
print('claimTypeMap $claimTypeMap');
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
@ -319,11 +333,40 @@ class _RaiseClaimDialogState extends State<RaiseClaimDialog> {
|
||||
};
|
||||
}).toList();
|
||||
|
||||
|
||||
isPolicyValid = true;
|
||||
});
|
||||
}
|
||||
|
||||
void loadClaimTypes() {
|
||||
print('serviceId $serviceId');
|
||||
if (serviceId == null) return;
|
||||
|
||||
String key = serviceId.toString();
|
||||
|
||||
if (claimTypeMap.containsKey(key)) {
|
||||
Map<String, dynamic> types = Map<String, dynamic>.from(claimTypeMap[key]);
|
||||
|
||||
claimTypeList = types.entries.map((entry) {
|
||||
return {
|
||||
'id': int.parse(entry.key),
|
||||
'name': entry.value,
|
||||
};
|
||||
}).toList();
|
||||
|
||||
print('claimTypeList $claimTypeList');
|
||||
|
||||
// // ✅ AUTO SELECT FIRST CLAIM TYPE
|
||||
// if (claimTypeList.isNotEmpty) {
|
||||
// claimTypeId = claimTypeList.first['id'];
|
||||
// }
|
||||
|
||||
} else {
|
||||
claimTypeList = [];
|
||||
claimTypeId = null;
|
||||
setState(() {});
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> getCDPoliciesDetails() async {
|
||||
print('9');
|
||||
setState(() {
|
||||
@ -333,7 +376,10 @@ class _RaiseClaimDialogState extends State<RaiseClaimDialog> {
|
||||
print('10');
|
||||
|
||||
final response = await apiService.getEmployeeAndDependenceToApi(
|
||||
empClientId, selectedClientPolicyId, empClientBranchId, _postPreToken!);
|
||||
empClientId,
|
||||
selectedClientPolicyId,
|
||||
empClientBranchId,
|
||||
_postPreToken!);
|
||||
|
||||
if (response['status'] == 'success') {
|
||||
final List<Map<String, dynamic>> members =
|
||||
@ -353,9 +399,7 @@ class _RaiseClaimDialogState extends State<RaiseClaimDialog> {
|
||||
'relationship': m['relationship'],
|
||||
'gender': m['gender'],
|
||||
'dob': m['dob'],
|
||||
'policy_name': serviceId == 1
|
||||
? null
|
||||
: m['policy_name'],
|
||||
'policy_name': serviceId == 1 ? null : m['policy_name'],
|
||||
};
|
||||
}).toList();
|
||||
});
|
||||
@ -373,60 +417,144 @@ class _RaiseClaimDialogState extends State<RaiseClaimDialog> {
|
||||
}
|
||||
|
||||
Future<void> sendFormDataToApi() async {
|
||||
|
||||
setState(() {
|
||||
hasSubmitted = serviceId != null ? true : false;
|
||||
isServiceValid = serviceId != null;
|
||||
isPolicyValid = selectedClientPolicyId != null;
|
||||
isMemberValid = selectedMemberId != null;
|
||||
MultiFileUploadWidget.showValidation = serviceId != null && FileUploadService().files.isEmpty;
|
||||
// MultiFileUploadWidget.showValidation = FileUploadService().files.isEmpty;
|
||||
// isClaimTypeValid = claimTypeId != 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;
|
||||
final isGmc = serviceId == 1 || serviceId == 72;
|
||||
|
||||
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;
|
||||
// isHospitalPhoneNoValid = !isGmc || (hospitalPhoneNoController.text.trim().length == 10);
|
||||
String phone = hospitalPhoneNoController.text.trim();
|
||||
// isHospitalPhoneNoValid = !isGmc || (RegExp(r'^\d{10}$').hasMatch(phone));
|
||||
isHospitalPhoneNoValid = !isGmc || phone.isNotEmpty;
|
||||
|
||||
|
||||
isAdmitDateValid = !isGmc || admitDate != null;
|
||||
isDischargeDateValid = !isGmc || dischargeDate != null;
|
||||
isClaimTypeValid = !isGmc || claimTypeId != null;
|
||||
|
||||
isClaimAmountValid = !isGmc || claimAmountController.text.trim().isNotEmpty;
|
||||
isClaimAmountValid =
|
||||
!isGmc || claimAmountController.text.trim().isNotEmpty;
|
||||
|
||||
// ☠ Accident / Death
|
||||
final isAccident = [2, 3, 4].contains(serviceId);
|
||||
|
||||
isAccidentService = isAccident ? true : false;
|
||||
|
||||
isAccidentDateValid = !isAccident || accidentDate != null;
|
||||
isIntimationDateValid = !isAccident || intimationDate != null;
|
||||
// final isAccident = [2, 3, 4].contains(serviceId);
|
||||
//
|
||||
// isAccidentService = isAccident ? true : false;
|
||||
//
|
||||
// isAccidentDateValid = !isAccident || accidentDate != null;
|
||||
// isIntimationDateValid = !isAccident || intimationDate != null;
|
||||
// 🎯 GPA / GTLI / EDLI validation
|
||||
// 🎯 GPA / GTLI / EDLI dynamic validation
|
||||
// if (serviceId == 2) {
|
||||
// print('serviceId == 2');
|
||||
// isAccidentDateValid = accidentDate != null;
|
||||
// isDeathDateValid = true;
|
||||
// }
|
||||
// else if (serviceId == 3 || serviceId == 4) {
|
||||
// print('serviceId == 3 || serviceId == 4');
|
||||
// isDeathDateValid = deathDate != null;
|
||||
// isAccidentDateValid = true;
|
||||
// }
|
||||
// else {
|
||||
// print('ELSE');
|
||||
// isAccidentDateValid = true;
|
||||
// isDeathDateValid = true;
|
||||
// }
|
||||
if (serviceId == 2) {
|
||||
// GPA
|
||||
isAccidentDateValid = accidentDate != null;
|
||||
isDeathDateValid = true;
|
||||
isIntimationDateValid = true;
|
||||
}
|
||||
else if (serviceId == 3) {
|
||||
// GTLI
|
||||
isDeathDateValid = deathDate != null;
|
||||
isAccidentDateValid = true;
|
||||
isIntimationDateValid = true;
|
||||
}
|
||||
else if (serviceId == 4) {
|
||||
// EDLI
|
||||
isDeathDateValid = deathDate != null;
|
||||
isAccidentDateValid = true;
|
||||
isIntimationDateValid = true;
|
||||
}
|
||||
else {
|
||||
isAccidentDateValid = true;
|
||||
isDeathDateValid = true;
|
||||
isIntimationDateValid = true;
|
||||
}
|
||||
});
|
||||
|
||||
// if (!isDeathDateValid) {
|
||||
// ToastHelper.showErrorToast(
|
||||
// context, 'Date of Death is required');
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// if (!isAccidentDateValid) {
|
||||
// ToastHelper.showErrorToast(
|
||||
// context, 'Accident Date is required');
|
||||
// return;
|
||||
// }
|
||||
|
||||
if (isServiceValid &&
|
||||
isPolicyValid &&
|
||||
isMemberValid &&
|
||||
// isSubjectValid &&
|
||||
isHospitalNameValid &&
|
||||
isHospitalAddressValid &&
|
||||
isHospitalStateValid &&
|
||||
isHospitalCityValid &&
|
||||
isHospitalPincodeValid &&
|
||||
isHospitalPhoneNoValid &&
|
||||
isAdmitDateValid &&
|
||||
isHospitalPhoneNoValid &&
|
||||
isDischargeDateValid &&
|
||||
isClaimAmountValid &&
|
||||
isAccidentDateValid &&
|
||||
isDeathDateValid &&
|
||||
isIntimationDateValid) {
|
||||
if (FileUploadService().files.isEmpty) {
|
||||
setState(() {
|
||||
MultiFileUploadWidget.hasFiles = false;
|
||||
});
|
||||
ToastHelper.showErrorToast(context, 'Please upload at least one document');
|
||||
|
||||
// ✅ Phone validation AFTER all required fields pass
|
||||
// ✅ Exact 10 digit validation AFTER all required fields filled
|
||||
if ((serviceId == 1 || serviceId == 72) &&
|
||||
hospitalPhoneNoController.text.trim().isNotEmpty &&
|
||||
!RegExp(r'^\d{10}$').hasMatch(hospitalPhoneNoController.text.trim())) {
|
||||
ToastHelper.showErrorToast(
|
||||
context,
|
||||
'Hospital phone number must be exactly 10 digits',
|
||||
);
|
||||
return;
|
||||
}
|
||||
// Proceed to submit
|
||||
|
||||
if (FileUploadService().files.isEmpty) {
|
||||
ToastHelper.showErrorToast(
|
||||
context,
|
||||
'Please upload at least one document',
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
} else {
|
||||
ToastHelper.showErrorToast(context, 'Please Fill Required Fields');
|
||||
ToastHelper.showErrorToast(
|
||||
context,
|
||||
'Please Fill Required Fields',
|
||||
);
|
||||
return;
|
||||
}
|
||||
setState(() => isSubmitting = true); // 🔥 start loader
|
||||
@ -453,16 +581,15 @@ class _RaiseClaimDialogState extends State<RaiseClaimDialog> {
|
||||
'relationship': selectedMemberObject?['relationship'],
|
||||
'gender': selectedMemberObject?['gender'],
|
||||
'age': selectedMemberObject?['dob'],
|
||||
'policy_name': serviceId == 1
|
||||
? null
|
||||
: selectedMemberObject?['policy_name'],
|
||||
|
||||
'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!);
|
||||
String formattedDischargeDate =
|
||||
DateFormat('yyyy-MM-dd').format(dischargeDate!);
|
||||
fields['claim_type'] = claimTypeId;
|
||||
fields['hospital_name'] = hospitalNameController.text;
|
||||
fields['hospital_address'] = hospitalAddressController.text;
|
||||
fields['hospital_city'] = hospitalCityController.text;
|
||||
@ -476,39 +603,54 @@ class _RaiseClaimDialogState extends State<RaiseClaimDialog> {
|
||||
fields['member_name'] = selectedMemberObject?['name'];
|
||||
fields['insured_emp_id'] = selectedMemberObject?['insured_emp_id'];
|
||||
} else {
|
||||
String formattedAccidentDate =
|
||||
if (accidentDate != null) {
|
||||
fields['date_of_accident'] =
|
||||
DateFormat('yyyy-MM-dd').format(accidentDate!);
|
||||
String formattedDeathDate = DateFormat('yyyy-MM-dd').format(deathDate!);
|
||||
String formattedBirthDate = DateFormat('yyyy-MM-dd').format(birthDate!);
|
||||
String formattedIntimationDate =
|
||||
}
|
||||
|
||||
if (deathDate != null) {
|
||||
fields['date_of_death'] =
|
||||
DateFormat('yyyy-MM-dd').format(deathDate!);
|
||||
}
|
||||
|
||||
if (birthDate != null) {
|
||||
fields['dob'] =
|
||||
DateFormat('yyyy-MM-dd').format(birthDate!);
|
||||
}
|
||||
|
||||
if (intimationDate != null) {
|
||||
fields['date_of_intimat'] =
|
||||
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'));
|
||||
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.headers['APP-SIGNATURE'] =
|
||||
'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y';
|
||||
final stringFields =
|
||||
fields.map((key, value) => MapEntry(key, value?.toString() ?? ''));
|
||||
print("📁 stringFields: ${stringFields}");
|
||||
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()}");
|
||||
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}'");
|
||||
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');
|
||||
ToastHelper.showErrorToast(
|
||||
context, 'Please enter name for all uploaded documents');
|
||||
setState(() => isLoading = false);
|
||||
return;
|
||||
}
|
||||
@ -581,7 +723,6 @@ class _RaiseClaimDialogState extends State<RaiseClaimDialog> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ✅ Combine all names into a JSON array string
|
||||
final claimDocNames = uploadedFiles.map((uf) => uf.label.trim()).toList();
|
||||
final encodedNames = jsonEncode(claimDocNames);
|
||||
@ -592,12 +733,12 @@ class _RaiseClaimDialogState extends State<RaiseClaimDialog> {
|
||||
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) {
|
||||
resetFormOnServiceChange();
|
||||
// 1️⃣ Close dialog first
|
||||
Navigator.pop(context);
|
||||
|
||||
@ -620,8 +761,6 @@ class _RaiseClaimDialogState extends State<RaiseClaimDialog> {
|
||||
Navigator.pop(context);
|
||||
ToastHelper.showErrorToast(context, "Failed: ${decoded['message']}");
|
||||
}
|
||||
|
||||
|
||||
} catch (e) {
|
||||
setState(() {
|
||||
isLoading = false;
|
||||
@ -713,9 +852,73 @@ class _RaiseClaimDialogState extends State<RaiseClaimDialog> {
|
||||
return age;
|
||||
}
|
||||
|
||||
void resetFormOnServiceChange() {
|
||||
hasSubmitted = false;
|
||||
MultiFileUploadWidget.showValidation = false;
|
||||
// Reset dropdown selections
|
||||
selectedClientPolicyId = null;
|
||||
selectedPolicyTypeId = null;
|
||||
policyNumberId = null;
|
||||
selectedMemberId = null;
|
||||
selectedMemberName = null;
|
||||
selectedMemberObject = null;
|
||||
claimTypeId = null;
|
||||
|
||||
// Clear lists
|
||||
employeePolicyList.clear();
|
||||
policyNumberList.clear();
|
||||
|
||||
// Clear all text controllers
|
||||
messageController.clear();
|
||||
accidentDetailsController.clear();
|
||||
hospitalNameController.clear();
|
||||
hospitalAddressController.clear();
|
||||
hospitalCityController.clear();
|
||||
hospitalStateController.clear();
|
||||
hospitalPinCodeController.clear();
|
||||
hospitalPhoneNoController.clear();
|
||||
claimAmountController.clear();
|
||||
sumInsuredController.clear();
|
||||
admitDateController.clear();
|
||||
dischargeDateController.clear();
|
||||
|
||||
// Reset dates
|
||||
accidentDate = null;
|
||||
deathDate = null;
|
||||
intimationDate = null;
|
||||
birthDate = null;
|
||||
admitDate = null;
|
||||
dischargeDate = null;
|
||||
|
||||
// Reset validation flags
|
||||
isPolicyValid = true;
|
||||
isMemberValid = true;
|
||||
isHospitalNameValid = true;
|
||||
isHospitalAddressValid = true;
|
||||
isHospitalCityValid = true;
|
||||
isHospitalStateValid = true;
|
||||
isHospitalPincodeValid = true;
|
||||
isHospitalPhoneNoValid = true;
|
||||
isAdmitDateValid = true;
|
||||
isDischargeDateValid = true;
|
||||
isClaimAmountValid = true;
|
||||
isAccidentDateValid = true;
|
||||
isIntimationDateValid = true;
|
||||
isDeathDateValid = true;
|
||||
|
||||
// Clear uploaded files
|
||||
fileService.clearAll();
|
||||
MultiFileUploadWidget.hasFiles = false;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Dialog(
|
||||
return WillPopScope(
|
||||
onWillPop: () async {
|
||||
resetFormOnServiceChange();
|
||||
return true;
|
||||
},
|
||||
child: Dialog(
|
||||
backgroundColor: Colors.white, // ✅ PURE WHITE popup
|
||||
insetPadding: const EdgeInsets.all(20),
|
||||
shape: RoundedRectangleBorder(
|
||||
@ -724,7 +927,8 @@ class _RaiseClaimDialogState extends State<RaiseClaimDialog> {
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
child: SizedBox(
|
||||
width: MediaQuery.of(context).size.width * 0.75, // Desktop popup width
|
||||
width:
|
||||
MediaQuery.of(context).size.width * 0.75, // Desktop popup width
|
||||
// height: MediaQuery.of(context).size.height * 0.85,
|
||||
child: Stack(
|
||||
children: [
|
||||
@ -748,7 +952,12 @@ class _RaiseClaimDialogState extends State<RaiseClaimDialog> {
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.close),
|
||||
onPressed: () => Navigator.pop(context),
|
||||
onPressed: () => {
|
||||
setState(() {
|
||||
resetFormOnServiceChange();
|
||||
}),
|
||||
Navigator.pop(context)
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
@ -763,11 +972,13 @@ class _RaiseClaimDialogState extends State<RaiseClaimDialog> {
|
||||
buildDropdownField(
|
||||
'Service',
|
||||
(value) {
|
||||
final selectedItem = departmentList.firstWhere(
|
||||
final selectedItem =
|
||||
departmentList.firstWhere(
|
||||
(item) => item['id'] == value,
|
||||
orElse: () => {},
|
||||
);
|
||||
setState(() {
|
||||
resetFormOnServiceChange();
|
||||
serviceId = value;
|
||||
serviceName = selectedItem['name'];
|
||||
policyNumberId = null;
|
||||
@ -775,6 +986,7 @@ class _RaiseClaimDialogState extends State<RaiseClaimDialog> {
|
||||
});
|
||||
print('🔥 serviceId set to $serviceId');
|
||||
filterPoliciesByService(value!);
|
||||
loadClaimTypes();
|
||||
},
|
||||
departmentList,
|
||||
'name',
|
||||
@ -785,15 +997,17 @@ class _RaiseClaimDialogState extends State<RaiseClaimDialog> {
|
||||
buildDropdownField(
|
||||
'Select Policy',
|
||||
(value) {
|
||||
final selectedPolicy =
|
||||
policyNumberList.firstWhere((p) => p['id'] == value);
|
||||
final selectedPolicy = policyNumberList
|
||||
.firstWhere((p) => p['id'] == value);
|
||||
|
||||
setState(() {
|
||||
// ✅ THIS is what you send to API
|
||||
selectedClientPolicyId = selectedPolicy['id'];
|
||||
selectedClientPolicyId =
|
||||
selectedPolicy['id'];
|
||||
|
||||
// optional
|
||||
selectedPolicyTypeId = selectedPolicy['policy_type_id'];
|
||||
selectedPolicyTypeId =
|
||||
selectedPolicy['policy_type_id'];
|
||||
policyNumberId = value;
|
||||
|
||||
isPolicyValid = true;
|
||||
@ -807,20 +1021,37 @@ class _RaiseClaimDialogState extends State<RaiseClaimDialog> {
|
||||
required: true,
|
||||
isValid: isPolicyValid,
|
||||
),
|
||||
|
||||
if (serviceId == 1 || serviceId == 72)
|
||||
buildDropdownField(
|
||||
'Select Claim Type',
|
||||
(value) {
|
||||
setState(() {
|
||||
claimTypeId = value;
|
||||
isClaimTypeValid = true;
|
||||
});
|
||||
},
|
||||
claimTypeList,
|
||||
'name',
|
||||
claimTypeId,
|
||||
required: true,
|
||||
isValid: isClaimTypeValid,
|
||||
),
|
||||
buildDropdownFieldSearch(
|
||||
'Member Name',
|
||||
(value) {
|
||||
final member = employeePolicyList.firstWhere(
|
||||
final member =
|
||||
employeePolicyList.firstWhere(
|
||||
(m) => m['id'] == value,
|
||||
);
|
||||
|
||||
setState(() {
|
||||
selectedMemberId = value;
|
||||
selectedMemberObject = member; // ✅ FULL OBJECT
|
||||
selectedMemberObject =
|
||||
member; // ✅ FULL OBJECT
|
||||
selectedMemberName = member['name'];
|
||||
isMemberValid = true;
|
||||
print('selectedMemberObject $selectedMemberObject');
|
||||
print(
|
||||
'selectedMemberObject $selectedMemberObject');
|
||||
});
|
||||
},
|
||||
employeePolicyList,
|
||||
@ -829,42 +1060,63 @@ class _RaiseClaimDialogState extends State<RaiseClaimDialog> {
|
||||
required: true,
|
||||
isValid: isMemberValid,
|
||||
),
|
||||
|
||||
]),
|
||||
_row([
|
||||
buildTextField('Message', messageController),
|
||||
if (serviceId == 1 || serviceId == 72)...[
|
||||
buildTextField('Hospital Name', hospitalNameController,required: true, isValid: isHospitalNameValid),
|
||||
buildTextField('Hospital Address', hospitalAddressController,required: true, isValid: isHospitalAddressValid),
|
||||
|
||||
if (serviceId == 1 || serviceId == 72) ...[
|
||||
buildTextField(
|
||||
'Hospital Name', hospitalNameController,
|
||||
required: true,
|
||||
isValid: isHospitalNameValid),
|
||||
buildTextField('Hospital Address',
|
||||
hospitalAddressController,
|
||||
required: true,
|
||||
isValid: isHospitalAddressValid),
|
||||
]
|
||||
]),
|
||||
|
||||
if (serviceId == 1 || serviceId == 72)
|
||||
_row([
|
||||
buildTextField('Hospital City', hospitalCityController,required: true, isValid: isHospitalCityValid),
|
||||
buildTextField('Hospital State', hospitalStateController,required: true, isValid: isHospitalStateValid),
|
||||
buildTextField(
|
||||
'Hospital Pincode',
|
||||
'Hospital City', hospitalCityController,
|
||||
required: true,
|
||||
isValid: isHospitalCityValid,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.allow(
|
||||
RegExp(r"[a-zA-Z\s]")),
|
||||
]),
|
||||
buildTextField(
|
||||
'Hospital State', hospitalStateController,
|
||||
required: true,
|
||||
isValid: isHospitalStateValid,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.allow(
|
||||
RegExp(r"[a-zA-Z\s]")),
|
||||
]),
|
||||
buildTextField('Hospital Pincode',
|
||||
hospitalPinCodeController,
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.digitsOnly,
|
||||
LengthLimitingTextInputFormatter(6),
|
||||
],
|
||||
required: true, isValid: isHospitalPincodeValid
|
||||
),
|
||||
required: true,
|
||||
isValid: isHospitalPincodeValid),
|
||||
]),
|
||||
if (serviceId == 1 || serviceId == 72)
|
||||
_row([
|
||||
buildTextField(
|
||||
'Hospital Phone No',
|
||||
buildTextField('Hospital Phone No',
|
||||
hospitalPhoneNoController,
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.digitsOnly,
|
||||
LengthLimitingTextInputFormatter(10),
|
||||
],
|
||||
required: true, isValid: isHospitalPhoneNoValid
|
||||
required: true,
|
||||
isValid: !hasSubmitted ||
|
||||
serviceId == null ||
|
||||
(serviceId != 1 && serviceId != 72) ||
|
||||
RegExp(r'^\d{10}$').hasMatch(hospitalPhoneNoController.text.trim()),
|
||||
),
|
||||
buildDatePickerField(
|
||||
label: 'Admit Date',
|
||||
@ -876,32 +1128,35 @@ class _RaiseClaimDialogState extends State<RaiseClaimDialog> {
|
||||
dischargeDate = null;
|
||||
});
|
||||
},
|
||||
required: true, isValid: isAdmitDateValid
|
||||
),
|
||||
required: true,
|
||||
isValid: isAdmitDateValid),
|
||||
buildDatePickerField(
|
||||
label: 'Discharge Date',
|
||||
selectedDate: dischargeDate,
|
||||
allowFuture: true,
|
||||
minDate: admitDate?.add(const Duration(days: 1)),
|
||||
onDateSelected: (d) => setState(() => dischargeDate = d),
|
||||
required: true, isValid: isDischargeDateValid
|
||||
),
|
||||
minDate: admitDate
|
||||
?.add(const Duration(days: 1)),
|
||||
onDateSelected: (d) =>
|
||||
setState(() => dischargeDate = d),
|
||||
required: true,
|
||||
isValid: isDischargeDateValid),
|
||||
buildTextField(
|
||||
'Claims Amount',
|
||||
claimAmountController,
|
||||
'Claims Amount', claimAmountController,
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
|
||||
required: true, isValid: isClaimAmountValid
|
||||
),
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.digitsOnly
|
||||
],
|
||||
required: true,
|
||||
isValid: isClaimAmountValid),
|
||||
]),
|
||||
|
||||
if ([2, 3, 4].contains(serviceId))
|
||||
_row([
|
||||
buildDatePickerField(
|
||||
label: 'Date of Birth',
|
||||
selectedDate: birthDate,
|
||||
allowFuture: false,
|
||||
onDateSelected: (d) => setState(() => birthDate = d),
|
||||
onDateSelected: (d) =>
|
||||
setState(() => birthDate = d),
|
||||
),
|
||||
buildDatePickerField(
|
||||
label: 'Accident Date',
|
||||
@ -914,13 +1169,16 @@ class _RaiseClaimDialogState extends State<RaiseClaimDialog> {
|
||||
intimationDate = null;
|
||||
});
|
||||
},
|
||||
required: true, isValid: isAccidentDateValid
|
||||
),
|
||||
required: serviceId == 2,
|
||||
isValid: isAccidentDateValid),
|
||||
buildDatePickerField(
|
||||
label: 'Date of Death',
|
||||
selectedDate: deathDate,
|
||||
allowFuture: false,
|
||||
onDateSelected: (d) => setState(() => deathDate = d),
|
||||
onDateSelected: (d) =>
|
||||
setState(() => deathDate = d),
|
||||
required: (serviceId == 3 || serviceId == 4) ? true : false, // 🔥 GTLI & EDLI
|
||||
isValid: isDeathDateValid,
|
||||
),
|
||||
]),
|
||||
if ([2, 3, 4].contains(serviceId))
|
||||
@ -929,18 +1187,18 @@ class _RaiseClaimDialogState extends State<RaiseClaimDialog> {
|
||||
label: 'Date of Intimation',
|
||||
selectedDate: intimationDate,
|
||||
allowFuture: false,
|
||||
onDateSelected: (d) => setState(() => intimationDate = d),
|
||||
required: true, isValid: isIntimationDateValid
|
||||
),
|
||||
onDateSelected: (d) =>
|
||||
setState(() => intimationDate = d)),
|
||||
buildTextField(
|
||||
'Sum Insured',
|
||||
sumInsuredController,
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.digitsOnly
|
||||
],
|
||||
),
|
||||
const SizedBox(),
|
||||
]),
|
||||
|
||||
_row([
|
||||
MultiFileUploadWidget(),
|
||||
]),
|
||||
@ -950,7 +1208,9 @@ class _RaiseClaimDialogState extends State<RaiseClaimDialog> {
|
||||
width: 120,
|
||||
height: 42,
|
||||
child: ElevatedButton(
|
||||
onPressed: isSubmitting ? null : sendFormDataToApi,
|
||||
onPressed: (isSubmitting || serviceId == null)
|
||||
? null
|
||||
: sendFormDataToApi,
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: const Color(0xFFE26728),
|
||||
shape: RoundedRectangleBorder(
|
||||
@ -968,7 +1228,8 @@ class _RaiseClaimDialogState extends State<RaiseClaimDialog> {
|
||||
)
|
||||
: const Text(
|
||||
'Send',
|
||||
style: TextStyle(color: Colors.white,
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.w600),
|
||||
),
|
||||
),
|
||||
@ -982,10 +1243,14 @@ class _RaiseClaimDialogState extends State<RaiseClaimDialog> {
|
||||
),
|
||||
),
|
||||
|
||||
/// 🔄 LOADER OVERLAY (UNCHANGED)
|
||||
/// 🔥 LOADER OVERLAY
|
||||
if (isLoading)
|
||||
Container(
|
||||
color: const Color(0x98FFFCE5),
|
||||
Positioned.fill(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white.withOpacity(0.6),
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
child: Center(
|
||||
child: Image.asset(
|
||||
'assets/nhance-loader.gif',
|
||||
@ -994,12 +1259,11 @@ class _RaiseClaimDialogState extends State<RaiseClaimDialog> {
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
);
|
||||
)));
|
||||
}
|
||||
|
||||
/// ---------- HELPERS ----------
|
||||
@ -1058,7 +1322,6 @@ class _RaiseClaimDialogState extends State<RaiseClaimDialog> {
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Widget buildTextField(
|
||||
String label,
|
||||
TextEditingController controller, {
|
||||
@ -1087,7 +1350,6 @@ class _RaiseClaimDialogState extends State<RaiseClaimDialog> {
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Widget buildTextAreaField(String label, TextEditingController controller) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@ -1168,9 +1430,6 @@ class _RaiseClaimDialogState extends State<RaiseClaimDialog> {
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Widget buildDropdownFieldSearch(
|
||||
String label,
|
||||
void Function(int?) onChanged,
|
||||
@ -1180,7 +1439,6 @@ class _RaiseClaimDialogState extends State<RaiseClaimDialog> {
|
||||
bool required = false,
|
||||
bool isValid = true,
|
||||
}) {
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
@ -1245,10 +1503,8 @@ class _RaiseClaimDialogState extends State<RaiseClaimDialog> {
|
||||
orElse: () => {},
|
||||
);
|
||||
|
||||
final text = matchedItem[displayField]
|
||||
?.toString()
|
||||
.toLowerCase() ??
|
||||
'';
|
||||
final text =
|
||||
matchedItem[displayField]?.toString().toLowerCase() ?? '';
|
||||
|
||||
return text.contains(searchValue.toLowerCase());
|
||||
},
|
||||
@ -1279,7 +1535,6 @@ class _RaiseClaimDialogState extends State<RaiseClaimDialog> {
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Widget buildDatePickerField({
|
||||
required String label,
|
||||
required DateTime? selectedDate,
|
||||
@ -1294,7 +1549,6 @@ class _RaiseClaimDialogState extends State<RaiseClaimDialog> {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
fieldLabel(label, required: required),
|
||||
|
||||
Container(
|
||||
height: 42,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
@ -1320,6 +1574,7 @@ class _RaiseClaimDialogState extends State<RaiseClaimDialog> {
|
||||
initialDate: initialDate,
|
||||
firstDate: first,
|
||||
lastDate: last,
|
||||
initialEntryMode: DatePickerEntryMode.calendarOnly,
|
||||
);
|
||||
|
||||
if (picked != null) {
|
||||
@ -1335,18 +1590,29 @@ class _RaiseClaimDialogState extends State<RaiseClaimDialog> {
|
||||
: 'Select',
|
||||
style: const TextStyle(color: Colors.black),
|
||||
),
|
||||
// ✅ Show clear button only if date selected
|
||||
if (selectedDate != null)
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
onDateSelected(null); // 🔥 Clear date
|
||||
},
|
||||
child: const Icon(
|
||||
Icons.close,
|
||||
size: 18,
|
||||
color: Colors.grey,
|
||||
),
|
||||
)
|
||||
else
|
||||
const Icon(Icons.calendar_today, size: 18),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
errorText(isValid),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Widget uploadBox() {
|
||||
// return Column(
|
||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@ -1380,7 +1646,6 @@ class _RaiseClaimDialogState extends State<RaiseClaimDialog> {
|
||||
child: Center(child: child),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// class RaiseClaimDialog extends StatelessWidget {
|
||||
|
||||
@ -73,11 +73,12 @@ class _CdPoliciesListState extends State<CdPoliciesList> {
|
||||
}
|
||||
|
||||
Future<void> checkIds() async {
|
||||
print('checkIds');
|
||||
_postPreToken = await tokenService.getCurrentToken();
|
||||
empClientId = await tokenService.readValue('empClientId');
|
||||
// empClientBranchId = await tokenService.readValue('empClientBranchId');
|
||||
empHrId = await tokenService.readValue('empHrId');
|
||||
|
||||
print('$_postPreToken - $empClientId - $empHrId');
|
||||
await getCDPoliciesDetails(empClientId, empHrId, _postPreToken);
|
||||
}
|
||||
|
||||
@ -165,7 +166,7 @@ class _CdPoliciesListState extends State<CdPoliciesList> {
|
||||
rows.add([
|
||||
item['insurer_name'] ?? '',
|
||||
item['cd_master_account_no'] ?? '',
|
||||
'₹${item['balance'] ?? '0'}',
|
||||
'${item['balance'] ?? '0'}',
|
||||
]);
|
||||
}
|
||||
|
||||
@ -393,6 +394,30 @@ class _CdPoliciesListState extends State<CdPoliciesList> {
|
||||
return InkWell(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
onTap: () async {
|
||||
await tokenService.writeValue(
|
||||
'hr_cd_insurer_name',
|
||||
filteredData[index]['insurer_name'].toString(),
|
||||
);
|
||||
|
||||
await tokenService.writeValue(
|
||||
'hr_cd_master_account_no',
|
||||
filteredData[index]['cd_master_account_no'].toString(),
|
||||
);
|
||||
|
||||
await tokenService.writeValue(
|
||||
'hr_cd_insurer_id',
|
||||
filteredData[index]['insurer_id'].toString(),
|
||||
);
|
||||
|
||||
await tokenService.writeValue(
|
||||
'hr_cd_ac_pk',
|
||||
filteredData[index]['cd_ac_pk'].toString(),
|
||||
);
|
||||
|
||||
await tokenService.writeValue(
|
||||
'hr_empClientId',
|
||||
empClientId.toString(),
|
||||
);
|
||||
|
||||
Navigator.push(
|
||||
context,
|
||||
@ -462,7 +487,8 @@ class _CDPolicyCard extends StatelessWidget {
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: Text(
|
||||
"₹${balance.toStringAsFixed(0)}",
|
||||
data['balance'] ?? '',
|
||||
// "₹${balance.toStringAsFixed(0)}",
|
||||
textAlign: TextAlign.right,
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 14,
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:csv/csv.dart';
|
||||
import 'package:firebase_auth/firebase_auth.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
@ -13,12 +12,12 @@ import 'package:nhancepolicy/service/api_service.dart';
|
||||
import 'package:nhancepolicy/service/token_storage_service.dart';
|
||||
import 'package:universal_html/html.dart' as html;
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
import '../config/environment.dart';
|
||||
import '../customAppBar/base_layout.dart';
|
||||
import '../customAppBar/customAppBar.dart';
|
||||
import '../customAppBar/customFooter.dart';
|
||||
import 'cdList.dart';
|
||||
import 'claims.dart';
|
||||
|
||||
class cdTransactionDetails extends StatefulWidget {
|
||||
final String insurerName;
|
||||
@ -42,6 +41,14 @@ class cdTransactionDetails extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _cdTransactionDetailsState extends State<cdTransactionDetails> {
|
||||
|
||||
String? localInsurerId;
|
||||
String? localCdAcPk;
|
||||
String? localEmpClientId;
|
||||
String? localInsurerName;
|
||||
String? localCdMasterAccountNo;
|
||||
|
||||
|
||||
final tokenService = TokenStorageService();
|
||||
Uint8List? fileBytes;
|
||||
List<Map<String, dynamic>> getCDTransData = [];
|
||||
@ -85,7 +92,9 @@ class _cdTransactionDetailsState extends State<cdTransactionDetails> {
|
||||
void initState() {
|
||||
super.initState();
|
||||
apiService = ApiService(context); // Initialize ApiService here
|
||||
getCdTransactionDetails();
|
||||
|
||||
restoreTransactionData();
|
||||
|
||||
}
|
||||
|
||||
@override
|
||||
@ -93,9 +102,51 @@ class _cdTransactionDetailsState extends State<cdTransactionDetails> {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// downloadPolicyFiles?file_id=13
|
||||
// getPolicyAndEndorsementFiles?cd_ac_pk=12
|
||||
|
||||
Future<void> restoreTransactionData() async {
|
||||
localInsurerId = widget.insurerId.trim().isNotEmpty
|
||||
? widget.insurerId
|
||||
: await tokenService.readValue('hr_cd_insurer_id');
|
||||
|
||||
localCdAcPk = widget.cd_ac_pk.trim().isNotEmpty
|
||||
? widget.cd_ac_pk
|
||||
: await tokenService.readValue('hr_cd_ac_pk');
|
||||
|
||||
localEmpClientId = widget.empClientId.trim().isNotEmpty
|
||||
? widget.empClientId
|
||||
: await tokenService.readValue('hr_empClientId');
|
||||
|
||||
localInsurerName = widget.insurerName.trim().isNotEmpty
|
||||
? widget.insurerName
|
||||
: await tokenService.readValue('hr_cd_insurer_name');
|
||||
|
||||
localCdMasterAccountNo = widget.cdMasterAccountNo.trim().isNotEmpty
|
||||
? widget.cdMasterAccountNo
|
||||
: await tokenService.readValue('hr_cd_master_account_no');
|
||||
|
||||
print('restore localInsurerId = $localInsurerId');
|
||||
print('restore localCdAcPk = $localCdAcPk');
|
||||
print('restore localEmpClientId = $localEmpClientId');
|
||||
|
||||
if (localInsurerId != null &&
|
||||
localCdAcPk != null &&
|
||||
localEmpClientId != null) {
|
||||
getCdTransactionDetails();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> clearPolicyStorage() async {
|
||||
await tokenService.removeValue('hr_cd_insurer_id');
|
||||
await tokenService.removeValue('hr_cd_ac_pk');
|
||||
await tokenService.removeValue('hr_empClientId');
|
||||
await tokenService.removeValue('hr_cd_insurer_name');
|
||||
await tokenService.removeValue('hr_cd_master_account_no');
|
||||
}
|
||||
|
||||
Future<void> getCdTransactionDetails() async {
|
||||
print('9');
|
||||
setState(() {
|
||||
@ -104,8 +155,8 @@ class _cdTransactionDetailsState extends State<cdTransactionDetails> {
|
||||
try {
|
||||
print('10');
|
||||
final _postPreToken = await tokenService.getCurrentToken();
|
||||
final response = await apiService.getCdTransactionData(widget.empClientId,
|
||||
widget.insurerId, widget.cd_ac_pk, _postPreToken!);
|
||||
final response = await apiService.getCdTransactionData(localEmpClientId!,
|
||||
localInsurerId!, localCdAcPk!, _postPreToken!);
|
||||
if (response['status'] == 'success') {
|
||||
setState(() {
|
||||
isLoading = false;
|
||||
@ -115,11 +166,16 @@ class _cdTransactionDetailsState extends State<cdTransactionDetails> {
|
||||
List<Map<String, dynamic>>.from(response['data']['deposit_data']);
|
||||
originalData = getCDTransData;
|
||||
filteredData = List.from(originalData);
|
||||
total_deposit = formatAmount(response['data']['total_deposit']);
|
||||
total_consumed = formatAmount(response['data']['total_consumed']);
|
||||
total_refund = formatAmount(response['data']['total_refund']);
|
||||
currect_balance = formatAmount(response['data']['currect_balance']);
|
||||
insurer_short_name = formatAmount(response['data']['insurer_short_name']);
|
||||
total_deposit = response['data']['total_deposit'];
|
||||
// total_deposit = formatAmount(response['data']['total_deposit']);
|
||||
total_consumed = response['data']['total_consumed'];
|
||||
// total_consumed = formatAmount(response['data']['total_consumed']);
|
||||
total_refund = response['data']['total_refund'];
|
||||
// total_refund = formatAmount(response['data']['total_refund']);
|
||||
currect_balance = response['data']['currect_balance'];
|
||||
// currect_balance = formatAmount(response['data']['currect_balance']);
|
||||
insurer_short_name = response['data']['insurer_short_name'];
|
||||
// insurer_short_name = formatAmount(response['data']['insurer_short_name']);
|
||||
print('filteredData');
|
||||
print(filteredData);
|
||||
});
|
||||
@ -144,25 +200,53 @@ class _cdTransactionDetailsState extends State<cdTransactionDetails> {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _openEndorsementFile(id) async {
|
||||
print('9');
|
||||
try {
|
||||
print('10');
|
||||
Future<void> _openEndorsementFile(id, file_name) async {
|
||||
// final http.Response response = await apiService.getHrFileDownloadToApi(id, widget.Token);
|
||||
final _postPreToken = await tokenService.getCurrentToken();
|
||||
final response = await apiService.getOpenEndorsementFileData(id, _postPreToken!);
|
||||
if (response['status'] == false) {
|
||||
ToastHelper.showErrorToast(context, response['message']);
|
||||
} else {
|
||||
print("**********-------*****");
|
||||
final apiurl = Environment.apiUrlPost;
|
||||
final String url = '$apiurl/downloadPolicyFiles?file_id=$id';
|
||||
|
||||
// ToastHelper.showWarningToast(
|
||||
// context, 'Request failed with status: ${response.statusCode}');
|
||||
print('Request failed with status: ${response['code']}');
|
||||
}
|
||||
final response = await http.get(
|
||||
Uri.parse(url),
|
||||
headers: {
|
||||
'APP-SIGNATURE':
|
||||
'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y',
|
||||
'Authorization': 'Bearer $_postPreToken',
|
||||
'Content-Type': 'application/json',
|
||||
// 'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||
},
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
try {
|
||||
print("PDF Downloaded");
|
||||
|
||||
// ✅ Create a blob from the response body bytes
|
||||
final blob = html.Blob([response.bodyBytes]);
|
||||
|
||||
// ✅ Generate a download URL
|
||||
final url = html.Url.createObjectUrlFromBlob(blob);
|
||||
|
||||
// ✅ Trigger file download automatically
|
||||
final anchor = html.AnchorElement(href: url)
|
||||
..setAttribute('download', '$file_name')
|
||||
..click();
|
||||
|
||||
// ✅ Revoke the URL to free memory
|
||||
html.Url.revokeObjectUrl(url);
|
||||
|
||||
ToastHelper.showSuccessToast(context, 'File Downloaded Successfully');
|
||||
} catch (e) {
|
||||
print('Exception occurred: $e');
|
||||
throw Exception('Error parsing response: $e');
|
||||
}
|
||||
} else {
|
||||
ToastHelper.showErrorToast(context, 'Failed to download');
|
||||
print("Download failed with status: ${response.statusCode}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Future<void> getCdEndorsementDetails(id) async {
|
||||
print('9');
|
||||
setState(() {
|
||||
@ -243,7 +327,7 @@ class _cdTransactionDetailsState extends State<cdTransactionDetails> {
|
||||
),
|
||||
onTap: () {
|
||||
// Navigator.pop(context); // close popup
|
||||
_openEndorsementFile(file['id']);
|
||||
_openEndorsementFile(file['id'],file['file_name']);
|
||||
},
|
||||
);
|
||||
},
|
||||
@ -387,9 +471,12 @@ class _cdTransactionDetailsState extends State<cdTransactionDetails> {
|
||||
: '-',
|
||||
item['endorsement_no'] ?? '',
|
||||
item['sub_type_text'] ?? '',
|
||||
item['transaction_type'] == 'Credit' ? '₹${formatAmount(item['amount'])}' : '-',
|
||||
item['transaction_type'] == 'Debit' ? '₹${formatAmount(item['amount'])}' : '-',
|
||||
'₹${formatAmount(item['balance']) ?? '0'}',
|
||||
item['transaction_type'] == 'Credit' ? '${item['amount']}' : '-',
|
||||
// item['transaction_type'] == 'Credit' ? '₹${formatAmount(item['amount'])}' : '-',
|
||||
item['transaction_type'] == 'Debit' ? '${item['amount']}' : '-',
|
||||
// item['transaction_type'] == 'Debit' ? '₹${formatAmount(item['amount'])}' : '-',
|
||||
'${item['balance'] ?? '0'}',
|
||||
// '₹${formatAmount(item['balance']) ?? '0'}',
|
||||
item['description'] ?? '',
|
||||
item['username'] ?? '',
|
||||
]);
|
||||
@ -541,7 +628,21 @@ class _cdTransactionDetailsState extends State<cdTransactionDetails> {
|
||||
children: [
|
||||
IconButton(
|
||||
tooltip: 'Previous Page',
|
||||
onPressed: () => Navigator.pop(context),
|
||||
onPressed: () async {
|
||||
await clearPolicyStorage();
|
||||
|
||||
if (Navigator.canPop(context)) {
|
||||
Navigator.pop(context);
|
||||
} else {
|
||||
Navigator.pushReplacement(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: 'cdPoliciesList'),
|
||||
builder: (_) => CdPoliciesList(),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.arrow_back_ios,
|
||||
size: 18,
|
||||
@ -552,7 +653,7 @@ class _cdTransactionDetailsState extends State<cdTransactionDetails> {
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
Text(
|
||||
'Transaction Details - ${insurer_short_name} (${widget.cdMasterAccountNo})',
|
||||
'Transaction Details - ${insurer_short_name} (${localCdMasterAccountNo ?? widget.cdMasterAccountNo})',
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w500,
|
||||
@ -762,21 +863,36 @@ class _cdTransactionDetailsState extends State<cdTransactionDetails> {
|
||||
SizedBox(width: 10),
|
||||
_cell(
|
||||
item['transaction_type'] == 'Credit'
|
||||
? formatAmount(item['amount'])
|
||||
? item['amount']
|
||||
: '-',
|
||||
2,
|
||||
alignRight: true,
|
||||
),
|
||||
// _cell(
|
||||
// item['transaction_type'] == 'Credit'
|
||||
// ? formatAmount(item['amount'])
|
||||
// : '-',
|
||||
// 2,
|
||||
// alignRight: true,
|
||||
// ),
|
||||
SizedBox(width: 10),
|
||||
_cell(
|
||||
item['transaction_type'] == 'Debit'
|
||||
? formatAmount(item['amount'])
|
||||
? item['amount']
|
||||
: '-',
|
||||
2,
|
||||
alignRight: true,
|
||||
),
|
||||
// _cell(
|
||||
// item['transaction_type'] == 'Debit'
|
||||
// ? formatAmount(item['amount'])
|
||||
// : '-',
|
||||
// 2,
|
||||
// alignRight: true,
|
||||
// ),
|
||||
SizedBox(width: 10),
|
||||
_cell(formatAmount(item['balance']), 2, alignRight: true),
|
||||
_cell(item['balance'], 2, alignRight: true),
|
||||
// _cell(formatAmount(item['balance']), 2, alignRight: true),
|
||||
SizedBox(width: 10),
|
||||
_cell(item['description'], 3),
|
||||
SizedBox(width: 10),
|
||||
@ -784,25 +900,72 @@ class _cdTransactionDetailsState extends State<cdTransactionDetails> {
|
||||
SizedBox(width: 10),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: SizedBox(
|
||||
height: 36,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
if (isAllowedSubType)
|
||||
_ActionIconButton(
|
||||
|
||||
/// --- PDF ICON SLOT ---
|
||||
SizedBox(
|
||||
width: 36,
|
||||
height: 36,
|
||||
child: Visibility(
|
||||
visible: isAllowedSubType,
|
||||
maintainSize: true,
|
||||
maintainAnimation: true,
|
||||
maintainState: true,
|
||||
child: _ActionIconButton(
|
||||
icon: Icons.picture_as_pdf_outlined,
|
||||
toolTip: 'View Endorsement PDF',
|
||||
onTap: () => getCdEndorsementDetails(item['id']),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
const SizedBox(width: 8),
|
||||
if (isAllowedSubType && hasSplitUpFile)
|
||||
_ActionIconButton(
|
||||
|
||||
/// --- FOLDER ICON SLOT ---
|
||||
SizedBox(
|
||||
width: 36,
|
||||
height: 36,
|
||||
child: Visibility(
|
||||
visible: isAllowedSubType && hasSplitUpFile,
|
||||
maintainSize: true,
|
||||
maintainAnimation: true,
|
||||
maintainState: true,
|
||||
child: _ActionIconButton(
|
||||
icon: Icons.folder_open_outlined,
|
||||
toolTip: 'View Files',
|
||||
onTap: () => _launchURL(item['split_up_url']),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
// Expanded(
|
||||
// flex: 2,
|
||||
// child: Row(
|
||||
// mainAxisAlignment: MainAxisAlignment.center,
|
||||
// children: [
|
||||
// if (isAllowedSubType)
|
||||
// _ActionIconButton(
|
||||
// icon: Icons.picture_as_pdf_outlined,
|
||||
// toolTip: 'View Endorsement PDF',
|
||||
// onTap: () => getCdEndorsementDetails(item['id']),
|
||||
// ),
|
||||
// const SizedBox(width: 8),
|
||||
// if (isAllowedSubType && hasSplitUpFile)
|
||||
// _ActionIconButton(
|
||||
// icon: Icons.folder_open_outlined,
|
||||
// toolTip: 'View Files',
|
||||
// onTap: () => _launchURL(item['split_up_url']),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
@ -66,6 +66,8 @@ class _ClaimsPolicieState extends State<ClaimsPolicies> {
|
||||
return filteredData.sublist(startIndex, endIndex);
|
||||
}
|
||||
|
||||
int? appliedClaimStatus;
|
||||
|
||||
Color getStatusColor(String status) {
|
||||
switch (status.toLowerCase()) {
|
||||
case 'claim received':
|
||||
@ -182,7 +184,7 @@ class _ClaimsPolicieState extends State<ClaimsPolicies> {
|
||||
});
|
||||
try {
|
||||
print('10');
|
||||
final response = await apiService.getClaimPoliciesToApi(_postPreToken!);
|
||||
final response = await apiService.getClaimPoliciesToApi(_postPreToken!,'');
|
||||
if (response['status'] == 'success') {
|
||||
setState(() {
|
||||
isLoading = false;
|
||||
@ -272,6 +274,9 @@ class _ClaimsPolicieState extends State<ClaimsPolicies> {
|
||||
final data = claim_Detials();
|
||||
print("data -- $data");
|
||||
getClaimList();
|
||||
setState(() {
|
||||
appliedClaimStatus = selectedClaimStatus; // ✅ apply only after API call
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> reset() async {
|
||||
@ -285,6 +290,7 @@ class _ClaimsPolicieState extends State<ClaimsPolicies> {
|
||||
selectedClaimStatus = null;
|
||||
selectedClaimStatusName = null;
|
||||
_currentPage = 1;
|
||||
appliedClaimStatus = null;
|
||||
|
||||
getClaimList();
|
||||
});
|
||||
@ -482,16 +488,19 @@ class _ClaimsPolicieState extends State<ClaimsPolicies> {
|
||||
/// 🔙 Back + Title (LEFT)
|
||||
Row(
|
||||
children: [
|
||||
// IconButton(
|
||||
// onPressed: () => {},
|
||||
// icon: const Icon(
|
||||
// Icons.arrow_back_ios,
|
||||
// size: 18,
|
||||
// color: Colors.black,
|
||||
// ),
|
||||
// padding: EdgeInsets.zero,
|
||||
// constraints: const BoxConstraints(),
|
||||
// ),
|
||||
if(widget.empCode.isNotEmpty)
|
||||
IconButton(
|
||||
onPressed: () => {
|
||||
Navigator.of(context).pop(),
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.arrow_back_ios,
|
||||
size: 18,
|
||||
color: Colors.black,
|
||||
),
|
||||
padding: EdgeInsets.zero,
|
||||
constraints: const BoxConstraints(),
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
Text(
|
||||
'Claims',
|
||||
@ -707,11 +716,6 @@ class _ClaimsPolicieState extends State<ClaimsPolicies> {
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Widget _buildDataRow(Map<String, dynamic> item) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 16),
|
||||
@ -866,21 +870,28 @@ class _ClaimsPolicieState extends State<ClaimsPolicies> {
|
||||
|
||||
if (statusMaster.isEmpty) return const SizedBox();
|
||||
|
||||
final List<dynamic> displayStatuses = appliedClaimStatus != null
|
||||
? statusMaster.where((status) =>
|
||||
int.parse(status['id'].toString()) == appliedClaimStatus)
|
||||
.toList()
|
||||
: statusMaster;
|
||||
|
||||
return SizedBox(
|
||||
height: 30,
|
||||
height: 35,
|
||||
child: ListView.separated(
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemCount: statusMaster.length,
|
||||
itemCount: displayStatuses.length,
|
||||
separatorBuilder: (_, __) => const SizedBox(width: 10),
|
||||
itemBuilder: (context, index) {
|
||||
final statusName =
|
||||
statusMaster[index]['claim_status']?.toString() ?? '';
|
||||
displayStatuses[index]['claim_status']?.toString() ?? '';
|
||||
|
||||
final count = getStatusCount(statusName);
|
||||
final color = getStatusColor(statusName);
|
||||
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 8),
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
||||
decoration: BoxDecoration(
|
||||
color: color,
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
|
||||
@ -34,6 +34,9 @@ class _hrDashboardState extends State<hrDashboard> with SingleTickerProviderStat
|
||||
final tokenService = TokenStorageService();
|
||||
final FocusNode _policyFocusNode = FocusNode();
|
||||
|
||||
bool isTpaDashboardEnabled = false;
|
||||
bool isTpaSelected = false;
|
||||
|
||||
// Variables for API data
|
||||
dynamic empClientBranchId;
|
||||
dynamic empHrId;
|
||||
@ -41,6 +44,7 @@ class _hrDashboardState extends State<hrDashboard> with SingleTickerProviderStat
|
||||
String? _postPreToken = '';
|
||||
int stausVal = 1;
|
||||
bool _isPolicyDropdownOpen = false;
|
||||
html.IFrameElement? _currentIframe;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@ -114,17 +118,32 @@ class _hrDashboardState extends State<hrDashboard> with SingleTickerProviderStat
|
||||
_metabaseLoaded = false;
|
||||
});
|
||||
|
||||
// ✅ REMOVE OLD IFRAME COMPLETELY
|
||||
_currentIframe?.remove();
|
||||
_currentIframe = null;
|
||||
|
||||
// ✅ CLEAR OLD VIEW TYPES
|
||||
_registeredViewTypes.clear();
|
||||
|
||||
final response = await apiService.postHrDashboard({
|
||||
"client_id": empClientId,
|
||||
"client_policy_id": clientPolicyId,
|
||||
}, _postPreToken);
|
||||
|
||||
if (response['status'] == 'success') {
|
||||
// ✅ ADD THIS LINE
|
||||
isTpaDashboardEnabled = response['is_tpa_dashboard_enable'] == true;
|
||||
setState(() {
|
||||
isTpaSelected = false;
|
||||
});
|
||||
|
||||
|
||||
_registerMetabaseIframe(
|
||||
token: response['data']['metabaseToken'],
|
||||
url: response['data']['metabaseUrl'],
|
||||
clientPolicyId: clientPolicyId,
|
||||
);
|
||||
|
||||
setState(() => _metabaseLoaded = true);
|
||||
} else {
|
||||
ToastHelper.showErrorToast(context, response['message']);
|
||||
@ -136,26 +155,74 @@ class _hrDashboardState extends State<hrDashboard> with SingleTickerProviderStat
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _loadTpaDashboard(String clientPolicyId) async {
|
||||
try {
|
||||
setState(() {
|
||||
isDashboardLoading = true;
|
||||
_metabaseLoaded = false;
|
||||
});
|
||||
|
||||
// ✅ REMOVE OLD IFRAME
|
||||
_currentIframe?.remove();
|
||||
_currentIframe = null;
|
||||
_registeredViewTypes.clear();
|
||||
|
||||
final response = await apiService.postHrTpaDashboard({
|
||||
"client_id": empClientId,
|
||||
"client_policy_id": clientPolicyId,
|
||||
}, _postPreToken);
|
||||
|
||||
if (response['status'] == 'success') {
|
||||
setState(() {
|
||||
isTpaSelected = true;
|
||||
});
|
||||
|
||||
_registerMetabaseIframe(
|
||||
token: response['data']['metabaseToken'],
|
||||
url: response['data']['metabaseUrl'],
|
||||
clientPolicyId: clientPolicyId,
|
||||
);
|
||||
|
||||
setState(() => _metabaseLoaded = true);
|
||||
|
||||
} else {
|
||||
ToastHelper.showErrorToast(context, response['message']);
|
||||
}
|
||||
} catch (e) {
|
||||
ToastHelper.showErrorToast(context, 'TPA Dashboard loading failed');
|
||||
} finally {
|
||||
setState(() => isDashboardLoading = false);
|
||||
}
|
||||
}
|
||||
|
||||
void _registerMetabaseIframe({
|
||||
required String token,
|
||||
required String url,
|
||||
required String clientPolicyId,
|
||||
}) {
|
||||
final viewType = 'metabase-dashboard-$clientPolicyId';
|
||||
// 🔥 ALWAYS CREATE UNIQUE VIEW TYPE
|
||||
final viewType =
|
||||
'metabase-dashboard-${clientPolicyId}-${DateTime.now().millisecondsSinceEpoch}';
|
||||
|
||||
_dashboardViewType = viewType;
|
||||
|
||||
if (_registeredViewTypes.contains(viewType)) return;
|
||||
final embedUrl =
|
||||
"$url/embed/dashboard/$token"
|
||||
"#theme=light&bordered=true&titled=true"
|
||||
"&v=${DateTime.now().millisecondsSinceEpoch}"; // 🔥 cache buster
|
||||
|
||||
final embedUrl = "$url/embed/dashboard/$token#theme=light&bordered=true&titled=true";
|
||||
|
||||
ui.platformViewRegistry.registerViewFactory(
|
||||
viewType,
|
||||
(int viewId) => html.IFrameElement()
|
||||
final iframe = html.IFrameElement()
|
||||
..src = embedUrl
|
||||
..style.border = 'none'
|
||||
..style.width = '100%'
|
||||
..style.height = '100%'
|
||||
..allowFullscreen = true,
|
||||
..allowFullscreen = true;
|
||||
|
||||
_currentIframe = iframe;
|
||||
|
||||
ui.platformViewRegistry.registerViewFactory(
|
||||
viewType,
|
||||
(int viewId) => iframe,
|
||||
);
|
||||
|
||||
_registeredViewTypes.add(viewType);
|
||||
@ -185,7 +252,7 @@ class _hrDashboardState extends State<hrDashboard> with SingleTickerProviderStat
|
||||
|
||||
Widget _buildDashboardView() {
|
||||
if (postModules.isNotEmpty && activePoliciesList.isEmpty) {
|
||||
return const Center(child: Text('No dashboard data available for your account'));
|
||||
return const Center(child: Text('No active policy found.'));
|
||||
}
|
||||
|
||||
return Padding(
|
||||
@ -339,6 +406,7 @@ class _hrDashboardState extends State<hrDashboard> with SingleTickerProviderStat
|
||||
color: Colors.white,
|
||||
child: Row(
|
||||
children: [
|
||||
if (!isTpaSelected)...[
|
||||
const Text(
|
||||
'Select Policy',
|
||||
style: TextStyle(fontWeight: FontWeight.w600, fontSize: 13),
|
||||
@ -429,6 +497,37 @@ class _hrDashboardState extends State<hrDashboard> with SingleTickerProviderStat
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
|
||||
const Spacer(),
|
||||
|
||||
if (isTpaDashboardEnabled)
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: isTpaSelected
|
||||
? Colors.teal
|
||||
: Colors.grey.shade300,
|
||||
foregroundColor:
|
||||
isTpaSelected ? Colors.white : Colors.black,
|
||||
),
|
||||
onPressed: () {
|
||||
if (selectedPolicyId == null) return;
|
||||
|
||||
if (isTpaSelected) {
|
||||
// 🔄 Switch BACK to Normal Dashboard
|
||||
_loadDashboardByPolicy(selectedPolicyId!);
|
||||
} else {
|
||||
// 🔄 Switch TO TPA Dashboard
|
||||
_loadTpaDashboard(selectedPolicyId!);
|
||||
}
|
||||
},
|
||||
child: Text(
|
||||
isTpaSelected
|
||||
? "Insights from Nhance"
|
||||
: "Insights from TPA ",
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -106,11 +106,56 @@ class _policiesState extends State<policies>
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _loadToken() async {
|
||||
final enrollmentRaw = await tokenService.readValue('enrollmentAllowed_modules'); // "[1]"
|
||||
final postRaw = await tokenService.readValue('empAllowed_modules'); // "[2,3,4]"
|
||||
// Future<void> _loadToken() async {
|
||||
// final enrollmentRaw = await tokenService.readValue('enrollmentAllowed_modules'); // "[1]"
|
||||
// final postRaw = await tokenService.readValue('empAllowed_modules'); // "[2,3,4]"
|
||||
//
|
||||
// // ✅ Decode safely
|
||||
// enrollmentModules = enrollmentRaw != null && enrollmentRaw.isNotEmpty
|
||||
// ? List<int>.from(jsonDecode(enrollmentRaw))
|
||||
// : [];
|
||||
//
|
||||
// postModules = postRaw != null && postRaw.isNotEmpty
|
||||
// ? List<int>.from(jsonDecode(postRaw))
|
||||
// : [];
|
||||
//
|
||||
// print('enrollmentModules $enrollmentModules');
|
||||
// print('postModules $postModules');
|
||||
//
|
||||
// _postPreToken = await tokenService.getCurrentToken();
|
||||
// print(_postPreToken);
|
||||
//
|
||||
// if (enrollmentModules.contains(1)) {
|
||||
// enrollmentClient_id = await tokenService.readValue('enrollmentClient_id');
|
||||
// enrollmentEmpClientBranchId =
|
||||
// await tokenService.readValue('enrollmentEmpClientBranchId');
|
||||
// enrollmentHrId = await tokenService.readValue('enrollmentHrId');
|
||||
//
|
||||
// await getPreCashDepositDetails(enrollmentEmpClientBranchId,
|
||||
// enrollmentClient_id, enrollmentHrId, _postPreToken);
|
||||
// }
|
||||
//
|
||||
// if (postModules.contains(2)) {
|
||||
// empClientId = await tokenService.readValue('empClientId');
|
||||
// empClientBranchId = await tokenService.readValue('empClientBranchId');
|
||||
// empHrId = await tokenService.readValue('empHrId');
|
||||
//
|
||||
// await getPostCashDepositDetails(empClientBranchId, empClientId, empHrId, _postPreToken);
|
||||
// }
|
||||
//
|
||||
// }
|
||||
|
||||
Future<void> _loadToken() async {
|
||||
setState(() {
|
||||
isLoading = true; // 🔥 START LOADER HERE
|
||||
});
|
||||
|
||||
try {
|
||||
final enrollmentRaw =
|
||||
await tokenService.readValue('enrollmentAllowed_modules');
|
||||
final postRaw =
|
||||
await tokenService.readValue('empAllowed_modules');
|
||||
|
||||
// ✅ Decode safely
|
||||
enrollmentModules = enrollmentRaw != null && enrollmentRaw.isNotEmpty
|
||||
? List<int>.from(jsonDecode(enrollmentRaw))
|
||||
: [];
|
||||
@ -119,30 +164,56 @@ class _policiesState extends State<policies>
|
||||
? List<int>.from(jsonDecode(postRaw))
|
||||
: [];
|
||||
|
||||
print('enrollmentModules $enrollmentModules');
|
||||
print('postModules $postModules');
|
||||
|
||||
_postPreToken = await tokenService.getCurrentToken();
|
||||
print(_postPreToken);
|
||||
|
||||
List<Future> apiCalls = [];
|
||||
|
||||
/// 👇 Add APIs dynamically
|
||||
if (enrollmentModules.contains(1)) {
|
||||
enrollmentClient_id = await tokenService.readValue('enrollmentClient_id');
|
||||
enrollmentClient_id =
|
||||
await tokenService.readValue('enrollmentClient_id');
|
||||
enrollmentEmpClientBranchId =
|
||||
await tokenService.readValue('enrollmentEmpClientBranchId');
|
||||
enrollmentHrId = await tokenService.readValue('enrollmentHrId');
|
||||
enrollmentHrId =
|
||||
await tokenService.readValue('enrollmentHrId');
|
||||
|
||||
await getPreCashDepositDetails(enrollmentEmpClientBranchId,
|
||||
enrollmentClient_id, enrollmentHrId, _postPreToken);
|
||||
apiCalls.add(
|
||||
getPreCashDepositDetails(
|
||||
enrollmentEmpClientBranchId,
|
||||
enrollmentClient_id,
|
||||
enrollmentHrId,
|
||||
_postPreToken,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
if (postModules.contains(2)) {
|
||||
empClientId = await tokenService.readValue('empClientId');
|
||||
empClientBranchId = await tokenService.readValue('empClientBranchId');
|
||||
empClientBranchId =
|
||||
await tokenService.readValue('empClientBranchId');
|
||||
empHrId = await tokenService.readValue('empHrId');
|
||||
|
||||
await getPostCashDepositDetails(empClientBranchId, empClientId, empHrId, _postPreToken);
|
||||
apiCalls.add(
|
||||
getPostCashDepositDetails(
|
||||
empClientBranchId,
|
||||
empClientId,
|
||||
empHrId,
|
||||
_postPreToken,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// 🔥 WAIT FOR ALL APIs
|
||||
await Future.wait(apiCalls);
|
||||
} catch (e) {
|
||||
print("Error in _loadToken: $e");
|
||||
} finally {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
isLoading = false; // 🔥 STOP LOADER ONLY ONCE
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> getPreCashDepositDetails(enrollmentEmpClientBranchId,
|
||||
@ -153,7 +224,6 @@ class _policiesState extends State<policies>
|
||||
print("hr_id -$enrollmentHrId");
|
||||
print("token -$_postPreToken");
|
||||
|
||||
isLoading = true;
|
||||
// setState(() {
|
||||
// _isLoading = true;
|
||||
// });
|
||||
@ -171,7 +241,6 @@ class _policiesState extends State<policies>
|
||||
// clintID!, clintBranchId!, hr_id, token);
|
||||
print('IN1');
|
||||
if (response['status'] == 'success') {
|
||||
isLoading = false;
|
||||
setState(() {
|
||||
print('response');
|
||||
print(response['data']);
|
||||
@ -198,7 +267,6 @@ class _policiesState extends State<policies>
|
||||
print("hr_id -$empHrId");
|
||||
print("token -$_postPreToken");
|
||||
|
||||
isLoading = true;
|
||||
// setState(() {
|
||||
// _isLoading = true;
|
||||
// });
|
||||
@ -213,7 +281,6 @@ class _policiesState extends State<policies>
|
||||
// clintID!, clintBranchId!, hr_id, token);
|
||||
print('IN1');
|
||||
if (response['status'] == 'success') {
|
||||
isLoading = false;
|
||||
setState(() {
|
||||
print('response');
|
||||
print(response['data']);
|
||||
@ -226,7 +293,6 @@ class _policiesState extends State<policies>
|
||||
|
||||
print('IN2');
|
||||
} else {
|
||||
isLoading = false;
|
||||
print('API request failed with status');
|
||||
setState(() {
|
||||
activePoliciesList = [];
|
||||
@ -345,7 +411,16 @@ class _policiesState extends State<policies>
|
||||
required List<Map<String, dynamic>> openEnrollment,
|
||||
required List<Map<String, dynamic>> activePolicies,
|
||||
}) {
|
||||
return Scaffold(
|
||||
return isLoading ? Container(
|
||||
color: Colors.transparent, // Semi-transparent background
|
||||
child: Center(
|
||||
child: // Your GIF loader widget
|
||||
Image.asset(
|
||||
height: 60,
|
||||
width: 60,
|
||||
'assets/nhance-loader.gif'), // Adjust path to your GIF loader
|
||||
),
|
||||
) : Scaffold(
|
||||
body: SingleChildScrollView(
|
||||
|
||||
// padding: const EdgeInsets.all(20),
|
||||
@ -385,12 +460,15 @@ class _policiesState extends State<policies>
|
||||
SizedBox(height: 15),
|
||||
Container(
|
||||
width: double.infinity,
|
||||
height: 400,
|
||||
// constraints: const BoxConstraints(
|
||||
// minHeight: 180,
|
||||
// ),
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
),
|
||||
child: IntrinsicHeight(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
@ -401,23 +479,26 @@ class _policiesState extends State<policies>
|
||||
SizedBox(height: 14),
|
||||
|
||||
/// ✅ SCROLLABLE AREA
|
||||
Expanded(
|
||||
child: openEnrollment.isEmpty
|
||||
openEnrollment.isEmpty
|
||||
? _EmptyBox('No policies open for enrollment')
|
||||
: _PolicyGrid(
|
||||
policies: openEnrollment,
|
||||
isEnrollment: true,
|
||||
),
|
||||
),
|
||||
|
||||
],
|
||||
),
|
||||
)
|
||||
|
||||
),
|
||||
],
|
||||
if(postModules.contains(2))...[
|
||||
SizedBox(height: 20),
|
||||
Container(
|
||||
width: double.infinity,
|
||||
height: 400,
|
||||
// constraints: const BoxConstraints(
|
||||
// minHeight: 180,
|
||||
// ),
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
@ -454,15 +535,14 @@ class _policiesState extends State<policies>
|
||||
const SizedBox(height: 14),
|
||||
|
||||
/// ✅ SCROLLABLE GRID
|
||||
Expanded(
|
||||
child: activePolicies.isEmpty
|
||||
activePolicies.isEmpty
|
||||
? stausVal == 0 ? _EmptyBox('You don’t have any expired policies at the moment.') : _EmptyBox('No active policies found')
|
||||
: _PolicyGrid(
|
||||
policies: activePolicies,
|
||||
isEnrollment: false,
|
||||
onBulkDownload: getEcardBulkDownload,
|
||||
),
|
||||
),
|
||||
|
||||
|
||||
const SizedBox(height: 8),
|
||||
Align(
|
||||
@ -513,31 +593,62 @@ class _PolicyGrid extends StatelessWidget {
|
||||
) {
|
||||
final width = MediaQuery.of(context).size.width;
|
||||
|
||||
if (width < 600) {
|
||||
return ResponsiveGridConfig(1, isEnrollment ? 1.25 : 1.15);
|
||||
} else if (width < 900) {
|
||||
return ResponsiveGridConfig(2, isEnrollment ? 1.6 : 1.45);
|
||||
} else if (width < 1400) {
|
||||
return ResponsiveGridConfig(3, isEnrollment ? 3.1 : 2.5);
|
||||
// if (width < 600) {
|
||||
// return ResponsiveGridConfig(1, isEnrollment ? 1.25 : 1.15);
|
||||
// } else if (width < 900) {
|
||||
// return ResponsiveGridConfig(2, isEnrollment ? 1.6 : 1.45);
|
||||
// } else if (width < 1400) {
|
||||
// return ResponsiveGridConfig(3, isEnrollment ? 3.1 : 2.5);
|
||||
// } else {
|
||||
// return ResponsiveGridConfig(4, isEnrollment ? 3.1 : 2.4);
|
||||
// }
|
||||
|
||||
|
||||
|
||||
if (width >= 1400) {
|
||||
return const ResponsiveGridConfig(4, 2.6); // Big screen
|
||||
} else if (width >= 1000) {
|
||||
return const ResponsiveGridConfig(3, 2.3); // Small desktop
|
||||
} else if (width >= 600) {
|
||||
return const ResponsiveGridConfig(2, 2.0); // Tablet
|
||||
} else {
|
||||
return ResponsiveGridConfig(4, isEnrollment ? 3.1 : 2.4);
|
||||
return const ResponsiveGridConfig(1, 1.8); // Mobile
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final tokenService = TokenStorageService();
|
||||
final config = _getGridConfig(context, isEnrollment);
|
||||
|
||||
return GridView.builder(
|
||||
final int rowCount = (policies.length / config.crossAxisCount).ceil();
|
||||
|
||||
double cardHeight;
|
||||
|
||||
if (isEnrollment) {
|
||||
cardHeight = 140;
|
||||
} else {
|
||||
cardHeight = 170;
|
||||
}
|
||||
|
||||
final double totalHeight =
|
||||
rowCount * cardHeight + ((rowCount - 1) * 16);
|
||||
|
||||
|
||||
return SizedBox(
|
||||
height: totalHeight,
|
||||
child: GridView.builder(
|
||||
physics: const BouncingScrollPhysics(),
|
||||
shrinkWrap: true,
|
||||
padding: EdgeInsets.zero,
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: config.crossAxisCount,
|
||||
childAspectRatio: config.childAspectRatio,
|
||||
crossAxisSpacing: 16,
|
||||
mainAxisSpacing: 16,
|
||||
mainAxisExtent: isEnrollment ? 120 : 150, // fixed card height
|
||||
),
|
||||
itemCount: policies.length,
|
||||
itemBuilder: (context, index) {
|
||||
@ -590,12 +701,15 @@ class _PolicyGrid extends StatelessWidget {
|
||||
onBulkDownload: onBulkDownload,
|
||||
onTap: () async {
|
||||
final token = await tokenService.getCurrentToken();
|
||||
final clientId =
|
||||
await tokenService.readValue('empClientId');
|
||||
final branchId =
|
||||
await tokenService.readValue('empClientBranchId');
|
||||
final clientId = await tokenService.readValue('empClientId');
|
||||
final branchId = await tokenService.readValue('empClientBranchId');
|
||||
|
||||
print("token: $token");
|
||||
print("clientId: $clientId");
|
||||
print("branchId: $branchId");
|
||||
|
||||
if (token == null || clientId == null || branchId == null) {
|
||||
print("Missing required values");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -630,6 +744,7 @@ class _PolicyGrid extends StatelessWidget {
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -51,8 +51,7 @@ class postFileUpload extends StatefulWidget {
|
||||
required this.cardInsurer_name,
|
||||
required this.cardPolicy_name,
|
||||
required this.cardPolicy_ExpDate,
|
||||
required this.total_premium
|
||||
})
|
||||
required this.total_premium})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
@ -61,6 +60,23 @@ class postFileUpload extends StatefulWidget {
|
||||
|
||||
class _postFileUploadState extends State<postFileUpload> {
|
||||
final tokenService = TokenStorageService();
|
||||
|
||||
|
||||
String localClientId = '';
|
||||
String localPolicyTypeId = '';
|
||||
String localClientPolicyId = '';
|
||||
String localClientBranchId = '';
|
||||
String localToken = '';
|
||||
String localTokenType = '';
|
||||
String localCardType = '';
|
||||
String localCardPolicyNo = '';
|
||||
String localCardInsurerName = '';
|
||||
String localCardPolicyName = '';
|
||||
String localCardPolicyExpDate = '';
|
||||
String localTotalPremium = '';
|
||||
|
||||
|
||||
|
||||
Uint8List? fileBytes;
|
||||
Uint8List? fileBytes2;
|
||||
late String _token;
|
||||
@ -101,9 +117,8 @@ class _postFileUploadState extends State<postFileUpload> {
|
||||
bool showSampleButton = false;
|
||||
String? currentApiValue; // To store the 'value' for the 2nd param
|
||||
|
||||
|
||||
int _currentPage = 1;
|
||||
int _rowsPerPage = 5;
|
||||
int _rowsPerPage = 6;
|
||||
|
||||
List<dynamic> get _paginatedData {
|
||||
final startIndex = (_currentPage - 1) * _rowsPerPage;
|
||||
@ -125,9 +140,12 @@ class _postFileUploadState extends State<postFileUpload> {
|
||||
void initState() {
|
||||
super.initState();
|
||||
apiService = ApiService(context);
|
||||
restoreUploadData().then((_) {
|
||||
_loadToken();
|
||||
getFileUploadMasterDetails();
|
||||
getFileListDetails();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@override
|
||||
@ -137,22 +155,85 @@ class _postFileUploadState extends State<postFileUpload> {
|
||||
}
|
||||
|
||||
Future<void> _loadToken() async {
|
||||
// final token = prefs.getString('hrtoken');
|
||||
final token = widget.Token;
|
||||
final token = localToken.isNotEmpty
|
||||
? localToken
|
||||
: await tokenService.readValue('upload_Token');
|
||||
|
||||
if (token != null && token.isNotEmpty) {
|
||||
setState(() {
|
||||
_token = token;
|
||||
});
|
||||
Map<String, dynamic>? decodedToken = Jwt.parseJwt(token);
|
||||
print('decodedToken $decodedToken');
|
||||
} else {
|
||||
// Token is empty or null, handle accordingly (e.g., navigate to login screen)
|
||||
// For now, let's navigate to the login screen
|
||||
ToastHelper.showErrorToast(context, 'Session Out');
|
||||
Navigator.pushReplacementNamed(context, 'hrLogin');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> restoreUploadData() async {
|
||||
localClientId = widget.ClientId.isNotEmpty
|
||||
? widget.ClientId
|
||||
: await tokenService.readValue('upload_ClientId') ?? '';
|
||||
|
||||
localPolicyTypeId = widget.policyTypeId.isNotEmpty
|
||||
? widget.policyTypeId
|
||||
: await tokenService.readValue('upload_policyTypeId') ?? '';
|
||||
|
||||
localClientPolicyId = widget.ClientPoliyId.isNotEmpty
|
||||
? widget.ClientPoliyId
|
||||
: await tokenService.readValue('upload_ClientPoliyId') ?? '';
|
||||
|
||||
localClientBranchId = widget.clientBranchId.isNotEmpty
|
||||
? widget.clientBranchId
|
||||
: await tokenService.readValue('upload_clientBranchId') ?? '';
|
||||
|
||||
localToken = widget.Token.isNotEmpty
|
||||
? widget.Token
|
||||
: await tokenService.readValue('upload_Token') ?? '';
|
||||
|
||||
localTokenType = widget.TokenType.isNotEmpty
|
||||
? widget.TokenType
|
||||
: await tokenService.readValue('upload_TokenType') ?? '';
|
||||
|
||||
localCardType = widget.cardType.isNotEmpty
|
||||
? widget.cardType
|
||||
: await tokenService.readValue('upload_cardType') ?? '';
|
||||
|
||||
localCardPolicyNo = widget.cardPolicyNo.isNotEmpty
|
||||
? widget.cardPolicyNo
|
||||
: await tokenService.readValue('upload_cardPolicyNo') ?? '';
|
||||
|
||||
localCardInsurerName = widget.cardInsurer_name.isNotEmpty
|
||||
? widget.cardInsurer_name
|
||||
: await tokenService.readValue('upload_cardInsurer_name') ?? '';
|
||||
|
||||
localCardPolicyName = widget.cardPolicy_name.isNotEmpty
|
||||
? widget.cardPolicy_name
|
||||
: await tokenService.readValue('upload_cardPolicy_name') ?? '';
|
||||
|
||||
localCardPolicyExpDate = widget.cardPolicy_ExpDate.isNotEmpty
|
||||
? widget.cardPolicy_ExpDate
|
||||
: await tokenService.readValue('upload_cardPolicy_ExpDate') ?? '';
|
||||
|
||||
localTotalPremium = widget.total_premium.isNotEmpty
|
||||
? widget.total_premium
|
||||
: await tokenService.readValue('upload_total_premium') ?? '';
|
||||
}
|
||||
|
||||
Future<void> clearUploadStorage() async {
|
||||
await tokenService.removeValue('upload_ClientId');
|
||||
await tokenService.removeValue('upload_policyTypeId');
|
||||
await tokenService.removeValue('upload_ClientPoliyId');
|
||||
await tokenService.removeValue('upload_clientBranchId');
|
||||
await tokenService.removeValue('upload_Token');
|
||||
await tokenService.removeValue('upload_TokenType');
|
||||
await tokenService.removeValue('upload_cardType');
|
||||
await tokenService.removeValue('upload_cardPolicyNo');
|
||||
await tokenService.removeValue('upload_cardInsurer_name');
|
||||
await tokenService.removeValue('upload_cardPolicy_name');
|
||||
await tokenService.removeValue('upload_cardPolicy_ExpDate');
|
||||
await tokenService.removeValue('upload_total_premium');
|
||||
}
|
||||
|
||||
// Future<void> getPolicyDetails() async {
|
||||
// setState(() {
|
||||
// clientPolicyId = argumentsData['client_policy_id'];
|
||||
@ -184,7 +265,7 @@ class _postFileUploadState extends State<postFileUpload> {
|
||||
Future<void> getFileUploadMasterDetails() async {
|
||||
print('9');
|
||||
try {
|
||||
final response = await apiService.getFileUploadMastersToApi(widget.Token);
|
||||
final response = await apiService.getFileUploadMastersToApi(localToken);
|
||||
|
||||
if (response['status'] == true) {
|
||||
print('getFileUploadMasterList1');
|
||||
@ -220,8 +301,8 @@ class _postFileUploadState extends State<postFileUpload> {
|
||||
|
||||
print('9');
|
||||
try {
|
||||
final response = await apiService.getFileListToApi(
|
||||
empPrimaryId, widget.cardPolicyNo, empClientId,widget.Token,widget.TokenType);
|
||||
final response = await apiService.getFileListToApi(empPrimaryId,
|
||||
localCardPolicyNo, empClientId, localToken, localTokenType);
|
||||
|
||||
if (response['status'] == 'success') {
|
||||
print('getThrFileList');
|
||||
@ -248,18 +329,20 @@ class _postFileUploadState extends State<postFileUpload> {
|
||||
}
|
||||
|
||||
Future<void> getHrFileDownload(id, file_name) async {
|
||||
// final http.Response response = await apiService.getHrFileDownloadToApi(id, widget.Token);
|
||||
// final http.Response response = await apiService.getHrFileDownloadToApi(id, localToken);
|
||||
print("**********-------*****");
|
||||
final encryptClientId = widget.ClientId;
|
||||
final encryptClientId = localClientId;
|
||||
print(encryptClientId);
|
||||
final apiurl = Environment.apiUrlPost;
|
||||
final String url = '$apiurl/hrFileDownload?id=$id&cliend_id=$encryptClientId';
|
||||
final token = widget.Token;
|
||||
final String url =
|
||||
'$apiurl/hrFileDownload?id=$id&cliend_id=$encryptClientId';
|
||||
final token = localToken;
|
||||
|
||||
final response = await http.get(
|
||||
Uri.parse(url),
|
||||
headers: {
|
||||
'APP-SIGNATURE': 'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y',
|
||||
'APP-SIGNATURE':
|
||||
'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y',
|
||||
'Authorization': 'Bearer $token',
|
||||
'Content-Type': 'application/json',
|
||||
// 'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||
@ -297,16 +380,17 @@ class _postFileUploadState extends State<postFileUpload> {
|
||||
Future<void> downloadPostSampleFile(String apiParam) async {
|
||||
print("fun Sam f - in");
|
||||
|
||||
final post_file_name = apiParam+'_sample_file.xlsx';
|
||||
print("fun Sam f - name $post_file_name" );
|
||||
final post_file_name = apiParam + '_sample_file.xlsx';
|
||||
print("fun Sam f - name $post_file_name");
|
||||
final apiurl = Environment.apiUrlPost;
|
||||
final String url = '$apiurl/downloadSampleExcel/$apiParam';
|
||||
final token = widget.Token;
|
||||
final token = localToken;
|
||||
|
||||
final response = await http.get(
|
||||
Uri.parse(url),
|
||||
headers: {
|
||||
'APP-SIGNATURE': 'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y',
|
||||
'APP-SIGNATURE':
|
||||
'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y',
|
||||
'Authorization': 'Bearer $token',
|
||||
'Content-Type': 'application/json',
|
||||
// 'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||
@ -315,7 +399,7 @@ class _postFileUploadState extends State<postFileUpload> {
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
try {
|
||||
print("fun sam f - ${response.statusCode}" );
|
||||
print("fun sam f - ${response.statusCode}");
|
||||
|
||||
// ✅ Create a blob from the response body bytes
|
||||
final blob = html.Blob([response.bodyBytes]);
|
||||
@ -333,7 +417,7 @@ class _postFileUploadState extends State<postFileUpload> {
|
||||
|
||||
ToastHelper.showSuccessToast(context, 'File Downloaded Successfully');
|
||||
} catch (e) {
|
||||
print("fun sam f - fail" );
|
||||
print("fun sam f - fail");
|
||||
throw Exception('Error parsing response: $e');
|
||||
}
|
||||
} else {
|
||||
@ -475,7 +559,8 @@ class _postFileUploadState extends State<postFileUpload> {
|
||||
print('else');
|
||||
// Attach the file to the request
|
||||
// Set authorization token in headers
|
||||
request.headers['APP-SIGNATURE'] = 'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y';
|
||||
request.headers['APP-SIGNATURE'] =
|
||||
'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y';
|
||||
request.headers['Authorization'] = 'Bearer $_token';
|
||||
// request.files.add(http.MultipartFile.fromBytes('file', fileBytes,
|
||||
// filename: fileName));
|
||||
@ -492,13 +577,13 @@ class _postFileUploadState extends State<postFileUpload> {
|
||||
));
|
||||
print('clintID: $clintID');
|
||||
|
||||
request.fields['client_id'] = widget.ClientId;
|
||||
request.fields['policy_no'] = widget.cardPolicyNo;
|
||||
request.fields['client_branch_id'] = widget.clientBranchId;
|
||||
request.fields['client_id'] = localClientId;
|
||||
request.fields['policy_no'] = localCardPolicyNo;
|
||||
request.fields['client_branch_id'] = localClientBranchId;
|
||||
request.fields['file_action'] = selectedKey!;
|
||||
// request.fields['status'] = selectedKey!;
|
||||
request.fields['created_by'] = empPrimaryId;
|
||||
request.fields['policy_id'] = widget.ClientPoliyId;
|
||||
request.fields['policy_id'] = localClientBranchId;
|
||||
// "client_id": 1,
|
||||
// "client_branch_id": 2,
|
||||
// "policy_no": "POL123456",
|
||||
@ -520,15 +605,15 @@ class _postFileUploadState extends State<postFileUpload> {
|
||||
isLoading = false;
|
||||
});
|
||||
ToastHelper.showSuccessToast(context, data['message']);
|
||||
getFileListDetails();
|
||||
setState(() {
|
||||
selectedValue = null;
|
||||
selectedKey = null;
|
||||
resetErrorCount();
|
||||
getFileListDetails();
|
||||
});
|
||||
} else {
|
||||
getFileListDetails();
|
||||
setState(() {
|
||||
getFileListDetails();
|
||||
isLoading = false;
|
||||
selectedValue = null;
|
||||
selectedKey = null;
|
||||
@ -587,7 +672,8 @@ class _postFileUploadState extends State<postFileUpload> {
|
||||
}
|
||||
|
||||
Widget _buildContent(BuildContext context) {
|
||||
return isLoading ? Container(
|
||||
return isLoading
|
||||
? Container(
|
||||
color: Colors.transparent, // Semi-transparent background
|
||||
child: Center(
|
||||
child: // Your GIF loader widget
|
||||
@ -596,21 +682,61 @@ class _postFileUploadState extends State<postFileUpload> {
|
||||
width: 60,
|
||||
'assets/nhance-loader.gif'), // Adjust path to your GIF loader
|
||||
),
|
||||
): Container(
|
||||
)
|
||||
: Container(
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
IconButton(
|
||||
tooltip: 'Previous Page',
|
||||
onPressed: () => {Navigator.pop(context)},
|
||||
onPressed: () async {
|
||||
if (Navigator.canPop(context)) {
|
||||
Navigator.pop(context);
|
||||
return;
|
||||
}
|
||||
|
||||
final clientId = await tokenService.readValue('hr_ClientId') ?? '';
|
||||
final policyTypeId = await tokenService.readValue('hr_policyTypeId') ?? '';
|
||||
final clientPolicyId = await tokenService.readValue('hr_ClientPoliyId') ?? '';
|
||||
final clientBranchId = await tokenService.readValue('hr_clientBranchId') ?? '';
|
||||
final token = await tokenService.readValue('hr_Token') ?? '';
|
||||
final tokenType = await tokenService.readValue('hr_TokenType') ?? '';
|
||||
final cardType = await tokenService.readValue('hr_cardType') ?? '';
|
||||
final policyNo = await tokenService.readValue('hr_cardPolicyNo') ?? '';
|
||||
final insurer = await tokenService.readValue('hr_cardInsurer_name') ?? '';
|
||||
final policyName = await tokenService.readValue('hr_cardPolicy_name') ?? '';
|
||||
final expDate = await tokenService.readValue('hr_cardPolicy_ExpDate') ?? '';
|
||||
final totalPremium = await tokenService.readValue('hr_total_premium') ?? '';
|
||||
final bulkDownload = await tokenService.readValue('hr_is_ecard_bulk_download_for_employee') ?? '0';
|
||||
|
||||
Navigator.pushReplacement(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: 'hrPolicyDetails'),
|
||||
builder: (_) => hrPolicyDetails(
|
||||
ClientId: clientId,
|
||||
policyTypeId: policyTypeId,
|
||||
ClientPoliyId: clientPolicyId,
|
||||
clientBranchId: clientBranchId,
|
||||
Token: token,
|
||||
TokenType: tokenType,
|
||||
cardType: cardType,
|
||||
cardPolicyNo: policyNo,
|
||||
cardInsurer_name: insurer,
|
||||
cardPolicy_name: policyName,
|
||||
cardPolicy_ExpDate: expDate,
|
||||
total_premium: totalPremium,
|
||||
is_ecard_bulk_download_for_employee: int.tryParse(bulkDownload) ?? 0,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.arrow_back_ios,
|
||||
size: 18,
|
||||
color: Colors.black,
|
||||
),
|
||||
padding: EdgeInsets.zero,
|
||||
constraints: const BoxConstraints(),
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
Expanded(
|
||||
@ -619,7 +745,7 @@ class _postFileUploadState extends State<postFileUpload> {
|
||||
// mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"${widget.cardType} - ${widget.cardPolicyNo} " ??
|
||||
"${localCardType} - ${localCardPolicyNo} " ??
|
||||
'',
|
||||
style: GoogleFonts.poppins(
|
||||
color: Colors.black,
|
||||
@ -628,10 +754,13 @@ class _postFileUploadState extends State<postFileUpload> {
|
||||
),
|
||||
),
|
||||
Text(
|
||||
widget.TokenType == 'pre'
|
||||
? "${widget.cardPolicy_name} (${widget.cardPolicy_ExpDate})"
|
||||
: "${widget.cardInsurer_name} - ${widget.cardPolicy_name} (${widget.cardPolicy_ExpDate})",
|
||||
style: GoogleFonts.poppins(color: Colors.grey, fontSize: 12, fontWeight: FontWeight.w400),
|
||||
localTokenType == 'pre'
|
||||
? "${localCardPolicyName} (${localCardPolicyExpDate})"
|
||||
: "${localCardInsurerName} - ${localCardPolicyName} (${localCardPolicyExpDate})",
|
||||
style: GoogleFonts.poppins(
|
||||
color: Colors.grey,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400),
|
||||
),
|
||||
],
|
||||
),
|
||||
@ -650,11 +779,15 @@ class _postFileUploadState extends State<postFileUpload> {
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: const Color(0xFFE26728),
|
||||
elevation: 0,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10)),
|
||||
),
|
||||
child: Text(
|
||||
'Sample Excel',
|
||||
style: GoogleFonts.poppins(fontSize: 14, fontWeight: FontWeight.w700, color: Colors.white),
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: Colors.white),
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -662,7 +795,12 @@ class _postFileUploadState extends State<postFileUpload> {
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height:20),
|
||||
SizedBox(height: 20),
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
@ -676,7 +814,8 @@ class _postFileUploadState extends State<postFileUpload> {
|
||||
onChanged: (val) {
|
||||
setState(() {
|
||||
selectedKey = val;
|
||||
final selectedItem = getFileUploadMasterList.firstWhere((e) => e['key'] == val);
|
||||
final selectedItem = getFileUploadMasterList
|
||||
.firstWhere((e) => e['key'] == val);
|
||||
selectedValue = selectedItem['value'];
|
||||
currentApiValue = selectedItem['key'];
|
||||
showSampleButton = true;
|
||||
@ -725,7 +864,8 @@ class _postFileUploadState extends State<postFileUpload> {
|
||||
});
|
||||
_dragAndDropFile(droppedFile);
|
||||
},
|
||||
builder: (context, candidateData, rejectedData) {
|
||||
builder:
|
||||
(context, candidateData, rejectedData) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
if (selectedValue != null) {
|
||||
@ -738,11 +878,13 @@ class _postFileUploadState extends State<postFileUpload> {
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
height: 40 ,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
height: 40,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderRadius:
|
||||
BorderRadius.circular(8),
|
||||
border: Border.all(
|
||||
color: const Color(0xFF00A6A6),
|
||||
width: 1,
|
||||
@ -752,8 +894,10 @@ class _postFileUploadState extends State<postFileUpload> {
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
fileName ?? 'Upload Your Documents',
|
||||
overflow: TextOverflow.ellipsis,
|
||||
fileName ??
|
||||
'Upload Your Documents',
|
||||
overflow:
|
||||
TextOverflow.ellipsis,
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 13,
|
||||
color: fileName == null
|
||||
@ -769,8 +913,7 @@ class _postFileUploadState extends State<postFileUpload> {
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
);
|
||||
));
|
||||
},
|
||||
),
|
||||
],
|
||||
@ -779,25 +922,17 @@ class _postFileUploadState extends State<postFileUpload> {
|
||||
],
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
Column(
|
||||
children: [
|
||||
_buildFileUploadedGrid(),
|
||||
const SizedBox(height: 16),
|
||||
_buildPagination(context),
|
||||
],
|
||||
),
|
||||
)
|
||||
|
||||
],
|
||||
),
|
||||
])))
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
}
|
||||
|
||||
Widget buildUploadBox({
|
||||
@ -852,8 +987,6 @@ class _postFileUploadState extends State<postFileUpload> {
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Widget buildStyledDropdown({
|
||||
required String label,
|
||||
required String? value,
|
||||
@ -906,7 +1039,6 @@ class _postFileUploadState extends State<postFileUpload> {
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Widget _buildFileUploadedGrid() {
|
||||
if (filteredData.isEmpty) {
|
||||
return const SizedBox(
|
||||
@ -916,13 +1048,14 @@ class _postFileUploadState extends State<postFileUpload> {
|
||||
}
|
||||
|
||||
return GridView.builder(
|
||||
shrinkWrap: true,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
shrinkWrap: true, // ✅ IMPORTANT
|
||||
physics: const NeverScrollableScrollPhysics(), // ✅ Disable inner scroll
|
||||
padding: const EdgeInsets.all(16),
|
||||
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2, // 👈 2 cards per row
|
||||
crossAxisCount: 2,
|
||||
crossAxisSpacing: 16,
|
||||
mainAxisSpacing: 16,
|
||||
childAspectRatio: 10, // 👈 card height
|
||||
childAspectRatio: 10,
|
||||
),
|
||||
itemCount: _paginatedData.length,
|
||||
itemBuilder: (context, index) {
|
||||
@ -930,6 +1063,8 @@ class _postFileUploadState extends State<postFileUpload> {
|
||||
return _buildFileCard(item);
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
}
|
||||
|
||||
Widget _buildFileCard(Map<String, dynamic> item) {
|
||||
@ -1014,9 +1149,7 @@ class _postFileUploadState extends State<postFileUpload> {
|
||||
children: [
|
||||
/// 🔴 Error + Status
|
||||
Row(
|
||||
children: [
|
||||
|
||||
],
|
||||
children: [],
|
||||
),
|
||||
|
||||
const SizedBox(height: 8),
|
||||
@ -1028,36 +1161,39 @@ class _postFileUploadState extends State<postFileUpload> {
|
||||
onTap: () async {
|
||||
print(item);
|
||||
// return;
|
||||
final String? token = await tokenService.getCurrentToken();
|
||||
final String? empClientId = await tokenService.readValue('empClientId');
|
||||
final String? empBranchId = await tokenService.readValue('empClientBranchId');
|
||||
final String? token =
|
||||
await tokenService.getCurrentToken();
|
||||
final String? empClientId =
|
||||
await tokenService.readValue('empClientId');
|
||||
final String? empBranchId =
|
||||
await tokenService.readValue('empClientBranchId');
|
||||
|
||||
print(item);
|
||||
print(empClientId);
|
||||
print(widget.policyTypeId);
|
||||
print(localPolicyTypeId);
|
||||
print(empBranchId);
|
||||
print(token);
|
||||
print('post');
|
||||
print(widget.cardType);
|
||||
print(widget.cardPolicyNo);
|
||||
print(widget.cardInsurer_name);
|
||||
print(widget.cardPolicy_name);
|
||||
print(widget.cardPolicy_ExpDate);
|
||||
print(localCardType);
|
||||
print(localCardPolicyNo);
|
||||
print(localCardInsurerName);
|
||||
print(localCardPolicyName);
|
||||
print(localCardPolicyExpDate);
|
||||
print(item['id']);
|
||||
|
||||
// ✅ SAFETY CHECK
|
||||
if (token == null ||
|
||||
empClientId == null ||
|
||||
empBranchId == null) {
|
||||
debugPrint('❌ Missing required data for navigation ${token}');
|
||||
debugPrint(
|
||||
'❌ Missing required data for navigation ${token}');
|
||||
return;
|
||||
}
|
||||
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) =>
|
||||
excelErrorScreen(
|
||||
builder: (context) => excelErrorScreen(
|
||||
ClientId: empClientId,
|
||||
policy_no: item['policy_no'],
|
||||
action: item['file_action'],
|
||||
@ -1065,8 +1201,7 @@ class _postFileUploadState extends State<postFileUpload> {
|
||||
clientBranchId: empBranchId,
|
||||
Token: token,
|
||||
TokenType: 'post',
|
||||
id: item['id']
|
||||
),
|
||||
id: item['id']),
|
||||
),
|
||||
);
|
||||
},
|
||||
@ -1100,8 +1235,8 @@ class _postFileUploadState extends State<postFileUpload> {
|
||||
),
|
||||
],
|
||||
),
|
||||
/// ⬇ Download
|
||||
|
||||
/// ⬇ Download
|
||||
],
|
||||
),
|
||||
],
|
||||
@ -1109,7 +1244,6 @@ class _postFileUploadState extends State<postFileUpload> {
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Widget _buildStatusChip(String status) {
|
||||
final s = status.toLowerCase();
|
||||
|
||||
@ -1142,7 +1276,6 @@ class _postFileUploadState extends State<postFileUpload> {
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
static final _dataBold = GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400,
|
||||
@ -1161,14 +1294,14 @@ class _postFileUploadState extends State<postFileUpload> {
|
||||
);
|
||||
|
||||
Widget _buildPagination(BuildContext context) {
|
||||
|
||||
final totalItems = filteredData.length;
|
||||
final int startEntry = totalItems == 0 ? 0 : ((_currentPage - 1) * _rowsPerPage) + 1;
|
||||
final int startEntry =
|
||||
totalItems == 0 ? 0 : ((_currentPage - 1) * _rowsPerPage) + 1;
|
||||
int endEntry = _currentPage * _rowsPerPage;
|
||||
if (endEntry > totalItems) endEntry = totalItems;
|
||||
|
||||
final totalPages = (filteredData.length / _rowsPerPage).ceil();
|
||||
const visiblePageCount = 5;
|
||||
const visiblePageCount = 6;
|
||||
|
||||
List<int> getVisiblePages() {
|
||||
if (totalPages <= visiblePageCount) {
|
||||
@ -1177,7 +1310,8 @@ class _postFileUploadState extends State<postFileUpload> {
|
||||
|
||||
if (_currentPage <= 3) {
|
||||
return [1, 2, 3, 4, 5];
|
||||
} if (_currentPage >= totalPages - 2) {
|
||||
}
|
||||
if (_currentPage >= totalPages - 2) {
|
||||
return [
|
||||
totalPages - 4,
|
||||
totalPages - 3,
|
||||
@ -1193,7 +1327,6 @@ class _postFileUploadState extends State<postFileUpload> {
|
||||
_currentPage + 1,
|
||||
_currentPage + 2,
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
List<int> visiblePages = getVisiblePages();
|
||||
@ -1208,7 +1341,7 @@ class _postFileUploadState extends State<postFileUpload> {
|
||||
// Dropdown for rows per page
|
||||
DropdownButton<int>(
|
||||
value: _rowsPerPage,
|
||||
items: [5, 10, 15, 20, 50].map((int value) {
|
||||
items: [6, 10, 15, 20, 50].map((int value) {
|
||||
return DropdownMenuItem<int>(
|
||||
value: value,
|
||||
child: Text(' $value ',
|
||||
|
||||
@ -11,13 +11,14 @@ import 'package:nhancepolicy/service/token_storage_service.dart';
|
||||
import 'package:universal_html/html.dart' as html;
|
||||
import 'package:flutter/foundation.dart' show kIsWeb;
|
||||
// import 'package:excel/excel.dart';
|
||||
import 'package:excel/excel.dart' hide Border,TextSpan;
|
||||
import 'package:excel/excel.dart' hide Border, TextSpan;
|
||||
import 'dart:io';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:csv/csv.dart';
|
||||
import '../config/environment.dart';
|
||||
import '../customAppBar/base_layout.dart';
|
||||
import 'excelVerification.dart';
|
||||
import 'hrPolicyDetails.dart';
|
||||
|
||||
class preFileUpload extends StatefulWidget {
|
||||
final String ClientId;
|
||||
@ -32,8 +33,8 @@ class preFileUpload extends StatefulWidget {
|
||||
final String cardPolicy_name;
|
||||
final String cardPolicy_ExpDate;
|
||||
final String total_premium;
|
||||
const preFileUpload(
|
||||
{Key? key,
|
||||
const preFileUpload({
|
||||
Key? key,
|
||||
required this.ClientId,
|
||||
required this.policyTypeId,
|
||||
required this.ClientPoliyId,
|
||||
@ -46,9 +47,7 @@ class preFileUpload extends StatefulWidget {
|
||||
required this.cardPolicy_name,
|
||||
required this.cardPolicy_ExpDate,
|
||||
required this.total_premium,
|
||||
|
||||
})
|
||||
: super(key: key);
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<preFileUpload> createState() => _excelVerifyState();
|
||||
@ -56,6 +55,20 @@ class preFileUpload extends StatefulWidget {
|
||||
|
||||
class _excelVerifyState extends State<preFileUpload> {
|
||||
final tokenService = TokenStorageService();
|
||||
|
||||
String localClientId = '';
|
||||
String localPolicyTypeId = '';
|
||||
String localClientPolicyId = '';
|
||||
String localClientBranchId = '';
|
||||
String localToken = '';
|
||||
String localTokenType = '';
|
||||
String localCardType = '';
|
||||
String localCardPolicyNo = '';
|
||||
String localCardInsurerName = '';
|
||||
String localCardPolicyName = '';
|
||||
String localCardPolicyExpDate = '';
|
||||
String localTotalPremium = '';
|
||||
|
||||
Uint8List? fileBytes;
|
||||
Uint8List? fileBytes2;
|
||||
late String _token;
|
||||
@ -92,7 +105,7 @@ class _excelVerifyState extends State<preFileUpload> {
|
||||
final List<String> _allowedExtensions = ['xlsx', 'xls'];
|
||||
|
||||
int _currentPage = 1;
|
||||
int _rowsPerPage = 5;
|
||||
int _rowsPerPage = 6;
|
||||
|
||||
List<dynamic> get _paginatedData {
|
||||
final startIndex = (_currentPage - 1) * _rowsPerPage;
|
||||
@ -105,8 +118,10 @@ class _excelVerifyState extends State<preFileUpload> {
|
||||
void initState() {
|
||||
super.initState();
|
||||
apiService = ApiService(context);
|
||||
getFileListDetails();
|
||||
restoreUploadData().then((_) {
|
||||
_loadToken();
|
||||
getFileListDetails();
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
@ -116,21 +131,85 @@ class _excelVerifyState extends State<preFileUpload> {
|
||||
}
|
||||
|
||||
Future<void> _loadToken() async {
|
||||
final token = widget.Token;
|
||||
final token = localToken.isNotEmpty
|
||||
? localToken
|
||||
: await tokenService.readValue('upload_Token');
|
||||
|
||||
if (token != null && token.isNotEmpty) {
|
||||
setState(() {
|
||||
_token = token;
|
||||
});
|
||||
Map<String, dynamic>? decodedToken = Jwt.parseJwt(token);
|
||||
print('decodedToken $decodedToken');
|
||||
} else {
|
||||
// Token is empty or null, handle accordingly (e.g., navigate to login screen)
|
||||
// For now, let's navigate to the login screen
|
||||
ToastHelper.showErrorToast(context, 'Session Out');
|
||||
Navigator.pushReplacementNamed(context, 'hrLogin');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> restoreUploadData() async {
|
||||
localClientId = widget.ClientId.isNotEmpty
|
||||
? widget.ClientId
|
||||
: await tokenService.readValue('upload_ClientId') ?? '';
|
||||
|
||||
localPolicyTypeId = widget.policyTypeId.isNotEmpty
|
||||
? widget.policyTypeId
|
||||
: await tokenService.readValue('upload_policyTypeId') ?? '';
|
||||
|
||||
localClientPolicyId = widget.ClientPoliyId.isNotEmpty
|
||||
? widget.ClientPoliyId
|
||||
: await tokenService.readValue('upload_ClientPoliyId') ?? '';
|
||||
|
||||
localClientBranchId = widget.clientBranchId.isNotEmpty
|
||||
? widget.clientBranchId
|
||||
: await tokenService.readValue('upload_clientBranchId') ?? '';
|
||||
|
||||
localToken = widget.Token.isNotEmpty
|
||||
? widget.Token
|
||||
: await tokenService.readValue('upload_Token') ?? '';
|
||||
|
||||
localTokenType = widget.TokenType.isNotEmpty
|
||||
? widget.TokenType
|
||||
: await tokenService.readValue('upload_TokenType') ?? '';
|
||||
|
||||
localCardType = widget.cardType.isNotEmpty
|
||||
? widget.cardType
|
||||
: await tokenService.readValue('upload_cardType') ?? '';
|
||||
|
||||
localCardPolicyNo = widget.cardPolicyNo.isNotEmpty
|
||||
? widget.cardPolicyNo
|
||||
: await tokenService.readValue('upload_cardPolicyNo') ?? '';
|
||||
|
||||
localCardInsurerName = widget.cardInsurer_name.isNotEmpty
|
||||
? widget.cardInsurer_name
|
||||
: await tokenService.readValue('upload_cardInsurer_name') ?? '';
|
||||
|
||||
localCardPolicyName = widget.cardPolicy_name.isNotEmpty
|
||||
? widget.cardPolicy_name
|
||||
: await tokenService.readValue('upload_cardPolicy_name') ?? '';
|
||||
|
||||
localCardPolicyExpDate = widget.cardPolicy_ExpDate.isNotEmpty
|
||||
? widget.cardPolicy_ExpDate
|
||||
: await tokenService.readValue('upload_cardPolicy_ExpDate') ?? '';
|
||||
|
||||
localTotalPremium = widget.total_premium.isNotEmpty
|
||||
? widget.total_premium
|
||||
: await tokenService.readValue('upload_total_premium') ?? '';
|
||||
}
|
||||
|
||||
Future<void> clearUploadStorage() async {
|
||||
await tokenService.removeValue('upload_ClientId');
|
||||
await tokenService.removeValue('upload_policyTypeId');
|
||||
await tokenService.removeValue('upload_ClientPoliyId');
|
||||
await tokenService.removeValue('upload_clientBranchId');
|
||||
await tokenService.removeValue('upload_Token');
|
||||
await tokenService.removeValue('upload_TokenType');
|
||||
await tokenService.removeValue('upload_cardType');
|
||||
await tokenService.removeValue('upload_cardPolicyNo');
|
||||
await tokenService.removeValue('upload_cardInsurer_name');
|
||||
await tokenService.removeValue('upload_cardPolicy_name');
|
||||
await tokenService.removeValue('upload_cardPolicy_ExpDate');
|
||||
await tokenService.removeValue('upload_total_premium');
|
||||
}
|
||||
|
||||
// Future<void> getPolicyDetails() async {
|
||||
// setState(() {
|
||||
// clientPolicyId = argumentsData['client_policy_id'];
|
||||
@ -210,15 +289,14 @@ class _excelVerifyState extends State<preFileUpload> {
|
||||
}
|
||||
|
||||
bool _validateDatesBeforeUpload() {
|
||||
if (openDateController.text.isEmpty ||
|
||||
closeDateController.text.isEmpty) {
|
||||
ToastHelper.showErrorToast2(context,'','Please select both Enrolment Open Date and Close Date');
|
||||
if (openDateController.text.isEmpty || closeDateController.text.isEmpty) {
|
||||
ToastHelper.showErrorToast2(
|
||||
context, '', 'Please select both Enrolment Open Date and Close Date');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void _processExcelData(Uint8List fileBytes, fileName) {
|
||||
List<List<Data>> dataArray;
|
||||
if (fileName.endsWith('.xlsx')) {
|
||||
@ -461,7 +539,6 @@ class _excelVerifyState extends State<preFileUpload> {
|
||||
}
|
||||
|
||||
Future<void> sendExcelFIleTOAPI(Uint8List fileBytes, fileName) async {
|
||||
|
||||
// Future.delayed(Duration(seconds: 3), () {
|
||||
// setState(() {
|
||||
isLoading = true;
|
||||
@ -486,7 +563,8 @@ class _excelVerifyState extends State<preFileUpload> {
|
||||
print('else');
|
||||
// Attach the file to the request
|
||||
// Set authorization token in headers
|
||||
request.headers['APP-SIGNATURE'] = 'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y';
|
||||
request.headers['APP-SIGNATURE'] =
|
||||
'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y';
|
||||
request.headers['Authorization'] = 'Bearer $_token';
|
||||
// request.files.add(http.MultipartFile.fromBytes('file', fileBytes,
|
||||
// filename: fileName));
|
||||
@ -497,10 +575,10 @@ class _excelVerifyState extends State<preFileUpload> {
|
||||
filename: fileName ?? 'default_filename.xlsx',
|
||||
));
|
||||
|
||||
request.fields['client_id'] = widget.ClientId;
|
||||
request.fields['client_id'] = localClientId;
|
||||
// if (policyFirstPart == 'GPA') {
|
||||
request.fields['policy_id'] = widget.ClientPoliyId;
|
||||
request.fields['client_branch_id'] = widget.clientBranchId;
|
||||
request.fields['policy_id'] = localClientPolicyId;
|
||||
request.fields['client_branch_id'] = localClientBranchId;
|
||||
request.fields['enrollment_open_date'] = openDateController.text;
|
||||
request.fields['enrollment_close_date'] = closeDateController.text;
|
||||
request.fields['created_by'] = enrollmentHrId!;
|
||||
@ -527,18 +605,21 @@ class _excelVerifyState extends State<preFileUpload> {
|
||||
isSuccess = true;
|
||||
successContent = data['message'];
|
||||
excelValidationStaus = 0;
|
||||
});
|
||||
resetErrorCount();
|
||||
handleImportAction();
|
||||
getFileListDetails();
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
isLoading = false;
|
||||
});
|
||||
handleImportAction();
|
||||
ToastHelper.showErrorToast2(context,"",data['message']);
|
||||
});
|
||||
|
||||
ToastHelper.showErrorToast2(context, "", data['message']);
|
||||
setState(() {
|
||||
resetErrorCount();
|
||||
getFileListDetails();
|
||||
});
|
||||
// ToastHelper.showErrorToast(context, data['message']);
|
||||
print('Table');
|
||||
}
|
||||
@ -570,7 +651,7 @@ class _excelVerifyState extends State<preFileUpload> {
|
||||
print('10');
|
||||
|
||||
response = await apiService.getImportLogHrActivity(
|
||||
postId!, preId!, widget.Token, activity);
|
||||
postId!, preId!, localToken, activity);
|
||||
|
||||
if (response['status'] == 'success') {
|
||||
print('Request success');
|
||||
@ -585,13 +666,15 @@ class _excelVerifyState extends State<preFileUpload> {
|
||||
}
|
||||
|
||||
Future<void> getFileListDetails() async {
|
||||
final enrollmentPrimaryId = await tokenService.readValue('enrollmentEmpPrimaryId');
|
||||
final enrollmentClientId = await tokenService.readValue('enrollmentClient_id');
|
||||
final enrollmentPrimaryId =
|
||||
await tokenService.readValue('enrollmentEmpPrimaryId');
|
||||
final enrollmentClientId =
|
||||
await tokenService.readValue('enrollmentClient_id');
|
||||
|
||||
print('9');
|
||||
try {
|
||||
final response = await apiService.getFileListToApi(
|
||||
enrollmentPrimaryId, widget.cardPolicyNo, enrollmentClientId,widget.Token,widget.TokenType);
|
||||
final response = await apiService.getFileListToApi(enrollmentPrimaryId,
|
||||
localCardPolicyNo, enrollmentClientId, localToken, localTokenType);
|
||||
|
||||
if (response['status'] == true) {
|
||||
print('getThrFileList');
|
||||
@ -640,7 +723,7 @@ class _excelVerifyState extends State<preFileUpload> {
|
||||
|
||||
// Future<void> downloadSampleFile() async {
|
||||
//
|
||||
// final response = await apiService.getSampleFileDownload(widget.Token);
|
||||
// final response = await apiService.getSampleFileDownload(localToken);
|
||||
// print('check 1');
|
||||
// if (response['status'] == 'success') {
|
||||
// final url = response['data'];
|
||||
@ -669,15 +752,16 @@ class _excelVerifyState extends State<preFileUpload> {
|
||||
}
|
||||
|
||||
Future<void> getHrFileDownload(id, file_name) async {
|
||||
// final http.Response response = await apiService.getHrFileDownloadToApi(id, widget.Token);
|
||||
// final http.Response response = await apiService.getHrFileDownloadToApi(id, localToken);
|
||||
final apiurl = Environment.apiUrl;
|
||||
final String url = '$apiurl/hrFileDownload?id=$id';
|
||||
final token = widget.Token;
|
||||
final token = localToken;
|
||||
|
||||
final response = await http.get(
|
||||
Uri.parse(url),
|
||||
headers: {
|
||||
'APP-SIGNATURE': 'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y',
|
||||
'APP-SIGNATURE':
|
||||
'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y',
|
||||
'Authorization': 'Bearer $token',
|
||||
'Content-Type': 'application/json',
|
||||
// 'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||
@ -717,7 +801,8 @@ class _excelVerifyState extends State<preFileUpload> {
|
||||
}
|
||||
|
||||
Widget _buildContent(BuildContext context) {
|
||||
return isLoading ? Container(
|
||||
return isLoading
|
||||
? Container(
|
||||
color: Colors.transparent, // Semi-transparent background
|
||||
child: Center(
|
||||
child: // Your GIF loader widget
|
||||
@ -726,7 +811,8 @@ class _excelVerifyState extends State<preFileUpload> {
|
||||
width: 60,
|
||||
'assets/nhance-loader.gif'), // Adjust path to your GIF loader
|
||||
),
|
||||
) : Container(
|
||||
)
|
||||
: Container(
|
||||
// padding: const EdgeInsets.all(20),
|
||||
// color: Color(0xFFEFF3F6),
|
||||
child: Column(
|
||||
@ -735,14 +821,53 @@ class _excelVerifyState extends State<preFileUpload> {
|
||||
children: [
|
||||
IconButton(
|
||||
tooltip: 'Previous Page',
|
||||
onPressed: () => {Navigator.pop(context)},
|
||||
onPressed: () async {
|
||||
if (Navigator.canPop(context)) {
|
||||
Navigator.pop(context);
|
||||
return;
|
||||
}
|
||||
|
||||
final clientId = await tokenService.readValue('hr_ClientId') ?? '';
|
||||
final policyTypeId = await tokenService.readValue('hr_policyTypeId') ?? '';
|
||||
final clientPolicyId = await tokenService.readValue('hr_ClientPoliyId') ?? '';
|
||||
final clientBranchId = await tokenService.readValue('hr_clientBranchId') ?? '';
|
||||
final token = await tokenService.readValue('hr_Token') ?? '';
|
||||
final tokenType = await tokenService.readValue('hr_TokenType') ?? '';
|
||||
final cardType = await tokenService.readValue('hr_cardType') ?? '';
|
||||
final policyNo = await tokenService.readValue('hr_cardPolicyNo') ?? '';
|
||||
final insurer = await tokenService.readValue('hr_cardInsurer_name') ?? '';
|
||||
final policyName = await tokenService.readValue('hr_cardPolicy_name') ?? '';
|
||||
final expDate = await tokenService.readValue('hr_cardPolicy_ExpDate') ?? '';
|
||||
final totalPremium = await tokenService.readValue('hr_total_premium') ?? '';
|
||||
final bulkDownload = await tokenService.readValue('hr_is_ecard_bulk_download_for_employee') ?? '0';
|
||||
|
||||
Navigator.pushReplacement(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: 'hrPolicyDetails'),
|
||||
builder: (_) => hrPolicyDetails(
|
||||
ClientId: clientId,
|
||||
policyTypeId: policyTypeId,
|
||||
ClientPoliyId: clientPolicyId,
|
||||
clientBranchId: clientBranchId,
|
||||
Token: token,
|
||||
TokenType: tokenType,
|
||||
cardType: cardType,
|
||||
cardPolicyNo: policyNo,
|
||||
cardInsurer_name: insurer,
|
||||
cardPolicy_name: policyName,
|
||||
cardPolicy_ExpDate: expDate,
|
||||
total_premium: totalPremium,
|
||||
is_ecard_bulk_download_for_employee: int.tryParse(bulkDownload) ?? 0,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.arrow_back_ios,
|
||||
size: 18,
|
||||
color: Colors.black,
|
||||
),
|
||||
padding: EdgeInsets.zero,
|
||||
constraints: const BoxConstraints(),
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
Container(
|
||||
@ -752,8 +877,7 @@ class _excelVerifyState extends State<preFileUpload> {
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"${widget.cardType} - ${widget.cardPolicyNo} " ??
|
||||
'',
|
||||
"${localCardType} - ${localCardPolicyNo} " ?? '',
|
||||
style: GoogleFonts.poppins(
|
||||
color: Colors.black,
|
||||
fontSize: 14,
|
||||
@ -761,9 +885,9 @@ class _excelVerifyState extends State<preFileUpload> {
|
||||
),
|
||||
),
|
||||
Text(
|
||||
widget.TokenType == 'pre'
|
||||
? "${widget.cardPolicy_name} (${widget.cardPolicy_ExpDate})"
|
||||
: "${widget.cardInsurer_name} - ${widget.cardPolicy_name} (${widget.cardPolicy_ExpDate})",
|
||||
localTokenType == 'pre'
|
||||
? "${localCardPolicyName} (${localCardPolicyExpDate})"
|
||||
: "${localCardInsurerName} - ${localCardPolicyName} (${localCardPolicyExpDate})",
|
||||
style: GoogleFonts.poppins(
|
||||
color: Colors.grey,
|
||||
fontSize: 12,
|
||||
@ -776,6 +900,11 @@ class _excelVerifyState extends State<preFileUpload> {
|
||||
],
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
@ -801,7 +930,6 @@ class _excelVerifyState extends State<preFileUpload> {
|
||||
|
||||
openDateController.text = formatted;
|
||||
}
|
||||
|
||||
},
|
||||
),
|
||||
),
|
||||
@ -812,9 +940,9 @@ class _excelVerifyState extends State<preFileUpload> {
|
||||
label: 'Enrolment Close Date',
|
||||
controller: closeDateController,
|
||||
onTap: () async {
|
||||
|
||||
if (openDateController.text.isEmpty) {
|
||||
ToastHelper.showErrorToast(context, 'Please select Enrolment Open Date first');
|
||||
ToastHelper.showErrorToast(context,
|
||||
'Please select Enrolment Open Date first');
|
||||
return;
|
||||
}
|
||||
|
||||
@ -823,7 +951,8 @@ class _excelVerifyState extends State<preFileUpload> {
|
||||
|
||||
final picked = await showDatePicker(
|
||||
context: context,
|
||||
firstDate: openDate, // ✅ Cannot select before open date
|
||||
firstDate:
|
||||
openDate, // ✅ Cannot select before open date
|
||||
lastDate: DateTime(2100),
|
||||
initialDate: openDate,
|
||||
);
|
||||
@ -852,8 +981,7 @@ class _excelVerifyState extends State<preFileUpload> {
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Container(
|
||||
@ -871,7 +999,8 @@ class _excelVerifyState extends State<preFileUpload> {
|
||||
onTap: () {
|
||||
if (!_validateDatesBeforeUpload()) return;
|
||||
if (fileName == null) {
|
||||
_uploadFile('Policy Name'); // ✅ same function
|
||||
_uploadFile(
|
||||
'Policy Name'); // ✅ same function
|
||||
}
|
||||
},
|
||||
child: DragTarget<html.File>(
|
||||
@ -891,64 +1020,96 @@ class _excelVerifyState extends State<preFileUpload> {
|
||||
return Container(
|
||||
alignment: Alignment.center,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.center,
|
||||
children: [
|
||||
fileName != null
|
||||
? Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment
|
||||
.center,
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 40,
|
||||
height: 40 ,
|
||||
height: 40,
|
||||
child: Tooltip(
|
||||
message: 'Upload', // The text that appears on hover
|
||||
message:
|
||||
'Upload', // The text that appears on hover
|
||||
child: ElevatedButton(
|
||||
onPressed: () => null,
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: const Color(0xFFD4F1F2),
|
||||
onPressed: () =>
|
||||
null,
|
||||
style:
|
||||
ElevatedButton
|
||||
.styleFrom(
|
||||
backgroundColor:
|
||||
const Color(
|
||||
0xFFD4F1F2),
|
||||
elevation: 0,
|
||||
padding: EdgeInsets.zero, // ✅ IMPORTANT
|
||||
alignment: Alignment.center, // ✅ FORCE CENTER
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
side: const BorderSide( // ✅ BORDER ADDED
|
||||
color: Color(0xFF00999E),
|
||||
padding: EdgeInsets
|
||||
.zero, // ✅ IMPORTANT
|
||||
alignment: Alignment
|
||||
.center, // ✅ FORCE CENTER
|
||||
shape:
|
||||
RoundedRectangleBorder(
|
||||
borderRadius:
|
||||
BorderRadius
|
||||
.circular(
|
||||
10),
|
||||
side:
|
||||
const BorderSide(
|
||||
// ✅ BORDER ADDED
|
||||
color: Color(
|
||||
0xFF00999E),
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
),
|
||||
child: Icon(
|
||||
Icons.file_upload_outlined,
|
||||
Icons
|
||||
.file_upload_outlined,
|
||||
size: 22,
|
||||
color: Color(0xFF00999E),
|
||||
)
|
||||
color: Color(
|
||||
0xFF00999E),
|
||||
)),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
const SizedBox(
|
||||
height: 15),
|
||||
Text(
|
||||
fileName!,
|
||||
style: const TextStyle(fontSize: 16),
|
||||
style: const TextStyle(
|
||||
fontSize: 16),
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
const SizedBox(
|
||||
height: 15),
|
||||
MouseRegion(
|
||||
cursor: SystemMouseCursors.click,
|
||||
cursor:
|
||||
SystemMouseCursors
|
||||
.click,
|
||||
child: GestureDetector(
|
||||
onTap: resetErrorCount,
|
||||
onTap:
|
||||
resetErrorCount,
|
||||
child: const Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment
|
||||
.center,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.delete_forever,
|
||||
Icons
|
||||
.delete_forever,
|
||||
size: 20,
|
||||
color: Colors.red,
|
||||
color:
|
||||
Colors.red,
|
||||
),
|
||||
SizedBox(width: 4),
|
||||
SizedBox(
|
||||
width: 4),
|
||||
Text(
|
||||
'Remove',
|
||||
style: TextStyle(
|
||||
style:
|
||||
TextStyle(
|
||||
fontSize: 13,
|
||||
color: Color(0xFF727272),
|
||||
color: Color(
|
||||
0xFF727272),
|
||||
),
|
||||
),
|
||||
],
|
||||
@ -961,53 +1122,78 @@ class _excelVerifyState extends State<preFileUpload> {
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 40,
|
||||
height: 40 ,
|
||||
height: 40,
|
||||
child: Tooltip(
|
||||
message: 'Upload', // The text that appears on hover
|
||||
message:
|
||||
'Upload', // The text that appears on hover
|
||||
child: ElevatedButton(
|
||||
onPressed: () {
|
||||
if (!_validateDatesBeforeUpload()) return;
|
||||
if (fileName == null) {
|
||||
_uploadFile('Policy Name');
|
||||
if (!_validateDatesBeforeUpload())
|
||||
return;
|
||||
if (fileName ==
|
||||
null) {
|
||||
_uploadFile(
|
||||
'Policy Name');
|
||||
}
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: const Color(0xFFD4F1F2),
|
||||
style:
|
||||
ElevatedButton
|
||||
.styleFrom(
|
||||
backgroundColor:
|
||||
const Color(
|
||||
0xFFD4F1F2),
|
||||
elevation: 0,
|
||||
padding: EdgeInsets.zero, // ✅ IMPORTANT
|
||||
alignment: Alignment.center, // ✅ FORCE CENTER
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
side: const BorderSide( // ✅ BORDER ADDED
|
||||
color: Color(0xFF00999E),
|
||||
padding: EdgeInsets
|
||||
.zero, // ✅ IMPORTANT
|
||||
alignment: Alignment
|
||||
.center, // ✅ FORCE CENTER
|
||||
shape:
|
||||
RoundedRectangleBorder(
|
||||
borderRadius:
|
||||
BorderRadius
|
||||
.circular(
|
||||
10),
|
||||
side:
|
||||
const BorderSide(
|
||||
// ✅ BORDER ADDED
|
||||
color: Color(
|
||||
0xFF00999E),
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
),
|
||||
child: Icon(
|
||||
Icons.file_upload_outlined,
|
||||
Icons
|
||||
.file_upload_outlined,
|
||||
size: 22,
|
||||
color: Color(0xFF00999E),
|
||||
)
|
||||
),
|
||||
color: Color(
|
||||
0xFF00999E),
|
||||
)),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
Text('Upload Your Documents',
|
||||
style: GoogleFonts.poppins(
|
||||
Text(
|
||||
'Upload Your Documents',
|
||||
style:
|
||||
GoogleFonts.poppins(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Color(0xFF000000)
|
||||
),
|
||||
fontWeight:
|
||||
FontWeight
|
||||
.w600,
|
||||
color: Color(
|
||||
0xFF000000)),
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
Text(
|
||||
'(Supported Format: XLSX)',
|
||||
style: GoogleFonts.poppins(
|
||||
style:
|
||||
GoogleFonts.poppins(
|
||||
fontSize: 10,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Color(0xFF707070)
|
||||
),
|
||||
fontWeight:
|
||||
FontWeight
|
||||
.w400,
|
||||
color: Color(
|
||||
0xFF707070)),
|
||||
),
|
||||
],
|
||||
),
|
||||
@ -1023,28 +1209,21 @@ class _excelVerifyState extends State<preFileUpload> {
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment
|
||||
.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Please download the sample file to review the format.',
|
||||
textAlign:
|
||||
TextAlign.center,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight:
|
||||
FontWeight.w400,
|
||||
color: Color(0xFF707070)
|
||||
)),
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Color(0xFF707070))),
|
||||
MouseRegion(
|
||||
cursor: SystemMouseCursors
|
||||
.click,
|
||||
cursor: SystemMouseCursors.click,
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
downloadSampleFile();
|
||||
@ -1063,20 +1242,17 @@ class _excelVerifyState extends State<preFileUpload> {
|
||||
],
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
Column(
|
||||
children: [
|
||||
_buildFileUploadedGrid(),
|
||||
const SizedBox(height: 16),
|
||||
_buildPagination(context),
|
||||
],
|
||||
),
|
||||
)
|
||||
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
@ -1084,20 +1260,18 @@ class _excelVerifyState extends State<preFileUpload> {
|
||||
|
||||
Widget _buildFileUploadedGrid() {
|
||||
if (filteredData.isEmpty) {
|
||||
return const SizedBox(
|
||||
height: 120,
|
||||
child: Center(child: Text('No uploaded files')),
|
||||
);
|
||||
return const Center(child: Text('No uploaded files'));
|
||||
}
|
||||
|
||||
return GridView.builder(
|
||||
shrinkWrap: true,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
shrinkWrap: true, // ✅ IMPORTANT
|
||||
physics: const NeverScrollableScrollPhysics(), // ✅ Disable inner scroll
|
||||
padding: const EdgeInsets.all(16),
|
||||
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2, // 👈 2 cards per row
|
||||
crossAxisCount: 2,
|
||||
crossAxisSpacing: 16,
|
||||
mainAxisSpacing: 16,
|
||||
childAspectRatio: 10, // 👈 card height
|
||||
childAspectRatio: 10,
|
||||
),
|
||||
itemCount: _paginatedData.length,
|
||||
itemBuilder: (context, index) {
|
||||
@ -1107,6 +1281,31 @@ class _excelVerifyState extends State<preFileUpload> {
|
||||
);
|
||||
}
|
||||
|
||||
// Widget _buildFileUploadedGrid() {
|
||||
// if (filteredData.isEmpty) {
|
||||
// return const SizedBox(
|
||||
// height: 120,
|
||||
// child: Center(child: Text('No uploaded files')),
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// return GridView.builder(
|
||||
// shrinkWrap: true,
|
||||
// physics: const NeverScrollableScrollPhysics(),
|
||||
// gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
// crossAxisCount: 2, // 👈 2 cards per row
|
||||
// crossAxisSpacing: 16,
|
||||
// mainAxisSpacing: 16,
|
||||
// childAspectRatio: 10, // 👈 card height
|
||||
// ),
|
||||
// itemCount: _paginatedData.length,
|
||||
// itemBuilder: (context, index) {
|
||||
// final item = _paginatedData[index];
|
||||
// return _buildFileCard(item);
|
||||
// },
|
||||
// );
|
||||
// }
|
||||
|
||||
Widget _buildFileCard(Map<String, dynamic> item) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 12),
|
||||
@ -1189,9 +1388,7 @@ class _excelVerifyState extends State<preFileUpload> {
|
||||
children: [
|
||||
/// 🔴 Error + Status
|
||||
Row(
|
||||
children: [
|
||||
|
||||
],
|
||||
children: [],
|
||||
),
|
||||
|
||||
const SizedBox(height: 8),
|
||||
@ -1201,40 +1398,44 @@ class _excelVerifyState extends State<preFileUpload> {
|
||||
if (item['file_error_status'] == '1')
|
||||
Tooltip(
|
||||
message: 'Info', // Added tooltip name
|
||||
child:InkWell(
|
||||
child: InkWell(
|
||||
onTap: () async {
|
||||
print(item);
|
||||
// return;
|
||||
final String? token = await tokenService.getCurrentToken();
|
||||
final String? enrollmentClient_id = await tokenService.readValue('enrollmentClient_id');
|
||||
final String? enrollmentEmpClientBranchId = await tokenService.readValue('enrollmentEmpClientBranchId');
|
||||
final String? token =
|
||||
await tokenService.getCurrentToken();
|
||||
final String? enrollmentClient_id = await tokenService
|
||||
.readValue('enrollmentClient_id');
|
||||
final String? enrollmentEmpClientBranchId =
|
||||
await tokenService
|
||||
.readValue('enrollmentEmpClientBranchId');
|
||||
|
||||
print(item);
|
||||
print(enrollmentClient_id);
|
||||
print(widget.policyTypeId);
|
||||
print(localPolicyTypeId);
|
||||
print(enrollmentEmpClientBranchId);
|
||||
print(token);
|
||||
print('post');
|
||||
print(widget.cardType);
|
||||
print(widget.cardPolicyNo);
|
||||
print(widget.cardInsurer_name);
|
||||
print(widget.cardPolicy_name);
|
||||
print(widget.cardPolicy_ExpDate);
|
||||
print(localCardType);
|
||||
print(localCardPolicyNo);
|
||||
print(localCardInsurerName);
|
||||
print(localCardPolicyName);
|
||||
print(localCardPolicyExpDate);
|
||||
print(item['id']);
|
||||
|
||||
// ✅ SAFETY CHECK
|
||||
if (token == null ||
|
||||
enrollmentClient_id == null ||
|
||||
enrollmentEmpClientBranchId == null) {
|
||||
debugPrint('❌ Missing required data for navigation ${token}');
|
||||
debugPrint(
|
||||
'❌ Missing required data for navigation ${token}');
|
||||
return;
|
||||
}
|
||||
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) =>
|
||||
excelErrorScreen(
|
||||
builder: (context) => excelErrorScreen(
|
||||
ClientId: enrollmentClient_id,
|
||||
policy_no: item['policy_no'],
|
||||
action: item['file_action'],
|
||||
@ -1242,8 +1443,7 @@ class _excelVerifyState extends State<preFileUpload> {
|
||||
clientBranchId: enrollmentEmpClientBranchId,
|
||||
Token: token,
|
||||
TokenType: 'pre',
|
||||
id: item['id']
|
||||
),
|
||||
id: item['id']),
|
||||
),
|
||||
);
|
||||
},
|
||||
@ -1259,7 +1459,7 @@ class _excelVerifyState extends State<preFileUpload> {
|
||||
SizedBox(width: 10),
|
||||
Tooltip(
|
||||
message: 'Download', // Added tooltip name
|
||||
child:InkWell(
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
getHrFileDownload(item['id'], item['file_name']);
|
||||
},
|
||||
@ -1281,8 +1481,8 @@ class _excelVerifyState extends State<preFileUpload> {
|
||||
),
|
||||
],
|
||||
),
|
||||
/// ⬇ Download
|
||||
|
||||
/// ⬇ Download
|
||||
],
|
||||
),
|
||||
],
|
||||
@ -1325,12 +1525,13 @@ class _excelVerifyState extends State<preFileUpload> {
|
||||
Widget _buildPagination(BuildContext context) {
|
||||
// 1. Calculate the range of entries being shown
|
||||
final totalItems = filteredData.length;
|
||||
final int startEntry = totalItems == 0 ? 0 : ((_currentPage - 1) * _rowsPerPage) + 1;
|
||||
final int startEntry =
|
||||
totalItems == 0 ? 0 : ((_currentPage - 1) * _rowsPerPage) + 1;
|
||||
int endEntry = _currentPage * _rowsPerPage;
|
||||
if (endEntry > totalItems) endEntry = totalItems;
|
||||
|
||||
final totalPages = (filteredData.length / _rowsPerPage).ceil();
|
||||
const visiblePageCount = 5;
|
||||
const visiblePageCount = 6;
|
||||
|
||||
List<int> getVisiblePages() {
|
||||
if (totalPages <= visiblePageCount) {
|
||||
@ -1356,7 +1557,6 @@ class _excelVerifyState extends State<preFileUpload> {
|
||||
_currentPage + 1,
|
||||
_currentPage + 2,
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
List<int> visiblePages = getVisiblePages();
|
||||
@ -1365,7 +1565,8 @@ class _excelVerifyState extends State<preFileUpload> {
|
||||
// Match this horizontal padding (16) to your Table Header padding for perfect alignment
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween, // Pushes text to left, buttons to right
|
||||
mainAxisAlignment: MainAxisAlignment
|
||||
.spaceBetween, // Pushes text to left, buttons to right
|
||||
children: [
|
||||
// --- LEFT SIDE: Showing Text ---
|
||||
Text(
|
||||
@ -1384,7 +1585,7 @@ class _excelVerifyState extends State<preFileUpload> {
|
||||
DropdownButton<int>(
|
||||
value: _rowsPerPage,
|
||||
// focusColor: Colors.transparent, // Fix: Removes the grey/blue highlight on change
|
||||
items: [5, 10, 15, 20, 50].map((int value) {
|
||||
items: [6, 10, 15, 20, 50].map((int value) {
|
||||
return DropdownMenuItem<int>(
|
||||
value: value,
|
||||
child: Text(' $value ',
|
||||
@ -1475,7 +1676,6 @@ class _excelVerifyState extends State<preFileUpload> {
|
||||
return '-';
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Widget _dateField({
|
||||
@ -1533,7 +1733,6 @@ Widget _dateField({
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
class Data {
|
||||
final dynamic value;
|
||||
final int row;
|
||||
|
||||
@ -12,6 +12,8 @@ class ApiService {
|
||||
String? _token;
|
||||
String? _hrtoken;
|
||||
bool _isSessionOutToastShown = false; // Flag to track toast message
|
||||
bool isTpaDashboardEnabled = false;
|
||||
bool isTpaSelected = false; // track which dashboard is active
|
||||
|
||||
ApiService(this.context) {
|
||||
_initializeToken();
|
||||
@ -676,9 +678,32 @@ class ApiService {
|
||||
}
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> getClaimPoliciesToApi(String token) async {
|
||||
Future<Map<String, dynamic>> postHrTpaDashboard(params, token) async {
|
||||
|
||||
final url = Uri.parse('${Environment.apiUrlPost}getHrTpaDashboard');
|
||||
|
||||
final headers = {
|
||||
'Authorization': 'Bearer ${token ?? ''}',
|
||||
'APP-SIGNATURE': 'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y',
|
||||
};
|
||||
|
||||
final response = await http.post(
|
||||
url,
|
||||
headers: headers,
|
||||
body: jsonEncode(params),
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
return jsonDecode(response.body);
|
||||
} else {
|
||||
throw Exception(
|
||||
'Failed to load HR TPA dashboard: ${response.statusCode}');
|
||||
}
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> getClaimPoliciesToApi(String token,empClientId) async {
|
||||
print("getgetClaimPoliciesToApii1");
|
||||
final url = Uri.parse('${Environment.apiUrlPost}claimsSearch');
|
||||
final url = Uri.parse('${Environment.apiUrlPost}claimsSearch?client_id=$empClientId');
|
||||
|
||||
final headers = {
|
||||
'Authorization': 'Bearer $token' ?? '',
|
||||
@ -993,6 +1018,10 @@ class ApiService {
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> _handleResponse(http.Response response) async {
|
||||
// 'throttle' => 429,
|
||||
// 'soft' => 429,
|
||||
// 'medium' => 403,
|
||||
// 'hard' => 451,
|
||||
if (response.statusCode == 200) {
|
||||
return jsonDecode(response.body);
|
||||
} else if (response.statusCode == 401) {
|
||||
@ -1001,6 +1030,17 @@ class ApiService {
|
||||
await _clearLocalStorageAndRedirect();
|
||||
}
|
||||
return {};
|
||||
} else if (response.statusCode == 403) {
|
||||
if (!_isSessionOutToastShown) {
|
||||
_isSessionOutToastShown = true;
|
||||
await _clearLocalStorageAndRedirect();
|
||||
}
|
||||
return {};
|
||||
}else if (response.statusCode == 451) {
|
||||
final body = jsonDecode(response.body);
|
||||
final message = body['message'];
|
||||
ToastHelper.showWarningToast(context, message);
|
||||
return {};
|
||||
} else if (response.statusCode == 429) {
|
||||
final body = jsonDecode(response.body);
|
||||
final message = body['message'];
|
||||
|
||||
@ -11,6 +11,7 @@ class MultiFileUploadWidget extends StatefulWidget {
|
||||
State<MultiFileUploadWidget> createState() => _MultiFileUploadWidgetState();
|
||||
|
||||
static bool hasFiles = false;
|
||||
static bool showValidation = false;
|
||||
}
|
||||
|
||||
class _MultiFileUploadWidgetState extends State<MultiFileUploadWidget> {
|
||||
@ -44,6 +45,7 @@ class _MultiFileUploadWidgetState extends State<MultiFileUploadWidget> {
|
||||
setState(() {
|
||||
errorMessage = null;
|
||||
MultiFileUploadWidget.hasFiles = fileService.files.isNotEmpty;
|
||||
MultiFileUploadWidget.showValidation = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -52,6 +54,9 @@ class _MultiFileUploadWidgetState extends State<MultiFileUploadWidget> {
|
||||
fileService.removeFileAt(index);
|
||||
setState(() {
|
||||
MultiFileUploadWidget.hasFiles = fileService.files.isNotEmpty;
|
||||
if (fileService.files.isEmpty) {
|
||||
MultiFileUploadWidget.showValidation = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -173,7 +178,9 @@ class _MultiFileUploadWidgetState extends State<MultiFileUploadWidget> {
|
||||
// ),
|
||||
],
|
||||
|
||||
if (fileService.files.isEmpty && errorMessage == null) ...[
|
||||
if (MultiFileUploadWidget.showValidation &&
|
||||
fileService.files.isEmpty &&
|
||||
errorMessage == null) ...[
|
||||
const SizedBox(height: 4),
|
||||
const Text(
|
||||
"Required",
|
||||
|
||||
@ -241,6 +241,9 @@ class TokenStorageService {
|
||||
await _secureStorage.write(key: key, value: value);
|
||||
}
|
||||
|
||||
Future<void> removeValue(String key) async {
|
||||
await _secureStorage.delete(key: key);
|
||||
}
|
||||
|
||||
Future<void> clearBranchSession() async {
|
||||
final keysToRemove = [
|
||||
|
||||
@ -33,6 +33,26 @@
|
||||
<link rel="manifest" href="manifest.json">
|
||||
|
||||
<style>
|
||||
/* Hide card three-dot menu */
|
||||
[data-testid="dashcard-action-panel"] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Fallback selector */
|
||||
.DashCard-actions {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Hide powered by footer */
|
||||
.MetabasePoweredBy {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Fallback */
|
||||
a[href*="metabase.com"] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.content {
|
||||
width: 10%;
|
||||
height: 10vh;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user