created notifications model and logic of type based parsing

This commit is contained in:
Username1548
2025-05-20 22:21:10 +07:00
parent aeedc35c42
commit c1e2b1c312
7 changed files with 350 additions and 23 deletions

View File

@@ -18,8 +18,7 @@ class WsManager {
PrivateChannel? _privateDirectChatChannel; PrivateChannel? _privateDirectChatChannel;
Stream<ChannelReadEvent>? get newMessagesStream => _privateMessagesChannel?.bind('App\\Events\\ChatMessageUpdated'); Stream<ChannelReadEvent>? get newMessagesStream => _privateMessagesChannel?.bind('App\\Events\\ChatMessageUpdated');
// TODO: change name of event to a right one
Stream<ChannelReadEvent>? get newNotificationsStream => _privateNotificationChannel?.bind('Illuminate\\Notifications\\Events\\BroadcastNotificationCreated'); Stream<ChannelReadEvent>? get newNotificationsStream => _privateNotificationChannel?.bind('Illuminate\\Notifications\\Events\\BroadcastNotificationCreated');
Stream<ChannelReadEvent>? get directChatStream => _privateDirectChatChannel?.bind('App\\Events\\ChatMessageUpdated'); Stream<ChannelReadEvent>? get directChatStream => _privateDirectChatChannel?.bind('App\\Events\\ChatMessageUpdated');

View File

@@ -1,25 +1,298 @@
import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:freezed_annotation/freezed_annotation.dart';
part 'notification_model.freezed.dart'; abstract class BaseNotificationModel {
part 'notification_model.g.dart'; abstract final NotificationType type;
@freezed
class NotificationModel with _$NotificationModel {
factory NotificationModel({
required NotificationType type
}) = _NotificationModel;
factory NotificationModel.fromJson(Map<String, dynamic> json) => _$NotificationModelFromJson(json);
} }
class PlanSubscriptionStartedToAuthorNotification implements BaseNotificationModel {
@override
final NotificationType type;
final String planName;
final String customerName;
final String chatId;
PlanSubscriptionStartedToAuthorNotification({
required this.type,
required this.planName,
required this.customerName,
required this.chatId,
});
factory PlanSubscriptionStartedToAuthorNotification.fromRest(Map<String, dynamic> json) {
throw UnimplementedError();
}
factory PlanSubscriptionStartedToAuthorNotification.fromWebSocket(Map<String, dynamic> json) {
throw UnimplementedError();
}
}
class PlanSubscriptionCanceledToAuthorNotification implements BaseNotificationModel {
@override
final NotificationType type;
final String planName;
final String customerName;
PlanSubscriptionCanceledToAuthorNotification({
required this.type,
required this.planName,
required this.customerName,
});
factory PlanSubscriptionCanceledToAuthorNotification.fromRest(Map<String, dynamic> json) {
throw UnimplementedError();
}
factory PlanSubscriptionCanceledToAuthorNotification.fromWebSocket(Map<String, dynamic> json) {
throw UnimplementedError();
}
}
class ChosenPlanStartedToClientNotification implements BaseNotificationModel {
@override
final NotificationType type;
final String planName;
final int planId;
ChosenPlanStartedToClientNotification({
required this.type,
required this.planName,
required this.planId,
});
factory ChosenPlanStartedToClientNotification.fromRest(Map<String, dynamic> json) {
throw UnimplementedError();
}
factory ChosenPlanStartedToClientNotification.fromWebSocket(Map<String, dynamic> json) {
throw UnimplementedError();
}
}
class ChosenPlanTomorrowReminderToClientNotification implements BaseNotificationModel {
@override
final NotificationType type;
final String planName;
ChosenPlanTomorrowReminderToClientNotification({
required this.type,
required this.planName,
});
factory ChosenPlanTomorrowReminderToClientNotification.fromRest(Map<String, dynamic> json) {
throw UnimplementedError();
}
factory ChosenPlanTomorrowReminderToClientNotification.fromWebSocket(Map<String, dynamic> json) {
throw UnimplementedError();
}
}
class DiaryReminderNotification implements BaseNotificationModel {
@override
final NotificationType type;
DiaryReminderNotification({required this.type});
factory DiaryReminderNotification.fromRest(Map<String, dynamic> json) {
throw UnimplementedError();
}
factory DiaryReminderNotification.fromWebSocket(Map<String, dynamic> json) {
throw UnimplementedError();
}
}
class ConsultantLeftCommentNotification implements BaseNotificationModel {
@override
final NotificationType type;
final DateTime date;
ConsultantLeftCommentNotification({
required this.type,
required this.date,
});
factory ConsultantLeftCommentNotification.fromRest(Map<String, dynamic> json) {
throw UnimplementedError();
}
factory ConsultantLeftCommentNotification.fromWebSocket(Map<String, dynamic> json) {
throw UnimplementedError();
}
}
class PersonalizedDietIsDefinedNotification implements BaseNotificationModel {
@override
final NotificationType type;
PersonalizedDietIsDefinedNotification({required this.type});
factory PersonalizedDietIsDefinedNotification.fromRest(Map<String, dynamic> json) {
throw UnimplementedError();
}
factory PersonalizedDietIsDefinedNotification.fromWebSocket(Map<String, dynamic> json) {
throw UnimplementedError();
}
}
class ChosenPlanFinishedToClientNotification implements BaseNotificationModel {
@override
final NotificationType type;
final String planName;
ChosenPlanFinishedToClientNotification({
required this.type,
required this.planName,
});
factory ChosenPlanFinishedToClientNotification.fromRest(Map<String, dynamic> json) {
throw UnimplementedError();
}
factory ChosenPlanFinishedToClientNotification.fromWebSocket(Map<String, dynamic> json) {
throw UnimplementedError();
}
}
class PlanSubscriptionCanceledToCustomerNotification implements BaseNotificationModel {
@override
final NotificationType type;
final String planName;
PlanSubscriptionCanceledToCustomerNotification({
required this.type,
required this.planName,
});
factory PlanSubscriptionCanceledToCustomerNotification.fromRest(Map<String, dynamic> json) {
throw UnimplementedError();
}
factory PlanSubscriptionCanceledToCustomerNotification.fromWebSocket(Map<String, dynamic> json) {
throw UnimplementedError();
}
}
class ChosenPlanStartedToConsultantNotification implements BaseNotificationModel {
@override
final NotificationType type;
final String planName;
final String customerName;
ChosenPlanStartedToConsultantNotification({
required this.type,
required this.planName,
required this.customerName,
});
factory ChosenPlanStartedToConsultantNotification.fromRest(Map<String, dynamic> json) {
throw UnimplementedError();
}
factory ChosenPlanStartedToConsultantNotification.fromWebSocket(Map<String, dynamic> json) {
throw UnimplementedError();
}
}
class ChosenPlanTomorrowReminderToConsultantNotification implements BaseNotificationModel {
@override
final NotificationType type;
final String planName;
final String customerName;
ChosenPlanTomorrowReminderToConsultantNotification({
required this.type,
required this.planName,
required this.customerName,
});
factory ChosenPlanTomorrowReminderToConsultantNotification.fromRest(Map<String, dynamic> json) {
throw UnimplementedError();
}
factory ChosenPlanTomorrowReminderToConsultantNotification.fromWebSocket(Map<String, dynamic> json) {
throw UnimplementedError();
}
}
class PlanSubscriptionPaidToAuthorNotification implements BaseNotificationModel {
@override
final NotificationType type;
final String planName;
final String customerName;
PlanSubscriptionPaidToAuthorNotification({
required this.type,
required this.planName,
required this.customerName,
});
factory PlanSubscriptionPaidToAuthorNotification.fromRest(Map<String, dynamic> json) {
throw UnimplementedError();
}
factory PlanSubscriptionPaidToAuthorNotification.fromWebSocket(Map<String, dynamic> json) {
throw UnimplementedError();
}
}
class ChosenPlanFinishedToConsultantNotification implements BaseNotificationModel {
@override
final NotificationType type;
final String planName;
final String customerName;
final int planId;
ChosenPlanFinishedToConsultantNotification({
required this.type,
required this.planName,
required this.customerName,
required this.planId,
});
factory ChosenPlanFinishedToConsultantNotification.fromRest(Map<String, dynamic> json) {
throw UnimplementedError();
}
factory ChosenPlanFinishedToConsultantNotification.fromWebSocket(Map<String, dynamic> json) {
throw UnimplementedError();
}
}
class UnknownNotification implements BaseNotificationModel {
@override
final NotificationType type;
UnknownNotification({
required this.type,
});
}
enum NotificationType { enum NotificationType {
@JsonValue('App\\Notifications\\UserSubscribedNotification')
userSubscribedNotification,
@JsonValue('App\\Notifications\\Plan\\PlanSubscriptionStartedToAuthor')
planSubscriptionStartedToAuthor, planSubscriptionStartedToAuthor,
@JsonValue('App\\Notifications\\Plan\\PlanSubscriptionCanceledToAuthor')
planSubscriptionCanceledToAuthor, planSubscriptionCanceledToAuthor,
chosenPlanStartedToClientNotification,
} chosenPlanTomorrowReminderToClientNotification,
diaryReminderNotification,
consultantLeftComment,
personalizedDietIsDefined,
chosenPlanFinishedToClient,
planSubscriptionCanceledToCustomer,
chosenPlanStartedToConsultantNotification,
chosenPlanTomorrowReminderToConsultantNotification,
planSubscriptionPaidToAuthor,
chosenPlanFinishedToConsultant,
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,
_ => NotificationType.unknown,
};
}

