This commit is contained in:
venbaittech 2024-07-28 11:50:54 +05:30
parent f7edbd6a99
commit b5d77d2426
28 changed files with 1079 additions and 440 deletions

8
.env
View File

@ -1,4 +1,4 @@
API_URL=https://venbait.in/nhance/dev/employeeRest/
TICKET_API_URL=https://venbait.in/nhance/helpdesk/dev/api
BASE_HREF=/nhance/employee/dev/
ENV=production
API_URL=https://dev.venbait.in/nhance/uat/employeeRest/
TICKET_API_URL=https://dev.venbait.in/nhance/helpdesk/uat/api
BASE_HREF=/nhance/employee/uat/
ENV=uat

View File

@ -1,4 +1,4 @@
API_URL=https://venbait.in/nhance/dev/employeeRest/
TICKET_API_URL=https://venbait.in/nhance/helpdesk/dev/api
BASE_HREF=/nhance/employee/dev/
API_URL=https://dev.venbait.in/nhance/uat/employeeRest/
TICKET_API_URL=https://dev.venbait.in/nhance/helpdesk/uat/api
BASE_HREF=/nhance/employee/uat/
ENV=production

4
.env.uat Normal file
View File

@ -0,0 +1,4 @@
API_URL=https://dev.venbait.in/nhance/uat/employeeRest/
TICKET_API_URL=https://dev.venbait.in/nhance/helpdesk/uat/api
BASE_HREF=/nhance/employee/uat/
ENV=uat

View File

@ -2,6 +2,7 @@ plugins {
id "com.android.application"
id "kotlin-android"
id "dev.flutter.flutter-gradle-plugin"
id "com.google.gms.google-services"
}
def localProperties = new Properties()
@ -45,7 +46,7 @@ android {
applicationId "com.example.nhance_app_pwa"
// You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
minSdkVersion flutter.minSdkVersion
minSdkVersion 23
targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
@ -64,4 +65,8 @@ flutter {
source '../..'
}
dependencies {}
dependencies {
implementation(platform("com.google.firebase:firebase-bom:33.1.2"))
implementation 'com.google.firebase:firebase-messaging:22.0.0'
implementation("com.google.firebase:firebase-auth:23.0.0")
}

View File

@ -0,0 +1,29 @@
{
"project_info": {
"project_number": "203846206303",
"project_id": "push-notification-enrollment",
"storage_bucket": "push-notification-enrollment.appspot.com"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:203846206303:android:01f39a22f39a50539b6cea",
"android_client_info": {
"package_name": "com.example.nhance_app_pwa"
}
},
"oauth_client": [],
"api_key": [
{
"current_key": "AIzaSyAdacw5svpqopDCpoEym7aDkI3F2AajEO4"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": []
}
}
}
],
"configuration_version": "1"
}

View File

@ -0,0 +1,29 @@
{
"project_info": {
"project_number": "203846206303",
"project_id": "push-notification-enrollment",
"storage_bucket": "push-notification-enrollment.appspot.com"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:203846206303:android:01f39a22f39a50539b6cea",
"android_client_info": {
"package_name": "com.example.nhance_app_pwa"
}
},
"oauth_client": [],
"api_key": [
{
"current_key": "AIzaSyAdacw5svpqopDCpoEym7aDkI3F2AajEO4"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": []
}
}
}
],
"configuration_version": "1"
}

View File

@ -1,4 +1,4 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.nhance_app_pwa">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

View File

