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'; import 'package:eatvio_app/core/widgets/show_error_dialog.dart'; import 'package:eatvio_app/features/consultations/models/consultation_model.dart'; import 'package:eatvio_app/features/diary/presentation/pages/diary_screen.dart'; import 'package:eatvio_app/features/user_details/presentation/user_details_screen.dart'; import 'package:eatvio_app/generated/l10n.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; class ConsultationCardWidget extends StatefulWidget { final ConsultationModel consultationsModel; const ConsultationCardWidget({ super.key, required this.consultationsModel, }); @override State createState() => _ConsultationCardWidgetState(); } class _ConsultationCardWidgetState extends State { final List titles = const [ 'Дневник не заполнялся и никаких движений в тот день не было.', 'Начат дневник питания, но не закончен.', 'Дневник заполнен, но не прокомментирован консультантом.', 'Дневник закончен и прокомментирован консультантом но не просмотрен пользователем.', 'Дневник заполнен, прокомментирован консультантом и после этого клиент просмотрел комментарии.', ]; final List legendColors = const [ Colors.white, Color(0xFFF0C497), Color(0xFFFF9500), Color(0xFF2F80ED), Color(0xFF4CD964), ]; late final List<(int, DiaryModel)> givenDaysWithDayNumber; final List> legendStates = [ [DiaryStateEnum.init], [DiaryStateEnum.started, DiaryStateEnum.lastDayStarted], [DiaryStateEnum.finished, DiaryStateEnum.lastDayFinished], [DiaryStateEnum.commented, DiaryStateEnum.lastDayCommented], [DiaryStateEnum.reviewedByUser] ]; @override void initState() { super.initState(); final startPlanDate = widget.consultationsModel.startDate; givenDaysWithDayNumber = List.generate(widget.consultationsModel.diaries.length, (index) { final dayNumber = widget.consultationsModel.diaries[index].date.difference(startPlanDate).inDays; return (dayNumber, widget.consultationsModel.diaries[index]); }); widget.consultationsModel.diaries; } @override Widget build(BuildContext context) { final s = S.of(context); return Material( color: Colors.white, borderRadius: BorderRadius.circular(12), child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ CircleAvatar( radius: 30, backgroundImage: NetworkImage(baseUrl + widget.consultationsModel.userProfilePhotoUrl), ), const SizedBox(width: 12), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( widget.consultationsModel.userName, style: const TextStyle( height: 1, color: Color(0xFF323F4B), fontSize: 16, fontWeight: FontWeight.w600, ), ), const SizedBox(height: 4), Text( widget.consultationsModel.planTitle, style: const TextStyle( height: 1, color: Color(0xFF88949F), fontSize: 14, fontWeight: FontWeight.w500, ), ), ], ), ], ), const SizedBox(height: 12), GestureDetector( onTap: () { GoRouter.of(context).pushNamed(UserDetailsScreen.name, extra: widget.consultationsModel.userSlug); }, child: Text( 'Анкета пользователя', style: TextStyle( color: appTheme.blueA400, decoration: TextDecoration.underline, decorationColor: appTheme.blueA400, fontWeight: FontWeight.w500, height: 1, ), ), ), const SizedBox(height: 12), const CustomDivider(), const SizedBox(height: 12), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( 'День ${widget.consultationsModel.currentDiaryDay} из ${widget.consultationsModel.duration}', style: const TextStyle( height: 1, color: Color(0xFF323F4B), fontSize: 16, fontWeight: FontWeight.w500, ), ), GestureDetector( onTap: () { showModalBottomSheet( context: context, useSafeArea: true, useRootNavigator: true, showDragHandle: true, builder: (context) => Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ const Text( 'Легенда', style: TextStyle( height: 1, fontSize: 20, fontWeight: FontWeight.w700, color: Color(0xFF323F4B), ), ), const SizedBox(height: 16), ListView.separated( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), itemBuilder: (context, index) => _legendTitle(titles[index], legendColors[index]), separatorBuilder: (context, index) => const SizedBox(height: 16), itemCount: titles.length, ), const SizedBox(height: 16), ], ), ), ); }, child: const Icon( Icons.help_outline_rounded, color: Color(0xFF323F4B), size: 20, ), ), ], ), const SizedBox(height: 16), SingleChildScrollView( scrollDirection: Axis.horizontal, child: Row( children: List.generate(widget.consultationsModel.duration, (index) { final day = givenDaysWithDayNumber.firstWhereOrNull((e) => e.$1 == index); 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( padding: const EdgeInsets.only(right: 12), child: Column( mainAxisAlignment: MainAxisAlignment.end, children: [ InkWell( onTap: () { if (!hasActivity || !canConsultantOpenThisDay) { showErrorDialog(context, title: s.you_can_not_open_this_day, description: '${widget.consultationsModel.userName} ${s.has_not_filled_it_yet}'); return; } GoRouter.of(context).push(UserDiaryScreen.path, extra: { 'diaryId': day.$2.id, 'currentDiaryDay': index + 1, }); }, borderRadius: BorderRadius.circular(100), child: Ink( decoration: BoxDecoration( color: hasActivity ? appTheme.dividerColor : appTheme.dividerColor.withValues(alpha: 0.4), borderRadius: BorderRadius.circular(100)), width: 58, height: 32, child: Center( child: Text( (index + 1).toString(), style: TextStyles.textMSemibold.copyWith( color: hasActivity ? appTheme.gray : appTheme.gray.withValues(alpha: 0.4), ), ), ), ), ), if (hasActivity) ...[ const SizedBox( height: 4, ), switch (day.$2.state) { DiaryStateEnum.init => const SizedBox.shrink(), DiaryStateEnum.started => Container( width: 8, height: 8, decoration: BoxDecoration(shape: BoxShape.circle, color: legendColors[1]), ), DiaryStateEnum.lastDayStarted => Container( width: 8, height: 8, decoration: BoxDecoration(shape: BoxShape.circle, color: legendColors[1]), ), DiaryStateEnum.finished => Container( width: 8, height: 8, decoration: BoxDecoration(shape: BoxShape.circle, color: legendColors[2]), ), DiaryStateEnum.lastDayFinished => Container( width: 8, height: 8, decoration: BoxDecoration(shape: BoxShape.circle, color: legendColors[2]), ), DiaryStateEnum.commented => Container( width: 8, height: 8, decoration: BoxDecoration(shape: BoxShape.circle, color: legendColors[3]), ), DiaryStateEnum.lastDayCommented => Container( width: 8, height: 8, decoration: BoxDecoration(shape: BoxShape.circle, color: legendColors[3]), ), DiaryStateEnum.reviewedByUser => Container( width: 8, height: 8, decoration: BoxDecoration(shape: BoxShape.circle, color: legendColors[4]), ), }, const SizedBox( height: 12, ), ] else const SizedBox( height: 24, ), ], ), ); }), ), ), const CustomDivider(), const SizedBox(height: 12), Text( '${widget.consultationsModel.consultationOptionPrice.toStringAsFixed(0)} ₽', style: const TextStyle( color: Color(0xFF019A3E), fontSize: 20, fontWeight: FontWeight.w600, ), ), const SizedBox(height: 16), Row( children: [ InkWell( borderRadius: BorderRadius.circular(20), onTap: () { final lastActiveDay = givenDaysWithDayNumber .where( (e) => e.$2.state == DiaryStateEnum.finished || e.$2.state == DiaryStateEnum.lastDayFinished, ) .lastOrNull; if (lastActiveDay != null) { GoRouter.of(context).push(UserDiaryScreen.path, extra: { 'diaryId': lastActiveDay.$2.id, 'currentDiaryDay': lastActiveDay.$1, }); GoRouter.of(context).push(UserDiaryScreen.path, extra: lastActiveDay.$2.id); return; } showErrorDialog(context, title: s.you_can_not_open_this_day, description: '${widget.consultationsModel.userName} ${s.has_not_filled_it_yet}'); }, child: Ink( width: MediaQuery.of(context).size.width - 32 - 52 - 8, 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(width: 8), InkWell( borderRadius: BorderRadius.circular(20), onTap: () {}, child: Ink( height: 52, width: 52, decoration: BoxDecoration( borderRadius: BorderRadius.circular(20), color: const Color(0xFFF6F6F6), ), child: const Center( child: Icon( Icons.chat_outlined, size: 24, ), ), ), ), ], ), ], ), ), ); } _legendTitle(String text, Color color) { return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( height: 20, width: 20, decoration: BoxDecoration( shape: BoxShape.circle, color: color, ), ), const SizedBox(width: 12), Flexible( child: Text( text, style: const TextStyle( height: 1, fontSize: 16, fontWeight: FontWeight.w500, color: Color(0xFF323F4B), ), ), ), ], ); } }