From 1f5a119c6091bee1f4a8cfb5319566e88458b17f Mon Sep 17 00:00:00 2001 From: mohammad Date: Tue, 6 Aug 2024 11:21:14 +0300 Subject: [PATCH] Home page --- lib/main.dart | 5 + lib/pages/auth/bloc/auth_bloc.dart | 36 +- lib/pages/auth/bloc/auth_event.dart | 7 +- lib/pages/auth/bloc/auth_state.dart | 4 +- lib/pages/auth/model/region_model.dart | 25 + .../auth/view/forget_password_web_page.dart | 405 ++++++------- lib/pages/auth/view/login_mobile_page.dart | 87 +-- lib/pages/auth/view/login_web_page.dart | 559 +++++++----------- lib/services/api/http_interceptor.dart | 1 + lib/services/auth_api.dart | 56 +- lib/utils/constants/api_const.dart | 1 + 11 files changed, 521 insertions(+), 665 deletions(-) create mode 100644 lib/pages/auth/model/region_model.dart diff --git a/lib/main.dart b/lib/main.dart index 379442f2..6a3f450f 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -33,6 +33,11 @@ class MyApp extends StatelessWidget { }, ), theme: ThemeData( + textTheme: const TextTheme( + bodySmall:TextStyle(), + bodyLarge:TextStyle(), + bodyMedium:TextStyle(), + ), colorScheme: ColorScheme.fromSeed( seedColor: Colors.deepPurple), // Set up color scheme useMaterial3: true, // Enable Material 3 diff --git a/lib/pages/auth/bloc/auth_bloc.dart b/lib/pages/auth/bloc/auth_bloc.dart index c1e21c71..e7b752f8 100644 --- a/lib/pages/auth/bloc/auth_bloc.dart +++ b/lib/pages/auth/bloc/auth_bloc.dart @@ -1,11 +1,11 @@ import 'dart:async'; -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:syncrow_web/pages/auth/bloc/auth_event.dart'; import 'package:syncrow_web/pages/auth/bloc/auth_state.dart'; import 'package:syncrow_web/pages/auth/model/login_with_email_model.dart'; +import 'package:syncrow_web/pages/auth/model/region_model.dart'; import 'package:syncrow_web/pages/auth/model/token.dart'; import 'package:syncrow_web/pages/auth/model/user_model.dart'; import 'package:syncrow_web/services/auth_api.dart'; @@ -22,35 +22,32 @@ class AuthBloc extends Bloc { on(_onStopTimer); on(_onUpdateTimer); on(_passwordVisible); + on(_fetchRegion); } -////////////////////////////// forget password ////////////////////////////////// + ////////////////////////////// forget password ////////////////////////////////// final TextEditingController forgetEmailController = TextEditingController(); final TextEditingController forgetPasswordController = TextEditingController(); final TextEditingController forgetOtp = TextEditingController(); final forgetFormKey = GlobalKey(); Timer? _timer; int _remainingTime = 0; + List? regionList; Future _onStartTimer(StartTimerEvent event, Emitter emit) async { if (_validateInputs(emit)) return; - print("StartTimerEvent received"); if (_timer != null && _timer!.isActive) { - print("Timer is already active"); return; } _remainingTime = 60; add(UpdateTimerEvent( remainingTime: _remainingTime, isButtonEnabled: false)); - print("Timer started, initial remaining time: $_remainingTime"); await AuthenticationAPI.sendOtp(email: forgetEmailController.text); _timer = Timer.periodic(const Duration(seconds: 1), (timer) { _remainingTime--; - print("Timer tick, remaining time: $_remainingTime"); // Debug print if (_remainingTime <= 0) { _timer?.cancel(); add(const UpdateTimerEvent(remainingTime: 0, isButtonEnabled: true)); - print("Timer finished"); // Debug print } else { add(UpdateTimerEvent( remainingTime: _remainingTime, isButtonEnabled: false)); @@ -92,8 +89,6 @@ class AuthBloc extends Bloc { - - ///////////////////////////////////// login ///////////////////////////////////// final TextEditingController loginEmailController = TextEditingController(); final TextEditingController loginPasswordController = TextEditingController(); @@ -108,7 +103,7 @@ class AuthBloc extends Bloc { bool showValidationMessage = false; void _login(LoginButtonPressed event, Emitter emit) async { - emit(LoginLoading()); + emit(AuthLoading()); if (isChecked) { try { if (event.username.isEmpty || event.password.isEmpty) { @@ -128,7 +123,6 @@ class AuthBloc extends Bloc { return; } if (token.accessTokenIsNotEmpty) { - debugPrint('token: ${token.accessToken}'); FlutterSecureStorage storage = const FlutterSecureStorage(); await storage.write( key: Token.loginAccessTokenKey, value: token.accessToken); @@ -148,7 +142,7 @@ class AuthBloc extends Bloc { } checkBoxToggle(CheckBoxEvent event, Emitter emit,) { - emit(LoginLoading()); + emit(AuthLoading()); isChecked = event.newValue!; emit(LoginInitial()); } @@ -161,15 +155,13 @@ class AuthBloc extends Bloc { } void _passwordVisible(PasswordVisibleEvent event, Emitter emit) { - emit(LoginLoading()); + emit(AuthLoading()); obscureText = !event.newValue!; emit(PasswordVisibleState()); } void launchURL(String url) { - if (kDebugMode) { - print('Launching URL: $url'); - } + } @@ -320,6 +312,18 @@ class AuthBloc extends Bloc { } } + void _fetchRegion(RegionInitialEvent event, Emitter emit) async { + try { + emit(AuthLoading()); + regionList = await AuthenticationAPI.fetchRegion(); + emit(LoginSuccess()); + } catch (e) { + emit( LoginFailure(error: e.toString())); + + } + } + + } diff --git a/lib/pages/auth/bloc/auth_event.dart b/lib/pages/auth/bloc/auth_event.dart index cdcfc51e..8a410555 100644 --- a/lib/pages/auth/bloc/auth_event.dart +++ b/lib/pages/auth/bloc/auth_event.dart @@ -17,7 +17,6 @@ class LoginButtonPressed extends AuthEvent { List get props => [username, password]; } - class CheckBoxEvent extends AuthEvent { final bool? newValue; @@ -49,4 +48,8 @@ class PasswordVisibleEvent extends AuthEvent{ final bool? newValue; const PasswordVisibleEvent({required this.newValue,}); -} \ No newline at end of file +} + +class RegionInitialEvent extends AuthEvent {} + +class SelectRegionEvent extends AuthEvent {} diff --git a/lib/pages/auth/bloc/auth_state.dart b/lib/pages/auth/bloc/auth_state.dart index 4620c722..9814955a 100644 --- a/lib/pages/auth/bloc/auth_state.dart +++ b/lib/pages/auth/bloc/auth_state.dart @@ -11,7 +11,7 @@ class LoginInitial extends AuthState {} class AuthTokenLoading extends AuthState {} -class LoginLoading extends AuthState {} +class AuthLoading extends AuthState {} class LoginSuccess extends AuthState {} @@ -74,5 +74,3 @@ class AuthSuccess extends AuthState {} class AuthTokenSuccess extends AuthSuccess {} - -// class AuthState extends AuthState {} diff --git a/lib/pages/auth/model/region_model.dart b/lib/pages/auth/model/region_model.dart new file mode 100644 index 00000000..fd6306a2 --- /dev/null +++ b/lib/pages/auth/model/region_model.dart @@ -0,0 +1,25 @@ + + +class RegionModel { + final String name; + final String id; + + RegionModel({ + required this.name, + required this.id, + }); + + factory RegionModel.fromJson(Map json) { + return RegionModel( + name: json['regionName'], + id: json['uuid'].toString(), // Ensure id is a String + ); + } + + Map toJson() { + return { + 'regionName': name, + 'uuid': id, + }; + } +} diff --git a/lib/pages/auth/view/forget_password_web_page.dart b/lib/pages/auth/view/forget_password_web_page.dart index 87ca4dee..2ed8bb4b 100644 --- a/lib/pages/auth/view/forget_password_web_page.dart +++ b/lib/pages/auth/view/forget_password_web_page.dart @@ -19,9 +19,7 @@ class ForgetPasswordWebPage extends StatelessWidget { create: (context) => AuthBloc(), child: BlocConsumer( listener: (context, state) { - if (state is LoadingForgetState) { - - } else if (state is SuccessForgetState){ + if (state is SuccessForgetState){ Navigator.of(context).pop(); } else if (state is FailureForgetState) { @@ -47,232 +45,237 @@ class ForgetPasswordWebPage extends StatelessWidget { Widget _buildForm(BuildContext context, AuthState state) { final forgetBloc = BlocProvider.of(context); return FirstLayer( - second: Container( - padding:const EdgeInsets.all(50) , - margin: const EdgeInsets.all(50), - decoration: BoxDecoration( - color: Colors.black.withOpacity(0.3), - borderRadius: const BorderRadius.all(Radius.circular(20)), - ), - child: Center( - child: ListView( - shrinkWrap: true, - children: [ - Row( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Spacer(), - Expanded( - flex: 2, - child: SvgPicture.asset( - Assets.loginLogo, + second: Center( + child: ListView( + children: [ + Container( + padding:const EdgeInsets.all(50) , + margin: const EdgeInsets.all(90), + decoration: BoxDecoration( + color: Colors.black.withOpacity(0.3), + borderRadius: const BorderRadius.all(Radius.circular(20)), + ), + child: Center( + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Spacer(), + Expanded( + flex: 3, + child: SvgPicture.asset( + Assets.loginLogo, + ), ), - ), - const Spacer(), - Container( - decoration: BoxDecoration( - color: Colors.white.withOpacity(0.1), - borderRadius: const BorderRadius.all(Radius.circular(30)), - border: Border.all(color: ColorsManager.graysColor.withOpacity(0.2)), - ), - child: Form( - key: forgetBloc.forgetFormKey, - child: Padding( - - padding: const EdgeInsets.symmetric(horizontal: 40, vertical: 25), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const SizedBox(height: 10), - const Text( - 'Forget Password', - style: TextStyle( - color: Colors.white, - fontSize: 24, - fontWeight: FontWeight.bold), - ), - const SizedBox(height: 20), - Text( - 'Please fill in your account information to\n retrieve your password', - style: smallTextStyle, - ), - const SizedBox(height: 20), - Column( + const Spacer(), + Expanded( + flex: 3, + child: Container( + decoration: BoxDecoration( + color: Colors.white.withOpacity(0.1), + borderRadius: const BorderRadius.all(Radius.circular(30)), + border: Border.all(color: ColorsManager.graysColor.withOpacity(0.2)), + ), + child: Form( + key: forgetBloc.forgetFormKey, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 40, vertical: 25), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ + children: [ + const SizedBox(height: 10), + const Text( + 'Forget Password', + style: TextStyle( + color: Colors.white, + fontSize: 24, + fontWeight: FontWeight.bold), + ), + const SizedBox(height: 20), Text( - "Country/Region", + 'Please fill in your account information to\nretrieve your password', style: smallTextStyle, ), - const SizedBox(height: 10), - SizedBox( - width: MediaQuery.of(context).size.width * 0.2, - child: DropdownButtonFormField( - validator: forgetBloc.validateRegion, - icon: const Icon( - Icons.keyboard_arrow_down_outlined, + const SizedBox(height: 20), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + "Country/Region", + style: smallTextStyle, ), - decoration: textBoxDecoration()!.copyWith( - hintText: null, + const SizedBox(height: 10), + SizedBox( + child: DropdownButtonFormField( + validator: forgetBloc.validateRegion, + icon: const Icon( + Icons.keyboard_arrow_down_outlined, + ), + decoration: textBoxDecoration()!.copyWith( + hintText: null, + ), + hint: SizedBox( + width: MediaQuery.sizeOf(context).width * 0.11, + child: const Align( + alignment: Alignment.centerLeft, + child: Text( + 'Select your region/country', + textAlign: TextAlign.center, + overflow: TextOverflow.ellipsis, + + ), + ), + ), + isDense: true, + style: const TextStyle(color: Colors.black), + items: forgetBloc.regions.map((String region) { + return DropdownMenuItem( + value: region, + child: Text(region), + ); + }).toList(), + onChanged: (String? value) { + print(value); + }, + ), + ) + ], + ), + const SizedBox(height: 20), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text("Account", + style: smallTextStyle, ), - hint: const Align( - alignment: Alignment.centerLeft, - child: Text( - 'Select your region/country', - textAlign: TextAlign.center, + const SizedBox(height: 10), + SizedBox( + child: TextFormField( + validator: forgetBloc.validateEmail, + controller: forgetBloc.forgetEmailController, + decoration: textBoxDecoration()!.copyWith(hintText: 'Enter your email'), + style: const TextStyle(color: Colors.black), ), ), - isDense: true, - style: const TextStyle(color: Colors.black), - items: forgetBloc.regions.map((String region) { - return DropdownMenuItem( - value: region, - child: Text(region), - ); - }).toList(), - onChanged: (String? value) { - print(value); - }, - ), - ) - ], - ), - const SizedBox(height: 20), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Text("Account", - style: smallTextStyle,), - const SizedBox(height: 10), - SizedBox( - width: MediaQuery.sizeOf(context).width * 0.2, - child: TextFormField( - validator: forgetBloc.validateEmail, - controller: forgetBloc.forgetEmailController, - decoration: textBoxDecoration()!.copyWith(hintText: 'Enter your email'), - style: const TextStyle(color: Colors.black), - ), + ], ), - ], - ), - const SizedBox(height: 20.0), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Text("One Time Password", - style: smallTextStyle,), - const SizedBox(height: 10), - SizedBox( - width: MediaQuery.sizeOf(context).width * 0.2, - child: TextFormField( - validator: forgetBloc.validateCode, - keyboardType: TextInputType.visiblePassword, - controller: forgetBloc.forgetOtp, - decoration: textBoxDecoration()!.copyWith( - hintText: 'Enter Code', - suffixIcon: SizedBox( - width: 100, - child: Center( - child: InkWell( - onTap: () { - BlocProvider.of(context).add(StartTimerEvent()); - }, - child: Text( - 'Get Code ${state is TimerState && !state.isButtonEnabled ? "(${state.remainingTime.toString()})" : ""}', - style: TextStyle( - color: state is TimerState && !state.isButtonEnabled - ? Colors.grey - : ColorsManager.btnColor, + const SizedBox(height: 20.0), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text("One Time Password", + style: smallTextStyle,), + const SizedBox(height: 10), + SizedBox( + child: TextFormField( + validator: forgetBloc.validateCode, + keyboardType: TextInputType.visiblePassword, + controller: forgetBloc.forgetOtp, + decoration: textBoxDecoration()!.copyWith( + hintText: 'Enter Code', + suffixIcon: SizedBox( + width: 100, + child: Center( + child: InkWell( + onTap: () { + BlocProvider.of(context).add(StartTimerEvent()); + }, + child: Text( + 'Get Code ${state is TimerState && !state.isButtonEnabled ? "(${state.remainingTime.toString()})" : ""}', + style: TextStyle( + color: state is TimerState && !state.isButtonEnabled + ? Colors.grey + : ColorsManager.btnColor, + ), + ), ), ), ), ), + style: const TextStyle(color: Colors.black), ), ), - style: const TextStyle(color: Colors.black), - ), + ], ), - ], - ), - const SizedBox(height: 20.0), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Text("Password", - style: smallTextStyle,), - const SizedBox(height: 10), + const SizedBox(height: 20.0), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text("Password", + style: smallTextStyle,), + const SizedBox(height: 10), + SizedBox( + child: TextFormField( + validator: forgetBloc.passwordValidator, + keyboardType: TextInputType.visiblePassword, + controller: forgetBloc.forgetPasswordController, + decoration: textBoxDecoration()!.copyWith( + hintText: 'At least 8 characters', + ), + style: const TextStyle(color: Colors.black), + ), + ), + ], + ), + const SizedBox( + height: 10, + ), + const SizedBox(height: 20.0), SizedBox( width: MediaQuery.sizeOf(context).width * 0.2, - child: TextFormField( - validator: forgetBloc.passwordValidator, - keyboardType: TextInputType.visiblePassword, - controller: forgetBloc.forgetPasswordController, - decoration: textBoxDecoration()!.copyWith( - hintText: 'At least 8 characters', - ), - style: const TextStyle(color: Colors.black), + child: DefaultButton( + backgroundColor: ColorsManager.btnColor, + child: const Text('Submit'), + onPressed: () { + if (forgetBloc.forgetFormKey.currentState!.validate()) { + forgetBloc.add(ChangePasswordEvent()); + } + }, ), ), + SizedBox(height: 10,), + SizedBox( + width: MediaQuery.sizeOf(context).width * 0.2, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Flexible( + child: Text( + "Do you have an account? ", + style: TextStyle(color: Colors.white), + )), + InkWell( + onTap: () { + Navigator.pop(context); + }, + child: const Flexible( + child: Text( + "Sign in", + )), + ), + ], + ), + ) ], ), - const SizedBox( - height: 10, - ), - const SizedBox(height: 20.0), - SizedBox( - width: MediaQuery.sizeOf(context).width * 0.2, - child: DefaultButton( - backgroundColor: ColorsManager.btnColor, - child: const Text('Submit'), - onPressed: () { - if (forgetBloc.forgetFormKey.currentState!.validate()) { - forgetBloc.add(ChangePasswordEvent()); - } - }, - ), - ), - SizedBox(height: 10,), - SizedBox( - width: MediaQuery.sizeOf(context).width * 0.2, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Flexible( - child: Text( - "Do you have an account? ", - style: TextStyle(color: Colors.white), - )), - InkWell( - onTap: () { - Navigator.pop(context); - }, - child: const Flexible( - child: Text( - "Sign in", - )), - ), - ], - ), - ) - ], + ), ), ), ), - ), - const Spacer(), - ], + const Spacer(), + ], + ), ), - ], - ), + ), + ], ), - ), + ) ); } } diff --git a/lib/pages/auth/view/login_mobile_page.dart b/lib/pages/auth/view/login_mobile_page.dart index 7b52400a..3e709735 100644 --- a/lib/pages/auth/view/login_mobile_page.dart +++ b/lib/pages/auth/view/login_mobile_page.dart @@ -15,7 +15,6 @@ import 'package:syncrow_web/utils/style.dart'; class LoginMobilePage extends StatelessWidget { const LoginMobilePage({super.key}); - @override Widget build(BuildContext context) { return Scaffold( @@ -39,7 +38,7 @@ class LoginMobilePage extends StatelessWidget { } }, builder: (context, state) { - if (state is LoginLoading) { + if (state is AuthLoading) { return const Center(child: CircularProgressIndicator()); } else { return _buildLoginForm(context); @@ -311,90 +310,6 @@ class LoginMobilePage extends StatelessWidget { }, ), ), - // Padding( - // padding: const EdgeInsets.all(5.0), - // child: SizedBox( - // width: MediaQuery.sizeOf(context).width * 0.2, - // child: Row( - // mainAxisAlignment: MainAxisAlignment.center, - // crossAxisAlignment: CrossAxisAlignment.center, - // children: [ - // Expanded(child: Image.asset(Assets.liftLine)), - // Expanded( - // child: Padding( - // padding: const EdgeInsets.all(5.0), - // child: Text('Or sign in with', - // style: smallTextStyle.copyWith(fontSize: 10), - // ), - // ) - // ), - // Expanded(child: Image.asset(Assets.rightLine)), - // ], - // ), - // ), - // ), - // SizedBox( - // width: MediaQuery.sizeOf(context).width * 0.2, - // child: Row( - // crossAxisAlignment: CrossAxisAlignment.center, - // children: [ - // Expanded( - // child: Container( - // decoration: containerDecoration, - // child:InkWell( - // child: Padding( - // padding: const EdgeInsets.all(8.0), - // child: Row( - // mainAxisAlignment: MainAxisAlignment.spaceAround, - // crossAxisAlignment: CrossAxisAlignment.center, - // children: [ - // SvgPicture.asset( - // Assets.google, - // fit: BoxFit.cover, - // ), - // const Flexible( - // child: Text('Google', - // style: TextStyle(color: Colors.black), - // ), - // ), - // ], - // ), - // ), - // onTap: () {}, - // ), - // ), - // ), - // SizedBox(width: 10,), - // Expanded( - // child: Container( - // decoration: containerDecoration, - // child:InkWell( - // child: Padding( - // padding: const EdgeInsets.all(8.0), - // child: Row( - // mainAxisAlignment: MainAxisAlignment.spaceAround, - // crossAxisAlignment: CrossAxisAlignment.center, - // children: [ - // SvgPicture.asset( - // Assets.facebook, - // fit: BoxFit.cover, - // ), - // const Flexible( - // child: Text('Facebook', - // style: TextStyle(color: Colors.black), - // ), - // ), - // ], - // ), - // ), - // onTap: () {}, - // ), - // ), - // ), - // - // ], - // ), - // ), const SizedBox( child: Row( mainAxisAlignment: MainAxisAlignment.center, diff --git a/lib/pages/auth/view/login_web_page.dart b/lib/pages/auth/view/login_web_page.dart index 67f7c7bc..ecacfb09 100644 --- a/lib/pages/auth/view/login_web_page.dart +++ b/lib/pages/auth/view/login_web_page.dart @@ -22,7 +22,7 @@ class LoginWebPage extends StatelessWidget { Widget build(BuildContext context) { return Scaffold( body: BlocProvider( - create: (context) => AuthBloc(), + create: (BuildContext context) => AuthBloc()..add(RegionInitialEvent()), child: BlocConsumer( listener: (context, state) { if (state is LoginSuccess) { @@ -41,7 +41,7 @@ class LoginWebPage extends StatelessWidget { } }, builder: (context, state) { - if (state is LoginLoading) { + if (state is AuthLoading) { return const Center(child: CircularProgressIndicator()); } else { return _buildLoginForm(context,state); @@ -55,364 +55,265 @@ class LoginWebPage extends StatelessWidget { Widget _buildLoginForm(BuildContext context,AuthState state) { final loginBloc = BlocProvider.of(context); return FirstLayer( - second: Container( - margin: const EdgeInsets.all(50), - decoration: BoxDecoration( - color: Colors.black.withOpacity(0.3), - borderRadius: const BorderRadius.all(Radius.circular(20)), - ), - child: Center( - child: ListView( - shrinkWrap: true, - children: [ - Row( + second: Center( + child: ListView( + shrinkWrap: true, + children: [ + Container( + padding:const EdgeInsets.all(50) , + margin: const EdgeInsets.all(90), + decoration: BoxDecoration( + color: Colors.black.withOpacity(0.3), + borderRadius: const BorderRadius.all(Radius.circular(20)), + ), + child: Center( + child:Row( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ const Spacer(), Expanded( - flex: 2, + flex: 3, child: SvgPicture.asset( Assets.loginLogo, ), ), const Spacer(), - Container( - decoration: BoxDecoration( - color: Colors.white.withOpacity(0.1), - borderRadius: const BorderRadius.all(Radius.circular(30)), - border: Border.all(color: ColorsManager.graysColor.withOpacity(0.2))), - child: Form( - key: loginBloc.loginFormKey, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 50, vertical: 25), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const SizedBox(height: 15), - const Text( - 'Login', - style: TextStyle( - color: Colors.white, - fontSize: 24, - fontWeight: FontWeight.bold), - ), - const SizedBox(height: 40), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Text( - "Country/Region", - style: smallTextStyle, - ), - const SizedBox( - height: 10, - ), - SizedBox( - width: MediaQuery.of(context).size.width * 0.2, - child: DropdownButtonFormField( - validator:loginBloc.validateRegion , - icon: const Icon( - Icons.keyboard_arrow_down_outlined, + Expanded( + flex: 3, + child: Container( + decoration: BoxDecoration( + color: Colors.white.withOpacity(0.1), + borderRadius: const BorderRadius.all(Radius.circular(30)), + border: Border.all(color: ColorsManager.graysColor.withOpacity(0.2))), + child: Form( + key: loginBloc.loginFormKey, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 50, vertical: 25), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 15), + const Text( + 'Login', + style: TextStyle( + color: Colors.white, + fontSize: 24, + fontWeight: FontWeight.bold), + ), + const SizedBox(height: 40), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + "Country/Region", + style: smallTextStyle, + ), + const SizedBox(height: 10,), + SizedBox( + child: DropdownButtonFormField( + validator:loginBloc.validateRegion , + icon: const Icon( + Icons.keyboard_arrow_down_outlined, + ), + decoration: textBoxDecoration()!.copyWith( + hintText: null,), + hint: SizedBox( + width: MediaQuery.sizeOf(context).width * 0.11, + child: const Align( + alignment: Alignment.centerLeft, + child: Text( + 'Select your region/country', + textAlign: TextAlign.center, + style: TextStyle(fontSize: 14), + overflow: TextOverflow.ellipsis, + ), + ), + ), + isDense: true, + style: const TextStyle(color: Colors.black), + items:loginBloc.regions.map((String region) { + return DropdownMenuItem( + value: region, + child: Text(region), + ); + }).toList(), + onChanged: (String? value) { + print(value); + }, + ), + ) + ], + ), + const SizedBox(height: 20.0), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text("Email", + style: smallTextStyle, + ), + const SizedBox( + height: 10, + ), + SizedBox( + child: TextFormField( + validator:loginBloc.validateEmail , + controller:loginBloc.loginEmailController, + decoration: textBoxDecoration()!.copyWith(hintText: 'Enter your email'), + style: const TextStyle(color: Colors.black), + ), + ), + ], + ), + const SizedBox(height: 20.0), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text("Password", style: smallTextStyle,), + const SizedBox( + height: 10, ), - decoration: textBoxDecoration()!.copyWith( - hintText: null, - ), - hint: const Align( - alignment: Alignment.centerLeft, - child: Text( - 'Select your region/country', - textAlign: TextAlign.center, + SizedBox( + child: TextFormField( + validator:loginBloc.validatePassword, + obscureText:loginBloc.obscureText, + keyboardType: TextInputType.visiblePassword, + controller:loginBloc.loginPasswordController, + decoration: textBoxDecoration()!.copyWith( + hintText: 'At least 8 characters', + suffixIcon: IconButton(onPressed: () { + loginBloc.add(PasswordVisibleEvent(newValue: loginBloc.obscureText)); + }, + icon: SizedBox( + child: SvgPicture.asset( + loginBloc.obscureText? + Assets.visiblePassword : + Assets.invisiblePassword, + height: 15, + width: 15, + ), + ), + ) + ), + style: const TextStyle(color: Colors.black), ), ), - isDense: true, - style: const TextStyle(color: Colors.black), - items:loginBloc.regions.map((String region) { - return DropdownMenuItem( - value: region, - child: Text(region), - ); - }).toList(), - onChanged: (String? value) { - print(value); - }, - ), - ) - ], - ), - const SizedBox(height: 20.0), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Text("Email", - style: smallTextStyle, + ], ), const SizedBox( - height: 10, + height: 20, ), SizedBox( - width: MediaQuery.sizeOf(context).width * 0.2, - child: TextFormField( - validator:loginBloc.validateEmail , - controller:loginBloc.loginEmailController, - decoration: textBoxDecoration()!.copyWith(hintText: 'Enter your email'), - style: const TextStyle(color: Colors.black), - ), - ), - ], - ), - const SizedBox(height: 20.0), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Text("Password", style: smallTextStyle,), - const SizedBox( - height: 10, - ), - SizedBox( - width: MediaQuery.sizeOf(context).width * 0.2, - child: TextFormField( - validator:loginBloc.validatePassword, - obscureText:loginBloc.obscureText, - keyboardType: TextInputType.visiblePassword, - controller:loginBloc.loginPasswordController, - decoration: textBoxDecoration()!.copyWith( - hintText: 'At least 8 characters', - suffixIcon: IconButton(onPressed: () { - loginBloc.add(PasswordVisibleEvent(newValue: loginBloc.obscureText)); - }, - icon: SizedBox( - child: SvgPicture.asset( - loginBloc.obscureText? - Assets.visiblePassword : - Assets.invisiblePassword, - height: 15, - width: 15, + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + InkWell( + onTap: () { + Navigator.of(context).push(MaterialPageRoute(builder: (context) => const ForgetPasswordPage(),)); + }, + child: Text( + "Forgot Password?", + style: smallTextStyle, ), ), - ) - ), - style: const TextStyle(color: Colors.black), + ], ), ), - ], - ), - const SizedBox( - height: 20, - ), - SizedBox( - width: MediaQuery.of(context).size.width * 0.2, - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - InkWell( - onTap: () { - Navigator.of(context).push(MaterialPageRoute(builder: (context) => const ForgetPasswordPage(),)); - }, - child: Text( - "Forgot Password?", - style: smallTextStyle, - ), - ), - ], - ), - ), - const SizedBox( - height: 32, - ), - Row( - children: [ - Transform.scale( - scale: 1.2, // Adjust the scale as needed - child: Checkbox( - fillColor: MaterialStateProperty.all(Colors.white), - activeColor: Colors.white, - value:loginBloc.isChecked, - checkColor: Colors.black, - shape: const CircleBorder(), - onChanged: (bool? newValue) { - loginBloc.add(CheckBoxEvent(newValue: newValue)); - }, - ), + const SizedBox( + height: 32, ), + Row( + children: [ + Transform.scale( + scale: 1.2, // Adjust the scale as needed + child: Checkbox( + fillColor: MaterialStateProperty.all(Colors.white), + activeColor: Colors.white, + value:loginBloc.isChecked, + checkColor: Colors.black, + shape: const CircleBorder(), + onChanged: (bool? newValue) { + loginBloc.add(CheckBoxEvent(newValue: newValue)); + }, + ), + ), + SizedBox( + width: MediaQuery.sizeOf(context).width * 0.16, + child: RichText( + text: TextSpan( + text: 'Agree to ', + style: const TextStyle(color: Colors.white), + children: [ + TextSpan( + text: '(Terms of Service)', + style: const TextStyle( + color: Colors.black,), + recognizer: TapGestureRecognizer() + ..onTap = () { + loginBloc.launchURL( + 'https://example.com/terms'); + }, + ), + TextSpan( + text: ' (Legal Statement)', + style: const TextStyle(color: Colors.black), + recognizer: TapGestureRecognizer() + ..onTap = () { + loginBloc.launchURL( + 'https://example.com/legal'); + }, + ), + TextSpan( + text: ' (Privacy Statement)', + style: const TextStyle( + color: Colors.black), + recognizer: TapGestureRecognizer() + ..onTap = () { + loginBloc.launchURL( + 'https://example.com/privacy'); + }, + ), + ], + ), + ), + ), + ], + ), + const SizedBox(height: 30.0), SizedBox( width: MediaQuery.sizeOf(context).width * 0.2, - child: RichText( - text: TextSpan( - text: 'Agree to ', - style: const TextStyle(color: Colors.white), - children: [ - TextSpan( - text: '(Terms of Service)', - style: const TextStyle( - color: Colors.black), - recognizer: TapGestureRecognizer() - ..onTap = () { - loginBloc.launchURL( - 'https://example.com/terms'); - }, + child: DefaultButton( + backgroundColor: loginBloc.isChecked? + ColorsManager.btnColor:ColorsManager.grayColor, + child: const Text('Sign in'), + onPressed: () { + if (loginBloc.loginFormKey.currentState!.validate()) { + loginBloc.add(LoginButtonPressed( + username: loginBloc.loginEmailController.text, + password: loginBloc.loginPasswordController.text, ), - TextSpan( - text: ' (Legal Statement)', - style: const TextStyle(color: Colors.black), - recognizer: TapGestureRecognizer() - ..onTap = () { - loginBloc.launchURL( - 'https://example.com/legal'); - }, - ), - TextSpan( - text: ' (Privacy Statement)', - style: const TextStyle( - color: Colors.black), - recognizer: TapGestureRecognizer() - ..onTap = () { - loginBloc.launchURL( - 'https://example.com/privacy'); - }, - ), - ], - ), + ); + } + }, ), ), - ], - ), - const SizedBox(height: 30.0), - SizedBox( - width: MediaQuery.sizeOf(context).width * 0.2, - child: DefaultButton( - backgroundColor: loginBloc.isChecked? - ColorsManager.btnColor:ColorsManager.grayColor, - child: const Text('Sign in'), - onPressed: () { - if (loginBloc.loginFormKey.currentState!.validate()) { - loginBloc.add(LoginButtonPressed( - username: loginBloc.loginEmailController.text, - password: loginBloc.loginPasswordController.text, - ), - ); - } - }, - ), - ), - ], - ), - ), - ) - ), + ], + ), + ), + ) + )), const Spacer(), ], - ), - ], - )), + ),), + ) + ], + ), ), ); } } -// Padding( -// padding: const EdgeInsets.all(5.0), -// child: SizedBox( -// width: MediaQuery.sizeOf(context).width * 0.2, -// child: Row( -// mainAxisAlignment: MainAxisAlignment.center, -// crossAxisAlignment: CrossAxisAlignment.center, -// children: [ -// Expanded(child: Image.asset(Assets.liftLine)), -// Expanded( -// child: Padding( -// padding: const EdgeInsets.all(5.0), -// child: Text('Or sign in with', -// style: smallTextStyle.copyWith(fontSize: 10), -// ), -// ) -// ), -// Expanded(child: Image.asset(Assets.rightLine)), -// ], -// ), -// ), -// ), -// SizedBox( -// width: MediaQuery.sizeOf(context).width * 0.2, -// child: Row( -// crossAxisAlignment: CrossAxisAlignment.center, -// children: [ -// Expanded( -// child: Container( -// decoration: containerDecoration, -// child:InkWell( -// child: Padding( -// padding: const EdgeInsets.all(8.0), -// child: Row( -// mainAxisAlignment: MainAxisAlignment.spaceAround, -// crossAxisAlignment: CrossAxisAlignment.center, -// children: [ -// SvgPicture.asset( -// Assets.google, -// fit: BoxFit.cover, -// ), -// const Flexible( -// child: Text('Google', -// style: TextStyle(color: Colors.black), -// ), -// ), -// ], -// ), -// ), -// onTap: () {}, -// ), -// ), -// ), -// SizedBox(width: 10,), -// Expanded( -// child: Container( -// decoration: containerDecoration, -// child:InkWell( -// child: Padding( -// padding: const EdgeInsets.all(8.0), -// child: Row( -// mainAxisAlignment: MainAxisAlignment.spaceAround, -// crossAxisAlignment: CrossAxisAlignment.center, -// children: [ -// SvgPicture.asset( -// Assets.facebook, -// fit: BoxFit.cover, -// ), -// const Flexible( -// child: Text('Facebook', -// style: TextStyle(color: Colors.black), -// ), -// ), -// ], -// ), -// ), -// onTap: () {}, -// ), -// ), -// ), -// -// ], -// ), -// ), -// SizedBox( -// width: MediaQuery.sizeOf(context).width * 0.2, -// child: const Row( -// mainAxisAlignment: MainAxisAlignment.center, -// crossAxisAlignment: CrossAxisAlignment.center, -// children: [ -// Flexible( -// child: Text( -// "Don't you have an account? ", -// style: TextStyle(color: Colors.white), -// )), -// Flexible( -// child: Text( -// "Sign up", -// )), -// ], -// ), -// ) \ No newline at end of file diff --git a/lib/services/api/http_interceptor.dart b/lib/services/api/http_interceptor.dart index 66e6302a..ff3fc0d4 100644 --- a/lib/services/api/http_interceptor.dart +++ b/lib/services/api/http_interceptor.dart @@ -13,6 +13,7 @@ class HTTPInterceptor extends InterceptorsWrapper { List headerExclusionListOfAddedParameters = [ ApiEndpoints.login, + ApiEndpoints.getRegion ]; @override diff --git a/lib/services/auth_api.dart b/lib/services/auth_api.dart index 3fc84c81..58a705ff 100644 --- a/lib/services/auth_api.dart +++ b/lib/services/auth_api.dart @@ -1,5 +1,6 @@ import 'dart:convert'; +import 'package:syncrow_web/pages/auth/model/region_model.dart'; import 'package:syncrow_web/pages/auth/model/token.dart'; import 'package:syncrow_web/services/api/http_service.dart'; import 'package:syncrow_web/utils/constants/api_const.dart'; @@ -17,51 +18,50 @@ class AuthenticationAPI { return response; } - static Future forgetPassword({ required var email, required var password}) async { + static Future forgetPassword( + {required var email, required var password}) async { final response = await HTTPService().post( path: ApiEndpoints.forgetPassword, - body: { - "email": email, - "password": password - }, + body: {"email": email, "password": password}, showServerMessage: true, - expectedResponseModel: (json) { - }); + expectedResponseModel: (json) {}); return response; } - static Future sendOtp({ required var email}) async { + static Future sendOtp({required var email}) async { final response = await HTTPService().post( path: ApiEndpoints.sendOtp, - body: { - "email": email, - "type": "VERIFICATION" - }, + body: {"email": email, "type": "VERIFICATION"}, showServerMessage: true, - expectedResponseModel: (json) { - print('json===$json'); - }); - + expectedResponseModel: (json) {}); return response; } - static Future verifyOtp({ required String email, required String otpCode}) async { + static Future verifyOtp( + {required String email, required String otpCode}) async { final response = await HTTPService().post( path: ApiEndpoints.verifyOtp, - body: { - "email": email, - "type": "VERIFICATION", - "otpCode": otpCode - }, + body: {"email": email, "type": "VERIFICATION", "otpCode": otpCode}, showServerMessage: true, expectedResponseModel: (json) { - print('json===${json['message']}'); - if(json['message']=='Otp Verified Successfully'){ - return true; - }else{ - return false; - } + if (json['message'] == 'Otp Verified Successfully') { + return true; + } else { + return false; + } }); return response; } + + static Future> fetchRegion() async { + final response = await HTTPService().get( + path: ApiEndpoints.getRegion, + showServerMessage: true, + expectedResponseModel: (json) { + return (json as List).map((zone) => RegionModel.fromJson(zone)).toList(); + } + ); + return response as List; + } + } diff --git a/lib/utils/constants/api_const.dart b/lib/utils/constants/api_const.dart index 93803c16..855d74e5 100644 --- a/lib/utils/constants/api_const.dart +++ b/lib/utils/constants/api_const.dart @@ -8,4 +8,5 @@ abstract class ApiEndpoints { static const String forgetPassword = '$baseUrl/authentication/user/forget-password'; static const String sendOtp = '$baseUrl/authentication/user/send-otp'; static const String verifyOtp = '$baseUrl/authentication/user/verify-otp'; + static const String getRegion = '$baseUrl/region'; }