added settings
This commit is contained in:
parent
a4527fbb73
commit
c512f143cb
|
|
@ -0,0 +1 @@
|
|||
export 'user_bloc/user_bloc.dart';
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
import '../../core/core.dart';
|
||||
import '../../domain/domain.dart';
|
||||
|
||||
part 'user_event.dart';
|
||||
part 'user_state.dart';
|
||||
|
||||
class UserBloc extends Bloc<UserEvent, UserState> {
|
||||
final GetCachedUserUseCase _getCachedUserUseCase;
|
||||
final SignInUseCase _signInUseCase;
|
||||
final SignUpUseCase _signUpUseCase;
|
||||
final SignOutUseCase _signOutUseCase;
|
||||
UserBloc(
|
||||
this._signInUseCase,
|
||||
this._getCachedUserUseCase,
|
||||
this._signOutUseCase,
|
||||
this._signUpUseCase,
|
||||
) : super(UserInitial()) {
|
||||
on<SignInUser>(_onSignIn);
|
||||
on<SignUpUser>(_onSignUp);
|
||||
on<CheckUser>(_onCheckUser);
|
||||
on<SignOutUser>(_onSignOut);
|
||||
}
|
||||
|
||||
void _onSignIn(SignInUser event, Emitter<UserState> emit) async {
|
||||
try {
|
||||
emit(UserLoading());
|
||||
final result = await _signInUseCase(event.params);
|
||||
result.fold(
|
||||
(failure) => emit(UserLoggedFail(failure)),
|
||||
(user) => emit(UserLogged(user)),
|
||||
);
|
||||
} catch (e) {
|
||||
emit(UserLoggedFail(ExceptionFailure()));
|
||||
}
|
||||
}
|
||||
|
||||
void _onCheckUser(CheckUser event, Emitter<UserState> emit) async {
|
||||
try {
|
||||
emit(UserLoading());
|
||||
final result = await _getCachedUserUseCase(NoParams());
|
||||
result.fold(
|
||||
(failure) => emit(UserLoggedFail(failure)),
|
||||
(user) => emit(UserLogged(user)),
|
||||
);
|
||||
} catch (e) {
|
||||
emit(UserLoggedFail(ExceptionFailure()));
|
||||
}
|
||||
}
|
||||
|
||||
FutureOr<void> _onSignUp(SignUpUser event, Emitter<UserState> emit) async {
|
||||
try {
|
||||
emit(UserLoading());
|
||||
final result = await _signUpUseCase(event.params);
|
||||
result.fold(
|
||||
(failure) => emit(UserLoggedFail(failure)),
|
||||
(user) => emit(UserLogged(user)),
|
||||
);
|
||||
} catch (e) {
|
||||
emit(UserLoggedFail(ExceptionFailure()));
|
||||
}
|
||||
}
|
||||
|
||||
void _onSignOut(SignOutUser event, Emitter<UserState> emit) async {
|
||||
try {
|
||||
emit(UserLoading());
|
||||
await _signOutUseCase(NoParams());
|
||||
emit(UserLoggedOut());
|
||||
} catch (e) {
|
||||
emit(UserLoggedFail(ExceptionFailure()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
part of 'user_bloc.dart';
|
||||
|
||||
@immutable
|
||||
abstract class UserEvent {}
|
||||
|
||||
class SignInUser extends UserEvent {
|
||||
final SignInParams params;
|
||||
SignInUser(this.params);
|
||||
}
|
||||
|
||||
class SignUpUser extends UserEvent {
|
||||
final SignUpParams params;
|
||||
SignUpUser(this.params);
|
||||
}
|
||||
|
||||
class SignOutUser extends UserEvent {}
|
||||
|
||||
class CheckUser extends UserEvent {}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
part of 'user_bloc.dart';
|
||||
|
||||
@immutable
|
||||
abstract class UserState extends Equatable {}
|
||||
|
||||
class UserInitial extends UserState {
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class UserLoading extends UserState {
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class UserLogged extends UserState {
|
||||
final User user;
|
||||
UserLogged(this.user);
|
||||
@override
|
||||
List<Object> get props => [user];
|
||||
}
|
||||
|
||||
class UserLoggedFail extends UserState {
|
||||
final Failure failure;
|
||||
UserLoggedFail(this.failure);
|
||||
@override
|
||||
List<Object> get props => [failure];
|
||||
}
|
||||
|
||||
class UserLoggedOut extends UserState {
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
|
@ -1,17 +1,28 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
import '../../application/application.dart';
|
||||
import '../core.dart';
|
||||
|
||||
import '../../di/di.dart' as di;
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
const MyApp({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return const MaterialApp(
|
||||
debugShowCheckedModeBanner: false,
|
||||
title: appTitle,
|
||||
onGenerateRoute: AppRouter.onGenerateRoute,
|
||||
initialRoute: AppRouter.splash,
|
||||
return MultiBlocProvider(
|
||||
providers: [
|
||||
BlocProvider(
|
||||
create: (context) => di.sl<UserBloc>()..add(CheckUser()),
|
||||
),
|
||||
],
|
||||
child: const MaterialApp(
|
||||
debugShowCheckedModeBanner: false,
|
||||
title: appTitle,
|
||||
onGenerateRoute: AppRouter.onGenerateRoute,
|
||||
initialRoute: AppRouter.splash,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,3 +3,6 @@ export 'constants/constants.dart';
|
|||
export 'errors/errors.dart';
|
||||
export 'router/router.dart';
|
||||
export 'observer/observer.dart';
|
||||
export 'usecases/usecases.dart';
|
||||
export 'networkchecker/network_info.dart';
|
||||
export 'utils/utils.dart';
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
import 'package:internet_connection_checker/internet_connection_checker.dart';
|
||||
|
||||
abstract class NetworkInfo {
|
||||
Future<bool> get isConnected;
|
||||
}
|
||||
|
||||
class NetworkInfoImpl implements NetworkInfo {
|
||||
final InternetConnectionChecker connectionChecker;
|
||||
|
||||
NetworkInfoImpl(this.connectionChecker);
|
||||
|
||||
@override
|
||||
Future<bool> get isConnected => connectionChecker.hasConnection;
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
import 'package:dartz/dartz.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
import '../errors/failures.dart';
|
||||
|
||||
abstract class UseCase<Type, Params> {
|
||||
Future<Either<Failure, Type>> call(Params params);
|
||||
}
|
||||
|
||||
class NoParams extends Equatable {
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
// TODO Implement this library.
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
export 'form_validator.dart';
|
||||
|
||||
class FormValidator {
|
||||
static String? validateField(String? val) {
|
||||
if (val == null || val.isEmpty) {
|
||||
return 'This field can\'t be empty';
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
export 'data_sources/data_sources.dart';
|
||||
export 'models/models.dart';
|
||||
export 'repositories/repositories.dart';
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
export 'local/local.dart';
|
||||
export 'remote/remote.dart';
|
||||
|
|
@ -0,0 +1 @@
|
|||
export 'user_local_data_source.dart';
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import '../../../core/core.dart';
|
||||
import '../../models/models.dart';
|
||||
|
||||
abstract class UserLocalDataSource {
|
||||
Future<String> getToken();
|
||||
|
||||
Future<UserModel> getUser();
|
||||
|
||||
Future<void> saveToken(String token);
|
||||
|
||||
Future<void> saveUser(UserModel user);
|
||||
|
||||
Future<void> clearCache();
|
||||
|
||||
Future<bool> isTokenAvailable();
|
||||
}
|
||||
|
||||
const cachedToken = 'TOKEN';
|
||||
const cachedUser = 'USER';
|
||||
|
||||
class UserLocalDataSourceImpl implements UserLocalDataSource {
|
||||
final FlutterSecureStorage secureStorage;
|
||||
final SharedPreferences sharedPreferences;
|
||||
UserLocalDataSourceImpl({required this.sharedPreferences, required this.secureStorage});
|
||||
|
||||
@override
|
||||
Future<String> getToken() async {
|
||||
String? token = await secureStorage.read(key: cachedToken);
|
||||
return Future.value(token);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> saveToken(String token) async {
|
||||
await secureStorage.write(key: cachedToken, value: token);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<UserModel> getUser() async {
|
||||
if (sharedPreferences.getBool('first_run') ?? true) {
|
||||
await secureStorage.deleteAll();
|
||||
sharedPreferences.setBool('first_run', false);
|
||||
}
|
||||
final jsonString = sharedPreferences.getString(cachedUser);
|
||||
if (jsonString != null) {
|
||||
return Future.value(userModelFromJson(jsonString));
|
||||
} else {
|
||||
throw CacheException();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> saveUser(UserModel user) {
|
||||
return sharedPreferences.setString(
|
||||
cachedUser,
|
||||
userModelToJson(user),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> isTokenAvailable() async {
|
||||
String? token = await secureStorage.read(key: cachedToken);
|
||||
return Future.value((token != null));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> clearCache() async {
|
||||
await secureStorage.deleteAll();
|
||||
// await sharedPreferences.remove(cachedCart);
|
||||
await sharedPreferences.remove(cachedUser);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
export 'user_remote_data_source.dart';
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
import '../../../core/core.dart';
|
||||
import '../../../domain/domain.dart';
|
||||
import '../../data.dart';
|
||||
|
||||
abstract class UserRemoteDataSource {
|
||||
Future<AuthenticationResponseModel> signIn(SignInParams params);
|
||||
Future<AuthenticationResponseModel> signUp(SignUpParams params);
|
||||
}
|
||||
|
||||
class UserRemoteDataSourceImpl implements UserRemoteDataSource {
|
||||
final http.Client client;
|
||||
UserRemoteDataSourceImpl({required this.client});
|
||||
|
||||
@override
|
||||
Future<AuthenticationResponseModel> signIn(SignInParams params) async {
|
||||
debugPrint('signIn');
|
||||
final response = await client.post(Uri.parse('$baseUrl/authentication/local/sign-in'),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: json.encode({
|
||||
'identifier': params.username,
|
||||
'password': params.password,
|
||||
}));
|
||||
if (response.statusCode == 200) {
|
||||
return authenticationResponseModelFromJson(response.body);
|
||||
} else if (response.statusCode == 400 || response.statusCode == 401) {
|
||||
throw CredentialFailure();
|
||||
} else {
|
||||
throw ServerException();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<AuthenticationResponseModel> signUp(SignUpParams params) async {
|
||||
final response = await client.post(Uri.parse('$baseUrl/authentication/local/sign-up'),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: json.encode({
|
||||
'firstName': params.firstName,
|
||||
'lastName': params.lastName,
|
||||
'email': params.email,
|
||||
'password': params.password,
|
||||
}));
|
||||
if (response.statusCode == 201) {
|
||||
return authenticationResponseModelFromJson(response.body);
|
||||
} else if (response.statusCode == 400 || response.statusCode == 401) {
|
||||
throw CredentialFailure();
|
||||
} else {
|
||||
throw ServerException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
export 'user/user_model.dart';
|
||||
export 'user/authentication_response_model.dart';
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'user_model.dart';
|
||||
|
||||
AuthenticationResponseModel authenticationResponseModelFromJson(String str) =>
|
||||
AuthenticationResponseModel.fromJson(json.decode(str));
|
||||
|
||||
String authenticationResponseModelToJson(AuthenticationResponseModel data) => json.encode(data.toJson());
|
||||
|
||||
class AuthenticationResponseModel {
|
||||
final String token;
|
||||
final UserModel user;
|
||||
|
||||
const AuthenticationResponseModel({
|
||||
required this.token,
|
||||
required this.user,
|
||||
});
|
||||
|
||||
factory AuthenticationResponseModel.fromJson(Map<String, dynamic> json) => AuthenticationResponseModel(
|
||||
token: json['token'],
|
||||
user: UserModel.fromJson(json['user']),
|
||||
);
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'token': token,
|
||||
'user': user.toJson(),
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import '../../../domain/entities/user/user.dart';
|
||||
|
||||
UserModel userModelFromJson(String str) => UserModel.fromJson(json.decode(str));
|
||||
|
||||
String userModelToJson(UserModel data) => json.encode(data.toJson());
|
||||
|
||||
class UserModel extends User {
|
||||
const UserModel({
|
||||
required super.id,
|
||||
required super.firstName,
|
||||
required super.lastName,
|
||||
required super.email,
|
||||
});
|
||||
|
||||
factory UserModel.fromJson(Map<String, dynamic> json) => UserModel(
|
||||
id: json['_id'],
|
||||
firstName: json['firstName'],
|
||||
lastName: json['lastName'],
|
||||
email: json['email'],
|
||||
);
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'_id': id,
|
||||
'firstName': firstName,
|
||||
'lastName': lastName,
|
||||
'email': email,
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
export 'user_repository_impl.dart';
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
import 'package:dartz/dartz.dart';
|
||||
|
||||
import '../../core/core.dart';
|
||||
import '../../domain/domain.dart';
|
||||
import '../data_sources/data_sources.dart';
|
||||
import '../models/user/authentication_response_model.dart';
|
||||
|
||||
typedef _DataSourceChooser = Future<AuthenticationResponseModel> Function();
|
||||
|
||||
class UserRepositoryImpl implements UserRepository {
|
||||
final UserRemoteDataSource remoteDataSource;
|
||||
final UserLocalDataSource localDataSource;
|
||||
final NetworkInfo networkInfo;
|
||||
|
||||
UserRepositoryImpl({
|
||||
required this.remoteDataSource,
|
||||
required this.localDataSource,
|
||||
required this.networkInfo,
|
||||
});
|
||||
|
||||
@override
|
||||
Future<Either<Failure, User>> signIn(params) async {
|
||||
return await _authenticate(() {
|
||||
return remoteDataSource.signIn(params);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Either<Failure, User>> signUp(params) async {
|
||||
return await _authenticate(() {
|
||||
return remoteDataSource.signUp(params);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Either<Failure, User>> getCachedUser() async {
|
||||
try {
|
||||
final user = await localDataSource.getUser();
|
||||
return Right(user);
|
||||
} on CacheFailure {
|
||||
return Left(CacheFailure());
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Either<Failure, NoParams>> signOut() async {
|
||||
try {
|
||||
await localDataSource.clearCache();
|
||||
return Right(NoParams());
|
||||
} on CacheFailure {
|
||||
return Left(CacheFailure());
|
||||
}
|
||||
}
|
||||
|
||||
Future<Either<Failure, User>> _authenticate(
|
||||
_DataSourceChooser getDataSource,
|
||||
) async {
|
||||
if (await networkInfo.isConnected) {
|
||||
try {
|
||||
final remoteResponse = await getDataSource();
|
||||
localDataSource.saveToken(remoteResponse.token);
|
||||
localDataSource.saveUser(remoteResponse.user);
|
||||
return Right(remoteResponse.user);
|
||||
} on Failure catch (failure) {
|
||||
return Left(failure);
|
||||
}
|
||||
} else {
|
||||
return Left(NetworkFailure());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
import 'package:internet_connection_checker/internet_connection_checker.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
import '../core/networkchecker/network_info.dart';
|
||||
import 'di.dart';
|
||||
|
||||
void registerCommonDependencies() async {
|
||||
final sharedPreferences = await SharedPreferences.getInstance();
|
||||
const secureStorage = FlutterSecureStorage();
|
||||
|
||||
sl.registerLazySingleton(() => sharedPreferences);
|
||||
sl.registerLazySingleton(() => secureStorage);
|
||||
sl.registerLazySingleton(() => http.Client());
|
||||
sl.registerLazySingleton(() => InternetConnectionChecker());
|
||||
|
||||
// Register NetworkInfo
|
||||
sl.registerLazySingleton<NetworkInfo>(() => NetworkInfoImpl(sl()));
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
import 'package:get_it/get_it.dart';
|
||||
|
||||
import 'common.dart';
|
||||
import 'user.dart';
|
||||
|
||||
final sl = GetIt.instance;
|
||||
|
||||
// Main Initialization
|
||||
Future<void> init() async {
|
||||
// Register features
|
||||
registerUserFeature();
|
||||
// registerCategoryFeature();
|
||||
// registerProductFeature();
|
||||
// registerDeliveryInfoFeature();
|
||||
// registerCartFeature();
|
||||
// registerOrderFeature();
|
||||
|
||||
// Register Cubits
|
||||
// registerCubits();
|
||||
|
||||
// Register common dependencies
|
||||
registerCommonDependencies();
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
// Feature: User
|
||||
|
||||
import '../application/user_bloc/user_bloc.dart';
|
||||
import '../data/data.dart';
|
||||
import '../domain/domain.dart';
|
||||
import 'di.dart';
|
||||
|
||||
void registerUserFeature() {
|
||||
// User BLoC and Use Cases
|
||||
sl.registerFactory(() => UserBloc(sl(), sl(), sl(), sl()));
|
||||
sl.registerLazySingleton(() => GetCachedUserUseCase(sl()));
|
||||
sl.registerLazySingleton(() => SignInUseCase(sl()));
|
||||
sl.registerLazySingleton(() => SignUpUseCase(sl()));
|
||||
sl.registerLazySingleton(() => SignOutUseCase(sl()));
|
||||
|
||||
// User Repository and Data Sources
|
||||
sl.registerLazySingleton<UserRepository>(
|
||||
() => UserRepositoryImpl(
|
||||
remoteDataSource: sl(),
|
||||
localDataSource: sl(),
|
||||
networkInfo: sl(),
|
||||
),
|
||||
);
|
||||
|
||||
sl.registerLazySingleton<UserLocalDataSource>(
|
||||
() => UserLocalDataSourceImpl(sharedPreferences: sl(), secureStorage: sl()),
|
||||
);
|
||||
|
||||
sl.registerLazySingleton<UserRemoteDataSource>(
|
||||
() => UserRemoteDataSourceImpl(client: sl()),
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
export 'entities/entities.dart';
|
||||
export 'repositories/repositories.dart';
|
||||
export 'usecases/usecases.dart';
|
||||
|
|
@ -0,0 +1 @@
|
|||
export 'user/user.dart';
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
import 'package:equatable/equatable.dart';
|
||||
|
||||
class User extends Equatable {
|
||||
final String id;
|
||||
final String firstName;
|
||||
final String lastName;
|
||||
final String? image;
|
||||
final String email;
|
||||
|
||||
const User({
|
||||
required this.id,
|
||||
required this.firstName,
|
||||
required this.lastName,
|
||||
this.image,
|
||||
required this.email,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object> get props => [
|
||||
id,
|
||||
firstName,
|
||||
lastName,
|
||||
email,
|
||||
];
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
export 'user_repository.dart';
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
import 'package:dartz/dartz.dart';
|
||||
|
||||
import '../../core/core.dart';
|
||||
import '../domain.dart';
|
||||
|
||||
abstract class UserRepository {
|
||||
Future<Either<Failure, User>> signIn(SignInParams params);
|
||||
Future<Either<Failure, User>> signUp(SignUpParams params);
|
||||
Future<Either<Failure, NoParams>> signOut();
|
||||
Future<Either<Failure, User>> getCachedUser();
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
export 'user/user.dart';
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
import 'package:dartz/dartz.dart';
|
||||
|
||||
import '../../../core/core.dart';
|
||||
import '../../domain.dart';
|
||||
|
||||
class GetCachedUserUseCase implements UseCase<User, NoParams> {
|
||||
final UserRepository repository;
|
||||
GetCachedUserUseCase(this.repository);
|
||||
|
||||
@override
|
||||
Future<Either<Failure, User>> call(NoParams params) async {
|
||||
return await repository.getCachedUser();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
import 'package:dartz/dartz.dart';
|
||||
|
||||
import '../../../core/core.dart';
|
||||
import '../../domain.dart';
|
||||
|
||||
class SignInUseCase implements UseCase<User, SignInParams> {
|
||||
final UserRepository repository;
|
||||
SignInUseCase(this.repository);
|
||||
|
||||
@override
|
||||
Future<Either<Failure, User>> call(SignInParams params) async {
|
||||
return await repository.signIn(params);
|
||||
}
|
||||
}
|
||||
|
||||
class SignInParams {
|
||||
final String username;
|
||||
final String password;
|
||||
const SignInParams({
|
||||
required this.username,
|
||||
required this.password,
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
import 'package:dartz/dartz.dart';
|
||||
|
||||
import '../../../core/core.dart';
|
||||
import '../../domain.dart';
|
||||
|
||||
class SignOutUseCase implements UseCase<NoParams, NoParams> {
|
||||
final UserRepository repository;
|
||||
SignOutUseCase(this.repository);
|
||||
|
||||
@override
|
||||
Future<Either<Failure, NoParams>> call(NoParams params) async {
|
||||
return await repository.signOut();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
import 'package:dartz/dartz.dart';
|
||||
|
||||
import '../../../core/core.dart';
|
||||
import '../../domain.dart';
|
||||
|
||||
class SignUpUseCase implements UseCase<User, SignUpParams> {
|
||||
final UserRepository repository;
|
||||
SignUpUseCase(this.repository);
|
||||
|
||||
@override
|
||||
Future<Either<Failure, User>> call(SignUpParams params) async {
|
||||
return await repository.signUp(params);
|
||||
}
|
||||
}
|
||||
|
||||
class SignUpParams {
|
||||
final String firstName;
|
||||
final String lastName;
|
||||
final String email;
|
||||
final String password;
|
||||
const SignUpParams({
|
||||
required this.firstName,
|
||||
required this.lastName,
|
||||
required this.email,
|
||||
required this.password,
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
export 'get_cached_user_usecase.dart';
|
||||
export 'sign_in_usecase.dart';
|
||||
export 'sign_out_usecase.dart';
|
||||
export 'sign_up_usecase.dart';
|
||||
|
|
@ -4,13 +4,14 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||
import 'package:flutter_phoenix/flutter_phoenix.dart';
|
||||
|
||||
import 'core/core.dart';
|
||||
import 'di/di.dart' as di;
|
||||
|
||||
Future<void> main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
// await GetStorage.init();
|
||||
|
||||
// await di.init();
|
||||
await di.init();
|
||||
|
||||
Bloc.observer = MyBlocObserver();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,33 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
|
||||
import '../../application/user_bloc/user_bloc.dart';
|
||||
import '../../configs/app.dart';
|
||||
import '../../configs/configs.dart';
|
||||
import '../../core/core.dart';
|
||||
import '../../domain/domain.dart';
|
||||
import '../widgets/button.dart';
|
||||
|
||||
class LoginScreen extends StatelessWidget {
|
||||
class LoginScreen extends StatefulWidget {
|
||||
const LoginScreen({super.key});
|
||||
|
||||
@override
|
||||
State<LoginScreen> createState() => _LoginScreenState();
|
||||
}
|
||||
|
||||
class _LoginScreenState extends State<LoginScreen> {
|
||||
final TextEditingController _userNameController = TextEditingController();
|
||||
final TextEditingController _passwordController = TextEditingController();
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_userNameController.dispose();
|
||||
_passwordController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
App.init(context);
|
||||
|
|
@ -82,68 +101,85 @@ class LoginScreen extends StatelessWidget {
|
|||
),
|
||||
child: Padding(
|
||||
padding: Space.hf().copyWith(top: 30),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Text(
|
||||
'Şahsy otaga giriş',
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Text(
|
||||
'Şahsy otaga giriş',
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
const Text(
|
||||
'özüňize berlen logini we açar sözi giriziň',
|
||||
style: TextStyle(
|
||||
color: Colors.grey,
|
||||
const Text(
|
||||
'özüňize berlen logini we açar sözi giriziň',
|
||||
style: TextStyle(
|
||||
color: Colors.grey,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
/// gap
|
||||
Space.yf(),
|
||||
/// gap
|
||||
Space.yf(),
|
||||
|
||||
/// username field
|
||||
const Text('Login'),
|
||||
Space.yf(0.30),
|
||||
const TextField(
|
||||
decoration: InputDecoration(
|
||||
hintText: 'Öz loginiňizi ýazyň',
|
||||
prefixIcon: Icon(Icons.person_outline),
|
||||
// suffixIcon: Icon(Icons.visibility_off),
|
||||
border: OutlineInputBorder(),
|
||||
/// username field
|
||||
const Text('Login'),
|
||||
Space.y!,
|
||||
TextFormField(
|
||||
controller: _userNameController,
|
||||
decoration: const InputDecoration(
|
||||
hintText: 'Öz loginiňizi ýazyň',
|
||||
prefixIcon: Icon(Icons.person_outline),
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
validator: (val) => FormValidator.validateField(val),
|
||||
),
|
||||
),
|
||||
|
||||
/// gap
|
||||
Space.yf(),
|
||||
/// gap
|
||||
Space.yf(),
|
||||
|
||||
/// password field
|
||||
const Text('Açar sözi'),
|
||||
Space.yf(0.30),
|
||||
const TextField(
|
||||
obscureText: true,
|
||||
decoration: InputDecoration(
|
||||
hintText: 'Öz açar sözüňi ýazyň',
|
||||
prefixIcon: Icon(Icons.lock_outline),
|
||||
suffixIcon: Icon(Icons.visibility_off),
|
||||
border: OutlineInputBorder(),
|
||||
/// password field
|
||||
const Text('Açar sözi'),
|
||||
Space.y!,
|
||||
TextFormField(
|
||||
controller: _passwordController,
|
||||
obscureText: true,
|
||||
decoration: const InputDecoration(
|
||||
hintText: 'Öz açar sözüňi ýazyň',
|
||||
prefixIcon: Icon(Icons.lock_outline),
|
||||
suffixIcon: Icon(Icons.visibility_off),
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
validator: (val) => FormValidator.validateField(val),
|
||||
),
|
||||
),
|
||||
|
||||
/// gap
|
||||
Space.yf(),
|
||||
/// gap
|
||||
Space.yf(),
|
||||
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: AppButton(
|
||||
textColor: AppColors.primary,
|
||||
btnColor: AppColors.yellow,
|
||||
onPressed: () {},
|
||||
text: 'Yzarlap başlaň',
|
||||
),
|
||||
)
|
||||
],
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: AppButton(
|
||||
textColor: AppColors.primary,
|
||||
btnColor: AppColors.yellow,
|
||||
onPressed: () {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
context.read<UserBloc>().add(
|
||||
SignInUser(
|
||||
SignInParams(
|
||||
username: _userNameController.text,
|
||||
password: _passwordController.text,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
text: 'Yzarlap başlaň',
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
|||
88
pubspec.lock
88
pubspec.lock
|
|
@ -134,6 +134,54 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.1"
|
||||
flutter_secure_storage:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_secure_storage
|
||||
sha256: "165164745e6afb5c0e3e3fcc72a012fb9e58496fb26ffb92cf22e16a821e85d0"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "9.2.2"
|
||||
flutter_secure_storage_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_secure_storage_linux
|
||||
sha256: "4d91bfc23047422cbcd73ac684bc169859ee766482517c22172c86596bf1464b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.1"
|
||||
flutter_secure_storage_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_secure_storage_macos
|
||||
sha256: "1693ab11121a5f925bbea0be725abfcfbbcf36c1e29e571f84a0c0f436147a81"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.2"
|
||||
flutter_secure_storage_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_secure_storage_platform_interface
|
||||
sha256: cf91ad32ce5adef6fba4d736a542baca9daf3beac4db2d04be350b87f69ac4a8
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.2"
|
||||
flutter_secure_storage_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_secure_storage_web
|
||||
sha256: f4ebff989b4f07b2656fb16b47852c0aab9fed9b4ec1c70103368337bc1886a9
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.1"
|
||||
flutter_secure_storage_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_secure_storage_windows
|
||||
sha256: b20b07cb5ed4ed74fc567b78a72936203f587eba460af1df11281c9326cd3709
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.2"
|
||||
flutter_svg:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
@ -184,6 +232,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.0+1"
|
||||
js:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: js
|
||||
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.7"
|
||||
leak_tracker:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -264,6 +320,30 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
path_provider:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider
|
||||
sha256: c9e7d3a4cd1410877472158bee69963a4579f78b68c65a2b7d40d1a7a88bb161
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.3"
|
||||
path_provider_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_android
|
||||
sha256: "30c5aa827a6ae95ce2853cdc5fe3971daaac00f6f081c419c013f7f57bff2f5e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.7"
|
||||
path_provider_foundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_foundation
|
||||
sha256: f234384a3fdd67f989b4d54a5d73ca2a6c422fa55ae694381ae0f4375cd1ea16
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.0"
|
||||
path_provider_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -485,6 +565,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.5.1"
|
||||
win32:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: win32
|
||||
sha256: a79dbe579cb51ecd6d30b17e0cae4e0ea15e2c0e66f69ad4198f22a6789e94f4
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.5.1"
|
||||
xdg_directories:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ dependencies:
|
|||
internet_connection_checker: ^1.0.0+1
|
||||
flutter_phoenix: ^1.1.1
|
||||
flutter_svg: ^2.0.10+1
|
||||
flutter_secure_storage: ^9.2.2
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
|
|
|||
Loading…
Reference in New Issue