mirror of
https://github.com/AdrianKuta/KahootQuiz.git
synced 2025-09-14 17:24:21 +02:00
feat: Implement Answer Feedback Banner
This commit introduces an `AnswerFeedbackBanner` composable that displays whether a selected answer is correct or wrong. It's integrated into the `Toolbar` section of the `QuizScreen`. Key changes: - **UI Layer (`ui:quiz` module):** - Created `AnswerFeedbackBanner.kt` composable: - Displays "Correct" or "Wrong" text with a green or red background respectively. - Uses `Surface` for elevation and `zIndex` to appear above other elements. - In `QuizScreen.kt`: - Modified the `toolbar` item to include a `Box` that layers the `Toolbar` and the new `AnswerFeedbackBanner`. - The `AnswerFeedbackBanner` is shown when `uiState.isAnswerCorrect` is not null. - In `QuizScreenViewModel.kt`: - Added `isAnswerCorrect: Boolean?` to `ScreenUiState.Success`. - Calculated `isAnswerCorrect` based on the selected choice and the correct answer for the current question. - **Resources (`ui:quiz` module):** - Added new string resources for "Correct" and "Wrong" in `strings.xml`.
This commit is contained in:
@@ -32,6 +32,7 @@ import dev.adriankuta.kahootquiz.core.designsystem.KahootQuizTheme
|
|||||||
import dev.adriankuta.kahootquiz.domain.models.Choice
|
import dev.adriankuta.kahootquiz.domain.models.Choice
|
||||||
import dev.adriankuta.kahootquiz.domain.models.Question
|
import dev.adriankuta.kahootquiz.domain.models.Question
|
||||||
import dev.adriankuta.kahootquiz.ui.quiz.components.Choices
|
import dev.adriankuta.kahootquiz.ui.quiz.components.Choices
|
||||||
|
import dev.adriankuta.kahootquiz.ui.quiz.components.AnswerFeedbackBanner
|
||||||
import dev.adriankuta.kahootquiz.ui.quiz.components.QuestionContent
|
import dev.adriankuta.kahootquiz.ui.quiz.components.QuestionContent
|
||||||
import dev.adriankuta.kahootquiz.ui.quiz.components.TimerBar
|
import dev.adriankuta.kahootquiz.ui.quiz.components.TimerBar
|
||||||
import dev.adriankuta.kahootquiz.ui.quiz.components.Toolbar
|
import dev.adriankuta.kahootquiz.ui.quiz.components.Toolbar
|
||||||
@@ -115,16 +116,26 @@ private fun QuizScreenSuccess(
|
|||||||
|
|
||||||
private fun LazyListScope.toolbar(
|
private fun LazyListScope.toolbar(
|
||||||
uiState: ScreenUiState.Success,
|
uiState: ScreenUiState.Success,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
item(key = "toolbar") {
|
item(key = "toolbar") {
|
||||||
Toolbar(
|
Box(
|
||||||
modifier = Modifier
|
modifier = modifier
|
||||||
.fillMaxWidth()
|
.height(72.dp),
|
||||||
.height(72.dp)
|
) {
|
||||||
.padding(8.dp),
|
Toolbar(
|
||||||
currentQuestionIndex = uiState.currentQuestionIndex,
|
modifier = Modifier
|
||||||
totalQuestions = uiState.totalQuestions,
|
.fillMaxSize()
|
||||||
)
|
.padding(8.dp),
|
||||||
|
currentQuestionIndex = uiState.currentQuestionIndex,
|
||||||
|
totalQuestions = uiState.totalQuestions,
|
||||||
|
)
|
||||||
|
uiState.isAnswerCorrect?.let { isCorrect ->
|
||||||
|
AnswerFeedbackBanner(
|
||||||
|
isCorrect = isCorrect,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -61,6 +61,9 @@ class QuizScreenViewModel @Inject constructor(
|
|||||||
QuizUiState.Loading -> ScreenUiState.Loading
|
QuizUiState.Loading -> ScreenUiState.Loading
|
||||||
is QuizUiState.Success -> {
|
is QuizUiState.Success -> {
|
||||||
val currentQuestion = quizState.quiz.questions.getOrNull(currentQuestionIndex)
|
val currentQuestion = quizState.quiz.questions.getOrNull(currentQuestionIndex)
|
||||||
|
val isAnswerCorrect = selectedChoiceIndex?.let { idx ->
|
||||||
|
currentQuestion?.choices?.getOrNull(idx)?.correct == true
|
||||||
|
}
|
||||||
|
|
||||||
ScreenUiState.Success(
|
ScreenUiState.Success(
|
||||||
currentQuestion = currentQuestion,
|
currentQuestion = currentQuestion,
|
||||||
@@ -71,6 +74,7 @@ class QuizScreenViewModel @Inject constructor(
|
|||||||
remainingTimeSeconds = remainingTimeSeconds,
|
remainingTimeSeconds = remainingTimeSeconds,
|
||||||
totalTimeSeconds = currentQuestion?.time?.inWholeSeconds?.toInt() ?: 0,
|
totalTimeSeconds = currentQuestion?.time?.inWholeSeconds?.toInt() ?: 0,
|
||||||
),
|
),
|
||||||
|
isAnswerCorrect = isAnswerCorrect,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -148,6 +152,7 @@ sealed interface ScreenUiState {
|
|||||||
val currentQuestionIndex: Int = 0,
|
val currentQuestionIndex: Int = 0,
|
||||||
val totalQuestions: Int = 0,
|
val totalQuestions: Int = 0,
|
||||||
val timerState: TimerState = TimerState(),
|
val timerState: TimerState = TimerState(),
|
||||||
|
val isAnswerCorrect: Boolean? = null,
|
||||||
) : ScreenUiState
|
) : ScreenUiState
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -0,0 +1,40 @@
|
|||||||
|
package dev.adriankuta.kahootquiz.ui.quiz.components
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.material3.Surface
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.zIndex
|
||||||
|
import dev.adriankuta.kahootquiz.core.designsystem.Green
|
||||||
|
import dev.adriankuta.kahootquiz.core.designsystem.Red
|
||||||
|
import dev.adriankuta.kahootquiz.ui.quiz.R
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun AnswerFeedbackBanner(
|
||||||
|
isCorrect: Boolean,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
) {
|
||||||
|
Surface(
|
||||||
|
modifier = modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.zIndex(10f),
|
||||||
|
shadowElevation = 8.dp,
|
||||||
|
color = if (isCorrect) Green else Red,
|
||||||
|
contentColor = Color.White,
|
||||||
|
) {
|
||||||
|
Box {
|
||||||
|
Text(
|
||||||
|
text = stringResource(if (isCorrect) R.string.correct else R.string.wrong),
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
modifier = Modifier.align(Alignment.Center),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -2,4 +2,6 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<string name="quiz">Quiz</string>
|
<string name="quiz">Quiz</string>
|
||||||
<string name="continue_text">Continue</string>
|
<string name="continue_text">Continue</string>
|
||||||
|
<string name="correct">Correct</string>
|
||||||
|
<string name="wrong">Wrong</string>
|
||||||
</resources>
|
</resources>
|
Reference in New Issue
Block a user