69 lines
2.5 KiB
Swift
69 lines
2.5 KiB
Swift
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)")
|
|
}
|
|
}
|