Files
FrenoCorp/Lendair/README.md
Senior Engineer 57eb01f5af 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
2026-05-03 12:17:15 -04:00

110 lines
4.1 KiB
Markdown

# Lendair iOS Notifications
## Overview
SwiftUI implementation of the notifications feature for the Lendair iOS app.
## Architecture
### MVVM Pattern
- **View**: `Views/` - SwiftUI views for notification display
- **ViewModel**: `ViewModels/` - State management and business logic
- **Service**: `Services/` - Data layer with API communication
- **Model**: `Models/` - Data structures and type definitions
### File Structure
```
Lendair/
├── Models/
│ └── Notification.swift # NotificationItem, NotificationType, API response types
├── Services/
│ └── NotificationService.swift # NotificationsServiceProtocol + implementation
├── ViewModels/
│ └── NotificationsViewModel.swift # State management, mark-as-read actions
├── Views/
│ ├── NotificationsView.swift # Main notifications list screen
│ └── NotificationRowView.swift # Individual notification row
└── README.md
```
## Components
### NotificationsView (`Views/NotificationsView.swift`)
- Main navigation container for the notifications screen
- Pull-to-refresh via `.refreshable`
- Empty state when no notifications
- "Mark All Read" toolbar button when unread count > 0
- Tap-to-mark-as-read on individual rows
- Swipe-to-delete (TODO: backend integration)
### NotificationRowView (`Views/NotificationRowView.swift`)
- Individual notification list item
- Type-specific SF Symbol icon with color coding
- Read/unread indicator (blue dot)
- Relative timestamp display
### NotificationsViewModel (`ViewModels/NotificationsViewModel.swift`)
- `@Published notifications` — sorted by createdAt descending
- `@Published isLoading` — loading state for UI feedback
- `@Published error` — typed error state (NotificationError)
- `fetchNotifications()` — loads from service
- `markAsRead(id:)` — marks single notification, updates local state
- `markAllAsRead()` — marks all unread, updates local state
- `unreadCount` — computed property for badge display
### NotificationsService (`Services/NotificationService.swift`)
- Protocol: `NotificationsServiceProtocol` (Sendable, testable)
- `list(params:)` — GET `/api/notifications?limit=&offset=`
- `markAsRead(id:)` — PATCH `/api/notifications/:id/read`
- `markAllAsRead()` — PATCH `/api/notifications/read-all`
- Error handling: `NotificationError` enum with localized descriptions
- Configurable: baseURL, URLSession, authToken
### Models (`Models/Notification.swift`)
- `NotificationItem` — Identifiable, Equatable, Codable
- `NotificationType` — 6 cases with icon/color mappings
- `NotificationListParams` — pagination parameters
- `NotificationListResponse`, `NotificationMarkAsReadResponse`, `NotificationMarkAllReadResponse` — API response types
## Notification Types
| Type | Icon | Color |
|------|------|-------|
| `LOAN_APPROVED` | checkmark.circle.fill | Green |
| `LOAN_REJECTED` | xmark.circle.fill | Red |
| `PAYMENT_RECEIVED` | arrow.down.circle.fill | Green |
| `PAYMENT_DUE` | exclamationmark.circle.fill | Orange |
| `NEW_LENDER` | person.circle.fill | Blue |
| `SYSTEM_UPDATE` | info.circle.fill | Gray |
## API Endpoints
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/api/notifications?limit=&offset=` | List notifications |
| PATCH | `/api/notifications/:id/read` | Mark single as read |
| PATCH | `/api/notifications/read-all` | Mark all as read |
## Testing
Tests are in `LendairTests/NotificationServiceTests.swift`:
- 12 ViewModel tests (fetch, mark-as-read, mark-all-read, unread count, refresh, error handling)
- 6 Model tests (icons, colors, equality, raw values, params)
- Uses `MockNotificationsService` conforming to `NotificationsServiceProtocol`
## Usage
```swift
// In your MainTabView or navigation stack
NavigationStack {
NotificationsView()
}
```
## Future Enhancements
1. **Push Notifications**: Integrate with UNUserNotificationCenter
2. **Notification Preferences**: Allow users to customize notification types
3. **Deep Linking**: Navigate to relevant screens when tapping notifications
4. **Offline Support**: Cache notifications locally with Core Data
5. **Analytics**: Track notification engagement metrics