Merged with dev

This commit is contained in:
Abdullah Alassaf
2024-08-08 14:07:11 +03:00
16 changed files with 643 additions and 741 deletions

View File

@ -4,6 +4,7 @@ import 'package:syncrow_web/pages/auth/bloc/auth_bloc.dart';
import 'package:syncrow_web/pages/auth/view/login_page.dart'; import 'package:syncrow_web/pages/auth/view/login_page.dart';
import 'package:syncrow_web/pages/home/view/home_page.dart'; import 'package:syncrow_web/pages/home/view/home_page.dart';
import 'package:syncrow_web/services/locator.dart'; import 'package:syncrow_web/services/locator.dart';
import 'package:syncrow_web/utils/color_manager.dart';
Future<void> main() async { Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
@ -33,14 +34,23 @@ class MyApp extends StatelessWidget {
}, },
), ),
theme: ThemeData( theme: ThemeData(
colorScheme: ColorScheme.fromSeed( textTheme: const TextTheme(
seedColor: Colors.deepPurple), // Set up color scheme bodySmall: TextStyle(
fontSize: 13, color: ColorsManager.whiteColors, fontWeight: FontWeight.bold),
bodyMedium: TextStyle(color: Colors.black87, fontSize: 14),
bodyLarge: TextStyle(fontSize: 16, color: Colors.white),
headlineSmall: TextStyle(color: Colors.black87, fontSize: 18),
headlineMedium: TextStyle(color: Colors.black87, fontSize: 20),
headlineLarge: TextStyle(
color: Colors.white,
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), // Set up color scheme
useMaterial3: true, // Enable Material 3 useMaterial3: true, // Enable Material 3
), ),
home: isLoggedIn == 'Success'? home: isLoggedIn == 'Success' ? const HomePage() : const LoginPage(),
const HomePage()
:
const LoginPage(),
); );
} }
} }

View File

