feat(order info): added order info screen

This commit is contained in:
Username1548
2025-04-04 20:21:31 +07:00
parent 9715f4cac9
commit 748484cf8f
387 changed files with 16171 additions and 18199 deletions

View File

@@ -7,12 +7,14 @@ import 'package:audioplayers/audioplayers.dart';
import 'package:dart_pusher_channels/dart_pusher_channels.dart';
import 'package:easy_debounce/easy_debounce.dart';
import 'package:eatvio_app/core/image_compressing/image_compress_utility.dart';
import 'package:eatvio_app/core/utils/date_time_utils.dart';
import 'package:eatvio_app/core/websockets/ws_manager.dart';
import 'package:eatvio_app/features/chat/models/chat_message_model.dart';
import 'package:eatvio_app/features/chat/presentation/bloc/chat_room_cubit/chat_room_state.dart';
import 'package:eatvio_app/features/chat/repositories/chat_repository.dart';
import 'package:eatvio_app/features/my_finance/models/card_model.dart';
import 'package:eatvio_app/features/my_finance/repositories/cards_repository.dart';
import 'package:eatvio_app/features/plans/enums/chosen_plan_state_enum.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class ChatRoomCubit extends Cubit<ChatRoomState> {
@@ -23,10 +25,10 @@ class ChatRoomCubit extends Cubit<ChatRoomState> {
StreamSubscription<ChannelReadEvent>? typingSubscription;
StreamSubscription<ChannelReadEvent>? messagesSubscription;
int currentPage = 1;
late final int lastPage;
late int lastPage;
bool isLoading = false;
ChatRoomCubit({required this.chatRepository, required this.wsManager, required this.cardsRepository}) : super(ChatRoomState.loading());
ChatRoomCubit({required this.chatRepository, required this.wsManager, required this.cardsRepository}) : super(const ChatRoomState.loading());
loadNextPage(String chatId) async {
if (currentPage < lastPage && !isLoading) {
@@ -47,7 +49,7 @@ class ChatRoomCubit extends Cubit<ChatRoomState> {
currentPage++;
} catch (e) {
emit(ChatRoomState.error(errorMessage: 'Ошибка получеия данных'));
emit(const ChatRoomState.error(errorMessage: 'Ошибка получеия данных'));
}
}
}
@@ -57,7 +59,7 @@ class ChatRoomCubit extends Cubit<ChatRoomState> {
final cards = await cardsRepository.getCards();
setCard(cards: cards);
} catch (e) {
emit(ChatRoomState.error(errorMessage: 'Ошибка получеия данных'));
emit(const ChatRoomState.error(errorMessage: 'Ошибка получеия данных'));
}
}
@@ -80,13 +82,29 @@ class ChatRoomCubit extends Cubit<ChatRoomState> {
await _subscribeToChatChannel(chatId: chatId);
emit(ChatRoomState.loaded(chatRoom: chatRoom, chatMessages: chatMessages.messagesList, isTyping: false, isLoading: isLoading, hasCard: false));
final cards = await cardsRepository.getCards();
setCard(cards: cards);
// final cards = await cardsRepository.getCards();
// setCard(cards: cards);
} catch (e) {
log(e.toString());
typingSubscription?.cancel();
messagesSubscription?.cancel();
wsManager.unsubscribeDirectChatChannel();
emit(ChatRoomState.error(errorMessage: 'Ошибка получеия данных'));
emit(const ChatRoomState.error(errorMessage: 'Ошибка получеия данных'));
}
}
Future<bool> choseStartPlanDate(DateTime date) async {
try {
if (state is! ChatRoomStateLoaded) return false;
final planId = (state as ChatRoomStateLoaded).chatRoom.chosenPlan?.id;
if (planId == null) return false;
final stringDate = date.format('yyyy-MM-dd');
await chatRepository.choseStartPlanDate(id: planId, date: {'start_date': stringDate});
emit((state as ChatRoomStateLoaded).copyWith.chatRoom.chosenPlan?.call(chosenPlanState: ChosenPlanStateEnum.stateStartDateHasBeenSet) ?? state);
return true;
} catch (e, st) {
log(e.toString(), stackTrace: st);
return false;
}
}
@@ -96,7 +114,7 @@ class ChatRoomCubit extends Cubit<ChatRoomState> {
final chatRoom = await chatRepository.getChatRoom(chatId);
emit((state as ChatRoomStateLoaded).copyWith(chatRoom: chatRoom));
} catch (e) {
emit(ChatRoomState.error(errorMessage: 'Ошибка получеия данных'));
emit(const ChatRoomState.error(errorMessage: 'Ошибка получеия данных'));
}
}
@@ -115,7 +133,7 @@ class ChatRoomCubit extends Cubit<ChatRoomState> {
typingSubscription = wsManager.clientTypingStream?.listen((event) {
emit((state as ChatRoomStateLoaded).copyWith(isTyping: true, isLoading: isLoading));
EasyDebounce.debounce('client-typing', Duration(seconds: 3), () => emit((state as ChatRoomStateLoaded).copyWith(isTyping: false, isLoading: isLoading)));
EasyDebounce.debounce('client-typing', const Duration(seconds: 3), () => emit((state as ChatRoomStateLoaded).copyWith(isTyping: false, isLoading: isLoading)));
});
}
@@ -136,9 +154,9 @@ class ChatRoomCubit extends Cubit<ChatRoomState> {
final ids = messagesIds.map((e) => e.id).toList();
await chatRepository.markMessagesAsRead(chatId, ids);
final currentMessages = [...(state as ChatRoomStateLoaded).chatMessages];
messagesIds.forEach((elem) {
for (var elem in messagesIds) {
currentMessages[elem.index] = currentMessages[elem.index].copyWith(isRead: true);
});
}
if (!isClosed) {
emit((state as ChatRoomStateLoaded).copyWith(chatMessages: currentMessages));
}
@@ -151,6 +169,18 @@ class ChatRoomCubit extends Cubit<ChatRoomState> {
}
}
Future<String?> getPaymentLink() async {
try {
final planId = (state as ChatRoomStateLoaded).chatRoom.chosenPlan?.id;
if (planId == null) return null;
final paymentModel = await chatRepository.getPaymentLink(id: planId);
return paymentModel.paymentUrl;
} catch (e, st) {
log(e.toString(), stackTrace: st);
return null;
}
}
@override
Future<void> close() async {
wsManager.unsubscribeDirectChatChannel();

View File

@@ -12,8 +12,7 @@ part of 'chat_room_state.dart';
T _$identity<T>(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',
);
'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');
/// @nodoc
mixin _$ChatRoomState {
@@ -22,58 +21,60 @@ mixin _$ChatRoomState {
TResult Function() $default, {
required TResult Function() loading,
required TResult Function(
ChatRoomModel chatRoom,
List<ChatMessageModel> chatMessages,
bool hasCard,
bool isTyping,
bool isLoading,
)
loaded,
ChatRoomModel chatRoom,
List<ChatMessageModel> chatMessages,
bool hasCard,
bool isTyping,
bool isLoading)
loaded,
required TResult Function(String errorMessage) error,
}) => throw _privateConstructorUsedError;
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>(
TResult? Function()? $default, {
TResult? Function()? loading,
TResult? Function(
ChatRoomModel chatRoom,
List<ChatMessageModel> chatMessages,
bool hasCard,
bool isTyping,
bool isLoading,
)?
loaded,
ChatRoomModel chatRoom,
List<ChatMessageModel> chatMessages,
bool hasCard,
bool isTyping,
bool isLoading)?
loaded,
TResult? Function(String errorMessage)? error,
}) => throw _privateConstructorUsedError;
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>(
TResult Function()? $default, {
TResult Function()? loading,
TResult Function(
ChatRoomModel chatRoom,
List<ChatMessageModel> chatMessages,
bool hasCard,
bool isTyping,
bool isLoading,
)?
loaded,
ChatRoomModel chatRoom,
List<ChatMessageModel> chatMessages,
bool hasCard,
bool isTyping,
bool isLoading)?
loaded,
TResult Function(String errorMessage)? error,
required TResult orElse(),
}) => throw _privateConstructorUsedError;
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult map<TResult extends Object?>(
TResult Function(_ChatRoomState value) $default, {
required TResult Function(ChatRoomStateLoading value) loading,
required TResult Function(ChatRoomStateLoaded value) loaded,
required TResult Function(ChatRoomStateError value) error,
}) => throw _privateConstructorUsedError;
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>(
TResult? Function(_ChatRoomState value)? $default, {
TResult? Function(ChatRoomStateLoading value)? loading,
TResult? Function(ChatRoomStateLoaded value)? loaded,
TResult? Function(ChatRoomStateError value)? error,
}) => throw _privateConstructorUsedError;
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>(
TResult Function(_ChatRoomState value)? $default, {
@@ -81,15 +82,15 @@ mixin _$ChatRoomState {
TResult Function(ChatRoomStateLoaded value)? loaded,
TResult Function(ChatRoomStateError value)? error,
required TResult orElse(),
}) => throw _privateConstructorUsedError;
}) =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $ChatRoomStateCopyWith<$Res> {
factory $ChatRoomStateCopyWith(
ChatRoomState value,
$Res Function(ChatRoomState) then,
) = _$ChatRoomStateCopyWithImpl<$Res, ChatRoomState>;
ChatRoomState value, $Res Function(ChatRoomState) then) =
_$ChatRoomStateCopyWithImpl<$Res, ChatRoomState>;
}
/// @nodoc
@@ -109,9 +110,8 @@ class _$ChatRoomStateCopyWithImpl<$Res, $Val extends ChatRoomState>
/// @nodoc
abstract class _$$ChatRoomStateImplCopyWith<$Res> {
factory _$$ChatRoomStateImplCopyWith(
_$ChatRoomStateImpl value,
$Res Function(_$ChatRoomStateImpl) then,
) = __$$ChatRoomStateImplCopyWithImpl<$Res>;
_$ChatRoomStateImpl value, $Res Function(_$ChatRoomStateImpl) then) =
__$$ChatRoomStateImplCopyWithImpl<$Res>;
}
/// @nodoc
@@ -119,9 +119,8 @@ class __$$ChatRoomStateImplCopyWithImpl<$Res>
extends _$ChatRoomStateCopyWithImpl<$Res, _$ChatRoomStateImpl>
implements _$$ChatRoomStateImplCopyWith<$Res> {
__$$ChatRoomStateImplCopyWithImpl(
_$ChatRoomStateImpl _value,
$Res Function(_$ChatRoomStateImpl) _then,
) : super(_value, _then);
_$ChatRoomStateImpl _value, $Res Function(_$ChatRoomStateImpl) _then)
: super(_value, _then);
/// Create a copy of ChatRoomState
/// with the given fields replaced by the non-null parameter values.
@@ -152,13 +151,12 @@ class _$ChatRoomStateImpl implements _ChatRoomState {
TResult Function() $default, {
required TResult Function() loading,
required TResult Function(
ChatRoomModel chatRoom,
List<ChatMessageModel> chatMessages,
bool hasCard,
bool isTyping,
bool isLoading,
)
loaded,
ChatRoomModel chatRoom,
List<ChatMessageModel> chatMessages,
bool hasCard,
bool isTyping,
bool isLoading)
loaded,
required TResult Function(String errorMessage) error,
}) {
return $default();
@@ -170,13 +168,12 @@ class _$ChatRoomStateImpl implements _ChatRoomState {
TResult? Function()? $default, {
TResult? Function()? loading,
TResult? Function(
ChatRoomModel chatRoom,
List<ChatMessageModel> chatMessages,
bool hasCard,
bool isTyping,
bool isLoading,
)?
loaded,
ChatRoomModel chatRoom,
List<ChatMessageModel> chatMessages,
bool hasCard,
bool isTyping,
bool isLoading)?
loaded,
TResult? Function(String errorMessage)? error,
}) {
return $default?.call();
@@ -188,13 +185,12 @@ class _$ChatRoomStateImpl implements _ChatRoomState {
TResult Function()? $default, {
TResult Function()? loading,
TResult Function(
ChatRoomModel chatRoom,
List<ChatMessageModel> chatMessages,
bool hasCard,
bool isTyping,
bool isLoading,
)?
loaded,
ChatRoomModel chatRoom,
List<ChatMessageModel> chatMessages,
bool hasCard,
bool isTyping,
bool isLoading)?
loaded,
TResult Function(String errorMessage)? error,
required TResult orElse(),
}) {
@@ -248,20 +244,18 @@ abstract class _ChatRoomState implements ChatRoomState {
/// @nodoc
abstract class _$$ChatRoomStateLoadingImplCopyWith<$Res> {
factory _$$ChatRoomStateLoadingImplCopyWith(
_$ChatRoomStateLoadingImpl value,
$Res Function(_$ChatRoomStateLoadingImpl) then,
) = __$$ChatRoomStateLoadingImplCopyWithImpl<$Res>;
factory _$$ChatRoomStateLoadingImplCopyWith(_$ChatRoomStateLoadingImpl value,
$Res Function(_$ChatRoomStateLoadingImpl) then) =
__$$ChatRoomStateLoadingImplCopyWithImpl<$Res>;
}
/// @nodoc
class __$$ChatRoomStateLoadingImplCopyWithImpl<$Res>
extends _$ChatRoomStateCopyWithImpl<$Res, _$ChatRoomStateLoadingImpl>
implements _$$ChatRoomStateLoadingImplCopyWith<$Res> {
__$$ChatRoomStateLoadingImplCopyWithImpl(
_$ChatRoomStateLoadingImpl _value,
$Res Function(_$ChatRoomStateLoadingImpl) _then,
) : super(_value, _then);
__$$ChatRoomStateLoadingImplCopyWithImpl(_$ChatRoomStateLoadingImpl _value,
$Res Function(_$ChatRoomStateLoadingImpl) _then)
: super(_value, _then);
/// Create a copy of ChatRoomState
/// with the given fields replaced by the non-null parameter values.
@@ -293,13 +287,12 @@ class _$ChatRoomStateLoadingImpl implements ChatRoomStateLoading {
TResult Function() $default, {
required TResult Function() loading,
required TResult Function(
ChatRoomModel chatRoom,
List<ChatMessageModel> chatMessages,
bool hasCard,
bool isTyping,
bool isLoading,
)
loaded,
ChatRoomModel chatRoom,
List<ChatMessageModel> chatMessages,
bool hasCard,
bool isTyping,
bool isLoading)
loaded,
required TResult Function(String errorMessage) error,
}) {
return loading();
@@ -311,13 +304,12 @@ class _$ChatRoomStateLoadingImpl implements ChatRoomStateLoading {
TResult? Function()? $default, {
TResult? Function()? loading,
TResult? Function(
ChatRoomModel chatRoom,
List<ChatMessageModel> chatMessages,
bool hasCard,
bool isTyping,
bool isLoading,
)?
loaded,
ChatRoomModel chatRoom,
List<ChatMessageModel> chatMessages,
bool hasCard,
bool isTyping,
bool isLoading)?
loaded,
TResult? Function(String errorMessage)? error,
}) {
return loading?.call();
@@ -329,13 +321,12 @@ class _$ChatRoomStateLoadingImpl implements ChatRoomStateLoading {
TResult Function()? $default, {
TResult Function()? loading,
TResult Function(
ChatRoomModel chatRoom,
List<ChatMessageModel> chatMessages,
bool hasCard,
bool isTyping,
bool isLoading,
)?
loaded,
ChatRoomModel chatRoom,
List<ChatMessageModel> chatMessages,
bool hasCard,
bool isTyping,
bool isLoading)?
loaded,
TResult Function(String errorMessage)? error,
required TResult orElse(),
}) {
@@ -389,18 +380,16 @@ abstract class ChatRoomStateLoading implements ChatRoomState {
/// @nodoc
abstract class _$$ChatRoomStateLoadedImplCopyWith<$Res> {
factory _$$ChatRoomStateLoadedImplCopyWith(
_$ChatRoomStateLoadedImpl value,
$Res Function(_$ChatRoomStateLoadedImpl) then,
) = __$$ChatRoomStateLoadedImplCopyWithImpl<$Res>;
factory _$$ChatRoomStateLoadedImplCopyWith(_$ChatRoomStateLoadedImpl value,
$Res Function(_$ChatRoomStateLoadedImpl) then) =
__$$ChatRoomStateLoadedImplCopyWithImpl<$Res>;
@useResult
$Res call({
ChatRoomModel chatRoom,
List<ChatMessageModel> chatMessages,
bool hasCard,
bool isTyping,
bool isLoading,
});
$Res call(
{ChatRoomModel chatRoom,
List<ChatMessageModel> chatMessages,
bool hasCard,
bool isTyping,
bool isLoading});
$ChatRoomModelCopyWith<$Res> get chatRoom;
}
@@ -409,10 +398,9 @@ abstract class _$$ChatRoomStateLoadedImplCopyWith<$Res> {
class __$$ChatRoomStateLoadedImplCopyWithImpl<$Res>
extends _$ChatRoomStateCopyWithImpl<$Res, _$ChatRoomStateLoadedImpl>
implements _$$ChatRoomStateLoadedImplCopyWith<$Res> {
__$$ChatRoomStateLoadedImplCopyWithImpl(
_$ChatRoomStateLoadedImpl _value,
$Res Function(_$ChatRoomStateLoadedImpl) _then,
) : super(_value, _then);
__$$ChatRoomStateLoadedImplCopyWithImpl(_$ChatRoomStateLoadedImpl _value,
$Res Function(_$ChatRoomStateLoadedImpl) _then)
: super(_value, _then);
/// Create a copy of ChatRoomState
/// with the given fields replaced by the non-null parameter values.
@@ -425,35 +413,28 @@ class __$$ChatRoomStateLoadedImplCopyWithImpl<$Res>
Object? isTyping = null,
Object? isLoading = null,
}) {
return _then(
_$ChatRoomStateLoadedImpl(
chatRoom:
null == chatRoom
? _value.chatRoom
: chatRoom // ignore: cast_nullable_to_non_nullable
as ChatRoomModel,
chatMessages:
null == chatMessages
? _value._chatMessages
: chatMessages // ignore: cast_nullable_to_non_nullable
as List<ChatMessageModel>,
hasCard:
null == hasCard
? _value.hasCard
: hasCard // ignore: cast_nullable_to_non_nullable
as bool,
isTyping:
null == isTyping
? _value.isTyping
: isTyping // ignore: cast_nullable_to_non_nullable
as bool,
isLoading:
null == isLoading
? _value.isLoading
: isLoading // ignore: cast_nullable_to_non_nullable
as bool,
),
);
return _then(_$ChatRoomStateLoadedImpl(
chatRoom: null == chatRoom
? _value.chatRoom
: chatRoom // ignore: cast_nullable_to_non_nullable
as ChatRoomModel,
chatMessages: null == chatMessages
? _value._chatMessages
: chatMessages // ignore: cast_nullable_to_non_nullable
as List<ChatMessageModel>,
hasCard: null == hasCard
? _value.hasCard
: hasCard // ignore: cast_nullable_to_non_nullable
as bool,
isTyping: null == isTyping
? _value.isTyping
: isTyping // ignore: cast_nullable_to_non_nullable
as bool,
isLoading: null == isLoading
? _value.isLoading
: isLoading // ignore: cast_nullable_to_non_nullable
as bool,
));
}
/// Create a copy of ChatRoomState
@@ -470,13 +451,13 @@ class __$$ChatRoomStateLoadedImplCopyWithImpl<$Res>
/// @nodoc
class _$ChatRoomStateLoadedImpl implements ChatRoomStateLoaded {
const _$ChatRoomStateLoadedImpl({
required this.chatRoom,
required final List<ChatMessageModel> chatMessages,
required this.hasCard,
required this.isTyping,
required this.isLoading,
}) : _chatMessages = chatMessages;
const _$ChatRoomStateLoadedImpl(
{required this.chatRoom,
required final List<ChatMessageModel> chatMessages,
required this.hasCard,
required this.isTyping,
required this.isLoading})
: _chatMessages = chatMessages;
@override
final ChatRoomModel chatRoom;
@@ -507,10 +488,8 @@ class _$ChatRoomStateLoadedImpl implements ChatRoomStateLoaded {
other is _$ChatRoomStateLoadedImpl &&
(identical(other.chatRoom, chatRoom) ||
other.chatRoom == chatRoom) &&
const DeepCollectionEquality().equals(
other._chatMessages,
_chatMessages,
) &&
const DeepCollectionEquality()
.equals(other._chatMessages, _chatMessages) &&
(identical(other.hasCard, hasCard) || other.hasCard == hasCard) &&
(identical(other.isTyping, isTyping) ||
other.isTyping == isTyping) &&
@@ -520,13 +499,12 @@ class _$ChatRoomStateLoadedImpl implements ChatRoomStateLoaded {
@override
int get hashCode => Object.hash(
runtimeType,
chatRoom,
const DeepCollectionEquality().hash(_chatMessages),
hasCard,
isTyping,
isLoading,
);
runtimeType,
chatRoom,
const DeepCollectionEquality().hash(_chatMessages),
hasCard,
isTyping,
isLoading);
/// Create a copy of ChatRoomState
/// with the given fields replaced by the non-null parameter values.
@@ -535,9 +513,7 @@ class _$ChatRoomStateLoadedImpl implements ChatRoomStateLoaded {
@pragma('vm:prefer-inline')
_$$ChatRoomStateLoadedImplCopyWith<_$ChatRoomStateLoadedImpl> get copyWith =>
__$$ChatRoomStateLoadedImplCopyWithImpl<_$ChatRoomStateLoadedImpl>(
this,
_$identity,
);
this, _$identity);
@override
@optionalTypeArgs
@@ -545,13 +521,12 @@ class _$ChatRoomStateLoadedImpl implements ChatRoomStateLoaded {
TResult Function() $default, {
required TResult Function() loading,
required TResult Function(
ChatRoomModel chatRoom,
List<ChatMessageModel> chatMessages,
bool hasCard,
bool isTyping,
bool isLoading,
)
loaded,
ChatRoomModel chatRoom,
List<ChatMessageModel> chatMessages,
bool hasCard,
bool isTyping,
bool isLoading)
loaded,
required TResult Function(String errorMessage) error,
}) {
return loaded(chatRoom, chatMessages, hasCard, isTyping, isLoading);
@@ -563,13 +538,12 @@ class _$ChatRoomStateLoadedImpl implements ChatRoomStateLoaded {
TResult? Function()? $default, {
TResult? Function()? loading,
TResult? Function(
ChatRoomModel chatRoom,
List<ChatMessageModel> chatMessages,
bool hasCard,
bool isTyping,
bool isLoading,
)?
loaded,
ChatRoomModel chatRoom,
List<ChatMessageModel> chatMessages,
bool hasCard,
bool isTyping,
bool isLoading)?
loaded,
TResult? Function(String errorMessage)? error,
}) {
return loaded?.call(chatRoom, chatMessages, hasCard, isTyping, isLoading);
@@ -581,13 +555,12 @@ class _$ChatRoomStateLoadedImpl implements ChatRoomStateLoaded {
TResult Function()? $default, {
TResult Function()? loading,
TResult Function(
ChatRoomModel chatRoom,
List<ChatMessageModel> chatMessages,
bool hasCard,
bool isTyping,
bool isLoading,
)?
loaded,
ChatRoomModel chatRoom,
List<ChatMessageModel> chatMessages,
bool hasCard,
bool isTyping,
bool isLoading)?
loaded,
TResult Function(String errorMessage)? error,
required TResult orElse(),
}) {
@@ -636,13 +609,12 @@ class _$ChatRoomStateLoadedImpl implements ChatRoomStateLoaded {
}
abstract class ChatRoomStateLoaded implements ChatRoomState {
const factory ChatRoomStateLoaded({
required final ChatRoomModel chatRoom,
required final List<ChatMessageModel> chatMessages,
required final bool hasCard,
required final bool isTyping,
required final bool isLoading,
}) = _$ChatRoomStateLoadedImpl;
const factory ChatRoomStateLoaded(
{required final ChatRoomModel chatRoom,
required final List<ChatMessageModel> chatMessages,
required final bool hasCard,
required final bool isTyping,
required final bool isLoading}) = _$ChatRoomStateLoadedImpl;
ChatRoomModel get chatRoom;
List<ChatMessageModel> get chatMessages;
@@ -659,10 +631,9 @@ abstract class ChatRoomStateLoaded implements ChatRoomState {
/// @nodoc
abstract class _$$ChatRoomStateErrorImplCopyWith<$Res> {
factory _$$ChatRoomStateErrorImplCopyWith(
_$ChatRoomStateErrorImpl value,
$Res Function(_$ChatRoomStateErrorImpl) then,
) = __$$ChatRoomStateErrorImplCopyWithImpl<$Res>;
factory _$$ChatRoomStateErrorImplCopyWith(_$ChatRoomStateErrorImpl value,
$Res Function(_$ChatRoomStateErrorImpl) then) =
__$$ChatRoomStateErrorImplCopyWithImpl<$Res>;
@useResult
$Res call({String errorMessage});
}
@@ -671,25 +642,23 @@ abstract class _$$ChatRoomStateErrorImplCopyWith<$Res> {
class __$$ChatRoomStateErrorImplCopyWithImpl<$Res>
extends _$ChatRoomStateCopyWithImpl<$Res, _$ChatRoomStateErrorImpl>
implements _$$ChatRoomStateErrorImplCopyWith<$Res> {
__$$ChatRoomStateErrorImplCopyWithImpl(
_$ChatRoomStateErrorImpl _value,
$Res Function(_$ChatRoomStateErrorImpl) _then,
) : super(_value, _then);
__$$ChatRoomStateErrorImplCopyWithImpl(_$ChatRoomStateErrorImpl _value,
$Res Function(_$ChatRoomStateErrorImpl) _then)
: super(_value, _then);
/// Create a copy of ChatRoomState
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({Object? errorMessage = null}) {
return _then(
_$ChatRoomStateErrorImpl(
errorMessage:
null == errorMessage
? _value.errorMessage
: errorMessage // ignore: cast_nullable_to_non_nullable
as String,
),
);
$Res call({
Object? errorMessage = null,
}) {
return _then(_$ChatRoomStateErrorImpl(
errorMessage: null == errorMessage
? _value.errorMessage
: errorMessage // ignore: cast_nullable_to_non_nullable
as String,
));
}
}
@@ -725,9 +694,7 @@ class _$ChatRoomStateErrorImpl implements ChatRoomStateError {
@pragma('vm:prefer-inline')
_$$ChatRoomStateErrorImplCopyWith<_$ChatRoomStateErrorImpl> get copyWith =>
__$$ChatRoomStateErrorImplCopyWithImpl<_$ChatRoomStateErrorImpl>(
this,
_$identity,
);
this, _$identity);
@override
@optionalTypeArgs
@@ -735,13 +702,12 @@ class _$ChatRoomStateErrorImpl implements ChatRoomStateError {
TResult Function() $default, {
required TResult Function() loading,
required TResult Function(
ChatRoomModel chatRoom,
List<ChatMessageModel> chatMessages,
bool hasCard,
bool isTyping,
bool isLoading,
)
loaded,
ChatRoomModel chatRoom,
List<ChatMessageModel> chatMessages,
bool hasCard,
bool isTyping,
bool isLoading)
loaded,
required TResult Function(String errorMessage) error,
}) {
return error(errorMessage);
@@ -753,13 +719,12 @@ class _$ChatRoomStateErrorImpl implements ChatRoomStateError {
TResult? Function()? $default, {
TResult? Function()? loading,
TResult? Function(
ChatRoomModel chatRoom,
List<ChatMessageModel> chatMessages,
bool hasCard,
bool isTyping,
bool isLoading,
)?
loaded,
ChatRoomModel chatRoom,
List<ChatMessageModel> chatMessages,
bool hasCard,
bool isTyping,
bool isLoading)?
loaded,
TResult? Function(String errorMessage)? error,
}) {
return error?.call(errorMessage);
@@ -771,13 +736,12 @@ class _$ChatRoomStateErrorImpl implements ChatRoomStateError {
TResult Function()? $default, {
TResult Function()? loading,
TResult Function(
ChatRoomModel chatRoom,
List<ChatMessageModel> chatMessages,
bool hasCard,
bool isTyping,
bool isLoading,
)?
loaded,
ChatRoomModel chatRoom,
List<ChatMessageModel> chatMessages,
bool hasCard,
bool isTyping,
bool isLoading)?
loaded,
TResult Function(String errorMessage)? error,
required TResult orElse(),
}) {

View File

@@ -12,8 +12,7 @@ part of 'chats_state.dart';
T _$identity<T>(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',
);
'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');
/// @nodoc
mixin _$ChatsState {
@@ -33,17 +32,15 @@ mixin _$ChatsState {
/// @nodoc
abstract class $ChatsStateCopyWith<$Res> {
factory $ChatsStateCopyWith(
ChatsState value,
$Res Function(ChatsState) then,
) = _$ChatsStateCopyWithImpl<$Res, ChatsState>;
ChatsState value, $Res Function(ChatsState) then) =
_$ChatsStateCopyWithImpl<$Res, ChatsState>;
@useResult
$Res call({
BaseState state,
int chatsWithUnreadMessagesCount,
List<ChatRoom> chatRooms,
bool isLoadingMoreChats,
String? errorMessage,
});
$Res call(
{BaseState state,
int chatsWithUnreadMessagesCount,
List<ChatRoom> chatRooms,
bool isLoadingMoreChats,
String? errorMessage});
}
/// @nodoc
@@ -67,36 +64,28 @@ class _$ChatsStateCopyWithImpl<$Res, $Val extends ChatsState>
Object? isLoadingMoreChats = null,
Object? errorMessage = freezed,
}) {
return _then(
_value.copyWith(
state:
null == state
? _value.state
: state // ignore: cast_nullable_to_non_nullable
as BaseState,
chatsWithUnreadMessagesCount:
null == chatsWithUnreadMessagesCount
? _value.chatsWithUnreadMessagesCount
: chatsWithUnreadMessagesCount // ignore: cast_nullable_to_non_nullable
as int,
chatRooms:
null == chatRooms
? _value.chatRooms
: chatRooms // ignore: cast_nullable_to_non_nullable
as List<ChatRoom>,
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
as String?,
)
as $Val,
);
return _then(_value.copyWith(
state: null == state
? _value.state
: state // ignore: cast_nullable_to_non_nullable
as BaseState,
chatsWithUnreadMessagesCount: null == chatsWithUnreadMessagesCount
? _value.chatsWithUnreadMessagesCount
: chatsWithUnreadMessagesCount // ignore: cast_nullable_to_non_nullable
as int,
chatRooms: null == chatRooms
? _value.chatRooms
: chatRooms // ignore: cast_nullable_to_non_nullable
as List<ChatRoom>,
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
as String?,
) as $Val);
}
}
@@ -104,18 +93,16 @@ class _$ChatsStateCopyWithImpl<$Res, $Val extends ChatsState>
abstract class _$$ChatsStateImplCopyWith<$Res>
implements $ChatsStateCopyWith<$Res> {
factory _$$ChatsStateImplCopyWith(
_$ChatsStateImpl value,
$Res Function(_$ChatsStateImpl) then,
) = __$$ChatsStateImplCopyWithImpl<$Res>;
_$ChatsStateImpl value, $Res Function(_$ChatsStateImpl) then) =
__$$ChatsStateImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({
BaseState state,
int chatsWithUnreadMessagesCount,
List<ChatRoom> chatRooms,
bool isLoadingMoreChats,
String? errorMessage,
});
$Res call(
{BaseState state,
int chatsWithUnreadMessagesCount,
List<ChatRoom> chatRooms,
bool isLoadingMoreChats,
String? errorMessage});
}
/// @nodoc
@@ -123,9 +110,8 @@ class __$$ChatsStateImplCopyWithImpl<$Res>
extends _$ChatsStateCopyWithImpl<$Res, _$ChatsStateImpl>
implements _$$ChatsStateImplCopyWith<$Res> {
__$$ChatsStateImplCopyWithImpl(
_$ChatsStateImpl _value,
$Res Function(_$ChatsStateImpl) _then,
) : super(_value, _then);
_$ChatsStateImpl _value, $Res Function(_$ChatsStateImpl) _then)
: super(_value, _then);
/// Create a copy of ChatsState
/// with the given fields replaced by the non-null parameter values.
@@ -138,48 +124,41 @@ class __$$ChatsStateImplCopyWithImpl<$Res>
Object? isLoadingMoreChats = null,
Object? errorMessage = freezed,
}) {
return _then(
_$ChatsStateImpl(
state:
null == state
? _value.state
: state // ignore: cast_nullable_to_non_nullable
as BaseState,
chatsWithUnreadMessagesCount:
null == chatsWithUnreadMessagesCount
? _value.chatsWithUnreadMessagesCount
: chatsWithUnreadMessagesCount // ignore: cast_nullable_to_non_nullable
as int,
chatRooms:
null == chatRooms
? _value._chatRooms
: chatRooms // ignore: cast_nullable_to_non_nullable
as List<ChatRoom>,
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
as String?,
),
);
return _then(_$ChatsStateImpl(
state: null == state
? _value.state
: state // ignore: cast_nullable_to_non_nullable
as BaseState,
chatsWithUnreadMessagesCount: null == chatsWithUnreadMessagesCount
? _value.chatsWithUnreadMessagesCount
: chatsWithUnreadMessagesCount // ignore: cast_nullable_to_non_nullable
as int,
chatRooms: null == chatRooms
? _value._chatRooms
: chatRooms // ignore: cast_nullable_to_non_nullable
as List<ChatRoom>,
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
as String?,
));
}
}
/// @nodoc
class _$ChatsStateImpl implements _ChatsState {
_$ChatsStateImpl({
this.state = BaseState.initial,
this.chatsWithUnreadMessagesCount = 0,
final List<ChatRoom> chatRooms = const [],
this.isLoadingMoreChats = false,
this.errorMessage = null,
}) : _chatRooms = chatRooms;
_$ChatsStateImpl(
{this.state = BaseState.initial,
this.chatsWithUnreadMessagesCount = 0,
final List<ChatRoom> chatRooms = const [],
this.isLoadingMoreChats = false,
this.errorMessage = null})
: _chatRooms = chatRooms;
@override
@JsonKey()
@@ -214,16 +193,12 @@ class _$ChatsStateImpl implements _ChatsState {
(other.runtimeType == runtimeType &&
other is _$ChatsStateImpl &&
(identical(other.state, state) || other.state == state) &&
(identical(
other.chatsWithUnreadMessagesCount,
chatsWithUnreadMessagesCount,
) ||
(identical(other.chatsWithUnreadMessagesCount,
chatsWithUnreadMessagesCount) ||
other.chatsWithUnreadMessagesCount ==
chatsWithUnreadMessagesCount) &&
const DeepCollectionEquality().equals(
other._chatRooms,
_chatRooms,
) &&
const DeepCollectionEquality()
.equals(other._chatRooms, _chatRooms) &&
(identical(other.isLoadingMoreChats, isLoadingMoreChats) ||
other.isLoadingMoreChats == isLoadingMoreChats) &&
(identical(other.errorMessage, errorMessage) ||
@@ -232,13 +207,12 @@ class _$ChatsStateImpl implements _ChatsState {
@override
int get hashCode => Object.hash(
runtimeType,
state,
chatsWithUnreadMessagesCount,
const DeepCollectionEquality().hash(_chatRooms),
isLoadingMoreChats,
errorMessage,
);
runtimeType,
state,
chatsWithUnreadMessagesCount,
const DeepCollectionEquality().hash(_chatRooms),
isLoadingMoreChats,
errorMessage);
/// Create a copy of ChatsState
/// with the given fields replaced by the non-null parameter values.
@@ -250,13 +224,12 @@ class _$ChatsStateImpl implements _ChatsState {
}
abstract class _ChatsState implements ChatsState {
factory _ChatsState({
final BaseState state,
final int chatsWithUnreadMessagesCount,
final List<ChatRoom> chatRooms,
final bool isLoadingMoreChats,
final String? errorMessage,
}) = _$ChatsStateImpl;
factory _ChatsState(
{final BaseState state,
final int chatsWithUnreadMessagesCount,
final List<ChatRoom> chatRooms,
final bool isLoadingMoreChats,
final String? errorMessage}) = _$ChatsStateImpl;
@override
BaseState get state;

View File

@@ -16,6 +16,7 @@ import 'package:eatvio_app/core/theme/theme_helper.dart';
import 'package:eatvio_app/features/chat/presentation/widgets/notification_banner.dart';
import 'package:eatvio_app/features/chat/presentation/widgets/order_card.dart';
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
import 'package:eatvio_app/features/order_info/presentation/info_by_order_screen.dart';
import 'package:eatvio_app/features/plans/enums/chosen_plan_state_enum.dart';
import 'package:eatvio_app/features/user_details/presentation/user_details_screen.dart';
import 'package:eatvio_app/generated/l10n.dart';
@@ -62,6 +63,7 @@ class _ChatScreenState extends State<ChatScreen> {
super.dispose();
}
@override
Widget build(BuildContext context) {
return BlocProvider<ChatRoomCubit>(
create: (BuildContext context) => chatRoomCubit,
@@ -73,7 +75,7 @@ class _ChatScreenState extends State<ChatScreen> {
} else if (state is ChatRoomStateError) {
return Scaffold(appBar: AppBar(), body: DataErrorWidget(onReload: () => chatRoomCubit.initChat(widget.chatId)));
} else {
return Scaffold(body: const Loader());
return const Scaffold(body: Loader());
}
},
),
@@ -85,11 +87,13 @@ class _ChatScreenState extends State<ChatScreen> {
final amIConsultant = chosenPlan?.consultantId == state.chatRoom.users.sender.id;
final showAboutOrderButton = showableChatBadgeStates.contains(chosenPlan?.chosenPlanState);
BannerType? bannerType;
if (amIConsultant && !state.hasCard) {
if (amIConsultant && state.hasCard) {
bannerType = BannerType.card;
} else if (amIConsultant && chosenPlan?.chosenPlanState == ChosenPlanStateEnum.stateInCoordination) {
bannerType = BannerType.date;
} else if (!amIConsultant && chosenPlan?.chosenPlanState == ChosenPlanStateEnum.stateStartDateHasBeenSet) {
} else if (!amIConsultant &&
(chosenPlan?.chosenPlanState == ChosenPlanStateEnum.stateStartDateHasBeenSet ||
chosenPlan?.chosenPlanState == ChosenPlanStateEnum.statePendingPayment)) {
bannerType = BannerType.payment;
}
return Scaffold(
@@ -122,20 +126,20 @@ class _ChatScreenState extends State<ChatScreen> {
width: 40,
height: 40,
alignment: Alignment.center,
decoration: BoxDecoration(
decoration: const BoxDecoration(
color: Color(0xFFEBF4FF),
shape: BoxShape.circle,
),
child: Text(
state.chatRoom.users.receiver.name.split(' ').first[0] + state.chatRoom.users.receiver.name.split(' ')[1][0],
style: TextStyle(
style: const TextStyle(
color: Color(0xFF7F9CF5),
fontWeight: FontWeight.w400,
fontSize: 20,
),
),
),
SizedBox(width: 16),
const SizedBox(width: 16),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@@ -154,7 +158,7 @@ class _ChatScreenState extends State<ChatScreen> {
secondCurve: Curves.easeOut,
secondChild: const SizedBox.shrink(),
crossFadeState: state.isTyping ? CrossFadeState.showFirst : CrossFadeState.showSecond,
duration: Duration(milliseconds: 150),
duration: const Duration(milliseconds: 150),
),
],
),
@@ -173,19 +177,19 @@ class _ChatScreenState extends State<ChatScreen> {
color: appTheme.whiteA700,
width: double.maxFinite,
child: SingleChildScrollView(
physics: BouncingScrollPhysics(),
physics: const BouncingScrollPhysics(),
controller: scrollController,
reverse: true,
child: Column(
children: [
SizedBox(height: 16),
const SizedBox(height: 16),
ListView.builder(
physics: NeverScrollableScrollPhysics(),
physics: const NeverScrollableScrollPhysics(),
reverse: true,
shrinkWrap: true,
itemBuilder: (context, index) {
if (index == state.chatMessages.length) {
return Padding(padding: const EdgeInsets.all(8), child: const Loader());
return const Padding(padding: EdgeInsets.all(8), child: Loader());
}
if ((index + 1 != state.chatMessages.length &&
@@ -200,13 +204,14 @@ class _ChatScreenState extends State<ChatScreen> {
onVisibilityChanged: (VisibilityInfo info) {
if (!state.chatMessages[index].isRead && !isCurrentUserAuthor && info.visibleFraction > 0) {
unreadMessagesIdsCopy.add((id: state.chatMessages[index].id, index: index));
EasyDebounce.debounce('mark_as_read', Duration(milliseconds: 500), () async {
EasyDebounce.debounce('mark_as_read', const Duration(milliseconds: 500), () async {
final result = await context.read<ChatRoomCubit>().markMessagesAsRead(state.chatRoom.id, unreadMessagesIdsCopy);
if (!result) return;
if (!context.mounted) return;
context.read<ChatsCubit>().reduceUnreadMessagesCount(
chatId: state.chatRoom.id,
count: unreadMessagesIdsCopy.length,
);
chatId: state.chatRoom.id,
count: unreadMessagesIdsCopy.length,
);
unreadMessagesIdsCopy.clear();
});
}
@@ -228,9 +233,10 @@ class _ChatScreenState extends State<ChatScreen> {
onVisibilityChanged: (VisibilityInfo info) {
if (!state.chatMessages[index].isRead && !isCurrentUserAuthor && info.visibleFraction > 0) {
unreadMessagesIds.add((id: state.chatMessages[index].id, index: index));
EasyDebounce.debounce('mark_as_read', Duration(milliseconds: 500), () async {
EasyDebounce.debounce('mark_as_read', const Duration(milliseconds: 500), () async {
final result = await context.read<ChatRoomCubit>().markMessagesAsRead(state.chatRoom.id, unreadMessagesIds);
if (!result) return;
if (!context.mounted) return;
context.read<ChatsCubit>().reduceUnreadMessagesCount(chatId: state.chatRoom.id, count: unreadMessagesIds.length);
unreadMessagesIds.clear();
});
@@ -247,7 +253,7 @@ class _ChatScreenState extends State<ChatScreen> {
},
itemCount: state.chatMessages.length + (state.isLoading ? 1 : 0),
),
SizedBox(height: 16),
const SizedBox(height: 16),
if (chosenPlan != null) ...[
OrderCard(
plan: chosenPlan.plan,
@@ -257,15 +263,15 @@ class _ChatScreenState extends State<ChatScreen> {
await context.read<ChatRoomCubit>().cancelChosenPlan(chatId: state.chatRoom.id, planId: chosenPlan.id);
},
),
if (amIConsultant) ...[
if (amIConsultant)
Padding(
padding: EdgeInsets.symmetric(vertical: 12, horizontal: 16),
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16),
child: CustomOutlinedButton(
text: S.current.user_info,
height: 52,
buttonTextStyle: TextStyles.textMSemibold.copyWith(color: appTheme.whiteA700),
buttonStyle: ButtonStyle(
side: WidgetStatePropertyAll(BorderSide.none),
side: const WidgetStatePropertyAll(BorderSide.none),
backgroundColor: WidgetStatePropertyAll(appTheme.blueA400),
),
onPressed: () async {
@@ -273,9 +279,8 @@ class _ChatScreenState extends State<ChatScreen> {
},
),
),
if (bannerType != null)
Padding(padding: EdgeInsets.symmetric(vertical: 12, horizontal: 16), child: NotificationBanner(bannerType: bannerType)),
],
if (bannerType != null)
Padding(padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16), child: NotificationBanner(bannerType: bannerType)),
],
],
),
@@ -283,11 +288,11 @@ class _ChatScreenState extends State<ChatScreen> {
),
),
Container(
padding: EdgeInsets.symmetric(vertical: 8),
padding: const EdgeInsets.symmetric(vertical: 8),
child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
SizedBox(width: 8),
const SizedBox(width: 8),
InkWell(
onTap: () async {
FilePickerResult? result = await FilePicker.platform.pickFiles(
@@ -320,14 +325,14 @@ class _ChatScreenState extends State<ChatScreen> {
await chatRoomCubit.sendMessage(chatId: widget.chatId, files: files);
}
},
customBorder: CircleBorder(),
customBorder: const CircleBorder(),
child: Ink(
height: 40,
width: 40,
child: Transform.rotate(angle: pi / 4, child: Icon(Icons.attach_file_rounded, size: 30, color: Color(0xFF858E99))),
child: Transform.rotate(angle: pi / 4, child: const Icon(Icons.attach_file_rounded, size: 30, color: Color(0xFF858E99))),
),
),
SizedBox(width: 8),
const SizedBox(width: 8),
Expanded(
child: SizedBox(
height: 40,
@@ -338,29 +343,29 @@ class _ChatScreenState extends State<ChatScreen> {
maxLines: null,
minLines: null,
keyboardType: TextInputType.multiline,
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w400, color: Colors.black, height: 1),
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w400, color: Colors.black, height: 1),
decoration: InputDecoration(
isDense: true,
contentPadding: EdgeInsets.symmetric(horizontal: 16, vertical: 10),
contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
hintText: 'Сообщение',
hintStyle: TextStyle(fontSize: 14, fontWeight: FontWeight.w400, height: 1, color: Color(0xFFAEAEB2)),
hintStyle: const TextStyle(fontSize: 14, fontWeight: FontWeight.w400, height: 1, color: Color(0xFFAEAEB2)),
filled: true,
border: OutlineInputBorder(borderRadius: BorderRadius.circular(100), borderSide: BorderSide(color: Color(0xFFD1D1D6), width: 1)),
border: OutlineInputBorder(borderRadius: BorderRadius.circular(100), borderSide: const BorderSide(color: Color(0xFFD1D1D6), width: 1)),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(100),
borderSide: BorderSide(color: Color(0xFFD1D1D6), width: 1),
borderSide: const BorderSide(color: Color(0xFFD1D1D6), width: 1),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(100),
borderSide: BorderSide(color: Color(0xFFD1D1D6), width: 1),
borderSide: const BorderSide(color: Color(0xFFD1D1D6), width: 1),
),
),
),
),
),
SizedBox(width: 8),
const SizedBox(width: 8),
InkWell(
customBorder: CircleBorder(),
customBorder: const CircleBorder(),
onTap: () {
if (textEditingController.text.isNotEmpty) {
chatRoomCubit.sendMessage(chatId: widget.chatId, data: textEditingController.text.trim());
@@ -373,16 +378,25 @@ class _ChatScreenState extends State<ChatScreen> {
decoration: BoxDecoration(color: appTheme.blueA400, shape: BoxShape.circle),
height: 40,
width: 40,
child: Icon(Icons.arrow_upward_rounded, size: 24, color: Colors.white),
child: const Icon(Icons.arrow_upward_rounded, size: 24, color: Colors.white),
),
),
SizedBox(width: 8),
const SizedBox(width: 8),
],
),
),
],
),
if (showAboutOrderButton) Positioned(top: 8, right: 15, left: 16, child: AboutOrderButton()),
if (showAboutOrderButton)
Positioned(
top: 8,
right: 15,
left: 16,
child: AboutOrderButton(
onTap: () {
GoRouter.of(context).push(InfoByOrderScreen.path, extra: state.chatRoom.chosenPlan);
},
)),
],
),
),

View File

@@ -11,7 +11,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class ChatsScreen extends StatefulWidget {
const ChatsScreen({Key? key}) : super(key: key);
const ChatsScreen({super.key});
@override
State<ChatsScreen> createState() => _ChatsScreenState();
@@ -20,6 +20,7 @@ class ChatsScreen extends StatefulWidget {
class _ChatsScreenState extends State<ChatsScreen> {
final searchController = TextEditingController();
@override
Widget build(BuildContext context) {
return BlocBuilder<ChatsCubit, ChatsState>(
builder: (context, state) {
@@ -47,7 +48,7 @@ class _ChatsScreenState extends State<ChatsScreen> {
if (query.length > 2) {
EasyDebounce.debounce(
'searchChatRoom',
Duration(milliseconds: 300),
const Duration(milliseconds: 300),
() => context.read<ChatsCubit>().getChatRooms(query: query),
);
} else {
@@ -55,9 +56,9 @@ class _ChatsScreenState extends State<ChatsScreen> {
}
},
controller: searchController,
fillColor: Color(0xFFF0F2F5),
fillColor: const Color(0xFFF0F2F5),
hintText: "Поиск",
hintStyle: TextStyle(
hintStyle: const TextStyle(
color: Color(0xFF7B8794),
),
),
@@ -84,18 +85,18 @@ class _ChatsScreenState extends State<ChatsScreen> {
return false;
},
child: ListView.separated(
padding: EdgeInsets.all(16),
padding: const EdgeInsets.all(16),
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
physics: const NeverScrollableScrollPhysics(),
separatorBuilder: (context, index) {
return SizedBox(
return const 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 const Center(child: Loader());
}
return ChatEntryWidget(chatRoom: state.chatRooms[index]);
},

View File

@@ -0,0 +1,49 @@
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
class PaymentScreen extends StatefulWidget {
static const name = 'paymentScreen';
static const path = '/payment-screen';
final String url;
const PaymentScreen({super.key, required this.url});
@override
State<PaymentScreen> createState() => _PaymentScreenState();
}
class _PaymentScreenState extends State<PaymentScreen> {
late final WebViewController _controller;
@override
void initState() {
super.initState();
_controller = WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
..setNavigationDelegate(
NavigationDelegate(
onProgress: (int progress) {},
onPageStarted: (String url) {},
onPageFinished: (String url) {},
onHttpError: (HttpResponseError error) {},
onWebResourceError: (WebResourceError error) {},
onNavigationRequest: (NavigationRequest request) {
log(request.url);
return NavigationDecision.navigate;
},
),
)
..loadRequest(Uri.parse(widget.url));
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: WebViewWidget(
controller: _controller,
),
);
}
}

View File

@@ -27,7 +27,7 @@ class PhotoViewScreen extends StatefulWidget {
}
class _PhotoViewScreenState extends State<PhotoViewScreen> {
late final pageController;
late final PageController pageController;
int imageIndex = 0;
@override
@@ -45,7 +45,7 @@ class _PhotoViewScreenState extends State<PhotoViewScreen> {
direction: DismissiblePageDismissDirection.vertical,
isFullScreen: true,
child: PhotoViewGallery.builder(
backgroundDecoration: BoxDecoration(
backgroundDecoration: const BoxDecoration(
color: Colors.transparent,
),
scrollPhysics: const BouncingScrollPhysics(),
@@ -71,29 +71,29 @@ class _PhotoViewScreenState extends State<PhotoViewScreen> {
child: Column(
children: [
const SizedBox(height: 32),
Text('Файл'),
const Text('Файл'),
const SizedBox(height: 8),
ListTile(
shape: RoundedRectangleBorder(
borderRadius: BorderRadiusStyle.circleBorder17,
),
contentPadding: EdgeInsets.all(16),
contentPadding: const EdgeInsets.all(16),
onTap: () async {
if (!await launchUrl(Uri.parse(widget.imageUrls[index]))) {
throw Exception('Could not launch ${widget.imageUrls[index]}');
}
},
leading: Icon(
leading: const Icon(
Icons.file_copy_outlined,
color: Colors.white,
),
trailing: Icon(
trailing: const Icon(
Icons.download_outlined,
color: Colors.white,
),
title: Text(
widget.imageUrls[index].replaceAll(baseUrl + '/storage/' + 'chat_files/', ''),
style: TextStyle(
widget.imageUrls[index].replaceAll('$baseUrl/storage/chat_files/', ''),
style: const TextStyle(
color: Colors.white,
fontSize: 12,
),
@@ -108,7 +108,7 @@ class _PhotoViewScreenState extends State<PhotoViewScreen> {
},
itemCount: widget.imageUrls.length,
loadingBuilder: (context, event) => Center(
child: Container(
child: SizedBox(
width: 20.0,
height: 20.0,
child: CircularProgressIndicator(

View File

@@ -5,12 +5,12 @@ import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
class AboutOrderButton extends StatelessWidget {
const AboutOrderButton({super.key});
const AboutOrderButton({super.key, required this.onTap});
final void Function() onTap;
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {},
onTap: onTap,
child: Container(
height: 44,
decoration: BoxDecoration(
@@ -20,13 +20,13 @@ class AboutOrderButton extends StatelessWidget {
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SizedBox.shrink(),
const SizedBox.shrink(),
Text(
S.current.more_about_order,
style: TextStyles.textSMedium.copyWith(color: appTheme.black),
),
Container(
margin: EdgeInsets.only(right: 4),
margin: const EdgeInsets.only(right: 4),
width: 36,
height: 36,
decoration: BoxDecoration(

View File

@@ -27,7 +27,7 @@ class ChatBubbleWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
final size = MediaQuery.sizeOf(context);
return Container(
return SizedBox(
width: size.width,
child: Padding(
padding: EdgeInsets.fromLTRB(isCurrentUser ? 64 : 16, 10, isCurrentUser ? 16 : 64, 4),
@@ -41,7 +41,7 @@ class ChatBubbleWidget extends StatelessWidget {
padding: const EdgeInsets.only(right: 4, bottom: 4),
child: Text(
sendTime.format('hh:mm'),
style: TextStyle(
style: const TextStyle(
color: Color(0xFF7B8794),
height: 1,
fontSize: 10,
@@ -52,16 +52,16 @@ class ChatBubbleWidget extends StatelessWidget {
constraints: BoxConstraints(maxWidth: size.width * 0.7),
decoration: BoxDecoration(
color: isCurrentUser ? appTheme.gray50 : appTheme.gray60004,
borderRadius: mediaData.length > 0
borderRadius: mediaData.isNotEmpty
? BorderRadius.circular(24)
: BorderRadius.horizontal(
left: isCurrentUser ? Radius.circular(32) : Radius.circular(16),
right: isCurrentUser ? Radius.circular(16) : Radius.circular(24),
left: isCurrentUser ? const Radius.circular(32) : const Radius.circular(16),
right: isCurrentUser ? const Radius.circular(16) : const Radius.circular(24),
),
),
child: Padding(
padding:
mediaData.isNotEmpty ? EdgeInsets.all(8) : EdgeInsets.only(top: 8, bottom: 8, left: isCurrentUser ? 16 : 8, right: isCurrentUser ? 8 : 16),
mediaData.isNotEmpty ? const EdgeInsets.all(8) : EdgeInsets.only(top: 8, bottom: 8, left: isCurrentUser ? 16 : 8, right: isCurrentUser ? 8 : 16),
child: Column(
crossAxisAlignment: isCurrentUser ? CrossAxisAlignment.end : CrossAxisAlignment.start,
children: [
@@ -70,7 +70,7 @@ class ChatBubbleWidget extends StatelessWidget {
width: size.width * 0.7,
child: CustomScrollView(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
physics: const NeverScrollableScrollPhysics(),
slivers: [
SliverList.separated(
itemBuilder: (BuildContext context, int index) {
@@ -78,25 +78,25 @@ class ChatBubbleWidget extends StatelessWidget {
!mediaData[index].toString().contains('.jpg') &&
!mediaData[index].toString().contains('.jpeg')) {
return ListTile(
contentPadding: EdgeInsets.all(4),
contentPadding: const EdgeInsets.all(4),
horizontalTitleGap: 8,
onTap: () async {
if (!await launchUrl(Uri.parse(baseUrl + '/storage/' + mediaData[index].toString()))) {
if (!await launchUrl(Uri.parse('$baseUrl/storage/${mediaData[index]}'))) {
throw Exception('Could not launch ${mediaData[index].toString()}');
}
},
leading: Icon(
leading: const Icon(
Icons.file_copy_outlined,
color: Colors.white,
),
trailing: Icon(
trailing: const Icon(
Icons.download_outlined,
color: Colors.white,
),
title: Text(
mediaData[index].toString().replaceAll('chat_files/', ''),
maxLines: 2,
style: TextStyle(
style: const TextStyle(
color: Colors.white,
fontSize: 12,
overflow: TextOverflow.ellipsis,
@@ -108,18 +108,18 @@ class ChatBubbleWidget extends StatelessWidget {
onTap: () {
context.pushTransparentRoute(
PhotoViewScreen(
imageUrls: mediaData.map((e) => baseUrl + '/storage/' + e.toString()).toList(),
imageUrls: mediaData.map((e) => '$baseUrl/storage/$e').toList(),
index: index,
),
);
},
child: Hero(
tag: baseUrl + '/storage/' + '${mediaData[index]}',
tag: '$baseUrl/storage/${mediaData[index]}',
transitionOnUserGestures: true,
child: ClipRRect(
borderRadius: BorderRadius.circular(16),
child: CachedNetworkImage(
imageUrl: baseUrl + '/storage/' + '${mediaData[index]}',
imageUrl: '$baseUrl/storage/${mediaData[index]}',
),
),
),
@@ -131,7 +131,7 @@ class ChatBubbleWidget extends StatelessWidget {
],
),
),
if (mediaData.isNotEmpty && text.isNotEmpty) SizedBox(height: 8),
if (mediaData.isNotEmpty && text.isNotEmpty) const SizedBox(height: 8),
if (text.isNotEmpty)
Text(
text,
@@ -146,7 +146,7 @@ class ChatBubbleWidget extends StatelessWidget {
padding: const EdgeInsets.only(left: 4, bottom: 4),
child: Text(
sendTime.format('hh:mm'),
style: TextStyle(
style: const TextStyle(
color: Color(0xFF7B8794),
height: 1,
fontSize: 10,

View File

@@ -8,7 +8,7 @@ import 'package:go_router/go_router.dart';
class ChatEntryWidget extends StatefulWidget {
final ChatRoom chatRoom;
ChatEntryWidget({
const ChatEntryWidget({
required this.chatRoom,
super.key,
});
@@ -29,10 +29,10 @@ class _ChatEntryWidgetState extends State<ChatEntryWidget> {
},
),
child: Ink(
padding: EdgeInsets.all(12),
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16),
color: Color(0xFFF6FAFF),
color: const Color(0xFFF6FAFF),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
@@ -52,10 +52,10 @@ class _ChatEntryWidgetState extends State<ChatEntryWidget> {
Text(
widget.chatRoom.users.toChatUser.name.length <= 20
? widget.chatRoom.users.toChatUser.name
: widget.chatRoom.users.toChatUser.name.substring(0, 20) + '...',
: '${widget.chatRoom.users.toChatUser.name.substring(0, 20)}...',
style: theme.textTheme.titleMedium,
),
SizedBox(height: 8),
const SizedBox(height: 8),
if (widget.chatRoom.lastMessage != null)
SizedBox(
width: MediaQuery.sizeOf(context).width * 0.5,
@@ -68,22 +68,22 @@ class _ChatEntryWidgetState extends State<ChatEntryWidget> {
),
],
),
Spacer(),
const Spacer(),
Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
if (widget.chatRoom.lastMessage != null)
Padding(
padding: EdgeInsets.only(left: 8),
padding: const EdgeInsets.only(left: 8),
child: Text(
widget.chatRoom.lastMessage!.updatedAt.format('dd MMM', 'ru'),
style: theme.textTheme.bodyMedium,
),
),
SizedBox(height: 4),
const SizedBox(height: 4),
if (widget.chatRoom.unreadMessagesCount > 0)
Container(
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 6),
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 6),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: appTheme.blueA400,

View File

@@ -3,8 +3,8 @@ import 'package:eatvio_app/core/theme/theme_helper.dart';
import 'package:flutter/material.dart';
class ChatSearchBarWidget extends StatelessWidget {
ChatSearchBarWidget({
Key? key,
const ChatSearchBarWidget({
super.key,
this.alignment,
this.width,
this.scrollPadding,
@@ -27,7 +27,7 @@ class ChatSearchBarWidget extends StatelessWidget {
this.validator,
this.onChanged,
required this.onSuffixIconTap,
}) : super(key: key);
});
final Alignment? alignment;
@@ -107,7 +107,7 @@ class ChatSearchBarWidget extends StatelessWidget {
hintText: hintText ?? "",
hintStyle: hintStyle ?? CustomTextStyles.bodySmallMulishBluegray800,
prefixIcon: prefix ??
Padding(
const Padding(
padding: EdgeInsets.only(left: 12),
child: Icon(
Icons.search,
@@ -126,7 +126,7 @@ class ChatSearchBarWidget extends StatelessWidget {
),
),
isDense: true,
contentPadding: EdgeInsets.all(16),
contentPadding: const EdgeInsets.all(16),
fillColor: fillColor ?? appTheme.gray100,
filled: filled,
border: borderDecoration ??

View File

@@ -0,0 +1,90 @@
import 'package:eatvio_app/core/utils/toasts.dart';
import 'package:eatvio_app/core/widgets/bottom_sheet_handler_bar.dart';
import 'package:eatvio_app/core/widgets/custom_divider.dart';
import 'package:eatvio_app/features/chat/presentation/bloc/chat_room_cubit/chat_room_cubit.dart';
import 'package:eatvio_app/features/chat/presentation/bloc/chat_room_cubit/chat_room_state.dart';
import 'package:eatvio_app/features/diets/presentation/widgets/calendar_widget.dart';
import 'package:eatvio_app/generated/l10n.dart';
import 'package:eatvio_app/core/theme/custom_text_style.dart';
import 'package:eatvio_app/core/theme/theme_helper.dart';
import 'package:eatvio_app/core/widgets/custom_outlined_button.dart';
import 'package:flutter/material.dart';
class ChosePlanDateWidget extends StatefulWidget {
const ChosePlanDateWidget({super.key, required this.chatCubit});
final ChatRoomCubit chatCubit;
@override
State<ChosePlanDateWidget> createState() => _ChosePlanDateWidget();
}
class _ChosePlanDateWidget extends State<ChosePlanDateWidget> {
final startDate = [DateTime.now()];
@override
Widget build(BuildContext context) {
final s = S.of(context);
String? planName;
if (widget.chatCubit.state is ChatRoomStateLoaded) {
planName = (widget.chatCubit.state as ChatRoomStateLoaded).chatRoom.chosenPlan?.plan.name;
}
return Column(
mainAxisSize: MainAxisSize.min,
children: [
const SizedBox(height: 4),
const BottomSheetHandlerBar(),
const SizedBox(height: 12),
Text(
planName ?? '',
style: TextStyles.headingXLSemibold.copyWith(
color: appTheme.black,
),
),
const SizedBox(height: 12),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 25.0),
child: Text(
s.chose_plan_start_date_2,
textAlign: TextAlign.center,
style: TextStyles.textMMedium.copyWith(
color: appTheme.black,
),
),
),
const SizedBox(height: 12),
const Padding(
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: CustomDivider(),
),
CalendarWidget(
startDate: startDate,
),
Padding(
padding: const EdgeInsets.only(left: 16, right: 16, top: 16, bottom: 28),
child: CustomOutlinedButton(
onPressed: () async {
final result = await widget.chatCubit.choseStartPlanDate(startDate[0]);
if (result) {
showSuccessToast('Дата установлена');
if (!context.mounted) return;
Navigator.pop(context);
} else {
showErrorToast('Не удалось установить дату');
if (!context.mounted) return;
Navigator.pop(context);
}
},
height: 60,
text: s.confirm,
buttonTextStyle: TextStyles.textLSemibold.copyWith(
color: appTheme.whiteA700,
),
buttonStyle: ButtonStyle(
backgroundColor: WidgetStatePropertyAll(appTheme.blueA400),
side: const WidgetStatePropertyAll(BorderSide.none),
),
),
),
],
);
}
}

View File

@@ -1,8 +1,13 @@
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/chat_room_cubit/chat_room_cubit.dart';
import 'package:eatvio_app/features/chat/presentation/pages/payment_screen.dart';
import 'package:eatvio_app/features/chat/presentation/widgets/chose_plan_date_widget.dart';
import 'package:eatvio_app/generated/l10n.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/svg.dart';
import 'package:go_router/go_router.dart';
class NotificationBanner extends StatelessWidget {
const NotificationBanner({super.key, required this.bannerType});
@@ -32,38 +37,52 @@ class NotificationBanner extends StatelessWidget {
BannerType.date => [
SizedBox(
width: size.width * 0.6,
child: Text(s.can_not_choose_start_date, style: TextStyles.textMMedium.copyWith(color: appTheme.black)),
child: Text(s.choose_plan_start_date, style: TextStyles.textMMedium.copyWith(color: appTheme.black)),
),
SizedBox(height: 12),
const SizedBox(height: 12),
GestureDetector(
onTap: () {},
child: Text(s.add_card, style: TextStyles.textLSemibold.copyWith(color: appTheme.blueA400)),
onTap: () {
final cubit = context.read<ChatRoomCubit>();
showModalBottomSheet(
context: context,
builder: (context) => ChosePlanDateWidget(
chatCubit: cubit,
),
);
},
child: Text(s.choose_date, style: TextStyles.textLSemibold.copyWith(color: appTheme.blueA400)),
),
SizedBox(height: 16),
const SizedBox(height: 16),
],
BannerType.card => [
SizedBox(
width: size.width * 0.6,
child: Text(s.can_not_choose_start_date, style: TextStyles.textMMedium.copyWith(color: appTheme.black)),
),
SizedBox(height: 12),
const SizedBox(height: 12),
GestureDetector(
onTap: () {},
child: Text(s.add_card, style: TextStyles.textLSemibold.copyWith(color: appTheme.blueA400)),
),
SizedBox(height: 16),
const SizedBox(height: 16),
],
BannerType.payment => [
SizedBox(
width: size.width * 0.6,
child: Text(s.can_not_choose_start_date, style: TextStyles.textMMedium.copyWith(color: appTheme.black)),
child: Text(s.tap_on_link_to_pay, style: TextStyles.textMMedium.copyWith(color: appTheme.black)),
),
SizedBox(height: 12),
const SizedBox(height: 12),
GestureDetector(
onTap: () {},
child: Text(s.add_card, style: TextStyles.textLSemibold.copyWith(color: appTheme.blueA400)),
onTap: () async {
final paymentLink = await context.read<ChatRoomCubit>().getPaymentLink();
if (paymentLink != null) {
if (!context.mounted) return;
GoRouter.of(context).push(PaymentScreen.path, extra: paymentLink);
}
},
child: Text(s.pay, style: TextStyles.textLSemibold.copyWith(color: appTheme.blueA400)),
),
SizedBox(height: 16),
const SizedBox(height: 16),
],
},
),

View File

@@ -33,8 +33,8 @@ class _OrderCardState extends State<OrderCard> {
};
final s = S.of(context);
return Container(
margin: EdgeInsets.symmetric(horizontal: 16),
padding: EdgeInsets.only(top: 8, bottom: 12, left: 8, right: 8),
margin: const EdgeInsets.symmetric(horizontal: 16),
padding: const EdgeInsets.only(top: 8, bottom: 12, left: 8, right: 8),
decoration: BoxDecoration(borderRadius: BorderRadius.circular(12), color: appTheme.gray60004),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
@@ -47,7 +47,7 @@ class _OrderCardState extends State<OrderCard> {
ClipRRect(
borderRadius: BorderRadius.circular(12),
child: Image.network(
baseUrl + '/storage/' + widget.plan.image,
'$baseUrl/storage/${widget.plan.image}',
width: double.infinity,
fit: BoxFit.cover,
),
@@ -59,7 +59,7 @@ class _OrderCardState extends State<OrderCard> {
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
decoration: BoxDecoration(
color: appTheme.blueA400,
borderRadius: BorderRadius.only(
borderRadius: const BorderRadius.only(
topRight: Radius.circular(12),
bottomRight: Radius.circular(12),
),
@@ -77,7 +77,7 @@ class _OrderCardState extends State<OrderCard> {
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
decoration: BoxDecoration(
color: appTheme.greenA700,
borderRadius: BorderRadius.only(
borderRadius: const BorderRadius.only(
topRight: Radius.circular(12),
bottomRight: Radius.circular(12),
),
@@ -91,17 +91,17 @@ class _OrderCardState extends State<OrderCard> {
],
),
),
SizedBox(height: 12),
const SizedBox(height: 12),
Text(
'${widget.plan.name}',
widget.plan.name,
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
),
SizedBox(height: 12),
const SizedBox(height: 12),
Text(
'${s.option}: ${option?.short ?? ''}',
style: TextStyles.textMSemibold.copyWith(color: appTheme.black),
),
SizedBox(height: 8),
const SizedBox(height: 8),
if (option != null)
...option.items
.map(
@@ -114,11 +114,11 @@ class _OrderCardState extends State<OrderCard> {
),
),
)
.toList(),
,
if (widget.isCustomerView) ...[
SizedBox(height: 8),
const SizedBox(height: 8),
isLoading
? Loader()
? const Loader()
: GestureDetector(
onTap: () async {
setState(() => isLoading = true);
@@ -126,7 +126,7 @@ class _OrderCardState extends State<OrderCard> {
setState(() => isLoading = false);
},
child: Text(
'${s.cancel_order}',
s.cancel_order,
style: TextStyles.textSMedium.copyWith(color: appTheme.strongRed),
),
),