diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist index 1dc6cf7..391a902 100644 --- a/ios/Flutter/AppFrameworkInfo.plist +++ b/ios/Flutter/AppFrameworkInfo.plist @@ -20,7 +20,5 @@ ???? CFBundleVersion 1.0 - MinimumOSVersion - 13.0 diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 60af84f..7c779a1 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -36,6 +36,8 @@ PODS: - Flutter (1.0.0) - flutter_native_splash (2.4.3): - Flutter + - image_picker_ios (0.0.1): + - Flutter - mobile_scanner (7.0.0): - Flutter - FlutterMacOS @@ -54,6 +56,7 @@ DEPENDENCIES: - file_picker (from `.symlinks/plugins/file_picker/ios`) - Flutter (from `Flutter`) - flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`) + - image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`) - mobile_scanner (from `.symlinks/plugins/mobile_scanner/darwin`) - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) @@ -72,6 +75,8 @@ EXTERNAL SOURCES: :path: Flutter flutter_native_splash: :path: ".symlinks/plugins/flutter_native_splash/ios" + image_picker_ios: + :path: ".symlinks/plugins/image_picker_ios/ios" mobile_scanner: :path: ".symlinks/plugins/mobile_scanner/darwin" path_provider_foundation: @@ -82,13 +87,14 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60 - file_picker: a0560bc09d61de87f12d246fc47d2119e6ef37be + file_picker: b159e0c068aef54932bb15dc9fd1571818edaf49 Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467 - flutter_native_splash: c32d145d68aeda5502d5f543ee38c192065986cf - mobile_scanner: 9157936403f5a0644ca3779a38ff8404c5434a93 - path_provider_foundation: bb55f6dbba17d0dccd6737fe6f7f34fbd0376880 + flutter_native_splash: df59bb2e1421aa0282cb2e95618af4dcb0c56c29 + image_picker_ios: 4f2f91b01abdb52842a8e277617df877e40f905b + mobile_scanner: 77265f3dc8d580810e91849d4a0811a90467ed5e + path_provider_foundation: 0b743cbb62d8e47eab856f09262bb8c1ddcfe6ba SDWebImage: 16309af6d214ba3f77a7c6f6fdda888cb313a50a - shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb + shared_preferences_foundation: 5086985c1d43c5ba4d5e69a4e8083a389e2909e6 SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4 PODFILE CHECKSUM: 251cb053df7158f337c0712f2ab29f4e0fa474ce diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 35a0ad9..e3773d4 100644 --- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ Bool { - GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } + + func didInitializeImplicitFlutterEngine(_ engineBridge: FlutterImplicitEngineBridge) { + GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry) + } } diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index 4d55b7f..da57af1 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -1,48 +1,69 @@ + + CADisableMinimumFrameDurationOnPhone + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Citycards Partner Flutter + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + citycards_partner_flutter + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + NSCameraUsageDescription + This app needs camera access to scan QR codes + NSPhotoLibraryUsageDescription + This app needs photos access to get QR code from photo library + UIApplicationSceneManifest - CADisableMinimumFrameDurationOnPhone - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleDisplayName - Citycards Partner Flutter - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - citycards_partner_flutter - CFBundlePackageType - APPL - CFBundleShortVersionString - $(FLUTTER_BUILD_NAME) - CFBundleSignature - ???? - CFBundleVersion - $(FLUTTER_BUILD_NUMBER) - LSRequiresIPhoneOS - - NSCameraUsageDescription - This app needs camera access to scan QR codes - NSPhotoLibraryUsageDescription - This app needs photos access to get QR code from photo library - UIApplicationSupportsIndirectInputEvents - - UILaunchStoryboardName - LaunchScreen.storyboard - UIMainStoryboardFile - Main - UIStatusBarHidden - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - - UIViewControllerBasedStatusBarAppearance + UIApplicationSupportsMultipleScenes + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneClassName + UIWindowScene + UISceneConfigurationName + flutter + UISceneDelegateClassName + FlutterSceneDelegate + UISceneStoryboardFile + Main + + + + UIApplicationSupportsIndirectInputEvents + + UILaunchStoryboardName + LaunchScreen.storyboard + UIMainStoryboardFile + Main + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + + UIViewControllerBasedStatusBarAppearance + + diff --git a/lib/login/views/forgot_password_page.dart b/lib/login/views/forgot_password_page.dart index 7a8ba2f..ec0530a 100644 --- a/lib/login/views/forgot_password_page.dart +++ b/lib/login/views/forgot_password_page.dart @@ -62,6 +62,29 @@ class _ForgotPasswordPageState extends State { behavior: HitTestBehavior.translucent, child: Scaffold( backgroundColor: AppColors.backgroundWhite, + appBar: AppBar( + backgroundColor: Colors.transparent, + elevation: 0, + leadingWidth: 70.w, + leading: Padding( + padding: EdgeInsets.only(left: 24.w, top: 8.h, bottom: 8.h), + child: InkWell( + onTap: () => Navigator.pop(context), + borderRadius: BorderRadius.circular(50), + child: Container( + decoration: const BoxDecoration( + color: AppColors.primaryRed, + shape: BoxShape.circle, + ), + child: Icon( + Icons.arrow_back_ios_new, + color: Colors.white, + size: 18.sp, + ), + ), + ), + ), + ), body: BlocConsumer( listener: (context, state) { if (state.status == ForgotPasswordStatus.success) { @@ -97,7 +120,7 @@ class _ForgotPasswordPageState extends State { child: SingleChildScrollView( child: Column( children: [ - SizedBox(height: 40.h), + SizedBox(height: 10.h), // ===== LOGO SECTION ===== Center( child: Column( diff --git a/lib/login/views/otp_verification_page.dart b/lib/login/views/otp_verification_page.dart index 01e1e08..27254fd 100644 --- a/lib/login/views/otp_verification_page.dart +++ b/lib/login/views/otp_verification_page.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flutter_otp_text_field/flutter_otp_text_field.dart'; +import 'package:pinput/pinput.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:google_fonts/google_fonts.dart'; import '../../constants/app_assets.dart'; @@ -21,7 +21,30 @@ class OtpVerificationPage extends StatelessWidget { behavior: HitTestBehavior.translucent, child: Scaffold( backgroundColor: AppColors.backgroundWhite, - body: BlocConsumer( + appBar: AppBar( + backgroundColor: Colors.transparent, + elevation: 0, + leadingWidth: 70.w, + leading: Padding( + padding: EdgeInsets.only(left: 24.w, top: 8.h, bottom: 8.h), + child: InkWell( + onTap: () => Navigator.pop(context), + borderRadius: BorderRadius.circular(50), + child: Container( + decoration: const BoxDecoration( + color: AppColors.primaryRed, + shape: BoxShape.circle, + ), + child: Icon( + Icons.arrow_back_ios_new, + color: Colors.white, + size: 18.sp, + ), + ), + ), + ), + ), + body: BlocListener( listener: (context, state) { if (state.status == VerifyOtpStatus.success) { Navigator.pushReplacementNamed( @@ -39,122 +62,149 @@ class OtpVerificationPage extends StatelessWidget { ); } }, - builder: (context, state) { - final isLoading = state.status == VerifyOtpStatus.loading; - - return SafeArea( - child: Padding( - padding: EdgeInsets.symmetric(horizontal: 24.w), - child: Column( - children: [ - Expanded( - child: SingleChildScrollView( - child: Column( - children: [ - SizedBox(height: 40.h), - // ===== LOGO SECTION ===== - Center( - child: Column( - children: [ - Image.asset( - AppAssets.appIcon, - height: 60.h, + child: SafeArea( + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 24.w), + child: Column( + children: [ + Expanded( + child: SingleChildScrollView( + child: Column( + children: [ + SizedBox(height: 10.h), + // ===== LOGO SECTION ===== + Center( + child: Column( + children: [ + Image.asset( + AppAssets.appIcon, + height: 60.h, + ), + SizedBox(height: 8.h), + Text( + "Partner's App", + style: GoogleFonts.poppins( + color: AppColors.primaryRed, + fontSize: 20.sp, + fontWeight: FontWeight.w500, ), - SizedBox(height: 8.h), - Text( - "Partner's App", - style: GoogleFonts.poppins( - color: AppColors.primaryRed, - fontSize: 20.sp, - fontWeight: FontWeight.w500, - ), - ), - ], - ), + ), + ], ), - SizedBox(height: 60.h), + ), + SizedBox(height: 60.h), - // ===== HEADER TEXT ===== - Text( - "Verify OTP", - textAlign: TextAlign.center, - style: GoogleFonts.poppins( - color: AppColors.black, - fontSize: 24.sp, - fontWeight: FontWeight.w600, - ), + // ===== HEADER TEXT ===== + Text( + "Verify OTP", + textAlign: TextAlign.center, + style: GoogleFonts.poppins( + color: AppColors.black, + fontSize: 24.sp, + fontWeight: FontWeight.w600, ), - SizedBox(height: 12.h), - Text( - "We've sent an OTP to your registered email. Please enter it below.", - textAlign: TextAlign.center, - style: GoogleFonts.poppins( - color: AppColors.textGrey, - fontSize: 16.sp, - height: 1.4, - ), + ), + SizedBox(height: 12.h), + Text( + "We've sent an OTP to your registered email. Please enter it below.", + textAlign: TextAlign.center, + style: GoogleFonts.poppins( + color: AppColors.textGrey, + fontSize: 16.sp, + height: 1.4, ), - SizedBox(height: 48.h), + ), + SizedBox(height: 48.h), - // ===== OTP INPUT FIELDS ===== - OtpTextField( - numberOfFields: 6, - borderColor: AppColors.borderGrey, - focusedBorderColor: AppColors.primaryRed, - showFieldAsBox: true, - fieldWidth: 45.w, - borderRadius: BorderRadius.circular(12.r), - enabledBorderColor: AppColors.borderGrey, - cursorColor: AppColors.primaryRed, + // ===== OTP INPUT FIELDS ===== + Pinput( + length: 6, + defaultPinTheme: PinTheme( + width: 48.w, + height: 52.h, textStyle: GoogleFonts.poppins( fontSize: 18.sp, fontWeight: FontWeight.w600, color: AppColors.black, ), - onCodeChanged: (String code) { - context.read().add( - OtpChanged(otp: code), - ); - }, - onSubmit: (String verificationCode) { - if (isLoading) return; - context.read().add( - OtpChanged(otp: verificationCode), - ); - context.read().add( - VerifyOtpSubmitted( - emailAddress: email, - otp: verificationCode, - ), - ); - }, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12.r), + border: Border.all(color: AppColors.borderGrey), + ), ), - ], - ), - ), - ), - - // ===== VERIFY BUTTON ===== - CustomButton( - text: "Verify", - isLoading: isLoading, - onPressed: state.otp.length == 6 && !isLoading - ? () { + focusedPinTheme: PinTheme( + width: 48.w, + height: 52.h, + textStyle: GoogleFonts.poppins( + fontSize: 18.sp, + fontWeight: FontWeight.w600, + color: AppColors.black, + ), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12.r), + border: Border.all(color: AppColors.primaryRed), + ), + ), + submittedPinTheme: PinTheme( + width: 48.w, + height: 52.h, + textStyle: GoogleFonts.poppins( + fontSize: 18.sp, + fontWeight: FontWeight.w600, + color: AppColors.black, + ), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12.r), + border: Border.all(color: AppColors.borderGrey), + ), + ), + onChanged: (String code) { + context.read().add( + OtpChanged(otp: code), + ); + }, + onCompleted: (String verificationCode) { context.read().add( VerifyOtpSubmitted( emailAddress: email, - otp: state.otp, + otp: verificationCode, ), ); - } - : null, + }, + ), + ], + ), ), - SizedBox(height: 24.h), - ], - ), + ), + + // ===== VERIFY BUTTON ===== + BlocBuilder( + buildWhen: (previous, current) => + previous.otp.length != current.otp.length || + previous.status != current.status, + builder: (context, state) { + final isLoading = state.status == VerifyOtpStatus.loading; + return CustomButton( + text: "Verify", + isLoading: isLoading, + onPressed: state.otp.length == 6 && !isLoading + ? () { + context.read().add( + VerifyOtpSubmitted( + emailAddress: email, + otp: state.otp, + ), + ); + } + : null, + ); + }, + ), + SizedBox(height: 24.h), + ], ), - ); - }, + ), + ), ), ), ); diff --git a/lib/login/views/reset_password_page.dart b/lib/login/views/reset_password_page.dart index f4227cc..5a9ec07 100644 --- a/lib/login/views/reset_password_page.dart +++ b/lib/login/views/reset_password_page.dart @@ -70,6 +70,29 @@ class _ResetPasswordPageState extends State { behavior: HitTestBehavior.translucent, child: Scaffold( backgroundColor: AppColors.backgroundWhite, + appBar: AppBar( + backgroundColor: Colors.transparent, + elevation: 0, + leadingWidth: 70.w, + leading: Padding( + padding: EdgeInsets.only(left: 24.w, top: 8.h, bottom: 8.h), + child: InkWell( + onTap: () => Navigator.pop(context), + borderRadius: BorderRadius.circular(50), + child: Container( + decoration: const BoxDecoration( + color: AppColors.primaryRed, + shape: BoxShape.circle, + ), + child: Icon( + Icons.arrow_back_ios_new, + color: Colors.white, + size: 18.sp, + ), + ), + ), + ), + ), body: BlocConsumer( listener: (context, state) { if (state.status == ResetPasswordStatus.success) { @@ -105,7 +128,7 @@ class _ResetPasswordPageState extends State { child: SingleChildScrollView( child: Column( children: [ - SizedBox(height: 40.h), + SizedBox(height: 10.h), // ===== LOGO SECTION ===== Center( child: Column( diff --git a/pubspec.lock b/pubspec.lock index b1995be..728c1ac 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -270,14 +270,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.4.7" - flutter_otp_text_field: - dependency: "direct main" - description: - name: flutter_otp_text_field - sha256: e7e589dc51cde120d63da6db55f3cef618f5d013d12adba76137ca1a51ce1390 - url: "https://pub.dev" - source: hosted - version: "1.5.1+1" flutter_plugin_android_lifecycle: dependency: transitive description: @@ -460,10 +452,10 @@ packages: dependency: transitive description: name: matcher - sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861 + sha256: "12956d0ad8390bbcc63ca2e1469c0619946ccb52809807067a7020d57e647aa6" url: "https://pub.dev" source: hosted - version: "0.12.19" + version: "0.12.18" material_color_utilities: dependency: transitive description: @@ -568,6 +560,14 @@ packages: url: "https://pub.dev" source: hosted version: "7.0.1" + pinput: + dependency: "direct main" + description: + name: pinput + sha256: "4c3f1b84768b47a56a1abdaca551bd7cef4ac673b882209039ecdf803a5d6e68" + url: "https://pub.dev" + source: hosted + version: "6.0.2" platform: dependency: transitive description: @@ -737,10 +737,10 @@ packages: dependency: transitive description: name: test_api - sha256: "8161c84903fd860b26bfdefb7963b3f0b68fee7adea0f59ef805ecca346f0c7a" + sha256: "93167629bfc610f71560ab9312acdda4959de4df6fac7492c89ff0d3886f6636" url: "https://pub.dev" source: hosted - version: "0.7.10" + version: "0.7.9" typed_data: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 38c6fa0..ac32c28 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -37,7 +37,6 @@ dependencies: cupertino_icons: ^1.0.8 google_fonts: ^6.3.2 flutter_bloc: ^9.1.1 - flutter_otp_text_field: ^1.5.1+1 intl: ^0.20.2 table_calendar: ^3.2.0 file_picker: ^10.3.3 @@ -52,6 +51,7 @@ dependencies: dio_cookie_manager: ^3.4.0 cookie_jar: ^4.0.9 image_picker: ^1.2.1 + pinput: ^6.0.2 dev_dependencies: flutter_test: