From eeb72ca189db0ae7bd2a1f56e45ccd6df01f110a Mon Sep 17 00:00:00 2001 From: Paul Date: Thu, 7 Aug 2025 23:19:48 +0200 Subject: [PATCH] fead: new leaderboard --- QuizApp/CategorySelectionView.swift | 78 ++++++++++++++++++++++++----- QuizApp/ContentView.swift | 52 ++++++++++++++++++- 2 files changed, 115 insertions(+), 15 deletions(-) diff --git a/QuizApp/CategorySelectionView.swift b/QuizApp/CategorySelectionView.swift index d10492f..bffe471 100644 --- a/QuizApp/CategorySelectionView.swift +++ b/QuizApp/CategorySelectionView.swift @@ -10,6 +10,11 @@ import SwiftUI struct CategorySelectionView: View { @StateObject private var viewModel = ViewModel() @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 { NavigationStack { @@ -56,9 +61,9 @@ struct CategorySelectionView: View { ) ) .padding(.horizontal) - + // Kategorien Header - Text("Verfügbare Quiz") + Text("Kategorien") .font(.title2) .fontWeight(.semibold) .frame(maxWidth: .infinity, alignment: .leading) @@ -71,22 +76,64 @@ struct CategorySelectionView: View { .onAppear { viewModel.loadQuestions(for: category) }) { + HStack { + Image(systemName: "play.circle.fill") + .foregroundColor(.blue) + .font(.title2) + + 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 { - Image(systemName: "play.circle.fill") - .foregroundColor(.blue) - .font(.title2) - - Text(category) + Text("\(index + 1).") .font(.headline) + .foregroundColor(index < 3 ? .orange : .primary) + .frame(width: 25, alignment: .leading) + + Text(scoreData["name"] as? String ?? "Unbekannt") + .font(.body) .foregroundColor(.primary) Spacer() - Image(systemName: "chevron.right") - .foregroundColor(.secondary) - .font(.caption) + Text("\(scoreData["score"] as? Int ?? 0) Punkte") + .font(.body) + .fontWeight(.medium) + .foregroundColor(.blue) } - .padding() + .padding(.horizontal, 16) + .padding(.vertical, 8) .background( RoundedRectangle(cornerRadius: 12) .fill(Color(.systemGray6)) @@ -94,18 +141,23 @@ struct CategorySelectionView: View { RoundedRectangle(cornerRadius: 12) .stroke(Color(.systemGray4), lineWidth: 1) ) + ) } - .buttonStyle(PlainButtonStyle()) } + .padding(.horizontal) + } else { + Text("Keine Leadboard Daten...") } - .padding(.horizontal) Spacer() } .background(Color.white) .navigationBarHidden(true) .navigationTitle("Quiz-Auswahl") + .onAppear { + loadBoardData() + } } } } diff --git a/QuizApp/ContentView.swift b/QuizApp/ContentView.swift index 692a6fd..c0bb598 100644 --- a/QuizApp/ContentView.swift +++ b/QuizApp/ContentView.swift @@ -17,6 +17,8 @@ struct ContentView: View { @State private var selectedAnswerIndex: Int? = nil @State private var isAnswered = false @State private var showExitAlert = false + @State private var playerName: String = "" + @State private var scoreIsSaved = false var body: some View { VStack { @@ -38,11 +40,26 @@ struct ContentView: View { Button("Zurück zur Kategorieauswahl") { dismiss() + } .padding() .background(Color.gray) .foregroundColor(.white) .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 { AudioServicesPlaySystemSound(1322) @@ -176,16 +193,47 @@ struct ContentView: View { viewModel.selectedAnswers[index] == nil { return Color.blue // aktuelle Frage } - + guard index < viewModel.selectedAnswers.count, let selected = viewModel.selectedAnswers[index], index < viewModel.questions.count else { return Color.gray.opacity(0.3) // unbeantwortet } - + let correct = viewModel.questions[index].correctAnswer 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 {