ios-tracker/HabitTracker/Views/HabitDetailView.swift
rene 22b8f5d806 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
2026-05-29 21:12:45 +02:00

82 lines
2.7 KiB
Swift

import SwiftUI
import SwiftData
struct HabitDetailView: View {
@Environment(\.modelContext) private var context
@Bindable var habit: Habit
var body: some View {
ScrollView {
VStack(spacing: 24) {
header
HStack(spacing: 12) {
StatTile(value: "\(habit.currentStreak)", label: "Aktuell", systemImage: "flame.fill", color: color)
StatTile(value: "\(habit.longestStreak)", label: "Rekord", systemImage: "trophy.fill", color: color)
StatTile(value: "\(habit.totalCompletions)", label: "Gesamt", systemImage: "checkmark.seal.fill", color: color)
}
MonthCalendarView(habit: habit) { day in
context.toggleCompletion(for: habit, on: day)
}
.padding()
.background(.background.secondary, in: RoundedRectangle(cornerRadius: 16))
VStack(spacing: 12) {
ReminderEditor(reminderTime: $habit.reminderTime)
}
.padding()
.background(.background.secondary, in: RoundedRectangle(cornerRadius: 16))
.onChange(of: habit.reminderTime) {
NotificationManager.reschedule(for: habit)
}
}
.padding()
}
.navigationTitle(habit.name)
.navigationBarTitleDisplayMode(.inline)
}
private var color: Color { Color(hex: habit.colorHex) }
private var header: some View {
VStack(spacing: 8) {
Image(systemName: habit.symbolName)
.font(.system(size: 44))
.foregroundStyle(color)
.frame(width: 88, height: 88)
.background(color.opacity(0.15), in: Circle())
Text(habit.name)
.font(.title2.bold())
}
}
}
private struct StatTile: View {
let value: String
let label: String
let systemImage: String
let color: Color
var body: some View {
VStack(spacing: 6) {
Image(systemName: systemImage)
.foregroundStyle(color)
Text(value)
.font(.title3.bold())
Text(label)
.font(.caption)
.foregroundStyle(.secondary)
}
.frame(maxWidth: .infinity)
.padding(.vertical, 16)
.background(.background.secondary, in: RoundedRectangle(cornerRadius: 16))
}
}
#Preview {
NavigationStack {
HabitDetailView(habit: Habit(name: "Wasser trinken", symbolName: "drop.fill", colorHex: "#007AFF"))
}
.modelContainer(for: [Habit.self, HabitEntry.self], inMemory: true)
}