74 lines
1.9 KiB
Swift
74 lines
1.9 KiB
Swift
|
|
//
|
||
|
|
// TodosViewModel.swift
|
||
|
|
// iris
|
||
|
|
//
|
||
|
|
// Created by Codex.
|
||
|
|
//
|
||
|
|
|
||
|
|
import Foundation
|
||
|
|
|
||
|
|
@MainActor
|
||
|
|
final class TodosViewModel: ObservableObject {
|
||
|
|
@Published private(set) var todos: [TodoItem] = []
|
||
|
|
@Published var newTitle: String = ""
|
||
|
|
|
||
|
|
private let store: TodoStore
|
||
|
|
|
||
|
|
init(store: TodoStore = TodoStore()) {
|
||
|
|
self.store = store
|
||
|
|
refresh()
|
||
|
|
}
|
||
|
|
|
||
|
|
func refresh() {
|
||
|
|
todos = sortedItems(store.snapshot())
|
||
|
|
}
|
||
|
|
|
||
|
|
func addTodo() {
|
||
|
|
let trimmed = normalizedTitle(newTitle)
|
||
|
|
guard !trimmed.isEmpty else { return }
|
||
|
|
store.add(title: trimmed)
|
||
|
|
newTitle = ""
|
||
|
|
refresh()
|
||
|
|
}
|
||
|
|
|
||
|
|
func deleteTodo(id: UUID) {
|
||
|
|
store.delete(id: id)
|
||
|
|
refresh()
|
||
|
|
}
|
||
|
|
|
||
|
|
func toggleCompleted(id: UUID) {
|
||
|
|
guard let current = todos.first(where: { $0.id == id }) else { return }
|
||
|
|
store.setCompleted(id: id, completed: !current.isCompleted)
|
||
|
|
refresh()
|
||
|
|
}
|
||
|
|
|
||
|
|
func updateTitle(id: UUID, title: String) {
|
||
|
|
let trimmed = normalizedTitle(title)
|
||
|
|
guard !trimmed.isEmpty else { return }
|
||
|
|
store.updateTitle(id: id, title: trimmed)
|
||
|
|
refresh()
|
||
|
|
}
|
||
|
|
|
||
|
|
private func normalizedTitle(_ raw: String) -> String {
|
||
|
|
raw.trimmingCharacters(in: .whitespacesAndNewlines)
|
||
|
|
}
|
||
|
|
|
||
|
|
private func sortedItems(_ items: [TodoItem]) -> [TodoItem] {
|
||
|
|
items.sorted { lhs, rhs in
|
||
|
|
if lhs.isCompleted != rhs.isCompleted {
|
||
|
|
return !lhs.isCompleted
|
||
|
|
}
|
||
|
|
if lhs.isCompleted {
|
||
|
|
let lhsDate = lhs.completedAt ?? lhs.updatedAt
|
||
|
|
let rhsDate = rhs.completedAt ?? rhs.updatedAt
|
||
|
|
if lhsDate != rhsDate {
|
||
|
|
return lhsDate > rhsDate
|
||
|
|
}
|
||
|
|
} else if lhs.createdAt != rhs.createdAt {
|
||
|
|
return lhs.createdAt > rhs.createdAt
|
||
|
|
}
|
||
|
|
return lhs.id.uuidString < rhs.id.uuidString
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|