import SwiftUI /// CSV-Import-Form für den `.csv`-Sub-Modus in `DeckEditorView`. Zeigt /// File-Picker-Button, Deck-Namens-Feld und eine Preview-Liste der /// erkannten Karten. /// /// State (Datei-Picker-Bool, geparste Rows, Deck-Name) lebt im Parent — /// dieser View arbeitet nur über `@Binding`. struct CSVImportFormSections: View { @Binding var rows: [CSVRow] @Binding var deckName: String @Binding var showImporter: Bool var body: some View { Section { Button { showImporter = true } label: { Label(rows.isEmpty ? "CSV-Datei wählen" : "Andere Datei wählen", systemImage: "doc.text") } } header: { Text("Datei") } footer: { Text("Format pro Zeile: vorne,hinten,typ. Typ-Spalte optional (Default basic).") } if !rows.isEmpty { Section("Deck-Name") { TextField("Deck-Name", text: $deckName) .textInputAutocapitalization(.sentences) } Section { preview } header: { Text("Vorschau (\(rows.count) Karten)") } footer: { Text("Image-Occlusion und Audio-Cards werden im CSV-Import übersprungen — die brauchen Datei-Uploads.") } } } @ViewBuilder private var preview: some View { let visible = rows.prefix(8) ForEach(Array(visible.enumerated()), id: \.offset) { _, row in VStack(alignment: .leading, spacing: 4) { Text(row.front) .font(.subheadline) .lineLimit(2) .foregroundStyle(CardsTheme.foreground) Text(row.back) .font(.caption) .lineLimit(2) .foregroundStyle(CardsTheme.mutedForeground) if row.type != .basic { Text(typeLabel(row.type)) .font(.caption2) .foregroundStyle(CardsTheme.primary) } } .padding(.vertical, 2) } if rows.count > visible.count { Text("… und \(rows.count - visible.count) weitere") .font(.caption) .foregroundStyle(CardsTheme.mutedForeground) } } private func typeLabel(_ type: CardType) -> String { switch type { case .basic: "Einfach" case .basicReverse: "Beidseitig" case .cloze: "Lückentext" case .typing: "Eintippen" case .multipleChoice: "Multiple Choice" case .imageOcclusion: "Bild-Verdeckung (übersprungen)" case .audioFront: "Audio (übersprungen)" } } }