delete added

This commit is contained in:
komekh 2024-09-12 15:27:18 +05:00
parent efdf52cb2e
commit 0739f345a9
19 changed files with 617 additions and 36 deletions

View File

@ -51,5 +51,14 @@
"error_message": "Что-то пошло не так. Пожалуйста, попробуйте еще раз.", "error_message": "Что-то пошло не так. Пожалуйста, попробуйте еще раз.",
"follow_orders_banner": "Отслеживайте ваш груз в реальном времени", "follow_orders_banner": "Отслеживайте ваш груз в реальном времени",
"order_empty": "У вас пока нет заказов", "order_empty": "У вас пока нет заказов",
"deliver_all": "Ваш надежный партнер в мире логистики!" "deliver_all": "Ваш надежный партнер в мире логистики!",
"user_already_registered": "Пользователь зарегистрирован!",
"alert": "Внимание!",
"or": "Или",
"register": "Зарегистрироваться",
"register_header": "Для входа в личный кабинет",
"register_desc": "необходимо зарегистрироваться",
"registration_success": "Регистрация прошла успешно!",
"dismiss": "OK",
"delete": "Удалить аккаунт"
} }

View File

@ -51,5 +51,14 @@
"error_message": "Näsazlyk ýüze çykdy. Täzeden synanşyp görmegiňizi haýyş edýäris.", "error_message": "Näsazlyk ýüze çykdy. Täzeden synanşyp görmegiňizi haýyş edýäris.",
"follow_orders_banner": "Ýükiňizi 24 sagadyň dowamynda yzarlamak indi elýeterli", "follow_orders_banner": "Ýükiňizi 24 sagadyň dowamynda yzarlamak indi elýeterli",
"order_empty": "Siziň entäk sargydyňyz ýok", "order_empty": "Siziň entäk sargydyňyz ýok",
"deliver_all": "Ýükleri eltip bermekde siziň ynamly hyzmatdaşyňyz!" "deliver_all": "Ýükleri eltip bermekde siziň ynamly hyzmatdaşyňyz!",
"user_already_registered": "Ulanyjy hasaba alnan!",
"alert": "Üns beriň",
"or": "Ýa-da",
"register": "Agza bol",
"register_header": "Şahsy otaga girmek üçin",
"register_desc": "hasaba alynmagyňyzy haýyş edýäris",
"registration_success": "Üstünlikli hasaba alyndy!",
"dismiss": "OK",
"delete": "Hasaby poz"
} }

View File

