pre merge commit

This commit is contained in:
Username1548
2025-03-10 22:25:30 +07:00
parent afac964e2e
commit f590c49def
18 changed files with 604 additions and 32 deletions

View File

@@ -0,0 +1,4 @@
<svg width="68" height="69" viewBox="0 0 68 69" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M68 34.6406C68 53.2716 52.7777 68.375 34 68.375C15.2223 68.375 0 53.2716 0 34.6406C0 16.0096 15.2223 0.90625 34 0.90625C52.7777 0.90625 68 16.0096 68 34.6406Z" fill="white"/>
<path d="M31.6767 54.8812V26.6568H36.2667V54.8812H31.6767ZM31.11 20.2473V15.1309H36.7767V20.2473H31.11Z" fill="#2F80ED"/>
</svg>

After

Width:  |  Height:  |  Size: 409 B

View File

@@ -241,12 +241,10 @@ class AppRouter {
path: '/chat-screen',
name: 'chatScreen',
builder: (context, state) {
final data = state.extra as Map<String, dynamic>;
final chatsCubit = data['chatsCubit'] as ChatsCubit;
final data = state.extra as Map<String, dynamic>;
final chatId = data['chatId'] as String;
return ChatScreen(
chatId: chatId,
chatsCubit: chatsCubit,
chatId: chatId,
);
},
),

View File

@@ -1,5 +1,5 @@
String baseUrl = 'https://eatvio.ru';
// String baseUrl = 'https://dev2.eatvio.com';
// String baseUrl = 'https://eatvio.ru';
String baseUrl = 'https://dev2.eatvio.com';
const List<int> durationValues = [7, 14, 21];
@@ -8,4 +8,4 @@ const List<String> planTypeValues = ['fit', 'slim', 'wellness', 'behavior'];
const newMessagesChannelName = 'private-new-chat-messages';
const newNotificationsChannelName = 'private-message-events';
const directChatChannelName = 'private-direct-chat';
const directChatChannelName = 'private-direct-chat';

View File

