diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj
index 2100a65d..d535af69 100644
--- a/ios/Runner.xcodeproj/project.pbxproj
+++ b/ios/Runner.xcodeproj/project.pbxproj
@@ -388,7 +388,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Distribution: ITVIO, OOO (VL68C36HYS)";
CODE_SIGN_STYLE = Manual;
- CURRENT_PROJECT_VERSION = 20;
+ CURRENT_PROJECT_VERSION = 21;
DEVELOPMENT_TEAM = VL68C36HYS;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
@@ -538,7 +538,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Distribution: ITVIO, OOO (VL68C36HYS)";
CODE_SIGN_STYLE = Manual;
- CURRENT_PROJECT_VERSION = 20;
+ CURRENT_PROJECT_VERSION = 21;
DEVELOPMENT_TEAM = VL68C36HYS;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
@@ -576,7 +576,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Distribution: ITVIO, OOO (VL68C36HYS)";
CODE_SIGN_STYLE = Manual;
- CURRENT_PROJECT_VERSION = 20;
+ CURRENT_PROJECT_VERSION = 21;
DEVELOPMENT_TEAM = VL68C36HYS;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist
index c23a16a5..498d4b70 100644
--- a/ios/Runner/Info.plist
+++ b/ios/Runner/Info.plist
@@ -21,7 +21,7 @@
CFBundleSignature
????
CFBundleVersion
- 20
+ 21
ITSAppUsesNonExemptEncryption
LSRequiresIPhoneOS
diff --git a/lib/core/app_router.dart b/lib/core/app_router.dart
index 172d840d..fec9b100 100644
--- a/lib/core/app_router.dart
+++ b/lib/core/app_router.dart
@@ -32,7 +32,7 @@ import 'package:eatvio_app/features/glossary/presentation/pages/glossary_screen.
import 'package:eatvio_app/features/menu/presentation/pages/menu_screen.dart';
import 'package:eatvio_app/features/my_diets/presentation/my_diets_screen.dart';
import 'package:eatvio_app/features/my_finance/presentation/pages/card_settings.dart';
-import 'package:eatvio_app/features/my_finance/presentation/pages/consultant_finance_screen.dart';
+import 'package:eatvio_app/features/finances_and_consultations_archive/presentation/consultations_archive_screen.dart';
import 'package:eatvio_app/features/my_finance/presentation/pages/user_finance_screen.dart';
import 'package:eatvio_app/features/my_plans/presentation/my_plans_screen.dart';
import 'package:eatvio_app/features/notifications/presentation/notifications_screen.dart';
@@ -177,7 +177,7 @@ class AppRouter {
GoRoute(
path: '/consultant-finance-screen',
name: 'consultantFinanceScreen',
- builder: (context, state) => const ConsultantFinanceScreen(),
+ builder: (context, state) => const ConsultationsArchiveScreen(),
),
GoRoute(
path: '/user-finance-screen',
diff --git a/lib/core/enums/filters_comparison_enum.dart b/lib/core/enums/filters_comparison_enum.dart
new file mode 100644
index 00000000..57957552
--- /dev/null
+++ b/lib/core/enums/filters_comparison_enum.dart
@@ -0,0 +1,13 @@
+enum FiltersComparisonEnum {
+ equal('\$eq'),
+ notEqual('\$ne'),
+ greaterThan('\$gt'),
+ lessThan('\$lt'),
+ greaterThanOrEqual('\$gte'),
+ lessThanOrEqual('\$lte'),
+ inArray('\$in'),
+ notInArray('\$notIn');
+
+ final String value;
+ const FiltersComparisonEnum(this.value);
+}
diff --git a/lib/core/locator_service.dart b/lib/core/locator_service.dart
index 1d44bc27..9ee53c7c 100644
--- a/lib/core/locator_service.dart
+++ b/lib/core/locator_service.dart
@@ -16,6 +16,7 @@ import 'package:eatvio_app/features/complaining/services/complaining_service.dar
import 'package:eatvio_app/features/consultations/presentation/cubit/consultations_cubit.dart';
import 'package:eatvio_app/features/consultations/repositories/consultations_repository.dart';
import 'package:eatvio_app/features/consultations/services/consultation_service.dart';
+import 'package:eatvio_app/features/finances_and_consultations_archive/cubit/archive/consultations_archive_cubit.dart';
import 'package:eatvio_app/features/create_diet/presentation/cubit/create_diet_cubit.dart';
import 'package:eatvio_app/features/create_diet/repositories/create_diet_repository.dart';
import 'package:eatvio_app/features/create_diet/services/create_diet_service.dart';
@@ -121,7 +122,8 @@ Future init() async {
sl.registerFactory(() => PlansCubit(feedRepository: sl(), planRepository: sl()));
sl.registerFactory(() => SettingsCubit(profileRepository: sl(), settingsRepository: sl()));
sl.registerFactory(() => RegisterConsultantCubit(consultantRepository: sl()));
- sl.registerFactory(() => DiaryCubit(diaryRepository: sl(), glossaryRepository: sl(), profileRepository: sl(), dietRepository: sl()));
+ sl.registerFactory(
+ () => DiaryCubit(chatRepository: sl(), diaryRepository: sl(), glossaryRepository: sl(), profileRepository: sl(), dietRepository: sl()));
sl.registerFactory(() => AboutDietCubit(dietsRepository: sl(), profileRepository: sl()));
sl.registerFactory(() => BlogPostCreateCubit(blogPostRepository: sl()));
sl.registerFactory(() => SubCubit(profileRepository: sl()));
@@ -144,6 +146,7 @@ Future init() async {
sl.registerFactory(() => CancelPlanCubit(cancelPlanRepository: sl()));
sl.registerFactory(() => VerifyEmailCubit(profileRepository: sl()));
sl.registerFactory(() => MyRecipesCubit(myRecipesRepository: sl(), aboutRecipeRepository: sl()));
+ sl.registerFactory(() => ConsultationsArchiveCubit(consultationsRepository: sl()));
// Repository
sl.registerLazySingleton(() => ChatRepository(chatService: sl()));
diff --git a/lib/core/theme/theme_helper.dart b/lib/core/theme/theme_helper.dart
index aa4e30a6..3b2a063d 100644
--- a/lib/core/theme/theme_helper.dart
+++ b/lib/core/theme/theme_helper.dart
@@ -101,8 +101,7 @@ class PrimaryColors {
// Blue
Color get blue400 => const Color(0XFF43A6F2);
- Color get blueA400 => const Color(0XFF2F80ED);
-
+ Color get blueA400 => const Color(0XFF2F80ED);
// BlueGray
Color get blueGray400 => const Color(0XFF7B8794);
diff --git a/lib/features/consultations/presentation/pages/consultations_screen.dart b/lib/features/consultations/presentation/pages/consultations_screen.dart
index 34f25b96..d6acb306 100644
--- a/lib/features/consultations/presentation/pages/consultations_screen.dart
+++ b/lib/features/consultations/presentation/pages/consultations_screen.dart
@@ -1,5 +1,6 @@
import 'package:eatvio_app/core/enums/base_state.dart';
import 'package:eatvio_app/core/locator_service.dart';
+import 'package:eatvio_app/core/theme/theme_helper.dart';
import 'package:eatvio_app/core/widgets/data_error_widget.dart';
import 'package:eatvio_app/core/widgets/loader.dart';
import 'package:eatvio_app/features/consultations/presentation/cubit/consultations_cubit.dart';
@@ -7,6 +8,7 @@ import 'package:eatvio_app/features/consultations/presentation/cubit/consultatio
import 'package:eatvio_app/features/consultations/presentation/widgets/consultation_card_widget.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:go_router/go_router.dart';
class ConsultationsScreen extends StatelessWidget {
static const path = '/consultations-screen';
@@ -46,15 +48,49 @@ class ConsultationsContent extends StatelessWidget {
context.read().loadConsultations();
}),
BaseState.initial => const Loader(),
- BaseState.success => ListView.separated(
- padding: const EdgeInsets.symmetric(vertical: 12),
- itemBuilder: (context, index) => ConsultationCardWidget(
- consultationsModel: state.consultations[index],
+ BaseState.success => SingleChildScrollView(
+ child: Column(
+ children: [
+ ListView.separated(
+ padding: const EdgeInsets.symmetric(vertical: 12),
+ physics: const NeverScrollableScrollPhysics(),
+ itemBuilder: (context, index) => ConsultationCardWidget(
+ consultationsModel: state.consultations[index],
+ ),
+ separatorBuilder: (context, index) => const SizedBox(
+ height: 12,
+ ),
+ shrinkWrap: true,
+ itemCount: state.consultations.length,
+ ),
+ const SizedBox(height: 20),
+ InkWell(
+ borderRadius: BorderRadius.circular(20),
+ onTap: () {
+ GoRouter.of(context).pushNamed('consultantFinanceScreen');
+ },
+ child: Ink(
+ width: MediaQuery.of(context).size.width - 32,
+ padding: const EdgeInsets.all(16),
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.circular(20),
+ color: appTheme.blueA400,
+ ),
+ child: const Center(
+ child: Text(
+ 'Архив консультаций',
+ style: TextStyle(
+ color: Colors.white,
+ fontSize: 16,
+ fontWeight: FontWeight.w600,
+ ),
+ ),
+ ),
+ ),
+ ),
+ const SizedBox(height: 20),
+ ],
),
- separatorBuilder: (context, index) => const SizedBox(
- height: 12,
- ),
- itemCount: state.consultations.length,
),
});
},
diff --git a/lib/features/consultations/presentation/widgets/consultation_card_widget.dart b/lib/features/consultations/presentation/widgets/consultation_card_widget.dart
index 834f0e58..0752847b 100644
--- a/lib/features/consultations/presentation/widgets/consultation_card_widget.dart
+++ b/lib/features/consultations/presentation/widgets/consultation_card_widget.dart
@@ -1,4 +1,5 @@
import 'package:collection/collection.dart';
+import 'package:eatvio_app/core/const.dart';
import 'package:eatvio_app/core/theme/custom_text_style.dart';
import 'package:eatvio_app/core/theme/theme_helper.dart';
import 'package:eatvio_app/core/widgets/custom_divider.dart';
@@ -73,7 +74,7 @@ class _ConsultationCardWidgetState extends State {
children: [
CircleAvatar(
radius: 30,
- backgroundImage: NetworkImage(widget.consultationsModel.userProfilePhotoUrl),
+ backgroundImage: NetworkImage(baseUrl + widget.consultationsModel.userProfilePhotoUrl),
),
const SizedBox(width: 12),
Column(
diff --git a/lib/features/consultations/repositories/consultations_repository.dart b/lib/features/consultations/repositories/consultations_repository.dart
index 93d84f67..3ebcef87 100644
--- a/lib/features/consultations/repositories/consultations_repository.dart
+++ b/lib/features/consultations/repositories/consultations_repository.dart
@@ -1,5 +1,7 @@
+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/services/consultation_service.dart';
+import 'package:eatvio_app/features/finances_and_consultations_archive/models/statistic_model.dart';
class ConsultationsRepository {
final ConsultationService consultationService;
@@ -13,4 +15,31 @@ class ConsultationsRepository {
rethrow;
}
}
+
+ Future> getFilteredConsultations({
+ String? state,
+ String? date,
+ FiltersComparisonEnum? stateComparison,
+ FiltersComparisonEnum? dateComparison,
+ }) async {
+ try {
+ final model = await consultationService.getFilteredConsultations(
+ state: state,
+ date: date,
+ stateComparison: stateComparison,
+ dateComparison: dateComparison,
+ );
+ return model.data;
+ } catch (e) {
+ rethrow;
+ }
+ }
+
+ Future getStatistic() async {
+ try {
+ return await consultationService.getStatistics();
+ } catch (e) {
+ rethrow;
+ }
+ }
}
diff --git a/lib/features/consultations/services/consultation_service.dart b/lib/features/consultations/services/consultation_service.dart
index 49ebe41c..fa14b69c 100644
--- a/lib/features/consultations/services/consultation_service.dart
+++ b/lib/features/consultations/services/consultation_service.dart
@@ -1,17 +1,69 @@
import 'package:dio/dio.dart';
+import 'package:eatvio_app/core/enums/filters_comparison_enum.dart';
import 'package:eatvio_app/features/consultations/models/consultation_model.dart';
-import 'package:retrofit/retrofit.dart';
+import 'package:eatvio_app/features/finances_and_consultations_archive/models/statistic_model.dart';
-part 'consultation_service.g.dart';
+class ConsultationService {
+ final Dio dio;
+ ConsultationService(this.dio);
-@RestApi()
-abstract class ConsultationService {
- factory ConsultationService(Dio dio, {String baseUrl}) = _ConsultationService;
+ Future getConsultations() async {
+ try {
+ final response = await dio.get('/api/consultations', queryParameters: {
+ 'filters[last_state][\$notIn][]': const [
+ 'initied',
+ 'in_coordination',
+ 'start_date_has_been_set',
+ 'pending_payment',
+ 'canceled_by_the_initiator',
+ 'charge_was_collected',
+ ],
+ 'sort[]': 'created_at:desc'
+ });
+ return ConsultationPaginationModel.fromJson(response.data);
+ } catch (e) {
+ rethrow;
+ }
+ }
- @GET('/api/consultations')
- Future getConsultations({
- @Query('filters[last_state][\$notIn][]') String query = 'canceled_by_the_initiator',
- @Query('filters[last_state][\$notIn][]') String query2 = 'charge_was_collected',
- @Query('sort[]') String sort = 'created_at:desc',
- });
+ Future getFilteredConsultations({
+ String? state,
+ String? date,
+ FiltersComparisonEnum? stateComparison,
+ FiltersComparisonEnum? dateComparison,
+ }) async {
+ try {
+ final response = await dio.get(
+ '/api/consultations',
+ queryParameters: {
+ if (stateComparison == FiltersComparisonEnum.notInArray)
+ 'filters[last_state][\$notIn][]': const [
+ 'initied',
+ 'in_coordination',
+ 'start_date_has_been_set',
+ 'pending_payment',
+ 'canceled_by_the_initiator',
+ 'charge_was_collected',
+ ]
+ else if (state != null && stateComparison != null)
+ 'filters[last_state][${stateComparison.value}]': state,
+ if (dateComparison != null && date != null) 'filters[start_date][${dateComparison.value}]': date,
+ },
+ );
+ return ConsultationPaginationModel.fromJson(response.data);
+ } catch (e) {
+ rethrow;
+ }
+ }
+
+ Future getStatistics() async {
+ try {
+ final response = await dio.get(
+ '/api/consultations/statistics',
+ );
+ return StatisticModel.fromJson(response.data);
+ } catch (e) {
+ rethrow;
+ }
+ }
}
diff --git a/lib/features/diary/presentation/bloc/diary_cubit.dart b/lib/features/diary/presentation/bloc/diary_cubit.dart
index a07f6611..425c95a7 100644
--- a/lib/features/diary/presentation/bloc/diary_cubit.dart
+++ b/lib/features/diary/presentation/bloc/diary_cubit.dart
@@ -3,6 +3,7 @@ import 'dart:io';
import 'package:eatvio_app/core/image_compressing/image_compress_utility.dart';
import 'package:eatvio_app/core/utils/date_time_utils.dart';
+import 'package:eatvio_app/features/chat/repositories/chat_repository.dart';
import 'package:eatvio_app/features/consultations/models/consultation_model.dart';
import 'package:eatvio_app/features/diary/models/consultant_review_model.dart';
import 'package:eatvio_app/features/diary/models/diary_day_model.dart';
@@ -23,8 +24,14 @@ class DiaryCubit extends Cubit {
final GlossaryRepository glossaryRepository;
final ProfileRepository profileRepository;
final DietRepository dietRepository;
+ final ChatRepository chatRepository;
int? diaryId;
- DiaryCubit({required this.diaryRepository, required this.glossaryRepository, required this.profileRepository, required this.dietRepository})
+ DiaryCubit(
+ {required this.chatRepository,
+ required this.diaryRepository,
+ required this.glossaryRepository,
+ required this.profileRepository,
+ required this.dietRepository})
: super(const DiaryState.loading()) {
today = DateTime.now();
selectedDay = today;
@@ -146,6 +153,7 @@ class DiaryCubit extends Cubit {
fetchDiary([bool needLoading = false, int? diaryId]) async {
this.diaryId ??= diaryId;
+
if (needLoading) {
emit(const DiaryState.loading());
selectedMeal = 1;
@@ -159,8 +167,15 @@ class DiaryCubit extends Cubit {
diaryDay = await diaryRepository.getDiaryByDate(stringDate);
}
ConsultantReviewModel? consultantReview;
+ int? planDuration;
+ int? currentPlanDay;
+ String? planName;
if (diaryDay.chosenPlanId != null) {
consultantReview = await diaryRepository.getDiaryComments(planId: diaryDay.chosenPlanId!, diaryId: diaryDay.id);
+ final chosenPlanModel = await chatRepository.getChosenPlan(id: diaryDay.chosenPlanId!);
+ planDuration = chosenPlanModel.plan.duration;
+ planName = chosenPlanModel.plan.name;
+ currentPlanDay = DateTime.now().difference(chosenPlanModel.startDate).inDays + 1;
}
final nutrition = await getNutrition(diaryDay.id);
@@ -179,6 +194,9 @@ class DiaryCubit extends Cubit {
consultantReview: consultantReview,
isDiaryFinished: isDiaryFinished,
isDiaryCommented: isDiaryCommented,
+ chosenPlanCurrentDay: currentPlanDay,
+ chosenPlanDuration: planDuration,
+ chosenPlanName: planName,
),
);
} catch (e, st) {
diff --git a/lib/features/diary/presentation/bloc/diary_state.dart b/lib/features/diary/presentation/bloc/diary_state.dart
index 40f1f0ef..828831d3 100644
--- a/lib/features/diary/presentation/bloc/diary_state.dart
+++ b/lib/features/diary/presentation/bloc/diary_state.dart
@@ -20,8 +20,11 @@ abstract class DiaryState with _$DiaryState {
required NutritionDataModel nutrition,
required DateTime selectedDay,
required int selectedMeal,
- @Default(false) bool isConsultantView,
+ int? chosenPlanCurrentDay,
+ String? chosenPlanName,
+ int? chosenPlanDuration,
ConsultantReviewModel? consultantReview,
+ @Default(false) bool isConsultantView,
@Default(false) bool isDiaryFinished,
@Default(false) bool isDiaryCommented,
}) = DiaryStateLoaded;
diff --git a/lib/features/diary/presentation/widgets/chosen_plan_widget.dart b/lib/features/diary/presentation/widgets/chosen_plan_widget.dart
new file mode 100644
index 00000000..30ce656c
--- /dev/null
+++ b/lib/features/diary/presentation/widgets/chosen_plan_widget.dart
@@ -0,0 +1,66 @@
+import 'package:eatvio_app/core/theme/custom_text_style.dart';
+import 'package:eatvio_app/core/theme/theme_helper.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/generated/l10n.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+class ChosenPlanWidget extends StatelessWidget {
+ const ChosenPlanWidget({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return BlocBuilder(builder: (context, state) {
+ if (state is DiaryStateLoaded) {
+ if (state.diary.typeOfDiary.hasChosenPlan) {
+ return ChosenPlanWidgetContent(
+ currentPlanDay: state.chosenPlanCurrentDay ?? 0,
+ planName: state.chosenPlanName ?? '',
+ planDuration: state.chosenPlanDuration ?? 0,
+ );
+ }
+ }
+
+ return const SizedBox.shrink();
+ });
+ }
+}
+
+class ChosenPlanWidgetContent extends StatelessWidget {
+ const ChosenPlanWidgetContent({
+ super.key,
+ required this.currentPlanDay,
+ required this.planName,
+ required this.planDuration,
+ });
+ final int currentPlanDay;
+ final String planName;
+ final int planDuration;
+ @override
+ Widget build(BuildContext context) {
+ final size = MediaQuery.sizeOf(context);
+ final s = S.of(context);
+ return Column(
+ children: [
+ Row(
+ children: [
+ SizedBox(
+ width: size.width * 0.4,
+ child: Text(planName, style: TextStyles.textLMedium.copyWith(color: appTheme.black)),
+ ),
+ const Spacer(),
+ Container(
+ decoration: BoxDecoration(color: appTheme.dividerColor, borderRadius: BorderRadius.circular(12)),
+ padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 12),
+ child: Text('${s.day} $currentPlanDay из $planDuration', style: TextStyles.textMSemibold.copyWith(color: appTheme.gray)),
+ )
+ ],
+ ),
+ const SizedBox(
+ height: 16,
+ )
+ ],
+ );
+ }
+}
diff --git a/lib/features/diary/presentation/widgets/meal_widget.dart b/lib/features/diary/presentation/widgets/meal_widget.dart
index dc34a7c0..b5bd196a 100644
--- a/lib/features/diary/presentation/widgets/meal_widget.dart
+++ b/lib/features/diary/presentation/widgets/meal_widget.dart
@@ -5,6 +5,7 @@ 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/widgets/add_product_button_widget.dart';
import 'package:eatvio_app/features/diary/presentation/widgets/chosen_diet_widget.dart';
+import 'package:eatvio_app/features/diary/presentation/widgets/chosen_plan_widget.dart';
import 'package:eatvio_app/features/diary/presentation/widgets/comment_container.dart';
import 'package:eatvio_app/features/diary/presentation/widgets/meal_button_widget.dart';
import 'package:eatvio_app/features/diary/presentation/widgets/meal_comment_widget.dart';
@@ -60,6 +61,7 @@ class _MealWidgetState extends State {
const TimeOfMealPickerWidget(),
const ChosenDietWidget(),
+ const ChosenPlanWidget(),
const ProductsListWidget(),
if (widget.showAddButton) ...[
const SizedBox(height: 12),
diff --git a/lib/features/feed/presentation/bloc/feed_cubit/feed_cubit.dart b/lib/features/feed/presentation/bloc/feed_cubit/feed_cubit.dart
index 15b51e8f..17c435cb 100644
--- a/lib/features/feed/presentation/bloc/feed_cubit/feed_cubit.dart
+++ b/lib/features/feed/presentation/bloc/feed_cubit/feed_cubit.dart
@@ -1,3 +1,5 @@
+import 'dart:developer';
+
import 'package:eatvio_app/features/feed/models/feed_blog_post_model.dart';
import 'package:eatvio_app/features/feed/presentation/bloc/feed_cubit/feed_state.dart';
import 'package:eatvio_app/features/feed/repositories/feed_repository.dart';
@@ -77,7 +79,13 @@ class FeedCubit extends Cubit {
}
}
- likePost(int id) async => await feedRepository.likeBlogPost(id: id);
+ likePost(int id) async {
+ try {
+ await feedRepository.likeBlogPost(id: id);
+ } catch (e, st) {
+ log(e.toString(), stackTrace: st);
+ }
+ }
unlikedPost(int id) async => await feedRepository.unlikedBlogPost(id: id);
diff --git a/lib/features/finances_and_consultations_archive/cubit/archive/consultations_archive_cubit.dart b/lib/features/finances_and_consultations_archive/cubit/archive/consultations_archive_cubit.dart
new file mode 100644
index 00000000..dd6c713e
--- /dev/null
+++ b/lib/features/finances_and_consultations_archive/cubit/archive/consultations_archive_cubit.dart
@@ -0,0 +1,86 @@
+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/archive/consultations_archive_state.dart';
+import 'package:eatvio_app/features/finances_and_consultations_archive/models/statistic_model.dart';
+import 'package:eatvio_app/features/finances_and_consultations_archive/period_enum.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+class ConsultationsArchiveCubit extends Cubit {
+ final ConsultationsRepository consultationsRepository;
+ ConsultationsArchiveCubit({
+ required this.consultationsRepository,
+ }) : super(
+ ConsultationsArchiveState(
+ statisticModel: StatisticModel(
+ total: 0,
+ canceled: 0,
+ inProgress: 0,
+ finished: 0,
+ ),
+ ),
+ );
+
+ Future getConsultations() async {
+ try {
+ emit(state.copyWith(isLoading: true));
+ final consultations = await consultationsRepository.getFilteredConsultations(
+ date: state.periodFilterStatus?.value,
+ state: state.consultationFilterStatus?.value,
+ dateComparison: state.periodFilterStatus == PeriodFilterStatus.all ? null : FiltersComparisonEnum.greaterThanOrEqual,
+ stateComparison: state.consultationFilterStatus == ConsultationFilterStatus.all
+ ? null
+ : state.consultationFilterStatus == ConsultationFilterStatus.inProgress
+ ? FiltersComparisonEnum.notInArray
+ : FiltersComparisonEnum.equal,
+ );
+ emit(state.copyWith(consultations: consultations, isLoading: false));
+ } catch (e) {
+ emit(state.copyWith(isLoading: false));
+ log(e.toString());
+ }
+ }
+
+ Future setConsultationsPeriod(PeriodFilterStatus period) async {
+ emit(state.copyWith(periodFilterStatus: period));
+ await getConsultations();
+ }
+
+ Future setConsultationsStatus(ConsultationFilterStatus status) async {
+ emit(state.copyWith(consultationFilterStatus: status));
+ await getConsultations();
+ }
+
+ Future getStatistic() async {
+ try {
+ emit(state.copyWith(isLoading: true));
+ final statistic = await consultationsRepository.getStatistic();
+ emit(state.copyWith(statisticModel: statistic, isLoading: false));
+ } catch (e) {
+ emit(state.copyWith(isLoading: false));
+ log(e.toString());
+ }
+ }
+}
+
+enum ConsultationFilterStatus {
+ all,
+ canceled,
+ finished,
+ inProgress;
+
+ String get name => switch (this) {
+ ConsultationFilterStatus.all => 'Все консультации',
+ ConsultationFilterStatus.canceled => 'Отменён',
+ ConsultationFilterStatus.finished => 'Завершён',
+ ConsultationFilterStatus.inProgress => 'В процессе',
+ };
+
+ String? get value => switch (this) {
+ ConsultationFilterStatus.all => null,
+ ConsultationFilterStatus.canceled => 'canceled_by_the_initiator',
+ ConsultationFilterStatus.finished => 'charge_was_collected',
+ ConsultationFilterStatus.inProgress => 'active',
+ };
+}
diff --git a/lib/features/finances_and_consultations_archive/cubit/archive/consultations_archive_state.dart b/lib/features/finances_and_consultations_archive/cubit/archive/consultations_archive_state.dart
new file mode 100644
index 00000000..c54f8073
--- /dev/null
+++ b/lib/features/finances_and_consultations_archive/cubit/archive/consultations_archive_state.dart
@@ -0,0 +1,22 @@
+
+import 'package:eatvio_app/features/consultations/models/consultation_model.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/models/statistic_model.dart';
+import 'package:eatvio_app/features/finances_and_consultations_archive/period_enum.dart';
+import 'package:freezed_annotation/freezed_annotation.dart';
+
+part 'consultations_archive_state.freezed.dart';
+
+@freezed
+abstract class ConsultationsArchiveState with _$ConsultationsArchiveState {
+
+ factory ConsultationsArchiveState({
+ @Default([]) List consultations,
+ @Default(false) isLoading,
+ @Default(null) String? error,
+ @Default(null) PeriodFilterStatus? periodFilterStatus,
+ @Default(null) ConsultationFilterStatus? consultationFilterStatus,
+ required StatisticModel statisticModel,
+ }) = _ConsultationsArchiveState;
+
+}
\ No newline at end of file
diff --git a/lib/features/finances_and_consultations_archive/cubit/consultant_finances/consultant_finances_cubit.dart b/lib/features/finances_and_consultations_archive/cubit/consultant_finances/consultant_finances_cubit.dart
new file mode 100644
index 00000000..1324da92
--- /dev/null
+++ b/lib/features/finances_and_consultations_archive/cubit/consultant_finances/consultant_finances_cubit.dart
@@ -0,0 +1,31 @@
+import 'dart:developer';
+
+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/period_enum.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+class ConsultantFinancesCubit extends Cubit {
+ final ConsultationsRepository consultationsRepository;
+ ConsultantFinancesCubit({
+ required this.consultationsRepository,
+ }) : super(
+ ConsultantFinancesState(),
+ );
+
+ Future getConsultations() async {
+ try {
+ emit(state.copyWith(isLoading: true));
+ } catch (e) {
+ emit(state.copyWith(isLoading: false));
+ log(e.toString());
+ }
+ }
+
+ Future setConsultationsPeriod(PeriodFilterStatus period) async {
+ emit(state.copyWith(periodFilterStatus: period));
+ await getConsultations();
+ }
+}
+
+
diff --git a/lib/features/finances_and_consultations_archive/cubit/consultant_finances/consultant_finances_state.dart b/lib/features/finances_and_consultations_archive/cubit/consultant_finances/consultant_finances_state.dart
new file mode 100644
index 00000000..9692d4a6
--- /dev/null
+++ b/lib/features/finances_and_consultations_archive/cubit/consultant_finances/consultant_finances_state.dart
@@ -0,0 +1,15 @@
+import 'package:eatvio_app/features/finances_and_consultations_archive/period_enum.dart';
+import 'package:freezed_annotation/freezed_annotation.dart';
+
+part 'consultant_finances_state.freezed.dart';
+
+@freezed
+abstract class ConsultantFinancesState with _$ConsultantFinancesState {
+ factory ConsultantFinancesState({
+ @Default([]) List financesModels,
+ @Default(false) isLoading,
+ @Default(null) String? error,
+ @Default(null) PeriodFilterStatus? periodFilterStatus,
+ }) = _ConsultantFinancesState;
+
+}
diff --git a/lib/features/finances_and_consultations_archive/models/statistic_model.dart b/lib/features/finances_and_consultations_archive/models/statistic_model.dart
new file mode 100644
index 00000000..34cc748a
--- /dev/null
+++ b/lib/features/finances_and_consultations_archive/models/statistic_model.dart
@@ -0,0 +1,16 @@
+import 'package:freezed_annotation/freezed_annotation.dart';
+
+part 'statistic_model.freezed.dart';
+part 'statistic_model.g.dart';
+
+@freezed
+abstract class StatisticModel with _$StatisticModel {
+ factory StatisticModel({
+ required int total,
+ @JsonKey(name: 'in_progress') required int inProgress,
+ required int finished,
+ required int canceled,
+ }) = _StatisticModel;
+
+ factory StatisticModel.fromJson(Map json) => _$StatisticModelFromJson(json);
+}
\ No newline at end of file
diff --git a/lib/features/finances_and_consultations_archive/period_enum.dart b/lib/features/finances_and_consultations_archive/period_enum.dart
new file mode 100644
index 00000000..a39489d9
--- /dev/null
+++ b/lib/features/finances_and_consultations_archive/period_enum.dart
@@ -0,0 +1,19 @@
+import 'package:eatvio_app/core/utils/date_time_utils.dart';
+
+enum PeriodFilterStatus {
+ all,
+ month,
+ week;
+
+ String get name => switch (this) {
+ PeriodFilterStatus.all => 'Все периоды',
+ PeriodFilterStatus.month => 'За месяц',
+ PeriodFilterStatus.week => 'За неделю',
+ };
+
+ String? get value => switch (this) {
+ PeriodFilterStatus.all => null,
+ PeriodFilterStatus.month => DateTime.now().subtract(const Duration(days: 30)).format('yyyy-MM-dd'),
+ PeriodFilterStatus.week => DateTime.now().subtract(const Duration(days: 7)).format('yyyy-MM-dd'),
+ };
+}
\ No newline at end of file
diff --git a/lib/features/finances_and_consultations_archive/presentation/consultant_finances_screen.dart b/lib/features/finances_and_consultations_archive/presentation/consultant_finances_screen.dart
new file mode 100644
index 00000000..bb225221
--- /dev/null
+++ b/lib/features/finances_and_consultations_archive/presentation/consultant_finances_screen.dart
@@ -0,0 +1,281 @@
+// 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/archive/consultations_archive_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_cubit.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/presentation/widgets/status_widget.dart';
+// import 'package:eatvio_app/generated/l10n.dart';
+// import 'package:flutter/material.dart';
+// import 'package:flutter_bloc/flutter_bloc.dart';
+
+// class ConsultantFinancesScreen extends StatefulWidget {
+// const ConsultantFinancesScreen({super.key});
+
+// @override
+// State createState() => _ConsultantFinancesScreenState();
+// }
+
+// class _ConsultantFinancesScreenState extends State {
+// @override
+// Widget build(BuildContext context) {
+// final s = S.of(context);
+// return BlocProvider(
+// create: (context) => sl(),
+// child: BlocBuilder(
+// builder: (context, state) {
+// return Scaffold(
+// backgroundColor: const Color(0xFFF0F2F5),
+// appBar: AppBar(
+// shape: const RoundedRectangleBorder(
+// borderRadius: BorderRadiusDirectional.vertical(
+// bottom: Radius.circular(12),
+// ),
+// ),
+// title: const Text('Архив консультаций'),
+// centerTitle: true,
+// ),
+// body: state.isLoading
+// ? const Center(
+// child: Loader(),
+// )
+// : SingleChildScrollView(
+// padding: const EdgeInsets.symmetric(vertical: 8),
+// child: Column(
+// children: [
+// Material(
+// color: Colors.white,
+// borderRadius: BorderRadius.circular(12),
+// child: Column(
+// crossAxisAlignment: CrossAxisAlignment.start,
+// children: [
+// const SizedBox(height: 16),
+// Padding(
+// padding: const EdgeInsets.symmetric(horizontal: 16),
+// child: Text(
+// 'Всего консультаций: ${state.statisticModel.total}',
+// style: const TextStyle(
+// fontSize: 16,
+// fontWeight: FontWeight.w500,
+// color: Color(0xFF6D6F71),
+// height: 1,
+// ),
+// ),
+// ),
+// const SizedBox(height: 12),
+// Row(
+// children: [
+// const SizedBox(width: 16),
+// Material(
+// color: const Color(0xFF0BB450).withAlpha(11),
+// borderRadius: BorderRadius.circular(8),
+// child: Padding(
+// padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
+// child: Text(
+// 'Завершено: ${state.statisticModel.finished}',
+// style: const TextStyle(
+// fontSize: 14,
+// fontWeight: FontWeight.w400,
+// color: Color(0xFF0BB450),
+// height: 1,
+// ),
+// ),
+// ),
+// ),
+// const SizedBox(width: 8),
+// Material(
+// color: const Color(0xFFD01717).withAlpha(11),
+// borderRadius: BorderRadius.circular(8),
+// child: Padding(
+// padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
+// child: Text(
+// 'Отменено: ${state.statisticModel.canceled}',
+// style: const TextStyle(
+// fontSize: 14,
+// fontWeight: FontWeight.w400,
+// color: Color(0xFFD01717),
+// height: 1,
+// ),
+// ),
+// ),
+// ),
+// ],
+// ),
+// const SizedBox(height: 16),
+// ],
+// ),
+// ),
+// 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(
+// 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().setConsultationsPeriod(value);
+// },
+// value: state.periodFilterStatus ?? PeriodFilterStatus.values.first,
+// ),
+// const SizedBox(height: 12),
+// CustomDropDownButton(
+// items: ConsultationFilterStatus.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().setConsultationsStatus(value);
+// },
+// value: state.consultationFilterStatus,
+// ),
+// const SizedBox(height: 12),
+// if (state.consultations.isNotEmpty)
+// ListView.separated(
+// shrinkWrap: true,
+// physics: const NeverScrollableScrollPhysics(),
+// itemBuilder: (context, index) {
+// 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: [
+// Text(
+// state.consultations[index].id.toString(),
+// style: const TextStyle(
+// color: Color(0xFF323F4B),
+// height: 1,
+// fontWeight: FontWeight.w500,
+// ),
+// ),
+// Text(
+// state.consultations[index].startDate.format('yyyy.MM.dd'),
+// style: const TextStyle(
+// color: Color(0xFF6D6F71),
+// height: 1,
+// fontWeight: FontWeight.w500,
+// ),
+// ),
+// ],
+// ),
+// const SizedBox(height: 8),
+// Text(
+// state.consultations[index].planTitle,
+// style: TextStyle(
+// color: appTheme.blueA400,
+// height: 1,
+// fontSize: 18,
+// fontWeight: FontWeight.w600,
+// ),
+// ),
+// 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,
+// ),
+// ),
+// ],
+// ),
+// ),
+// ),
+// ),
+// ],
+// ),
+// ),
+// );
+// },
+// ),
+// );
+// }
+// }
diff --git a/lib/features/finances_and_consultations_archive/presentation/consultations_archive_screen.dart b/lib/features/finances_and_consultations_archive/presentation/consultations_archive_screen.dart
new file mode 100644
index 00000000..fa934bcf
--- /dev/null
+++ b/lib/features/finances_and_consultations_archive/presentation/consultations_archive_screen.dart
@@ -0,0 +1,281 @@
+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/archive/consultations_archive_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/period_enum.dart';
+import 'package:eatvio_app/features/finances_and_consultations_archive/presentation/widgets/status_widget.dart';
+import 'package:eatvio_app/generated/l10n.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+class ConsultationsArchiveScreen extends StatefulWidget {
+ const ConsultationsArchiveScreen({super.key});
+
+ @override
+ State createState() => _ConsultationsArchiveScreenState();
+}
+
+class _ConsultationsArchiveScreenState extends State {
+ @override
+ Widget build(BuildContext context) {
+ final s = S.of(context);
+ return BlocProvider(
+ create: (context) => sl()
+ ..getConsultations()
+ ..getStatistic(),
+ child: BlocBuilder(
+ builder: (context, state) {
+ return Scaffold(
+ backgroundColor: const Color(0xFFF0F2F5),
+ appBar: AppBar(
+ shape: const RoundedRectangleBorder(
+ borderRadius: BorderRadiusDirectional.vertical(
+ bottom: Radius.circular(12),
+ ),
+ ),
+ title: const Text('Архив консультаций'),
+ centerTitle: true,
+ ),
+ body: state.isLoading
+ ? const Center(
+ child: Loader(),
+ )
+ : SingleChildScrollView(
+ padding: const EdgeInsets.symmetric(vertical: 8),
+ child: Column(
+ children: [
+ Material(
+ color: Colors.white,
+ borderRadius: BorderRadius.circular(12),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ const SizedBox(height: 16),
+ Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 16),
+ child: Text(
+ 'Всего консультаций: ${state.statisticModel.total}',
+ style: const TextStyle(
+ fontSize: 16,
+ fontWeight: FontWeight.w500,
+ color: Color(0xFF6D6F71),
+ height: 1,
+ ),
+ ),
+ ),
+ const SizedBox(height: 12),
+ Row(
+ children: [
+ const SizedBox(width: 16),
+ Material(
+ color: const Color(0xFF0BB450).withAlpha(11),
+ borderRadius: BorderRadius.circular(8),
+ child: Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
+ child: Text(
+ 'Завершено: ${state.statisticModel.finished}',
+ style: const TextStyle(
+ fontSize: 14,
+ fontWeight: FontWeight.w400,
+ color: Color(0xFF0BB450),
+ height: 1,
+ ),
+ ),
+ ),
+ ),
+ const SizedBox(width: 8),
+ Material(
+ color: const Color(0xFFD01717).withAlpha(11),
+ borderRadius: BorderRadius.circular(8),
+ child: Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
+ child: Text(
+ 'Отменено: ${state.statisticModel.canceled}',
+ style: const TextStyle(
+ fontSize: 14,
+ fontWeight: FontWeight.w400,
+ color: Color(0xFFD01717),
+ height: 1,
+ ),
+ ),
+ ),
+ ),
+ ],
+ ),
+ const SizedBox(height: 16),
+ ],
+ ),
+ ),
+ 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(
+ 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().setConsultationsPeriod(value);
+ },
+ value: state.periodFilterStatus ?? PeriodFilterStatus.values.first,
+ ),
+ const SizedBox(height: 12),
+ CustomDropDownButton(
+ items: ConsultationFilterStatus.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().setConsultationsStatus(value);
+ },
+ value: state.consultationFilterStatus ?? ConsultationFilterStatus.values.first,
+ ),
+ const SizedBox(height: 12),
+ if (state.consultations.isNotEmpty)
+ ListView.separated(
+ shrinkWrap: true,
+ physics: const NeverScrollableScrollPhysics(),
+ itemBuilder: (context, index) {
+ 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: [
+ Text(
+ state.consultations[index].id.toString(),
+ style: const TextStyle(
+ color: Color(0xFF323F4B),
+ height: 1,
+ fontWeight: FontWeight.w500,
+ ),
+ ),
+ Text(
+ state.consultations[index].startDate.format('yyyy.MM.dd'),
+ style: const TextStyle(
+ color: Color(0xFF6D6F71),
+ height: 1,
+ fontWeight: FontWeight.w500,
+ ),
+ ),
+ ],
+ ),
+ const SizedBox(height: 8),
+ Text(
+ state.consultations[index].planTitle,
+ style: TextStyle(
+ color: appTheme.blueA400,
+ height: 1,
+ fontSize: 18,
+ fontWeight: FontWeight.w600,
+ ),
+ ),
+ 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.consultations.length,
+ )
+ else
+ const Padding(
+ padding: EdgeInsets.symmetric(vertical: 40.0),
+ child: Text(
+ 'У вас нет таких консультаций',
+ style: TextStyles.textMMedium,
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ ),
+ ],
+ ),
+ ),
+ );
+ },
+ ),
+ );
+ }
+}
diff --git a/lib/features/finances_and_consultations_archive/presentation/widgets/status_widget.dart b/lib/features/finances_and_consultations_archive/presentation/widgets/status_widget.dart
new file mode 100644
index 00000000..d53c254a
--- /dev/null
+++ b/lib/features/finances_and_consultations_archive/presentation/widgets/status_widget.dart
@@ -0,0 +1,63 @@
+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';
+
+class StatusWidget extends StatelessWidget {
+ const StatusWidget({super.key, required this.status});
+ final ChosenPlanStateEnum status;
+
+ @override
+ Widget build(BuildContext context) {
+ if (status == ChosenPlanStateEnum.stateCanceledByTheInitiator) {
+ return Material(
+ color: appTheme.lightRed,
+ borderRadius: BorderRadius.circular(8),
+ child: Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
+ child: Text(
+ 'Отменён',
+ style: TextStyle(
+ fontSize: 14,
+ fontWeight: FontWeight.w400,
+ color: appTheme.strongRed,
+ height: 1,
+ ),
+ ),
+ ),
+ );
+ } else if (status == ChosenPlanStateEnum.stateChargeWasCollected) {
+ return Material(
+ color: const Color(0xFF0BB450).withAlpha(11),
+ borderRadius: BorderRadius.circular(8),
+ child: const Padding(
+ padding: EdgeInsets.symmetric(horizontal: 16, vertical: 4),
+ child: Text(
+ 'Успешно',
+ style: TextStyle(
+ fontSize: 14,
+ fontWeight: FontWeight.w400,
+ color: Color(0xFF0BB450),
+ height: 1,
+ ),
+ ),
+ ),
+ );
+ }
+ return Material(
+ color: appTheme.transparentBlue,
+ borderRadius: BorderRadius.circular(8),
+ child: Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
+ child: Text(
+ 'В процессе',
+ style: TextStyle(
+ fontSize: 14,
+ fontWeight: FontWeight.w400,
+ color: appTheme.blueA400,
+ height: 1,
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/features/my_finance/presentation/pages/consultant_finance_screen.dart b/lib/features/my_finance/presentation/pages/consultant_finance_screen.dart
deleted file mode 100644
index 3bd9dc47..00000000
--- a/lib/features/my_finance/presentation/pages/consultant_finance_screen.dart
+++ /dev/null
@@ -1,259 +0,0 @@
-import 'package:collection/collection.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/widgets/custom_drop_down_button.dart';
-import 'package:eatvio_app/features/my_finance/entities/consultant_finance_entity.dart';
-import 'package:flutter/material.dart';
-
-class ConsultantFinanceScreen extends StatefulWidget {
- const ConsultantFinanceScreen({super.key});
-
- @override
- State createState() => _ConsultantFinanceScreenState();
-}
-
-class _ConsultantFinanceScreenState extends State {
- final List periods = ['За всё время', 'За месяц', 'За неделю'];
- final List statuses = ['Все консультации', 'Отменён', 'Завершён', 'В процессе'];
-
- @override
- Widget build(BuildContext context) {
- return Scaffold(
- backgroundColor: const Color(0xFFF0F2F5),
- appBar: AppBar(
- shape: const RoundedRectangleBorder(
- borderRadius: BorderRadiusDirectional.vertical(
- bottom: Radius.circular(12),
- ),
- ),
- title: const Text('Архив консультаций'),
- centerTitle: true,
- ),
- body: SingleChildScrollView(
- padding: const EdgeInsets.symmetric(vertical: 8),
- child: Column(
- children: [
- Material(
- color: Colors.white,
- borderRadius: BorderRadius.circular(12),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- const SizedBox(height: 16),
- Padding(
- padding: const EdgeInsets.symmetric(horizontal: 16),
- child: Text(
- 'Всего консультаций: ${testFinanceEntity.totalConsultationsCount}',
- style: const TextStyle(
- fontSize: 16,
- fontWeight: FontWeight.w500,
- color: Color(0xFF6D6F71),
- height: 1,
- ),
- ),
- ),
- const SizedBox(height: 12),
- Row(
- children: [
- const SizedBox(width: 16),
- Material(
- color: const Color(0xFF0BB450).withAlpha(11),
- borderRadius: BorderRadius.circular(8),
- child: Padding(
- padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
- child: Text(
- 'Завершено: ${testFinanceEntity.completedCount}',
- style: const TextStyle(
- fontSize: 14,
- fontWeight: FontWeight.w400,
- color: Color(0xFF0BB450),
- height: 1,
- ),
- ),
- ),
- ),
- const SizedBox(width: 8),
- Material(
- color: const Color(0xFFD01717).withAlpha(11),
- borderRadius: BorderRadius.circular(8),
- child: Padding(
- padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
- child: Text(
- 'Отменено: ${testFinanceEntity.canceledCount}',
- style: const TextStyle(
- fontSize: 14,
- fontWeight: FontWeight.w400,
- color: Color(0xFFD01717),
- height: 1,
- ),
- ),
- ),
- ),
- ],
- ),
- const SizedBox(height: 16),
- ],
- ),
- ),
- 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(
- items: periods
- .mapIndexed(
- (index, value) => DropdownMenuItem(
- value: periods[index],
- child: Text(
- periods[index],
- style: TextStyles.textMMedium.copyWith(color: appTheme.black),
- ),
- ),
- )
- .toList(),
- onChanged: (value) {},
- value: periods.first,
- ),
- const SizedBox(height: 12),
- CustomDropDownButton(
- items: statuses
- .mapIndexed(
- (index, value) => DropdownMenuItem(
- value: statuses[index],
- child: Text(
- statuses[index],
- style: TextStyles.textMMedium.copyWith(color: appTheme.black),
- ),
- ),
- )
- .toList(),
- onChanged: (value) {},
- value: statuses.first,
- ),
- const SizedBox(height: 12),
- ListView.separated(
- shrinkWrap: true,
- physics: const NeverScrollableScrollPhysics(),
- itemBuilder: (context, index) => 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: [
- Text(
- testFinanceEntity.consultationsList[index].id,
- style: const TextStyle(
- color: Color(0xFF323F4B),
- height: 1,
- fontWeight: FontWeight.w500,
- ),
- ),
- Text(
- testFinanceEntity.consultationsList[index].date.format('dd.MM.yyy', 'RU'),
- style: const TextStyle(
- color: Color(0xFF6D6F71),
- height: 1,
- fontWeight: FontWeight.w500,
- ),
- ),
- ],
- ),
- const SizedBox(height: 8),
- Text(
- testFinanceEntity.consultationsList[index].title,
- style: TextStyle(
- color: appTheme.blueA400,
- height: 1,
- fontSize: 18,
- fontWeight: FontWeight.w600,
- ),
- ),
- const SizedBox(height: 8),
- Text(
- 'Покупатель: ${testFinanceEntity.consultationsList[index].clientName}',
- style: const TextStyle(
- color: Color(0xFF323F4B),
- height: 1,
- fontSize: 14,
- fontWeight: FontWeight.w500,
- ),
- ),
- const SizedBox(height: 8),
- Text(
- '${testFinanceEntity.consultationsList[index].planDuration} дней',
- 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(
- '${testFinanceEntity.consultationsList[index].price} ₽',
- style: const TextStyle(
- color: Color(0xFF323F4B),
- height: 1,
- fontSize: 18,
- fontWeight: FontWeight.w600,
- ),
- ),
- Material(
- color: const Color(0xFF0BB450).withAlpha(11),
- borderRadius: BorderRadius.circular(8),
- child: Padding(
- padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
- child: Text(
- testFinanceEntity.consultationsList[index].status.name,
- style: const TextStyle(
- fontSize: 14,
- fontWeight: FontWeight.w400,
- color: Color(0xFF0BB450),
- height: 1,
- ),
- ),
- ),
- ),
- ],
- ),
- ],
- ),
- ),
- ),
- separatorBuilder: (context, index) => const SizedBox(height: 12),
- itemCount: testFinanceEntity.consultationsList.length,
- ),
- ],
- ),
- ),
- ),
- ),
- ],
- ),
- ),
- );
- }
-}
diff --git a/lib/features/plans/enums/chosen_plan_state_enum.dart b/lib/features/plans/enums/chosen_plan_state_enum.dart
index 308df73c..0b768d5f 100644
--- a/lib/features/plans/enums/chosen_plan_state_enum.dart
+++ b/lib/features/plans/enums/chosen_plan_state_enum.dart
@@ -55,4 +55,16 @@ enum ChosenPlanStateEnum {
return true;
}
}
+
+ static List getActiveStates() {
+ return [
+ ChosenPlanStateEnum.statePaid,
+ ChosenPlanStateEnum.stateStarted,
+ ChosenPlanStateEnum.stateInProgress,
+ ChosenPlanStateEnum.stateLastDayStarted,
+ ChosenPlanStateEnum.stateLastDayFinished,
+ ChosenPlanStateEnum.stateComplained,
+ ChosenPlanStateEnum.stateDone
+ ];
+ }
}
diff --git a/lib/features/profile/presentation/pages/profile_screen.dart b/lib/features/profile/presentation/pages/profile_screen.dart
index 64c7dda7..d5d360d8 100644
--- a/lib/features/profile/presentation/pages/profile_screen.dart
+++ b/lib/features/profile/presentation/pages/profile_screen.dart
@@ -562,7 +562,7 @@ class _ProfileScreenState extends State {
color: Colors.white,
borderRadius: BorderRadius.circular(12),
child: Padding(
- padding: const EdgeInsets.only(left: 16, right: 16, top: 20),
+ padding: const EdgeInsets.all(16),
child: Column(
children: [
ListView.separated(
@@ -964,7 +964,7 @@ class _ProfileScreenState extends State {
context.pushTransparentRoute(
rootNavigator: true,
PhotoViewScreen(
- imageUrls: [state.profile.profilePhotoUrl],
+ imageUrls: [baseUrl + state.profile.profilePhotoUrl],
index: 0,
),
);