- 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
93 lines
2.4 KiB
Swift
93 lines
2.4 KiB
Swift
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
|
|
}
|