import SwiftUI struct BookCardView: View { let title: String let author: String let coverURL: URL? let status: ReadingStatus let progress: Double? var body: some View { VStack(alignment: .leading, spacing: Theme.Spacing.small) { AsyncImage(url: coverURL) { phase in switch phase { case .success(let image): image.resizable().scaledToFill() default: ZStack { RoundedRectangle(cornerRadius: Theme.Radius.image) .fill(Color.gray.opacity(0.22)) Image(systemName: "book.closed") .font(.title2) .foregroundStyle(.secondary) } } } .frame(height: 170) .clipShape(RoundedRectangle(cornerRadius: Theme.Radius.image, style: .continuous)) Text(title) .font(.headline) .lineLimit(2) .minimumScaleFactor(0.85) Text(author.isEmpty ? "Unknown Author" : author) .font(.subheadline) .foregroundStyle(.secondary) .lineLimit(1) HStack(spacing: Theme.Spacing.xSmall) { Image(systemName: status.symbol) Text(status.title) .lineLimit(1) } .font(.caption.weight(.semibold)) .padding(.horizontal, 8) .padding(.vertical, 5) .foregroundStyle(status.color) .background(status.color.opacity(0.14), in: Capsule()) if let progress, status == .reading { ProgressView(value: progress) .tint(status.color) .animation(.easeOut(duration: 0.35), value: progress) .accessibilityLabel("Reading progress") .accessibilityValue("\(Int(progress * 100)) percent") } } .padding(Theme.Spacing.medium) .background(.background, in: RoundedRectangle(cornerRadius: Theme.Radius.card, style: .continuous)) .overlay { RoundedRectangle(cornerRadius: Theme.Radius.card, style: .continuous) .stroke(Color.primary.opacity(0.06), lineWidth: 1) } .shadow(color: Theme.Shadow.card.color, radius: Theme.Shadow.card.radius, y: Theme.Shadow.card.y) .accessibilityElement(children: .combine) .accessibilityLabel("\(title), \(author), \(status.title)") } }