@@ -87,6 +87,7 @@ Future<void> init() async {
sl.registerLazySingleton<NotificationsCubit>(() => NotificationsCubit(wsManager: sl()));
sl.registerLazySingleton<FeedCubit>(() => FeedCubit(feedRepository: sl()));
sl.registerLazySingleton<ProfileAvatarCubit>(() => ProfileAvatarCubit(profileRepository: sl()));
sl.registerLazySingleton<ChatsCubit>(() => ChatsCubit(chatRepository: sl(), wsManager: sl(), profileRepository: sl()));
// Cubit factories
sl.registerFactory<RegistrationCubit>(() => RegistrationCubit(registrationRepository: sl()));
@@ -96,8 +97,7 @@ Future<void> init() async {
sl.registerFactory<ProfileCubit>(() => ProfileCubit(profileRepository: sl(), chatRepository: sl()));
sl.registerFactory<profilePlans.PlansCubit>(() => profilePlans.PlansCubit(plansRepository: sl()));
sl.registerFactory<DietsCubit>(() => DietsCubit(feedRepository: sl(), dietsRepository: sl()));
sl.registerFactory<CommentsCubit>(() => CommentsCubit(feedRepository: sl()));
sl.registerFactory<ChatsCubit>(() => ChatsCubit(chatRepository: sl(), wsManager: sl(), profileRepository: sl()));
sl.registerFactory<CommentsCubit>(() => CommentsCubit(feedRepository: sl()));
sl.registerFactory<PlansCubit>(() => PlansCubit(feedRepository: sl(), planRepository: sl()));
sl.registerFactory<SettingsCubit>(() => SettingsCubit(profileRepository: sl(), settingsRepository: sl()));
sl.registerFactory<RegisterConsultantCubit>(() => RegisterConsultantCubit(consultantRepository: sl()));

View File

@@ -11,6 +11,7 @@ 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';
@@ -19,10 +20,8 @@ import 'package:visibility_detector/visibility_detector.dart';
class ChatScreen extends StatefulWidget {
final String chatId;
final ChatsCubit chatsCubit;
const ChatScreen({
required this.chatId,
required this.chatsCubit,
super.key,
});
@@ -174,7 +173,9 @@ class _ChatScreenState extends State<ChatScreen> {
() async {
final result = await context.read<ChatRoomCubit>().markMessagesAsRead(state.chatRoom.id, unreadMessagesIdsCopy);
if (!result) return;
widget.chatsCubit.reduceUnreadMessagesCount(chatId: state.chatRoom.id, count: unreadMessagesIdsCopy.length);
context
.read<ChatsCubit>()
.reduceUnreadMessagesCount(chatId: state.chatRoom.id, count: unreadMessagesIdsCopy.length);
unreadMessagesIdsCopy.clear();
},
);
@@ -203,7 +204,7 @@ class _ChatScreenState extends State<ChatScreen> {
() async {
final result = await context.read<ChatRoomCubit>().markMessagesAsRead(state.chatRoom.id, unreadMessagesIds);
if (!result) return;
widget.chatsCubit.reduceUnreadMessagesCount(chatId: state.chatRoom.id, count: unreadMessagesIds.length);
context.read<ChatsCubit>().reduceUnreadMessagesCount(chatId: state.chatRoom.id, count: unreadMessagesIds.length);
unreadMessagesIds.clear();
},
);

View File

@@ -28,7 +28,6 @@ class _ChatEntryWidgetState extends State<ChatEntryWidget> {
'chatScreen',
extra: {
'chatId': widget.chatRoom.id.toString(),
'chatsCubit': context.read<ChatsCubit>(),
},
),
child: Ink(

View File

@@ -0,0 +1,77 @@
import 'package:eatvio_app/core/theme/custom_text_style.dart';
import 'package:eatvio_app/core/theme/theme_helper.dart';
import 'package:eatvio_app/generated/l10n.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
class NotificationBanner extends StatelessWidget {
const NotificationBanner({super.key, required this.bannerType});
final BannerType bannerType;
@override
Widget build(BuildContext context) {
final size = MediaQuery.sizeOf(context);
final s = S.of(context);
return Container(
decoration: BoxDecoration(
color: appTheme.gray50,
borderRadius: BorderRadius.circular(20),
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(top: 12, right: 8, left: 12),
child: SvgPicture.asset('assets/icons/reversed_exclamation_mark.svg', height: 68, width: 68),
),
Padding(
padding: const EdgeInsets.only(top: 16),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: switch (bannerType) {
BannerType.date => [
SizedBox(
width: size.width * 0.6,
child: Text(s.can_not_choose_start_date, style: TextStyles.textMMedium.copyWith(color: appTheme.black)),
),
SizedBox(height: 12),
GestureDetector(
onTap: () {},
child: Text(s.add_card, style: TextStyles.textLSemibold.copyWith(color: appTheme.blueA400)),
),
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),
GestureDetector(
onTap: () {},
child: Text(s.add_card, style: TextStyles.textLSemibold.copyWith(color: appTheme.blueA400)),
),
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)),
),
SizedBox(height: 12),
GestureDetector(
onTap: () {},
child: Text(s.add_card, style: TextStyles.textLSemibold.copyWith(color: appTheme.blueA400)),
),
SizedBox(height: 16),
],
},
),
),
],
),
);
}
}
enum BannerType { date, card, payment }

View File

@@ -0,0 +1,20 @@
import 'package:eatvio_app/features/feed/models/plan_pagination_model.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'chosen_plan_model.freezed.dart';
part 'chosen_plan_model.g.dart';
@freezed
class ChosenPlanModel with _$ChosenPlanModel {
factory ChosenPlanModel({
@JsonKey() required int id,
@JsonKey(name: 'option_type') required String optionType,
@JsonKey(name: 'start_date') required DateTime startDate,
@JsonKey(name: 'chat_id') required String chatId,
@JsonKey(name: 'plan') required PlanModel plan,
}) = _ChosenPlanModel;
factory ChosenPlanModel.fromJson(Map<String, dynamic> json) => _$ChosenPlanModelFromJson(json);
}

View File

