Files
eatvio_app/lib/features/diary/presentation/pages/diary_screen.dart
2024-10-24 16:59:51 +03:00

307 lines
8.9 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'package:eatvio_app/features/diary/models/diary_day_model.dart';
import 'package:eatvio_app/features/diary/presentation/bloc/diary_cubit.dart';
import 'package:eatvio_app/features/diary/presentation/bloc/diary_state.dart';
import 'package:eatvio_app/locator_service.dart';
import 'package:eatvio_app/theme/theme_helper.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:rive/rive.dart';
import 'package:table_calendar/table_calendar.dart';
class DiaryScreen extends StatefulWidget {
const DiaryScreen({super.key});
@override
State<DiaryScreen> createState() => _DiaryScreenState();
}
class _DiaryScreenState extends State<DiaryScreen> {
final DiaryCubit diaryCubit = sl<DiaryCubit>();
CalendarFormat _calendarFormat = CalendarFormat.month;
DateTime _focusedDay = DateTime.now();
DateTime? _selectedDay = DateTime.now();
int currentSelectedMealNumber = 1;
@override
Widget build(BuildContext context) {
return BlocProvider<DiaryCubit>(
create: (BuildContext context) => diaryCubit..getDiaryDay(_selectedDay!.toString()),
child: BlocConsumer<DiaryCubit, DiaryState>(
listener: (BuildContext context, DiaryState state) {
if (state is DiaryStateLoaded) {
setState(() {
_calendarFormat = CalendarFormat.week;
});
}
},
builder: (BuildContext context, DiaryState state) {
return Scaffold(
backgroundColor: Colors.grey.shade200,
appBar: AppBar(
toolbarHeight: 0,
),
body: SingleChildScrollView(
physics: const BouncingScrollPhysics(),
child: Column(
children: [
_calendar(state),
if (state is DiaryStateLoading) _loader(),
if (state is DiaryStateLoaded) _meals(state.diary),
],
),
),
);
},
),
);
}
_arrowDown() {
return GestureDetector(
onTapDown: (_) {
setState(() {
if (_calendarFormat == CalendarFormat.week) {
_calendarFormat = CalendarFormat.month;
} else {
_calendarFormat = CalendarFormat.week;
}
});
},
child: Container(
padding: const EdgeInsets.only(top: 8, bottom: 16),
width: double.infinity,
child: Icon(
_calendarFormat == CalendarFormat.month ? Icons.keyboard_arrow_up_rounded : Icons.keyboard_arrow_down_rounded,
color: Colors.grey.shade600,
),
),
);
}
_divider(BuildContext context) {
return Container(
height: 0.4,
width: MediaQuery.of(context).size.width - 32,
decoration: BoxDecoration(
color: Colors.black26,
borderRadius: BorderRadius.circular(16),
),
);
}
_products(List<Portion> portions) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
for (int i = 0; i < portions.length; i++) ...[
_product(
portions[i].productName,
portions[i].quantity,
),
i < portions.length - 1 ? const SizedBox(height: 8) : const SizedBox.shrink(),
],
],
);
}
_product(String product, int portion) {
return ListTile(
onTap: () {},
trailing: Icon(Icons.more_vert_rounded),
title: Text(product),
subtitle: Text('$portion г'),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
tileColor: Color(0xFFF6FAFF),
);
}
_meals(DiaryDayModel diaryDay) {
return Material(
borderRadius: BorderRadius.circular(20),
color: Colors.white,
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Прием пищи',
style: TextStyle(
color: Color(0xFF323F4B),
fontSize: 18,
fontWeight: FontWeight.w500,
),
),
const SizedBox(height: 16),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_mealButton(1),
_mealButton(2),
_mealButton(3),
_mealButton(4),
_mealButton(5),
],
),
const SizedBox(height: 12),
_divider(context),
const SizedBox(height: 12),
Text(
'Время приема пищи',
style: TextStyle(
color: Color(0xFF323F4B),
fontSize: 16,
fontWeight: FontWeight.w500,
),
),
const SizedBox(height: 12),
_divider(context),
const SizedBox(height: 12),
_products(diaryDay.meals[currentSelectedMealNumber - 1].portions),
const SizedBox(height: 16),
_addProductButton(),
],
),
),
);
}
_mealButton(int mealNumber) {
bool isActive = currentSelectedMealNumber == mealNumber;
return InkWell(
onTap: () {
setState(() {
if (currentSelectedMealNumber == mealNumber) return;
currentSelectedMealNumber = mealNumber;
});
},
borderRadius: BorderRadius.circular(100),
child: Ink(
width: MediaQuery.of(context).size.width / 5 - (96 / 5),
height: 32,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(100),
color: isActive ? appTheme.blueA400 : Color(0xFFF1F2F6),
),
child: Center(
child: Text(
'$mealNumber',
style: TextStyle(
color: isActive ? Colors.white : Colors.black,
fontSize: 16,
fontWeight: FontWeight.w600,
),
),
),
),
);
}
_loader() {
return Center(
child: SizedBox(
height: 32,
width: 32,
child: RiveAnimation.asset(
'assets/rive_animations/loading.riv',
),
),
);
}
_calendar(DiaryState state) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding: const EdgeInsets.only(top: 16),
child: TableCalendar(
firstDay: DateTime.utc(2010, 10, 16),
lastDay: DateTime.utc(2030, 3, 14),
locale: 'ru_RU',
startingDayOfWeek: StartingDayOfWeek.monday,
focusedDay: _focusedDay,
calendarFormat: _calendarFormat,
headerStyle: HeaderStyle(
titleCentered: true,
formatButtonVisible: false,
leftChevronVisible: false,
rightChevronVisible: false,
),
selectedDayPredicate: (day) {
return isSameDay(_selectedDay, day);
},
onDaySelected: (selectedDay, focusedDay) {
if (state is! DiaryStateLoaded) return;
if (!isSameDay(_selectedDay, selectedDay)) {
setState(() {
_selectedDay = selectedDay;
_focusedDay = focusedDay;
});
diaryCubit.getDiaryDay(_selectedDay!.toString());
}
},
onFormatChanged: (format) {
if (_calendarFormat != format) {
setState(() {
_calendarFormat = format;
});
}
},
onPageChanged: (focusedDay) {
_focusedDay = focusedDay;
},
calendarStyle: CalendarStyle(
selectedDecoration: BoxDecoration(
color: appTheme.blueA400,
shape: BoxShape.circle,
),
todayTextStyle: TextStyle(
color: Colors.black,
),
todayDecoration: BoxDecoration(
border: Border.all(
color: appTheme.blueA400,
width: 2,
),
shape: BoxShape.circle,
),
),
),
),
_arrowDown(),
],
);
}
_addProductButton() {
return InkWell(
onTap: () {},
borderRadius: BorderRadius.circular(20),
child: Ink(
padding: EdgeInsets.symmetric(horizontal: 16),
width: MediaQuery.of(context).size.width - 32,
decoration: BoxDecoration(
color: appTheme.blueA400,
borderRadius: BorderRadius.circular(20),
),
child: Container(
padding: EdgeInsets.all(16),
alignment: Alignment.center,
child: Text(
'Добавить',
style: TextStyle(
color: Colors.white,
fontSize: 18,
fontWeight: FontWeight.w600,
),
),
),
),
);
}
}