Files
eatvio_app/lib/features/calendar/presentation/pages/calendar_screen.dart
2025-07-02 19:01:37 +07:00

273 lines
11 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/core/theme/app_decoration.dart';
import 'package:eatvio_app/core/widgets/loader.dart';
import 'package:eatvio_app/features/calendar/presentation/bloc/calendar_cubit.dart';
import 'package:eatvio_app/features/calendar/presentation/bloc/calendar_state.dart';
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:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:go_router/go_router.dart';
import 'package:intl/intl.dart';
class CalendarScreen extends StatelessWidget {
const CalendarScreen({super.key});
@override
Widget build(BuildContext context) {
return BlocProvider<CalendarCubit>(
create: (context) => sl<CalendarCubit>()..loadCalendarList(),
child: BlocBuilder<CalendarCubit, CalendarState>(
builder: (context, state) {
if (state is CalendarStateLoaded) {
return _buildCalendar(context, state);
} else if (state is CalendarStateLoading) {
return const Scaffold(
body: Loader(),
);
} else if (state is CalendarStateError) {
return Scaffold(
body: Padding(
padding: const EdgeInsets.all(16),
child: Center(
child: Text(state.errorMessage),
),
),
);
}
return const Scaffold(
body: Padding(
padding: EdgeInsets.all(16),
child: Center(
child: Text("Неопределенная ошибка"),
),
),
);
},
),
);
}
Widget _buildCalendar(BuildContext context, CalendarStateLoaded state) {
return Stack(
alignment: Alignment.bottomCenter,
children: [
FormBuilder(
child: Scaffold(
appBar: AppBar(
title: const Text(
'Календарь',
),
),
backgroundColor: Colors.white,
resizeToAvoidBottomInset: true,
body: SizedBox(
width: double.maxFinite,
child: Column(
children: [
Expanded(
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.only(bottom: 8),
child: Column(
children: [
const SizedBox(height: 24),
_buildCalendarBody(context, state),
const SizedBox(height: 24),
],
),
),
),
),
],
),
),
),
),
],
);
}
ListView _buildCalendarBody(BuildContext context, CalendarStateLoaded state) {
return ListView.separated(
padding: const EdgeInsets.all(8),
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
separatorBuilder: (context, index) {
return const SizedBox(
height: 4,
);
},
itemCount: state.calendarList.length,
itemBuilder: (context, index) {
Map<String, dynamic> diary = {};
if (state.calendarList[index].diary is List<dynamic>) {
diary['status'] = 'Скоро';
return InkWell(
borderRadius: BorderRadiusStyle.circleBorder8,
child: Ink(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
borderRadius: BorderRadiusStyle.circleBorder8,
color: state.calendarList[index].isCurrentDayIncludedInTheChosenDietProgression
? const Color.fromRGBO(59, 130, 246, .2)
: const Color.fromRGBO(126, 136, 151, .1),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
formatDate(state.calendarList[index].date),
style: theme.textTheme.titleMedium,
),
const SizedBox(height: 4),
if (state.calendarList[index].isCurrentDayIncludedInTheChosenDietProgression)
Container(
padding: const EdgeInsets.all(4.0), // Отступы внутри контейнера
decoration: BoxDecoration(
color: const Color.fromRGBO(13, 110, 253, 1),
borderRadius: BorderRadius.circular(24.0), // Закругленные углы
),
child: Text(
'Посмотреть диету на день',
style: CustomTextStyles.titleSmallBold, // Предполагается, что текст белый
),
),
if (!state.calendarList[index].isCurrentDayIncludedInTheChosenDietProgression)
Container(
padding: const EdgeInsets.all(4.0), // Отступы внутри контейнера
decoration: BoxDecoration(
color: const Color.fromRGBO(108, 117, 125, 1),
borderRadius: BorderRadius.circular(24.0), // Закругленные углы
),
child: Text(
'Cкоро',
style: CustomTextStyles.titleSmallBold, // Предполагается, что текст белый
),
),
],
),
),
],
),
),
);
} else {
diary = state.calendarList[index].diary as Map<String, dynamic>;
return InkWell(
borderRadius: BorderRadiusStyle.circleBorder8,
onTap: () => GoRouter.of(context).go(
'/diary-screen',
extra: diary['id'].toString(),
),
child: Ink(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
borderRadius: BorderRadiusStyle.circleBorder8,
color: getBackgroundColor(diary['state']),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
formatDate(state.calendarList[index].date),
style: theme.textTheme.titleMedium,
),
const SizedBox(height: 4),
Row(
children: [
Container(
padding: const EdgeInsets.all(4.0), // Отступы внутри контейнера
decoration: BoxDecoration(
color: diary['state'] == 'finished' ? const Color.fromRGBO(1, 154, 62, 1) : const Color.fromRGBO(154, 74, 1, 1),
borderRadius: BorderRadius.circular(24.0), // Закругленные углы
),
child: Text(
_getStateText(diary['state'] ?? ''),
style: CustomTextStyles.titleSmallBold, // Предполагается, что текст белый
),
),
const SizedBox(width: 4),
if (diary['state'] == 'started')
Container(
padding: const EdgeInsets.all(4.0), // Отступы внутри контейнера
decoration: BoxDecoration(
color: const Color.fromRGBO(13, 110, 253, 1),
borderRadius: BorderRadius.circular(24.0), // Закругленные углы
),
child: Text(
'Заполнить отчет',
style: CustomTextStyles.titleSmallBold, // Предполагается, что текст белый
),
),
if (diary['state'] == 'finished')
Container(
padding: const EdgeInsets.all(4.0), // Отступы внутри контейнера
decoration: BoxDecoration(
color: const Color.fromRGBO(13, 110, 253, 1),
borderRadius: BorderRadius.circular(24.0), // Закругленные углы
),
child: Text(
'Изменить отчет',
style: CustomTextStyles.titleSmallBold, // Предполагается, что текст белый
),
),
],
),
],
),
),
],
),
),
);
}
},
);
}
}
String _getStateText(String state) {
switch (state) {
case 'finished':
return 'Готово';
case 'started':
return 'В процессе';
default:
return ''; // Возвращаем пустую строку, если состояние не распознано
}
}
String formatDate(String dateString) {
// Преобразуем строку в объект DateTime
DateTime dateTime = DateTime.parse(dateString);
// Форматируем дату
String formattedDate = DateFormat('d MMMM', 'ru_RU').format(dateTime);
// Возвращаем результат в нужном формате
return formattedDate;
}
Color getBackgroundColor(String? status) {
switch (status) {
case 'finished':
return const Color.fromRGBO(1, 154, 62, .1);
case 'started':
return const Color.fromRGBO(154, 74, 1, .1);
default:
return const Color.fromRGBO(126, 136, 151, .1);
}
}