This commit is contained in:
Surendiran 2026-02-13 10:25:27 +05:30
parent 5d0566e338
commit 511a671c06
20 changed files with 1482 additions and 1800 deletions

View File

@ -19,12 +19,12 @@ if (project.hasProperty('google-services.json')) {
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '53'
flutterVersionCode = '54'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '2.0.15'
flutterVersionName = '2.0.16'
}
def keystoreProperties = new Properties()

View File

@ -9,7 +9,6 @@ import 'package:nhance_app_pwa/customAppBar/responsive.dart';
import 'package:nhance_app_pwa/customAppBar/toastHelper.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../config/environment.dart';
import '../models/platform_helper_mobile.dart'
if (dart.library.html) '../models/platform_helper_other.dart';
@ -29,7 +28,7 @@ class _CustomAppBarState extends State<CustomAppBar> {
bool showBackToHR = true;
bool hideInactiveStatus = true;
dynamic empStatus;
dynamic _postToken;
// dynamic _postToken;
bool isTokenAvailable = false;
late ApiService apiService;
final session = SessionManager();
@ -44,16 +43,28 @@ class _CustomAppBarState extends State<CustomAppBar> {
Future<void> checkEnrollToken() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
setState(() {
isTokenAvailable = prefs.getString('enrollToken') != null;
isTokenAvailable = prefs.getString('pre_token') != null;
});
}
Future<void> getEmpStatus() async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
// final empStatusValue = prefs.getString('enrollmentEmp_status');
final postTokenValue = prefs.getString('post_token');
setState(() {
empStatus = prefs.getString('enrollmentEmp_status');
// _postToken = prefs.getString('_postToken');
isTokenAvailable = prefs.getString('_postToken') != null;
// // empStatus: null-safe + empty-safe
// empStatus = (empStatusValue != null && empStatusValue.isNotEmpty)
// ? empStatusValue
// : null;
// token availability: null + empty check
isTokenAvailable =
postTokenValue != null && postTokenValue.trim().isNotEmpty;
debugPrint('empStatus: $empStatus');
debugPrint('isTokenAvailable: $isTokenAvailable');
});
}
@ -80,7 +91,8 @@ class _CustomAppBarState extends State<CustomAppBar> {
body: json.encode(params),
headers: {
HttpHeaders.contentTypeHeader: 'application/json',
'APP-SIGNATURE': 'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y',
'APP-SIGNATURE':
'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y',
},
);
@ -95,7 +107,8 @@ class _CustomAppBarState extends State<CustomAppBar> {
prefs.setString('mpin', data['Mpin']);
}
if (data['is_biometric_enabled'] != null) {
prefs.setString('is_biometric_enabled', data['is_biometric_enabled']);
prefs.setString(
'is_biometric_enabled', data['is_biometric_enabled']);
}
if (data['is_mpin_skipped'] != null) {
prefs.setString('is_mpin_skipped', data['is_mpin_skipped']);
@ -169,8 +182,6 @@ class _CustomAppBarState extends State<CustomAppBar> {
}
}
@override
Widget build(BuildContext context) {
final sw = MediaQuery.of(context).size.width;
@ -207,19 +218,19 @@ class _CustomAppBarState extends State<CustomAppBar> {
),
// AdaptiveNavBar Column
if (!isTokenAvailable)
Row(
mainAxisSize: MainAxisSize.min,
children: [
NavBarItem(
text: "Logout",
onTap: () async {
logout(context);
},
),
],
),
Row(
mainAxisSize: MainAxisSize.min,
children: [
NavBarItem(
text: "Logout",
onTap: () async {
logout(context);
},
),
],
),
// if (empStatus == 'enrolled')
if (isTokenAvailable)
if (isTokenAvailable && Responsive.isDesktop(context))
Row(
mainAxisSize: MainAxisSize.min,
children: [
@ -236,21 +247,9 @@ class _CustomAppBarState extends State<CustomAppBar> {
},
),
NavBarItem(
text: "Help",
text: "FAQs",
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,
);
context.push('/faqs');
},
),
NavBarItem(
@ -259,6 +258,29 @@ class _CustomAppBarState extends State<CustomAppBar> {
context.push('/profile');
},
),
NavBarItem(
text: "Help",
onTap: () {
context.push('/help');
},
),
// NavBarItem(
// text: "Wellness",
// onTap: () => handleMenuTap(() {
// PopupHelper.showRedirectPopup(
// context: context,
// apiService: apiService,
// empPrimaryId: session.empPrimaryId,
// );
// }),
// ),
NavBarItem(
text: "Logout",
onTap: () {
logout(context);
},
),
],
),
],
@ -269,6 +291,7 @@ class _CustomAppBarState extends State<CustomAppBar> {
);
}
}
class NavBarItem extends StatelessWidget {
final String text;
final VoidCallback? onTap;
@ -298,4 +321,4 @@ class NavBarItem extends StatelessWidget {
),
);
}
}
}

View File

