Complete native rewrite of the web-based SoliCards game as a SwiftUI multiplatform app targeting iOS 17+, iPadOS 17+, and macOS 14+. Three solitaire variants (Klondike, Spider, FreeCell) with full game rules, drag & drop, smart zoom layout, 6 themes, 4 difficulty levels, SwiftData persistence, VoiceOver accessibility, and 57 unit tests. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
64 lines
2.2 KiB
Swift
64 lines
2.2 KiB
Swift
import SwiftUI
|
|
import SwiftData
|
|
|
|
struct StatisticsView: View {
|
|
@Query private var records: [StatsRecord]
|
|
@Environment(\.dismiss) private var dismiss
|
|
|
|
var body: some View {
|
|
NavigationStack {
|
|
List {
|
|
if records.isEmpty {
|
|
ContentUnavailableView("No Statistics Yet",
|
|
systemImage: "chart.bar",
|
|
description: Text("Play some games to see your stats here."))
|
|
} else {
|
|
ForEach(GameVariant.allCases) { variant in
|
|
let variantRecords = records.filter { $0.variant == variant.rawValue }
|
|
if !variantRecords.isEmpty {
|
|
Section(variant.displayName) {
|
|
ForEach(variantRecords, id: \.variant) { record in
|
|
statsRow(record)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
.navigationTitle("Statistics")
|
|
#if os(iOS)
|
|
.navigationBarTitleDisplayMode(.inline)
|
|
#endif
|
|
.toolbar {
|
|
ToolbarItem(placement: .confirmationAction) {
|
|
Button("Done") { dismiss() }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private func statsRow(_ record: StatsRecord) -> some View {
|
|
VStack(alignment: .leading, spacing: 4) {
|
|
HStack {
|
|
Text(record.difficulty.capitalized)
|
|
.font(.subheadline.bold())
|
|
Spacer()
|
|
Text("\(record.gamesWon)/\(record.gamesPlayed) wins")
|
|
.font(.caption)
|
|
.foregroundStyle(.secondary)
|
|
}
|
|
HStack {
|
|
if record.gamesPlayed > 0 {
|
|
Text("Win rate: \(record.winRate * 100, specifier: "%.0f")%")
|
|
Spacer()
|
|
if record.bestStreak > 0 {
|
|
Text("Best streak: \(record.bestStreak)")
|
|
}
|
|
}
|
|
}
|
|
.font(.caption)
|
|
.foregroundStyle(.secondary)
|
|
}
|
|
}
|
|
}
|