From 521bd49a17934c8316627cff40cd940c03667cf7 Mon Sep 17 00:00:00 2001 From: SurendarSuri30 Date: Fri, 14 Nov 2025 15:50:33 +0530 Subject: [PATCH] incomplete wellness and username password --- android/app/build.gradle | 4 +- lib/main.dart | 38 + lib/pages/changePassword.dart | 770 ++++++++++++++++++ lib/pages/email_verify.dart | 42 + lib/pages/enrollment/addons.dart | 24 +- lib/pages/enrollment/empDetails.dart | 26 +- lib/pages/enrollment/empReview.dart | 27 +- lib/pages/postEnrollment/claims.dart | 16 +- lib/pages/postEnrollment/home.dart | 1 + lib/pages/postEnrollment/policies.dart | 2 +- lib/pages/postEnrollment/profile.dart | 49 ++ .../postEnrollment/service/api_service.dart | 2 +- lib/pages/postEnrollment/wellness.dart | 644 +++++++++++---- .../postEnrollment/wellness_web_view.dart | 32 + lib/pages/service/SessionManager.dart | 4 + lib/pages/service/popup_helper.dart | 2 +- lib/pages/setPassword.dart | 695 ++++++++++++++++ pubspec.yaml | 4 +- 18 files changed, 2156 insertions(+), 226 deletions(-) create mode 100644 lib/pages/changePassword.dart create mode 100644 lib/pages/postEnrollment/wellness_web_view.dart create mode 100644 lib/pages/setPassword.dart diff --git a/android/app/build.gradle b/android/app/build.gradle index ea3f6df..07d735e 100755 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -19,12 +19,12 @@ if (project.hasProperty('google-services.json')) { def flutterVersionCode = localProperties.getProperty('flutter.versionCode') if (flutterVersionCode == null) { - flutterVersionCode = '42' + flutterVersionCode = '44' } def flutterVersionName = localProperties.getProperty('flutter.versionName') if (flutterVersionName == null) { - flutterVersionName = '2.0.4' + flutterVersionName = '2.0.6' } def keystoreProperties = new Properties() diff --git a/lib/main.dart b/lib/main.dart index e81643d..7e36671 100755 --- a/lib/main.dart +++ b/lib/main.dart @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:nhance_app_pwa/customAppBar/toastHelper.dart'; +import 'package:nhance_app_pwa/pages/changePassword.dart'; import 'package:nhance_app_pwa/pages/email_verify.dart'; import 'package:nhance_app_pwa/pages/enrollment/addons.dart'; import 'package:nhance_app_pwa/pages/enrollment/empDetails.dart'; @@ -25,12 +26,14 @@ import 'package:nhance_app_pwa/pages/postEnrollment/termsofuse.dart'; import 'package:nhance_app_pwa/pages/postEnrollment/tickets.dart'; import 'package:nhance_app_pwa/pages/postEnrollment/tickettracklist.dart'; import 'package:nhance_app_pwa/pages/postEnrollment/wellness.dart'; +import 'package:nhance_app_pwa/pages/postEnrollment/wellness_web_view.dart'; import 'package:nhance_app_pwa/pages/service/SessionManager.dart'; import 'package:nhance_app_pwa/pages/service/TokenService.dart'; import 'package:nhance_app_pwa/pages/service/data_manager.dart'; import 'package:nhance_app_pwa/pages/session/SetPinBiometric.dart'; import 'package:nhance_app_pwa/pages/session/changePin.dart'; import 'package:nhance_app_pwa/pages/session/settingUpPinAndBiometric.dart'; +import 'package:nhance_app_pwa/pages/setPassword.dart'; import 'package:nhance_app_pwa/pages/verify.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -300,6 +303,41 @@ Future main() async { GoRoute( path: '/empReviewDetails', builder: (context, state) => empReviewDetails()), + GoRoute( + path: '/changePassword', + name: 'changePassword', + builder: (context, state) { + final email = state.uri.queryParameters['email'] ?? ''; + final clientId = state.uri.queryParameters['client_id'] ?? ''; + return changesPassword( + email: email, + client_id: clientId, + ); + }, + ), + GoRoute( + path: '/setPassword', + name: 'setPassword', + builder: (context, state) { + final email = state.uri.queryParameters['email'] ?? ''; + final clientId = state.uri.queryParameters['client_id'] ?? ''; + final route = state.uri.queryParameters['route'] ?? ''; + + return setPassword( + email: email, + client_id: clientId, + route: route, + ); + }, + ), + GoRoute( + path: '/wellnessWebView', + builder: (context, state) { + final url = state.extra as String; // receiving URL + return WellnessWebView(url: url); + }, + ), + ], // ✅ Middleware hook diff --git a/lib/pages/changePassword.dart b/lib/pages/changePassword.dart new file mode 100644 index 0000000..b211920 --- /dev/null +++ b/lib/pages/changePassword.dart @@ -0,0 +1,770 @@ +import 'dart:convert'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:go_router/go_router.dart'; +import 'package:http/http.dart' as http; +import 'package:nhance_app_pwa/pages/service/SessionManager.dart'; +import 'dart:io'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import '../customAppBar/responsive.dart'; +import '../customAppBar/toastHelper.dart'; +import '../models/environment.dart'; + +class changesPassword extends StatefulWidget { + final String email; + final String client_id; + const changesPassword({ + super.key, + required this.email, + required this.client_id, + }); + + @override + State createState() => _changesPasswordState(); +} + +class _changesPasswordState extends State { + final TextEditingController oldPasswordController = TextEditingController(); + final TextEditingController newPasswordController = TextEditingController(); + final TextEditingController confirmPasswordController = TextEditingController(); + final _formKey = GlobalKey(); + dynamic _preToken; + dynamic _postToken; + dynamic clientName; + dynamic clientLogo; + bool _isLoading = false; + bool _obscureOldPassword = true; + bool _obscureNewPassword = true; + bool _obscureConfirmPassword = true; + late SessionManager session; + + @override + void initState() { + super.initState(); + } + + + Future resetYourPassword() async { + final oldpassword = oldPasswordController.text.trim(); + final newPassword = newPasswordController.text.trim(); + final confirmPassword = confirmPasswordController.text.trim(); + try { + if (_formKey.currentState!.validate()) { + if (confirmPassword != newPassword) { + ToastHelper.showErrorToast(context, 'Passwords do not match'); + return; + } + setState(() { + _isLoading = true; + }); + + // Determine the API and the payload based on the visible field + String apiEndpoint = Environment.apiUrlEnrollment + 'changePassword'; + Map payload = { + 'email_id': widget.email, + 'client_id': widget.client_id, + 'old_password': oldpassword, + 'new_password': newPassword, + 'confirm_password': confirmPassword + }; + + // var enteredMobileNumber = mobileController.text; + final response = await http.post( + Uri.parse(apiEndpoint), + body: json.encode(payload), + headers: { + HttpHeaders.contentTypeHeader: 'application/json', + }, + ); + + if (response.statusCode == 200) { + Map data = json.decode(response.body); + String? statusVerification = data['status']; + String? message = data['message']; + if (statusVerification == 'success') { + final SharedPreferences prefs = await SharedPreferences + .getInstance(); + await SessionManager().clear(); + await prefs.clear(); + setState(() { + _isLoading = false; + }); + ToastHelper.showSuccessToast(context, message!); + context.go('/login'); + } 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'); + } + + // 🔹 Password validation + // if (password.isEmpty) { + // ToastHelper.showErrorToast(context, 'Please enter your password'); + // return; + // } + // if (password.length < 6) { + // ToastHelper.showErrorToast(context, 'Password must be at least 6 characters'); + // return; + // } + // if (!RegExp(r'^(?=.*[A-Z])(?=.*[0-9]).{6,}$').hasMatch(password)) { + // ToastHelper.showErrorToast(context, 'Include at least 1 uppercase letter and 1 number'); + // return; + // } + // + // // 🔹 Confirm password validation + // if (confirmPassword.isEmpty) { + // ToastHelper.showErrorToast(context, 'Please confirm your password'); + // return; + // } + } + + //Ends Login with UserName and Password + + @override + Widget build(BuildContext context) { + Size _size = MediaQuery.of(context).size; + EdgeInsets marginInsets = EdgeInsets.zero; + + // const focusedBorderColor = Colors.white; + // const fillColor = Color.fromRGBO(243, 246, 249, 0); + // const borderColor = Color.fromRGBO(23, 171, 144, 0.4); + + if (Responsive.isDesktop(context)) { + marginInsets = const EdgeInsets.only( + left: 0, + right: 0, + bottom: 0, + top: 0, + ); + } else if (Responsive.isMobile(context)) { + marginInsets = const EdgeInsets.only( + left: 25, // Example value for mobile + right: 25, // Example value for mobile + bottom: 0, // Example value for mobile + top: 0, // Example value for mobile + ); + } else if (Responsive.isTablet(context)) { + marginInsets = const EdgeInsets.only( + left: 25, //// Example value for mobile + right: 25, // Example value for mobile + bottom: 0, // Example value for mobile + top: 0, // Example value for mobile + ); + } + return WillPopScope( + onWillPop: () async { + // Close the app on mobile back button press + exit(0); // This will exit the app + return false; // Return false to prevent any other actions + }, + child: Scaffold( + body: SingleChildScrollView( + keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag, + child: Container( + height: _size.height, + color: Colors.white, + child: Stack( + children: [ + // Visibility( + // visible: _size.width <= 1100, + // child: ClipRRect( + // borderRadius: BorderRadius.only( + // bottomLeft: Radius.circular(30), + // bottomRight: Radius.circular(30), + // ), + // child: Container( + // height: _size.height / 3, + // width: double.infinity, + // color: Color(0xFFFFFCE5), + // child: Stack( + // children: [ + // Column( + // children: [ + // SizedBox(height: _size.height / 6.4), + // Row( + // mainAxisAlignment: MainAxisAlignment + // .center, // Align to the center + // children: [ + // Expanded( + // flex: Responsive.isDesktop(context) + // ? 10 + // : 12, + // child: Align( + // alignment: + // Responsive.isDesktop(context) + // ? Alignment.centerLeft + // : Alignment.bottomCenter, + // child: Image.asset( + // 'assets/nhance_app_logo.png', + // width: 150, + // height: 100, + // )), + // ), + // if (!Responsive.isMobile(context) && + // !Responsive.isTablet(context)) + // Expanded( + // flex: 2, + // child: MouseRegion( + // cursor: SystemMouseCursors.click, + // child: GestureDetector( + // onTap: () { + // // Add your navigation logic here + // // For example, you can use Navigator.push to navigate to another page + // Navigator.pushNamed( + // context, 'hrLogin'); + // }, + // child: Row( + // mainAxisAlignment: MainAxisAlignment + // .end, // Align to the end (right) + // children: [ + // Text( + // 'HR Login', + // style: TextStyle( + // color: Color( + // 0xFF000000), // Text color + // // Add other text styles as needed + // ), + // ), + // SizedBox(width: 5), + // Icon( + // Icons + // .east, // Icon for customer login + // color: Colors + // .black, // Adjust color as needed + // ), + // ], + // ), + // ), + // ), + // ), + // ], + // ), + // ], + // ), + // ], + // ), + // ), + // ), + // ), + Container( + margin: marginInsets, + alignment: Alignment.bottomCenter, + child: SingleChildScrollView( + child: Form( + key: _formKey, + child: Column( + children: [ + Row( + children: [ + Expanded( + flex: _size.width < 1100 ? 6 : 12, + child: Container( + margin: _size.width > 1100 + ? EdgeInsets.only(left: 20, right: 20) + : EdgeInsets.only(left: 0, right: 0), + child: Column( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + if (!Responsive.isMobile(context) && + !Responsive.isTablet(context)) + Row( + children: [ + InkWell( + onTap: () { + context.go('/home'); + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + // if (!Responsive.isDesktop(context)) + Icon( + Icons.chevron_left, + color: Color(0xFF000000), + size: 30, + ), + SizedBox( + width: Responsive.isDesktop(context) + ? 0 + : 5), + ], + ), + ), + Expanded( + flex: 12, + child: Align( + alignment: Alignment + .topLeft, // ✅ Always top-left + child: _size.width <= 1100 + ? Image.asset( + 'assets/nhance_app_logo.png', + width: 150, + height: 150, + ) + : _size.width > 1100 + ? Image.asset( + 'assets/nhance_app_logo.png', + width: 150, + height: 150, + ) + : Image.asset( + 'assets/nhance_app_logo.png', + width: 150, + height: 150, + ), + ), + ), + ], + ), + SizedBox( + height: Responsive.isDesktop(context) + ? _size.height * 0.1 + : 10, + ), + SizedBox(height: 10), + Container( + margin: Responsive.isDesktop(context) + ? EdgeInsets.symmetric( + horizontal: 150) + : EdgeInsets.symmetric( + horizontal: 0), + child: Row( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Text( + "Welcome to Nhance", + style: GoogleFonts.poppins( + fontSize: 16, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ), + SizedBox( + height: 10, + ), + Container( + margin: Responsive.isDesktop(context) + ? EdgeInsets.symmetric( + horizontal: 150) + : EdgeInsets.symmetric( + horizontal: 0), + child: Row( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Expanded( + child: Text( + "Login with your to review and enroll for exciting health benefits for you and your family", + style: GoogleFonts.poppins( + fontSize: 12, + color: Color(0xFF000000)), + textAlign: TextAlign.center, + ), + ) + ], + ), + ), + SizedBox( + height: 20, + ), + + Column( + children: [ + // 🔹 Password Field + Container( + height: 55, + margin: Responsive.isDesktop( + context) + ? const EdgeInsets + .symmetric( + horizontal: 150) + : const EdgeInsets + .symmetric( + horizontal: 0), + decoration: BoxDecoration( + border: Border.all( + width: 1, + color: Colors.grey), + borderRadius: + BorderRadius.circular( + 10), + ), + child: TextFormField( + controller: + oldPasswordController, + obscureText: + _obscureOldPassword, + textAlignVertical: + TextAlignVertical + .center, + decoration: InputDecoration( + border: InputBorder.none, + hintText: + "Old Password", + contentPadding: + const EdgeInsets + .symmetric( + horizontal: 10), + suffixIcon: IconButton( + icon: Icon( + _obscureOldPassword + ? Icons + .visibility_off + : Icons + .visibility, + color: Colors.grey, + ), + onPressed: () { + setState(() { + _obscureOldPassword = + !_obscureOldPassword; + }); + }, + ), + ), + validator: (value) { + if (value == null || + value.isEmpty) { + return 'Please enter your old password'; + } + if (value.length < 6) { + return 'Password must be at least 6 characters'; + } + if (!RegExp( + r'^(?=.*[A-Z])(?=.*[0-9]).{6,}$') + .hasMatch(value)) { + return 'Include at least 1 uppercase letter and 1 number'; + } + return null; + }, + ), + ), + const SizedBox(height: 10), + Container( + height: 55, + margin: Responsive.isDesktop( + context) + ? const EdgeInsets + .symmetric( + horizontal: 150) + : const EdgeInsets + .symmetric( + horizontal: 0), + decoration: BoxDecoration( + border: Border.all( + width: 1, + color: Colors.grey), + borderRadius: + BorderRadius.circular( + 10), + ), + child: TextFormField( + controller: + newPasswordController, + obscureText: + _obscureNewPassword, + textAlignVertical: + TextAlignVertical + .center, + decoration: InputDecoration( + border: InputBorder.none, + hintText: + "New Password", + contentPadding: + const EdgeInsets + .symmetric( + horizontal: 10), + suffixIcon: IconButton( + icon: Icon( + _obscureNewPassword + ? Icons + .visibility_off + : Icons + .visibility, + color: Colors.grey, + ), + onPressed: () { + setState(() { + _obscureNewPassword = + !_obscureNewPassword; + }); + }, + ), + ), + validator: (value) { + if (value == null || + value.isEmpty) { + return 'Please enter your new password'; + } + if (value.length < 6) { + return 'Password must be at least 6 characters'; + } + if (!RegExp( + r'^(?=.*[A-Z])(?=.*[0-9]).{6,}$') + .hasMatch(value)) { + return 'Include at least 1 uppercase letter and 1 number'; + } + return null; + }, + ), + ), + const SizedBox(height: 10), + Container( + height: 55, + margin: Responsive.isDesktop( + context) + ? const EdgeInsets + .symmetric( + horizontal: 150) + : const EdgeInsets + .symmetric( + horizontal: 0), + decoration: BoxDecoration( + border: Border.all( + width: 1, + color: Colors.grey), + borderRadius: + BorderRadius.circular( + 10), + ), + child: TextFormField( + controller: + confirmPasswordController, + obscureText: + _obscureConfirmPassword, + textAlignVertical: + TextAlignVertical + .center, + decoration: InputDecoration( + border: InputBorder.none, + hintText: + "Confirm Password", + contentPadding: + const EdgeInsets + .symmetric( + horizontal: 10), + suffixIcon: IconButton( + icon: Icon( + _obscureConfirmPassword + ? Icons + .visibility_off + : Icons + .visibility, + color: Colors.grey, + ), + onPressed: () { + setState(() { + _obscureConfirmPassword = + !_obscureConfirmPassword; + }); + }, + ), + ), + validator: (value) { + if (value == null || + value.isEmpty) { + return 'Please confirm your password'; + } + if (value != + newPasswordController + .text) { + return 'Passwords do not match'; + } + return null; + }, + ), + ), + ], + ), + SizedBox(height: 15), + Container( + margin: + Responsive.isDesktop(context) + ? EdgeInsets.symmetric( + horizontal: 150) + : EdgeInsets.symmetric( + horizontal: 0), + child: SizedBox( + width: double.infinity, + height: 40, + child: ElevatedButton( + style: + ElevatedButton.styleFrom( + backgroundColor: + Color(0xFF00989E), + shape: + RoundedRectangleBorder( + borderRadius: + BorderRadius.circular( + 10), + ), + ), + onPressed: _isLoading + ? null + : resetYourPassword, + + child: _isLoading + ? CircularProgressIndicator( + valueColor: + AlwaysStoppedAnimation< + Color>( + Color(0xFF00989E), + ), + ) + : Text( + "Reset Password", + style: GoogleFonts + .poppins( + color: Color( + 0xFFFFFFFF), + ), + ), + ), + ), + ), + + SizedBox( + height: Responsive.isDesktop(context) + ? _size.height * 0.3 + : _size.height * 0.2, + ), + // SizedBox( + // height: _size.height * 0.1, + // ), + Container( + alignment: Alignment.bottomCenter, + padding: + EdgeInsets.symmetric(vertical: 8), + child: RichText( + textAlign: TextAlign.center, + text: TextSpan( + text: + 'By continuing, you agree with our ', + style: GoogleFonts.poppins( + color: Colors.black, + fontSize: 9, + ), + children: [ + WidgetSpan( + child: MouseRegion( + cursor: SystemMouseCursors + .click, + child: GestureDetector( + onTap: () { + context.go( + '/privacypolicy'); + // Navigator.pushNamed( + // context, + // 'privacypolicy'); + }, + child: Text( + 'privacy policy ', + style: + GoogleFonts.poppins( + color: + Color(0xFF00989E), + fontSize: 9, + decoration: + TextDecoration + .underline, + ), + ), + ), + ), + ), + TextSpan( + text: 'and ', + style: GoogleFonts.poppins( + color: Colors.black, + fontSize: 9, + ), + ), + WidgetSpan( + child: MouseRegion( + cursor: SystemMouseCursors + .click, + child: GestureDetector( + onTap: () { + context + .go('/termsofuse'); + // Navigator.pushNamed( + // context, + // 'termsofuse'); + }, + child: Text( + 'terms of use', + style: + GoogleFonts.poppins( + color: + Color(0xFF00989E), + fontSize: 9, + decoration: + TextDecoration + .underline, + ), + ), + ), + ), + ), + ], + ), + ), + ), + ], + ), + ), + ), + if (_size.width > 1100) + Expanded( + flex: _size.width < 1100 ? 6 : 12, + child: LayoutBuilder( + builder: (BuildContext context, + BoxConstraints constraints) { + if (constraints.maxWidth > 600) { + return Image.asset( + 'assets/login_web.jpg', + height: _size.height, + fit: BoxFit.cover, + ); + } else { + return SizedBox(); + } + }, + ), + ), + ], + ), + ], + ), + ), + ), + ), + ], + )), + ))); + } +} diff --git a/lib/pages/email_verify.dart b/lib/pages/email_verify.dart index 4f4107b..01ed784 100755 --- a/lib/pages/email_verify.dart +++ b/lib/pages/email_verify.dart @@ -442,6 +442,7 @@ class _MyEmailVerifyState extends State { // final SharedPreferences prefs = await SharedPreferences.getInstance(); // prefs.setString('empEmailid', widget.email); ToastHelper.showSuccessToast(context, 'Successfully Login'); + // checkPassword(context,session.empEmailCorporate,session.client_id,'home'); // if (emp_status == 'enrolled' || emp_status == 'active') { context.go('/home'); // Navigator.pushReplacementNamed(context, 'home'); @@ -498,6 +499,7 @@ class _MyEmailVerifyState extends State { } else { if (_preToken != null && _preToken.isNotEmpty) { ToastHelper.showSuccessToast(context, 'Successfully Login'); + // checkPassword(context,session.enrollmentEmailCorporate,session.enrollmentClient_id,'empDetails'); // if (emp_status == 'enrolled' || emp_status == 'active') { // Navigator.pushReplacementNamed(context, 'home'); // } else { @@ -646,6 +648,46 @@ class _MyEmailVerifyState extends State { } } + Future checkPassword(BuildContext context,email_id,client_id,route) async { + print('checkLoginPin'); + try { + final params = {'email_id': email_id,'client_id':client_id}; + + print('params $params'); + + final response = await http.post( + Uri.parse(Environment.apiUrlEnrollment + 'checkPassword'), + body: json.encode(params), + headers: { + HttpHeaders.contentTypeHeader: 'application/json', + }, + ); + + if (response.statusCode == 200) { + Map data = json.decode(response.body); + if(data['status'] == 'success') { + context.go('/${route}'); + } else if(data['status'] == 'failed'){ + print('setPassword'); + context.goNamed( + 'setPassword', + queryParameters: { + 'email': email_id, + 'client_id': client_id, + 'route': route, + }, + ); + } + } else { + ToastHelper.showErrorToast(context, 'Something went wrong'); + throw Exception('Failed to verify pin number'); + } + } catch (e) { + ToastHelper.showErrorToast(context, 'Something went wrong'); + print('Error: $e'); + } + } + Future getClientLogoAndDetails() async { var url = Uri.parse(Environment.apiUrlEnrollment + 'getClientDetails?post_client_id=${session.client_id}&post_branch_id=${session.empClientBranchId}&pre_client_id=${session.enrollmentClient_id}&pre_branch_id=${session.enrollmentEmpClientBranchId}'); diff --git a/lib/pages/enrollment/addons.dart b/lib/pages/enrollment/addons.dart index 42e8674..b5c074d 100755 --- a/lib/pages/enrollment/addons.dart +++ b/lib/pages/enrollment/addons.dart @@ -190,9 +190,11 @@ class _addOnsDetailsState extends State { } Future getTokenStatus() async { - // final SharedPreferences prefs = await SharedPreferences.getInstance(); - setState(() async { - isTokenAvailable = (await TokenService.getPostToken())?.isNotEmpty ?? false; + final token = await TokenService.getPostToken(); + + setState(() { + isTokenAvailable = token != null && token.isNotEmpty; + print('isTokenAvailable $isTokenAvailable'); }); } @@ -1674,6 +1676,7 @@ class _addOnsDetailsState extends State { for (var floater in addOnsDependentMappedFamilyFloatersDependent) { bool isValueExist = floater['is_value_exist']; Map floaterData = floater['data']; + final dobDate = floaterData['dob'] ?? ''; if (isValueExist) { familyFloaterContainers.add( @@ -1736,7 +1739,7 @@ class _addOnsDetailsState extends State { ), ), Text( - '${floaterData['relationship']} - ${floaterData['dob']}', + '${floaterData['relationship']} - ${dobDate}', textAlign: TextAlign.left, style: GoogleFonts.poppins( fontSize: @@ -3054,8 +3057,7 @@ class _addOnsDetailsState extends State { .map((item) { Map data = item['data']; - String formattedDate = - formatDate(data['dob']); + String formattedDate = data['dob'] ?? ''; return Row( crossAxisAlignment: CrossAxisAlignment @@ -3691,8 +3693,7 @@ class _addOnsDetailsState extends State { .map((item) { Map data = item['data']; - String formattedDate = - formatDate(data['dob']); + String formattedDate = data['dob'] ?? ''; return Row( crossAxisAlignment: CrossAxisAlignment @@ -4927,6 +4928,7 @@ class _addOnsDetailsState extends State { gmcIsValueValid = (gmcSiPremiumValue != 0 && gmcGstValue != 0); // gmcSumInsured = item['Policy_Terms']['sum_insured']; gmcMappedFamilyFloaters = item['mapped_family_floaters']; + print('gmcMappedFamilyFloaters checking $gmcMappedFamilyFloaters'); dynamic getTrueObjects = gmcMappedFamilyFloaters .where((element) => element['is_value_exist'] == true) .toList(); @@ -5067,7 +5069,7 @@ class _addOnsDetailsState extends State { .where((item) => item['is_value_exist'] == true) .map((item) { Map data = item['data']; - String formattedDate = formatDate(data['dob']); + String formattedDate = data['dob'] ?? ''; return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -5361,12 +5363,12 @@ class _addOnsDetailsState extends State { for (var floater in gpaMappedFamilyFloaters) { bool isValueExist = floater['is_value_exist']; Map floaterData = floater['data']; + final dobDate = floaterData['dob'] ?? ''; gpaSelfDetails = floaterData['name'] + ' ~ ' + floaterData['relationship'] + ' ~ ' + - ' DOB : ' + - formatDate(floaterData['dob']); + ' DOB : ' + dobDate; if (isValueExist) { familyFloaterContainers.add( diff --git a/lib/pages/enrollment/empDetails.dart b/lib/pages/enrollment/empDetails.dart index cc00340..fb186da 100755 --- a/lib/pages/enrollment/empDetails.dart +++ b/lib/pages/enrollment/empDetails.dart @@ -131,11 +131,20 @@ class _empDetailsState extends State { super.dispose(); } + // Future getTokenStatus() async { + // final SharedPreferences prefs = await SharedPreferences.getInstance(); + // setState(() async { + // isTokenAvailable = + // (await TokenService.getPostToken())?.isNotEmpty ?? false; + // print('isTokenAvailable $isTokenAvailable'); + // }); + // } + Future getTokenStatus() async { - // final SharedPreferences prefs = await SharedPreferences.getInstance(); - setState(() async { - isTokenAvailable = - (await TokenService.getPostToken())?.isNotEmpty ?? false; + final token = await TokenService.getPostToken(); + + setState(() { + isTokenAvailable = token != null && token.isNotEmpty; print('isTokenAvailable $isTokenAvailable'); }); } @@ -856,6 +865,7 @@ class _empDetailsState extends State { right: 10), // Add padding to the container child: Row( children: [ + if(isTokenAvailable) InkWell( onTap: () { context.go('/home'); @@ -1147,7 +1157,7 @@ class _empDetailsState extends State { // Set values to all fields _relationShipController.text = floaterData['relationship'] ?? ''; _memberNameController.text = floaterData['name'] ?? ''; - _dobController.text = formatDate(floaterData['dob']) ?? ''; + _dobController.text = floaterData['dob'] ?? ''; // Add more fields as needed } @@ -1809,6 +1819,7 @@ class _empDetailsState extends State { for (var floater in gpaMappedFamilyFloaters) { bool isValueExist = floater['is_value_exist']; Map floaterData = floater['data']; + final dobDate = floaterData['dob'] ?? ''; if (isValueExist) { familyFloaterContainers.add(Container( @@ -1868,7 +1879,7 @@ class _empDetailsState extends State { ), ), Text( - '${floaterData['relationship']} - ${formatDate(floaterData['dob'])}' ?? + '${floaterData['relationship']} - ${dobDate}' ?? 'NA', textAlign: TextAlign.left, style: GoogleFonts.poppins( @@ -2308,6 +2319,7 @@ class _empDetailsState extends State { for (var floater in gmcMappedFamilyFloaters) { bool isValueExist = floater['is_value_exist']; Map floaterData = floater['data']; + final dobDate = floaterData['dob'] ?? ''; if (isValueExist) { familyFloaterContainers.add( @@ -2369,7 +2381,7 @@ class _empDetailsState extends State { ), ), Text( - '${floaterData['relationship']} - ${formatDate(floaterData['dob'])}', + '${floaterData['relationship']} - ${dobDate}', textAlign: TextAlign.left, style: GoogleFonts.poppins( fontSize: Responsive.isDesktop(context) ? 18 : 16, diff --git a/lib/pages/enrollment/empReview.dart b/lib/pages/enrollment/empReview.dart index 5bff0ff..89aee41 100755 --- a/lib/pages/enrollment/empReview.dart +++ b/lib/pages/enrollment/empReview.dart @@ -190,10 +190,11 @@ class _empReviewDetailsState extends State { } Future getTokenStatus() async { - // final SharedPreferences prefs = await SharedPreferences.getInstance(); - setState(() async { - isTokenAvailable = - (await TokenService.getPostToken())?.isNotEmpty ?? false; + final token = await TokenService.getPostToken(); + + setState(() { + isTokenAvailable = token != null && token.isNotEmpty; + print('isTokenAvailable $isTokenAvailable'); }); } @@ -1986,8 +1987,8 @@ class _empReviewDetailsState extends State { item['is_value_exist'] == true) .map((item) { - Map data = - item['data']; + Map data = item['data']; + final dobDate = data['dob'] ?? ''; return Row( crossAxisAlignment: CrossAxisAlignment.start, @@ -2002,7 +2003,7 @@ class _empReviewDetailsState extends State { : 5), // Space between icon and text Expanded( child: Text( - '${data['name']} - ${data['relationship']} - ${data['dob']}', + '${data['name']} - ${data['relationship']} - ${dobDate}', style: GoogleFonts.poppins( fontSize: Responsive.isDesktop( @@ -2245,8 +2246,7 @@ class _empReviewDetailsState extends State { .map((item) { Map data = item['data']; - String formattedDate = - formatDate(data['dob']); + String formattedDate = data['dob'] ?? ''; return Row( crossAxisAlignment: CrossAxisAlignment.start, @@ -2513,8 +2513,7 @@ class _empReviewDetailsState extends State { .map((item) { Map data = item['data']; - String formattedDate = - formatDate(data['dob']); + String formattedDate = data['dob'] ?? ''; return Row( crossAxisAlignment: CrossAxisAlignment.start, @@ -3427,12 +3426,12 @@ class _empReviewDetailsState extends State { for (var floater in gpaMappedFamilyFloaters) { bool isValueExist = floater['is_value_exist']; Map floaterData = floater['data']; + final dobDate = floaterData['dob'] ?? ''; gpaSelfDetails = floaterData['name'] + ' ~ ' + floaterData['relationship'] + ' ~ ' + - ' DOB : ' + - formatDate(floaterData['dob']); + ' DOB : ' + dobDate; if (isValueExist) { familyFloaterContainers.add( @@ -3980,7 +3979,7 @@ class _empReviewDetailsState extends State { .where((item) => item['is_value_exist'] == true) .map((item) { Map data = item['data']; - String formattedDate = formatDate(data['dob']); + String formattedDate = data['dob'] ?? ''; return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ diff --git a/lib/pages/postEnrollment/claims.dart b/lib/pages/postEnrollment/claims.dart index 21ee7df..04b26cf 100755 --- a/lib/pages/postEnrollment/claims.dart +++ b/lib/pages/postEnrollment/claims.dart @@ -961,14 +961,14 @@ class _claimsState extends State { print(claimsDepartmentName); final Map statusColors = { - 'Received': Colors.amber, - 'Rejected': Colors.red, - 'Cancelled': Colors.red, - 'Returned': Colors.deepOrange, - 'Closed': Colors.grey, - 'Approved': Colors.green, - 'Settled': Colors.lightBlueAccent, - 'Under Process': Colors.brown, + 'Received': Colors.blueGrey, // New / Received + 'Under Process': Colors.orangeAccent, // Work in progress + 'Approved': Colors.green, // Approved + 'Settled': Colors.teal, // Completed successfully + 'Returned': Colors.deepOrange, // Sent back for correction + 'Rejected': Colors.red, // Rejected + 'Cancelled': Colors.redAccent, // Cancelled + 'Closed': Colors.grey, // Closed }; // Determine the color based on the claimStatus diff --git a/lib/pages/postEnrollment/home.dart b/lib/pages/postEnrollment/home.dart index c4b6421..b591ede 100755 --- a/lib/pages/postEnrollment/home.dart +++ b/lib/pages/postEnrollment/home.dart @@ -1009,6 +1009,7 @@ class _HomeState extends State { } else if (index == 3) { context.push('/help'); } else if (index == 4) { + // context.push('/wellness'); // Wellness tab clicked → show popup PopupHelper.showRedirectPopup( context: context, diff --git a/lib/pages/postEnrollment/policies.dart b/lib/pages/postEnrollment/policies.dart index fb271de..daa1c7b 100755 --- a/lib/pages/postEnrollment/policies.dart +++ b/lib/pages/postEnrollment/policies.dart @@ -385,7 +385,7 @@ class _policiesState extends State { width: 8), // Adjust space between icon and text Text( - 'Initiate a Claims', + 'Initiate a Claim', style: GoogleFonts.poppins( fontSize: Responsive.isDesktop( context) diff --git a/lib/pages/postEnrollment/profile.dart b/lib/pages/postEnrollment/profile.dart index 1bdc63a..e421c11 100755 --- a/lib/pages/postEnrollment/profile.dart +++ b/lib/pages/postEnrollment/profile.dart @@ -786,6 +786,13 @@ class _profileState extends State { crossAxisAlignment: CrossAxisAlignment.end, mainAxisSize: MainAxisSize.min, children: [ + // ✅ Change Password Button + // if(Responsive.isDesktop(context)) + // _buildChangePasswordButton(context), + + // const SizedBox(width: 10), + + // ✅ Logout Button Responsive.isDesktop(context) ? _buildLogoutButton(context) : Expanded( @@ -909,6 +916,48 @@ class _profileState extends State { )); } + Widget _buildChangePasswordButton(BuildContext context) { + return Container( + alignment: Alignment.center, + child: ElevatedButton( + onPressed: () { + // 👉 Navigate to Change Password Page using GoRouter + final email = selfEmailCorporate ?? ''; // get from your session or state + final clientId = client_id ?? ''; // set actual value here + + context.goNamed( + 'changePassword', + queryParameters: { + 'email': email, + 'client_id': clientId, + }, + ); + }, + style: ElevatedButton.styleFrom( + backgroundColor: const Color(0xFFE26728), // Orange button + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5), + ), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Icon(Icons.lock_open, color: Colors.white), + const SizedBox(width: 8), + Text( + 'Change Password', + style: GoogleFonts.poppins( + color: Colors.white, + fontWeight: FontWeight.w500, + ), + ), + ], + ), + ), + ); + } + + Widget _buildLogoutButton(BuildContext context) { return Container( alignment: Alignment.center, diff --git a/lib/pages/postEnrollment/service/api_service.dart b/lib/pages/postEnrollment/service/api_service.dart index 81299ba..718d372 100755 --- a/lib/pages/postEnrollment/service/api_service.dart +++ b/lib/pages/postEnrollment/service/api_service.dart @@ -140,7 +140,7 @@ class ApiService { return response; } - Future> getWellnessLink(empPrimaryId) async { + Future> getWellnessLink(empPrimaryId,client_policy_id) async { print(_postToken); if (_postToken == null) { await _initializeToken(); diff --git a/lib/pages/postEnrollment/wellness.dart b/lib/pages/postEnrollment/wellness.dart index 1720edb..ab35263 100755 --- a/lib/pages/postEnrollment/wellness.dart +++ b/lib/pages/postEnrollment/wellness.dart @@ -3,6 +3,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import 'package:go_router/go_router.dart'; import 'package:google_fonts/google_fonts.dart'; +import 'package:intl/intl.dart'; +import 'package:jwt_decode/jwt_decode.dart'; import 'package:nhance_app_pwa/customAppBar/customAppBar.dart'; import 'package:nhance_app_pwa/pages/postEnrollment/service/api_service.dart'; import 'package:nhance_app_pwa/pages/postEnrollment/service/svg_service.dart'; @@ -13,6 +15,8 @@ import '../../customAppBar/customFooter.dart'; import '../../customAppBar/responsive.dart'; import '../../customAppBar/tabs.dart'; import '../../customAppBar/toastHelper.dart'; +import '../service/SessionManager.dart'; +import '../service/TokenService.dart'; class wellness extends StatefulWidget { const wellness({Key? key}) : super(key: key); @@ -23,14 +27,25 @@ class wellness extends StatefulWidget { class _wellnessState extends State { late ApiService apiService; + bool isLoadingGif = false; dynamic wellnessURL; dynamic wellnessMessage; + dynamic empCodeString; + dynamic empName; + dynamic empPrimaryId; + dynamic client_id; + dynamic client_branch_id; + dynamic mobileNo; + dynamic policyList; + dynamic employeeDetailsList; + final session = SessionManager(); @override void initState() { super.initState(); apiService = ApiService(context); - getWellnessLink(); + // getWellnessLink(); + _loadToken(); } @override @@ -38,28 +53,165 @@ class _wellnessState extends State { super.dispose(); } + Future _loadToken() async { + print('_loadToken'); + final String? token = await TokenService.getPostToken(); + if (token != null && token.isNotEmpty) { + // Decode the JWT token received from the API response + Map? decodedToken = Jwt.parseJwt(token); + print(decodedToken); + mobileNo = session.mobileNo; + client_branch_id = session.empClientBranchId; + empCodeString = session.empCodeString; + empName = session.gpaEmpName; + print(empCodeString); // Check if emp_code is correct + empPrimaryId = session.empPrimaryId; + client_id = session.client_id; + print(client_id); + // getAdvertisementSliderImage(); + getActiveAndInactivePolicyDetails('Active'); + } + } - Future getWellnessLink() async { - final SharedPreferences prefs = await SharedPreferences.getInstance(); - final String? empPrimaryId = prefs.getString('empPrimaryId'); + Future getActiveAndInactivePolicyDetails(String status) async { + print(getActiveAndInactivePolicyDetails); + if (client_id == null || empCodeString == null) { + return; + } + setState(() { + isLoadingGif = true; + }); + print('check 1'); + final response = await apiService.getActiveAndInactivePolicyDetails( + client_id!, empCodeString!, status, client_branch_id, mobileNo); + print('check 1'); + if (response['status'] == 'success') { + policyList = response['data']; + print('policyList $policyList'); - final response = await apiService.getWellnessLink(empPrimaryId); + // ------------------------------------------- + // 1️⃣ CHECK FOR GMC OR GMC-PARENT + // ------------------------------------------- + final gmcPolicies = policyList.where((item) { + final type = (item['policy_type'] ?? '').toString(); + return type == 'GMC' || type == 'GMC - Parents'; + }).toList(); + + print('gmcPolicies $gmcPolicies'); + + if (gmcPolicies.isNotEmpty) { + final mergedEmployeeDetails = getMergedEmployeeDetails(gmcPolicies); + + print("🟢 Merged Employee Details: $mergedEmployeeDetails"); + + setState(() { + employeeDetailsList = mergedEmployeeDetails; + }); + + print('mergedEmployeeDetails $employeeDetailsList'); + + setState(() => isLoadingGif = false); + + // continue your logic here… + return; + } + + // ------------------------------------------- + // 2️⃣ IF NO GMC, CHECK FOR GPA + // ------------------------------------------- + final gpaPolicies = policyList.where((item) { + final type = (item['policy_type'] ?? '').toString(); + return type == 'GPA'; + }).toList(); + + if (gpaPolicies.isNotEmpty) { + print("🟠 GPA FOUND — calling Wellness API directly"); + + final firstPolicy = gpaPolicies[0]; + + final empID = firstPolicy['EmployeePolicy'][0]['employee_id']; + final clientPolicyId = firstPolicy['client_policy_id']; + + print("EMPLOYEE ID: $empID"); + print("CLIENT POLICY ID: $clientPolicyId"); + + setState(() => isLoadingGif = false); + + await getWellnessLink(empID, clientPolicyId); + + return; + } + + // ------------------------------------------- + // 3️⃣ NO GMC, NO GPA + // ------------------------------------------- + print("❌ No valid policy found"); + ToastHelper.showErrorToast(context, "No valid policies found."); + setState(() => isLoadingGif = false); + + + } else { + setState(() { + isLoadingGif = false; + }); + print('API request failed with status: ${response['status']}'); + } + } + + List getMergedEmployeeDetails(List? gmcPolicies) { + print('123'); + if (gmcPolicies == null || gmcPolicies.isEmpty) return []; + print('getMergedEmployeeDetails $gmcPolicies'); + + List finalList = []; + + for (var policy in gmcPolicies) { + final details = policy['EmployeePolicy']; + final clientPolicyId = policy['client_policy_id']; + + if (details != null) { + if (details is List) { + // Add client_policy_id to each employee + for (var emp in details) { + finalList.add({ + ...emp, // existing employee fields + "client_policy_id": clientPolicyId + }); + } + } else if (details is Map) { + // Single employee object + finalList.add({ + ...details, + "client_policy_id": clientPolicyId + }); + } + } + + } + + return finalList; + } + + + Future getWellnessLink(employee_id,client_policy_id) async { + + final response = await apiService.getWellnessLink(employee_id,client_policy_id); print('check 1'); if (response['status'] == 'success') { wellnessURL = response['data']; print('✅ Link: $wellnessURL'); + openInWebView(context,wellnessURL); // await _launchURL(wellnessURL); // Only launch if status is success } else if (response['status'] == 'failed') { wellnessMessage = response['message']; print('❌ Error: $wellnessMessage'); - // ToastHelper.showErrorToast(context, wellnessMessage); + ToastHelper.showErrorToast(context, wellnessMessage); } else { ToastHelper.showErrorToast(context, '⚠️ Unknown response format'); print('⚠️ Unknown response format'); } } - Future _launchURL(String url, BuildContext context) async { print('url $url'); try { @@ -70,8 +222,19 @@ class _wellnessState extends State { } } + void openInWebView(BuildContext context, String url) { + if (kIsWeb) { + // 🌐 Open in new browser tab (web) + _launchURL(url,context); + } else { + // 📱 Open in platform WebView + context.push('/wellnessWebView', extra: wellnessURL); + } + } + @override Widget build(BuildContext context) { + return PopScope( canPop: false, onPopInvokedWithResult: (didPop, result) { @@ -79,188 +242,311 @@ class _wellnessState extends State { context.pop(); }, child: Scaffold( - backgroundColor: Colors.white, - appBar: CustomAppBar(), - body: Stack(children: [ - SingleChildScrollView( - child: Column( - mainAxisAlignment: MainAxisAlignment - .center, // Center both text and button vertically - children: [ + backgroundColor: Colors.white, + appBar: CustomAppBar(), + body: Stack(children: [ + SingleChildScrollView( + child: Container( + padding: Responsive.isDesktop(context) + ? EdgeInsets.symmetric( + horizontal: MediaQuery.of(context).size.width * + 0.2, // 30% of screen width as horizontal padding + vertical: MediaQuery.of(context).size.height * + 0.03, // 5% of screen height as vertical padding + ) + : EdgeInsets.all(10), + color: Colors.white, + child: Column(children: [ + Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded( + flex: 12, + child: InkWell( + onTap: () { + context.pop(); + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Icon( + Icons + .chevron_left, // Replace with your desired icon + color: Color(0xFF000000), + size: 30, + ), + SizedBox( + width: + 5), // Adjust space between icon and text + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + 'Wellness', + textAlign: TextAlign.start, + style: GoogleFonts.poppins( + fontSize: 16, + fontWeight: FontWeight.w600, + color: Color(0xFF000000), + ), + ), + Text( + 'Select your family member to avail the wellness benefits.', + textAlign: TextAlign.start, + style: GoogleFonts.poppins( + fontSize: + 11, // Adjust the font size as needed + fontWeight: FontWeight.w400, + color: Color(0xFF000000), + ), + ), + ], + ), + ], + ), + ), + ), + ], + ), + // Add more rows as needed + ], + ), + ), + SizedBox(height: 15), + if (employeeDetailsList != null && employeeDetailsList.length > 0) + SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: generateFamilyMembers(employeeDetailsList), + ), + ), + SizedBox(height: Responsive.isDesktop(context) ? 40 : 70), + ]), + )), + if (isLoadingGif) Container( - padding: Responsive.isDesktop(context) - ? EdgeInsets.only(top: 15, bottom: 15, left: 25, right: 25) - : EdgeInsets.only(top: 0, bottom: 0, left: 0, right: 0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Expanded( - flex: 12, - child: InkWell( - onTap: () { - context.pop(); - }, - child: Row( - mainAxisAlignment: MainAxisAlignment.start, + color: Color(0x98FFFCE5), // Semi-transparent background + child: Center( + child: // Your GIF loader widget + Image.asset( + height: 60, + width: 60, + 'assets/nhance-loader.gif'), // Adjust path to your GIF loader + ), + ), + if (Responsive.isDesktop(context)) + Align( + alignment: Alignment.bottomCenter, + child: Container( + width: double.infinity, // Make the footer full width + child: CustomFooter(), + ), + ), + ]), + // floatingActionButton: Responsive.isDesktop(context) + // ? null + // : FloatingActionButton( + // onPressed: () { + // Navigator.pushNamed(context, 'chatbot'); + // }, + // child: Icon(Icons.chat), + // ), + floatingActionButtonLocation: Responsive.isDesktop(context) + ? null + : FloatingActionButtonLocation.miniEndFloat, + bottomNavigationBar: Responsive.isDesktop(context) + ? null + : CustomBottomNavigationBar( + onTabChanged: (index) { + // Add your navigation logic here + // For example: + if (index == 0) { + context.push('/home'); + } else if (index == 1) { + context.push('/claims'); + } else if (index == 2) { + context.push('/profile'); + } else if (index == 3) { + context.push('/help'); + } else if (index == 4) { + context.push('/wellness'); + } + }, + icons: [ + Icons.home_outlined, + Icons.sticky_note_2_outlined, + Icons.person_outline_outlined, + Icons.headset_mic_outlined, + Icons.health_and_safety_outlined, + ], + labels: [ + "Home", + "Claims", + "Profile", + "Help", + "Wellness", + ], + initialIndex: 4, // Initial index of the bottom navigation bar + ), + ) + ); + } + + + List generateFamilyMembers(List data) { + return [ + ListView.builder( + shrinkWrap: true, + physics: NeverScrollableScrollPhysics(), + itemCount: data.length, + itemBuilder: (BuildContext context, int index) { + var item = data[index]; + // String claimsName = item['user_name']; + String gender = item['gender'] ?? ''; + String dob = item['dob'] ?? ''; + String name = item['name'] ?? ''; + String relationship = item['relationship'] ?? ''; + String employee_id = item['employee_id'] ?? ''; + String client_policy_id = item['client_policy_id'] ?? ''; + + print('${name} - ${employee_id}--${client_policy_id}'); + + return GestureDetector( + onTap: () { + getWellnessLink(employee_id,client_policy_id); + }, + child: MouseRegion( + cursor: SystemMouseCursors.click, + child: Card( + elevation: 5, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(15.0), + ), + child: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(15.0), + ), + padding: EdgeInsets.symmetric(vertical: 5, horizontal: 5), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Expanded( + flex: 8, + child: Container( + alignment: Alignment.centerLeft, + padding: Responsive.isDesktop(context) + ? EdgeInsets.only( + top: 10, + bottom: 10, + left: 10, + right: 10) + : EdgeInsets.only( + top: 15, + bottom: 15, + left: 7, + right: 7), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Icon( - Icons - .chevron_left, // Replace with your desired icon - color: Color(0xFF000000), - size: 30, + Row( + children: [ + // 👇 SVG icon based on gender + if (gender == 'M') + SvgPicture.string( + SvgService.getSvg('personMale'), + width: 25, + height: 25, + ) + else if (gender == 'F') + SvgPicture.string( + SvgService.getSvg('personFemale'), + width: 25, + height: 25, + ), + + const SizedBox(width: 6), + + // Name text + Text( + name ?? '', + textAlign: TextAlign.start, + style: GoogleFonts.poppins( + fontSize: Responsive.isDesktop(context) ? 16 : 14, + color: const Color(0xFF000000), + fontWeight: FontWeight.w400, + ), + ), + ], + ), + + const SizedBox(height: 4), + + // DOB text + Text( + "DOB: ${formatDob(dob!) ?? '-'}", + style: GoogleFonts.poppins( + fontSize: Responsive.isDesktop(context) ? 14 : 12, + color: const Color(0xFF606060), + fontWeight: FontWeight.w300, + ), ), ], + ) + ), + ), + Expanded( + flex: 4, + child: Container( + alignment: Alignment.centerRight, + padding: Responsive.isDesktop(context) + ? EdgeInsets.only( + top: 10, + bottom: 10, + left: 10, + right: 10) + : EdgeInsets.only( + top: 15, + bottom: 15, + left: 7, + right: 7), + child: Text( + relationship!, + textAlign: TextAlign.end, + style: GoogleFonts.poppins( + fontSize: + Responsive.isDesktop(context) + ? 16 + : 14, + color: Color(0xFF404040), + fontWeight: FontWeight.w400, ), ), ), - ], - ), - Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Expanded( - flex: 12, - child: Container( - alignment: Alignment.center, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Image.asset( - 'assets/wellness.png', // Path to your image in assets folder - width: 250, - height: 250, - ), - ], - ))), - ], - ), - // Add more rows as needed - ], - ), - ), - SizedBox(height: 15), - Container( - decoration: BoxDecoration( - color: Colors.white, // Set background color for the container - ), - padding: Responsive.isDesktop(context) - ? EdgeInsets.symmetric(horizontal: 400,vertical: 10) - : EdgeInsets.only(top: 5, bottom: 5, left: 10, right: 10), - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Padding( - padding: EdgeInsets.only(bottom: 10), - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Text( - 'You are being redirected out of this app.', - textAlign: TextAlign.center, - style: GoogleFonts.poppins( - fontSize: Responsive.isDesktop(context) ? 16 : 12, - fontWeight: FontWeight.w400, - color: const Color(0xFF777777), - ), - ), - SizedBox(height: 4), // spacing between lines - Text( - 'Click Proceed to Continue', - textAlign: TextAlign.center, - style: GoogleFonts.poppins( - fontSize: Responsive.isDesktop(context) ? 16 : 12, - fontWeight: FontWeight.w400, - color: const Color(0xFF777777), - ), - ), - ], - ) ), - ]), - ), - SizedBox(height: 15), // Space between text and button - ElevatedButton( - onPressed: () { - print('wellnessURL $wellnessURL'); - if(wellnessURL != null){ - _launchURL(wellnessURL,context); - } else { - ToastHelper.showInfoToast(context, wellnessMessage); - } - }, - child: Text( - 'Proceed', - style: GoogleFonts.poppins(color: Colors.white), - ), - style: ElevatedButton.styleFrom( - backgroundColor: Color(0xFFE26728), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(5), + ], ), ), ), - ], - ), - ), - if (Responsive.isDesktop(context)) - Align( - alignment: Alignment.bottomCenter, - child: Container( - width: double.infinity, // Make the footer full width - child: CustomFooter(), ), - ), - ]), - // floatingActionButton: Responsive.isDesktop(context) - // ? null - // : FloatingActionButton( - // onPressed: () { - // Navigator.pushNamed(context, 'chatbot'); - // }, - // child: Icon(Icons.chat), - // ), - floatingActionButtonLocation: Responsive.isDesktop(context) - ? null - : FloatingActionButtonLocation.miniEndFloat, - bottomNavigationBar: Responsive.isDesktop(context) - ? null - : CustomBottomNavigationBar( - onTabChanged: (index) { - // Add your navigation logic here - // For example: - if (index == 0) { - context.push('/home'); - } else if (index == 1) { - context.push('/claims'); - } else if (index == 2) { - context.push('/profile'); - } else if (index == 3) { - context.push('/help'); - } else if (index == 4) { - context.push('/wellness'); - } - }, - icons: [ - Icons.home_outlined, - Icons.sticky_note_2_outlined, - Icons.person_outline_outlined, - Icons.headset_mic_outlined, - Icons.health_and_safety_outlined, - ], - labels: [ - "Home", - "Claims", - "Profile", - "Help", - "Wellness", - ], - initialIndex: 4, // Initial index of the bottom navigation bar - ), - ) - ); + ); + }, + ), + ]; } -} + String formatDob(String dob) { + try { + final date = DateTime.parse(dob); // input format: yyyy-MM-dd + return DateFormat("d MMM yyyy").format(date); // output: 18 Jul 1988 + } catch (e) { + return dob; // fallback in case of error + } + } + +} \ No newline at end of file diff --git a/lib/pages/postEnrollment/wellness_web_view.dart b/lib/pages/postEnrollment/wellness_web_view.dart new file mode 100644 index 0000000..b7b51cc --- /dev/null +++ b/lib/pages/postEnrollment/wellness_web_view.dart @@ -0,0 +1,32 @@ +import 'package:flutter/material.dart'; +import 'package:webview_flutter/webview_flutter.dart'; + +class WellnessWebView extends StatefulWidget { + final String url; + + const WellnessWebView({super.key, required this.url}); + + @override + State createState() => _WellnessWebViewState(); +} + +class _WellnessWebViewState extends State { + late final WebViewController controller; + + @override + void initState() { + super.initState(); + + controller = WebViewController() + ..setJavaScriptMode(JavaScriptMode.unrestricted) + ..loadRequest(Uri.parse(widget.url)); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text("Wellness")), + body: WebViewWidget(controller: controller), + ); + } +} diff --git a/lib/pages/service/SessionManager.dart b/lib/pages/service/SessionManager.dart index e39fde5..be92492 100644 --- a/lib/pages/service/SessionManager.dart +++ b/lib/pages/service/SessionManager.dart @@ -173,6 +173,7 @@ class SessionManager { String? enrollmentGpaEmpName; String? enrollmentClient_id; String? enrollmentEmp_status; + String? enrollmentEmailCorporate; /// Save Post Enrollment Token Future initializeFromPostToken(String token) async { @@ -214,6 +215,7 @@ class SessionManager { enrollmentGpaEmpName = decoded['name']?.toString(); enrollmentClient_id = decoded['client_id']?.toString(); enrollmentEmp_status = decoded['emp_status']?.toString(); + enrollmentEmailCorporate = decoded['email_corporate']?.toString(); // persist prefs.setString('enrollmentEmpClientBranchId', enrollmentEmpClientBranchId ?? ''); @@ -222,6 +224,7 @@ class SessionManager { prefs.setString('enrollmentGpaEmpName', enrollmentGpaEmpName ?? ''); prefs.setString('enrollmentClient_id', enrollmentClient_id ?? ''); prefs.setString('enrollmentEmp_status', enrollmentEmp_status ?? ''); + prefs.setString('enrollmentEmailCorporate', enrollmentEmailCorporate ?? ''); debugPrint('Pre Session initialized: $decoded'); } @@ -265,6 +268,7 @@ class SessionManager { enrollmentGpaEmpName = null; enrollmentClient_id = null; enrollmentEmp_status = null; + enrollmentEmailCorporate = null; final prefs = await SharedPreferences.getInstance(); await prefs.clear(); diff --git a/lib/pages/service/popup_helper.dart b/lib/pages/service/popup_helper.dart index 210404d..52b9b54 100644 --- a/lib/pages/service/popup_helper.dart +++ b/lib/pages/service/popup_helper.dart @@ -28,7 +28,7 @@ class PopupHelper { String wellnessMessage = ''; // 🔹 Fetch link using API - final response = await apiService.getWellnessLink(empPrimaryId); + final response = await apiService.getWellnessLink(empPrimaryId,''); print('Wellness response : $response'); diff --git a/lib/pages/setPassword.dart b/lib/pages/setPassword.dart new file mode 100644 index 0000000..24c21a9 --- /dev/null +++ b/lib/pages/setPassword.dart @@ -0,0 +1,695 @@ +import 'dart:convert'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:go_router/go_router.dart'; +import 'package:http/http.dart' as http; +import 'package:nhance_app_pwa/pages/service/SessionManager.dart'; +import 'dart:io'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import '../customAppBar/responsive.dart'; +import '../customAppBar/toastHelper.dart'; +import '../models/environment.dart'; + +class setPassword extends StatefulWidget { + final String email; + final String client_id; + final String route; + const setPassword({ + super.key, + required this.email, + required this.client_id, + required this.route, + }); + + @override + State createState() => _setPasswordState(); +} + +class _setPasswordState extends State { + final TextEditingController newPasswordController = TextEditingController(); + final TextEditingController confirmPasswordController = TextEditingController(); + final _formKey = GlobalKey(); + dynamic _preToken; + dynamic _postToken; + dynamic clientName; + dynamic clientLogo; + bool _isLoading = false; + bool _obscureNewPassword = true; + bool _obscureConfirmPassword = true; + late SessionManager session; + + @override + void initState() { + super.initState(); + } + + + Future resetYourPassword() async { + final newPassword = newPasswordController.text.trim(); + final confirmPassword = confirmPasswordController.text.trim(); + try { + if (_formKey.currentState!.validate()) { + if (confirmPassword != newPassword) { + ToastHelper.showErrorToast(context, 'Passwords do not match'); + return; + } + setState(() { + _isLoading = true; + }); + + // Determine the API and the payload based on the visible field + String apiEndpoint = Environment.apiUrlEnrollment + 'savePassword'; + Map payload = { + 'email_id': widget.email, + 'client_id': widget.client_id, + 'password': newPassword, + 'confirm_password': confirmPassword + }; + + // var enteredMobileNumber = mobileController.text; + final response = await http.post( + Uri.parse(apiEndpoint), + body: json.encode(payload), + headers: { + HttpHeaders.contentTypeHeader: 'application/json', + }, + ); + + if (response.statusCode == 200) { + Map data = json.decode(response.body); + bool userVerification = data['data']['user_verification']; + String message = data['data']['message']; + if (userVerification) { + setState(() { + _isLoading = false; + }); + ToastHelper.showSuccessToast(context, message!); + context.go('/${widget.route}'); + } 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'); + } + + // 🔹 Password validation + // if (password.isEmpty) { + // ToastHelper.showErrorToast(context, 'Please enter your password'); + // return; + // } + // if (password.length < 6) { + // ToastHelper.showErrorToast(context, 'Password must be at least 6 characters'); + // return; + // } + // if (!RegExp(r'^(?=.*[A-Z])(?=.*[0-9]).{6,}$').hasMatch(password)) { + // ToastHelper.showErrorToast(context, 'Include at least 1 uppercase letter and 1 number'); + // return; + // } + // + // // 🔹 Confirm password validation + // if (confirmPassword.isEmpty) { + // ToastHelper.showErrorToast(context, 'Please confirm your password'); + // return; + // } + } + + //Ends Login with UserName and Password + + @override + Widget build(BuildContext context) { + Size _size = MediaQuery.of(context).size; + EdgeInsets marginInsets = EdgeInsets.zero; + + // const focusedBorderColor = Colors.white; + // const fillColor = Color.fromRGBO(243, 246, 249, 0); + // const borderColor = Color.fromRGBO(23, 171, 144, 0.4); + + if (Responsive.isDesktop(context)) { + marginInsets = const EdgeInsets.only( + left: 0, + right: 0, + bottom: 0, + top: 0, + ); + } else if (Responsive.isMobile(context)) { + marginInsets = const EdgeInsets.only( + left: 25, // Example value for mobile + right: 25, // Example value for mobile + bottom: 0, // Example value for mobile + top: 0, // Example value for mobile + ); + } else if (Responsive.isTablet(context)) { + marginInsets = const EdgeInsets.only( + left: 25, //// Example value for mobile + right: 25, // Example value for mobile + bottom: 0, // Example value for mobile + top: 0, // Example value for mobile + ); + } + return WillPopScope( + onWillPop: () async { + // Close the app on mobile back button press + exit(0); // This will exit the app + return false; // Return false to prevent any other actions + }, + child: Scaffold( + body: SingleChildScrollView( + keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag, + child: Container( + height: _size.height, + color: Colors.white, + child: Stack( + children: [ + // Visibility( + // visible: _size.width <= 1100, + // child: ClipRRect( + // borderRadius: BorderRadius.only( + // bottomLeft: Radius.circular(30), + // bottomRight: Radius.circular(30), + // ), + // child: Container( + // height: _size.height / 3, + // width: double.infinity, + // color: Color(0xFFFFFCE5), + // child: Stack( + // children: [ + // Column( + // children: [ + // SizedBox(height: _size.height / 6.4), + // Row( + // mainAxisAlignment: MainAxisAlignment + // .center, // Align to the center + // children: [ + // Expanded( + // flex: Responsive.isDesktop(context) + // ? 10 + // : 12, + // child: Align( + // alignment: + // Responsive.isDesktop(context) + // ? Alignment.centerLeft + // : Alignment.bottomCenter, + // child: Image.asset( + // 'assets/nhance_app_logo.png', + // width: 150, + // height: 100, + // )), + // ), + // if (!Responsive.isMobile(context) && + // !Responsive.isTablet(context)) + // Expanded( + // flex: 2, + // child: MouseRegion( + // cursor: SystemMouseCursors.click, + // child: GestureDetector( + // onTap: () { + // // Add your navigation logic here + // // For example, you can use Navigator.push to navigate to another page + // Navigator.pushNamed( + // context, 'hrLogin'); + // }, + // child: Row( + // mainAxisAlignment: MainAxisAlignment + // .end, // Align to the end (right) + // children: [ + // Text( + // 'HR Login', + // style: TextStyle( + // color: Color( + // 0xFF000000), // Text color + // // Add other text styles as needed + // ), + // ), + // SizedBox(width: 5), + // Icon( + // Icons + // .east, // Icon for customer login + // color: Colors + // .black, // Adjust color as needed + // ), + // ], + // ), + // ), + // ), + // ), + // ], + // ), + // ], + // ), + // ], + // ), + // ), + // ), + // ), + Container( + margin: marginInsets, + alignment: Alignment.bottomCenter, + child: SingleChildScrollView( + child: Form( + key: _formKey, + child: Column( + children: [ + Row( + children: [ + Expanded( + flex: _size.width < 1100 ? 6 : 12, + child: Container( + margin: _size.width > 1100 + ? EdgeInsets.only(left: 20, right: 20) + : EdgeInsets.only(left: 0, right: 0), + child: Column( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + if (!Responsive.isMobile(context) && + !Responsive.isTablet(context)) + Row( + children: [ + // InkWell( + // onTap: () { + // context.go('/home'); + // }, + // child: Row( + // mainAxisAlignment: MainAxisAlignment.start, + // children: [ + // // if (!Responsive.isDesktop(context)) + // Icon( + // Icons.chevron_left, + // color: Color(0xFF000000), + // size: 30, + // ), + // SizedBox( + // width: Responsive.isDesktop(context) + // ? 0 + // : 5), + // ], + // ), + // ), + Expanded( + flex: 12, + child: Align( + alignment: Alignment + .topLeft, // ✅ Always top-left + child: _size.width <= 1100 + ? Image.asset( + 'assets/nhance_app_logo.png', + width: 150, + height: 150, + ) + : _size.width > 1100 + ? Image.asset( + 'assets/nhance_app_logo.png', + width: 150, + height: 150, + ) + : Image.asset( + 'assets/nhance_app_logo.png', + width: 150, + height: 150, + ), + ), + ), + ], + ), + SizedBox( + height: Responsive.isDesktop(context) + ? _size.height * 0.1 + : 10, + ), + SizedBox(height: 10), + Container( + margin: Responsive.isDesktop(context) + ? EdgeInsets.symmetric( + horizontal: 150) + : EdgeInsets.symmetric( + horizontal: 0), + child: Row( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Text( + "Welcome to Nhance", + style: GoogleFonts.poppins( + fontSize: 16, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ), + SizedBox( + height: 10, + ), + Container( + margin: Responsive.isDesktop(context) + ? EdgeInsets.symmetric( + horizontal: 150) + : EdgeInsets.symmetric( + horizontal: 0), + child: Row( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Expanded( + child: Text( + "Login with your to review and enroll for exciting health benefits for you and your family", + style: GoogleFonts.poppins( + fontSize: 12, + color: Color(0xFF000000)), + textAlign: TextAlign.center, + ), + ) + ], + ), + ), + SizedBox( + height: 20, + ), + + Column( + children: [ + // 🔹 Password Field + Container( + height: 55, + margin: Responsive.isDesktop( + context) + ? const EdgeInsets + .symmetric( + horizontal: 150) + : const EdgeInsets + .symmetric( + horizontal: 0), + decoration: BoxDecoration( + border: Border.all( + width: 1, + color: Colors.grey), + borderRadius: + BorderRadius.circular( + 10), + ), + child: TextFormField( + controller: + newPasswordController, + obscureText: + _obscureNewPassword, + textAlignVertical: + TextAlignVertical + .center, + decoration: InputDecoration( + border: InputBorder.none, + hintText: + "New Password", + contentPadding: + const EdgeInsets + .symmetric( + horizontal: 10), + suffixIcon: IconButton( + icon: Icon( + _obscureNewPassword + ? Icons + .visibility_off + : Icons + .visibility, + color: Colors.grey, + ), + onPressed: () { + setState(() { + _obscureNewPassword = + !_obscureNewPassword; + }); + }, + ), + ), + validator: (value) { + if (value == null || + value.isEmpty) { + return 'Please enter your new password'; + } + if (value.length < 6) { + return 'Password must be at least 6 characters'; + } + if (!RegExp( + r'^(?=.*[A-Z])(?=.*[0-9]).{6,}$') + .hasMatch(value)) { + return 'Include at least 1 uppercase letter and 1 number'; + } + return null; + }, + ), + ), + const SizedBox(height: 10), + Container( + height: 55, + margin: Responsive.isDesktop( + context) + ? const EdgeInsets + .symmetric( + horizontal: 150) + : const EdgeInsets + .symmetric( + horizontal: 0), + decoration: BoxDecoration( + border: Border.all( + width: 1, + color: Colors.grey), + borderRadius: + BorderRadius.circular( + 10), + ), + child: TextFormField( + controller: + confirmPasswordController, + obscureText: + _obscureConfirmPassword, + textAlignVertical: + TextAlignVertical + .center, + decoration: InputDecoration( + border: InputBorder.none, + hintText: + "Confirm Password", + contentPadding: + const EdgeInsets + .symmetric( + horizontal: 10), + suffixIcon: IconButton( + icon: Icon( + _obscureConfirmPassword + ? Icons + .visibility_off + : Icons + .visibility, + color: Colors.grey, + ), + onPressed: () { + setState(() { + _obscureConfirmPassword = + !_obscureConfirmPassword; + }); + }, + ), + ), + validator: (value) { + if (value == null || + value.isEmpty) { + return 'Please confirm your password'; + } + if (value != + newPasswordController + .text) { + return 'Passwords do not match'; + } + return null; + }, + ), + ), + ], + ), + SizedBox(height: 15), + Container( + margin: + Responsive.isDesktop(context) + ? EdgeInsets.symmetric( + horizontal: 150) + : EdgeInsets.symmetric( + horizontal: 0), + child: SizedBox( + width: double.infinity, + height: 40, + child: ElevatedButton( + style: + ElevatedButton.styleFrom( + backgroundColor: + Color(0xFF00989E), + shape: + RoundedRectangleBorder( + borderRadius: + BorderRadius.circular( + 10), + ), + ), + onPressed: _isLoading + ? null + : resetYourPassword, + + child: _isLoading + ? CircularProgressIndicator( + valueColor: + AlwaysStoppedAnimation< + Color>( + Color(0xFF00989E), + ), + ) + : Text( + "Reset Password", + style: GoogleFonts + .poppins( + color: Color( + 0xFFFFFFFF), + ), + ), + ), + ), + ), + + SizedBox( + height: Responsive.isDesktop(context) + ? _size.height * 0.3 + : _size.height * 0.2, + ), + // SizedBox( + // height: _size.height * 0.1, + // ), + Container( + alignment: Alignment.bottomCenter, + padding: + EdgeInsets.symmetric(vertical: 8), + child: RichText( + textAlign: TextAlign.center, + text: TextSpan( + text: + 'By continuing, you agree with our ', + style: GoogleFonts.poppins( + color: Colors.black, + fontSize: 9, + ), + children: [ + WidgetSpan( + child: MouseRegion( + cursor: SystemMouseCursors + .click, + child: GestureDetector( + onTap: () { + context.go( + '/privacypolicy'); + // Navigator.pushNamed( + // context, + // 'privacypolicy'); + }, + child: Text( + 'privacy policy ', + style: + GoogleFonts.poppins( + color: + Color(0xFF00989E), + fontSize: 9, + decoration: + TextDecoration + .underline, + ), + ), + ), + ), + ), + TextSpan( + text: 'and ', + style: GoogleFonts.poppins( + color: Colors.black, + fontSize: 9, + ), + ), + WidgetSpan( + child: MouseRegion( + cursor: SystemMouseCursors + .click, + child: GestureDetector( + onTap: () { + context + .go('/termsofuse'); + // Navigator.pushNamed( + // context, + // 'termsofuse'); + }, + child: Text( + 'terms of use', + style: + GoogleFonts.poppins( + color: + Color(0xFF00989E), + fontSize: 9, + decoration: + TextDecoration + .underline, + ), + ), + ), + ), + ), + ], + ), + ), + ), + ], + ), + ), + ), + if (_size.width > 1100) + Expanded( + flex: _size.width < 1100 ? 6 : 12, + child: LayoutBuilder( + builder: (BuildContext context, + BoxConstraints constraints) { + if (constraints.maxWidth > 600) { + return Image.asset( + 'assets/login_web.jpg', + height: _size.height, + fit: BoxFit.cover, + ); + } else { + return SizedBox(); + } + }, + ), + ), + ], + ), + ], + ), + ), + ), + ), + ], + )), + ))); + } +} diff --git a/pubspec.yaml b/pubspec.yaml index 97ff453..21e4e70 100755 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,8 +17,8 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. #version: 1.0.32+32 -version: 1.0.21+24 -#version: 2.0.4+42 +version: 1.0.22+25 +#version: 2.0.6+44 environment: sdk: '>=3.3.3 <4.0.0'