@ -71,6 +71,8 @@ class _MyEmailVerifyState extends State<MyEmailVerify> {
// final FirebaseMessaging _firebaseMessaging = FirebaseMessaging.instance;
// final FirebaseAuth _auth = FirebaseAuth.instance;
bool _isLoading = false;
bool _isOtpVerified = false;
late String _verificationId;
dynamic empMobileNo;
@ -204,7 +206,13 @@ class _MyEmailVerifyState extends State<MyEmailVerify> {
}
void verifyOTP(String otp) async {
if (_isLoading) return; // prevent double tap
setState(() {
_isLoading = true;
});
try {
// print('EMAIL PARAMS : ${widget.email} - OTP : $otp');
final Map<String, dynamic> payload = (widget.type == 'mobile')
? {'otp': _otpController.text, 'mobile_number': widget.value}
@ -220,9 +228,6 @@ class _MyEmailVerifyState extends State<MyEmailVerify> {
);
print('response : ${response.statusCode}');
if (response.statusCode == 200) {
setState(() {
_isLoading = false;
});
Map<String, dynamic> data = json.decode(response.body);
print('data: $data');
@ -271,43 +276,40 @@ class _MyEmailVerifyState extends State<MyEmailVerify> {
if (postStatus == 'success') {
setState(() {
_isLoading = false;
_isOtpVerified = true; // LOCK
});
postSuccessData(post, data);
} else if (status == 'success') {
setState(() {
_isLoading = false;
_isOtpVerified = true; // LOCK
});
enrollmentSuccessData(data);
} else {
setState(() {
_isLoading = false;
});
final SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.clear();
ToastHelper.showErrorToast(context, 'Invalid OTP. Please try again');
ToastHelper.showErrorToast(context, 'OTP verification failed. Please try again.');
// Show a Snackbar if the OTP is invalid
print('Invalid OTP. Please try again');
print('OTP verification failed. Please try again.');
}
} else {
setState(() {
_isLoading = false;
});
final SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.clear();
ToastHelper.showWarningToast(context, 'Something went wrong');
throw Exception('Failed to verify OTP');
}
} catch (e) {
setState(() {
_isLoading = false;
});
final SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.clear();
print('Error: $e');
ToastHelper.showWarningToast(context, 'Something went wrong');
// Show a Snackbar if there's an error while verifying OTP
print('Failed to verify OTP. Please try again.');
} finally {
if (mounted) {
setState(() {
_isLoading = false;
});
}
}
}
@ -339,13 +341,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!,
);
}
// 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']);
@ -417,7 +419,7 @@ class _MyEmailVerifyState extends State<MyEmailVerify> {
// prefs.setString('enrollmentClient_id', enrollmentClient_id);
// enrollmentEmp_status = decodedToken['emp_status'];
// prefs.setString('enrollmentEmp_status', enrollmentEmp_status);
getClientLogoAndDetails();
// getClientLogoAndDetails();
}
//
// if(kIsWeb) {
@ -505,7 +507,7 @@ class _MyEmailVerifyState extends State<MyEmailVerify> {
// prefs.setString('enrollmentClient_id', enrollmentClient_id);
// enrollmentEmp_status = decodedToken['emp_status'];
// prefs.setString('enrollmentEmp_status', enrollmentEmp_status);
getClientLogoAndDetails();
// getClientLogoAndDetails();
print('Successfully Login');
@ -513,7 +515,7 @@ class _MyEmailVerifyState extends State<MyEmailVerify> {
// final enrollToken = prefs.getString('enrollToken');
// int skipStatus = prefs.getInt('skipStatus') ?? 1;
// final mpinText = prefs.getString('mpinText');
print(isMobilePlatform());
// print(isMobilePlatform());
if (isMobilePlatform()) {
// if (prefs.containsKey('mpin') && mpinText == 'Mpin - exist') {
if (_preToken != null && _preToken.isNotEmpty) {
@ -546,6 +548,7 @@ class _MyEmailVerifyState extends State<MyEmailVerify> {
_otpController.text = '';
_secondsRemaining = 60;
_isTimerRunning = true;
_isLoading = false;
});
startTimer();
verifyMobileAndEmailNumber();
@ -1063,6 +1066,15 @@ class _MyEmailVerifyState extends State<MyEmailVerify> {
keyboardType: TextInputType.number,
showCursor: true,
controller: _otpController,
validator: (value) {
if (value == null || value.isEmpty) {
return 'OTP is required';
}
if (value.length < 6) {
return 'Please enter a valid 6-digit OTP';
}
return null;
},
),
),
SizedBox(height: 10),
@ -1118,20 +1130,28 @@ class _MyEmailVerifyState extends State<MyEmailVerify> {
BorderRadius.circular(10),
),
),
onPressed: () {
if (_formKey.currentState!
.validate()) {
_formKey.currentState!
.save(); // Save form fields before calling verifyOTP
verifyOTP(
_otpController.text);
}
},
child: Text(
"Submit",
style: GoogleFonts.poppins(
color: Color(0xFFFFFFFF)),
),
onPressed: (_isLoading || _isOtpVerified)
? null
: () {
if (_formKey.currentState!.validate()) {
verifyOTP(_otpController.text.trim());
}
},
child: _isLoading
? CircularProgressIndicator(
valueColor:
AlwaysStoppedAnimation<
Color>(
Color(0xFF00989E),
),
)
: Text( "Submit",
style: GoogleFonts
.poppins(
color: Color(
0xFFFFFFFF),
),
)
),
),
),

View File

@ -4590,40 +4590,38 @@ class _addOnsDetailsState extends State<addOnsDetails> {
? CustomBottomNavigationBar(
onTabChanged: (index) {
// Add your navigation logic here
// For example:
// repositionBotman();
if (index == 0) {
context.go('/home');
// Navigator.pushNamed(context, 'home');
context.push('/home');
} else if (index == 1) {
context.go('/claims');
// Navigator.pushNamed(context, 'claims');
context.push('/claims');
} else if (index == 2) {
context.go('/profile');
// Navigator.pushNamed(context, 'profile');
context.push('/faqs');
} else if (index == 3) {
context.go('/help');
// Navigator.pushNamed(context, 'help');
context.push('/profile');
} else if (index == 4) {
context.go('/wellness');
// Navigator.pushNamed(context, 'wellness');
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.question_answer_outlined,
Icons.person_outline_outlined,
Icons.headset_mic_outlined,
Icons.health_and_safety_outlined,
],
labels: [
"Home",
"Claims",
"Profile",
"Help",
"wellness",
],
initialIndex:
0, // Initial index of the bottom navigation bar
labels: ["Home", "Claims", "FAQs", "Profile","Help"],
initialIndex: 0, // Initial index of the bottom navigation bar
) : null,
) );
}

View File

@ -1044,42 +1044,41 @@ class _empDetailsState extends State<empDetails> {
? null
: isTokenAvailable
? CustomBottomNavigationBar(
onTabChanged: (index) {
// For example:
if (index == 0) {
context.go('/home');
// Navigator.pushNamed(context, 'home');
} else if (index == 1) {
context.go('/claims');
// Navigator.pushNamed(context, 'claims');
} else if (index == 2) {
context.go('/profile');
// Navigator.pushNamed(context, 'profile');
} else if (index == 3) {
context.go('/help');
// Navigator.pushNamed(context, 'help');
} else if (index == 4) {
context.go('/wellness');
// Navigator.pushNamed(context, 'wellness');
}
},
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:
0, // 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('/faqs');
} else if (index == 3) {
context.push('/profile');
} else if (index == 4) {
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.question_answer_outlined,
Icons.person_outline_outlined,
Icons.headset_mic_outlined,
],
labels: ["Home", "Claims", "FAQs", "Profile","Help"],
initialIndex: 0, // Initial index of the bottom navigation bar
)
: null,
));
}

View File

