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(() {
|
||||
|
||||
136
lib/hrLogin.dart
136
lib/hrLogin.dart
@ -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,48 +519,106 @@ class _MyPhoneState extends State<MyHrLogin> {
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
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,
|
||||
),
|
||||
),
|
||||
],
|
||||
width: double.infinity,
|
||||
alignment: Alignment.bottomCenter,
|
||||
padding: const 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(
|
||||
text: 'privacy policy ',
|
||||
style: GoogleFonts.poppins(
|
||||
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 ',
|
||||
style: GoogleFonts.poppins(
|
||||
color: Colors.black,
|
||||
fontSize: 9,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text: 'terms of use',
|
||||
style: GoogleFonts.poppins(
|
||||
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,
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
387
lib/main.dart
387
lib/main.dart
@ -62,117 +62,282 @@ Future<void> startApp() async {
|
||||
projectId: 'nhance-ee8d1'));
|
||||
// await dotenv.load(fileName: Environment.fileName);
|
||||
|
||||
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
|
||||
// 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',
|
||||
debugShowCheckedModeBanner: false,
|
||||
initialRoute: (initialToken == null || initialToken!.isEmpty)
|
||||
? 'hrLogin'
|
||||
: 'hrHome',
|
||||
theme: ThemeData(
|
||||
primaryColor: const Color(0xFF00999E),
|
||||
scaffoldBackgroundColor: Colors.white,
|
||||
colorScheme: ColorScheme.fromSeed(
|
||||
seedColor: const Color(0xFF00999E),
|
||||
),
|
||||
textTheme: GoogleFonts.poppinsTextTheme(),
|
||||
elevatedButtonTheme: ElevatedButtonThemeData(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: const Color(0xFF00999E),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
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: '',
|
||||
),
|
||||
},
|
||||
));
|
||||
routes: appRoutes,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
final Map<String, WidgetBuilder> appRoutes = {
|
||||
'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: '',
|
||||
),
|
||||
};
|
||||
|
||||
/// 🔐 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;
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -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');
|
||||
final _postPreToken = await tokenService.getCurrentToken();
|
||||
final response = await apiService.getOpenEndorsementFileData(id, _postPreToken!);
|
||||
if (response['status'] == false) {
|
||||
ToastHelper.showErrorToast(context, response['message']);
|
||||
} else {
|
||||
Future<void> _openEndorsementFile(id, file_name) async {
|
||||
// final http.Response response = await apiService.getHrFileDownloadToApi(id, widget.Token);
|
||||
final _postPreToken = await tokenService.getCurrentToken();
|
||||
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) {
|
||||
throw Exception('Error parsing response: $e');
|
||||
}
|
||||
} catch (e) {
|
||||
print('Exception occurred: $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: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
if (isAllowedSubType)
|
||||
_ActionIconButton(
|
||||
icon: Icons.picture_as_pdf_outlined,
|
||||
toolTip: 'View Endorsement PDF',
|
||||
onTap: () => getCdEndorsementDetails(item['id']),
|
||||
child: SizedBox(
|
||||
height: 36,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
|
||||
/// --- 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(
|
||||
icon: Icons.folder_open_outlined,
|
||||
toolTip: 'View Files',
|
||||
onTap: () => _launchURL(item['split_up_url']),
|
||||
|
||||
const SizedBox(width: 8),
|
||||
|
||||
/// --- 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";
|
||||
final iframe = html.IFrameElement()
|
||||
..src = embedUrl
|
||||
..style.border = 'none'
|
||||
..style.width = '100%'
|
||||
..style.height = '100%'
|
||||
..allowFullscreen = true;
|
||||
|
||||
_currentIframe = iframe;
|
||||
|
||||
ui.platformViewRegistry.registerViewFactory(
|
||||
viewType,
|
||||
(int viewId) => html.IFrameElement()
|
||||
..src = embedUrl
|
||||
..style.border = 'none'
|
||||
..style.width = '100%'
|
||||
..style.height = '100%'
|
||||
..allowFullscreen = true,
|
||||
(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,95 +406,127 @@ class _hrDashboardState extends State<hrDashboard> with SingleTickerProviderStat
|
||||
color: Colors.white,
|
||||
child: Row(
|
||||
children: [
|
||||
const Text(
|
||||
'Select Policy',
|
||||
style: TextStyle(fontWeight: FontWeight.w600, fontSize: 13),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
SizedBox(
|
||||
width: 420,
|
||||
height: 40,
|
||||
child: SearchAnchor(
|
||||
viewBackgroundColor: Colors.white,
|
||||
viewConstraints: const BoxConstraints(maxHeight: 220),
|
||||
|
||||
builder: (BuildContext context, SearchController controller) {
|
||||
String displayText = "Select Policy";
|
||||
|
||||
if (selectedPolicyId != null) {
|
||||
final policy = activePoliciesList.firstWhere(
|
||||
(p) => p['client_policy_id'].toString() == selectedPolicyId,
|
||||
orElse: () => {},
|
||||
);
|
||||
if (policy.isNotEmpty) {
|
||||
displayText = "${policy['type']} - ${policy['policy_no']}";
|
||||
}
|
||||
}
|
||||
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
setState(() => _isPolicyDropdownOpen = true); // 🔥 OPEN
|
||||
controller.openView();
|
||||
},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: Colors.grey.shade300),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
displayText,
|
||||
style: const TextStyle(fontSize: 12),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
const Icon(Icons.arrow_drop_down, color: Colors.grey),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
|
||||
suggestionsBuilder:
|
||||
(BuildContext context, SearchController controller) {
|
||||
final input = controller.text.toLowerCase();
|
||||
|
||||
return activePoliciesList
|
||||
.where((policy) =>
|
||||
policy['type']
|
||||
.toString()
|
||||
.toLowerCase()
|
||||
.contains(input) ||
|
||||
policy['policy_no']
|
||||
.toString()
|
||||
.toLowerCase()
|
||||
.contains(input))
|
||||
.map((policy) {
|
||||
final label =
|
||||
"${policy['type']} - ${policy['policy_no']}";
|
||||
|
||||
return ListTile(
|
||||
dense: true,
|
||||
title: Text(label, style: const TextStyle(fontSize: 13)),
|
||||
onTap: () {
|
||||
setState(() {
|
||||
selectedPolicyId =
|
||||
policy['client_policy_id'].toString();
|
||||
_isPolicyDropdownOpen = false; // 🔥 CLOSE
|
||||
});
|
||||
|
||||
controller.closeView(label);
|
||||
_loadDashboardByPolicy(selectedPolicyId!);
|
||||
},
|
||||
);
|
||||
}).toList();
|
||||
},
|
||||
if (!isTpaSelected)...[
|
||||
const Text(
|
||||
'Select Policy',
|
||||
style: TextStyle(fontWeight: FontWeight.w600, fontSize: 13),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
SizedBox(
|
||||
width: 420,
|
||||
height: 40,
|
||||
child: SearchAnchor(
|
||||
viewBackgroundColor: Colors.white,
|
||||
viewConstraints: const BoxConstraints(maxHeight: 220),
|
||||
|
||||
builder: (BuildContext context, SearchController controller) {
|
||||
String displayText = "Select Policy";
|
||||
|
||||
if (selectedPolicyId != null) {
|
||||
final policy = activePoliciesList.firstWhere(
|
||||
(p) => p['client_policy_id'].toString() == selectedPolicyId,
|
||||
orElse: () => {},
|
||||
);
|
||||
if (policy.isNotEmpty) {
|
||||
displayText = "${policy['type']} - ${policy['policy_no']}";
|
||||
}
|
||||
}
|
||||
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
setState(() => _isPolicyDropdownOpen = true); // 🔥 OPEN
|
||||
controller.openView();
|
||||
},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: Colors.grey.shade300),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
displayText,
|
||||
style: const TextStyle(fontSize: 12),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
const Icon(Icons.arrow_drop_down, color: Colors.grey),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
|
||||
suggestionsBuilder:
|
||||
(BuildContext context, SearchController controller) {
|
||||
final input = controller.text.toLowerCase();
|
||||
|
||||
return activePoliciesList
|
||||
.where((policy) =>
|
||||
policy['type']
|
||||
.toString()
|
||||
.toLowerCase()
|
||||
.contains(input) ||
|
||||
policy['policy_no']
|
||||
.toString()
|
||||
.toLowerCase()
|
||||
.contains(input))
|
||||
.map((policy) {
|
||||
final label =
|
||||
"${policy['type']} - ${policy['policy_no']}";
|
||||
|
||||
return ListTile(
|
||||
dense: true,
|
||||
title: Text(label, style: const TextStyle(fontSize: 13)),
|
||||
onTap: () {
|
||||
setState(() {
|
||||
selectedPolicyId =
|
||||
policy['client_policy_id'].toString();
|
||||
_isPolicyDropdownOpen = false; // 🔥 CLOSE
|
||||
});
|
||||
|
||||
controller.closeView(label);
|
||||
_loadDashboardByPolicy(selectedPolicyId!);
|
||||
},
|
||||
);
|
||||
}).toList();
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
|
||||
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,43 +106,114 @@ 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]"
|
||||
//
|
||||
// // ✅ 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 {
|
||||
final enrollmentRaw = await tokenService.readValue('enrollmentAllowed_modules'); // "[1]"
|
||||
final postRaw = await tokenService.readValue('empAllowed_modules'); // "[2,3,4]"
|
||||
setState(() {
|
||||
isLoading = true; // 🔥 START LOADER HERE
|
||||
});
|
||||
|
||||
// ✅ Decode safely
|
||||
enrollmentModules = enrollmentRaw != null && enrollmentRaw.isNotEmpty
|
||||
? List<int>.from(jsonDecode(enrollmentRaw))
|
||||
: [];
|
||||
try {
|
||||
final enrollmentRaw =
|
||||
await tokenService.readValue('enrollmentAllowed_modules');
|
||||
final postRaw =
|
||||
await tokenService.readValue('empAllowed_modules');
|
||||
|
||||
postModules = postRaw != null && postRaw.isNotEmpty
|
||||
? List<int>.from(jsonDecode(postRaw))
|
||||
: [];
|
||||
enrollmentModules = enrollmentRaw != null && enrollmentRaw.isNotEmpty
|
||||
? List<int>.from(jsonDecode(enrollmentRaw))
|
||||
: [];
|
||||
|
||||
print('enrollmentModules $enrollmentModules');
|
||||
print('postModules $postModules');
|
||||
postModules = postRaw != null && postRaw.isNotEmpty
|
||||
? List<int>.from(jsonDecode(postRaw))
|
||||
: [];
|
||||
|
||||
_postPreToken = await tokenService.getCurrentToken();
|
||||
print(_postPreToken);
|
||||
_postPreToken = await tokenService.getCurrentToken();
|
||||
|
||||
if (enrollmentModules.contains(1)) {
|
||||
enrollmentClient_id = await tokenService.readValue('enrollmentClient_id');
|
||||
enrollmentEmpClientBranchId =
|
||||
await tokenService.readValue('enrollmentEmpClientBranchId');
|
||||
enrollmentHrId = await tokenService.readValue('enrollmentHrId');
|
||||
List<Future> apiCalls = [];
|
||||
|
||||
await getPreCashDepositDetails(enrollmentEmpClientBranchId,
|
||||
enrollmentClient_id, enrollmentHrId, _postPreToken);
|
||||
/// 👇 Add APIs dynamically
|
||||
if (enrollmentModules.contains(1)) {
|
||||
enrollmentClient_id =
|
||||
await tokenService.readValue('enrollmentClient_id');
|
||||
enrollmentEmpClientBranchId =
|
||||
await tokenService.readValue('enrollmentEmpClientBranchId');
|
||||
enrollmentHrId =
|
||||
await tokenService.readValue('enrollmentHrId');
|
||||
|
||||
apiCalls.add(
|
||||
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');
|
||||
|
||||
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
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
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> 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,39 +460,45 @@ 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: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Open for Enrollment',
|
||||
style: GoogleFonts.poppins(fontSize: 14, fontWeight: FontWeight.w600),
|
||||
),
|
||||
SizedBox(height: 14),
|
||||
child: IntrinsicHeight(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Open for Enrollment',
|
||||
style: GoogleFonts.poppins(fontSize: 14, fontWeight: FontWeight.w600),
|
||||
),
|
||||
SizedBox(height: 14),
|
||||
|
||||
/// ✅ SCROLLABLE AREA
|
||||
openEnrollment.isEmpty
|
||||
? _EmptyBox('No policies open for enrollment')
|
||||
: _PolicyGrid(
|
||||
policies: openEnrollment,
|
||||
isEnrollment: true,
|
||||
),
|
||||
|
||||
],
|
||||
),
|
||||
)
|
||||
|
||||
/// ✅ SCROLLABLE AREA
|
||||
Expanded(
|
||||
child: 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,123 +593,158 @@ 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(
|
||||
physics: const BouncingScrollPhysics(),
|
||||
padding: EdgeInsets.zero,
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: config.crossAxisCount,
|
||||
childAspectRatio: config.childAspectRatio,
|
||||
crossAxisSpacing: 16,
|
||||
mainAxisSpacing: 16,
|
||||
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) {
|
||||
final data = policies[index];
|
||||
|
||||
return isEnrollment
|
||||
? _EnrollmentPolicyCardNew(
|
||||
data: data,
|
||||
onTap: () async {
|
||||
final token = await tokenService.getCurrentToken();
|
||||
final clientId =
|
||||
await tokenService.readValue('enrollmentClient_id');
|
||||
final branchId = await tokenService
|
||||
.readValue('enrollmentEmpClientBranchId');
|
||||
|
||||
if (token == null || clientId == null || branchId == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: 'hrPolicyDetails'),
|
||||
builder: (_) => hrPolicyDetails(
|
||||
ClientId: clientId,
|
||||
policyTypeId:
|
||||
data['policy_type_id'].toString(),
|
||||
ClientPoliyId:
|
||||
data['client_policy_id'].toString(),
|
||||
clientBranchId: branchId,
|
||||
Token: token,
|
||||
TokenType: "pre",
|
||||
cardType: data['type'].toString(),
|
||||
cardPolicyNo: data['policy_no'].toString(),
|
||||
cardInsurer_name:
|
||||
data['insurer_short_name'].toString(),
|
||||
cardPolicy_name:
|
||||
data['policy_name'].toString(),
|
||||
cardPolicy_ExpDate:
|
||||
data['policy_expiry_date'].toString(),
|
||||
total_premium: '',
|
||||
is_ecard_bulk_download_for_employee: 0,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
)
|
||||
: _ActivePolicyCardNew(
|
||||
data: data,
|
||||
onBulkDownload: onBulkDownload,
|
||||
onTap: () async {
|
||||
final token = await tokenService.getCurrentToken();
|
||||
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;
|
||||
}
|
||||
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: 'hrPolicyDetails'),
|
||||
builder: (_) => hrPolicyDetails(
|
||||
ClientId: clientId,
|
||||
policyTypeId:
|
||||
data['policy_type_id'].toString(),
|
||||
ClientPoliyId:
|
||||
data['client_policy_id'].toString(),
|
||||
clientBranchId: branchId,
|
||||
Token: token,
|
||||
TokenType: 'post',
|
||||
cardType: data['type'].toString(),
|
||||
cardPolicyNo: data['policy_no'].toString(),
|
||||
cardInsurer_name:
|
||||
data['insurer_short_name'].toString(),
|
||||
cardPolicy_name:
|
||||
data['policy_name'].toString(),
|
||||
cardPolicy_ExpDate:
|
||||
data['policy_expiry_date'].toString(),
|
||||
total_premium:
|
||||
data['total_premium'].toString(),
|
||||
is_ecard_bulk_download_for_employee:
|
||||
data['is_ecard_bulk_download_for_employee'],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
itemCount: policies.length,
|
||||
itemBuilder: (context, index) {
|
||||
final data = policies[index];
|
||||
|
||||
return isEnrollment
|
||||
? _EnrollmentPolicyCardNew(
|
||||
data: data,
|
||||
onTap: () async {
|
||||
final token = await tokenService.getCurrentToken();
|
||||
final clientId =
|
||||
await tokenService.readValue('enrollmentClient_id');
|
||||
final branchId = await tokenService
|
||||
.readValue('enrollmentEmpClientBranchId');
|
||||
|
||||
if (token == null || clientId == null || branchId == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: 'hrPolicyDetails'),
|
||||
builder: (_) => hrPolicyDetails(
|
||||
ClientId: clientId,
|
||||
policyTypeId:
|
||||
data['policy_type_id'].toString(),
|
||||
ClientPoliyId:
|
||||
data['client_policy_id'].toString(),
|
||||
clientBranchId: branchId,
|
||||
Token: token,
|
||||
TokenType: "pre",
|
||||
cardType: data['type'].toString(),
|
||||
cardPolicyNo: data['policy_no'].toString(),
|
||||
cardInsurer_name:
|
||||
data['insurer_short_name'].toString(),
|
||||
cardPolicy_name:
|
||||
data['policy_name'].toString(),
|
||||
cardPolicy_ExpDate:
|
||||
data['policy_expiry_date'].toString(),
|
||||
total_premium: '',
|
||||
is_ecard_bulk_download_for_employee: 0,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
)
|
||||
: _ActivePolicyCardNew(
|
||||
data: data,
|
||||
onBulkDownload: onBulkDownload,
|
||||
onTap: () async {
|
||||
final token = await tokenService.getCurrentToken();
|
||||
final clientId =
|
||||
await tokenService.readValue('empClientId');
|
||||
final branchId =
|
||||
await tokenService.readValue('empClientBranchId');
|
||||
|
||||
if (token == null || clientId == null || branchId == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: 'hrPolicyDetails'),
|
||||
builder: (_) => hrPolicyDetails(
|
||||
ClientId: clientId,
|
||||
policyTypeId:
|
||||
data['policy_type_id'].toString(),
|
||||
ClientPoliyId:
|
||||
data['client_policy_id'].toString(),
|
||||
clientBranchId: branchId,
|
||||
Token: token,
|
||||
TokenType: 'post',
|
||||
cardType: data['type'].toString(),
|
||||
cardPolicyNo: data['policy_no'].toString(),
|
||||
cardInsurer_name:
|
||||
data['insurer_short_name'].toString(),
|
||||
cardPolicy_name:
|
||||
data['policy_name'].toString(),
|
||||
cardPolicy_ExpDate:
|
||||
data['policy_expiry_date'].toString(),
|
||||
total_premium:
|
||||
data['total_premium'].toString(),
|
||||
is_ecard_bulk_download_for_employee:
|
||||
data['is_ecard_bulk_download_for_employee'],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
_loadToken();
|
||||
getFileUploadMasterDetails();
|
||||
getFileListDetails();
|
||||
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,217 +672,267 @@ class _postFileUploadState extends State<postFileUpload> {
|
||||
}
|
||||
|
||||
Widget _buildContent(BuildContext context) {
|
||||
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
|
||||
),
|
||||
): Container(
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
IconButton(
|
||||
tooltip: 'Previous Page',
|
||||
onPressed: () => {Navigator.pop(context)},
|
||||
icon: const Icon(
|
||||
Icons.arrow_back_ios,
|
||||
size: 18,
|
||||
color: Colors.black,
|
||||
),
|
||||
padding: EdgeInsets.zero,
|
||||
constraints: const BoxConstraints(),
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// mainAxisAlignment: MainAxisAlignment.start,
|
||||
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
|
||||
),
|
||||
)
|
||||
: Container(
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
"${widget.cardType} - ${widget.cardPolicyNo} " ??
|
||||
'',
|
||||
style: GoogleFonts.poppins(
|
||||
color: Colors.black,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
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),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
// Visibility toggles based on dropdown selection
|
||||
Visibility(
|
||||
visible: showSampleButton,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 10),
|
||||
child: SizedBox(
|
||||
child: ElevatedButton(
|
||||
onPressed: () {
|
||||
// Pass the dynamic value to the function
|
||||
downloadPostSampleFile(currentApiValue ?? '');
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: const Color(0xFFE26728),
|
||||
elevation: 0,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
||||
),
|
||||
child: Text(
|
||||
'Sample Excel',
|
||||
style: GoogleFonts.poppins(fontSize: 14, fontWeight: FontWeight.w700, color: Colors.white),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height:20),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
/// Select File Action
|
||||
Expanded(
|
||||
flex: 5,
|
||||
child: buildStyledDropdown(
|
||||
label: 'Select File Action',
|
||||
value: selectedKey,
|
||||
items: getFileUploadMasterList,
|
||||
onChanged: (val) {
|
||||
setState(() {
|
||||
selectedKey = val;
|
||||
final selectedItem = getFileUploadMasterList.firstWhere((e) => e['key'] == val);
|
||||
selectedValue = selectedItem['value'];
|
||||
currentApiValue = selectedItem['key'];
|
||||
showSampleButton = true;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
tooltip: 'Previous Page',
|
||||
onPressed: () async {
|
||||
if (Navigator.canPop(context)) {
|
||||
Navigator.pop(context);
|
||||
return;
|
||||
}
|
||||
|
||||
const SizedBox(width: 16),
|
||||
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';
|
||||
|
||||
/// Upload Box
|
||||
Expanded(
|
||||
flex: 5,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
/// ✅ LABEL
|
||||
RichText(
|
||||
text: TextSpan(
|
||||
text: 'Upload File',
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.black,
|
||||
),
|
||||
children: const [
|
||||
TextSpan(
|
||||
text: '(Supported Formats: XLSX)',
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
color: Colors.grey,
|
||||
fontWeight: FontWeight.w400,
|
||||
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,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"${localCardType} - ${localCardPolicyNo} " ??
|
||||
'',
|
||||
style: GoogleFonts.poppins(
|
||||
color: Colors.black,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
localTokenType == 'pre'
|
||||
? "${localCardPolicyName} (${localCardPolicyExpDate})"
|
||||
: "${localCardInsurerName} - ${localCardPolicyName} (${localCardPolicyExpDate})",
|
||||
style: GoogleFonts.poppins(
|
||||
color: Colors.grey,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
const SizedBox(height: 6),
|
||||
|
||||
/// ✅ DOTTED UPLOAD BOX
|
||||
DragTarget<html.File>(
|
||||
onAccept: (html.File droppedFile) {
|
||||
setState(() {
|
||||
fileName = droppedFile.name;
|
||||
});
|
||||
_dragAndDropFile(droppedFile);
|
||||
},
|
||||
builder: (context, candidateData, rejectedData) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
if (selectedValue != null) {
|
||||
_uploadFile();
|
||||
} else {
|
||||
ToastHelper.showErrorToast(
|
||||
context,
|
||||
'Please select file action',
|
||||
);
|
||||
}
|
||||
// Visibility toggles based on dropdown selection
|
||||
Visibility(
|
||||
visible: showSampleButton,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 10),
|
||||
child: SizedBox(
|
||||
child: ElevatedButton(
|
||||
onPressed: () {
|
||||
// Pass the dynamic value to the function
|
||||
downloadPostSampleFile(currentApiValue ?? '');
|
||||
},
|
||||
child: Container(
|
||||
height: 40 ,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(
|
||||
color: const Color(0xFF00A6A6),
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
fileName ?? 'Upload Your Documents',
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 13,
|
||||
color: fileName == null
|
||||
? Colors.grey
|
||||
: Colors.black,
|
||||
),
|
||||
),
|
||||
),
|
||||
const Icon(
|
||||
Icons.file_upload_outlined,
|
||||
size: 18,
|
||||
color: Colors.black,
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
);
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: const Color(0xFFE26728),
|
||||
elevation: 0,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10)),
|
||||
),
|
||||
child: Text(
|
||||
'Sample Excel',
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: Colors.white),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
children: [
|
||||
_buildFileUploadedGrid(),
|
||||
const SizedBox(height: 16),
|
||||
_buildPagination(context),
|
||||
],
|
||||
),
|
||||
)
|
||||
SizedBox(height: 20),
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
/// Select File Action
|
||||
Expanded(
|
||||
flex: 5,
|
||||
child: buildStyledDropdown(
|
||||
label: 'Select File Action',
|
||||
value: selectedKey,
|
||||
items: getFileUploadMasterList,
|
||||
onChanged: (val) {
|
||||
setState(() {
|
||||
selectedKey = val;
|
||||
final selectedItem = getFileUploadMasterList
|
||||
.firstWhere((e) => e['key'] == val);
|
||||
selectedValue = selectedItem['value'];
|
||||
currentApiValue = selectedItem['key'];
|
||||
showSampleButton = true;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
const SizedBox(width: 16),
|
||||
|
||||
/// Upload Box
|
||||
Expanded(
|
||||
flex: 5,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
/// ✅ LABEL
|
||||
RichText(
|
||||
text: TextSpan(
|
||||
text: 'Upload File',
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.black,
|
||||
),
|
||||
children: const [
|
||||
TextSpan(
|
||||
text: '(Supported Formats: XLSX)',
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
color: Colors.grey,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
const SizedBox(height: 6),
|
||||
|
||||
/// ✅ DOTTED UPLOAD BOX
|
||||
DragTarget<html.File>(
|
||||
onAccept: (html.File droppedFile) {
|
||||
setState(() {
|
||||
fileName = droppedFile.name;
|
||||
});
|
||||
_dragAndDropFile(droppedFile);
|
||||
},
|
||||
builder:
|
||||
(context, candidateData, rejectedData) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
if (selectedValue != null) {
|
||||
_uploadFile();
|
||||
} else {
|
||||
ToastHelper.showErrorToast(
|
||||
context,
|
||||
'Please select file action',
|
||||
);
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
height: 40,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius:
|
||||
BorderRadius.circular(8),
|
||||
border: Border.all(
|
||||
color: const Color(0xFF00A6A6),
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
fileName ??
|
||||
'Upload Your Documents',
|
||||
overflow:
|
||||
TextOverflow.ellipsis,
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 13,
|
||||
color: fileName == null
|
||||
? Colors.grey
|
||||
: Colors.black,
|
||||
),
|
||||
),
|
||||
),
|
||||
const Icon(
|
||||
Icons.file_upload_outlined,
|
||||
size: 18,
|
||||
color: Colors.black,
|
||||
),
|
||||
],
|
||||
),
|
||||
));
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
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,20 +1048,23 @@ 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
|
||||
crossAxisSpacing: 16,
|
||||
mainAxisSpacing: 16,
|
||||
childAspectRatio: 10, // 👈 card height
|
||||
),
|
||||
itemCount: _paginatedData.length,
|
||||
itemBuilder: (context, index) {
|
||||
final item = _paginatedData[index];
|
||||
return _buildFileCard(item);
|
||||
},
|
||||
);
|
||||
crossAxisCount: 2,
|
||||
crossAxisSpacing: 16,
|
||||
mainAxisSpacing: 16,
|
||||
childAspectRatio: 10,
|
||||
),
|
||||
itemCount: _paginatedData.length,
|
||||
itemBuilder: (context, index) {
|
||||
final item = _paginatedData[index];
|
||||
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),
|
||||
@ -1024,58 +1157,60 @@ class _postFileUploadState extends State<postFileUpload> {
|
||||
Row(
|
||||
children: [
|
||||
if (item['file_error_status'] == '1')
|
||||
InkWell(
|
||||
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');
|
||||
InkWell(
|
||||
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');
|
||||
|
||||
print(item);
|
||||
print(empClientId);
|
||||
print(widget.policyTypeId);
|
||||
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(item['id']);
|
||||
print(item);
|
||||
print(empClientId);
|
||||
print(localPolicyTypeId);
|
||||
print(empBranchId);
|
||||
print(token);
|
||||
print('post');
|
||||
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}');
|
||||
return;
|
||||
}
|
||||
// ✅ SAFETY CHECK
|
||||
if (token == null ||
|
||||
empClientId == null ||
|
||||
empBranchId == null) {
|
||||
debugPrint(
|
||||
'❌ Missing required data for navigation ${token}');
|
||||
return;
|
||||
}
|
||||
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) =>
|
||||
excelErrorScreen(
|
||||
ClientId: empClientId,
|
||||
policy_no: item['policy_no'],
|
||||
action: item['file_action'],
|
||||
created_at: item['created_at'],
|
||||
clientBranchId: empBranchId,
|
||||
Token: token,
|
||||
TokenType: 'post',
|
||||
id: item['id']
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
child: Icon(
|
||||
Icons.error,
|
||||
size: 16,
|
||||
color: Colors.red,
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => excelErrorScreen(
|
||||
ClientId: empClientId,
|
||||
policy_no: item['policy_no'],
|
||||
action: item['file_action'],
|
||||
created_at: item['created_at'],
|
||||
clientBranchId: empBranchId,
|
||||
Token: token,
|
||||
TokenType: 'post',
|
||||
id: item['id']),
|
||||
),
|
||||
);
|
||||
},
|
||||
child: Icon(
|
||||
Icons.error,
|
||||
size: 16,
|
||||
color: Colors.red,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(width: 10),
|
||||
_buildStatusChip(item['status']),
|
||||
SizedBox(width: 10),
|
||||
@ -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,
|
||||
@ -1186,14 +1320,13 @@ class _postFileUploadState extends State<postFileUpload> {
|
||||
totalPages
|
||||
];
|
||||
}
|
||||
return [
|
||||
_currentPage - 2,
|
||||
_currentPage - 1,
|
||||
_currentPage,
|
||||
_currentPage + 1,
|
||||
_currentPage + 2,
|
||||
];
|
||||
|
||||
return [
|
||||
_currentPage - 2,
|
||||
_currentPage - 1,
|
||||
_currentPage,
|
||||
_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 ',
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -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