From 1f07f153b23fa9a7ae0ea648b498dad60f96c594 Mon Sep 17 00:00:00 2001 From: JustZvan Date: Wed, 8 Apr 2026 19:41:36 +0200 Subject: feat: 1.2 --- app/src/main/java/sh/lajo/buddy/EducationScreen.kt | 216 +++++++++++++++++++++ 1 file changed, 216 insertions(+) create mode 100644 app/src/main/java/sh/lajo/buddy/EducationScreen.kt (limited to 'app/src/main/java/sh/lajo/buddy/EducationScreen.kt') diff --git a/app/src/main/java/sh/lajo/buddy/EducationScreen.kt b/app/src/main/java/sh/lajo/buddy/EducationScreen.kt new file mode 100644 index 0000000..e37770a --- /dev/null +++ b/app/src/main/java/sh/lajo/buddy/EducationScreen.kt @@ -0,0 +1,216 @@ +package sh.lajo.buddy + +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.ArrowBack +import androidx.compose.material3.* +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import coil.compose.AsyncImage + +@Composable +fun EducationScreen(repository: EducationRepository = remember { EducationRepository() }) { + var lectures by remember { mutableStateOf>(emptyList()) } + var selectedLecture by remember { mutableStateOf(null) } + var showingQuiz by remember { mutableStateOf(false) } + var isLoading by remember { mutableStateOf(true) } + + LaunchedEffect(Unit) { + lectures = repository.fetchLectures() + isLoading = false + } + + if (isLoading) { + Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { + CircularProgressIndicator() + } + } else if (showingQuiz && selectedLecture != null) { + QuizScreen(quiz = selectedLecture!!.quiz, onBack = { showingQuiz = false }) + } else if (selectedLecture != null) { + LectureDetailScreen( + lecture = selectedLecture!!, + onBack = { selectedLecture = null }, + onStartQuiz = { showingQuiz = true } + ) + } else { + LectureListScreen(lectures = lectures, onLectureClick = { selectedLecture = it }) + } +} + +@Composable +fun LectureListScreen(lectures: List, onLectureClick: (EducationLecture) -> Unit) { + LazyColumn( + modifier = Modifier.fillMaxSize(), + contentPadding = PaddingValues(16.dp), + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + item { + Text( + text = "Edukacija", + style = MaterialTheme.typography.headlineMedium, + modifier = Modifier.padding(bottom = 16.dp) + ) + } + items(lectures) { lecture -> + ElevatedCard( + onClick = { onLectureClick(lecture) }, + modifier = Modifier.fillMaxWidth() + ) { + Text( + text = lecture.title, + modifier = Modifier.padding(16.dp), + style = MaterialTheme.typography.titleLarge + ) + } + } + } +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun LectureDetailScreen( + lecture: EducationLecture, + onBack: () -> Unit, + onStartQuiz: () -> Unit +) { + Scaffold( + topBar = { + TopAppBar( + title = { Text(lecture.title) }, + navigationIcon = { + IconButton(onClick = onBack) { + Icon(Icons.Default.ArrowBack, contentDescription = "Back") + } + } + ) + } + ) { paddingValues -> + LazyColumn( + modifier = Modifier + .fillMaxSize() + .padding(paddingValues), + contentPadding = PaddingValues(16.dp), + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + lecture.lectureItems.forEach { item -> + item { + Text(text = item.title, style = MaterialTheme.typography.headlineSmall) + } + items(item.lectureElements) { element -> + when (element.type) { + "text" -> element.text?.let { Text(text = it, style = MaterialTheme.typography.bodyLarge) } + "image" -> element.imageUrl?.let { + AsyncImage( + model = it, + contentDescription = null, + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 8.dp) + ) + } + } + } + item { + HorizontalDivider(modifier = Modifier.padding(vertical = 8.dp)) + } + } + item { + Button( + onClick = onStartQuiz, + modifier = Modifier + .fillMaxWidth() + .padding(top = 16.dp) + ) { + Text("Započni kviz") + } + } + } + } +} + +@Composable +fun QuizScreen(quiz: Quiz, onBack: () -> Unit) { + var currentQuestionIndex by remember { mutableIntStateOf(0) } + var selectedAnswerIndex by remember { mutableStateOf(null) } + var score by remember { mutableIntStateOf(0) } + var showResult by remember { mutableStateOf(false) } + + val currentQuestion = quiz.questions.getOrNull(currentQuestionIndex) + + if (showResult || currentQuestion == null) { + Column( + modifier = Modifier + .fillMaxSize() + .padding(16.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center + ) { + Text(text = "Kviz završen!", style = MaterialTheme.typography.headlineMedium) + Spacer(modifier = Modifier.height(8.dp)) + Text(text = "Tvoj rezultat: $score / ${quiz.questions.size}", style = MaterialTheme.typography.titleLarge) + Spacer(modifier = Modifier.height(24.dp)) + Button(onClick = onBack) { + Text("Povratak na predavanje") + } + } + } else { + Column( + modifier = Modifier + .fillMaxSize() + .padding(16.dp) + ) { + Text( + text = "Pitanje ${currentQuestionIndex + 1} od ${quiz.questions.size}", + style = MaterialTheme.typography.labelMedium + ) + Spacer(modifier = Modifier.height(8.dp)) + Text(text = currentQuestion.question, style = MaterialTheme.typography.headlineSmall) + Spacer(modifier = Modifier.height(24.dp)) + currentQuestion.answers.forEachIndexed { index, answer -> + val isSelected = selectedAnswerIndex == index + OutlinedCard( + onClick = { selectedAnswerIndex = index }, + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 4.dp), + colors = CardDefaults.outlinedCardColors( + containerColor = if (isSelected) MaterialTheme.colorScheme.primaryContainer else MaterialTheme.colorScheme.surface + ), + border = CardDefaults.outlinedCardBorder().run { + if (isSelected) copy(width = 2.dp) else this + } + ) { + Text( + text = answer, + modifier = Modifier.padding(16.dp), + style = MaterialTheme.typography.bodyLarge + ) + } + } + Spacer(modifier = Modifier.weight(1f)) + Button( + onClick = { + // correctAnswer in JSON is "1" which refers to index 1 (second answer) + val correctIndex = currentQuestion.correctAnswer.toIntOrNull() ?: 0 + if (selectedAnswerIndex == correctIndex) { + score++ + } + if (currentQuestionIndex < quiz.questions.size - 1) { + currentQuestionIndex++ + selectedAnswerIndex = null + } else { + showResult = true + } + }, + enabled = selectedAnswerIndex != null, + modifier = Modifier.fillMaxWidth() + ) { + Text(if (currentQuestionIndex < quiz.questions.size - 1) "Sljedeće pitanje" else "Završi kviz") + } + } + } +} -- cgit v1.2.3