Deck-Liste mit Web-Parität: alle eigenen Decks aus cardecky-api, Card-/Due-Counts pro Deck (Web-Pattern: separate Calls), Pull-to- Refresh, Offline-Read via SwiftData, Inbox-Banner für Marketplace- Forks. - Deck-Codable-DTO mit snake_case-CodingKeys (DeckCategory, DeckVisibility, FsrsSettings) - ISO8601-Date-Decoder mit Fractional-Seconds-Toleranz - CardsAPI.listDecks() + cardCount() + dueCount() - CachedDeck SwiftData-Model mit lastFetchedAt - DeckListStore (API + Cache, paralleles Counts-Fetching via TaskGroup) - DeckListView mit forest-Theme, deck.color-Streifen, Inbox-Banner - AccountView mit Sign-out - DashboardView durch DeckListView ersetzt - 6 Unit-Tests + 1 UI-Test grün Phasen-Plan: mana/docs/playbooks/CARDS_NATIVE_GREENFIELD.md Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
49 lines
1.4 KiB
Swift
49 lines
1.4 KiB
Swift
import ManaCore
|
|
import SwiftUI
|
|
|
|
struct AccountView: View {
|
|
@Environment(AuthClient.self) private var auth
|
|
|
|
var body: some View {
|
|
ZStack {
|
|
CardsTheme.background.ignoresSafeArea()
|
|
VStack(spacing: 24) {
|
|
Image(systemName: "person.crop.circle.fill")
|
|
.resizable()
|
|
.frame(width: 80, height: 80)
|
|
.foregroundStyle(CardsTheme.primary)
|
|
|
|
if let email = auth.currentEmail {
|
|
Text(email)
|
|
.font(.headline)
|
|
.foregroundStyle(CardsTheme.foreground)
|
|
}
|
|
|
|
Spacer()
|
|
|
|
Button(role: .destructive) {
|
|
Task { await auth.signOut() }
|
|
} label: {
|
|
Text("Abmelden")
|
|
.frame(maxWidth: .infinity)
|
|
.padding(.vertical, 12)
|
|
.background(CardsTheme.error.opacity(0.1), in: RoundedRectangle(cornerRadius: 8))
|
|
.foregroundStyle(CardsTheme.error)
|
|
}
|
|
.padding(.horizontal, 32)
|
|
}
|
|
.padding(.top, 48)
|
|
}
|
|
.navigationTitle("Account")
|
|
#if os(iOS)
|
|
.navigationBarTitleDisplayMode(.inline)
|
|
#endif
|
|
}
|
|
}
|
|
|
|
#Preview {
|
|
NavigationStack {
|
|
AccountView()
|
|
.environment(AuthClient(config: AppConfig.manaAppConfig))
|
|
}
|
|
}
|