diff --git a/composeApp/src/desktopMain/kotlin/com/jaytux/grader/Util.kt b/composeApp/src/desktopMain/kotlin/com/jaytux/grader/Util.kt new file mode 100644 index 0000000..3d4f8a5 --- /dev/null +++ b/composeApp/src/desktopMain/kotlin/com/jaytux/grader/Util.kt @@ -0,0 +1,9 @@ +package com.jaytux.grader + +fun String.maxN(n: Int): String { + return if (this.length > n) { + this.substring(0, n - 3) + "..." + } else { + this + } +} \ No newline at end of file diff --git a/composeApp/src/desktopMain/kotlin/com/jaytux/grader/ui/Assignments.kt b/composeApp/src/desktopMain/kotlin/com/jaytux/grader/ui/Assignments.kt index 9ff78f8..6e29dde 100644 --- a/composeApp/src/desktopMain/kotlin/com/jaytux/grader/ui/Assignments.kt +++ b/composeApp/src/desktopMain/kotlin/com/jaytux/grader/ui/Assignments.kt @@ -15,7 +15,6 @@ import androidx.compose.ui.unit.dp import com.jaytux.grader.viewmodel.GroupAssignmentState import com.mohamedrejeb.richeditor.model.rememberRichTextState import com.mohamedrejeb.richeditor.ui.material3.OutlinedRichTextEditor -import com.mohamedrejeb.richeditor.ui.material3.RichTextEditor @OptIn(ExperimentalMaterial3Api::class) @Composable diff --git a/composeApp/src/desktopMain/kotlin/com/jaytux/grader/ui/Views.kt b/composeApp/src/desktopMain/kotlin/com/jaytux/grader/ui/Views.kt index b2944ca..8617489 100644 --- a/composeApp/src/desktopMain/kotlin/com/jaytux/grader/ui/Views.kt +++ b/composeApp/src/desktopMain/kotlin/com/jaytux/grader/ui/Views.kt @@ -11,11 +11,13 @@ import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.dp import androidx.compose.ui.window.DialogWindow import androidx.compose.ui.window.WindowPosition import androidx.compose.ui.window.rememberDialogState +import com.jaytux.grader.maxN import com.jaytux.grader.viewmodel.GroupState import com.jaytux.grader.viewmodel.StudentState @@ -26,37 +28,114 @@ fun StudentView(state: StudentState) { val groupGrades by state.groupGrades.entities val soloGrades by state.soloGrades.entities - // TODO: incorporate grades into UI - Column(Modifier.padding(10.dp)) { PaneHeader(state.student.name, "student", state.editionCourse) Row { - Column(Modifier.padding(10.dp).weight(0.45f)) { - Spacer(Modifier.height(10.dp)) - InteractToEdit(state.student.name, { state.update { this.name = it } }, "Name") - InteractToEdit(state.student.contact, { state.update { this.contact = it } }, "Contact") - InteractToEdit(state.student.note, { state.update { this.note = it } }, "Note", singleLine = false) - } - Box(Modifier.weight(0.55f)) {} - } - Row { - Column(Modifier.weight(0.5f)) { - Text("Courses", style = MaterialTheme.typography.headlineSmall) - ListOrEmpty(courses, { Text("Not a member of any course") }) { _, it -> - val (ed, course) = it - Text("${course.name} (${ed.name})", style = MaterialTheme.typography.bodyMedium) + Column(Modifier.weight(0.45f)) { + Column(Modifier.padding(10.dp).weight(0.35f)) { + Spacer(Modifier.height(10.dp)) + InteractToEdit(state.student.name, { state.update { this.name = it } }, "Name") + InteractToEdit(state.student.contact, { state.update { this.contact = it } }, "Contact") + InteractToEdit(state.student.note, { state.update { this.note = it } }, "Note", singleLine = false) + } + Column(Modifier.weight(0.20f)) { + Text("Courses", style = MaterialTheme.typography.headlineSmall) + ListOrEmpty(courses, { Text("Not a member of any course") }) { _, it -> + val (ed, course) = it + Text("${course.name} (${ed.name})", style = MaterialTheme.typography.bodyMedium) + } + } + Column(Modifier.weight(0.45f)) { + Text("Groups", style = MaterialTheme.typography.headlineSmall) + ListOrEmpty(groups, { Text("Not a member of any group") }) { _, it -> + Row { + val (group, c) = it + val (course, ed) = c + Text(group.name, style = MaterialTheme.typography.bodyMedium) + Spacer(Modifier.width(5.dp)) + Text( + "(in course $course ($ed))", + Modifier.align(Alignment.Bottom), + style = MaterialTheme.typography.bodySmall + ) + } + + } } } + Column(Modifier.weight(0.55f)) { + Text("Courses", style = MaterialTheme.typography.headlineSmall) + LazyColumn { + item { + Text("As group member", fontWeight = FontWeight.Bold) + } + items(groupGrades) { + groupGradeWidget(it) + } - Column(Modifier.weight(0.5f)) { - Text("Groups", style = MaterialTheme.typography.headlineSmall) - ListOrEmpty(groups, { Text("Not a member of any group") }) { _, it -> + item { + Text("Solo assignments", fontWeight = FontWeight.Bold) + } + items(soloGrades) { + soloGradeWidget(it) + } + } + } + } + } +} + +@Composable +fun groupGradeWidget(gg: StudentState.LocalGroupGrade) { + val (group, assignment, gGrade, iGrade) = gg + var expanded by remember { mutableStateOf(false) } + Row(Modifier.padding(5.dp)) { + Spacer(Modifier.width(10.dp)) + Surface( + Modifier.clickable { expanded = !expanded }.fillMaxWidth(), + tonalElevation = 5.dp, + shape = MaterialTheme.shapes.medium + ) { + Column(Modifier.padding(5.dp)) { + Text("${assignment.maxN(25)} (${iGrade ?: gGrade ?: "no grade yet"})") + + if (expanded) { Row { - val (group, c) = it - val (course, ed) = c - Text(group.name, style = MaterialTheme.typography.bodyMedium) - Spacer(Modifier.width(5.dp)) - Text("(in course $course ($ed))", Modifier.align(Alignment.Bottom), style = MaterialTheme.typography.bodySmall) + Spacer(Modifier.width(10.dp)) + Column { + ItalicAndNormal("Assignment: ", assignment) + ItalicAndNormal("Group name: ", group) + ItalicAndNormal("Group grade: ", gGrade ?: "no grade yet") + ItalicAndNormal("Individual grade: ", iGrade ?: "no individual grade") + } + } + } + } + } + } +} + +@Composable +fun soloGradeWidget(sg: StudentState.LocalSoloGrade) { + val (assignment, grade) = sg + var expanded by remember { mutableStateOf(false) } + Row(Modifier.padding(5.dp)) { + Spacer(Modifier.width(10.dp)) + Surface( + Modifier.clickable { expanded = !expanded }.fillMaxWidth(), + tonalElevation = 5.dp, + shape = MaterialTheme.shapes.medium + ) { + Column(Modifier.padding(5.dp)) { + Text("${assignment.maxN(25)} (${grade ?: "no grade yet"})") + + if (expanded) { + Row { + Spacer(Modifier.width(10.dp)) + Column { + ItalicAndNormal("Assignment: ", assignment) + ItalicAndNormal("Individual grade: ", grade ?: "no grade yet") + } } } } diff --git a/composeApp/src/desktopMain/kotlin/com/jaytux/grader/ui/Widgets.kt b/composeApp/src/desktopMain/kotlin/com/jaytux/grader/ui/Widgets.kt index 28f4688..a2dd106 100644 --- a/composeApp/src/desktopMain/kotlin/com/jaytux/grader/ui/Widgets.kt +++ b/composeApp/src/desktopMain/kotlin/com/jaytux/grader/ui/Widgets.kt @@ -342,4 +342,10 @@ fun DateTimePicker( // ) // } } +} + +@Composable +fun ItalicAndNormal(italic: String, normal: String) = Row{ + Text(italic, fontStyle = FontStyle.Italic) + Text(normal) } \ No newline at end of file