Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ae0928d914 | ||
|
|
79816d3066 |
@@ -20,7 +20,5 @@
|
|||||||
<string>????</string>
|
<string>????</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>1.0</string>
|
<string>1.0</string>
|
||||||
<key>MinimumOSVersion</key>
|
|
||||||
<string>13.0</string>
|
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ PODS:
|
|||||||
- Flutter (1.0.0)
|
- Flutter (1.0.0)
|
||||||
- flutter_native_splash (2.4.3):
|
- flutter_native_splash (2.4.3):
|
||||||
- Flutter
|
- Flutter
|
||||||
|
- image_picker_ios (0.0.1):
|
||||||
|
- Flutter
|
||||||
- mobile_scanner (7.0.0):
|
- mobile_scanner (7.0.0):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
@@ -54,6 +56,7 @@ DEPENDENCIES:
|
|||||||
- file_picker (from `.symlinks/plugins/file_picker/ios`)
|
- file_picker (from `.symlinks/plugins/file_picker/ios`)
|
||||||
- Flutter (from `Flutter`)
|
- Flutter (from `Flutter`)
|
||||||
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
|
- 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`)
|
- mobile_scanner (from `.symlinks/plugins/mobile_scanner/darwin`)
|
||||||
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
|
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
|
||||||
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||||
@@ -72,6 +75,8 @@ EXTERNAL SOURCES:
|
|||||||
:path: Flutter
|
:path: Flutter
|
||||||
flutter_native_splash:
|
flutter_native_splash:
|
||||||
:path: ".symlinks/plugins/flutter_native_splash/ios"
|
:path: ".symlinks/plugins/flutter_native_splash/ios"
|
||||||
|
image_picker_ios:
|
||||||
|
:path: ".symlinks/plugins/image_picker_ios/ios"
|
||||||
mobile_scanner:
|
mobile_scanner:
|
||||||
:path: ".symlinks/plugins/mobile_scanner/darwin"
|
:path: ".symlinks/plugins/mobile_scanner/darwin"
|
||||||
path_provider_foundation:
|
path_provider_foundation:
|
||||||
@@ -82,13 +87,14 @@ EXTERNAL SOURCES:
|
|||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
|
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
|
||||||
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
|
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
|
||||||
file_picker: a0560bc09d61de87f12d246fc47d2119e6ef37be
|
file_picker: b159e0c068aef54932bb15dc9fd1571818edaf49
|
||||||
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
|
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
|
||||||
flutter_native_splash: c32d145d68aeda5502d5f543ee38c192065986cf
|
flutter_native_splash: df59bb2e1421aa0282cb2e95618af4dcb0c56c29
|
||||||
mobile_scanner: 9157936403f5a0644ca3779a38ff8404c5434a93
|
image_picker_ios: 4f2f91b01abdb52842a8e277617df877e40f905b
|
||||||
path_provider_foundation: bb55f6dbba17d0dccd6737fe6f7f34fbd0376880
|
mobile_scanner: 77265f3dc8d580810e91849d4a0811a90467ed5e
|
||||||
|
path_provider_foundation: 0b743cbb62d8e47eab856f09262bb8c1ddcfe6ba
|
||||||
SDWebImage: 16309af6d214ba3f77a7c6f6fdda888cb313a50a
|
SDWebImage: 16309af6d214ba3f77a7c6f6fdda888cb313a50a
|
||||||
shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb
|
shared_preferences_foundation: 5086985c1d43c5ba4d5e69a4e8083a389e2909e6
|
||||||
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
|
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
|
||||||
|
|
||||||
PODFILE CHECKSUM: 251cb053df7158f337c0712f2ab29f4e0fa474ce
|
PODFILE CHECKSUM: 251cb053df7158f337c0712f2ab29f4e0fa474ce
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<Scheme
|
<Scheme
|
||||||
LastUpgradeVersion = "1610"
|
LastUpgradeVersion = "1510"
|
||||||
version = "1.3">
|
version = "1.3">
|
||||||
<BuildAction
|
<BuildAction
|
||||||
parallelizeBuildables = "YES"
|
parallelizeBuildables = "YES"
|
||||||
|
|||||||
@@ -2,12 +2,15 @@ import Flutter
|
|||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
@main
|
@main
|
||||||
@objc class AppDelegate: FlutterAppDelegate {
|
@objc class AppDelegate: FlutterAppDelegate, FlutterImplicitEngineDelegate {
|
||||||
override func application(
|
override func application(
|
||||||
_ application: UIApplication,
|
_ application: UIApplication,
|
||||||
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
||||||
) -> Bool {
|
) -> Bool {
|
||||||
GeneratedPluginRegistrant.register(with: self)
|
|
||||||
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func didInitializeImplicitFlutterEngine(_ engineBridge: FlutterImplicitEngineBridge) {
|
||||||
|
GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,27 @@
|
|||||||
<string>This app needs camera access to scan QR codes</string>
|
<string>This app needs camera access to scan QR codes</string>
|
||||||
<key>NSPhotoLibraryUsageDescription</key>
|
<key>NSPhotoLibraryUsageDescription</key>
|
||||||
<string>This app needs photos access to get QR code from photo library</string>
|
<string>This app needs photos access to get QR code from photo library</string>
|
||||||
|
<key>UIApplicationSceneManifest</key>
|
||||||
|
<dict>
|
||||||
|
<key>UIApplicationSupportsMultipleScenes</key>
|
||||||
|
<false/>
|
||||||
|
<key>UISceneConfigurations</key>
|
||||||
|
<dict>
|
||||||
|
<key>UIWindowSceneSessionRoleApplication</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>UISceneClassName</key>
|
||||||
|
<string>UIWindowScene</string>
|
||||||
|
<key>UISceneConfigurationName</key>
|
||||||
|
<string>flutter</string>
|
||||||
|
<key>UISceneDelegateClassName</key>
|
||||||
|
<string>FlutterSceneDelegate</string>
|
||||||
|
<key>UISceneStoryboardFile</key>
|
||||||
|
<string>Main</string>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>UILaunchStoryboardName</key>
|
<key>UILaunchStoryboardName</key>
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> {
|
|||||||
on<LoginRememberMeToggled>(_onRememberMeToggled);
|
on<LoginRememberMeToggled>(_onRememberMeToggled);
|
||||||
on<LoginEmailErrorToggled>(_onEmailErrorToggled);
|
on<LoginEmailErrorToggled>(_onEmailErrorToggled);
|
||||||
on<LoginPasswordErrorToggled>(_onPasswordErrorToggled);
|
on<LoginPasswordErrorToggled>(_onPasswordErrorToggled);
|
||||||
|
on<LoginReset>(_onReset);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ================= LOGIN SUBMITTED =================
|
// ================= LOGIN SUBMITTED =================
|
||||||
@@ -87,4 +88,11 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> {
|
|||||||
) {
|
) {
|
||||||
emit(state.copyWith(showPasswordError: event.show));
|
emit(state.copyWith(showPasswordError: event.show));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _onReset(
|
||||||
|
LoginReset event,
|
||||||
|
Emitter<LoginState> emit,
|
||||||
|
) {
|
||||||
|
emit(const LoginState());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -42,6 +42,10 @@ class LoginEmailErrorToggled extends LoginEvent {
|
|||||||
List<Object?> get props => [show];
|
List<Object?> get props => [show];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class LoginReset extends LoginEvent {
|
||||||
|
const LoginReset();
|
||||||
|
}
|
||||||
|
|
||||||
class LoginPasswordErrorToggled extends LoginEvent {
|
class LoginPasswordErrorToggled extends LoginEvent {
|
||||||
final bool show;
|
final bool show;
|
||||||
const LoginPasswordErrorToggled(this.show);
|
const LoginPasswordErrorToggled(this.show);
|
||||||
|
|||||||
@@ -62,6 +62,29 @@ class _ForgotPasswordPageState extends State<ForgotPasswordPage> {
|
|||||||
behavior: HitTestBehavior.translucent,
|
behavior: HitTestBehavior.translucent,
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
backgroundColor: AppColors.backgroundWhite,
|
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<ForgotPasswordBloc, ForgotPasswordState>(
|
body: BlocConsumer<ForgotPasswordBloc, ForgotPasswordState>(
|
||||||
listener: (context, state) {
|
listener: (context, state) {
|
||||||
if (state.status == ForgotPasswordStatus.success) {
|
if (state.status == ForgotPasswordStatus.success) {
|
||||||
@@ -97,7 +120,7 @@ class _ForgotPasswordPageState extends State<ForgotPasswordPage> {
|
|||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
SizedBox(height: 40.h),
|
SizedBox(height: 10.h),
|
||||||
// ===== LOGO SECTION =====
|
// ===== LOGO SECTION =====
|
||||||
Center(
|
Center(
|
||||||
child: Column(
|
child: Column(
|
||||||
|
|||||||
@@ -22,6 +22,12 @@ class _LoginPageState extends State<LoginPage> {
|
|||||||
final _emailFocusNode = FocusNode();
|
final _emailFocusNode = FocusNode();
|
||||||
final _passwordFocusNode = FocusNode();
|
final _passwordFocusNode = FocusNode();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
context.read<LoginBloc>().add(const LoginReset());
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_emailController.dispose();
|
_emailController.dispose();
|
||||||
@@ -32,9 +38,7 @@ class _LoginPageState extends State<LoginPage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool _isEmailValid(String email) {
|
bool _isEmailValid(String email) {
|
||||||
return RegExp(
|
return RegExp(r'^[\w-\.]+@([\w-]+\.)+[a-zA-Z]{2,4}$').hasMatch(email);
|
||||||
r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$')
|
|
||||||
.hasMatch(email);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onLoginPressed(BuildContext context) {
|
void _onLoginPressed(BuildContext context) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.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:flutter_screenutil/flutter_screenutil.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
import '../../constants/app_assets.dart';
|
import '../../constants/app_assets.dart';
|
||||||
@@ -21,7 +21,30 @@ class OtpVerificationPage extends StatelessWidget {
|
|||||||
behavior: HitTestBehavior.translucent,
|
behavior: HitTestBehavior.translucent,
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
backgroundColor: AppColors.backgroundWhite,
|
backgroundColor: AppColors.backgroundWhite,
|
||||||
body: BlocConsumer<VerifyOtpBloc, VerifyOtpState>(
|
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<VerifyOtpBloc, VerifyOtpState>(
|
||||||
listener: (context, state) {
|
listener: (context, state) {
|
||||||
if (state.status == VerifyOtpStatus.success) {
|
if (state.status == VerifyOtpStatus.success) {
|
||||||
Navigator.pushReplacementNamed(
|
Navigator.pushReplacementNamed(
|
||||||
@@ -39,10 +62,7 @@ class OtpVerificationPage extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
builder: (context, state) {
|
child: SafeArea(
|
||||||
final isLoading = state.status == VerifyOtpStatus.loading;
|
|
||||||
|
|
||||||
return SafeArea(
|
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: EdgeInsets.symmetric(horizontal: 24.w),
|
padding: EdgeInsets.symmetric(horizontal: 24.w),
|
||||||
child: Column(
|
child: Column(
|
||||||
@@ -51,7 +71,7 @@ class OtpVerificationPage extends StatelessWidget {
|
|||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
SizedBox(height: 40.h),
|
SizedBox(height: 10.h),
|
||||||
// ===== LOGO SECTION =====
|
// ===== LOGO SECTION =====
|
||||||
Center(
|
Center(
|
||||||
child: Column(
|
child: Column(
|
||||||
@@ -97,30 +117,53 @@ class OtpVerificationPage extends StatelessWidget {
|
|||||||
SizedBox(height: 48.h),
|
SizedBox(height: 48.h),
|
||||||
|
|
||||||
// ===== OTP INPUT FIELDS =====
|
// ===== OTP INPUT FIELDS =====
|
||||||
OtpTextField(
|
Pinput(
|
||||||
numberOfFields: 6,
|
length: 6,
|
||||||
borderColor: AppColors.borderGrey,
|
defaultPinTheme: PinTheme(
|
||||||
focusedBorderColor: AppColors.primaryRed,
|
width: 48.w,
|
||||||
showFieldAsBox: true,
|
height: 52.h,
|
||||||
fieldWidth: 45.w,
|
|
||||||
borderRadius: BorderRadius.circular(12.r),
|
|
||||||
enabledBorderColor: AppColors.borderGrey,
|
|
||||||
cursorColor: AppColors.primaryRed,
|
|
||||||
textStyle: GoogleFonts.poppins(
|
textStyle: GoogleFonts.poppins(
|
||||||
fontSize: 18.sp,
|
fontSize: 18.sp,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: AppColors.black,
|
color: AppColors.black,
|
||||||
),
|
),
|
||||||
onCodeChanged: (String code) {
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(12.r),
|
||||||
|
border: Border.all(color: AppColors.borderGrey),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
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<VerifyOtpBloc>().add(
|
context.read<VerifyOtpBloc>().add(
|
||||||
OtpChanged(otp: code),
|
OtpChanged(otp: code),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
onSubmit: (String verificationCode) {
|
onCompleted: (String verificationCode) {
|
||||||
if (isLoading) return;
|
|
||||||
context.read<VerifyOtpBloc>().add(
|
|
||||||
OtpChanged(otp: verificationCode),
|
|
||||||
);
|
|
||||||
context.read<VerifyOtpBloc>().add(
|
context.read<VerifyOtpBloc>().add(
|
||||||
VerifyOtpSubmitted(
|
VerifyOtpSubmitted(
|
||||||
emailAddress: email,
|
emailAddress: email,
|
||||||
@@ -135,7 +178,13 @@ class OtpVerificationPage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
|
|
||||||
// ===== VERIFY BUTTON =====
|
// ===== VERIFY BUTTON =====
|
||||||
CustomButton(
|
BlocBuilder<VerifyOtpBloc, VerifyOtpState>(
|
||||||
|
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",
|
text: "Verify",
|
||||||
isLoading: isLoading,
|
isLoading: isLoading,
|
||||||
onPressed: state.otp.length == 6 && !isLoading
|
onPressed: state.otp.length == 6 && !isLoading
|
||||||
@@ -148,13 +197,14 @@ class OtpVerificationPage extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
SizedBox(height: 24.h),
|
SizedBox(height: 24.h),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
),
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -70,6 +70,29 @@ class _ResetPasswordPageState extends State<ResetPasswordPage> {
|
|||||||
behavior: HitTestBehavior.translucent,
|
behavior: HitTestBehavior.translucent,
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
backgroundColor: AppColors.backgroundWhite,
|
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<ResetPasswordBloc, ResetPasswordState>(
|
body: BlocConsumer<ResetPasswordBloc, ResetPasswordState>(
|
||||||
listener: (context, state) {
|
listener: (context, state) {
|
||||||
if (state.status == ResetPasswordStatus.success) {
|
if (state.status == ResetPasswordStatus.success) {
|
||||||
@@ -105,7 +128,7 @@ class _ResetPasswordPageState extends State<ResetPasswordPage> {
|
|||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
SizedBox(height: 40.h),
|
SizedBox(height: 10.h),
|
||||||
// ===== LOGO SECTION =====
|
// ===== LOGO SECTION =====
|
||||||
Center(
|
Center(
|
||||||
child: Column(
|
child: Column(
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
class ApiUrls {
|
class ApiUrls {
|
||||||
|
|
||||||
// static const baseUrl = "https://devapi.citycards.betadelivery.com"; // Normal API
|
// static const baseUrl = "https://devapi.citycards.betadelivery.com"; // Normal API
|
||||||
static const baseUrl = "https://testingapi.citycards.betadelivery.com"; // Test API
|
// static const baseUrl = "https://testingapi.citycards.betadelivery.com"; // Test API
|
||||||
// static const baseUrl = "https://uatapi.citycard.betadelivery.com"; // Production Lvl API
|
static const baseUrl = "https://uatapi.citycard.betadelivery.com"; // Production Lvl API
|
||||||
|
|
||||||
static const refreshToken = "$baseUrl/partner/auth/refresh";
|
static const refreshToken = "$baseUrl/partner/auth/refresh";
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import '../blocs/profile/profile_bloc.dart';
|
|||||||
import '../blocs/profile/profile_event.dart';
|
import '../blocs/profile/profile_event.dart';
|
||||||
import '../blocs/profile/profile_state.dart';
|
import '../blocs/profile/profile_state.dart';
|
||||||
import '../models/profile_model.dart'; // Import UserDetails model
|
import '../models/profile_model.dart'; // Import UserDetails model
|
||||||
|
import '../../login/blocs/login/login_bloc.dart';
|
||||||
|
|
||||||
class ProfileScreen extends StatelessWidget {
|
class ProfileScreen extends StatelessWidget {
|
||||||
const ProfileScreen({super.key});
|
const ProfileScreen({super.key});
|
||||||
@@ -192,6 +193,7 @@ class ProfileScreen extends StatelessWidget {
|
|||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
LocalPreference.clearAllExceptOnBoarding();
|
LocalPreference.clearAllExceptOnBoarding();
|
||||||
|
context.read<LoginBloc>().add(const LoginReset());
|
||||||
Navigator.pushNamedAndRemoveUntil(
|
Navigator.pushNamedAndRemoveUntil(
|
||||||
context,
|
context,
|
||||||
AppRouter.login,
|
AppRouter.login,
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ class SubmitQrCodeBloc
|
|||||||
SubmitQrCodeEventTriggered event,
|
SubmitQrCodeEventTriggered event,
|
||||||
Emitter<SubmitQrCodeState> emit,
|
Emitter<SubmitQrCodeState> emit,
|
||||||
) async {
|
) async {
|
||||||
|
if (state is SubmitQrCodeLoading) return;
|
||||||
if (event.qrCode.trim().isEmpty) {
|
if (event.qrCode.trim().isEmpty) {
|
||||||
emit(const SubmitQrCodeFailure(
|
emit(const SubmitQrCodeFailure(
|
||||||
errorMessage: 'QR code cannot be empty'));
|
errorMessage: 'QR code cannot be empty'));
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ class _QrScanScreenState extends State<QrScanScreen>
|
|||||||
late MobileScannerController _cameraController;
|
late MobileScannerController _cameraController;
|
||||||
final ValueNotifier<bool> _isTorchOn = ValueNotifier(false);
|
final ValueNotifier<bool> _isTorchOn = ValueNotifier(false);
|
||||||
bool _cameraAvailable = true;
|
bool _cameraAvailable = true;
|
||||||
|
bool _isScanProcessing = false;
|
||||||
|
|
||||||
final sheetContentKey = GlobalKey();
|
final sheetContentKey = GlobalKey();
|
||||||
final ValueNotifier<double> sheetExtent = ValueNotifier(0.5);
|
final ValueNotifier<double> sheetExtent = ValueNotifier(0.5);
|
||||||
@@ -85,6 +86,7 @@ class _QrScanScreenState extends State<QrScanScreen>
|
|||||||
if (!mounted || !_cameraAvailable) return;
|
if (!mounted || !_cameraAvailable) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
_isScanProcessing = false; // Reset flag when camera starts
|
||||||
if (!_cameraController.value.isStarting) {
|
if (!_cameraController.value.isStarting) {
|
||||||
await _cameraController.start();
|
await _cameraController.start();
|
||||||
}
|
}
|
||||||
@@ -182,11 +184,14 @@ class _QrScanScreenState extends State<QrScanScreen>
|
|||||||
controller: _cameraController,
|
controller: _cameraController,
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
onDetect: (capture) {
|
onDetect: (capture) {
|
||||||
|
if (_isScanProcessing) return;
|
||||||
|
|
||||||
final barcode =
|
final barcode =
|
||||||
capture.barcodes.first.rawValue ?? '';
|
capture.barcodes.first.rawValue ?? '';
|
||||||
if (barcode.isNotEmpty &&
|
if (barcode.isNotEmpty &&
|
||||||
state is! SubmitQrCodeLoading &&
|
state is! SubmitQrCodeLoading &&
|
||||||
state is SubmitQrCodeInitial) {
|
state is SubmitQrCodeInitial) {
|
||||||
|
_isScanProcessing = true;
|
||||||
final extractedCode = _extractQrCode(barcode);
|
final extractedCode = _extractQrCode(barcode);
|
||||||
_cameraController.stop();
|
_cameraController.stop();
|
||||||
context.read<SubmitQrCodeBloc>().add(
|
context.read<SubmitQrCodeBloc>().add(
|
||||||
|
|||||||
24
pubspec.lock
24
pubspec.lock
@@ -270,14 +270,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.4.7"
|
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:
|
flutter_plugin_android_lifecycle:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -460,10 +452,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: matcher
|
name: matcher
|
||||||
sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861
|
sha256: "12956d0ad8390bbcc63ca2e1469c0619946ccb52809807067a7020d57e647aa6"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.12.19"
|
version: "0.12.18"
|
||||||
material_color_utilities:
|
material_color_utilities:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -568,6 +560,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "7.0.1"
|
version: "7.0.1"
|
||||||
|
pinput:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: pinput
|
||||||
|
sha256: "4c3f1b84768b47a56a1abdaca551bd7cef4ac673b882209039ecdf803a5d6e68"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "6.0.2"
|
||||||
platform:
|
platform:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -737,10 +737,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: test_api
|
name: test_api
|
||||||
sha256: "8161c84903fd860b26bfdefb7963b3f0b68fee7adea0f59ef805ecca346f0c7a"
|
sha256: "93167629bfc610f71560ab9312acdda4959de4df6fac7492c89ff0d3886f6636"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.7.10"
|
version: "0.7.9"
|
||||||
typed_data:
|
typed_data:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -37,7 +37,6 @@ dependencies:
|
|||||||
cupertino_icons: ^1.0.8
|
cupertino_icons: ^1.0.8
|
||||||
google_fonts: ^6.3.2
|
google_fonts: ^6.3.2
|
||||||
flutter_bloc: ^9.1.1
|
flutter_bloc: ^9.1.1
|
||||||
flutter_otp_text_field: ^1.5.1+1
|
|
||||||
intl: ^0.20.2
|
intl: ^0.20.2
|
||||||
table_calendar: ^3.2.0
|
table_calendar: ^3.2.0
|
||||||
file_picker: ^10.3.3
|
file_picker: ^10.3.3
|
||||||
@@ -52,6 +51,7 @@ dependencies:
|
|||||||
dio_cookie_manager: ^3.4.0
|
dio_cookie_manager: ^3.4.0
|
||||||
cookie_jar: ^4.0.9
|
cookie_jar: ^4.0.9
|
||||||
image_picker: ^1.2.1
|
image_picker: ^1.2.1
|
||||||
|
pinput: ^6.0.2
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|||||||
Reference in New Issue
Block a user