@@ -0,0 +1,283 @@
// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// 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 'chosen_plan_model.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
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');
ChosenPlanModel _$ChosenPlanModelFromJson(Map<String, dynamic> json) {
return _ChosenPlanModel.fromJson(json);
}
/// @nodoc
mixin _$ChosenPlanModel {
@JsonKey()
int get id => throw _privateConstructorUsedError;
@JsonKey(name: 'option_type')
String get optionType => throw _privateConstructorUsedError;
@JsonKey(name: 'start_date')
DateTime get startDate => 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<String, dynamic> toJson() => throw _privateConstructorUsedError;
/// Create a copy of ChosenPlanModel
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
$ChosenPlanModelCopyWith<ChosenPlanModel> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $ChosenPlanModelCopyWith<$Res> {
factory $ChosenPlanModelCopyWith(
ChosenPlanModel value, $Res Function(ChosenPlanModel) then) =
_$ChosenPlanModelCopyWithImpl<$Res, ChosenPlanModel>;
@useResult
$Res call(
{@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;
}
/// @nodoc
class _$ChosenPlanModelCopyWithImpl<$Res, $Val extends ChosenPlanModel>
implements $ChosenPlanModelCopyWith<$Res> {
_$ChosenPlanModelCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of ChosenPlanModel
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? id = null,
Object? optionType = null,
Object? startDate = null,
Object? chatId = null,
Object? plan = null,
}) {
return _then(_value.copyWith(
id: null == id
? _value.id
: id // ignore: cast_nullable_to_non_nullable
as int,
optionType: null == optionType
? _value.optionType
: optionType // ignore: cast_nullable_to_non_nullable
as String,
startDate: null == startDate
? _value.startDate
: startDate // ignore: cast_nullable_to_non_nullable
as DateTime,
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
abstract class _$$ChosenPlanModelImplCopyWith<$Res>
implements $ChosenPlanModelCopyWith<$Res> {
factory _$$ChosenPlanModelImplCopyWith(_$ChosenPlanModelImpl value,
$Res Function(_$ChosenPlanModelImpl) then) =
__$$ChosenPlanModelImplCopyWithImpl<$Res>;
@override
@useResult
$Res call(
{@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;
}
/// @nodoc
class __$$ChosenPlanModelImplCopyWithImpl<$Res>
extends _$ChosenPlanModelCopyWithImpl<$Res, _$ChosenPlanModelImpl>
implements _$$ChosenPlanModelImplCopyWith<$Res> {
__$$ChosenPlanModelImplCopyWithImpl(
_$ChosenPlanModelImpl _value, $Res Function(_$ChosenPlanModelImpl) _then)
: super(_value, _then);
/// Create a copy of ChosenPlanModel
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? id = null,
Object? optionType = null,
Object? startDate = null,
Object? chatId = null,
Object? plan = null,
}) {
return _then(_$ChosenPlanModelImpl(
id: null == id
? _value.id
: id // ignore: cast_nullable_to_non_nullable
as int,
optionType: null == optionType
? _value.optionType
: optionType // ignore: cast_nullable_to_non_nullable
as String,
startDate: null == startDate
? _value.startDate
: startDate // ignore: cast_nullable_to_non_nullable
as DateTime,
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,
));
}
}
/// @nodoc
@JsonSerializable()
class _$ChosenPlanModelImpl implements _ChosenPlanModel {
_$ChosenPlanModelImpl(
{@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});
factory _$ChosenPlanModelImpl.fromJson(Map<String, dynamic> json) =>
_$$ChosenPlanModelImplFromJson(json);
@override
@JsonKey()
final int id;
@override
@JsonKey(name: 'option_type')
final String optionType;
@override
@JsonKey(name: 'start_date')
final DateTime startDate;
@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)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$ChosenPlanModelImpl &&
(identical(other.id, id) || other.id == id) &&
(identical(other.optionType, optionType) ||
other.optionType == optionType) &&
(identical(other.startDate, startDate) ||
other.startDate == startDate) &&
(identical(other.chatId, chatId) || other.chatId == chatId) &&
(identical(other.plan, plan) || other.plan == plan));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode =>
Object.hash(runtimeType, id, optionType, startDate, chatId, plan);
/// Create a copy of ChosenPlanModel
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$ChosenPlanModelImplCopyWith<_$ChosenPlanModelImpl> get copyWith =>
__$$ChosenPlanModelImplCopyWithImpl<_$ChosenPlanModelImpl>(
this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$ChosenPlanModelImplToJson(
this,
);
}
}
abstract class _ChosenPlanModel implements ChosenPlanModel {
factory _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}) =
_$ChosenPlanModelImpl;
factory _ChosenPlanModel.fromJson(Map<String, dynamic> json) =
_$ChosenPlanModelImpl.fromJson;
@override
@JsonKey()
int get id;
@override
@JsonKey(name: 'option_type')
String get optionType;
@override
@JsonKey(name: 'start_date')
DateTime get startDate;
@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.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
_$$ChosenPlanModelImplCopyWith<_$ChosenPlanModelImpl> get copyWith =>
throw _privateConstructorUsedError;
}

View File

@@ -0,0 +1,27 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'chosen_plan_model.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_$ChosenPlanModelImpl _$$ChosenPlanModelImplFromJson(
Map<String, dynamic> json) =>
_$ChosenPlanModelImpl(
id: (json['id'] as num).toInt(),
optionType: json['option_type'] as String,
startDate: DateTime.parse(json['start_date'] as String),
chatId: json['chat_id'] as String,
plan: PlanModel.fromJson(json['plan'] as Map<String, dynamic>),
);
Map<String, dynamic> _$$ChosenPlanModelImplToJson(
_$ChosenPlanModelImpl instance) =>
<String, dynamic>{
'id': instance.id,
'option_type': instance.optionType,
'start_date': instance.startDate.toIso8601String(),
'chat_id': instance.chatId,
'plan': instance.plan,
};

