forked from eatvio/eatvio_app
feat: consultations
This commit is contained in:
@@ -4,8 +4,7 @@ import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/new_
|
||||
import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/new_messages_cubit/new_messages_state.dart';
|
||||
import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/notifications_cubit/notifications_cubit.dart';
|
||||
import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/notifications_cubit/notifications_state.dart';
|
||||
import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/profile_avatar_cubit/profile_avatar_cubit.dart';
|
||||
import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/profile_avatar_cubit/profile_avatar_state.dart';
|
||||
import 'package:eatvio_app/features/profile/models/profile_model.dart';
|
||||
import 'package:eatvio_app/generated/l10n.dart';
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -13,14 +12,14 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
int currentBottomNavBarIndex = 0;
|
||||
|
||||
class BottomNavigationBarWidget extends StatefulWidget {
|
||||
final ProfileModel profileModel;
|
||||
final Widget child;
|
||||
|
||||
const BottomNavigationBarWidget({
|
||||
super.key,
|
||||
required this.child,
|
||||
required this.profileModel,
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -28,32 +27,42 @@ class BottomNavigationBarWidget extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _BottomNavigationBarWidgetState extends State<BottomNavigationBarWidget> {
|
||||
int currentBottomNavBarIndex = 0;
|
||||
late final List<String> pages;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
if (widget.profileModel.roles.contains('consultant')) {
|
||||
pages = [
|
||||
'/my-profile-screen',
|
||||
'/feed-screen',
|
||||
'/diary-screen',
|
||||
'/consultations-screen',
|
||||
'/chat-select-screen',
|
||||
'/notifications-screen',
|
||||
'/menu-screen',
|
||||
];
|
||||
} else {
|
||||
pages = [
|
||||
'/my-profile-screen',
|
||||
'/feed-screen',
|
||||
'/diary-screen',
|
||||
'/chat-select-screen',
|
||||
'/notifications-screen',
|
||||
'/menu-screen',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
void _onItemTapped(int index) async {
|
||||
if (currentBottomNavBarIndex != index) {
|
||||
setState(() {
|
||||
currentBottomNavBarIndex = index;
|
||||
});
|
||||
}
|
||||
switch (currentBottomNavBarIndex) {
|
||||
case 0:
|
||||
GoRouter.of(context).replace('/my-profile-screen');
|
||||
break;
|
||||
case 1:
|
||||
GoRouter.of(context).replace('/feed-screen');
|
||||
break;
|
||||
case 2:
|
||||
GoRouter.of(context).replace('/diary-screen');
|
||||
break;
|
||||
case 3:
|
||||
GoRouter.of(context).replace('/chat-select-screen');
|
||||
break;
|
||||
case 4:
|
||||
GoRouter.of(context).replace('/notifications-screen');
|
||||
break;
|
||||
case 5:
|
||||
GoRouter.of(context).replace('/menu-screen');
|
||||
break;
|
||||
}
|
||||
GoRouter.of(context).replace(pages[currentBottomNavBarIndex]);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -71,19 +80,9 @@ class _BottomNavigationBarWidgetState extends State<BottomNavigationBarWidget> {
|
||||
items: [
|
||||
BottomNavigationBarItem(
|
||||
label: '',
|
||||
icon: BlocBuilder<ProfileAvatarCubit, ProfileAvatarState>(
|
||||
builder: (BuildContext context, ProfileAvatarState state) {
|
||||
if (state is ProfileAvatarStateLoaded) {
|
||||
return CircleAvatar(
|
||||
backgroundImage: NetworkImage(state.profile.profilePhotoUrl),
|
||||
radius: 16,
|
||||
);
|
||||
}
|
||||
return CircleAvatar(
|
||||
radius: 16,
|
||||
backgroundColor: Colors.black12,
|
||||
);
|
||||
},
|
||||
icon: CircleAvatar(
|
||||
backgroundImage: NetworkImage(widget.profileModel.profilePhotoUrl),
|
||||
radius: 16,
|
||||
),
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
@@ -134,6 +133,31 @@ class _BottomNavigationBarWidgetState extends State<BottomNavigationBarWidget> {
|
||||
),
|
||||
),
|
||||
),
|
||||
if (widget.profileModel.roles.contains('consultant'))
|
||||
BottomNavigationBarItem(
|
||||
label: 'Консультации',
|
||||
icon: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 2),
|
||||
child: SvgPicture.asset(
|
||||
colorFilter: ColorFilter.mode(Colors.grey, BlendMode.srcIn),
|
||||
'assets/icons/consultations.svg',
|
||||
width: 20,
|
||||
height: 20,
|
||||
),
|
||||
),
|
||||
activeIcon: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 2),
|
||||
child: SvgPicture.asset(
|
||||
'assets/icons/consultations.svg',
|
||||
width: 20,
|
||||
height: 20,
|
||||
colorFilter: ColorFilter.mode(
|
||||
appTheme.blueA400,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
label: s.chat,
|
||||
icon: BlocBuilder<NewMessagesCubit, NewMessagesState>(
|
||||
@@ -154,7 +178,7 @@ class _BottomNavigationBarWidgetState extends State<BottomNavigationBarWidget> {
|
||||
ImageConstant.icnChat,
|
||||
width: 20,
|
||||
height: 20,
|
||||
colorFilter: currentBottomNavBarIndex == 3
|
||||
colorFilter: pages[currentBottomNavBarIndex] == '/chat-select-screen'
|
||||
? ColorFilter.mode(
|
||||
appTheme.blueA400,
|
||||
BlendMode.srcIn,
|
||||
@@ -184,7 +208,7 @@ class _BottomNavigationBarWidgetState extends State<BottomNavigationBarWidget> {
|
||||
padding: const EdgeInsets.only(bottom: 2),
|
||||
child: SvgPicture.asset(
|
||||
ImageConstant.icnBell,
|
||||
colorFilter: currentBottomNavBarIndex == 4
|
||||
colorFilter: pages[currentBottomNavBarIndex] == '/notifications-screen'
|
||||
? ColorFilter.mode(
|
||||
appTheme.blueA400,
|
||||
BlendMode.srcIn,
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
import 'dart:math';
|
||||
|
||||
class ConsultationsEntity {
|
||||
final String name; // Имя и фамилия пользователя который проходит план
|
||||
final String planName; // Название плана который проходит
|
||||
final String clientSlug; // Слаг пользователя который проходит
|
||||
final String photoUrl; // Ссылка на аватрку пользователя
|
||||
final DateTime startPlanDate; // Дата начала прохождения плана
|
||||
final DateTime endPlanDate; // Дата окончания прохождения плана
|
||||
final int paymentAmount; // Сумма выплаты которую получит консультант
|
||||
final int currentDayOfPlan; // Текущий день прохождения плана
|
||||
final int totalDaysOfPlan; // Общее число дней в плане
|
||||
final List<DayOfPlanEntity> days; // Дни плана
|
||||
final bool haveUnreadMessages; // Есть ли непрочитанные сообщения в чате от пользователя
|
||||
|
||||
ConsultationsEntity({
|
||||
required this.name,
|
||||
required this.planName,
|
||||
required this.clientSlug,
|
||||
required this.photoUrl,
|
||||
required this.startPlanDate,
|
||||
required this.endPlanDate,
|
||||
required this.paymentAmount,
|
||||
required this.days,
|
||||
required this.haveUnreadMessages,
|
||||
required this.currentDayOfPlan,
|
||||
required this.totalDaysOfPlan,
|
||||
});
|
||||
}
|
||||
|
||||
enum LegendOfPlanDay {
|
||||
Empty, // Дневник не заполнялся и никаких движений в тот день не было.
|
||||
NotCompleted, // Начат дневник питания, но не закончен.
|
||||
EndBuyUserDontCheck, // Дневник закончен и прокомментирован консультантом но не просмотрен пользователем.
|
||||
CompletedButConsultantCommentEmpty, // Дневник заполнен, но не прокомментирован консультантом.
|
||||
FullCompleted, // Дневник заполнен, прокомментирован консультантом и после этого клиент просмотрел комментарии.
|
||||
}
|
||||
|
||||
class DayOfPlanEntity {
|
||||
final DateTime dateTime;
|
||||
final List<LegendOfPlanDay> daysLegends;
|
||||
|
||||
DayOfPlanEntity({
|
||||
required this.dateTime,
|
||||
required this.daysLegends,
|
||||
});
|
||||
}
|
||||
|
||||
List<ConsultationsEntity> generateTestData() {
|
||||
final random = Random();
|
||||
final List<String> names = ["Иван Петров", "Анна Смирнова", "Дмитрий Соколов", "Елена Козлова", "Алексей Иванов"];
|
||||
final List<String> plans = ["Похудение", "Набор массы", "Детокс", "Здоровое питание", "Вегетарианство"];
|
||||
|
||||
List<ConsultationsEntity> testConsultations = List.generate(20, (index) {
|
||||
DateTime startDate = DateTime.now().subtract(Duration(days: random.nextInt(30)));
|
||||
DateTime endDate = startDate.add(Duration(days: 30));
|
||||
|
||||
List<DayOfPlanEntity> days = List.generate(30, (i) {
|
||||
DateTime dayDate = startDate.add(Duration(days: i));
|
||||
List<LegendOfPlanDay> legends = List.generate(random.nextInt(3) + 1, (j) => LegendOfPlanDay.values[random.nextInt(LegendOfPlanDay.values.length)]);
|
||||
return DayOfPlanEntity(dateTime: dayDate, daysLegends: legends);
|
||||
});
|
||||
|
||||
return ConsultationsEntity(
|
||||
name: names[random.nextInt(names.length)],
|
||||
planName: plans[random.nextInt(plans.length)],
|
||||
clientSlug: "client_${index + 1}",
|
||||
startPlanDate: startDate,
|
||||
endPlanDate: endDate,
|
||||
paymentAmount: (random.nextInt(10) + 1) * 1000,
|
||||
days: days,
|
||||
haveUnreadMessages: random.nextBool(),
|
||||
photoUrl: '',
|
||||
currentDayOfPlan: Random().nextInt(6) + 1,
|
||||
totalDaysOfPlan: Random().nextInt(7) + 14,
|
||||
);
|
||||
});
|
||||
|
||||
return testConsultations;
|
||||
}
|
||||
|
||||
List<ConsultationsEntity> testData = generateTestData();
|
||||
@@ -0,0 +1,28 @@
|
||||
import 'package:eatvio_app/features/consultations/entities/consultations_entity.dart';
|
||||
import 'package:eatvio_app/features/consultations/presentation/widgets/consultation_card_widget.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class ConsultationsScreen extends StatelessWidget {
|
||||
const ConsultationsScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: Color(0xFFF0F2F5),
|
||||
appBar: AppBar(
|
||||
title: Text('Консультации'),
|
||||
centerTitle: true,
|
||||
),
|
||||
body: ListView.separated(
|
||||
padding: EdgeInsets.symmetric(vertical: 12),
|
||||
itemBuilder: (context, index) => ConsultationCardWidget(
|
||||
consultationsEntity: testData[index],
|
||||
),
|
||||
separatorBuilder: (context, index) => const SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
itemCount: testData.length,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,268 @@
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/core/widgets/custom_divider.dart';
|
||||
import 'package:eatvio_app/features/consultations/entities/consultations_entity.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:table_calendar/table_calendar.dart';
|
||||
|
||||
class ConsultationCardWidget extends StatelessWidget {
|
||||
final List<String> titles = const [
|
||||
'Дневник не заполнялся и никаких движений в тот день не было.',
|
||||
'Показывает границы плана питания или публичной диеты в будущем.',
|
||||
'Начат дневник питания, но не закончен.',
|
||||
'Дневник закончен и прокомментирован консультантом но не просмотрен пользователем.',
|
||||
'Дневник заполнен, но не прокомментирован консультантом.',
|
||||
'Дневник заполнен, прокомментирован консультантом и после этого клиент просмотрел комментарии.',
|
||||
];
|
||||
final List<Color> legendColors = const [
|
||||
Colors.white,
|
||||
Color(0xFFCAC9C9),
|
||||
Color(0xFFF0C497),
|
||||
Color(0xFF2F80ED),
|
||||
Color(0xFFFF9500),
|
||||
Color(0xFF4CD964),
|
||||
];
|
||||
final ConsultationsEntity consultationsEntity;
|
||||
|
||||
const ConsultationCardWidget({
|
||||
super.key,
|
||||
required this.consultationsEntity,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext 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,
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
consultationsEntity.name,
|
||||
style: TextStyle(
|
||||
height: 1,
|
||||
color: Color(0xFF323F4B),
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
consultationsEntity.planName,
|
||||
style: TextStyle(
|
||||
height: 1,
|
||||
color: Color(0xFF88949F),
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Text(
|
||||
'Анкета пользователя',
|
||||
style: TextStyle(
|
||||
color: appTheme.blueA400,
|
||||
decoration: TextDecoration.underline,
|
||||
decorationColor: appTheme.blueA400,
|
||||
fontWeight: FontWeight.w500,
|
||||
height: 1,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
CustomDivider(),
|
||||
const SizedBox(height: 12),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'День ${consultationsEntity.currentDayOfPlan} из ${consultationsEntity.totalDaysOfPlan}',
|
||||
style: 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: [
|
||||
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) => SizedBox(height: 16),
|
||||
itemCount: titles.length,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
child: Icon(
|
||||
Icons.help_outline_rounded,
|
||||
color: Color(0xFF323F4B),
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
TableCalendar(
|
||||
focusedDay: DateTime.now(),
|
||||
firstDay: DateTime.utc(2020, 10, 16),
|
||||
lastDay: DateTime.utc(2030, 3, 14),
|
||||
locale: 'ru_RU',
|
||||
startingDayOfWeek: StartingDayOfWeek.monday,
|
||||
headerVisible: false,
|
||||
calendarFormat: CalendarFormat.week,
|
||||
calendarStyle: CalendarStyle(
|
||||
weekendDecoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
defaultDecoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
selectedDecoration: BoxDecoration(
|
||||
color: appTheme.blueA400,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
todayTextStyle: TextStyle(
|
||||
color: Colors.black,
|
||||
),
|
||||
todayDecoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
color: appTheme.blueA400,
|
||||
width: 2,
|
||||
),
|
||||
color: Colors.white,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
CustomDivider(),
|
||||
const SizedBox(height: 12),
|
||||
Text(
|
||||
'${consultationsEntity.paymentAmount} ₽',
|
||||
style: TextStyle(
|
||||
color: Color(0xFF019A3E),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Row(
|
||||
children: [
|
||||
InkWell(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
onTap: () {},
|
||||
child: Ink(
|
||||
width: MediaQuery.of(context).size.width - 32 - 52 - 8,
|
||||
padding: EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
color: appTheme.blueA400,
|
||||
),
|
||||
child: 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: Color(0xFFF6F6F6),
|
||||
),
|
||||
child: 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: TextStyle(
|
||||
height: 1,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Color(0xFF323F4B),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,9 @@ class FeedConsultantModel with _$FeedConsultantModel {
|
||||
const factory FeedConsultantModel({
|
||||
required String slug,
|
||||
required String name,
|
||||
@JsonKey(name: 'rating_place') required int ratingPlace,
|
||||
@JsonKey(name: 'additional_info') required String description,
|
||||
@JsonKey(name: 'rating_place') int? ratingPlace,
|
||||
@JsonKey(name: 'total_scores') required int totalScores,
|
||||
@JsonKey(name: 'profile_photo_url') required String photo,
|
||||
required List<BadgeModel> badges,
|
||||
}) = _FeedConsultantModel;
|
||||
|
||||
@@ -258,8 +258,12 @@ FeedConsultantModel _$FeedConsultantModelFromJson(Map<String, dynamic> json) {
|
||||
mixin _$FeedConsultantModel {
|
||||
String get slug => throw _privateConstructorUsedError;
|
||||
String get name => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: 'additional_info')
|
||||
String get description => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: 'rating_place')
|
||||
int get ratingPlace => throw _privateConstructorUsedError;
|
||||
int? get ratingPlace => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: 'total_scores')
|
||||
int get totalScores => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: 'profile_photo_url')
|
||||
String get photo => throw _privateConstructorUsedError;
|
||||
List<BadgeModel> get badges => throw _privateConstructorUsedError;
|
||||
@@ -283,7 +287,9 @@ abstract class $FeedConsultantModelCopyWith<$Res> {
|
||||
$Res call(
|
||||
{String slug,
|
||||
String name,
|
||||
@JsonKey(name: 'rating_place') int ratingPlace,
|
||||
@JsonKey(name: 'additional_info') String description,
|
||||
@JsonKey(name: 'rating_place') int? ratingPlace,
|
||||
@JsonKey(name: 'total_scores') int totalScores,
|
||||
@JsonKey(name: 'profile_photo_url') String photo,
|
||||
List<BadgeModel> badges});
|
||||
}
|
||||
@@ -305,7 +311,9 @@ class _$FeedConsultantModelCopyWithImpl<$Res, $Val extends FeedConsultantModel>
|
||||
$Res call({
|
||||
Object? slug = null,
|
||||
Object? name = null,
|
||||
Object? ratingPlace = null,
|
||||
Object? description = null,
|
||||
Object? ratingPlace = freezed,
|
||||
Object? totalScores = null,
|
||||
Object? photo = null,
|
||||
Object? badges = null,
|
||||
}) {
|
||||
@@ -318,9 +326,17 @@ class _$FeedConsultantModelCopyWithImpl<$Res, $Val extends FeedConsultantModel>
|
||||
? _value.name
|
||||
: name // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
ratingPlace: null == ratingPlace
|
||||
description: null == description
|
||||
? _value.description
|
||||
: description // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
ratingPlace: freezed == ratingPlace
|
||||
? _value.ratingPlace
|
||||
: ratingPlace // ignore: cast_nullable_to_non_nullable
|
||||
as int?,
|
||||
totalScores: null == totalScores
|
||||
? _value.totalScores
|
||||
: totalScores // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
photo: null == photo
|
||||
? _value.photo
|
||||
@@ -345,7 +361,9 @@ abstract class _$$FeedConsultantModelImplCopyWith<$Res>
|
||||
$Res call(
|
||||
{String slug,
|
||||
String name,
|
||||
@JsonKey(name: 'rating_place') int ratingPlace,
|
||||
@JsonKey(name: 'additional_info') String description,
|
||||
@JsonKey(name: 'rating_place') int? ratingPlace,
|
||||
@JsonKey(name: 'total_scores') int totalScores,
|
||||
@JsonKey(name: 'profile_photo_url') String photo,
|
||||
List<BadgeModel> badges});
|
||||
}
|
||||
@@ -365,7 +383,9 @@ class __$$FeedConsultantModelImplCopyWithImpl<$Res>
|
||||
$Res call({
|
||||
Object? slug = null,
|
||||
Object? name = null,
|
||||
Object? ratingPlace = null,
|
||||
Object? description = null,
|
||||
Object? ratingPlace = freezed,
|
||||
Object? totalScores = null,
|
||||
Object? photo = null,
|
||||
Object? badges = null,
|
||||
}) {
|
||||
@@ -378,9 +398,17 @@ class __$$FeedConsultantModelImplCopyWithImpl<$Res>
|
||||
? _value.name
|
||||
: name // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
ratingPlace: null == ratingPlace
|
||||
description: null == description
|
||||
? _value.description
|
||||
: description // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
ratingPlace: freezed == ratingPlace
|
||||
? _value.ratingPlace
|
||||
: ratingPlace // ignore: cast_nullable_to_non_nullable
|
||||
as int?,
|
||||
totalScores: null == totalScores
|
||||
? _value.totalScores
|
||||
: totalScores // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
photo: null == photo
|
||||
? _value.photo
|
||||
@@ -400,7 +428,9 @@ class _$FeedConsultantModelImpl implements _FeedConsultantModel {
|
||||
const _$FeedConsultantModelImpl(
|
||||
{required this.slug,
|
||||
required this.name,
|
||||
@JsonKey(name: 'rating_place') required this.ratingPlace,
|
||||
@JsonKey(name: 'additional_info') required this.description,
|
||||
@JsonKey(name: 'rating_place') this.ratingPlace,
|
||||
@JsonKey(name: 'total_scores') required this.totalScores,
|
||||
@JsonKey(name: 'profile_photo_url') required this.photo,
|
||||
required final List<BadgeModel> badges})
|
||||
: _badges = badges;
|
||||
@@ -413,8 +443,14 @@ class _$FeedConsultantModelImpl implements _FeedConsultantModel {
|
||||
@override
|
||||
final String name;
|
||||
@override
|
||||
@JsonKey(name: 'additional_info')
|
||||
final String description;
|
||||
@override
|
||||
@JsonKey(name: 'rating_place')
|
||||
final int ratingPlace;
|
||||
final int? ratingPlace;
|
||||
@override
|
||||
@JsonKey(name: 'total_scores')
|
||||
final int totalScores;
|
||||
@override
|
||||
@JsonKey(name: 'profile_photo_url')
|
||||
final String photo;
|
||||
@@ -428,7 +464,7 @@ class _$FeedConsultantModelImpl implements _FeedConsultantModel {
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'FeedConsultantModel(slug: $slug, name: $name, ratingPlace: $ratingPlace, photo: $photo, badges: $badges)';
|
||||
return 'FeedConsultantModel(slug: $slug, name: $name, description: $description, ratingPlace: $ratingPlace, totalScores: $totalScores, photo: $photo, badges: $badges)';
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -438,15 +474,26 @@ class _$FeedConsultantModelImpl implements _FeedConsultantModel {
|
||||
other is _$FeedConsultantModelImpl &&
|
||||
(identical(other.slug, slug) || other.slug == slug) &&
|
||||
(identical(other.name, name) || other.name == name) &&
|
||||
(identical(other.description, description) ||
|
||||
other.description == description) &&
|
||||
(identical(other.ratingPlace, ratingPlace) ||
|
||||
other.ratingPlace == ratingPlace) &&
|
||||
(identical(other.totalScores, totalScores) ||
|
||||
other.totalScores == totalScores) &&
|
||||
(identical(other.photo, photo) || other.photo == photo) &&
|
||||
const DeepCollectionEquality().equals(other._badges, _badges));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType, slug, name, ratingPlace, photo,
|
||||
int get hashCode => Object.hash(
|
||||
runtimeType,
|
||||
slug,
|
||||
name,
|
||||
description,
|
||||
ratingPlace,
|
||||
totalScores,
|
||||
photo,
|
||||
const DeepCollectionEquality().hash(_badges));
|
||||
|
||||
/// Create a copy of FeedConsultantModel
|
||||
@@ -470,7 +517,9 @@ abstract class _FeedConsultantModel implements FeedConsultantModel {
|
||||
const factory _FeedConsultantModel(
|
||||
{required final String slug,
|
||||
required final String name,
|
||||
@JsonKey(name: 'rating_place') required final int ratingPlace,
|
||||
@JsonKey(name: 'additional_info') required final String description,
|
||||
@JsonKey(name: 'rating_place') final int? ratingPlace,
|
||||
@JsonKey(name: 'total_scores') required final int totalScores,
|
||||
@JsonKey(name: 'profile_photo_url') required final String photo,
|
||||
required final List<BadgeModel> badges}) = _$FeedConsultantModelImpl;
|
||||
|
||||
@@ -482,8 +531,14 @@ abstract class _FeedConsultantModel implements FeedConsultantModel {
|
||||
@override
|
||||
String get name;
|
||||
@override
|
||||
@JsonKey(name: 'additional_info')
|
||||
String get description;
|
||||
@override
|
||||
@JsonKey(name: 'rating_place')
|
||||
int get ratingPlace;
|
||||
int? get ratingPlace;
|
||||
@override
|
||||
@JsonKey(name: 'total_scores')
|
||||
int get totalScores;
|
||||
@override
|
||||
@JsonKey(name: 'profile_photo_url')
|
||||
String get photo;
|
||||
|
||||
@@ -30,7 +30,9 @@ _$FeedConsultantModelImpl _$$FeedConsultantModelImplFromJson(
|
||||
_$FeedConsultantModelImpl(
|
||||
slug: json['slug'] as String,
|
||||
name: json['name'] as String,
|
||||
ratingPlace: (json['rating_place'] as num).toInt(),
|
||||
description: json['additional_info'] as String,
|
||||
ratingPlace: (json['rating_place'] as num?)?.toInt(),
|
||||
totalScores: (json['total_scores'] as num).toInt(),
|
||||
photo: json['profile_photo_url'] as String,
|
||||
badges: (json['badges'] as List<dynamic>)
|
||||
.map((e) => BadgeModel.fromJson(e as Map<String, dynamic>))
|
||||
@@ -42,7 +44,9 @@ Map<String, dynamic> _$$FeedConsultantModelImplToJson(
|
||||
<String, dynamic>{
|
||||
'slug': instance.slug,
|
||||
'name': instance.name,
|
||||
'additional_info': instance.description,
|
||||
'rating_place': instance.ratingPlace,
|
||||
'total_scores': instance.totalScores,
|
||||
'profile_photo_url': instance.photo,
|
||||
'badges': instance.badges,
|
||||
};
|
||||
|
||||
@@ -81,7 +81,14 @@ class ImtChartWidget extends StatelessWidget {
|
||||
series: _getSplineSeries(),
|
||||
tooltipBehavior: TooltipBehavior(enable: true),
|
||||
),
|
||||
if (weightPoints.isEmpty) Text('Индекс Массы Тела рассчитывается при указанных весе и росте'),
|
||||
if (weightPoints.isEmpty)
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 32),
|
||||
child: Text(
|
||||
'Индекс Массы Тела рассчитывается при указанных весе и росте',
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user