@ -14,18 +14,24 @@ class UserBloc extends Bloc<UserEvent, UserState> {
final GetCachedUserUseCase _getCachedUserUseCase; final GetCachedUserUseCase _getCachedUserUseCase;
final GetRemoteUserUsecase _getRemoteUserUseCase; final GetRemoteUserUsecase _getRemoteUserUseCase;
final SignInUseCase _signInUseCase; final SignInUseCase _signInUseCase;
final SignUpUseCase _signUpUseCase;
final SignOutUseCase _signOutUseCase; final SignOutUseCase _signOutUseCase;
final DeleteAccountUseCase _deleteAccountUseCase;
UserBloc( UserBloc(
this._signInUseCase, this._signInUseCase,
this._signUpUseCase,
this._getCachedUserUseCase, this._getCachedUserUseCase,
this._getRemoteUserUseCase, this._getRemoteUserUseCase,
this._signOutUseCase, this._signOutUseCase,
this._deleteAccountUseCase,
) : super(UserInitial()) { ) : super(UserInitial()) {
on<SignInUser>(_onSignIn); on<SignInUser>(_onSignIn);
on<SignUpUser>(_onSignUp);
on<CheckUser>(_onCheckUser); on<CheckUser>(_onCheckUser);
on<GetRemoteUser>(_onGetRemoteUser); on<GetRemoteUser>(_onGetRemoteUser);
on<SignOutUser>(_onSignOut); on<SignOutUser>(_onSignOut);
on<GetUser>(_onGetUser); on<GetUser>(_onGetUser);
on<DeleteAccount>(_onDeleteAccount);
} }
void _onSignIn(SignInUser event, Emitter<UserState> emit) async { void _onSignIn(SignInUser event, Emitter<UserState> emit) async {
@ -42,6 +48,28 @@ class UserBloc extends Bloc<UserEvent, UserState> {
} }
} }
void _onSignUp(SignUpUser event, Emitter<UserState> emit) async {
try {
emit(UserLoading());
// await Future.delayed(const Duration(seconds: 3));
final result = await _signUpUseCase(event.params);
result.fold(
(failure) => emit(UserLoggedFail(failure)),
(code) {
if (code == 200) {
emit(UserRegistered());
} else if (code == 409) {
emit(UserAlreadyRegistered());
} else {
emit(UserLoggedFail(ExceptionFailure()));
}
},
);
} catch (e) {
emit(UserLoggedFail(ExceptionFailure()));
}
}
void _onCheckUser(CheckUser event, Emitter<UserState> emit) async { void _onCheckUser(CheckUser event, Emitter<UserState> emit) async {
try { try {
emit(UserLoading()); emit(UserLoading());
@ -65,6 +93,25 @@ class UserBloc extends Bloc<UserEvent, UserState> {
} }
} }
void _onDeleteAccount(DeleteAccount event, Emitter<UserState> emit) async {
try {
emit(DeleteLoading());
final result = await _deleteAccountUseCase(NoParams());
result.fold(
(failure) => emit(_mapFailureToState(failure)),
(code) {
if (code == 204) {
emit(AccountDeleted());
} else {
emit(UserLoggedFail(ExceptionFailure()));
}
},
);
} catch (e) {
emit(UserLoggedFail(ExceptionFailure()));
}
}
FutureOr<void> _onGetRemoteUser( FutureOr<void> _onGetRemoteUser(
GetRemoteUser event, GetRemoteUser event,
Emitter<UserState> emit, Emitter<UserState> emit,

View File

@ -8,6 +8,11 @@ class SignInUser extends UserEvent {
SignInUser(this.params); SignInUser(this.params);
} }
class SignUpUser extends UserEvent {
final SignUpParams params;
SignUpUser(this.params);
}
class SignOutUser extends UserEvent {} class SignOutUser extends UserEvent {}
class CheckUser extends UserEvent {} class CheckUser extends UserEvent {}
@ -15,3 +20,5 @@ class CheckUser extends UserEvent {}
class GetRemoteUser extends UserEvent {} class GetRemoteUser extends UserEvent {}
class GetUser extends UserEvent {} class GetUser extends UserEvent {}
class DeleteAccount extends UserEvent {}

View File

@ -38,3 +38,23 @@ class UserLoggedOut extends UserState {
@override @override
List<Object> get props => []; List<Object> get props => [];
} }
class AccountDeleted extends UserState {
@override
List<Object> get props => [];
}
class UserRegistered extends UserState {
@override
List<Object> get props => [];
}
class UserAlreadyRegistered extends UserState {
@override
List<Object> get props => [];
}
class DeleteLoading extends UserState {
@override
List<Object> get props => [];
}

View File

@ -1,6 +1,6 @@
const String baseUrl = 'https://192.168.99.64:5001/api'; // const String baseUrl = 'https://192.168.99.64:5001/api';
const String imageUrl = 'https://192.168.99.64:5001'; // const String imageUrl = 'https://192.168.99.64:5001';
// const String baseUrl = 'https://cargo.tpsadvertising.com/api'; const String baseUrl = 'https://cargo.tpsadvertising.com/api';
// const String imageUrl = 'https://cargo.tpsadvertising.com'; const String imageUrl = 'https://cargo.tpsadvertising.com';
const String defaultApiKey = ''; const String defaultApiKey = '';
const String defaultSources = ''; const String defaultSources = '';

View File

@ -8,6 +8,7 @@ sealed class AppRouter {
static const String splash = '/splash'; static const String splash = '/splash';
static const String splash2 = '/splash2'; static const String splash2 = '/splash2';
static const String login = '/login'; static const String login = '/login';
static const String register = '/register';
static const String root = '/root'; static const String root = '/root';
static const String orderDetails = '/order-details'; static const String orderDetails = '/order-details';
@ -20,6 +21,8 @@ sealed class AppRouter {
return MaterialPageRoute(builder: (_) => const Splash2Screen()); return MaterialPageRoute(builder: (_) => const Splash2Screen());
case login: case login:
return MaterialPageRoute(builder: (_) => const LoginScreen()); return MaterialPageRoute(builder: (_) => const LoginScreen());
case register:
return MaterialPageRoute(builder: (_) => const RegisterScreen());
case root: case root:
return MaterialPageRoute(builder: (_) => const RootScreen()); return MaterialPageRoute(builder: (_) => const RootScreen());
case orderDetails: case orderDetails:

View File

@ -1,5 +1,6 @@
import 'dart:convert'; import 'dart:convert';
import 'package:flutter/widgets.dart';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
import '../../../core/core.dart'; import '../../../core/core.dart';
@ -8,6 +9,8 @@ import '../../data.dart';
abstract class UserRemoteDataSource { abstract class UserRemoteDataSource {
Future<String> signIn(SignInParams params); Future<String> signIn(SignInParams params);
Future<int> signUp(SignUpParams params);
Future<int> deleteAccount(String token);
Future<User> getUser(String token); Future<User> getUser(String token);
Future<void> registerFBToken(String token, String fbToken); Future<void> registerFBToken(String token, String fbToken);
} }
@ -41,6 +44,23 @@ class UserRemoteDataSourceImpl implements UserRemoteDataSource {
} }
} }
@override
Future<int> signUp(SignUpParams params) async {
final response = await client.post(
Uri.parse('$baseUrl/Client/Register'),
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'accept': '*/*',
},
body: {
'username': params.username.trim(),
'password': params.password,
},
);
return response.statusCode;
}
@override @override
Future<User> getUser(String token) async { Future<User> getUser(String token) async {
final response = await client.get( final response = await client.get(
@ -62,7 +82,8 @@ class UserRemoteDataSourceImpl implements UserRemoteDataSource {
@override @override
Future<void> registerFBToken(String token, String fbToken) async { Future<void> registerFBToken(String token, String fbToken) async {
final response = await client.post( /* final response = */
await client.post(
Uri.parse('$baseUrl/Client/FirebaseToken?token=$fbToken'), Uri.parse('$baseUrl/Client/FirebaseToken?token=$fbToken'),
headers: { headers: {
'accept': '*/*', 'accept': '*/*',
@ -75,4 +96,20 @@ class UserRemoteDataSourceImpl implements UserRemoteDataSource {
throw ServerException(); throw ServerException();
} */ } */
} }
@override
Future<int> deleteAccount(String token) async {
final response = await client.delete(
Uri.parse('$baseUrl/Client/DeleteAccount'),
headers: {
'accept': '*/*',
'Content-Type': 'application/json',
'Authorization': 'Bearer $token',
},
);
debugPrint(response.body);
return response.statusCode;
}
} }

View File

@ -38,6 +38,22 @@ class UserRepositoryImpl implements UserRepository {
} }
} }
@override
Future<Either<Failure, int>> signUp(params) async {
if (await networkInfo.isConnected) {
try {
/// register
final code = await remoteDataSource.signUp(params);
return Right(code);
} on Failure catch (failure) {
return Left(failure);
}
} else {
return Left(NetworkFailure());
}
}
@override @override
Future<Either<Failure, User>> getCachedUser() async { Future<Either<Failure, User>> getCachedUser() async {
try { try {
@ -62,6 +78,22 @@ class UserRepositoryImpl implements UserRepository {
} }
} }
@override
Future<Either<Failure, int>> deleteAccount() async {
try {
final String token = await localDataSource.getToken();
final code = await remoteDataSource.deleteAccount(token);
if (code == 204) {
await localDataSource.clearCache();
}
return Right(code);
} on CacheFailure {
return Left(CacheFailure());
} catch (error) {
return Left(ExceptionFailure());
}
}
@override @override
Future<Either<Failure, User>> getRemoteUser() async { Future<Either<Failure, User>> getRemoteUser() async {
if (!await networkInfo.isConnected) { if (!await networkInfo.isConnected) {

View File

@ -7,10 +7,12 @@ import 'di.dart';
void registerUserFeature() { void registerUserFeature() {
// User BLoC and Use Cases // User BLoC and Use Cases
sl.registerFactory(() => UserBloc(sl(), sl(), sl(), sl())); sl.registerFactory(() => UserBloc(sl(), sl(), sl(), sl(), sl(), sl()));
sl.registerLazySingleton(() => GetCachedUserUseCase(sl())); sl.registerLazySingleton(() => GetCachedUserUseCase(sl()));
sl.registerLazySingleton(() => SignInUseCase(sl())); sl.registerLazySingleton(() => SignInUseCase(sl()));
sl.registerLazySingleton(() => SignUpUseCase(sl()));
sl.registerLazySingleton(() => SignOutUseCase(sl())); sl.registerLazySingleton(() => SignOutUseCase(sl()));
sl.registerLazySingleton(() => DeleteAccountUseCase(sl()));
sl.registerLazySingleton(() => GetRemoteUserUsecase(sl())); sl.registerLazySingleton(() => GetRemoteUserUsecase(sl()));
// User Repository and Data Sources // User Repository and Data Sources

View File

@ -5,7 +5,9 @@ import '../domain.dart';
abstract class UserRepository { abstract class UserRepository {
Future<Either<Failure, String>> signIn(SignInParams params); Future<Either<Failure, String>> signIn(SignInParams params);
Future<Either<Failure, int>> signUp(SignUpParams params);
Future<Either<Failure, NoParams>> signOut(); Future<Either<Failure, NoParams>> signOut();
Future<Either<Failure, int>> deleteAccount();
Future<Either<Failure, User>> getCachedUser(); Future<Either<Failure, User>> getCachedUser();
Future<Either<Failure, User>> getRemoteUser(); Future<Either<Failure, User>> getRemoteUser();
} }

View File

@ -0,0 +1,14 @@
import 'package:dartz/dartz.dart';
import '../../../core/core.dart';
import '../../domain.dart';
class DeleteAccountUseCase implements UseCase<int, NoParams> {
final UserRepository repository;
DeleteAccountUseCase(this.repository);
@override
Future<Either<Failure, int>> call(NoParams params) async {
return await repository.deleteAccount();
}
}

View File

@ -1,27 +1,27 @@
// import 'package:dartz/dartz.dart'; import 'package:dartz/dartz.dart';
// import '../../../core/core.dart'; import '../../../core/core.dart';
// import '../../domain.dart'; import '../../domain.dart';
// class SignUpUseCase implements UseCase<User, SignUpParams> { class SignUpUseCase implements UseCase<int, SignUpParams> {
// final UserRepository repository; final UserRepository repository;
// SignUpUseCase(this.repository); SignUpUseCase(this.repository);
// @override @override
// Future<Either<Failure, User>> call(SignUpParams params) async { Future<Either<Failure, int>> call(SignUpParams params) async {
// return await repository.signUp(params); return await repository.signUp(params);
// } }
// } }
// class SignUpParams { class SignUpParams {
// final String firstName; // final String firstName;
// final String lastName; // final String lastName;
// final String email; final String username;
// final String password; final String password;
// const SignUpParams({ const SignUpParams({
// required this.firstName, // required this.firstName,
// required this.lastName, // required this.lastName,
// required this.email, required this.username,
// required this.password, required this.password,
// }); });
// } }

View File

@ -2,4 +2,5 @@ export 'get_cached_user_usecase.dart';
export 'sign_in_usecase.dart'; export 'sign_in_usecase.dart';
export 'sign_out_usecase.dart'; export 'sign_out_usecase.dart';
export 'sign_up_usecase.dart'; export 'sign_up_usecase.dart';
export 'delete_account_usecase.dart';
export 'get_remote_user_usecase.dart'; export 'get_remote_user_usecase.dart';

View File

@ -7,6 +7,7 @@ import '../../configs/configs.dart';
import '../../core/core.dart'; import '../../core/core.dart';
import '../../domain/domain.dart'; import '../../domain/domain.dart';
import '../widgets/widgets.dart'; import '../widgets/widgets.dart';
import 'dart:io' show Platform;
class LoginScreen extends StatefulWidget { class LoginScreen extends StatefulWidget {
const LoginScreen({super.key}); const LoginScreen({super.key});
@ -100,7 +101,7 @@ class _LoginScreenState extends State<LoginScreen> {
/// form part /// form part
SizedBox( SizedBox(
height: AppDimensions.normalize(165), height: AppDimensions.normalize(190),
child: Stack( child: Stack(
clipBehavior: Clip.none, clipBehavior: Clip.none,
children: [ children: [
@ -232,6 +233,56 @@ class _LoginScreenState extends State<LoginScreen> {
); );
}, },
), ),
if (Platform.isAndroid)
Align(
alignment: Alignment.center,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
/// spacer
Space.yf(),
Text(
'or'.tr(),
style: AppText.h3,
),
Space.yf(),
Container(
padding: const EdgeInsets.symmetric(horizontal: 22),
height: 40,
decoration: BoxDecoration(
border: Border.all(
color: AppColors.primary, // Border color
width: 1.0, // Border width
),
borderRadius: BorderRadius.circular(8.0),
),
child: TextButton(
style: TextButton.styleFrom(
foregroundColor: AppColors.primary,
padding: EdgeInsets.zero,
textStyle: const TextStyle(
color: Colors.black,
),
),
onPressed: () {
debugPrint('register');
Navigator.of(context).pushNamedAndRemoveUntil(
AppRouter.register,
(route) => false,
);
},
child: Text(
'register'.tr(),
style: AppText.b1b,
),
),
),
Space.yf(0.30),
],
),
)
], ],
), ),
), ),

View File

@ -34,7 +34,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
backgroundColor: AppColors.surface, backgroundColor: AppColors.surface,
body: BlocConsumer<UserBloc, UserState>( body: BlocConsumer<UserBloc, UserState>(
listener: (context, state) { listener: (context, state) {
if (state is UserLoggedOut || state is UserLoggedFail) { if (state is UserLoggedOut || state is UserLoggedFail || state is AccountDeleted) {
_navigateToLoginScreen(context); _navigateToLoginScreen(context);
} }
}, },
@ -120,11 +120,42 @@ class _ProfileScreenState extends State<ProfileScreen> {
}, },
child: Text( child: Text(
'logout'.tr(), 'logout'.tr(),
style: AppText.b1!.copyWith(
color: AppColors.primary,
),
),
),
),
///gap
Space.yf(3),
BlocBuilder<UserBloc, UserState>(
builder: (context, state) {
if (state is DeleteLoading) {
// Show loader when the state is DeleteLoading
return const Align(
alignment: Alignment.center,
child: CircularProgressIndicator(), // Loader
);
} else {
// Show the delete button in other states
return Align(
alignment: Alignment.center,
child: TextButton(
onPressed: () {
context.read<UserBloc>().add(DeleteAccount());
},
child: Text(
'delete'.tr(),
style: AppText.b1!.copyWith( style: AppText.b1!.copyWith(
color: Colors.red, color: Colors.red,
), ),
), ),
), ),
);
}
},
), ),
], ],
), ),

