Home page

This commit is contained in:
mohammad
2024-08-06 11:21:14 +03:00
parent 09dc49b630
commit 1f5a119c60
11 changed files with 521 additions and 665 deletions

View File

@ -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

View File

@ -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<AuthEvent, AuthState> {
on<StopTimerEvent>(_onStopTimer);
on<UpdateTimerEvent>(_onUpdateTimer);
on<PasswordVisibleEvent>(_passwordVisible);
on<RegionInitialEvent>(_fetchRegion);
}
////////////////////////////// forget password //////////////////////////////////
////////////////////////////// forget password //////////////////////////////////
final TextEditingController forgetEmailController = TextEditingController();
final TextEditingController forgetPasswordController = TextEditingController();
final TextEditingController forgetOtp = TextEditingController();
final forgetFormKey = GlobalKey<FormState>();
Timer? _timer;
int _remainingTime = 0;
List<RegionModel>? regionList;
Future<void> _onStartTimer(StartTimerEvent event, Emitter<AuthState> 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<AuthEvent, AuthState> {
///////////////////////////////////// login /////////////////////////////////////
final TextEditingController loginEmailController = TextEditingController();
final TextEditingController loginPasswordController = TextEditingController();
@ -108,7 +103,7 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
bool showValidationMessage = false;
void _login(LoginButtonPressed event, Emitter<AuthState> emit) async {
emit(LoginLoading());
emit(AuthLoading());
if (isChecked) {
try {
if (event.username.isEmpty || event.password.isEmpty) {
@ -128,7 +123,6 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
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<AuthEvent, AuthState> {
}
checkBoxToggle(CheckBoxEvent event, Emitter<AuthState> emit,) {
emit(LoginLoading());
emit(AuthLoading());
isChecked = event.newValue!;
emit(LoginInitial());
}
@ -161,15 +155,13 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
}
void _passwordVisible(PasswordVisibleEvent event, Emitter<AuthState> 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<AuthEvent, AuthState> {
}
}
void _fetchRegion(RegionInitialEvent event, Emitter<AuthState> emit) async {
try {
emit(AuthLoading());
regionList = await AuthenticationAPI.fetchRegion();
emit(LoginSuccess());
} catch (e) {
emit( LoginFailure(error: e.toString()));
}
}
}

View File

@ -17,7 +17,6 @@ class LoginButtonPressed extends AuthEvent {
List<Object> 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,});
}
}
class RegionInitialEvent extends AuthEvent {}
class SelectRegionEvent extends AuthEvent {}

View File

@ -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 {}

View File

@ -0,0 +1,25 @@
class RegionModel {
final String name;
final String id;
RegionModel({
required this.name,
required this.id,
});
factory RegionModel.fromJson(Map<String, dynamic> json) {
return RegionModel(
name: json['regionName'],
id: json['uuid'].toString(), // Ensure id is a String
);
}
Map<String, dynamic> toJson() {
return {
'regionName': name,
'uuid': id,
};
}
}

View File

@ -19,9 +19,7 @@ class ForgetPasswordWebPage extends StatelessWidget {
create: (context) => AuthBloc(),
child: BlocConsumer<AuthBloc, AuthState>(
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<AuthBloc>(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: <Widget>[
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: <Widget>[
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<String>(
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<String>(
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<String>(
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<String>(
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<AuthBloc>(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<AuthBloc>(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(),
],
),
),
],
),
),
],
),
),
)
);
}
}

View File

@ -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,

View File

@ -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<AuthBloc, AuthState>(
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<AuthBloc>(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: <Widget>[
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<String>(
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: <Widget>[
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<String>(
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<String>(
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<String>(
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<Color>(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<Color>(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",
// )),
// ],
// ),
// )

View File

@ -13,6 +13,7 @@ class HTTPInterceptor extends InterceptorsWrapper {
List<String> headerExclusionListOfAddedParameters = [
ApiEndpoints.login,
ApiEndpoints.getRegion
];
@override

View File

@ -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<bool> verifyOtp({ required String email, required String otpCode}) async {
static Future<bool> 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<List<RegionModel>> 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<RegionModel>;
}
}

View File

@ -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';
}