feat: add SwiftData persistence for lists and todos
This commit is contained in:
@@ -1,26 +1,35 @@
|
||||
import Foundation
|
||||
import Observation
|
||||
import SwiftData
|
||||
|
||||
@Observable
|
||||
class ListStore {
|
||||
var lists: [TodoList]
|
||||
var lists: [TodoList] = []
|
||||
|
||||
private let modelContext: ModelContext
|
||||
|
||||
var inboxID: UUID {
|
||||
lists.first { $0.isInbox }!.id
|
||||
}
|
||||
|
||||
init() {
|
||||
self.lists = [TodoList(name: "Inbox", isInbox: true)]
|
||||
init(modelContext: ModelContext) {
|
||||
self.modelContext = modelContext
|
||||
ensureInbox()
|
||||
fetchLists()
|
||||
}
|
||||
|
||||
func addList(name: String) {
|
||||
let list = TodoList(name: name)
|
||||
lists.append(list)
|
||||
modelContext.insert(list)
|
||||
save()
|
||||
fetchLists()
|
||||
}
|
||||
|
||||
func deleteList(_ list: TodoList) {
|
||||
guard !list.isInbox else { return }
|
||||
lists.removeAll { $0.id == list.id }
|
||||
modelContext.delete(list)
|
||||
save()
|
||||
fetchLists()
|
||||
}
|
||||
|
||||
func addItem(
|
||||
@@ -30,14 +39,19 @@ class ListStore {
|
||||
deadline: Date? = nil,
|
||||
priority: Priority? = nil
|
||||
) {
|
||||
guard let index = lists.firstIndex(where: { $0.id == listID }) else { return }
|
||||
guard let list = lists.first(where: { $0.id == listID }) else { return }
|
||||
let item = TodoItem(title: title, notes: notes, deadline: deadline, priority: priority)
|
||||
lists[index].items.append(item)
|
||||
list.items.append(item)
|
||||
save()
|
||||
fetchLists()
|
||||
}
|
||||
|
||||
func deleteItem(_ itemID: UUID, from listID: UUID) {
|
||||
guard let listIndex = lists.firstIndex(where: { $0.id == listID }) else { return }
|
||||
lists[listIndex].items.removeAll { $0.id == itemID }
|
||||
guard let list = lists.first(where: { $0.id == listID }),
|
||||
let item = list.items.first(where: { $0.id == itemID }) else { return }
|
||||
modelContext.delete(item)
|
||||
save()
|
||||
fetchLists()
|
||||
}
|
||||
|
||||
func updateItem(
|
||||
@@ -49,22 +63,51 @@ class ListStore {
|
||||
priority: Priority? = nil,
|
||||
isCompleted: Bool? = nil
|
||||
) {
|
||||
guard let listIndex = lists.firstIndex(where: { $0.id == listID }),
|
||||
let itemIndex = lists[listIndex].items.firstIndex(where: { $0.id == itemID }) else { return }
|
||||
lists[listIndex].items[itemIndex].title = title
|
||||
lists[listIndex].items[itemIndex].notes = notes
|
||||
lists[listIndex].items[itemIndex].deadline = deadline
|
||||
lists[listIndex].items[itemIndex].priority = priority
|
||||
guard let list = lists.first(where: { $0.id == listID }),
|
||||
let item = list.items.first(where: { $0.id == itemID }) else { return }
|
||||
item.title = title
|
||||
item.notes = notes
|
||||
item.deadline = deadline
|
||||
item.priority = priority
|
||||
if let isCompleted {
|
||||
lists[listIndex].items[itemIndex].isCompleted = isCompleted
|
||||
item.isCompleted = isCompleted
|
||||
}
|
||||
lists[listIndex].items[itemIndex].modifiedAt = Date()
|
||||
item.modifiedAt = Date()
|
||||
save()
|
||||
fetchLists()
|
||||
}
|
||||
|
||||
func toggleItemCompleted(_ itemID: UUID, in listID: UUID) {
|
||||
guard let listIndex = lists.firstIndex(where: { $0.id == listID }),
|
||||
let itemIndex = lists[listIndex].items.firstIndex(where: { $0.id == itemID }) else { return }
|
||||
lists[listIndex].items[itemIndex].isCompleted.toggle()
|
||||
lists[listIndex].items[itemIndex].modifiedAt = Date()
|
||||
guard let list = lists.first(where: { $0.id == listID }),
|
||||
let item = list.items.first(where: { $0.id == itemID }) else { return }
|
||||
item.isCompleted.toggle()
|
||||
item.modifiedAt = Date()
|
||||
save()
|
||||
fetchLists()
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func ensureInbox() {
|
||||
let descriptor = FetchDescriptor<TodoList>(predicate: #Predicate { $0.isInbox })
|
||||
let count = (try? modelContext.fetchCount(descriptor)) ?? 0
|
||||
if count == 0 {
|
||||
let inbox = TodoList(name: "Inbox", isInbox: true)
|
||||
modelContext.insert(inbox)
|
||||
save()
|
||||
}
|
||||
}
|
||||
|
||||
private func fetchLists() {
|
||||
let descriptor = FetchDescriptor<TodoList>(sortBy: [SortDescriptor(\.name)])
|
||||
let fetched = (try? modelContext.fetch(descriptor)) ?? []
|
||||
// Inbox always first
|
||||
let inbox = fetched.filter { $0.isInbox }
|
||||
let rest = fetched.filter { !$0.isInbox }
|
||||
lists = inbox + rest
|
||||
}
|
||||
|
||||
private func save() {
|
||||
try? modelContext.save()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user