backup changes and email and mobile number same
0
.env.production
Executable file → Normal file
0
.gitignore
vendored
Executable file → Normal file
0
analysis_options.yaml
Executable file → Normal file
0
android/.gitignore
vendored
Executable file → Normal file
0
android/app/build.gradle
Executable file → Normal file
0
android/app/google-services.json
Executable file → Normal file
0
android/app/src/debug/AndroidManifest.xml
Executable file → Normal file
0
android/app/src/main/AndroidManifest.xml
Executable file → Normal file
0
android/app/src/main/kotlin/com/example/nhancepolicy/MainActivity.kt
Executable file → Normal file
0
android/app/src/main/res/drawable-v21/launch_background.xml
Executable file → Normal file
0
android/app/src/main/res/drawable/launch_background.xml
Executable file → Normal file
0
android/app/src/main/res/mipmap-hdpi/ic_launcher.png
Executable file → Normal file
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
0
android/app/src/main/res/mipmap-mdpi/ic_launcher.png
Executable file → Normal file
|
Before Width: | Height: | Size: 996 B After Width: | Height: | Size: 996 B |
0
android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
Executable file → Normal file
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
0
android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Executable file → Normal file
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
0
android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Executable file → Normal file
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
0
android/app/src/main/res/values-night/styles.xml
Executable file → Normal file
0
android/app/src/main/res/values/styles.xml
Executable file → Normal file
0
android/app/src/profile/AndroidManifest.xml
Executable file → Normal file
0
android/build.gradle
Executable file → Normal file
0
android/gradle.properties
Executable file → Normal file
0
android/gradle/wrapper/gradle-wrapper.properties
vendored
Executable file → Normal file
0
android/settings.gradle
Executable file → Normal file
0
assets/Group_3.png
Executable file → Normal file
|
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 5.2 KiB |
0
assets/Nhance-Logo-Final 1.png
Executable file → Normal file
|
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.0 KiB |
0
assets/Solid_gray.png
Executable file → Normal file
|
Before Width: | Height: | Size: 99 B After Width: | Height: | Size: 99 B |
BIN
assets/Template_File.xlsx
Executable file → Normal file
0
assets/Vector.png
Executable file → Normal file
|
Before Width: | Height: | Size: 840 B After Width: | Height: | Size: 840 B |
0
assets/hrLogin.jpg
Executable file → Normal file
|
Before Width: | Height: | Size: 476 KiB After Width: | Height: | Size: 476 KiB |
0
assets/login_web.jpg
Executable file → Normal file
|
Before Width: | Height: | Size: 833 KiB After Width: | Height: | Size: 833 KiB |
0
assets/mobileViewLogo.png
Executable file → Normal file
|
Before Width: | Height: | Size: 146 KiB After Width: | Height: | Size: 146 KiB |
0
assets/navbarLogo.png
Executable file → Normal file
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
0
assets/nhance-loader.gif
Executable file → Normal file
|
Before Width: | Height: | Size: 493 KiB After Width: | Height: | Size: 493 KiB |
0
assets/nhance_client_logo.png
Executable file → Normal file
|
Before Width: | Height: | Size: 145 KiB After Width: | Height: | Size: 145 KiB |
0
assets/policy.png
Executable file → Normal file
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
0
build_web_test.sh
Executable file → Normal file
0
build_web_uat.sh
Executable file → Normal file
0
ios/.gitignore
vendored
Executable file → Normal file
0
ios/Flutter/AppFrameworkInfo.plist
Executable file → Normal file
0
ios/Flutter/Debug.xcconfig
Executable file → Normal file
0
ios/Flutter/Release.xcconfig
Executable file → Normal file
0
ios/Runner/AppDelegate.swift
Executable file → Normal file
0
ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
Executable file → Normal file
0
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
Executable file → Normal file
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
0
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
Executable file → Normal file
|
Before Width: | Height: | Size: 494 B After Width: | Height: | Size: 494 B |
0
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
Executable file → Normal file
|
Before Width: | Height: | Size: 772 B After Width: | Height: | Size: 772 B |
0
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
Executable file → Normal file
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
0
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
Executable file → Normal file
|
Before Width: | Height: | Size: 663 B After Width: | Height: | Size: 663 B |
0
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
Executable file → Normal file
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
0
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
Executable file → Normal file
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
0
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
Executable file → Normal file
|
Before Width: | Height: | Size: 772 B After Width: | Height: | Size: 772 B |
0
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
Executable file → Normal file
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
0
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
Executable file → Normal file
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
0
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
Executable file → Normal file
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
0
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
Executable file → Normal file
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
0
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
Executable file → Normal file
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
0
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
Executable file → Normal file
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
0
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
Executable file → Normal file
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
0
ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json
vendored
Executable file → Normal file
0
ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
vendored
Executable file → Normal file
|
Before Width: | Height: | Size: 68 B After Width: | Height: | Size: 68 B |
0
ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
vendored
Executable file → Normal file
|
Before Width: | Height: | Size: 68 B After Width: | Height: | Size: 68 B |
0
ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
vendored
Executable file → Normal file
|
Before Width: | Height: | Size: 68 B After Width: | Height: | Size: 68 B |
0
ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md
vendored
Executable file → Normal file
0
ios/Runner/Base.lproj/LaunchScreen.storyboard → ios/Runner/Base.lproj/LaunchScreen.storyboard.xml
Executable file → Normal file
0
ios/Runner/Base.lproj/Main.storyboard → ios/Runner/Base.lproj/Main.storyboard.xml
Executable file → Normal file
0
ios/Runner/Info.plist
Executable file → Normal file
0
ios/Runner/Runner-Bridging-Header.h
Executable file → Normal file
0
ios/RunnerTests/RunnerTests.swift
Executable file → Normal file
0
lib/addons.dart
Executable file → Normal file
@ -154,7 +154,7 @@ class _BranchSelectionPageState extends State<BranchSelectionPage> {
|
|||||||
} else {
|
} else {
|
||||||
// Desktop
|
// Desktop
|
||||||
crossAxisCount = 3;
|
crossAxisCount = 3;
|
||||||
childAspectRatio = 5;
|
childAspectRatio = 5 ;
|
||||||
}
|
}
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: Color(0xFFEFF3F6),
|
backgroundColor: Color(0xFFEFF3F6),
|
||||||
|
|||||||
0
lib/customAppBar/customAppBar.dart
Executable file → Normal file
0
lib/customAppBar/customAppBarChatbot.dart
Executable file → Normal file
0
lib/customAppBar/customFooter.dart
Executable file → Normal file
0
lib/customAppBar/enrollmentAppBar.dart
Executable file → Normal file
0
lib/customAppBar/toastHelper.dart
Executable file → Normal file
@ -117,10 +117,23 @@ class _MyEmailVerifyState extends State<MyEmailVerify> {
|
|||||||
Map<String, dynamic> data = json.decode(response.body);
|
Map<String, dynamic> data = json.decode(response.body);
|
||||||
print('Response data: $data');
|
print('Response data: $data');
|
||||||
|
|
||||||
|
// ✅ Safely extract preEnrollmentData
|
||||||
|
List<dynamic> preEnrollmentData = [];
|
||||||
|
if (data['data'] is List) {
|
||||||
|
preEnrollmentData = data['data'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// ✅ Safely extract postEnrollmentData
|
||||||
|
final postEnrollment = data['post_enrollment'] ?? {};
|
||||||
|
List<dynamic> postEnrollmentData = [];
|
||||||
|
if (postEnrollment['data'] is List) {
|
||||||
|
postEnrollmentData = postEnrollment['data'];
|
||||||
|
}
|
||||||
|
|
||||||
// Extract enrollment data
|
// Extract enrollment data
|
||||||
List<dynamic> preEnrollmentData = data['data'] ?? [];
|
// List<dynamic> preEnrollmentData = data['data'] ?? [];
|
||||||
Map<String, dynamic> postEnrollment = data['post_enrollment'] ?? {};
|
// Map<String, dynamic> postEnrollment = data['post_enrollment'] ?? {};
|
||||||
List<dynamic> postEnrollmentData = postEnrollment['data'] ?? [];
|
// List<dynamic> postEnrollmentData = postEnrollment['data'] ?? [];
|
||||||
|
|
||||||
// Save to global storage
|
// Save to global storage
|
||||||
final tokenStorage = TokenStorageService();
|
final tokenStorage = TokenStorageService();
|
||||||
|
|||||||
0
lib/empDetails.dart
Executable file → Normal file
0
lib/empReview.dart
Executable file → Normal file
24
lib/excel_verification.dart
Executable file → Normal file
@ -20,6 +20,7 @@ import 'package:intl/intl.dart';
|
|||||||
import 'package:csv/csv.dart';
|
import 'package:csv/csv.dart';
|
||||||
|
|
||||||
import 'package:spreadsheet_decoder/spreadsheet_decoder.dart';
|
import 'package:spreadsheet_decoder/spreadsheet_decoder.dart';
|
||||||
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
import 'customAppBar/customFooter.dart';
|
import 'customAppBar/customFooter.dart';
|
||||||
|
|
||||||
@ -581,6 +582,29 @@ class _excelVerifyState extends State<excelVerify> {
|
|||||||
anchor.click(); // Trigger a click on the anchor element
|
anchor.click(); // Trigger a click on the anchor element
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Future<void> downloadSampleFile() async {
|
||||||
|
//
|
||||||
|
// final response = await apiService.getSampleFileDownload(widget.Token);
|
||||||
|
// print('check 1');
|
||||||
|
// if (response['status'] == 'success') {
|
||||||
|
// final url = response['data'];
|
||||||
|
// _launchURL(url);
|
||||||
|
// } else {
|
||||||
|
// ToastHelper.showErrorToast(context, '⚠️ Unknown response format');
|
||||||
|
// print('⚠️ Unknown response format');
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Future<void> _launchURL(String url) async {
|
||||||
|
// print('url $url');
|
||||||
|
// try {
|
||||||
|
// final Uri uri = Uri.parse(url);
|
||||||
|
// await launchUrl(uri, mode: LaunchMode.externalApplication);
|
||||||
|
// } catch (e) {
|
||||||
|
// print('Could not launch URL: $e');
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
resetErrorCount() {
|
resetErrorCount() {
|
||||||
setState(() {
|
setState(() {
|
||||||
fileBytes = null;
|
fileBytes = null;
|
||||||
|
|||||||
0
lib/firebase-config.dart
Executable file → Normal file
0
lib/home.dart
Executable file → Normal file
434
lib/hrDashboard.dart
Executable file → Normal file
@ -48,6 +48,7 @@ class _hrDashboardState extends State<hrDashboard>
|
|||||||
String? _postToken = '';
|
String? _postToken = '';
|
||||||
late String _token;
|
late String _token;
|
||||||
dynamic getPolicyNo;
|
dynamic getPolicyNo;
|
||||||
|
dynamic branchName;
|
||||||
// bool _isLoading = false;
|
// bool _isLoading = false;
|
||||||
dynamic getPolicyNameDetails;
|
dynamic getPolicyNameDetails;
|
||||||
dynamic enrollmentClient_id;
|
dynamic enrollmentClient_id;
|
||||||
@ -131,7 +132,7 @@ class _hrDashboardState extends State<hrDashboard>
|
|||||||
_postToken = await tokenService.getCurrentToken();
|
_postToken = await tokenService.getCurrentToken();
|
||||||
print(enrollToken);
|
print(enrollToken);
|
||||||
print(_postToken);
|
print(_postToken);
|
||||||
|
branchName = prefs.getString('branchName') ?? '';
|
||||||
|
|
||||||
if (enrollToken != null && enrollToken!.isNotEmpty) {
|
if (enrollToken != null && enrollToken!.isNotEmpty) {
|
||||||
// Map<String, dynamic>? decodedToken = Jwt.parseJwt(enrollToken!);
|
// Map<String, dynamic>? decodedToken = Jwt.parseJwt(enrollToken!);
|
||||||
@ -499,10 +500,48 @@ class _hrDashboardState extends State<hrDashboard>
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Future<bool> _showLogoutDialog() async {
|
||||||
|
return await showDialog<bool>(
|
||||||
|
context: context,
|
||||||
|
barrierDismissible: false,
|
||||||
|
builder: (context) => AlertDialog(
|
||||||
|
title: Text("Confirm Logout"),
|
||||||
|
content: Text("Do you want to logout?"),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.of(context).pop(false),
|
||||||
|
child: Text("Cancel"),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.of(context).pop(true),
|
||||||
|
child: Text("Logout"),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
) ??
|
||||||
|
false;
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
if (getCardArrays == []) {
|
if (getCardArrays == []) {
|
||||||
return Scaffold(
|
return PopScope(
|
||||||
|
canPop: false, // ✅ Prevents automatic back navigation
|
||||||
|
onPopInvoked: (didPop) async {
|
||||||
|
// This is triggered when browser back button is pressed
|
||||||
|
bool logout = await _showLogoutDialog();
|
||||||
|
|
||||||
|
if (logout) {
|
||||||
|
// ✅ Clear storage & logout
|
||||||
|
// Example:
|
||||||
|
// await storage.clear();
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
prefs.clear();
|
||||||
|
print('LocalStorage Cleared');
|
||||||
|
Navigator.pushNamed(context, 'hrLogin');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Scaffold(
|
||||||
appBar: CustomAppBar(),
|
appBar: CustomAppBar(),
|
||||||
body: SingleChildScrollView(
|
body: SingleChildScrollView(
|
||||||
child: Container(
|
child: Container(
|
||||||
@ -515,7 +554,7 @@ class _hrDashboardState extends State<hrDashboard>
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
));
|
)));
|
||||||
} else {
|
} else {
|
||||||
int numCards = getCardArrays.length;
|
int numCards = getCardArrays.length;
|
||||||
int numExpanded = numCards < 4 ? numCards : 4;
|
int numExpanded = numCards < 4 ? numCards : 4;
|
||||||
@ -525,199 +564,238 @@ class _hrDashboardState extends State<hrDashboard>
|
|||||||
|
|
||||||
print("visibleTabAll - $visibleTabs");
|
print("visibleTabAll - $visibleTabs");
|
||||||
print("tabViewsAll - $tabViews");
|
print("tabViewsAll - $tabViews");
|
||||||
|
return PopScope(
|
||||||
|
canPop: false, // ✅ Prevents automatic back navigation
|
||||||
|
onPopInvoked: (didPop) async {
|
||||||
|
// This is triggered when browser back button is pressed
|
||||||
|
bool logout = await _showLogoutDialog();
|
||||||
|
|
||||||
return Scaffold(
|
if (logout) {
|
||||||
appBar: CustomAppBar(),
|
// ✅ Clear storage & logout
|
||||||
body: Stack(children: [
|
// Example:
|
||||||
Container(
|
// await storage.clear();
|
||||||
padding: const EdgeInsets.only(
|
final prefs = await SharedPreferences.getInstance();
|
||||||
top: 20, bottom: 40, left: 40, right: 40),
|
prefs.clear();
|
||||||
|
print('LocalStorage Cleared');
|
||||||
|
Navigator.pushNamed(context, 'hrLogin');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Scaffold(
|
||||||
|
appBar: CustomAppBar(),
|
||||||
|
body: Stack(children: [
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
top: 20, bottom: 40, left: 40, right: 40),
|
||||||
|
|
||||||
// padding: const EdgeInsets.only(
|
// padding: const EdgeInsets.only(
|
||||||
// top: 20, bottom: 20, left: 50, right: 50),
|
// top: 20, bottom: 20, left: 50, right: 50),
|
||||||
color: const Color(0xFFEFF3F6),
|
color: const Color(0xFFEFF3F6),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
// height: 75,
|
// height: 75,
|
||||||
height: MediaQuery.of(context).size.height * 0.12,
|
height: MediaQuery.of(context).size.height * 0.12,
|
||||||
|
|
||||||
padding: Responsive.isDesktop(context)
|
padding: Responsive.isDesktop(context)
|
||||||
? const EdgeInsets.only(
|
? const EdgeInsets.only(
|
||||||
top: 10, bottom: 10, left: 20, right: 20)
|
top: 10, bottom: 10, left: 20, right: 20)
|
||||||
: EdgeInsets.only(
|
: EdgeInsets.only(
|
||||||
top: 10,
|
top: 10,
|
||||||
bottom: 10,
|
bottom: 10,
|
||||||
left: 10,
|
left: 10,
|
||||||
right: 10), // Add padding to the container
|
right: 10), // Add padding to the container
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 6,
|
flex: 6,
|
||||||
child: Container(
|
child: Container(
|
||||||
width: 150,
|
width: 150,
|
||||||
height: 80,
|
height: 80,
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: Image.network(
|
child: Image.network(
|
||||||
Uri.encodeFull(clientLogo ?? ''),
|
Uri.encodeFull(clientLogo ?? ''),
|
||||||
width: 200,
|
width: 200,
|
||||||
height: 200,
|
height: 200,
|
||||||
fit: BoxFit.contain,
|
fit: BoxFit.contain,
|
||||||
frameBuilder: (BuildContext context, Widget child, int? frame, bool wasSynchronouslyLoaded) {
|
frameBuilder: (BuildContext context, Widget child, int? frame, bool wasSynchronouslyLoaded) {
|
||||||
if (wasSynchronouslyLoaded) {
|
if (wasSynchronouslyLoaded) {
|
||||||
return child;
|
return child;
|
||||||
}
|
}
|
||||||
return AnimatedOpacity(
|
return AnimatedOpacity(
|
||||||
opacity: frame == null ? 0 : 1,
|
opacity: frame == null ? 0 : 1,
|
||||||
duration: const Duration(milliseconds: 500),
|
duration: const Duration(milliseconds: 500),
|
||||||
curve: Curves.easeOut,
|
curve: Curves.easeOut,
|
||||||
child: child,
|
child: child,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
loadingBuilder: (BuildContext context, Widget child, ImageChunkEvent? loadingProgress) {
|
loadingBuilder: (BuildContext context, Widget child, ImageChunkEvent? loadingProgress) {
|
||||||
if (loadingProgress == null) {
|
if (loadingProgress == null) {
|
||||||
return child;
|
return child;
|
||||||
}
|
}
|
||||||
return Center(
|
return Center(
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
width: 30,
|
width: 30,
|
||||||
height: 30,
|
height: 30,
|
||||||
child: CircularProgressIndicator(
|
child: CircularProgressIndicator(
|
||||||
strokeWidth: 2,
|
strokeWidth: 2,
|
||||||
valueColor: AlwaysStoppedAnimation<Color>(Colors.grey),
|
valueColor: AlwaysStoppedAnimation<Color>(Colors.grey),
|
||||||
value: loadingProgress.expectedTotalBytes != null
|
value: loadingProgress.expectedTotalBytes != null
|
||||||
? loadingProgress.cumulativeBytesLoaded /
|
? loadingProgress.cumulativeBytesLoaded /
|
||||||
(loadingProgress.expectedTotalBytes ?? 1)
|
(loadingProgress.expectedTotalBytes ?? 1)
|
||||||
: null,
|
: null,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
errorBuilder: (BuildContext context, Object error, StackTrace? stackTrace) {
|
||||||
|
return Text('');
|
||||||
|
// Image.asset(
|
||||||
|
// 'assets/Solid_gray.png',
|
||||||
|
// width: 80,
|
||||||
|
// height: 60,
|
||||||
|
// fit: BoxFit.cover,
|
||||||
|
// );
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
flex: 9,
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.end, // right aligned
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
// ⭐ Client Name
|
||||||
|
Text(
|
||||||
|
clientName ?? '',
|
||||||
|
textAlign: TextAlign.right,
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: Responsive.isDesktop(context) ? 20 : 18,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
|
||||||
},
|
const SizedBox(height: 20),
|
||||||
errorBuilder: (BuildContext context, Object error, StackTrace? stackTrace) {
|
|
||||||
return Text('');
|
// ⭐ Branch Name (new line)
|
||||||
// Image.asset(
|
Text(
|
||||||
// 'assets/Solid_gray.png',
|
'Branch: ${branchName}' ?? '',
|
||||||
// width: 80,
|
textAlign: TextAlign.right,
|
||||||
// height: 60,
|
style: GoogleFonts.poppins(
|
||||||
// fit: BoxFit.cover,
|
fontSize: Responsive.isDesktop(context) ? 16 : 14,
|
||||||
// );
|
fontWeight: FontWeight.w400,
|
||||||
},
|
color: Colors.grey[700],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
],
|
||||||
),
|
),
|
||||||
Expanded(
|
|
||||||
flex: 9,
|
|
||||||
child: Text(
|
|
||||||
clientName ?? '',
|
|
||||||
textAlign: TextAlign.right,
|
|
||||||
style: GoogleFonts.poppins(
|
|
||||||
fontSize: Responsive.isDesktop(context) ? 20 : 18,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
SizedBox(height: 8),
|
|
||||||
|
|
||||||
tabData.isNotEmpty
|
|
||||||
? Container(
|
|
||||||
// padding: const EdgeInsets.all(5),
|
|
||||||
// height: MediaQuery.of(context).size.height * 0.08,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Color(
|
|
||||||
0xFFC4E3E6), // 🔹 Background behind the TabBar
|
|
||||||
borderRadius: BorderRadius.circular(12),
|
|
||||||
border: Border.all(color: Colors.transparent),
|
|
||||||
boxShadow: [
|
|
||||||
BoxShadow(
|
|
||||||
color: Colors.black.withOpacity(0.15),
|
|
||||||
blurRadius: 4,
|
|
||||||
offset: const Offset(0, 4),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
// mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
// mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
TabBar(
|
|
||||||
controller: _tabController,
|
|
||||||
isScrollable: true,
|
|
||||||
labelPadding: EdgeInsets.zero,
|
|
||||||
dividerColor: Colors.transparent,
|
|
||||||
indicatorColor: Colors.transparent,
|
|
||||||
indicatorPadding: EdgeInsets.zero,
|
|
||||||
labelColor: Colors.white,
|
|
||||||
unselectedLabelColor: const Color(0xFF828282),
|
|
||||||
// tabs: visibleTabs,
|
|
||||||
tabs: List.generate(tabData.length, (index) {
|
|
||||||
final data = tabData[index];
|
|
||||||
return CustomTab(
|
|
||||||
icon: data['icon'],
|
|
||||||
label: data['label'],
|
|
||||||
isSelected: selectedIndex == index,
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: Container(
|
|
||||||
height: MediaQuery.of(context).size.height * 0.6,
|
|
||||||
// color: Colors.white,
|
|
||||||
child: Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
Image.asset(
|
|
||||||
'assets/claimsData.png', // Replace 'default_image.png' with your default image asset path
|
|
||||||
width: 300,
|
|
||||||
height: 300,
|
|
||||||
fit: BoxFit.cover,
|
|
||||||
),
|
|
||||||
const Text("No Data Available"),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
SizedBox(height: 16),
|
|
||||||
// Expanded TabBarView
|
|
||||||
Expanded(
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 5),
|
|
||||||
child: TabBarView(
|
|
||||||
controller: _tabController,
|
|
||||||
children: getTabViews(),
|
|
||||||
// children: tabViews,
|
|
||||||
),
|
),
|
||||||
),
|
|
||||||
|
SizedBox(height: 8),
|
||||||
|
|
||||||
|
tabData.isNotEmpty
|
||||||
|
? Container(
|
||||||
|
// padding: const EdgeInsets.all(5),
|
||||||
|
// height: MediaQuery.of(context).size.height * 0.08,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Color(
|
||||||
|
0xFFC4E3E6), // 🔹 Background behind the TabBar
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
border: Border.all(color: Colors.transparent),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.black.withOpacity(0.15),
|
||||||
|
blurRadius: 4,
|
||||||
|
offset: const Offset(0, 4),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
// mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
// mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
TabBar(
|
||||||
|
controller: _tabController,
|
||||||
|
isScrollable: true,
|
||||||
|
labelPadding: EdgeInsets.zero,
|
||||||
|
dividerColor: Colors.transparent,
|
||||||
|
indicatorColor: Colors.transparent,
|
||||||
|
indicatorPadding: EdgeInsets.zero,
|
||||||
|
labelColor: Colors.white,
|
||||||
|
unselectedLabelColor: const Color(0xFF828282),
|
||||||
|
// tabs: visibleTabs,
|
||||||
|
tabs: List.generate(tabData.length, (index) {
|
||||||
|
final data = tabData[index];
|
||||||
|
return CustomTab(
|
||||||
|
icon: data['icon'],
|
||||||
|
label: data['label'],
|
||||||
|
isSelected: selectedIndex == index,
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: Container(
|
||||||
|
height: MediaQuery.of(context).size.height * 0.6,
|
||||||
|
// color: Colors.white,
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Image.asset(
|
||||||
|
'assets/claimsData.png', // Replace 'default_image.png' with your default image asset path
|
||||||
|
width: 300,
|
||||||
|
height: 300,
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
),
|
||||||
|
const Text("No Data Available"),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
SizedBox(height: 16),
|
||||||
|
// Expanded TabBarView
|
||||||
|
Expanded(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 5),
|
||||||
|
child: TabBarView(
|
||||||
|
controller: _tabController,
|
||||||
|
children: getTabViews(),
|
||||||
|
// children: tabViews,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
if (isLoading)
|
||||||
),
|
Container(
|
||||||
if (isLoading)
|
color: Color(0x98FFFCE5), // Semi-transparent background
|
||||||
Container(
|
child: Center(
|
||||||
color: Color(0x98FFFCE5), // Semi-transparent background
|
child: // Your GIF loader widget
|
||||||
child: Center(
|
|
||||||
child: // Your GIF loader widget
|
|
||||||
Image.asset(
|
Image.asset(
|
||||||
height: 60,
|
height: 60,
|
||||||
width: 60,
|
width: 60,
|
||||||
'assets/nhance-loader.gif'), // Adjust path to your GIF loader
|
'assets/nhance-loader.gif'), // Adjust path to your GIF loader
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Align(
|
||||||
|
alignment: Alignment.bottomCenter,
|
||||||
|
child: Container(
|
||||||
|
width: double.infinity, // Make the footer full width
|
||||||
|
child: CustomFooter(),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
]))
|
||||||
Align(
|
);
|
||||||
alignment: Alignment.bottomCenter,
|
|
||||||
child: Container(
|
|
||||||
width: double.infinity, // Make the footer full width
|
|
||||||
child: CustomFooter(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
]));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
0
lib/hrHome.dart
Executable file → Normal file
316
lib/hrLogin.dart
Executable file → Normal file
@ -24,9 +24,10 @@ class MyHrLogin extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _MyPhoneState extends State<MyHrLogin> {
|
class _MyPhoneState extends State<MyHrLogin> {
|
||||||
final TextEditingController emailController = TextEditingController();
|
final TextEditingController emailMobileController = TextEditingController();
|
||||||
TextEditingController countryController = TextEditingController();
|
// final TextEditingController emailController = TextEditingController();
|
||||||
TextEditingController mobileController = TextEditingController();
|
// TextEditingController countryController = TextEditingController();
|
||||||
|
// TextEditingController mobileController = TextEditingController();
|
||||||
final _formKey = GlobalKey<FormState>();
|
final _formKey = GlobalKey<FormState>();
|
||||||
bool _isCheckingToken = false;
|
bool _isCheckingToken = false;
|
||||||
dynamic empMobileNo;
|
dynamic empMobileNo;
|
||||||
@ -42,7 +43,7 @@ class _MyPhoneState extends State<MyHrLogin> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
print('vndbbcbdskbvkjs1');
|
print('vndbbcbdskbvkjs1');
|
||||||
countryController.text = "+91";
|
// countryController.text = "+91";
|
||||||
super.initState();
|
super.initState();
|
||||||
clearLocalStorageWhenStarts('initState');
|
clearLocalStorageWhenStarts('initState');
|
||||||
}
|
}
|
||||||
@ -74,14 +75,30 @@ class _MyPhoneState extends State<MyHrLogin> {
|
|||||||
_isLoading = true;
|
_isLoading = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
String input = emailMobileController.text.trim();
|
||||||
|
|
||||||
|
bool isEmail = RegExp(r'^[^@]+@[^@]+\.[^@]+$').hasMatch(input);
|
||||||
|
bool isMobile = RegExp(r'^[0-9]{10}$').hasMatch(input);
|
||||||
|
|
||||||
|
if (isEmail) {
|
||||||
|
setState(() {
|
||||||
|
isEmailFieldVisible = true;
|
||||||
|
});
|
||||||
|
print("User entered Email: $input");
|
||||||
|
} else if (isMobile) {
|
||||||
|
isEmailFieldVisible = false;
|
||||||
|
print("User entered Mobile: $input");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Determine the API and the payload based on the visible field
|
// Determine the API and the payload based on the visible field
|
||||||
String apiEndpoint = isEmailFieldVisible
|
String apiEndpoint = isEmailFieldVisible
|
||||||
? Environment.apiUrl + 'verifyHrWithEmail'
|
? Environment.apiUrl + 'verifyHrWithEmail'
|
||||||
: Environment.apiUrl + 'verifyHrWithMobileNumber';
|
: Environment.apiUrl + 'verifyHrWithMobileNumber';
|
||||||
|
|
||||||
Map<String, dynamic> payload = isEmailFieldVisible
|
Map<String, dynamic> payload = isEmailFieldVisible
|
||||||
? {'email': emailController.text}
|
? {'email': emailMobileController.text}
|
||||||
: {'mobile_number': mobileController.text};
|
: {'mobile_number': emailMobileController.text};
|
||||||
|
|
||||||
// var enteredMobileNumber = mobileController.text;
|
// var enteredMobileNumber = mobileController.text;
|
||||||
final response = await http.post(
|
final response = await http.post(
|
||||||
@ -101,28 +118,28 @@ class _MyPhoneState extends State<MyHrLogin> {
|
|||||||
await SharedPreferences.getInstance();
|
await SharedPreferences.getInstance();
|
||||||
if (isEmailFieldVisible) {
|
if (isEmailFieldVisible) {
|
||||||
print('isEmailFieldVisible $isEmailFieldVisible');
|
print('isEmailFieldVisible $isEmailFieldVisible');
|
||||||
prefs.setString('empEmail', emailController.text);
|
prefs.setString('empEmail', emailMobileController.text);
|
||||||
print('${emailController.text}');
|
print('${emailMobileController.text}');
|
||||||
ToastHelper.showSuccessToast(
|
ToastHelper.showSuccessToast(
|
||||||
context, 'Verification code sent to ${emailController.text}');
|
context, 'Verification code sent to ${emailMobileController.text}');
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) => MyEmailVerify(
|
builder: (context) => MyEmailVerify(
|
||||||
type: 'email',
|
type: 'email',
|
||||||
value: emailController.text.trim(), // Pass the phone number
|
value: emailMobileController.text.trim(), // Pass the phone number
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
ToastHelper.showSuccessToast(
|
ToastHelper.showSuccessToast(
|
||||||
context, 'Verification code sent to ${emailController.text}');
|
context, 'Verification code sent to ${emailMobileController.text}');
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) => MyEmailVerify(
|
builder: (context) => MyEmailVerify(
|
||||||
type: 'mobile',
|
type: 'mobile',
|
||||||
value: mobileController.text.trim(), // Pass the phone number
|
value: emailMobileController.text.trim(), // Pass the phone number
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -556,140 +573,112 @@ class _MyPhoneState extends State<MyHrLogin> {
|
|||||||
),
|
),
|
||||||
Column(
|
Column(
|
||||||
children: [
|
children: [
|
||||||
isEmailFieldVisible
|
Container(
|
||||||
? Container(
|
height: 55,
|
||||||
height: 55,
|
margin: Responsive.isDesktop(context)
|
||||||
margin: Responsive.isDesktop(
|
? const EdgeInsets.symmetric(horizontal: 150)
|
||||||
context)
|
: const EdgeInsets.symmetric(horizontal: 0),
|
||||||
? EdgeInsets.symmetric(
|
decoration: BoxDecoration(
|
||||||
horizontal: 150)
|
border: Border.all(width: 1, color: Colors.grey),
|
||||||
: EdgeInsets.symmetric(
|
borderRadius: BorderRadius.circular(10),
|
||||||
horizontal: 0),
|
),
|
||||||
decoration: BoxDecoration(
|
child: TextFormField(
|
||||||
border: Border.all(
|
controller: emailMobileController,
|
||||||
width: 1,
|
keyboardType: TextInputType.text,
|
||||||
color: Colors.grey),
|
decoration: const InputDecoration(
|
||||||
borderRadius:
|
border: InputBorder.none,
|
||||||
BorderRadius.circular(10),
|
hintText: "Email / Mobile Number ",
|
||||||
),
|
contentPadding: EdgeInsets.symmetric(horizontal: 10),
|
||||||
child: TextFormField(
|
|
||||||
controller: emailController,
|
|
||||||
keyboardType: TextInputType
|
|
||||||
.emailAddress,
|
|
||||||
decoration: InputDecoration(
|
|
||||||
border: InputBorder.none,
|
|
||||||
hintText:
|
|
||||||
"Enter your email",
|
|
||||||
contentPadding:
|
|
||||||
EdgeInsets.symmetric(
|
|
||||||
horizontal: 10),
|
|
||||||
),
|
|
||||||
validator: (value) {
|
|
||||||
if (value == null ||
|
|
||||||
value.isEmpty) {
|
|
||||||
return 'Please enter your email';
|
|
||||||
}
|
|
||||||
if (!RegExp(
|
|
||||||
r'^[^@]+@[^@]+\.[^@]+')
|
|
||||||
.hasMatch(value)) {
|
|
||||||
return 'Please enter a valid email';
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: Container(
|
|
||||||
height: 55,
|
|
||||||
margin: Responsive.isDesktop(
|
|
||||||
context)
|
|
||||||
? EdgeInsets.symmetric(
|
|
||||||
horizontal: 150)
|
|
||||||
: EdgeInsets.symmetric(
|
|
||||||
horizontal: 0),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
border: Border.all(
|
|
||||||
width: 1,
|
|
||||||
color: Colors.grey),
|
|
||||||
borderRadius:
|
|
||||||
BorderRadius.circular(10),
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
SizedBox(width: 10),
|
|
||||||
SizedBox(
|
|
||||||
width: 40,
|
|
||||||
child: TextField(
|
|
||||||
controller:
|
|
||||||
countryController,
|
|
||||||
keyboardType:
|
|
||||||
TextInputType
|
|
||||||
.number,
|
|
||||||
decoration:
|
|
||||||
InputDecoration(
|
|
||||||
border:
|
|
||||||
InputBorder.none,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
"|",
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 33,
|
|
||||||
color: Colors.grey),
|
|
||||||
),
|
|
||||||
SizedBox(width: 10),
|
|
||||||
Expanded(
|
|
||||||
child: TextFormField(
|
|
||||||
controller:
|
|
||||||
mobileController,
|
|
||||||
keyboardType:
|
|
||||||
TextInputType.phone,
|
|
||||||
decoration:
|
|
||||||
InputDecoration(
|
|
||||||
border:
|
|
||||||
InputBorder.none,
|
|
||||||
hintText:
|
|
||||||
"Enter your mobile number",
|
|
||||||
),
|
|
||||||
validator: (value) {
|
|
||||||
if (value == null ||
|
|
||||||
value.isEmpty) {
|
|
||||||
return 'Please enter your mobile number';
|
|
||||||
}
|
|
||||||
if (value.length !=
|
|
||||||
10) {
|
|
||||||
return 'Mobile number must be 10 digits';
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
inputFormatters: [
|
|
||||||
FilteringTextInputFormatter
|
|
||||||
.digitsOnly,
|
|
||||||
LengthLimitingTextInputFormatter(
|
|
||||||
10),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
|
validator: (value) {
|
||||||
|
if (value == null || value.trim().isEmpty) {
|
||||||
|
return "Please enter email or mobile number";
|
||||||
|
}
|
||||||
|
|
||||||
|
String input = value.trim();
|
||||||
|
|
||||||
|
// ❌ Reject all spaces
|
||||||
|
if (input.contains(' ')) {
|
||||||
|
return "No spaces allowed";
|
||||||
|
}
|
||||||
|
|
||||||
|
final emailRegex = RegExp(r'^[^@]+@[^@]+\.[^@]+$');
|
||||||
|
final mobileRegex = RegExp(r'^[0-9]{10}$');
|
||||||
|
|
||||||
|
bool isEmailFormat = emailRegex.hasMatch(input);
|
||||||
|
bool isMobileFormat = mobileRegex.hasMatch(input);
|
||||||
|
|
||||||
|
// ---------------------------
|
||||||
|
// 🛑 MOBILE VALIDATION
|
||||||
|
// ---------------------------
|
||||||
|
if (RegExp(r'^[0-9]+$').hasMatch(input)) {
|
||||||
|
if (input.length != 10) {
|
||||||
|
return "Mobile number must be exactly 10 digits";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------
|
||||||
|
// 🛑 EMAIL VALIDATION
|
||||||
|
// ---------------------------
|
||||||
|
|
||||||
|
// Reject anything that has '@' but is NOT a valid email format
|
||||||
|
if (input.contains('@') && !isEmailFormat) {
|
||||||
|
return "Enter a valid email address";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reject email with extra digits at the end
|
||||||
|
if (input.contains('@') && RegExp(r'\d+$').hasMatch(input)) {
|
||||||
|
return "Email cannot contain extra numbers";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reject email+mobile combination
|
||||||
|
if (input.contains('@') && RegExp(r'\d{10}$').hasMatch(input)) {
|
||||||
|
return "Enter only email OR mobile number";
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------
|
||||||
|
// 🛑 MIXED CONTENT (letters + digits but NOT email)
|
||||||
|
// ---------------------------
|
||||||
|
bool hasLetters = RegExp(r'[A-Za-z]').hasMatch(input);
|
||||||
|
bool hasDigits = RegExp(r'[0-9]').hasMatch(input);
|
||||||
|
|
||||||
|
if ((hasLetters && hasDigits) && !input.contains('@')) {
|
||||||
|
return "Enter only email OR 10-digit mobile number";
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------
|
||||||
|
// 🟢 FINAL CHECK
|
||||||
|
// ---------------------------
|
||||||
|
if (!isEmailFormat && !isMobileFormat) {
|
||||||
|
return "Enter a valid email or 10-digit mobile number";
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
),
|
||||||
|
),
|
||||||
SizedBox(height: 15),
|
SizedBox(height: 15),
|
||||||
Container(
|
Container(
|
||||||
margin: Responsive.isDesktop(context)
|
margin: Responsive.isDesktop(
|
||||||
|
context)
|
||||||
? EdgeInsets.symmetric(
|
? EdgeInsets.symmetric(
|
||||||
horizontal: 150)
|
horizontal: 150)
|
||||||
: EdgeInsets.symmetric(
|
: EdgeInsets.symmetric(
|
||||||
horizontal: 0),
|
horizontal: 0),
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
height: 45,
|
height: 45,
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton
|
||||||
|
.styleFrom(
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
Color(0xFF00989E),
|
Color(0xFF00989E),
|
||||||
shape: RoundedRectangleBorder(
|
shape:
|
||||||
|
RoundedRectangleBorder(
|
||||||
borderRadius:
|
borderRadius:
|
||||||
BorderRadius.circular(10),
|
BorderRadius
|
||||||
|
.circular(10),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
onPressed: _isLoading
|
onPressed: _isLoading
|
||||||
@ -697,40 +686,37 @@ class _MyPhoneState extends State<MyHrLogin> {
|
|||||||
: verifyMobileAndEmailNumber,
|
: verifyMobileAndEmailNumber,
|
||||||
child: _isLoading
|
child: _isLoading
|
||||||
? CircularProgressIndicator(
|
? CircularProgressIndicator(
|
||||||
valueColor:
|
valueColor:
|
||||||
AlwaysStoppedAnimation<
|
AlwaysStoppedAnimation<
|
||||||
Color>(
|
Color>(
|
||||||
Color(0xFF00989E),
|
Color(0xFF00989E),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: Text(
|
: Text( "Login with Email / Mobile OTP",
|
||||||
isEmailFieldVisible
|
style: GoogleFonts
|
||||||
? "Login with Email OTP"
|
.poppins(
|
||||||
: "Login with Mobile OTP",
|
color: Color(
|
||||||
style:
|
0xFFFFFFFF),
|
||||||
GoogleFonts.poppins(
|
),
|
||||||
color:
|
|
||||||
Color(0xFFFFFFFF),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(height: 15),
|
|
||||||
MouseRegion(
|
|
||||||
cursor: SystemMouseCursors.click,
|
|
||||||
child: GestureDetector(
|
|
||||||
onTap: toggleField,
|
|
||||||
child: Text(
|
|
||||||
isEmailFieldVisible
|
|
||||||
? "Login with Mobile No"
|
|
||||||
: "Login with Email",
|
|
||||||
style: TextStyle(
|
|
||||||
color: Color(0xFF00989E),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
SizedBox(height: 15),
|
||||||
|
// MouseRegion(
|
||||||
|
// cursor: SystemMouseCursors.click,
|
||||||
|
// child: GestureDetector(
|
||||||
|
// onTap: toggleField,
|
||||||
|
// child: Text(
|
||||||
|
// isEmailFieldVisible
|
||||||
|
// ? "Login with Mobile No"
|
||||||
|
// : "Login with Email",
|
||||||
|
// style: TextStyle(
|
||||||
|
// color: Color(0xFF00989E),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
|
|||||||
23
lib/hrPolicyDetails.dart
Executable file → Normal file
@ -174,6 +174,27 @@ class _HrPolicyDetailsState extends State<hrPolicyDetails>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> getEcardDownload(String? empCode,String? empId,String? clientPolicyId,String? policyNo) async {
|
||||||
|
final eCarDParams = {
|
||||||
|
'id': empId,
|
||||||
|
'emp_code': empCode,
|
||||||
|
'client_policy_id': clientPolicyId,
|
||||||
|
'policy_no': policyNo
|
||||||
|
};
|
||||||
|
final response = await apiService.getEcardRequest(eCarDParams,widget.Token);
|
||||||
|
print('check 1');
|
||||||
|
final ecardDownloadUrl = response['data']['eCardDownload'];
|
||||||
|
final message = response['data']['message'];
|
||||||
|
if (ecardDownloadUrl != null) {
|
||||||
|
print('✅ Link: $ecardDownloadUrl');
|
||||||
|
await _launchURL(ecardDownloadUrl); // Only launch if status is success
|
||||||
|
// ToastHelper.showSuccessToast(context, message);
|
||||||
|
} else {
|
||||||
|
print('❌ Error: $message');
|
||||||
|
ToastHelper.showErrorToast(context, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> _launchURL(String url) async {
|
Future<void> _launchURL(String url) async {
|
||||||
final Uri uri = Uri.parse(url); // Parse the URL properly
|
final Uri uri = Uri.parse(url); // Parse the URL properly
|
||||||
print('_launchURL $uri');
|
print('_launchURL $uri');
|
||||||
@ -933,7 +954,7 @@ class _HrPolicyDetailsState extends State<hrPolicyDetails>
|
|||||||
padding: const EdgeInsets.symmetric(horizontal: 4.0),
|
padding: const EdgeInsets.symmetric(horizontal: 4.0),
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
_launchURL(item['ecard_download_link']);
|
getEcardDownload(item['emp_code'],item['employee_id'],item['client_policy_id'],item['policy_no']);
|
||||||
},
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
height: 40,
|
height: 40,
|
||||||
|
|||||||
0
lib/hrVerify.dart
Executable file → Normal file
0
lib/main.dart
Executable file → Normal file
0
lib/models/environment.dart
Executable file → Normal file
0
lib/models/platform_helper_mobile.dart
Executable file → Normal file
0
lib/models/platform_helper_other.dart
Executable file → Normal file
0
lib/oldPolicy.dart
Executable file → Normal file
0
lib/phone.dart
Executable file → Normal file
0
lib/responsive.dart
Executable file → Normal file
30
lib/service/api_service.dart
Executable file → Normal file
@ -612,6 +612,18 @@ class ApiService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<Map<String, dynamic>> getEcardRequest(eCardParam,String token) async {
|
||||||
|
final url = Uri.parse('${Environment.apiUrlPost}ecardRequest');
|
||||||
|
final headers = {
|
||||||
|
'Authorization': 'Bearer $token' ?? '',
|
||||||
|
'Content-Type': 'application/json', // Ensure content type is JSON
|
||||||
|
};
|
||||||
|
final jsonBody = jsonEncode(eCardParam);
|
||||||
|
// Send formDataJson as the body
|
||||||
|
final response = await _makePostRequestWithoutFormData(url,jsonBody, headers);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
Future<Map<String, dynamic>> getCdTransactionData(
|
Future<Map<String, dynamic>> getCdTransactionData(
|
||||||
String clintID, String insurerId, String cd_ac_pk, String token) async {
|
String clintID, String insurerId, String cd_ac_pk, String token) async {
|
||||||
print("getCashDepositDetailsToApi1");
|
print("getCashDepositDetailsToApi1");
|
||||||
@ -638,6 +650,17 @@ class ApiService {
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<Map<String, dynamic>> getSampleFileDownload(String token) async {
|
||||||
|
final url = Uri.parse(
|
||||||
|
'${Environment.apiUrl}downloadSampleExcel/enrollment');
|
||||||
|
|
||||||
|
final headers = {
|
||||||
|
'Authorization': 'Bearer $token' ?? '',
|
||||||
|
};
|
||||||
|
final response = await _makeGetRequest(url, headers);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
Future<Map<String, dynamic>> getEmployeeAndDependenceToApi(
|
Future<Map<String, dynamic>> getEmployeeAndDependenceToApi(
|
||||||
String clintID, String getPolicyNo, String empRefId, String token) async {
|
String clintID, String getPolicyNo, String empRefId, String token) async {
|
||||||
print(_hrtoken);
|
print(_hrtoken);
|
||||||
@ -754,6 +777,13 @@ class ApiService {
|
|||||||
// return response;
|
// return response;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
Future<Map<String, dynamic>> _makePostRequestWithoutFormData(
|
||||||
|
Uri url, String body, Map<String, String> headers) async {
|
||||||
|
|
||||||
|
final response = await http.post(url, headers: headers, body: body);
|
||||||
|
return _handleResponse(response);
|
||||||
|
}
|
||||||
|
|
||||||
Future<Map<String, dynamic>> _makeGetRequest(
|
Future<Map<String, dynamic>> _makeGetRequest(
|
||||||
Uri url, Map<String, String> headers) async {
|
Uri url, Map<String, String> headers) async {
|
||||||
final response = await http.get(url, headers: headers);
|
final response = await http.get(url, headers: headers);
|
||||||
|
|||||||
@ -228,7 +228,7 @@ class _ActivePolicieState extends State<ActivePolicies> {
|
|||||||
child: getCardArrays.isEmpty
|
child: getCardArrays.isEmpty
|
||||||
? Center(
|
? Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
'No data found',
|
'No Policy Mapping Found',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
color: Colors.grey.shade600,
|
color: Colors.grey.shade600,
|
||||||
|
|||||||