From 1eebe2c4687267686d1aaf46831527464dd9d4ae Mon Sep 17 00:00:00 2001 From: komekh Date: Thu, 29 Aug 2024 13:48:59 +0500 Subject: [PATCH] developed --- assets/images/search.png | Bin 0 -> 7035 bytes assets/locale/ru-RU.json | 13 +- assets/locale/tr-TR.json | 13 +- .../contact_cubit/contact_cubit.dart | 28 ++ .../contact_cubit/contact_state.dart | 23 ++ .../splash_cubit/splash_cubit.dart | 2 +- lib/core/app/app.dart | 5 +- lib/core/constants/assets.dart | 1 + .../remote/contact_remote_data_source.dart | 31 ++ .../remote/order_remote_data_source.dart | 2 +- lib/data/data_sources/remote/remote.dart | 1 + lib/data/models/contact/contact_model.dart | 25 ++ .../contact/contact_response_model.dart | 24 ++ lib/data/models/models.dart | 2 + lib/data/models/user/user_model.dart | 2 +- .../repositories/contact_repository_impl.dart | 33 ++ lib/data/repositories/repositories.dart | 1 + lib/di/contact.dart | 23 ++ lib/di/di.dart | 2 + lib/domain/entities/contact/contact.dart | 16 + .../entities/contact/contact_response.dart | 9 + lib/domain/entities/entities.dart | 2 + .../repositories/contact_repository.dart | 8 + lib/domain/repositories/repositories.dart | 1 + .../contact/get_contacts_usecase.dart | 14 + lib/domain/usecases/usecases.dart | 5 +- .../screens/histories_screen.dart | 13 +- lib/presentation/screens/order_details.dart | 4 +- lib/presentation/screens/orders.dart | 17 +- lib/presentation/screens/profile.dart | 294 +++++++++++------- lib/presentation/widgets/empty_order.dart | 26 ++ lib/presentation/widgets/info_card.dart | 5 +- lib/presentation/widgets/location_card.dart | 2 +- lib/presentation/widgets/order_card.dart | 46 ++- lib/presentation/widgets/retry_widget.dart | 5 +- lib/presentation/widgets/widgets.dart | 1 + pubspec.lock | 64 ++++ pubspec.yaml | 1 + 38 files changed, 598 insertions(+), 166 deletions(-) create mode 100644 assets/images/search.png create mode 100644 lib/application/contact_cubit/contact_cubit.dart create mode 100644 lib/application/contact_cubit/contact_state.dart create mode 100644 lib/data/data_sources/remote/contact_remote_data_source.dart create mode 100644 lib/data/models/contact/contact_model.dart create mode 100644 lib/data/models/contact/contact_response_model.dart create mode 100644 lib/data/repositories/contact_repository_impl.dart create mode 100644 lib/di/contact.dart create mode 100644 lib/domain/entities/contact/contact.dart create mode 100644 lib/domain/entities/contact/contact_response.dart create mode 100644 lib/domain/repositories/contact_repository.dart create mode 100644 lib/domain/usecases/contact/get_contacts_usecase.dart create mode 100644 lib/presentation/widgets/empty_order.dart diff --git a/assets/images/search.png b/assets/images/search.png new file mode 100644 index 0000000000000000000000000000000000000000..c7bf5755e98e88a2a333a84b1d7c776f74431aa4 GIT binary patch literal 7035 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 literal 0 HcmV?d00001 diff --git a/assets/locale/ru-RU.json b/assets/locale/ru-RU.json index 3cc31be..8960a9f 100644 --- a/assets/locale/ru-RU.json +++ b/assets/locale/ru-RU.json @@ -4,7 +4,7 @@ "follow_orders": "öz ýüküňizi yzarlaň", "order_history": "Sargytlaryň taryhy", "order_history_desc": "şu ýerde siziň sargytlaryňyz wagt tertipi boyunça görkezilen", - "order_not_available": "Sargyt yok", + "order_not_available": "Siziň ýapylan sargytlaryňyz ýok", "personal_cabinet": "Şahsy otagym", "splash_text": "Довезём всё!", "start_tracking": "Yzarlap başlaň", @@ -29,14 +29,14 @@ "order_status": "Ýagdaýy", "order_carrier": "Awtoulag №", "order_shop": "Dükan №", - "order_from": "Nireden ugradyldy:", - "order_to": "Nirä barmaly:", - "order_placement_count": "'Ýer sany", + "order_from": "Nireden ugradyldy", + "order_to": "Nirä barmaly", + "order_placement_count": "Ýer sany", "order_volume": "Kuby", "order_dimensions": "Göwrümi", "order_dimensions_desc": "(ini, uzynlygy, beýikligi)", "order_product_name": "Harydyň ady", - "contact_support": "Tehniki goldaw bilen habarlaşmak", + "contact_support": "Habarlaşmak üçin", "privacy_policy": "Gizlinlik syýasaty", "use_terms": "Ulanyş şertleri", "logout": "Şahsy otagdan çykmak", @@ -47,5 +47,6 @@ "Reserved": "Rezerw", "Received": "Kabul edildi", "Delivered": "Gowşuryldy", - "image_preview": "Image Preview" + "image_preview": "Image Preview", + "error_message": "Something went wrong. Please try again." } diff --git a/assets/locale/tr-TR.json b/assets/locale/tr-TR.json index a809f27..f7df714 100644 --- a/assets/locale/tr-TR.json +++ b/assets/locale/tr-TR.json @@ -4,7 +4,7 @@ "follow_orders": "öz ýüküňizi yzarlaň", "order_history": "Sargytlaryň taryhy", "order_history_desc": "şu ýerde siziň sargytlaryňyz wagt tertipi boyunça görkezilen", - "order_not_available": "Sargyt yok", + "order_not_available": "Siziň ýapylan sargytlaryňyz ýok", "personal_cabinet": "Şahsy otagym", "splash_text": "Довезём всё!", "start_tracking": "Yzarlap başlaň", @@ -29,14 +29,14 @@ "order_status": "Ýagdaýy", "order_carrier": "Awtoulag №", "order_shop": "Dükan №", - "order_from": "Nireden ugradyldy:", - "order_to": "Nirä barmaly:", - "order_placement_count": "'Ýer sany", + "order_from": "Nireden ugradyldy", + "order_to": "Nirä barmaly", + "order_placement_count": "Ýer sany", "order_volume": "Kuby", "order_dimensions": "Göwrümi", "order_dimensions_desc": "(ini, uzynlygy, beýikligi)", "order_product_name": "Harydyň ady", - "contact_support": "Tehniki goldaw bilen habarlaşmak", + "contact_support": "Habarlaşmak üçin", "privacy_policy": "Gizlinlik syýasaty", "use_terms": "Ulanyş şertleri", "logout": "Şahsy otagdan çykmak", @@ -47,5 +47,6 @@ "Reserved": "Rezerw", "Received": "Kabul edildi", "Delivered": "Gowşuryldy", - "image_preview": "Image Preview" + "image_preview": "Image Preview", + "error_message": "Something went wrong. Please try again." } diff --git a/lib/application/contact_cubit/contact_cubit.dart b/lib/application/contact_cubit/contact_cubit.dart new file mode 100644 index 0000000..dd7f7af --- /dev/null +++ b/lib/application/contact_cubit/contact_cubit.dart @@ -0,0 +1,28 @@ +import 'package:equatable/equatable.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +import '../../core/core.dart'; +import '../../domain/domain.dart'; + +part 'contact_state.dart'; + +class ContactCubit extends Cubit { + final GetContactsUseCase _getContactsUseCase; + + ContactCubit(this._getContactsUseCase) : super(ContactInitial()); + + Future getContacts() async { + try { + emit(ContactLoading()); + final result = await _getContactsUseCase(NoParams()); + result.fold( + (failure) => emit(ContactError()), + (response) => emit( + ContactLoaded(contacts: response.contacts), + ), + ); + } catch (e) { + emit(ContactError()); + } + } +} diff --git a/lib/application/contact_cubit/contact_state.dart b/lib/application/contact_cubit/contact_state.dart new file mode 100644 index 0000000..3a5e34b --- /dev/null +++ b/lib/application/contact_cubit/contact_state.dart @@ -0,0 +1,23 @@ +part of 'contact_cubit.dart'; + +sealed class ContactState extends Equatable { + const ContactState(); + + @override + List get props => []; +} + +final class ContactInitial extends ContactState {} + +final class ContactLoading extends ContactState {} + +final class ContactError extends ContactState {} + +final class ContactLoaded extends ContactState { + final List contacts; + + const ContactLoaded({required this.contacts}); + + @override + List get props => [contacts]; +} diff --git a/lib/application/splash_cubit/splash_cubit.dart b/lib/application/splash_cubit/splash_cubit.dart index 452f3cb..bf055d0 100644 --- a/lib/application/splash_cubit/splash_cubit.dart +++ b/lib/application/splash_cubit/splash_cubit.dart @@ -18,7 +18,7 @@ class SplashCubit extends Cubit { SplashCubit(this._splashUseCase) : super(SplashInitial()); Future checkToken() async { - await Future.delayed(const Duration(seconds: 1)); // Simulating some loading time + // await Future.delayed(const Duration(seconds: 1)); // Simulating some loading time try { final result = await _splashUseCase(NoParams()); result.fold((failure) => emit(NavigateToSplash2()), (result) { diff --git a/lib/core/app/app.dart b/lib/core/app/app.dart index e68168f..b222779 100644 --- a/lib/core/app/app.dart +++ b/lib/core/app/app.dart @@ -1,10 +1,10 @@ +import 'package:cargo/application/contact_cubit/contact_cubit.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../../application/application.dart'; import '../../di/di.dart' as di; -import '../../domain/entities/order/filter_params_model.dart'; import '../core.dart'; class MyApp extends StatelessWidget { @@ -18,6 +18,9 @@ class MyApp extends StatelessWidget { BlocProvider( create: (context) => di.sl()..checkToken(), ), + BlocProvider( + create: (context) => di.sl(), + ), BlocProvider( create: (context) => di.sl()..add(LanguageInitial()), ), diff --git a/lib/core/constants/assets.dart b/lib/core/constants/assets.dart index 54336e5..f805730 100644 --- a/lib/core/constants/assets.dart +++ b/lib/core/constants/assets.dart @@ -10,4 +10,5 @@ sealed class AppAssets { static const String boxesPng = 'assets/images/boxes.png'; static const String trucksPng = 'assets/images/trucks.png'; static const String header = 'assets/images/header.png'; + static const String search = 'assets/images/search.png'; } diff --git a/lib/data/data_sources/remote/contact_remote_data_source.dart b/lib/data/data_sources/remote/contact_remote_data_source.dart new file mode 100644 index 0000000..b9e87d9 --- /dev/null +++ b/lib/data/data_sources/remote/contact_remote_data_source.dart @@ -0,0 +1,31 @@ +import 'package:http/http.dart' as http; + +import '../../../core/core.dart'; +import '../../data.dart'; + +abstract class ContactRemoteDataSource { + Future getContacts(String token); +} + +class ContactRemoteDataSourceImpl implements ContactRemoteDataSource { + final http.Client client; + ContactRemoteDataSourceImpl({required this.client}); + + @override + Future getContacts(String token) async { + final response = await client.get( + Uri.parse('$baseUrl/odata/Contact'), + headers: { + 'Content-Type': 'application/json', + 'accept': '*/*', + 'Authorization': 'Bearer $token', + }, + ); + + if (response.statusCode == 200) { + return contactResponseModelFromJson(response.body); + } else { + throw ServerException(); + } + } +} diff --git a/lib/data/data_sources/remote/order_remote_data_source.dart b/lib/data/data_sources/remote/order_remote_data_source.dart index 76f5f59..396d8a4 100644 --- a/lib/data/data_sources/remote/order_remote_data_source.dart +++ b/lib/data/data_sources/remote/order_remote_data_source.dart @@ -20,7 +20,7 @@ class OrderRemoteDataSourceImpl implements OrderRemoteDataSource { Uri uri; if (params.filter == OrderFilter.Home) { uri = Uri.parse( - '$baseUrl/Goods?pageNumber=${params.offset}&pageSize=${params.limit}&state=Reserved&state=Received', + '$baseUrl/Goods?pageNumber=${params.offset}&pageSize=${params.limit}&state=Received', ); } else { uri = Uri.parse( diff --git a/lib/data/data_sources/remote/remote.dart b/lib/data/data_sources/remote/remote.dart index 0d63525..70c50b5 100644 --- a/lib/data/data_sources/remote/remote.dart +++ b/lib/data/data_sources/remote/remote.dart @@ -1,2 +1,3 @@ export 'user_remote_data_source.dart'; export 'order_remote_data_source.dart'; +export 'contact_remote_data_source.dart'; diff --git a/lib/data/models/contact/contact_model.dart b/lib/data/models/contact/contact_model.dart new file mode 100644 index 0000000..2291c1e --- /dev/null +++ b/lib/data/models/contact/contact_model.dart @@ -0,0 +1,25 @@ +import '../../../domain/entities/contact/contact.dart'; + +class ContactModel extends ContactEntity { + ContactModel({ + required super.oid, + required super.number, + required super.name, + }); + + factory ContactModel.fromJson(Map json) { + return ContactModel( + oid: json['Oid'], + number: json['Number'], + name: json['Name'], + ); + } + + Map toJson() { + return { + 'Oid': oid, + 'Number': number, + 'Name': name, + }; + } +} diff --git a/lib/data/models/contact/contact_response_model.dart b/lib/data/models/contact/contact_response_model.dart new file mode 100644 index 0000000..eecb023 --- /dev/null +++ b/lib/data/models/contact/contact_response_model.dart @@ -0,0 +1,24 @@ +import 'dart:convert'; + +import '../../../domain/entities/entities.dart'; +import 'contact_model.dart'; + +ContactResponseModel contactResponseModelFromJson(String str) => ContactResponseModel.fromJson(json.decode(str)); + +class ContactResponseModel extends ContactResponse { + ContactResponseModel({required super.contacts}); + + factory ContactResponseModel.fromJson(Map json) { + return ContactResponseModel( + contacts: List.from( + json['value'].map((contact) => ContactModel.fromJson(contact)), + ), + ); + } + + // Map toJson() { + // return { + // 'value': contacts.map((contact) => contact.toJson()).toList(), + // }; + // } +} diff --git a/lib/data/models/models.dart b/lib/data/models/models.dart index 27ac758..188e645 100644 --- a/lib/data/models/models.dart +++ b/lib/data/models/models.dart @@ -4,3 +4,5 @@ export 'user/user_model.dart'; export 'order/order_model.dart'; export 'order/order_response_model.dart'; export 'route/route_model.dart'; +export 'contact/contact_model.dart'; +export 'contact/contact_response_model.dart'; diff --git a/lib/data/models/user/user_model.dart b/lib/data/models/user/user_model.dart index 491b204..f12decb 100644 --- a/lib/data/models/user/user_model.dart +++ b/lib/data/models/user/user_model.dart @@ -29,7 +29,7 @@ class UserModel extends User { Map toJson() => { 'Oid': oid, - 'FulName': fullName, + 'Fulname': fullName, 'PhoneNo': phone, }; } diff --git a/lib/data/repositories/contact_repository_impl.dart b/lib/data/repositories/contact_repository_impl.dart new file mode 100644 index 0000000..9b72449 --- /dev/null +++ b/lib/data/repositories/contact_repository_impl.dart @@ -0,0 +1,33 @@ +import 'package:dartz/dartz.dart'; + +import '../../core/core.dart'; +import '../../domain/domain.dart'; +import '../data_sources/data_sources.dart'; +import '../models/contact/contact_response_model.dart'; + +class ContactRepositoryImpl extends ContactRepository { + final ContactRemoteDataSource remoteDataSource; + final UserLocalDataSource localDataSource; + final NetworkInfo networkInfo; + + ContactRepositoryImpl({ + required this.remoteDataSource, + required this.localDataSource, + required this.networkInfo, + }); + + @override + Future> getContacts() async { + if (!await networkInfo.isConnected) { + return Left(NetworkFailure()); + } + + try { + final String token = await localDataSource.getToken(); + final response = await remoteDataSource.getContacts(token); + return Right(response); + } on Failure catch (failure) { + return Left(failure); + } + } +} diff --git a/lib/data/repositories/repositories.dart b/lib/data/repositories/repositories.dart index 4d4377f..07e6c9d 100644 --- a/lib/data/repositories/repositories.dart +++ b/lib/data/repositories/repositories.dart @@ -1,3 +1,4 @@ export 'user_repository_impl.dart'; export 'splash_repository_impl.dart'; export 'order_repository_impl.dart'; +export 'contact_repository_impl.dart'; diff --git a/lib/di/contact.dart b/lib/di/contact.dart new file mode 100644 index 0000000..08578e5 --- /dev/null +++ b/lib/di/contact.dart @@ -0,0 +1,23 @@ +import '../application/contact_cubit/contact_cubit.dart'; +import '../data/data.dart'; +import '../domain/domain.dart'; +import 'di.dart'; + +void registerContactFeature() { + // Contact cubit and Use Cases + sl.registerFactory(() => ContactCubit(sl())); + sl.registerLazySingleton(() => GetContactsUseCase(sl())); + + // Contact Repository and Data Sources + sl.registerLazySingleton( + () => ContactRepositoryImpl( + localDataSource: sl(), + remoteDataSource: sl(), + networkInfo: sl(), + ), + ); + + sl.registerLazySingleton( + () => ContactRemoteDataSourceImpl(client: sl()), + ); +} diff --git a/lib/di/di.dart b/lib/di/di.dart index 7a01890..24e59da 100644 --- a/lib/di/di.dart +++ b/lib/di/di.dart @@ -1,6 +1,7 @@ import 'package:get_it/get_it.dart'; import 'common.dart'; +import 'contact.dart'; import 'cubits.dart'; import 'language.dart'; import 'order.dart'; @@ -17,6 +18,7 @@ Future init() async { registerLanguageFeature(); registerSplashFeature(); registerOrderFeature(); + registerContactFeature(); // registerCategoryFeature(); // registerProductFeature(); // registerDeliveryInfoFeature(); diff --git a/lib/domain/entities/contact/contact.dart b/lib/domain/entities/contact/contact.dart new file mode 100644 index 0000000..47a9bd0 --- /dev/null +++ b/lib/domain/entities/contact/contact.dart @@ -0,0 +1,16 @@ +import 'package:equatable/equatable.dart'; + +class ContactEntity extends Equatable { + final String oid; + final String number; + final String name; + + const ContactEntity({ + required this.oid, + required this.number, + required this.name, + }); + + @override + List get props => [oid, number, name]; +} diff --git a/lib/domain/entities/contact/contact_response.dart b/lib/domain/entities/contact/contact_response.dart new file mode 100644 index 0000000..bed1a93 --- /dev/null +++ b/lib/domain/entities/contact/contact_response.dart @@ -0,0 +1,9 @@ +import 'contact.dart'; + +class ContactResponse { + final List contacts; + + ContactResponse({ + required this.contacts, + }); +} diff --git a/lib/domain/entities/entities.dart b/lib/domain/entities/entities.dart index fa01f45..80b2175 100644 --- a/lib/domain/entities/entities.dart +++ b/lib/domain/entities/entities.dart @@ -5,3 +5,5 @@ export 'order/order_response.dart'; export 'order/pagination_meta_data.dart'; export 'route/route.dart'; export 'route/route_response.dart'; +export 'contact/contact.dart'; +export 'contact/contact_response.dart'; diff --git a/lib/domain/repositories/contact_repository.dart b/lib/domain/repositories/contact_repository.dart new file mode 100644 index 0000000..91e3626 --- /dev/null +++ b/lib/domain/repositories/contact_repository.dart @@ -0,0 +1,8 @@ +import 'package:dartz/dartz.dart'; + +import '../../core/core.dart'; +import '../../data/models/contact/contact_response_model.dart'; + +abstract class ContactRepository { + Future> getContacts(); +} diff --git a/lib/domain/repositories/repositories.dart b/lib/domain/repositories/repositories.dart index 91bfac6..7b2bab7 100644 --- a/lib/domain/repositories/repositories.dart +++ b/lib/domain/repositories/repositories.dart @@ -1,3 +1,4 @@ export 'user_repository.dart'; export 'splash_repository.dart'; export 'order_repository.dart'; +export 'contact_repository.dart'; diff --git a/lib/domain/usecases/contact/get_contacts_usecase.dart b/lib/domain/usecases/contact/get_contacts_usecase.dart new file mode 100644 index 0000000..bf4c7de --- /dev/null +++ b/lib/domain/usecases/contact/get_contacts_usecase.dart @@ -0,0 +1,14 @@ +import 'package:dartz/dartz.dart'; + +import '../../../core/core.dart'; +import '../../domain.dart'; + +class GetContactsUseCase implements UseCase { + final ContactRepository repository; + GetContactsUseCase(this.repository); + + @override + Future> call(NoParams params) async { + return await repository.getContacts(); + } +} diff --git a/lib/domain/usecases/usecases.dart b/lib/domain/usecases/usecases.dart index 45509c2..ad95996 100644 --- a/lib/domain/usecases/usecases.dart +++ b/lib/domain/usecases/usecases.dart @@ -1,3 +1,4 @@ -export 'user/user.dart'; -export 'splash/splash_usecase.dart'; +export 'contact/get_contacts_usecase.dart'; export 'order/order.dart'; +export 'splash/splash_usecase.dart'; +export 'user/user.dart'; diff --git a/lib/presentation/screens/histories_screen.dart b/lib/presentation/screens/histories_screen.dart index 66a834a..929960a 100644 --- a/lib/presentation/screens/histories_screen.dart +++ b/lib/presentation/screens/histories_screen.dart @@ -50,6 +50,7 @@ class _HistoriesScreenState extends State { 'order_history'.tr(), style: AppText.h1b, ), + Space.yf(0.4), Text( 'order_history_desc'.tr(), style: const TextStyle( @@ -77,6 +78,12 @@ class _HistoriesScreenState extends State { ), ); } else if (state is OrderLoaded) { + if (state.orders.isEmpty) { + return const SliverToBoxAdapter( + child: EmptyOrder(), + ); + } + return SliverList( delegate: SliverChildBuilderDelegate( (BuildContext context, int index) { @@ -93,11 +100,7 @@ class _HistoriesScreenState extends State { ), ); } else { - return SliverToBoxAdapter( - child: Center( - child: Text('order_not_available'.tr()), - ), - ); + return const SizedBox.shrink(); } }, ), diff --git a/lib/presentation/screens/order_details.dart b/lib/presentation/screens/order_details.dart index dbc54ba..8aadb4d 100644 --- a/lib/presentation/screens/order_details.dart +++ b/lib/presentation/screens/order_details.dart @@ -108,7 +108,7 @@ class _OrderDetailsScreenState extends State { children: [ Text( '${'order_info'.tr()} №${widget.order.no}', - style: AppText.b1b, + style: AppText.h2b, ), /// gap @@ -131,7 +131,7 @@ class _OrderDetailsScreenState extends State { children: [ Text( 'route'.tr(), - style: AppText.b1b, + style: AppText.h2b, ), /// gap diff --git a/lib/presentation/screens/orders.dart b/lib/presentation/screens/orders.dart index 393f8c3..a94f5eb 100644 --- a/lib/presentation/screens/orders.dart +++ b/lib/presentation/screens/orders.dart @@ -1,5 +1,6 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../../application/order_bloc/order_bloc.dart'; @@ -54,7 +55,7 @@ class _OrdersScreenState extends State with AutomaticKeepAliveClie fontWeight: FontWeight.bold, ), ), - Space.yf(0.30), + Space.yf(0.40), Text( 'follow_orders'.tr(), style: const TextStyle( @@ -83,6 +84,14 @@ class _OrdersScreenState extends State with AutomaticKeepAliveClie ), ); } else if (state is OrderLoaded) { + if (state.orders.isEmpty) { + return SliverToBoxAdapter( + child: SizedBox( + height: MediaQuery.of(context).size.height / 2.5, + child: const EmptyOrder(), + ), + ); + } return SliverList( delegate: SliverChildBuilderDelegate( (BuildContext context, int index) { @@ -99,11 +108,7 @@ class _OrdersScreenState extends State with AutomaticKeepAliveClie ), ); } else { - return const SliverToBoxAdapter( - child: Center( - child: Text('No orders available'), - ), - ); + return const SizedBox.shrink(); } }, ), diff --git a/lib/presentation/screens/profile.dart b/lib/presentation/screens/profile.dart index 8edf967..99193d8 100644 --- a/lib/presentation/screens/profile.dart +++ b/lib/presentation/screens/profile.dart @@ -1,12 +1,16 @@ import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:url_launcher/url_launcher.dart'; +import '../../application/contact_cubit/contact_cubit.dart'; import '../../application/user_bloc/user_bloc.dart'; import '../../configs/configs.dart'; import '../../core/core.dart'; +import '../../domain/entities/contact/contact.dart'; import '../../domain/entities/user/user.dart'; -import '../widgets/lang_selection.dart'; +import '../presentation.dart'; class ProfileScreen extends StatefulWidget { const ProfileScreen({super.key}); @@ -20,6 +24,7 @@ class _ProfileScreenState extends State { void initState() { super.initState(); context.read().add(GetUser()); + context.read().getContacts(); } @override @@ -55,138 +60,199 @@ class _ProfileScreenState extends State { } Widget _buildProfileContent(BuildContext context, User user) { - return SingleChildScrollView( - child: Padding( - padding: Space.all(1, 1), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - /// gap - Space.yf(1.3), + return Padding( + padding: Space.all(1, 1), + child: Stack( + children: [ + SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + /// gap + Space.yf(1.3), - /// header - Text( - 'personal_cabinet'.tr(), - style: AppText.h1b, + /// header + Text( + 'personal_cabinet'.tr(), + style: AppText.h1b, + ), + + Space.y!, + + /// user card + _buildUserCard(context, user), + + ///gap + Space.yf(2), + + /// settings card + _buildSettingsCard(context), + + ///gap + Space.yf(2), + + /// contacts list + BlocBuilder( + builder: (context, state) { + if (state is ContactLoading) { + return const Center(child: CircularProgressIndicator()); + } else if (state is ContactLoaded) { + return state.contacts.isEmpty ? const SizedBox.shrink() : _buildContactsList(state.contacts); + } else if (state is ContactError) { + return RetryWidget( + onRetry: () { + context.read().getContacts(); + }, + ); + } else { + return const SizedBox.shrink(); + } + }, + ), + ], ), + ), - Space.y!, - - /// card - SizedBox( - width: double.infinity, - child: Card( - color: Colors.white, - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - children: [ - /// name surname - RowWidget( - text: user.fullName, - leadingIcon: Icons.person_2_outlined, - ), - - /// gap - Space.yf(1), - - /// phone - RowWidget( - text: user.phone, - leadingIcon: Icons.phone_android_outlined, - ), - ], - ), + /// logout at the bottom + Align( + alignment: Alignment.bottomCenter, + child: TextButton( + onPressed: () { + context.read().add(SignOutUser()); + }, + child: Text( + 'logout'.tr(), + style: AppText.b1!.copyWith( + color: Colors.red, ), ), ), + ), + ], + ), + ); + } - ///gap - Space.yf(2), + Widget _buildUserCard(BuildContext context, User user) { + return SizedBox( + width: double.infinity, + child: Card( + color: Colors.white, + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + children: [ + /// name surname + RowWidget( + text: user.fullName, + leadingIcon: Icons.person_2_outlined, + ), - /// card - SizedBox( - width: double.infinity, - child: Card( - color: Colors.white, - child: Padding( - padding: const EdgeInsets.all(16.0), + /// phone + if (user.phone.isNotEmpty) + Column( + children: [ + /// gap + Space.yf(1), + + /// phone + RowWidget( + text: user.phone, + leadingIcon: Icons.phone_android_outlined, + ), + ], + ) + ], + ), + ), + ), + ); + } + + Widget _buildSettingsCard(BuildContext context) { + return SizedBox( + width: double.infinity, + child: Card( + color: Colors.white, + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + children: [ + /// language + GestureDetector( + onTap: () => onSelectLang(context), + child: Container( + color: Colors.transparent, child: RowWidget( - text: 'contact_support'.tr(), - leadingIcon: Icons.contact_support_outlined, + text: 'profile_select_lang'.tr(), + leadingIcon: Icons.language_outlined, trailingIcon: Icons.arrow_forward_ios, ), ), ), - ), + ], + ), + ), + ), + ); + } - ///gap - Space.yf(2), - - /// card - SizedBox( - width: double.infinity, - child: Card( - color: Colors.white, - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( + Widget _buildContactsList(List contacts) { + return SizedBox( + width: double.infinity, + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'contact_support'.tr(), + style: AppText.h3b, + ), + Space.yf(0.8), + ...contacts.map( + (contact) { + return Column( + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, children: [ - /// language - GestureDetector( - onTap: () => onSelectLang(context), - child: Container( - color: Colors.transparent, - child: RowWidget( - text: 'profile_select_lang'.tr(), - leadingIcon: Icons.language_outlined, - trailingIcon: Icons.arrow_forward_ios, - ), + const Icon(Icons.phone_iphone), + const SizedBox(width: 8), + RichText( + text: TextSpan( + children: [ + TextSpan( + text: '${contact.number} ', + style: const TextStyle( + color: Colors.black, // Use appropriate color + fontWeight: FontWeight.bold, // You can choose different font styles + fontSize: 16, // Set font size + ), + recognizer: TapGestureRecognizer() + ..onTap = () { + final Uri phoneUri = Uri(scheme: 'tel', path: contact.number); + launchUrl(phoneUri); + }, + ), + TextSpan( + text: contact.name, + style: TextStyle( + color: Colors.grey[700], // A different color for the name + fontSize: 16, + ), + ), + ], ), ), - - /// name surname - RowWidget( - text: 'privacy_policy'.tr(), - leadingIcon: Icons.gpp_maybe_outlined, - trailingIcon: Icons.arrow_forward_ios, - ), - - /// phone - RowWidget( - text: 'use_terms'.tr(), - leadingIcon: Icons.file_copy_outlined, - trailingIcon: Icons.arrow_forward_ios, - ), ], ), - ), - ), - ), - - ///gap - Space.yf(2), - - /// logout - Align( - alignment: Alignment.center, - child: TextButton( - onPressed: () { - context.read().add(SignOutUser()); - }, - child: Text( - 'logout'.tr(), - style: AppText.b1!.copyWith( - color: Colors.red, - ), - ), - ), - ), - - ///gap - Space.yf(2), - ], - ), + Space.yf(0.6) + ], + ); + }, + ), + ], ), ); } diff --git a/lib/presentation/widgets/empty_order.dart b/lib/presentation/widgets/empty_order.dart new file mode 100644 index 0000000..61ffc3e --- /dev/null +++ b/lib/presentation/widgets/empty_order.dart @@ -0,0 +1,26 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; + +import '../../configs/space.dart'; +import '../../core/constants/constants.dart'; + +class EmptyOrder extends StatelessWidget { + const EmptyOrder({super.key}); + + @override + Widget build(BuildContext context) { + return SizedBox( + height: MediaQuery.of(context).size.height - kToolbarHeight * 3, + child: Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Image.asset(AppAssets.search), + Space.yf(), + Text('order_not_available'.tr()), + ], + ), + ), + ); + } +} diff --git a/lib/presentation/widgets/info_card.dart b/lib/presentation/widgets/info_card.dart index f63bf6f..13bcf54 100644 --- a/lib/presentation/widgets/info_card.dart +++ b/lib/presentation/widgets/info_card.dart @@ -60,10 +60,11 @@ class RowTextWidget extends StatelessWidget { @override Widget build(BuildContext context) { return Row( + crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( title, - style: AppText.b1!.copyWith( + style: AppText.h3!.copyWith( color: const Color(0xFF57575C), ), maxLines: 2, @@ -72,7 +73,7 @@ class RowTextWidget extends StatelessWidget { Expanded( child: Text( info, - style: AppText.b1!.copyWith( + style: AppText.h3!.copyWith( color: const Color(0xFF0C0C0D), fontWeight: FontWeight.w500, ), diff --git a/lib/presentation/widgets/location_card.dart b/lib/presentation/widgets/location_card.dart index 22e8a93..5fee6a1 100644 --- a/lib/presentation/widgets/location_card.dart +++ b/lib/presentation/widgets/location_card.dart @@ -52,7 +52,7 @@ class LocationCard extends StatelessWidget { Space.x!, Text( routes[index].name, - style: AppText.b1b, + style: AppText.h3b, ), const Spacer(), Text( diff --git a/lib/presentation/widgets/order_card.dart b/lib/presentation/widgets/order_card.dart index 6e575d1..dbd9d45 100644 --- a/lib/presentation/widgets/order_card.dart +++ b/lib/presentation/widgets/order_card.dart @@ -6,6 +6,11 @@ import '../../core/core.dart'; import '../../domain/domain.dart'; import 'vertical_line.dart'; +final infoStyle = AppText.b2b!.copyWith( + color: const Color(0xFF57575C), + fontSize: 16, +); + class OrderCard extends StatelessWidget { final OrderEntity order; @@ -61,11 +66,30 @@ class OrderCard extends StatelessWidget { ), ), const Spacer(), - Text( + /* Text( '${'order_sent'.tr()}: ${order.departedAt}', style: AppText.b2b!.copyWith( color: AppColors.grey, ), + ), */ + + RichText( + text: TextSpan( + text: '${'order_sent'.tr()}: ', + style: AppText.b2b!.copyWith( + color: AppColors.grey, + ), + children: [ + TextSpan( + text: order.departedAt, + style: AppText.b2b!.copyWith( + color: const Color(0xFF57575C), + fontWeight: FontWeight.bold, + fontSize: 15, + ), + ), + ], + ), ), ], ), @@ -107,9 +131,7 @@ class OrderCard extends StatelessWidget { ), Text( order.from, - style: AppText.b2b!.copyWith( - color: const Color(0xFF57575C), - ), + style: infoStyle, maxLines: 2, overflow: TextOverflow.ellipsis, ), @@ -122,9 +144,7 @@ class OrderCard extends StatelessWidget { ), Text( order.to, - style: AppText.b2b!.copyWith( - color: const Color(0xFF57575C), - ), + style: infoStyle, maxLines: 2, overflow: TextOverflow.ellipsis, ), @@ -148,9 +168,7 @@ class OrderCard extends StatelessWidget { ), Text( order.placesCount.toString(), - style: AppText.b2b!.copyWith( - color: const Color(0xFF57575C), - ), + style: infoStyle, ), const SizedBox(height: 8), Text( @@ -161,9 +179,7 @@ class OrderCard extends StatelessWidget { ), Text( order.volume.toString(), - style: AppText.b2b!.copyWith( - color: const Color(0xFF57575C), - ), + style: infoStyle, ), ], ), @@ -194,9 +210,7 @@ class OrderCard extends StatelessWidget { ), Text( order.shopNo, - style: AppText.b2b!.copyWith( - color: const Color(0xFF57575C), - ), + style: infoStyle, ), ], ), diff --git a/lib/presentation/widgets/retry_widget.dart b/lib/presentation/widgets/retry_widget.dart index c8628ae..aa8660c 100644 --- a/lib/presentation/widgets/retry_widget.dart +++ b/lib/presentation/widgets/retry_widget.dart @@ -1,3 +1,4 @@ +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; class RetryWidget extends StatelessWidget { @@ -7,7 +8,7 @@ class RetryWidget extends StatelessWidget { const RetryWidget({ super.key, required this.onRetry, - this.message = 'Something went wrong. Please try again.', + this.message = 'error_message', }); @override @@ -19,7 +20,7 @@ class RetryWidget extends StatelessWidget { Padding( padding: const EdgeInsets.all(16.0), child: Text( - message, + message.tr(), textAlign: TextAlign.center, style: const TextStyle(fontSize: 16, color: Colors.black54), ), diff --git a/lib/presentation/widgets/widgets.dart b/lib/presentation/widgets/widgets.dart index dc033a7..3031313 100644 --- a/lib/presentation/widgets/widgets.dart +++ b/lib/presentation/widgets/widgets.dart @@ -12,3 +12,4 @@ export 'retry_widget.dart'; export 'successful_auth_dialog.dart'; export 'vertical_line.dart'; export 'images.dart'; +export 'empty_order.dart'; diff --git a/pubspec.lock b/pubspec.lock index 6d853db..83f399e 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -626,6 +626,70 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.2" + url_launcher: + dependency: "direct main" + description: + name: url_launcher + sha256: "21b704ce5fa560ea9f3b525b43601c678728ba46725bab9b01187b4831377ed3" + url: "https://pub.dev" + source: hosted + version: "6.3.0" + url_launcher_android: + dependency: transitive + description: + name: url_launcher_android + sha256: f0c73347dfcfa5b3db8bc06e1502668265d39c08f310c29bff4e28eea9699f79 + url: "https://pub.dev" + source: hosted + version: "6.3.9" + url_launcher_ios: + dependency: transitive + description: + name: url_launcher_ios + sha256: e43b677296fadce447e987a2f519dcf5f6d1e527dc35d01ffab4fff5b8a7063e + url: "https://pub.dev" + source: hosted + version: "6.3.1" + url_launcher_linux: + dependency: transitive + description: + name: url_launcher_linux + sha256: e2b9622b4007f97f504cd64c0128309dfb978ae66adbe944125ed9e1750f06af + url: "https://pub.dev" + source: hosted + version: "3.2.0" + url_launcher_macos: + dependency: transitive + description: + name: url_launcher_macos + sha256: "9a1a42d5d2d95400c795b2914c36fdcb525870c752569438e4ebb09a2b5d90de" + url: "https://pub.dev" + source: hosted + version: "3.2.0" + url_launcher_platform_interface: + dependency: transitive + description: + name: url_launcher_platform_interface + sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + url_launcher_web: + dependency: transitive + description: + name: url_launcher_web + sha256: "772638d3b34c779ede05ba3d38af34657a05ac55b06279ea6edd409e323dca8e" + url: "https://pub.dev" + source: hosted + version: "2.3.3" + url_launcher_windows: + dependency: transitive + description: + name: url_launcher_windows + sha256: "49c10f879746271804767cb45551ec5592cdab00ee105c06dddde1a98f73b185" + url: "https://pub.dev" + source: hosted + version: "3.1.2" vector_graphics: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 8a5bf68..676bc25 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -29,6 +29,7 @@ dependencies: intl: ^0.19.0 # cached_network_image: ^3.4.1 flutter_native_splash: ^2.4.1 + url_launcher: ^6.3.0 dev_dependencies: flutter_test: