import SwiftUI /// Tab root for "Konto" (see `App/MainTabView.swift`, which references /// `SettingsView()` with a zero-arg initializer as its third tab). Wrapped in /// its own `NavigationStack` — every push (folders, change password, delete /// account) and the Pro-upgrade sheet originate from here. struct SettingsView: View { @EnvironmentObject private var appState: AppState @State private var showPaywall = false var body: some View { NavigationStack { Form { profileSection foldersSection accountSection } .zenithListBackground() .navigationTitle("Konto") .sheet(isPresented: $showPaywall) { PaywallView() } } } // MARK: - Profil @ViewBuilder private var profileSection: some View { Section { if let user = appState.currentUser { VStack(alignment: .leading, spacing: 4) { Text(user.name?.isEmpty == false ? user.name! : "Unbenannt") .zenithHeadlineMdStyle() if let email = user.email { Text(email) .zenithBodySmStyle() } } .padding(.vertical, ZenithSpacing.unit) .listRowBackground(Color.zenithSurface) .listRowSeparatorTint(Color.zenithBorder) if user.isPro { proStatusRow(for: user) .listRowBackground(Color.zenithSurface) .listRowSeparatorTint(Color.zenithBorder) } else { freeStatusRow .listRowBackground(Color.zenithSurface) .listRowSeparatorTint(Color.zenithBorder) } } } } private func proStatusRow(for user: User) -> some View { VStack(alignment: .leading, spacing: ZenithSpacing.xs) { HStack(spacing: ZenithSpacing.xs) { Text("PRO") .zenithLabelCapsStyle(color: .white) .padding(.horizontal, 8) .padding(.vertical, 3) .background(Color.zenithBlack) ZenithChip(text: planDisplayName(user.plan)) } if let expiresAt = user.expiresAt, let date = ISO8601.parse(expiresAt) { let formatted = date.formatted(date: .abbreviated, time: .omitted) Text(user.cancelAtPeriodEnd ? "Läuft aus am \(formatted)" : "Verlängert sich am \(formatted)") .zenithLabelMdStyle(color: .zenithMuted) } } .padding(.vertical, ZenithSpacing.unit) } private var freeStatusRow: some View { VStack(alignment: .leading, spacing: ZenithSpacing.xs) { Text("Kostenlos") .zenithBodyStyle(color: .zenithMuted) Button("Auf Pro upgraden") { showPaywall = true } .buttonStyle(.zenithPrimary) } .padding(.vertical, ZenithSpacing.unit) } private func planDisplayName(_ plan: String) -> String { switch plan { case "weekly": return "Wochen-Pass" case "annual": return "Jahres-Pass" case "lifetime": return "Lifetime" case "free": return "Kostenlos" default: return plan.capitalized } } // MARK: - Ordner private var foldersSection: some View { Section { NavigationLink { ProjectsListView() } label: { Label { Text("Ordner verwalten").zenithBodyStyle() } icon: { Image(systemName: "folder").foregroundStyle(Color.zenithMuted) } } .listRowBackground(Color.zenithSurface) .listRowSeparatorTint(Color.zenithBorder) } header: { Text("Ordner").zenithLabelCapsStyle() } } // MARK: - Konto private var accountSection: some View { Section { NavigationLink { ChangePasswordView() } label: { Label { Text("Passwort ändern").zenithBodyStyle() } icon: { Image(systemName: "lock").foregroundStyle(Color.zenithMuted) } } .listRowBackground(Color.zenithSurface) .listRowSeparatorTint(Color.zenithBorder) Button { Task { await appState.logout() } } label: { Label { Text("Abmelden") } icon: { Image(systemName: "arrow.backward.square") } } .buttonStyle(.zenithPlain) .listRowBackground(Color.zenithSurface) .listRowSeparatorTint(Color.zenithBorder) NavigationLink { DeleteAccountView() } label: { Label { Text("Konto löschen").zenithBodyStyle(color: .zenithError) } icon: { Image(systemName: "trash").foregroundStyle(Color.zenithError) } } .listRowBackground(Color.zenithSurface) .listRowSeparatorTint(Color.zenithBorder) } header: { Text("Konto").zenithLabelCapsStyle() } } }