New framework: - AccessibilityLabels.swift: centralized A11y struct with VoiceOver strings - AccessibilityModifiers.swift: reusable .a11yHeader, .a11yDecorative, .a11yButton, .a11yCard, .a11yStatValue View extensions Shared components: decorative elements hidden, stat views combined, status/priority badges labeled, error views announced, empty states grouped Cards: ResidenceCard, TaskCard, DynamicTaskCard, ContractorCard, DocumentCard, WarrantyCard — all grouped with combined labels, chevrons hidden, action buttons labeled Main screens: Login, Register, Residences, Tasks, Contractors, Documents — toolbar buttons labeled, section headers marked, form field hints added Onboarding: all 10 views — header traits, button hints, task selection state, progress indicator, decorative backgrounds hidden Profile/Subscription: toggle hints, theme selection state, feature comparison table accessibility, subscription button labels iOS build verified: BUILD SUCCEEDED
144 lines
5.0 KiB
Swift
144 lines
5.0 KiB
Swift
import SwiftUI
|
|
import ComposeApp
|
|
|
|
// MARK: - Share Code Card
|
|
struct ShareCodeCard: View {
|
|
let shareCode: ShareCodeResponse?
|
|
let isGeneratingCode: Bool
|
|
let isGeneratingPackage: Bool
|
|
let onGenerateCode: () -> Void
|
|
let onEasyShare: () -> Void
|
|
|
|
var body: some View {
|
|
VStack(alignment: .leading, spacing: 16) {
|
|
// Header
|
|
HStack {
|
|
Image(systemName: "person.badge.plus")
|
|
.font(.title2)
|
|
.foregroundColor(Color.appPrimary)
|
|
Text("Invite Others")
|
|
.font(.headline)
|
|
.foregroundColor(Color.appTextPrimary)
|
|
}
|
|
|
|
// Easy Share Section (on top - recommended method)
|
|
VStack(alignment: .leading, spacing: 8) {
|
|
Text("Easy Share")
|
|
.font(.subheadline)
|
|
.foregroundColor(Color.appTextSecondary)
|
|
|
|
Button(action: onEasyShare) {
|
|
HStack {
|
|
if isGeneratingPackage {
|
|
ProgressView()
|
|
.tint(.white)
|
|
} else {
|
|
Image(systemName: "square.and.arrow.up")
|
|
}
|
|
Text("Send Invite Link")
|
|
}
|
|
.frame(maxWidth: .infinity)
|
|
}
|
|
.buttonStyle(.borderedProminent)
|
|
.disabled(isGeneratingPackage)
|
|
|
|
Text("Send a .honeydue file via Messages, Email, or AirDrop. They just tap to join.")
|
|
.font(.caption)
|
|
.foregroundColor(Color.appTextSecondary)
|
|
}
|
|
.padding()
|
|
.background(Color.appBackgroundSecondary)
|
|
.cornerRadius(12)
|
|
|
|
// Divider with "or"
|
|
HStack {
|
|
Rectangle()
|
|
.fill(Color.appTextSecondary.opacity(0.3))
|
|
.frame(height: 1)
|
|
Text("or")
|
|
.font(.caption)
|
|
.foregroundColor(Color.appTextSecondary)
|
|
Rectangle()
|
|
.fill(Color.appTextSecondary.opacity(0.3))
|
|
.frame(height: 1)
|
|
}
|
|
.accessibilityHidden(true)
|
|
|
|
// Share Code Section
|
|
VStack(alignment: .leading, spacing: 8) {
|
|
Text("Share Code")
|
|
.font(.subheadline)
|
|
.foregroundColor(Color.appTextSecondary)
|
|
|
|
HStack {
|
|
if let shareCode = shareCode {
|
|
Text(shareCode.code)
|
|
.font(.system(size: 32, weight: .bold, design: .monospaced))
|
|
.foregroundColor(Color.appPrimary)
|
|
.kerning(4)
|
|
.accessibilityLabel("Share code: \(shareCode.code)")
|
|
|
|
Spacer()
|
|
|
|
Button {
|
|
UIPasteboard.general.string = shareCode.code
|
|
} label: {
|
|
Image(systemName: "doc.on.doc")
|
|
.foregroundColor(Color.appPrimary)
|
|
}
|
|
.buttonStyle(.bordered)
|
|
.accessibilityLabel("Copy share code")
|
|
} else {
|
|
Text("No active code")
|
|
.font(.body)
|
|
.foregroundColor(Color.appTextSecondary)
|
|
.italic()
|
|
|
|
Spacer()
|
|
}
|
|
}
|
|
|
|
// Generate Code Button
|
|
Button(action: onGenerateCode) {
|
|
HStack {
|
|
if isGeneratingCode {
|
|
ProgressView()
|
|
.tint(.white)
|
|
} else {
|
|
Image(systemName: "arrow.clockwise")
|
|
}
|
|
Text(shareCode != nil ? "Generate New Code" : "Generate Code")
|
|
}
|
|
.frame(maxWidth: .infinity)
|
|
}
|
|
.buttonStyle(.borderedProminent)
|
|
.disabled(isGeneratingCode)
|
|
.accessibilityLabel("Generate new share code")
|
|
|
|
if shareCode != nil {
|
|
Text("Share this 6-character code. They can enter it in the app to join.")
|
|
.font(.caption)
|
|
.foregroundColor(Color.appTextSecondary)
|
|
}
|
|
}
|
|
.padding()
|
|
.background(Color.appBackgroundSecondary)
|
|
.cornerRadius(12)
|
|
}
|
|
.padding()
|
|
.background(Color.appPrimary.opacity(0.05))
|
|
.cornerRadius(16)
|
|
}
|
|
}
|
|
|
|
#Preview {
|
|
ShareCodeCard(
|
|
shareCode: nil,
|
|
isGeneratingCode: false,
|
|
isGeneratingPackage: false,
|
|
onGenerateCode: {},
|
|
onEasyShare: {}
|
|
)
|
|
.padding()
|
|
}
|