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