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 abea207..d31498f 100644 --- a/composeApp/src/desktopMain/kotlin/com/jaytux/grader/ui/Assignments.kt +++ b/composeApp/src/desktopMain/kotlin/com/jaytux/grader/ui/Assignments.kt @@ -20,8 +20,6 @@ import com.mohamedrejeb.richeditor.ui.material3.OutlinedRichTextEditor @OptIn(ExperimentalMaterial3Api::class) @Composable fun GroupAssignmentView(state: GroupAssignmentState) { - val (course, edition) = state.editionCourse - val name by state.name val task by state.task val deadline by state.deadline val allFeedback by state.feedback.entities @@ -29,7 +27,6 @@ fun GroupAssignmentView(state: GroupAssignmentState) { var idx by remember(state) { mutableStateOf(0) } Column(Modifier.padding(10.dp)) { - PaneHeader(name, "group assignment", course, edition) if(allFeedback.any { it.second.feedback == null }) { Text("Groups in bold have no feedback yet.", fontStyle = FontStyle.Italic) } @@ -150,8 +147,6 @@ fun groupFeedback(state: GroupAssignmentState, fdbk: GroupAssignmentState.LocalG @OptIn(ExperimentalMaterial3Api::class) @Composable fun SoloAssignmentView(state: SoloAssignmentState) { - val name by state.name - val (course, edition) = state.editionCourse val task by state.task val deadline by state.deadline val suggestions by state.autofill.entities @@ -160,7 +155,6 @@ fun SoloAssignmentView(state: SoloAssignmentState) { var idx by remember(state) { mutableStateOf(0) } Column(Modifier.padding(10.dp)) { - PaneHeader(name, "individual assignment", course, edition) Row { Surface(Modifier.weight(0.25f), tonalElevation = 10.dp) { LazyColumn(Modifier.fillMaxHeight().padding(10.dp)) { diff --git a/composeApp/src/desktopMain/kotlin/com/jaytux/grader/ui/Editions.kt b/composeApp/src/desktopMain/kotlin/com/jaytux/grader/ui/Editions.kt index ffc0177..a6d6187 100644 --- a/composeApp/src/desktopMain/kotlin/com/jaytux/grader/ui/Editions.kt +++ b/composeApp/src/desktopMain/kotlin/com/jaytux/grader/ui/Editions.kt @@ -15,10 +15,6 @@ import androidx.compose.ui.window.* import com.jaytux.grader.data.* import com.jaytux.grader.viewmodel.* -enum class OpenPanel(val tabName: String) { - Student("Students"), Group("Groups"), Assignment("Assignments") -} - data class Navigators( val student: (Student) -> Unit, val group: (Group) -> Unit, @@ -36,41 +32,41 @@ fun EditionView(state: EditionState) = Row(Modifier.padding(0.dp)) { val mergedAssignments by remember(solo, groupAs) { mutableStateOf(Assignment.merge(groupAs, solo)) } - var selected by remember { mutableStateOf(-1) } - var tab by remember { mutableStateOf(OpenPanel.Assignment) } + val hist by state.history val navs = Navigators( - student = { tab = OpenPanel.Student; selected = students.indexOfFirst { s -> s.id == it.id } }, - group = { tab = OpenPanel.Group; selected = groups.indexOfFirst { g -> g.id == it.id } }, - assignment = { tab = OpenPanel.Assignment; selected = mergedAssignments.indexOfFirst { a -> a.id() == it.id() } } + student = { state.navTo(OpenPanel.Student, students.indexOfFirst{ s -> s.id == it.id }) }, + group = { state.navTo(OpenPanel.Group, groups.indexOfFirst { g -> g.id == it.id }) }, + assignment = { state.navTo(OpenPanel.Assignment, mergedAssignments.indexOfFirst { a -> a.id() == it.id() }) } ) + val (id, tab) = hist.last() Surface(Modifier.weight(0.25f), tonalElevation = 5.dp) { TabLayout( OpenPanel.entries, tab.ordinal, - { tab = OpenPanel.entries[it]; selected = -1 }, + { state.navTo(OpenPanel.entries[it]) }, { Text(it.tabName) } ) { when(tab) { OpenPanel.Student -> StudentPanel( - course, edition, students, availableStudents, selected, - { selected = it }, + course, edition, students, availableStudents, id, + { state.navTo(it) }, { name, note, contact, add -> state.newStudent(name, contact, note, add) }, { students -> state.addToCourse(students) }, { s, name -> state.setStudentName(s, name) } ) { s -> state.delete(s) } OpenPanel.Group -> GroupPanel( - course, edition, groups, selected, - { selected = it }, + course, edition, groups, id, + { state.navTo(it) }, { name -> state.newGroup(name) }, { g, name -> state.setGroupName(g, name) } ) { g -> state.delete(g) } OpenPanel.Assignment -> AssignmentPanel( - course, edition, mergedAssignments, selected, - { selected = it }, + course, edition, mergedAssignments, id, + { state.navTo(it) }, { type, name -> state.newAssignment(type, name) }, { a, name -> state.setAssignmentTitle(a, name) } ) { a -> state.delete(a) } @@ -78,15 +74,36 @@ fun EditionView(state: EditionState) = Row(Modifier.padding(0.dp)) { } } - Box(Modifier.weight(0.75f)) { - if(selected != -1) { + Column(Modifier.weight(0.75f)) { + Row { + IconButton({ state.back() }, enabled = hist.size >= 2) { + Icon(ChevronLeft, "Back", Modifier.size(MaterialTheme.typography.headlineMedium.fontSize.toDp()).align(Alignment.CenterVertically)) + } when(tab) { - OpenPanel.Student -> StudentView(StudentState(students[selected], edition), navs) - OpenPanel.Group -> GroupView(GroupState(groups[selected]), navs) + OpenPanel.Student -> { + if(id == -1) PaneHeader("Nothing selected", "students", course, edition) + else PaneHeader(students[id].name, "student", course, edition) + } + OpenPanel.Group -> { + if(id == -1) PaneHeader("Nothing selected", "groups", course, edition) + else PaneHeader(groups[id].name, "group", course, edition) + } OpenPanel.Assignment -> { - when(val a = mergedAssignments[selected]) { - is Assignment.SAssignment -> SoloAssignmentView(SoloAssignmentState(a.assignment)) - is Assignment.GAssignment -> GroupAssignmentView(GroupAssignmentState(a.assignment)) + if(id == -1) PaneHeader("Nothing selected", "assignments", course, edition) + else PaneHeader(mergedAssignments[id].name(), "assignment", course, edition) + } + } + } + Box(Modifier.weight(1f)) { + if (id != -1) { + when (tab) { + OpenPanel.Student -> StudentView(StudentState(students[id], edition), navs) + OpenPanel.Group -> GroupView(GroupState(groups[id]), navs) + OpenPanel.Assignment -> { + when (val a = mergedAssignments[id]) { + is Assignment.SAssignment -> SoloAssignmentView(SoloAssignmentState(a.assignment)) + is Assignment.GAssignment -> GroupAssignmentView(GroupAssignmentState(a.assignment)) + } } } } 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 7831368..8b0e379 100644 --- a/composeApp/src/desktopMain/kotlin/com/jaytux/grader/ui/Views.kt +++ b/composeApp/src/desktopMain/kotlin/com/jaytux/grader/ui/Views.kt @@ -17,8 +17,6 @@ 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.data.Group -import com.jaytux.grader.data.Student import com.jaytux.grader.maxN import com.jaytux.grader.viewmodel.GroupState import com.jaytux.grader.viewmodel.StudentState @@ -31,7 +29,6 @@ fun StudentView(state: StudentState, nav: Navigators) { val soloGrades by state.soloGrades.entities Column(Modifier.padding(10.dp)) { - PaneHeader(state.student.name, "student", state.editionCourse) Row { Column(Modifier.weight(0.45f)) { Column(Modifier.padding(10.dp).weight(0.35f)) { @@ -150,12 +147,10 @@ fun GroupView(state: GroupState, nav: Navigators) { val members by state.members.entities val available by state.availableStudents.entities val allRoles by state.roles.entities - val (course, edition) = state.course var pickRole: Pair Unit>? by remember { mutableStateOf(null) } Column(Modifier.padding(10.dp)) { - PaneHeader(state.group.name, "group", course, edition) Row { Column(Modifier.weight(0.5f)) { Text("Students", style = MaterialTheme.typography.headlineSmall) diff --git a/composeApp/src/desktopMain/kotlin/com/jaytux/grader/viewmodel/DbState.kt b/composeApp/src/desktopMain/kotlin/com/jaytux/grader/viewmodel/DbState.kt index 0f8cb5f..dfcc283 100644 --- a/composeApp/src/desktopMain/kotlin/com/jaytux/grader/viewmodel/DbState.kt +++ b/composeApp/src/desktopMain/kotlin/com/jaytux/grader/viewmodel/DbState.kt @@ -87,12 +87,18 @@ class EditionListState(val course: Course) { } } +enum class OpenPanel(val tabName: String) { + Student("Students"), Group("Groups"), Assignment("Assignments") +} + class EditionState(val edition: Edition) { val course = transaction { edition.course } val students = RawDbState { edition.soloStudents.sortAsc(Students.name).toList() } val groups = RawDbState { edition.groups.sortAsc(Groups.name).toList() } val solo = RawDbState { edition.soloAssignments.sortAsc(SoloAssignments.name).toList() } val groupAs = RawDbState { edition.groupAssignments.sortAsc(GroupAssignments.name).toList() } + private val _history = mutableStateOf(listOf(-1 to OpenPanel.Assignment)) + val history = _history.immutable() val availableStudents = RawDbState { Student.find { @@ -217,6 +223,16 @@ class EditionState(val edition: Edition) { is Assignment.GAssignment -> delete(assignment.assignment) is Assignment.SAssignment -> delete(assignment.assignment) } + + fun navTo(panel: OpenPanel, id: Int = -1) { + _history.value += (id to panel) + } + fun navTo(id: Int) = navTo(_history.value.last().second, id) + fun back() { + var temp = _history.value.dropLast(1) + while(temp.last().first == -1 && temp.size >= 2) temp = temp.dropLast(1) + _history.value = temp + } } class StudentState(val student: Student, edition: Edition) {