Files
eatvio_app/lib/features/notifications/presentation/widgets/notification_widget.dart
2025-08-11 14:53:43 +03:00

574 lines
22 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/custom_text_style.dart';
import 'package:eatvio_app/core/theme/theme_helper.dart';
import 'package:eatvio_app/core/utils/date_time_utils.dart';
import 'package:eatvio_app/core/widgets/custom_outlined_button.dart';
import 'package:eatvio_app/features/my_finance/presentation/pages/card_settings.dart';
import 'package:eatvio_app/features/notifications/models/notification_model.dart';
import 'package:eatvio_app/generated/l10n.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
class NotificationWidget extends StatelessWidget {
const NotificationWidget({super.key, required this.notification});
final BaseNotificationModel notification;
@override
Widget build(BuildContext context) {
return switch (notification) {
PlanSubscriptionStartedToAuthorNotification() => _PlanSubscriptionStartedToAuthorWidget(
notification: notification as PlanSubscriptionStartedToAuthorNotification,
),
PlanSubscriptionCanceledToAuthorNotification() => _PlanSubscriptionCanceledToAuthorWidget(
notification: notification as PlanSubscriptionCanceledToAuthorNotification,
),
ChosenPlanStartedToClientNotification() => _ChosenPlanStartedToClientWidget(notification: notification as ChosenPlanStartedToClientNotification),
ChosenPlanTomorrowReminderToClientNotification() => _ChosenPlanTomorrowReminderToClientWidget(
notification: notification as ChosenPlanTomorrowReminderToClientNotification,
),
DiaryReminderNotification() => _DiaryReminderWidget(notification: notification as DiaryReminderNotification),
ConsultantLeftCommentNotification() => _ConsultantLeftCommentWidget(notification: notification as ConsultantLeftCommentNotification),
PersonalizedDietIsDefinedNotification() => _PersonalizedDietIsDefinedWidget(notification: notification as PersonalizedDietIsDefinedNotification),
ChosenPlanFinishedToClientNotification() => _ChosenPlanFinishedToClientWidget(notification: notification as ChosenPlanFinishedToClientNotification),
PlanSubscriptionCanceledToCustomerNotification() => _PlanSubscriptionCanceledToCustomerWidget(
notification: notification as PlanSubscriptionCanceledToCustomerNotification,
),
ChosenPlanStartedToConsultantNotification() => _ChosenPlanStartedToConsultantWidget(
notification: notification as ChosenPlanStartedToConsultantNotification,
),
ChosenPlanTomorrowReminderToConsultantNotification() => _ChosenPlanTomorrowReminderToConsultantWidget(
notification: notification as ChosenPlanTomorrowReminderToConsultantNotification,
),
PlanSubscriptionPaidToAuthorNotification() => _PlanSubscriptionPaidToAuthorWidget(notification: notification as PlanSubscriptionPaidToAuthorNotification),
ChosenPlanFinishedToConsultantNotification() => _ChosenPlanFinishedToConsultantWidget(
notification: notification as ChosenPlanFinishedToConsultantNotification,
),
ChosenPlanLastDayFinishedForUser() => _ChosenPlanLastDayFinishedForUserWidget(notification: notification as ChosenPlanLastDayFinishedForUser),
ChosenPlanConsultantLastDayStarted() => _ChosenPlanConsultantLastDayStartedWidget(notification: notification as ChosenPlanConsultantLastDayStarted),
ComplaintToModerationForUser() => _ComplaintToModerationForUserWidget(notification: notification as ComplaintToModerationForUser),
CommentReplied() => _CommentRepliedWidget(notification: notification as CommentReplied),
ScoreAdded() => _ScoreAddedWidget(notification: notification as ScoreAdded),
EntityCommented() => _EntityCommentedWidget(notification: notification as EntityCommented),
// Новые типы уведомлений
PlanSubscriptionExpiredNotification() => _PlanSubscriptionExpiredWidget(notification: notification as PlanSubscriptionExpiredNotification),
PlanSubscriptionRenewedNotification() => _PlanSubscriptionRenewedWidget(notification: notification as PlanSubscriptionRenewedNotification),
ConsultantAssignedNotification() => _ConsultantAssignedWidget(notification: notification as ConsultantAssignedNotification),
ConsultantUnassignedNotification() => _ConsultantUnassignedWidget(notification: notification as ConsultantUnassignedNotification),
PaymentFailedNotification() => _PaymentFailedWidget(notification: notification as PaymentFailedNotification),
PaymentSuccessfulNotification() => _PaymentSuccessfulWidget(notification: notification as PaymentSuccessfulNotification),
GoalAchievedNotification() => _GoalAchievedWidget(notification: notification as GoalAchievedNotification),
WorkoutReminderNotification() => _WorkoutReminderWidget(notification: notification as WorkoutReminderNotification),
MealReminderNotification() => _MealReminderWidget(notification: notification as MealReminderNotification),
UnknownNotification() => _UnknownNotificationWidget(notification: notification as UnknownNotification),
};
}
}
class _PlanSubscriptionStartedToAuthorWidget extends StatelessWidget {
const _PlanSubscriptionStartedToAuthorWidget({required this.notification});
final PlanSubscriptionStartedToAuthorNotification notification;
@override
Widget build(BuildContext context) {
final s = S.of(context);
return _BaseNotificationWidget(
isRead: notification.isRead,
notificationsText: s.userSubscribedToPlan(notification.customerName, notification.planName),
createdAt: notification.createdAt,
);
}
}
class _PlanSubscriptionCanceledToAuthorWidget extends StatelessWidget {
const _PlanSubscriptionCanceledToAuthorWidget({required this.notification});
final PlanSubscriptionCanceledToAuthorNotification notification;
@override
Widget build(BuildContext context) {
final s = S.of(context);
return _BaseNotificationWidget(
isRead: notification.isRead,
notificationsText: s.userCanceldThePlanSubscription(notification.customerName, notification.planName),
createdAt: notification.createdAt,
);
}
}
class _ChosenPlanStartedToClientWidget extends StatelessWidget {
const _ChosenPlanStartedToClientWidget({required this.notification});
final ChosenPlanStartedToClientNotification notification;
@override
Widget build(BuildContext context) {
final s = S.of(context);
return _BaseNotificationWidget(isRead: notification.isRead, notificationsText: s.planStarted(notification.planName), createdAt: notification.createdAt);
}
}
class _ChosenPlanTomorrowReminderToClientWidget extends StatelessWidget {
const _ChosenPlanTomorrowReminderToClientWidget({required this.notification});
final ChosenPlanTomorrowReminderToClientNotification notification;
@override
Widget build(BuildContext context) {
final s = S.of(context);
return _BaseNotificationWidget(
isRead: notification.isRead,
notificationsText: s.tomorrowYourPlanWillStart(notification.planName),
createdAt: notification.createdAt,
);
}
}
class _DiaryReminderWidget extends StatelessWidget {
const _DiaryReminderWidget({required this.notification});
final DiaryReminderNotification notification;
@override
Widget build(BuildContext context) {
final s = S.of(context);
return _BaseNotificationWidget(isRead: notification.isRead, notificationsText: s.fillYasterday, createdAt: notification.createdAt);
}
}
class _ConsultantLeftCommentWidget extends StatelessWidget {
const _ConsultantLeftCommentWidget({required this.notification});
final ConsultantLeftCommentNotification notification;
@override
Widget build(BuildContext context) {
final s = S.of(context);
return _BaseNotificationWidget(
isRead: notification.isRead,
notificationsText: s.consultantLeftComment(notification.date.format('dd.MM.yyyy')),
createdAt: notification.createdAt,
);
}
}
class _PersonalizedDietIsDefinedWidget extends StatelessWidget {
const _PersonalizedDietIsDefinedWidget({required this.notification});
final PersonalizedDietIsDefinedNotification notification;
@override
Widget build(BuildContext context) {
return _BaseNotificationWidget(isRead: notification.isRead, notificationsText: 'Персональная диета определена', createdAt: notification.createdAt);
}
}
class _ChosenPlanFinishedToClientWidget extends StatelessWidget {
const _ChosenPlanFinishedToClientWidget({required this.notification});
final ChosenPlanFinishedToClientNotification notification;
@override
Widget build(BuildContext context) {
final s = S.of(context);
return _BaseNotificationWidget(
isRead: notification.isRead,
notificationsText: '${s.congratsYouHaveFinishedPlan} «${notification.planName}»',
createdAt: notification.createdAt,
);
}
}
class _PlanSubscriptionCanceledToCustomerWidget extends StatelessWidget {
const _PlanSubscriptionCanceledToCustomerWidget({required this.notification});
final PlanSubscriptionCanceledToCustomerNotification notification;
@override
Widget build(BuildContext context) {
final s = S.of(context);
return _BaseNotificationWidget(
isRead: notification.isRead,
notificationsText: s.youCanceledSubscriptionToPlan(notification.planName),
createdAt: notification.createdAt,
);
}
}
class _ChosenPlanStartedToConsultantWidget extends StatelessWidget {
const _ChosenPlanStartedToConsultantWidget({required this.notification});
final ChosenPlanStartedToConsultantNotification notification;
@override
Widget build(BuildContext context) {
final s = S.of(context);
return _BaseNotificationWidget(
isRead: notification.isRead,
notificationsText: s.planWithUserStarted(notification.planName, notification.customerName),
createdAt: notification.createdAt,
);
}
}
class _ChosenPlanTomorrowReminderToConsultantWidget extends StatelessWidget {
const _ChosenPlanTomorrowReminderToConsultantWidget({required this.notification});
final ChosenPlanTomorrowReminderToConsultantNotification notification;
@override
Widget build(BuildContext context) {
final s = S.of(context);
return _BaseNotificationWidget(
isRead: notification.isRead,
notificationsText: s.tommorowPlanWithUserWillStart(notification.planName, notification.customerName),
createdAt: notification.createdAt,
);
}
}
class _PlanSubscriptionPaidToAuthorWidget extends StatelessWidget {
const _PlanSubscriptionPaidToAuthorWidget({required this.notification});
final PlanSubscriptionPaidToAuthorNotification notification;
@override
Widget build(BuildContext context) {
final s = S.of(context);
return _BaseNotificationWidget(
isRead: notification.isRead,
notificationsText: s.userPaidThePlan(notification.customerName, notification.planName),
createdAt: notification.createdAt,
);
}
}
class _ChosenPlanFinishedToConsultantWidget extends StatelessWidget {
const _ChosenPlanFinishedToConsultantWidget({required this.notification});
final ChosenPlanFinishedToConsultantNotification notification;
@override
Widget build(BuildContext context) {
final s = S.of(context);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('${s.congratsYouHaveFinishedPlan} «${notification.planName}»', style: TextStyles.textMSemibold.copyWith(color: appTheme.black)),
const SizedBox(height: 12),
Text(s.userConfirmedPlanCompletionWithoutSum, style: TextStyles.textSMedium.copyWith(color: appTheme.black)),
const SizedBox(height: 12),
CustomOutlinedButton(
text: s.collectCharge,
buttonTextStyle: TextStyles.textMSemibold.copyWith(color: appTheme.whiteA700),
buttonStyle: ButtonStyle(side: const WidgetStatePropertyAll(BorderSide.none), backgroundColor: WidgetStatePropertyAll(appTheme.green)),
onPressed: () {
GoRouter.of(context).pushNamed(CardSettingsScreen.name, extra: notification.planId);
},
),
],
),
),
if (!notification.isRead)
Container(
decoration: BoxDecoration(color: appTheme.blueA400, shape: BoxShape.circle),
width: 8,
height: 8,
),
],
),
const SizedBox(height: 4),
Text(
'${notification.createdAt.day} ${_getMonthName(notification.createdAt.month)} ${notification.createdAt.hour.toString().padLeft(2, '0')}:${notification.createdAt.minute.toString().padLeft(2, '0')}',
style: TextStyles.textSMedium.copyWith(color: appTheme.gray600),
),
],
);
}
String _getMonthName(int month) {
switch (month) {
case 1:
return 'янв';
case 2:
return 'фев';
case 3:
return 'мар';
case 4:
return 'апр';
case 5:
return 'май';
case 6:
return 'июн';
case 7:
return 'июл';
case 8:
return 'авг';
case 9:
return 'сен';
case 10:
return 'окт';
case 11:
return 'ноя';
case 12:
return 'дек';
default:
return '';
}
}
}
// CardSettingsScreen
class _BaseNotificationWidget extends StatelessWidget {
const _BaseNotificationWidget({required this.notificationsText, required this.isRead, required this.createdAt});
final String notificationsText;
final bool isRead;
final DateTime createdAt;
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Expanded(
child: Text(notificationsText, style: TextStyles.textMMedium.copyWith(color: appTheme.black)),
),
if (!isRead)
Container(
decoration: BoxDecoration(color: appTheme.blueA400, shape: BoxShape.circle),
width: 8,
height: 8,
),
],
),
const SizedBox(height: 4),
Text(
'${createdAt.day} ${_getMonthName(createdAt.month)} ${createdAt.hour.toString().padLeft(2, '0')}:${createdAt.minute.toString().padLeft(2, '0')}',
style: TextStyles.textSMedium.copyWith(color: appTheme.gray600),
),
],
);
}
String _getMonthName(int month) {
switch (month) {
case 1:
return 'янв';
case 2:
return 'фев';
case 3:
return 'мар';
case 4:
return 'апр';
case 5:
return 'май';
case 6:
return 'июн';
case 7:
return 'июл';
case 8:
return 'авг';
case 9:
return 'сен';
case 10:
return 'окт';
case 11:
return 'ноя';
case 12:
return 'дек';
default:
return '';
}
}
}
class _ChosenPlanLastDayFinishedForUserWidget extends StatelessWidget {
const _ChosenPlanLastDayFinishedForUserWidget({required this.notification});
final ChosenPlanLastDayFinishedForUser notification;
@override
Widget build(BuildContext context) {
return _BaseNotificationWidget(isRead: notification.isRead, notificationsText: 'Последний день плана завершен', createdAt: notification.createdAt);
}
}
class _ChosenPlanConsultantLastDayStartedWidget extends StatelessWidget {
const _ChosenPlanConsultantLastDayStartedWidget({required this.notification});
final ChosenPlanConsultantLastDayStarted notification;
@override
Widget build(BuildContext context) {
return _BaseNotificationWidget(
isRead: notification.isRead,
notificationsText: 'Последний день плана начался: ${notification.planName}',
createdAt: notification.createdAt,
);
}
}
class _ComplaintToModerationForUserWidget extends StatelessWidget {
const _ComplaintToModerationForUserWidget({required this.notification});
final ComplaintToModerationForUser notification;
@override
Widget build(BuildContext context) {
return _BaseNotificationWidget(isRead: notification.isRead, notificationsText: 'Жалоба отправлена на модерацию', createdAt: notification.createdAt);
}
}
class _CommentRepliedWidget extends StatelessWidget {
const _CommentRepliedWidget({required this.notification});
final CommentReplied notification;
@override
Widget build(BuildContext context) {
return _BaseNotificationWidget(
isRead: notification.isRead,
notificationsText: 'Ответ на комментарий: ${notification.entityName}',
createdAt: notification.createdAt,
);
}
}
class _ScoreAddedWidget extends StatelessWidget {
const _ScoreAddedWidget({required this.notification});
final ScoreAdded notification;
@override
Widget build(BuildContext context) {
return _BaseNotificationWidget(
isRead: notification.isRead,
notificationsText: 'Добавлены баллы: ${notification.scoreValue}',
createdAt: notification.createdAt,
);
}
}
class _EntityCommentedWidget extends StatelessWidget {
const _EntityCommentedWidget({required this.notification});
final EntityCommented notification;
@override
Widget build(BuildContext context) {
return _BaseNotificationWidget(
isRead: notification.isRead,
notificationsText: 'Комментарий к ${notification.entityTranslatedType}: ${notification.entityName}',
createdAt: notification.createdAt,
);
}
}
class _UnknownNotificationWidget extends StatelessWidget {
const _UnknownNotificationWidget({required this.notification});
final UnknownNotification notification;
@override
Widget build(BuildContext context) {
return _BaseNotificationWidget(
isRead: notification.isRead,
notificationsText: 'Неизвестное уведомление: ${notification.type.toString()}',
createdAt: notification.createdAt,
);
}
}
// Новые виджеты для дополнительных типов уведомлений
class _PlanSubscriptionExpiredWidget extends StatelessWidget {
const _PlanSubscriptionExpiredWidget({required this.notification});
final PlanSubscriptionExpiredNotification notification;
@override
Widget build(BuildContext context) {
return _BaseNotificationWidget(
isRead: notification.isRead,
notificationsText: 'Подписка на план "${notification.planName}" истекла',
createdAt: notification.createdAt,
);
}
}
class _PlanSubscriptionRenewedWidget extends StatelessWidget {
const _PlanSubscriptionRenewedWidget({required this.notification});
final PlanSubscriptionRenewedNotification notification;
@override
Widget build(BuildContext context) {
return _BaseNotificationWidget(
isRead: notification.isRead,
notificationsText: 'Подписка на план "${notification.planName}" продлена до ${notification.renewalDate}',
createdAt: notification.createdAt,
);
}
}
class _ConsultantAssignedWidget extends StatelessWidget {
const _ConsultantAssignedWidget({required this.notification});
final ConsultantAssignedNotification notification;
@override
Widget build(BuildContext context) {
return _BaseNotificationWidget(
isRead: notification.isRead,
notificationsText: 'К плану "${notification.planName}" назначен консультант ${notification.consultantName}',
createdAt: notification.createdAt,
);
}
}
class _ConsultantUnassignedWidget extends StatelessWidget {
const _ConsultantUnassignedWidget({required this.notification});
final ConsultantUnassignedNotification notification;
@override
Widget build(BuildContext context) {
return _BaseNotificationWidget(
isRead: notification.isRead,
notificationsText: 'Консультант ${notification.consultantName} отстранен от плана "${notification.planName}"',
createdAt: notification.createdAt,
);
}
}
class _PaymentFailedWidget extends StatelessWidget {
const _PaymentFailedWidget({required this.notification});
final PaymentFailedNotification notification;
@override
Widget build(BuildContext context) {
return _BaseNotificationWidget(
isRead: notification.isRead,
notificationsText: 'Ошибка оплаты плана "${notification.planName}": ${notification.errorMessage}',
createdAt: notification.createdAt,
);
}
}
class _PaymentSuccessfulWidget extends StatelessWidget {
const _PaymentSuccessfulWidget({required this.notification});
final PaymentSuccessfulNotification notification;
@override
Widget build(BuildContext context) {
return _BaseNotificationWidget(
isRead: notification.isRead,
notificationsText: 'Успешная оплата плана "${notification.planName}" на сумму ${notification.amount} ${notification.currency}',
createdAt: notification.createdAt,
);
}
}
class _GoalAchievedWidget extends StatelessWidget {
const _GoalAchievedWidget({required this.notification});
final GoalAchievedNotification notification;
@override
Widget build(BuildContext context) {
return _BaseNotificationWidget(
isRead: notification.isRead,
notificationsText: 'Достигнута цель "${notification.goalName}": ${notification.achievedValue}/${notification.targetValue}',
createdAt: notification.createdAt,
);
}
}
class _WorkoutReminderWidget extends StatelessWidget {
const _WorkoutReminderWidget({required this.notification});
final WorkoutReminderNotification notification;
@override
Widget build(BuildContext context) {
return _BaseNotificationWidget(
isRead: notification.isRead,
notificationsText: 'Напоминание о тренировке "${notification.workoutName}" (${notification.duration} мин)',
createdAt: notification.createdAt,
);
}
}
class _MealReminderWidget extends StatelessWidget {
const _MealReminderWidget({required this.notification});
final MealReminderNotification notification;
@override
Widget build(BuildContext context) {
return _BaseNotificationWidget(
isRead: notification.isRead,
notificationsText: 'Напоминание о приеме пищи "${notification.mealName}" (${notification.calories} ккал)',
createdAt: notification.createdAt,
);
}
}