BusinessCard/BusinessCardWatch/Views/WatchContentView.swift

128 lines
4.7 KiB
Swift

import SwiftUI
struct WatchContentView: View {
@Environment(WatchCardStore.self) private var cardStore
private let qrService = WatchQRCodeService()
var body: some View {
ScrollView {
VStack(spacing: WatchDesign.Spacing.large) {
if let card = cardStore.defaultCard {
WatchQRCodeCardView(card: card, qrService: qrService)
} else if cardStore.cards.isEmpty {
WatchEmptyStateView()
}
if !cardStore.cards.isEmpty {
WatchCardPickerView()
}
}
.padding(WatchDesign.Spacing.medium)
}
.background(Color.WatchPalette.background)
.onAppear {
cardStore.loadCards()
}
}
}
private struct WatchEmptyStateView: View {
var body: some View {
VStack(spacing: WatchDesign.Spacing.medium) {
Image(systemName: "rectangle.stack")
.font(.title)
.foregroundStyle(Color.WatchPalette.muted)
Text("No Cards")
.font(.headline)
.foregroundStyle(Color.WatchPalette.text)
Text("Open the iPhone app to create cards")
.font(.caption)
.foregroundStyle(Color.WatchPalette.muted)
.multilineTextAlignment(.center)
}
.padding(WatchDesign.Spacing.large)
}
}
private struct WatchQRCodeCardView: View {
let card: WatchCard
let qrService: WatchQRCodeService
var body: some View {
VStack(spacing: WatchDesign.Spacing.small) {
Text("Default Card")
.font(.headline)
.foregroundStyle(Color.WatchPalette.text)
if let image = qrService.qrCode(from: card.vCardPayload) {
Image(decorative: image, scale: 1)
.resizable()
.interpolation(.none)
.scaledToFit()
.frame(width: WatchDesign.Size.qrSize, height: WatchDesign.Size.qrSize)
.padding(WatchDesign.Spacing.small)
.background(Color.WatchPalette.card)
.clipShape(.rect(cornerRadius: WatchDesign.CornerRadius.large))
}
Text(card.displayName)
.font(.subheadline)
.foregroundStyle(Color.WatchPalette.text)
Text(card.role)
.font(.caption)
.foregroundStyle(Color.WatchPalette.muted)
}
.padding(WatchDesign.Spacing.medium)
.background(Color.WatchPalette.card)
.clipShape(.rect(cornerRadius: WatchDesign.CornerRadius.large))
.accessibilityElement(children: .ignore)
.accessibilityLabel(String(localized: "Default card QR code"))
.accessibilityValue("\(card.displayName), \(card.role)")
}
}
private struct WatchCardPickerView: View {
@Environment(WatchCardStore.self) private var cardStore
var body: some View {
VStack(alignment: .leading, spacing: WatchDesign.Spacing.small) {
Text("Choose default")
.font(.headline)
.foregroundStyle(Color.WatchPalette.text)
ForEach(cardStore.cards) { card in
Button {
cardStore.setDefault(card)
} label: {
HStack {
Text(card.displayName)
.foregroundStyle(Color.WatchPalette.text)
Spacer()
if card.id == cardStore.defaultCardID {
Image(systemName: "checkmark")
.foregroundStyle(Color.WatchPalette.accent)
}
}
}
.buttonStyle(.plain)
.padding(.vertical, WatchDesign.Spacing.small)
.padding(.horizontal, WatchDesign.Spacing.medium)
.frame(maxWidth: .infinity, alignment: .leading)
.background(card.id == cardStore.defaultCardID ? Color.WatchPalette.accent.opacity(WatchDesign.Opacity.strong) : Color.WatchPalette.card)
.clipShape(.rect(cornerRadius: WatchDesign.CornerRadius.medium))
.accessibilityValue(card.id == cardStore.defaultCardID ? String(localized: "Selected") : String(localized: "Not selected"))
}
}
.padding(WatchDesign.Spacing.medium)
.background(Color.WatchPalette.card.opacity(WatchDesign.Opacity.hint))
.clipShape(.rect(cornerRadius: WatchDesign.CornerRadius.large))
}
}
#Preview {
WatchContentView()
.environment(WatchCardStore())
}