feat: added new CategorySelectionView

fix: progress bar will now be resetted correctly
This commit is contained in:
2025-08-06 18:23:06 +02:00
parent f7379c9814
commit ef779cf936
6 changed files with 260 additions and 63 deletions

View File

@@ -0,0 +1,39 @@
//
// CategorySelectionView.swift
// QuizApp
//
// Created by Paul on 06.08.25.
//
import SwiftUI
struct CategorySelectionView: View {
@ObservedObject var viewModel = ViewModel()
@State private var selectedCategory: String? = nil
var body: some View {
if viewModel.selectedCategory != nil && !viewModel.questions.isEmpty {
ContentView(viewModel: viewModel)
} else {
VStack(spacing: 20) {
Text("Wähle eine Kategorie")
.font(.largeTitle)
ForEach(viewModel.availableCategories, id: \.self) { category in
Button(action: {
viewModel.loadQuestions(for: category)
selectedCategory = category
}) {
Text(category)
.font(.title2)
.padding()
.frame(maxWidth: 300)
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(12)
}
}
}
}
}
}

View File

@@ -2,7 +2,7 @@
// ContentView.swift // ContentView.swift
// QuizApp // QuizApp
// //
// Created by Paul Nowotka on 02.08.25. // Created by Paul on 02.08.25.
// //
import SwiftUI import SwiftUI
@@ -31,6 +31,14 @@ struct ContentView: View {
.background(Color.blue) .background(Color.blue)
.foregroundColor(.white) .foregroundColor(.white)
.cornerRadius(10) .cornerRadius(10)
Button("Zurück zur Kategorieauswahl") {
viewModel.selectedCategory = nil
}
.padding()
.background(Color.gray)
.foregroundColor(.white)
.cornerRadius(10)
} }
} else if let frage = viewModel.currentQuestion { } else if let frage = viewModel.currentQuestion {
Text("Punkte: \(viewModel.score)") Text("Punkte: \(viewModel.score)")
@@ -132,6 +140,7 @@ struct ContentView: View {
selectedAnswerIndex = nil selectedAnswerIndex = nil
isAnswered = false isAnswered = false
viewModel.answeredCount = 0 viewModel.answeredCount = 0
viewModel.selectedAnswers = Array(repeating: nil, count: viewModel.questions.count)
} }
func colorForAnswer(at index: Int) -> Color { func colorForAnswer(at index: Int) -> Color {
@@ -155,5 +164,5 @@ struct ContentView: View {
} }
#Preview { #Preview {
ContentView() CategorySelectionView()
} }

View File

@@ -2,7 +2,7 @@
// QuizAppApp.swift // QuizAppApp.swift
// QuizApp // QuizApp
// //
// Created by Paul Nowotka on 02.08.25. // Created by Paul on 02.08.25.
// //
import SwiftUI import SwiftUI
@@ -11,7 +11,7 @@ import SwiftUI
struct QuizAppApp: App { struct QuizAppApp: App {
var body: some Scene { var body: some Scene {
WindowGroup { WindowGroup {
ContentView() CategorySelectionView()
} }
} }
} }

View File

@@ -2,15 +2,13 @@
// Topic.swift // Topic.swift
// QuizApp // QuizApp
// //
// Created by Paul Nowotka on 03.08.25. // Created by Paul on 03.08.25.
// //
import Foundation import Foundation
struct QuizQuestion: Decodable, Hashable { struct QuizQuestion: Decodable, Hashable {
let question: String let question: String
let answers: [String] let answers: [String]
let correctAnswer: Int let correctAnswer: Int
} }

View File

