- project.yml mit Bundle ev.mana.zitare + Widget + ShareExt-Targets - ManaSwiftCore (ManaCore + ManaTokens) + ManaSwiftUI (ManaAuthUI) als Package-Dependencies via path: - Pure SwiftUI für Native-Surfaces, WKWebView nur für Lese-Tabs (Hybrid-Sonderfall vs cards/memoro/manaspur, dokumentiert im Playbook ZITARE_NATIVE_GREENFIELD.md) - Theme: paper-Variant aus @mana/themes - ZitareAPI.healthCheck via direct URLSession (öffentlicher Endpoint, kein AuthenticatedTransport-Gate) - 6/6 AppConfigTests + 1/1 UI-Smoke grün auf iPhone 16e Simulator - Live: zitare-api.mana.how/healthz → HTTP/2 200 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
106 lines
3.1 KiB
Swift
106 lines
3.1 KiB
Swift
import ManaCore
|
|
import SwiftUI
|
|
|
|
/// Phase ζ-0 minimal: zeigt Auth-Status und Healthz-Probe-Ergebnis.
|
|
/// Phase ζ-3 erweitert um ManaAuthUI-Login-Sheet und Submission-
|
|
/// History-Link (via WebShell auf `zitare.mana.how/me`).
|
|
struct AccountView: View {
|
|
@Environment(AuthClient.self) private var auth
|
|
let healthStatus: HealthStatus
|
|
|
|
var body: some View {
|
|
ScrollView {
|
|
VStack(spacing: 24) {
|
|
header
|
|
|
|
statusCard
|
|
|
|
Spacer(minLength: 32)
|
|
|
|
aboutCard
|
|
}
|
|
.padding()
|
|
}
|
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
|
.background(ZitareTheme.background)
|
|
}
|
|
|
|
private var header: some View {
|
|
VStack(spacing: 8) {
|
|
Image(systemName: "quote.opening")
|
|
.font(.system(size: 48))
|
|
.foregroundStyle(ZitareTheme.primary)
|
|
Text("Zitare")
|
|
.font(.largeTitle)
|
|
.fontWeight(.semibold)
|
|
Text("Öffentlicher Zitat-Korpus von mana e.V.")
|
|
.font(.callout)
|
|
.foregroundStyle(ZitareTheme.mutedForeground)
|
|
.multilineTextAlignment(.center)
|
|
}
|
|
.padding(.top, 32)
|
|
}
|
|
|
|
private var statusCard: some View {
|
|
VStack(alignment: .leading, spacing: 12) {
|
|
row("Auth", value: authStatusLabel)
|
|
Divider()
|
|
row("API", value: healthLabel)
|
|
}
|
|
.padding()
|
|
.background(ZitareTheme.surface)
|
|
.clipShape(RoundedRectangle(cornerRadius: 12))
|
|
.overlay(
|
|
RoundedRectangle(cornerRadius: 12)
|
|
.stroke(ZitareTheme.border, lineWidth: 1)
|
|
)
|
|
}
|
|
|
|
private var aboutCard: some View {
|
|
VStack(alignment: .leading, spacing: 8) {
|
|
Text("Phase ζ-0 — Setup")
|
|
.font(.caption)
|
|
.foregroundStyle(ZitareTheme.mutedForeground)
|
|
Text(
|
|
"Diese App ist noch im Aufbau. Web-App live auf "
|
|
+ "zitare.com und zitare.mana.how. "
|
|
+ "Plan in mana/docs/playbooks/ZITARE_NATIVE_GREENFIELD.md."
|
|
)
|
|
.font(.footnote)
|
|
.foregroundStyle(ZitareTheme.foreground)
|
|
}
|
|
.padding()
|
|
.frame(maxWidth: .infinity, alignment: .leading)
|
|
}
|
|
|
|
private func row(_ label: String, value: String) -> some View {
|
|
HStack {
|
|
Text(label)
|
|
.foregroundStyle(ZitareTheme.mutedForeground)
|
|
Spacer()
|
|
Text(value)
|
|
.foregroundStyle(ZitareTheme.foreground)
|
|
.fontWeight(.medium)
|
|
}
|
|
}
|
|
|
|
private var authStatusLabel: String {
|
|
switch auth.status {
|
|
case .unknown: "—"
|
|
case .signedOut: "Nicht eingeloggt"
|
|
case .guest: "Gast"
|
|
case .signingIn: "Login läuft …"
|
|
case .twoFactorRequired: "2FA erforderlich"
|
|
case let .signedIn(email): email
|
|
case .error: "Fehler"
|
|
}
|
|
}
|
|
|
|
private var healthLabel: String {
|
|
switch healthStatus {
|
|
case .unknown: "—"
|
|
case .ok: "OK"
|
|
case .down: "nicht erreichbar"
|
|
}
|
|
}
|
|
}
|