@ -1,3 +1,14 @@
buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.0.2' // Use the appropriate version for your project
classpath 'com.google.gms:google-services:4.4.2' // Correct version for google-services
}
}
allprojects {
repositories {
google()

View File

@ -21,6 +21,7 @@ plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "7.3.0" apply false
id "org.jetbrains.kotlin.android" version "1.8.22" apply false
id("com.google.gms.google-services") version "4.4.2" apply false
}
include ":app"

View File

@ -32,8 +32,8 @@ flutter build web --release --base-href "$BASE_HREF"
# Check if the build was successful
if [ $? -ne 0 ]; then
echo "Flutter prod build failed"
echo "Flutter PRODUCTION build failed"
exit 1
fi
echo "Flutter prod build succeeded"
echo "Flutter PRODUCTION build succeeded"

39
build_web_uat.sh Executable file
View File

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

View File

@ -1,8 +1,12 @@
import 'package:flutter/material.dart';
import 'package:adaptive_navbar/adaptive_navbar.dart';
import 'package:nhance_app_pwa/customAppBar/responsive.dart';
import 'package:nhance_app_pwa/customAppBar/toastHelper.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../models/platform_helper_mobile.dart'
if (dart.library.html) '../models/platform_helper_other.dart';
class CustomAppBar extends StatefulWidget implements PreferredSizeWidget {
@override
_CustomAppBarState createState() => _CustomAppBarState();
@ -14,17 +18,46 @@ class CustomAppBar extends StatefulWidget implements PreferredSizeWidget {
class _CustomAppBarState extends State<CustomAppBar> {
bool showBackToHR = true;
bool hideInactiveStatus = true;
dynamic empStatus;
@override
void initState() {
super.initState();
getEmpStatus();
}
Future<void> getEmpStatus() async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
empStatus = prefs.getString('emp_status');
}
Future<void> logout(BuildContext context) async {
final prefs = await SharedPreferences.getInstance();
final String? token = prefs.getString('token');
// final prefs = await SharedPreferences.getInstance();
// final String? token = prefs.getString('token');
//
// if (token != null && token.isNotEmpty) {
// await prefs.clear();
// Navigator.pushNamed(context, 'login');
// }
if (token != null && token.isNotEmpty) {
if (isMobilePlatform()) {
final SharedPreferences prefs = await SharedPreferences.getInstance();
// Get the value of the mobile_number key
String? mobileNumber = prefs.getString('empMobileNo');
// Clear all keys
await prefs.clear();
// Re-set the mobile_number key
if (mobileNumber != null) {
await prefs.setString('empMobileNo', mobileNumber);
}
ToastHelper.showSuccessToast(context, 'logout');
// Navigate to login page
Navigator.pushNamed(context, 'login');
} else {
final prefs = await SharedPreferences.getInstance();
await prefs.clear();
Navigator.pushNamed(context, 'login');
}
@ -66,31 +99,32 @@ class _CustomAppBarState extends State<CustomAppBar> {
),
),
// AdaptiveNavBar Column
Expanded(
flex: Responsive.isDesktop(context) ? 9 : 3,
child: AdaptiveNavBar(
screenWidth: sw,
backgroundColor: Color(0xFFFFFCE5),
leading:
Container(), // Set an empty container as we have the logo separately
title: Text(''),
navBarItems: [
if (Responsive.isDesktop(context))
if (!Responsive.isDesktop(context) && empStatus != 'enrolled')
Expanded(
flex: Responsive.isDesktop(context) ? 9 : 3,
child: AdaptiveNavBar(
screenWidth: sw,
backgroundColor: Color(0xFFFFFCE5),
leading:
Container(), // Set an empty container as we have the logo separately
title: Text(''),
navBarItems: [
if (Responsive.isDesktop(context))
NavBarItem(
text: "Inactive Policy",
onTap: () {
Navigator.pushNamed(context, 'oldPolicy');
},
),
NavBarItem(
text: "Inactive Policy",
onTap: () {
Navigator.pushNamed(context, 'oldPolicy');
text: "Logout",
onTap: () async {
logout(context);
},
),
NavBarItem(
text: "Logout",
onTap: () async {
logout(context);
},
),
],
],
),
),
),
],
),
),

View File

@ -1,3 +1,4 @@
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:nhance_app_pwa/pages/enrollment/addons.dart';
@ -27,6 +28,12 @@ import 'models/environment.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: const FirebaseOptions(
apiKey: 'AIzaSyAdacw5svpqopDCpoEym7aDkI3F2AajEO4',
appId: '1:203846206303:android:01f39a22f39a50539b6cea',
messagingSenderId: '203846206303',
projectId: 'push-notification-enrollment'));
await dotenv.load(fileName: Environment.fileName);
final AuthService _authService = AuthService();
@ -49,7 +56,12 @@ Future<void> main() async {
// ),
routes: {
'login': (context) => login(),
'verify': (context) => MyVerify(),
'verify': (context) => MyVerify(
verificationId: '',
mobileNumber: '',
resendToken: null,
onResendCode: (String, int) {},
),
'pinSettingPage': (context) => pinSettingPage(),
'pinPage': (context) => pinPage(),
'changePin': (context) => changePin(),

View File

@ -1,21 +1,19 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import '../pages/postEnrollment/home.dart';
class Environment {
static String get fileName {
const bool isProduction =
bool.fromEnvironment('dart.vm.product', defaultValue: false);
const bool isTest = bool.fromEnvironment('ENV', defaultValue: false);
const String env =
String.fromEnvironment('ENV', defaultValue: 'development');
if (isProduction) {
return '.env.production';
} else if (isTest) {
return '.env.test';
} else {
return '.env.development';
switch (env) {
case 'production':
return '.env.production';
case 'test':
return '.env.test';
case 'uat':
return '.env.uat';
default:
return '.env.development';
}
}
@ -32,45 +30,10 @@ class Environment {
}
static String get apiUrlTicket {
return dotenv.env['TICKET_API_URL'] ?? 'API_URL not found!';
return dotenv.env['TICKET_API_URL'] ?? 'TICKET_API_URL not found!';
}
static String get ticketToken {
return 'uncp8FvG310bEyYdV9MmStlo7KDRZ65fLWTeXCI2JzwPrNHjBqQhUiAgxsaO';
}
}
Future<void> main() async {
await dotenv.load(fileName: Environment.fileName);
runApp(MyApp());
}
// class Environment {
// static String get fileName {
// if (kReleaseMode) {
// return '.env.production';
// } else {
// return '.env.development';
// }
// }
//
// static String get apiUrl {
// return dotenv.env['API_URL'] ?? 'API_URL not found!';
// }
//
// static String get baseHref {
// return dotenv.env['BASE_HREF'] ?? 'BASE_HREF not found!';
// }
//
// static String get env {
// return dotenv.env['ENV'] ?? 'ENV not found!';
// }
//
// static String get apiUrlTicket {
// return dotenv.env['TICKET_API_URL'] ?? 'API_URL not found!';
// }
//
// static String get ticketToken {
// return 'uncp8FvG310bEyYdV9MmStlo7KDRZ65fLWTeXCI2JzwPrNHjBqQhUiAgxsaO';
// }
// }

View File

@ -124,6 +124,7 @@ class _addOnsDetailsState extends State<addOnsDetails> {
dynamic gpaDataIsEmpty = 1;
dynamic empRefId;
dynamic empClientBranchId;
dynamic selfEmpStatus;
@override
void initState() {
@ -168,6 +169,7 @@ class _addOnsDetailsState extends State<addOnsDetails> {
// Decode the JWT token received from the API response
Map<String, dynamic>? decodedToken = Jwt.parseJwt(token);
print(decodedToken);
selfEmpStatus = prefs.getString('selfEmpStatus');
empClientBranchId = prefs.getString('empClientBranchId');
empCodeString = prefs.getString('empCode');
print(empCodeString); // Check if emp_code is correct
@ -1826,7 +1828,7 @@ class _addOnsDetailsState extends State<addOnsDetails> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
flex: 8,
flex: 9,
child: Container(
alignment: Alignment.centerLeft,
child: Column(
@ -1843,7 +1845,7 @@ class _addOnsDetailsState extends State<addOnsDetails> {
Responsive.isDesktop(
context)
? 18
: 14,
: 13,
),
),
Row(
@ -1857,7 +1859,7 @@ class _addOnsDetailsState extends State<addOnsDetails> {
.isDesktop(
context)
? 20
: 16,
: 14,
fontWeight:
FontWeight.w600,
),
@ -1899,7 +1901,7 @@ class _addOnsDetailsState extends State<addOnsDetails> {
],
))),
Expanded(
flex: 4,
flex: 3,
child: Container(
alignment: Alignment.centerRight,
child: Column(
@ -1916,7 +1918,7 @@ class _addOnsDetailsState extends State<addOnsDetails> {
Responsive.isDesktop(
context)
? 18
: 14,
: 13,
),
),
Text(
@ -1927,7 +1929,7 @@ class _addOnsDetailsState extends State<addOnsDetails> {
Responsive.isDesktop(
context)
? 20
: 16,
: 14,
fontWeight: FontWeight.w600,
),
),
@ -4151,7 +4153,8 @@ class _addOnsDetailsState extends State<addOnsDetails> {
'assets/nhance-loader.gif'), // Adjust path to your GIF loader
),
),
if (Responsive.isDesktop(context))
if (Responsive.isDesktop(context) ||
(!Responsive.isDesktop(context) && selfEmpStatus != 'enrolled'))
Align(
alignment: Alignment.bottomCenter,
child: Container(
@ -4162,46 +4165,53 @@ class _addOnsDetailsState extends State<addOnsDetails> {
]),
floatingActionButton: Responsive.isDesktop(context)
? null
: FloatingActionButton(
onPressed: () => Navigator.push(
context,
MaterialPageRoute(builder: (context) => chatbot()),
),
child: Icon(Icons.chat),
),
: selfEmpStatus == 'enrolled'
? FloatingActionButton(
onPressed: () => Navigator.push(
context,
MaterialPageRoute(builder: (context) => chatbot()),
),
child: Icon(Icons.chat),
)
: null,
floatingActionButtonLocation: Responsive.isDesktop(context)
? null
: FloatingActionButtonLocation.miniEndFloat,
: selfEmpStatus == 'enrolled'
? FloatingActionButtonLocation.miniEndFloat
: null,
bottomNavigationBar: Responsive.isDesktop(context)
? null
: CustomBottomNavigationBar(
onTabChanged: (index) {
// Add your navigation logic here
// For example:
if (index == 0) {
Navigator.pushNamed(context, 'home');
} else if (index == 1) {
Navigator.pushNamed(context, 'claims');
} else if (index == 2) {
Navigator.pushNamed(context, 'profile');
} else if (index == 3) {
Navigator.pushNamed(context, 'help');
}
},
icons: [
Icons.home_outlined,
Icons.sticky_note_2_outlined,
Icons.person_outline_outlined,
Icons.headset_mic_outlined,
],
labels: [
"Home",
"Claim",
"Profile",
"Help",
],
initialIndex: 0, // Initial index of the bottom navigation bar
),
: selfEmpStatus == 'enrolled'
? CustomBottomNavigationBar(
onTabChanged: (index) {
// Add your navigation logic here
// For example:
if (index == 0) {
Navigator.pushNamed(context, 'home');
} else if (index == 1) {
Navigator.pushNamed(context, 'claims');
} else if (index == 2) {
Navigator.pushNamed(context, 'profile');
} else if (index == 3) {
Navigator.pushNamed(context, 'help');
}
},
icons: [
Icons.home_outlined,
Icons.sticky_note_2_outlined,
Icons.person_outline_outlined,
Icons.headset_mic_outlined,
],
labels: [
"Home",
"Claim",
"Profile",
"Help",
],
initialIndex:
0, // Initial index of the bottom navigation bar
)
: null,
);
}
}
@ -4571,7 +4581,7 @@ class _addOnsDetailsState extends State<addOnsDetails> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
flex: 8,
flex: 9,
child: Container(
alignment: Alignment.centerLeft,
child: Column(
@ -4586,7 +4596,7 @@ class _addOnsDetailsState extends State<addOnsDetails> {
fontSize:
Responsive.isDesktop(context)
? 18
: 14,
: 13,
),
),
Row(
@ -4598,7 +4608,7 @@ class _addOnsDetailsState extends State<addOnsDetails> {
fontSize:
Responsive.isDesktop(context)
? 20
: 16,
: 14,
fontWeight: FontWeight.w600,
),
),
@ -4633,7 +4643,7 @@ class _addOnsDetailsState extends State<addOnsDetails> {
],
))),
Expanded(
flex: 4,
flex: 3,
child: Container(
alignment: Alignment.centerRight,
child: Column(
@ -4647,7 +4657,7 @@ class _addOnsDetailsState extends State<addOnsDetails> {
fontSize:
Responsive.isDesktop(context)
? 18
: 14,
: 13,
),
),
Text(
@ -4657,7 +4667,7 @@ class _addOnsDetailsState extends State<addOnsDetails> {
fontSize:
Responsive.isDesktop(context)
? 20
: 16,
: 14,
fontWeight: FontWeight.w600,
),
),

View File

@ -390,54 +390,83 @@ class _empDetailsState extends State<empDetails> {
Future<void> _selectDate(BuildContext context, formType) async {
print(formType);
var ageValidation = formType['age_validation'];
int min =
int.parse(ageValidation['min']); // Parsing the string to an integer
int max =
int.parse(ageValidation['max']); // Parsing the string to an integer
print(min);
print(max);
late DateTime minDate;
late DateTime maxDate;
print(ageValidation);
// int min = int.parse(ageValidation['min']);
// int max = int.parse(ageValidation['max']);
// Ensure ageValidation is a Map and contains the expected values
if (ageValidation is Map<String, dynamic>) {
int min = ageValidation.containsKey('min')
? int.tryParse(ageValidation['min'].toString()) ?? 0
: 0;
int max = ageValidation.containsKey('max')
? int.tryParse(ageValidation['max'].toString()) ?? 100
: 100;
final DateTime now = DateTime.now();
print('Min age: $min');
print('Max age: $max');
late DateTime minDate;
late DateTime maxDate;
maxDate = DateTime(now.year - min, now.month, now.day);
print(maxDate);
minDate = DateTime(now.year - max, now.month, now.day);
print(minDate);
final DateTime now = DateTime.now();
// if (formType['form_type'] == 'child') {
// // For 'child' form type, allow 0-25 age
// minDate = DateTime(now.year - 25, now.month, now.day);
// maxDate = now;
// } else {
// // For other form types, allow 18-100 age
// minDate = DateTime(1900);
// maxDate = DateTime(now.year - 18, now.month, now.day);
// }
maxDate = DateTime(now.year - min, now.month, now.day);
print(maxDate);
minDate = DateTime(now.year - max, now.month, now.day);
print(minDate);
// Ensure initialDate is within the range of minDate and maxDate
DateTime initialDate =
_selectedDate ?? maxDate; // Use maxDate if _selectedDate is null
initialDate = initialDate.isBefore(minDate) ? minDate : initialDate;
initialDate = initialDate.isAfter(maxDate) ? maxDate : initialDate;
// if (formType['form_type'] == 'child') {
// // For 'child' form type, allow 0-25 age
// minDate = DateTime(now.year - 25, now.month, now.day);
// maxDate = now;
// } else {
// // For other form types, allow 18-100 age
// minDate = DateTime(1900);
// maxDate = DateTime(now.year - 18, now.month, now.day);
// }
final DateTime? picked = await showDatePicker(
context: context,
initialDate: initialDate,
firstDate: minDate,
lastDate: maxDate,
selectableDayPredicate: (DateTime date) {
return date.isAfter(minDate.subtract(const Duration(days: 1))) &&
date.isBefore(maxDate.add(const Duration(days: 1)));
},
);
// Ensure initialDate is within the range of minDate and maxDate
DateTime initialDate =
_selectedDate ?? maxDate; // Use maxDate if _selectedDate is null
initialDate = initialDate.isBefore(minDate) ? minDate : initialDate;
initialDate = initialDate.isAfter(maxDate) ? maxDate : initialDate;
if (picked != null && picked != _selectedDate) {
setState(() {
_selectedDate = picked;
_dobController.text = DateFormat('dd-MM-yyyy').format(_selectedDate);
});
final DateTime? picked = await showDatePicker(
context: context,
initialDate: initialDate,
firstDate: minDate,
lastDate: maxDate,
selectableDayPredicate: (DateTime date) {
return date.isAfter(minDate.subtract(const Duration(days: 1))) &&
date.isBefore(maxDate.add(const Duration(days: 1)));
},
builder: (BuildContext context, Widget? child) {
return Theme(
data: ThemeData.light().copyWith(
primaryColor: Color(0xFFE26728), // Header background color
colorScheme: ColorScheme.light(
primary: Color(0xFFE26728), secondary: Color(0xFFE26728)),
buttonTheme: ButtonThemeData(textTheme: ButtonTextTheme.primary),
// dialogBackgroundColor:
// Colors.white, // Background color of the dialog
iconTheme: IconThemeData(color: Color(0xFFE26728)),
textButtonTheme: TextButtonThemeData(
style: TextButton.styleFrom(
foregroundColor: Color(0xFFE26728)), // Button color
),
),
child: child!,
);
},
);
if (picked != null && picked != _selectedDate) {
setState(() {
_selectedDate = picked;
_dobController.text = DateFormat('dd-MM-yyyy').format(_selectedDate);
});
}
} else {
print('Invalid age validation data');
}
}
@ -663,6 +692,7 @@ class _empDetailsState extends State<empDetails> {
));
} else {
return Scaffold(
backgroundColor: Color(0xFFFFFFFF),
appBar: CustomAppBar(),
body: Stack(children: [
SingleChildScrollView(
@ -782,7 +812,7 @@ class _empDetailsState extends State<empDetails> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
flex: 8,
flex: 9,
child: Container(
alignment: Alignment.centerLeft,
child: Column(
@ -799,13 +829,13 @@ class _empDetailsState extends State<empDetails> {
Responsive.isDesktop(
context)
? 18
: 14,
: 13,
),
),
Row(
children: [
Text(
'Group Personal Accident Coverage ',
'Group Personal Accident Coverage',
textAlign: TextAlign.left,
style:
GoogleFonts.poppins(
@ -813,7 +843,7 @@ class _empDetailsState extends State<empDetails> {
.isDesktop(
context)
? 20
: 16,
: 14,
fontWeight:
FontWeight.w600,
),
@ -855,7 +885,7 @@ class _empDetailsState extends State<empDetails> {
],
))),
Expanded(
flex: 4,
flex: 3,
child: Container(
alignment: Alignment.centerRight,
child: Column(
@ -872,7 +902,7 @@ class _empDetailsState extends State<empDetails> {
Responsive.isDesktop(
context)
? 18
: 14,
: 13,
),
),
Text(
@ -883,7 +913,7 @@ class _empDetailsState extends State<empDetails> {
Responsive.isDesktop(
context)
? 20
: 16,
: 14,
fontWeight: FontWeight.w600,
),
),
@ -1155,7 +1185,8 @@ class _empDetailsState extends State<empDetails> {
'assets/nhance-loader.gif'), // Adjust path to your GIF loader
),
),
if (Responsive.isDesktop(context))
if (Responsive.isDesktop(context) ||
(!Responsive.isDesktop(context) && selfEmpStatus != 'enrolled'))
Align(
alignment: Alignment.bottomCenter,
child: Container(
@ -1166,46 +1197,53 @@ class _empDetailsState extends State<empDetails> {
]),
floatingActionButton: Responsive.isDesktop(context)
? null
: FloatingActionButton(
onPressed: () => Navigator.push(
context,
MaterialPageRoute(builder: (context) => chatbot()),
),
child: Icon(Icons.chat),
),
: selfEmpStatus == 'enrolled'
? FloatingActionButton(
onPressed: () => Navigator.push(
context,
MaterialPageRoute(builder: (context) => chatbot()),
),
child: Icon(Icons.chat),
)
: null,
floatingActionButtonLocation: Responsive.isDesktop(context)
? null
: FloatingActionButtonLocation.miniEndFloat,
: selfEmpStatus == 'enrolled'
? FloatingActionButtonLocation.miniEndFloat
: null,
bottomNavigationBar: Responsive.isDesktop(context)
? null
: CustomBottomNavigationBar(
onTabChanged: (index) {
// Add your navigation logic here
// For example:
if (index == 0) {
Navigator.pushNamed(context, 'home');
} else if (index == 1) {
Navigator.pushNamed(context, 'claims');
} else if (index == 2) {
Navigator.pushNamed(context, 'profile');
} else if (index == 3) {
Navigator.pushNamed(context, 'help');
}
},
icons: [
Icons.home_outlined,
Icons.sticky_note_2_outlined,
Icons.person_outline_outlined,
Icons.headset_mic_outlined,
],
labels: [
"Home",
"Claim",
"Profile",
"Help",
],
initialIndex: 0, // Initial index of the bottom navigation bar
),
: selfEmpStatus == 'enrolled'
? CustomBottomNavigationBar(
onTabChanged: (index) {
// Add your navigation logic here
// For example:
if (index == 0) {
Navigator.pushNamed(context, 'home');
} else if (index == 1) {
Navigator.pushNamed(context, 'claims');
} else if (index == 2) {
Navigator.pushNamed(context, 'profile');
} else if (index == 3) {
Navigator.pushNamed(context, 'help');
}
},
icons: [
Icons.home_outlined,
Icons.sticky_note_2_outlined,
Icons.person_outline_outlined,
Icons.headset_mic_outlined,
],
labels: [
"Home",
"Claim",
"Profile",
"Help",
],
initialIndex:
0, // Initial index of the bottom navigation bar
)
: null,
);
}
}
@ -1224,6 +1262,13 @@ class _empDetailsState extends State<empDetails> {
)
.toList();
// Set the dropdown value based on the form_type
String? dropdownValue;
if (floaterData['form_type'] == 'spouse') {
dropdownValue = 'Spouse';
_relationShipController.text = 'Spouse';
}
print(selectedRelationships);
print(gmcMappedFamilyFloaters);
if (action == 'Add') {
@ -1272,6 +1317,7 @@ class _empDetailsState extends State<empDetails> {
width: Responsive.isDesktop(context) ? 500 : 800,
child: SingleChildScrollView(
child: Card(
color: Colors.white,
elevation: 0,
child: Padding(
padding: Responsive.isDesktop(context)
@ -1325,14 +1371,16 @@ class _empDetailsState extends State<empDetails> {
hintText: 'Relationship',
labelText: 'Relationship',
contentPadding: EdgeInsets.symmetric(
vertical: 5, horizontal: 5),
vertical: 10, horizontal: 15),
),
value: action == 'Edit'
? _relationShipController.text
: null,
value: dropdownValue ??
(action == 'Edit'
? _relationShipController.text
: null),
onChanged: (value) {
_relationShipController.text = value!;
},
dropdownColor: Colors.white,
items: selectedRelationships
.map((relationship) {
final String relationshipName =
@ -1526,6 +1574,7 @@ class _empDetailsState extends State<empDetails> {
width: Responsive.isDesktop(context) ? 1000 : 800,
child: SingleChildScrollView(
child: Card(
color: Colors.white,
elevation: 0,
child: Padding(
padding: Responsive.isDesktop(context)
@ -1630,21 +1679,21 @@ class _empDetailsState extends State<empDetails> {
),
),
),
SizedBox(width: 10),
Expanded(
flex: 4,
child: TextFormField(
readOnly: true,
initialValue: selfEmailPersonal ?? '',
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: 'Email personal',
labelText: 'Email personal',
contentPadding: EdgeInsets.symmetric(
vertical: 10, horizontal: 15),
),
),
),
// SizedBox(width: 10),
// Expanded(
// flex: 4,
// child: TextFormField(
// readOnly: true,
// initialValue: selfEmailPersonal ?? '',
// decoration: InputDecoration(
// border: OutlineInputBorder(),
// hintText: 'Email personal',
// labelText: 'Email personal',
// contentPadding: EdgeInsets.symmetric(
// vertical: 10, horizontal: 15),
// ),
// ),
// ),
SizedBox(width: 10),
Expanded(
flex: 4,
@ -1765,18 +1814,18 @@ class _empDetailsState extends State<empDetails> {
vertical: 10, horizontal: 15),
),
),
SizedBox(height: 15),
TextFormField(
readOnly: true,
initialValue: selfEmailPersonal ?? '',
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: 'Email personal',
labelText: 'Email personal',
contentPadding: EdgeInsets.symmetric(
vertical: 10, horizontal: 15),
),
),
// SizedBox(height: 15),
// TextFormField(
// readOnly: true,
// initialValue: selfEmailPersonal ?? '',
// decoration: InputDecoration(
// border: OutlineInputBorder(),
// hintText: 'Email personal',
// labelText: 'Email personal',
// contentPadding: EdgeInsets.symmetric(
// vertical: 10, horizontal: 15),
// ),
// ),
SizedBox(height: 15),
TextFormField(
readOnly: true,
@ -2164,7 +2213,7 @@ class _empDetailsState extends State<empDetails> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
flex: 8,
flex: 9,
child: Container(
alignment: Alignment.centerLeft,
child: Column(
@ -2177,7 +2226,7 @@ class _empDetailsState extends State<empDetails> {
style: GoogleFonts.poppins(
fontSize: Responsive.isDesktop(context)
? 18
: 14,
: 13,
),
),
Row(
@ -2189,7 +2238,7 @@ class _empDetailsState extends State<empDetails> {
fontSize:
Responsive.isDesktop(context)
? 20
: 16,
: 14,
fontWeight: FontWeight.w600,
),
),
@ -2224,7 +2273,7 @@ class _empDetailsState extends State<empDetails> {
],
))),
Expanded(
flex: 4,
flex: 3,
child: Container(
alignment: Alignment.centerRight,
child: Column(
@ -2237,7 +2286,7 @@ class _empDetailsState extends State<empDetails> {
style: GoogleFonts.poppins(
fontSize: Responsive.isDesktop(context)
? 18
: 14,
: 13,
),
),
Text(
@ -2246,7 +2295,7 @@ class _empDetailsState extends State<empDetails> {
style: GoogleFonts.poppins(
fontSize: Responsive.isDesktop(context)
? 20
: 16,
: 14,
fontWeight: FontWeight.w600,
),
),

View File

@ -121,6 +121,7 @@ class _empReviewDetailsState extends State<empReviewDetails> {
dynamic gmcDataIsEmpty = 1;
dynamic gpaDataIsEmpty = 1;
dynamic empClientBranchId;
dynamic selfEmpStatus;
@override
void initState() {
@ -156,6 +157,7 @@ class _empReviewDetailsState extends State<empReviewDetails> {
setState(() {
_token = token;
});
selfEmpStatus = prefs.getString('selfEmpStatus');
empClientBranchId = prefs.getString('empClientBranchId');
empCodeString = prefs.getString('empCode');
print(empCodeString); // Check if emp_code is correct
@ -706,12 +708,14 @@ class _empReviewDetailsState extends State<empReviewDetails> {
});
print('response.statusCode == 200');
ToastHelper.showSuccessToast(context, 'Saved Successfully...');
_showSuccessDialog();
} else {
setState(() {
isLoading = false;
});
// Handle other status codes
ToastHelper.showErrorToast(context, 'Failed to Save');
_showErrorDialog();
print('Request failed with status: ${response['code']}');
}
} catch (e) {
@ -723,6 +727,67 @@ class _empReviewDetailsState extends State<empReviewDetails> {
}
}
void _showSuccessDialog() {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
backgroundColor: Colors.white,
title: Text(
'Success',
style: GoogleFonts.poppins(
color: Colors.green,
),
),
content: Text('Enrollment Completed'),
actions: <Widget>[
TextButton(
child: Text(
'OK',
style: GoogleFonts.poppins(
color: Color(0xFFE26728),
),
),
onPressed: () {
Navigator.popAndPushNamed(context, 'home');
},
),
],
);
},
);
}
void _showErrorDialog() {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text(
'Error',
style: GoogleFonts.poppins(
color: Colors.red,
),
),
content: Text('Something went wrong. Enrollemnt not completed'),
actions: <Widget>[
TextButton(
child: Text(
'OK',
style: GoogleFonts.poppins(
color: Color(0xFFE26728),
),
),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
}
@override
Widget build(BuildContext context) {
if ((gpaMappedFamilyFloaters == [] && gpaMappedFamilyFloaters == null) &&
@ -958,7 +1023,7 @@ class _empReviewDetailsState extends State<empReviewDetails> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
flex: 8,
flex: 9,
child: Container(
alignment: Alignment.centerLeft,
child: Column(
@ -975,7 +1040,7 @@ class _empReviewDetailsState extends State<empReviewDetails> {
Responsive.isDesktop(
context)
? 18
: 14,
: 13,
),
),
Row(
@ -989,7 +1054,7 @@ class _empReviewDetailsState extends State<empReviewDetails> {
.isDesktop(
context)
? 20
: 16,
: 14,
fontWeight:
FontWeight.w600,
),
@ -1031,7 +1096,7 @@ class _empReviewDetailsState extends State<empReviewDetails> {
],
))),
Expanded(
flex: 4,
flex: 3,
child: Container(
alignment: Alignment.centerRight,
child: Column(
@ -1048,7 +1113,7 @@ class _empReviewDetailsState extends State<empReviewDetails> {
Responsive.isDesktop(
context)
? 18
: 14,
: 13,
),
),
Text(
@ -1059,7 +1124,7 @@ class _empReviewDetailsState extends State<empReviewDetails> {
Responsive.isDesktop(
context)
? 20
: 16,
: 14,
fontWeight: FontWeight.w600,
),
),
@ -1183,7 +1248,7 @@ class _empReviewDetailsState extends State<empReviewDetails> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
flex: 8,
flex: 9,
child: Container(
alignment: Alignment.centerLeft,
child: Column(
@ -1200,7 +1265,7 @@ class _empReviewDetailsState extends State<empReviewDetails> {
Responsive.isDesktop(
context)
? 18
: 14,
: 13,
),
),
Row(
@ -1214,7 +1279,7 @@ class _empReviewDetailsState extends State<empReviewDetails> {
.isDesktop(
context)
? 20
: 16,
: 14,
fontWeight:
FontWeight.w600,
),
@ -1256,7 +1321,7 @@ class _empReviewDetailsState extends State<empReviewDetails> {
],
))),
Expanded(
flex: 4,
flex: 3,
child: Container(
alignment: Alignment.centerRight,
child: Column(
@ -1273,7 +1338,7 @@ class _empReviewDetailsState extends State<empReviewDetails> {
Responsive.isDesktop(
context)
? 18
: 14,
: 13,
),
),
Text(
@ -1284,7 +1349,7 @@ class _empReviewDetailsState extends State<empReviewDetails> {
Responsive.isDesktop(
context)
? 20
: 16,
: 14,
fontWeight: FontWeight.w600,
),
),
@ -1406,7 +1471,7 @@ class _empReviewDetailsState extends State<empReviewDetails> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
flex: 8,
flex: 9,
child: Container(
alignment: Alignment.centerLeft,
child: Column(
@ -1423,63 +1488,74 @@ class _empReviewDetailsState extends State<empReviewDetails> {
Responsive.isDesktop(
context)
? 18
: 14,
: 13,
),
),
Row(
children: [
Text(
topUpParentTypeName ?? '',
textAlign: TextAlign.left,
style:
GoogleFonts.poppins(
fontSize: Responsive
.isDesktop(
context)
? 20
: 16,
fontWeight:
FontWeight.w600,
),
),
if (topUpParentECardDownload !=
null)
GestureDetector(
onTap: () async {
// Convert the URL string to a Uri object
Uri uri = Uri.parse(
topUpParentECardDownload);
// Check if the URL is valid
if (await canLaunchUrl(
uri)) {
// Open the URL in the default browser
await launchUrl(
uri);
} else {
// Handle the case where the URL cannot be launched
print(
'Could not launch $topUpParentECardDownload');
}
},
child: MouseRegion(
cursor:
SystemMouseCursors
.click,
child: Icon(
Icons.file_download,
color: Color(
0xFFE26728),
size: 25,
Container(
// padding: EdgeInsets.all(8.0),
child: Row(
children: [
Flexible(
child: Text(
topUpParentTypeName ??
'',
textAlign:
TextAlign.left,
style: GoogleFonts
.poppins(
fontSize: Responsive
.isDesktop(
context)
? 20
: 14,
fontWeight:
FontWeight.w600,
),
softWrap: true,
overflow: TextOverflow
.visible,
),
),
],
),
if (topUpParentECardDownload !=
null)
GestureDetector(
onTap: () async {
// Convert the URL string to a Uri object
Uri uri = Uri.parse(
topUpParentECardDownload);
// Check if the URL is valid
if (await canLaunchUrl(
uri)) {
// Open the URL in the default browser
await launchUrl(
uri);
} else {
// Handle the case where the URL cannot be launched
print(
'Could not launch $topUpParentECardDownload');
}
},
child: MouseRegion(
cursor:
SystemMouseCursors
.click,
child: Icon(
Icons
.file_download,
color: Color(
0xFFE26728),
size: 25,
),
),
),
],
),
)
],
))),
Expanded(
flex: 4,
flex: 3,
child: Container(
alignment: Alignment.centerRight,
child: Column(
@ -1497,7 +1573,7 @@ class _empReviewDetailsState extends State<empReviewDetails> {
Responsive.isDesktop(
context)
? 18
: 14,
: 13,
),
),
Text(
@ -1508,7 +1584,7 @@ class _empReviewDetailsState extends State<empReviewDetails> {
Responsive.isDesktop(
context)
? 20
: 16,
: 14,
fontWeight: FontWeight.w600,
),
),
@ -2395,7 +2471,8 @@ class _empReviewDetailsState extends State<empReviewDetails> {
'assets/nhance-loader.gif'), // Adjust path to your GIF loader
),
),
if (Responsive.isDesktop(context))
if (Responsive.isDesktop(context) ||
(!Responsive.isDesktop(context) && selfEmpStatus != 'enrolled'))
Align(
alignment: Alignment.bottomCenter,
child: Container(
@ -2406,46 +2483,53 @@ class _empReviewDetailsState extends State<empReviewDetails> {
]),
floatingActionButton: Responsive.isDesktop(context)
? null
: FloatingActionButton(
onPressed: () => Navigator.push(
context,
MaterialPageRoute(builder: (context) => chatbot()),
),
child: Icon(Icons.chat),
),
: selfEmpStatus == 'enrolled'
? FloatingActionButton(
onPressed: () => Navigator.push(
context,
MaterialPageRoute(builder: (context) => chatbot()),
),
child: Icon(Icons.chat),
)
: null,
floatingActionButtonLocation: Responsive.isDesktop(context)
? null
: FloatingActionButtonLocation.miniEndFloat,
: selfEmpStatus == 'enrolled'
? FloatingActionButtonLocation.miniEndFloat
: null,
bottomNavigationBar: Responsive.isDesktop(context)
? null
: CustomBottomNavigationBar(
onTabChanged: (index) {
// Add your navigation logic here
// For example:
if (index == 0) {
Navigator.pushNamed(context, 'home');
} else if (index == 1) {
Navigator.pushNamed(context, 'claims');
} else if (index == 2) {
Navigator.pushNamed(context, 'profile');
} else if (index == 3) {
Navigator.pushNamed(context, 'help');
}
},
icons: [
Icons.home_outlined,
Icons.sticky_note_2_outlined,
Icons.person_outline_outlined,
Icons.headset_mic_outlined,
],
labels: [
"Home",
"Claim",
"Profile",
"Help",
],
initialIndex: 0, // Initial index of the bottom navigation bar
),
: selfEmpStatus == 'enrolled'
? CustomBottomNavigationBar(
onTabChanged: (index) {
// Add your navigation logic here
// For example:
if (index == 0) {
Navigator.pushNamed(context, 'home');
} else if (index == 1) {
Navigator.pushNamed(context, 'claims');
} else if (index == 2) {
Navigator.pushNamed(context, 'profile');
} else if (index == 3) {
Navigator.pushNamed(context, 'help');
}
},
icons: [
Icons.home_outlined,
Icons.sticky_note_2_outlined,
Icons.person_outline_outlined,
Icons.headset_mic_outlined,
],
labels: [
"Home",
"Claim",
"Profile",
"Help",
],
initialIndex:
0, // Initial index of the bottom navigation bar
)
: null,
);
}
}
@ -2510,7 +2594,7 @@ class _empReviewDetailsState extends State<empReviewDetails> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
flex: 8,
flex: 9,
child: Container(
alignment: Alignment.centerLeft,
child: Column(
@ -2525,7 +2609,7 @@ class _empReviewDetailsState extends State<empReviewDetails> {
fontSize:
Responsive.isDesktop(context)
? 18
: 14,
: 13,
),
),
Row(
@ -2537,7 +2621,7 @@ class _empReviewDetailsState extends State<empReviewDetails> {
fontSize:
Responsive.isDesktop(context)
? 20
: 16,
: 14,
fontWeight: FontWeight.w600,
),
),
@ -2573,7 +2657,7 @@ class _empReviewDetailsState extends State<empReviewDetails> {
],
))),
Expanded(
flex: 4,
flex: 3,
child: Container(
alignment: Alignment.centerRight,
child: Column(
@ -2587,7 +2671,7 @@ class _empReviewDetailsState extends State<empReviewDetails> {
fontSize:
Responsive.isDesktop(context)
? 18
: 14,
: 13,
),
),
Text(
@ -2597,7 +2681,7 @@ class _empReviewDetailsState extends State<empReviewDetails> {
fontSize:
Responsive.isDesktop(context)
? 20
: 16,
: 14,
fontWeight: FontWeight.w600,
),
),

View File

@ -0,0 +1,23 @@
import 'package:firebase_core/firebase_core.dart';
const firebaseConfig = {
'apiKey': "AIzaSyAg0e5u7Piy6sWfgKl0C6D2XYyOakGB4wg",
'authDomain': "push-notification-enrollment.firebaseapp.com",
'projectId': "push-notification-enrollment",
'storageBucket': "push-notification-enrollment.appspot.com",
'messagingSenderId': "203846206303",
'appId': "1:203846206303:web:292619fd22c24ff99b6cea",
};
Future<void> initializeFirebase() async {
await Firebase.initializeApp(
options: FirebaseOptions(
apiKey: firebaseConfig['apiKey']!,
authDomain: firebaseConfig['authDomain']!,
projectId: firebaseConfig['projectId']!,
storageBucket: firebaseConfig['storageBucket']!,
messagingSenderId: firebaseConfig['messagingSenderId']!,
appId: firebaseConfig['appId']!,
),
);
}

View File

@ -1,7 +1,9 @@
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:http/http.dart' as http;
import 'package:nhance_app_pwa/pages/verify.dart';
import 'dart:convert';
import 'dart:io';
import 'package:shared_preferences/shared_preferences.dart';
@ -26,6 +28,12 @@ class _loginState extends State<login> {
bool _isCheckingToken = false;
dynamic empMobileNo;
final FirebaseAuth _auth = FirebaseAuth.instance;
late String _verificationId;
int? _resendToken;
bool _isLoading = false;
@override
void initState() {
countryController.text = "+91";
@ -73,8 +81,13 @@ class _loginState extends State<login> {
}
Future<void> verifyMobileNumber() async {
// _verifyPhoneNumber();
// return;
try {
if (_formKey.currentState!.validate()) {
setState(() {
_isLoading = true;
});
// var enteredMobileNumber = countryController.text + mobileController.text;
var enteredMobileNumber = mobileController.text;
final response = await http.post(
@ -93,26 +106,142 @@ class _loginState extends State<login> {
final SharedPreferences prefs =
await SharedPreferences.getInstance();
var enteredMobileNumber = mobileController.text;
var countryCode = countryController.text;
prefs.setString('empMobileNo', enteredMobileNumber);
ToastHelper.showSuccessToast(context, message);
Navigator.pushNamed(context, 'verify',
arguments: enteredMobileNumber);
// await FirebaseAuth.instance.verifyPhoneNumber(
// phoneNumber: '${countryCode + enteredMobileNumber}',
// verificationCompleted: (PhoneAuthCredential credential) {},
// verificationFailed: (FirebaseAuthException e) {},
// codeSent: (String verificationId, int? resendToken) {},
// codeAutoRetrievalTimeout: (String verificationId) {},
//
_verifyPhoneNumber();
// ToastHelper.showSuccessToast(context, message);
// Navigator.pushNamed(context, 'verify',
// arguments: enteredMobileNumber);
} else {
setState(() {
_isLoading = false;
});
ToastHelper.showErrorToast(context, message);
print('Invalid mobile number');
}
} else {
setState(() {
_isLoading = false;
});
ToastHelper.showErrorToast(context, 'Something went wrong');
throw Exception('Failed to verify mobile number');
}
}
} catch (e) {
setState(() {
_isLoading = false;
});
ToastHelper.showErrorToast(context, 'Something went wrong');
print('Error: $e');
}
}
Future<void> _verifyPhoneNumber() async {
var enteredMobileNumber = mobileController.text;
var countryCode = countryController.text;
print('${countryCode + enteredMobileNumber}');
await _auth.verifyPhoneNumber(
phoneNumber: '${countryCode + enteredMobileNumber}',
timeout: const Duration(seconds: 60),
verificationCompleted: (PhoneAuthCredential credential) async {
await _auth.signInWithCredential(credential);
ToastHelper.showSuccessToast(context, 'Verified Successfully!');
setState(() {
_isLoading = false;
});
},
verificationFailed: (FirebaseAuthException e) {
ToastHelper.showSuccessToast(context, 'Verification Failed!');
if (e.code == 'invalid-phone-number') {
print('The provided phone number is not valid.');
}
setState(() {
_isLoading = false;
});
},
codeSent: (String verificationId, int? resendToken) {
setState(() {
_verificationId = verificationId;
_resendToken = resendToken;
});
ToastHelper.showSuccessToast(
context, 'Verification code sent to ${enteredMobileNumber}');
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => MyVerify(
verificationId: _verificationId,
mobileNumber: enteredMobileNumber,
resendToken: _resendToken,
onResendCode: _resendCode, // Pass the phone number
),
),
);
setState(() {
_isLoading = false;
});
},
codeAutoRetrievalTimeout: (String verificationId) {
setState(() {
_verificationId = verificationId;
});
ToastHelper.showSuccessToast(context, 'Code auto-retrieval timed out.');
setState(() {
_isLoading = false;
});
},
);
}
void _resendCode(String mobileNumber, int? resendToken) async {
await _auth.verifyPhoneNumber(
phoneNumber: '${countryController.text + mobileNumber}',
timeout: const Duration(seconds: 60),
forceResendingToken: resendToken,
verificationCompleted: (PhoneAuthCredential credential) async {
await _auth.signInWithCredential(credential);
},
verificationFailed: (FirebaseAuthException e) {
if (e.code == 'invalid-phone-number') {
print('The provided phone number is not valid.');
}
},
codeSent: (String verificationId, int? resendToken) {
setState(() {
_verificationId = verificationId;
_resendToken = resendToken;
});
ToastHelper.showSuccessToast(
context, 'Verification code resent to ${mobileNumber}');
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => MyVerify(
verificationId: _verificationId,
mobileNumber: mobileNumber,
resendToken: _resendToken,
onResendCode: _resendCode,
),
),
);
},
codeAutoRetrievalTimeout: (String verificationId) {
setState(() {
_verificationId = verificationId;
});
},
);
}
@override
Widget build(BuildContext context) {
Size _size = MediaQuery.of(context).size;
@ -414,12 +543,21 @@ class _loginState extends State<login> {
BorderRadius.circular(10),
),
),
onPressed: verifyMobileNumber,
child: Text(
"Login With OTP",
style: GoogleFonts.poppins(
color: Color(0xFFFFFFFF)),
),
onPressed: _isLoading
? null
: verifyMobileNumber,
child: _isLoading
? CircularProgressIndicator(
valueColor:
AlwaysStoppedAnimation<
Color>(
Color(0xFF00989E)),
)
: Text(
"Login With OTP",
style: GoogleFonts.poppins(
color: Color(0xFFFFFFFF)),
),
),
),
),

View File

@ -326,7 +326,7 @@ class _policiesState extends State<policies> {
width:
8), // Adjust space between icon and text
Text(
'File a Claim',
'Initiate a Claim',
style: GoogleFonts.poppins(
fontSize: Responsive.isDesktop(
context)

View File

@ -118,29 +118,6 @@ class ApiService {
return response;
}
Future<Map<String, dynamic>> _makeGetRequest(
Uri url, Map<String, String> headers) async {
final response = await http.get(url, headers: headers);
return _handleResponse(response);
}
Future<Map<String, dynamic>> _makePostRequest(
Uri url, Map<String, String> body, Map<String, String> headers) async {
final response = await http.post(url, headers: headers, body: body);
return _handleResponse(response);
}
Future<Map<String, dynamic>> _handleResponse(http.Response response) async {
if (response.statusCode == 200) {
return jsonDecode(response.body);
} else if (response.statusCode == 401) {
await _clearLocalStorageAndRedirect();
return {};
} else {
throw Exception('Failed to load data');
}
}
Future<void> _clearLocalStorageAndRedirect() async {
final prefs = await SharedPreferences.getInstance();
await prefs.clear();
@ -176,4 +153,27 @@ class ApiService {
final response = await _makeGetRequest(url, headers);
return response;
}
Future<Map<String, dynamic>> _makeGetRequest(
Uri url, Map<String, String> headers) async {
final response = await http.get(url, headers: headers);
return _handleResponse(response);
}
Future<Map<String, dynamic>> _makePostRequest(
Uri url, Map<String, String> body, Map<String, String> headers) async {
final response = await http.post(url, headers: headers, body: body);
return _handleResponse(response);
}
Future<Map<String, dynamic>> _handleResponse(http.Response response) async {
if (response.statusCode == 200) {
return jsonDecode(response.body);
} else if (response.statusCode == 401) {
await _clearLocalStorageAndRedirect();
return {};
} else {
throw Exception('Failed to load data');
}
}
}

View File

@ -0,0 +1,10 @@
@JS()
library recaptcha_helper;
import 'package:js/js.dart';
@JS('grecaptcha.execute')
external void executeRecaptcha(String siteKey, Function(String) callback);
@JS('grecaptcha.ready')
external void grecaptchaReady(Function callback);

View File

@ -1,5 +1,8 @@
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:nhance_app_pwa/pages/postEnrollment/service/api_service.dart';
import 'package:pinput/pinput.dart';
import 'dart:async';
import 'package:flutter/gestures.dart';
@ -16,17 +19,30 @@ import '../models/platform_helper_mobile.dart'
if (dart.library.html) '../models/platform_helper_other.dart';
class MyVerify extends StatefulWidget {
const MyVerify({Key? key}) : super(key: key);
final String verificationId;
final String mobileNumber;
final int? resendToken;
final Function(String, int?) onResendCode;
const MyVerify({
Key? key,
required this.verificationId,
required this.mobileNumber,
required this.resendToken,
required this.onResendCode,
}) : super(key: key);
@override
State<MyVerify> createState() => _MyVerifyState();
}
class _MyVerifyState extends State<MyVerify> {
TextEditingController countryController = TextEditingController();
late ApiService apiService;
TextEditingController _otpController = TextEditingController();
final _formKey = GlobalKey<FormState>();
late Timer _timer;
int _secondsRemaining = 30;
int _secondsRemaining = 60;
bool _isTimerRunning = false;
dynamic empCodeString;
dynamic empClientBranchId;
@ -37,12 +53,29 @@ class _MyVerifyState extends State<MyVerify> {
dynamic clientName;
dynamic clientLogo;
dynamic emp_status;
dynamic fCMToken;
late String verificationId;
late String mobileNumber;
final FirebaseMessaging _firebaseMessaging = FirebaseMessaging.instance;
final FirebaseAuth _auth = FirebaseAuth.instance;
bool _isLoading = false;
late String _verificationId;
@override
void initState() {
super.initState();
countryController.text = "+91";
apiService = ApiService(context);
// checkTokenAvailability();
// Start the timer when the widget is initialized
verificationId = widget.verificationId;
mobileNumber = widget.mobileNumber;
print('Received verificationId: $verificationId');
print('Received mobileNumber: $mobileNumber');
if (verificationId.isEmpty) {
// Handle the case where verificationId is not provided
Navigator.pop(context);
}
startTimer();
}
@ -52,6 +85,52 @@ class _MyVerifyState extends State<MyVerify> {
super.dispose();
}
Future<void> initNotification() async {
await _firebaseMessaging.requestPermission();
fCMToken = await _firebaseMessaging.getToken();
print('Token : $fCMToken');
sendDeviceToken(fCMToken);
FirebaseMessaging.onBackgroundMessage(handleBackgroundMessage);
}
Future<void> handleBackgroundMessage(RemoteMessage message) async {
print('Title ${message.notification?.title}');
print('Body ${message.notification?.body}');
print('Playload ${message.data}');
}
void sendDeviceToken(deviceToken) async {
// Retrieve the passed mobile number value
try {
final response = await http.post(
Uri.parse(Environment.apiUrl + 'storeFireBase'),
body: json
.encode({'mobile': mobileNumber, 'firebase_token': deviceToken}),
headers: {
HttpHeaders.contentTypeHeader: 'application/json',
'Authorization': 'Bearer $_token',
},
);
if (response.statusCode == 200) {
Map<String, dynamic> data = json.decode(response.body);
print('data: $data');
String status = data['status'];
print(status);
if (status == 'success') {
print('Token Store Successfully');
} else {
print('Please try again');
}
} else {
throw Exception('Failed to store');
}
} catch (e) {
print('Error: $e');
}
}
void startTimer() {
_isTimerRunning = true;
_timer = Timer.periodic(Duration(seconds: 1), (Timer timer) {
@ -81,59 +160,68 @@ class _MyVerifyState extends State<MyVerify> {
// }
// }
Future<void> resendOTP(String mobileNumber) async {
print(mobileNumber);
// Update the UI as needed
setState(() {
_secondsRemaining = 30;
_isTimerRunning = true;
});
startTimer();
try {
final response = await http.post(
Uri.parse(Environment.apiUrl + 'verifyEmployeeNumber'),
body: json.encode({'mobile_number': mobileNumber}),
headers: {
HttpHeaders.contentTypeHeader: 'application/json',
},
);
// Future<void> resendOTP(String mobileNumber) async {
// print(mobileNumber);
// // Update the UI as needed
// setState(() {
// _secondsRemaining = 60;
// _isTimerRunning = true;
// });
// startTimer();
// try {
// final response = await http.post(
// Uri.parse(Environment.apiUrl + 'verifyEmployeeNumber'),
// body: json.encode({'mobile_number': mobileNumber}),
// headers: {
// HttpHeaders.contentTypeHeader: 'application/json',
// },
// );
//
// if (response.statusCode == 200) {
// // Handle successful response
// ToastHelper.showSuccessToast(context, 'OTP resent successfully');
// } else {
// // Handle other response status codes
// ToastHelper.showErrorToast(context, 'Failed to resend OTP');
// throw Exception('Failed to resend OTP');
// }
// } catch (e) {
// // Handle API call errors
// print('Error: $e');
// ToastHelper.showErrorToast(
// context, 'Failed to resend OTP. Please try again.');
// }
// }
if (response.statusCode == 200) {
// Handle successful response
ToastHelper.showSuccessToast(context, 'OTP resent successfully');
} else {
// Handle other response status codes
ToastHelper.showErrorToast(context, 'Failed to resend OTP');
throw Exception('Failed to resend OTP');
}
} catch (e) {
// Handle API call errors
print('Error: $e');
ToastHelper.showErrorToast(
context, 'Failed to resend OTP. Please try again.');
}
}
void verifyOTP(String otp) async {
void generateToken(bool otpVerifyStatus) async {
// Retrieve the passed mobile number value
final String mobileNumber =
ModalRoute.of(context)!.settings.arguments as String;
// final String mobileNumber =
// ModalRoute.of(context)!.settings.arguments as String;
try {
final response = await http.post(
Uri.parse(Environment.apiUrl + 'getVerifiedUserData'),
body: json.encode({'mobile_number': mobileNumber, 'otp': otp}),
body: json.encode({
'mobile_number': mobileNumber,
'otp_verification': otpVerifyStatus
}),
headers: {
HttpHeaders.contentTypeHeader: 'application/json',
},
);
if (response.statusCode == 200) {
setState(() {
_isLoading = false;
});
Map<String, dynamic> data = json.decode(response.body);
print('data: $data');
_token = data['data'];
String status = data['status'];
print(status);
if (status == 'success') {
setState(() {
_isLoading = false;
});
final SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setString('token', data['data']);
@ -164,6 +252,7 @@ class _MyVerifyState extends State<MyVerify> {
if (isMobilePlatform()) {
// if (prefs.containsKey('mpin') && mpinText == 'Mpin - exist') {
if (token != null && token.isNotEmpty) {
await initNotification();
Navigator.pushReplacementNamed(context, 'pinSettingPage');
}
// }
@ -178,16 +267,25 @@ class _MyVerifyState extends State<MyVerify> {
}
}
} else {
setState(() {
_isLoading = false;
});
ToastHelper.showErrorToast(context, 'Invalid OTP. Please try again');
// Show a Snackbar if the OTP is invalid
// ToastHelper.showErrorToast(context, 'Invalid OTP. Please try again');
print('Invalid OTP. Please try again');
}
} else {
setState(() {
_isLoading = false;
});
ToastHelper.showWarningToast(context, 'Something went wrong');
throw Exception('Failed to verify OTP');
}
} catch (e) {
setState(() {
_isLoading = false;
});
print('Error: $e');
ToastHelper.showWarningToast(context, 'Something went wrong');
// Show a Snackbar if there's an error while verifying OTP
@ -197,6 +295,50 @@ class _MyVerifyState extends State<MyVerify> {
}
}
void verifyOTP(String otp) async {
try {
setState(() {
_isLoading = true;
});
PhoneAuthCredential credential = PhoneAuthProvider.credential(
verificationId: verificationId,
smsCode: otp,
);
await FirebaseAuth.instance
.signInWithCredential(credential)
.then((user) async {
if (user != null) {
// Handle successful verification
ToastHelper.showSuccessToast(context, 'Successfully Login...!');
bool otpVerifyStatus = true;
generateToken(otpVerifyStatus);
} else {
setState(() {
_isLoading = false;
});
ToastHelper.showErrorToast(context, 'Invalid OTP. Please try again');
}
});
} catch (e) {
setState(() {
_isLoading = false;
});
print('Error: $e');
ToastHelper.showErrorToast(
context, 'Failed to verify OTP. Please try again.');
}
}
void _resendOTP() {
setState(() {
_secondsRemaining = 60;
_isTimerRunning = true;
});
startTimer();
widget.onResendCode(widget.mobileNumber, widget.resendToken);
}
Future<void> getClientLogoAndDetails() async {
var url = Uri.parse(Environment.apiUrl +
'getClientDetails?client_id=$client_id&emp_code=$empCodeString');
@ -247,8 +389,8 @@ class _MyVerifyState extends State<MyVerify> {
@override
Widget build(BuildContext context) {
// Retrieve the passed mobile number value
final String mobileNumber =
ModalRoute.of(context)!.settings.arguments as String;
// final String mobileNumber =
// ModalRoute.of(context)!.settings.arguments as String;
Size _size = MediaQuery.of(context).size;
EdgeInsets marginInsets = EdgeInsets.zero;
if (Responsive.isDesktop(context)) {
@ -524,7 +666,7 @@ class _MyVerifyState extends State<MyVerify> {
)
: InkWell(
onTap: () {
resendOTP(mobileNumber);
_resendOTP();
},
child: Text(
"Resend OTP",

View File

@ -5,6 +5,10 @@
import FlutterMacOS
import Foundation
import firebase_auth
import firebase_core
import firebase_messaging
import google_sign_in_ios
import path_provider_foundation
import shared_preferences_foundation
import smart_auth
@ -13,6 +17,10 @@ import url_launcher_macos
import video_player_avfoundation
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FLTFirebaseAuthPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAuthPlugin"))
FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin"))
FLTFirebaseMessagingPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseMessagingPlugin"))
FLTGoogleSignInPlugin.register(with: registry.registrar(forPlugin: "FLTGoogleSignInPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
SmartAuthPlugin.register(with: registry.registrar(forPlugin: "SmartAuthPlugin"))

View File

@ -57,6 +57,12 @@ dependencies:
path_provider: ^2.1.3
dash_chat_2: ^0.0.21
local_auth: ^2.2.0
firebase_core: ^3.2.0
firebase_messaging: ^15.0.3
firebase_auth: ^5.1.2
google_sign_in: ^6.2.1
js: ^0.7.1
firebase_auth_web: ^5.12.4
dev_dependencies:
flutter_test:

View File

@ -72,6 +72,40 @@
<div id="loading_indicator" class="container overlay">
<img class="indicator" src="assets/nhance-loader.gif">
</div>
<script type="module">
// Import the functions you need from the SDKs you need
import { initializeApp } from "https://www.gstatic.com/firebasejs/10.12.4/firebase-app.js";
// TODO: Add SDKs for Firebase products that you want to use
// https://firebase.google.com/docs/web/setup#available-libraries
// Your web app's Firebase configuration
const firebaseConfig = {
apiKey: "AIzaSyAg0e5u7Piy6sWfgKl0C6D2XYyOakGB4wg",
authDomain: "push-notification-enrollment.firebaseapp.com",
projectId: "push-notification-enrollment",
storageBucket: "push-notification-enrollment.appspot.com",
messagingSenderId: "203846206303",
appId: "1:203846206303:web:292619fd22c24ff99b6cea"
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
</script>
<!-- <script src="https://www.gstatic.com/firebasejs/8.10.0/firebase-app.js"></script>-->
<!-- <script src="https://www.gstatic.com/firebasejs/8.10.0/firebase-auth.js"></script>-->
<!-- <script>-->
<!-- var firebaseConfig = {-->
<!-- apiKey: "AIzaSyAdacw5svpqopDCpoEym7aDkI3F2AajEO4",-->
<!-- authDomain: "push-notification-enrollment.firebaseapp.com",-->
<!-- projectId: "push-notification-enrollment",-->
<!-- storageBucket: "push-notification-enrollment.appspot.com",-->
<!-- messagingSenderId: "203846206303",-->
<!-- appId: "1:203846206303:android:01f39a22f39a50539b6cea"-->
<!-- };-->
<!-- firebase.initializeApp(firebaseConfig);-->
<!-- </script>-->
<script>
window.addEventListener('load', function(ev) {
// Download main.dart.js

View File

@ -6,11 +6,17 @@
#include "generated_plugin_registrant.h"
#include <firebase_auth/firebase_auth_plugin_c_api.h>
#include <firebase_core/firebase_core_plugin_c_api.h>
#include <local_auth_windows/local_auth_plugin.h>
#include <smart_auth/smart_auth_plugin.h>
#include <url_launcher_windows/url_launcher_windows.h>
void RegisterPlugins(flutter::PluginRegistry* registry) {
FirebaseAuthPluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FirebaseAuthPluginCApi"));
FirebaseCorePluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FirebaseCorePluginCApi"));
LocalAuthPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("LocalAuthPlugin"));
SmartAuthPluginRegisterWithRegistrar(

View File

@ -3,6 +3,8 @@
#
list(APPEND FLUTTER_PLUGIN_LIST
firebase_auth
firebase_core
local_auth_windows
smart_auth
url_launcher_windows