@ -586,6 +586,7 @@ class _empReviewDetailsState extends State<empReviewDetails> {
// setState(() {
topUpClientPolicyId =
topUpSiPolicies['gmc_si_topup']['client_policy_id'];
print('topUpClientPolicyId12345 $topUpClientPolicyId');
topUpSumInsured = topUpSiPolicies['gmc_si_topup']
['family_floaters_of_only_si_value'];
@ -3309,43 +3310,41 @@ setState(() {
? null
: isTokenAvailable
? CustomBottomNavigationBar(
onTabChanged: (index) {
// Add your navigation logic here
// For example:
if (index == 0) {
context.go('/home');
// Navigator.pushNamed(context, 'home');
} else if (index == 1) {
context.go('/claims');
// Navigator.pushNamed(context, 'claims');
} else if (index == 2) {
context.go('/profile');
// Navigator.pushNamed(context, 'profile');
} else if (index == 3) {
context.go('/help');
// Navigator.pushNamed(context, 'help');
} else if (index == 4) {
context.go('/wellness');
// Navigator.pushNamed(context, 'wellness');
}
},
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:
0, // 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('/faqs');
} else if (index == 3) {
context.push('/profile');
} else if (index == 4) {
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.question_answer_outlined,
Icons.person_outline_outlined,
Icons.headset_mic_outlined,
],
labels: ["Home", "Claims", "FAQs", "Profile","Help"],
initialIndex: 0, // Initial index of the bottom navigation bar
)
: null,
));
}

View File

@ -508,6 +508,11 @@ class ApiService {
await _clearLocalStorageAndRedirect();
}
return {};
} else if (response.statusCode == 429) {
final body = jsonDecode(response.body);
final message = body['message'];
ToastHelper.showWarningToast(context, message);
return {};
} else {
throw Exception('Failed to load data');
}

View File

@ -280,7 +280,14 @@ class _loginState extends State<login> {
ToastHelper.showErrorToast(context, message);
print('Invalid mobile number');
}
} else {
} else if (response.statusCode == 429) {
setState(() {
_isLoading = false;
});
Map<String, dynamic> data = json.decode(response.body);
final message = data['message'];
ToastHelper.showErrorToast(context, message);
} else {
setState(() {
_isLoading = false;
});

View File

@ -129,8 +129,6 @@ class _ClaimHistoryPopupState extends State<ClaimHistoryPopup>
});
}
// -------------------------
// Remove assignment
// -------------------------

View File

