import ManaCore import SwiftData import SwiftUI struct PendingShareRoute: Hashable { let share: PendingShare } /// User wählt Ziel-Deck, optional Back-Text. Submit → CardCreate /// via API, anschließend wird die PendingShare aus dem Store entfernt. struct PendingShareConsumeView: View { let share: PendingShare let onDone: () -> Void @Environment(AuthClient.self) private var auth @Environment(\.dismiss) private var dismiss @Query(sort: \CachedDeck.updatedAt, order: .reverse) private var decks: [CachedDeck] @State private var selectedDeckId: String? @State private var front: String @State private var back: String = "" @State private var isSubmitting = false @State private var errorMessage: String? init(share: PendingShare, onDone: @escaping () -> Void) { self.share = share self.onDone = onDone _front = State(initialValue: share.text) } var body: some View { Form { Section("Ziel-Deck") { if decks.isEmpty { Text("Erst ein Deck erstellen.") .foregroundStyle(CardsTheme.mutedForeground) } else { Picker("Deck", selection: $selectedDeckId) { Text("Wählen …").tag(String?.none) ForEach(decks) { deck in Text(deck.name).tag(String?.some(deck.id)) } } } } Section("Vorderseite") { TextField("Front", text: $front, axis: .vertical) .lineLimit(2 ... 6) } Section("Rückseite") { TextField("Back (optional, default: Quell-URL)", text: $back, axis: .vertical) .lineLimit(2 ... 4) } if let sourceURL = share.sourceURL { Section("Quelle") { Text(sourceURL) .font(.caption) .foregroundStyle(CardsTheme.mutedForeground) } } if let errorMessage { Section { Text(errorMessage) .font(.footnote) .foregroundStyle(CardsTheme.error) } } } .navigationTitle("Geteilten Inhalt speichern") #if os(iOS) .navigationBarTitleDisplayMode(.inline) #endif .toolbar { ToolbarItem(placement: .cancellationAction) { Button("Verwerfen", role: .destructive) { PendingShareStore.remove(id: share.id) onDone() dismiss() } } ToolbarItem(placement: .confirmationAction) { Button("Speichern") { Task { await submit() } } .disabled(selectedDeckId == nil || front.trimmed.isEmpty || isSubmitting) } } } private func submit() async { guard let deckId = selectedDeckId else { return } isSubmitting = true errorMessage = nil defer { isSubmitting = false } let backText = back.trimmed.isEmpty ? (share.sourceURL ?? "—") : back.trimmed let api = CardsAPI(auth: auth) let body = CardCreateBody( deckId: deckId, type: .basic, fields: CardFieldsBuilder.basic(front: front.trimmed, back: backText), mediaRefs: nil ) do { _ = try await api.createCard(body) onDone() dismiss() } catch { errorMessage = (error as? LocalizedError)?.errorDescription ?? String(describing: error) } } } private extension String { var trimmed: String { trimmingCharacters(in: .whitespacesAndNewlines) } }