feat: added new CategorySelectionView
fix: progress bar will now be resetted correctly
This commit is contained in:
39
QuizApp/CategorySelectionView.swift
Normal file
39
QuizApp/CategorySelectionView.swift
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
]
|
]
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user