@ -29,6 +29,7 @@ class _generalExclusionsDeductiblesState
late ApiService apiService;
int _currentIndex = 0;
bool isActive = true;
bool isLoading = false;
dynamic _token;
dynamic empCodeString;
dynamic empPrimaryId;
@ -40,30 +41,19 @@ class _generalExclusionsDeductiblesState
late Map<String, String> generalContent;
late Map<String, String> generalNotes;
dynamic type3;
dynamic type3SectionName;
dynamic type3Heading;
late Map<String, String> type3Content;
// Headings
String? type3SectionName, type3Heading;
String? type4SectionName, type4Heading;
String? type5Heading;
String? type6Heading;
String? type7Heading;
dynamic type4;
dynamic type4SectionName;
dynamic type4Heading;
late Map<String, String> type4Content;
dynamic type5;
dynamic type5SectionName;
dynamic type5Heading;
late Map<String, String> type5Content;
dynamic type6;
dynamic type6SectionName;
dynamic type6Heading;
late Map<String, String> type6Content;
dynamic type7;
dynamic type7SectionName;
dynamic type7Heading;
late Map<String, String> type7Content;
// Content lists
List<String> type3Content = [];
List<String> type4Content = [];
List<String> type5Content = [];
List<String> type6Content = [];
List<String> type7Content = [];
final session = SessionManager();
@ -95,68 +85,81 @@ class _generalExclusionsDeductiblesState
}
}
/// 🔥 Extract <li> text from HTML
List<String> extractListItems(String html) {
final regex = RegExp(r'<li>(.*?)<\/li>', dotAll: true);
return regex
.allMatches(html)
.map((m) => m.group(1)!.replaceAll(RegExp(r'<[^>]*>'), '').trim())
.toList();
}
Future<void> getCashlessAndReimbursement() async {
final response = await apiService.getCashlessAndReimbursementToApi();
print('check 1');
if (response['status'] == 'success') {
print(response['data']);
setState(() => isLoading = true);
try {
final response = await apiService.getCashlessAndReimbursementToApi();
if (response['status'] != 'success') {
setState(() => isLoading = false);
return;
}
final List data = response['data'];
final filtered =
data.where((e) => e['content_section'] != 'Video').toList();
Map<String, dynamic>? findType(String type) {
try {
return filtered.firstWhere((e) => e['type'] == type);
} catch (_) {
return null;
}
}
final t3 = findType('3');
final t4 = findType('4');
final t5 = findType('5');
final t6 = findType('6');
final t7 = findType('7');
setState(() {
generalExclusionsDetails = response['data'][3];
type3 = response['data'][2];
print(type3);
type3SectionName = type3['content_section'];
type3Heading = type3['heading'];
Map<String, dynamic> type3ContentjsonData =
jsonDecode(type3['content']);
type3Content = Map<String, String>.from(type3ContentjsonData);
print('type3Content');
print(type3Content);
if (t3 != null) {
type3SectionName = t3['content_section'];
type3Heading = t3['heading'];
type3Content = extractListItems(t3['content']);
}
type4 = response['data'][3];
print(type4);
type4SectionName = type4['content_section'];
type4Heading = type4['heading'];
Map<String, dynamic> type4ContentjsonData =
jsonDecode(type4['content']);
type4Content = Map<String, String>.from(type4ContentjsonData);
print('type4Content');
print(type4Content);
if (t4 != null) {
type4Heading = t4['heading'];
type4Content = extractListItems(t4['content']);
}
type5 = response['data'][4];
print(type5);
type5SectionName = type5['content_section'];
type5Heading = type5['heading'];
Map<String, dynamic> type5ContentjsonData =
jsonDecode(type5['content']);
type5Content = Map<String, String>.from(type5ContentjsonData);
print('type5Content');
print(type5Content);
if (t5 != null) {
type5Heading = t5['heading'];
type5Content = extractListItems(t5['content']);
}
type6 = response['data'][5];
print(type6);
type6SectionName = type6['content_section'];
type6Heading = type6['heading'];
Map<String, dynamic> type6ContentjsonData =
jsonDecode(type6['content']);
type6Content = Map<String, String>.from(type6ContentjsonData);
print('type6Content');
print(type6Content);
if (t6 != null) {
type6Heading = t6['heading'];
type6Content = extractListItems(t6['content']);
}
type7 = response['data'][6];
print(type7);
type7SectionName = type7['content_section'];
type7Heading = type7['heading'];
Map<String, dynamic> type7ContentjsonData =
jsonDecode(type7['content']);
type7Content = Map<String, String>.from(type7ContentjsonData);
print('type7Content');
print(type7Content);
if (t7 != null) {
type7Heading = t7['heading'];
type7Content = extractListItems(t7['content']);
}
isLoading = false;
});
} else {
print('API request failed with status: ${response['status']}');
} catch (e) {
debugPrint('API ERROR: $e');
setState(() => isLoading = false);
}
}
@override
Widget build(BuildContext context) {
return PopScope(
@ -166,682 +169,140 @@ class _generalExclusionsDeductiblesState
context.pop();
},
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.03,
)
: EdgeInsets.all(10),
color: Colors.white,
backgroundColor: Colors.white,
body: 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
),
)
: SingleChildScrollView(
padding: Responsive.isDesktop(context)
? EdgeInsets.symmetric(
horizontal: MediaQuery.of(context).size.width * 0.2,
vertical: MediaQuery.of(context).size.height * 0.03,
)
: EdgeInsets.all(10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: Responsive.isDesktop(context)
? EdgeInsets.symmetric(vertical: 15, horizontal: 25)
: EdgeInsets.all(0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Expanded(
flex: 12,
child: InkWell(
onTap: () {
context.pop();
},
child: Row(
mainAxisAlignment:
MainAxisAlignment.start,
children: [
// if (!Responsive.isDesktop(context))
Icon(
Icons.chevron_left,
color: Color(0xFF000000),
size: 30,
),
SizedBox(
width: Responsive.isDesktop(context)
? 0
: 5),
Column(
mainAxisAlignment:
MainAxisAlignment.center,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
'General Exclusions & Deductibles',
textAlign: TextAlign.start,
style: GoogleFonts.poppins(
fontSize: 16,
fontWeight: FontWeight.w600,
color: Color(0xFF000000),
),
),
],
),
],
),
),
),
],
),
],
),
Text(
'General Exclusions & Deductibles',
style: GoogleFonts.poppins(
fontSize: 18, fontWeight: FontWeight.w600),
),
SizedBox(height: 15),
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
),
padding: Responsive.isDesktop(context)
? EdgeInsets.symmetric(vertical: 15, horizontal: 25)
: EdgeInsets.all(10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.only(bottom: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
type3SectionName ?? '',
style: GoogleFonts.poppins(
fontSize: Responsive.isDesktop(context)
? 18
: 16,
fontWeight: FontWeight.w500,
color: Color(0xFF000000),
),
),
],
),
),
if (generalExclusionsDetails != null)
Padding(
padding:
EdgeInsets.only(bottom: 20, left: 15),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
SizedBox(height: 10),
LayoutBuilder(
builder: (context, constraints) {
double itemHeight =
50; // Adjust item height based on content
double listViewHeight =
type3Content.length * itemHeight;
double maxHeight =
constraints.maxHeight;
if (listViewHeight > maxHeight) {
listViewHeight = maxHeight;
}
return Container(
height: listViewHeight,
child: ListView.builder(
itemCount: type3Content.length,
itemBuilder: (context, index) {
String key = type3Content.keys
.elementAt(index);
String value =
type3Content[key]!;
return Padding(
padding: const EdgeInsets
.symmetric(vertical: 8.0),
child: Row(
crossAxisAlignment:
CrossAxisAlignment
.start,
children: <Widget>[
Padding(
padding:
const EdgeInsets
.only(
left: 20.0),
child: Text(
"",
style: GoogleFonts
.poppins(
fontSize: 16,
fontWeight:
FontWeight.w400,
color: Color(
0xFFE26728),
),
),
),
Expanded(
child: Text(
value,
style: GoogleFonts
.poppins(
fontSize: 16,
fontWeight:
FontWeight.w400,
color: Color(
0xFF000000),
),
),
),
],
),
);
},
),
);
},
),
],
),
),
]),
),
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
),
padding: Responsive.isDesktop(context)
? EdgeInsets.symmetric(vertical: 15, horizontal: 25)
: EdgeInsets.all(10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.only(bottom: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
type4SectionName ?? '',
style: GoogleFonts.poppins(
fontSize: Responsive.isDesktop(context)
? 18
: 16,
fontWeight: FontWeight.w500,
color: Color(0xFF000000),
),
),
],
),
),
if (generalExclusionsDetails != null)
Padding(
padding:
EdgeInsets.only(bottom: 20, left: 15),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
type4Heading ?? '',
style: GoogleFonts.poppins(
fontSize:
Responsive.isDesktop(context)
? 18
: 16,
fontWeight: FontWeight.w500,
color: Color(0xFF000000),
),
),
SizedBox(height: 10),
LayoutBuilder(
builder: (context, constraints) {
double itemHeight =
40; // Adjust item height based on content
double listViewHeight =
type4Content.length * itemHeight;
double maxHeight =
constraints.maxHeight;
if (listViewHeight > maxHeight) {
listViewHeight = maxHeight;
}
return Container(
height: listViewHeight,
child: ListView.builder(
itemCount: type4Content.length,
itemBuilder: (context, index) {
String key = type4Content.keys
.elementAt(index);
String value =
type4Content[key]!;
return Padding(
padding: const EdgeInsets
.symmetric(vertical: 8.0),
child: Row(
crossAxisAlignment:
CrossAxisAlignment
.start,
children: <Widget>[
Padding(
padding:
const EdgeInsets
.only(
left: 20.0),
child: Text(
"",
style: GoogleFonts
.poppins(
fontSize: 16,
fontWeight:
FontWeight.w400,
color: Color(
0xFFE26728),
),
),
),
Expanded(
child: Text(
value,
style: GoogleFonts
.poppins(
fontSize: 16,
fontWeight:
FontWeight.w400,
color: Color(
0xFF000000),
),
),
),
],
),
);
},
),
);
},
),
],
),
),
]),
),
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
),
padding: Responsive.isDesktop(context)
? EdgeInsets.symmetric(vertical: 15, horizontal: 25)
: EdgeInsets.all(10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (generalExclusionsDetails != null)
Padding(
padding:
EdgeInsets.only(bottom: 20, left: 15),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
type5Heading ?? '',
style: GoogleFonts.poppins(
fontSize:
Responsive.isDesktop(context)
? 18
: 16,
fontWeight: FontWeight.w500,
color: Color(0xFF000000),
),
),
SizedBox(height: 10),
LayoutBuilder(
builder: (context, constraints) {
double itemHeight =
40; // Adjust item height based on content
double listViewHeight =
type5Content.length * itemHeight;
double maxHeight =
constraints.maxHeight;
if (listViewHeight > maxHeight) {
listViewHeight = maxHeight;
}
return Container(
height: listViewHeight,
child: ListView.builder(
itemCount: type5Content.length,
itemBuilder: (context, index) {
String key = type5Content.keys
.elementAt(index);
String value =
type5Content[key]!;
return Padding(
padding: const EdgeInsets
.symmetric(vertical: 8.0),
child: Row(
crossAxisAlignment:
CrossAxisAlignment
.start,
children: <Widget>[
Padding(
padding:
const EdgeInsets
.only(
left: 20.0),
child: Text(
"",
style: GoogleFonts
.poppins(
fontSize: 16,
fontWeight:
FontWeight.w400,
color: Color(
0xFFE26728),
),
),
),
Expanded(
child: Text(
value,
style: GoogleFonts
.poppins(
fontSize: 16,
fontWeight:
FontWeight.w400,
color: Color(
0xFF000000),
),
),
),
],
),
);
},
),
);
},
),
],
),
),
]),
),
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
),
padding: Responsive.isDesktop(context)
? EdgeInsets.symmetric(vertical: 15, horizontal: 25)
: EdgeInsets.all(10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (generalExclusionsDetails != null)
Padding(
padding:
EdgeInsets.only(bottom: 20, left: 15),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
type6Heading ?? '',
style: GoogleFonts.poppins(
fontSize:
Responsive.isDesktop(context)
? 18
: 16,
fontWeight: FontWeight.w500,
color: Color(0xFF000000),
),
),
SizedBox(height: 10),
LayoutBuilder(
builder: (context, constraints) {
double itemHeight =
40; // Adjust item height based on content
double listViewHeight =
type6Content.length * itemHeight;
double maxHeight =
constraints.maxHeight;
if (listViewHeight > maxHeight) {
listViewHeight = maxHeight;
}
return Container(
height: listViewHeight,
child: ListView.builder(
itemCount: type6Content.length,
itemBuilder: (context, index) {
String key = type6Content.keys
.elementAt(index);
String value =
type6Content[key]!;
return Padding(
padding: const EdgeInsets
.symmetric(vertical: 8.0),
child: Row(
crossAxisAlignment:
CrossAxisAlignment
.start,
children: <Widget>[
Padding(
padding:
const EdgeInsets
.only(
left: 20.0),
child: Text(
"",
style: GoogleFonts
.poppins(
fontSize: 16,
fontWeight:
FontWeight.w400,
color: Color(
0xFFE26728),
),
),
),
Expanded(
child: Text(
value,
style: GoogleFonts
.poppins(
fontSize: 16,
fontWeight:
FontWeight.w400,
color: Color(
0xFF000000),
),
),
),
],
),
);
},
),
);
},
),
],
),
),
]),
),
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
),
padding: Responsive.isDesktop(context)
? EdgeInsets.symmetric(vertical: 15, horizontal: 25)
: EdgeInsets.all(10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (generalExclusionsDetails != null)
Padding(
padding:
EdgeInsets.only(bottom: 20, left: 15),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
type7Heading ?? '',
style: GoogleFonts.poppins(
fontSize:
Responsive.isDesktop(context)
? 18
: 16,
fontWeight: FontWeight.w500,
color: Color(0xFF000000),
),
),
SizedBox(height: 10),
LayoutBuilder(
builder: (context, constraints) {
double itemHeight =
40; // Adjust item height based on content
double listViewHeight =
type7Content.length * itemHeight;
double maxHeight =
constraints.maxHeight;
if (listViewHeight > maxHeight) {
listViewHeight = maxHeight;
}
return Container(
height: listViewHeight,
child: ListView.builder(
itemCount: type7Content.length,
itemBuilder: (context, index) {
String key = type7Content.keys
.elementAt(index);
String value =
type7Content[key]!;
return Padding(
padding: const EdgeInsets
.symmetric(vertical: 8.0),
child: Row(
crossAxisAlignment:
CrossAxisAlignment
.start,
children: <Widget>[
Padding(
padding:
const EdgeInsets
.only(
left: 20.0),
child: Text(
"",
style: GoogleFonts
.poppins(
fontSize: 16,
fontWeight:
FontWeight.w400,
color: Color(
0xFFE26728),
),
),
),
Expanded(
child: Text(
value,
style: GoogleFonts
.poppins(
fontSize: 16,
fontWeight:
FontWeight.w400,
color: Color(
0xFF000000),
),
),
),
],
),
);
},
),
);
},
),
],
),
),
]),
),
SizedBox(height: Responsive.isDesktop(context) ? 40 : 10),
const SizedBox(height: 20),
if (type3Content.isNotEmpty) ...[
Text(type3SectionName ?? '',
style: GoogleFonts.poppins(
fontSize: 18, fontWeight: FontWeight.w500)),
const SizedBox(height: 10),
buildBulletList(type3Content),
],
if (type4Content.isNotEmpty) ...[
const SizedBox(height: 20),
Text(type4Heading ?? '',
style: GoogleFonts.poppins(
fontSize: 18, fontWeight: FontWeight.w500)),
buildBulletList(type4Content),
],
if (type5Content.isNotEmpty) ...[
const SizedBox(height: 20),
Text(type5Heading ?? '',
style: GoogleFonts.poppins(
fontSize: 18, fontWeight: FontWeight.w500)),
buildBulletList(type5Content),
],
if (type6Content.isNotEmpty) ...[
const SizedBox(height: 20),
Text(type6Heading ?? '',
style: GoogleFonts.poppins(
fontSize: 18, fontWeight: FontWeight.w500)),
buildBulletList(type6Content),
],
if (type7Content.isNotEmpty) ...[
const SizedBox(height: 20),
Text(type7Heading ?? '',
style: GoogleFonts.poppins(
fontSize: 18, fontWeight: FontWeight.w500)),
buildBulletList(type7Content),
],
],
),
),
),
if (Responsive.isDesktop(context))
Align(
alignment: Alignment.bottomCenter,
child: Container(
width: double.infinity,
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('/faqs');
} else if (index == 3) {
context.push('/profile');
} else if (index == 4) {
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.question_answer_outlined,
Icons.person_outline_outlined,
Icons.headset_mic_outlined,
],
labels: ["Home", "Claims", "FAQs", "Profile","Help"],
initialIndex: 0, // Initial index of the bottom navigation bar
),
? SizedBox(
height: 40, // 👈 FIXED HEIGHT (adjust if needed)
width: double.infinity,
child: CustomFooter(),
)
: CustomBottomNavigationBar(
initialIndex: 0,
labels: const ["Home", "Claims", "FAQs", "Profile", "Help"],
icons: const [
Icons.home_outlined,
Icons.sticky_note_2_outlined,
Icons.question_answer_outlined,
Icons.person_outline_outlined,
Icons.headset_mic_outlined,
],
onTabChanged: (index) {
if (index == 0) context.push('/home');
if (index == 1) context.push('/claims');
if (index == 2) context.push('/faqs');
if (index == 3) context.push('/profile');
if (index == 4) context.push('/help');
},
),
));
}
Widget buildBulletList(List<String> items) {
if (items.isEmpty) return const SizedBox.shrink();
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: items.map((text) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 6),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Padding(
padding: EdgeInsets.only(top: 2),
child: Text(
"",
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w600,
color: Color(0xFFE26728),
),
),
),
const SizedBox(width: 8),
Expanded(
child: Text(
text,
style: GoogleFonts.poppins(
fontSize: 16,
fontWeight: FontWeight.w400,
color: Color(0xFF000000),
),
),
),
],
),
);
}).toList(),
);
}
}

