Files
WorterBuch/WorterBuch/FlashcardCardView.swift

115 lines
4.2 KiB
Swift

//
// FlashcardCardView.swift
// WorterBuch
//
import SwiftUI
import PencilKit
struct FlashcardCardView: View {
let entry: VocabularyEntry
let showAnswer: Bool
@State private var explanationRevealed: Bool = false
var body: some View {
VStack(alignment: .leading, spacing: 20) {
// English section (always visible)
VStack(alignment: .leading, spacing: 8) {
Text("English")
.font(.caption)
.foregroundColor(.secondary)
.textCase(.uppercase)
Text(entry.englishTranslationText ?? "")
.font(.title)
.fontWeight(.semibold)
}
.frame(maxWidth: .infinity, alignment: .leading)
Divider()
// Explanation section (always visible but with spoiler effect)
VStack(alignment: .leading, spacing: 8) {
Text("Explanation")
.font(.caption)
.foregroundColor(.secondary)
.textCase(.uppercase)
if let explanation = entry.germanExplanationText, !explanation.isEmpty {
Button(action: {
explanationRevealed = true
}) {
Text(explanation)
.font(.body)
.foregroundColor(.primary)
.frame(maxWidth: .infinity, alignment: .leading)
.blur(radius: explanationRevealed ? 0 : 8)
.disabled(explanationRevealed)
}
.buttonStyle(.plain)
} else {
Text("No explanation provided")
.font(.body)
.foregroundColor(.secondary)
.italic()
}
}
.frame(maxWidth: .infinity, alignment: .leading)
if showAnswer {
Divider()
// German section with handwriting and text
VStack(alignment: .leading, spacing: 12) {
Text("German Word")
.font(.caption)
.foregroundColor(.secondary)
.textCase(.uppercase)
// Handwriting drawing (prominent)
if !entry.germanWordPKDrawing.bounds.isEmpty {
Image(uiImage: entry.germanWordPKDrawing.image(
from: entry.germanWordPKDrawing.bounds,
scale: 2.0
))
.resizable()
.aspectRatio(contentMode: .fit)
.frame(maxHeight: 120)
.frame(maxWidth: .infinity)
.padding()
.background(Color(.systemGray6))
.cornerRadius(12)
}
// Transcribed text
if let germanText = entry.germanWordText, !germanText.isEmpty {
Text(germanText)
.font(.title2)
.fontWeight(.medium)
.frame(maxWidth: .infinity, alignment: .center)
.padding(.vertical, 8)
}
}
.frame(maxWidth: .infinity, alignment: .leading)
.transition(.asymmetric(
insertion: .scale(scale: 0.8).combined(with: .opacity),
removal: .opacity
))
}
}
.padding(24)
.frame(maxWidth: 600)
.background(Color(.systemBackground))
.cornerRadius(16)
.shadow(color: .black.opacity(0.1), radius: 10, x: 0, y: 4)
.overlay(
RoundedRectangle(cornerRadius: 16)
.stroke(Color.blue.opacity(0.2), lineWidth: 2)
)
.onChange(of: showAnswer) { _ in
// Reset explanation reveal when moving to next card
explanationRevealed = false
}
}
}