View File

@@ -4,7 +4,7 @@ import 'package:eatvio_app/features/notifications/presentation/notifications_cub
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
class NotificationsCubit extends Cubit<NotificationsState> { class NotificationsCubit extends Cubit<NotificationsState> {
final List<NotificationModel> _notifications = []; final List<BaseNotificationModel> _notifications = [];
final WsManager wsManager; final WsManager wsManager;
NotificationsCubit({required this.wsManager}) : super(const NotificationsState.empty()) { NotificationsCubit({required this.wsManager}) : super(const NotificationsState.empty()) {

View File

@@ -10,7 +10,7 @@ abstract class NotificationsState with _$NotificationsState {
const factory NotificationsState.empty() = NotificationsStateEmpty; const factory NotificationsState.empty() = NotificationsStateEmpty;
const factory NotificationsState.loaded({ const factory NotificationsState.loaded({
required List<NotificationModel> notifications, required List<BaseNotificationModel> notifications,
required int notificationsCount, required int notificationsCount,
}) = NotificationsStateLoaded; }) = NotificationsStateLoaded;

View File

@@ -3,7 +3,7 @@ import 'package:flutter/material.dart';
class NotificationWidget extends StatelessWidget { class NotificationWidget extends StatelessWidget {
const NotificationWidget({super.key, required this.notification}); const NotificationWidget({super.key, required this.notification});
final NotificationModel notification; final BaseNotificationModel notification;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
// return (notification.type) { // return (notification.type) {
@@ -12,4 +12,3 @@ class NotificationWidget extends StatelessWidget {
return Container(); return Container();
} }
} }

View File

@@ -0,0 +1,15 @@
import 'package:eatvio_app/features/notifications/models/notification_model.dart';
import 'package:eatvio_app/features/notifications/service/notifications_service.dart';
class NotificationsRepository {
final NotificationsService notificationsService;
NotificationsRepository({required this.notificationsService});
Future<List<BaseNotificationModel>?> getNotifications({required int page}) {
try {
return notificationsService.getNotifications(page: page);
} catch (e) {
rethrow;
}
}
}

View File

@@ -0,0 +1,41 @@
import 'package:dio/dio.dart';
import 'package:eatvio_app/features/notifications/models/notification_model.dart';
class NotificationsService {
final Dio dio;
NotificationsService(this.dio);
Future<List<BaseNotificationModel>?> getNotifications({required int page}) async {
try {
final response = await dio.get('api/profile/notifications?page=$page');
if (response.statusCode == 200) {
final data = response.data['data'] as List<Map<String, dynamic>>;
final notifications = data.map((notificationJson) {
final stringifiedType = notificationJson['data']['notification_class_name'];
final type = NotificationType.getTypeFromString(stringifiedType);
return switch (type) {
NotificationType.planSubscriptionStartedToAuthor => PlanSubscriptionStartedToAuthorNotification.fromRest(notificationJson),
NotificationType.planSubscriptionCanceledToAuthor => PlanSubscriptionCanceledToAuthorNotification.fromRest(notificationJson),
NotificationType.chosenPlanStartedToClientNotification => ChosenPlanStartedToClientNotification.fromRest(notificationJson),
NotificationType.chosenPlanTomorrowReminderToClientNotification => ChosenPlanTomorrowReminderToClientNotification.fromRest(notificationJson),
NotificationType.diaryReminderNotification => DiaryReminderNotification.fromRest(notificationJson),
NotificationType.consultantLeftComment => ConsultantLeftCommentNotification.fromRest(notificationJson),
NotificationType.personalizedDietIsDefined => PersonalizedDietIsDefinedNotification.fromRest(notificationJson),
NotificationType.chosenPlanFinishedToClient => ChosenPlanFinishedToClientNotification.fromRest(notificationJson),
NotificationType.planSubscriptionCanceledToCustomer => PlanSubscriptionCanceledToAuthorNotification.fromRest(notificationJson),
NotificationType.chosenPlanStartedToConsultantNotification => ChosenPlanStartedToConsultantNotification.fromRest(notificationJson),
NotificationType.chosenPlanTomorrowReminderToConsultantNotification =>
ChosenPlanTomorrowReminderToConsultantNotification.fromRest(notificationJson),
NotificationType.planSubscriptionPaidToAuthor => PlanSubscriptionPaidToAuthorNotification.fromRest(notificationJson),
NotificationType.chosenPlanFinishedToConsultant => ChosenPlanFinishedToConsultantNotification.fromRest(notificationJson),
NotificationType.unknown => UnknownNotification(type: type),
};
}).toList();
return notifications;
}
return null;
} catch (e) {
rethrow;
}
}
}