View File

@@ -1,8 +1,10 @@
import 'dart:developer';
import 'package:dio/dio.dart';
import 'package:easy_debounce/easy_debounce.dart';
import 'package:eatvio_app/core/utils/toasts.dart';
import 'package:eatvio_app/features/diets/repositories/diet_repository.dart';
import 'package:eatvio_app/features/plans/models/chosen_plan_model.dart';
import 'package:eatvio_app/features/plans/presentation/cubit/about_plan_state.dart';
import 'package:eatvio_app/features/plans/repositories/plan_repository.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
@@ -125,4 +127,27 @@ class AboutPlanCubit extends Cubit<AboutPlanState> {
},
);
}
Future<ChosenPlanModel?> chosePlan() async {
try {
final slug = state.planModel?.slug;
final optionIndex = state.chosenOptionIndex;
if (slug != null) {
final optionName = _getOptionNameFromIndex(optionIndex);
final body = {'options_type': optionName};
return await planRepository.chosePlan(slug, body);
}
} on DioException catch (e, st) {
log(e.toString(), stackTrace: st);
} catch (e, st) {
log(e.toString(), stackTrace: st);
}
return null;
}
String _getOptionNameFromIndex(int index) => switch (index) {
1 => 'options2',
2 => 'options3',
_ => 'options1',
};
}

View File

@@ -10,6 +10,7 @@ import 'package:eatvio_app/core/widgets/bookmark_button.dart';
import 'package:eatvio_app/core/widgets/data_error_widget.dart';
import 'package:eatvio_app/core/widgets/info_row.dart';
import 'package:eatvio_app/core/widgets/loader.dart';
import 'package:eatvio_app/core/widgets/show_error_dialog.dart';
import 'package:eatvio_app/features/diets/presentation/widgets/author_card.dart';
import 'package:eatvio_app/features/diets/presentation/widgets/expandable_text.dart';
import 'package:eatvio_app/features/diets/presentation/widgets/info_bouble.dart';
@@ -30,6 +31,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_portal/flutter_portal.dart';
import 'package:flutter_svg/svg.dart';
import 'package:go_router/go_router.dart';
import '../widgets/option_widget.dart';
@@ -217,17 +219,21 @@ class _AboutPlanScreenState extends State<AboutPlanScreen> {
borderRadius: BorderRadius.circular(16),
),
backgroundColor: appTheme.greenA700,
onPressed: () {
/// TODO: добавить обработку покупки плана
// showModalBottomSheet(
// context: context,
// builder: (context) => StartDietBottomSheet(
// aboutDietCubit: context.read<AboutDietCubit>(),
// ),
// );
onPressed: () async {
final chosenPlan = await context.read<AboutPlanCubit>().chosePlan();
if (chosenPlan == null) {
showErrorDialog(context, title: 'Не удалось заказать план');
return;
}
GoRouter.of(context).pushReplacementNamed(
'chatScreen',
extra: {
'chatId': chosenPlan.chatId,
},
);
},
label: Text(
s.startDiet,
s.to_order,
style: TextStyles.textMSemibold.copyWith(color: appTheme.whiteA700),
),
),

View File

@@ -1,9 +1,9 @@
import 'dart:async';
import 'package:eatvio_app/features/diets/repositories/diet_repository.dart';
import 'package:eatvio_app/features/feed/models/plan_pagination_model.dart';
import 'package:eatvio_app/features/plans/models/chosen_plan_model.dart';
import 'package:eatvio_app/features/plans/services/plan_service.dart';
class PlanRepository {
final PlanService planService;
@@ -48,9 +48,15 @@ class PlanRepository {
}
}
Future<ChosenPlanModel> chosePlan(String slug, Map<String, dynamic> option ) async {
try {
return await planService.chosePlan(slug: slug, option: option);
} catch (e) {
rethrow;
}
}
void emitLikesStateToFeed(LikesState state) => _planLikeStateStreamController.add(state);
void emitFavoriteStateToFeed(FavoriteState state) => _planFavoriteStateStreamController.add(state);
void emitCommentsStateToFeed(CommentsState state) => _planCommentsStateStreamController.add(state);
}

