Initial commit

This commit is contained in:
jahongireshonqulov
2025-10-18 09:40:06 +05:00
commit 1bf3e41abe
352 changed files with 16315 additions and 0 deletions

View File

@@ -0,0 +1,116 @@
import 'package:cargocalculaterapp/core/local_source/local_source.dart';
import 'package:cargocalculaterapp/generated/l10n.dart';
import 'package:cargocalculaterapp/router/app_routes.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../../../../constants/constants.dart';
import '../../../../../injector_container.dart';
import '../../../../../router/name_routes.dart';
import '../../../data/model/login_request.dart';
import '../../../domain/usecases/login_usecase.dart';
import '../../pages/auth_confirm/argument/auth_confirm_argument.dart';
part 'auth_event.dart';
part 'auth_state.dart';
class AuthBloc extends Bloc<AuthEvent, AuthState> {
AuthBloc(this.loginUseCase)
: super(
const AuthState(
passwordHidden: true,
isLoading: false,
isButtonEnabled: false,
),
) {
on<PasswordVisibilityEvent>(_showHidePassword);
on<OnInputEnterEvent>(_onInputEnter);
on<SubmitEvent>(_onSubmit);
}
final LoginUseCase loginUseCase;
void _showHidePassword(
PasswordVisibilityEvent event,
Emitter<AuthState> emit,
) {
emit(state.copyWith(passwordHidden: !state.passwordHidden));
}
void _onInputEnter(OnInputEnterEvent event, Emitter<AuthState> emit) {
emit(
state.copyWith(
isButtonEnabled:
(isEmail(event.login) || isPhoneNumber(event.login)) &&
event.password.isNotEmpty,
),
);
}
Future<void> _onSubmit(SubmitEvent event, Emitter<AuthState> emit) async {
emit(state.copyWith(isLoading: true));
final response = await loginUseCase(
LoginRequest(
email: isEmail(event.login) ? event.login : "",
phone: isPhoneNumber(event.login)
? event.login.replaceAll("+", "")
: "",
ucode: event.password,
),
);
response.fold(
(l) {
emit(state.copyWith(isLoading: false));
showErrorSnackBar();
},
(r) {
emit(state.copyWith(isLoading: false));
sl<LocalSource>().setUCode(event.password);
Navigator.pushNamed(
rootNavigatorKey.currentContext!,
Routes.authConfirm,
arguments: AuthConfirmArgument(
fullName: "",
mail: isEmail(event.login) ? event.login : "",
phoneNumber: isPhoneNumber(event.login) ? event.login : "",
fromLoginPage: true,
password: event.password,
),
);
},
);
}
bool isEmail(String input) {
return RegExConst.emailRegex.hasMatch(input);
}
bool isPhoneNumber(String input) {
return RegExConst.phoneRegex.hasMatch(input);
}
void showErrorSnackBar() {
final snackBar = SnackBar(
backgroundColor: Colors.red,
content: Row(
children: [
const Icon(Icons.error, color: Colors.white),
const SizedBox(width: 8),
Expanded(
child: Text(
AppLocalization.current.login_error,
style: const TextStyle(color: Colors.white),
),
),
],
),
behavior: SnackBarBehavior.floating,
duration: const Duration(seconds: 3),
);
ScaffoldMessenger.of(
rootNavigatorKey.currentContext!,
).showSnackBar(snackBar);
}
}

View File

@@ -0,0 +1,32 @@
part of 'auth_bloc.dart';
sealed class AuthEvent extends Equatable {
const AuthEvent();
}
final class PasswordVisibilityEvent extends AuthEvent {
const PasswordVisibilityEvent();
@override
List<Object?> get props => [];
}
final class OnInputEnterEvent extends AuthEvent {
final String login;
final String password;
const OnInputEnterEvent({required this.login, required this.password});
@override
List<Object?> get props => [login, password];
}
final class SubmitEvent extends AuthEvent {
final String login;
final String password;
const SubmitEvent({required this.login, required this.password});
@override
List<Object?> get props => [login, password];
}

View File

@@ -0,0 +1,28 @@
part of 'auth_bloc.dart';
class AuthState extends Equatable {
const AuthState({
required this.passwordHidden,
required this.isLoading,
required this.isButtonEnabled,
});
final bool passwordHidden;
final bool isLoading;
final bool isButtonEnabled;
AuthState copyWith({
bool? passwordHidden,
bool? isLoading,
bool? isButtonEnabled,
}) {
return AuthState(
isLoading: isLoading ?? this.isLoading,
passwordHidden: passwordHidden ?? this.passwordHidden,
isButtonEnabled: isButtonEnabled ?? this.isButtonEnabled,
);
}
@override
List<Object?> get props => [passwordHidden, isLoading, isButtonEnabled];
}

View File

