feat: Implement notifications feature, enhance profile settings with new sections, and integrate Firebase configurations for multiple environments.

This commit is contained in:
pradeepkumar
2026-03-08 21:48:56 +05:30
parent 0362d7cfe0
commit 744b7b7ca8
24 changed files with 3413 additions and 557 deletions

View File

@@ -0,0 +1,53 @@
class AppNotification {
final String id;
final String userId;
final String type; // 'connection' | 'message' | 'system' | 'update' | 'request'
final String title;
final String description;
final bool read;
final String? actionUrl;
final Map<String, String>? data;
final DateTime createdAt;
const AppNotification({
required this.id,
required this.userId,
required this.type,
required this.title,
required this.description,
required this.read,
this.actionUrl,
this.data,
required this.createdAt,
});
factory AppNotification.fromJson(Map<String, dynamic> json) {
return AppNotification(
id: json['id'] as String,
userId: json['userId'] as String? ?? '',
type: json['type'] as String? ?? 'system',
title: json['title'] as String? ?? '',
description: json['description'] as String? ?? '',
read: json['read'] as bool? ?? false,
actionUrl: json['actionUrl'] as String?,
data: json['data'] != null
? Map<String, String>.from(json['data'] as Map)
: null,
createdAt: DateTime.parse(json['createdAt'] as String),
);
}
AppNotification copyWith({bool? read}) {
return AppNotification(
id: id,
userId: userId,
type: type,
title: title,
description: description,
read: read ?? this.read,
actionUrl: actionUrl,
data: data,
createdAt: createdAt,
);
}
}

View File

@@ -0,0 +1,103 @@
import 'package:dio/dio.dart';
import 'package:real_estate_mobile/core/network/api_client.dart';
import 'package:real_estate_mobile/core/network/api_exceptions.dart';
import 'package:real_estate_mobile/features/notifications/data/models/notification_model.dart';
class NotificationRepository {
final Dio _dio = ApiClient.instance.dio;
/// Fetch notifications with optional filter and pagination.
/// GET /notifications?filter=all|unread&page=1&limit=20
Future<NotificationsResponse> getNotifications({
String filter = 'all',
int page = 1,
int limit = 20,
}) async {
try {
final response = await _dio.get('/notifications', queryParameters: {
'filter': filter,
'page': page,
'limit': limit,
});
final data = response.data['data'] as Map<String, dynamic>;
return NotificationsResponse.fromJson(data);
} on DioException catch (e) {
if (e.error is ApiException) throw e.error as ApiException;
throw ApiException(
message: e.message ?? 'Failed to fetch notifications',
statusCode: e.response?.statusCode,
);
}
}
/// Get unread notification count.
/// GET /notifications/unread-count
Future<int> getUnreadCount() async {
try {
final response = await _dio.get('/notifications/unread-count');
final data = response.data['data'] as Map<String, dynamic>;
return data['unreadCount'] as int? ?? 0;
} on DioException catch (e) {
if (e.error is ApiException) throw e.error as ApiException;
throw ApiException(
message: e.message ?? 'Failed to fetch unread count',
statusCode: e.response?.statusCode,
);
}
}
/// Mark a single notification as read.
/// PATCH /notifications/:id/read
Future<void> markAsRead(String notificationId) async {
try {
await _dio.patch('/notifications/$notificationId/read');
} on DioException catch (e) {
if (e.error is ApiException) throw e.error as ApiException;
throw ApiException(
message: e.message ?? 'Failed to mark notification as read',
statusCode: e.response?.statusCode,
);
}
}
/// Mark all notifications as read.
/// PATCH /notifications/read-all
Future<void> markAllAsRead() async {
try {
await _dio.patch('/notifications/read-all');
} on DioException catch (e) {
if (e.error is ApiException) throw e.error as ApiException;
throw ApiException(
message: e.message ?? 'Failed to mark all as read',
statusCode: e.response?.statusCode,
);
}
}
}
class NotificationsResponse {
final List<AppNotification> notifications;
final int unreadCount;
final int totalPages;
final int currentPage;
const NotificationsResponse({
required this.notifications,
required this.unreadCount,
required this.totalPages,
required this.currentPage,
});
factory NotificationsResponse.fromJson(Map<String, dynamic> json) {
final list = (json['notifications'] as List<dynamic>?)
?.map((e) => AppNotification.fromJson(e as Map<String, dynamic>))
.toList() ??
[];
return NotificationsResponse(
notifications: list,
unreadCount: json['unreadCount'] as int? ?? 0,
totalPages: json['totalPages'] as int? ?? 1,
currentPage: json['currentPage'] as int? ?? 1,
);
}
}