post_enrollment_app/lib/main.dart
2026-05-19 12:30:28 +05:30

409 lines
13 KiB
Dart
Executable File

// import 'package:firebase_app_check/firebase_app_check.dart';
// import 'package:firebase_core/firebase_core.dart';
// import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:nhance_app_pwa/customAppBar/toastHelper.dart';
import 'package:nhance_app_pwa/features/chatbot/presentation/chatbot_host.dart';
import 'package:nhance_app_pwa/pages/changePassword.dart';
import 'package:nhance_app_pwa/pages/email_verify.dart';
import 'package:nhance_app_pwa/pages/enrollment/addons.dart';
import 'package:nhance_app_pwa/pages/enrollment/empDetails.dart';
import 'package:nhance_app_pwa/pages/enrollment/empReview.dart';
import 'package:nhance_app_pwa/pages/login.dart';
import 'package:nhance_app_pwa/pages/sso_login_return_page.dart';
import 'package:nhance_app_pwa/pages/postEnrollment/AddPolicyScreen.dart';
import 'package:nhance_app_pwa/pages/postEnrollment/claimprocess.dart';
import 'package:nhance_app_pwa/pages/postEnrollment/claims.dart';
import 'package:nhance_app_pwa/pages/postEnrollment/faqs.dart';
import 'package:nhance_app_pwa/pages/postEnrollment/generalexclusionsdeductibles.dart';
import 'package:nhance_app_pwa/pages/postEnrollment/help.dart';
import 'package:nhance_app_pwa/pages/postEnrollment/home.dart';
import 'package:nhance_app_pwa/pages/postEnrollment/planclaimsform.dart';
import 'package:nhance_app_pwa/pages/postEnrollment/policies.dart';
import 'package:nhance_app_pwa/pages/postEnrollment/privacypolicy.dart';
import 'package:nhance_app_pwa/pages/postEnrollment/profile.dart';
import 'package:nhance_app_pwa/pages/postEnrollment/raisedTicketList.dart';
import 'package:nhance_app_pwa/pages/postEnrollment/retailClaimForm.dart';
import 'package:nhance_app_pwa/pages/postEnrollment/service/api_service.dart';
import 'package:nhance_app_pwa/pages/postEnrollment/termsofuse.dart';
import 'package:nhance_app_pwa/pages/postEnrollment/tickets.dart';
import 'package:nhance_app_pwa/pages/postEnrollment/tickettracklist.dart';
import 'package:nhance_app_pwa/pages/postEnrollment/wellness.dart';
import 'package:nhance_app_pwa/pages/postEnrollment/wellness_web_view.dart';
import 'package:nhance_app_pwa/pages/service/SessionManager.dart';
import 'package:nhance_app_pwa/pages/service/TokenService.dart';
import 'package:nhance_app_pwa/pages/service/data_manager.dart';
import 'package:nhance_app_pwa/pages/session/SetPinBiometric.dart';
import 'package:nhance_app_pwa/pages/session/changePin.dart';
import 'package:nhance_app_pwa/pages/session/settingUpPinAndBiometric.dart';
import 'package:nhance_app_pwa/pages/setPassword.dart';
import 'package:nhance_app_pwa/pages/verify.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:flutter/foundation.dart';
import 'package:go_router/go_router.dart';
import 'config/environment.dart';
import 'logger.dart';
// import 'dart:html' as html;
Future<void> main() async {
await startApp();
}
// === Splash (only for mobile) ===
class SplashScreen extends StatefulWidget {
const SplashScreen({super.key});
@override
State<SplashScreen> createState() => _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> {
@override
void initState() {
super.initState();
_navigate();
}
Future<void> _navigate() async {
await Future.delayed(const Duration(seconds: 3));
final prefs = await SharedPreferences.getInstance();
final isMpinSkipped = prefs.getString('is_mpin_skipped');
if (isMpinSkipped == '0') {
if (mounted) context.go('/pinPage');
} else {
if (mounted) context.go('/login');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
color: const Color(0x98FFFCE5),
child: Center(
child: Image.asset('assets/nhance-loader.gif', height: 60, width: 60),
),
),
);
}
}
/// Middleware logic for tokens + mpin
Future<String?> tokenRedirectLogic(
BuildContext context, GoRouterState state) async {
logDebug('ABCDEFGH');
const guestRoutes = [
'/login',
'/sso-login',
'/verify',
'/mailVerify',
'/pinPage',
'/splash',
];
final hasToken = await TokenService.hasValidToken();
logDebug('hasToken : $hasToken');
final location = state.matchedLocation;
final session = SessionManager();
logDebug('Location: $location');
logDebug('hasToken: $hasToken');
if (hasToken) {
await session.restoreSession();
}
if (!kIsWeb && hasToken) {
final reauth = await _mobileReauthRedirectIfNeeded(location);
if (reauth != null) return reauth;
}
// Logged in on a guest route → home (only when mobile session is unlocked).
if (hasToken && guestRoutes.contains(location)) {
if (!kIsWeb && !session.isMobileAppSessionUnlocked) {
return null;
}
return '/home';
}
if (!hasToken && guestRoutes.contains(location)) {
return null;
}
if (!hasToken && !guestRoutes.contains(location)) {
WidgetsBinding.instance.addPostFrameCallback((_) {
ToastHelper.showErrorToast(
context, 'Session expired. Please login again.');
});
return '/login';
}
return null;
}
/// After a full app restart (new process), require MPIN or password login before
/// protected routes. Tokens remain in secure storage. Minimizing does not lock.
Future<String?> _mobileReauthRedirectIfNeeded(String location) async {
const allowedWhileLocked = <String>{
'/login',
'/pinPage',
'/verify',
'/mailVerify',
'/sso-login',
'/pinSettingPage',
'/changePin',
};
final session = SessionManager();
if (session.isMobileAppSessionUnlocked) return null;
if (allowedWhileLocked.contains(location)) return null;
final prefs = await SharedPreferences.getInstance();
final skip = prefs.getString('is_mpin_skipped');
return skip == '0' ? '/pinPage' : '/login';
}
/// When not using `-t lib/config/main_uat.dart`, pass e.g. `--dart-define=APP_FLAVOR=uat`
/// so [Environment.flavor] (and logger UAT rules) match the build.
void _applyAppFlavorFromDartDefine() {
const fromDefine = String.fromEnvironment('APP_FLAVOR', defaultValue: '');
switch (fromDefine.toLowerCase()) {
case 'uat':
Environment.flavor = Flavor.uat;
break;
case 'prod':
Environment.flavor = Flavor.prod;
break;
case 'prod1':
Environment.flavor = Flavor.prod1;
break;
case 'dev':
Environment.flavor = Flavor.dev;
break;
default:
break;
}
}
Future<void> startApp() async {
WidgetsFlutterBinding.ensureInitialized();
_applyAppFlavorFromDartDefine();
await TokenService.clearLegacyWebAuthFromSharedPreferences();
// await dotenv.load(fileName: Environment.fileName);
// Initialize prefs before router
final prefs = await SharedPreferences.getInstance();
// ✅ Initial route for mobile vs web
final initialLocation = kIsWeb ? '/login' : '/splash';
// === GoRouter Setup ===
final router = GoRouter(
initialLocation: initialLocation,
routes: [
GoRoute(
path: '/splash', builder: (context, state) => const SplashScreen()),
GoRoute(path: '/login', builder: (context, state) => const login()),
GoRoute(
path: '/sso-login',
builder: (context, state) => const SsoLoginReturnPage(),
),
GoRoute(
path: '/mailVerify',
builder: (context, state) {
final data = state.extra as Map<String, dynamic>;
final type = data['type'] as String;
final value = data['value'] as String;
return MyEmailVerify(type: type, value: value);
},
),
GoRoute(path: '/pinPage', builder: (context, state) => pinPage()),
GoRoute(
path: '/pinSettingPage',
builder: (context, state) => pinSettingPage()),
GoRoute(
path: '/changePin',
builder: (context, state) => changePin(),
),
GoRoute(
path: '/home',
builder: (context, state) => ChatbotHost(
child: Home(),
triggerIntroOnHome: true,
),
),
GoRoute(
path: '/profile',
builder: (context, state) => ChatbotHost(child: profile()),
),
GoRoute(
path: '/help',
builder: (context, state) => ChatbotHost(child: help()),
),
GoRoute(
path: '/claimprocess', builder: (context, state) => ChatbotHost(child: claimprocess()),
),
GoRoute(path: '/wellness', builder: (context, state) => ChatbotHost(child:wellness()),
),
GoRoute(
path: '/privacypolicy', builder: (context, state) => privacypolicy()),
GoRoute(path: '/termsofuse', builder: (context, state) => termsofuse()),
GoRoute(
path: '/generalExclusionsDeductibles',
builder: (context, state) => ChatbotHost(child:generalExclusionsDeductibles()),
),
GoRoute(path: '/tickets', builder: (context, state) => ChatbotHost(child:tickets()),
),
GoRoute(
path: '/policies',
builder: (context, state) {
final arguments =
state.extra as Map<String, dynamic>?; // 👈 receive here
return ChatbotHost(child:policies(arguments: arguments));
},
),
GoRoute(
path: '/claims',
builder: (context, state) {
final int tabIndex = state.extra as int? ?? 0; // default to 0
return ChatbotHost(child: claims(initialTab: tabIndex));
},
),
GoRoute(
path: '/planclaimsform',
builder: (context, state) {
final details = state.extra as Map<String, dynamic>?;
return ChatbotHost(child: planclaimsform(details: details));
},
),
GoRoute(
path: '/retailClaimForm',
builder: (context, state) {
final details = state.extra as Map<String, dynamic>?;
return ChatbotHost(child:retailClaimForm(details: details));
},
),
GoRoute(
path: '/raisedTicketHistory',
builder: (context, state) => ChatbotHost(child:raisedTicketHistory()),
),
GoRoute(
path: '/tickettracklist/:ticketID',
builder: (context, state) {
final ticketID = state.pathParameters['ticketID']!;
return ChatbotHost(child:tickettracklist(ticketID: ticketID));
},
),
// GoRoute(
// path: '/tickettracklist',
// builder: (context, state) {
// final ticketID = state.extra as String; // cast to correct type
// return tickettracklist(ticketID: ticketID);
// },
// ),
GoRoute(
path: '/empDetails',
builder: (context, state) => empDetails(),
),
GoRoute(
path: '/faqs',
builder: (context, state) => ChatbotHost(child: faqs()),
),
GoRoute(
path: '/addOnsDetails', builder: (context, state) => addOnsDetails()),
GoRoute(
path: '/empReviewDetails',
builder: (context, state) => empReviewDetails()),
GoRoute(
path: '/AddPolicyScreen',
builder: (context, state) => AddPolicyScreen()),
GoRoute(
path: '/changePassword',
name: 'changePassword',
builder: (context, state) {
final email = state.uri.queryParameters['email'] ?? '';
final clientId = state.uri.queryParameters['client_id'] ?? '';
return changesPassword(
email: email,
client_id: clientId,
);
},
),
GoRoute(
path: '/setPassword',
name: 'setPassword',
builder: (context, state) {
final email = state.uri.queryParameters['email'] ?? '';
final clientId = state.uri.queryParameters['client_id'] ?? '';
final route = state.uri.queryParameters['route'] ?? '';
return setPassword(
email: email,
client_id: clientId,
route: route,
);
},
),
GoRoute(
path: '/wellnessWebView',
builder: (context, state) {
final url = state.extra as String; // receiving URL
return WellnessWebView(url: url);
},
),
],
// ✅ Middleware hook
redirect: (context, state) async =>
await tokenRedirectLogic(context, state),
);
runApp(
ProviderScope(
child: MyApp(router: router),
),
);
}
class MyApp extends StatefulWidget {
final GoRouter router; // ✅ define router as a field
const MyApp({super.key, required this.router});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
final apiService = ApiService(context);
DataManager().init(apiService);
// DataManager().loadAdvertisementImages();
});
}
@override
Widget build(BuildContext context) {
return MaterialApp.router(
routerConfig: widget.router, // ✅ this now works
debugShowCheckedModeBanner: false,
);
}
}