@@ -0,0 +1,112 @@
import 'package:equatable/equatable.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../../../../core/error/failure.dart';
import '../../../../../core/functions/base_finctions.dart';
import '../../../../../core/local_source/local_source.dart';
import '../../../../../injector_container.dart';
import '../../../../../service/notification_service.dart';
import '../../../data/model/auth_verification_request.dart';
import '../../../data/model/fcm_add_request.dart';
import '../../../data/model/login_request.dart';
import '../../../data/model/sign_up_request.dart';
import '../../../domain/usecases/fcm_add_usecase.dart';
import '../../../domain/usecases/login_usecase.dart';
import '../../../domain/usecases/sign_up_usecase.dart';
import '../../../domain/usecases/verify_phone_usecase.dart';
import '../../pages/auth_confirm/argument/auth_confirm_argument.dart';
part 'auth_confirm_event.dart';
part 'auth_confirm_state.dart';
class AuthConfirmBloc extends Bloc<AuthConfirmEvent, AuthConfirmState> {
AuthConfirmBloc(
this.signUpUseCase,
this.verifyPhoneUseCase,
this.loginUseCase,
this.fcmAddUseCase,
) : super(const InitialState(true)) {
on<TimerChangedEvent>(_timerChanged);
on<SmsCodeEnterEvent>(_codeChanged);
on<ResendCodeEvent>(_resendCode);
on<OnSubmitEvent>(_onSubmitCode);
}
final SignUpUseCase signUpUseCase;
final VerifyPhoneUseCase verifyPhoneUseCase;
final LoginUseCase loginUseCase;
final FcmAddUseCase fcmAddUseCase;
Future<void> _timerChanged(
TimerChangedEvent event,
Emitter<AuthConfirmState> emit,
) async {
emit(InitialState(event.isVisible));
}
void _codeChanged(SmsCodeEnterEvent event, Emitter<AuthConfirmState> emit) {
if (event.code.length == 4) {
emit(ButtonEnableState(state.isTimerVisible, event.code));
} else {
emit(InitialState(state.isTimerVisible));
}
}
Future<void> _resendCode(
ResendCodeEvent event,
Emitter<AuthConfirmState> emit,
) async {
add(const TimerChangedEvent(isVisible: true));
if (event.argument.fromLoginPage) {
await loginUseCase(
LoginRequest(
email: event.argument.mail,
phone: event.argument.phoneNumber?.replaceAll("+", ""),
ucode: event.argument.password,
),
);
} else {
await signUpUseCase(
SignUpRequest(
fullname: event.argument.fullName,
email: event.argument.mail,
phoneNumber: event.argument.phoneNumber?.replaceAll("+", ""),
),
);
}
}
Future<void> _onSubmitCode(
OnSubmitEvent event,
Emitter<AuthConfirmState> emit,
) async {
emit(LoadingState(state.isTimerVisible));
final response = await verifyPhoneUseCase(
AuthVerificationRequest(
phoneNumber: event.argument?.phoneNumber?.replaceAll("+", ""),
smsCode: event.code,
email: event.argument?.mail ?? "",
),
);
await response.fold(
(l) {
if (l is ServerFailure) {
Functions.showErrorSnackBar(l.message);
}
emit(InitialState(state.isTimerVisible));
},
(r) async {
sl<LocalSource>().setHasProfile(true);
sl<LocalSource>().setAccessToken(r.accessToken ?? "");
await _addFcmToken();
emit(SuccessSate(state.isTimerVisible));
},
);
}
Future<void> _addFcmToken() async {
final String fcmToken = await NotificationService.getFcmToken();
await fcmAddUseCase(FcmAddRequest(sfmToken: fcmToken));
}
}

View File

@@ -0,0 +1,42 @@
part of 'auth_confirm_bloc.dart';
sealed class AuthConfirmEvent extends Equatable {
const AuthConfirmEvent();
}
final class SmsCodeEnterEvent extends AuthConfirmEvent {
final String code;
const SmsCodeEnterEvent(this.code);
@override
List<Object?> get props => [code];
}
final class TimerChangedEvent extends AuthConfirmEvent {
final bool isVisible;
const TimerChangedEvent({required this.isVisible});
@override
List<Object?> get props => [isVisible];
}
final class OnSubmitEvent extends AuthConfirmEvent {
final String code;
final AuthConfirmArgument? argument;
const OnSubmitEvent({required this.code, required this.argument});
@override
List<Object?> get props => [code, argument];
}
final class ResendCodeEvent extends AuthConfirmEvent {
final AuthConfirmArgument argument;
const ResendCodeEvent({required this.argument});
@override
List<Object?> get props => [argument];
}

View File

