Initiales HabitTracker-Projekt: SwiftUI + SwiftData Gewohnheiten-Tracker
Natives iOS-App-Gerüst (Xcode 26, synchronisierte Ordner, iOS 18+). Features: - Gewohnheiten anlegen (Name, SF-Symbol, Farbe), heute abhaken, Streaks, Löschen - Detailansicht mit Monatskalender (Tage nachtragbar) und Statistiken - Tägliche Erinnerungen via lokale Notifications - Home-Screen-Widget (klein/mittel) mit App-Group-Datenaustausch
This commit is contained in:
commit
22b8f5d806
24 changed files with 1448 additions and 0 deletions
69
HabitTracker/Views/HabitListView.swift
Normal file
69
HabitTracker/Views/HabitListView.swift
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
import SwiftUI
|
||||
import SwiftData
|
||||
|
||||
struct HabitListView: View {
|
||||
@Environment(\.modelContext) private var context
|
||||
@Environment(\.scenePhase) private var scenePhase
|
||||
@Query(sort: \Habit.createdAt) private var habits: [Habit]
|
||||
@State private var showingAdd = false
|
||||
|
||||
var body: some View {
|
||||
NavigationStack {
|
||||
Group {
|
||||
if habits.isEmpty {
|
||||
ContentUnavailableView(
|
||||
"Keine Gewohnheiten",
|
||||
systemImage: "checklist",
|
||||
description: Text("Tippe auf +, um deine erste Gewohnheit anzulegen.")
|
||||
)
|
||||
} else {
|
||||
List {
|
||||
ForEach(habits) { habit in
|
||||
NavigationLink {
|
||||
HabitDetailView(habit: habit)
|
||||
} label: {
|
||||
HabitRowView(habit: habit)
|
||||
}
|
||||
}
|
||||
.onDelete(perform: delete)
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationTitle("Heute")
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .topBarTrailing) {
|
||||
Button {
|
||||
showingAdd = true
|
||||
} label: {
|
||||
Label("Hinzufügen", systemImage: "plus")
|
||||
}
|
||||
}
|
||||
}
|
||||
.sheet(isPresented: $showingAdd) {
|
||||
AddHabitView()
|
||||
}
|
||||
}
|
||||
.task {
|
||||
WidgetSync.refresh(context)
|
||||
}
|
||||
.onChange(of: scenePhase) { _, phase in
|
||||
if phase == .active {
|
||||
WidgetSync.refresh(context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func delete(at offsets: IndexSet) {
|
||||
for index in offsets {
|
||||
let habit = habits[index]
|
||||
NotificationManager.cancel(for: habit)
|
||||
context.delete(habit)
|
||||
}
|
||||
WidgetSync.refresh(context)
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
HabitListView()
|
||||
.modelContainer(for: [Habit.self, HabitEntry.self], inMemory: true)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue