retail and chnages done

This commit is contained in:
Surendiran 2025-12-15 14:28:48 +05:30
parent 45eb1d4c36
commit 6de1ea4a49
67 changed files with 10821 additions and 3936 deletions

6
.env
View File

@ -1,6 +0,0 @@
API_URL=https://venbait.in/nhance/dev/employeeRest/
chatbot_Url=https://venbait.in/nhance/dev/chatbot
API_URL_Enrollment=https://venbait.in/enrollment/employeeRest/
TICKET_API_URL=https://venbait.in/nhance/dev/api
BASE_HREF=/nhance/app/dev/
ENV=development

View File

@ -1,6 +0,0 @@
API_URL=https://venbait.in/nhance/dev/employeeRest/
chatbot_Url=https://venbait.in/nhance/dev/chatbot
API_URL_Enrollment=https://venbait.in/enrollment/employeeRest/
TICKET_API_URL=https://venbait.in/nhance/dev/api
BASE_HREF=/nhance/app/dev/
ENV=development

View File

@ -1,6 +0,0 @@
API_URL=https://app.nhanceindia.in/zenith/employeeRest/
API_URL_Enrollment=https://app.nhanceindia.in/enrolment/employeeRest/
TICKET_API_URL=https://app.nhanceindia.in/zenith/api
chatbot_Url=https://app.nhanceindia.in/zenith/chatbot
BASE_HREF=/app/
ENV=production

View File

@ -1,6 +0,0 @@
API_URL=https://app.nhanceindia.in/zenith/employeeRest/
API_URL_Enrollment=https://app.nhanceindia.in/enrolment/employeeRest/
TICKET_API_URL=https://app.nhanceindia.in/zenith/api
chatbot_Url=https://app.nhanceindia.in/zenith/chatbot
BASE_HREF=/app/
ENV=production

View File

@ -1,6 +0,0 @@
API_URL=https://app.nhanceindia.in/zenith/employeeRest/
API_URL_Enrollment=https://app.nhanceindia.in/enrolment/employeeRest/
TICKET_API_URL=https://app.nhanceindia.in/zenith/api
chatbot_Url=https://app.nhanceindia.in/zenith/chatbot
BASE_HREF=/app/
ENV=production

View File