@@ -0,0 +1,44 @@
part of 'auth_confirm_bloc.dart';
sealed class AuthConfirmState extends Equatable {
const AuthConfirmState(this.isTimerVisible);
final bool isTimerVisible;
}
class InitialState extends AuthConfirmState {
const InitialState(super.isTimerVisible);
@override
List<Object?> get props => [super.isTimerVisible];
}
class LoadingState extends AuthConfirmState {
const LoadingState(super.isTimerVisible);
@override
List<Object?> get props => [super.isTimerVisible];
}
class SuccessSate extends AuthConfirmState {
const SuccessSate(super.isTimerVisible);
@override
List<Object?> get props => [super.isTimerVisible];
}
class ErrorState extends AuthConfirmState {
const ErrorState(super.isTimerVisible);
@override
List<Object?> get props => [super.isTimerVisible];
}
class ButtonEnableState extends AuthConfirmState {
const ButtonEnableState(super.isTimerVisible, this.code);
final String code;
@override
List<Object?> get props => [super.isTimerVisible, code];
}

View File

@@ -0,0 +1,95 @@
import 'package:cargocalculaterapp/core/local_source/local_source.dart';
import 'package:cargocalculaterapp/generated/l10n.dart';
import 'package:cargocalculaterapp/router/app_routes.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../../../../constants/constants.dart';
import '../../../../../core/error/failure.dart';
import '../../../../../core/functions/base_finctions.dart';
import '../../../../../injector_container.dart';
import '../../../../../router/name_routes.dart';
import '../../../data/model/sign_up_request.dart';
import '../../../domain/usecases/sign_up_usecase.dart';
import '../../pages/auth_confirm/argument/auth_confirm_argument.dart';
part 'sign_up_event.dart';
part 'sign_up_state.dart';
class SignUpBloc extends Bloc<SignUpEvent, SignUpState> {
SignUpBloc(this.signUpUseCase)
: super(
const SignUpState(
isLoading: false,
isButtonEnabled: false,
passwordHidden: true,
),
) {
on<PasswordVisibilityEvent>(_passwordVisibility);
on<OnInputEnterEvent>(_onDataEnter);
on<SubmitEvent>(_signUp);
}
final SignUpUseCase signUpUseCase;
void _passwordVisibility(
PasswordVisibilityEvent event,
Emitter<SignUpState> emit,
) {
emit(state.copyWith(isButtonEnabled: !state.isButtonEnabled));
}
void _onDataEnter(OnInputEnterEvent event, Emitter<SignUpState> emit) {
emit(
state.copyWith(
isButtonEnabled:
(isEmail(event.login) || isPhoneNumber(event.login)) &&
event.fullName.isNotEmpty,
),
);
}
bool isEmail(String input) {
return RegExConst.emailRegex.hasMatch(input);
}
bool isPhoneNumber(String input) {
return RegExConst.phoneRegex.hasMatch(input);
}
Future<void> _signUp(SubmitEvent event, Emitter<SignUpState> emit) async {
emit(state.copyWith(isLoading: true));
final response = await signUpUseCase(
SignUpRequest(
fullname: event.fullName,
email: isEmail(event.login) ? event.login : "",
phoneNumber: isPhoneNumber(event.login)
? event.login.replaceAll("+", "")
: "",
),
);
response.fold(
(l) {
emit(state.copyWith(isLoading: false));
if (l is ServerFailure) {
Functions.showErrorSnackBar(AppLocalization.current.phone_registered);
}
},
(r) {
sl<LocalSource>().setAccessToken(r.token ?? "");
emit(state.copyWith(isLoading: false));
Navigator.pushNamed(
rootNavigatorKey.currentContext!,
Routes.authConfirm,
arguments: AuthConfirmArgument(
fullName: event.fullName,
mail: isEmail(event.login) ? event.login : "",
phoneNumber: isPhoneNumber(event.login) ? event.login : "",
fromLoginPage: false,
),
);
},
);
}
}

View File

@@ -0,0 +1,32 @@
part of 'sign_up_bloc.dart';
sealed class SignUpEvent extends Equatable {
const SignUpEvent();
}
final class PasswordVisibilityEvent extends SignUpEvent {
const PasswordVisibilityEvent();
@override
List<Object?> get props => [];
}
final class OnInputEnterEvent extends SignUpEvent {
final String login;
final String fullName;
const OnInputEnterEvent({required this.login, required this.fullName});
@override
List<Object?> get props => [login, fullName];
}
final class SubmitEvent extends SignUpEvent {
final String login;
final String fullName;
const SubmitEvent({required this.login, required this.fullName});
@override
List<Object?> get props => [login, fullName];
}

View File

@@ -0,0 +1,28 @@
part of 'sign_up_bloc.dart';
class SignUpState extends Equatable {
const SignUpState({
required this.passwordHidden,
required this.isLoading,
required this.isButtonEnabled,
});
final bool passwordHidden;
final bool isLoading;
final bool isButtonEnabled;
SignUpState copyWith({
bool? passwordHidden,
bool? isLoading,
bool? isButtonEnabled,
}) {
return SignUpState(
isLoading: isLoading ?? this.isLoading,
passwordHidden: passwordHidden ?? this.passwordHidden,
isButtonEnabled: isButtonEnabled ?? this.isButtonEnabled,
);
}
@override
List<Object?> get props => [passwordHidden, isLoading, isButtonEnabled];
}