fead: new leaderboard

This commit is contained in:
2025-08-07 23:19:48 +02:00
parent 681e8258c4
commit eeb72ca189
2 changed files with 115 additions and 15 deletions

View File

@@ -10,6 +10,11 @@ import SwiftUI
struct CategorySelectionView: View { struct CategorySelectionView: View {
@StateObject private var viewModel = ViewModel() @StateObject private var viewModel = ViewModel()
@AppStorage("globalScore") var globalScore: Int = 0 @AppStorage("globalScore") var globalScore: Int = 0
@State private var boardData: [[String: Any]] = []
private func loadBoardData() {
boardData = UserDefaults.standard.array(forKey: "leaderboard") as? [[String: Any]] ?? []
}
var body: some View { var body: some View {
NavigationStack { NavigationStack {
@@ -58,7 +63,7 @@ struct CategorySelectionView: View {
.padding(.horizontal) .padding(.horizontal)
// Kategorien Header // Kategorien Header
Text("Verfügbare Quiz") Text("Kategorien")
.font(.title2) .font(.title2)
.fontWeight(.semibold) .fontWeight(.semibold)
.frame(maxWidth: .infinity, alignment: .leading) .frame(maxWidth: .infinity, alignment: .leading)
@@ -71,22 +76,64 @@ struct CategorySelectionView: View {
.onAppear { .onAppear {
viewModel.loadQuestions(for: category) viewModel.loadQuestions(for: category)
}) { }) {
HStack { HStack {
Image(systemName: "play.circle.fill") Image(systemName: "play.circle.fill")
.foregroundColor(.blue) .foregroundColor(.blue)
.font(.title2) .font(.title2)
Text(category) Text(category)
.font(.headline)
.foregroundColor(.primary)
Spacer()
Image(systemName: "chevron.right")
.foregroundColor(.secondary)
.font(.caption)
}
.padding()
.background(
RoundedRectangle(cornerRadius: 12)
.fill(Color(.systemGray6))
.overlay(
RoundedRectangle(cornerRadius: 12)
.stroke(Color(.systemGray4), lineWidth: 1)
)
)
}
.buttonStyle(PlainButtonStyle())
}
}
.padding(.horizontal)
// Scoreboard
Text("Leaderboard")
.font(.title2)
.fontWeight(.semibold)
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.horizontal)
if !boardData.isEmpty {
VStack(spacing: 8) {
ForEach(Array(boardData.prefix(5).enumerated()), id: \.offset) { index, scoreData in
HStack {
Text("\(index + 1).")
.font(.headline) .font(.headline)
.foregroundColor(index < 3 ? .orange : .primary)
.frame(width: 25, alignment: .leading)
Text(scoreData["name"] as? String ?? "Unbekannt")
.font(.body)
.foregroundColor(.primary) .foregroundColor(.primary)
Spacer() Spacer()
Image(systemName: "chevron.right") Text("\(scoreData["score"] as? Int ?? 0) Punkte")
.foregroundColor(.secondary) .font(.body)
.font(.caption) .fontWeight(.medium)
.foregroundColor(.blue)
} }
.padding() .padding(.horizontal, 16)
.padding(.vertical, 8)
.background( .background(
RoundedRectangle(cornerRadius: 12) RoundedRectangle(cornerRadius: 12)
.fill(Color(.systemGray6)) .fill(Color(.systemGray6))
@@ -94,18 +141,23 @@ struct CategorySelectionView: View {
RoundedRectangle(cornerRadius: 12) RoundedRectangle(cornerRadius: 12)
.stroke(Color(.systemGray4), lineWidth: 1) .stroke(Color(.systemGray4), lineWidth: 1)
) )
) )
} }
.buttonStyle(PlainButtonStyle())
} }
.padding(.horizontal)
} else {
Text("Keine Leadboard Daten...")
} }
.padding(.horizontal)
Spacer() Spacer()
} }
.background(Color.white) .background(Color.white)
.navigationBarHidden(true) .navigationBarHidden(true)
.navigationTitle("Quiz-Auswahl") .navigationTitle("Quiz-Auswahl")
.onAppear {
loadBoardData()
}
} }
} }
} }

View File

@@ -17,6 +17,8 @@ struct ContentView: View {
@State private var selectedAnswerIndex: Int? = nil @State private var selectedAnswerIndex: Int? = nil
@State private var isAnswered = false @State private var isAnswered = false
@State private var showExitAlert = false @State private var showExitAlert = false
@State private var playerName: String = ""
@State private var scoreIsSaved = false
var body: some View { var body: some View {
VStack { VStack {
@@ -38,11 +40,26 @@ struct ContentView: View {
Button("Zurück zur Kategorieauswahl") { Button("Zurück zur Kategorieauswahl") {
dismiss() dismiss()
} }
.padding() .padding()
.background(Color.gray) .background(Color.gray)
.foregroundColor(.white) .foregroundColor(.white)
.cornerRadius(10) .cornerRadius(10)
TextField("Dein Name:", text: $playerName)
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding(.horizontal)
Button("Score speichern") {
saveScore()
dismiss()
}
.padding()
.background(playerName.isEmpty ? Color.gray : Color.green)
.foregroundColor(.white)
.cornerRadius(10)
.disabled(playerName.isEmpty)
} }
.onAppear { .onAppear {
AudioServicesPlaySystemSound(1322) AudioServicesPlaySystemSound(1322)
@@ -186,6 +203,37 @@ struct ContentView: View {
let correct = viewModel.questions[index].correctAnswer let correct = viewModel.questions[index].correctAnswer
return selected == correct ? .green : .red return selected == correct ? .green : .red
} }
private func saveScore() {
// Bestehende Scores laden
var savedScores = UserDefaults.standard.array(forKey: "leaderboard") as? [[String: Any]] ?? []
// Neuen Score hinzufügen
let newScore: [String: Any] = [
"name": playerName,
"score": viewModel.score,
"date": Date()
]
savedScores.append(newScore)
// Nach Score sortieren
savedScores.sort { score1, score2 in
let score1Value = score1["score"] as? Int ?? 0
let score2Value = score2["score"] as? Int ?? 0
return score1Value > score2Value
}
// Nur die besten 10 Scores behalten
if savedScores.count > 5 {
savedScores = Array(savedScores.prefix(10))
}
UserDefaults.standard.set(savedScores, forKey: "leaderboard")
scoreIsSaved = true
print("Score gespeichert: \(playerName) - \(viewModel.score) Punkte")
}
} }
#Preview { #Preview {