341 lines
12 KiB
Dart
Executable File
341 lines
12 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:nhance_app_pwa/customAppBar/toastHelper.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/postEnrollment/botman_chat.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/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/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/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/verify.dart';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
import 'models/environment.dart';
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:go_router/go_router.dart';
|
|
// import 'dart:html' as html;
|
|
|
|
// === 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 {
|
|
print('ABCDEFGH');
|
|
const allowedWithoutToken = [
|
|
'/login',
|
|
'/verify',
|
|
'/mailVerify',
|
|
'/pinPage',
|
|
'/splash',
|
|
];
|
|
|
|
final location = state.uri.toString();
|
|
|
|
// ✅ Allow login, verify, splash without token
|
|
if (allowedWithoutToken.contains(location)) return null;
|
|
|
|
// ✅ Check if token exists
|
|
// final hasToken = await TokenService.hasValidToken();
|
|
// if (!hasToken) return '/login';
|
|
final hasToken = await TokenService.hasValidToken();
|
|
print('hasToken : $hasToken');
|
|
if (!hasToken) {
|
|
print('!!!!hasToken : $hasToken');
|
|
await SessionManager().clear();
|
|
// Show toast once
|
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
ToastHelper.showErrorToast(context, 'Session expired. Please login again.');
|
|
});
|
|
return '/login';
|
|
}
|
|
|
|
// ✅ Restore session (decode JWT etc.)
|
|
await SessionManager().restoreSession();
|
|
|
|
// ✅ Mobile mpin check
|
|
// if (!kIsWeb) {
|
|
// final prefs = await SharedPreferences.getInstance();
|
|
// final isMpinSkipped = prefs.getString('is_mpin_skipped');
|
|
// if (isMpinSkipped == '0' && state.uri.toString() != '/pinPage') {
|
|
// return '/pinPage';
|
|
// }
|
|
// }
|
|
|
|
return null; // no redirect
|
|
}
|
|
|
|
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
|
|
await Firebase.initializeApp();
|
|
print("Handling background message: ${message.messageId}");
|
|
}
|
|
|
|
Future<void> main() async {
|
|
WidgetsFlutterBinding.ensureInitialized();
|
|
// final SharedPreferences prefs = await SharedPreferences.getInstance();
|
|
// prefs.clear();
|
|
if (kIsWeb) {
|
|
await Firebase.initializeApp(
|
|
options: const FirebaseOptions(
|
|
// apiKey: 'AIzaSyC4yHbCX4mQu0jO81pJrDwxKLQlTQWofrc',
|
|
// appId: '1:1084115316849:android:68b14c4ff37f4bbc6c6bd0',
|
|
// messagingSenderId: '1084115316849',
|
|
// projectId: 'nhance-ee8d1'
|
|
apiKey: "AIzaSyC4yHbCX4mQu0jO81pJrDwxKLQlTQWofrc",
|
|
authDomain: "nhance-ee8d1.firebaseapp.com",
|
|
projectId: "nhance-ee8d1",
|
|
storageBucket: "nhance-ee8d1.firebasestorage.app",
|
|
messagingSenderId: "1084115316849",
|
|
appId: "1:1084115316849:web:8fc3b1c886349ae86c6bd0"));
|
|
} else {
|
|
await Firebase.initializeApp();
|
|
await FirebaseAppCheck.instance.activate(
|
|
// webProvider: ReCaptchaV3Provider('recaptcha-v3-site-key'),
|
|
androidProvider: AndroidProvider.playIntegrity,
|
|
appleProvider: AppleProvider.appAttest,
|
|
);
|
|
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
|
|
|
|
FirebaseMessaging messaging = FirebaseMessaging.instance;
|
|
// NotificationSettings settings = await messaging.requestPermission();
|
|
NotificationSettings settings =
|
|
await FirebaseMessaging.instance.requestPermission(
|
|
alert: true,
|
|
badge: true,
|
|
sound: true,
|
|
);
|
|
print('User granted permission: ${settings.authorizationStatus}');
|
|
|
|
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
|
|
print('Foreground Message: ${message.notification?.title}');
|
|
});
|
|
|
|
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
|
|
print('User tapped on notification');
|
|
});
|
|
}
|
|
|
|
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) => login()),
|
|
GoRoute(
|
|
path: '/verify',
|
|
builder: (context, state) {
|
|
final extras = state.extra as Map<String, dynamic>?;
|
|
|
|
return MyVerify(
|
|
verificationId: extras?['verificationId'] ?? '',
|
|
mobileNumber: extras?['mobileNumber'] ?? '',
|
|
resendToken: extras?['resendToken'],
|
|
onResendCode: extras?['onResendCode'],
|
|
);
|
|
},
|
|
),
|
|
// GoRoute(
|
|
// path: '/chatbot',
|
|
// builder: (context, state) {
|
|
// final extras = state.extra as Map<String, dynamic>?;
|
|
// return ChatbotWebViewPage(
|
|
// client_branch_id: extras?['client_branch_id'] ?? "",
|
|
// empCodeString: extras?['empCodeString'] ?? "",
|
|
// empName: extras?['empName'] ?? "",
|
|
// empPrimaryId: extras?['empPrimaryId'] ?? "",
|
|
// client_id: extras?['client_id'] ?? "",
|
|
// );
|
|
// },
|
|
// ),
|
|
|
|
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: '/mailVerify',
|
|
// builder: (context, state) {
|
|
// final email = state.extra as String;
|
|
// return MyEmailVerify(email: email);
|
|
// },
|
|
// ),
|
|
// GoRoute(path: '/mailVerify', builder: (context, state) => MyEmailVerify(email: '')),
|
|
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) => Home()),
|
|
GoRoute(path: '/profile', builder: (context, state) => profile()),
|
|
GoRoute(path: '/help', builder: (context, state) => help()),
|
|
GoRoute(path: '/claimprocess', builder: (context, state) => claimprocess()),
|
|
GoRoute(path: '/wellness', builder: (context, state) => wellness()),
|
|
GoRoute(path: '/privacypolicy', builder: (context, state) => privacypolicy()),
|
|
GoRoute(path: '/termsofuse', builder: (context, state) => termsofuse()),
|
|
GoRoute(path: '/generalExclusionsDeductibles', builder: (context, state) => generalExclusionsDeductibles()),
|
|
GoRoute(path: '/raisedTicketHistory', builder: (context, state) => raisedTicketHistory()),
|
|
GoRoute(path: '/tickets', builder: (context, state) => tickets()),
|
|
GoRoute(
|
|
path: '/policies',
|
|
builder: (context, state) {
|
|
final arguments = state.extra as Map<String, dynamic>?; // 👈 receive here
|
|
return policies(arguments: arguments);
|
|
},
|
|
),
|
|
GoRoute(
|
|
path: '/claims',
|
|
builder: (context, state) {
|
|
final int tabIndex = state.extra as int? ?? 1 ; // default to 0
|
|
return claims(initialTab: tabIndex);
|
|
},
|
|
),
|
|
GoRoute(
|
|
path: '/planclaimsform',
|
|
builder: (context, state) {
|
|
final details = state.extra as Map<String, dynamic>?;
|
|
return planclaimsform(details: details);
|
|
},
|
|
),
|
|
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: '/addOnsDetails', builder: (context, state) => addOnsDetails()),
|
|
GoRoute(path: '/empReviewDetails', builder: (context, state) => empReviewDetails()),
|
|
],
|
|
|
|
// ✅ Middleware hook
|
|
redirect: (context, state) async =>
|
|
await tokenRedirectLogic(context, state),
|
|
);
|
|
// ✅ Load API data once at startup
|
|
// runApp(
|
|
// Builder(
|
|
// builder: (context) {
|
|
// final apiService = ApiService(context); // ✅ context is available here
|
|
// DataManager().init(apiService);
|
|
// DataManager().loadAdvertisementImages(); // load once
|
|
//
|
|
// return MyApp(router: router);
|
|
// },
|
|
// ),
|
|
// );
|
|
runApp(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,
|
|
);
|
|
}
|
|
}
|