View File

@ -506,82 +506,82 @@ class _helpState extends State<help> {
]),
),
Container(
width: Responsive.isDesktop(context) ? 500 : double.infinity,
height: 75,
// padding: Responsive.isDesktop(context)
// ? EdgeInsets.only(top: 20, bottom: 20, left: 30, right: 30)
// : EdgeInsets.only(top: 5, bottom: 5,left: 10,right: 10),
padding: Responsive.isDesktop(context)
? EdgeInsets.only(
top: 20, bottom: 20, left: 30, right: 30)
: EdgeInsets.symmetric(vertical: 5, horizontal: 10),
child: Row(
children: [
// Expanded(
// flex: 6,
// child: ElevatedButton(
// onPressed: () {
// var details = {
// 'claimsDetails': '',
// 'fromClaimPage': 1,
// };
// Navigator.pushNamed(context, 'planclaimsform',
// arguments: details);
// },
// style: ElevatedButton.styleFrom(
// backgroundColor: Color(0xFFE26728),
// shape: RoundedRectangleBorder(
// borderRadius: BorderRadius.circular(5),
// ),
// ),
// child: Text(
// 'Raise Claims',
// style: GoogleFonts.poppins(color: Colors.white),
// ),
// ),
// ),
// SizedBox(width: 10),
Expanded(
flex: 4,
child: ElevatedButton(
onPressed: () {
context.go('/tickets');
},
style: ElevatedButton.styleFrom(
backgroundColor: Color(0xFFE26728),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5),
),
),
child: Text(
'Raise a Query',
style: GoogleFonts.poppins(color: Colors.white),
),
),
),
SizedBox(width: 10),
Expanded(
flex: 4,
child: ElevatedButton(
onPressed: () {
context.go('/raisedTicketHistory');
},
style: ElevatedButton.styleFrom(
backgroundColor: Color(0xFFE26728),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5),
),
),
child: Text(
'Track Queries',
style: GoogleFonts.poppins(color: Colors.white),
),
),
),
],
),
),
// Container(
// width: Responsive.isDesktop(context) ? 500 : double.infinity,
// height: 75,
// // padding: Responsive.isDesktop(context)
// // ? EdgeInsets.only(top: 20, bottom: 20, left: 30, right: 30)
// // : EdgeInsets.only(top: 5, bottom: 5,left: 10,right: 10),
// padding: Responsive.isDesktop(context)
// ? EdgeInsets.only(
// top: 20, bottom: 20, left: 30, right: 30)
// : EdgeInsets.symmetric(vertical: 5, horizontal: 10),
// child: Row(
// children: [
// // Expanded(
// // flex: 6,
// // child: ElevatedButton(
// // onPressed: () {
// // var details = {
// // 'claimsDetails': '',
// // 'fromClaimPage': 1,
// // };
// // Navigator.pushNamed(context, 'planclaimsform',
// // arguments: details);
// // },
// // style: ElevatedButton.styleFrom(
// // backgroundColor: Color(0xFFE26728),
// // shape: RoundedRectangleBorder(
// // borderRadius: BorderRadius.circular(5),
// // ),
// // ),
// // child: Text(
// // 'Raise Claims',
// // style: GoogleFonts.poppins(color: Colors.white),
// // ),
// // ),
// // ),
// // SizedBox(width: 10),
// Expanded(
// flex: 4,
// child: ElevatedButton(
// onPressed: () {
// context.go('/tickets');
// },
// style: ElevatedButton.styleFrom(
// backgroundColor: Color(0xFFE26728),
// shape: RoundedRectangleBorder(
// borderRadius: BorderRadius.circular(5),
// ),
// ),
// child: Text(
// 'Raise a Query',
// style: GoogleFonts.poppins(color: Colors.white),
// ),
// ),
// ),
// SizedBox(width: 10),
// Expanded(
// flex: 4,
// child: ElevatedButton(
// onPressed: () {
// context.go('/raisedTicketHistory');
// },
// style: ElevatedButton.styleFrom(
// backgroundColor: Color(0xFFE26728),
// shape: RoundedRectangleBorder(
// borderRadius: BorderRadius.circular(5),
// ),
// ),
// child: Text(
// 'Track Queries',
// style: GoogleFonts.poppins(color: Colors.white),
// ),
// ),
// ),
// ],
// ),
// ),
SizedBox(height: 5),

