forked from eatvio/eatvio_app
Compare commits
1 Commits
comments
...
consultant
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
96e80ced38 |
@@ -1,4 +1,5 @@
|
|||||||
String baseUrl = 'https://eatvio.ru';
|
String baseUrl = 'https://eatvio.ru';
|
||||||
|
// String baseUrl = 'https://dev2.eatvio.com';
|
||||||
|
|
||||||
const List<int> durationValues = [7, 14, 21];
|
const List<int> durationValues = [7, 14, 21];
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,9 @@ import 'package:eatvio_app/features/cancel_plan_bottom_sheet/service/cancel_plan
|
|||||||
import 'package:eatvio_app/features/complaining/presentation/cubit/complaining_cubit.dart';
|
import 'package:eatvio_app/features/complaining/presentation/cubit/complaining_cubit.dart';
|
||||||
import 'package:eatvio_app/features/complaining/repositories/complaining_repository.dart';
|
import 'package:eatvio_app/features/complaining/repositories/complaining_repository.dart';
|
||||||
import 'package:eatvio_app/features/complaining/services/complaining_service.dart';
|
import 'package:eatvio_app/features/complaining/services/complaining_service.dart';
|
||||||
|
import 'package:eatvio_app/features/consultant_rating/presentation/cubit/consultant_rating_cubit.dart';
|
||||||
|
import 'package:eatvio_app/features/consultant_rating/repositories/consultant_rating_repository.dart';
|
||||||
|
import 'package:eatvio_app/features/consultant_rating/services/consultant_rating_service.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/repositories/consultations_repository.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/consultations/services/consultation_service.dart';
|
||||||
@@ -158,6 +161,7 @@ Future<void> init() async {
|
|||||||
sl.registerFactory<ConsultationsArchiveCubit>(() => ConsultationsArchiveCubit(consultationsRepository: sl()));
|
sl.registerFactory<ConsultationsArchiveCubit>(() => ConsultationsArchiveCubit(consultationsRepository: sl()));
|
||||||
sl.registerFactory<ConsultantFinancesCubit>(() => ConsultantFinancesCubit(consultationsRepository: sl()));
|
sl.registerFactory<ConsultantFinancesCubit>(() => ConsultantFinancesCubit(consultationsRepository: sl()));
|
||||||
sl.registerFactory<UserPurchasesCubit>(() => UserPurchasesCubit(consultationsRepository: sl()));
|
sl.registerFactory<UserPurchasesCubit>(() => UserPurchasesCubit(consultationsRepository: sl()));
|
||||||
|
sl.registerFactory<ConsultantRatingCubit>(() => ConsultantRatingCubit(sl()));
|
||||||
|
|
||||||
// Repository
|
// Repository
|
||||||
sl.registerLazySingleton<ChatRepository>(() => ChatRepository(chatService: sl()));
|
sl.registerLazySingleton<ChatRepository>(() => ChatRepository(chatService: sl()));
|
||||||
@@ -186,6 +190,7 @@ Future<void> init() async {
|
|||||||
sl.registerLazySingleton<CreatePlanRepository>(() => CreatePlanRepository(createPlanService: sl()));
|
sl.registerLazySingleton<CreatePlanRepository>(() => CreatePlanRepository(createPlanService: sl()));
|
||||||
sl.registerLazySingleton<NotificationsRepository>(() => NotificationsRepository(notificationsService: sl()));
|
sl.registerLazySingleton<NotificationsRepository>(() => NotificationsRepository(notificationsService: sl()));
|
||||||
sl.registerFactory<MyRecipesRepository>(() => MyRecipesRepository(myRecipesService: sl()));
|
sl.registerFactory<MyRecipesRepository>(() => MyRecipesRepository(myRecipesService: sl()));
|
||||||
|
sl.registerFactory<ConsultantRatingRepository>(() => ConsultantRatingRepository(sl()));
|
||||||
|
|
||||||
// Services
|
// Services
|
||||||
sl.registerLazySingleton<ChatService>(() => ChatService(sl()));
|
sl.registerLazySingleton<ChatService>(() => ChatService(sl()));
|
||||||
@@ -214,8 +219,9 @@ Future<void> init() async {
|
|||||||
sl.registerLazySingleton<CancelPlanService>(() => CancelPlanService(sl()));
|
sl.registerLazySingleton<CancelPlanService>(() => CancelPlanService(sl()));
|
||||||
sl.registerLazySingleton<CreatePlanService>(() => CreatePlanService(sl()));
|
sl.registerLazySingleton<CreatePlanService>(() => CreatePlanService(sl()));
|
||||||
sl.registerLazySingleton<NotificationsService>(() => NotificationsService(sl()));
|
sl.registerLazySingleton<NotificationsService>(() => NotificationsService(sl()));
|
||||||
sl.registerLazySingleton<MyRecipesService>(() => MyRecipesService(sl()));
|
|
||||||
sl.registerLazySingleton<FirebaseApi>(() => FirebaseApi());
|
sl.registerLazySingleton<FirebaseApi>(() => FirebaseApi());
|
||||||
|
sl.registerLazySingleton<MyRecipesService>(() => MyRecipesService(sl()));
|
||||||
|
sl.registerLazySingleton<ConsultantRatingService>(() => ConsultantRatingService(sl()));
|
||||||
|
|
||||||
// External
|
// External
|
||||||
sl.registerLazySingleton(
|
sl.registerLazySingleton(
|
||||||
|
|||||||
@@ -1,16 +1,42 @@
|
|||||||
|
import 'package:eatvio_app/features/feed/models/feed_blog_post_model.dart';
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
|
||||||
part 'rating_model.freezed.dart';
|
part 'rating_model.freezed.dart';
|
||||||
part 'rating_model.g.dart';
|
part 'rating_model.g.dart';
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
abstract class RatingModel with _$RatingModel {
|
abstract class RatingPaginationModel with _$RatingPaginationModel {
|
||||||
|
factory RatingPaginationModel({
|
||||||
|
required List<RatingModel> data,
|
||||||
|
}) = _RatingPaginationModel;
|
||||||
|
|
||||||
|
factory RatingPaginationModel.fromJson(Map<String, dynamic> json) => _$RatingPaginationModelFromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
abstract class RatingModel with _$RatingModel {
|
||||||
factory RatingModel({
|
factory RatingModel({
|
||||||
required DateTime date,
|
@JsonKey(name: 'created_at', fromJson: parseDate) required DateTime date,
|
||||||
required String title,
|
@JsonKey(name: 'log_data') required RatingEnum type,
|
||||||
required int amount,
|
@JsonKey(name: 'log_scores') required int amount,
|
||||||
}) = _RatingModel;
|
}) = _RatingModel;
|
||||||
|
|
||||||
factory RatingModel.fromJson(Map<String, dynamic> json) => _$RatingModelFromJson(json);
|
factory RatingModel.fromJson(Map<String, dynamic> json) => _$RatingModelFromJson(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum RatingEnum {
|
||||||
|
@JsonValue('ADDED_RECIPE')
|
||||||
|
addedRecipe,
|
||||||
|
@JsonValue('ADDED_PUBLIC_DIET')
|
||||||
|
addedPublicDiet,
|
||||||
|
@JsonValue('ADDED_BLOG_POST')
|
||||||
|
addedBlogPost,
|
||||||
|
@JsonValue('INVITED_A_NEW_USER')
|
||||||
|
invitedUser,
|
||||||
|
@JsonValue('HAS_MEDICAL_DEGREE')
|
||||||
|
hasMedicalDegree,
|
||||||
|
@JsonValue('CONSULTED')
|
||||||
|
consulted,
|
||||||
|
@JsonValue('PRODUCT_NUTRITINAL_VALUE_APPROVED')
|
||||||
|
addedGlossary;
|
||||||
|
}
|
||||||
|
|||||||
19
lib/features/consultant_rating/models/statistics_model.dart
Normal file
19
lib/features/consultant_rating/models/statistics_model.dart
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
|
||||||
|
part 'statistics_model.freezed.dart';
|
||||||
|
part 'statistics_model.g.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
abstract class StatisticsModel with _$StatisticsModel {
|
||||||
|
|
||||||
|
factory StatisticsModel({
|
||||||
|
@JsonKey(name: 'count_referal') int? countReferal,
|
||||||
|
@JsonKey(name: 'count_blog_posts') int? blogPostsCount,
|
||||||
|
@JsonKey(name: 'count_recipes') int? recipesCount,
|
||||||
|
@JsonKey(name: 'count_diets') int? dietsCount,
|
||||||
|
@JsonKey(name: 'count_consultants') int? consultationsCount,
|
||||||
|
@JsonKey(name: 'count_products_nutritional_values') int? qwe,
|
||||||
|
}) = _StatisticsModel;
|
||||||
|
|
||||||
|
factory StatisticsModel.fromJson(Map<String, dynamic> json) => _$StatisticsModelFromJson(json);
|
||||||
|
}
|
||||||
@@ -1,12 +1,16 @@
|
|||||||
|
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/widgets/custom_outlined_button.dart';
|
import 'package:eatvio_app/core/widgets/custom_outlined_button.dart';
|
||||||
import 'package:eatvio_app/features/consultant_rating/models/rating_model.dart';
|
import 'package:eatvio_app/core/widgets/data_error_widget.dart';
|
||||||
|
import 'package:eatvio_app/features/consultant_rating/presentation/cubit/consultant_rating_cubit.dart';
|
||||||
|
import 'package:eatvio_app/features/consultant_rating/presentation/cubit/consultant_rating_state.dart';
|
||||||
import 'package:eatvio_app/features/consultant_rating/presentation/widgets/rating_history_widget.dart';
|
import 'package:eatvio_app/features/consultant_rating/presentation/widgets/rating_history_widget.dart';
|
||||||
import 'package:eatvio_app/features/consultant_rating/presentation/widgets/rating_widget.dart';
|
import 'package:eatvio_app/features/consultant_rating/presentation/widgets/rating_widget.dart';
|
||||||
import 'package:eatvio_app/features/consultant_rating/presentation/widgets/statistic_widget.dart';
|
import 'package:eatvio_app/features/consultant_rating/presentation/widgets/statistic_widget.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';
|
||||||
|
|
||||||
class ConsultantRatingScreen extends StatelessWidget {
|
class ConsultantRatingScreen extends StatelessWidget {
|
||||||
static const name = 'consultantRatingScreen';
|
static const name = 'consultantRatingScreen';
|
||||||
@@ -15,7 +19,10 @@ class ConsultantRatingScreen extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return const ConsultantRatingPageContent();
|
return BlocProvider<ConsultantRatingCubit>(
|
||||||
|
create: (context) => sl<ConsultantRatingCubit>()..getConsultantStatistics()..getScoreLogs(),
|
||||||
|
child: const ConsultantRatingPageContent(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -25,52 +32,56 @@ class ConsultantRatingPageContent extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final s = S.of(context);
|
final s = S.of(context);
|
||||||
return Scaffold(
|
return BlocBuilder<ConsultantRatingCubit, ConsultantRatingState>(
|
||||||
backgroundColor: appTheme.gray100,
|
builder: (context, state) {
|
||||||
appBar: AppBar(
|
return Scaffold(
|
||||||
centerTitle: true,
|
backgroundColor: appTheme.gray100,
|
||||||
title: Text(
|
appBar: AppBar(
|
||||||
s.rating_and_statistics,
|
centerTitle: true,
|
||||||
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
|
title: Text(
|
||||||
),
|
s.rating_and_statistics,
|
||||||
),
|
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
|
||||||
body: SingleChildScrollView(
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
const RatingWidget(
|
|
||||||
rating: 1058,
|
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
),
|
||||||
Padding(
|
body: state.error != null
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
? DataErrorWidget(onReload: () async {
|
||||||
child: CustomOutlinedButton(
|
await context.read<ConsultantRatingCubit>().getConsultantStatistics();
|
||||||
text: s.copy_referral_link,
|
if (!context.mounted) return;
|
||||||
height: 52,
|
await context.read<ConsultantRatingCubit>().getScoreLogs();
|
||||||
buttonTextStyle: TextStyles.textMSemibold.copyWith(color: appTheme.whiteA700),
|
})
|
||||||
buttonStyle: ButtonStyle(
|
: SingleChildScrollView(
|
||||||
side: const WidgetStatePropertyAll(BorderSide.none),
|
child: Column(
|
||||||
backgroundColor: WidgetStatePropertyAll(appTheme.blueA400),
|
children: [
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
const RatingWidget(
|
||||||
|
rating: 1058,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
|
child: CustomOutlinedButton(
|
||||||
|
text: s.copy_referral_link,
|
||||||
|
height: 52,
|
||||||
|
buttonTextStyle: TextStyles.textMSemibold.copyWith(color: appTheme.whiteA700),
|
||||||
|
buttonStyle: ButtonStyle(
|
||||||
|
side: const WidgetStatePropertyAll(BorderSide.none),
|
||||||
|
backgroundColor: WidgetStatePropertyAll(appTheme.blueA400),
|
||||||
|
),
|
||||||
|
onPressed: () {},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
StatisticWidget(isLoading: state.isStatisticsLoading, statistics: state.statistics,),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
RatingHistoryWidget(
|
||||||
|
isLoading: state.isRatingLoading,
|
||||||
|
ratingHistory: state.ratings,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
onPressed: () {},
|
);
|
||||||
),
|
},
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
const StatisticWidget(),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
RatingHistoryWidget(
|
|
||||||
ratingHistory: [
|
|
||||||
RatingModel(date: DateTime.now(), title: ' djkasjdasjkdkjasjkdjkaskjdjklasjkld', amount: 201300),
|
|
||||||
RatingModel(date: DateTime.now(), title: 'djkasjdasjkdkjasjkdjkaskjdjklasjkld', amount: 89323),
|
|
||||||
RatingModel(date: DateTime.now(), title: 'djkasjdasjkdkjasjkdjkaskjdjklasjkld', amount: 20),
|
|
||||||
RatingModel(date: DateTime.now(), title: 'djkasjdasjkdkjasjkdjkaskjdjklasjkld', amount: 1212),
|
|
||||||
RatingModel(date: DateTime.now(), title: 'qweqweeq', amount: 323),
|
|
||||||
RatingModel(date: DateTime.now(), title: 'ee', amount: 1),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
import 'dart:developer';
|
||||||
|
|
||||||
|
import 'package:eatvio_app/features/consultant_rating/presentation/cubit/consultant_rating_state.dart';
|
||||||
|
import 'package:eatvio_app/features/consultant_rating/repositories/consultant_rating_repository.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
|
class ConsultantRatingCubit extends Cubit<ConsultantRatingState> {
|
||||||
|
final ConsultantRatingRepository repository;
|
||||||
|
ConsultantRatingCubit(this.repository) : super(ConsultantRatingState());
|
||||||
|
|
||||||
|
Future<void> getConsultantStatistics({String? date}) async {
|
||||||
|
try {
|
||||||
|
emit(state.copyWith(isStatisticsLoading: true));
|
||||||
|
final statistics = await repository.getConsultantStatistics(date: date);
|
||||||
|
emit(state.copyWith(isStatisticsLoading: false, statistics: statistics, error: null));
|
||||||
|
} catch (e, st) {
|
||||||
|
emit(state.copyWith(isStatisticsLoading: true, error: e.toString()));
|
||||||
|
log(e.toString(), stackTrace: st);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> getScoreLogs({String? date}) async {
|
||||||
|
try {
|
||||||
|
emit(state.copyWith(isRatingLoading: true));
|
||||||
|
final scoreLogs = await repository.getScoreLogs(date: date);
|
||||||
|
emit(state.copyWith(isRatingLoading: false, ratings: scoreLogs, error: null));
|
||||||
|
} catch (e, st) {
|
||||||
|
emit(state.copyWith(isRatingLoading: true, error: e.toString()));
|
||||||
|
log(e.toString(), stackTrace: st);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import 'package:eatvio_app/features/consultant_rating/models/rating_model.dart';
|
||||||
|
import 'package:eatvio_app/features/consultant_rating/models/statistics_model.dart';
|
||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
|
||||||
|
part 'consultant_rating_state.freezed.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
abstract class ConsultantRatingState with _$ConsultantRatingState {
|
||||||
|
factory ConsultantRatingState({
|
||||||
|
@Default(false) bool isStatisticsLoading,
|
||||||
|
@Default(false) bool isRatingLoading,
|
||||||
|
@Default(null) StatisticsModel? statistics,
|
||||||
|
@Default(null) String? error,
|
||||||
|
@Default(<RatingModel>[]) List<RatingModel> ratings,
|
||||||
|
}) = _ConsultantRatingState;
|
||||||
|
}
|
||||||
@@ -1,42 +1,29 @@
|
|||||||
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/widgets/custom_drop_down_button.dart';
|
import 'package:eatvio_app/core/widgets/custom_drop_down_button.dart';
|
||||||
|
import 'package:eatvio_app/features/consultant_rating/presentation/cubit/consultant_rating_cubit.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:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
class PeriodFilterWidget extends StatefulWidget {
|
class PeriodFilterWidget extends StatefulWidget {
|
||||||
const PeriodFilterWidget({super.key});
|
const PeriodFilterWidget({super.key, required this.isStatistic});
|
||||||
|
final bool isStatistic;
|
||||||
@override
|
@override
|
||||||
State<PeriodFilterWidget> createState() => _PeriodFilterWidgetState();
|
State<PeriodFilterWidget> createState() => _PeriodFilterWidgetState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _PeriodFilterWidgetState extends State<PeriodFilterWidget> {
|
class _PeriodFilterWidgetState extends State<PeriodFilterWidget> {
|
||||||
final List<String> periodDropDownTitles = [];
|
PeriodFilterStatus _currentState = PeriodFilterStatus.all;
|
||||||
int periodDropDownIndex = 0;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void didChangeDependencies() {
|
|
||||||
super.didChangeDependencies();
|
|
||||||
final s = S.of(context);
|
|
||||||
if (periodDropDownTitles.isEmpty) {
|
|
||||||
periodDropDownTitles.addAll([
|
|
||||||
s.for_whole_period_of_time,
|
|
||||||
s.for_a_year,
|
|
||||||
s.for_a_month,
|
|
||||||
s.for_a_week,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final s = S.of(context);
|
final s = S.of(context);
|
||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
CustomDropDownButton(
|
CustomDropDownButton<PeriodFilterStatus>(
|
||||||
hint: Text(
|
hint: Text(
|
||||||
s.choose_diet_duration,
|
s.choose_diet_duration,
|
||||||
style: TextStyles.textSMedium.copyWith(color: appTheme.black),
|
style: TextStyles.textSMedium.copyWith(color: appTheme.black),
|
||||||
@@ -44,24 +31,59 @@ class _PeriodFilterWidgetState extends State<PeriodFilterWidget> {
|
|||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
setState(() {
|
setState(() {
|
||||||
periodDropDownIndex = periodDropDownTitles.indexOf(value);
|
_currentState = value;
|
||||||
});
|
});
|
||||||
|
if (widget.isStatistic) {
|
||||||
|
if (value == PeriodFilterStatus.all) {
|
||||||
|
context.read<ConsultantRatingCubit>().getConsultantStatistics();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
context.read<ConsultantRatingCubit>().getConsultantStatistics(date: value.value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (value == PeriodFilterStatus.all) {
|
||||||
|
context.read<ConsultantRatingCubit>().getScoreLogs();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
context.read<ConsultantRatingCubit>().getScoreLogs(date: value.value);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
items: periodDropDownTitles
|
items: PeriodFilterStatus.values
|
||||||
.mapIndexed(
|
.mapIndexed(
|
||||||
(index, value) => DropdownMenuItem(
|
(index, value) => DropdownMenuItem(
|
||||||
value: periodDropDownTitles[index],
|
value: PeriodFilterStatus.values[index],
|
||||||
child: Text(
|
child: Text(
|
||||||
periodDropDownTitles[index],
|
PeriodFilterStatus.values[index].name,
|
||||||
style: TextStyles.textMMedium.copyWith(color: appTheme.black),
|
style: TextStyles.textMMedium.copyWith(color: appTheme.black),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.toList(),
|
.toList(),
|
||||||
value: periodDropDownTitles[periodDropDownIndex],
|
value: _currentState,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum PeriodFilterStatus {
|
||||||
|
all,
|
||||||
|
month,
|
||||||
|
week,
|
||||||
|
year;
|
||||||
|
|
||||||
|
String get name => switch (this) {
|
||||||
|
PeriodFilterStatus.all => 'Все периоды',
|
||||||
|
PeriodFilterStatus.month => 'За месяц',
|
||||||
|
PeriodFilterStatus.week => 'За неделю',
|
||||||
|
PeriodFilterStatus.year => 'За год',
|
||||||
|
};
|
||||||
|
|
||||||
|
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'),
|
||||||
|
PeriodFilterStatus.year => DateTime.now().subtract(const Duration(days: 365)).format('yyyy-MM-dd'),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ class RatingHistoryItem extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return Container(
|
||||||
height: 80,
|
|
||||||
padding: const EdgeInsets.all(12),
|
padding: const EdgeInsets.all(12),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: appTheme.gray100,
|
color: appTheme.gray100,
|
||||||
@@ -29,7 +28,7 @@ class RatingHistoryItem extends StatelessWidget {
|
|||||||
date.format('dd.MM.yyyy'),
|
date.format('dd.MM.yyyy'),
|
||||||
style: TextStyles.textXSSemibold.copyWith(color: appTheme.gray),
|
style: TextStyles.textXSSemibold.copyWith(color: appTheme.gray),
|
||||||
),
|
),
|
||||||
const Spacer(),
|
const SizedBox(height: 12),
|
||||||
Text(
|
Text(
|
||||||
title,
|
title,
|
||||||
style: TextStyles.textMMedium.copyWith(color: appTheme.black),
|
style: TextStyles.textMMedium.copyWith(color: appTheme.black),
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
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/widgets/loader.dart';
|
||||||
import 'package:eatvio_app/core/widgets/main_background_bouble.dart';
|
import 'package:eatvio_app/core/widgets/main_background_bouble.dart';
|
||||||
import 'package:eatvio_app/features/consultant_rating/models/rating_model.dart';
|
import 'package:eatvio_app/features/consultant_rating/models/rating_model.dart';
|
||||||
import 'package:eatvio_app/features/consultant_rating/presentation/widgets/period_filter_widget.dart';
|
import 'package:eatvio_app/features/consultant_rating/presentation/widgets/period_filter_widget.dart';
|
||||||
@@ -9,7 +10,8 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
|
|
||||||
class RatingHistoryWidget extends StatelessWidget {
|
class RatingHistoryWidget extends StatelessWidget {
|
||||||
const RatingHistoryWidget({super.key, required this.ratingHistory});
|
const RatingHistoryWidget({super.key, required this.ratingHistory, required this.isLoading});
|
||||||
|
final bool isLoading;
|
||||||
final List<RatingModel> ratingHistory;
|
final List<RatingModel> ratingHistory;
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@@ -20,50 +22,60 @@ class RatingHistoryWidget extends StatelessWidget {
|
|||||||
right: 16,
|
right: 16,
|
||||||
top: 16,
|
top: 16,
|
||||||
),
|
),
|
||||||
child: Column(
|
child: isLoading
|
||||||
children: [
|
? const Center(child: Loader())
|
||||||
Row(
|
: Column(
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Row(
|
||||||
s.rating_history,
|
children: [
|
||||||
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
|
Text(
|
||||||
),
|
s.rating_history,
|
||||||
const Spacer(),
|
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
|
||||||
SvgPicture.asset(
|
),
|
||||||
'assets/icons/question_mark.svg',
|
const Spacer(),
|
||||||
height: 22,
|
SvgPicture.asset(
|
||||||
width: 22,
|
'assets/icons/question_mark.svg',
|
||||||
colorFilter: ColorFilter.mode(
|
height: 22,
|
||||||
appTheme.blueA400,
|
width: 22,
|
||||||
BlendMode.srcIn,
|
colorFilter: ColorFilter.mode(
|
||||||
|
appTheme.blueA400,
|
||||||
|
BlendMode.srcIn,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(
|
||||||
],
|
height: 16,
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
height: 16,
|
|
||||||
),
|
|
||||||
const PeriodFilterWidget(),
|
|
||||||
const SizedBox(
|
|
||||||
height: 12,
|
|
||||||
),
|
|
||||||
ListView.builder(
|
|
||||||
physics: const NeverScrollableScrollPhysics(),
|
|
||||||
itemBuilder: (context, index) {
|
|
||||||
return Padding(
|
|
||||||
padding: index == ratingHistory.length - 1 ? EdgeInsets.zero : const EdgeInsets.only(bottom: 12),
|
|
||||||
child: RatingHistoryItem(
|
|
||||||
title: ratingHistory[index].title,
|
|
||||||
amount: ratingHistory[index].amount,
|
|
||||||
date: ratingHistory[index].date,
|
|
||||||
),
|
),
|
||||||
);
|
const PeriodFilterWidget(isStatistic: false),
|
||||||
},
|
const SizedBox(
|
||||||
itemCount: ratingHistory.length,
|
height: 12,
|
||||||
shrinkWrap: true,
|
),
|
||||||
),
|
ListView.builder(
|
||||||
],
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
),
|
itemBuilder: (context, index) {
|
||||||
|
return Padding(
|
||||||
|
padding: index == ratingHistory.length - 1 ? EdgeInsets.zero : const EdgeInsets.only(bottom: 12),
|
||||||
|
child: RatingHistoryItem(
|
||||||
|
title: switch (ratingHistory[index].type) {
|
||||||
|
RatingEnum.addedRecipe => 'Добавление рецепта',
|
||||||
|
RatingEnum.addedPublicDiet => 'Добавление публичной диеты',
|
||||||
|
RatingEnum.addedBlogPost => 'Добавление поста',
|
||||||
|
RatingEnum.invitedUser => 'Регистрация по реф. ссылке',
|
||||||
|
RatingEnum.hasMedicalDegree => 'Получение мед. степени',
|
||||||
|
RatingEnum.consulted => 'Консультация',
|
||||||
|
RatingEnum.addedGlossary => 'Добавление продукта в глоссарий',
|
||||||
|
},
|
||||||
|
amount: ratingHistory[index].amount,
|
||||||
|
date: ratingHistory[index].date,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
itemCount: ratingHistory.length,
|
||||||
|
shrinkWrap: true,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
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/widgets/loader.dart';
|
||||||
import 'package:eatvio_app/core/widgets/main_background_bouble.dart';
|
import 'package:eatvio_app/core/widgets/main_background_bouble.dart';
|
||||||
|
import 'package:eatvio_app/features/consultant_rating/models/statistics_model.dart';
|
||||||
import 'package:eatvio_app/features/consultant_rating/presentation/widgets/period_filter_widget.dart';
|
import 'package:eatvio_app/features/consultant_rating/presentation/widgets/period_filter_widget.dart';
|
||||||
import 'package:eatvio_app/features/consultant_rating/presentation/widgets/statistic_bouble.dart';
|
import 'package:eatvio_app/features/consultant_rating/presentation/widgets/statistic_bouble.dart';
|
||||||
import 'package:eatvio_app/generated/l10n.dart';
|
import 'package:eatvio_app/generated/l10n.dart';
|
||||||
@@ -8,14 +10,15 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
|
|
||||||
class StatisticWidget extends StatelessWidget {
|
class StatisticWidget extends StatelessWidget {
|
||||||
const StatisticWidget({super.key});
|
const StatisticWidget({super.key, required this.isLoading, required this.statistics});
|
||||||
|
final bool isLoading;
|
||||||
|
final StatisticsModel? statistics;
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final s = S.of(context);
|
final s = S.of(context);
|
||||||
return MainBackgroundBouble(
|
return MainBackgroundBouble(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
child: Column(
|
child: isLoading ? const Center(child: Loader()) : Column(
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
@@ -38,15 +41,17 @@ class StatisticWidget extends StatelessWidget {
|
|||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 16,
|
height: 16,
|
||||||
),
|
),
|
||||||
const PeriodFilterWidget(),
|
const PeriodFilterWidget(
|
||||||
|
isStatistic: true,
|
||||||
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 12,
|
height: 12,
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(child: StatisticBouble(number: 12, title: s.invited_people_count)),
|
Expanded(child: StatisticBouble(number: statistics?.countReferal ?? 0, title: s.invited_people_count)),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
Expanded(child: StatisticBouble(number: 12, title: s.published_posts_count)),
|
Expanded(child: StatisticBouble(number: statistics?.blogPostsCount ?? 0, title: s.published_posts_count)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
@@ -54,9 +59,9 @@ class StatisticWidget extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(child: StatisticBouble(number: 12, title: s.published_recipes_count)),
|
Expanded(child: StatisticBouble(number: statistics?.recipesCount ?? 0, title: s.published_recipes_count)),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
Expanded(child: StatisticBouble(number: 12, title: s.published_diets_count)),
|
Expanded(child: StatisticBouble(number: statistics?.dietsCount ?? 0, title: s.published_diets_count)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
@@ -64,9 +69,9 @@ class StatisticWidget extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(child: StatisticBouble(number: 12, title: s.consultations_count)),
|
Expanded(child: StatisticBouble(number: statistics?.consultationsCount ?? 0, title: s.consultations_count)),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
Expanded(child: StatisticBouble(number: 12, title: s.active_consultations_count)),
|
Expanded(child: StatisticBouble(number: statistics?.qwe ?? 0, title: s.active_consultations_count)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
import 'package:eatvio_app/features/consultant_rating/models/rating_model.dart';
|
||||||
|
import 'package:eatvio_app/features/consultant_rating/models/statistics_model.dart';
|
||||||
|
import 'package:eatvio_app/features/consultant_rating/services/consultant_rating_service.dart';
|
||||||
|
|
||||||
|
class ConsultantRatingRepository {
|
||||||
|
final ConsultantRatingService service;
|
||||||
|
|
||||||
|
ConsultantRatingRepository(this.service);
|
||||||
|
|
||||||
|
Future<StatisticsModel> getConsultantStatistics({String? date}) async {
|
||||||
|
try {
|
||||||
|
return await service.getConsultantStatistics(date: date);
|
||||||
|
} catch (e) {
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<RatingModel>> getScoreLogs({String? date}) async {
|
||||||
|
try {
|
||||||
|
final data = (await service.getScoreLogs(date: date)).data;
|
||||||
|
return data;
|
||||||
|
} catch (e) {
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import 'package:dio/dio.dart';
|
||||||
|
import 'package:eatvio_app/features/consultant_rating/models/rating_model.dart';
|
||||||
|
import 'package:eatvio_app/features/consultant_rating/models/statistics_model.dart';
|
||||||
|
|
||||||
|
import 'package:retrofit/retrofit.dart';
|
||||||
|
|
||||||
|
part 'consultant_rating_service.g.dart';
|
||||||
|
|
||||||
|
@RestApi()
|
||||||
|
abstract class ConsultantRatingService {
|
||||||
|
factory ConsultantRatingService(Dio dio, {String baseUrl}) = _ConsultantRatingService;
|
||||||
|
|
||||||
|
@GET('/api/consultants/rating/statistics')
|
||||||
|
Future<StatisticsModel> getConsultantStatistics({@Query('filters[duration][\$gte]') String? date});
|
||||||
|
|
||||||
|
@GET('/api/consultants/score/logs')
|
||||||
|
Future<RatingPaginationModel> getScoreLogs({@Query('filters[duration][\$gte]') String? date});
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ 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/consultant_rating/presentation/consultant_rating_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/consultant_finances_screen.dart';
|
||||||
import 'package:eatvio_app/features/finances_and_consultations_archive/presentation/user_purchases_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';
|
||||||
@@ -49,6 +50,15 @@ class MenuScreen extends StatelessWidget {
|
|||||||
GoRouter.of(context).push(UserPurchasesScreen.path);
|
GoRouter.of(context).push(UserPurchasesScreen.path);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
if (profileModel.roles.contains('consultant')) _divider(context),
|
||||||
|
if (profileModel.roles.contains('consultant'))
|
||||||
|
_tile(
|
||||||
|
leading: 'assets/icons/finance.svg',
|
||||||
|
title: 'Мой рейтинг',
|
||||||
|
onTap: () {
|
||||||
|
GoRouter.of(context).push(ConsultantRatingScreen.path);
|
||||||
|
},
|
||||||
|
),
|
||||||
_divider(context),
|
_divider(context),
|
||||||
_tile(leading: ImageConstant.icnGlossary, title: 'Глоссарий', onTap: () => GoRouter.of(context).push('/glossary-screen')),
|
_tile(leading: ImageConstant.icnGlossary, title: 'Глоссарий', onTap: () => GoRouter.of(context).push('/glossary-screen')),
|
||||||
_divider(context),
|
_divider(context),
|
||||||
|
|||||||
Reference in New Issue
Block a user