forked from eatvio/eatvio_app
273 lines
11 KiB
Dart
273 lines
11 KiB
Dart
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);
|
||
}
|
||
}
|