Skip to content

Instantly share code, notes, and snippets.

@mottzi
Created August 25, 2025 14:55
Show Gist options
  • Select an option

  • Save mottzi/e85a5ed1ddfa38c6c80366362bb59fba to your computer and use it in GitHub Desktop.

Select an option

Save mottzi/e85a5ed1ddfa38c6c80366362bb59fba to your computer and use it in GitHub Desktop.
extension Habit {
// .sheet() on line 47
struct Dashboard: View {
@Namespace private var habitTransition
@Environment(\.colorScheme) var colorScheme
@Environment(\.scenePhase) private var scenePhase
@Environment(Habit.Dashboard.Manager.self) var dashboardManager
var cardManagers: [Card.Manager] { dashboardManager.cardManagers }
@State private var presentAddSheet = false
var body: some View {
let _ = print("Habit.Dashboard: 🔄 \(cardManagers.count) Habit.Cards")
// let _ = Self._printChanges()
NavigationStack {
ScrollView {
LazyVGrid(columns: columns, spacing: 16) {
ForEach(cardManagers.enumerated, id: \.element.habit.id) { index, cardManager in
NavigationLink {
Habit.Card.DetailView()
.environment(cardManager)
.environment(dashboardManager)
.if(dashboardManager.useZoomTransition) { view in
view.navigationTransition(.zoom(sourceID: cardManager.habit.id, in: habitTransition))
}
} label: {
Habit.Card()
.environment(cardManager)
.environment(\.cardOffset, index)
.if(dashboardManager.useZoomTransition) { view in
view.matchedTransitionSource(id: cardManager.habit.id, in: habitTransition)
}
}
.buttonStyle(.plain)
}
}
.padding(16)
.safeAreaInset(edge: .bottom) { debugButton }
}
.navigationTitle("Habit Rabbit")
.animation(.default, value: cardManagers.count)
.overlay(alignment: .bottomTrailing) { addHabitButton }
.toolbar { modePicker }
.sheet(isPresented: $presentAddSheet) { AddHabitSheet() }
}
.tint(colorScheme == .dark ? .white : .black)
.onCalendarDayChanged { dashboardManager.setLastDay(to: .now) }
}
private let columns = [
GridItem(.flexible(), spacing: 16),
GridItem(.flexible(), spacing: 16),
]
}
}
extension Habit.Dashboard {
struct AddHabitSheet: View {
@Environment(\.colorScheme) private var colorScheme
@Environment(\.dismiss) private var dismiss
@State private var habitName = ""
@State private var habitUnit = ""
var body: some View {
NavigationStack {
VStack(spacing: 14) {
VStack(alignment: .leading, spacing: 8) {
Text("Habit Name")
.font(.headline)
.fontWeight(.semibold)
.foregroundStyle(.secondary)
TextField("Stretching", text: $habitName)
.textFieldStyle(.plain)
.font(.title)
.fontWeight(.semibold)
}
Divider()
VStack(alignment: .leading, spacing: 8) {
Text("Unit")
.font(.headline)
.fontWeight(.semibold)
.foregroundStyle(.secondary)
TextField("Sessions", text: $habitUnit)
.textFieldStyle(.plain)
.font(.title)
.fontWeight(.semibold)
}
Spacer()
}
.navigationBarTitleDisplayMode(.inline)
.padding()
.padding(.horizontal)
.toolbar {
ToolbarItem(placement: .topBarLeading) { closeButton }
ToolbarItem(placement: .topBarTrailing) { addButton }
}
}
.presentationBackground(.thickMaterial)
.presentationDetents([.medium])
.presentationDragIndicator(.visible)
}
private var closeButton: some View {
Button(role: .cancel) {
dismiss()
} label: {
Text("Cancel")
.fontWeight(.semibold)
}
.tint(.red)
}
private var addButton: some View {
Button(role: .none) {
dismiss()
} label: {
Text("Add Habit")
.fontWeight(.semibold)
}
.buttonStyle(.borderedProminent)
.buttonBorderShape(.capsule)
.tint(.blue)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment