Files
eatvio_app/lib/features/menu/presentation/pages/notifications_settings_screen.dart
2025-09-10 15:58:26 +03:00

286 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/locator_service.dart';
import 'package:eatvio_app/core/theme/theme_helper.dart';
import 'package:eatvio_app/features/menu/models/notification_settings_model.dart';
import 'package:eatvio_app/features/menu/presentation/bloc/notification_settings_cubit/notification_settings_cubit.dart';
import 'package:eatvio_app/features/menu/presentation/bloc/notification_settings_cubit/notification_settings_state.dart';
import 'package:eatvio_app/generated/l10n.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/flutter_svg.dart';
class NotificationsSettingsScreen extends StatelessWidget {
const NotificationsSettingsScreen({super.key});
@override
Widget build(BuildContext context) {
return BlocProvider(create: (context) => sl<NotificationSettingsCubit>()..getNotificationSettings(), child: const NotificationsSettingsContent());
}
}
class NotificationsSettingsContent extends StatelessWidget {
const NotificationsSettingsContent({super.key});
@override
Widget build(BuildContext context) {
final s = S.of(context);
return Scaffold(
appBar: AppBar(title: Text(s.notifications)),
body: BlocBuilder<NotificationSettingsCubit, NotificationSettingsState>(
builder: (context, state) {
if (state is NotificationSettingsStateLoading) {
return const Center(child: CircularProgressIndicator());
} else if (state is NotificationSettingsStateError) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Ошибка: ${state.errorMessage}'),
ElevatedButton(
onPressed: () {
context.read<NotificationSettingsCubit>().getNotificationSettings();
},
child: const Text('Повторить'),
),
],
),
);
} else if (state is NotificationSettingsStateLoaded) {
return _buildSettingsContent(context, state.notificationSettings);
}
return const Center(child: Text('Нет данных'));
},
),
);
}
Widget _buildSettingsContent(BuildContext context, NotificationSettingsModel notificationSettings) {
final cubit = context.read<NotificationSettingsCubit>();
return Column(
children: [
_tile(
padding: const EdgeInsets.symmetric(horizontal: 16),
onTap: () {},
title: 'Новые обновления',
subtitle: null,
trailing: CupertinoSwitch(
value: notificationSettings.newUpdatesNotification,
activeTrackColor: appTheme.blueA400,
onChanged: (newValue) {
_updateNotificationSetting(cubit, {'new_updates_notification': newValue});
},
),
),
_divider(context),
_tile(
padding: const EdgeInsets.symmetric(horizontal: 16),
onTap: () {},
title: 'Напоминать о взвешивании',
subtitle: null,
trailing: CupertinoSwitch(
value: notificationSettings.weightMeasurementsNotification,
activeTrackColor: appTheme.blueA400,
onChanged: (newValue) {
_updateNotificationSetting(cubit, {'weight_measurements_notification': newValue});
},
),
),
_divider(context),
_tile(
padding: const EdgeInsets.symmetric(horizontal: 16),
onTap: () {},
title: 'Email уведомления',
subtitle: null,
trailing: CupertinoSwitch(
value: notificationSettings.isEmailNotificationsEnabled,
activeTrackColor: appTheme.blueA400,
onChanged: (newValue) {
_updateNotificationSetting(cubit, {'is_email_notifications_enabled': newValue});
},
),
),
_divider(context),
_tile(
padding: const EdgeInsets.symmetric(horizontal: 16),
onTap: () {},
title: 'Push уведомления',
subtitle: null,
trailing: CupertinoSwitch(
value: notificationSettings.isPushNotificationsEnabled,
activeTrackColor: appTheme.blueA400,
onChanged: (newValue) {
_updateNotificationSetting(cubit, {'is_push_notifications_enabled': newValue});
},
),
),
_divider(context),
_buildDiaryRemindersSection(context, notificationSettings.diaryReminderNotifications, cubit),
],
);
}
Widget _buildDiaryRemindersSection(BuildContext context, DiaryReminderNotifications diaryReminderNotifications, NotificationSettingsCubit cubit) {
return Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Напоминание о заполнении дневника',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500, color: appTheme.cardNotificationsBG),
),
const SizedBox(height: 8),
_buildReminderTile(context, '№1 Напоминание о приеме пищи', diaryReminderNotifications.firstReminder, 'first_reminder', cubit),
const SizedBox(height: 8),
_buildReminderTile(context, '№2 Напоминание о приеме пищи', diaryReminderNotifications.secondReminder, 'second_reminder', cubit),
const SizedBox(height: 8),
_buildReminderTile(context, '№3 Напоминание о приеме пищи', diaryReminderNotifications.thirdReminder, 'third_reminder', cubit),
],
),
);
}
void _updateNotificationSetting(NotificationSettingsCubit cubit, Map<String, dynamic> data) {
cubit.updateNotificationSettings(data);
}
void _updateReminderSetting(NotificationSettingsCubit cubit, String reminderType, Map<String, dynamic> data) {
final updateData = {
'diary_reminder_notifications': {reminderType: data},
};
cubit.updateNotificationSettings(updateData);
}
Widget _buildReminderTile(BuildContext context, String title, ReminderSettings reminder, String reminderType, NotificationSettingsCubit cubit) {
return Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(borderRadius: BorderRadius.circular(12), color: appTheme.dividerColor),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
reminderType == 'third_reminder' ? SvgPicture.asset('assets/icons/retire.svg') : SvgPicture.asset('assets/icons/wakeup.svg'),
const SizedBox(width: 8),
Text(
title,
style: const TextStyle(color: Color(0xFF323F4B), fontSize: 16, fontWeight: FontWeight.w500),
),
],
),
const SizedBox(height: 8),
Row(
mainAxisSize: MainAxisSize.max,
children: [
Expanded(
child: GestureDetector(
onTap: reminder.enabled
? () {
_showTimePicker(context, reminder, reminderType, cubit);
}
: null,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
decoration: BoxDecoration(color: reminder.enabled ? Colors.white : Colors.white.withAlpha((255 * 0.7).toInt()), borderRadius: BorderRadius.circular(48)),
child: Center(
child: Text(
'${reminder.localTimeHours.toString().padLeft(2, '0')}:${reminder.localTimeMins.toString().padLeft(2, '0')}',
style: TextStyle(fontSize: 17, color: appTheme.gray, fontWeight: FontWeight.w500),
),
),
),
),
),
const SizedBox(width: 8),
CupertinoSwitch(
value: reminder.enabled,
activeTrackColor: appTheme.blueA400,
onChanged: (newValue) {
_updateReminderSetting(cubit, reminderType, {
'enabled': newValue,
'local_time_hours': reminder.localTimeHours,
'local_time_mins': reminder.localTimeMins,
});
},
),
],
),
],
),
);
}
void _showTimePicker(BuildContext context, ReminderSettings reminder, String reminderType, NotificationSettingsCubit cubit) {
int selectedHour = reminder.localTimeHours;
int selectedMinute = reminder.localTimeMins;
showCupertinoModalPopup<void>(
context: context,
builder: (BuildContext context) {
return Container(
height: 300,
padding: const EdgeInsets.only(top: 6.0),
margin: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
color: CupertinoColors.systemBackground.resolveFrom(context),
child: SafeArea(
top: false,
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
CupertinoButton(child: const Text('Отмена'), onPressed: () => Navigator.of(context).pop()),
CupertinoButton(
child: const Text('Готово'),
onPressed: () {
_updateReminderSetting(cubit, reminderType, {
'enabled': reminder.enabled,
'local_time_hours': selectedHour,
'local_time_mins': selectedMinute,
});
Navigator.of(context).pop();
},
),
],
),
Expanded(
child: CupertinoDatePicker(
mode: CupertinoDatePickerMode.time,
use24hFormat: true,
initialDateTime: DateTime(2024, 1, 1, selectedHour, selectedMinute),
onDateTimeChanged: (DateTime newDateTime) {
selectedHour = newDateTime.hour;
selectedMinute = newDateTime.minute;
},
),
),
],
),
),
);
},
);
}
ListTile _tile({required String title, required Function()? onTap, Widget? trailing, EdgeInsets? padding, Widget? subtitle}) {
return ListTile(
contentPadding: padding,
onTap: onTap,
title: Text(title, style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w500, height: 1)),
subtitle: subtitle,
trailing: trailing ?? const Icon(Icons.arrow_forward_ios_rounded, size: 12, color: Colors.black38),
);
}
Center _divider(BuildContext context) {
return Center(
child: Container(
height: 0.4,
width: MediaQuery.of(context).size.width - 32,
decoration: BoxDecoration(color: Colors.black26, borderRadius: BorderRadius.circular(16)),
),
);
}
}