FRE-4738: Implement mark-as-read and mark-all-read actions
- Extract NotificationItem/NotificationType to Models/Notification.swift - Create NotificationsServiceProtocol with testable service layer - Implement markAsRead(id:) and markAllAsRead() with HTTP calls - Add NotificationError enum with localized descriptions - Update NotificationsViewModel to use protocol-based service - Add 18 unit tests (12 ViewModel + 6 Model) with mock service - Update README with architecture documentation
This commit is contained in:
92
Lendair/Models/Notification.swift
Normal file
92
Lendair/Models/Notification.swift
Normal file
@@ -0,0 +1,92 @@
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
|
||||
// MARK: - Notification Item
|
||||
|
||||
struct NotificationItem: Identifiable, Equatable, Codable {
|
||||
let id: String
|
||||
let type: NotificationType
|
||||
let title: String
|
||||
let message: String
|
||||
let createdAt: Date
|
||||
var isRead: Bool
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case id, type, title, message, createdAt, isRead
|
||||
}
|
||||
|
||||
init(id: String, type: NotificationType, title: String, message: String, createdAt: Date, isRead: Bool) {
|
||||
self.id = id
|
||||
self.type = type
|
||||
self.title = title
|
||||
self.message = message
|
||||
self.createdAt = createdAt
|
||||
self.isRead = isRead
|
||||
}
|
||||
|
||||
static func == (lhs: NotificationItem, rhs: NotificationItem) -> Bool {
|
||||
lhs.id == rhs.id && lhs.isRead == rhs.isRead
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Notification Type
|
||||
|
||||
enum NotificationType: String, CaseIterable, Codable {
|
||||
case loanApproved = "LOAN_APPROVED"
|
||||
case loanRejected = "LOAN_REJECTED"
|
||||
case paymentReceived = "PAYMENT_RECEIVED"
|
||||
case paymentDue = "PAYMENT_DUE"
|
||||
case newLender = "NEW_LENDER"
|
||||
case systemUpdate = "SYSTEM_UPDATE"
|
||||
|
||||
var icon: String {
|
||||
switch self {
|
||||
case .loanApproved: return "checkmark.circle.fill"
|
||||
case .loanRejected: return "xmark.circle.fill"
|
||||
case .paymentReceived: return "arrow.down.circle.fill"
|
||||
case .paymentDue: return "exclamationmark.circle.fill"
|
||||
case .newLender: return "person.circle.fill"
|
||||
case .systemUpdate: return "info.circle.fill"
|
||||
}
|
||||
}
|
||||
|
||||
var color: Color {
|
||||
switch self {
|
||||
case .loanApproved: return .green
|
||||
case .loanRejected: return .red
|
||||
case .paymentReceived: return .green
|
||||
case .paymentDue: return .orange
|
||||
case .newLender: return .blue
|
||||
case .systemUpdate: return .gray
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - List Parameters
|
||||
|
||||
struct NotificationListParams: Encodable {
|
||||
var limit: Int
|
||||
var offset: Int
|
||||
|
||||
init(limit: Int = 20, offset: Int = 0) {
|
||||
self.limit = limit
|
||||
self.offset = offset
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - API Response Types
|
||||
|
||||
struct NotificationListResponse: Decodable {
|
||||
let notifications: [NotificationItem]
|
||||
let hasMore: Bool
|
||||
}
|
||||
|
||||
struct NotificationMarkAsReadResponse: Decodable {
|
||||
let success: Bool
|
||||
let notificationId: String
|
||||
}
|
||||
|
||||
struct NotificationMarkAllReadResponse: Decodable {
|
||||
let success: Bool
|
||||
let markedCount: Int
|
||||
}
|
||||
Reference in New Issue
Block a user