View File

@ -1800,7 +1800,7 @@ class _HomeState extends State<Home> {
return GestureDetector(
onTap: () {
context.go('/policies', extra: item);
context.push('/policies', extra: item);
},
child: MouseRegion(
cursor: SystemMouseCursors.click,

View File

@ -78,6 +78,7 @@ class _planclaimsformState extends State<planclaimsform> {
// List<html.File> uploadedFiles = [];
List<PlatformFile> uploadedFiles = [];
final fileService = FileUploadService();
bool isSubmitting = false;
// Declare subjectController and bodyController as instance variables
@ -177,7 +178,10 @@ class _planclaimsformState extends State<planclaimsform> {
sumInsuredController.dispose();
admitDateController.dispose();
dischargeDateController.dispose();
serviceId = null;
departmentList.clear();
super.dispose();
fileService.clearAll();
}
// void repositionBotman() {
@ -537,6 +541,7 @@ class _planclaimsformState extends State<planclaimsform> {
}
Future<void> sendFormDataToApi() async {
setState(() => isSubmitting = true); // 🔥 start loader
setState(() {
isServiceValid = serviceId != null;
isPolicyValid = policyNumberId != null;
@ -653,7 +658,7 @@ class _planclaimsformState extends State<planclaimsform> {
_token = await TokenService.getPostToken();
final request = http.MultipartRequest('POST', Uri.parse('${Environment.apiUrl}/initiateClaim'));
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() ?? ''));
@ -780,6 +785,8 @@ class _planclaimsformState extends State<planclaimsform> {
isLoading = false;
});
print('Error submitting form data: $e');
} finally {
setState(() => isSubmitting = false); // 🔥 stop loader
}
}
@ -1412,7 +1419,16 @@ SizedBox(height: 15),
onPressed: () {
sendFormDataToApi();
},
child: Text(
child: isSubmitting
? SizedBox(
height: 22,
width: 22,
child: CircularProgressIndicator(
strokeWidth: 2,
color: Colors.white,
),
)
: Text(
'Send',
style: GoogleFonts.poppins(
color: Colors.white),

View File

@ -291,7 +291,8 @@ class _policiesState extends State<policies> {
canPop: false,
onPopInvokedWithResult: (didPop, result) {
if (didPop) return;
context.go('/home');
// context.go('/home');
context.pop();
},
child: Scaffold(
backgroundColor: Colors.white,
@ -330,7 +331,8 @@ class _policiesState extends State<policies> {
flex: 1,
child: InkWell(
onTap: () {
context.go('/home');
// context.go('/home');
context.pop();
},
child: Icon(
Icons

View File

@ -69,6 +69,7 @@ class _profileState extends State<profile> {
final session = SessionManager();
String installedVersion = "";
String? storeVersion = "";
bool showSetMpin = false;
void _onTabChanged(int index) {
setState(() {
@ -81,7 +82,9 @@ class _profileState extends State<profile> {
super.initState();
apiService = ApiService(context); // Initialize ApiService here
_loadToken();
// _checkMpinStatus();
if(!kIsWeb){
_checkMpinStatus();
loadVersionInfo();
}
}
@ -91,6 +94,22 @@ class _profileState extends State<profile> {
super.dispose();
}
Future<void> _checkMpinStatus() async {
print('check Mpin Status');
// if (kIsWeb) return; // skip web
final prefs = await SharedPreferences.getInstance();
final String? isMpinSkipped = prefs.getString('is_mpin_skipped');
print('check Mpin Status');
print(isMpinSkipped);
setState(() {
showSetMpin = isMpinSkipped == "1";
print('check Mpin Status');
print(showSetMpin);
});
}
Future<void> loadVersionInfo() async {
print('App version:}');
installedVersion = await AppVersionService.getInstalledVersion();
@ -762,15 +781,20 @@ class _profileState extends State<profile> {
alignment: Alignment.center,
child: ElevatedButton(
onPressed: () {
print('changePin');
context.go('/changePin');
if (showSetMpin) {
print('pinSettingPage');
context.go('/pinSettingPage'); // Set MPIN page
} else {
print('changePin');
context.go('/changePin'); // Change PIN page
}
},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// Adjust space between icon and text
Text(
'Change Pin',
showSetMpin ? 'Set MPIN' : 'Change PIN',
style: GoogleFonts.poppins(
color: Color(0xFFE26728)),
),

View File

@ -42,6 +42,10 @@ class ApiService {
Future<Map<String, dynamic>> getClaimsHistoryToApi(
String ticket_type_id) async {
print("getCashDepositDetailsToApi1");
print(_postToken);
if (_postToken == null) {
await _initializeToken();
}
final url =
Uri.parse('${Environment.apiUrl}claimView?ticket_id=$ticket_type_id');
@ -112,7 +116,7 @@ class ApiService {
await _initializeToken();
}
final url = Uri.parse(
'${Environment.apiUrl}/get_ticket_data?emp_id=$empPrimaryId&mobile_number=$mobileNo&email_id=$emailID');
'${Environment.apiUrl}get_ticket_data?emp_id=$empPrimaryId&mobile_number=$mobileNo&email_id=$emailID');
final headers = {
'Authorization': 'Bearer $_postToken' ?? '',
};
@ -242,7 +246,7 @@ class ApiService {
if (_postToken == null) {
await _initializeToken();
}
final url = Uri.parse('${Environment.apiUrl}/get_ticket_type?client_id=$clientId&emp_code=$empCode');
final url = Uri.parse('${Environment.apiUrl}get_ticket_type?client_id=$clientId&emp_code=$empCode');
final headers = {
'Authorization': 'Bearer $_postToken' ?? '',
};
@ -255,7 +259,7 @@ class ApiService {
if (_postToken == null) {
await _initializeToken();
}
final url = Uri.parse('${Environment.apiUrl}/getClaimTypeMaster');
final url = Uri.parse('${Environment.apiUrl}getClaimTypeMaster');
final headers = {
'Authorization': 'Bearer $_postToken' ?? '',
};
@ -286,7 +290,7 @@ class ApiService {
if (_postToken == null) {
await _initializeToken();
}
final url = Uri.parse('${Environment.apiUrl}/initiateClaim');
final url = Uri.parse('${Environment.apiUrl}initiateClaim');
// Convert formData to Map<String, String>
Map<String, String> stringFormData =
formData.map((key, value) => MapEntry(key, value.toString()));
@ -299,6 +303,10 @@ class ApiService {
Future<Map<String, dynamic>> sendClaimsMessageToApi(
Map<String, dynamic> formData) async {
print(_postToken);
if (_postToken == null) {
await _initializeToken();
}
print("sendClaimsMessageToApi");
final url = Uri.parse('${Environment.apiUrl}ticketConversationSave');
// final url = Uri.parse('${Environment.apiUrlTicket}/messages/create');
@ -398,6 +406,11 @@ class ApiService {
} else if (response.statusCode == 401) {
await _clearLocalStorageAndRedirect();
return {};
} else if (response.statusCode == 429) {
final body = jsonDecode(response.body);
final message = body['message'];
ToastHelper.showWarningToast(context, message);
return {};
} else {
throw Exception('Failed to load data');
}

File diff suppressed because it is too large Load Diff

View File

@ -32,6 +32,9 @@ class _changePinState extends State<changePin> {
dynamic empEmailid;
dynamic _token;
dynamic emp_status;
bool _isSaving = false;
bool _isPinChanged = false; // hard success lock
@override
void initState(){
@ -53,6 +56,14 @@ class _changePinState extends State<changePin> {
}
Future<void> setChangePin() async {
if (_isSaving || _isPinChanged) return;
if (!_formKey.currentState!.validate()) return;
setState(() {
_isSaving = true;
});
try {
if (_formKey.currentState!.validate()) {
final SharedPreferences prefs = await SharedPreferences.getInstance();
@ -87,6 +98,9 @@ class _changePinState extends State<changePin> {
bool pinVerification = data['data']['mpin_verification'];
String message = data['data']['message'];
if (pinVerification) {
setState(() {
_isPinChanged = true;
});
ToastHelper.showSuccessToast(context, message);
context.go('/profile');
} else {
@ -103,7 +117,14 @@ class _changePinState extends State<changePin> {
} catch (e) {
ToastHelper.showErrorToast(context, 'Something went wrong');
print('Error: $e');
} finally {
if (mounted) {
setState(() {
_isSaving = false;
});
}
}
}
String? _validatePin(String? value) {
@ -343,6 +364,7 @@ class _changePinState extends State<changePin> {
margin: EdgeInsets.symmetric(
horizontal: 0),
child: Pinput(
enabled: !_isSaving && !_isPinChanged,
length: 4,
defaultPinTheme:
defaultPinTheme,
@ -445,6 +467,7 @@ class _changePinState extends State<changePin> {
: EdgeInsets.symmetric(
horizontal: 0),
child: Pinput(
enabled: !_isSaving && !_isPinChanged,
length: 4,
defaultPinTheme:
defaultPinTheme,
@ -533,15 +556,23 @@ class _changePinState extends State<changePin> {
.circular(10),
),
),
onPressed: () async {
onPressed: (_isSaving || _isPinChanged)
? null
: () {
setChangePin();
},
child: Text(
child: _isSaving
? const SizedBox(
width: 20,
height: 20,
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
),
)
: Text(
"Save",
style:
GoogleFonts.poppins(
color: Color(
0xFFFFFFFF)),
style: GoogleFonts.poppins(color: Colors.white),
),
),
),

View File

@ -35,6 +35,8 @@ class _pinSettingPageState extends State<pinSettingPage> {
dynamic _postToken;
dynamic emp_status;
final session = SessionManager();
bool _isSavingPin = false;
bool _isPinSaved = false; // hard success lock
@override
void initState() {
@ -49,6 +51,11 @@ class _pinSettingPageState extends State<pinSettingPage> {
}
Future<void> setLoginPin(skipOrNot) async {
if (_isSavingPin || _isPinSaved) return;
setState(() {
_isSavingPin = true;
});
try {
print('setLoginPin');
// Only validate if not skipping
@ -63,7 +70,7 @@ class _pinSettingPageState extends State<pinSettingPage> {
print('setLoginPin112233 $skipOrNot');
prefs.setString('is_mpin_skipped', skipOrNot.toString());
print('setLoginPin112233');
emp_status = session.emp_status;
// emp_status = session.emp_status;
enrollToken = await TokenService.getPreToken();
_postToken = await TokenService.getPostToken();
String pin = _pinController.text;
@ -126,6 +133,10 @@ class _pinSettingPageState extends State<pinSettingPage> {
bool userVerification = data['data']['user_verification'];
String message = data['data']['message'];
if (userVerification) {
setState(() {
_isPinSaved = true; // 🔒 HARD LOCK
});
if (_enableBiometric == true) {
await _authService.saveBiometricEnableKey(_enableBiometric);
bool biometricEnabled =
@ -163,7 +174,15 @@ class _pinSettingPageState extends State<pinSettingPage> {
} catch (e) {
ToastHelper.showErrorToast(context, 'Something went wrong');
print('Error: $e');
} finally {
if (mounted) {
setState(() {
_isSavingPin = false;
});
}
}
}
String? _validatePin(String? value) {
@ -424,6 +443,7 @@ class _pinSettingPageState extends State<pinSettingPage> {
EdgeInsets.symmetric(
horizontal: 0),
child: Pinput(
enabled: !_isSavingPin && !_isPinSaved,
length: 4,
defaultPinTheme:
defaultPinTheme,
@ -539,6 +559,7 @@ class _pinSettingPageState extends State<pinSettingPage> {
: EdgeInsets.symmetric(
horizontal: 0),
child: Pinput(
enabled: !_isSavingPin && !_isPinSaved,
length: 4,
defaultPinTheme:
defaultPinTheme,
@ -687,15 +708,23 @@ class _pinSettingPageState extends State<pinSettingPage> {
10),
),
),
onPressed: () async {
onPressed: (_isSavingPin || _isPinSaved)
? null
: () {
setLoginPin(0);
},
child: Text(
child: _isSavingPin
? const SizedBox(
width: 20,
height: 20,
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
),
)
: Text(
"Save",
style: GoogleFonts
.poppins(
color: Color(
0xFFFFFFFF)),
style: GoogleFonts.poppins(color: Colors.white),
),
),
),
@ -708,20 +737,18 @@ class _pinSettingPageState extends State<pinSettingPage> {
.center,
children: [
GestureDetector(
onTap: () {
// setSkipStatus();
onTap: (_isSavingPin || _isPinSaved)
? null
: () {
setLoginPin(1);
},
child: Text(
'Skip ?',
style: GoogleFonts
.poppins(
style: GoogleFonts.poppins(
fontSize: 12,
color: Color(
0xFF929292),
fontWeight:
FontWeight
.w400,
color: (_isSavingPin || _isPinSaved)
? Colors.grey
: const Color(0xFF929292),
),
),
),

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.28+33
#version: 2.0.15+53
version: 1.0.29+34
#version: 2.0.16+54
environment:
sdk: '>=3.3.3 <4.0.0'