forked from eatvio/eatvio_app
merge upstream
This commit is contained in:
11
ios/Podfile
11
ios/Podfile
@@ -40,6 +40,17 @@ post_install do |installer|
|
|||||||
target.build_configurations.each do |config|
|
target.build_configurations.each do |config|
|
||||||
config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"] = "arm64"
|
config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"] = "arm64"
|
||||||
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '14.0'
|
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '14.0'
|
||||||
|
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
|
||||||
|
'$(inherited)',
|
||||||
|
## dart: PermissionGroup.camera
|
||||||
|
'PERMISSION_CAMERA=1',
|
||||||
|
## dart: PermissionGroup.photos
|
||||||
|
'PERMISSION_PHOTOS=1',
|
||||||
|
'PERMISSION_NOTIFICATIONS=1',
|
||||||
|
## dart: PermissionGroup.mediaLibrary
|
||||||
|
'PERMISSION_MEDIA_LIBRARY=1',
|
||||||
|
]
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ import 'package:eatvio_app/features/chat/presentation/pages/photo_view_screen.da
|
|||||||
import 'package:eatvio_app/features/consultant/become_consultant/presentation/pages/become_consultant_screen.dart';
|
import 'package:eatvio_app/features/consultant/become_consultant/presentation/pages/become_consultant_screen.dart';
|
||||||
import 'package:eatvio_app/features/consultant/become_consultant/presentation/pages/stepper_become_consultant_screen.dart';
|
import 'package:eatvio_app/features/consultant/become_consultant/presentation/pages/stepper_become_consultant_screen.dart';
|
||||||
import 'package:eatvio_app/features/consultations/presentation/pages/consultations_screen.dart';
|
import 'package:eatvio_app/features/consultations/presentation/pages/consultations_screen.dart';
|
||||||
|
import 'package:eatvio_app/features/finances_and_consultations_archive/presentation/consultant_finances_screen.dart';
|
||||||
|
import 'package:eatvio_app/features/finances_and_consultations_archive/presentation/user_purchases_screen.dart';
|
||||||
import 'package:eatvio_app/features/order_info/presentation/info_by_order_screen.dart';
|
import 'package:eatvio_app/features/order_info/presentation/info_by_order_screen.dart';
|
||||||
import 'package:eatvio_app/features/create_diet/presentation/create_diet_screen.dart';
|
import 'package:eatvio_app/features/create_diet/presentation/create_diet_screen.dart';
|
||||||
import 'package:eatvio_app/features/create_diet/presentation/diet_preview_screen.dart';
|
import 'package:eatvio_app/features/create_diet/presentation/diet_preview_screen.dart';
|
||||||
@@ -210,10 +212,20 @@ class AppRouter {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: '/consultant-finance-screen',
|
path: ConsultationsArchiveScreen.path,
|
||||||
name: 'consultantFinanceScreen',
|
name: ConsultationsArchiveScreen.name,
|
||||||
builder: (context, state) => const ConsultationsArchiveScreen(),
|
builder: (context, state) => const ConsultationsArchiveScreen(),
|
||||||
),
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: ConsultantFinancesScreen.path,
|
||||||
|
name: ConsultantFinancesScreen.name,
|
||||||
|
builder: (context, state) => const ConsultantFinancesScreen(),
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: UserPurchasesScreen.path,
|
||||||
|
name: UserPurchasesScreen.name,
|
||||||
|
builder: (context, state) => const UserPurchasesScreen(),
|
||||||
|
),
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: '/user-finance-screen',
|
path: '/user-finance-screen',
|
||||||
name: 'userFinanceScreen',
|
name: 'userFinanceScreen',
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ import 'package:eatvio_app/features/blog_post_create/bloc/blog_post_create_cubit
|
|||||||
import 'package:eatvio_app/features/blog_post_create/repositories/blog_post_repository.dart';
|
import 'package:eatvio_app/features/blog_post_create/repositories/blog_post_repository.dart';
|
||||||
import 'package:eatvio_app/features/blog_post_create/services/blog_post_service.dart';
|
import 'package:eatvio_app/features/blog_post_create/services/blog_post_service.dart';
|
||||||
import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/new_messages_cubit/new_messages_cubit.dart';
|
import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/new_messages_cubit/new_messages_cubit.dart';
|
||||||
|
import 'package:eatvio_app/features/finances_and_consultations_archive/cubit/consultant_finances/consultant_finances_cubit.dart';
|
||||||
|
import 'package:eatvio_app/features/finances_and_consultations_archive/cubit/user_purchases/user_purchases_cubit.dart';
|
||||||
import 'package:eatvio_app/features/notifications/presentation/notifications_cubit/notifications_cubit.dart';
|
import 'package:eatvio_app/features/notifications/presentation/notifications_cubit/notifications_cubit.dart';
|
||||||
import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/profile_avatar_cubit/profile_avatar_cubit.dart';
|
import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/profile_avatar_cubit/profile_avatar_cubit.dart';
|
||||||
import 'package:eatvio_app/features/calendar/presentation/bloc/calendar_cubit.dart';
|
import 'package:eatvio_app/features/calendar/presentation/bloc/calendar_cubit.dart';
|
||||||
@@ -123,8 +125,14 @@ Future<void> init() async {
|
|||||||
sl.registerFactory<PlansCubit>(() => PlansCubit(feedRepository: sl(), planRepository: sl()));
|
sl.registerFactory<PlansCubit>(() => PlansCubit(feedRepository: sl(), planRepository: sl()));
|
||||||
sl.registerFactory<SettingsCubit>(() => SettingsCubit(profileRepository: sl(), settingsRepository: sl(), consultantRepository: sl()));
|
sl.registerFactory<SettingsCubit>(() => SettingsCubit(profileRepository: sl(), settingsRepository: sl(), consultantRepository: sl()));
|
||||||
sl.registerFactory<RegisterConsultantCubit>(() => RegisterConsultantCubit(consultantRepository: sl()));
|
sl.registerFactory<RegisterConsultantCubit>(() => RegisterConsultantCubit(consultantRepository: sl()));
|
||||||
sl.registerFactory<DiaryCubit>(
|
sl.registerFactory<DiaryCubit>(() => DiaryCubit(
|
||||||
() => DiaryCubit(chatRepository: sl(), diaryRepository: sl(), glossaryRepository: sl(), profileRepository: sl(), dietRepository: sl()));
|
chatRepository: sl(),
|
||||||
|
diaryRepository: sl(),
|
||||||
|
glossaryRepository: sl(),
|
||||||
|
profileRepository: sl(),
|
||||||
|
dietRepository: sl(),
|
||||||
|
settingsRepository: sl(),
|
||||||
|
));
|
||||||
sl.registerFactory<AboutDietCubit>(() => AboutDietCubit(dietsRepository: sl(), profileRepository: sl()));
|
sl.registerFactory<AboutDietCubit>(() => AboutDietCubit(dietsRepository: sl(), profileRepository: sl()));
|
||||||
sl.registerFactory<BlogPostCreateCubit>(() => BlogPostCreateCubit(blogPostRepository: sl()));
|
sl.registerFactory<BlogPostCreateCubit>(() => BlogPostCreateCubit(blogPostRepository: sl()));
|
||||||
sl.registerFactory<SubCubit>(() => SubCubit(profileRepository: sl()));
|
sl.registerFactory<SubCubit>(() => SubCubit(profileRepository: sl()));
|
||||||
@@ -148,6 +156,8 @@ Future<void> init() async {
|
|||||||
sl.registerFactory<VerifyEmailCubit>(() => VerifyEmailCubit(profileRepository: sl()));
|
sl.registerFactory<VerifyEmailCubit>(() => VerifyEmailCubit(profileRepository: sl()));
|
||||||
sl.registerFactory<MyRecipesCubit>(() => MyRecipesCubit(myRecipesRepository: sl(), aboutRecipeRepository: sl()));
|
sl.registerFactory<MyRecipesCubit>(() => MyRecipesCubit(myRecipesRepository: sl(), aboutRecipeRepository: sl()));
|
||||||
sl.registerFactory<ConsultationsArchiveCubit>(() => ConsultationsArchiveCubit(consultationsRepository: sl()));
|
sl.registerFactory<ConsultationsArchiveCubit>(() => ConsultationsArchiveCubit(consultationsRepository: sl()));
|
||||||
|
sl.registerFactory<ConsultantFinancesCubit>(() => ConsultantFinancesCubit(consultationsRepository: sl()));
|
||||||
|
sl.registerFactory<UserPurchasesCubit>(() => UserPurchasesCubit(consultationsRepository: sl()));
|
||||||
|
|
||||||
// Repository
|
// Repository
|
||||||
sl.registerLazySingleton<ChatRepository>(() => ChatRepository(chatService: sl()));
|
sl.registerLazySingleton<ChatRepository>(() => ChatRepository(chatService: sl()));
|
||||||
|
|||||||
23
lib/core/permission_handler/permission_handler.dart
Normal file
23
lib/core/permission_handler/permission_handler.dart
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import 'package:eatvio_app/core/widgets/show_error_dialog.dart';
|
||||||
|
import 'package:eatvio_app/generated/l10n.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:permission_handler/permission_handler.dart';
|
||||||
|
|
||||||
|
class PermissionHandler {
|
||||||
|
static Future<void> checkPermission({
|
||||||
|
required Permission permission,
|
||||||
|
required String title,
|
||||||
|
required String description,
|
||||||
|
required Future<void> Function() onGranted,
|
||||||
|
required BuildContext context,
|
||||||
|
}) async {
|
||||||
|
final permissionState = await permission.request();
|
||||||
|
if (permissionState.isGranted) {
|
||||||
|
await onGranted();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (context.mounted) {
|
||||||
|
showErrorDialog(context, title: title, description: description, buttonTitle: S.of(context).allowAccess, needToOpenSettings: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,8 +4,9 @@ import 'package:eatvio_app/core/theme/theme_helper.dart';
|
|||||||
import 'package:eatvio_app/generated/l10n.dart';
|
import 'package:eatvio_app/generated/l10n.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
|
import 'package:permission_handler/permission_handler.dart';
|
||||||
|
|
||||||
Future<void> showErrorDialog(BuildContext context, {String? title, String? description}) async {
|
Future<void> showErrorDialog(BuildContext context, {String? title, String? description, String? buttonTitle, bool? needToOpenSettings}) async {
|
||||||
return await showDialog<void>(
|
return await showDialog<void>(
|
||||||
context: context,
|
context: context,
|
||||||
barrierColor: Colors.transparent,
|
barrierColor: Colors.transparent,
|
||||||
@@ -43,8 +44,13 @@ Future<void> showErrorDialog(BuildContext context, {String? title, String? descr
|
|||||||
Align(
|
Align(
|
||||||
alignment: Alignment.centerRight,
|
alignment: Alignment.centerRight,
|
||||||
child: TextButton(
|
child: TextButton(
|
||||||
onPressed: () => AppRouter.navigatorKey.currentContext?.pop(),
|
onPressed: () {
|
||||||
child: Text(s.ok, style: TextStyles.textLSemibold.copyWith(color: appTheme.blueA400)),
|
AppRouter.navigatorKey.currentContext?.pop();
|
||||||
|
if (needToOpenSettings ?? false) {
|
||||||
|
openAppSettings();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Text(buttonTitle ?? s.ok, style: TextStyles.textLSemibold.copyWith(color: appTheme.blueA400)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
import 'package:eatvio_app/core/app_router.dart';
|
||||||
import 'package:eatvio_app/core/const.dart';
|
import 'package:eatvio_app/core/const.dart';
|
||||||
|
import 'package:eatvio_app/core/permission_handler/permission_handler.dart';
|
||||||
import 'package:eatvio_app/core/theme/app_decoration.dart';
|
import 'package:eatvio_app/core/theme/app_decoration.dart';
|
||||||
import 'package:eatvio_app/core/widgets/show_error_dialog.dart';
|
import 'package:eatvio_app/core/widgets/show_error_dialog.dart';
|
||||||
import 'package:eatvio_app/features/blog_post_create/bloc/blog_post_create_cubit/blog_post_create_cubit.dart';
|
import 'package:eatvio_app/features/blog_post_create/bloc/blog_post_create_cubit/blog_post_create_cubit.dart';
|
||||||
@@ -17,6 +19,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||||||
import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart';
|
import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
|
import 'package:permission_handler/permission_handler.dart';
|
||||||
|
|
||||||
class BlogPostCreateScreen extends StatefulWidget {
|
class BlogPostCreateScreen extends StatefulWidget {
|
||||||
final FeedBlogPostModel? feedBlogPostModel;
|
final FeedBlogPostModel? feedBlogPostModel;
|
||||||
@@ -80,47 +83,65 @@ class _BlogPostCreateScreenState extends State<BlogPostCreateScreen> {
|
|||||||
_showImagePicker() {
|
_showImagePicker() {
|
||||||
showCupertinoModalPopup<void>(
|
showCupertinoModalPopup<void>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => CupertinoActionSheet(
|
builder: (context) {
|
||||||
actions: [
|
final s = S.of(context);
|
||||||
CupertinoActionSheetAction(
|
return CupertinoActionSheet(
|
||||||
onPressed: () async {
|
actions: [
|
||||||
final picker = ImagePicker();
|
CupertinoActionSheetAction(
|
||||||
image = await picker.pickImage(source: ImageSource.camera);
|
onPressed: () async {
|
||||||
setState(() {});
|
PermissionHandler.checkPermission(
|
||||||
if (!context.mounted) return;
|
permission: Permission.camera,
|
||||||
Navigator.of(context).pop();
|
title: s.allowAccessToCamera,
|
||||||
},
|
description: s.allowAccessToCameraDescription,
|
||||||
child: const Row(
|
onGranted: () async {
|
||||||
children: [
|
final picker = ImagePicker();
|
||||||
Icon(Icons.photo_camera),
|
image = await picker.pickImage(source: ImageSource.camera);
|
||||||
SizedBox(width: 8),
|
setState(() {});
|
||||||
Text('Фото'),
|
AppRouter.navigatorKey.currentContext?.pop();
|
||||||
],
|
},
|
||||||
|
context: context,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: const Row(
|
||||||
|
children: [
|
||||||
|
Icon(Icons.photo_camera),
|
||||||
|
SizedBox(width: 8),
|
||||||
|
Text('Фото'),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
CupertinoActionSheetAction(
|
||||||
CupertinoActionSheetAction(
|
onPressed: () async {
|
||||||
onPressed: () async {
|
PermissionHandler.checkPermission(
|
||||||
final picker = ImagePicker();
|
permission: Permission.photos,
|
||||||
image = await picker.pickImage(source: ImageSource.gallery);
|
title: s.allowAcessToGalery,
|
||||||
setState(() {});
|
description: s.allowAcessToGaleryDescription,
|
||||||
if (!context.mounted) return;
|
onGranted: () async {
|
||||||
Navigator.of(context).pop();
|
final picker = ImagePicker();
|
||||||
},
|
image = await picker.pickImage(source: ImageSource.gallery);
|
||||||
child: const Row(
|
setState(() {});
|
||||||
children: [
|
if (!context.mounted) return;
|
||||||
Icon(Icons.photo),
|
AppRouter.navigatorKey.currentContext?.pop();
|
||||||
SizedBox(width: 8),
|
},
|
||||||
Text('Галерея'),
|
context: context,
|
||||||
],
|
);
|
||||||
|
},
|
||||||
|
child: const Row(
|
||||||
|
children: [
|
||||||
|
Icon(Icons.photo),
|
||||||
|
SizedBox(width: 8),
|
||||||
|
Text('Галерея'),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
|
],
|
||||||
|
cancelButton: CupertinoActionSheetAction(
|
||||||
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
|
isDestructiveAction: true,
|
||||||
|
child: const Text('Отмена'),
|
||||||
),
|
),
|
||||||
],
|
);
|
||||||
cancelButton: CupertinoActionSheetAction(
|
},
|
||||||
onPressed: () => Navigator.of(context).pop(),
|
|
||||||
isDestructiveAction: true,
|
|
||||||
child: const Text('Отмена'),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import 'package:eatvio_app/core/widgets/loader.dart';
|
|||||||
import 'package:eatvio_app/features/consultations/presentation/cubit/consultations_cubit.dart';
|
import 'package:eatvio_app/features/consultations/presentation/cubit/consultations_cubit.dart';
|
||||||
import 'package:eatvio_app/features/consultations/presentation/cubit/consultations_state.dart';
|
import 'package:eatvio_app/features/consultations/presentation/cubit/consultations_state.dart';
|
||||||
import 'package:eatvio_app/features/consultations/presentation/widgets/consultation_card_widget.dart';
|
import 'package:eatvio_app/features/consultations/presentation/widgets/consultation_card_widget.dart';
|
||||||
|
import 'package:eatvio_app/features/finances_and_consultations_archive/presentation/consultations_archive_screen.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
@@ -67,7 +68,7 @@ class ConsultationsContent extends StatelessWidget {
|
|||||||
InkWell(
|
InkWell(
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
GoRouter.of(context).pushNamed('consultantFinanceScreen');
|
GoRouter.of(context).pushNamed(ConsultationsArchiveScreen.name);
|
||||||
},
|
},
|
||||||
child: Ink(
|
child: Ink(
|
||||||
width: MediaQuery.of(context).size.width - 32,
|
width: MediaQuery.of(context).size.width - 32,
|
||||||
|
|||||||
@@ -185,6 +185,8 @@ class _ConsultationCardWidgetState extends State<ConsultationCardWidget> {
|
|||||||
children: List.generate(widget.consultationsModel.duration, (index) {
|
children: List.generate(widget.consultationsModel.duration, (index) {
|
||||||
final day = givenDaysWithDayNumber.firstWhereOrNull((e) => e.$1 == index);
|
final day = givenDaysWithDayNumber.firstWhereOrNull((e) => e.$1 == index);
|
||||||
final hasActivity = day != null && day.$2.state != DiaryStateEnum.init;
|
final hasActivity = day != null && day.$2.state != DiaryStateEnum.init;
|
||||||
|
final canConsultantOpenThisDay = day != null &&
|
||||||
|
(day.$2.state != DiaryStateEnum.init && day.$2.state != DiaryStateEnum.started && day.$2.state != DiaryStateEnum.lastDayStarted);
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.only(right: 12),
|
padding: const EdgeInsets.only(right: 12),
|
||||||
child: Column(
|
child: Column(
|
||||||
@@ -192,7 +194,7 @@ class _ConsultationCardWidgetState extends State<ConsultationCardWidget> {
|
|||||||
children: [
|
children: [
|
||||||
InkWell(
|
InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
if (!hasActivity) {
|
if (!hasActivity || !canConsultantOpenThisDay) {
|
||||||
showErrorDialog(context,
|
showErrorDialog(context,
|
||||||
title: s.you_can_not_open_this_day, description: '${widget.consultationsModel.userName} ${s.has_not_filled_it_yet}');
|
title: s.you_can_not_open_this_day, description: '${widget.consultationsModel.userName} ${s.has_not_filled_it_yet}');
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import 'package:eatvio_app/core/enums/filters_comparison_enum.dart';
|
import 'package:eatvio_app/core/enums/filters_comparison_enum.dart';
|
||||||
import 'package:eatvio_app/features/consultations/models/consultation_model.dart';
|
import 'package:eatvio_app/features/consultations/models/consultation_model.dart';
|
||||||
import 'package:eatvio_app/features/consultations/services/consultation_service.dart';
|
import 'package:eatvio_app/features/consultations/services/consultation_service.dart';
|
||||||
|
import 'package:eatvio_app/features/finances_and_consultations_archive/models/consultant_finance_model.dart';
|
||||||
import 'package:eatvio_app/features/finances_and_consultations_archive/models/statistic_model.dart';
|
import 'package:eatvio_app/features/finances_and_consultations_archive/models/statistic_model.dart';
|
||||||
|
import 'package:eatvio_app/features/finances_and_consultations_archive/models/user_purchases_model.dart';
|
||||||
|
|
||||||
class ConsultationsRepository {
|
class ConsultationsRepository {
|
||||||
final ConsultationService consultationService;
|
final ConsultationService consultationService;
|
||||||
@@ -42,4 +44,20 @@ class ConsultationsRepository {
|
|||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<List<ConsultantFinanceModel>> getConsultantFinances(String? date, FiltersComparisonEnum? dateComparison) async {
|
||||||
|
try {
|
||||||
|
return await consultationService.getConsultantFinances(date, dateComparison);
|
||||||
|
} catch (e) {
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<UserPurchasesModel>> getUserPurchases(String? date, FiltersComparisonEnum? dateComparison) async {
|
||||||
|
try {
|
||||||
|
return await consultationService.getUserPurchases(date, dateComparison);
|
||||||
|
} catch (e) {
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:eatvio_app/core/enums/filters_comparison_enum.dart';
|
import 'package:eatvio_app/core/enums/filters_comparison_enum.dart';
|
||||||
import 'package:eatvio_app/features/consultations/models/consultation_model.dart';
|
import 'package:eatvio_app/features/consultations/models/consultation_model.dart';
|
||||||
|
import 'package:eatvio_app/features/finances_and_consultations_archive/models/consultant_finance_model.dart';
|
||||||
import 'package:eatvio_app/features/finances_and_consultations_archive/models/statistic_model.dart';
|
import 'package:eatvio_app/features/finances_and_consultations_archive/models/statistic_model.dart';
|
||||||
|
import 'package:eatvio_app/features/finances_and_consultations_archive/models/user_purchases_model.dart';
|
||||||
|
|
||||||
class ConsultationService {
|
class ConsultationService {
|
||||||
final Dio dio;
|
final Dio dio;
|
||||||
@@ -66,4 +68,42 @@ class ConsultationService {
|
|||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<List<ConsultantFinanceModel>> getConsultantFinances(
|
||||||
|
String? date,
|
||||||
|
FiltersComparisonEnum? dateComparison,
|
||||||
|
) async {
|
||||||
|
try {
|
||||||
|
final response = await dio.get(
|
||||||
|
'/api/finances/my_finances',
|
||||||
|
queryParameters: {
|
||||||
|
if (dateComparison != null && date != null) 'filters[end_date]': date,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
final data = response.data as Map<String, dynamic>;
|
||||||
|
final consultations = data['data'] as List<dynamic>;
|
||||||
|
return consultations.map((consultation) => ConsultantFinanceModel.fromJson(consultation as Map<String, dynamic>)).toList();
|
||||||
|
} catch (e) {
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<UserPurchasesModel>> getUserPurchases(
|
||||||
|
String? date,
|
||||||
|
FiltersComparisonEnum? dateComparison,
|
||||||
|
) async {
|
||||||
|
try {
|
||||||
|
final response = await dio.get(
|
||||||
|
'/api/finances/my_purchases',
|
||||||
|
queryParameters: {
|
||||||
|
if (dateComparison != null && date != null) 'filters[start_date]': date,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
final data = response.data as Map<String, dynamic>;
|
||||||
|
final purchases = data['data'] as List<dynamic>;
|
||||||
|
return purchases.map((purchase) => UserPurchasesModel.fromJson(purchase as Map<String, dynamic>)).toList();
|
||||||
|
} catch (e) {
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:dotted_border/dotted_border.dart';
|
import 'package:dotted_border/dotted_border.dart';
|
||||||
|
import 'package:eatvio_app/core/app_router.dart';
|
||||||
|
import 'package:eatvio_app/core/permission_handler/permission_handler.dart';
|
||||||
import 'package:eatvio_app/core/theme/custom_text_style.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/theme/theme_helper.dart';
|
||||||
import 'package:eatvio_app/features/create_diet/presentation/cubit/create_diet_cubit.dart';
|
import 'package:eatvio_app/features/create_diet/presentation/cubit/create_diet_cubit.dart';
|
||||||
@@ -11,7 +13,9 @@ import 'package:flutter/cupertino.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
|
import 'package:permission_handler/permission_handler.dart';
|
||||||
|
|
||||||
class DietImagePickerWidget extends StatefulWidget {
|
class DietImagePickerWidget extends StatefulWidget {
|
||||||
const DietImagePickerWidget({super.key});
|
const DietImagePickerWidget({super.key});
|
||||||
@@ -28,11 +32,18 @@ class _DietImagePickerWidgetState extends State<DietImagePickerWidget> {
|
|||||||
actions: [
|
actions: [
|
||||||
CupertinoActionSheetAction(
|
CupertinoActionSheetAction(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
final picker = ImagePicker();
|
PermissionHandler.checkPermission(
|
||||||
final image = await picker.pickImage(source: ImageSource.camera);
|
permission: Permission.camera,
|
||||||
cubit.setImage(image);
|
title: s.allowAccessToCamera,
|
||||||
if (!context.mounted) return;
|
description: s.allowAccessToCameraDescription,
|
||||||
Navigator.of(context).pop();
|
onGranted: () async {
|
||||||
|
final picker = ImagePicker();
|
||||||
|
final image = await picker.pickImage(source: ImageSource.camera);
|
||||||
|
cubit.setImage(image);
|
||||||
|
AppRouter.navigatorKey.currentContext?.pop();
|
||||||
|
},
|
||||||
|
context: context,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
@@ -44,11 +55,18 @@ class _DietImagePickerWidgetState extends State<DietImagePickerWidget> {
|
|||||||
),
|
),
|
||||||
CupertinoActionSheetAction(
|
CupertinoActionSheetAction(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
final picker = ImagePicker();
|
PermissionHandler.checkPermission(
|
||||||
final image = await picker.pickImage(source: ImageSource.gallery);
|
permission: Permission.photos,
|
||||||
cubit.setImage(image);
|
title: s.allowAcessToGalery,
|
||||||
if (!context.mounted) return;
|
description: s.allowAcessToGaleryDescription,
|
||||||
Navigator.of(context).pop();
|
onGranted: () async {
|
||||||
|
final picker = ImagePicker();
|
||||||
|
final image = await picker.pickImage(source: ImageSource.gallery);
|
||||||
|
cubit.setImage(image);
|
||||||
|
AppRouter.navigatorKey.currentContext?.pop();
|
||||||
|
},
|
||||||
|
context: context,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:dotted_border/dotted_border.dart';
|
import 'package:dotted_border/dotted_border.dart';
|
||||||
|
import 'package:eatvio_app/core/app_router.dart';
|
||||||
|
import 'package:eatvio_app/core/permission_handler/permission_handler.dart';
|
||||||
import 'package:eatvio_app/core/theme/custom_text_style.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/theme/theme_helper.dart';
|
||||||
import 'package:eatvio_app/features/create_diet/presentation/widgets/error_widget.dart';
|
import 'package:eatvio_app/features/create_diet/presentation/widgets/error_widget.dart';
|
||||||
@@ -11,7 +13,9 @@ import 'package:flutter/cupertino.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
|
import 'package:permission_handler/permission_handler.dart';
|
||||||
|
|
||||||
class PlanImagePickerWidget extends StatefulWidget {
|
class PlanImagePickerWidget extends StatefulWidget {
|
||||||
const PlanImagePickerWidget({super.key});
|
const PlanImagePickerWidget({super.key});
|
||||||
@@ -28,11 +32,18 @@ class _PlanImagePickerWidgetState extends State<PlanImagePickerWidget> {
|
|||||||
actions: [
|
actions: [
|
||||||
CupertinoActionSheetAction(
|
CupertinoActionSheetAction(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
final picker = ImagePicker();
|
PermissionHandler.checkPermission(
|
||||||
final image = await picker.pickImage(source: ImageSource.camera);
|
permission: Permission.camera,
|
||||||
cubit.setImage(image);
|
title: s.allowAccessToCamera,
|
||||||
if (!context.mounted) return;
|
description: s.allowAccessToCameraDescription,
|
||||||
Navigator.of(context).pop();
|
onGranted: () async {
|
||||||
|
final picker = ImagePicker();
|
||||||
|
final image = await picker.pickImage(source: ImageSource.camera);
|
||||||
|
cubit.setImage(image);
|
||||||
|
AppRouter.navigatorKey.currentContext?.pop();
|
||||||
|
},
|
||||||
|
context: context,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
@@ -44,11 +55,18 @@ class _PlanImagePickerWidgetState extends State<PlanImagePickerWidget> {
|
|||||||
),
|
),
|
||||||
CupertinoActionSheetAction(
|
CupertinoActionSheetAction(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
final picker = ImagePicker();
|
PermissionHandler.checkPermission(
|
||||||
final image = await picker.pickImage(source: ImageSource.gallery);
|
permission: Permission.photos,
|
||||||
cubit.setImage(image);
|
title: s.allowAcessToGalery,
|
||||||
if (!context.mounted) return;
|
description: s.allowAcessToGaleryDescription,
|
||||||
Navigator.of(context).pop();
|
onGranted: () async {
|
||||||
|
final picker = ImagePicker();
|
||||||
|
final image = await picker.pickImage(source: ImageSource.gallery);
|
||||||
|
cubit.setImage(image);
|
||||||
|
AppRouter.navigatorKey.currentContext?.pop();
|
||||||
|
},
|
||||||
|
context: context,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
|
|||||||
@@ -1,11 +1,16 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:eatvio_app/core/app_router.dart';
|
||||||
|
import 'package:eatvio_app/core/permission_handler/permission_handler.dart';
|
||||||
import 'package:eatvio_app/features/create_recipe/presentation/bloc/create_recipe_cubit/create_recipe_cubit.dart';
|
import 'package:eatvio_app/features/create_recipe/presentation/bloc/create_recipe_cubit/create_recipe_cubit.dart';
|
||||||
|
import 'package:eatvio_app/generated/l10n.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
|
import 'package:permission_handler/permission_handler.dart';
|
||||||
|
|
||||||
class ImageWidget extends StatefulWidget {
|
class ImageWidget extends StatefulWidget {
|
||||||
const ImageWidget({super.key, required this.image});
|
const ImageWidget({super.key, required this.image});
|
||||||
@@ -67,55 +72,72 @@ class _ImageWidgetState extends State<ImageWidget> {
|
|||||||
_showImagePicker() {
|
_showImagePicker() {
|
||||||
showCupertinoModalPopup<void>(
|
showCupertinoModalPopup<void>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => CupertinoActionSheet(
|
builder: (context) {
|
||||||
actions: [
|
final s = S.of(context);
|
||||||
CupertinoActionSheetAction(
|
return CupertinoActionSheet(
|
||||||
onPressed: () async {
|
actions: [
|
||||||
final picker = ImagePicker();
|
CupertinoActionSheetAction(
|
||||||
final image = await picker.pickImage(source: ImageSource.camera);
|
onPressed: () async {
|
||||||
setState(() {});
|
PermissionHandler.checkPermission(
|
||||||
if (image != null) {
|
permission: Permission.camera,
|
||||||
createRecipeCubit.replaceImage(File(image.path));
|
title: s.allowAccessToCamera,
|
||||||
createRecipeCubit.validateImage();
|
description: s.allowAccessToCameraDescription,
|
||||||
}
|
onGranted: () async {
|
||||||
if (!context.mounted) return;
|
final picker = ImagePicker();
|
||||||
Navigator.of(context).pop();
|
final image = await picker.pickImage(source: ImageSource.camera);
|
||||||
},
|
setState(() {});
|
||||||
child: const Row(
|
if (image != null) {
|
||||||
children: [
|
createRecipeCubit.replaceImage(File(image.path));
|
||||||
Icon(Icons.photo_camera),
|
createRecipeCubit.validateImage();
|
||||||
SizedBox(width: 8),
|
}
|
||||||
Text('Фото'),
|
AppRouter.navigatorKey.currentContext?.pop();
|
||||||
],
|
},
|
||||||
|
context: context,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: const Row(
|
||||||
|
children: [
|
||||||
|
Icon(Icons.photo_camera),
|
||||||
|
SizedBox(width: 8),
|
||||||
|
Text('Фото'),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
CupertinoActionSheetAction(
|
||||||
CupertinoActionSheetAction(
|
onPressed: () async {
|
||||||
onPressed: () async {
|
PermissionHandler.checkPermission(
|
||||||
final picker = ImagePicker();
|
permission: Permission.photos,
|
||||||
final image = await picker.pickImage(source: ImageSource.gallery);
|
title: s.allowAcessToGalery,
|
||||||
setState(() {});
|
description: s.allowAcessToGaleryDescription,
|
||||||
if (image != null) {
|
onGranted: () async {
|
||||||
createRecipeCubit.replaceImage(File(image.path));
|
final picker = ImagePicker();
|
||||||
createRecipeCubit.validateImage();
|
final image = await picker.pickImage(source: ImageSource.gallery);
|
||||||
}
|
setState(() {});
|
||||||
if (!context.mounted) return;
|
if (image != null) {
|
||||||
Navigator.of(context).pop();
|
createRecipeCubit.replaceImage(File(image.path));
|
||||||
},
|
createRecipeCubit.validateImage();
|
||||||
child: const Row(
|
}
|
||||||
children: [
|
AppRouter.navigatorKey.currentContext?.pop();
|
||||||
Icon(Icons.photo),
|
},
|
||||||
SizedBox(width: 8),
|
context: context,
|
||||||
Text('Галерея'),
|
);
|
||||||
],
|
},
|
||||||
|
child: const Row(
|
||||||
|
children: [
|
||||||
|
Icon(Icons.photo),
|
||||||
|
SizedBox(width: 8),
|
||||||
|
Text('Галерея'),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
|
],
|
||||||
|
cancelButton: CupertinoActionSheetAction(
|
||||||
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
|
isDestructiveAction: true,
|
||||||
|
child: const Text('Отмена'),
|
||||||
),
|
),
|
||||||
],
|
);
|
||||||
cancelButton: CupertinoActionSheetAction(
|
},
|
||||||
onPressed: () => Navigator.of(context).pop(),
|
|
||||||
isDestructiveAction: true,
|
|
||||||
child: const Text('Отмена'),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,15 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:eatvio_app/core/app_router.dart';
|
||||||
|
import 'package:eatvio_app/core/permission_handler/permission_handler.dart';
|
||||||
import 'package:eatvio_app/features/create_recipe/presentation/bloc/create_recipe_cubit/create_recipe_cubit.dart';
|
import 'package:eatvio_app/features/create_recipe/presentation/bloc/create_recipe_cubit/create_recipe_cubit.dart';
|
||||||
|
import 'package:eatvio_app/generated/l10n.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
|
import 'package:permission_handler/permission_handler.dart';
|
||||||
|
|
||||||
class StepImageWidget extends StatefulWidget {
|
class StepImageWidget extends StatefulWidget {
|
||||||
final CreateRecipeCubit createRecipeCubit;
|
final CreateRecipeCubit createRecipeCubit;
|
||||||
@@ -12,7 +17,8 @@ class StepImageWidget extends StatefulWidget {
|
|||||||
|
|
||||||
const StepImageWidget({
|
const StepImageWidget({
|
||||||
super.key,
|
super.key,
|
||||||
required this.index, required this.createRecipeCubit,
|
required this.index,
|
||||||
|
required this.createRecipeCubit,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -79,53 +85,70 @@ class _StepImageWidgetState extends State<StepImageWidget> {
|
|||||||
_showImagePicker() {
|
_showImagePicker() {
|
||||||
showCupertinoModalPopup<void>(
|
showCupertinoModalPopup<void>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => CupertinoActionSheet(
|
builder: (context) {
|
||||||
actions: [
|
final s = S.of(context);
|
||||||
CupertinoActionSheetAction(
|
return CupertinoActionSheet(
|
||||||
onPressed: () async {
|
actions: [
|
||||||
final picker = ImagePicker();
|
CupertinoActionSheetAction(
|
||||||
image = await picker.pickImage(source: ImageSource.camera);
|
onPressed: () async {
|
||||||
setState(() {});
|
PermissionHandler.checkPermission(
|
||||||
if (image != null) {
|
permission: Permission.camera,
|
||||||
widget.createRecipeCubit.replaceImageInStep(File(image!.path), widget.index);
|
title: s.allowAccessToCamera,
|
||||||
}
|
description: s.allowAccessToCameraDescription,
|
||||||
if (!context.mounted) return;
|
onGranted: () async {
|
||||||
Navigator.of(context).pop();
|
final picker = ImagePicker();
|
||||||
},
|
image = await picker.pickImage(source: ImageSource.camera);
|
||||||
child: const Row(
|
setState(() {});
|
||||||
children: [
|
if (image != null) {
|
||||||
Icon(Icons.photo_camera),
|
widget.createRecipeCubit.replaceImageInStep(File(image!.path), widget.index);
|
||||||
SizedBox(width: 8),
|
}
|
||||||
Text('Фото'),
|
AppRouter.navigatorKey.currentContext?.pop();
|
||||||
],
|
},
|
||||||
|
context: context,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: const Row(
|
||||||
|
children: [
|
||||||
|
Icon(Icons.photo_camera),
|
||||||
|
SizedBox(width: 8),
|
||||||
|
Text('Фото'),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
CupertinoActionSheetAction(
|
||||||
CupertinoActionSheetAction(
|
onPressed: () async {
|
||||||
onPressed: () async {
|
PermissionHandler.checkPermission(
|
||||||
final picker = ImagePicker();
|
permission: Permission.photos,
|
||||||
image = await picker.pickImage(source: ImageSource.gallery);
|
title: s.allowAcessToGalery,
|
||||||
setState(() {});
|
description: s.allowAcessToGaleryDescription,
|
||||||
if (image != null) {
|
onGranted: () async {
|
||||||
widget.createRecipeCubit.replaceImageInStep(File(image!.path), widget.index);
|
final picker = ImagePicker();
|
||||||
}
|
image = await picker.pickImage(source: ImageSource.gallery);
|
||||||
if (!context.mounted) return;
|
setState(() {});
|
||||||
Navigator.of(context).pop();
|
if (image != null) {
|
||||||
},
|
widget.createRecipeCubit.replaceImageInStep(File(image!.path), widget.index);
|
||||||
child: const Row(
|
}
|
||||||
children: [
|
AppRouter.navigatorKey.currentContext?.pop();
|
||||||
Icon(Icons.photo),
|
},
|
||||||
SizedBox(width: 8),
|
context: context,
|
||||||
Text('Галерея'),
|
);
|
||||||
],
|
},
|
||||||
|
child: const Row(
|
||||||
|
children: [
|
||||||
|
Icon(Icons.photo),
|
||||||
|
SizedBox(width: 8),
|
||||||
|
Text('Галерея'),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
|
],
|
||||||
|
cancelButton: CupertinoActionSheetAction(
|
||||||
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
|
isDestructiveAction: true,
|
||||||
|
child: const Text('Отмена'),
|
||||||
),
|
),
|
||||||
],
|
);
|
||||||
cancelButton: CupertinoActionSheetAction(
|
},
|
||||||
onPressed: () => Navigator.of(context).pop(),
|
|
||||||
isDestructiveAction: true,
|
|
||||||
child: const Text('Отмена'),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import 'package:eatvio_app/features/diets/repositories/diet_repository.dart';
|
|||||||
import 'package:eatvio_app/features/glossary/models/glossary_model.dart';
|
import 'package:eatvio_app/features/glossary/models/glossary_model.dart';
|
||||||
import 'package:eatvio_app/features/glossary/repositories/glossary_repository.dart';
|
import 'package:eatvio_app/features/glossary/repositories/glossary_repository.dart';
|
||||||
import 'package:eatvio_app/features/profile/repositories/profile_repository.dart';
|
import 'package:eatvio_app/features/profile/repositories/profile_repository.dart';
|
||||||
|
import 'package:eatvio_app/features/settings/repositories/service_repository.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
class DiaryCubit extends Cubit<DiaryState> {
|
class DiaryCubit extends Cubit<DiaryState> {
|
||||||
@@ -25,14 +26,16 @@ class DiaryCubit extends Cubit<DiaryState> {
|
|||||||
final ProfileRepository profileRepository;
|
final ProfileRepository profileRepository;
|
||||||
final DietRepository dietRepository;
|
final DietRepository dietRepository;
|
||||||
final ChatRepository chatRepository;
|
final ChatRepository chatRepository;
|
||||||
|
final SettingsRepository settingsRepository;
|
||||||
int? diaryId;
|
int? diaryId;
|
||||||
DiaryCubit(
|
DiaryCubit({
|
||||||
{required this.chatRepository,
|
required this.chatRepository,
|
||||||
required this.diaryRepository,
|
required this.diaryRepository,
|
||||||
required this.glossaryRepository,
|
required this.glossaryRepository,
|
||||||
required this.profileRepository,
|
required this.profileRepository,
|
||||||
required this.dietRepository})
|
required this.dietRepository,
|
||||||
: super(const DiaryState.loading()) {
|
required this.settingsRepository,
|
||||||
|
}) : super(const DiaryState.loading()) {
|
||||||
today = DateTime.now();
|
today = DateTime.now();
|
||||||
selectedDay = today;
|
selectedDay = today;
|
||||||
diaryRepository.forceFetchStream.listen((_) {
|
diaryRepository.forceFetchStream.listen((_) {
|
||||||
@@ -160,11 +163,16 @@ class DiaryCubit extends Cubit<DiaryState> {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
final DiaryDayModel diaryDay;
|
final DiaryDayModel diaryDay;
|
||||||
|
bool isMoodEnabled = false;
|
||||||
|
bool isWakeUpAndRetireTimeEnabled = false;
|
||||||
if (diaryId != null) {
|
if (diaryId != null) {
|
||||||
diaryDay = await diaryRepository.getDiaryDay(diaryId);
|
diaryDay = await diaryRepository.getDiaryDay(diaryId);
|
||||||
} else {
|
} else {
|
||||||
final stringDate = selectedDay.format('yyyy-MM-dd');
|
final stringDate = selectedDay.format('yyyy-MM-dd');
|
||||||
diaryDay = await diaryRepository.getDiaryByDate(stringDate);
|
diaryDay = await diaryRepository.getDiaryByDate(stringDate);
|
||||||
|
final profileSettings = await settingsRepository.getProfileSettings();
|
||||||
|
isMoodEnabled = profileSettings.isMoodFillable;
|
||||||
|
isWakeUpAndRetireTimeEnabled = profileSettings.isBedtimeFillable;
|
||||||
}
|
}
|
||||||
ConsultantReviewModel? consultantReview;
|
ConsultantReviewModel? consultantReview;
|
||||||
int? planDuration;
|
int? planDuration;
|
||||||
@@ -197,6 +205,8 @@ class DiaryCubit extends Cubit<DiaryState> {
|
|||||||
chosenPlanCurrentDay: currentPlanDay,
|
chosenPlanCurrentDay: currentPlanDay,
|
||||||
chosenPlanDuration: planDuration,
|
chosenPlanDuration: planDuration,
|
||||||
chosenPlanName: planName,
|
chosenPlanName: planName,
|
||||||
|
isMoodEnabled: isMoodEnabled,
|
||||||
|
isWakeUpAndRetireEnabled: isWakeUpAndRetireTimeEnabled
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} catch (e, st) {
|
} catch (e, st) {
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ abstract class DiaryState with _$DiaryState {
|
|||||||
@Default(false) bool isConsultantView,
|
@Default(false) bool isConsultantView,
|
||||||
@Default(false) bool isDiaryFinished,
|
@Default(false) bool isDiaryFinished,
|
||||||
@Default(false) bool isDiaryCommented,
|
@Default(false) bool isDiaryCommented,
|
||||||
|
@Default(false) bool isWakeUpAndRetireEnabled,
|
||||||
|
@Default(false) bool isMoodEnabled,
|
||||||
}) = DiaryStateLoaded;
|
}) = DiaryStateLoaded;
|
||||||
|
|
||||||
const factory DiaryState.loadedTomorrowWithDiet({
|
const factory DiaryState.loadedTomorrowWithDiet({
|
||||||
|
|||||||
@@ -80,13 +80,17 @@ class DiaryScreenContent extends StatelessWidget {
|
|||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: Colors.grey.shade200,
|
backgroundColor: Colors.grey.shade200,
|
||||||
appBar: AppBar(
|
appBar: diaryId == null
|
||||||
title: Text(
|
? AppBar(
|
||||||
state is DiaryStateLoaded ? DateTime.parse(state.diary.date).toLocal().format('d MMMM') : '',
|
toolbarHeight: 0,
|
||||||
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
|
)
|
||||||
),
|
: AppBar(
|
||||||
centerTitle: true,
|
title: Text(
|
||||||
),
|
state is DiaryStateLoaded ? DateTime.parse(state.diary.date).toLocal().format('d MMMM') : '',
|
||||||
|
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
|
||||||
|
),
|
||||||
|
centerTitle: true,
|
||||||
|
),
|
||||||
body: SingleChildScrollView(
|
body: SingleChildScrollView(
|
||||||
padding: const EdgeInsets.only(bottom: 16, top: 8),
|
padding: const EdgeInsets.only(bottom: 16, top: 8),
|
||||||
physics: const BouncingScrollPhysics(),
|
physics: const BouncingScrollPhysics(),
|
||||||
@@ -101,13 +105,13 @@ class DiaryScreenContent extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
if (state is DiaryStateLoaded)
|
if (state is DiaryStateLoaded)
|
||||||
WakeupAndRetireWidget(
|
WakeupAndRetireWidget(
|
||||||
showRetire: state.diary.typeOfDiary.hasChosenPlan,
|
isEnabled: state.diary.typeOfDiary.hasChosenPlan || state.isConsultantView || state.isWakeUpAndRetireEnabled,
|
||||||
disable: state.isConsultantView || state.isDiaryFinished || state.isDiaryCommented,
|
disable: state.isConsultantView || state.isDiaryFinished || state.isDiaryCommented,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
if (state is DiaryStateLoaded)
|
if (state is DiaryStateLoaded)
|
||||||
MealWidget(
|
MealWidget(
|
||||||
showMood: state.diary.typeOfDiary.hasChosenPlan,
|
showMood: state.diary.typeOfDiary.hasChosenPlan || state.isConsultantView || state.isMoodEnabled,
|
||||||
showAddButton: !state.isConsultantView && !state.isDiaryFinished && !state.isDiaryCommented,
|
showAddButton: !state.isConsultantView && !state.isDiaryFinished && !state.isDiaryCommented,
|
||||||
),
|
),
|
||||||
if (state is DiaryStateLoadedTomorrowWithDiet)
|
if (state is DiaryStateLoadedTomorrowWithDiet)
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ class CaloriesChartWidget extends StatelessWidget {
|
|||||||
context: context,
|
context: context,
|
||||||
builder: (context) => const AlertDialog(
|
builder: (context) => const AlertDialog(
|
||||||
content: Text(
|
content: Text(
|
||||||
'График отображает сколько калорий вам нужно ежедневно для похуденияи поддержания веса, согласно формуле Харриса-Бенедикта.\nИзменить коэффициент физической нагрузки можно в настройках.',
|
'График отображает сколько калорий Вам нужно ежедневно для поддержания веса, согласно формуле Харриса-Бенедикта. Изменить коэффициент физической нагрузки можно в настройках',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
color: Color(0xFF323F4B),
|
color: Color(0xFF323F4B),
|
||||||
|
|||||||
@@ -59,7 +59,6 @@ class _MealWidgetState extends State<MealWidget> {
|
|||||||
),
|
),
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
const TimeOfMealPickerWidget(),
|
const TimeOfMealPickerWidget(),
|
||||||
|
|
||||||
const ChosenDietWidget(),
|
const ChosenDietWidget(),
|
||||||
const ChosenPlanWidget(),
|
const ChosenPlanWidget(),
|
||||||
const ProductsListWidget(),
|
const ProductsListWidget(),
|
||||||
|
|||||||
@@ -1,16 +1,21 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:cached_network_image/cached_network_image.dart';
|
import 'package:cached_network_image/cached_network_image.dart';
|
||||||
|
import 'package:eatvio_app/core/app_router.dart';
|
||||||
import 'package:eatvio_app/core/const.dart';
|
import 'package:eatvio_app/core/const.dart';
|
||||||
|
import 'package:eatvio_app/core/permission_handler/permission_handler.dart';
|
||||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||||
import 'package:eatvio_app/features/diary/models/diary_day_model.dart';
|
import 'package:eatvio_app/features/diary/models/diary_day_model.dart';
|
||||||
import 'package:eatvio_app/features/diary/presentation/bloc/diary_cubit.dart';
|
import 'package:eatvio_app/features/diary/presentation/bloc/diary_cubit.dart';
|
||||||
import 'package:eatvio_app/features/diary/presentation/bloc/diary_state.dart';
|
import 'package:eatvio_app/features/diary/presentation/bloc/diary_state.dart';
|
||||||
|
import 'package:eatvio_app/generated/l10n.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
|
import 'package:permission_handler/permission_handler.dart';
|
||||||
|
|
||||||
class PhotoGalleryWidget extends StatefulWidget {
|
class PhotoGalleryWidget extends StatefulWidget {
|
||||||
const PhotoGalleryWidget({super.key});
|
const PhotoGalleryWidget({super.key});
|
||||||
@@ -32,55 +37,75 @@ class _PhotoGalleryWidgetState extends State<PhotoGalleryWidget> {
|
|||||||
showImagePicker(DiaryDayModel diaryDay) {
|
showImagePicker(DiaryDayModel diaryDay) {
|
||||||
showCupertinoModalPopup<void>(
|
showCupertinoModalPopup<void>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => CupertinoActionSheet(
|
builder: (context) {
|
||||||
actions: [
|
final s = S.of(context);
|
||||||
CupertinoActionSheetAction(
|
return CupertinoActionSheet(
|
||||||
onPressed: () async {
|
actions: [
|
||||||
Navigator.of(context).pop();
|
CupertinoActionSheetAction(
|
||||||
final picker = ImagePicker();
|
onPressed: () async {
|
||||||
XFile? image = await picker.pickImage(source: ImageSource.camera);
|
PermissionHandler.checkPermission(
|
||||||
if (image != null) {
|
permission: Permission.camera,
|
||||||
diaryCubit.uploadPhotos(
|
title: s.allowAccessToCamera,
|
||||||
files: [File(image.path)],
|
description: s.allowAccessToCameraDescription,
|
||||||
diaryId: diaryDay.id,
|
onGranted: () async {
|
||||||
|
AppRouter.navigatorKey.currentContext?.pop();
|
||||||
|
|
||||||
|
final picker = ImagePicker();
|
||||||
|
XFile? image = await picker.pickImage(source: ImageSource.camera);
|
||||||
|
if (image != null) {
|
||||||
|
diaryCubit.uploadPhotos(
|
||||||
|
files: [File(image.path)],
|
||||||
|
diaryId: diaryDay.id,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
context: context,
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
},
|
child: const Row(
|
||||||
child: const Row(
|
children: [
|
||||||
children: [
|
Icon(Icons.photo_camera),
|
||||||
Icon(Icons.photo_camera),
|
SizedBox(width: 8),
|
||||||
SizedBox(width: 8),
|
Text('Фото'),
|
||||||
Text('Фото'),
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
CupertinoActionSheetAction(
|
||||||
CupertinoActionSheetAction(
|
onPressed: () async {
|
||||||
onPressed: () async {
|
PermissionHandler.checkPermission(
|
||||||
Navigator.of(context).pop();
|
permission: Permission.photos,
|
||||||
final picker = ImagePicker();
|
title: s.allowAcessToGalery,
|
||||||
List<XFile>? images = await picker.pickMultiImage();
|
description: s.allowAcessToGaleryDescription,
|
||||||
if (images.isNotEmpty) {
|
onGranted: () async {
|
||||||
diaryCubit.uploadPhotos(
|
AppRouter.navigatorKey.currentContext?.pop();
|
||||||
files: images.map((f) => File(f.path)).toList(),
|
final picker = ImagePicker();
|
||||||
diaryId: diaryDay.id,
|
List<XFile>? images = await picker.pickMultiImage();
|
||||||
|
if (images.isNotEmpty) {
|
||||||
|
diaryCubit.uploadPhotos(
|
||||||
|
files: images.map((f) => File(f.path)).toList(),
|
||||||
|
diaryId: diaryDay.id,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
context: context,
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
},
|
child: const Row(
|
||||||
child: const Row(
|
children: [
|
||||||
children: [
|
Icon(Icons.photo),
|
||||||
Icon(Icons.photo),
|
SizedBox(width: 8),
|
||||||
SizedBox(width: 8),
|
Text('Галерея'),
|
||||||
Text('Галерея'),
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
|
],
|
||||||
|
cancelButton: CupertinoActionSheetAction(
|
||||||
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
|
isDestructiveAction: true,
|
||||||
|
child: const Text('Отмена'),
|
||||||
),
|
),
|
||||||
],
|
);
|
||||||
cancelButton: CupertinoActionSheetAction(
|
},
|
||||||
onPressed: () => Navigator.of(context).pop(),
|
|
||||||
isDestructiveAction: true,
|
|
||||||
child: const Text('Отмена'),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,7 +117,9 @@ class _PhotoGalleryWidgetState extends State<PhotoGalleryWidget> {
|
|||||||
int mealIndex = state.selectedMeal - 1;
|
int mealIndex = state.selectedMeal - 1;
|
||||||
if (state.diary.meals[mealIndex].photos.isEmpty && !state.isConsultantView && !state.isDiaryFinished && !state.isDiaryCommented) {
|
if (state.diary.meals[mealIndex].photos.isEmpty && !state.isConsultantView && !state.isDiaryFinished && !state.isDiaryCommented) {
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: () => showImagePicker(state.diary),
|
onTap: () async {
|
||||||
|
showImagePicker(state.diary);
|
||||||
|
},
|
||||||
child: SvgPicture.asset(
|
child: SvgPicture.asset(
|
||||||
width: MediaQuery.of(context).size.width - 32,
|
width: MediaQuery.of(context).size.width - 32,
|
||||||
'assets/no_one_image_was_added.svg',
|
'assets/no_one_image_was_added.svg',
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ import 'package:flutter_svg/flutter_svg.dart';
|
|||||||
import '../../../../core/theme/theme_helper.dart';
|
import '../../../../core/theme/theme_helper.dart';
|
||||||
|
|
||||||
class WakeupAndRetireWidget extends StatefulWidget {
|
class WakeupAndRetireWidget extends StatefulWidget {
|
||||||
const WakeupAndRetireWidget({super.key, required this.showRetire, this.disable = false});
|
const WakeupAndRetireWidget({super.key, required this.isEnabled, this.disable = false});
|
||||||
final bool showRetire;
|
final bool isEnabled;
|
||||||
final bool disable;
|
final bool disable;
|
||||||
@override
|
@override
|
||||||
State<WakeupAndRetireWidget> createState() => _WakeupAndRetireWidgetState();
|
State<WakeupAndRetireWidget> createState() => _WakeupAndRetireWidgetState();
|
||||||
@@ -94,6 +94,9 @@ class _WakeupAndRetireWidgetState extends State<WakeupAndRetireWidget> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocBuilder<DiaryCubit, DiaryState>(
|
return BlocBuilder<DiaryCubit, DiaryState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
|
if (!widget.isEnabled) {
|
||||||
|
return const SizedBox.shrink();
|
||||||
|
}
|
||||||
if (state is DiaryStateLoaded) {
|
if (state is DiaryStateLoaded) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 4),
|
padding: const EdgeInsets.symmetric(horizontal: 4),
|
||||||
@@ -157,67 +160,65 @@ class _WakeupAndRetireWidgetState extends State<WakeupAndRetireWidget> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (widget.showRetire) ...[
|
const SizedBox(width: 8),
|
||||||
const SizedBox(width: 8),
|
Expanded(
|
||||||
Expanded(
|
child: Material(
|
||||||
child: Material(
|
borderRadius: BorderRadius.circular(12),
|
||||||
borderRadius: BorderRadius.circular(12),
|
color: Colors.white,
|
||||||
color: Colors.white,
|
child: Padding(
|
||||||
child: Padding(
|
padding: const EdgeInsets.symmetric(
|
||||||
padding: const EdgeInsets.symmetric(
|
horizontal: 8,
|
||||||
horizontal: 8,
|
vertical: 12,
|
||||||
vertical: 12,
|
),
|
||||||
),
|
child: Column(
|
||||||
child: Column(
|
children: [
|
||||||
children: [
|
Row(
|
||||||
Row(
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
children: [
|
||||||
children: [
|
SvgPicture.asset('assets/icons/retire.svg'),
|
||||||
SvgPicture.asset('assets/icons/retire.svg'),
|
const SizedBox(width: 8),
|
||||||
const SizedBox(width: 8),
|
const Text(
|
||||||
const Text(
|
'Уход ко сну',
|
||||||
'Уход ко сну',
|
style: TextStyle(
|
||||||
style: TextStyle(
|
fontSize: 16,
|
||||||
fontSize: 16,
|
fontWeight: FontWeight.w500,
|
||||||
|
height: 1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
InkWell(
|
||||||
|
onTap: widget.disable ? null : () => showTimePicker(state.diary.id, false),
|
||||||
|
borderRadius: BorderRadius.circular(100),
|
||||||
|
child: Ink(
|
||||||
|
height: 32,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(100),
|
||||||
|
color: const Color(0xFFF1F2F6),
|
||||||
|
),
|
||||||
|
child: Container(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
|
child: Text(
|
||||||
|
state.diary.retire.toString().substring(
|
||||||
|
0,
|
||||||
|
state.diary.retire.toString().length - 3,
|
||||||
|
),
|
||||||
|
style: const TextStyle(
|
||||||
|
color: Color(0xFF6D6F71),
|
||||||
|
fontSize: 17,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
height: 1,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const SizedBox(height: 8),
|
|
||||||
InkWell(
|
|
||||||
onTap: widget.disable ? null : () => showTimePicker(state.diary.id, false),
|
|
||||||
borderRadius: BorderRadius.circular(100),
|
|
||||||
child: Ink(
|
|
||||||
height: 32,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.circular(100),
|
|
||||||
color: const Color(0xFFF1F2F6),
|
|
||||||
),
|
|
||||||
child: Container(
|
|
||||||
alignment: Alignment.center,
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
|
||||||
child: Text(
|
|
||||||
state.diary.retire.toString().substring(
|
|
||||||
0,
|
|
||||||
state.diary.retire.toString().length - 3,
|
|
||||||
),
|
|
||||||
style: const TextStyle(
|
|
||||||
color: Color(0xFF6D6F71),
|
|
||||||
fontSize: 17,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
]
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
|
|
||||||
|
import 'package:eatvio_app/core/enums/filters_comparison_enum.dart';
|
||||||
import 'package:eatvio_app/features/consultations/repositories/consultations_repository.dart';
|
import 'package:eatvio_app/features/consultations/repositories/consultations_repository.dart';
|
||||||
import 'package:eatvio_app/features/finances_and_consultations_archive/cubit/consultant_finances/consultant_finances_state.dart';
|
import 'package:eatvio_app/features/finances_and_consultations_archive/cubit/consultant_finances/consultant_finances_state.dart';
|
||||||
import 'package:eatvio_app/features/finances_and_consultations_archive/period_enum.dart';
|
import 'package:eatvio_app/features/finances_and_consultations_archive/period_enum.dart';
|
||||||
@@ -13,19 +14,22 @@ class ConsultantFinancesCubit extends Cubit<ConsultantFinancesState> {
|
|||||||
ConsultantFinancesState(),
|
ConsultantFinancesState(),
|
||||||
);
|
);
|
||||||
|
|
||||||
Future<void> getConsultations() async {
|
Future<void> getConsultantFinances() async {
|
||||||
try {
|
try {
|
||||||
emit(state.copyWith(isLoading: true));
|
emit(state.copyWith(isLoading: true));
|
||||||
|
final consultantFinances = await consultationsRepository.getConsultantFinances(
|
||||||
|
state.periodFilterStatus?.value,
|
||||||
|
state.periodFilterStatus == PeriodFilterStatus.all ? null : FiltersComparisonEnum.greaterThanOrEqual,
|
||||||
|
);
|
||||||
|
emit(state.copyWith(financesModels: consultantFinances, isLoading: false));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(state.copyWith(isLoading: false));
|
emit(state.copyWith(financesModels: [], isLoading: false));
|
||||||
log(e.toString());
|
log(e.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> setConsultationsPeriod(PeriodFilterStatus period) async {
|
Future<void> setFinancesPeriod(PeriodFilterStatus period) async {
|
||||||
emit(state.copyWith(periodFilterStatus: period));
|
emit(state.copyWith(periodFilterStatus: period));
|
||||||
await getConsultations();
|
await getConsultantFinances();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import 'package:eatvio_app/features/finances_and_consultations_archive/models/consultant_finance_model.dart';
|
||||||
import 'package:eatvio_app/features/finances_and_consultations_archive/period_enum.dart';
|
import 'package:eatvio_app/features/finances_and_consultations_archive/period_enum.dart';
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
|
||||||
@@ -6,7 +7,7 @@ part 'consultant_finances_state.freezed.dart';
|
|||||||
@freezed
|
@freezed
|
||||||
abstract class ConsultantFinancesState with _$ConsultantFinancesState {
|
abstract class ConsultantFinancesState with _$ConsultantFinancesState {
|
||||||
factory ConsultantFinancesState({
|
factory ConsultantFinancesState({
|
||||||
@Default([]) List<String> financesModels,
|
@Default([]) List<ConsultantFinanceModel> financesModels,
|
||||||
@Default(false) isLoading,
|
@Default(false) isLoading,
|
||||||
@Default(null) String? error,
|
@Default(null) String? error,
|
||||||
@Default(null) PeriodFilterStatus? periodFilterStatus,
|
@Default(null) PeriodFilterStatus? periodFilterStatus,
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
import 'dart:developer';
|
||||||
|
|
||||||
|
import 'package:eatvio_app/core/enums/filters_comparison_enum.dart';
|
||||||
|
import 'package:eatvio_app/features/consultations/repositories/consultations_repository.dart';
|
||||||
|
import 'package:eatvio_app/features/finances_and_consultations_archive/cubit/user_purchases/user_purchases_state.dart';
|
||||||
|
import 'package:eatvio_app/features/finances_and_consultations_archive/period_enum.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
|
class UserPurchasesCubit extends Cubit<UserPurchasesState> {
|
||||||
|
final ConsultationsRepository consultationsRepository;
|
||||||
|
UserPurchasesCubit({
|
||||||
|
required this.consultationsRepository,
|
||||||
|
}) : super(
|
||||||
|
UserPurchasesState(),
|
||||||
|
);
|
||||||
|
|
||||||
|
Future<void> getUserPurchases() async {
|
||||||
|
try {
|
||||||
|
emit(state.copyWith(isLoading: true));
|
||||||
|
final purchasesModels = await consultationsRepository.getUserPurchases(
|
||||||
|
state.periodFilterStatus?.value,
|
||||||
|
state.periodFilterStatus == PeriodFilterStatus.all ? null : FiltersComparisonEnum.greaterThanOrEqual,
|
||||||
|
);
|
||||||
|
|
||||||
|
emit(state.copyWith(purchasesModels: purchasesModels, isLoading: false));
|
||||||
|
} catch (e) {
|
||||||
|
emit(state.copyWith(purchasesModels: [], isLoading: false));
|
||||||
|
log(e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> setPurchasesPeriod(PeriodFilterStatus period) async {
|
||||||
|
emit(state.copyWith(periodFilterStatus: period));
|
||||||
|
await getUserPurchases();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import 'package:eatvio_app/features/finances_and_consultations_archive/models/user_purchases_model.dart';
|
||||||
|
import 'package:eatvio_app/features/finances_and_consultations_archive/period_enum.dart';
|
||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
|
||||||
|
part 'user_purchases_state.freezed.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
abstract class UserPurchasesState with _$UserPurchasesState {
|
||||||
|
factory UserPurchasesState({
|
||||||
|
@Default([]) List<UserPurchasesModel> purchasesModels,
|
||||||
|
@Default(false) isLoading,
|
||||||
|
@Default(null) String? error,
|
||||||
|
@Default(null) PeriodFilterStatus? periodFilterStatus,
|
||||||
|
}) = _UserPurchasesState;
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
import 'package:eatvio_app/features/feed/models/feed_blog_post_model.dart';
|
||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
|
||||||
|
part 'consultant_finance_model.freezed.dart';
|
||||||
|
part 'consultant_finance_model.g.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
abstract class ConsultantFinanceModel with _$ConsultantFinanceModel {
|
||||||
|
factory ConsultantFinanceModel({
|
||||||
|
@JsonKey(name: 'start_date', fromJson: parseDate) required DateTime startDate,
|
||||||
|
@JsonKey(name: 'bank_id') required String bankId,
|
||||||
|
@JsonKey(name: 'title') required String title,
|
||||||
|
@JsonKey(name: 'clientName') required String clientName,
|
||||||
|
@JsonKey(name: 'duration') required int duration,
|
||||||
|
@JsonKey(name: 'payment_price', fromJson: _parsePayment) required String paymentPrice,
|
||||||
|
required PaymentStatus? paymentStatus,
|
||||||
|
}) = _ConsultantFinanceModel;
|
||||||
|
|
||||||
|
factory ConsultantFinanceModel.fromJson(Map<String, dynamic> json) => _$ConsultantFinanceModelFromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
String _parsePayment(json) {
|
||||||
|
return ((json as int) / 100).toStringAsFixed(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
enum PaymentStatus {
|
||||||
|
@JsonValue('COMPLETED')
|
||||||
|
completed,
|
||||||
|
@JsonValue('REJECTED')
|
||||||
|
rejected,
|
||||||
|
@JsonValue('CHECKED')
|
||||||
|
checked
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import 'package:eatvio_app/features/feed/models/feed_blog_post_model.dart';
|
||||||
|
import 'package:eatvio_app/features/plans/enums/chosen_plan_state_enum.dart';
|
||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
|
||||||
|
part 'user_purchases_model.freezed.dart';
|
||||||
|
part 'user_purchases_model.g.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
abstract class UserPurchasesModel with _$UserPurchasesModel {
|
||||||
|
factory UserPurchasesModel({
|
||||||
|
@JsonKey(name: 'start_date', fromJson: parseDate) required DateTime startDate,
|
||||||
|
@JsonKey(name: 'bank_id') required String bankId,
|
||||||
|
@JsonKey(name: 'title') required String title,
|
||||||
|
@JsonKey(name: 'consultantName') required String consultantName,
|
||||||
|
@JsonKey(name: 'duration') required int duration,
|
||||||
|
@JsonKey(name: 'price') required int paymentPrice,
|
||||||
|
@JsonKey(name: 'chosen_plan_last_state') required ChosenPlanStateEnum chosenPlanState,
|
||||||
|
}) = _UserPurchasesModel;
|
||||||
|
|
||||||
|
factory UserPurchasesModel.fromJson(Map<String, dynamic> json) => _$UserPurchasesModelFromJson(json);
|
||||||
|
}
|
||||||
@@ -1,281 +1,225 @@
|
|||||||
// import 'package:eatvio_app/core/locator_service.dart';
|
import 'package:eatvio_app/core/locator_service.dart';
|
||||||
// import 'package:eatvio_app/core/theme/custom_text_style.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/theme/theme_helper.dart';
|
||||||
// import 'package:eatvio_app/core/utils/date_time_utils.dart';
|
import 'package:eatvio_app/core/utils/date_time_utils.dart';
|
||||||
// import 'package:eatvio_app/core/utils/localization_utils.dart';
|
import 'package:eatvio_app/core/utils/localization_utils.dart';
|
||||||
// import 'package:eatvio_app/core/widgets/custom_drop_down_button.dart';
|
import 'package:eatvio_app/core/widgets/custom_drop_down_button.dart';
|
||||||
// import 'package:eatvio_app/core/widgets/loader.dart';
|
import 'package:eatvio_app/core/widgets/loader.dart';
|
||||||
// import 'package:eatvio_app/features/finances_and_consultations_archive/cubit/archive/consultations_archive_cubit.dart';
|
import 'package:eatvio_app/features/finances_and_consultations_archive/cubit/consultant_finances/consultant_finances_cubit.dart';
|
||||||
// import 'package:eatvio_app/features/finances_and_consultations_archive/cubit/archive/consultations_archive_state.dart';
|
import 'package:eatvio_app/features/finances_and_consultations_archive/cubit/consultant_finances/consultant_finances_state.dart';
|
||||||
// import 'package:eatvio_app/features/finances_and_consultations_archive/cubit/consultant_finances/consultant_finances_cubit.dart';
|
import 'package:eatvio_app/features/finances_and_consultations_archive/models/consultant_finance_model.dart';
|
||||||
// import 'package:eatvio_app/features/finances_and_consultations_archive/cubit/consultant_finances/consultant_finances_state.dart';
|
import 'package:eatvio_app/features/finances_and_consultations_archive/period_enum.dart';
|
||||||
// import 'package:eatvio_app/features/finances_and_consultations_archive/period_enum.dart';
|
import 'package:eatvio_app/features/finances_and_consultations_archive/presentation/widgets/status_widget.dart';
|
||||||
// import 'package:eatvio_app/features/finances_and_consultations_archive/presentation/widgets/status_widget.dart';
|
import 'package:eatvio_app/features/my_finance/presentation/pages/card_settings.dart';
|
||||||
// import 'package:eatvio_app/generated/l10n.dart';
|
import 'package:eatvio_app/generated/l10n.dart';
|
||||||
// import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
// import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
|
|
||||||
// class ConsultantFinancesScreen extends StatefulWidget {
|
class ConsultantFinancesScreen extends StatefulWidget {
|
||||||
// const ConsultantFinancesScreen({super.key});
|
const ConsultantFinancesScreen({super.key});
|
||||||
|
static const name = 'consultantFinancesScreen';
|
||||||
|
static const path = '/consultant-finances-screen';
|
||||||
|
@override
|
||||||
|
State<ConsultantFinancesScreen> createState() => _ConsultantFinancesScreenState();
|
||||||
|
}
|
||||||
|
|
||||||
// @override
|
class _ConsultantFinancesScreenState extends State<ConsultantFinancesScreen> {
|
||||||
// State<ConsultantFinancesScreen> createState() => _ConsultantFinancesScreenState();
|
@override
|
||||||
// }
|
Widget build(BuildContext context) {
|
||||||
|
final s = S.of(context);
|
||||||
// class _ConsultantFinancesScreenState extends State<ConsultantFinancesScreen> {
|
return BlocProvider<ConsultantFinancesCubit>(
|
||||||
// @override
|
create: (context) => sl<ConsultantFinancesCubit>()..getConsultantFinances(),
|
||||||
// Widget build(BuildContext context) {
|
child: BlocBuilder<ConsultantFinancesCubit, ConsultantFinancesState>(
|
||||||
// final s = S.of(context);
|
builder: (context, state) {
|
||||||
// return BlocProvider<ConsultantFinancesCubit>(
|
return Scaffold(
|
||||||
// create: (context) => sl<ConsultantFinancesCubit>(),
|
backgroundColor: const Color(0xFFF0F2F5),
|
||||||
// child: BlocBuilder<ConsultantFinancesCubit, ConsultantFinancesState>(
|
appBar: AppBar(
|
||||||
// builder: (context, state) {
|
shape: const RoundedRectangleBorder(
|
||||||
// return Scaffold(
|
borderRadius: BorderRadiusDirectional.vertical(
|
||||||
// backgroundColor: const Color(0xFFF0F2F5),
|
bottom: Radius.circular(12),
|
||||||
// appBar: AppBar(
|
),
|
||||||
// shape: const RoundedRectangleBorder(
|
),
|
||||||
// borderRadius: BorderRadiusDirectional.vertical(
|
title: Text(
|
||||||
// bottom: Radius.circular(12),
|
'Финансы',
|
||||||
// ),
|
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
|
||||||
// ),
|
),
|
||||||
// title: const Text('Архив консультаций'),
|
centerTitle: true,
|
||||||
// centerTitle: true,
|
),
|
||||||
// ),
|
body: state.isLoading
|
||||||
// body: state.isLoading
|
? const Center(
|
||||||
// ? const Center(
|
child: Loader(),
|
||||||
// child: Loader(),
|
)
|
||||||
// )
|
: SingleChildScrollView(
|
||||||
// : SingleChildScrollView(
|
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||||
// padding: const EdgeInsets.symmetric(vertical: 8),
|
child: Column(
|
||||||
// child: Column(
|
children: [
|
||||||
// children: [
|
InkWell(
|
||||||
// Material(
|
onTap: () {
|
||||||
// color: Colors.white,
|
GoRouter.of(context).pushNamed(CardSettingsScreen.name);
|
||||||
// borderRadius: BorderRadius.circular(12),
|
},
|
||||||
// child: Column(
|
borderRadius: BorderRadius.circular(20),
|
||||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
child: Ink(
|
||||||
// children: [
|
decoration: BoxDecoration(borderRadius: BorderRadius.circular(20), color: appTheme.blueA400),
|
||||||
// const SizedBox(height: 16),
|
width: MediaQuery.of(context).size.width - 32,
|
||||||
// Padding(
|
child: const Center(
|
||||||
// padding: const EdgeInsets.symmetric(horizontal: 16),
|
child: Padding(
|
||||||
// child: Text(
|
padding: EdgeInsets.all(16),
|
||||||
// 'Всего консультаций: ${state.statisticModel.total}',
|
child: Text('Управление картами', style: TextStyle(color: Colors.white, fontSize: 16, fontWeight: FontWeight.w600)),
|
||||||
// style: const TextStyle(
|
),
|
||||||
// fontSize: 16,
|
),
|
||||||
// fontWeight: FontWeight.w500,
|
),
|
||||||
// color: Color(0xFF6D6F71),
|
),
|
||||||
// height: 1,
|
const SizedBox(height: 8),
|
||||||
// ),
|
Material(
|
||||||
// ),
|
color: Colors.white,
|
||||||
// ),
|
borderRadius: BorderRadius.circular(12),
|
||||||
// const SizedBox(height: 12),
|
child: Padding(
|
||||||
// Row(
|
padding: const EdgeInsets.only(left: 16, right: 16, top: 16),
|
||||||
// children: [
|
child: SingleChildScrollView(
|
||||||
// const SizedBox(width: 16),
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
// Material(
|
child: Column(
|
||||||
// color: const Color(0xFF0BB450).withAlpha(11),
|
children: [
|
||||||
// borderRadius: BorderRadius.circular(8),
|
CustomDropDownButton<PeriodFilterStatus>(
|
||||||
// child: Padding(
|
items: PeriodFilterStatus.values
|
||||||
// padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
|
.map(
|
||||||
// child: Text(
|
(value) => DropdownMenuItem(
|
||||||
// 'Завершено: ${state.statisticModel.finished}',
|
value: value,
|
||||||
// style: const TextStyle(
|
child: Text(
|
||||||
// fontSize: 14,
|
value.name,
|
||||||
// fontWeight: FontWeight.w400,
|
style: TextStyles.textMMedium.copyWith(color: appTheme.black),
|
||||||
// color: Color(0xFF0BB450),
|
),
|
||||||
// height: 1,
|
),
|
||||||
// ),
|
)
|
||||||
// ),
|
.toList(),
|
||||||
// ),
|
onChanged: (value) {
|
||||||
// ),
|
if (value == null) return;
|
||||||
// const SizedBox(width: 8),
|
context.read<ConsultantFinancesCubit>().setFinancesPeriod(value);
|
||||||
// Material(
|
},
|
||||||
// color: const Color(0xFFD01717).withAlpha(11),
|
value: state.periodFilterStatus ?? PeriodFilterStatus.values.first,
|
||||||
// borderRadius: BorderRadius.circular(8),
|
),
|
||||||
// child: Padding(
|
const SizedBox(height: 12),
|
||||||
// padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
|
if (state.financesModels.isNotEmpty)
|
||||||
// child: Text(
|
ListView.separated(
|
||||||
// 'Отменено: ${state.statisticModel.canceled}',
|
shrinkWrap: true,
|
||||||
// style: const TextStyle(
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
// fontSize: 14,
|
itemBuilder: (context, index) {
|
||||||
// fontWeight: FontWeight.w400,
|
final Status modelStatus = switch (state.financesModels[index].paymentStatus) {
|
||||||
// color: Color(0xFFD01717),
|
null => Status.inProgress,
|
||||||
// height: 1,
|
PaymentStatus.completed => Status.success,
|
||||||
// ),
|
PaymentStatus.rejected => Status.canceled,
|
||||||
// ),
|
PaymentStatus.checked => Status.success,
|
||||||
// ),
|
};
|
||||||
// ),
|
return Material(
|
||||||
// ],
|
color: const Color(0xFFF6F6F6),
|
||||||
// ),
|
borderRadius: BorderRadius.circular(20),
|
||||||
// const SizedBox(height: 16),
|
child: Padding(
|
||||||
// ],
|
padding: const EdgeInsets.all(12),
|
||||||
// ),
|
child: Column(
|
||||||
// ),
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
// const SizedBox(height: 8),
|
children: [
|
||||||
// Material(
|
Row(
|
||||||
// color: Colors.white,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
// borderRadius: BorderRadius.circular(12),
|
children: [
|
||||||
// child: Padding(
|
Builder(builder: (context) {
|
||||||
// padding: const EdgeInsets.only(left: 16, right: 16, top: 16),
|
final idLen = state.financesModels[index].bankId.length;
|
||||||
// child: SingleChildScrollView(
|
return Text(
|
||||||
// physics: const NeverScrollableScrollPhysics(),
|
'${state.financesModels[index].bankId.substring(0, 4)}...${state.financesModels[index].bankId.substring(idLen - 4, idLen)} ',
|
||||||
// child: Column(
|
style: TextStyles.textSMedium.copyWith(color: appTheme.black),
|
||||||
// children: [
|
);
|
||||||
// CustomDropDownButton<PeriodFilterStatus>(
|
}),
|
||||||
// items: PeriodFilterStatus.values
|
Text(
|
||||||
// .map(
|
state.financesModels[index].startDate.format('yyyy.MM.dd'),
|
||||||
// (value) => DropdownMenuItem(
|
style: const TextStyle(
|
||||||
// value: value,
|
color: Color(0xFF6D6F71),
|
||||||
// child: Text(
|
height: 1,
|
||||||
// value.name,
|
fontWeight: FontWeight.w500,
|
||||||
// style: TextStyles.textMMedium.copyWith(color: appTheme.black),
|
),
|
||||||
// ),
|
),
|
||||||
// ),
|
],
|
||||||
// )
|
),
|
||||||
// .toList(),
|
const SizedBox(height: 8),
|
||||||
// onChanged: (value) {
|
Text(
|
||||||
// if (value == null) return;
|
state.financesModels[index].title,
|
||||||
// context.read<ConsultationsArchiveCubit>().setConsultationsPeriod(value);
|
style: TextStyle(
|
||||||
// },
|
color: appTheme.blueA400,
|
||||||
// value: state.periodFilterStatus ?? PeriodFilterStatus.values.first,
|
height: 1,
|
||||||
// ),
|
fontSize: 18,
|
||||||
// const SizedBox(height: 12),
|
fontWeight: FontWeight.w600,
|
||||||
// CustomDropDownButton<ConsultationFilterStatus>(
|
),
|
||||||
// items: ConsultationFilterStatus.values
|
),
|
||||||
// .map(
|
const SizedBox(height: 8),
|
||||||
// (value) => DropdownMenuItem(
|
Text(
|
||||||
// value: value,
|
'Покупатель: ${state.financesModels[index].clientName}',
|
||||||
// child: Text(
|
style: const TextStyle(
|
||||||
// value.name,
|
color: Color(0xFF323F4B),
|
||||||
// style: TextStyles.textMMedium.copyWith(color: appTheme.black),
|
height: 1,
|
||||||
// ),
|
fontSize: 14,
|
||||||
// ),
|
fontWeight: FontWeight.w500,
|
||||||
// )
|
),
|
||||||
// .toList(),
|
),
|
||||||
// onChanged: (value) {
|
const SizedBox(height: 8),
|
||||||
// if (value == null) return;
|
Text(
|
||||||
// context.read<ConsultationsArchiveCubit>().setConsultationsStatus(value);
|
'${state.financesModels[index].duration} ${getDayForm(state.financesModels[index].duration, s)}',
|
||||||
// },
|
style: const TextStyle(
|
||||||
// value: state.consultationFilterStatus,
|
color: Color(0xFF323F4B),
|
||||||
// ),
|
height: 1,
|
||||||
// const SizedBox(height: 12),
|
fontSize: 14,
|
||||||
// if (state.consultations.isNotEmpty)
|
fontWeight: FontWeight.w500,
|
||||||
// ListView.separated(
|
),
|
||||||
// shrinkWrap: true,
|
),
|
||||||
// physics: const NeverScrollableScrollPhysics(),
|
const SizedBox(height: 8),
|
||||||
// itemBuilder: (context, index) {
|
Container(
|
||||||
// return Material(
|
height: 1,
|
||||||
// color: const Color(0xFFF6F6F6),
|
width: double.infinity,
|
||||||
// borderRadius: BorderRadius.circular(20),
|
decoration: const BoxDecoration(
|
||||||
// child: Padding(
|
color: Color(0xFFDEDEDF),
|
||||||
// padding: const EdgeInsets.all(12),
|
),
|
||||||
// child: Column(
|
),
|
||||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
const SizedBox(height: 8),
|
||||||
// children: [
|
Row(
|
||||||
// Row(
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
children: [
|
||||||
// children: [
|
Text(
|
||||||
// Text(
|
'${state.financesModels[index].paymentPrice} ₽',
|
||||||
// state.consultations[index].id.toString(),
|
style: const TextStyle(
|
||||||
// style: const TextStyle(
|
color: Color(0xFF323F4B),
|
||||||
// color: Color(0xFF323F4B),
|
height: 1,
|
||||||
// height: 1,
|
fontSize: 18,
|
||||||
// fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w600,
|
||||||
// ),
|
),
|
||||||
// ),
|
),
|
||||||
// Text(
|
StatusWidget(
|
||||||
// state.consultations[index].startDate.format('yyyy.MM.dd'),
|
status: modelStatus,
|
||||||
// style: const TextStyle(
|
),
|
||||||
// color: Color(0xFF6D6F71),
|
],
|
||||||
// height: 1,
|
),
|
||||||
// fontWeight: FontWeight.w500,
|
],
|
||||||
// ),
|
),
|
||||||
// ),
|
),
|
||||||
// ],
|
);
|
||||||
// ),
|
},
|
||||||
// const SizedBox(height: 8),
|
separatorBuilder: (context, index) => const SizedBox(height: 12),
|
||||||
// Text(
|
itemCount: state.financesModels.length,
|
||||||
// state.consultations[index].planTitle,
|
)
|
||||||
// style: TextStyle(
|
else
|
||||||
// color: appTheme.blueA400,
|
const Padding(
|
||||||
// height: 1,
|
padding: EdgeInsets.symmetric(vertical: 40.0),
|
||||||
// fontSize: 18,
|
child: Text(
|
||||||
// fontWeight: FontWeight.w600,
|
'У вас нет таких консультаций',
|
||||||
// ),
|
style: TextStyles.textMMedium,
|
||||||
// ),
|
),
|
||||||
// const SizedBox(height: 8),
|
),
|
||||||
// Text(
|
],
|
||||||
// 'Покупатель: ${state.consultations[index].userName}',
|
),
|
||||||
// style: const TextStyle(
|
),
|
||||||
// color: Color(0xFF323F4B),
|
),
|
||||||
// height: 1,
|
),
|
||||||
// fontSize: 14,
|
],
|
||||||
// fontWeight: FontWeight.w500,
|
)),
|
||||||
// ),
|
);
|
||||||
// ),
|
},
|
||||||
// const SizedBox(height: 8),
|
),
|
||||||
// Text(
|
);
|
||||||
// '${state.consultations[index].duration} ${getDayForm(state.consultations[index].duration, s)}',
|
}
|
||||||
// style: const TextStyle(
|
}
|
||||||
// color: Color(0xFF323F4B),
|
|
||||||
// height: 1,
|
|
||||||
// fontSize: 14,
|
|
||||||
// fontWeight: FontWeight.w500,
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// const SizedBox(height: 8),
|
|
||||||
// Container(
|
|
||||||
// height: 1,
|
|
||||||
// width: double.infinity,
|
|
||||||
// decoration: const BoxDecoration(
|
|
||||||
// color: Color(0xFFDEDEDF),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// const SizedBox(height: 8),
|
|
||||||
// Row(
|
|
||||||
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
// children: [
|
|
||||||
// Text(
|
|
||||||
// '${state.consultations[index].consultantPayment.toStringAsFixed(2)} ₽',
|
|
||||||
// style: const TextStyle(
|
|
||||||
// color: Color(0xFF323F4B),
|
|
||||||
// height: 1,
|
|
||||||
// fontSize: 18,
|
|
||||||
// fontWeight: FontWeight.w600,
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// StatusWidget(
|
|
||||||
// status: state.consultations[index].chosenPlanState,
|
|
||||||
// ),
|
|
||||||
// ],
|
|
||||||
// ),
|
|
||||||
// ],
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// );
|
|
||||||
// },
|
|
||||||
// separatorBuilder: (context, index) => const SizedBox(height: 12),
|
|
||||||
// itemCount: state.financesModels.length,
|
|
||||||
// )
|
|
||||||
// else
|
|
||||||
// const Padding(
|
|
||||||
// padding: EdgeInsets.symmetric(vertical: 40.0),
|
|
||||||
// child: Text(
|
|
||||||
// 'У вас нет таких консультаций',
|
|
||||||
// style: TextStyles.textMMedium,
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ],
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ],
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// );
|
|
||||||
// },
|
|
||||||
// ),
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|||||||
@@ -9,13 +9,15 @@ import 'package:eatvio_app/features/finances_and_consultations_archive/cubit/arc
|
|||||||
import 'package:eatvio_app/features/finances_and_consultations_archive/cubit/archive/consultations_archive_state.dart';
|
import 'package:eatvio_app/features/finances_and_consultations_archive/cubit/archive/consultations_archive_state.dart';
|
||||||
import 'package:eatvio_app/features/finances_and_consultations_archive/period_enum.dart';
|
import 'package:eatvio_app/features/finances_and_consultations_archive/period_enum.dart';
|
||||||
import 'package:eatvio_app/features/finances_and_consultations_archive/presentation/widgets/status_widget.dart';
|
import 'package:eatvio_app/features/finances_and_consultations_archive/presentation/widgets/status_widget.dart';
|
||||||
|
import 'package:eatvio_app/features/plans/enums/chosen_plan_state_enum.dart';
|
||||||
import 'package:eatvio_app/generated/l10n.dart';
|
import 'package:eatvio_app/generated/l10n.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
class ConsultationsArchiveScreen extends StatefulWidget {
|
class ConsultationsArchiveScreen extends StatefulWidget {
|
||||||
const ConsultationsArchiveScreen({super.key});
|
const ConsultationsArchiveScreen({super.key});
|
||||||
|
static const name = 'consultationsArchiveScreen';
|
||||||
|
static const path = '/consultations-archive-screen';
|
||||||
@override
|
@override
|
||||||
State<ConsultationsArchiveScreen> createState() => _ConsultationsArchiveScreenState();
|
State<ConsultationsArchiveScreen> createState() => _ConsultationsArchiveScreenState();
|
||||||
}
|
}
|
||||||
@@ -164,6 +166,15 @@ class _ConsultationsArchiveScreenState extends State<ConsultationsArchiveScreen>
|
|||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
physics: const NeverScrollableScrollPhysics(),
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
|
final Status consultationStatus;
|
||||||
|
if (state.consultations[index].chosenPlanState == ChosenPlanStateEnum.stateCanceledByTheInitiator) {
|
||||||
|
consultationStatus = Status.canceled;
|
||||||
|
} else if (state.consultations[index].chosenPlanState == ChosenPlanStateEnum.stateChargeWasCollected) {
|
||||||
|
consultationStatus = Status.success;
|
||||||
|
} else {
|
||||||
|
consultationStatus = Status.inProgress;
|
||||||
|
}
|
||||||
|
|
||||||
return Material(
|
return Material(
|
||||||
color: const Color(0xFFF6F6F6),
|
color: const Color(0xFFF6F6F6),
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
@@ -245,7 +256,7 @@ class _ConsultationsArchiveScreenState extends State<ConsultationsArchiveScreen>
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
StatusWidget(
|
StatusWidget(
|
||||||
status: state.consultations[index].chosenPlanState,
|
status: consultationStatus,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -0,0 +1,209 @@
|
|||||||
|
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/core/utils/date_time_utils.dart';
|
||||||
|
import 'package:eatvio_app/core/utils/localization_utils.dart';
|
||||||
|
import 'package:eatvio_app/core/widgets/custom_drop_down_button.dart';
|
||||||
|
import 'package:eatvio_app/core/widgets/loader.dart';
|
||||||
|
import 'package:eatvio_app/features/finances_and_consultations_archive/cubit/user_purchases/user_purchases_cubit.dart';
|
||||||
|
import 'package:eatvio_app/features/finances_and_consultations_archive/cubit/user_purchases/user_purchases_state.dart';
|
||||||
|
import 'package:eatvio_app/features/finances_and_consultations_archive/period_enum.dart';
|
||||||
|
import 'package:eatvio_app/features/finances_and_consultations_archive/presentation/widgets/status_widget.dart';
|
||||||
|
import 'package:eatvio_app/features/plans/enums/chosen_plan_state_enum.dart';
|
||||||
|
import 'package:eatvio_app/generated/l10n.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
|
class UserPurchasesScreen extends StatefulWidget {
|
||||||
|
const UserPurchasesScreen({super.key});
|
||||||
|
static const name = 'userPurchasesScreen';
|
||||||
|
static const path = '/user-purchases-screen';
|
||||||
|
@override
|
||||||
|
State<UserPurchasesScreen> createState() => _UserPurchasesScreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _UserPurchasesScreen extends State<UserPurchasesScreen> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final s = S.of(context);
|
||||||
|
return BlocProvider<UserPurchasesCubit>(
|
||||||
|
create: (context) => sl<UserPurchasesCubit>()..getUserPurchases(),
|
||||||
|
child: BlocBuilder<UserPurchasesCubit, UserPurchasesState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: const Color(0xFFF0F2F5),
|
||||||
|
appBar: AppBar(
|
||||||
|
shape: const RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadiusDirectional.vertical(
|
||||||
|
bottom: Radius.circular(12),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
title: Text(
|
||||||
|
'Финансы',
|
||||||
|
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
|
||||||
|
),
|
||||||
|
centerTitle: true,
|
||||||
|
),
|
||||||
|
body: state.isLoading
|
||||||
|
? const Center(
|
||||||
|
child: Loader(),
|
||||||
|
)
|
||||||
|
: SingleChildScrollView(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
Material(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 16, right: 16, top: 16),
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
CustomDropDownButton<PeriodFilterStatus>(
|
||||||
|
items: PeriodFilterStatus.values
|
||||||
|
.map(
|
||||||
|
(value) => DropdownMenuItem(
|
||||||
|
value: value,
|
||||||
|
child: Text(
|
||||||
|
value.name,
|
||||||
|
style: TextStyles.textMMedium.copyWith(color: appTheme.black),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList(),
|
||||||
|
onChanged: (value) {
|
||||||
|
if (value == null) return;
|
||||||
|
context.read<UserPurchasesCubit>().setPurchasesPeriod(value);
|
||||||
|
},
|
||||||
|
value: state.periodFilterStatus ?? PeriodFilterStatus.values.first,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
if (state.purchasesModels.isNotEmpty)
|
||||||
|
ListView.separated(
|
||||||
|
shrinkWrap: true,
|
||||||
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final Status purchaseStatus;
|
||||||
|
if (state.purchasesModels[index].chosenPlanState == ChosenPlanStateEnum.stateCanceledByTheInitiator) {
|
||||||
|
purchaseStatus = Status.canceled;
|
||||||
|
} else if (state.purchasesModels[index].chosenPlanState == ChosenPlanStateEnum.stateChargeWasCollected) {
|
||||||
|
purchaseStatus = Status.success;
|
||||||
|
} else {
|
||||||
|
purchaseStatus = Status.inProgress;
|
||||||
|
}
|
||||||
|
return Material(
|
||||||
|
color: const Color(0xFFF6F6F6),
|
||||||
|
borderRadius: BorderRadius.circular(20),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(12),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Builder(builder: (context) {
|
||||||
|
final idLen = state.purchasesModels[index].bankId.length;
|
||||||
|
return Text(
|
||||||
|
'${state.purchasesModels[index].bankId.substring(0, 4)}...${state.purchasesModels[index].bankId.substring(idLen - 4, idLen)} ',
|
||||||
|
style: TextStyles.textSMedium.copyWith(color: appTheme.black),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
Text(
|
||||||
|
state.purchasesModels[index].startDate.format('yyyy.MM.dd'),
|
||||||
|
style: const TextStyle(
|
||||||
|
color: Color(0xFF6D6F71),
|
||||||
|
height: 1,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
Text(
|
||||||
|
state.purchasesModels[index].title,
|
||||||
|
style: TextStyle(
|
||||||
|
color: appTheme.blueA400,
|
||||||
|
height: 1,
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
Text(
|
||||||
|
'Продавец: ${state.purchasesModels[index].consultantName}',
|
||||||
|
style: const TextStyle(
|
||||||
|
color: Color(0xFF323F4B),
|
||||||
|
height: 1,
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
Text(
|
||||||
|
'${state.purchasesModels[index].duration} ${getDayForm(state.purchasesModels[index].duration, s)}',
|
||||||
|
style: const TextStyle(
|
||||||
|
color: Color(0xFF323F4B),
|
||||||
|
height: 1,
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
Container(
|
||||||
|
height: 1,
|
||||||
|
width: double.infinity,
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
color: Color(0xFFDEDEDF),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'${state.purchasesModels[index].paymentPrice} ₽',
|
||||||
|
style: const TextStyle(
|
||||||
|
color: Color(0xFF323F4B),
|
||||||
|
height: 1,
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
StatusWidget(
|
||||||
|
status: purchaseStatus,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
separatorBuilder: (context, index) => const SizedBox(height: 12),
|
||||||
|
itemCount: state.purchasesModels.length,
|
||||||
|
)
|
||||||
|
else
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 40.0),
|
||||||
|
child: Text(
|
||||||
|
'У вас нет таких консультаций',
|
||||||
|
style: TextStyles.textMMedium,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,15 +1,15 @@
|
|||||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||||
import 'package:eatvio_app/features/plans/enums/chosen_plan_state_enum.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class StatusWidget extends StatelessWidget {
|
class StatusWidget extends StatelessWidget {
|
||||||
const StatusWidget({super.key, required this.status});
|
const StatusWidget({super.key, required this.status});
|
||||||
final ChosenPlanStateEnum status;
|
final Status status;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
if (status == ChosenPlanStateEnum.stateCanceledByTheInitiator) {
|
return switch (status){
|
||||||
return Material(
|
|
||||||
|
Status.canceled => Material(
|
||||||
color: appTheme.lightRed,
|
color: appTheme.lightRed,
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
child: Padding(
|
child: Padding(
|
||||||
@@ -24,9 +24,9 @@ class StatusWidget extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
),
|
||||||
} else if (status == ChosenPlanStateEnum.stateChargeWasCollected) {
|
|
||||||
return Material(
|
Status.success => Material(
|
||||||
color: const Color(0xFF0BB450).withAlpha(11),
|
color: const Color(0xFF0BB450).withAlpha(11),
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
child: const Padding(
|
child: const Padding(
|
||||||
@@ -41,9 +41,9 @@ class StatusWidget extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
),
|
||||||
}
|
|
||||||
return Material(
|
Status.inProgress => Material(
|
||||||
color: appTheme.transparentBlue,
|
color: appTheme.transparentBlue,
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
child: Padding(
|
child: Padding(
|
||||||
@@ -58,6 +58,13 @@ class StatusWidget extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum Status {
|
||||||
|
canceled,
|
||||||
|
success,
|
||||||
|
inProgress
|
||||||
|
}
|
||||||
@@ -4,6 +4,8 @@ import 'package:eatvio_app/core/token_storage.dart';
|
|||||||
import 'package:eatvio_app/core/utils/image_constant.dart';
|
import 'package:eatvio_app/core/utils/image_constant.dart';
|
||||||
import 'package:eatvio_app/core/locator_service.dart';
|
import 'package:eatvio_app/core/locator_service.dart';
|
||||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||||
|
import 'package:eatvio_app/features/finances_and_consultations_archive/presentation/consultant_finances_screen.dart';
|
||||||
|
import 'package:eatvio_app/features/finances_and_consultations_archive/presentation/user_purchases_screen.dart';
|
||||||
import 'package:eatvio_app/features/my_diets/presentation/my_diets_screen.dart';
|
import 'package:eatvio_app/features/my_diets/presentation/my_diets_screen.dart';
|
||||||
import 'package:eatvio_app/features/my_plans/presentation/my_plans_screen.dart';
|
import 'package:eatvio_app/features/my_plans/presentation/my_plans_screen.dart';
|
||||||
import 'package:eatvio_app/features/profile/models/profile_model.dart';
|
import 'package:eatvio_app/features/profile/models/profile_model.dart';
|
||||||
@@ -40,7 +42,11 @@ class MenuScreen extends StatelessWidget {
|
|||||||
leading: 'assets/icons/finance.svg',
|
leading: 'assets/icons/finance.svg',
|
||||||
title: 'Мои финансы',
|
title: 'Мои финансы',
|
||||||
onTap: () {
|
onTap: () {
|
||||||
GoRouter.of(context).pushNamed('userFinanceScreen');
|
if (profileModel.roles.contains('consultant')) {
|
||||||
|
GoRouter.of(context).push(ConsultantFinancesScreen.path);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
GoRouter.of(context).push(UserPurchasesScreen.path);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
_divider(context),
|
_divider(context),
|
||||||
|
|||||||
@@ -2,8 +2,10 @@ import 'dart:io';
|
|||||||
|
|
||||||
import 'package:cached_network_image/cached_network_image.dart';
|
import 'package:cached_network_image/cached_network_image.dart';
|
||||||
import 'package:dismissible_page/dismissible_page.dart';
|
import 'package:dismissible_page/dismissible_page.dart';
|
||||||
|
import 'package:eatvio_app/core/app_router.dart';
|
||||||
import 'package:eatvio_app/core/const.dart';
|
import 'package:eatvio_app/core/const.dart';
|
||||||
import 'package:eatvio_app/core/enums/complained_content.dart';
|
import 'package:eatvio_app/core/enums/complained_content.dart';
|
||||||
|
import 'package:eatvio_app/core/permission_handler/permission_handler.dart';
|
||||||
import 'package:eatvio_app/core/utils/date_time_utils.dart';
|
import 'package:eatvio_app/core/utils/date_time_utils.dart';
|
||||||
import 'package:eatvio_app/core/widgets/data_error_widget.dart';
|
import 'package:eatvio_app/core/widgets/data_error_widget.dart';
|
||||||
import 'package:eatvio_app/core/widgets/loader.dart';
|
import 'package:eatvio_app/core/widgets/loader.dart';
|
||||||
@@ -26,6 +28,7 @@ import 'package:eatvio_app/features/profile/presentation/widgets/profile_blog_po
|
|||||||
import 'package:eatvio_app/features/profile/presentation/widgets/weight_chart_widget.dart';
|
import 'package:eatvio_app/features/profile/presentation/widgets/weight_chart_widget.dart';
|
||||||
import 'package:eatvio_app/core/locator_service.dart';
|
import 'package:eatvio_app/core/locator_service.dart';
|
||||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||||
|
import 'package:eatvio_app/generated/l10n.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
@@ -34,6 +37,7 @@ import 'package:go_router/go_router.dart';
|
|||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
import 'package:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:permission_handler/permission_handler.dart';
|
||||||
import 'package:share_plus/share_plus.dart';
|
import 'package:share_plus/share_plus.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
@@ -600,9 +604,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
|||||||
|
|
||||||
_educationBlock(String title, String date) {
|
_educationBlock(String title, String date) {
|
||||||
final parsedDate = DateTime.tryParse(date);
|
final parsedDate = DateTime.tryParse(date);
|
||||||
final formattedDate = parsedDate != null
|
final formattedDate = parsedDate != null ? DateFormat('d MMMM y', 'ru_RU').format(parsedDate) : date;
|
||||||
? DateFormat('d MMMM y', 'ru_RU').format(parsedDate)
|
|
||||||
: date;
|
|
||||||
|
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
@@ -640,7 +642,6 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
_socialLinks(ProfileStateLoaded state) {
|
_socialLinks(ProfileStateLoaded state) {
|
||||||
if (!state.profile.roles.contains('consultant')) {
|
if (!state.profile.roles.contains('consultant')) {
|
||||||
return const SizedBox.shrink();
|
return const SizedBox.shrink();
|
||||||
@@ -993,51 +994,70 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
|||||||
if (value == 'replace') {
|
if (value == 'replace') {
|
||||||
showCupertinoModalPopup<void>(
|
showCupertinoModalPopup<void>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => CupertinoActionSheet(
|
builder: (context) {
|
||||||
actions: [
|
final s = S.of(context);
|
||||||
CupertinoActionSheetAction(
|
return CupertinoActionSheet(
|
||||||
onPressed: () async {
|
actions: [
|
||||||
Navigator.of(context).pop();
|
CupertinoActionSheetAction(
|
||||||
final picker = ImagePicker();
|
onPressed: () async {
|
||||||
XFile? image = await picker.pickImage(source: ImageSource.camera);
|
PermissionHandler.checkPermission(
|
||||||
if (image != null) {
|
permission: Permission.camera,
|
||||||
await profileCubit.uploadPhoto(File(image.path));
|
title: s.allowAccessToCamera,
|
||||||
await sl<ProfileAvatarCubit>().getMyProfile();
|
description: s.allowAccessToCameraDescription,
|
||||||
}
|
onGranted: () async {
|
||||||
},
|
AppRouter.navigatorKey.currentContext?.pop();
|
||||||
child: const Row(
|
final picker = ImagePicker();
|
||||||
children: [
|
XFile? image = await picker.pickImage(source: ImageSource.camera);
|
||||||
Icon(Icons.photo_camera),
|
if (image != null) {
|
||||||
SizedBox(width: 8),
|
await profileCubit.uploadPhoto(File(image.path));
|
||||||
Text('Фото'),
|
await sl<ProfileAvatarCubit>().getMyProfile();
|
||||||
],
|
}
|
||||||
|
},
|
||||||
|
context: context,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: const Row(
|
||||||
|
children: [
|
||||||
|
Icon(Icons.photo_camera),
|
||||||
|
SizedBox(width: 8),
|
||||||
|
Text('Фото'),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
CupertinoActionSheetAction(
|
||||||
CupertinoActionSheetAction(
|
onPressed: () async {
|
||||||
onPressed: () async {
|
PermissionHandler.checkPermission(
|
||||||
Navigator.of(context).pop();
|
permission: Permission.photos,
|
||||||
final picker = ImagePicker();
|
title: s.allowAcessToGalery,
|
||||||
XFile? image = await picker.pickImage(source: ImageSource.gallery);
|
description: s.allowAcessToGaleryDescription,
|
||||||
if (image != null) {
|
onGranted: () async {
|
||||||
await profileCubit.uploadPhoto(File(image.path));
|
AppRouter.navigatorKey.currentContext?.pop();
|
||||||
await sl<ProfileAvatarCubit>().getMyProfile();
|
final picker = ImagePicker();
|
||||||
}
|
XFile? image = await picker.pickImage(source: ImageSource.gallery);
|
||||||
},
|
if (image != null) {
|
||||||
child: const Row(
|
await profileCubit.uploadPhoto(File(image.path));
|
||||||
children: [
|
await sl<ProfileAvatarCubit>().getMyProfile();
|
||||||
Icon(Icons.photo),
|
}
|
||||||
SizedBox(width: 8),
|
},
|
||||||
Text('Галерея'),
|
context: context,
|
||||||
],
|
);
|
||||||
|
},
|
||||||
|
child: const Row(
|
||||||
|
children: [
|
||||||
|
Icon(Icons.photo),
|
||||||
|
SizedBox(width: 8),
|
||||||
|
Text('Галерея'),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
|
],
|
||||||
|
cancelButton: CupertinoActionSheetAction(
|
||||||
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
|
isDestructiveAction: true,
|
||||||
|
child: const Text('Отмена'),
|
||||||
),
|
),
|
||||||
],
|
);
|
||||||
cancelButton: CupertinoActionSheetAction(
|
},
|
||||||
onPressed: () => Navigator.of(context).pop(),
|
|
||||||
isDestructiveAction: true,
|
|
||||||
child: const Text('Отмена'),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (value == 'delete') {
|
if (value == 'delete') {
|
||||||
|
|||||||
@@ -73,6 +73,19 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"allergies_presence": MessageLookupByLibrary.simpleMessage(
|
"allergies_presence": MessageLookupByLibrary.simpleMessage(
|
||||||
"Наличие аллергии",
|
"Наличие аллергии",
|
||||||
),
|
),
|
||||||
|
"allowAccess": MessageLookupByLibrary.simpleMessage("Разрешить доступ"),
|
||||||
|
"allowAccessToCamera": MessageLookupByLibrary.simpleMessage(
|
||||||
|
"Разрешите доступ к камере",
|
||||||
|
),
|
||||||
|
"allowAccessToCameraDescription": MessageLookupByLibrary.simpleMessage(
|
||||||
|
"Предоставление доступа позволит вам делать фотографии и добавлять к записям",
|
||||||
|
),
|
||||||
|
"allowAcessToGalery": MessageLookupByLibrary.simpleMessage(
|
||||||
|
"Разрешите доступ к фото",
|
||||||
|
),
|
||||||
|
"allowAcessToGaleryDescription": MessageLookupByLibrary.simpleMessage(
|
||||||
|
"Предоставление доступа позволит вам добавлять фото к записям",
|
||||||
|
),
|
||||||
"another_form_of_comment": MessageLookupByLibrary.simpleMessage(
|
"another_form_of_comment": MessageLookupByLibrary.simpleMessage(
|
||||||
"комментария",
|
"комментария",
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -28,9 +28,10 @@ class S {
|
|||||||
static const AppLocalizationDelegate delegate = AppLocalizationDelegate();
|
static const AppLocalizationDelegate delegate = AppLocalizationDelegate();
|
||||||
|
|
||||||
static Future<S> load(Locale locale) {
|
static Future<S> load(Locale locale) {
|
||||||
final name = (locale.countryCode?.isEmpty ?? false)
|
final name =
|
||||||
? locale.languageCode
|
(locale.countryCode?.isEmpty ?? false)
|
||||||
: locale.toString();
|
? locale.languageCode
|
||||||
|
: locale.toString();
|
||||||
final localeName = Intl.canonicalizedLocale(name);
|
final localeName = Intl.canonicalizedLocale(name);
|
||||||
return initializeMessages(localeName).then((_) {
|
return initializeMessages(localeName).then((_) {
|
||||||
Intl.defaultLocale = localeName;
|
Intl.defaultLocale = localeName;
|
||||||
@@ -3343,6 +3344,56 @@ class S {
|
|||||||
args: [],
|
args: [],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// `Разрешите доступ к фото`
|
||||||
|
String get allowAcessToGalery {
|
||||||
|
return Intl.message(
|
||||||
|
'Разрешите доступ к фото',
|
||||||
|
name: 'allowAcessToGalery',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Предоставление доступа позволит вам добавлять фото к записям`
|
||||||
|
String get allowAcessToGaleryDescription {
|
||||||
|
return Intl.message(
|
||||||
|
'Предоставление доступа позволит вам добавлять фото к записям',
|
||||||
|
name: 'allowAcessToGaleryDescription',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Разрешите доступ к камере`
|
||||||
|
String get allowAccessToCamera {
|
||||||
|
return Intl.message(
|
||||||
|
'Разрешите доступ к камере',
|
||||||
|
name: 'allowAccessToCamera',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Предоставление доступа позволит вам делать фотографии и добавлять к записям`
|
||||||
|
String get allowAccessToCameraDescription {
|
||||||
|
return Intl.message(
|
||||||
|
'Предоставление доступа позволит вам делать фотографии и добавлять к записям',
|
||||||
|
name: 'allowAccessToCameraDescription',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Разрешить доступ`
|
||||||
|
String get allowAccess {
|
||||||
|
return Intl.message(
|
||||||
|
'Разрешить доступ',
|
||||||
|
name: 'allowAccess',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AppLocalizationDelegate extends LocalizationsDelegate<S> {
|
class AppLocalizationDelegate extends LocalizationsDelegate<S> {
|
||||||
|
|||||||
@@ -397,6 +397,11 @@
|
|||||||
"planStarted": "План «{planName}» начался",
|
"planStarted": "План «{planName}» начался",
|
||||||
"userCanceldThePlanSubscription": "Пользователь {name} отменил подписку на план «{planName}»",
|
"userCanceldThePlanSubscription": "Пользователь {name} отменил подписку на план «{planName}»",
|
||||||
"userSubscribedToPlan": "Пользователь {name} подписался на план «{planName}»",
|
"userSubscribedToPlan": "Пользователь {name} подписался на план «{planName}»",
|
||||||
"markAsRead": "Отметить всё прочитанным"
|
"markAsRead": "Отметить всё прочитанным",
|
||||||
|
"allowAcessToGalery": "Разрешите доступ к фото",
|
||||||
|
"allowAcessToGaleryDescription": "Предоставление доступа позволит вам добавлять фото к записям",
|
||||||
|
"allowAccessToCamera": "Разрешите доступ к камере",
|
||||||
|
"allowAccessToCameraDescription": "Предоставление доступа позволит вам делать фотографии и добавлять к записям",
|
||||||
|
"allowAccess": "Разрешить доступ"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ dependencies:
|
|||||||
version: ^3.0.2
|
version: ^3.0.2
|
||||||
package_info_plus: ^8.3.0
|
package_info_plus: ^8.3.0
|
||||||
device_info_plus: ^11.4.0
|
device_info_plus: ^11.4.0
|
||||||
|
permission_handler: ^12.0.0+1
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
build_runner: ^2.4.15
|
build_runner: ^2.4.15
|
||||||
|
|||||||
Reference in New Issue
Block a user