From 9d53760137db12d0848b7e8e657a173be6989341 Mon Sep 17 00:00:00 2001 From: Username1548 Date: Thu, 13 Mar 2025 02:30:10 +0700 Subject: [PATCH] fixed pagination --- lib/core/app_router.dart | 1 - lib/core/const.dart | 5 +- lib/core/utils/pagination_utils.dart | 8 + .../auth/presentation/pages/auth_screen.dart | 39 +- lib/features/chat/models/chat_room_model.dart | 9 + .../chat/models/chat_room_model.freezed.dart | 60 +++- .../chat/models/chat_room_model.g.dart | 2 + ...l.dart => chat_room_pagination_model.dart} | 24 +- ...> chat_room_pagination_model.freezed.dart} | 335 +++++++++++++++--- ...dart => chat_room_pagination_model.g.dart} | 24 +- .../bloc/chat_room_cubit/chat_room_cubit.dart | 11 + .../bloc/chats_cubit/chats_cubit.dart | 59 ++- .../bloc/chats_cubit/chats_state.dart | 3 +- .../bloc/chats_cubit/chats_state.freezed.dart | 25 +- .../chat/presentation/pages/chat_screen.dart | 1 - .../chat/presentation/pages/chats_screen.dart | 60 ++-- .../widgets/chat_entry_widget.dart | 4 +- .../chat/presentation/widgets/order_card.dart | 20 ++ .../chat/repositories/chat_repository.dart | 6 +- lib/features/chat/services/chat_service.dart | 5 +- .../chat/services/chat_service.g.dart | 13 +- lib/features/dev_tools/test_cases.dart | 30 +- .../bloc/diets_cubit/diets_cubit.dart | 2 +- .../bloc/feed_cubit/feed_cubit.dart | 2 +- .../bloc/plans_cubit/plans_cubit.dart | 2 +- .../bloc/recipes_cubit/recipes_cubit.dart | 2 +- .../feed/presentation/pages/feed_screen.dart | 30 +- .../feed/presentation/widgets/blog_posts.dart | 33 +- .../feed/presentation/widgets/diets.dart | 27 +- .../feed/presentation/widgets/plans.dart | 33 +- .../feed/presentation/widgets/recipes.dart | 33 +- .../plans/enums/chosen_plan_state_enum.dart | 44 +++ .../plans/models/chosen_plan_model.dart | 4 +- .../models/chosen_plan_model.freezed.dart | 79 ++--- .../plans/models/chosen_plan_model.g.dart | 22 +- .../bloc/profile_cubit/profile_cubit.dart | 5 +- .../presentation/pages/profile_screen.dart | 4 +- .../widgets/sub_action_button_widget.dart | 6 +- 38 files changed, 778 insertions(+), 294 deletions(-) create mode 100644 lib/core/utils/pagination_utils.dart rename lib/features/chat/models/{chat_room_preview_model.dart => chat_room_pagination_model.dart} (65%) rename lib/features/chat/models/{chat_room_preview_model.freezed.dart => chat_room_pagination_model.freezed.dart} (73%) rename lib/features/chat/models/{chat_room_preview_model.g.dart => chat_room_pagination_model.g.dart} (76%) create mode 100644 lib/features/chat/presentation/widgets/order_card.dart create mode 100644 lib/features/plans/enums/chosen_plan_state_enum.dart diff --git a/lib/core/app_router.dart b/lib/core/app_router.dart index fca6fac5..bea9fda0 100644 --- a/lib/core/app_router.dart +++ b/lib/core/app_router.dart @@ -7,7 +7,6 @@ import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/prof import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/profile_avatar_cubit/profile_avatar_state.dart'; import 'package:eatvio_app/features/bottom_navigation_bar/presentation/widgets/bottom_navigation_bar_widget.dart'; import 'package:eatvio_app/features/calendar/presentation/pages/calendar_screen.dart'; -import 'package:eatvio_app/features/chat/presentation/bloc/chats_cubit/chats_cubit.dart'; import 'package:eatvio_app/features/chat/presentation/pages/chat_screen.dart'; import 'package:eatvio_app/features/chat/presentation/pages/chats_screen.dart'; import 'package:eatvio_app/features/chat/presentation/pages/photo_view_screen.dart'; diff --git a/lib/core/const.dart b/lib/core/const.dart index 0b91d766..68cdc249 100644 --- a/lib/core/const.dart +++ b/lib/core/const.dart @@ -1,5 +1,5 @@ // String baseUrl = 'https://eatvio.ru'; -String baseUrl = 'https://dev2.eatvio.com'; +String baseUrl = 'http://10.55.5.123:8080'; const List durationValues = [7, 14, 21]; @@ -8,4 +8,5 @@ const List planTypeValues = ['fit', 'slim', 'wellness', 'behavior']; const newMessagesChannelName = 'private-new-chat-messages'; const newNotificationsChannelName = 'private-message-events'; -const directChatChannelName = 'private-direct-chat'; \ No newline at end of file +const directChatChannelName = 'private-direct-chat'; +const thresholdForPagination = 150; diff --git a/lib/core/utils/pagination_utils.dart b/lib/core/utils/pagination_utils.dart new file mode 100644 index 00000000..c6f6da95 --- /dev/null +++ b/lib/core/utils/pagination_utils.dart @@ -0,0 +1,8 @@ +import 'package:eatvio_app/core/const.dart'; +import 'package:flutter/material.dart'; + +void loadNewContent(ScrollNotification notification, Future Function() load) { + if (notification.metrics.pixels >= notification.metrics.maxScrollExtent - thresholdForPagination && !notification.metrics.outOfRange) { + load(); + } +} diff --git a/lib/features/auth/presentation/pages/auth_screen.dart b/lib/features/auth/presentation/pages/auth_screen.dart index e446ece8..818578ae 100644 --- a/lib/features/auth/presentation/pages/auth_screen.dart +++ b/lib/features/auth/presentation/pages/auth_screen.dart @@ -6,6 +6,7 @@ import 'package:eatvio_app/core/widgets/custom_text_form_field.dart'; import 'package:eatvio_app/features/auth/presentation/bloc/auth_cubit.dart'; import 'package:eatvio_app/generated/l10n.dart'; import 'package:flutter/cupertino.dart'; +import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_native_splash/flutter_native_splash.dart'; @@ -99,30 +100,30 @@ class _AuthScreenState extends State { ], ), Spacer(), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - 'Нажимая "Войти", Вы соглашаетесь с ', + Center( + child: RichText( + textAlign: TextAlign.center, + text: TextSpan( + text: 'Нажимая "Войти", Вы соглашаетесь \n', style: TextStyle( fontSize: 12, + color: Colors.black, ), - ), - GestureDetector( - onTap: () async { - await launchUrl(Uri.parse(baseUrl + '/oferta_bs.pdf')); - }, - child: Text( - 'Публичной офертой', - style: TextStyle( - fontSize: 12, - color: appTheme.blueA400, - decorationColor: appTheme.blueA400, - decoration: TextDecoration.underline, + children: [ + TextSpan(text: 'c '), + TextSpan( + text: ' Публичной офертой', + style: TextStyle( + fontSize: 12, + color: appTheme.blueA400, + decorationColor: appTheme.blueA400, + decoration: TextDecoration.underline, + ), + recognizer: TapGestureRecognizer()..onTap = () async => await launchUrl(Uri.parse(baseUrl + '/oferta_bs.pdf')), ), - ), + ], ), - ], + ), ), const SizedBox(height: 16), Container( diff --git a/lib/features/chat/models/chat_room_model.dart b/lib/features/chat/models/chat_room_model.dart index f9e9a416..13c12d0e 100644 --- a/lib/features/chat/models/chat_room_model.dart +++ b/lib/features/chat/models/chat_room_model.dart @@ -1,5 +1,6 @@ import 'package:eatvio_app/features/chat/models/chat_room_settings_model.dart'; import 'package:eatvio_app/features/chat/models/chat_user_model.dart'; +import 'package:eatvio_app/features/plans/models/chosen_plan_model.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; part 'chat_room_model.freezed.dart'; @@ -11,7 +12,15 @@ class ChatRoomModel with _$ChatRoomModel { required String id, @JsonKey(name: 'chat_room_setting') required ChatRoomSettingsModel chatRoomSettings, required Map users, + @JsonKey(name: 'chosen_plan', fromJson: _parseChosenPlan) required ChosenPlanModel? chosenPlan, }) = _ChatRoomModel; factory ChatRoomModel.fromJson(Map json) => _$ChatRoomModelFromJson(json); } + +ChosenPlanModel? _parseChosenPlan(json) { + if (json is Map) { + return ChosenPlanModel.fromJson(json); + } + return null; +} diff --git a/lib/features/chat/models/chat_room_model.freezed.dart b/lib/features/chat/models/chat_room_model.freezed.dart index 6afb3a94..7f46b373 100644 --- a/lib/features/chat/models/chat_room_model.freezed.dart +++ b/lib/features/chat/models/chat_room_model.freezed.dart @@ -25,6 +25,8 @@ mixin _$ChatRoomModel { ChatRoomSettingsModel get chatRoomSettings => throw _privateConstructorUsedError; Map get users => throw _privateConstructorUsedError; + @JsonKey(name: 'chosen_plan', fromJson: _parseChosenPlan) + ChosenPlanModel? get chosenPlan => throw _privateConstructorUsedError; /// Serializes this ChatRoomModel to a JSON map. Map toJson() => throw _privateConstructorUsedError; @@ -46,9 +48,12 @@ abstract class $ChatRoomModelCopyWith<$Res> { {String id, @JsonKey(name: 'chat_room_setting') ChatRoomSettingsModel chatRoomSettings, - Map users}); + Map users, + @JsonKey(name: 'chosen_plan', fromJson: _parseChosenPlan) + ChosenPlanModel? chosenPlan}); $ChatRoomSettingsModelCopyWith<$Res> get chatRoomSettings; + $ChosenPlanModelCopyWith<$Res>? get chosenPlan; } /// @nodoc @@ -69,6 +74,7 @@ class _$ChatRoomModelCopyWithImpl<$Res, $Val extends ChatRoomModel> Object? id = null, Object? chatRoomSettings = null, Object? users = null, + Object? chosenPlan = freezed, }) { return _then(_value.copyWith( id: null == id @@ -83,6 +89,10 @@ class _$ChatRoomModelCopyWithImpl<$Res, $Val extends ChatRoomModel> ? _value.users : users // ignore: cast_nullable_to_non_nullable as Map, + chosenPlan: freezed == chosenPlan + ? _value.chosenPlan + : chosenPlan // ignore: cast_nullable_to_non_nullable + as ChosenPlanModel?, ) as $Val); } @@ -96,6 +106,20 @@ class _$ChatRoomModelCopyWithImpl<$Res, $Val extends ChatRoomModel> return _then(_value.copyWith(chatRoomSettings: value) as $Val); }); } + + /// Create a copy of ChatRoomModel + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $ChosenPlanModelCopyWith<$Res>? get chosenPlan { + if (_value.chosenPlan == null) { + return null; + } + + return $ChosenPlanModelCopyWith<$Res>(_value.chosenPlan!, (value) { + return _then(_value.copyWith(chosenPlan: value) as $Val); + }); + } } /// @nodoc @@ -110,10 +134,14 @@ abstract class _$$ChatRoomModelImplCopyWith<$Res> {String id, @JsonKey(name: 'chat_room_setting') ChatRoomSettingsModel chatRoomSettings, - Map users}); + Map users, + @JsonKey(name: 'chosen_plan', fromJson: _parseChosenPlan) + ChosenPlanModel? chosenPlan}); @override $ChatRoomSettingsModelCopyWith<$Res> get chatRoomSettings; + @override + $ChosenPlanModelCopyWith<$Res>? get chosenPlan; } /// @nodoc @@ -132,6 +160,7 @@ class __$$ChatRoomModelImplCopyWithImpl<$Res> Object? id = null, Object? chatRoomSettings = null, Object? users = null, + Object? chosenPlan = freezed, }) { return _then(_$ChatRoomModelImpl( id: null == id @@ -146,6 +175,10 @@ class __$$ChatRoomModelImplCopyWithImpl<$Res> ? _value._users : users // ignore: cast_nullable_to_non_nullable as Map, + chosenPlan: freezed == chosenPlan + ? _value.chosenPlan + : chosenPlan // ignore: cast_nullable_to_non_nullable + as ChosenPlanModel?, )); } } @@ -156,7 +189,9 @@ class _$ChatRoomModelImpl implements _ChatRoomModel { const _$ChatRoomModelImpl( {required this.id, @JsonKey(name: 'chat_room_setting') required this.chatRoomSettings, - required final Map users}) + required final Map users, + @JsonKey(name: 'chosen_plan', fromJson: _parseChosenPlan) + required this.chosenPlan}) : _users = users; factory _$ChatRoomModelImpl.fromJson(Map json) => @@ -175,9 +210,13 @@ class _$ChatRoomModelImpl implements _ChatRoomModel { return EqualUnmodifiableMapView(_users); } + @override + @JsonKey(name: 'chosen_plan', fromJson: _parseChosenPlan) + final ChosenPlanModel? chosenPlan; + @override String toString() { - return 'ChatRoomModel(id: $id, chatRoomSettings: $chatRoomSettings, users: $users)'; + return 'ChatRoomModel(id: $id, chatRoomSettings: $chatRoomSettings, users: $users, chosenPlan: $chosenPlan)'; } @override @@ -188,13 +227,15 @@ class _$ChatRoomModelImpl implements _ChatRoomModel { (identical(other.id, id) || other.id == id) && (identical(other.chatRoomSettings, chatRoomSettings) || other.chatRoomSettings == chatRoomSettings) && - const DeepCollectionEquality().equals(other._users, _users)); + const DeepCollectionEquality().equals(other._users, _users) && + (identical(other.chosenPlan, chosenPlan) || + other.chosenPlan == chosenPlan)); } @JsonKey(includeFromJson: false, includeToJson: false) @override int get hashCode => Object.hash(runtimeType, id, chatRoomSettings, - const DeepCollectionEquality().hash(_users)); + const DeepCollectionEquality().hash(_users), chosenPlan); /// Create a copy of ChatRoomModel /// with the given fields replaced by the non-null parameter values. @@ -217,7 +258,9 @@ abstract class _ChatRoomModel implements ChatRoomModel { {required final String id, @JsonKey(name: 'chat_room_setting') required final ChatRoomSettingsModel chatRoomSettings, - required final Map users}) = _$ChatRoomModelImpl; + required final Map users, + @JsonKey(name: 'chosen_plan', fromJson: _parseChosenPlan) + required final ChosenPlanModel? chosenPlan}) = _$ChatRoomModelImpl; factory _ChatRoomModel.fromJson(Map json) = _$ChatRoomModelImpl.fromJson; @@ -229,6 +272,9 @@ abstract class _ChatRoomModel implements ChatRoomModel { ChatRoomSettingsModel get chatRoomSettings; @override Map get users; + @override + @JsonKey(name: 'chosen_plan', fromJson: _parseChosenPlan) + ChosenPlanModel? get chosenPlan; /// Create a copy of ChatRoomModel /// with the given fields replaced by the non-null parameter values. diff --git a/lib/features/chat/models/chat_room_model.g.dart b/lib/features/chat/models/chat_room_model.g.dart index 68d3195c..834f2d0e 100644 --- a/lib/features/chat/models/chat_room_model.g.dart +++ b/lib/features/chat/models/chat_room_model.g.dart @@ -15,6 +15,7 @@ _$ChatRoomModelImpl _$$ChatRoomModelImplFromJson(Map json) => (k, e) => MapEntry(k, ChatUserModel.fromJson(e as Map)), ), + chosenPlan: _parseChosenPlan(json['chosen_plan']), ); Map _$$ChatRoomModelImplToJson(_$ChatRoomModelImpl instance) => @@ -22,4 +23,5 @@ Map _$$ChatRoomModelImplToJson(_$ChatRoomModelImpl instance) => 'id': instance.id, 'chat_room_setting': instance.chatRoomSettings, 'users': instance.users, + 'chosen_plan': instance.chosenPlan, }; diff --git a/lib/features/chat/models/chat_room_preview_model.dart b/lib/features/chat/models/chat_room_pagination_model.dart similarity index 65% rename from lib/features/chat/models/chat_room_preview_model.dart rename to lib/features/chat/models/chat_room_pagination_model.dart index bc6e4b5d..6d44a685 100644 --- a/lib/features/chat/models/chat_room_preview_model.dart +++ b/lib/features/chat/models/chat_room_pagination_model.dart @@ -1,16 +1,28 @@ import 'package:eatvio_app/features/chat/models/chat_message_model.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; -part 'chat_room_preview_model.freezed.dart'; -part 'chat_room_preview_model.g.dart'; +part 'chat_room_pagination_model.freezed.dart'; +part 'chat_room_pagination_model.g.dart'; @freezed -class ChatRoomPreviewModel with _$ChatRoomPreviewModel { - const factory ChatRoomPreviewModel({ - @JsonKey(name: "chatRooms") required List chatRooms, +class ChatRoomPaginationModel with _$ChatRoomPaginationModel { + const factory ChatRoomPaginationModel({ + @JsonKey(name: "chatRooms") required ChatRooms chatRooms, + @JsonKey(name: "number_of_unread_chat_rooms") required int unreadChatsCount, }) = _ChatRoomPreviewModel; - factory ChatRoomPreviewModel.fromJson(Map json) => _$ChatRoomPreviewModelFromJson(json); + factory ChatRoomPaginationModel.fromJson(Map json) => _$ChatRoomPaginationModelFromJson(json); +} + +@freezed +class ChatRooms with _$ChatRooms { + const factory ChatRooms({ + @JsonKey(name: "data") required List data, + @JsonKey(name: "last_page") required int lastPage, + @JsonKey(name: "current_page") required int currentPage, + }) = _ChatRooms; + + factory ChatRooms.fromJson(Map json) => _$ChatRoomsFromJson(json); } @freezed diff --git a/lib/features/chat/models/chat_room_preview_model.freezed.dart b/lib/features/chat/models/chat_room_pagination_model.freezed.dart similarity index 73% rename from lib/features/chat/models/chat_room_preview_model.freezed.dart rename to lib/features/chat/models/chat_room_pagination_model.freezed.dart index 940c3106..42d8ef5f 100644 --- a/lib/features/chat/models/chat_room_preview_model.freezed.dart +++ b/lib/features/chat/models/chat_room_pagination_model.freezed.dart @@ -3,7 +3,7 @@ // ignore_for_file: type=lint // ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark -part of 'chat_room_preview_model.dart'; +part of 'chat_room_pagination_model.dart'; // ************************************************************************** // FreezedGenerator @@ -14,92 +14,125 @@ T _$identity(T value) => value; final _privateConstructorUsedError = UnsupportedError( 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models'); -ChatRoomPreviewModel _$ChatRoomPreviewModelFromJson(Map json) { +ChatRoomPaginationModel _$ChatRoomPaginationModelFromJson( + Map json) { return _ChatRoomPreviewModel.fromJson(json); } /// @nodoc -mixin _$ChatRoomPreviewModel { +mixin _$ChatRoomPaginationModel { @JsonKey(name: "chatRooms") - List get chatRooms => throw _privateConstructorUsedError; + ChatRooms get chatRooms => throw _privateConstructorUsedError; + @JsonKey(name: "number_of_unread_chat_rooms") + int get unreadChatsCount => throw _privateConstructorUsedError; - /// Serializes this ChatRoomPreviewModel to a JSON map. + /// Serializes this ChatRoomPaginationModel to a JSON map. Map toJson() => throw _privateConstructorUsedError; - /// Create a copy of ChatRoomPreviewModel + /// Create a copy of ChatRoomPaginationModel /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) - $ChatRoomPreviewModelCopyWith get copyWith => + $ChatRoomPaginationModelCopyWith get copyWith => throw _privateConstructorUsedError; } /// @nodoc -abstract class $ChatRoomPreviewModelCopyWith<$Res> { - factory $ChatRoomPreviewModelCopyWith(ChatRoomPreviewModel value, - $Res Function(ChatRoomPreviewModel) then) = - _$ChatRoomPreviewModelCopyWithImpl<$Res, ChatRoomPreviewModel>; +abstract class $ChatRoomPaginationModelCopyWith<$Res> { + factory $ChatRoomPaginationModelCopyWith(ChatRoomPaginationModel value, + $Res Function(ChatRoomPaginationModel) then) = + _$ChatRoomPaginationModelCopyWithImpl<$Res, ChatRoomPaginationModel>; @useResult - $Res call({@JsonKey(name: "chatRooms") List chatRooms}); + $Res call( + {@JsonKey(name: "chatRooms") ChatRooms chatRooms, + @JsonKey(name: "number_of_unread_chat_rooms") int unreadChatsCount}); + + $ChatRoomsCopyWith<$Res> get chatRooms; } /// @nodoc -class _$ChatRoomPreviewModelCopyWithImpl<$Res, - $Val extends ChatRoomPreviewModel> - implements $ChatRoomPreviewModelCopyWith<$Res> { - _$ChatRoomPreviewModelCopyWithImpl(this._value, this._then); +class _$ChatRoomPaginationModelCopyWithImpl<$Res, + $Val extends ChatRoomPaginationModel> + implements $ChatRoomPaginationModelCopyWith<$Res> { + _$ChatRoomPaginationModelCopyWithImpl(this._value, this._then); // ignore: unused_field final $Val _value; // ignore: unused_field final $Res Function($Val) _then; - /// Create a copy of ChatRoomPreviewModel + /// Create a copy of ChatRoomPaginationModel /// with the given fields replaced by the non-null parameter values. @pragma('vm:prefer-inline') @override $Res call({ Object? chatRooms = null, + Object? unreadChatsCount = null, }) { return _then(_value.copyWith( chatRooms: null == chatRooms ? _value.chatRooms : chatRooms // ignore: cast_nullable_to_non_nullable - as List, + as ChatRooms, + unreadChatsCount: null == unreadChatsCount + ? _value.unreadChatsCount + : unreadChatsCount // ignore: cast_nullable_to_non_nullable + as int, ) as $Val); } + + /// Create a copy of ChatRoomPaginationModel + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $ChatRoomsCopyWith<$Res> get chatRooms { + return $ChatRoomsCopyWith<$Res>(_value.chatRooms, (value) { + return _then(_value.copyWith(chatRooms: value) as $Val); + }); + } } /// @nodoc abstract class _$$ChatRoomPreviewModelImplCopyWith<$Res> - implements $ChatRoomPreviewModelCopyWith<$Res> { + implements $ChatRoomPaginationModelCopyWith<$Res> { factory _$$ChatRoomPreviewModelImplCopyWith(_$ChatRoomPreviewModelImpl value, $Res Function(_$ChatRoomPreviewModelImpl) then) = __$$ChatRoomPreviewModelImplCopyWithImpl<$Res>; @override @useResult - $Res call({@JsonKey(name: "chatRooms") List chatRooms}); + $Res call( + {@JsonKey(name: "chatRooms") ChatRooms chatRooms, + @JsonKey(name: "number_of_unread_chat_rooms") int unreadChatsCount}); + + @override + $ChatRoomsCopyWith<$Res> get chatRooms; } /// @nodoc class __$$ChatRoomPreviewModelImplCopyWithImpl<$Res> - extends _$ChatRoomPreviewModelCopyWithImpl<$Res, _$ChatRoomPreviewModelImpl> + extends _$ChatRoomPaginationModelCopyWithImpl<$Res, + _$ChatRoomPreviewModelImpl> implements _$$ChatRoomPreviewModelImplCopyWith<$Res> { __$$ChatRoomPreviewModelImplCopyWithImpl(_$ChatRoomPreviewModelImpl _value, $Res Function(_$ChatRoomPreviewModelImpl) _then) : super(_value, _then); - /// Create a copy of ChatRoomPreviewModel + /// Create a copy of ChatRoomPaginationModel /// with the given fields replaced by the non-null parameter values. @pragma('vm:prefer-inline') @override $Res call({ Object? chatRooms = null, + Object? unreadChatsCount = null, }) { return _then(_$ChatRoomPreviewModelImpl( chatRooms: null == chatRooms - ? _value._chatRooms + ? _value.chatRooms : chatRooms // ignore: cast_nullable_to_non_nullable - as List, + as ChatRooms, + unreadChatsCount: null == unreadChatsCount + ? _value.unreadChatsCount + : unreadChatsCount // ignore: cast_nullable_to_non_nullable + as int, )); } } @@ -108,24 +141,23 @@ class __$$ChatRoomPreviewModelImplCopyWithImpl<$Res> @JsonSerializable() class _$ChatRoomPreviewModelImpl implements _ChatRoomPreviewModel { const _$ChatRoomPreviewModelImpl( - {@JsonKey(name: "chatRooms") required final List chatRooms}) - : _chatRooms = chatRooms; + {@JsonKey(name: "chatRooms") required this.chatRooms, + @JsonKey(name: "number_of_unread_chat_rooms") + required this.unreadChatsCount}); factory _$ChatRoomPreviewModelImpl.fromJson(Map json) => _$$ChatRoomPreviewModelImplFromJson(json); - final List _chatRooms; @override @JsonKey(name: "chatRooms") - List get chatRooms { - if (_chatRooms is EqualUnmodifiableListView) return _chatRooms; - // ignore: implicit_dynamic_type - return EqualUnmodifiableListView(_chatRooms); - } + final ChatRooms chatRooms; + @override + @JsonKey(name: "number_of_unread_chat_rooms") + final int unreadChatsCount; @override String toString() { - return 'ChatRoomPreviewModel(chatRooms: $chatRooms)'; + return 'ChatRoomPaginationModel(chatRooms: $chatRooms, unreadChatsCount: $unreadChatsCount)'; } @override @@ -133,16 +165,17 @@ class _$ChatRoomPreviewModelImpl implements _ChatRoomPreviewModel { return identical(this, other) || (other.runtimeType == runtimeType && other is _$ChatRoomPreviewModelImpl && - const DeepCollectionEquality() - .equals(other._chatRooms, _chatRooms)); + (identical(other.chatRooms, chatRooms) || + other.chatRooms == chatRooms) && + (identical(other.unreadChatsCount, unreadChatsCount) || + other.unreadChatsCount == unreadChatsCount)); } @JsonKey(includeFromJson: false, includeToJson: false) @override - int get hashCode => - Object.hash(runtimeType, const DeepCollectionEquality().hash(_chatRooms)); + int get hashCode => Object.hash(runtimeType, chatRooms, unreadChatsCount); - /// Create a copy of ChatRoomPreviewModel + /// Create a copy of ChatRoomPaginationModel /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @override @@ -160,19 +193,23 @@ class _$ChatRoomPreviewModelImpl implements _ChatRoomPreviewModel { } } -abstract class _ChatRoomPreviewModel implements ChatRoomPreviewModel { +abstract class _ChatRoomPreviewModel implements ChatRoomPaginationModel { const factory _ChatRoomPreviewModel( - {@JsonKey(name: "chatRooms") - required final List chatRooms}) = _$ChatRoomPreviewModelImpl; + {@JsonKey(name: "chatRooms") required final ChatRooms chatRooms, + @JsonKey(name: "number_of_unread_chat_rooms") + required final int unreadChatsCount}) = _$ChatRoomPreviewModelImpl; factory _ChatRoomPreviewModel.fromJson(Map json) = _$ChatRoomPreviewModelImpl.fromJson; @override @JsonKey(name: "chatRooms") - List get chatRooms; + ChatRooms get chatRooms; + @override + @JsonKey(name: "number_of_unread_chat_rooms") + int get unreadChatsCount; - /// Create a copy of ChatRoomPreviewModel + /// Create a copy of ChatRoomPaginationModel /// with the given fields replaced by the non-null parameter values. @override @JsonKey(includeFromJson: false, includeToJson: false) @@ -180,6 +217,218 @@ abstract class _ChatRoomPreviewModel implements ChatRoomPreviewModel { get copyWith => throw _privateConstructorUsedError; } +ChatRooms _$ChatRoomsFromJson(Map json) { + return _ChatRooms.fromJson(json); +} + +/// @nodoc +mixin _$ChatRooms { + @JsonKey(name: "data") + List get data => throw _privateConstructorUsedError; + @JsonKey(name: "last_page") + int get lastPage => throw _privateConstructorUsedError; + @JsonKey(name: "current_page") + int get currentPage => throw _privateConstructorUsedError; + + /// Serializes this ChatRooms to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of ChatRooms + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $ChatRoomsCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ChatRoomsCopyWith<$Res> { + factory $ChatRoomsCopyWith(ChatRooms value, $Res Function(ChatRooms) then) = + _$ChatRoomsCopyWithImpl<$Res, ChatRooms>; + @useResult + $Res call( + {@JsonKey(name: "data") List data, + @JsonKey(name: "last_page") int lastPage, + @JsonKey(name: "current_page") int currentPage}); +} + +/// @nodoc +class _$ChatRoomsCopyWithImpl<$Res, $Val extends ChatRooms> + implements $ChatRoomsCopyWith<$Res> { + _$ChatRoomsCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of ChatRooms + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? data = null, + Object? lastPage = null, + Object? currentPage = null, + }) { + return _then(_value.copyWith( + data: null == data + ? _value.data + : data // ignore: cast_nullable_to_non_nullable + as List, + lastPage: null == lastPage + ? _value.lastPage + : lastPage // ignore: cast_nullable_to_non_nullable + as int, + currentPage: null == currentPage + ? _value.currentPage + : currentPage // ignore: cast_nullable_to_non_nullable + as int, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$ChatRoomsImplCopyWith<$Res> + implements $ChatRoomsCopyWith<$Res> { + factory _$$ChatRoomsImplCopyWith( + _$ChatRoomsImpl value, $Res Function(_$ChatRoomsImpl) then) = + __$$ChatRoomsImplCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {@JsonKey(name: "data") List data, + @JsonKey(name: "last_page") int lastPage, + @JsonKey(name: "current_page") int currentPage}); +} + +/// @nodoc +class __$$ChatRoomsImplCopyWithImpl<$Res> + extends _$ChatRoomsCopyWithImpl<$Res, _$ChatRoomsImpl> + implements _$$ChatRoomsImplCopyWith<$Res> { + __$$ChatRoomsImplCopyWithImpl( + _$ChatRoomsImpl _value, $Res Function(_$ChatRoomsImpl) _then) + : super(_value, _then); + + /// Create a copy of ChatRooms + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? data = null, + Object? lastPage = null, + Object? currentPage = null, + }) { + return _then(_$ChatRoomsImpl( + data: null == data + ? _value._data + : data // ignore: cast_nullable_to_non_nullable + as List, + lastPage: null == lastPage + ? _value.lastPage + : lastPage // ignore: cast_nullable_to_non_nullable + as int, + currentPage: null == currentPage + ? _value.currentPage + : currentPage // ignore: cast_nullable_to_non_nullable + as int, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$ChatRoomsImpl implements _ChatRooms { + const _$ChatRoomsImpl( + {@JsonKey(name: "data") required final List data, + @JsonKey(name: "last_page") required this.lastPage, + @JsonKey(name: "current_page") required this.currentPage}) + : _data = data; + + factory _$ChatRoomsImpl.fromJson(Map json) => + _$$ChatRoomsImplFromJson(json); + + final List _data; + @override + @JsonKey(name: "data") + List get data { + if (_data is EqualUnmodifiableListView) return _data; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_data); + } + + @override + @JsonKey(name: "last_page") + final int lastPage; + @override + @JsonKey(name: "current_page") + final int currentPage; + + @override + String toString() { + return 'ChatRooms(data: $data, lastPage: $lastPage, currentPage: $currentPage)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ChatRoomsImpl && + const DeepCollectionEquality().equals(other._data, _data) && + (identical(other.lastPage, lastPage) || + other.lastPage == lastPage) && + (identical(other.currentPage, currentPage) || + other.currentPage == currentPage)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash(runtimeType, + const DeepCollectionEquality().hash(_data), lastPage, currentPage); + + /// Create a copy of ChatRooms + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ChatRoomsImplCopyWith<_$ChatRoomsImpl> get copyWith => + __$$ChatRoomsImplCopyWithImpl<_$ChatRoomsImpl>(this, _$identity); + + @override + Map toJson() { + return _$$ChatRoomsImplToJson( + this, + ); + } +} + +abstract class _ChatRooms implements ChatRooms { + const factory _ChatRooms( + {@JsonKey(name: "data") required final List data, + @JsonKey(name: "last_page") required final int lastPage, + @JsonKey(name: "current_page") required final int currentPage}) = + _$ChatRoomsImpl; + + factory _ChatRooms.fromJson(Map json) = + _$ChatRoomsImpl.fromJson; + + @override + @JsonKey(name: "data") + List get data; + @override + @JsonKey(name: "last_page") + int get lastPage; + @override + @JsonKey(name: "current_page") + int get currentPage; + + /// Create a copy of ChatRooms + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ChatRoomsImplCopyWith<_$ChatRoomsImpl> get copyWith => + throw _privateConstructorUsedError; +} + ChatRoom _$ChatRoomFromJson(Map json) { return _ChatRoom.fromJson(json); } diff --git a/lib/features/chat/models/chat_room_preview_model.g.dart b/lib/features/chat/models/chat_room_pagination_model.g.dart similarity index 76% rename from lib/features/chat/models/chat_room_preview_model.g.dart rename to lib/features/chat/models/chat_room_pagination_model.g.dart index ad812d46..3b9ac87b 100644 --- a/lib/features/chat/models/chat_room_preview_model.g.dart +++ b/lib/features/chat/models/chat_room_pagination_model.g.dart @@ -1,6 +1,6 @@ // GENERATED CODE - DO NOT MODIFY BY HAND -part of 'chat_room_preview_model.dart'; +part of 'chat_room_pagination_model.dart'; // ************************************************************************** // JsonSerializableGenerator @@ -9,15 +9,31 @@ part of 'chat_room_preview_model.dart'; _$ChatRoomPreviewModelImpl _$$ChatRoomPreviewModelImplFromJson( Map json) => _$ChatRoomPreviewModelImpl( - chatRooms: (json['chatRooms'] as List) - .map((e) => ChatRoom.fromJson(e as Map)) - .toList(), + chatRooms: ChatRooms.fromJson(json['chatRooms'] as Map), + unreadChatsCount: (json['number_of_unread_chat_rooms'] as num).toInt(), ); Map _$$ChatRoomPreviewModelImplToJson( _$ChatRoomPreviewModelImpl instance) => { 'chatRooms': instance.chatRooms, + 'number_of_unread_chat_rooms': instance.unreadChatsCount, + }; + +_$ChatRoomsImpl _$$ChatRoomsImplFromJson(Map json) => + _$ChatRoomsImpl( + data: (json['data'] as List) + .map((e) => ChatRoom.fromJson(e as Map)) + .toList(), + lastPage: (json['last_page'] as num).toInt(), + currentPage: (json['current_page'] as num).toInt(), + ); + +Map _$$ChatRoomsImplToJson(_$ChatRoomsImpl instance) => + { + 'data': instance.data, + 'last_page': instance.lastPage, + 'current_page': instance.currentPage, }; _$ChatRoomImpl _$$ChatRoomImplFromJson(Map json) => diff --git a/lib/features/chat/presentation/bloc/chat_room_cubit/chat_room_cubit.dart b/lib/features/chat/presentation/bloc/chat_room_cubit/chat_room_cubit.dart index a7f94802..3ba4422c 100644 --- a/lib/features/chat/presentation/bloc/chat_room_cubit/chat_room_cubit.dart +++ b/lib/features/chat/presentation/bloc/chat_room_cubit/chat_room_cubit.dart @@ -86,6 +86,17 @@ class ChatRoomCubit extends Cubit { } } + Future updateChatRoom(String chatId) async{ + try { + final chatRoom = await chatRepository.getChatRoom(chatId); + emit( + (state as ChatRoomStateLoaded).copyWith(chatRoom: chatRoom), + ); + } catch (e) { + emit(ChatRoomState.error(errorMessage: 'Ошибка получеия данных')); + } + } + Future _subscribeToChatChannel({ required String chatId, }) async { diff --git a/lib/features/chat/presentation/bloc/chats_cubit/chats_cubit.dart b/lib/features/chat/presentation/bloc/chats_cubit/chats_cubit.dart index f165ca83..a4f0bbf2 100644 --- a/lib/features/chat/presentation/bloc/chats_cubit/chats_cubit.dart +++ b/lib/features/chat/presentation/bloc/chats_cubit/chats_cubit.dart @@ -1,5 +1,6 @@ import 'dart:async'; import 'dart:convert'; +import 'dart:developer'; import 'package:eatvio_app/core/enums/base_state.dart'; import 'package:eatvio_app/core/websockets/ws_manager.dart'; @@ -30,21 +31,24 @@ class ChatsCubit extends Cubit { }); } String? _query; + int page = 1; + late int lastPage; Future getChatRoomsWithLoading({String? query}) async { + page = 1; _query = query; emit(state.copyWith(state: BaseState.loading)); try { - final chatRooms = await chatRepository.getChatRoomPreviews(query: query); - final unreadChats = chatRooms.where( - (element) => element.unreadMessagesCount > 0, - ); + final chatRoomsPaginationModel = await chatRepository.getChatRooms(query: query); + final unreadChats = chatRoomsPaginationModel.unreadChatsCount; + lastPage = chatRoomsPaginationModel.chatRooms.lastPage + 1; emit( state.copyWith( - chatRooms: chatRooms, - chatsWithUnreadMessagesCount: unreadChats.length, + chatRooms: chatRoomsPaginationModel.chatRooms.data, + chatsWithUnreadMessagesCount: unreadChats, state: BaseState.success, ), ); + page++; } catch (e) { emit( state.copyWith(errorMessage: e.toString(), state: BaseState.error), @@ -53,26 +57,55 @@ class ChatsCubit extends Cubit { } Future getChatRooms({String? query}) async { + page = 1; _query = query; try { - final chatRooms = await chatRepository.getChatRoomPreviews(query: query); - final unreadChats = chatRooms.where( - (element) => element.unreadMessagesCount > 0, - ); + final chatRoomsPaginationModel = await chatRepository.getChatRooms(query: query); + final unreadChats = chatRoomsPaginationModel.unreadChatsCount; + lastPage = chatRoomsPaginationModel.chatRooms.lastPage + 1; emit( state.copyWith( - chatRooms: chatRooms, - chatsWithUnreadMessagesCount: unreadChats.length, + chatRooms: chatRoomsPaginationModel.chatRooms.data, + chatsWithUnreadMessagesCount: unreadChats, state: BaseState.success, ), ); - } catch (e) { + page++; + } catch (e, st) { + log(e.toString(), stackTrace: st); emit( state.copyWith(errorMessage: e.toString(), state: BaseState.error), ); } } + Future loadMoreChatRooms() async { + try { + if (state.isLoadingMoreChats || lastPage == page) return; + emit(state.copyWith(isLoadingMoreChats: true)); + final chatRoomsPaginationModel = await chatRepository.getChatRooms(query: _query, page: page); + final unreadChats = chatRoomsPaginationModel.unreadChatsCount; + emit( + state.copyWith( + chatRooms: [...state.chatRooms, ...chatRoomsPaginationModel.chatRooms.data], + chatsWithUnreadMessagesCount: unreadChats, + state: BaseState.success, + isLoadingMoreChats: false, + ), + ); + page++; + } catch (e, st) { + log(e.toString(), stackTrace: st); + emit( + state.copyWith( + errorMessage: e.toString(), + state: BaseState.error, + isLoadingMoreChats: false, + ), + ); + } + } + void reduceUnreadMessagesCount({required String chatId, required int count}) { bool isChatRead = false; final updatedChatRooms = state.chatRooms.map((room) { diff --git a/lib/features/chat/presentation/bloc/chats_cubit/chats_state.dart b/lib/features/chat/presentation/bloc/chats_cubit/chats_state.dart index 24bde4fa..700542d0 100644 --- a/lib/features/chat/presentation/bloc/chats_cubit/chats_state.dart +++ b/lib/features/chat/presentation/bloc/chats_cubit/chats_state.dart @@ -1,5 +1,5 @@ import 'package:eatvio_app/core/enums/base_state.dart'; -import 'package:eatvio_app/features/chat/models/chat_room_preview_model.dart'; +import 'package:eatvio_app/features/chat/models/chat_room_pagination_model.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; part 'chats_state.freezed.dart'; @@ -11,6 +11,7 @@ class ChatsState with _$ChatsState { @Default(BaseState.initial) BaseState state, @Default(0) int chatsWithUnreadMessagesCount, @Default([]) List chatRooms, + @Default(false) bool isLoadingMoreChats, @Default(null) String? errorMessage, }) = _ChatsState; diff --git a/lib/features/chat/presentation/bloc/chats_cubit/chats_state.freezed.dart b/lib/features/chat/presentation/bloc/chats_cubit/chats_state.freezed.dart index 77fd911d..a2271568 100644 --- a/lib/features/chat/presentation/bloc/chats_cubit/chats_state.freezed.dart +++ b/lib/features/chat/presentation/bloc/chats_cubit/chats_state.freezed.dart @@ -19,6 +19,7 @@ mixin _$ChatsState { BaseState get state => throw _privateConstructorUsedError; int get chatsWithUnreadMessagesCount => throw _privateConstructorUsedError; List get chatRooms => throw _privateConstructorUsedError; + bool get isLoadingMoreChats => throw _privateConstructorUsedError; String? get errorMessage => throw _privateConstructorUsedError; /// Create a copy of ChatsState @@ -38,6 +39,7 @@ abstract class $ChatsStateCopyWith<$Res> { {BaseState state, int chatsWithUnreadMessagesCount, List chatRooms, + bool isLoadingMoreChats, String? errorMessage}); } @@ -59,6 +61,7 @@ class _$ChatsStateCopyWithImpl<$Res, $Val extends ChatsState> Object? state = null, Object? chatsWithUnreadMessagesCount = null, Object? chatRooms = null, + Object? isLoadingMoreChats = null, Object? errorMessage = freezed, }) { return _then(_value.copyWith( @@ -74,6 +77,10 @@ class _$ChatsStateCopyWithImpl<$Res, $Val extends ChatsState> ? _value.chatRooms : chatRooms // ignore: cast_nullable_to_non_nullable as List, + isLoadingMoreChats: null == isLoadingMoreChats + ? _value.isLoadingMoreChats + : isLoadingMoreChats // ignore: cast_nullable_to_non_nullable + as bool, errorMessage: freezed == errorMessage ? _value.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable @@ -94,6 +101,7 @@ abstract class _$$ChatsStateImplCopyWith<$Res> {BaseState state, int chatsWithUnreadMessagesCount, List chatRooms, + bool isLoadingMoreChats, String? errorMessage}); } @@ -113,6 +121,7 @@ class __$$ChatsStateImplCopyWithImpl<$Res> Object? state = null, Object? chatsWithUnreadMessagesCount = null, Object? chatRooms = null, + Object? isLoadingMoreChats = null, Object? errorMessage = freezed, }) { return _then(_$ChatsStateImpl( @@ -128,6 +137,10 @@ class __$$ChatsStateImplCopyWithImpl<$Res> ? _value._chatRooms : chatRooms // ignore: cast_nullable_to_non_nullable as List, + isLoadingMoreChats: null == isLoadingMoreChats + ? _value.isLoadingMoreChats + : isLoadingMoreChats // ignore: cast_nullable_to_non_nullable + as bool, errorMessage: freezed == errorMessage ? _value.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable @@ -143,6 +156,7 @@ class _$ChatsStateImpl implements _ChatsState { {this.state = BaseState.initial, this.chatsWithUnreadMessagesCount = 0, final List chatRooms = const [], + this.isLoadingMoreChats = false, this.errorMessage = null}) : _chatRooms = chatRooms; @@ -161,13 +175,16 @@ class _$ChatsStateImpl implements _ChatsState { return EqualUnmodifiableListView(_chatRooms); } + @override + @JsonKey() + final bool isLoadingMoreChats; @override @JsonKey() final String? errorMessage; @override String toString() { - return 'ChatsState(state: $state, chatsWithUnreadMessagesCount: $chatsWithUnreadMessagesCount, chatRooms: $chatRooms, errorMessage: $errorMessage)'; + return 'ChatsState(state: $state, chatsWithUnreadMessagesCount: $chatsWithUnreadMessagesCount, chatRooms: $chatRooms, isLoadingMoreChats: $isLoadingMoreChats, errorMessage: $errorMessage)'; } @override @@ -182,6 +199,8 @@ class _$ChatsStateImpl implements _ChatsState { chatsWithUnreadMessagesCount) && const DeepCollectionEquality() .equals(other._chatRooms, _chatRooms) && + (identical(other.isLoadingMoreChats, isLoadingMoreChats) || + other.isLoadingMoreChats == isLoadingMoreChats) && (identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)); } @@ -192,6 +211,7 @@ class _$ChatsStateImpl implements _ChatsState { state, chatsWithUnreadMessagesCount, const DeepCollectionEquality().hash(_chatRooms), + isLoadingMoreChats, errorMessage); /// Create a copy of ChatsState @@ -208,6 +228,7 @@ abstract class _ChatsState implements ChatsState { {final BaseState state, final int chatsWithUnreadMessagesCount, final List chatRooms, + final bool isLoadingMoreChats, final String? errorMessage}) = _$ChatsStateImpl; @override @@ -217,6 +238,8 @@ abstract class _ChatsState implements ChatsState { @override List get chatRooms; @override + bool get isLoadingMoreChats; + @override String? get errorMessage; /// Create a copy of ChatsState diff --git a/lib/features/chat/presentation/pages/chat_screen.dart b/lib/features/chat/presentation/pages/chat_screen.dart index 4b2d8b94..1d0b8b0c 100644 --- a/lib/features/chat/presentation/pages/chat_screen.dart +++ b/lib/features/chat/presentation/pages/chat_screen.dart @@ -11,7 +11,6 @@ import 'package:eatvio_app/features/chat/presentation/widgets/chat_bubble_widget import 'package:eatvio_app/core/locator_service.dart'; import 'package:eatvio_app/core/theme/custom_text_style.dart'; import 'package:eatvio_app/core/theme/theme_helper.dart'; -import 'package:eatvio_app/features/chat/presentation/widgets/notification_banner.dart'; import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; diff --git a/lib/features/chat/presentation/pages/chats_screen.dart b/lib/features/chat/presentation/pages/chats_screen.dart index 18f2b581..75882083 100644 --- a/lib/features/chat/presentation/pages/chats_screen.dart +++ b/lib/features/chat/presentation/pages/chats_screen.dart @@ -1,5 +1,6 @@ import 'package:easy_debounce/easy_debounce.dart'; import 'package:eatvio_app/core/enums/base_state.dart'; +import 'package:eatvio_app/core/utils/pagination_utils.dart'; import 'package:eatvio_app/core/widgets/data_error_widget.dart'; import 'package:eatvio_app/core/widgets/loader.dart'; import 'package:eatvio_app/features/chat/presentation/bloc/chats_cubit/chats_cubit.dart'; @@ -16,7 +17,7 @@ class ChatsScreen extends StatefulWidget { State createState() => _ChatsScreenState(); } -class _ChatsScreenState extends State { +class _ChatsScreenState extends State { final searchController = TextEditingController(); Widget build(BuildContext context) { @@ -65,45 +66,40 @@ class _ChatsScreenState extends State { ), ]; }, - body: stateBuilder(state), + body: switch (state.state) { + BaseState.error => DataErrorWidget(onReload: () => context.read().getChatRooms()), + BaseState.success => _buildChatList(context, state), + _ => const Loader(), + }, ), ); }, ); } - stateBuilder(ChatsState state) { - if (state.state == BaseState.loading) { - return Scaffold( - body: const Loader(), - ); - } else if (state.state == BaseState.success) { - return _buildChatList(context, state); - } else if (state.state == BaseState.error) { - return Scaffold( - body: DataErrorWidget(onReload: () => context.read().getChatRooms()), - ); - } else { - return Scaffold( - body: const Loader(), - ); - } - } - _buildChatList(BuildContext context, ChatsState state) { - return ListView.separated( - padding: EdgeInsets.all(16), - shrinkWrap: true, - physics: NeverScrollableScrollPhysics(), - separatorBuilder: (context, index) { - return SizedBox( - height: 8, - ); - }, - itemCount: state.chatRooms.length, - itemBuilder: (context, index) { - return ChatEntryWidget(chatRoom: state.chatRooms[index]); + return NotificationListener( + onNotification: (notification) { + loadNewContent(notification, context.read().loadMoreChatRooms); + return false; }, + child: ListView.separated( + padding: EdgeInsets.all(16), + shrinkWrap: true, + physics: NeverScrollableScrollPhysics(), + separatorBuilder: (context, index) { + return SizedBox( + height: 8, + ); + }, + itemCount: state.isLoadingMoreChats ? state.chatRooms.length + 1 : state.chatRooms.length, + itemBuilder: (context, index) { + if (index == state.chatRooms.length) { + return Center(child: Loader()); + } + return ChatEntryWidget(chatRoom: state.chatRooms[index]); + }, + ), ); } } diff --git a/lib/features/chat/presentation/widgets/chat_entry_widget.dart b/lib/features/chat/presentation/widgets/chat_entry_widget.dart index 66e0d700..4e1eea67 100644 --- a/lib/features/chat/presentation/widgets/chat_entry_widget.dart +++ b/lib/features/chat/presentation/widgets/chat_entry_widget.dart @@ -1,10 +1,8 @@ import 'package:eatvio_app/core/utils/date_time_utils.dart'; -import 'package:eatvio_app/features/chat/models/chat_room_preview_model.dart'; +import 'package:eatvio_app/features/chat/models/chat_room_pagination_model.dart'; import 'package:eatvio_app/core/theme/custom_text_style.dart'; import 'package:eatvio_app/core/theme/theme_helper.dart'; -import 'package:eatvio_app/features/chat/presentation/bloc/chats_cubit/chats_cubit.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:go_router/go_router.dart'; class ChatEntryWidget extends StatefulWidget { diff --git a/lib/features/chat/presentation/widgets/order_card.dart b/lib/features/chat/presentation/widgets/order_card.dart new file mode 100644 index 00000000..5f57f362 --- /dev/null +++ b/lib/features/chat/presentation/widgets/order_card.dart @@ -0,0 +1,20 @@ +import 'package:eatvio_app/features/feed/models/plan_pagination_model.dart'; +import 'package:flutter/material.dart'; + +class OrderCard extends StatelessWidget { + final PlanModel plan; + final bool isUserView; + const OrderCard({super.key, required this.plan, required this.isUserView}); + + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.only(top: 8, bottom: 12, left: 8, right: 8), + child: Column( + children: [ + + ], + ), + ); + } +} diff --git a/lib/features/chat/repositories/chat_repository.dart b/lib/features/chat/repositories/chat_repository.dart index 9458d9f5..bdc537f8 100644 --- a/lib/features/chat/repositories/chat_repository.dart +++ b/lib/features/chat/repositories/chat_repository.dart @@ -5,7 +5,7 @@ import 'package:dio/dio.dart'; import 'package:eatvio_app/features/chat/models/chat_message_model.dart'; import 'package:eatvio_app/features/chat/models/chat_messages_model.dart'; import 'package:eatvio_app/features/chat/models/chat_room_model.dart'; -import 'package:eatvio_app/features/chat/models/chat_room_preview_model.dart'; +import 'package:eatvio_app/features/chat/models/chat_room_pagination_model.dart'; import 'package:eatvio_app/features/chat/services/chat_service.dart'; import 'package:http_parser/http_parser.dart'; @@ -62,9 +62,9 @@ class ChatRepository { } } - Future> getChatRoomPreviews({String? query}) async { + Future getChatRooms({String? query, int page = 1}) async { try { - return (await chatService.getChatRoomPreviews(query: query)).chatRooms; + return (await chatService.getChatRooms(query: query, page: page)); } catch (e) { rethrow; } diff --git a/lib/features/chat/services/chat_service.dart b/lib/features/chat/services/chat_service.dart index 2eb2423f..65910a34 100644 --- a/lib/features/chat/services/chat_service.dart +++ b/lib/features/chat/services/chat_service.dart @@ -1,7 +1,7 @@ import 'package:dio/dio.dart'; import 'package:eatvio_app/features/chat/models/chat_messages_model.dart'; import 'package:eatvio_app/features/chat/models/chat_room_model.dart'; -import 'package:eatvio_app/features/chat/models/chat_room_preview_model.dart'; +import 'package:eatvio_app/features/chat/models/chat_room_pagination_model.dart'; import 'package:retrofit/retrofit.dart'; part 'chat_service.g.dart'; @@ -11,7 +11,8 @@ abstract class ChatService { factory ChatService(Dio dio, {String baseUrl}) = _ChatService; @GET('/api/chat/index') - Future getChatRoomPreviews({ + Future getChatRooms({ + @Query('page') required int page, @Query('find') String? query, }); diff --git a/lib/features/chat/services/chat_service.g.dart b/lib/features/chat/services/chat_service.g.dart index 4cd570df..69a70741 100644 --- a/lib/features/chat/services/chat_service.g.dart +++ b/lib/features/chat/services/chat_service.g.dart @@ -18,13 +18,16 @@ class _ChatService implements ChatService { final ParseErrorLogger? errorLogger; @override - Future getChatRoomPreviews({String? query}) async { + Future getChatRooms({ + required int page, + String? query, + }) async { final _extra = {}; - final queryParameters = {r'find': query}; + final queryParameters = {r'page': page, r'find': query}; queryParameters.removeWhere((k, v) => v == null); final _headers = {}; const Map? _data = null; - final _options = _setStreamType( + final _options = _setStreamType( Options(method: 'GET', headers: _headers, extra: _extra) .compose( _dio.options, @@ -35,9 +38,9 @@ class _ChatService implements ChatService { .copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)), ); final _result = await _dio.fetch>(_options); - late ChatRoomPreviewModel _value; + late ChatRoomPaginationModel _value; try { - _value = ChatRoomPreviewModel.fromJson(_result.data!); + _value = ChatRoomPaginationModel.fromJson(_result.data!); } on Object catch (e, s) { errorLogger?.logError(e, s, _options); rethrow; diff --git a/lib/features/dev_tools/test_cases.dart b/lib/features/dev_tools/test_cases.dart index 8c92a104..39e563f5 100644 --- a/lib/features/dev_tools/test_cases.dart +++ b/lib/features/dev_tools/test_cases.dart @@ -125,10 +125,10 @@ class GetChatRoomPreviews implements TestCases { Future run({required String baseUrl}) async { try { // get all of needed services - final dio = sl(); - final chatService = ChatService(dio, baseUrl: baseUrl); + // final dio = sl(); + // final chatService = ChatService(dio, baseUrl: baseUrl); - await chatService.getChatRoomPreviews(); + // await chatService.getChatRooms(); return true; } catch (e) { return false; @@ -143,11 +143,11 @@ class GetChatRoom implements TestCases { @override Future run({required String baseUrl}) async { try { - final dio = sl(); - final chatService = ChatService(dio, baseUrl: baseUrl); + // final dio = sl(); + // final chatService = ChatService(dio, baseUrl: baseUrl); - final chatRoomsModels = await chatService.getChatRoomPreviews(); - await chatService.getChatRoom(id: chatRoomsModels.chatRooms.firstOrNull?.id ?? ''); + // final chatRoomsModels = await chatService.getChatRoomPreviews(); + // await chatService.getChatRoom(id: chatRoomsModels.chatRooms.firstOrNull?.id ?? ''); return true; } catch (e) { return false; @@ -162,11 +162,11 @@ class SendMessage implements TestCases { @override Future run({required String baseUrl}) async { try { - final dio = sl(); - final chatService = ChatService(dio, baseUrl: baseUrl); + // final dio = sl(); + // final chatService = ChatService(dio, baseUrl: baseUrl); - final chatRoomsModels = await chatService.getChatRoomPreviews(); - await chatService.sendMessage(id: chatRoomsModels.chatRooms.firstOrNull?.id ?? '', data: 'test message'); + // final chatRoomsModels = await chatService.getChatRoomPreviews(); + // await chatService.sendMessage(id: chatRoomsModels.chatRooms.firstOrNull?.id ?? '', data: 'test message'); return true; } catch (e) { return false; @@ -181,11 +181,11 @@ class GetChatMessages implements TestCases { @override Future run({required String baseUrl}) async { try { - final dio = sl(); - final chatService = ChatService(dio, baseUrl: baseUrl); + // final dio = sl(); + // final chatService = ChatService(dio, baseUrl: baseUrl); - final chatRoomsModels = await chatService.getChatRoomPreviews(); - await chatService.getChatMessages(id: chatRoomsModels.chatRooms.firstOrNull?.id ?? '', page: 1); + // final chatRoomsModels = await chatService.getChatRoomPreviews(); + // await chatService.getChatMessages(id: chatRoomsModels.chatRooms.firstOrNull?.id ?? '', page: 1); return true; } catch (e) { return false; diff --git a/lib/features/feed/presentation/bloc/diets_cubit/diets_cubit.dart b/lib/features/feed/presentation/bloc/diets_cubit/diets_cubit.dart index 1770e23d..84da2f34 100644 --- a/lib/features/feed/presentation/bloc/diets_cubit/diets_cubit.dart +++ b/lib/features/feed/presentation/bloc/diets_cubit/diets_cubit.dart @@ -115,7 +115,7 @@ class DietsCubit extends Cubit { } } - loadNextPage() async { + Future loadNextPage() async { if (currentPage < lastPage && !isLoading) { isLoading = true; diff --git a/lib/features/feed/presentation/bloc/feed_cubit/feed_cubit.dart b/lib/features/feed/presentation/bloc/feed_cubit/feed_cubit.dart index 2af91d22..51552e2b 100644 --- a/lib/features/feed/presentation/bloc/feed_cubit/feed_cubit.dart +++ b/lib/features/feed/presentation/bloc/feed_cubit/feed_cubit.dart @@ -47,7 +47,7 @@ class FeedCubit extends Cubit { } } - loadNextPage() async { + Future loadNextPage() async { if (currentPage < lastPage && !isLoading) { isLoading = true; diff --git a/lib/features/feed/presentation/bloc/plans_cubit/plans_cubit.dart b/lib/features/feed/presentation/bloc/plans_cubit/plans_cubit.dart index 69c0f2ee..10d6addb 100644 --- a/lib/features/feed/presentation/bloc/plans_cubit/plans_cubit.dart +++ b/lib/features/feed/presentation/bloc/plans_cubit/plans_cubit.dart @@ -174,7 +174,7 @@ class PlansCubit extends Cubit { } } - loadNextPage() async { + Future loadNextPage() async { if (currentPage < lastPage && !isLoading) { isLoading = true; diff --git a/lib/features/feed/presentation/bloc/recipes_cubit/recipes_cubit.dart b/lib/features/feed/presentation/bloc/recipes_cubit/recipes_cubit.dart index 0144fc00..1eb1027f 100644 --- a/lib/features/feed/presentation/bloc/recipes_cubit/recipes_cubit.dart +++ b/lib/features/feed/presentation/bloc/recipes_cubit/recipes_cubit.dart @@ -67,7 +67,7 @@ class RecipesCubit extends Cubit { } } - loadNextPage() async { + Future loadNextPage() async { if (currentPage < lastPage && !isLoading) { isLoading = true; diff --git a/lib/features/feed/presentation/pages/feed_screen.dart b/lib/features/feed/presentation/pages/feed_screen.dart index faf90370..e139da56 100644 --- a/lib/features/feed/presentation/pages/feed_screen.dart +++ b/lib/features/feed/presentation/pages/feed_screen.dart @@ -77,38 +77,12 @@ class _FeedScreenContentState extends State { final consultantsScrollController = ScrollController(); @override - void initState() { - blogPostsScrollController.addListener(_onScrollBlogPosts); - recipesScrollController.addListener(_onScrollRecipes); - dietsScrollController.addListener(_onScrollDiets); - plansScrollController.addListener(_onScrollPlans); + void initState() { consultantsScrollController.addListener(_onScrollConsultants); super.initState(); - } + } - _onScrollBlogPosts() { - if (blogPostsScrollController.offset >= blogPostsScrollController.position.maxScrollExtent && !blogPostsScrollController.position.outOfRange) { - context.read().loadNextPage(); - } - } - _onScrollRecipes() { - if (recipesScrollController.offset >= recipesScrollController.position.maxScrollExtent && !recipesScrollController.position.outOfRange) { - context.read().loadNextPage(); - } - } - - _onScrollDiets() { - if (dietsScrollController.offset >= dietsScrollController.position.maxScrollExtent && !dietsScrollController.position.outOfRange) { - context.read().loadNextPage(); - } - } - - _onScrollPlans() { - if (plansScrollController.offset >= plansScrollController.position.maxScrollExtent && !plansScrollController.position.outOfRange) { - context.read().loadNextPage(); - } - } _onScrollConsultants() { if (consultantsScrollController.offset >= consultantsScrollController.position.maxScrollExtent && !consultantsScrollController.position.outOfRange) {} diff --git a/lib/features/feed/presentation/widgets/blog_posts.dart b/lib/features/feed/presentation/widgets/blog_posts.dart index da5363fe..fa77dcf9 100644 --- a/lib/features/feed/presentation/widgets/blog_posts.dart +++ b/lib/features/feed/presentation/widgets/blog_posts.dart @@ -1,3 +1,4 @@ +import 'package:eatvio_app/core/utils/pagination_utils.dart'; import 'package:eatvio_app/core/widgets/data_error_widget.dart'; import 'package:eatvio_app/core/widgets/loader.dart'; import 'package:eatvio_app/features/feed/presentation/bloc/feed_cubit/feed_cubit.dart'; @@ -16,20 +17,26 @@ class BlogPosts extends StatelessWidget { child: BlocBuilder( builder: (BuildContext context, FeedState state) { if (state is FeedStateLoaded) { - return ListView.separated( - padding: EdgeInsets.symmetric(vertical: 8), - shrinkWrap: true, - physics: BouncingScrollPhysics(), - itemBuilder: (context, index) { - if (index == state.feedBlogPostList.length) { - return const Loader(); - } - return BlogPostWidget(index: index); + return NotificationListener( + onNotification: (notification) { + loadNewContent(notification, context.read().loadNextPage); + return false; }, - separatorBuilder: (context, index) { - return SizedBox(height: 8); - }, - itemCount: state.isLoading ? state.feedBlogPostList.length + 1 : state.feedBlogPostList.length, + child: ListView.separated( + padding: EdgeInsets.symmetric(vertical: 8), + shrinkWrap: true, + physics: BouncingScrollPhysics(), + itemBuilder: (context, index) { + if (index == state.feedBlogPostList.length) { + return const Loader(); + } + return BlogPostWidget(index: index); + }, + separatorBuilder: (context, index) { + return SizedBox(height: 8); + }, + itemCount: state.isLoading ? state.feedBlogPostList.length + 1 : state.feedBlogPostList.length, + ), ); } else if (state is FeedStateError) { return DataErrorWidget( diff --git a/lib/features/feed/presentation/widgets/diets.dart b/lib/features/feed/presentation/widgets/diets.dart index 254a9567..405d6469 100644 --- a/lib/features/feed/presentation/widgets/diets.dart +++ b/lib/features/feed/presentation/widgets/diets.dart @@ -1,3 +1,4 @@ +import 'package:eatvio_app/core/utils/pagination_utils.dart'; import 'package:eatvio_app/core/widgets/data_error_widget.dart'; import 'package:eatvio_app/core/widgets/loader.dart'; import 'package:eatvio_app/features/feed/presentation/bloc/diets_cubit/diets_cubit.dart'; @@ -28,17 +29,23 @@ class Diets extends StatelessWidget { return Stack( children: [ SizedBox.expand(), - ListView.separated( - padding: EdgeInsets.symmetric(vertical: 8), - shrinkWrap: true, - physics: BouncingScrollPhysics(), - itemBuilder: (context, index) { - return DietsWidget(diet: state.dietsList[index], index: index); + NotificationListener( + onNotification: (notification) { + loadNewContent(notification, context.read().loadNextPage); + return false; }, - separatorBuilder: (context, index) { - return SizedBox(height: 8); - }, - itemCount: state.dietsList.length, + child: ListView.separated( + padding: EdgeInsets.symmetric(vertical: 8), + shrinkWrap: true, + physics: BouncingScrollPhysics(), + itemBuilder: (context, index) { + return DietsWidget(diet: state.dietsList[index], index: index); + }, + separatorBuilder: (context, index) { + return SizedBox(height: 8); + }, + itemCount: state.dietsList.length, + ), ), Positioned( right: 0, diff --git a/lib/features/feed/presentation/widgets/plans.dart b/lib/features/feed/presentation/widgets/plans.dart index cc3a1a63..e8d894a3 100644 --- a/lib/features/feed/presentation/widgets/plans.dart +++ b/lib/features/feed/presentation/widgets/plans.dart @@ -1,3 +1,4 @@ +import 'package:eatvio_app/core/utils/pagination_utils.dart'; import 'package:eatvio_app/core/widgets/data_error_widget.dart'; import 'package:eatvio_app/core/widgets/loader.dart'; import 'package:eatvio_app/features/feed/presentation/bloc/plans_cubit/plans_cubit.dart'; @@ -28,20 +29,26 @@ class Plans extends StatelessWidget { return Stack( children: [ SizedBox.expand(), - ListView.separated( - padding: EdgeInsets.symmetric(vertical: 8), - shrinkWrap: true, - physics: BouncingScrollPhysics(), - itemBuilder: (context, index) { - return PlanWidget( - plan: state.plans[index], - index: index, - ); + NotificationListener( + onNotification: (notification) { + loadNewContent(notification, context.read().loadNextPage); + return false; }, - separatorBuilder: (context, index) { - return SizedBox(height: 8); - }, - itemCount: state.plans.length, + child: ListView.separated( + padding: EdgeInsets.symmetric(vertical: 8), + shrinkWrap: true, + physics: BouncingScrollPhysics(), + itemBuilder: (context, index) { + return PlanWidget( + plan: state.plans[index], + index: index, + ); + }, + separatorBuilder: (context, index) { + return SizedBox(height: 8); + }, + itemCount: state.plans.length, + ), ), Positioned( right: 0, diff --git a/lib/features/feed/presentation/widgets/recipes.dart b/lib/features/feed/presentation/widgets/recipes.dart index b75d50ee..d62f2320 100644 --- a/lib/features/feed/presentation/widgets/recipes.dart +++ b/lib/features/feed/presentation/widgets/recipes.dart @@ -1,3 +1,4 @@ +import 'package:eatvio_app/core/utils/pagination_utils.dart'; import 'package:eatvio_app/core/widgets/data_error_widget.dart'; import 'package:eatvio_app/core/widgets/loader.dart'; import 'package:eatvio_app/features/feed/presentation/bloc/recipes_cubit/recipes_cubit.dart'; @@ -29,20 +30,26 @@ class Recipes extends StatelessWidget { ); } - return ListView.separated( - padding: EdgeInsets.symmetric(vertical: 8), - shrinkWrap: true, - physics: BouncingScrollPhysics(), - itemBuilder: (context, index) { - return RecipesWidget( - recipe: state.recipesList[index], - index: index, - ); + return NotificationListener( + onNotification: (notification) { + loadNewContent(notification, context.read().loadNextPage); + return false; }, - separatorBuilder: (context, index) { - return SizedBox(height: 8); - }, - itemCount: state.recipesList.length, + child: ListView.separated( + padding: EdgeInsets.symmetric(vertical: 8), + shrinkWrap: true, + physics: BouncingScrollPhysics(), + itemBuilder: (context, index) { + return RecipesWidget( + recipe: state.recipesList[index], + index: index, + ); + }, + separatorBuilder: (context, index) { + return SizedBox(height: 8); + }, + itemCount: state.recipesList.length, + ), ); }, ), diff --git a/lib/features/plans/enums/chosen_plan_state_enum.dart b/lib/features/plans/enums/chosen_plan_state_enum.dart new file mode 100644 index 00000000..03016712 --- /dev/null +++ b/lib/features/plans/enums/chosen_plan_state_enum.dart @@ -0,0 +1,44 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +enum ChosenPlanStateEnum { + @JsonValue('initied') + stateInited, + @JsonValue('start_date_has_been_set') + stateStartDateHasBeenSet, + @JsonValue('in_coordination') + stateInCoordination, + @JsonValue('started') + stateStarted, + @JsonValue('in_progress') + stateInProgress, + @JsonValue('pending_payment') + statePendingPayment, + @JsonValue('confirmed_by_consultant') + stateConfirmedByConsultant, + @JsonValue('paid') + statePaid, + @JsonValue('canceled_by_the_initiator') + stateCanceledByTheInitiator, + @JsonValue('last_day_started') + stateLastDayStarted, + @JsonValue('last_day_finished') + stateLastDayFinished, + @JsonValue('complained') + stateComplained, + @JsonValue('done') + stateDone, + @JsonValue('charge_was_collected') + stateChargeWasCollected; + + static List getShowableChatBadgeStates() { + return [ + ChosenPlanStateEnum.stateInCoordination, + ChosenPlanStateEnum.stateStartDateHasBeenSet, + ChosenPlanStateEnum.statePendingPayment, + ChosenPlanStateEnum.statePaid, + ChosenPlanStateEnum.stateLastDayStarted, + ChosenPlanStateEnum.stateLastDayFinished, + ChosenPlanStateEnum.stateDone, + ]; + } +} diff --git a/lib/features/plans/models/chosen_plan_model.dart b/lib/features/plans/models/chosen_plan_model.dart index 525418b2..f42d6d80 100644 --- a/lib/features/plans/models/chosen_plan_model.dart +++ b/lib/features/plans/models/chosen_plan_model.dart @@ -1,4 +1,4 @@ -import 'package:eatvio_app/features/feed/models/plan_pagination_model.dart'; +import 'package:eatvio_app/features/plans/enums/chosen_plan_state_enum.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; part 'chosen_plan_model.freezed.dart'; @@ -11,8 +11,8 @@ class ChosenPlanModel with _$ChosenPlanModel { @JsonKey() required int id, @JsonKey(name: 'option_type') required String optionType, @JsonKey(name: 'start_date') required DateTime startDate, + @JsonKey(name: 'last_state') required ChosenPlanStateEnum chosenPlanState, @JsonKey(name: 'chat_id') required String chatId, - @JsonKey(name: 'plan') required PlanModel plan, }) = _ChosenPlanModel; diff --git a/lib/features/plans/models/chosen_plan_model.freezed.dart b/lib/features/plans/models/chosen_plan_model.freezed.dart index b26b04cd..3c7d7325 100644 --- a/lib/features/plans/models/chosen_plan_model.freezed.dart +++ b/lib/features/plans/models/chosen_plan_model.freezed.dart @@ -26,10 +26,10 @@ mixin _$ChosenPlanModel { String get optionType => throw _privateConstructorUsedError; @JsonKey(name: 'start_date') DateTime get startDate => throw _privateConstructorUsedError; + @JsonKey(name: 'last_state') + ChosenPlanStateEnum get chosenPlanState => throw _privateConstructorUsedError; @JsonKey(name: 'chat_id') String get chatId => throw _privateConstructorUsedError; - @JsonKey(name: 'plan') - PlanModel get plan => throw _privateConstructorUsedError; /// Serializes this ChosenPlanModel to a JSON map. Map toJson() => throw _privateConstructorUsedError; @@ -51,10 +51,8 @@ abstract class $ChosenPlanModelCopyWith<$Res> { {@JsonKey() int id, @JsonKey(name: 'option_type') String optionType, @JsonKey(name: 'start_date') DateTime startDate, - @JsonKey(name: 'chat_id') String chatId, - @JsonKey(name: 'plan') PlanModel plan}); - - $PlanModelCopyWith<$Res> get plan; + @JsonKey(name: 'last_state') ChosenPlanStateEnum chosenPlanState, + @JsonKey(name: 'chat_id') String chatId}); } /// @nodoc @@ -75,8 +73,8 @@ class _$ChosenPlanModelCopyWithImpl<$Res, $Val extends ChosenPlanModel> Object? id = null, Object? optionType = null, Object? startDate = null, + Object? chosenPlanState = null, Object? chatId = null, - Object? plan = null, }) { return _then(_value.copyWith( id: null == id @@ -91,26 +89,16 @@ class _$ChosenPlanModelCopyWithImpl<$Res, $Val extends ChosenPlanModel> ? _value.startDate : startDate // ignore: cast_nullable_to_non_nullable as DateTime, + chosenPlanState: null == chosenPlanState + ? _value.chosenPlanState + : chosenPlanState // ignore: cast_nullable_to_non_nullable + as ChosenPlanStateEnum, chatId: null == chatId ? _value.chatId : chatId // ignore: cast_nullable_to_non_nullable as String, - plan: null == plan - ? _value.plan - : plan // ignore: cast_nullable_to_non_nullable - as PlanModel, ) as $Val); } - - /// Create a copy of ChosenPlanModel - /// with the given fields replaced by the non-null parameter values. - @override - @pragma('vm:prefer-inline') - $PlanModelCopyWith<$Res> get plan { - return $PlanModelCopyWith<$Res>(_value.plan, (value) { - return _then(_value.copyWith(plan: value) as $Val); - }); - } } /// @nodoc @@ -125,11 +113,8 @@ abstract class _$$ChosenPlanModelImplCopyWith<$Res> {@JsonKey() int id, @JsonKey(name: 'option_type') String optionType, @JsonKey(name: 'start_date') DateTime startDate, - @JsonKey(name: 'chat_id') String chatId, - @JsonKey(name: 'plan') PlanModel plan}); - - @override - $PlanModelCopyWith<$Res> get plan; + @JsonKey(name: 'last_state') ChosenPlanStateEnum chosenPlanState, + @JsonKey(name: 'chat_id') String chatId}); } /// @nodoc @@ -148,8 +133,8 @@ class __$$ChosenPlanModelImplCopyWithImpl<$Res> Object? id = null, Object? optionType = null, Object? startDate = null, + Object? chosenPlanState = null, Object? chatId = null, - Object? plan = null, }) { return _then(_$ChosenPlanModelImpl( id: null == id @@ -164,14 +149,14 @@ class __$$ChosenPlanModelImplCopyWithImpl<$Res> ? _value.startDate : startDate // ignore: cast_nullable_to_non_nullable as DateTime, + chosenPlanState: null == chosenPlanState + ? _value.chosenPlanState + : chosenPlanState // ignore: cast_nullable_to_non_nullable + as ChosenPlanStateEnum, chatId: null == chatId ? _value.chatId : chatId // ignore: cast_nullable_to_non_nullable as String, - plan: null == plan - ? _value.plan - : plan // ignore: cast_nullable_to_non_nullable - as PlanModel, )); } } @@ -183,8 +168,8 @@ class _$ChosenPlanModelImpl implements _ChosenPlanModel { {@JsonKey() required this.id, @JsonKey(name: 'option_type') required this.optionType, @JsonKey(name: 'start_date') required this.startDate, - @JsonKey(name: 'chat_id') required this.chatId, - @JsonKey(name: 'plan') required this.plan}); + @JsonKey(name: 'last_state') required this.chosenPlanState, + @JsonKey(name: 'chat_id') required this.chatId}); factory _$ChosenPlanModelImpl.fromJson(Map json) => _$$ChosenPlanModelImplFromJson(json); @@ -199,15 +184,15 @@ class _$ChosenPlanModelImpl implements _ChosenPlanModel { @JsonKey(name: 'start_date') final DateTime startDate; @override + @JsonKey(name: 'last_state') + final ChosenPlanStateEnum chosenPlanState; + @override @JsonKey(name: 'chat_id') final String chatId; - @override - @JsonKey(name: 'plan') - final PlanModel plan; @override String toString() { - return 'ChosenPlanModel(id: $id, optionType: $optionType, startDate: $startDate, chatId: $chatId, plan: $plan)'; + return 'ChosenPlanModel(id: $id, optionType: $optionType, startDate: $startDate, chosenPlanState: $chosenPlanState, chatId: $chatId)'; } @override @@ -220,14 +205,15 @@ class _$ChosenPlanModelImpl implements _ChosenPlanModel { other.optionType == optionType) && (identical(other.startDate, startDate) || other.startDate == startDate) && - (identical(other.chatId, chatId) || other.chatId == chatId) && - (identical(other.plan, plan) || other.plan == plan)); + (identical(other.chosenPlanState, chosenPlanState) || + other.chosenPlanState == chosenPlanState) && + (identical(other.chatId, chatId) || other.chatId == chatId)); } @JsonKey(includeFromJson: false, includeToJson: false) @override - int get hashCode => - Object.hash(runtimeType, id, optionType, startDate, chatId, plan); + int get hashCode => Object.hash( + runtimeType, id, optionType, startDate, chosenPlanState, chatId); /// Create a copy of ChosenPlanModel /// with the given fields replaced by the non-null parameter values. @@ -251,8 +237,9 @@ abstract class _ChosenPlanModel implements ChosenPlanModel { {@JsonKey() required final int id, @JsonKey(name: 'option_type') required final String optionType, @JsonKey(name: 'start_date') required final DateTime startDate, - @JsonKey(name: 'chat_id') required final String chatId, - @JsonKey(name: 'plan') required final PlanModel plan}) = + @JsonKey(name: 'last_state') + required final ChosenPlanStateEnum chosenPlanState, + @JsonKey(name: 'chat_id') required final String chatId}) = _$ChosenPlanModelImpl; factory _ChosenPlanModel.fromJson(Map json) = @@ -268,11 +255,11 @@ abstract class _ChosenPlanModel implements ChosenPlanModel { @JsonKey(name: 'start_date') DateTime get startDate; @override + @JsonKey(name: 'last_state') + ChosenPlanStateEnum get chosenPlanState; + @override @JsonKey(name: 'chat_id') String get chatId; - @override - @JsonKey(name: 'plan') - PlanModel get plan; /// Create a copy of ChosenPlanModel /// with the given fields replaced by the non-null parameter values. diff --git a/lib/features/plans/models/chosen_plan_model.g.dart b/lib/features/plans/models/chosen_plan_model.g.dart index 52ecbdb7..7e64a4e4 100644 --- a/lib/features/plans/models/chosen_plan_model.g.dart +++ b/lib/features/plans/models/chosen_plan_model.g.dart @@ -12,8 +12,9 @@ _$ChosenPlanModelImpl _$$ChosenPlanModelImplFromJson( id: (json['id'] as num).toInt(), optionType: json['option_type'] as String, startDate: DateTime.parse(json['start_date'] as String), + chosenPlanState: + $enumDecode(_$ChosenPlanStateEnumEnumMap, json['last_state']), chatId: json['chat_id'] as String, - plan: PlanModel.fromJson(json['plan'] as Map), ); Map _$$ChosenPlanModelImplToJson( @@ -22,6 +23,23 @@ Map _$$ChosenPlanModelImplToJson( 'id': instance.id, 'option_type': instance.optionType, 'start_date': instance.startDate.toIso8601String(), + 'last_state': _$ChosenPlanStateEnumEnumMap[instance.chosenPlanState]!, 'chat_id': instance.chatId, - 'plan': instance.plan, }; + +const _$ChosenPlanStateEnumEnumMap = { + ChosenPlanStateEnum.stateInited: 'initied', + ChosenPlanStateEnum.stateStartDateHasBeenSet: 'start_date_has_been_set', + ChosenPlanStateEnum.stateInCoordination: 'in_coordination', + ChosenPlanStateEnum.stateStarted: 'started', + ChosenPlanStateEnum.stateInProgress: 'in_progress', + ChosenPlanStateEnum.statePendingPayment: 'pending_payment', + ChosenPlanStateEnum.stateConfirmedByConsultant: 'confirmed_by_consultant', + ChosenPlanStateEnum.statePaid: 'paid', + ChosenPlanStateEnum.stateCanceledByTheInitiator: 'canceled_by_the_initiator', + ChosenPlanStateEnum.stateLastDayStarted: 'last_day_started', + ChosenPlanStateEnum.stateLastDayFinished: 'last_day_finished', + ChosenPlanStateEnum.stateComplained: 'complained', + ChosenPlanStateEnum.stateDone: 'done', + ChosenPlanStateEnum.stateChargeWasCollected: 'charge_was_collected', +}; diff --git a/lib/features/profile/presentation/bloc/profile_cubit/profile_cubit.dart b/lib/features/profile/presentation/bloc/profile_cubit/profile_cubit.dart index 6b89e051..71fb1729 100644 --- a/lib/features/profile/presentation/bloc/profile_cubit/profile_cubit.dart +++ b/lib/features/profile/presentation/bloc/profile_cubit/profile_cubit.dart @@ -101,8 +101,9 @@ class ProfileCubit extends Cubit { }) async { try { return (await chatRepository.getChatRoomIdByUserSlug(slug: slug)).id; - } catch (e) { - rethrow; + } catch (e, st) { + log(e.toString(), stackTrace: st); + return ''; } } diff --git a/lib/features/profile/presentation/pages/profile_screen.dart b/lib/features/profile/presentation/pages/profile_screen.dart index 6d12aa9b..707eddfa 100644 --- a/lib/features/profile/presentation/pages/profile_screen.dart +++ b/lib/features/profile/presentation/pages/profile_screen.dart @@ -1079,7 +1079,9 @@ class _ProfileScreenState extends State { onTap: () async { GoRouter.of(context).pushNamed( 'chatScreen', - extra: await profileCubit.getChatRoomIdBySlug(slug: widget.author!.authorSlug), + extra: { + 'chatId': await profileCubit.getChatRoomIdBySlug(slug: widget.author!.authorSlug), + }, ); }, child: Container( diff --git a/lib/features/profile/presentation/widgets/sub_action_button_widget.dart b/lib/features/profile/presentation/widgets/sub_action_button_widget.dart index 0db41687..429d7176 100644 --- a/lib/features/profile/presentation/widgets/sub_action_button_widget.dart +++ b/lib/features/profile/presentation/widgets/sub_action_button_widget.dart @@ -62,8 +62,10 @@ class _SubActionButtonWidgetState extends State { return InkWell( onTap: () async { GoRouter.of(context).pushNamed( - 'chatScreen', - extra: await sl().getChatRoomIdBySlug(slug: widget.slug), + 'chatScreen', + extra: { + 'chatId': await sl().getChatRoomIdBySlug(slug: widget.slug), + }, ); }, borderRadius: BorderRadius.circular(8),