feat: progress bar

This commit is contained in:
2025-08-05 21:58:37 +02:00
parent 1ce4ca6241
commit f7379c9814
2 changed files with 49 additions and 0 deletions

View File

@@ -37,6 +37,23 @@ struct ContentView: View {
.font(.headline) .font(.headline)
.padding(.bottom, 10) .padding(.bottom, 10)
//Fortschrittsbalken
VStack(spacing: 4) {
HStack(spacing: 4) {
ForEach(0..<viewModel.questions.count, id: \.self) { index in
Rectangle()
.fill(colorForAnswer(at: index))
.frame(width: 20, height: index == viewModel.currentQuestionIndex ? 14 : 10)
.cornerRadius(3)
}
}
Text("Frage \(viewModel.currentQuestionIndex + 1) von \(viewModel.questions.count)")
.font(.caption)
.foregroundColor(.gray)
}
.padding(.bottom, 10)
Text(frage.question) Text(frage.question)
.font(.title) .font(.title)
.multilineTextAlignment(.center) .multilineTextAlignment(.center)
@@ -49,6 +66,8 @@ struct ContentView: View {
print("Selected:", index) print("Selected:", index)
print("Correct:", frage.correctAnswer) print("Correct:", frage.correctAnswer)
viewModel.incrementScore(selectedIndex: index) viewModel.incrementScore(selectedIndex: index)
viewModel.answeredCount += 1
viewModel.selectedAnswers[viewModel.currentQuestionIndex] = index
}) { }) {
Text(frage.answers[index]) Text(frage.answers[index])
.padding(.vertical, 12) .padding(.vertical, 12)
@@ -93,6 +112,7 @@ struct ContentView: View {
} }
} }
} }
private func buttonColor(for index: Int, correctIndex: Int) -> Color { private func buttonColor(for index: Int, correctIndex: Int) -> Color {
guard isAnswered else { return .blue } guard isAnswered else { return .blue }
@@ -104,14 +124,34 @@ struct ContentView: View {
return .gray return .gray
} }
} }
private func restartQuiz() { private func restartQuiz() {
viewModel.currentQuestionIndex = 0 viewModel.currentQuestionIndex = 0
viewModel.score = 0 viewModel.score = 0
viewModel.isQuizFinished = false viewModel.isQuizFinished = false
selectedAnswerIndex = nil selectedAnswerIndex = nil
isAnswered = false isAnswered = false
viewModel.answeredCount = 0
} }
func colorForAnswer(at index: Int) -> Color {
if index == viewModel.currentQuestionIndex,
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
}
} }
#Preview { #Preview {

View File

@@ -13,6 +13,14 @@ class ViewModel: ObservableObject {
@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
@Published var answeredCount: Int = 0
@Published var selectedAnswers: [Int?] = []
var progress: Double {
guard !questions.isEmpty else { return 0.0 }
return Double(answeredCount) / Double(questions.count)
}
var currentQuestion: QuizQuestion? { var currentQuestion: QuizQuestion? {
guard currentQuestionIndex < questions.count else { return nil } guard currentQuestionIndex < questions.count else { return nil }
@@ -28,6 +36,7 @@ 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) questions = try JSONDecoder().decode([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 = [] questions = []