@ -1,11 +1,11 @@
import 'dart:async'; import 'dart:async';
import 'package:flutter/foundation.dart';
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_secure_storage/flutter_secure_storage.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_event.dart';
import 'package:syncrow_web/pages/auth/bloc/auth_state.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/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/token.dart';
import 'package:syncrow_web/pages/auth/model/user_model.dart'; import 'package:syncrow_web/pages/auth/model/user_model.dart';
import 'package:syncrow_web/services/auth_api.dart'; import 'package:syncrow_web/services/auth_api.dart';
@ -22,35 +22,32 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
on<StopTimerEvent>(_onStopTimer); on<StopTimerEvent>(_onStopTimer);
on<UpdateTimerEvent>(_onUpdateTimer); on<UpdateTimerEvent>(_onUpdateTimer);
on<PasswordVisibleEvent>(_passwordVisible); on<PasswordVisibleEvent>(_passwordVisible);
on<RegionInitialEvent>(_fetchRegion);
} }
////////////////////////////// forget password ////////////////////////////////// ////////////////////////////// forget password //////////////////////////////////
final TextEditingController forgetEmailController = TextEditingController(); final TextEditingController forgetEmailController = TextEditingController();
final TextEditingController forgetPasswordController = TextEditingController(); final TextEditingController forgetPasswordController = TextEditingController();
final TextEditingController forgetOtp = TextEditingController(); final TextEditingController forgetOtp = TextEditingController();
final forgetFormKey = GlobalKey<FormState>(); final forgetFormKey = GlobalKey<FormState>();
Timer? _timer; Timer? _timer;
int _remainingTime = 0; int _remainingTime = 0;
List<RegionModel>? regionList;
Future<void> _onStartTimer(StartTimerEvent event, Emitter<AuthState> emit) async { Future<void> _onStartTimer(StartTimerEvent event, Emitter<AuthState> emit) async {
if (_validateInputs(emit)) return; if (_validateInputs(emit)) return;
print("StartTimerEvent received");
if (_timer != null && _timer!.isActive) { if (_timer != null && _timer!.isActive) {
print("Timer is already active");
return; return;
} }
_remainingTime = 60; _remainingTime = 60;
add(UpdateTimerEvent( add(UpdateTimerEvent(
remainingTime: _remainingTime, isButtonEnabled: false)); remainingTime: _remainingTime, isButtonEnabled: false));
print("Timer started, initial remaining time: $_remainingTime");
await AuthenticationAPI.sendOtp(email: forgetEmailController.text); await AuthenticationAPI.sendOtp(email: forgetEmailController.text);
_timer = Timer.periodic(const Duration(seconds: 1), (timer) { _timer = Timer.periodic(const Duration(seconds: 1), (timer) {
_remainingTime--; _remainingTime--;
print("Timer tick, remaining time: $_remainingTime"); // Debug print
if (_remainingTime <= 0) { if (_remainingTime <= 0) {
_timer?.cancel(); _timer?.cancel();
add(const UpdateTimerEvent(remainingTime: 0, isButtonEnabled: true)); add(const UpdateTimerEvent(remainingTime: 0, isButtonEnabled: true));
print("Timer finished"); // Debug print
} else { } else {
add(UpdateTimerEvent( add(UpdateTimerEvent(
remainingTime: _remainingTime, isButtonEnabled: false)); remainingTime: _remainingTime, isButtonEnabled: false));
@ -92,8 +89,6 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
///////////////////////////////////// login ///////////////////////////////////// ///////////////////////////////////// login /////////////////////////////////////
final TextEditingController loginEmailController = TextEditingController(); final TextEditingController loginEmailController = TextEditingController();
final TextEditingController loginPasswordController = TextEditingController(); final TextEditingController loginPasswordController = TextEditingController();
@ -103,12 +98,13 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
String newPassword = ''; String newPassword = '';
String maskedEmail = ''; String maskedEmail = '';
String otpCode = ''; String otpCode = '';
String validate = '';
static Token token = Token.emptyConstructor(); static Token token = Token.emptyConstructor();
static UserModel? user; static UserModel? user;
bool showValidationMessage = false; bool showValidationMessage = false;
void _login(LoginButtonPressed event, Emitter<AuthState> emit) async { void _login(LoginButtonPressed event, Emitter<AuthState> emit) async {
emit(LoginLoading()); emit(AuthLoading());
if (isChecked) { if (isChecked) {
try { try {
if (event.username.isEmpty || event.password.isEmpty) { if (event.username.isEmpty || event.password.isEmpty) {
@ -123,12 +119,12 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
), ),
); );
} catch (failure) { } catch (failure) {
validate='Something went wrong';
emit(const LoginFailure(error: 'Something went wrong')); emit(const LoginFailure(error: 'Something went wrong'));
// emit(LoginFailure(error: failure.toString())); // emit(LoginFailure(error: failure.toString()));
return; return;
} }
if (token.accessTokenIsNotEmpty) { if (token.accessTokenIsNotEmpty) {
debugPrint('token: ${token.accessToken}');
FlutterSecureStorage storage = const FlutterSecureStorage(); FlutterSecureStorage storage = const FlutterSecureStorage();
await storage.write( await storage.write(
key: Token.loginAccessTokenKey, value: token.accessToken); key: Token.loginAccessTokenKey, value: token.accessToken);
@ -148,7 +144,7 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
} }
checkBoxToggle(CheckBoxEvent event, Emitter<AuthState> emit,) { checkBoxToggle(CheckBoxEvent event, Emitter<AuthState> emit,) {
emit(LoginLoading()); emit(AuthLoading());
isChecked = event.newValue!; isChecked = event.newValue!;
emit(LoginInitial()); emit(LoginInitial());
} }
@ -161,15 +157,13 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
} }
void _passwordVisible(PasswordVisibleEvent event, Emitter<AuthState> emit) { void _passwordVisible(PasswordVisibleEvent event, Emitter<AuthState> emit) {
emit(LoginLoading()); emit(AuthLoading());
obscureText = !event.newValue!; obscureText = !event.newValue!;
emit(PasswordVisibleState()); emit(PasswordVisibleState());
} }
void launchURL(String url) { void launchURL(String url) {
if (kDebugMode) {
print('Launching URL: $url');
}
} }
@ -320,6 +314,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]; List<Object> get props => [username, password];
} }
class CheckBoxEvent extends AuthEvent { class CheckBoxEvent extends AuthEvent {
final bool? newValue; final bool? newValue;
@ -49,4 +48,8 @@ class PasswordVisibleEvent extends AuthEvent{
final bool? newValue; final bool? newValue;
const PasswordVisibleEvent({required this.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 AuthTokenLoading extends AuthState {}
class LoginLoading extends AuthState {} class AuthLoading extends AuthState {}
class LoginSuccess extends AuthState {} class LoginSuccess extends AuthState {}
@ -35,13 +35,13 @@ class LoginInvalid extends AuthState {
List<Object> get props => [error]; List<Object> get props => [error];
} }
class InitialForgetState extends AuthState{} class InitialForgetState extends AuthState {}
class LoadingForgetState extends AuthState{} class LoadingForgetState extends AuthState {}
class SuccessForgetState extends AuthState{} class SuccessForgetState extends AuthState {}
class PasswordVisibleState extends AuthState{} class PasswordVisibleState extends AuthState {}
class FailureForgetState extends AuthState { class FailureForgetState extends AuthState {
final String error; final String error;
@ -51,7 +51,7 @@ class FailureForgetState extends AuthState {
} }
class TimerState extends AuthState { class TimerState extends AuthState {
final bool isButtonEnabled ; final bool isButtonEnabled;
final int remainingTime; final int remainingTime;
const TimerState({required this.isButtonEnabled, required this.remainingTime}); const TimerState({required this.isButtonEnabled, required this.remainingTime});
@ -60,7 +60,6 @@ class TimerState extends AuthState {
List<Object> get props => [isButtonEnabled, remainingTime]; List<Object> get props => [isButtonEnabled, remainingTime];
} }
class AuthError extends AuthState { class AuthError extends AuthState {
final String message; final String message;
String? code; String? code;
@ -70,9 +69,7 @@ class AuthError extends AuthState {
class AuthTokenError extends AuthError { class AuthTokenError extends AuthError {
AuthTokenError({required super.message, super.code}); AuthTokenError({required super.message, super.code});
} }
class AuthSuccess extends AuthState {} class AuthSuccess extends AuthState {}
class AuthTokenSuccess extends AuthSuccess {} 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

@ -11,7 +11,6 @@ import 'package:syncrow_web/utils/constants/assets.dart';
import 'package:syncrow_web/utils/style.dart'; import 'package:syncrow_web/utils/style.dart';
class ForgetPasswordWebPage extends StatelessWidget { class ForgetPasswordWebPage extends StatelessWidget {
const ForgetPasswordWebPage({super.key}); const ForgetPasswordWebPage({super.key});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
@ -19,9 +18,7 @@ class ForgetPasswordWebPage extends StatelessWidget {
create: (context) => AuthBloc(), create: (context) => AuthBloc(),
child: BlocConsumer<AuthBloc, AuthState>( child: BlocConsumer<AuthBloc, AuthState>(
listener: (context, state) { listener: (context, state) {
if (state is LoadingForgetState) { if (state is SuccessForgetState){
} else if (state is SuccessForgetState){
Navigator.of(context).pop(); Navigator.of(context).pop();
} }
else if (state is FailureForgetState) { else if (state is FailureForgetState) {
@ -45,234 +42,266 @@ class ForgetPasswordWebPage extends StatelessWidget {
} }
Widget _buildForm(BuildContext context, AuthState state) { Widget _buildForm(BuildContext context, AuthState state) {
late ScrollController _scrollController;
_scrollController = ScrollController();
void _scrollToCenter() {
final double middlePosition = _scrollController.position.maxScrollExtent / 2;
_scrollController.animateTo(
middlePosition,
duration: const Duration(seconds: 1),
curve: Curves.easeInOut,
);
}
WidgetsBinding.instance.addPostFrameCallback((_) {
_scrollToCenter();
});
final forgetBloc = BlocProvider.of<AuthBloc>(context); final forgetBloc = BlocProvider.of<AuthBloc>(context);
Size size = MediaQuery.of(context).size;
return FirstLayer( return FirstLayer(
second: Container( second: Center(
padding:const EdgeInsets.all(50) , child: ListView(
margin: const EdgeInsets.all(50), shrinkWrap: true,
decoration: BoxDecoration( controller: _scrollController,
color: Colors.black.withOpacity(0.3), children: [
borderRadius: const BorderRadius.all(Radius.circular(20)), Container(
), padding: EdgeInsets.all(size.width*0.02),
child: Center( margin: EdgeInsets.all(size.width*0.09),
child: ListView( decoration: BoxDecoration(
shrinkWrap: true, color: Colors.black.withOpacity(0.3),
children: [ borderRadius: const BorderRadius.all(Radius.circular(20)),
Row( ),
crossAxisAlignment: CrossAxisAlignment.center, child: Center(
mainAxisAlignment: MainAxisAlignment.center, child: Row(
children: [ crossAxisAlignment: CrossAxisAlignment.center,
const Spacer(), mainAxisAlignment: MainAxisAlignment.center,
Expanded( children: [
flex: 2, const Spacer(),
child: SvgPicture.asset( Expanded(
Assets.loginLogo, flex: 3,
child: SvgPicture.asset(
Assets.loginLogo,
),
), ),
), const Spacer(),
const Spacer(), Expanded(
Container( flex: 3,
decoration: BoxDecoration( child: Container(
color: Colors.white.withOpacity(0.1), decoration: BoxDecoration(
borderRadius: const BorderRadius.all(Radius.circular(30)), color: Colors.white.withOpacity(0.1),
border: Border.all(color: ColorsManager.graysColor.withOpacity(0.2)), borderRadius: const BorderRadius.all(Radius.circular(30)),
), border: Border.all(color: ColorsManager.graysColor.withOpacity(0.2)),
child: Form( ),
key: forgetBloc.forgetFormKey, child: Form(
child: Padding( key: forgetBloc.forgetFormKey,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 40, vertical: 25), padding: EdgeInsets.symmetric(
child: Column( horizontal: size.width*0.02,
mainAxisAlignment: MainAxisAlignment.spaceEvenly, vertical: size.width*0.003),
crossAxisAlignment: CrossAxisAlignment.start, child: Column(
children: <Widget>[ mainAxisAlignment: MainAxisAlignment.spaceEvenly,
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(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start, children: <Widget>[
children: [ const SizedBox(height: 10),
Text( const Text(
"Country/Region", 'Forget Password',
style: smallTextStyle, style: TextStyle(
color: Colors.white,
fontSize: 24,
fontWeight: FontWeight.bold),
), ),
const SizedBox(height: 10), const SizedBox(height: 10),
SizedBox( Text(
width: MediaQuery.of(context).size.width * 0.2, 'Please fill in your account information to\nretrieve your password',
child: DropdownButtonFormField<String>( style: Theme.of(context).textTheme.bodySmall,
validator: forgetBloc.validateRegion, ),
icon: const Icon( const SizedBox(height: 10),
Icons.keyboard_arrow_down_outlined, Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
"Country/Region",
style: Theme.of(context).textTheme.bodySmall,
), ),
decoration: textBoxDecoration()!.copyWith( const SizedBox(height: 10),
hintText: null, SizedBox(
child: DropdownButtonFormField<String>(
validator: forgetBloc.validateRegion,
icon: const Icon(
Icons.keyboard_arrow_down_outlined,
),
decoration: textBoxDecoration()!.copyWith(
hintText: null,
),
hint: SizedBox(
width: size.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: Theme.of(context).textTheme.bodySmall,
), ),
hint: const Align( const SizedBox(height: 10),
alignment: Alignment.centerLeft, SizedBox(
child: Text( child: TextFormField(
'Select your region/country', validator: forgetBloc.validateEmail,
textAlign: TextAlign.center, 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(
const SizedBox(height: 20.0), crossAxisAlignment: CrossAxisAlignment.start,
Column( mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start, children: [
mainAxisAlignment: MainAxisAlignment.start, Text("One Time Password",
children: [ style: Theme.of(context).textTheme.bodySmall,),
Text("One Time Password", const SizedBox(height: 10),
style: smallTextStyle,), SizedBox(
const SizedBox(height: 10), child: TextFormField(
SizedBox( validator: forgetBloc.validateCode,
width: MediaQuery.sizeOf(context).width * 0.2, keyboardType: TextInputType.visiblePassword,
child: TextFormField( controller: forgetBloc.forgetOtp,
validator: forgetBloc.validateCode, decoration: textBoxDecoration()!.copyWith(
keyboardType: TextInputType.visiblePassword, hintText: 'Enter Code',
controller: forgetBloc.forgetOtp, suffixIcon: SizedBox(
decoration: textBoxDecoration()!.copyWith( width: 100,
hintText: 'Enter Code', child: Center(
suffixIcon: SizedBox( child: InkWell(
width: 100, onTap: () {
child: Center( BlocProvider.of<AuthBloc>(context).add(StartTimerEvent());
child: InkWell( },
onTap: () { child: Text(
BlocProvider.of<AuthBloc>(context).add(StartTimerEvent()); 'Get Code ${state is TimerState && !state.isButtonEnabled ? "(${state.remainingTime.toString()})" : ""}',
}, style: TextStyle(
child: Text( color: state is TimerState && !state.isButtonEnabled
'Get Code ${state is TimerState && !state.isButtonEnabled ? "(${state.remainingTime.toString()})" : ""}', ? Colors.grey
style: TextStyle( : ColorsManager.btnColor,
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(
const SizedBox(height: 20.0), crossAxisAlignment: CrossAxisAlignment.start,
Column( mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start, children: [
mainAxisAlignment: MainAxisAlignment.start, Text("Password",
children: [ style: Theme.of(context).textTheme.bodySmall,),
Text("Password", const SizedBox(height: 10),
style: smallTextStyle,), SizedBox(
const SizedBox(height: 10), child: TextFormField(
SizedBox( validator: forgetBloc.passwordValidator,
width: MediaQuery.sizeOf(context).width * 0.2, keyboardType: TextInputType.visiblePassword,
child: TextFormField( controller: forgetBloc.forgetPasswordController,
validator: forgetBloc.passwordValidator, decoration: textBoxDecoration()!.copyWith(
keyboardType: TextInputType.visiblePassword, hintText: 'At least 8 characters',
controller: forgetBloc.forgetPasswordController, ),
decoration: textBoxDecoration()!.copyWith( style: const TextStyle(color: Colors.black),
hintText: 'At least 8 characters', ),
), ),
style: const TextStyle(color: Colors.black), ],
),
), ),
const SizedBox(
height: 10,
),
const SizedBox(height: 20.0),
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
width: size.width * 0.2,
child: DefaultButton(
backgroundColor: ColorsManager.btnColor,
child: const Text('Submit'),
onPressed: () {
if (forgetBloc.forgetFormKey.currentState!.validate()) {
forgetBloc.add(ChangePasswordEvent());
}
},
),
),
],
),
const SizedBox(height: 10.0),
SizedBox(child: Text(forgetBloc.validate,
style: const TextStyle(fontWeight: FontWeight.w700,color: ColorsManager.red ),),),
SizedBox(height: 10,),
SizedBox(
width: size.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 { class LoginMobilePage extends StatelessWidget {
const LoginMobilePage({super.key}); const LoginMobilePage({super.key});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
@ -39,7 +38,7 @@ class LoginMobilePage extends StatelessWidget {
} }
}, },
builder: (context, state) { builder: (context, state) {
if (state is LoginLoading) { if (state is AuthLoading) {
return const Center(child: CircularProgressIndicator()); return const Center(child: CircularProgressIndicator());
} else { } else {
return _buildLoginForm(context); return _buildLoginForm(context);
@ -128,7 +127,7 @@ class LoginMobilePage extends StatelessWidget {
children: [ children: [
Text( Text(
"Country/Region", "Country/Region",
style: smallTextStyle, style: Theme.of(context).textTheme.bodySmall,
), ),
SizedBox( SizedBox(
child: DropdownButtonFormField<String>( child: DropdownButtonFormField<String>(
@ -169,7 +168,7 @@ class LoginMobilePage extends StatelessWidget {
children: [ children: [
Text( Text(
"Email", "Email",
style: smallTextStyle, style: Theme.of(context).textTheme.bodySmall,
), ),
SizedBox( SizedBox(
child: TextFormField( child: TextFormField(
@ -189,7 +188,7 @@ class LoginMobilePage extends StatelessWidget {
children: [ children: [
Text( Text(
"Password", "Password",
style: smallTextStyle, style: Theme.of(context).textTheme.bodySmall,
), ),
SizedBox( SizedBox(
child: TextFormField( child: TextFormField(
@ -222,7 +221,7 @@ class LoginMobilePage extends StatelessWidget {
}, },
child: Text( child: Text(
"Forgot Password?", "Forgot Password?",
style: smallTextStyle, style: Theme.of(context).textTheme.bodySmall,
), ),
), ),
], ],
@ -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( const SizedBox(
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,

View File

@ -7,7 +7,6 @@ import 'package:syncrow_web/utils/responsive_layout.dart';
class LoginPage extends StatelessWidget { class LoginPage extends StatelessWidget {
const LoginPage({super.key}); const LoginPage({super.key});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return const ResponsiveLayout( return const ResponsiveLayout(

View File

@ -15,14 +15,20 @@ import 'package:syncrow_web/utils/constants/assets.dart';
import 'package:syncrow_web/pages/home/view/home_page.dart'; import 'package:syncrow_web/pages/home/view/home_page.dart';
import 'package:syncrow_web/utils/style.dart'; import 'package:syncrow_web/utils/style.dart';
class LoginWebPage extends StatelessWidget { class LoginWebPage extends StatefulWidget {
const LoginWebPage({super.key}); const LoginWebPage({super.key});
@override
State<LoginWebPage> createState() => _LoginWebPageState();
}
class _LoginWebPageState extends State<LoginWebPage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
body: BlocProvider( body: BlocProvider(
create: (context) => AuthBloc(), create: (BuildContext context) => AuthBloc(),
child: BlocConsumer<AuthBloc, AuthState>( child: BlocConsumer<AuthBloc, AuthState>(
listener: (context, state) { listener: (context, state) {
if (state is LoginSuccess) { if (state is LoginSuccess) {
@ -41,7 +47,7 @@ class LoginWebPage extends StatelessWidget {
} }
}, },
builder: (context, state) { builder: (context, state) {
if (state is LoginLoading) { if (state is AuthLoading) {
return const Center(child: CircularProgressIndicator()); return const Center(child: CircularProgressIndicator());
} else { } else {
return _buildLoginForm(context,state); return _buildLoginForm(context,state);
@ -54,365 +60,282 @@ class LoginWebPage extends StatelessWidget {
Widget _buildLoginForm(BuildContext context,AuthState state) { Widget _buildLoginForm(BuildContext context,AuthState state) {
final loginBloc = BlocProvider.of<AuthBloc>(context); final loginBloc = BlocProvider.of<AuthBloc>(context);
Size size = MediaQuery.of(context).size;
late ScrollController _scrollController;
_scrollController = ScrollController();
void _scrollToCenter() {
final double middlePosition = _scrollController.position.maxScrollExtent / 2;
_scrollController.animateTo(
middlePosition,
duration: const Duration(seconds: 1),
curve: Curves.easeInOut,
);
}
WidgetsBinding.instance.addPostFrameCallback((_) {
_scrollToCenter();
});
return FirstLayer( return FirstLayer(
second: Container( second: Center(
margin: const EdgeInsets.all(50), child: ListView(
decoration: BoxDecoration( controller: _scrollController,
color: Colors.black.withOpacity(0.3), shrinkWrap: true,
borderRadius: const BorderRadius.all(Radius.circular(20)), children: [
), Container(
child: Center( padding: EdgeInsets.all(size.width*0.02) ,
child: ListView( margin: EdgeInsets.all(size.width*0.09),
shrinkWrap: true, decoration: BoxDecoration(
children: [ color: Colors.black.withOpacity(0.3),
Row( borderRadius: const BorderRadius.all(Radius.circular(20)),
),
child: Center(
child:Row(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
const Spacer(), const Spacer(),
Expanded( Expanded(
flex: 2, flex: 3,
child: SvgPicture.asset( child: SvgPicture.asset(
Assets.loginLogo, Assets.loginLogo,
), ),
), ),
const Spacer(), const Spacer(),
Container( Expanded(
decoration: BoxDecoration( flex: 3,
color: Colors.white.withOpacity(0.1), child: Container(
borderRadius: const BorderRadius.all(Radius.circular(30)), decoration: BoxDecoration(
border: Border.all(color: ColorsManager.graysColor.withOpacity(0.2))), color: Colors.white.withOpacity(0.1),
child: Form( borderRadius: const BorderRadius.all(Radius.circular(30)),
key: loginBloc.loginFormKey, border: Border.all(color: ColorsManager.graysColor.withOpacity(0.2))),
child: Padding( child: Form(
padding: const EdgeInsets.symmetric(horizontal: 50, vertical: 25), key: loginBloc.loginFormKey,
child: Column( child: Padding(
mainAxisAlignment: MainAxisAlignment.spaceEvenly, padding: EdgeInsets.symmetric(
crossAxisAlignment: CrossAxisAlignment.start, horizontal: size.width*0.02,
children: <Widget>[ vertical: size.width*0.003),
const SizedBox(height: 15), child: Column(
const Text( mainAxisAlignment: MainAxisAlignment.spaceEvenly,
'Login',
style: TextStyle(
color: Colors.white,
fontSize: 24,
fontWeight: FontWeight.bold),
),
const SizedBox(height: 40),
Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start, children: <Widget>[
children: [ const SizedBox(height: 40),
Text( Text(
"Country/Region", 'Login',
style: smallTextStyle, style:Theme.of(context).textTheme.headlineLarge),
), SizedBox(height: size.height*0.03),
const SizedBox( Column(
height: 10, crossAxisAlignment: CrossAxisAlignment.start,
), mainAxisAlignment: MainAxisAlignment.start,
SizedBox( children: [
width: MediaQuery.of(context).size.width * 0.2, Text(
child: DropdownButtonFormField<String>( "Country/Region",
validator:loginBloc.validateRegion , style: Theme.of(context).textTheme.bodySmall,
icon: const Icon(
Icons.keyboard_arrow_down_outlined,
), ),
decoration: textBoxDecoration()!.copyWith( const SizedBox(height: 10,),
hintText: null, SizedBox(
child: DropdownButtonFormField<String>(
validator:loginBloc.validateRegion ,
icon: const Icon(
Icons.keyboard_arrow_down_outlined,
),
decoration: textBoxDecoration()!.copyWith(
hintText: null,),
hint: SizedBox(
width: size.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) {},
),
)
],
),
const SizedBox(height: 20.0),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text("Email",
style: Theme.of(context).textTheme.bodySmall,
), ),
hint: const Align( const SizedBox(
alignment: Alignment.centerLeft, height: 10,
child: Text( ),
'Select your region/country', SizedBox(
textAlign: TextAlign.center, child: TextFormField(
validator:loginBloc.validateEmail ,
controller:loginBloc.loginEmailController,
decoration: textBoxDecoration()!.copyWith(hintText: 'Enter your email'),
style: const TextStyle(color: Colors.black),
), ),
), ),
isDense: true, ],
style: const TextStyle(color: Colors.black), ),
items:loginBloc.regions.map((String region) { const SizedBox(height: 20.0),
return DropdownMenuItem<String>( Column(
value: region, crossAxisAlignment: CrossAxisAlignment.start,
child: Text(region), mainAxisAlignment: MainAxisAlignment.start,
); children: [
}).toList(), Text("Password", style: Theme.of(context).textTheme.bodySmall,),
onChanged: (String? value) { const SizedBox(
print(value); height: 10,
}, ),
), SizedBox(
) child: TextFormField(
], validator:loginBloc.validatePassword,
), obscureText:loginBloc.obscureText,
const SizedBox(height: 20.0), keyboardType: TextInputType.visiblePassword,
Column( controller:loginBloc.loginPasswordController,
crossAxisAlignment: CrossAxisAlignment.start, decoration: textBoxDecoration()!.copyWith(
mainAxisAlignment: MainAxisAlignment.start, hintText: 'At least 8 characters',
children: [ suffixIcon: IconButton(onPressed: () {
Text("Email", loginBloc.add(PasswordVisibleEvent(newValue: loginBloc.obscureText));
style: smallTextStyle, },
icon: SizedBox(
child: SvgPicture.asset(
loginBloc.obscureText?
Assets.visiblePassword :
Assets.invisiblePassword,
height: 15,
width: 15,
),
),
)
),
style: const TextStyle(color: Colors.black),
),
),
],
), ),
const SizedBox( const SizedBox(
height: 10, height: 20,
), ),
SizedBox( SizedBox(
width: MediaQuery.sizeOf(context).width * 0.2, child: Row(
child: TextFormField( mainAxisAlignment: MainAxisAlignment.end,
validator:loginBloc.validateEmail , children: [
controller:loginBloc.loginEmailController, InkWell(
decoration: textBoxDecoration()!.copyWith(hintText: 'Enter your email'), onTap: () {
style: const TextStyle(color: Colors.black), Navigator.of(context).push(MaterialPageRoute(builder: (context) => const ForgetPasswordPage(),));
), },
), child: Text(
], "Forgot Password?",
), style: Theme.of(context).textTheme.bodySmall,
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,
), ),
), ),
) ],
),
style: const TextStyle(color: Colors.black),
), ),
), ),
], const SizedBox(
), height: 20,
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));
},
),
), ),
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:size.width * 0.14,
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: 20.0),
SizedBox( SizedBox(
width: MediaQuery.sizeOf(context).width * 0.2, width:size.width * 0.2,
child: RichText( child: DefaultButton(
text: TextSpan( backgroundColor: loginBloc.isChecked?
text: 'Agree to ', ColorsManager.btnColor:ColorsManager.grayColor,
style: const TextStyle(color: Colors.white), child: const Text('Sign in'),
children: [ onPressed: () {
TextSpan( if (loginBloc.loginFormKey.currentState!.validate()) {
text: '(Terms of Service)', loginBloc.add(LoginButtonPressed(
style: const TextStyle( username: loginBloc.loginEmailController.text,
color: Colors.black), password: loginBloc.loginPasswordController.text,
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: 15.0),
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [ SizedBox(child: Text(loginBloc.validate,
style: const TextStyle(fontWeight: FontWeight.w700,color: ColorsManager.red ),),)],)
], ],
), ),
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(), 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

@ -1,6 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/style.dart';
class DefaultButton extends StatelessWidget { class DefaultButton extends StatelessWidget {
const DefaultButton({ const DefaultButton({
@ -48,7 +47,7 @@ class DefaultButton extends StatelessWidget {
ButtonStyle( ButtonStyle(
textStyle: MaterialStateProperty.all( textStyle: MaterialStateProperty.all(
customTextStyle customTextStyle
?? smallTextStyle.copyWith( ?? Theme.of(context).textTheme.bodySmall!.copyWith(
fontSize: 13, fontSize: 13,
color: foregroundColor, color: foregroundColor,
fontWeight: FontWeight.normal fontWeight: FontWeight.normal

View File

@ -13,7 +13,7 @@ class HomeMobilePage extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size; Size size = MediaQuery.of(context).size;
return WebScaffold( return WebScaffold(
enableMenuSideba:false , enableMenuSideba: false,
appBarTitle: Row( appBarTitle: Row(
children: [ children: [
SvgPicture.asset( SvgPicture.asset(
@ -51,11 +51,11 @@ class HomeMobilePage extends StatelessWidget {
childAspectRatio: 1.5, childAspectRatio: 1.5,
), ),
itemBuilder: (context, index) { itemBuilder: (context, index) {
return HomeCard( return HomeCard(
index:index, index: index,
active:ceilingSensorButtons[index]['active'], active: homeItems[index]['active'],
name: ceilingSensorButtons[index]['title'], name: homeItems[index]['title'],
img:ceilingSensorButtons[index]['icon'] , img: homeItems[index]['icon'],
onTap: () {}, onTap: () {},
); );
}, },
@ -69,8 +69,7 @@ class HomeMobilePage extends StatelessWidget {
); );
} }
dynamic ceilingSensorButtons = dynamic homeItems = [
[
{ {
'title': 'Access', 'title': 'Access',
'icon': Assets.accessIcon, 'icon': Assets.accessIcon,
@ -84,7 +83,7 @@ class HomeMobilePage extends StatelessWidget {
}, },
{ {
'title': 'Devices', 'title': 'Devices',
'icon':Assets.devicesIcon, 'icon': Assets.devicesIcon,
'active': true, 'active': true,
}, },
{ {
@ -108,11 +107,12 @@ class HomeMobilePage extends StatelessWidget {
'icon': Assets.integrationsIcon, 'icon': Assets.integrationsIcon,
'color': ColorsManager.slidingBlueColor.withOpacity(0.2), 'color': ColorsManager.slidingBlueColor.withOpacity(0.2),
'active': false, 'active': false,
}, { },
'title': 'Asset', {
'icon': Assets.assetIcon, 'title': 'Asset',
'color': ColorsManager.slidingBlueColor.withOpacity(0.2), 'icon': Assets.assetIcon,
'active': false, 'color': ColorsManager.slidingBlueColor.withOpacity(0.2),
}, 'active': false,
},
]; ];
} }

View File

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

View File

@ -1,5 +1,6 @@
import 'dart:convert'; 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/pages/auth/model/token.dart';
import 'package:syncrow_web/services/api/http_service.dart'; import 'package:syncrow_web/services/api/http_service.dart';
import 'package:syncrow_web/utils/constants/api_const.dart'; import 'package:syncrow_web/utils/constants/api_const.dart';
@ -17,51 +18,50 @@ class AuthenticationAPI {
return response; 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( final response = await HTTPService().post(
path: ApiEndpoints.forgetPassword, path: ApiEndpoints.forgetPassword,
body: { body: {"email": email, "password": password},
"email": email,
"password": password
},
showServerMessage: true, showServerMessage: true,
expectedResponseModel: (json) { expectedResponseModel: (json) {});
});
return response; return response;
} }
static Future sendOtp({ required var email}) async { static Future sendOtp({required var email}) async {
final response = await HTTPService().post( final response = await HTTPService().post(
path: ApiEndpoints.sendOtp, path: ApiEndpoints.sendOtp,
body: { body: {"email": email, "type": "VERIFICATION"},
"email": email,
"type": "VERIFICATION"
},
showServerMessage: true, showServerMessage: true,
expectedResponseModel: (json) { expectedResponseModel: (json) {});
print('json===$json');
});
return response; 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( final response = await HTTPService().post(
path: ApiEndpoints.verifyOtp, path: ApiEndpoints.verifyOtp,
body: { body: {"email": email, "type": "VERIFICATION", "otpCode": otpCode},
"email": email,
"type": "VERIFICATION",
"otpCode": otpCode
},
showServerMessage: true, showServerMessage: true,
expectedResponseModel: (json) { expectedResponseModel: (json) {
print('json===${json['message']}'); if (json['message'] == 'Otp Verified Successfully') {
if(json['message']=='Otp Verified Successfully'){ return true;
return true; } else {
}else{ return false;
return false; }
}
}); });
return response; 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 forgetPassword = '$baseUrl/authentication/user/forget-password';
static const String sendOtp = '$baseUrl/authentication/user/send-otp'; static const String sendOtp = '$baseUrl/authentication/user/send-otp';
static const String verifyOtp = '$baseUrl/authentication/user/verify-otp'; static const String verifyOtp = '$baseUrl/authentication/user/verify-otp';
static const String getRegion = '$baseUrl/region';
} }

View File

@ -22,11 +22,5 @@ InputDecoration? textBoxDecoration({bool suffixIcon = false}) => InputDecoration
); );
TextStyle appBarTextStyle =
const TextStyle(fontSize: 20, color: ColorsManager.whiteColors);
TextStyle smallTextStyle =
const TextStyle(fontSize: 13, color: ColorsManager.whiteColors,fontWeight: FontWeight.bold);
Decoration containerDecoration = const BoxDecoration(color: Colors.white,borderRadius: BorderRadius.all(Radius.circular(20))); Decoration containerDecoration = const BoxDecoration(color: Colors.white,borderRadius: BorderRadius.all(Radius.circular(20)));

View File

@ -2,28 +2,23 @@ import 'package:flutter/material.dart';
import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
class WebAppBar extends StatelessWidget { class WebAppBar extends StatelessWidget {
final Widget? title; final Widget? title;
final List<Widget>? body; final List<Widget>? body;
const WebAppBar({super.key,this.title,this.body}); const WebAppBar({super.key, this.title, this.body});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Container(
height: 120, height: 120,
decoration: const BoxDecoration(color:ColorsManager.secondaryColor ), decoration: const BoxDecoration(color: ColorsManager.secondaryColor),
padding: const EdgeInsets.all(10), padding: const EdgeInsets.all(10),
child: Expanded( child: Expanded(
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
SizedBox(width: 40,),
Expanded( Expanded(
child: title! child: title!,
// Text( ),
// title!,style: const TextStyle(
// fontSize: 30,
// color: Colors.white),)
),
if (body != null) if (body != null)
Expanded( Expanded(
flex: 2, flex: 2,
@ -32,31 +27,36 @@ class WebAppBar extends StatelessWidget {
children: body!, children: body!,
), ),
), ),
const Row( Row(
children: [ children: [
SizedBox(width: 10,), const SizedBox(
SizedBox.square( width: 10,
dimension: 40, ),
child: CircleAvatar( const SizedBox.square(
backgroundColor: Colors.white, dimension: 40,
child: SizedBox.square( child: CircleAvatar(
dimension: 35, backgroundColor: Colors.white,
child: CircleAvatar( child: SizedBox.square(
backgroundColor: Colors.grey, dimension: 35,
child: FlutterLogo(), child: CircleAvatar(
), backgroundColor: Colors.grey,
), child: FlutterLogo(),
), ),
), ),
const SizedBox(width: 10,), ),
const Text('mohamamd alnemer ',style: TextStyle(fontSize: 16,color: Colors.white),), ),
Icon(Icons.arrow_drop_down,color: ColorsManager.whiteColors,), const SizedBox(
SizedBox(width: 40,) width: 10,
),
Text(
'mohamamd alnemer ',
style: Theme.of(context).textTheme.bodyLarge,
),
], ],
) )
], ],
), ),
) , ),
); );
} }
} }