feat(notifications): Issue-191

This commit is contained in:
mso7nueh
2025-08-06 11:28:02 +03:00
parent d53fdd1ccb
commit cd9357c050
8 changed files with 918 additions and 281 deletions

View File

@@ -1,8 +1,7 @@
import 'package:eatvio_app/features/feed/models/feed_blog_post_model.dart';
sealed class BaseNotificationModel {
abstract final NotificationType type;
abstract final bool isRead;
abstract final DateTime createdAt;
}
class PlanSubscriptionStartedToAuthorNotification implements BaseNotificationModel {
@@ -13,6 +12,8 @@ class PlanSubscriptionStartedToAuthorNotification implements BaseNotificationMod
final String planName;
final String customerName;
final String chatId;
@override
final DateTime createdAt;
PlanSubscriptionStartedToAuthorNotification({
required this.type,
@@ -20,15 +21,17 @@ class PlanSubscriptionStartedToAuthorNotification implements BaseNotificationMod
required this.customerName,
required this.chatId,
required this.isRead,
required this.createdAt,
});
factory PlanSubscriptionStartedToAuthorNotification.fromJson(Map<String, dynamic> json, NotificationType type, {bool? isRead}) {
factory PlanSubscriptionStartedToAuthorNotification.fromJson(Map<String, dynamic> json, NotificationType type, {bool? isRead, String? createdAt}) {
return PlanSubscriptionStartedToAuthorNotification(
type: type,
planName: json['plan_name'],
customerName: json['user_name'],
chatId: json['chat_id'],
isRead: isRead ?? false,
createdAt: parseDate(createdAt ?? json['created_at'] ?? DateTime.now().toIso8601String()),
);
}
}
@@ -40,20 +43,24 @@ class PlanSubscriptionCanceledToAuthorNotification implements BaseNotificationMo
final bool isRead;
final String planName;
final String customerName;
@override
final DateTime createdAt;
PlanSubscriptionCanceledToAuthorNotification({
required this.type,
required this.planName,
required this.customerName,
required this.isRead,
required this.createdAt,
});
factory PlanSubscriptionCanceledToAuthorNotification.fromJson(Map<String, dynamic> json, NotificationType type, {bool? isRead}) {
factory PlanSubscriptionCanceledToAuthorNotification.fromJson(Map<String, dynamic> json, NotificationType type, {bool? isRead, String? createdAt}) {
return PlanSubscriptionCanceledToAuthorNotification(
type: type,
planName: json['plan_name'],
customerName: json['user_name'],
isRead: isRead ?? false,
createdAt: parseDate(createdAt ?? json['created_at'] ?? DateTime.now().toIso8601String()),
);
}
}
@@ -65,20 +72,18 @@ class ChosenPlanStartedToClientNotification implements BaseNotificationModel {
final bool isRead;
final String planName;
final int planId;
@override
final DateTime createdAt;
ChosenPlanStartedToClientNotification({
required this.type,
required this.planName,
required this.planId,
required this.isRead,
});
ChosenPlanStartedToClientNotification({required this.type, required this.planName, required this.planId, required this.isRead, required this.createdAt});
factory ChosenPlanStartedToClientNotification.fromJson(Map<String, dynamic> json, NotificationType type, {bool? isRead}) {
factory ChosenPlanStartedToClientNotification.fromJson(Map<String, dynamic> json, NotificationType type, {bool? isRead, String? createdAt}) {
return ChosenPlanStartedToClientNotification(
type: type,
planName: json['plan_name'],
planId: json['plan_id'],
isRead: isRead ?? false,
createdAt: parseDate(createdAt ?? json['created_at'] ?? DateTime.now().toIso8601String()),
);
}
}
@@ -89,15 +94,18 @@ class ChosenPlanTomorrowReminderToClientNotification implements BaseNotification
@override
final bool isRead;
final String planName;
@override
final DateTime createdAt;
ChosenPlanTomorrowReminderToClientNotification({
required this.type,
required this.planName,
required this.isRead,
});
ChosenPlanTomorrowReminderToClientNotification({required this.type, required this.planName, required this.isRead, required this.createdAt});
factory ChosenPlanTomorrowReminderToClientNotification.fromJson(Map<String, dynamic> json, NotificationType type, {bool? isRead}) {
return ChosenPlanTomorrowReminderToClientNotification(type: type, planName: json['plan_name'], isRead: isRead ?? false);
factory ChosenPlanTomorrowReminderToClientNotification.fromJson(Map<String, dynamic> json, NotificationType type, {bool? isRead, String? createdAt}) {
return ChosenPlanTomorrowReminderToClientNotification(
type: type,
planName: json['plan_name'],
isRead: isRead ?? false,
createdAt: parseDate(createdAt ?? json['created_at'] ?? DateTime.now().toIso8601String()),
);
}
}
@@ -106,11 +114,17 @@ class DiaryReminderNotification implements BaseNotificationModel {
final NotificationType type;
@override
final bool isRead;
@override
final DateTime createdAt;
DiaryReminderNotification({required this.type, required this.isRead});
DiaryReminderNotification({required this.type, required this.isRead, required this.createdAt});
factory DiaryReminderNotification.fromJson(Map<String, dynamic> json, NotificationType type, {bool? isRead}) {
return DiaryReminderNotification(type: type, isRead: isRead ?? false);
factory DiaryReminderNotification.fromJson(Map<String, dynamic> json, NotificationType type, {bool? isRead, String? createdAt}) {
return DiaryReminderNotification(
type: type,
isRead: isRead ?? false,
createdAt: parseDate(createdAt ?? json['created_at'] ?? DateTime.now().toIso8601String()),
);
}
}
@@ -120,18 +134,17 @@ class ConsultantLeftCommentNotification implements BaseNotificationModel {
@override
final bool isRead;
final DateTime date;
@override
final DateTime createdAt;
ConsultantLeftCommentNotification({
required this.type,
required this.date,
required this.isRead,
});
ConsultantLeftCommentNotification({required this.type, required this.date, required this.isRead, required this.createdAt});
factory ConsultantLeftCommentNotification.fromJson(Map<String, dynamic> json, NotificationType type, {bool? isRead}) {
factory ConsultantLeftCommentNotification.fromJson(Map<String, dynamic> json, NotificationType type, {bool? isRead, String? createdAt}) {
return ConsultantLeftCommentNotification(
type: type,
date: parseDate(json['diary_date']),
date: parseDate(json['diary_date'] ?? DateTime.now().toIso8601String()),
isRead: isRead ?? false,
createdAt: parseDate(createdAt ?? json['created_at'] ?? DateTime.now().toIso8601String()),
);
}
}
@@ -141,16 +154,16 @@ class PersonalizedDietIsDefinedNotification implements BaseNotificationModel {
final NotificationType type;
@override
final bool isRead;
@override
final DateTime createdAt;
PersonalizedDietIsDefinedNotification({
required this.type,
required this.isRead,
});
PersonalizedDietIsDefinedNotification({required this.type, required this.isRead, required this.createdAt});
factory PersonalizedDietIsDefinedNotification.fromJson(Map<String, dynamic> json, NotificationType type, {bool? isRead}) {
factory PersonalizedDietIsDefinedNotification.fromJson(Map<String, dynamic> json, NotificationType type, {bool? isRead, String? createdAt}) {
return PersonalizedDietIsDefinedNotification(
type: type,
isRead: isRead ?? false,
createdAt: parseDate(createdAt ?? json['created_at'] ?? DateTime.now().toIso8601String()),
);
}
}
@@ -161,17 +174,16 @@ class ChosenPlanFinishedToClientNotification implements BaseNotificationModel {
@override
final bool isRead;
final String planName;
ChosenPlanFinishedToClientNotification({
required this.type,
required this.planName,
required this.isRead,
});
@override
final DateTime createdAt;
ChosenPlanFinishedToClientNotification({required this.type, required this.planName, required this.isRead, required this.createdAt});
factory ChosenPlanFinishedToClientNotification.fromJson(Map<String, dynamic> json, NotificationType type, {bool? isRead}) {
factory ChosenPlanFinishedToClientNotification.fromJson(Map<String, dynamic> json, NotificationType type, {bool? isRead, String? createdAt}) {
return ChosenPlanFinishedToClientNotification(
type: type,
planName: json['plan_name'],
isRead: isRead ?? false,
createdAt: parseDate(createdAt ?? json['created_at'] ?? DateTime.now().toIso8601String()),
);
}
}
@@ -182,17 +194,16 @@ class PlanSubscriptionCanceledToCustomerNotification implements BaseNotification
@override
final bool isRead;
final String planName;
PlanSubscriptionCanceledToCustomerNotification({
required this.type,
required this.planName,
required this.isRead,
});
@override
final DateTime createdAt;
PlanSubscriptionCanceledToCustomerNotification({required this.type, required this.planName, required this.isRead, required this.createdAt});
factory PlanSubscriptionCanceledToCustomerNotification.fromJson(Map<String, dynamic> json, NotificationType type, {bool? isRead}) {
factory PlanSubscriptionCanceledToCustomerNotification.fromJson(Map<String, dynamic> json, NotificationType type, {bool? isRead, String? createdAt}) {
return PlanSubscriptionCanceledToCustomerNotification(
type: type,
planName: json['plan_name'],
isRead: isRead ?? false,
createdAt: parseDate(createdAt ?? json['created_at'] ?? DateTime.now().toIso8601String()),
);
}
}
@@ -204,19 +215,23 @@ class ChosenPlanStartedToConsultantNotification implements BaseNotificationModel
final bool isRead;
final String planName;
final String customerName;
@override
final DateTime createdAt;
ChosenPlanStartedToConsultantNotification({
required this.type,
required this.isRead,
required this.planName,
required this.customerName,
required this.createdAt,
});
factory ChosenPlanStartedToConsultantNotification.fromJson(Map<String, dynamic> json, NotificationType type, {bool? isRead}) {
factory ChosenPlanStartedToConsultantNotification.fromJson(Map<String, dynamic> json, NotificationType type, {bool? isRead, String? createdAt}) {
return ChosenPlanStartedToConsultantNotification(
type: type,
isRead: isRead ?? false,
planName: json['plan_name'],
customerName: json['client_name'],
createdAt: parseDate(createdAt ?? json['created_at'] ?? DateTime.now().toIso8601String()),
);
}
}
@@ -228,19 +243,23 @@ class ChosenPlanTomorrowReminderToConsultantNotification implements BaseNotifica
final bool isRead;
final String planName;
final String customerName;
@override
final DateTime createdAt;
ChosenPlanTomorrowReminderToConsultantNotification({
required this.type,
required this.planName,
required this.customerName,
required this.isRead,
required this.createdAt,
});
factory ChosenPlanTomorrowReminderToConsultantNotification.fromJson(Map<String, dynamic> json, NotificationType type, {bool? isRead}) {
factory ChosenPlanTomorrowReminderToConsultantNotification.fromJson(Map<String, dynamic> json, NotificationType type, {bool? isRead, String? createdAt}) {
return ChosenPlanTomorrowReminderToConsultantNotification(
type: type,
planName: json['plan_name'],
customerName: json['client_name'],
isRead: isRead ?? false,
createdAt: parseDate(createdAt ?? json['created_at'] ?? DateTime.now().toIso8601String()),
);
}
}
@@ -252,19 +271,23 @@ class PlanSubscriptionPaidToAuthorNotification implements BaseNotificationModel
final bool isRead;
final String planName;
final String customerName;
@override
final DateTime createdAt;
PlanSubscriptionPaidToAuthorNotification({
required this.type,
required this.isRead,
required this.planName,
required this.customerName,
required this.createdAt,
});
factory PlanSubscriptionPaidToAuthorNotification.fromJson(Map<String, dynamic> json, NotificationType type, {bool? isRead}) {
factory PlanSubscriptionPaidToAuthorNotification.fromJson(Map<String, dynamic> json, NotificationType type, {bool? isRead, String? createdAt}) {
return PlanSubscriptionPaidToAuthorNotification(
type: type,
isRead: isRead ?? false,
planName: json['plan_name'],
customerName: json['user_name'],
createdAt: parseDate(createdAt ?? json['created_at'] ?? DateTime.now().toIso8601String()),
);
}
}
@@ -277,21 +300,25 @@ class ChosenPlanFinishedToConsultantNotification implements BaseNotificationMode
final String planName;
final String customerName;
final int planId;
@override
final DateTime createdAt;
ChosenPlanFinishedToConsultantNotification({
required this.type,
required this.planName,
required this.customerName,
required this.planId,
required this.isRead,
required this.createdAt,
});
factory ChosenPlanFinishedToConsultantNotification.fromJson(Map<String, dynamic> json, NotificationType type, {bool? isRead}) {
factory ChosenPlanFinishedToConsultantNotification.fromJson(Map<String, dynamic> json, NotificationType type, {bool? isRead, String? createdAt}) {
return ChosenPlanFinishedToConsultantNotification(
type: type,
planName: json['plan_name'],
customerName: json['client_name'],
planId: json['plan_id'],
isRead: isRead ?? false,
createdAt: parseDate(createdAt ?? json['created_at'] ?? DateTime.now().toIso8601String()),
);
}
}
@@ -301,16 +328,212 @@ class ChosenPlanLastDayFinishedForUser implements BaseNotificationModel {
final NotificationType type;
@override
final bool isRead;
@override
final DateTime createdAt;
ChosenPlanLastDayFinishedForUser({
required this.type,
required this.isRead,
});
ChosenPlanLastDayFinishedForUser({required this.type, required this.isRead, required this.createdAt});
factory ChosenPlanLastDayFinishedForUser.fromJson(Map<String, dynamic> json, NotificationType type, {bool? isRead}) {
factory ChosenPlanLastDayFinishedForUser.fromJson(Map<String, dynamic> json, NotificationType type, {bool? isRead, String? createdAt}) {
return ChosenPlanLastDayFinishedForUser(
type: type,
isRead: isRead ?? false,
createdAt: parseDate(createdAt ?? json['created_at'] ?? DateTime.now().toIso8601String()),
);
}
}
class ChosenPlanConsultantLastDayStarted implements BaseNotificationModel {
@override
final NotificationType type;
@override
final bool isRead;
final String planName;
final int planId;
final String chatId;
final String chatUrl;
@override
final DateTime createdAt;
ChosenPlanConsultantLastDayStarted({
required this.type,
required this.planName,
required this.planId,
required this.chatId,
required this.chatUrl,
required this.isRead,
required this.createdAt,
});
factory ChosenPlanConsultantLastDayStarted.fromJson(Map<String, dynamic> json, NotificationType type, {bool? isRead, String? createdAt}) {
return ChosenPlanConsultantLastDayStarted(
type: type,
planName: json['plan_name'],
planId: json['plan_id'],
chatId: json['chat_id'],
chatUrl: json['chat_url'],
isRead: isRead ?? false,
createdAt: parseDate(createdAt ?? json['created_at'] ?? DateTime.now().toIso8601String()),
);
}
}
class ComplaintToModerationForUser implements BaseNotificationModel {
@override
final NotificationType type;
@override
final bool isRead;
final String message;
final int entityId;
final String entityType;
@override
final DateTime createdAt;
ComplaintToModerationForUser({
required this.type,
required this.message,
required this.entityId,
required this.entityType,
required this.isRead,
required this.createdAt,
});
factory ComplaintToModerationForUser.fromJson(Map<String, dynamic> json, NotificationType type, {bool? isRead, String? createdAt}) {
return ComplaintToModerationForUser(
type: type,
message: json['message'],
entityId: json['entity_id'],
entityType: json['entity_type'],
isRead: isRead ?? false,
createdAt: parseDate(createdAt ?? json['created_at'] ?? DateTime.now().toIso8601String()),
);
}
}
class CommentReplied implements BaseNotificationModel {
@override
final NotificationType type;
@override
final bool isRead;
final String entityName;
final int commentedEntityId;
final String commentedEntityType;
final String author;
final int authorId;
final int parentCommentId;
@override
final DateTime createdAt;
CommentReplied({
required this.type,
required this.entityName,
required this.commentedEntityId,
required this.commentedEntityType,
required this.author,
required this.authorId,
required this.parentCommentId,
required this.isRead,
required this.createdAt,
});
factory CommentReplied.fromJson(Map<String, dynamic> json, NotificationType type, {bool? isRead, String? createdAt}) {
return CommentReplied(
type: type,
entityName: json['entity_name'],
commentedEntityId: json['commented_entity_id'],
commentedEntityType: json['commented_entity_type'],
author: json['author'],
authorId: json['author_id'],
parentCommentId: json['parrent_comment_id'],
isRead: isRead ?? false,
createdAt: parseDate(createdAt ?? json['created_at'] ?? DateTime.now().toIso8601String()),
);
}
}
class ScoreAdded implements BaseNotificationModel {
@override
final NotificationType type;
@override
final bool isRead;
final String scoreKey;
final int scorableId;
final String scorableType;
final String scorableName;
final String scorableSlug;
final int scoreValue;
@override
final DateTime createdAt;
ScoreAdded({
required this.type,
required this.scoreKey,
required this.scorableId,
required this.scorableType,
required this.scorableName,
required this.scorableSlug,
required this.scoreValue,
required this.isRead,
required this.createdAt,
});
factory ScoreAdded.fromJson(Map<String, dynamic> json, NotificationType type, {bool? isRead, String? createdAt}) {
return ScoreAdded(
type: type,
scoreKey: json['score_key'],
scorableId: json['scorable_id'],
scorableType: json['scorable_type'],
scorableName: json['scorable_name'] ?? '',
scorableSlug: json['scorable_slug'] ?? '',
scoreValue: json['score_value'],
isRead: isRead ?? false,
createdAt: parseDate(createdAt ?? json['created_at'] ?? DateTime.now().toIso8601String()),
);
}
}
class EntityCommented implements BaseNotificationModel {
@override
final NotificationType type;
@override
final bool isRead;
final String entityName;
final int entityId;
final String entityType;
final String entityTranslatedType;
final String entityUrl;
final String authorName;
final int authorId;
final String authorSlug;
@override
final DateTime createdAt;
EntityCommented({
required this.type,
required this.entityName,
required this.entityId,
required this.entityType,
required this.entityTranslatedType,
required this.entityUrl,
required this.authorName,
required this.authorId,
required this.authorSlug,
required this.isRead,
required this.createdAt,
});
factory EntityCommented.fromJson(Map<String, dynamic> json, NotificationType type, {bool? isRead, String? createdAt}) {
return EntityCommented(
type: type,
entityName: json['entity_name'],
entityId: json['entity_id'],
entityType: json['entity_type'],
entityTranslatedType: json['entity_traslated_type'],
entityUrl: json['entity_url'],
authorName: json['author_name'],
authorId: json['author_id'],
authorSlug: json['author_slug'],
isRead: isRead ?? false,
createdAt: parseDate(createdAt ?? json['created_at'] ?? DateTime.now().toIso8601String()),
);
}
}
@@ -320,11 +543,10 @@ class UnknownNotification implements BaseNotificationModel {
final NotificationType type;
@override
final bool isRead;
@override
final DateTime createdAt;
UnknownNotification({
required this.type,
this.isRead = true,
});
UnknownNotification({required this.type, this.isRead = true, DateTime? createdAt}) : createdAt = createdAt ?? DateTime.fromMillisecondsSinceEpoch(0);
}
enum NotificationType {
@@ -342,23 +564,37 @@ enum NotificationType {
planSubscriptionPaidToAuthor,
chosenPlanFinishedToConsultant,
chosenPlanLastDayFinishedForUser,
// Новые типы
chosenPlanConsultantLastDayStarted,
complaintToModerationForUser,
commentReplied,
scoreAdded,
entityCommented,
unknown;
static NotificationType getTypeFromString(String type) => switch (type) {
'App\\Notifications\\Plan\\PlanSubscriptionStartedToAuthor' => NotificationType.planSubscriptionStartedToAuthor,
'App\\Notifications\\Plan\\PlanSubscriptionCanceledToAuthor' => NotificationType.planSubscriptionCanceledToAuthor,
'App\\Notifications\\Plan\\ChosenPlanStartedToClientNotification' => NotificationType.chosenPlanStartedToClientNotification,
'App\\Notifications\\Plan\\ChosenPlanTomorrowReminderToClientNotification' => NotificationType.chosenPlanStartedToClientNotification,
'App\\Notifications\\DiaryReminderNotification' => NotificationType.diaryReminderNotification,
'App\\Notifications\\Plan\\ConsultantLeftComment' => NotificationType.consultantLeftComment,
'App\\Notifications\\Plan\\PersonalizedDietIsDefined' => NotificationType.personalizedDietIsDefined,
'App\\Notifications\\Plan\\ChosenPlanFinishedToClient' => NotificationType.chosenPlanFinishedToClient,
'App\\Notifications\\Plan\\PlanSubscriptionCanceledToCustomer' => NotificationType.planSubscriptionCanceledToCustomer,
'App\\Notifications\\Plan\\ChosenPlanStartedToConsultantNotification' => NotificationType.chosenPlanStartedToConsultantNotification,
'App\\Notifications\\Plan\\ChosenPlanTomorrowReminderToConsultantNotification' => NotificationType.chosenPlanTomorrowReminderToConsultantNotification,
'App\\Notifications\\Plan\\PlanSubscriptionPaidToAuthor' => NotificationType.planSubscriptionPaidToAuthor,
'App\\Notifications\\Plan\\ChosenPlanFinishedToConsultant' => NotificationType.chosenPlanFinishedToConsultant,
'App\\Notifications\\ChosenPlan\\LastDayFinishedForUser' => NotificationType.chosenPlanLastDayFinishedForUser,
_ => NotificationType.unknown,
};
'App\\Notifications\\Plan\\PlanSubscriptionStartedToAuthor' => NotificationType.planSubscriptionStartedToAuthor,
'App\\Notifications\\Plan\\PlanSubscriptionCanceledToAuthor' => NotificationType.planSubscriptionCanceledToAuthor,
'App\\Notifications\\Plan\\ChosenPlanStartedToClientNotification' => NotificationType.chosenPlanStartedToClientNotification,
'App\\Notifications\\Plan\\ChosenPlanTomorrowReminderToClientNotification' => NotificationType.chosenPlanStartedToClientNotification,
'App\\Notifications\\DiaryReminderNotification' => NotificationType.diaryReminderNotification,
'App\\Notifications\\Plan\\ConsultantLeftComment' => NotificationType.consultantLeftComment,
'App\\Notifications\\Plan\\PersonalizedDietIsDefined' => NotificationType.personalizedDietIsDefined,
'App\\Notifications\\Plan\\ChosenPlanFinishedToClient' => NotificationType.chosenPlanFinishedToClient,
'App\\Notifications\\Plan\\PlanSubscriptionCanceledToCustomer' => NotificationType.planSubscriptionCanceledToCustomer,
'App\\Notifications\\Plan\\ChosenPlanStartedToConsultantNotification' => NotificationType.chosenPlanStartedToConsultantNotification,
'App\\Notifications\\Plan\\ChosenPlanTomorrowReminderToConsultantNotification' => NotificationType.chosenPlanTomorrowReminderToConsultantNotification,
'App\\Notifications\\Plan\\PlanSubscriptionPaidToAuthor' => NotificationType.planSubscriptionPaidToAuthor,
'App\\Notifications\\Plan\\ChosenPlanFinishedToConsultant' => NotificationType.chosenPlanFinishedToConsultant,
'App\\Notifications\\ChosenPlan\\LastDayFinishedForUser' => NotificationType.chosenPlanLastDayFinishedForUser,
// Новые маппинги
'App\\Notifications\\ChosenPlan\\LastDayStartedForConsultant' => NotificationType.chosenPlanConsultantLastDayStarted,
'App\\Notifications\\ComplaintToModerationNotify' => NotificationType.complaintToModerationForUser,
'App\\Notifications\\Comment\\Replied' => NotificationType.commentReplied,
'App\\Notifications\\Score\\ScoreAdded' => NotificationType.scoreAdded,
'App\\Notifications\\Comment\\EntityCommented' => NotificationType.entityCommented,
_ => NotificationType.unknown,
};
}
DateTime parseDate(String date) => DateTime.parse(date).toLocal();