View File

@ -0,0 +1,314 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../application/user_bloc/user_bloc.dart';
import '../../configs/configs.dart';
import '../../core/core.dart';
import '../../domain/domain.dart';
import '../widgets/widgets.dart';
import 'dart:io' show Platform;
class RegisterScreen extends StatefulWidget {
const RegisterScreen({super.key});
@override
State<RegisterScreen> createState() => _RegisterScreenState();
}
class _RegisterScreenState extends State<RegisterScreen> {
final TextEditingController _userNameController = TextEditingController();
final TextEditingController _passwordController = TextEditingController();
final _formKey = GlobalKey<FormState>();
bool _obscureText = true;
void _nextScreen() {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('registration_success'.tr()),
backgroundColor: Colors.green,
duration: const Duration(seconds: 2),
),
);
Navigator.of(context).pushNamedAndRemoveUntil(
AppRouter.login,
(route) => false,
);
}
void _onEyeTapped() {
setState(() {
_obscureText = !_obscureText;
});
}
@override
void dispose() {
_userNameController.dispose();
_passwordController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
App.init(context);
return Scaffold(
body: SingleChildScrollView(
child: Column(
children: [
/// image part
Container(
height: AppDimensions.normalize(155),
color: AppColors.primary,
child: SingleChildScrollView(
physics: const NeverScrollableScrollPhysics(),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
padding: const EdgeInsets.only(top: 20, bottom: 20),
child: Column(
children: [
// SvgPicture.asset(
// AppAssets.logo,
// height: AppDimensions.normalize(30),
// ),
Space.yf(4),
Image.asset(
AppAssets.logoLogin,
),
Space.yf(0.50),
Text(
appTitle,
style: AppText.h1b?.copyWith(
color: Colors.white,
),
),
Space.yf(0.30),
Text(
'deliver_all'.tr(),
style: AppText.b1?.copyWith(
color: AppColors.yellow,
),
),
Image.asset(
AppAssets.trucksPng,
height: AppDimensions.normalize(52),
width: double.infinity,
fit: BoxFit.fill,
),
],
),
),
],
),
),
),
/// form part
SizedBox(
height: AppDimensions.normalize(190),
child: Stack(
clipBehavior: Clip.none,
children: [
Positioned(
top: -20,
left: 0,
right: 0,
bottom: 0,
child: Container(
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(16),
topRight: Radius.circular(16),
),
),
child: Padding(
padding: Space.hf().copyWith(top: 30),
child: Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'register_header'.tr(),
style: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
Space.yf(0.5),
Text(
'register_desc'.tr(),
style: const TextStyle(
color: Colors.grey,
),
),
/// gap
Space.yf(),
/// username field
Text('login'.tr()),
Space.y!,
TextFormField(
controller: _userNameController,
decoration: InputDecoration(
hintText: 'login_hint'.tr(),
prefixIcon: const Icon(Icons.person_outline),
border: const OutlineInputBorder(),
),
validator: (val) => FormValidator.validateField(val),
),
/// gap
Space.yf(),
/// password field
Text('password'.tr()),
Space.y!,
TextFormField(
controller: _passwordController,
obscureText: _obscureText,
decoration: InputDecoration(
hintText: 'password_hint'.tr(),
prefixIcon: const Icon(Icons.lock_outline),
suffixIcon: GestureDetector(
onTap: _onEyeTapped,
child: _obscureText
? const Icon(Icons.visibility_off)
: const Icon(
Icons.visibility,
),
),
border: const OutlineInputBorder(),
),
validator: (val) => FormValidator.validateField(val),
),
/// gap
Space.yf(),
BlocConsumer<UserBloc, UserState>(
listener: (context, state) {
if (state is UserRegistered) {
_nextScreen();
} else if (state is UserAlreadyRegistered) {
showErrorDialog(
context: context,
header: 'alert'.tr(),
body: 'user_already_registered'.tr(),
);
} else if (state is UserLoggedFail) {
if (state.failure is CredentialFailure) {
showErrorDialog(
context: context,
header: 'credentials_validation_header'.tr(),
body: 'credentials_validation_body'.tr(),
);
} else {
showAuthErrorDialog(context);
}
}
},
builder: (context, state) {
if (state is UserLoading) {
return const Center(
child: CircularProgressIndicator(),
);
}
return SizedBox(
width: double.infinity,
child: AppButton(
textColor: Colors.white,
btnColor: AppColors.primary,
onPressed: () {
if (_formKey.currentState!.validate()) {
Keyboard.hide(context);
/// sign in
context.read<UserBloc>().add(
SignUpUser(
SignUpParams(
username: _userNameController.text,
password: _passwordController.text,
),
),
);
}
},
text: 'register'.tr(),
),
);
},
),
if (Platform.isAndroid)
Align(
alignment: Alignment.center,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
/// spacer
Space.yf(),
Text(
'or'.tr(),
style: AppText.h3,
),
Space.yf(),
Container(
padding: const EdgeInsets.symmetric(horizontal: 22),
height: 40,
decoration: BoxDecoration(
border: Border.all(
color: AppColors.primary, // Border color
width: 1.0, // Border width
),
borderRadius: BorderRadius.circular(8.0),
),
child: TextButton(
style: TextButton.styleFrom(
foregroundColor: AppColors.primary,
padding: EdgeInsets.zero,
textStyle: const TextStyle(
color: Colors.black,
),
),
onPressed: () {
debugPrint('login');
Navigator.of(context).pushNamedAndRemoveUntil(
AppRouter.login,
(route) => false,
);
},
child: Text(
'start_tracking'.tr(),
style: AppText.b1b,
),
),
),
Space.yf(0.30),
],
),
)
],
),
),
),
),
),
],
),
),
],
),
),
);
}
}

View File

@ -7,3 +7,4 @@ export 'root.dart';
export 'splash.dart'; export 'splash.dart';
export 'splash2.dart'; export 'splash2.dart';
export 'image_full.dart'; export 'image_full.dart';
export 'register.dart';

View File

@ -1,3 +1,4 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import '../../configs/configs.dart'; import '../../configs/configs.dart';
@ -7,7 +8,7 @@ Future<void> showErrorDialog({
required BuildContext context, required BuildContext context,
required String header, required String header,
required String body, required String body,
String dismissButtonText = 'Dismiss', String dismissButtonText = 'dismiss',
VoidCallback? onDismiss, VoidCallback? onDismiss,
}) async { }) async {
return showDialog( return showDialog(
@ -52,7 +53,7 @@ Future<void> showErrorDialog({
} }
}, },
child: Text( child: Text(
dismissButtonText, dismissButtonText.tr(),
style: AppText.h3b?.copyWith( style: AppText.h3b?.copyWith(
color: AppColors.primary, color: AppColors.primary,
), ),