456 lines
14 KiB
Dart
Executable File
456 lines
14 KiB
Dart
Executable File
import 'package:flutter/material.dart';
|
|
import 'package:google_fonts/google_fonts.dart';
|
|
import 'package:nhancepolicy/addons.dart';
|
|
import 'package:nhancepolicy/branch/branch_selection_page.dart';
|
|
import 'package:nhancepolicy/empReview.dart';
|
|
import 'package:nhancepolicy/empDetails.dart';
|
|
import 'package:nhancepolicy/presentation/preFileUpload.dart';
|
|
import 'package:nhancepolicy/hrHome.dart';
|
|
import 'package:nhancepolicy/hrVerify.dart';
|
|
import 'package:nhancepolicy/presentation/excelVerification.dart';
|
|
import 'package:nhancepolicy/presentation/postFileUpload.dart';
|
|
import 'package:nhancepolicy/presentation/cdList.dart';
|
|
import 'package:nhancepolicy/presentation/claims.dart';
|
|
import 'package:nhancepolicy/presentation/nonEBClaimsList.dart';
|
|
import 'package:nhancepolicy/presentation/pendingDependentApproval.dart';
|
|
import 'package:nhancepolicy/presentation/policies.dart';
|
|
import 'package:nhancepolicy/service/session/session_service.dart';
|
|
import 'package:nhancepolicy/service/token_storage_service.dart';
|
|
import 'package:nhancepolicy/home.dart';
|
|
import 'package:nhancepolicy/presentation/claims_overview/claims_overview_dashboard.dart';
|
|
import 'package:flutter_dotenv/flutter_dotenv.dart';
|
|
import 'package:nhancepolicy/hrLogin.dart';
|
|
import 'package:nhancepolicy/presentation/hrPolicyDetails.dart';
|
|
import 'package:nhancepolicy/oldPolicy.dart';
|
|
// import 'package:firebase_core/firebase_core.dart';
|
|
|
|
import 'presentation/cdTransactionDetails.dart';
|
|
import 'config/environment.dart';
|
|
import 'email_verify.dart';
|
|
import 'package:nhancepolicy/logger.dart';
|
|
|
|
Future<void> startApp() async {
|
|
// html.window.onBeforeUnload.listen((event) {
|
|
// logDebug('Local Storage cleared by window');
|
|
// html.window.localStorage.clear();
|
|
// });
|
|
// Ask confirmation (browser may or may not show it again)
|
|
// html.window.onBeforeUnload.listen((event) {
|
|
// final e = event as html.BeforeUnloadEvent;
|
|
// e.preventDefault();
|
|
// e.returnValue = '';
|
|
// });
|
|
|
|
// Always clear when user leaves (refresh/close)
|
|
// html.window.onUnload.listen((event) {
|
|
// html.window.localStorage.clear();
|
|
// });
|
|
// await dotenv.load(fileName: Environment.fileName);
|
|
WidgetsFlutterBinding.ensureInitialized();
|
|
|
|
// final sessionService = SessionService();
|
|
// await sessionService.restoreSession(); // ⭐ IMPORTANT
|
|
|
|
// Initialize token storage
|
|
await TokenStorageService().initialize();
|
|
|
|
// await Firebase.initializeApp(
|
|
// options: const FirebaseOptions(
|
|
// apiKey: 'AIzaSyCSvDM5fG2blDBE69Cae3S-iYRwwNBy7xo',
|
|
// appId: '1:1084115316849:web:ce28f12a426f285d6c6bd0',
|
|
// messagingSenderId: '1084115316849',
|
|
// 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
|
|
// ),
|
|
// ),
|
|
// ),
|
|
// 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));
|
|
}
|
|
|
|
/// Routes that require an authenticated HR session.
|
|
/// Public auth-flow routes (hrLogin, mailVerify, branchSelection) stay excluded.
|
|
const Set<String> _authProtectedRoutes = {
|
|
'hrHome',
|
|
'hrDashboard',
|
|
'policies',
|
|
'pendingDependentApproval',
|
|
'claimsOverviewDashboard',
|
|
'ClaimsPolicies',
|
|
'nonEBClaimsList',
|
|
'CdPoliciesList',
|
|
'cdTransactionDetails',
|
|
'hrPolicyDetails',
|
|
'oldPolicy',
|
|
'preFileUpload',
|
|
'postFileUpload',
|
|
'excelErrorScreen',
|
|
'empDetails',
|
|
'addOnsDetails',
|
|
'empReviewDetails',
|
|
};
|
|
|
|
String _normalizeRouteName(String routeName) {
|
|
var name = routeName.trim();
|
|
if (name.startsWith('#')) {
|
|
name = name.substring(1);
|
|
}
|
|
if (name.startsWith('/')) {
|
|
name = name.substring(1);
|
|
}
|
|
// Flutter web may include query/hash fragments; keep only path segment.
|
|
final hashIndex = name.indexOf('#');
|
|
if (hashIndex != -1) {
|
|
name = name.substring(hashIndex + 1);
|
|
}
|
|
final queryIndex = name.indexOf('?');
|
|
if (queryIndex != -1) {
|
|
name = name.substring(0, queryIndex);
|
|
}
|
|
return name;
|
|
}
|
|
|
|
bool _hasValidSession() {
|
|
final token = TokenStorageService().getCurrentToken();
|
|
return token != null && token.trim().isNotEmpty;
|
|
}
|
|
|
|
class MyApp extends StatelessWidget {
|
|
final String? initialToken;
|
|
|
|
const MyApp({super.key, this.initialToken});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final fallbackRoute =
|
|
(initialToken == null || initialToken!.isEmpty) ? 'hrLogin' : 'hrHome';
|
|
|
|
return MaterialApp(
|
|
title: 'Nhance HR',
|
|
debugShowCheckedModeBanner: false,
|
|
initialRoute: fallbackRoute,
|
|
onGenerateInitialRoutes: (String initialRouteName) {
|
|
final requested = _normalizeRouteName(initialRouteName);
|
|
final resolved = (requested.isEmpty || requested == '/')
|
|
? fallbackRoute
|
|
: requested;
|
|
|
|
// Deep-link guard: unauthenticated access to protected URLs → HR login
|
|
final targetRoute =
|
|
(!_hasValidSession() && _authProtectedRoutes.contains(resolved))
|
|
? 'hrLogin'
|
|
: resolved;
|
|
|
|
final builder = appRoutes[targetRoute] ?? appRoutes['hrLogin']!;
|
|
return [
|
|
MaterialPageRoute(
|
|
builder: builder,
|
|
settings: RouteSettings(name: targetRoute),
|
|
),
|
|
];
|
|
},
|
|
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: appRoutes,
|
|
);
|
|
}
|
|
}
|
|
|
|
final Map<String, WidgetBuilder> appRoutes = {
|
|
'mailVerify': (context) => MyEmailVerify(
|
|
type: '',
|
|
value: '',
|
|
),
|
|
'home': (context) => MyApp(),
|
|
'hrLogin': (context) => MyHrLogin(),
|
|
// 'hrVerify': (context) => MyHrVerify(
|
|
// verificationId: '',
|
|
// mobileNumber: '',
|
|
// resendToken: null,
|
|
// onResendCode: (String, int) {},
|
|
// ),
|
|
'hrHome': (context) => AuthWrapper(
|
|
builder: (_) => MyHrHome(),
|
|
),
|
|
'preFileUpload': (context) => AuthWrapper(
|
|
builder: (_) => const preFileUpload(
|
|
ClientId: '',
|
|
policyTypeId: '',
|
|
ClientPoliyId: '',
|
|
clientBranchId: '',
|
|
Token: '',
|
|
TokenType: '',
|
|
cardType: '',
|
|
cardPolicyNo: '',
|
|
cardInsurer_name: '',
|
|
cardPolicy_name: '',
|
|
cardPolicy_ExpDate: '',
|
|
total_premium: '',
|
|
),
|
|
),
|
|
'postFileUpload': (context) => AuthWrapper(
|
|
builder: (_) => const postFileUpload(
|
|
ClientId: '',
|
|
policyTypeId: '',
|
|
ClientPoliyId: '',
|
|
clientBranchId: '',
|
|
Token: '',
|
|
TokenType: '',
|
|
cardType: '',
|
|
cardPolicyNo: '',
|
|
cardInsurer_name: '',
|
|
cardPolicy_name: '',
|
|
cardPolicy_ExpDate: '',
|
|
total_premium: '',
|
|
),
|
|
),
|
|
'excelErrorScreen': (context) => AuthWrapper(
|
|
builder: (_) => const excelErrorScreen(
|
|
ClientId: '',
|
|
policy_no: '',
|
|
action: '',
|
|
created_at: '',
|
|
clientBranchId: '',
|
|
Token: '',
|
|
TokenType: '',
|
|
id: ''),
|
|
),
|
|
'empDetails': (context) => AuthWrapper(
|
|
builder: (_) => empDetails(),
|
|
),
|
|
'addOnsDetails': (context) => AuthWrapper(
|
|
builder: (_) => addOnsDetails(),
|
|
),
|
|
'empReviewDetails': (context) => AuthWrapper(
|
|
builder: (_) => empReviewDetails(),
|
|
),
|
|
'hrDashboard': (context) => AuthWrapper(
|
|
builder: (_) => const policies(),
|
|
),
|
|
'claimsOverviewDashboard': (context) => AuthWrapper(
|
|
builder: (_) => const ClaimsOverviewDashboard(),
|
|
),
|
|
'hrPolicyDetails': (context) => AuthWrapper(
|
|
builder: (_) => 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) => AuthWrapper(
|
|
builder: (_) => oldPolicy(),
|
|
),
|
|
// Branch selection happens after login but before a branch token is set.
|
|
'branchSelection': (context) => BranchSelectionPage(),
|
|
'policies': (context) => AuthWrapper(
|
|
builder: (_) => const policies(),
|
|
),
|
|
'pendingDependentApproval': (context) => AuthWrapper(
|
|
builder: (_) => const PendingDependentApproval(),
|
|
),
|
|
'CdPoliciesList': (context) => AuthWrapper(
|
|
builder: (_) => CdPoliciesList(),
|
|
),
|
|
'ClaimsPolicies': (context) => AuthWrapper(
|
|
builder: (_) => const ClaimsPolicies(
|
|
empCode: '',
|
|
),
|
|
),
|
|
'nonEBClaimsList': (context) => AuthWrapper(
|
|
builder: (_) => const NonEBClaimsList(
|
|
empCode: '',
|
|
),
|
|
),
|
|
'cdTransactionDetails': (context) => AuthWrapper(
|
|
builder: (_) => cdTransactionDetails(
|
|
insurerName: '',
|
|
cdMasterAccountNo: '',
|
|
insurerId: '',
|
|
cd_ac_pk: '',
|
|
empClientId: '',
|
|
),
|
|
),
|
|
};
|
|
|
|
/// 🔐 Auth Wrapper — blocks protected pages until a valid session exists.
|
|
/// Uses a builder so protected widgets are not constructed without a token.
|
|
class AuthWrapper extends StatefulWidget {
|
|
final WidgetBuilder builder;
|
|
|
|
const AuthWrapper({super.key, required this.builder});
|
|
|
|
@override
|
|
State<AuthWrapper> createState() => _AuthWrapperState();
|
|
}
|
|
|
|
class _AuthWrapperState extends State<AuthWrapper> {
|
|
late final bool _isAuthenticated;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_isAuthenticated = _hasValidSession();
|
|
|
|
if (!_isAuthenticated) {
|
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
if (!mounted) return;
|
|
Navigator.pushNamedAndRemoveUntil(
|
|
context,
|
|
'hrLogin',
|
|
(route) => false,
|
|
);
|
|
});
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
if (!_isAuthenticated) {
|
|
// Do not render protected UI while redirecting to login.
|
|
return const Scaffold(
|
|
body: Center(
|
|
child: CircularProgressIndicator(
|
|
color: Color(0xFF00999E),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
return widget.builder(context);
|
|
}
|
|
}
|