View File

@@ -1,20 +1,18 @@
import 'package:dio/dio.dart';
import 'package:eatvio_app/features/feed/models/plan_pagination_model.dart';
import 'package:eatvio_app/features/plans/models/chosen_plan_model.dart';
import 'package:retrofit/retrofit.dart';
part 'plan_service.g.dart';
@RestApi()
abstract class PlanService {
factory PlanService(Dio dio, {String baseUrl}) = _PlanService;
@GET('/api/plans/show/{slug}')
Future<PlanModel> getPlan(@Path('slug') String slug);
@POST('/api/plans/{slug}/like')
@POST('/api/plans/{slug}/like')
Future<void> likePlan({
@Path() required String slug,
});
@@ -28,4 +26,10 @@ abstract class PlanService {
Future<void> removeFromFavorite({
@Path() required String slug,
});
}
@POST('/api/plans/{slug}/choose')
Future<ChosenPlanModel> chosePlan({
@Path() required String slug,
@Body() required Map<String, dynamic> option,
});
}

View File

@@ -101,6 +101,37 @@ class _PlanService implements PlanService {
await _dio.fetch<void>(_options);
}
@override
Future<ChosenPlanModel> chosePlan({
required String slug,
required Map<String, dynamic> option,
}) async {
final _extra = <String, dynamic>{};
final queryParameters = <String, dynamic>{};
final _headers = <String, dynamic>{};
final _data = <String, dynamic>{};
_data.addAll(option);
final _options = _setStreamType<ChosenPlanModel>(
Options(method: 'POST', headers: _headers, extra: _extra)
.compose(
_dio.options,
'/api/plans/${slug}/choose',
queryParameters: queryParameters,
data: _data,
)
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
);
final _result = await _dio.fetch<Map<String, dynamic>>(_options);
late ChosenPlanModel _value;
try {
_value = ChosenPlanModel.fromJson(_result.data!);
} on Object catch (e, s) {
errorLogger?.logError(e, s, _options);
rethrow;
}
return _value;
}
RequestOptions _setStreamType<T>(RequestOptions requestOptions) {
if (T != dynamic &&
!(requestOptions.responseType == ResponseType.bytes ||

View File

@@ -32,6 +32,7 @@ class MessageLookup extends MessageLookupByLibrary {
"Кол-во активных консультаций"),
"active_diet_state": MessageLookupByLibrary.simpleMessage("Активная"),
"add": MessageLookupByLibrary.simpleMessage("Добавить"),
"add_card": MessageLookupByLibrary.simpleMessage("Привязать карту"),
"add_cover": MessageLookupByLibrary.simpleMessage("Добавьте обложку"),
"add_measure": MessageLookupByLibrary.simpleMessage("Добавить замер"),
"adding_plan": MessageLookupByLibrary.simpleMessage("Добавление плана"),
@@ -58,6 +59,8 @@ class MessageLookup extends MessageLookupByLibrary {
"calls_for_bullying":
MessageLookupByLibrary.simpleMessage("Призывы к травле"),
"calories": MessageLookupByLibrary.simpleMessage("Калории"),
"can_not_choose_start_date": MessageLookupByLibrary.simpleMessage(
"Дату старта плана невозможно выбрать, пока Вы не привяжите карту"),
"can_not_load_data_please_try_again":
MessageLookupByLibrary.simpleMessage(
"Не удалось загрузить данные. Попробуйте обновить страницу"),
@@ -72,10 +75,13 @@ class MessageLookup extends MessageLookupByLibrary {
"chest": MessageLookupByLibrary.simpleMessage("Грудь"),
"chest_circumference":
MessageLookupByLibrary.simpleMessage("Обхват груди"),
"choose_date": MessageLookupByLibrary.simpleMessage("Выбрать дату"),
"choose_diet_duration":
MessageLookupByLibrary.simpleMessage("Выберите срок диеты"),
"choose_plan_duration":
MessageLookupByLibrary.simpleMessage("Выберите срок плана"),
"choose_plan_start_date": MessageLookupByLibrary.simpleMessage(
"Выберите дату старта плана питания"),
"choose_start_diet_date": MessageLookupByLibrary.simpleMessage(
"Выберите дату старты диеты. Она отобразиться у Вас в дневнике"),
"circumference_empty": MessageLookupByLibrary.simpleMessage(
@@ -130,6 +136,8 @@ class MessageLookup extends MessageLookupByLibrary {
"create_diet": MessageLookupByLibrary.simpleMessage("Создание диеты"),
"customer_price":
MessageLookupByLibrary.simpleMessage("Цена для покупателя"),
"date_has_ben_set": MessageLookupByLibrary.simpleMessage(
"Дата старта начала консультации установлена"),
"date_of_birth": MessageLookupByLibrary.simpleMessage("Дата рождения"),
"day": MessageLookupByLibrary.simpleMessage("День"),
"days": MessageLookupByLibrary.simpleMessage("дней"),
@@ -327,6 +335,7 @@ class MessageLookup extends MessageLookupByLibrary {
"Пароль обязателен для заполнения"),
"password_short": MessageLookupByLibrary.simpleMessage(
"В пароле должно быть минимум 6 символов"),
"pay": MessageLookupByLibrary.simpleMessage("Оплатить"),
"pcs": MessageLookupByLibrary.simpleMessage("шт"),
"personal": MessageLookupByLibrary.simpleMessage("Персональные"),
"personal_diet_state":
@@ -424,6 +433,7 @@ class MessageLookup extends MessageLookupByLibrary {
"time": MessageLookupByLibrary.simpleMessage("Время прохождения"),
"toOffer": MessageLookupByLibrary.simpleMessage("Предложить"),
"to_draft": MessageLookupByLibrary.simpleMessage("В черновик"),
"to_order": MessageLookupByLibrary.simpleMessage("Заказать"),
"try_again": MessageLookupByLibrary.simpleMessage("Попробовать снова"),
"type_here_your_complaint":
MessageLookupByLibrary.simpleMessage("Напишите здесь свою жалобу"),

View File

@@ -3179,6 +3179,78 @@ class S {
args: [],
);
}
/// `Заказать`
String get to_order {
return Intl.message(
'Заказать',
name: 'to_order',
desc: '',
args: [],
);
}
/// `Дату старта плана невозможно выбрать, пока Вы не привяжите карту`
String get can_not_choose_start_date {
return Intl.message(
'Дату старта плана невозможно выбрать, пока Вы не привяжите карту',
name: 'can_not_choose_start_date',
desc: '',
args: [],
);
}
/// `Привязать карту`
String get add_card {
return Intl.message(
'Привязать карту',
name: 'add_card',
desc: '',
args: [],
);
}
/// `Выберите дату старта плана питания`
String get choose_plan_start_date {
return Intl.message(
'Выберите дату старта плана питания',
name: 'choose_plan_start_date',
desc: '',
args: [],
);
}
/// `Выбрать дату`
String get choose_date {
return Intl.message(
'Выбрать дату',
name: 'choose_date',
desc: '',
args: [],
);
}
/// `Дата старта начала консультации установлена`
String get date_has_ben_set {
return Intl.message(
'Дата старта начала консультации установлена',
name: 'date_has_ben_set',
desc: '',
args: [],
);
}
// skipped getter for the 'tap_on_link_to)pay' key
/// `Оплатить`
String get pay {
return Intl.message(
'Оплатить',
name: 'pay',
desc: '',
args: [],
);
}
}
class AppLocalizationDelegate extends LocalizationsDelegate<S> {

View File

@@ -311,6 +311,15 @@
"could_not_update_diet": "Не удалось обновить диету",
"could_not_publish_blog_post": "Не удалось опубликовать пост",
"could_not_update_blog_post": "Не удалось обновить пост",
"could_not_delete_blog_post": "Не удалось удалить пост"
"could_not_delete_blog_post": "Не удалось удалить пост",
"to_order": "Заказать",
"can_not_choose_start_date": "Дату старта плана невозможно выбрать, пока Вы не привяжите карту",
"add_card": "Привязать карту",
"choose_plan_start_date": "Выберите дату старта плана питания",
"choose_date": "Выбрать дату",
"date_has_ben_set": "Дата старта начала консультации установлена",
"tap_on_link_to)pay": "Перейдите по ссылке для оплаты консультации",
"pay": "Оплатить"
}