import SwiftUI func wizardStepTitle(_ step: Int) -> String { let titles = [ L10n.t("wizard.step.title.match"), L10n.t("wizard.step.title.transmission"), L10n.t("wizard.step.title.network") ] return titles[min(max(step, 1), 3) - 1] } struct WizardStepIndicator: View { let currentStep: Int var body: some View { HStack(spacing: 6) { ForEach(1...3, id: \.self) { step in RoundedRectangle(cornerRadius: 2) .fill(step <= currentStep ? MatchColors.primaryRed : MatchColors.surfaceElevated) .frame(height: 4) } } .padding(.horizontal, 20) .padding(.vertical, 12) } } struct WizardFooterButtons: View { var showBack: Bool = true let onBack: () -> Void let forwardLabel: String var forwardLoading: Bool = false let onForward: () -> Void var body: some View { HStack(spacing: 12) { if showBack { MatchSecondaryButton(label: L10n.t("wizard.action.back"), action: onBack) .frame(maxWidth: .infinity) .accessibilityIdentifier("wizard.back") } MatchPrimaryButton(label: forwardLabel, action: onForward, loading: forwardLoading) .frame(maxWidth: .infinity) .accessibilityIdentifier("wizard.next") } } } struct WizardOutlinedField: View { let label: String @Binding var text: String var body: some View { VStack(alignment: .leading, spacing: 6) { Text(label) .font(MatchTypography.bodyMedium) .foregroundStyle(MatchColors.textSecondary) TextField("", text: $text) .padding(12) .overlay( RoundedRectangle(cornerRadius: 8) .stroke(MatchColors.outline, lineWidth: 1) ) } } } struct WizardReadOnlyField: View { let label: String let value: String var body: some View { VStack(alignment: .leading, spacing: 4) { Text(label).font(MatchTypography.bodyMedium) Text(value).font(MatchTypography.titleMedium) } .frame(maxWidth: .infinity, alignment: .leading) .padding(14) .background(MatchColors.surfaceElevated, in: RoundedRectangle(cornerRadius: 10)) } } struct WizardChoiceButton: View { let label: String let selected: Bool let action: () -> Void var body: some View { Group { if selected { MatchPrimaryButton(label: label, action: action) } else { MatchSecondaryButton(label: label, action: action) } } } } struct MetricCard: View { let label: String let value: String var highlight: Bool = false var body: some View { VStack(spacing: 4) { Text(label) .font(MatchTypography.bodyMedium) .foregroundStyle(MatchColors.textSecondary) Text(value) .font(MatchTypography.titleMedium) .foregroundStyle(highlight ? MatchColors.successGreen : .white) } .frame(maxWidth: .infinity) .padding(12) .background( highlight ? MatchColors.successGreen.opacity(0.12) : MatchColors.surfaceElevated, in: RoundedRectangle(cornerRadius: 10) ) } } struct WizardPlatformCard: View { let title: String let subtitle: String? let selected: Bool var enabled: Bool = true var badge: String? let onClick: () -> Void var body: some View { Button(action: onClick) { HStack(alignment: .center, spacing: 12) { Text(selected ? "●" : "○") .foregroundStyle(selected ? MatchColors.primaryRed : MatchColors.textSecondary) VStack(alignment: .leading, spacing: 4) { Text(title) .font(MatchTypography.titleMedium) .foregroundStyle(.white.opacity(enabled ? 1 : 0.55)) if let subtitle { Text(subtitle) .font(MatchTypography.bodyMedium) .foregroundStyle(MatchColors.textSecondary.opacity(enabled ? 1 : 0.55)) } } Spacer(minLength: 8) if let badge { Text(badge) .font(MatchTypography.labelLarge) .foregroundStyle(MatchColors.textSecondary) .padding(.horizontal, 8) .padding(.vertical, 4) .background(MatchColors.surface, in: RoundedRectangle(cornerRadius: 6)) } } .padding(14) .background( selected ? MatchColors.primaryRed.opacity(0.15) : MatchColors.surfaceElevated, in: RoundedRectangle(cornerRadius: 10) ) .overlay( RoundedRectangle(cornerRadius: 10) .stroke(selected ? MatchColors.primaryRed : .clear, lineWidth: 1) ) .frame(maxWidth: .infinity, alignment: .leading) } .buttonStyle(.plain) .disabled(!enabled) .opacity(enabled ? 1 : 0.55) .frame(maxWidth: .infinity) } }