polish iOS study flow

This commit is contained in:
2026-04-09 15:51:03 +02:00
parent 5c0aa9542a
commit 0cfd847d62
16 changed files with 508 additions and 94 deletions
@@ -1,7 +1,90 @@
import SwiftUI
struct SelectionOption: Identifiable, Equatable {
let id: String
let title: String
let subtitle: String
let odds: String
}
struct SelectionView: View {
let statusText: String
let options: [SelectionOption]
let selectedOptionID: String?
let isLocked: Bool
let confirmTitle: String
let onSelect: (SelectionOption) -> Void
let onConfirm: () -> Void
var body: some View {
Text("Selection scaffold")
VStack(alignment: .leading, spacing: HermesTheme.sectionSpacing) {
statusBadge
VStack(spacing: 10) {
ForEach(options) { option in
optionButton(option)
}
}
Button {
onConfirm()
} label: {
Text(confirmTitle)
}
.buttonStyle(HermesPrimaryButtonStyle())
.disabled(isLocked || selectedOptionID == nil)
}
}
private var statusBadge: some View {
HStack(spacing: 8) {
Image(systemName: isLocked ? "lock.fill" : "hand.tap.fill")
.font(.caption.weight(.semibold))
Text(statusText)
.font(.caption.weight(.semibold))
}
.foregroundStyle(isLocked ? HermesTheme.warning : HermesTheme.textSecondary)
.padding(.horizontal, 12)
.padding(.vertical, 8)
.background((isLocked ? HermesTheme.warning : HermesTheme.accent).opacity(0.16))
.clipShape(Capsule())
}
private func optionButton(_ option: SelectionOption) -> some View {
let selected = selectedOptionID == option.id
return Button {
onSelect(option)
} label: {
HStack(alignment: .center, spacing: 14) {
VStack(alignment: .leading, spacing: 4) {
Text(option.title)
.font(.headline.weight(.semibold))
Text(option.subtitle)
.font(.caption)
.foregroundStyle(selected ? HermesTheme.background.opacity(0.68) : HermesTheme.textSecondary)
}
Spacer(minLength: 8)
VStack(alignment: .trailing, spacing: 4) {
Text(option.odds)
.font(.headline.weight(.bold))
Image(systemName: selected ? "checkmark.circle.fill" : "circle")
.font(.subheadline.weight(.semibold))
}
}
.padding(.horizontal, 16)
.padding(.vertical, 14)
.foregroundStyle(selected ? HermesTheme.background : HermesTheme.textPrimary)
.background(selected ? HermesTheme.accent : HermesTheme.surfaceElevated)
.overlay(
RoundedRectangle(cornerRadius: HermesTheme.insetRadius, style: .continuous)
.stroke(selected ? HermesTheme.accent : HermesTheme.accent.opacity(0.14), lineWidth: 1)
)
.clipShape(RoundedRectangle(cornerRadius: HermesTheme.insetRadius, style: .continuous))
}
.buttonStyle(.plain)
.disabled(isLocked)
}
}