@ -19,12 +19,12 @@ if (project.hasProperty('google-services.json')) {
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '44'
flutterVersionCode = '45'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '2.0.6'
flutterVersionName = '2.0.7'
}
def keystoreProperties = new Properties()
@ -104,6 +104,23 @@ android {
enableSplit = true // Ensures a proper split per architecture
}
}
flavorDimensions "app"
productFlavors {
dev {
dimension "app"
// no suffix
}
uat {
dimension "app"
// no suffix
}
prod {
dimension "app"
// no suffix
}
}
}
flutter {

BIN
assets/cardBG.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 221 KiB

BIN
assets/nhance.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

BIN
assets/retail.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 826 KiB

View File

@ -1,19 +0,0 @@
#!/bin/bash
# Define the path to the .env file for development
ENV_FILE_PATH=".env.development"
# Check if the .env file exists
if [ ! -f $ENV_FILE_PATH ]; then
echo "$ENV_FILE_PATH does not exist"
exit 1
fi
# Copy the .env file for development to .env
cp $ENV_FILE_PATH .env
# Build the APK for development
flutter build apk --debug
# Optionally, remove the .env file after the build
# rm .env

View File

@ -1,19 +0,0 @@
#!/bin/bash
# Define the path to the .env file for production
ENV_FILE_PATH=".env.production"
# Check if the .env file exists
if [ ! -f $ENV_FILE_PATH ]; then
echo "$ENV_FILE_PATH does not exist"
exit 1
fi
# Copy the .env file for production to .env
cp $ENV_FILE_PATH .env
# Build the APK for production
flutter build apk --release
# Optionally, remove the .env file after the build
# rm .env

View File

@ -1,19 +0,0 @@
#!/bin/bash
# Define the path to the .env file for testing
ENV_FILE_PATH=".env.test"
# Check if the .env file exists
if [ ! -f $ENV_FILE_PATH ]; then
echo "$ENV_FILE_PATH does not exist"
exit 1
fi
# Copy the .env file for testing to .env
cp $ENV_FILE_PATH .env
# Build the APK for testing
flutter build apk --debug
# Optionally, remove the .env file after the build
# rm .env

View File

@ -1,40 +0,0 @@
#!/bin/bash
# Define the path to the .env.development file
ENV_FILE_PATH=".env.development"
# Check if the .env.development file exists
if [ ! -f $ENV_FILE_PATH ]; then
echo "$ENV_FILE_PATH does not exist"
exit 1
fi
# Copy the .env.development file to .env
cp $ENV_FILE_PATH .env
echo "Copied $ENV_FILE_PATH to .env"
# Source the .env file to load the environment variables
source .env
# Check if the required variables are set
if [ -z "$BASE_HREF" ] || [ -z "$API_URL" ] || [ -z "$TICKET_API_URL" ]; then
echo "Environment variables not set correctly in .env"
exit 1
fi
# Print the loaded variables for verification
echo "Loaded BASE_HREF: $BASE_HREF"
echo "Loaded API_URL: $API_URL"
echo "Loaded TICKET_API_URL: $TICKET_API_URL"
echo "Loaded ticketToken: $ticketToken"
# Build the web app for development with base href
flutter build web --release --base-href "$BASE_HREF"
# Check if the build was successful
if [ $? -ne 0 ]; then
echo "Flutter dev build failed"
exit 1
fi
echo "Flutter dev build succeeded"

View File

@ -1,39 +0,0 @@
#!/bin/bash
# Define the path to the .env.production file
ENV_FILE_PATH=".env.production"
# Check if the .env.production file exists
if [ ! -f $ENV_FILE_PATH ]; then
echo "$ENV_FILE_PATH does not exist"
exit 1
fi
# Copy the .env.production file to .env
cp $ENV_FILE_PATH .env
echo "Copied $ENV_FILE_PATH to .env"
# Source the .env file to load the environment variables
source .env
# Check if the required variables are set
if [ -z "$BASE_HREF" ] || [ -z "$API_URL" ] || [ -z "$TICKET_API_URL" ]; then
echo "Environment variables not set correctly in .env"
exit 1
fi
# Print the loaded variables for verification
echo "Loaded BASE_HREF: $BASE_HREF"
echo "Loaded API_URL: $API_URL"
echo "Loaded TICKET_API_URL: $TICKET_API_URL"
# Build the web app for production with base href
flutter build web --release --base-href "$BASE_HREF"
# Check if the build was successful
if [ $? -ne 0 ]; then
echo "Flutter PRODUCTION build failed"
exit 1
fi
echo "Flutter PRODUCTION build succeeded"

View File

@ -1,39 +0,0 @@
#!/bin/bash
# Define the path to the .env.test file
ENV_FILE_PATH=".env.test"
# Check if the .env.test file exists
if [ ! -f $ENV_FILE_PATH ]; then
echo "$ENV_FILE_PATH does not exist"
exit 1
fi
# Copy the .env.test file to .env
cp $ENV_FILE_PATH .env
echo "Copied $ENV_FILE_PATH to .env"
# Source the .env file to load the environment variables
source .env
# Check if the required variables are set
if [ -z "$BASE_HREF" ] || [ -z "$API_URL" ] || [ -z "$TICKET_API_URL" ]; then
echo "Environment variables not set correctly in .env"
exit 1
fi
# Print the loaded variables for verification
echo "Loaded BASE_HREF: $BASE_HREF"
echo "Loaded API_URL: $API_URL"
echo "Loaded TICKET_API_URL: $TICKET_API_URL"
# Build the web app for the test environment with base href
flutter build web --release --base-href "$BASE_HREF"
# Check if the build was successful
if [ $? -ne 0 ]; then
echo "Flutter test build failed"
exit 1
fi
echo "Flutter test build succeeded"

View File

@ -1,39 +0,0 @@
#!/bin/bash
# Define the path to the .env.uat file
ENV_FILE_PATH=".env.uat"
# Check if the .env.uat file exists
if [ ! -f $ENV_FILE_PATH ]; then
echo "$ENV_FILE_PATH does not exist"
exit 1
fi
# Copy the .env.uat file to .env
cp $ENV_FILE_PATH .env
echo "Copied $ENV_FILE_PATH to .env"
# Source the .env file to load the environment variables
source .env
# Check if the required variables are set
if [ -z "$BASE_HREF" ] || [ -z "$API_URL" ] || [ -z "$TICKET_API_URL" ]; then
echo "Environment variables not set correctly in .env"
exit 1
fi
# Print the loaded variables for verification
echo "Loaded BASE_HREF: $BASE_HREF"
echo "Loaded API_URL: $API_URL"
echo "Loaded TICKET_API_URL: $TICKET_API_URL"
# Build the web app for UAT with base href
flutter build web --release --base-href "$BASE_HREF"
# Check if the build was successful
if [ $? -ne 0 ]; then
echo "Flutter UAT build failed"
exit 1
fi
echo "Flutter UAT build succeeded"

View File

View File

View File

View File

@ -0,0 +1,69 @@
// lib/environment.dart
enum Flavor { dev, uat, prod, prod1 }
class Environment {
static Flavor flavor = Flavor.dev; // overwritten by each main_*.dart
static bool get isProd => flavor == Flavor.prod || flavor == Flavor.prod1;
static String get apiUrl {
switch (flavor) {
case Flavor.dev:
return "https://venbait.in/nhance/dev/employeeRest/";
case Flavor.uat:
return "https://appstage.nhanceindia.in/nexus/employeeRest/";
case Flavor.prod:
return "https://app.nhanceindia.in/zenith/employeeRest/";
case Flavor.prod1:
return "https://app.nhanceindia.in/zenith/employeeRest/";
}
}
// static String get ticketApiUrl {
// switch (flavor) {
// case Flavor.dev:
// return "https://venbait.in/nhance/dev/api";
// case Flavor.uat:
// return "https://uat.nhanceindia.in/zenith/api";
// case Flavor.prod:
// return "https://app.nhanceindia.in/zenith/api";
// }
// }
static String get apiUrlEnrollment {
switch (flavor) {
case Flavor.dev:
return "https://venbait.in/enrollment/employeeRest/";
case Flavor.uat:
return "https://appstage.nhanceindia.in/apex/employeeRest/";
case Flavor.prod:
return "https://app.nhanceindia.in/enrolment/employeeRest/";
case Flavor.prod1:
return "https://app.nhanceindia.in/enrolment/employeeRest/";
}
}
// static String get chatbotUrl {
// switch (flavor) {
// case Flavor.dev:
// return "https://venbait.in/nhance/dev/chatbot";
// case Flavor.uat:
// return "https://uat.nhanceindia.in/zenith/chatbot";
// case Flavor.prod:
// return "https://app.nhanceindia.in/zenith/chatbot";
// }
// }
static String get baseHref {
switch (flavor) {
case Flavor.dev:
return "/nhance/app/dev/";
case Flavor.uat:
return "/";
case Flavor.prod:
return "/app/";
case Flavor.prod1:
return "/";
}
}
}

9
lib/config/main_dev.dart Normal file
View File

@ -0,0 +1,9 @@
import '../main.dart';
import 'environment.dart';
Future<void> main() async {
Environment.flavor = Flavor.dev;
await startApp();
}

10
lib/config/main_prod.dart Normal file
View File

@ -0,0 +1,10 @@
import '../main.dart';
import 'environment.dart';
Future<void> main() async {
Environment.flavor = Flavor.prod;
await startApp();
}

View File

@ -0,0 +1,10 @@
import '../main.dart';
import 'environment.dart';
Future<void> main() async {
Environment.flavor = Flavor.prod1;
await startApp();
}

10
lib/config/main_uat.dart Normal file
View File

@ -0,0 +1,10 @@
import '../main.dart';
import 'environment.dart';
Future<void> main() async {
Environment.flavor = Flavor.uat;
await startApp();
}

View File

@ -20,20 +20,37 @@ class _CustomAppBarState extends State<CustomAppBar> {
Size get preferredSize => Size.fromHeight(kToolbarHeight);
late ApiService apiService;
final session = SessionManager();
bool isRetailLoggedIn = false;
@override
void initState() {
super.initState();
apiService = ApiService(context);
checkRetailOrNot();
}
checkRetailOrNot() async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
isRetailLoggedIn = prefs.getBool('isRetailLoggedIn') ?? false;
print('isRetailLoggedIn Navbar $isRetailLoggedIn');
}
void handleMenuTap(VoidCallback? action) {
if (isRetailLoggedIn) {
return;
}
action?.call();
}
Future<void> logout(BuildContext context) async {
final prefs = await SharedPreferences.getInstance();
final String? token = prefs.getString('_postToken');
final String? token = prefs.getString('post_token');
if (token != null && token.isNotEmpty) {
await prefs.clear();
context.go('/phone');
context.go('/login');
// Navigator.pushNamed(context, 'phone');
}
}
@ -41,6 +58,7 @@ class _CustomAppBarState extends State<CustomAppBar> {
@override
Widget build(BuildContext context) {
final sw = MediaQuery.of(context).size.width;
return Scaffold(
backgroundColor: Color(0xFFFFFCE5), // Set background color for AppBar
appBar: PreferredSize(
@ -89,38 +107,42 @@ class _CustomAppBarState extends State<CustomAppBar> {
children: [
NavBarItem(
text: "Home",
onTap: () {
onTap: () => handleMenuTap(() {
context.push('/home');
},
}),
),
NavBarItem(
text: "Claims",
onTap: () {
onTap: () => handleMenuTap(() {
context.push('/claims');
},
}),
),
NavBarItem(
text: "Help",
onTap: () {
onTap: () => handleMenuTap(() {
context.push('/help');
},
),
NavBarItem(
text: "Wellness",
onTap: () {
// context.push('/wellness');
// Wellness tab clicked show popup
PopupHelper.showRedirectPopup(
context: context,
apiService: apiService,
empPrimaryId: session.empPrimaryId,
);
},
}),
),
// NavBarItem(
// text: "Wellness",
// onTap: () => handleMenuTap(() {
// PopupHelper.showRedirectPopup(
// context: context,
// apiService: apiService,
// empPrimaryId: session.empPrimaryId,
// );
// }),
// ),
NavBarItem(
text: "Profile",
onTap: () {
onTap: () => handleMenuTap(() {
context.push('/profile');
}),
),
NavBarItem(
text: "Logout",
onTap: () {
logout(context);
},
),
],

View File

@ -9,7 +9,8 @@ import 'package:nhance_app_pwa/customAppBar/responsive.dart';
import 'package:nhance_app_pwa/customAppBar/toastHelper.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../models/environment.dart';
import '../config/environment.dart';
import '../models/platform_helper_mobile.dart'
if (dart.library.html) '../models/platform_helper_other.dart';
import '../pages/postEnrollment/service/api_service.dart';
@ -179,107 +180,85 @@ class _CustomAppBarState extends State<CustomAppBar> {
preferredSize: widget.preferredSize,
child: SafeArea(
child: Container(
padding: Responsive.isDesktop(context)
? EdgeInsets.symmetric(horizontal: 16.0)
: EdgeInsets.symmetric(horizontal: 0),
padding: EdgeInsets.symmetric(
horizontal: MediaQuery.of(context).size.width *
(Responsive.isDesktop(context) ? 0.03 : 0.02),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
// Logo Column
Expanded(
flex: Responsive.isDesktop(context) ? 3 : 9,
child: Row(
mainAxisAlignment: Responsive.isDesktop(context)
? MainAxisAlignment.spaceEvenly
: MainAxisAlignment.start,
children: [
Container(
margin: EdgeInsets.only(top: 10, bottom: 10),
width: Responsive.isDesktop(context) ? 150 : 130,
height: Responsive.isDesktop(context) ? 150 : 130,
child: Image.asset(
'assets/nhance_client_logo.png',
fit: BoxFit.contain,
),
Row(
mainAxisAlignment: Responsive.isDesktop(context)
? MainAxisAlignment.spaceEvenly
: MainAxisAlignment.start,
children: [
Container(
margin: EdgeInsets.only(top: 10, bottom: 10),
width: 150,
height: 150,
child: Image.asset(
'assets/nhance_client_logo.png',
fit: BoxFit.contain,
),
],
),
),
],
),
// AdaptiveNavBar Column
if (!isTokenAvailable)
Expanded(
flex: Responsive.isDesktop(context) ? 9 : 3,
child: AdaptiveNavBar(
screenWidth: sw,
backgroundColor: Color(0xFFFFFCE5),
leading:
Container(), // Set an empty container as we have the logo separately
title: Text(''),
navBarItems: [
if (Responsive.isDesktop(context))
NavBarItem(
text: "",
onTap: () {
// Navigator.pushNamed(context, 'oldPolicy');
},
),
if (!isTokenAvailable)
NavBarItem(
text: "Logout",
onTap: () async {
logout(context);
},
),
],
Row(
mainAxisSize: MainAxisSize.min,
children: [
NavBarItem(
text: "Logout",
onTap: () async {
logout(context);
},
),
),
],
),
// if (empStatus == 'enrolled')
if (isTokenAvailable)
Expanded(
flex: Responsive.isDesktop(context) ? 9 : 3,
child: AdaptiveNavBar(
screenWidth: sw,
backgroundColor: const Color(0xFFFFFBDE),
leading:
Container(), // Set an empty container as we have the logo separately
title: Text(''),
navBarItems: [
NavBarItem(
text: "Home",
onTap: () {
context.push('/home');
},
),
NavBarItem(
text: "Claims",
onTap: () {
context.push('/claims');
},
),
NavBarItem(
text: "Help",
onTap: () {
context.push('/help');
},
),
NavBarItem(
text: "Wellness",
onTap: () {
// Wellness tab clicked show popup
PopupHelper.showRedirectPopup(
context: context,
apiService: apiService,
empPrimaryId: session.empPrimaryId,
);
},
),
NavBarItem(
text: "Profile",
onTap: () {
context.push('/profile');
},
),
],
),
Row(
mainAxisSize: MainAxisSize.min,
children: [
NavBarItem(
text: "Home",
onTap: () {
context.push('/home');
},
),
NavBarItem(
text: "Claims",
onTap: () {
context.push('/claims');
},
),
NavBarItem(
text: "Help",
onTap: () {
context.push('/help');
},
),
NavBarItem(
text: "Wellness",
onTap: () {
// context.push('/wellness');
// Wellness tab clicked show popup
PopupHelper.showRedirectPopup(
context: context,
apiService: apiService,
empPrimaryId: session.empPrimaryId,
);
},
),
NavBarItem(
text: "Profile",
onTap: () {
context.push('/profile');
},
),
],
),
],
),
@ -289,3 +268,33 @@ class _CustomAppBarState extends State<CustomAppBar> {
);
}
}
class NavBarItem extends StatelessWidget {
final String text;
final VoidCallback? onTap;
const NavBarItem({
Key? key,
required this.text,
this.onTap,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return InkWell(
borderRadius: BorderRadius.circular(6),
onTap: onTap,
hoverColor: const Color(0xFFF4F3E7), // subtle hover background
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
child: Text(
text,
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
color: Colors.black87,
),
),
),
);
}
}

View File

@ -10,6 +10,7 @@ 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/AddPolicyScreen.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';
@ -21,6 +22,7 @@ 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';
@ -37,9 +39,10 @@ import 'package:nhance_app_pwa/pages/setPassword.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 'config/environment.dart';
// import 'dart:html' as html;
// === Splash (only for mobile) ===
@ -118,69 +121,15 @@ Future<String?> tokenRedirectLogic(
// 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 {
Future<void> startApp() 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);
// await dotenv.load(fileName: Environment.fileName);
// Initialize prefs before router
final prefs = await SharedPreferences.getInstance();
@ -195,32 +144,7 @@ Future<void> main() async {
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',
@ -233,14 +157,7 @@ Future<void> main() async {
},
),
// 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',
@ -261,9 +178,7 @@ Future<void> main() async {
GoRoute(
path: '/generalExclusionsDeductibles',
builder: (context, state) => generalExclusionsDeductibles()),
GoRoute(
path: '/raisedTicketHistory',
builder: (context, state) => raisedTicketHistory()),
GoRoute(path: '/tickets', builder: (context, state) => tickets()),
GoRoute(
path: '/policies',
@ -288,12 +203,29 @@ Future<void> main() async {
},
),
GoRoute(
path: '/tickettracklist',
path: '/retailClaimForm',
builder: (context, state) {
final ticketID = state.extra as String; // cast to correct type
final details = state.extra as Map<String, dynamic>?;
return retailClaimForm(details: details);
},
),
GoRoute(
path: '/raisedTicketHistory',
builder: (context, state) => raisedTicketHistory()),
GoRoute(
path: '/tickettracklist/:ticketID',
builder: (context, state) {
final ticketID = state.pathParameters['ticketID']!;
return 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(),
@ -303,6 +235,9 @@ Future<void> main() async {
GoRoute(
path: '/empReviewDetails',
builder: (context, state) => empReviewDetails()),
GoRoute(
path: '/AddPolicyScreen',
builder: (context, state) => AddPolicyScreen()),
GoRoute(
path: '/changePassword',
name: 'changePassword',
@ -344,18 +279,7 @@ Future<void> main() async {
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));
}
@ -376,7 +300,7 @@ class _MyAppState extends State<MyApp> {
WidgetsBinding.instance.addPostFrameCallback((_) {
final apiService = ApiService(context);
DataManager().init(apiService);
DataManager().loadAdvertisementImages();
// DataManager().loadAdvertisementImages();
});
}

View File

@ -1,52 +0,0 @@
import 'package:flutter_dotenv/flutter_dotenv.dart';
class Environment {
static String get fileName {
const String env =
String.fromEnvironment('ENV', defaultValue: 'development');
switch (env) {
case 'production':
return '.env.production';
case 'test':
return '.env.test';
case 'uat':
return '.env.uat';
default:
return '.env.development';
}
}
static String get apiUrl {
return dotenv.env['API_URL'] ?? 'API_URL not found!';
}
static String get apiUrlEnrollment {
return dotenv.env['API_URL_Enrollment'] ?? 'API_URL not found!';
}
static String get chatBotUrl {
return dotenv.env['chatbot_Url'] ?? 'CHAT_BOT_URL not found!';
}
static String get baseHref {
return dotenv.env['BASE_HREF'] ?? 'BASE_HREF not found!';
}
static String get env {
return dotenv.env['ENV'] ?? 'ENV not found!';
}
static String get apiUrlTicket {
return dotenv.env['TICKET_API_URL'] ?? 'TICKET_API_URL not found!';
}
//Live
static String get ticketToken {
return dotenv.env['ticketToken'] ?? 'TICKET_API_URL not found!';
}
//Dev
// static String get ticketToken {
// return 'uncp8FvG310bEyYdV9MmStlo7KDRZ65fLWTeXCI2JzwPrNHjBqQhUiAgxsaO';
// }
}

View File

@ -10,9 +10,9 @@ import 'package:nhance_app_pwa/pages/service/SessionManager.dart';
import 'dart:io';
import 'package:google_fonts/google_fonts.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../config/environment.dart';
import '../customAppBar/responsive.dart';
import '../customAppBar/toastHelper.dart';
import '../models/environment.dart';
class changesPassword extends StatefulWidget {
final String email;
@ -91,6 +91,7 @@ class _changesPasswordState extends State<changesPassword> {
body: json.encode(payload),
headers: {
HttpHeaders.contentTypeHeader: 'application/json',
'APP-SIGNATURE': 'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y',
},
);

View File

@ -8,6 +8,7 @@ import 'package:google_fonts/google_fonts.dart';
import 'package:nhance_app_pwa/pages/postEnrollment/service/api_service.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:pinput/pinput.dart';
import 'dart:async';
import 'package:flutter/gestures.dart';
@ -17,10 +18,10 @@ import 'dart:io';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:jwt_decode/jwt_decode.dart';
import '../config/environment.dart';
import '../customAppBar/responsive.dart';
import '../customAppBar/toastHelper.dart';
import '../models/environment.dart';
import '../models/platform_helper_mobile.dart'
import '../models/platform_helper_mobile.dart'
if (dart.library.html) '../models/platform_helper_other.dart';
// import 'dart:html' as html;
@ -75,6 +76,7 @@ class _MyEmailVerifyState extends State<MyEmailVerify> {
dynamic empMobileNo;
dynamic empEmailid;
late SessionManager session;
final dataManager = DataManager();
@override
void initState() {
@ -165,6 +167,7 @@ class _MyEmailVerifyState extends State<MyEmailVerify> {
headers: {
HttpHeaders.contentTypeHeader: 'application/json',
'Authorization': 'Bearer $_preToken',
'APP-SIGNATURE': 'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y',
},
);
@ -212,6 +215,7 @@ class _MyEmailVerifyState extends State<MyEmailVerify> {
body: json.encode(payload),
headers: {
HttpHeaders.contentTypeHeader: 'application/json',
'APP-SIGNATURE': 'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y',
},
);
print('response : ${response.statusCode}');
@ -231,6 +235,14 @@ class _MyEmailVerifyState extends State<MyEmailVerify> {
return; // stop execution
}
if (data['status'] == 'OTP is required') {
final SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.clear();
ToastHelper.showErrorToast(context, data['message'] ?? 'OTP is required');
print('API error → ${data['message']}');
return; // stop execution
}
// --- Extract tokens safely ---
String? preToken;
if (data['data'] is String) {
@ -327,6 +339,13 @@ class _MyEmailVerifyState extends State<MyEmailVerify> {
await SessionManager().initializeFromPostToken(post['data']);
session = await SessionManager();
if (session.client_id != null && session.client_id!.isNotEmpty) {
await dataManager.loadSelfEmployeeProfile(
clientId: session.client_id!,
empCode: session.empCodeString!,
clientBranchId: session.empClientBranchId!,
);
}
// // Decode the JWT token received from the API response
// Map<String, dynamic>? decodedToken = Jwt.parseJwt(post['data']);
@ -424,6 +443,8 @@ class _MyEmailVerifyState extends State<MyEmailVerify> {
// int skipStatus = prefs.getInt('skipStatus') ?? 1;
// final mpinText = prefs.getString('mpinText');
// print(isMobilePlatform());
if (isMobilePlatform()) {
// if (prefs.containsKey('mpin') && mpinText == 'Mpin - exist') {
if (_postToken != null && _postToken.isNotEmpty) {
@ -439,10 +460,20 @@ class _MyEmailVerifyState extends State<MyEmailVerify> {
// }
} else {
if (_postToken != null && _postToken.isNotEmpty) {
// final SharedPreferences prefs = await SharedPreferences.getInstance();
final SharedPreferences prefs = await SharedPreferences.getInstance();
// prefs.setString('empEmailid', widget.email);
ToastHelper.showSuccessToast(context, 'Successfully Login');
checkPassword(context,session.empEmailCorporate,session.client_id,'home');
ToastHelper.showSuccessToast(context, 'Successfully Logged In');
if (session.client_id != null && session.client_id!.isNotEmpty) {
prefs.setBool('isRetailLoggedIn', false);
checkPassword(context, session.empEmailCorporate, session.client_id, 'home');
} else {
if (session.client_id == null || session.client_id!.isEmpty ||
session.empCodeString == null || session.empCodeString!.isEmpty ||
session.empClientBranchId == null || session.empClientBranchId!.isEmpty) {
prefs.setBool('isRetailLoggedIn', true);
}
context.go('/home');
}
// if (emp_status == 'enrolled' || emp_status == 'active') {
// context.go('/home');
// Navigator.pushReplacementNamed(context, 'home');
@ -498,7 +529,7 @@ class _MyEmailVerifyState extends State<MyEmailVerify> {
// }
} else {
if (_preToken != null && _preToken.isNotEmpty) {
ToastHelper.showSuccessToast(context, 'Successfully Login');
ToastHelper.showSuccessToast(context, 'Successfully Logged In');
checkPassword(context,session.enrollmentEmailCorporate,session.enrollmentClient_id,'empDetails');
// if (emp_status == 'enrolled' || emp_status == 'active') {
// Navigator.pushReplacementNamed(context, 'home');
@ -536,6 +567,7 @@ class _MyEmailVerifyState extends State<MyEmailVerify> {
body: json.encode(payload),
headers: {
HttpHeaders.contentTypeHeader: 'application/json',
'APP-SIGNATURE': 'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y',
},
);
@ -588,6 +620,7 @@ class _MyEmailVerifyState extends State<MyEmailVerify> {
body: json.encode(params),
headers: {
HttpHeaders.contentTypeHeader: 'application/json',
'APP-SIGNATURE': 'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y',
},
);
@ -612,7 +645,7 @@ class _MyEmailVerifyState extends State<MyEmailVerify> {
}
if (_postToken != null && _postToken.isNotEmpty) {
ToastHelper.showSuccessToast(context, 'Successfully Login');
ToastHelper.showSuccessToast(context, 'Successfully Logged In');
context.go('/home');
// Navigator.pushReplacementNamed(context, 'home');
} else {
@ -660,6 +693,7 @@ class _MyEmailVerifyState extends State<MyEmailVerify> {
body: json.encode(params),
headers: {
HttpHeaders.contentTypeHeader: 'application/json',
'APP-SIGNATURE': 'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y',
},
);
@ -697,6 +731,7 @@ class _MyEmailVerifyState extends State<MyEmailVerify> {
headers: {
'Authorization':
'Bearer $_preToken', // Add token to the Authorization header
'APP-SIGNATURE': 'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y',
},
);
if (response.statusCode == 200) {
@ -918,7 +953,7 @@ class _MyEmailVerifyState extends State<MyEmailVerify> {
child: Align(
alignment: Responsive
.isDesktop(context)
? Alignment.centerLeft
? Alignment.center
: Alignment
.bottomCenter, // Align to the start
child: _size.width <= 1100

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -61,39 +61,20 @@ class _empReviewDetailsState extends State<empReviewDetails> {
dynamic gpaSelfRelationship;
dynamic gpaSelfDetails;
dynamic gpaECardDownload;
dynamic gpaGstValue;
dynamic gpaSiPremiumValue;
dynamic gpaIsPremiumSummery;
dynamic gpaTotalableValue;
late bool isValueValid;
dynamic gpaTotalAmt;
dynamic gmcTotalAmt;
dynamic gmcGstValue;
dynamic gmcSiPremiumValue;
dynamic gmcTotalableValue;
late bool gmcIsValueValid;
dynamic gmcECardDownload;
dynamic gmcIsPremiumSummery;
dynamic gmcDisclaimer;
dynamic gmcClintPolicyId = 0;
dynamic gmcMappedFamilyFloaters = [];
dynamic gmcSelfName;
dynamic gmcSelfDob;
dynamic gmcSelfRelationship;
dynamic gmcSelfDetails;
dynamic gmcPolicyName;
dynamic gmcPolicyType;
dynamic gmcNotes;
dynamic gmcSumInsured;
dynamic gmcTypeName;
dynamic clientName;
dynamic clientLogo;
dynamic addOnsDependentMappedFamilyFloatersArray;
dynamic addOnsDependentClientPolicyId;
dynamic gmcAddOnsselectedSI;
dynamic gmcAddOnsselectedDependent;
dynamic gmcFloaterTextDescription;
dynamic gmcFloaterTextHeading;
dynamic dependentValue;
dynamic siValue;
late int addOnsDependentSumInsured;
@ -169,7 +150,6 @@ class _empReviewDetailsState extends State<empReviewDetails> {
bool gmchasPremiumSummary = false;
List<Map<String, dynamic>> allDisclaimer =
[]; // Declare this to store all disclaimers
late List<bool> checkboxValues;
bool isTokenAvailable = false;
bool isEnrollCompletedStatus = false;
final session = SessionManager();
@ -184,7 +164,7 @@ class _empReviewDetailsState extends State<empReviewDetails> {
isLoading = false;
});
});
checkboxValues = List<bool>.filled(allDisclaimer.length, false);
// checkboxValues = List<bool>.filled(allDisclaimer.length, false);
getTokenStatus();
}
@ -1368,8 +1348,7 @@ class _empReviewDetailsState extends State<empReviewDetails> {
@override
Widget build(BuildContext context) {
if ((gpaMappedFamilyFloaters == [] && gpaMappedFamilyFloaters == null) &&
(gmcMappedFamilyFloaters == [] && gmcMappedFamilyFloaters == null)) {
if (gpaDataIsEmpty == 0 && gmcDataIsEmpty == 0) {
return PopScope(
canPop: false,
onPopInvokedWithResult: (didPop, result) {
@ -3380,6 +3359,14 @@ class _empReviewDetailsState extends State<empReviewDetails> {
}
}
double toDoubleSafe(dynamic value) {
if (value == null) return 0.0;
if (value is num) return value.toDouble();
if (value is String) return double.tryParse(value) ?? 0.0;
return 0.0;
}
List<Widget> generateGpaCards(List<dynamic> data) {
List<Widget> cards = [];
@ -3390,37 +3377,70 @@ class _empReviewDetailsState extends State<empReviewDetails> {
String? gpaPolicyName = item['Policy_Name'];
String? gpaPolicyType = item['type'];
String? gpaECardDownload = item['eCardDownload'];
gpaGstValue = item['si_gst_value'];
gpaSiPremiumValue = item['si_premium_value'];
setState(() {
gpaIsPremiumSummery = item['is_premium_summery'];
});
gpaTotalableValue = gpaSiPremiumValue + gpaGstValue;
isValueValid = (gpaSiPremiumValue != 0 && gpaGstValue != 0);
String? gpaSumInsured;
print('GPA Disclaimer $allDisclaimer');
setState(() {
checkboxValues = List.generate(allDisclaimer.length, (_) => false);
});
double gpaGstValue = toDoubleSafe(item['si_gst_value']);
double gpaSiPremiumValue = toDoubleSafe(item['si_premium_value']);
List<dynamic> gpaMappedFamilyFloaters = [];
// bool gpaIsPremiumSummery = item['is_premium_summery'] ?? false;
bool gpaIsPremiumSummery = false;
dynamic summery = item['is_premium_summery'];
if (item['mapped_family_floaters'] != null) {
gpaMappedFamilyFloaters = [item['mapped_family_floaters']];
if (summery is bool) {
gpaIsPremiumSummery = summery;
} else if (summery is String) {
gpaIsPremiumSummery = (summery == "1");
} else if (summery is int) {
gpaIsPremiumSummery = (summery == 1);
}
dynamic getTrueObjects = gpaMappedFamilyFloaters
double gpaTotalableValue = gpaSiPremiumValue + gpaGstValue;
bool isValueValid = (gpaSiPremiumValue != 0 && gpaGstValue != 0);
String? gpaSumInsured;
print('GPA Disclaimer $allDisclaimer');
// local checkbox list
List<bool> checkboxValues =
List<bool>.generate(allDisclaimer.length, (_) => false);
// ---------------------------------------------
// FIX: mapped_family_floaters is ALREADY A LIST
// ---------------------------------------------
List<dynamic> gpaMappedFamilyFloaters =
item['mapped_family_floaters'] is List
? item['mapped_family_floaters']
: [];
// ---------------------------------------------
// Filter TRUE objects
// ---------------------------------------------
List<dynamic> getTrueObjects = gpaMappedFamilyFloaters
.where((element) => element['is_value_exist'] == true)
.toList();
if (getTrueObjects.length > 0) {
// ---------------------------------------------
// FIX: safe selection of Sum Insured
// ---------------------------------------------
if (getTrueObjects.isNotEmpty) {
gpaSumInsured = getTrueObjects[0]["data"]["basic_cover_si"];
} else {
gpaSumInsured = item['Policy_Terms']['sumInsured2'];
gpaSumInsured = item['Policy_Terms']?['sumInsured2'];
}
int gpaOpenForEnrollment = int.parse(item['OpenForEnrollment']);
// ---------------------------------------------
// FIX: OpenForEnrollment can be int or String
// ---------------------------------------------
int gpaOpenForEnrollment = 0;
dynamic enroll = item['OpenForEnrollment'];
if (enroll is int) {
gpaOpenForEnrollment = enroll;
} else if (enroll is String) {
gpaOpenForEnrollment = int.tryParse(enroll) ?? 0;
}
List<Widget> familyFloaterContainers = [];
for (var floater in gpaMappedFamilyFloaters) {
@ -3809,51 +3829,71 @@ class _empReviewDetailsState extends State<empReviewDetails> {
List<Widget> generateGmcCards(List<dynamic> data) {
List<Widget> cards = [];
gmcEnrollmentStatus = isEnrollmentOpen(data);
// gmcEnrollmentStatus = isEnrollmentOpen(data);
for (var item in data) {
setState(() {
gmcPolicyName = item['Policy_Name'];
gmcPolicyType = item['type'];
gmcFloaterTextHeading = item['floter_text_heading'];
gmcFloaterTextDescription = item['floter_text_description'];
gmcNotes = item['notes'];
gmcECardDownload = item['eCardDownload'];
gmcGstValue = item['family_floaters_of_dependent_and_gst_value'];
gmcSiPremiumValue =
item['family_floaters_of_dependent_and_si_premium_value'];
gmcTotalableValue = gmcGstValue + gmcSiPremiumValue;
gmcIsValueValid = (gmcSiPremiumValue != 0 && gmcGstValue != 0);
setState(() {
gmcIsPremiumSummery = item['is_premium_summery'];
});
String gmcPolicyName = item['Policy_Name'] ?? '';
String gmcPolicyType = item['type'] ?? '';
String gmcFloaterTextHeading = item['floter_text_heading'] ?? '';
String gmcFloaterTextDescription = item['floter_text_description'] ?? '';
String gmcNotes = item['notes'] ?? '';
String gmcECardDownload = item['eCardDownload'] ?? '';
// gmcSumInsured = item['Policy_Terms']['sum_insured'];
gmcMappedFamilyFloaters = item['mapped_family_floaters'];
// allDisclaimer = allDisclaimer.toSet().toList();
print('GPA Disclaimer $allDisclaimer');
dynamic getTrueObjects = gmcMappedFamilyFloaters
.where((element) => element['is_value_exist'] == true)
.toList();
print('getTrueObjects');
print(getTrueObjects);
if (getTrueObjects.length > 0) {
print('true');
gmcSumInsured = gmcMappedFamilyFloaters[0]["data"]["basic_cover_si"];
} else {
print('false');
gmcSumInsured = item['Policy_Terms']['sum_insured'];
}
gmcTypeName = item['type'];
});
print('forEach Card');
print(gmcMappedFamilyFloaters);
dynamic getTrueObjects = gmcMappedFamilyFloaters
// bool gmcIsPremiumSummery = item['is_premium_summery'] ?? false;
bool gmcIsPremiumSummery = false;
dynamic summery = item['is_premium_summery'];
if (summery is bool) {
gmcIsPremiumSummery = summery;
} else if (summery is String) {
gmcIsPremiumSummery = (summery == "1");
} else if (summery is int) {
gmcIsPremiumSummery = (summery == 1);
}
// -------------------------------
// SAFE numeric conversion
// -------------------------------
double gmcGstValue = toDoubleSafe(item['family_floaters_of_dependent_and_gst_value']);
double gmcSiPremiumValue = toDoubleSafe(item['family_floaters_of_dependent_and_si_premium_value']);
double gmcTotalableValue = gmcSiPremiumValue + gmcGstValue;
bool gmcIsValueValid = (gmcSiPremiumValue != 0 && gmcGstValue != 0);
// -------------------------------
// SAFE list handling
// -------------------------------
List gmcMappedFamilyFloaters = item['mapped_family_floaters'] is List
? item['mapped_family_floaters']
: [];
print('GPA Disclaimer $allDisclaimer');
// -------------------------------
// Find objects where is_value_exist == true
// -------------------------------
List trueObjects = gmcMappedFamilyFloaters
.where((element) => element['is_value_exist'] == true)
.toList();
print(getTrueObjects);
// -------------------------------
// SAFE Suinsured calculation
// -------------------------------
double gmcSumInsured;
Widget card = getTrueObjects.length > 0
if (trueObjects.isNotEmpty) {
gmcSumInsured = toDoubleSafe(trueObjects[0]["data"]["basic_cover_si"]);
} else {
gmcSumInsured = toDoubleSafe(item['Policy_Terms']?['sum_insured']);
}
String gmcTypeName = gmcPolicyType;
print("gmcMappedFamilyFloaters: $gmcMappedFamilyFloaters");
print("trueObjects: $trueObjects");
Widget card = trueObjects.length > 0
? Card(
elevation: 0,
color: Colors.white,

View File

@ -1,388 +0,0 @@
import 'dart:convert';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:intl/intl.dart';
import 'package:jwt_decode/jwt_decode.dart';
import 'package:nhance_app_pwa/customAppBar/enrollmentAppBar.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:http/http.dart' as http;
import '../../customAppBar/responsive.dart';
import '../../customAppBar/toastHelper.dart';
import '../../models/environment.dart';
class oldPolicy extends StatefulWidget {
const oldPolicy({Key? key}) : super(key: key);
@override
State<oldPolicy> createState() => _oldPolicyState();
}
class _oldPolicyState extends State<oldPolicy> {
dynamic _token;
dynamic empCodeString;
dynamic empPrimaryId;
dynamic client_id;
dynamic gpaEmpName;
dynamic oldPolicyList;
dynamic oldPolicyName;
dynamic oldPolicyClientId;
dynamic oldPolicyClientPolicyId;
dynamic oldPolicySiGstValue;
dynamic oldPolicySiPremiumValue;
dynamic oldPolicySiValue;
dynamic oldPolicyType;
dynamic oldPolicyEmployeePolicy;
dynamic oldPolicyDataIsEmpty = 1;
dynamic oldPolicyTypeHeading;
dynamic oldPolicyFloaterTextHeading;
dynamic oldPolicyStartDate;
dynamic oldPolicyEndDate;
dynamic empClientBranchId;
@override
void initState() {
super.initState();
_loadToken();
}
@override
void dispose() {
super.dispose();
}
Future<void> _loadToken() async {
print('_loadToken');
final SharedPreferences prefs = await SharedPreferences.getInstance();
final String? token = prefs.getString('token');
if (token != null && token.isNotEmpty) {
setState(() {
_token = token;
});
// Decode the JWT token received from the API response
Map<String, dynamic>? decodedToken = Jwt.parseJwt(token);
print(decodedToken);
empClientBranchId = prefs.getString('empClientBranchId');
empCodeString = prefs.getString('empCode');
print(empCodeString); // Check if emp_code is correct
empPrimaryId = prefs.getString('empPrimaryId');
gpaEmpName = prefs.getString('gpaEmpName');
client_id = prefs.getString('client_id');
print(client_id);
getOldPolicyDetails();
} 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, 'phone');
}
}
Future<void> getOldPolicyDetails() async {
var url = Uri.parse(Environment.apiUrl +
'getEmployeeActiveOrInactivePolicy?client_id=$client_id&emp_code=$empCodeString&type=Inactive&client_branch_id=$empClientBranchId');
try {
var response = await http.get(
url,
headers: {
'Authorization':
'Bearer $_token', // Add token to the Authorization header
},
);
if (response.statusCode == 200) {
Map<String, dynamic> data = json.decode(response.body);
if (data['status'] == 'success') {
setState(() {
oldPolicyList = data['data'];
print('gmcPolicies');
});
// Assuming data is a List
print(oldPolicyList);
} else {
setState(() {
oldPolicyDataIsEmpty = 0;
});
// Handle other status messages if needed
// ToastHelper.showErrorToast(
// context, 'API request failed with status: ${data['status']}');
print('API request failed with status: ${data['status']}');
}
} else {
setState(() {
oldPolicyDataIsEmpty = 0;
});
// Handle other status codes
// ToastHelper.showErrorToast(
// context, 'Request failed with status: ${response.statusCode}');
print('Request failed with status: ${response.statusCode}');
}
} catch (e) {
// Handle exceptions
print('Exception occurred: $e');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: CustomAppBar(),
body: _buildBody(),
);
}
Widget _buildBody() {
if (oldPolicyList == null) {
return Center(child: _buildNoDataWidget());
} else if (oldPolicyList!.isEmpty) {
return Center(child: _buildNoDataWidget());
} else {
return _buildPolicyListWidget();
}
}
Widget _buildNoDataWidget() {
return SingleChildScrollView(
child: Container(
color: Color(0xFFEFF3F6),
child: Column(
children: [
Center(
child: Text('No Data Available'),
)
],
),
),
);
}
Widget _buildPolicyListWidget() {
return Stack(
children: [
SingleChildScrollView(
child: Container(
padding: Responsive.isDesktop(context)
? EdgeInsets.symmetric(
horizontal: MediaQuery.of(context).size.width *
0.2, // 30% of screen width as horizontal padding
vertical: MediaQuery.of(context).size.height *
0.03, // 5% of screen height as vertical padding
)
: EdgeInsets.all(10),
color: Color(0xFFEFF3F6),
child: Column(
children: [
if (oldPolicyDataIsEmpty == 1)
...generateGmcCards(oldPolicyList),
],
),
),
)
],
);
}
List<Widget> generateGmcCards(List<dynamic> data) {
List<Widget> cards = [];
print('data');
print(data);
for (var item in data) {
setState(() {
oldPolicyName = item['policy_name'];
oldPolicyTypeHeading = item['heading'];
oldPolicyFloaterTextHeading = item['floter_text_heading'];
oldPolicyClientId = item['client_id'];
oldPolicyClientPolicyId = item['client_policy_id'];
oldPolicySiGstValue = item['si_gst_value'];
oldPolicySiPremiumValue = item['si_premium_value'];
oldPolicySiValue = item['si_value'];
oldPolicyType = item['policy_type'];
oldPolicyStartDate = item['policy_start_date'];
oldPolicyEndDate = item['policy_end_date'];
oldPolicyEmployeePolicy = item['EmployeePolicy'];
});
Widget card = Card(
elevation: 0,
child: Padding(
padding: Responsive.isDesktop(context)
? EdgeInsets.all(20)
: EdgeInsets.all(10),
child: Column(
children: [
Container(
decoration: BoxDecoration(
color: Color(
0xFFFFF1DD), // Set background color for the container
borderRadius: BorderRadius.circular(
5), // Set border radius for the container
),
padding: Responsive.isDesktop(context)
? EdgeInsets.only(
top: 15, bottom: 15, left: 25, right: 25)
: EdgeInsets.only(
top: 10, bottom: 10, left: 10, right: 10),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
flex: 8,
child: Container(
alignment: Alignment.centerLeft,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
oldPolicyName ?? '',
textAlign: TextAlign.left,
style: GoogleFonts.poppins(
fontSize: Responsive.isDesktop(context)
? 18
: 14,
),
),
Text(
oldPolicyTypeHeading ?? '',
textAlign: TextAlign.left,
style: GoogleFonts.poppins(
fontSize: Responsive.isDesktop(context)
? 20
: 16,
fontWeight: FontWeight.w600,
),
),
],
))),
Expanded(
flex: 4,
child: Container(
alignment: Alignment.centerRight,
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text(
oldPolicyFloaterTextHeading ?? '',
textAlign: TextAlign.right,
style: GoogleFonts.poppins(
fontSize: Responsive.isDesktop(context)
? 18
: 14,
),
),
Text(
'${oldPolicySiValue != null ? oldPolicySiValue : 'NA'}',
textAlign: TextAlign.right,
style: GoogleFonts.poppins(
fontSize: Responsive.isDesktop(context)
? 20
: 16,
fontWeight: FontWeight.w600,
),
),
],
))),
],
),
),
SizedBox(height: 15),
Container(
padding: Responsive.isDesktop(context)
? EdgeInsets.only(top: 0, bottom: 0, left: 15, right: 15)
: EdgeInsets.only(top: 0, bottom: 0, left: 5, right: 5),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: oldPolicyEmployeePolicy.map<Widget>((data) {
String formattedDate = formatDate(data['dob']);
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Icon(Icons.arrow_right,
color: Color(0xFFE26728)), // Arrow icon
SizedBox(
width: Responsive.isDesktop(context)
? 10
: 5), // Space between icon and text
Expanded(
child: Text(
'${data['name']} ~ ${data['relationship']} ~ DOB : $formattedDate',
style: GoogleFonts.poppins(
fontSize:
Responsive.isDesktop(context) ? 18 : 16,
color: Color(0xFF232526),
),
),
),
],
);
}).toList(),
),
),
SizedBox(height: 15),
Container(
padding: Responsive.isDesktop(context)
? EdgeInsets.only(top: 0, bottom: 0, left: 25, right: 25)
: EdgeInsets.only(top: 0, bottom: 0, left: 10, right: 10),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
flex: 12,
child: Container(
alignment: Alignment.centerLeft,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
RichText(
text: TextSpan(
text: 'Policy Period : ',
style: GoogleFonts.poppins(
fontSize: 16,
fontWeight: FontWeight.w500,
color: Color(0xFF232526),
),
children: <TextSpan>[
TextSpan(
text:
'$oldPolicyStartDate To $oldPolicyEndDate',
style: GoogleFonts.poppins(
fontSize: 14,
color: Color(0xFF232526),
),
),
],
),
),
],
),
),
),
],
),
),
],
),
));
cards.add(card);
cards.add(SizedBox(height: 10));
}
return cards;
}
String formatDate(String inputDate) {
// Parse the input date string
DateTime dateTime = DateTime.parse(inputDate);
// Format the date to 'dd MMMM yyyy'
String formattedDate = DateFormat('dd MMMM yyyy').format(dateTime);
return formattedDate;
}
}

View File

@ -3,8 +3,9 @@ import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';
import 'dart:convert';
import '../../../config/environment.dart';
import '../../../customAppBar/toastHelper.dart';
import '../../../models/environment.dart';
import '../../service/TokenService.dart';
class ApiService {
@ -186,13 +187,27 @@ class ApiService {
return response;
}
Future<Map<String, dynamic>> deleteItemToApi(id) async {
Future<Map<String, dynamic>> deleteItemToApi(id,copyStatus,gmcClientPolicyId) async {
print(_token);
if (_token == null) {
await _initializeToken();
}
final url =
Uri.parse('${Environment.apiUrlEnrollment}deleteDependence?id=$id');
Uri.parse('${Environment.apiUrlEnrollment}deleteDependence?id=$id&is_from_copy=$copyStatus&client_policy_id=$gmcClientPolicyId');
final headers = {
'Authorization': 'Bearer $_token' ?? '',
};
final response = await _makeGetRequest(url, headers);
return response;
}
Future<Map<String, dynamic>> copyActivePolicy(enrollmentClient_id,enrollmentEmpCodeString,newClientPolicy) async {
print(_token);
if (_token == null) {
await _initializeToken();
}
final url =
Uri.parse('${Environment.apiUrlEnrollment}copyActiveEmployeeAndDependentDetails?client_id=$enrollmentClient_id&emp_code=$enrollmentEmpCodeString&new_client_policy_id=$newClientPolicy');
final headers = {
'Authorization': 'Bearer $_token' ?? '',
};
@ -470,12 +485,16 @@ class ApiService {
Future<Map<String, dynamic>> _makeGetRequest(
Uri url, Map<String, String> headers) async {
// Add global APP_SIGNATURE header
headers['APP-SIGNATURE'] = 'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y';
final response = await http.get(url, headers: headers);
return _handleResponse(response);
}
Future<Map<String, dynamic>> _makePostRequest(
Uri url, String body, Map<String, String> headers) async {
// Add global APP_SIGNATURE header
headers['APP-SIGNATURE'] = 'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y';
final response = await http.post(url, headers: headers, body: body);
return _handleResponse(response);
}

View File

@ -13,9 +13,9 @@ import 'dart:convert';
import 'dart:io';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:google_fonts/google_fonts.dart';
import '../config/environment.dart';
import '../customAppBar/responsive.dart';
import '../customAppBar/toastHelper.dart';
import '../models/environment.dart';
import '../models/platform_helper_mobile.dart'
if (dart.library.html) '../models/platform_helper_other.dart';
import 'package:pinput/pinput.dart';
@ -138,6 +138,7 @@ class _loginState extends State<login> {
body: json.encode(params),
headers: {
HttpHeaders.contentTypeHeader: 'application/json',
'APP-SIGNATURE': 'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y',
},
);
@ -232,6 +233,7 @@ class _loginState extends State<login> {
body: json.encode(payload),
headers: {
HttpHeaders.contentTypeHeader: 'application/json',
'APP-SIGNATURE': 'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y',
},
);
@ -460,6 +462,7 @@ class _loginState extends State<login> {
body: json.encode(payload),
headers: {
HttpHeaders.contentTypeHeader: 'application/json',
'APP-SIGNATURE': 'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y',
},
);
print('response : ${response.statusCode}');
@ -571,7 +574,7 @@ class _loginState extends State<login> {
getClientLogoAndDetails();
}
if (_postToken != null && _postToken.isNotEmpty) {
ToastHelper.showSuccessToast(context, 'Successfully Login');
ToastHelper.showSuccessToast(context, 'Successfully Logged In');
context.go('/home');
// Navigator.pushReplacementNamed(context, 'home');
} else {
@ -588,7 +591,7 @@ class _loginState extends State<login> {
print('Successfully Login');
print(isMobilePlatform());
if (_preToken != null && _preToken.isNotEmpty) {
ToastHelper.showSuccessToast(context, 'Successfully Login');
ToastHelper.showSuccessToast(context, 'Successfully Logged In');
context.go('/home');
// Navigator.pushReplacementNamed(context, 'home');
} else {
@ -606,6 +609,7 @@ class _loginState extends State<login> {
headers: {
'Authorization':
'Bearer $_preToken', // Add token to the Authorization header
'APP-SIGNATURE': 'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y',
},
);
if (response.statusCode == 200) {
@ -675,6 +679,7 @@ class _loginState extends State<login> {
body: json.encode(payload),
headers: {
HttpHeaders.contentTypeHeader: 'application/json',
'APP-SIGNATURE': 'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y',
},
);
@ -740,6 +745,7 @@ class _loginState extends State<login> {
body: json.encode(payload),
headers: {
HttpHeaders.contentTypeHeader: 'application/json',
'APP-SIGNATURE': 'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y',
},
);
@ -816,6 +822,7 @@ class _loginState extends State<login> {
body: json.encode(payload),
headers: {
HttpHeaders.contentTypeHeader: 'application/json',
'APP-SIGNATURE': 'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y',
},
);
@ -897,6 +904,7 @@ class _loginState extends State<login> {
body: json.encode(payload),
headers: {
HttpHeaders.contentTypeHeader: 'application/json',
'APP-SIGNATURE': 'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y',
},
);
@ -1130,8 +1138,7 @@ class _loginState extends State<login> {
Expanded(
flex: 12,
child: Align(
alignment: Alignment
.topLeft, // Always top-left
alignment: Alignment.center,
child: _size.width <= 1100
? Image.asset(
'assets/nhance_app_logo.png',
@ -1155,7 +1162,7 @@ class _loginState extends State<login> {
),
SizedBox(
height: Responsive.isDesktop(context)
? _size.height * 0.1
? _size.height * 0.0
: 10,
),
SizedBox(height: 10),
@ -1985,117 +1992,9 @@ class _loginState extends State<login> {
SizedBox(
height: _size.width <= 1100 ? 0 : 0,
),
// _size.width > 1100
// ? Container(
// margin: EdgeInsets.symmetric(
// horizontal: 150),
// child: Column(
// children: [
// SizedBox(height: 30),
// Text(
// "Benefits of Login",
// style:
// GoogleFonts.poppins(
// fontSize: 20,
// fontWeight:
// FontWeight.bold,
// ),
// ),
// SizedBox(height: 15),
// ],
// ))
// : SizedBox(),
// _size.width > 1100
// ? Container(
// margin: EdgeInsets.symmetric(
// horizontal: 150),
// child: Row(
// mainAxisAlignment:
// MainAxisAlignment.center,
// children: [
// Expanded(
// flex: 6,
// child: Container(
// padding: EdgeInsets
// .symmetric(
// vertical: 8),
// child: Row(
// mainAxisAlignment:
// MainAxisAlignment
// .center,
// children: [
// Expanded(
// child: Container(
// padding: EdgeInsets
// .symmetric(
// vertical:
// 12),
// decoration:
// BoxDecoration(
// border:
// Border(
// right:
// BorderSide(
// width: 1,
// color: Colors
// .black,
// ),
// ),
// ),
// child: Column(
// children: [
// Icon(
// Icons
// .policy,
// color: Color(
// 0xFFE26728)),
// SizedBox(
// height:
// 10),
// Text(
// "View Policy"),
// ],
// ),
// ),
// ),
// Expanded(
// child: Container(
// padding: EdgeInsets
// .symmetric(
// vertical:
// 12),
// child: Column(
// children: [
// Icon(
// Icons
// .edit,
// color: Color(
// 0xFFE26728)),
// SizedBox(
// height:
// 10),
// Text(
// "Manage Claims"),
// ],
// ),
// ),
// ),
// ],
// ),
// ),
// ),
// ],
// ),
// )
// : SizedBox(
// height: Responsive.isDesktop(
// context)
// ? _size.height * 0.1
// : _size.height * 0.2,
// ),
SizedBox(
height: Responsive.isDesktop(context)
? _size.height * 0.3
? _size.height * 0.1
: _size.height * 0.2,
),
// SizedBox(

View File

@ -0,0 +1,386 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:intl/intl.dart';
import 'package:jwt_decode/jwt_decode.dart';
import 'package:nhance_app_pwa/pages/postEnrollment/service/api_service.dart';
import '../../customAppBar/customAppBar.dart';
import '../../customAppBar/customFooter.dart';
import '../../customAppBar/responsive.dart';
import '../../customAppBar/tabs.dart';
import '../../customAppBar/toastHelper.dart';
import '../service/SessionManager.dart';
import '../service/TokenService.dart';
class AddPolicyScreen extends StatefulWidget {
const AddPolicyScreen({super.key});
@override
State<AddPolicyScreen> createState() => _AddPolicyScreenState();
}
class _AddPolicyScreenState extends State<AddPolicyScreen> {
final _formKey = GlobalKey<FormState>();
bool isLoading = false;
dynamic _token;
final session = SessionManager();
late ApiService apiService;
dynamic empCodeString;
dynamic empPrimaryId;
dynamic client_id;
dynamic mobileNo;
dynamic client_branch_id;
dynamic decodedToken;
// Form controllers
final TextEditingController policyNoController = TextEditingController();
final TextEditingController expDateController = TextEditingController();
String? selectedPolicyType;
String? selectedInsurer;
List<Map<String, dynamic>> policyTypeData = [];
List<Map<String, dynamic>> insurerData = [];
@override
void initState() {
super.initState();
apiService = ApiService(context);
_loadToken();
}
Future<void> _loadToken() async {
final String? token = await TokenService.getPostToken();
if (token != null && token.isNotEmpty) {
setState(() => _token = token);
decodedToken = Jwt.parseJwt(token);
mobileNo = session.mobileNo;
client_branch_id = session.empClientBranchId;
empCodeString = session.empCodeString;
empPrimaryId = session.empPrimaryId;
client_id = session.client_id;
getPolicyTypeAndInsurerMaster();
}
}
Future<void> pickExpiryDate() async {
DateTime today = DateTime.now();
DateTime? picked = await showDatePicker(
context: context,
initialDate: today.add(const Duration(days: 1)), // default tomorrow
firstDate: DateTime(today.year, today.month, today.day), // no past
lastDate: DateTime(2100),
);
if (picked != null) {
expDateController.text = DateFormat("dd MMM yyyy").format(picked);
setState(() {});
}
}
Future<void> getPolicyTypeAndInsurerMaster() async {
setState(() => isLoading = true);
try {
final response = await apiService.fetchPolicyTypeAndInsurer();
if (response['status'] == 'success') {
policyTypeData =
List<Map<String, dynamic>>.from(response['data']['policy_type']);
insurerData =
List<Map<String, dynamic>>.from(response['data']['insurer']);
setState(() => isLoading = false);
} else {
throw Exception('Failed to fetch master data');
}
} catch (error) {
print('Error fetching list: $error');
}
}
Future<void> submitForm() async {
try {
if (_formKey.currentState!.validate()) {
setState(() => isLoading = true);
Map<String, dynamic> formData = {
'emp_id': empPrimaryId,
'policy_type_id': selectedPolicyType,
'insurer_id': selectedInsurer,
'policy_no': policyNoController.text,
'policy_end_date': expDateController.text,
'policy_start_date': '',
};
final response = await apiService.sendRetailPolicyDetails(formData);
if (response['status'] == 'success') {
ToastHelper.showSuccessToast(context, response['message']);
selectedPolicyType = null;
selectedInsurer = null;
policyNoController.clear();
expDateController.clear();
setState(() => isLoading = false);
context.go('/home');
}
}
} catch (e) {
print('Submit error: $e');
}
}
// ------------------------------------------------------
// WIDGETS
// ------------------------------------------------------
Widget dropdownFieldMap({
required String? value,
required String hint,
required List<Map<String, dynamic>> items,
required String validatorMsg,
bool isMandatory = true,
required Function(String?) onChanged,
required String labelKey,
required String valueKey,
}) {
return DropdownButtonFormField<String>(
value: value,
decoration: inputDecoration(hint),
items: items.map((item) {
return DropdownMenuItem(
value: item[valueKey].toString(), // send ID
child: Text(item[labelKey].toString()), // show name
);
}).toList(),
validator: (value) {
if (!isMandatory) return null;
return value == null ? validatorMsg : null;
},
onChanged: onChanged,
);
}
TextStyle labelStyle() => GoogleFonts.poppins(
fontSize: 13,
fontWeight: FontWeight.w500,
color: Colors.black87,
);
InputDecoration inputDecoration(String hint, {Widget? suffix}) {
return InputDecoration(
suffixIcon: suffix,
hintText: hint,
contentPadding: const EdgeInsets.all(14),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
),
);
}
@override
Widget build(BuildContext context) {
return PopScope(
canPop: false,
onPopInvokedWithResult: (didPop, result) {
if (didPop) return;
context.go('/home');
},
child: Scaffold(
backgroundColor: Colors.white,
appBar: CustomAppBar(),
body: Stack(children: [
SingleChildScrollView(
child: Container(
padding: Responsive.isDesktop(context)
? EdgeInsets.symmetric(
horizontal: MediaQuery.of(context).size.width * 0.2,
vertical: MediaQuery.of(context).size.height * 0.05,
)
: const EdgeInsets.all(10),
color: Colors.white,
child: Column(children: [
Card(
elevation: 5,
color: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15)),
child: Padding(
padding: const EdgeInsets.all(15),
child: Column(
children: [
Row(
children: [
InkWell(
onTap: () => context.go('/home'),
child: const Icon(Icons.chevron_left, size: 30),
),
const SizedBox(width: 10),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("Add Your Insurance Policy",
style: GoogleFonts.poppins(
fontSize: 16,
fontWeight: FontWeight.w600,
)),
const SizedBox(height: 2),
Text(
'Add and manage all your insurance policies taken anywhere for value added services and renewal reminders',
maxLines: 3,
overflow: TextOverflow.ellipsis,
style: GoogleFonts.poppins(fontSize: 12),
),
],
),
)
],
),
const SizedBox(height: 20),
/// FORM
Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("Type of Policy", style: labelStyle()),
const SizedBox(height: 5),
dropdownFieldMap(
value: selectedPolicyType,
hint: "Select policy type",
items: policyTypeData,
validatorMsg: "Please select a policy type",
labelKey: "policy_type",
valueKey: "policy_type_id",
onChanged: (val) =>
setState(() => selectedPolicyType = val),
),
const SizedBox(height: 20),
Text("Insurer", style: labelStyle()),
const SizedBox(height: 5),
dropdownFieldMap(
value: selectedInsurer,
hint: "Select insurer",
items: insurerData,
validatorMsg: "Please select an insurer",
labelKey: "insurer_name",
valueKey: "insurer_id",
onChanged: (val) =>
setState(() => selectedInsurer = val),
),
const SizedBox(height: 20),
Text("Policy Number", style: labelStyle()),
const SizedBox(height: 5),
TextFormField(
controller: policyNoController,
decoration:
inputDecoration("Enter policy number"),
validator: (value) => null, // NOT MANDATORY
),
const SizedBox(height: 20),
Text("Expiry Date", style: labelStyle()),
const SizedBox(height: 5),
GestureDetector(
onTap: pickExpiryDate,
child: AbsorbPointer(
child: TextFormField(
controller: expDateController,
decoration: inputDecoration(
"Select expiry date",
suffix: const Icon(Icons.calendar_month),
),
validator: (value) => value == null ||
value.isEmpty
? "Expiry date required"
: null,
),
),
),
const SizedBox(height: 30),
SizedBox(
width: double.infinity,
height: 50,
child: ElevatedButton(
onPressed: submitForm,
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFFE26828),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
),
child: Text(
"Save Policy",
style: GoogleFonts.poppins(
fontSize: 16,
color: Colors.white,
fontWeight: FontWeight.w600,
),
),
),
),
],
),
),
],
),
),
),
const SizedBox(height: 60),
]),
),
),
if (isLoading)
Container(
color: Colors.white70,
child: Center(
child: Image.asset(
'assets/nhance-loader.gif',
height: 60,
width: 60,
),
),
),
if (Responsive.isDesktop(context))
Align(
alignment: Alignment.bottomCenter,
child: SizedBox(
width: double.infinity, child: CustomFooter())),
]),
bottomNavigationBar: Responsive.isDesktop(context)
? null
: CustomBottomNavigationBar(
icons: [
Icons.home_outlined,
Icons.sticky_note_2_outlined,
Icons.person_outline_outlined,
Icons.headset_mic_outlined,
Icons.health_and_safety_outlined,
],
labels: ["Home", "Claims", "Profile", "Help", "Wellness"],
initialIndex: 3,
onTabChanged: (index) {
if (index == 0) context.go('/home');
if (index == 1) context.go('/claims');
if (index == 2) context.go('/profile');
if (index == 3) context.go('/help');
},
),
),
);
}
}

View File

@ -1,98 +1,98 @@
import 'package:flutter/material.dart';
import 'package:nhance_app_pwa/models/environment.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:url_launcher/url_launcher.dart';
class ChatbotWebViewPage extends StatefulWidget {
final String client_branch_id;
final String empCodeString;
final String empName;
final String empPrimaryId;
final String client_id;
const ChatbotWebViewPage({
Key? key,
required this.client_branch_id,
required this.empCodeString,
required this.empName,
required this.empPrimaryId,
required this.client_id,
}) : super(key: key);
@override
State<ChatbotWebViewPage> createState() => _ChatbotWebViewPageState();
}
class _ChatbotWebViewPageState extends State<ChatbotWebViewPage> {
late final WebViewController _controller;
late final String chatbotDomain;
late final String initialUrl;
@override
void initState() {
super.initState();
final chatbotURL = Environment.chatBotUrl;
print('chatbotURL $chatbotURL');
initialUrl = Uri.parse(
'$chatbotURL'
'?employee_id=${widget.empPrimaryId}'
'&emp_code=${widget.empCodeString}'
'&origin=mob'
'&name=${Uri.encodeComponent(widget.empName)}'
'&client_id=${widget.client_id}'
'&client_branch_id=${widget.client_branch_id}',
).toString();
// Extract the domain for comparison
final uri = Uri.parse(chatbotURL);
chatbotDomain = '${uri.scheme}://${uri.host}';
_controller = WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
..setBackgroundColor(Colors.transparent)
..setNavigationDelegate(
NavigationDelegate(
onNavigationRequest: (NavigationRequest request) {
debugPrint("Navigation requested: ${request.url}");
debugPrint("Is main frame: ${request.isMainFrame}");
// Allow navigation within the chatbot domain
if (request.url.startsWith(chatbotDomain)) {
return NavigationDecision.navigate;
} else {
// Open external links in browser
_launchInExternalBrowser(Uri.parse(request.url));
return NavigationDecision.prevent;
}
},
onWebResourceError: (error) {
debugPrint("WebView error: ${error.description}");
},
onPageStarted: (String url) {
debugPrint("Page started loading: $url");
},
onPageFinished: (String url) {
debugPrint("Page finished loading: $url");
},
),
)
..loadRequest(Uri.parse(initialUrl));
}
Future<void> _launchInExternalBrowser(Uri url) async {
if (await canLaunchUrl(url)) {
await launchUrl(url, mode: LaunchMode.externalApplication);
} else {
debugPrint("Could not launch $url");
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Ask ILA')),
body: WebViewWidget(controller: _controller),
);
}
}
// import 'package:flutter/material.dart';
// import 'package:nhance_app_pwa/models/environment.dart';
// import 'package:webview_flutter/webview_flutter.dart';
// import 'package:url_launcher/url_launcher.dart';
//
// class ChatbotWebViewPage extends StatefulWidget {
// final String client_branch_id;
// final String empCodeString;
// final String empName;
// final String empPrimaryId;
// final String client_id;
//
// const ChatbotWebViewPage({
// Key? key,
// required this.client_branch_id,
// required this.empCodeString,
// required this.empName,
// required this.empPrimaryId,
// required this.client_id,
// }) : super(key: key);
//
// @override
// State<ChatbotWebViewPage> createState() => _ChatbotWebViewPageState();
// }
//
// class _ChatbotWebViewPageState extends State<ChatbotWebViewPage> {
// late final WebViewController _controller;
// late final String chatbotDomain;
// late final String initialUrl;
//
// @override
// void initState() {
// super.initState();
// final chatbotURL = Environment.chatBotUrl;
// print('chatbotURL $chatbotURL');
//
// initialUrl = Uri.parse(
// '$chatbotURL'
// '?employee_id=${widget.empPrimaryId}'
// '&emp_code=${widget.empCodeString}'
// '&origin=mob'
// '&name=${Uri.encodeComponent(widget.empName)}'
// '&client_id=${widget.client_id}'
// '&client_branch_id=${widget.client_branch_id}',
// ).toString();
//
// // Extract the domain for comparison
// final uri = Uri.parse(chatbotURL);
// chatbotDomain = '${uri.scheme}://${uri.host}';
//
// _controller = WebViewController()
// ..setJavaScriptMode(JavaScriptMode.unrestricted)
// ..setBackgroundColor(Colors.transparent)
// ..setNavigationDelegate(
// NavigationDelegate(
// onNavigationRequest: (NavigationRequest request) {
// debugPrint("Navigation requested: ${request.url}");
// debugPrint("Is main frame: ${request.isMainFrame}");
//
// // Allow navigation within the chatbot domain
// if (request.url.startsWith(chatbotDomain)) {
// return NavigationDecision.navigate;
// } else {
// // Open external links in browser
// _launchInExternalBrowser(Uri.parse(request.url));
// return NavigationDecision.prevent;
// }
// },
// onWebResourceError: (error) {
// debugPrint("WebView error: ${error.description}");
// },
// onPageStarted: (String url) {
// debugPrint("Page started loading: $url");
// },
// onPageFinished: (String url) {
// debugPrint("Page finished loading: $url");
// },
// ),
// )
// ..loadRequest(Uri.parse(initialUrl));
// }
//
// Future<void> _launchInExternalBrowser(Uri url) async {
// if (await canLaunchUrl(url)) {
// await launchUrl(url, mode: LaunchMode.externalApplication);
// } else {
// debugPrint("Could not launch $url");
// }
// }
//
// @override
// Widget build(BuildContext context) {
// return Scaffold(
// appBar: AppBar(title: const Text('Ask ILA')),
// body: WebViewWidget(controller: _controller),
// );
// }
// }

View File

@ -815,39 +815,39 @@ class _claimprocessState extends State<claimprocess> {
bottomNavigationBar: Responsive.isDesktop(context)
? null
: CustomBottomNavigationBar(
onTabChanged: (index) {
if (index == 0) {
context.go('/home');
} else if (index == 1) {
context.go('/claims');
} else if (index == 2) {
context.go('/profile');
} else if (index == 3) {
context.go('/help');
} else if (index == 4) {
// Wellness tab clicked show popup
PopupHelper.showRedirectPopup(
context: context,
apiService: apiService,
empPrimaryId: session.empPrimaryId,
);
}
},
icons: [
Icons.home_outlined,
Icons.sticky_note_2_outlined,
Icons.person_outline_outlined,
Icons.headset_mic_outlined,
Icons.health_and_safety_outlined,
],
labels: [
"Home",
"Claims",
"Profile",
"Help",
"Wellness",
],
),
onTabChanged: (index) {
// Add your navigation logic here
// repositionBotman();
if (index == 0) {
context.push('/home');
} else if (index == 1) {
context.push('/claims');
} else if (index == 2) {
context.push('/profile');
} else if (index == 3) {
context.push('/help');
}
// else if (index == 4) {
// // context.push('/wellness');
// // Wellness tab clicked show popup
// if(!isRetailLoggedIn)
// PopupHelper.showRedirectPopup(
// context: context,
// apiService: apiService,
// empPrimaryId: session.empPrimaryId,
// );
// }
},
icons: [
Icons.home_outlined,
Icons.sticky_note_2_outlined,
Icons.person_outline_outlined,
Icons.headset_mic_outlined,
// Icons.health_and_safety_outlined,
],
labels: ["Home", "Claims", "Profile", "Help"],
initialIndex: 0, // Initial index of the bottom navigation bar
),
));
}
}

View File

@ -8,6 +8,7 @@ import 'package:jwt_decode/jwt_decode.dart';
import 'package:nhance_app_pwa/customAppBar/customAppBar.dart';
import 'package:nhance_app_pwa/pages/postEnrollment/service/api_service.dart';
import 'package:nhance_app_pwa/pages/postEnrollment/service/svg_service.dart';
import 'package:ribbon_widget/ribbon_widget.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:http/http.dart' as http;
@ -29,6 +30,19 @@ class claims extends StatefulWidget {
State<claims> createState() => _claimsState();
}
const TextStyle _kTextStyle = TextStyle(
color: Color(0xFFFFFFFF),
fontSize: 12,
fontWeight: FontWeight.w900,
height: 1.0);
enum RibbonLocation {
topStart,
topEnd,
bottomStart,
bottomEnd,
}
class _claimsState extends State<claims> {
bool isLoading = false;
late ApiService apiService;
@ -46,6 +60,7 @@ class _claimsState extends State<claims> {
dynamic policyHeading;
dynamic policyName;
dynamic EmployeePolicy;
dynamic emailId;
List<Map<String, String>> employeeDetails = [];
dynamic argumentsData;
dynamic empMobileNo;
@ -57,6 +72,7 @@ class _claimsState extends State<claims> {
dynamic client_branch_id;
dynamic mobileNo;
final session = SessionManager();
List<dynamic> retailPolicyDetails = [];
List<DropdownMenuItem<int>> getDepartmentItems() {
return [
@ -108,13 +124,14 @@ class _claimsState extends State<claims> {
final String? token = await TokenService.getPostToken();
if (token != null && token.isNotEmpty) {
// Decode the JWT token received from the API response
mobileNo = session.mobileNo;
mobileNo = session.mobileNo ?? '';
client_branch_id = session.empClientBranchId;
empCodeString = session.empCodeString;
empName = session.gpaEmpName;
print(empCodeString); // Check if emp_code is correct
empPrimaryId = session.empPrimaryId;
client_id = session.client_id;
emailId = session.empEmailCorporate ?? '';
print(client_id);
getActiveAndInactivePolicyDetails();
getTrackClaimsList();
@ -133,11 +150,11 @@ class _claimsState extends State<claims> {
try {
// Call both APIs
final responseActive = await apiService.getActiveAndInactivePolicyDetails(
client_id!, empCodeString!, 'Active', client_branch_id, mobileNo);
client_id!, empCodeString!, 'Active', client_branch_id, mobileNo,emailId);
final responseInactive =
await apiService.getActiveAndInactivePolicyDetails(client_id!,
empCodeString!, 'Inactive', client_branch_id, mobileNo);
empCodeString!, 'Inactive', client_branch_id, mobileNo,emailId);
final bool isActiveSuccess = responseActive['status'] == 'success' &&
responseActive['data'] != null;
@ -152,7 +169,14 @@ class _claimsState extends State<claims> {
? List<Map<String, dynamic>>.from(responseInactive['data'])
: [];
final combinedPolicies = [...activeData, ...inactiveData];
retailPolicyDetails = List.from(responseActive['retail_policy_data'] ?? []);
// Remove retail objects without policy_transaction_id
final filteredRetail = retailPolicyDetails
.where((item) => item.containsKey('policy_transaction_id'))
.toList();
final combinedPolicies = [...activeData, ...inactiveData, ...filteredRetail];
setState(() {
policyList = combinedPolicies;
@ -177,7 +201,7 @@ class _claimsState extends State<claims> {
return;
}
print('check 1');
final response = await apiService.getTrackClaimsList(empPrimaryId!);
final response = await apiService.getTrackClaimsList(empPrimaryId!,mobileNo,emailId);
print('check 1');
// if (response['success'] == true) {
setState(() {
@ -734,207 +758,353 @@ class _claimsState extends State<claims> {
bottomNavigationBar: Responsive.isDesktop(context)
? null
: CustomBottomNavigationBar(
onTabChanged: (index) {
// Add your navigation logic here
// For example:
if (index == 0) {
context.push('/home');
} else if (index == 1) {
context.push('/claims');
} else if (index == 2) {
context.push('/profile');
} else if (index == 3) {
context.push('/help');
} else if (index == 4) {
// Wellness tab clicked show popup
PopupHelper.showRedirectPopup(
context: context,
apiService: apiService,
empPrimaryId: session.empPrimaryId,
);
}
},
icons: [
Icons.home_outlined,
Icons.sticky_note_2_outlined,
Icons.person_outline_outlined,
Icons.headset_mic_outlined,
Icons.health_and_safety_outlined,
],
labels: [
"Home",
"Claims",
"Profile",
"Help",
"Wellness",
],
initialIndex: 1, // Initial index of the bottom navigation bar
),
onTabChanged: (index) {
// Add your navigation logic here
// repositionBotman();
if (index == 0) {
context.push('/home');
} else if (index == 1) {
context.push('/claims');
} else if (index == 2) {
context.push('/profile');
} else if (index == 3) {
context.push('/help');
}
// else if (index == 4) {
// // context.push('/wellness');
// // Wellness tab clicked show popup
// if(!isRetailLoggedIn)
// PopupHelper.showRedirectPopup(
// context: context,
// apiService: apiService,
// empPrimaryId: session.empPrimaryId,
// );
// }
},
icons: [
Icons.home_outlined,
Icons.sticky_note_2_outlined,
Icons.person_outline_outlined,
Icons.headset_mic_outlined,
// Icons.health_and_safety_outlined,
],
labels: ["Home", "Claims", "Profile", "Help"],
initialIndex: 0, // Initial index of the bottom navigation bar
),
));
}
// List<Widget> generateYourPlanList(List<dynamic> data) {
// return [
// ListView.builder(
// shrinkWrap: true,
// physics: NeverScrollableScrollPhysics(),
// itemCount: data.length,
// itemBuilder: (BuildContext context, int index) {
// var item = data[index];
// String policyHeading = item['heading'];
// String policyName = item['policy_name'];
// String policyStatus = item['policy_status'];
// String si_value = item['si_value'];
// String policyEndDate = item['policy_end_date'];
// String policyNo = item['policy_no'];
// String clientPolicyId = item['client_policy_id'];
// String sumInsuredLabel = item['sum_insured_label'];
// List<dynamic> employeePolicy = item['EmployeePolicy'];
//
// return GestureDetector(
// onTap: () {
// var details = {'claimsDetails': item, 'fromClaimPage': 0};
// context.go('/planclaimsform', extra: details);
// },
// child: MouseRegion(
// cursor: SystemMouseCursors.click,
// child: Card(
// elevation: 5,
// shape: RoundedRectangleBorder(
// borderRadius: BorderRadius.circular(15.0),
// ),
// child: Container(
// decoration: BoxDecoration(
// color: Colors.white,
// borderRadius: BorderRadius.circular(15.0),
// ),
// padding: EdgeInsets.symmetric(vertical: 15, horizontal: 15),
// child: Row(
// mainAxisAlignment: MainAxisAlignment
// .spaceBetween, // Center content horizontally
// crossAxisAlignment:
// CrossAxisAlignment.center, // Center content vertically
// children: [
// Expanded(
// flex: 4,
// child: Container(
// alignment: Alignment.centerLeft,
// child: Column(
// mainAxisAlignment: MainAxisAlignment.start,
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// Text(
// 'Insurer',
// textAlign: TextAlign.left,
// style: GoogleFonts.poppins(
// fontSize:
// Responsive.isDesktop(context) ? 16 : 12,
// fontWeight: FontWeight.w400,
// color: Color(0xFF979797),
// ),
// ),
// Text(
// policyName ?? '',
// textAlign: TextAlign.left,
// style: GoogleFonts.poppins(
// fontSize:
// Responsive.isDesktop(context) ? 18 : 14,
// fontWeight: FontWeight.w600,
// color: Color(0xFF000000),
// ),
// ),
// ],
// ),
// ),
// ),
// Expanded(
// flex: 3,
// child: Container(
// alignment: Alignment.centerLeft,
// child: Column(
// mainAxisAlignment: MainAxisAlignment.start,
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// Text(
// 'Status',
// textAlign: TextAlign.center,
// style: GoogleFonts.poppins(
// fontSize:
// Responsive.isDesktop(context) ? 16 : 12,
// fontWeight: FontWeight.w400,
// color: Color(0xFF979797),
// ),
// ),
// Text(
// policyStatus ?? '',
// textAlign: TextAlign.center,
// style: GoogleFonts.poppins(
// fontSize:
// Responsive.isDesktop(context) ? 18 : 14,
// fontWeight: FontWeight.w600,
// color: policyStatus == 'Active'
// ? Colors.green
// : Colors.red,
// ),
// ),
// ],
// ),
// ),
// ),
// Expanded(
// flex: 4,
// child: Container(
// alignment: Alignment.centerRight,
// child: Column(
// mainAxisAlignment: MainAxisAlignment.end,
// crossAxisAlignment: CrossAxisAlignment.end,
// children: [
// Text(
// sumInsuredLabel ?? '',
// textAlign: TextAlign.end,
// style: GoogleFonts.poppins(
// fontSize:
// Responsive.isDesktop(context) ? 16 : 12,
// fontWeight: FontWeight.w400,
// color: Color(0xFF979797),
// ),
// ),
// Text(
// '$si_value',
// textAlign: TextAlign.end,
// style: GoogleFonts.poppins(
// fontSize:
// Responsive.isDesktop(context) ? 18 : 14,
// fontWeight: FontWeight.w600,
// color: Color(0xFF000000),
// ),
// ),
// ],
// ),
// ),
// ),
// Expanded(
// flex: 1,
// child: Container(
// alignment: Alignment.centerRight,
// child: Icon(
// Icons.chevron_right,
// color: Color(0xFFE26728),
// size: Responsive.isDesktop(context) ? 30 : 26,
// ),
// ),
// ),
// ],
// ),
// ),
// ),
// ),
// );
// },
// ),
// ];
// }
List<Widget> generateYourPlanList(List<dynamic> data) {
return [
ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
physics: const NeverScrollableScrollPhysics(),
itemCount: data.length,
itemBuilder: (BuildContext context, int index) {
var item = data[index];
String policyHeading = item['heading'];
String policyName = item['policy_name'];
String policyStatus = item['policy_status'];
String si_value = item['si_value'];
String policyEndDate = item['policy_end_date'];
String policyNo = item['policy_no'];
String clientPolicyId = item['client_policy_id'];
String sumInsuredLabel = item['sum_insured_label'];
List<dynamic> employeePolicy = item['EmployeePolicy'];
// **CHECK IF THIS IS A RETAIL POLICY**
bool isRetail = item.containsKey('policy_transaction_id');
// ----------------------------
// NORMAL POLICY DATA (GMC/GPA)
// ----------------------------
String policyHeading = item['heading'] ?? '';
String policyName = item['policy_name'] ?? '';
String policyStatus = item['policy_status'] ?? '';
String siValue = item['si_value'] ?? '';
String sumInsuredLabel = item['sum_insured_label'] ?? '';
// ----------------------------
// RETAIL POLICY DATA
// ----------------------------
String insurerShortName = item['insurer_short_name'] ?? '';
String policyType = item['policy_type'] ?? '';
String vehicleNo = item['vehicle_no'] ?? '';
return GestureDetector(
onTap: () {
var details = {'claimsDetails': item, 'fromClaimPage': 0};
context.go('/planclaimsform', extra: details);
},
child: MouseRegion(
cursor: SystemMouseCursors.click,
child: Card(
elevation: 5,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
),
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(15.0),
),
padding: EdgeInsets.symmetric(vertical: 15, horizontal: 15),
child: Row(
mainAxisAlignment: MainAxisAlignment
.spaceBetween, // Center content horizontally
crossAxisAlignment:
CrossAxisAlignment.center, // Center content vertically
children: [
Expanded(
flex: 4,
child: Container(
alignment: Alignment.centerLeft,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Insurer',
textAlign: TextAlign.left,
style: GoogleFonts.poppins(
fontSize:
Responsive.isDesktop(context) ? 16 : 12,
fontWeight: FontWeight.w400,
color: Color(0xFF979797),
),
),
Text(
policyName ?? '',
textAlign: TextAlign.left,
style: GoogleFonts.poppins(
fontSize:
Responsive.isDesktop(context) ? 18 : 14,
fontWeight: FontWeight.w600,
color: Color(0xFF000000),
),
),
],
),
),
onTap: () {
if (isRetail) {
// Retail policy click allow clicking
var details = {
"retailDetails": item,
};
context.go('/retailClaimForm', extra: details);
} else {
// Normal claim policy click
var details = {
"claimsDetails": item,
"fromClaimPage": 0,
};
context.go('/planclaimsform', extra: details);
}
},
child: MouseRegion(
cursor: SystemMouseCursors.click,
child: Card(
elevation: 5,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
),
child: Container(
padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 15),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(15.0),
),
Expanded(
flex: 3,
child: Container(
alignment: Alignment.centerLeft,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Status',
textAlign: TextAlign.center,
style: GoogleFonts.poppins(
fontSize:
Responsive.isDesktop(context) ? 16 : 12,
fontWeight: FontWeight.w400,
color: Color(0xFF979797),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
// LEFT SECTION
Expanded(
flex: 4,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
isRetail ? "Insurer" : "Insurer",
style: GoogleFonts.poppins(
fontSize: Responsive.isDesktop(context) ? 16 : 12,
color: const Color(0xFF979797)),
),
),
Text(
policyStatus ?? '',
textAlign: TextAlign.center,
style: GoogleFonts.poppins(
fontSize:
Responsive.isDesktop(context) ? 18 : 14,
fontWeight: FontWeight.w600,
color: policyStatus == 'Active'
? Colors.green
: Colors.red,
Text(
isRetail ? insurerShortName : policyName,
style: GoogleFonts.poppins(
fontSize: Responsive.isDesktop(context) ? 18 : 14,
fontWeight: FontWeight.w600),
),
),
],
],
),
),
),
),
Expanded(
flex: 4,
child: Container(
alignment: Alignment.centerRight,
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text(
sumInsuredLabel ?? '',
textAlign: TextAlign.end,
style: GoogleFonts.poppins(
fontSize:
Responsive.isDesktop(context) ? 16 : 12,
fontWeight: FontWeight.w400,
color: Color(0xFF979797),
// CENTER (Status or Policy Type)
Expanded(
flex: 3,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
isRetail ? "Policy Type" : "Status",
style: GoogleFonts.poppins(
fontSize: Responsive.isDesktop(context) ? 16 : 12,
color: const Color(0xFF979797)),
),
),
Text(
'$si_value',
textAlign: TextAlign.end,
style: GoogleFonts.poppins(
fontSize:
Responsive.isDesktop(context) ? 18 : 14,
fontWeight: FontWeight.w600,
color: Color(0xFF000000),
Text(
isRetail ? policyType : policyStatus,
style: GoogleFonts.poppins(
fontSize: Responsive.isDesktop(context) ? 18 : 14,
fontWeight: FontWeight.w600,
color: isRetail
? Colors.black
: (policyStatus == "Active"
? Colors.green
: Colors.red),
),
),
),
],
],
),
),
),
),
Expanded(
flex: 1,
child: Container(
alignment: Alignment.centerRight,
child: Icon(
Icons.chevron_right,
color: Color(0xFFE26728),
size: Responsive.isDesktop(context) ? 30 : 26,
// RIGHT (Insured Name OR Sum Insured)
Expanded(
flex: 4,
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text(
isRetail ? "Vehicle No" : sumInsuredLabel,
style: GoogleFonts.poppins(
fontSize: Responsive.isDesktop(context) ? 16 : 12,
color: const Color(0xFF979797)),
),
Text(
isRetail ? vehicleNo : "$siValue",
style: GoogleFonts.poppins(
fontSize: Responsive.isDesktop(context) ? 18 : 14,
fontWeight: FontWeight.w600),
),
],
),
),
),
// ARROW
const Icon(Icons.chevron_right,
color: Color(0xFFE26728), size: 26),
],
),
],
),
),
),
),
),
);
);
},
),
];
}
List<Widget> generateTrackList(List<dynamic> data) {
return [
ListView.builder(
@ -949,6 +1119,11 @@ class _claimsState extends State<claims> {
String claimsDate = item['created_at'] ?? '';
String claimStatus = item['claim_status'] ?? '';
String claimsDepartmentName = item['ticket_policy_type'] ?? '';
String rawClaimNumber = item['claim_number']?.toString().trim() ?? '';
String claimNumber = rawClaimNumber.isNotEmpty
? ' - ($rawClaimNumber)'
: '';
// String claimsReplies = item['replies'];
// List<dynamic> messageList = item['message_list'];
@ -989,6 +1164,16 @@ class _claimsState extends State<claims> {
statusColor = Color(0xFF979797); // Default color if status is null
}
bool isRetailPolicy = false;
String? policyTxId = item['policy_transaction_id'];
if (policyTxId != null && policyTxId.toString().trim().isNotEmpty) {
isRetailPolicy = true; // Retail
} else {
isRetailPolicy = false; // Nhance GMC/GPA
}
return GestureDetector(
onTap: () {
print("Tappp - $ticketId");
@ -1003,16 +1188,13 @@ class _claimsState extends State<claims> {
insetPadding: EdgeInsets.all(16),
child: ClaimHistoryPopup(
ticket_id: item['id'],
empName: item['emp_name'], // example
empCode: item['emp_code'], // example
empName: isRetailPolicy ? '' : item['emp_name'],
empCode: isRetailPolicy ? '' : item['emp_code'],
policyType: item['ticket_policy_type']!,
// policyType: item['policy_type'],
// clientPolicyNo: item['client_policy_no'],
clientPolicyNo: item['policy_no']?.toString(),
claimAmount: item['claim_amount']?.toString(),
// claimNo: item['claim_no'],
claimNo: item['claim_number']?.toString(),
// postToken: widget.postToken,
isRetailPolicy: isRetailPolicy, // NEW
),
);
},
@ -1047,17 +1229,32 @@ class _claimsState extends State<claims> {
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
claimsDepartmentName ?? '',
textAlign: TextAlign.left,
style: GoogleFonts.poppins(
fontSize: Responsive.isDesktop(context)
? 18
: 16,
fontWeight: FontWeight.w600,
color: Color(0xFF000000),
RichText(
text: TextSpan(
children: [
// First Part: claimsDepartmentName e.g., "GMC"
TextSpan(
text: claimsDepartmentName ?? '',
style: GoogleFonts.poppins(
fontSize: Responsive.isDesktop(context) ? 18 : 16,
fontWeight: FontWeight.w700,
color: const Color(0xFF000000),
),
),
// Second Part: claimNumber e.g., "(54534543)"
TextSpan(
text: '${claimNumber ?? ''}',
style: GoogleFonts.poppins(
fontSize: Responsive.isDesktop(context) ? 16 : 12,
fontWeight: FontWeight.w500,
color: const Color(0xFF555555), // lighter color
),
),
],
),
),
SizedBox(height: 5),
Tooltip(
message:

File diff suppressed because it is too large Load Diff

View File

@ -807,39 +807,39 @@ class _generalExclusionsDeductiblesState
bottomNavigationBar: Responsive.isDesktop(context)
? null
: CustomBottomNavigationBar(
onTabChanged: (index) {
if (index == 0) {
context.go('/home');
} else if (index == 1) {
context.go('/claims');
} else if (index == 2) {
context.go('/profile');
} else if (index == 3) {
context.go('/help');
} else if (index == 4) {
// Wellness tab clicked show popup
PopupHelper.showRedirectPopup(
context: context,
apiService: apiService,
empPrimaryId: session.empPrimaryId,
);
}
},
icons: [
Icons.home_outlined,
Icons.sticky_note_2_outlined,
Icons.person_outline_outlined,
Icons.headset_mic_outlined,
Icons.health_and_safety_outlined,
],
labels: [
"Home",
"Claims",
"Profile",
"Help",
"Wellness",
],
),
onTabChanged: (index) {
// Add your navigation logic here
// repositionBotman();
if (index == 0) {
context.push('/home');
} else if (index == 1) {
context.push('/claims');
} else if (index == 2) {
context.push('/profile');
} else if (index == 3) {
context.push('/help');
}
// else if (index == 4) {
// // context.push('/wellness');
// // Wellness tab clicked show popup
// if(!isRetailLoggedIn)
// PopupHelper.showRedirectPopup(
// context: context,
// apiService: apiService,
// empPrimaryId: session.empPrimaryId,
// );
// }
},
icons: [
Icons.home_outlined,
Icons.sticky_note_2_outlined,
Icons.person_outline_outlined,
Icons.headset_mic_outlined,
// Icons.health_and_safety_outlined,
],
labels: ["Home", "Claims", "Profile", "Help"],
initialIndex: 0, // Initial index of the bottom navigation bar
),
));
}
}

View File

@ -42,6 +42,7 @@ class _helpState extends State<help> {
dynamic _token;
dynamic empCodeString;
dynamic empPrimaryId;
dynamic empEmailID;
dynamic client_id;
dynamic policyList;
dynamic policyDataIsEmpty = 1;
@ -135,6 +136,8 @@ class _helpState extends State<help> {
// Decode the JWT token received from the API response
Map<String, dynamic>? decodedToken = Jwt.parseJwt(token);
print(decodedToken);
empMobileNo = session.mobileNo ?? '';
empEmailID = session.empEmailCorporate ?? '';
client_branch_id = session.empClientBranchId;
empCodeString = session.empCodeString;
print(empCodeString); // Check if emp_code is correct
@ -189,7 +192,7 @@ class _helpState extends State<help> {
isLoading = true;
});
print('check 1');
final response = await apiService.getTrackClaimsList(empPrimaryId!);
final response = await apiService.getTrackClaimsList(empPrimaryId!,empMobileNo,empEmailID);
print('check 2');
setState(() {
isLoading = false;
@ -1043,40 +1046,39 @@ class _helpState extends State<help> {
bottomNavigationBar: Responsive.isDesktop(context)
? null
: CustomBottomNavigationBar(
onTabChanged: (index) {
if (index == 0) {
context.push('/home');
} else if (index == 1) {
context.push('/claims');
} else if (index == 2) {
context.push('/profile');
} else if (index == 3) {
context.push('/help');
} else if (index == 4) {
// Wellness tab clicked show popup
PopupHelper.showRedirectPopup(
context: context,
apiService: apiService,
empPrimaryId: session.empPrimaryId,
);
}
},
icons: [
Icons.home_outlined,
Icons.sticky_note_2_outlined,
Icons.person_outline_outlined,
Icons.headset_mic_outlined,
Icons.health_and_safety_outlined,
],
labels: [
"Home",
"Claims",
"Profile",
"Help",
"Wellness",
],
initialIndex: 3, // Initial index of the bottom navigation bar
),
onTabChanged: (index) {
// Add your navigation logic here
// repositionBotman();
if (index == 0) {
context.push('/home');
} else if (index == 1) {
context.push('/claims');
} else if (index == 2) {
context.push('/profile');
} else if (index == 3) {
context.push('/help');
}
// else if (index == 4) {
// // context.push('/wellness');
// // Wellness tab clicked show popup
// if(!isRetailLoggedIn)
// PopupHelper.showRedirectPopup(
// context: context,
// apiService: apiService,
// empPrimaryId: session.empPrimaryId,
// );
// }
},
icons: [
Icons.home_outlined,
Icons.sticky_note_2_outlined,
Icons.person_outline_outlined,
Icons.headset_mic_outlined,
// Icons.health_and_safety_outlined,
],
labels: ["Home", "Claims", "Profile", "Help"],
initialIndex: 0, // Initial index of the bottom navigation bar
),
));
}

File diff suppressed because it is too large Load Diff

View File

@ -11,6 +11,7 @@ import 'package:nhance_app_pwa/pages/postEnrollment/service/api_service.dart';
import 'package:nhance_app_pwa/pages/postEnrollment/service/file_upload_service.dart';
import 'package:nhance_app_pwa/pages/postEnrollment/service/multi_file_upload_widget.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../../config/environment.dart';
import '../../customAppBar/customFooter.dart';
import '../../customAppBar/responsive.dart';
import '../../customAppBar/tabs.dart';
@ -18,7 +19,6 @@ import '../../customAppBar/toastHelper.dart';
import 'package:http/http.dart' as http;
// import 'package:universal_html/html.dart' as html;
import '../../models/environment.dart';
import 'package:file_picker/file_picker.dart';
import '../service/SessionManager.dart';
@ -70,6 +70,7 @@ class _planclaimsformState extends State<planclaimsform> {
dynamic policyTypeCondition;
dynamic client_policy_id;
dynamic selfDetails;
dynamic emailId;
List<Map<String, dynamic>> employeePolicyList = [];
String? selectedFileNames;
// html.File? uploadedFile;
@ -83,6 +84,11 @@ class _planclaimsformState extends State<planclaimsform> {
late TextEditingController messageController;
late TextEditingController accidentDetailsController;
late TextEditingController hospitalNameController;
late TextEditingController hospitalAddressController;
late TextEditingController hospitalCityController;
late TextEditingController hospitalStateController;
late TextEditingController hospitalPinCodeController;
late TextEditingController hospitalPhoneNoController;
late TextEditingController claimAmountController;
late TextEditingController sumInsuredController;
late TextEditingController admitDateController;
@ -113,6 +119,11 @@ class _planclaimsformState extends State<planclaimsform> {
bool isMemberValid = true;
bool isSubjectValid = true;
bool isHospitalNameValid = true;
bool isHospitalAddressValid = true;
bool isHospitalCityValid = true;
bool isHospitalStateValid = true;
bool isHospitalPincodeValid = true;
bool isHospitalPhoneNoValid = true;
bool isAdmitDischargeValid = true;
bool isClaimAmountValid = true;
bool isAccidentDateValid = true;
@ -131,6 +142,11 @@ class _planclaimsformState extends State<planclaimsform> {
messageController = TextEditingController();
accidentDetailsController = TextEditingController();
hospitalNameController = TextEditingController();
hospitalAddressController = TextEditingController();
hospitalCityController = TextEditingController();
hospitalStateController = TextEditingController();
hospitalPinCodeController = TextEditingController();
hospitalPhoneNoController = TextEditingController();
claimAmountController = TextEditingController();
sumInsuredController = TextEditingController();
admitDateController = TextEditingController();
@ -151,6 +167,11 @@ class _planclaimsformState extends State<planclaimsform> {
messageController.dispose();
accidentDetailsController.dispose();
hospitalNameController.dispose();
hospitalAddressController.dispose();
hospitalCityController.dispose();
hospitalStateController.dispose();
hospitalPinCodeController.dispose();
hospitalPhoneNoController.dispose();
claimAmountController.dispose();
sumInsuredController.dispose();
admitDateController.dispose();
@ -243,6 +264,7 @@ class _planclaimsformState extends State<planclaimsform> {
print(empCodeString); // Check if emp_code is correct
empPrimaryId = session.empPrimaryId;
client_id = session.client_id;
emailId = session.empEmailCorporate;
print(client_id);
getActiveAndInactivePolicyDetails();
fetchDepartmentList();
@ -258,11 +280,11 @@ class _planclaimsformState extends State<planclaimsform> {
try {
// Call both APIs
final responseActive = await apiService.getActiveAndInactivePolicyDetails(
client_id!, empCodeString!, 'Active', client_branch_id,mobileNo
client_id!, empCodeString!, 'Active', client_branch_id,mobileNo,emailId
);
final responseInactive = await apiService.getActiveAndInactivePolicyDetails(
client_id!, empCodeString!, 'Inactive', client_branch_id,mobileNo
client_id!, empCodeString!, 'Inactive', client_branch_id,mobileNo,emailId
);
final bool isActiveSuccess = responseActive['status'] == 'success' && responseActive['data'] != null;
@ -520,6 +542,11 @@ class _planclaimsformState extends State<planclaimsform> {
isMemberValid = selectedMemberId != null;
isSubjectValid = subjectController.text.trim().isNotEmpty;
isHospitalNameValid = policyTypeCondition != 1 || hospitalNameController.text.trim().isNotEmpty;
isHospitalAddressValid = policyTypeCondition != 1 || hospitalAddressController.text.trim().isNotEmpty;
isHospitalStateValid = policyTypeCondition != 1 || hospitalStateController.text.trim().isNotEmpty;
isHospitalCityValid = policyTypeCondition != 1 || hospitalCityController.text.trim().isNotEmpty;
isHospitalPincodeValid = policyTypeCondition != 1 || hospitalPinCodeController.text.trim().isNotEmpty;
isHospitalPhoneNoValid = policyTypeCondition != 1 || hospitalPhoneNoController.text.trim().isNotEmpty;
// isAdmitDischargeValid = policyTypeCondition != 1 || (admitDate != null && dischargeDate != null);
isAdmitDateValid = policyTypeCondition != 1 || admitDate != null;
isDischargeDateValid = policyTypeCondition != 1 || dischargeDate != null;
@ -533,6 +560,11 @@ class _planclaimsformState extends State<planclaimsform> {
isMemberValid &&
isSubjectValid &&
isHospitalNameValid &&
isHospitalAddressValid &&
isHospitalStateValid &&
isHospitalCityValid &&
isHospitalPincodeValid &&
isHospitalPhoneNoValid &&
isAdmitDateValid &&
isDischargeDateValid &&
isClaimAmountValid &&
@ -590,6 +622,11 @@ class _planclaimsformState extends State<planclaimsform> {
String formattedAdmitDate = DateFormat('yyyy-MM-dd').format(admitDate!);
String formattedDischargeDate = DateFormat('yyyy-MM-dd').format(dischargeDate!);
fields['hospital_name'] = hospitalNameController.text;
fields['hospital_address'] = hospitalAddressController.text;
fields['hospital_city'] = hospitalCityController.text;
fields['hospital_state'] = hospitalStateController.text;
fields['hospital_pin_code'] = hospitalPinCodeController.text;
fields['hospital_phone_no'] = hospitalPhoneNoController.text;
fields['doa'] = formattedAdmitDate;
fields['dod'] = formattedDischargeDate;
fields['claim_amount'] = claimAmountController.text;
@ -617,6 +654,7 @@ class _planclaimsformState extends State<planclaimsform> {
final request = http.MultipartRequest('POST', Uri.parse('${Environment.apiUrl}/initiateClaim'));
request.headers['Authorization'] = 'Bearer $_token';
request.headers['APP-SIGNATURE'] = 'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y';
final stringFields = fields.map((key, value) => MapEntry(key, value?.toString() ?? ''));
request.fields.addAll(stringFields);
@ -1163,6 +1201,26 @@ SizedBox(height: 15),
buildTextField('Hospital Name', hospitalNameController),
if (!isHospitalNameValid)
Text('Please enter the Hospital Name', style: TextStyle(color: Colors.red)),
SizedBox(height: 15),
buildTextAreaField('Hospital Address',hospitalAddressController),
if (!isHospitalAddressValid)
Text('Please enter the Hospital Address', style: TextStyle(color: Colors.red)),
SizedBox(height: 15),
buildTextField('Hospital City', hospitalCityController),
if (!isHospitalCityValid)
Text('Please enter the Hospital City', style: TextStyle(color: Colors.red)),
SizedBox(height: 15),
buildTextField('Hospital State', hospitalStateController),
if (!isHospitalStateValid)
Text('Please enter the Hospital State', style: TextStyle(color: Colors.red)),
SizedBox(height: 15),
buildTextField('Hospital Pincode', hospitalPinCodeController),
if (!isHospitalPincodeValid)
Text('Please enter the Hospital Pincode', style: TextStyle(color: Colors.red)),
SizedBox(height: 15),
buildTextField('Hospital Phone No', hospitalPhoneNoController),
if (!isHospitalPhoneNoValid)
Text('Please enter the Hospital Phone No', style: TextStyle(color: Colors.red)),
],
SizedBox(height: 15),
if (serviceId == 2 ||
@ -1398,41 +1456,39 @@ SizedBox(height: 15),
bottomNavigationBar: Responsive.isDesktop(context)
? null
: CustomBottomNavigationBar(
onTabChanged: (index) {
// repositionBotman();
if (index == 0) {
context.go('/home');
} else if (index == 1) {
context.go('/claims');
} else if (index == 2) {
context.go('/profile');
} else if (index == 3) {
context.go('/help');
} else if (index == 4) {
// Wellness tab clicked show popup
PopupHelper.showRedirectPopup(
context: context,
apiService: apiService,
empPrimaryId: session.empPrimaryId,
);
}
},
icons: [
Icons.home_outlined,
Icons.sticky_note_2_outlined,
Icons.person_outline_outlined,
Icons.headset_mic_outlined,
Icons.health_and_safety_outlined,
],
labels: [
"Home",
"Claims",
"Profile",
"Help",
"Wellness",
],
initialIndex: 1,// Initial index of the bottom navigation bar
),
onTabChanged: (index) {
// Add your navigation logic here
// repositionBotman();
if (index == 0) {
context.push('/home');
} else if (index == 1) {
context.push('/claims');
} else if (index == 2) {
context.push('/profile');
} else if (index == 3) {
context.push('/help');
}
// else if (index == 4) {
// // context.push('/wellness');
// // Wellness tab clicked show popup
// if(!isRetailLoggedIn)
// PopupHelper.showRedirectPopup(
// context: context,
// apiService: apiService,
// empPrimaryId: session.empPrimaryId,
// );
// }
},
icons: [
Icons.home_outlined,
Icons.sticky_note_2_outlined,
Icons.person_outline_outlined,
Icons.headset_mic_outlined,
// Icons.health_and_safety_outlined,
],
labels: ["Home", "Claims", "Profile", "Help"],
initialIndex: 0, // Initial index of the bottom navigation bar
),
)
);
}

View File

@ -1106,39 +1106,39 @@ class _policiesState extends State<policies> {
bottomNavigationBar: Responsive.isDesktop(context)
? null
: CustomBottomNavigationBar(
onTabChanged: (index) {
if (index == 0) {
context.go('/home');
} else if (index == 1) {
context.go('/claims');
} else if (index == 2) {
context.go('/profile');
} else if (index == 3) {
context.go('/help');
} else if (index == 4) {
// Wellness tab clicked show popup
PopupHelper.showRedirectPopup(
context: context,
apiService: apiService,
empPrimaryId: session.empPrimaryId,
);
}
},
icons: [
Icons.home_outlined,
Icons.sticky_note_2_outlined,
Icons.person_outline_outlined,
Icons.headset_mic_outlined,
Icons.health_and_safety_outlined,
],
labels: [
"Home",
"Claims",
"Profile",
"Help",
"Wellness",
], // Initial index of the bottom navigation bar
),
onTabChanged: (index) {
// Add your navigation logic here
// repositionBotman();
if (index == 0) {
context.push('/home');
} else if (index == 1) {
context.push('/claims');
} else if (index == 2) {
context.push('/profile');
} else if (index == 3) {
context.push('/help');
}
// else if (index == 4) {
// // context.push('/wellness');
// // Wellness tab clicked show popup
// if(!isRetailLoggedIn)
// PopupHelper.showRedirectPopup(
// context: context,
// apiService: apiService,
// empPrimaryId: session.empPrimaryId,
// );
// }
},
icons: [
Icons.home_outlined,
Icons.sticky_note_2_outlined,
Icons.person_outline_outlined,
Icons.headset_mic_outlined,
// Icons.health_and_safety_outlined,
],
labels: ["Home", "Claims", "Profile", "Help"],
initialIndex: 0, // Initial index of the bottom navigation bar
),
)
);
}

View File

@ -11,12 +11,12 @@ import 'package:nhance_app_pwa/pages/postEnrollment/service/api_service.dart';
import 'package:nhance_app_pwa/pages/service/SessionManager.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../../config/environment.dart';
import '../../customAppBar/customFooter.dart';
import '../../customAppBar/responsive.dart';
import '../../customAppBar/tabs.dart';
import '../../customAppBar/toastHelper.dart';
import 'package:http/http.dart' as http;
import '../../models/environment.dart';
import '../../models/platform_helper_mobile.dart'
if (dart.library.html) '../../models/platform_helper_other.dart';
@ -64,6 +64,7 @@ class _profileState extends State<profile> {
dynamic selfFamilyFloaterKey;
dynamic selfEmpStatus;
dynamic client_branch_id;
dynamic selfDetails;
final dataManager = DataManager();
final session = SessionManager();
String installedVersion = "";
@ -126,6 +127,15 @@ class _profileState extends State<profile> {
empPrimaryId = session.empPrimaryId;
client_id = session.client_id;
print(client_id);
await dataManager.loadSelfEmployeeProfile(
clientId: session.client_id!,
empCode: session.empCodeString!,
clientBranchId: session.empClientBranchId!,
)
.then((_) {
selfDetails = dataManager.selfProfile;
print('selfDetails $selfDetails');
});
getSelfEmployeeProfile();
}
}
@ -137,7 +147,7 @@ class _profileState extends State<profile> {
}
Future<void> getSelfEmployeeProfile() async {
final selfDetails = dataManager.selfProfile;
// final selfDetails = dataManager.selfProfile;
print('profile');
print(profile);
// if (client_id == null || empCodeString == null) {
@ -879,40 +889,39 @@ class _profileState extends State<profile> {
bottomNavigationBar: Responsive.isDesktop(context)
? null
: CustomBottomNavigationBar(
onTabChanged: (index) {
if (index == 0) {
context.push('/home');
} else if (index == 1) {
context.push('/claims');
} else if (index == 2) {
context.push('/profile');
} else if (index == 3) {
context.push('/help');
} else if (index == 4) {
// Wellness tab clicked show popup
PopupHelper.showRedirectPopup(
context: context,
apiService: apiService,
empPrimaryId: session.empPrimaryId,
);
}
},
icons: [
Icons.home_outlined,
Icons.sticky_note_2_outlined,
Icons.person_outline_outlined,
Icons.headset_mic_outlined,
Icons.health_and_safety_outlined,
],
labels: [
"Home",
"Claims",
"Profile",
"Help",
"Wellness",
],
initialIndex: 2, // Initial index of the bottom navigation bar
),
onTabChanged: (index) {
// Add your navigation logic here
// repositionBotman();
if (index == 0) {
context.push('/home');
} else if (index == 1) {
context.push('/claims');
} else if (index == 2) {
context.push('/profile');
} else if (index == 3) {
context.push('/help');
}
// else if (index == 4) {
// // context.push('/wellness');
// // Wellness tab clicked show popup
// if(!isRetailLoggedIn)
// PopupHelper.showRedirectPopup(
// context: context,
// apiService: apiService,
// empPrimaryId: session.empPrimaryId,
// );
// }
},
icons: [
Icons.home_outlined,
Icons.sticky_note_2_outlined,
Icons.person_outline_outlined,
Icons.headset_mic_outlined,
// Icons.health_and_safety_outlined,
],
labels: ["Home", "Claims", "Profile", "Help"],
initialIndex: 0, // Initial index of the bottom navigation bar
),
));
}

View File

@ -306,39 +306,36 @@ class _raisedTicketHistoryState extends State<raisedTicketHistory> {
: CustomBottomNavigationBar(
onTabChanged: (index) {
// Add your navigation logic here
// For example:
// repositionBotman();
if (index == 0) {
context.go('/home');
context.push('/home');
} else if (index == 1) {
context.go('/claims');
context.push('/claims');
} else if (index == 2) {
context.go('/profile');
context.push('/profile');
} else if (index == 3) {
context.go('/help');
} else if (index == 4) {
// Wellness tab clicked show popup
PopupHelper.showRedirectPopup(
context: context,
apiService: apiService,
empPrimaryId: session.empPrimaryId,
);
context.push('/help');
}
// else if (index == 4) {
// // context.push('/wellness');
// // Wellness tab clicked show popup
// if(!isRetailLoggedIn)
// PopupHelper.showRedirectPopup(
// context: context,
// apiService: apiService,
// empPrimaryId: session.empPrimaryId,
// );
// }
},
icons: [
Icons.home_outlined,
Icons.sticky_note_2_outlined,
Icons.person_outline_outlined,
Icons.headset_mic_outlined,
Icons.health_and_safety_outlined,
// Icons.health_and_safety_outlined,
],
labels: [
"Home",
"Claims",
"Profile",
"Help",
"Wellness",
],
initialIndex: 3, // Initial index of the bottom navigation bar
labels: ["Home", "Claims", "Profile", "Help"],
initialIndex: 0, // Initial index of the bottom navigation bar
),
)
);
@ -398,7 +395,8 @@ class _raisedTicketHistoryState extends State<raisedTicketHistory> {
return GestureDetector(
onTap: () {
print("Navigating with thz_id: ${item['thz_id']}");
context.go('/tickettracklist', extra: item['thz_id']);
context.go('/tickettracklist/${item['thz_id']}');
// context.go('/tickettracklist', extra: item['thz_id']);
},
child: MouseRegion(
cursor: SystemMouseCursors.click,

View File

@ -0,0 +1,576 @@
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:intl/intl.dart';
import 'package:jwt_decode/jwt_decode.dart';
import 'package:nhance_app_pwa/customAppBar/customAppBar.dart';
import 'package:nhance_app_pwa/pages/postEnrollment/service/api_service.dart';
import 'package:nhance_app_pwa/pages/service/SessionManager.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../../config/environment.dart';
import '../../customAppBar/customFooter.dart';
import '../../customAppBar/responsive.dart';
import '../../customAppBar/tabs.dart';
import '../../customAppBar/toastHelper.dart';
import 'package:http/http.dart' as http;
import '../service/TokenService.dart';
import '../service/popup_helper.dart';
class retailClaimForm extends StatefulWidget {
final Map<String, dynamic>? details;
const retailClaimForm({Key? key, this.details}) : super(key: key);
@override
State<retailClaimForm> createState() => _retailClaimFormsState();
}
class _retailClaimFormsState extends State<retailClaimForm> {
late ApiService apiService;
bool isLoading = false;
dynamic _token;
dynamic empCodeString;
dynamic empPrimaryId;
dynamic client_id;
Map<String, dynamic>? decodedToken;
dynamic client_branch_id;
dynamic mobileNo;
dynamic policyTypeCondition;
dynamic client_policy_id;
dynamic emailId;
String? selectedClaimTypeId; // claim type id to submit
List<dynamic> claimTypeMasterList = []; // api list
TextEditingController policyNoController = TextEditingController();
TextEditingController descriptionController = TextEditingController();
// Create a unique form key for each accordion section
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
bool isServiceValid = true;
bool isPolicyValid = true;
bool isSubjectValid = true;
bool isMessageValid = true;
final session = SessionManager();
@override
void initState() {
super.initState();
apiService = ApiService(context); // Initialize ApiService here
descriptionController = TextEditingController();
policyNoController = TextEditingController();
// Retail policy details
final retailData = widget.details?['retailDetails'] ?? {};
policyNoController.text = retailData['policy_no'] ?? "";
_loadToken();
}
@override
void dispose() {
// Dispose the controllers to avoid memory leaks
policyNoController.dispose();
descriptionController.dispose();
super.dispose();
}
Future<void> _loadToken() async {
print('_loadToken');
final String? token = await TokenService.getPostToken();
if (token != null && token.isNotEmpty) {
setState(() {
_token = token;
});
// Decode the JWT token received from the API response
decodedToken = Jwt.parseJwt(token);
print(decodedToken);
mobileNo = session.mobileNo;
client_branch_id = session.empClientBranchId;
empCodeString = session.empCodeString;
print(empCodeString); // Check if emp_code is correct
empPrimaryId = session.empPrimaryId;
client_id = session.client_id;
emailId = session.empEmailCorporate;
print(client_id);
getClaimTypeMasterList();
}
}
Future<void> getClaimTypeMasterList() async {
setState(() => isLoading = true);
try {
final response = await apiService.getClaimTypeMasterApi();
if (response["status"] == "success") {
setState(() {
claimTypeMasterList = response["data"];
});
}
} finally {
setState(() => isLoading = false);
}
}
Future<void> submitRetailClaim() async {
if (!formKey.currentState!.validate()) {
ToastHelper.showErrorToast(context, "Please fill required fields");
return;
}
setState(() => isLoading = true);
final retailData = widget.details?['retailDetails'] ?? {};
try {
// ------------------------------
// Prepare data
// ------------------------------
Map<String, dynamic> formData = {
"policy_transaction_id": widget.details?['retailDetails']['policy_transaction_id'] ?? "",
"policy_no": policyNoController.text,
"policy_type_id": widget.details?['retailDetails']['policy_type_id'] ?? "",
"claim_type":selectedClaimTypeId,
"claim_description": descriptionController.text,
};
print("Retail Claim FormData: $formData");
// ------------------------------
// Prepare MultipartRequest
// ------------------------------
final request = http.MultipartRequest(
'POST',
Uri.parse("${Environment.apiUrl}/initiateClaim"),
);
request.headers['Authorization'] = 'Bearer $_token';
request.headers['APP-SIGNATURE'] = 'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y';
// Convert all values to String and add to fields
final stringFields = formData.map(
(key, value) => MapEntry(key, value?.toString() ?? ''),
);
request.fields.addAll(stringFields);
// ------------------------------
// Send request
// ------------------------------
final response = await request.send();
final responseBody = await response.stream.bytesToString();
print("Retail Claim API Response: $responseBody");
final decoded = jsonDecode(responseBody);
// ------------------------------
// Handle Response
// ------------------------------
if (decoded['status'] == true) {
ToastHelper.showSuccessToast(
context,
decoded['message'] ?? "Claim submitted successfully!",
);
// Clear form
selectedClaimTypeId = null;
descriptionController.clear();
setState(() => isLoading = false);
// Redirect
context.go("/claims");
} else {
ToastHelper.showErrorToast(
context,
decoded['message'] ?? "Failed to submit claim",
);
}
} catch (e) {
print("Retail claim submit ERROR: $e");
ToastHelper.showErrorToast(context, "Something went wrong");
}
setState(() => isLoading = false);
}
@override
Widget build(BuildContext context) {
return PopScope(
canPop: false,
onPopInvokedWithResult: (didPop, result) {
if (didPop) return;
context.go('/claims');
},
child: Scaffold(
backgroundColor: Colors.white,
appBar: CustomAppBar(),
body: Stack(children: [
SingleChildScrollView(
child: Container(
padding: Responsive.isDesktop(context)
? EdgeInsets.symmetric(
horizontal: MediaQuery.of(context).size.width *
0.2, // 30% of screen width as horizontal padding
vertical: MediaQuery.of(context).size.height *
0.05, // 5% of screen height as vertical padding
)
: EdgeInsets.all(10),
color: Colors.white,
child: Column(children: [
Card(
elevation: 5,
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(15.0), // Set border radius here
),
child: Container(
decoration: BoxDecoration(
color: Colors.white, // Set background color to white
borderRadius: BorderRadius.circular(
15.0), // Set border radius for Container
),
padding: Responsive.isDesktop(context)
? EdgeInsets.only(
top: 15, bottom: 15, left: 15, right: 15)
: EdgeInsets.only(
top: 10,
bottom: 10,
left: 10,
right: 10), // Add padding to the container
child: Row(
children: [
Expanded(
flex: 12,
child: Container(
alignment: Alignment.centerLeft,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
decoration: BoxDecoration(
color: Color(
0xFFFFFCE5), // Set background color for the container
borderRadius: BorderRadius.circular(
10), // Set border radius for the container
),
padding: Responsive.isDesktop(context)
? EdgeInsets.only(
top: 20,
bottom: 20,
left: 0,
right: 0)
: EdgeInsets.only(
top: 10,
bottom: 10,
left: 10,
right: 10),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment:
MainAxisAlignment.start,
children: [
Expanded(
// flex: 1,
child: InkWell(
onTap: () {
context.go('/claims');
},
child: Icon(
Icons
.chevron_left, // Replace with your desired icon
color: Color(0xFF000000),
size: 30,
),
),
),
Expanded(
flex: 11,
child: Row(
mainAxisAlignment: Responsive
.isDesktop(context)
? MainAxisAlignment.start
: MainAxisAlignment.start,
children: [
Text(
'Claim Retail',
textAlign:
TextAlign.start,
style:
GoogleFonts.poppins(
fontSize: Responsive
.isDesktop(
context)
? 20
: 16,
fontWeight:
FontWeight.w600,
color:
Color(0xFF000000),
),
)
],
),
)
],
), // Space between rows
// Add more rows as needed
],
),
),
SizedBox(height: 15),
Container(
child: Column(
children: [
Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Container(
width: double.infinity,
alignment: Alignment.centerLeft,
child: Column(
mainAxisAlignment:
MainAxisAlignment.start,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Form(
key: formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// ---------------- Claim Type Dropdown ----------------
DropdownButtonFormField<String>(
value: selectedClaimTypeId,
decoration: const InputDecoration(labelText: "Claim Type"),
items: claimTypeMasterList.map<DropdownMenuItem<String>>((item) {
return DropdownMenuItem(
value: item['id']?.toString() ?? "", // FIXED
child: Text(item['claim_type']?.toString() ?? ""), // FIXED
);
}).toList(),
onChanged: (value) {
setState(() => selectedClaimTypeId = value);
},
validator: (value) =>
value == null || value.isEmpty ? "Please select a Claim Type" : null,
),
const SizedBox(height: 20),
// ---------------- Policy Number (readonly) ----------------
TextFormField(
controller: policyNoController,
readOnly: true,
decoration: const InputDecoration(
labelText: "Policy Number",
),
validator: (value) {
if (value == null || value.isEmpty) {
return "Policy Number missing";
}
return null;
},
),
const SizedBox(height: 20),
// ---------------- Claim Description ----------------
TextFormField(
controller: descriptionController,
maxLines: 5,
decoration: const InputDecoration(
labelText: "Claim Description",
),
validator: (value) {
if (value == null || value.trim().isEmpty) {
return "Please enter the claim description";
}
return null;
},
),
const SizedBox(height: 25),
// ---------------- Submit Button ----------------
Align(
alignment: Alignment.centerRight,
child: ElevatedButton(
onPressed: () => submitRetailClaim(),
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFFE26728),
),
child: Text("Submit", style: GoogleFonts.poppins(color: Colors.white)),
),
),
],
),
)
],
),
),
],
),
],
),
),
],
))),
],
),
),
),
SizedBox(height: Responsive.isDesktop(context) ? 40 : 60),
]),
)),
if (isLoading)
Container(
color: Color(0x98FFFCE5), // 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
),
),
if (Responsive.isDesktop(context))
Align(
alignment: Alignment.bottomCenter,
child: Container(
width: double.infinity, // Make the footer full width
child: CustomFooter(),
),
),
]),
// floatingActionButton: Responsive.isDesktop(context)
// ? null
// : FloatingActionButton(
// onPressed: () {
// Navigator.pushNamed(context, 'chatbot');
// },
// child: Icon(Icons.chat),
// ),
floatingActionButtonLocation: Responsive.isDesktop(context)
? null
: FloatingActionButtonLocation.miniEndFloat,
bottomNavigationBar: Responsive.isDesktop(context)
? null
: CustomBottomNavigationBar(
onTabChanged: (index) {
// Add your navigation logic here
// repositionBotman();
if (index == 0) {
context.push('/home');
} else if (index == 1) {
context.push('/claims');
} else if (index == 2) {
context.push('/profile');
} else if (index == 3) {
context.push('/help');
}
// else if (index == 4) {
// // context.push('/wellness');
// // Wellness tab clicked show popup
// if(!isRetailLoggedIn)
// PopupHelper.showRedirectPopup(
// context: context,
// apiService: apiService,
// empPrimaryId: session.empPrimaryId,
// );
// }
},
icons: [
Icons.home_outlined,
Icons.sticky_note_2_outlined,
Icons.person_outline_outlined,
Icons.headset_mic_outlined,
// Icons.health_and_safety_outlined,
],
labels: ["Home", "Claims", "Profile", "Help"],
initialIndex: 0, // Initial index of the bottom navigation bar
),
));
}
Widget buildTextField(String label, TextEditingController controller,
[TextInputType keyboardType = TextInputType.text]) {
return TextFormField(
controller: controller,
decoration: InputDecoration(labelText: label),
keyboardType: keyboardType,
maxLength: 150,
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter the $label';
}
return null;
},
);
}
Widget buildTextAreaField(String label, TextEditingController controller) {
return TextFormField(
controller: controller,
decoration: InputDecoration(labelText: label),
maxLines: 5,
maxLength: 1500,
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter the $label';
}
return null;
},
);
}
Widget buildDropdownField<T>(
String label,
void Function(T?) onChanged,
bool readOnly,
List<Map<String, dynamic>> itemsList,
String displayField,
T? selectedValue, {
String valueKey = 'id',
String? combineField,
}) {
return DropdownButtonFormField<T>(
value: selectedValue,
decoration: InputDecoration(labelText: label),
items: itemsList.map<DropdownMenuItem<T>>((item) {
// If combineField is provided show "policy_no - policy_type"
String textToShow;
if (combineField != null) {
textToShow = "${item[displayField]} - ${item[combineField]}";
} else {
textToShow = item[displayField].toString();
}
return DropdownMenuItem<T>(
value: item[valueKey] as T, // cast to generic type
child:
Text(textToShow), // always display as String
);
}).toList(),
onChanged: readOnly ? null : onChanged,
validator: (value) {
if (value == null) {
return 'Please select a $label';
}
return null;
},
);
}
}

View File

@ -2,11 +2,12 @@ import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:http/http.dart' as http;
import 'package:nhance_app_pwa/customAppBar/toastHelper.dart';
import 'package:nhance_app_pwa/models/environment.dart';
import 'package:nhance_app_pwa/pages/service/TokenService.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'dart:convert';
import '../../../config/environment.dart';
class ApiService {
final BuildContext context;
String? _postToken;
@ -20,17 +21,17 @@ class ApiService {
}
Future<Map<String, dynamic>> getActiveAndInactivePolicyDetails(
String clientId,
String empCode,
String status,
String branchID,
String mobileNo) async {
String? clientId,
String? empCode,
String? status,
String? branchID,
String? mobileNo,String? emailId) async {
print(_postToken);
if (_postToken == null) {
await _initializeToken();
}
final url = Uri.parse(
'${Environment.apiUrl}getEmployeeActiveOrInactivePolicy?client_id=$clientId&emp_code=$empCode&type=$status&client_branch_id=$branchID&mobile_no=$mobileNo');
'${Environment.apiUrl}getEmployeeActiveOrInactivePolicy?client_id=${clientId ?? ''}&emp_code=${empCode ?? ''}&type=${status ?? ''}&client_branch_id=${branchID ?? ''}&mobile_no=${mobileNo ?? ''}&email_id=${emailId ?? ''}');
final headers = {
'Authorization': 'Bearer $_postToken' ?? '',
};
@ -51,12 +52,12 @@ class ApiService {
return response;
}
Future<Map<String, dynamic>> getAdvertisementImageToApi() async {
Future<Map<String, dynamic>> getAdvertisementImageToApi(clientID) async {
print(_postToken);
if (_postToken == null) {
await _initializeToken();
}
final url = Uri.parse('${Environment.apiUrl}getAdvertisementImage');
final url = Uri.parse('${Environment.apiUrl}getAdvertisementImage?client_id=$clientID');
final headers = {
'Authorization': 'Bearer $_postToken' ?? '',
};
@ -92,13 +93,13 @@ class ApiService {
return response;
}
Future<Map<String, dynamic>> getTrackClaimsList(String empPrimaryId) async {
Future<Map<String, dynamic>> getTrackClaimsList(String empPrimaryId,mobileNo,emailID) async {
print(_postToken);
if (_postToken == null) {
await _initializeToken();
}
final url = Uri.parse(
'${Environment.apiUrl}/get_ticket_data?emp_id=$empPrimaryId');
'${Environment.apiUrl}/get_ticket_data?emp_id=$empPrimaryId&mobile_number=$mobileNo&email_id=$emailID');
final headers = {
'Authorization': 'Bearer $_postToken' ?? '',
};
@ -170,6 +171,22 @@ class ApiService {
return response;
}
Future<Map<String, dynamic>> sendRetailPolicyDetails(formData) async {
print(_postToken);
if (_postToken == null) {
await _initializeToken();
}
final url = Uri.parse('${Environment.apiUrl}addEmpRetailPolicy');
final headers = {
'Authorization': 'Bearer $_postToken' ?? '',
'Content-Type': 'application/json', // Ensure content type is JSON
};
final jsonBody = jsonEncode(formData);
// Send formDataJson as the body
final response = await _makePostRequestWithoutFormData(url,jsonBody, headers);
return response;
}
Future<bool> updateMobileNumber(Map<String, dynamic> updateParam) async {
if (_postToken == null) {
await _initializeToken();
@ -194,6 +211,19 @@ class ApiService {
}
Future<Map<String, dynamic>> fetchPolicyTypeAndInsurer() async {
print(_postToken);
if (_postToken == null) {
await _initializeToken();
}
final url = Uri.parse('${Environment.apiUrl}getPolicyTypeAndInsurer');
final headers = {
'Authorization': 'Bearer $_postToken' ?? '',
};
final response = await _makeGetRequest(url, headers);
return response;
}
Future<Map<String, dynamic>> fetchDepartmentList(String clientId, String empCode) async {
print(_postToken);
if (_postToken == null) {
@ -207,6 +237,19 @@ class ApiService {
return response;
}
Future<Map<String, dynamic>> getClaimTypeMasterApi() async {
print(_postToken);
if (_postToken == null) {
await _initializeToken();
}
final url = Uri.parse('${Environment.apiUrl}/getClaimTypeMaster');
final headers = {
'Authorization': 'Bearer $_postToken' ?? '',
};
final response = await _makeGetRequest(url, headers);
return response;
}
Future<Map<String, dynamic>> sendTicketFormDataToApi(
Map<String, dynamic> formData) async {
print(_postToken);
@ -313,19 +356,24 @@ class ApiService {
Future<Map<String, dynamic>> _makeGetRequest(
Uri url, Map<String, String> headers) async {
// Add global APP_SIGNATURE header
headers['APP-SIGNATURE'] = 'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y';
final response = await http.get(url, headers: headers);
return _handleResponse(response);
}
Future<Map<String, dynamic>> _makePostRequest(
Uri url, Map<String, String> body, Map<String, String> headers) async {
// Add global APP_SIGNATURE header
headers['APP-SIGNATURE'] = 'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y';
final response = await http.post(url, headers: headers, body: body);
return _handleResponse(response);
}
Future<Map<String, dynamic>> _makePostRequestWithoutFormData(
Uri url, String body, Map<String, String> headers) async {
// Add global APP_SIGNATURE header
headers['APP-SIGNATURE'] = 'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y';
final response = await http.post(url, headers: headers, body: body);
return _handleResponse(response);
}

View File

@ -3,12 +3,14 @@ import 'package:nhance_app_pwa/customAppBar/responsive.dart';
import 'file_upload_service.dart';
class MultiFileUploadWidget extends StatefulWidget {
const MultiFileUploadWidget({super.key});
final bool forceMobile;
const MultiFileUploadWidget({super.key, this.forceMobile = false});
@override
State<MultiFileUploadWidget> createState() => _MultiFileUploadWidgetState();
static bool hasFiles = false; // Static variable to check from parent
static bool hasFiles = false;
}
class _MultiFileUploadWidgetState extends State<MultiFileUploadWidget> {
@ -60,7 +62,7 @@ class _MultiFileUploadWidgetState extends State<MultiFileUploadWidget> {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (Responsive.isMobile(context)) ...[
if (widget.forceMobile || Responsive.isMobile(context)) ...[
OutlinedButton.icon(
onPressed: _pickFiles,
icon: const Icon(Icons.file_upload_outlined,

File diff suppressed because one or more lines are too long

View File

@ -47,6 +47,7 @@ class _ticketsState extends State<tickets> {
dynamic policyTypeCondition;
dynamic client_policy_id;
dynamic selfDetails;
dynamic emailId;
List<Map<String, dynamic>> employeePolicyList = [];
// Declare subjectController and bodyController as instance variables
@ -103,6 +104,7 @@ class _ticketsState extends State<tickets> {
print(empCodeString); // Check if emp_code is correct
empPrimaryId = session.empPrimaryId;
client_id = session.client_id;
emailId = session.empEmailCorporate;
print(client_id);
getActiveAndInactivePolicyDetails();
getSelfEmployeeProfile();
@ -117,11 +119,11 @@ class _ticketsState extends State<tickets> {
try {
// Call both APIs
final responseActive = await apiService.getActiveAndInactivePolicyDetails(
client_id!, empCodeString!, 'Active', client_branch_id, mobileNo);
client_id!, empCodeString!, 'Active', client_branch_id, mobileNo,emailId);
final responseInactive =
await apiService.getActiveAndInactivePolicyDetails(client_id!,
empCodeString!, 'Inactive', client_branch_id, mobileNo);
empCodeString!, 'Inactive', client_branch_id, mobileNo,emailId);
final bool isActiveSuccess = responseActive['status'] == 'success' &&
responseActive['data'] != null;
@ -476,6 +478,7 @@ class _ticketsState extends State<tickets> {
policyNumberId,
valueKey:
'policy_no',
combineField: 'policy_name',
),
if (!isPolicyValid)
Text(
@ -601,41 +604,39 @@ class _ticketsState extends State<tickets> {
bottomNavigationBar: Responsive.isDesktop(context)
? null
: CustomBottomNavigationBar(
onTabChanged: (index) {
// repositionBotman();
if (index == 0) {
context.go('/home');
} else if (index == 1) {
context.go('/claims');
} else if (index == 2) {
context.go('/profile');
} else if (index == 3) {
context.go('/help');
} else if (index == 4) {
// Wellness tab clicked show popup
PopupHelper.showRedirectPopup(
context: context,
apiService: apiService,
empPrimaryId: session.empPrimaryId,
);
}
},
icons: [
Icons.home_outlined,
Icons.sticky_note_2_outlined,
Icons.person_outline_outlined,
Icons.headset_mic_outlined,
Icons.health_and_safety_outlined,
],
labels: [
"Home",
"Claims",
"Profile",
"Help",
"Wellness",
],
initialIndex: 3, // Initial index of the bottom navigation bar
),
onTabChanged: (index) {
// Add your navigation logic here
// repositionBotman();
if (index == 0) {
context.push('/home');
} else if (index == 1) {
context.push('/claims');
} else if (index == 2) {
context.push('/profile');
} else if (index == 3) {
context.push('/help');
}
// else if (index == 4) {
// // context.push('/wellness');
// // Wellness tab clicked show popup
// if(!isRetailLoggedIn)
// PopupHelper.showRedirectPopup(
// context: context,
// apiService: apiService,
// empPrimaryId: session.empPrimaryId,
// );
// }
},
icons: [
Icons.home_outlined,
Icons.sticky_note_2_outlined,
Icons.person_outline_outlined,
Icons.headset_mic_outlined,
// Icons.health_and_safety_outlined,
],
labels: ["Home", "Claims", "Profile", "Help"],
initialIndex: 0, // Initial index of the bottom navigation bar
),
));
}
@ -678,15 +679,24 @@ class _ticketsState extends State<tickets> {
String displayField,
T? selectedValue, {
String valueKey = 'id',
}) {
String? combineField,
}) {
return DropdownButtonFormField<T>(
value: selectedValue,
decoration: InputDecoration(labelText: label),
items: itemsList.map<DropdownMenuItem<T>>((item) {
// If combineField is provided show "policy_no - policy_type"
String textToShow;
if (combineField != null) {
textToShow = "${item[displayField]} - ${item[combineField]}";
} else {
textToShow = item[displayField].toString();
}
return DropdownMenuItem<T>(
value: item[valueKey] as T, // cast to generic type
child:
Text(item[displayField].toString()), // always display as String
Text(textToShow), // always display as String
);
}).toList(),
onChanged: readOnly ? null : onChanged,

View File

@ -675,40 +675,39 @@ class _tickettracklistState extends State<tickettracklist> {
bottomNavigationBar: Responsive.isDesktop(context)
? null
: CustomBottomNavigationBar(
onTabChanged: (index) {
if (index == 0) {
context.go('/home');
} else if (index == 1) {
context.go('/claims');
} else if (index == 2) {
context.go('/profile');
} else if (index == 3) {
context.go('/help');
} else if (index == 4) {
// Wellness tab clicked show popup
PopupHelper.showRedirectPopup(
context: context,
apiService: apiService,
empPrimaryId: session.empPrimaryId,
);
}
},
icons: [
Icons.home_outlined,
Icons.sticky_note_2_outlined,
Icons.person_outline_outlined,
Icons.headset_mic_outlined,
Icons.health_and_safety_outlined,
],
labels: [
"Home",
"Claims",
"Profile",
"Help",
"Wellness",
],
initialIndex: 3, // Initial index of the bottom navigation bar
),
onTabChanged: (index) {
// Add your navigation logic here
// repositionBotman();
if (index == 0) {
context.push('/home');
} else if (index == 1) {
context.push('/claims');
} else if (index == 2) {
context.push('/profile');
} else if (index == 3) {
context.push('/help');
}
// else if (index == 4) {
// // context.push('/wellness');
// // Wellness tab clicked show popup
// if(!isRetailLoggedIn)
// PopupHelper.showRedirectPopup(
// context: context,
// apiService: apiService,
// empPrimaryId: session.empPrimaryId,
// );
// }
},
icons: [
Icons.home_outlined,
Icons.sticky_note_2_outlined,
Icons.person_outline_outlined,
Icons.headset_mic_outlined,
// Icons.health_and_safety_outlined,
],
labels: ["Home", "Claims", "Profile", "Help"],
initialIndex: 0, // Initial index of the bottom navigation bar
),
)
);
}

View File

@ -38,6 +38,7 @@ class _wellnessState extends State<wellness> {
dynamic mobileNo;
dynamic policyList;
dynamic employeeDetailsList;
dynamic emailId;
final session = SessionManager();
@override
@ -67,6 +68,7 @@ class _wellnessState extends State<wellness> {
print(empCodeString); // Check if emp_code is correct
empPrimaryId = session.empPrimaryId;
client_id = session.client_id;
emailId = session.empEmailCorporate;
print(client_id);
// getAdvertisementSliderImage();
getActiveAndInactivePolicyDetails('Active');
@ -83,7 +85,7 @@ class _wellnessState extends State<wellness> {
});
print('check 1');
final response = await apiService.getActiveAndInactivePolicyDetails(
client_id!, empCodeString!, status, client_branch_id, mobileNo);
client_id!, empCodeString!, status, client_branch_id, mobileNo,emailId);
print('check 1');
if (response['status'] == 'success') {
policyList = response['data'];
@ -365,7 +367,7 @@ class _wellnessState extends State<wellness> {
: CustomBottomNavigationBar(
onTabChanged: (index) {
// Add your navigation logic here
// For example:
// repositionBotman();
if (index == 0) {
context.push('/home');
} else if (index == 1) {
@ -374,25 +376,27 @@ class _wellnessState extends State<wellness> {
context.push('/profile');
} else if (index == 3) {
context.push('/help');
} else if (index == 4) {
context.push('/wellness');
}
// else if (index == 4) {
// // context.push('/wellness');
// // Wellness tab clicked show popup
// if(!isRetailLoggedIn)
// PopupHelper.showRedirectPopup(
// context: context,
// apiService: apiService,
// empPrimaryId: session.empPrimaryId,
// );
// }
},
icons: [
Icons.home_outlined,
Icons.sticky_note_2_outlined,
Icons.person_outline_outlined,
Icons.headset_mic_outlined,
Icons.health_and_safety_outlined,
// Icons.health_and_safety_outlined,
],
labels: [
"Home",
"Claims",
"Profile",
"Help",
"Wellness",
],
initialIndex: 4, // Initial index of the bottom navigation bar
labels: ["Home", "Claims", "Profile", "Help"],
initialIndex: 0, // Initial index of the bottom navigation bar
),
)
);

View File

@ -0,0 +1,109 @@
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import '../../customAppBar/responsive.dart';
import '../postEnrollment/service/api_service.dart';
import 'SessionManager.dart';
import 'common_update_mobile_dialog.dart';
import 'data_manager.dart';
class BlinkingCard extends StatefulWidget {
final VoidCallback onUpdated; // 👈 add this
const BlinkingCard({super.key, required this.onUpdated});
@override
State<BlinkingCard> createState() => _BlinkingCardState();
}
class _BlinkingCardState extends State<BlinkingCard>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<Color?> _colorTween;
late ApiService apiService;
final dataManager = DataManager();
final session = SessionManager();
@override
void initState() {
super.initState();
apiService = ApiService(context);
_controller = AnimationController(
duration: const Duration(seconds: 1),
vsync: this,
)..repeat(reverse: true); // 🔥 blinking loop
_colorTween = ColorTween(
begin: const Color(0xFFFFE5E5), // Light red
end: const Color(0xFFFFC1C1), // slightly darker for blink effect
).animate(_controller);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _colorTween,
builder: (context, child) {
return Card(
elevation: 3,
shadowColor: Colors.red.shade50,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
child: Container(
decoration: BoxDecoration(
color: _colorTween.value, // 🔥 blinking background color
borderRadius: BorderRadius.circular(10),
),
padding: const EdgeInsets.all(12),
child: Row(
children: [
Expanded(
flex: 7,
child: Text(
"Update Mobile Number",
style: GoogleFonts.poppins(
fontSize: Responsive.isDesktop(context) ? 18 : 12,
fontWeight: FontWeight.w500,
color: const Color(0xFF404040),
),
),
),
Expanded(
flex: 5,
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
ElevatedButton(
onPressed: true ? () async {
final selfDetails = dataManager.selfProfile;
final updatedNumber = await showUpdateMobileDialog(context, apiService, session.client_id!, selfDetails?['email_corporate'], selfDetails?['mobile']);
if (updatedNumber != null && updatedNumber.isNotEmpty) {
// setState(() => selfMobile = updatedNumber);
dataManager.loadSelfEmployeeProfile(
clientId: session.client_id!,
empCode: session.empCodeString!,
clientBranchId: session.empClientBranchId!,
);
widget.onUpdated();
}
} : null,
child: const Text("Update"),
),
],
),
)
],
),
),
);
},
);
}
}

View File

@ -8,8 +8,8 @@ import 'package:go_router/go_router.dart';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';
import '../../config/environment.dart';
import '../../customAppBar/toastHelper.dart';
import '../../models/environment.dart';
import '../../models/platform_helper_mobile.dart';
import 'SessionManager.dart';
@ -96,6 +96,7 @@ class TokenService {
body: json.encode(params),
headers: {
HttpHeaders.contentTypeHeader: 'application/json',
'APP-SIGNATURE': 'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y',
},
);

View File

@ -5,7 +5,6 @@ import 'package:google_fonts/google_fonts.dart';
import 'package:http/http.dart' as http;
import '../../customAppBar/toastHelper.dart';
import '../../models/environment.dart';
import '../postEnrollment/service/api_service.dart';
import 'package:flutter/material.dart';

View File

@ -47,7 +47,7 @@ class DataManager extends ChangeNotifier {
Future<void> loadAdvertisementImages() async {
if (_adsLoaded) return;
final response = await _apiService.getAdvertisementImageToApi();
final response = await _apiService.getAdvertisementImageToApi('');
if (response['status'] == 'success') {
_advertisementImages = await List<String>.from(response['data']);
_adsLoaded = true;
@ -72,7 +72,7 @@ class DataManager extends ChangeNotifier {
empCode,
status,
clientBranchId!,
mobileNo!,
mobileNo ?? '',''
);
if (response['status'] == 'success') {
@ -94,7 +94,7 @@ class DataManager extends ChangeNotifier {
required String clientBranchId,
bool forceRefresh = false,
}) async {
if (_selfProfileLoaded && !forceRefresh) return;
// if (_selfProfileLoaded && !forceRefresh) return;
final response = await _apiService.getSelfEmployeeProfileDetails(
clientId,

View File

@ -0,0 +1,275 @@
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:go_router/go_router.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:nhance_app_pwa/customAppBar/responsive.dart';
import 'package:nhance_app_pwa/pages/postEnrollment/service/svg_service.dart';
import 'package:flutter/foundation.dart';
import 'package:shared_preferences/shared_preferences.dart';
void showBlurPopup(BuildContext context, emp_name) {
showDialog(
context: context,
barrierColor: Colors.black.withOpacity(0.6),
barrierDismissible: true,
builder: (context) {
return BlurPopup(
empName: emp_name,
isWeb: kIsWeb, // WEB OR MOBILE
);
},
);
}
class BlurPopup extends StatelessWidget {
final String empName;
final bool isWeb;
const BlurPopup({super.key, required this.empName,required this.isWeb,});
@override
Widget build(BuildContext context) {
return Stack(
children: [
// Blurred background
BackdropFilter(
filter: ImageFilter.blur(sigmaX: 6, sigmaY: 6),
child: Container(color: Colors.black.withOpacity(0.3)),
),
Align(
alignment: isWeb ? Alignment.center : Alignment.bottomCenter,
child: Material(
// <-- FIX: Add Material widget
color: Colors.transparent,
child: Container(
width: isWeb ? 600 : double.infinity,
margin: isWeb ? const EdgeInsets.symmetric(horizontal: 20) : null,
padding: EdgeInsets.all(20),
decoration: BoxDecoration(
color: Color(0xFF55babe),
borderRadius: isWeb ? BorderRadius.all(Radius.circular(20)) : BorderRadius.vertical(top: Radius.circular(25)),
),
child: SingleChildScrollView(
child: buildPopupContent(context,empName),
),
),
),
),
],
);
}
}
Widget buildPopupContent(BuildContext context, String empName) {
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// if(Responsive.isDesktop(context))
// Align(
// alignment: Alignment.topRight,
// child: InkWell(
// onTap: () => Navigator.pop(context),
// child: const Icon(Icons.close,
// size: 26, color: Colors.black87),
// ),
// ),
// if(Responsive.isDesktop(context))
// const SizedBox(height: 10),
// Center(
// child: Container(
// height: 90,
// width: 90,
// decoration: const BoxDecoration(
// shape: BoxShape.circle,
// color: Color(0xFFF8E6E8),
// ),
// padding: const EdgeInsets.all(18), // adjust svg size
// child: SvgPicture.string(SvgService.initialPopup)
// ),
// ),
// Center(
// child: Container(
// height: 90,
// width: 90,
// decoration: const BoxDecoration(
// shape: BoxShape.circle,
// color: Color(0xFFF8E6E8),
// ),
// child: const Icon(Icons.rocket_launch_outlined,
// color: Colors.red, size: 45),
// ),
// ),
//
// const SizedBox(height: 15),
Center(
child: Text(
"🚀 New Policy Alert!",
style: GoogleFonts.poppins(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
const SizedBox(height: 8),
Center(
child: Text(
"Hello $empName,",
textAlign: TextAlign.center,
style: GoogleFonts.poppins(
fontSize: 18,
color: Colors.black87,
fontWeight: FontWeight.w600,
),
),
),
const SizedBox(height: 10),
Text(
"We've confirmed your enrollment in your new health insurance policy.",
style: GoogleFonts.poppins(
fontSize: 15, color: Colors.black87),
),
const SizedBox(height: 8),
Text(
"Your next crucial step is to ensure your coverage is accurate! "
"Please take a moment now to verify and update the following information:",
style: GoogleFonts.poppins(
fontSize: 15, color: Colors.black87),
),
const SizedBox(height: 10),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Icon(Icons.check_circle,
color: Color(0xFFE26728), size: 25),
SizedBox(width: 10),
Expanded(
child: Text(
"Your Personal Profile: Confirm your contact details and basic information are up-to-date.",
style: GoogleFonts.poppins(fontSize: 15),
),
),
],
),
const SizedBox(height: 10),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Icon(Icons.groups,
color: Color(0xFFE26728), size: 25),
SizedBox(width: 10),
Expanded(
child: Text(
"Family Composition: Check and update the list of covered dependents on your policy.",
style: GoogleFonts.poppins(fontSize: 15),
),
),
],
),
const SizedBox(height: 10),
Text(
"Why update now? Accurate details ensure fast claim processing and correct coverage for your entire family.",
style: GoogleFonts.poppins(
fontSize: 15, color: Colors.black87),
),
const SizedBox(height: 15),
// Primary Button Update Details
SizedBox(
width: double.infinity,
height: 40,
child: DecoratedBox(
decoration: BoxDecoration(
color: Color(0xFFE26728),
borderRadius: BorderRadius.circular(10),
),
child: ElevatedButton(
onPressed: () async {
final prefs = await SharedPreferences.getInstance();
await prefs.setBool('cancel_flag', true);
context.go('/empDetails');
},
style: ElevatedButton.styleFrom(
backgroundColor: Colors.transparent,
shadowColor: Colors.transparent,
),
child: Text(
"Update My Details Now",
style: GoogleFonts.poppins(
color: Colors.white,
fontSize: 15,
fontWeight: FontWeight.w500,
),
),
),
),
),
const SizedBox(height: 15),
Center(
child: Text(
"You can complete this later in the Profile section, but we highly recommend doing it now.",
textAlign: TextAlign.center,
style: GoogleFonts.poppins(
fontSize: 14,
color: Colors.black87,
fontWeight: FontWeight.w400,
),
),
),
const SizedBox(height: 15),
// Cancel Button
SizedBox(
width: double.infinity,
height: 40,
child: OutlinedButton(
onPressed: () async {
final prefs = await SharedPreferences.getInstance();
await prefs.setBool('cancel_flag', true); // Save the key
Navigator.pop(context);
},
style: OutlinedButton.styleFrom(
side: const BorderSide(color: Colors.black54),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
),
child: Text(
"Cancel And Go Back",
style: GoogleFonts.poppins(
color: Colors.black87,
fontSize: 15,
fontWeight: FontWeight.w500,
),
),
),
),
const SizedBox(height: 10),
],
);
}

View File

@ -0,0 +1,318 @@
library ribbon;
import 'package:flutter/material.dart';
import 'dart:math' as math;
const TextStyle _kTextStyle = TextStyle(
color: Color(0xFFFFFFFF),
fontSize: 12,
fontWeight: FontWeight.w900,
height: 1.0);
enum RibbonLocation {
topStart,
topEnd,
bottomStart,
bottomEnd,
}
class Ribbon extends StatelessWidget {
final double nearLength;
final double farLength;
final String title;
final Color color;
final TextStyle titleStyle;
final RibbonLocation location;
final Widget child;
const Ribbon(
{Key? key,
required this.nearLength,
required this.farLength,
required this.title,
this.titleStyle = _kTextStyle,
this.color = Colors.white,
this.location = RibbonLocation.topStart,
required this.child})
: super(key: key);
@override
Widget build(BuildContext context) {
return CustomPaint(
foregroundPainter: _RibbonPainter(
nearLength: nearLength,
farLength: farLength,
title: title,
titleStyle: titleStyle,
color: color,
location: location,
),
child: child);
}
}
class _RibbonPainter extends CustomPainter {
double nearLength;
double farLength;
final String title;
final Color color;
final TextStyle titleStyle;
final RibbonLocation location;
bool initialized = false;
late TextPainter textPainter;
late Paint paintRibbon;
late Path pathRibbon;
late double rotateRibbon;
late Offset offsetRibbon;
late Offset offsetTitle;
late Paint paintShadow;
static const BoxShadow _shadow = BoxShadow(
color: Color(0x7F000000),
blurRadius: 6.0,
);
_RibbonPainter(
{required this.nearLength,
required this.farLength,
required this.title,
required this.titleStyle,
required this.color,
required this.location});
@override
void paint(Canvas canvas, Size size) {
if (!initialized) _initializ(size);
// canvas.drawPath(pathRibbon, paintShadow);
canvas
..drawShadow(pathRibbon, const Color(0x7F000000), 2.0, true)
..drawPath(pathRibbon, paintRibbon)
// canvas
..translate(offsetRibbon.dx, offsetRibbon.dy)
..rotate(rotateRibbon);
// ..clipPath(pathRibbon);
textPainter.paint(canvas, offsetTitle);
}
@override
bool shouldRepaint(_RibbonPainter oldDelegate) {
return title != oldDelegate.title ||
nearLength != oldDelegate.nearLength ||
farLength != oldDelegate.farLength ||
color != oldDelegate.color ||
location != oldDelegate.location;
}
void _initializ(Size size) {
initialized = true;
if (nearLength > farLength) {
double temp = farLength;
farLength = nearLength;
nearLength = temp;
}
if (farLength > size.width) farLength = size.width;
TextSpan span = TextSpan(style: titleStyle, text: title);
textPainter = TextPainter(
text: span,
textAlign: TextAlign.center,
textDirection: TextDirection.ltr);
textPainter.layout();
paintRibbon = Paint()
..color = color
..style = PaintingStyle.fill;
offsetTitle = Offset(-textPainter.width / 2, -textPainter.height / 2);
rotateRibbon = _rotation;
pathRibbon = _ribbonPath(size);
paintShadow = _shadow.toPaint();
}
Path _ribbonPath(Size size) {
Path path = Path();
List<Offset> vec = [];
if (size.width <= size.height) {
switch (location) {
case RibbonLocation.topStart:
path.moveTo(nearLength, 0);
vec.add(Offset(nearLength, 0));
path.lineTo(farLength, 0);
vec.add(Offset(farLength, 0));
path.lineTo(0, farLength);
vec.add(Offset(0, farLength));
path.lineTo(0, nearLength);
vec.add(Offset(0, nearLength));
break;
case RibbonLocation.topEnd:
path.moveTo(size.width - nearLength, 0);
vec.add(Offset(size.width - nearLength, 0));
path.lineTo(size.width - farLength, 0);
vec.add(Offset(size.width - farLength, 0));
path.lineTo(size.width, farLength);
vec.add(Offset(size.width, farLength));
path.lineTo(size.width, nearLength);
vec.add(Offset(size.width, nearLength));
break;
case RibbonLocation.bottomStart:
path.moveTo(0, size.height - nearLength);
vec.add(Offset(0, size.height - nearLength));
path.lineTo(0, size.height - farLength);
vec.add(Offset(0, size.height - farLength));
path.lineTo(farLength, size.height);
vec.add(Offset(farLength, size.height));
path.lineTo(nearLength, size.height);
vec.add(Offset(nearLength, size.height));
break;
case RibbonLocation.bottomEnd:
path.moveTo(size.width - nearLength, size.height);
vec.add(Offset(size.width - nearLength, size.height));
path.lineTo(size.width - farLength, size.height);
vec.add(Offset(size.width - farLength, size.height));
path.lineTo(size.width, size.height - farLength);
vec.add(Offset(size.width, size.height - farLength));
path.lineTo(size.width, size.height - nearLength);
vec.add(Offset(size.width, size.height - nearLength));
break;
}
} else {
switch (location) {
case RibbonLocation.topStart:
path.moveTo(nearLength, 0);
vec.add(Offset(nearLength, 0));
path.lineTo(farLength, 0);
vec.add(Offset(farLength, 0));
if (farLength <= size.height) {
path.lineTo(0, farLength);
vec.add(Offset(0, farLength));
path.lineTo(0, nearLength);
vec.add(Offset(0, nearLength));
} else {
path.lineTo(farLength - size.height, size.height);
vec.add(Offset(farLength - size.height, size.height));
if (nearLength <= size.height) {
path.lineTo(0, size.height);
vec.add(Offset(0, size.height));
path.lineTo(0, nearLength);
vec.add(Offset(0, nearLength));
} else {
path.lineTo(nearLength - size.height, size.height);
vec.add(Offset(nearLength - size.height, size.height));
}
}
break;
case RibbonLocation.topEnd:
path.moveTo(size.width - nearLength, 0);
vec.add(Offset(size.width - nearLength, 0));
path.lineTo(size.width - farLength, 0);
vec.add(Offset(size.width - farLength, 0));
if (farLength <= size.height) {
path.lineTo(size.width, farLength);
vec.add(Offset(size.width, farLength));
path.lineTo(size.width, nearLength);
vec.add(Offset(size.width, nearLength));
} else {
path.lineTo(size.width - (farLength - size.height), size.height);
vec.add(
Offset(size.width - (farLength - size.height), size.height));
if (nearLength <= size.height) {
path.lineTo(size.width, size.height);
vec.add(Offset(size.width, size.height));
path.lineTo(size.width, nearLength);
vec.add(Offset(size.width, nearLength));
} else {
path.lineTo(size.width - (nearLength - size.height), size.height);
vec.add(
Offset(size.width - (nearLength - size.height), size.height));
}
}
break;
case RibbonLocation.bottomStart:
path.moveTo(nearLength, size.height);
vec.add(Offset(nearLength, size.height));
path.lineTo(farLength, size.height);
vec.add(Offset(farLength, size.height));
if (farLength <= size.height) {
path.lineTo(0, size.height - farLength);
vec.add(Offset(0, size.height - farLength));
path.lineTo(0, size.height - nearLength);
vec.add(Offset(0, size.height - nearLength));
} else {
path.lineTo(farLength - size.height, 0);
vec.add(Offset(farLength - size.height, 0));
if (nearLength <= size.height) {
path.lineTo(0, 0);
vec.add(const Offset(0, 0));
path.lineTo(0, size.height - nearLength);
vec.add(Offset(0, size.height - nearLength));
} else {
path.lineTo(nearLength - size.height, 0);
vec.add(Offset(nearLength - size.height, 0));
}
}
break;
case RibbonLocation.bottomEnd:
path.moveTo(size.width - nearLength, size.height);
vec.add(Offset(size.width - nearLength, size.height));
path.lineTo(size.width - farLength, size.height);
vec.add(Offset(size.width - farLength, size.height));
if (farLength <= size.height) {
path.lineTo(size.width, size.height - farLength);
vec.add(Offset(size.width, size.height - farLength));
path.lineTo(size.width, size.height - nearLength);
vec.add(Offset(size.width, size.height - nearLength));
} else {
path.lineTo(size.width - (farLength - size.height), 0);
vec.add(Offset(size.width - (farLength - size.height), 0));
if (nearLength <= size.height) {
path.lineTo(size.width, 0);
vec.add(Offset(size.width, 0));
path.lineTo(size.width, size.height - nearLength);
vec.add(Offset(size.width, size.height - nearLength));
} else {
path.lineTo(size.width - (nearLength - size.height), 0);
vec.add(Offset(size.width - (nearLength - size.height), 0));
}
}
break;
}
}
path.close();
List<Offset> vec2 = vec.toSet().toList();
offsetRibbon = _center(vec2);
// print('cx = ${offsetRibbon.dx},cy = ${offsetRibbon.dy}');
return path;
}
double get _rotation {
switch (location) {
case RibbonLocation.topStart:
return -math.pi / 4;
case RibbonLocation.topEnd:
return math.pi / 4;
case RibbonLocation.bottomStart:
return math.pi / 4;
case RibbonLocation.bottomEnd:
return -math.pi / 4;
}
}
Offset _center(List<Offset> vecs) {
double sumX = 0, sumY = 0, sumS = 0;
double x1 = vecs[0].dx;
double y1 = vecs[0].dy;
double x2 = vecs[1].dx;
double y2 = vecs[1].dy;
double x3, y3;
for (int i = 2; i < vecs.length; i++) {
x3 = vecs[i].dx;
y3 = vecs[i].dy;
double s = ((x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1)) / 2.0;
sumX += (x1 + x2 + x3) * s;
sumY += (y1 + y2 + y3) * s;
sumS += s;
x2 = x3;
y2 = y3;
}
double cx = sumX / sumS / 3.0;
double cy = sumY / sumS / 3.0;
return Offset(cx, cy);
}
}

View File

@ -9,8 +9,8 @@ import 'package:jwt_decode/jwt_decode.dart';
import 'package:nhance_app_pwa/customAppBar/toastHelper.dart';
import 'package:pinput/pinput.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../../config/environment.dart';
import '../../customAppBar/responsive.dart';
import '../../models/environment.dart';
import '../postEnrollment/service/svg_service.dart';
import '../service/SessionManager.dart';
import '../service/TokenService.dart';
@ -87,6 +87,7 @@ class _pinPageState extends State<pinPage> {
body: json.encode(params),
headers: {
HttpHeaders.contentTypeHeader: 'application/json',
'APP-SIGNATURE': 'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y',
},
);
@ -171,6 +172,7 @@ class _pinPageState extends State<pinPage> {
body: json.encode(params),
headers: {
HttpHeaders.contentTypeHeader: 'application/json',
'APP-SIGNATURE': 'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y',
},
);
@ -268,7 +270,7 @@ class _pinPageState extends State<pinPage> {
print(_postToken);
if (_postToken != null && _postToken.isNotEmpty) {
ToastHelper.showSuccessToast(context, 'Successfully Login');
ToastHelper.showSuccessToast(context, 'Successfully Logged In');
// if (enrollmentEmp_status == 'enrolled' ||
// enrollmentEmp_status == 'active') {
print('Token12345: ${await TokenService.getPostToken()}');
@ -310,7 +312,7 @@ class _pinPageState extends State<pinPage> {
// Redirect to another page
final token = await TokenService.getPreToken();
if (token != null && token.isNotEmpty) {
ToastHelper.showSuccessToast(context, 'Successfully Login');
ToastHelper.showSuccessToast(context, 'Successfully Logged In');
// if (enrollmentEmp_status == 'enrolled' ||
// enrollmentEmp_status == 'active') {
// Navigator.pushReplacementNamed(context, 'home');
@ -366,6 +368,7 @@ class _pinPageState extends State<pinPage> {
body: json.encode(params),
headers: {
HttpHeaders.contentTypeHeader: 'application/json',
'APP-SIGNATURE': 'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y',
},
);
@ -410,6 +413,7 @@ class _pinPageState extends State<pinPage> {
headers: {
'Authorization':
'Bearer $_token', // Add token to the Authorization header
'APP-SIGNATURE': 'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y',
},
);
if (response.statusCode == 200) {
@ -789,43 +793,46 @@ class _pinPageState extends State<pinPage> {
)),
Align(
alignment: Alignment.bottomCenter,
child: Container(
width: double.infinity, // Make the footer full width
child: RichText(
textAlign: TextAlign.center,
text: TextSpan(
text: 'By continuing, you agree with our ',
style: GoogleFonts.poppins(
color: Colors.black,
fontSize: 9,
child: SafeArea(
child: Container(
padding: EdgeInsets.only(bottom: 8),
width: double.infinity,
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(0xFF00989E),
fontSize: 9,
),
),
TextSpan(
text: 'and ',
style: GoogleFonts.poppins(
color: Colors.black,
fontSize: 9,
),
),
TextSpan(
text: 'terms of use',
style: GoogleFonts.poppins(
color: Color(0xFF00989E),
fontSize: 9,
),
),
],
),
children: <TextSpan>[
TextSpan(
text: 'privacy policy ',
style: GoogleFonts.poppins(
color: Color(0xFF00989E),
fontSize: 9,
),
),
TextSpan(
text: 'and ',
style: GoogleFonts.poppins(
color: Colors.black,
fontSize: 9,
),
),
TextSpan(
text: 'terms of use',
style: GoogleFonts.poppins(
color: Color(0xFF00989E),
fontSize: 9,
),
),
],
),
),
),
),
)
]),
))));
}

View File

@ -8,9 +8,9 @@ import 'package:flutter/material.dart';
import 'package:nhance_app_pwa/pages/service/TokenService.dart';
import 'package:pinput/pinput.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../../config/environment.dart';
import '../../customAppBar/responsive.dart';
import '../../customAppBar/toastHelper.dart';
import '../../models/environment.dart';
import '../postEnrollment/service/svg_service.dart';
import 'authenticationService.dart';
@ -78,6 +78,7 @@ class _changePinState extends State<changePin> {
headers: {
HttpHeaders.contentTypeHeader: 'application/json',
'Authorization': 'Bearer $_token',
'APP-SIGNATURE': 'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y',
},
);
print('response $response');
@ -123,7 +124,7 @@ class _changePinState extends State<changePin> {
return 'PIN must be 4 digits';
}
if (value == _oldPinController.text) {
return 'Pin not should be same';
return 'Please enter a different PIN.';
}
return null;
}

View File

@ -8,9 +8,9 @@ import 'package:google_fonts/google_fonts.dart';
import 'package:nhance_app_pwa/pages/service/TokenService.dart';
import 'package:pinput/pinput.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../../config/environment.dart';
import '../../customAppBar/responsive.dart';
import '../../customAppBar/toastHelper.dart';
import '../../models/environment.dart';
import '../postEnrollment/service/svg_service.dart';
import '../service/SessionManager.dart';
import 'authenticationService.dart';
@ -117,6 +117,7 @@ class _pinSettingPageState extends State<pinSettingPage> {
headers: {
HttpHeaders.contentTypeHeader: 'application/json',
'Authorization': 'Bearer $token',
'APP-SIGNATURE': 'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y',
},
);
@ -717,43 +718,46 @@ class _pinSettingPageState extends State<pinSettingPage> {
)),
Align(
alignment: Alignment.bottomCenter,
child: Container(
width: double.infinity, // Make the footer full width
child: RichText(
textAlign: TextAlign.center,
text: TextSpan(
text: 'By continuing, you agree with our ',
style: GoogleFonts.poppins(
color: Colors.black,
fontSize: 9,
child: SafeArea(
child: Container(
padding: EdgeInsets.only(bottom: 8),
width: double.infinity,
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(0xFF00989E),
fontSize: 9,
),
),
TextSpan(
text: 'and ',
style: GoogleFonts.poppins(
color: Colors.black,
fontSize: 9,
),
),
TextSpan(
text: 'terms of use',
style: GoogleFonts.poppins(
color: Color(0xFF00989E),
fontSize: 9,
),
),
],
),
children: <TextSpan>[
TextSpan(
text: 'privacy policy ',
style: GoogleFonts.poppins(
color: Color(0xFF00989E),
fontSize: 9,
),
),
TextSpan(
text: 'and ',
style: GoogleFonts.poppins(
color: Colors.black,
fontSize: 9,
),
),
TextSpan(
text: 'terms of use',
style: GoogleFonts.poppins(
color: Color(0xFF00989E),
fontSize: 9,
),
),
],
),
),
),
),
)
]),
))));
}

View File

@ -10,9 +10,9 @@ import 'package:nhance_app_pwa/pages/service/SessionManager.dart';
import 'dart:io';
import 'package:google_fonts/google_fonts.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../config/environment.dart';
import '../customAppBar/responsive.dart';
import '../customAppBar/toastHelper.dart';
import '../models/environment.dart';
class setPassword extends StatefulWidget {
final String email;
@ -89,6 +89,7 @@ class _setPasswordState extends State<setPassword> {
body: json.encode(payload),
headers: {
HttpHeaders.contentTypeHeader: 'application/json',
'APP-SIGNATURE': 'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y',
},
);

View File

@ -17,8 +17,8 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix.
#version: 1.0.32+32
version: 1.0.22+25
#version: 2.0.6+44
version: 1.0.23+26
#version: 2.0.7+45
environment:
sdk: '>=3.3.3 <4.0.0'
@ -62,12 +62,16 @@ dependencies:
webview_flutter: ^4.13.0
webview_flutter_android: ^4.7.0
flutter_inappwebview: ^6.1.5
file_picker: ^10.3.2
file_picker: ^10.3.7
file_selector: ^1.0.3
universal_html: ^2.2.4
go_router: ^16.2.2
flutter_secure_storage: ^9.2.4
printing: ^5.14.2
flutter_animate: ^4.5.2
carousel_slider: ^5.1.1
dropdown_search: ^6.0.2
ribbon_widget: ^1.0.5
dev_dependencies:
flutter_test:
@ -94,11 +98,6 @@ flutter:
# To add assets to your application, add an assets section, like this:
assets:
- assets/
- .env
- .env.development
- .env.production
- .env.test
- .env.uat
- assets/botman_chat.html
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg

View File

@ -6,18 +6,18 @@
<meta charset="UTF-8">
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
<meta name="description" content="Nhance App Flutter">
<meta name="description" content="Nhance Benefits">
<!-- iOS meta tags & icons -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-title" content="nhance_app_pwa">
<meta name="apple-mobile-web-app-title" content="nhance_benefits">
<link rel="apple-touch-icon" href="icons/Icon-192.png">
<!-- Favicon -->
<link rel="icon" type="image/png" href="favicon.png"/>
<title>Nhance</title>
<title>Nhance Benefits</title>
<link rel="manifest" href="manifest.json">
<style>