@@ -2,14 +2,16 @@
// ViewModel.swift // ViewModel.swift
// QuizApp // QuizApp
// //
// Created by Paul Nowotka on 03.08.25. // Created by Paul on 03.08.25.
// //
import Foundation import Foundation
class ViewModel: ObservableObject { class ViewModel: ObservableObject {
private var allQuestionsByCategory: [String: [QuizQuestion]] = [:]
@Published var questions: [QuizQuestion] = [] @Published var questions: [QuizQuestion] = []
@Published var selectedCategory: String? = nil
@Published var currentQuestionIndex: Int = 0 @Published var currentQuestionIndex: Int = 0
@Published var score: Int = 0 @Published var score: Int = 0
@Published var isQuizFinished: Bool = false @Published var isQuizFinished: Bool = false
@@ -27,6 +29,11 @@ class ViewModel: ObservableObject {
return questions[currentQuestionIndex] return questions[currentQuestionIndex]
} }
var availableCategories: [String] {
return Array(allQuestionsByCategory.keys).sorted()
}
init() { init() {
guard let url = Bundle.main.url(forResource: "data", withExtension: "json") else { guard let url = Bundle.main.url(forResource: "data", withExtension: "json") else {
questions = [] questions = []
@@ -35,11 +42,10 @@ class ViewModel: ObservableObject {
do { do {
let data = try Data(contentsOf: url) let data = try Data(contentsOf: url)
questions = try JSONDecoder().decode([QuizQuestion].self, from: data) allQuestionsByCategory = try JSONDecoder().decode([String: [QuizQuestion]].self, from: data)
self.selectedAnswers = Array(repeating: nil, count: questions.count)
} catch { } catch {
print("Fehler beim Laden des Inhalts: \(error)") print("Fehler beim Laden des Inhalts: \(error)")
questions = [] allQuestionsByCategory = [:]
} }
} }
@@ -51,6 +57,17 @@ class ViewModel: ObservableObject {
} }
} }
func loadQuestions(for category: String) {
selectedCategory = category
questions = allQuestionsByCategory[category] ?? []
currentQuestionIndex = 0
score = 0
isQuizFinished = false
answeredCount = 0
selectedAnswers = Array(repeating: nil, count: questions.count)
}
func incrementScore(selectedIndex: Int) { func incrementScore(selectedIndex: Int) {
if let correct = currentQuestion?.correctAnswer, selectedIndex == correct { if let correct = currentQuestion?.correctAnswer, selectedIndex == correct {
score += 1 score += 1

View File

@@ -1,52 +1,186 @@
[ {
"Hauptstädte": [
{ {
"question": "Was ist die Hauptstadt von Frankreich?", "question": "Was ist die Hauptstadt von Frankreich?",
"answers": ["Rom", "Berlin", "Paris"], "answers": [
"Rom",
"Berlin",
"Paris"
],
"correctAnswer": 2 "correctAnswer": 2
}, },
{ {
"question": "Was ist die Hauptstadt von Deutschland?", "question": "Was ist die Hauptstadt von Deutschland?",
"answers": ["Berlin", "Wien", "Hamburg"], "answers": [
"Berlin",
"Wien",
"Hamburg"
],
"correctAnswer": 0 "correctAnswer": 0
}, },
{ {
"question": "Was ist die Hauptstadt von Italien?", "question": "Was ist die Hauptstadt von Italien?",
"answers": ["Rom", "Mailand", "Neapel"], "answers": [
"Rom",
"Mailand",
"Neapel"
],
"correctAnswer": 0 "correctAnswer": 0
}, },
{ {
"question": "Was ist die Hauptstadt von Spanien?", "question": "Was ist die Hauptstadt von Spanien?",
"answers": ["Barcelona", "Madrid", "Valencia"], "answers": [
"Barcelona",
"Madrid",
"Valencia"
],
"correctAnswer": 1 "correctAnswer": 1
}, },
{ {
"question": "Was ist die Hauptstadt von Österreich?", "question": "Was ist die Hauptstadt von Österreich?",
"answers": ["Graz", "Salzburg", "Wien"], "answers": [
"Graz",
"Salzburg",
"Wien"
],
"correctAnswer": 2 "correctAnswer": 2
}, },
{ {
"question": "Was ist die Hauptstadt der Schweiz?", "question": "Was ist die Hauptstadt der Schweiz?",
"answers": ["Zürich", "Bern", "Genf"], "answers": [
"Zürich",
"Bern",
"Genf"
],
"correctAnswer": 1 "correctAnswer": 1
}, },
{ {
"question": "Was ist die Hauptstadt von Portugal?", "question": "Was ist die Hauptstadt von Portugal?",
"answers": ["Lissabon", "Porto", "Faro"], "answers": [
"Lissabon",
"Porto",
"Faro"
],
"correctAnswer": 0 "correctAnswer": 0
}, },
{ {
"question": "Was ist die Hauptstadt von Belgien?", "question": "Was ist die Hauptstadt von Belgien?",
"answers": ["Brüssel", "Antwerpen", "Brügge"], "answers": [
"Brüssel",
"Antwerpen",
"Brügge"
],
"correctAnswer": 0 "correctAnswer": 0
}, },
{ {
"question": "Was ist die Hauptstadt von Niederlande?", "question": "Was ist die Hauptstadt von Niederlande?",
"answers": ["Rotterdam", "Amsterdam", "Den Haag"], "answers": [
"Rotterdam",
"Amsterdam",
"Den Haag"
],
"correctAnswer": 1 "correctAnswer": 1
}, },
{ {
"question": "Was ist die Hauptstadt von Polen?", "question": "Was ist die Hauptstadt von Polen?",
"answers": ["Warschau", "Krakau", "Danzig"], "answers": [
"Warschau",
"Krakau",
"Danzig"
],
"correctAnswer": 0 "correctAnswer": 0
} }
],
"Mathematik": [
{
"question": "Was ist 5 + 3?",
"answers": [
"7",
"8",
"9"
],
"correctAnswer": 1
},
{
"question": "Was ist 12 - 4?",
"answers": [
"6",
"8",
"9"
],
"correctAnswer": 1
},
{
"question": "Was ist 6 × 7?",
"answers": [
"42",
"36",
"48"
],
"correctAnswer": 0
},
{
"question": "Was ist 81 ÷ 9?",
"answers": [
"8",
"9",
"10"
],
"correctAnswer": 1
},
{
"question": "Was ist das Quadrat von 5?",
"answers": [
"20",
"25",
"30"
],
"correctAnswer": 1
},
{
"question": "Was ist 10 % von 200?",
"answers": [
"20",
"25",
"10"
],
"correctAnswer": 0
},
{
"question": "Was ergibt 2³?",
"answers": [
"6",
"8",
"9"
],
"correctAnswer": 1
},
{
"question": "Was ist die Wurzel aus 64?",
"answers": [
"6",
"7",
"8"
],
"correctAnswer": 2
},
{
"question": "Was ist 3 × (4 + 2)?",
"answers": [
"18",
"20",
"12"
],
"correctAnswer": 0
},
{
"question": "Wie viel ist 100 ÷ 4?",
"answers": [
"20",
"25",
"30"
],
"correctAnswer": 1
}
] ]
}