resolve conflicts and merge
This commit is contained in:
		
						commit
						13b9c0591f
					
				
					 38 changed files with 1291 additions and 64 deletions
				
			
		| 
						 | 
				
			
			@ -9,7 +9,12 @@ import androidx.compose.foundation.layout.padding
 | 
			
		|||
import androidx.compose.foundation.shape.RoundedCornerShape
 | 
			
		||||
import androidx.compose.material.Text
 | 
			
		||||
import androidx.compose.material.TextButton
 | 
			
		||||
import androidx.compose.runtime.*
 | 
			
		||||
import androidx.compose.runtime.Composable
 | 
			
		||||
import androidx.compose.runtime.LaunchedEffect
 | 
			
		||||
import androidx.compose.runtime.getValue
 | 
			
		||||
import androidx.compose.runtime.mutableStateOf
 | 
			
		||||
import androidx.compose.runtime.remember
 | 
			
		||||
import androidx.compose.runtime.setValue
 | 
			
		||||
import androidx.compose.ui.Alignment
 | 
			
		||||
import androidx.compose.ui.Modifier
 | 
			
		||||
import androidx.compose.ui.graphics.Color
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,80 @@
 | 
			
		|||
package be.ugent.sel.studeez.screens.tasks
 | 
			
		||||
 | 
			
		||||
import androidx.compose.foundation.layout.Column
 | 
			
		||||
import androidx.compose.foundation.layout.padding
 | 
			
		||||
import androidx.compose.foundation.lazy.LazyColumn
 | 
			
		||||
import androidx.compose.foundation.lazy.items
 | 
			
		||||
import androidx.compose.runtime.Composable
 | 
			
		||||
import androidx.compose.runtime.collectAsState
 | 
			
		||||
import androidx.compose.ui.Modifier
 | 
			
		||||
import androidx.compose.ui.res.stringResource
 | 
			
		||||
import androidx.compose.ui.tooling.preview.Preview
 | 
			
		||||
import androidx.compose.ui.unit.dp
 | 
			
		||||
import be.ugent.sel.studeez.common.composable.NewTaskSubjectButton
 | 
			
		||||
import be.ugent.sel.studeez.common.composable.PrimaryScreenTemplate
 | 
			
		||||
import be.ugent.sel.studeez.common.composable.drawer.DrawerActions
 | 
			
		||||
import be.ugent.sel.studeez.common.composable.navbar.NavigationBarActions
 | 
			
		||||
import be.ugent.sel.studeez.common.composable.tasks.SubjectEntry
 | 
			
		||||
import be.ugent.sel.studeez.data.local.models.task.Subject
 | 
			
		||||
import kotlinx.coroutines.flow.Flow
 | 
			
		||||
import kotlinx.coroutines.flow.flowOf
 | 
			
		||||
import be.ugent.sel.studeez.R.string as AppText
 | 
			
		||||
 | 
			
		||||
@Composable
 | 
			
		||||
fun SubjectRoute(
 | 
			
		||||
    open: (String) -> Unit,
 | 
			
		||||
    viewModel: SubjectViewModel,
 | 
			
		||||
    drawerActions: DrawerActions,
 | 
			
		||||
    navigationBarActions: NavigationBarActions,
 | 
			
		||||
) {
 | 
			
		||||
    SubjectScreen(
 | 
			
		||||
        drawerActions = drawerActions,
 | 
			
		||||
        navigationBarActions = navigationBarActions,
 | 
			
		||||
        addSubject = { viewModel.addSubject(open) },
 | 
			
		||||
        getSubjects = viewModel::getSubjects,
 | 
			
		||||
        onViewSubject = { viewModel.onViewSubject(it, open) },
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Composable
 | 
			
		||||
fun SubjectScreen(
 | 
			
		||||
    drawerActions: DrawerActions,
 | 
			
		||||
    navigationBarActions: NavigationBarActions,
 | 
			
		||||
    addSubject: () -> Unit,
 | 
			
		||||
    getSubjects: () -> Flow<List<Subject>>,
 | 
			
		||||
    onViewSubject: (Subject) -> Unit,
 | 
			
		||||
) {
 | 
			
		||||
    PrimaryScreenTemplate(
 | 
			
		||||
        title = stringResource(AppText.my_subjects),
 | 
			
		||||
        drawerActions = drawerActions,
 | 
			
		||||
        navigationBarActions = navigationBarActions,
 | 
			
		||||
        barAction = {},
 | 
			
		||||
    ) {
 | 
			
		||||
        val subjects = getSubjects().collectAsState(initial = emptyList())
 | 
			
		||||
        Column(
 | 
			
		||||
            modifier = Modifier.padding(top = 5.dp)
 | 
			
		||||
        ) {
 | 
			
		||||
            LazyColumn {
 | 
			
		||||
                items(subjects.value) {
 | 
			
		||||
                    SubjectEntry(
 | 
			
		||||
                        subject = it,
 | 
			
		||||
                        onViewSubject = { onViewSubject(it) },
 | 
			
		||||
                    )
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            NewTaskSubjectButton(onClick = addSubject, AppText.new_subject)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Preview
 | 
			
		||||
@Composable
 | 
			
		||||
fun SubjectScreenPreview() {
 | 
			
		||||
    SubjectScreen(
 | 
			
		||||
        drawerActions = DrawerActions({}, {}, {}, {}, {}),
 | 
			
		||||
        navigationBarActions = NavigationBarActions({ false }, {}, {}, {}, {}, {}, {}, {}),
 | 
			
		||||
        addSubject = {},
 | 
			
		||||
        getSubjects = { flowOf() },
 | 
			
		||||
        onViewSubject = {},
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,31 @@
 | 
			
		|||
package be.ugent.sel.studeez.screens.tasks
 | 
			
		||||
 | 
			
		||||
import be.ugent.sel.studeez.data.SelectedSubject
 | 
			
		||||
import be.ugent.sel.studeez.data.local.models.task.Subject
 | 
			
		||||
import be.ugent.sel.studeez.domain.LogService
 | 
			
		||||
import be.ugent.sel.studeez.domain.SubjectDAO
 | 
			
		||||
import be.ugent.sel.studeez.navigation.StudeezDestinations
 | 
			
		||||
import be.ugent.sel.studeez.screens.StudeezViewModel
 | 
			
		||||
import dagger.hilt.android.lifecycle.HiltViewModel
 | 
			
		||||
import kotlinx.coroutines.flow.Flow
 | 
			
		||||
import javax.inject.Inject
 | 
			
		||||
 | 
			
		||||
@HiltViewModel
 | 
			
		||||
class SubjectViewModel @Inject constructor(
 | 
			
		||||
    private val subjectDAO: SubjectDAO,
 | 
			
		||||
    private val selectedSubject: SelectedSubject,
 | 
			
		||||
    logService: LogService,
 | 
			
		||||
) : StudeezViewModel(logService) {
 | 
			
		||||
    fun addSubject(open: (String) -> Unit) {
 | 
			
		||||
        open(StudeezDestinations.ADD_SUBJECT_FORM)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun getSubjects(): Flow<List<Subject>> {
 | 
			
		||||
        return subjectDAO.getSubjects()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun onViewSubject(subject: Subject, open: (String) -> Unit) {
 | 
			
		||||
        selectedSubject.set(subject)
 | 
			
		||||
        open(StudeezDestinations.TASKS_SCREEN)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,113 @@
 | 
			
		|||
package be.ugent.sel.studeez.screens.tasks
 | 
			
		||||
 | 
			
		||||
import androidx.compose.foundation.layout.Column
 | 
			
		||||
import androidx.compose.foundation.layout.padding
 | 
			
		||||
import androidx.compose.foundation.lazy.LazyColumn
 | 
			
		||||
import androidx.compose.foundation.lazy.items
 | 
			
		||||
import androidx.compose.material.Icon
 | 
			
		||||
import androidx.compose.material.IconButton
 | 
			
		||||
import androidx.compose.material.icons.Icons
 | 
			
		||||
import androidx.compose.material.icons.filled.Edit
 | 
			
		||||
import androidx.compose.runtime.Composable
 | 
			
		||||
import androidx.compose.runtime.collectAsState
 | 
			
		||||
import androidx.compose.ui.Modifier
 | 
			
		||||
import androidx.compose.ui.res.stringResource
 | 
			
		||||
import androidx.compose.ui.tooling.preview.Preview
 | 
			
		||||
import androidx.compose.ui.unit.dp
 | 
			
		||||
import be.ugent.sel.studeez.common.composable.NewTaskSubjectButton
 | 
			
		||||
import be.ugent.sel.studeez.common.composable.SecondaryScreenTemplate
 | 
			
		||||
import be.ugent.sel.studeez.common.composable.tasks.TaskEntry
 | 
			
		||||
import be.ugent.sel.studeez.data.local.models.task.Subject
 | 
			
		||||
import be.ugent.sel.studeez.data.local.models.task.Task
 | 
			
		||||
import kotlinx.coroutines.flow.Flow
 | 
			
		||||
import kotlinx.coroutines.flow.flowOf
 | 
			
		||||
import be.ugent.sel.studeez.R.string as AppText
 | 
			
		||||
 | 
			
		||||
data class TaskActions(
 | 
			
		||||
    val addTask: () -> Unit,
 | 
			
		||||
    val getSubject: () -> Subject,
 | 
			
		||||
    val getTasks: () -> Flow<List<Task>>,
 | 
			
		||||
    val deleteTask: (Task) -> Unit,
 | 
			
		||||
    val onCheckTask: (Task, Boolean) -> Unit,
 | 
			
		||||
    val editSubject: () -> Unit,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
fun getTaskActions(viewModel: TaskViewModel, open: (String) -> Unit): TaskActions {
 | 
			
		||||
    return TaskActions(
 | 
			
		||||
        addTask = { viewModel.addTask(open) },
 | 
			
		||||
        getTasks = viewModel::getTasks,
 | 
			
		||||
        getSubject = viewModel::getSelectedSubject,
 | 
			
		||||
        deleteTask = viewModel::deleteTask,
 | 
			
		||||
        onCheckTask = { task, isChecked -> viewModel.toggleTaskCompleted(task, isChecked) },
 | 
			
		||||
        editSubject = { viewModel.editSubject(open) }
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Composable
 | 
			
		||||
fun TaskRoute(
 | 
			
		||||
    goBack: () -> Unit,
 | 
			
		||||
    open: (String) -> Unit,
 | 
			
		||||
    viewModel: TaskViewModel,
 | 
			
		||||
) {
 | 
			
		||||
    TaskScreen(
 | 
			
		||||
        goBack = goBack,
 | 
			
		||||
        taskActions = getTaskActions(viewModel = viewModel, open = open),
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Composable
 | 
			
		||||
fun TaskScreen(
 | 
			
		||||
    goBack: () -> Unit,
 | 
			
		||||
    taskActions: TaskActions,
 | 
			
		||||
) {
 | 
			
		||||
    SecondaryScreenTemplate(
 | 
			
		||||
        title = taskActions.getSubject().name,
 | 
			
		||||
        popUp = goBack,
 | 
			
		||||
        barAction = { EditAction(onClick = taskActions.editSubject) }
 | 
			
		||||
    ) {
 | 
			
		||||
        val tasks = taskActions.getTasks().collectAsState(initial = emptyList())
 | 
			
		||||
        Column(
 | 
			
		||||
            modifier = Modifier.padding(top = 5.dp)
 | 
			
		||||
        ) {
 | 
			
		||||
            LazyColumn {
 | 
			
		||||
                items(tasks.value) {
 | 
			
		||||
                    TaskEntry(
 | 
			
		||||
                        task = it,
 | 
			
		||||
                        onCheckTask = { isChecked -> taskActions.onCheckTask(it, isChecked) },
 | 
			
		||||
                        onDeleteTask = { taskActions.deleteTask(it) },
 | 
			
		||||
                    )
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            NewTaskSubjectButton(onClick = taskActions.addTask, AppText.new_task)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Composable
 | 
			
		||||
fun EditAction(
 | 
			
		||||
    onClick: () -> Unit
 | 
			
		||||
) {
 | 
			
		||||
    IconButton(onClick = onClick) {
 | 
			
		||||
        Icon(
 | 
			
		||||
            imageVector = Icons.Default.Edit,
 | 
			
		||||
            contentDescription = stringResource(AppText.edit_task)
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Preview
 | 
			
		||||
@Composable
 | 
			
		||||
fun TaskScreenPreview() {
 | 
			
		||||
    TaskScreen(
 | 
			
		||||
        goBack = {},
 | 
			
		||||
        taskActions = TaskActions(
 | 
			
		||||
            {},
 | 
			
		||||
            { Subject(name = "Test Subject") },
 | 
			
		||||
            { flowOf() },
 | 
			
		||||
            {},
 | 
			
		||||
            { _, _ -> run {} },
 | 
			
		||||
            {},
 | 
			
		||||
        )
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,50 @@
 | 
			
		|||
package be.ugent.sel.studeez.screens.tasks
 | 
			
		||||
 | 
			
		||||
import be.ugent.sel.studeez.data.SelectedSubject
 | 
			
		||||
import be.ugent.sel.studeez.data.local.models.task.Subject
 | 
			
		||||
import be.ugent.sel.studeez.data.local.models.task.Task
 | 
			
		||||
import be.ugent.sel.studeez.domain.LogService
 | 
			
		||||
import be.ugent.sel.studeez.domain.SubjectDAO
 | 
			
		||||
import be.ugent.sel.studeez.domain.TaskDAO
 | 
			
		||||
import be.ugent.sel.studeez.navigation.StudeezDestinations
 | 
			
		||||
import be.ugent.sel.studeez.screens.StudeezViewModel
 | 
			
		||||
import dagger.hilt.android.lifecycle.HiltViewModel
 | 
			
		||||
import kotlinx.coroutines.flow.Flow
 | 
			
		||||
import javax.inject.Inject
 | 
			
		||||
 | 
			
		||||
@HiltViewModel
 | 
			
		||||
class TaskViewModel @Inject constructor(
 | 
			
		||||
    private val taskDAO: TaskDAO,
 | 
			
		||||
    private val subjectDAO: SubjectDAO,
 | 
			
		||||
    private val selectedSubject: SelectedSubject,
 | 
			
		||||
    logService: LogService,
 | 
			
		||||
) : StudeezViewModel(logService) {
 | 
			
		||||
    fun addTask(open: (String) -> Unit) {
 | 
			
		||||
        open(StudeezDestinations.ADD_TASK_FORM)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun getTasks(): Flow<List<Task>> {
 | 
			
		||||
        return taskDAO.getTasks(selectedSubject())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun deleteSubject(open: (String) -> Unit) {
 | 
			
		||||
        subjectDAO.deleteSubject(selectedSubject())
 | 
			
		||||
        open(StudeezDestinations.SUBJECT_SCREEN)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun getSelectedSubject(): Subject {
 | 
			
		||||
        return selectedSubject()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun deleteTask(task: Task) {
 | 
			
		||||
        taskDAO.deleteTask(task)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun toggleTaskCompleted(task: Task, completed: Boolean) {
 | 
			
		||||
        taskDAO.toggleTaskCompleted(task, completed)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun editSubject(open: (String) -> Unit) {
 | 
			
		||||
        open(StudeezDestinations.EDIT_SUBJECT_FORM)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,119 @@
 | 
			
		|||
package be.ugent.sel.studeez.screens.tasks.forms
 | 
			
		||||
 | 
			
		||||
import androidx.annotation.StringRes
 | 
			
		||||
import androidx.compose.foundation.layout.Column
 | 
			
		||||
import androidx.compose.material.OutlinedTextField
 | 
			
		||||
import androidx.compose.material.Text
 | 
			
		||||
import androidx.compose.runtime.Composable
 | 
			
		||||
import androidx.compose.runtime.getValue
 | 
			
		||||
import androidx.compose.ui.Modifier
 | 
			
		||||
import androidx.compose.ui.graphics.Color
 | 
			
		||||
import androidx.compose.ui.res.stringResource
 | 
			
		||||
import androidx.compose.ui.tooling.preview.Preview
 | 
			
		||||
import be.ugent.sel.studeez.common.composable.BasicButton
 | 
			
		||||
import be.ugent.sel.studeez.common.composable.DeleteButton
 | 
			
		||||
import be.ugent.sel.studeez.common.composable.SecondaryScreenTemplate
 | 
			
		||||
import be.ugent.sel.studeez.common.ext.basicButton
 | 
			
		||||
import be.ugent.sel.studeez.common.ext.fieldModifier
 | 
			
		||||
import be.ugent.sel.studeez.resources
 | 
			
		||||
import be.ugent.sel.studeez.R.string as AppText
 | 
			
		||||
 | 
			
		||||
@Composable
 | 
			
		||||
fun SubjectAddRoute(
 | 
			
		||||
    goBack: () -> Unit,
 | 
			
		||||
    openAndPopUp: (String, String) -> Unit,
 | 
			
		||||
    viewModel: SubjectFormViewModel,
 | 
			
		||||
) {
 | 
			
		||||
    val uiState by viewModel.uiState
 | 
			
		||||
    SubjectForm(
 | 
			
		||||
        title = AppText.new_subject,
 | 
			
		||||
        goBack = goBack,
 | 
			
		||||
        uiState = uiState,
 | 
			
		||||
        onConfirm = { viewModel.onCreate(openAndPopUp) },
 | 
			
		||||
        onNameChange = viewModel::onNameChange,
 | 
			
		||||
        onColorChange = {},
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Composable
 | 
			
		||||
fun SubjectEditRoute(
 | 
			
		||||
    goBack: () -> Unit,
 | 
			
		||||
    openAndPopUp: (String, String) -> Unit,
 | 
			
		||||
    viewModel: SubjectFormViewModel,
 | 
			
		||||
) {
 | 
			
		||||
    val uiState by viewModel.uiState
 | 
			
		||||
    SubjectForm(
 | 
			
		||||
        title = AppText.edit_subject,
 | 
			
		||||
        goBack = goBack,
 | 
			
		||||
        uiState = uiState,
 | 
			
		||||
        onConfirm = { viewModel.onEdit(openAndPopUp) },
 | 
			
		||||
        onNameChange = viewModel::onNameChange,
 | 
			
		||||
        onColorChange = {},
 | 
			
		||||
    ) {
 | 
			
		||||
        DeleteButton(text = AppText.delete_subject) {
 | 
			
		||||
            viewModel.onDelete(openAndPopUp)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Composable
 | 
			
		||||
fun SubjectForm(
 | 
			
		||||
    @StringRes title: Int,
 | 
			
		||||
    goBack: () -> Unit,
 | 
			
		||||
    uiState: SubjectFormUiState,
 | 
			
		||||
    onConfirm: () -> Unit,
 | 
			
		||||
    onNameChange: (String) -> Unit,
 | 
			
		||||
    onColorChange: (Color) -> Unit,
 | 
			
		||||
    extraButton: @Composable () -> Unit = {},
 | 
			
		||||
) {
 | 
			
		||||
    SecondaryScreenTemplate(
 | 
			
		||||
        title = resources().getString(title),
 | 
			
		||||
        popUp = goBack,
 | 
			
		||||
    ) {
 | 
			
		||||
        Column {
 | 
			
		||||
            OutlinedTextField(
 | 
			
		||||
                singleLine = true,
 | 
			
		||||
                value = uiState.name,
 | 
			
		||||
                onValueChange = onNameChange,
 | 
			
		||||
                placeholder = { Text(stringResource(id = AppText.name)) },
 | 
			
		||||
                modifier = Modifier.fieldModifier(),
 | 
			
		||||
            )
 | 
			
		||||
            BasicButton(
 | 
			
		||||
                text = AppText.confirm,
 | 
			
		||||
                modifier = Modifier.basicButton(),
 | 
			
		||||
                onClick = onConfirm,
 | 
			
		||||
            )
 | 
			
		||||
            extraButton()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Preview
 | 
			
		||||
@Composable
 | 
			
		||||
fun AddSubjectFormPreview() {
 | 
			
		||||
    SubjectForm(
 | 
			
		||||
        title = AppText.new_subject,
 | 
			
		||||
        goBack = {},
 | 
			
		||||
        uiState = SubjectFormUiState(),
 | 
			
		||||
        onConfirm = {},
 | 
			
		||||
        onNameChange = {},
 | 
			
		||||
        onColorChange = {},
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Preview
 | 
			
		||||
@Composable
 | 
			
		||||
fun EditSubjectFormPreview() {
 | 
			
		||||
    SubjectForm(
 | 
			
		||||
        title = AppText.edit_subject,
 | 
			
		||||
        goBack = {},
 | 
			
		||||
        uiState = SubjectFormUiState(
 | 
			
		||||
            name = "Test Subject",
 | 
			
		||||
        ),
 | 
			
		||||
        onConfirm = {},
 | 
			
		||||
        onNameChange = {},
 | 
			
		||||
        onColorChange = {},
 | 
			
		||||
    ) {
 | 
			
		||||
        DeleteButton(text = AppText.delete_subject) {}
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,6 @@
 | 
			
		|||
package be.ugent.sel.studeez.screens.tasks.forms
 | 
			
		||||
 | 
			
		||||
data class SubjectFormUiState(
 | 
			
		||||
    val name: String = "",
 | 
			
		||||
    val color: Long = 0xFFFFD200,
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,69 @@
 | 
			
		|||
package be.ugent.sel.studeez.screens.tasks.forms
 | 
			
		||||
 | 
			
		||||
import androidx.compose.runtime.mutableStateOf
 | 
			
		||||
import be.ugent.sel.studeez.data.SelectedSubject
 | 
			
		||||
import be.ugent.sel.studeez.data.local.models.task.Subject
 | 
			
		||||
import be.ugent.sel.studeez.domain.LogService
 | 
			
		||||
import be.ugent.sel.studeez.domain.SubjectDAO
 | 
			
		||||
import be.ugent.sel.studeez.navigation.StudeezDestinations
 | 
			
		||||
import be.ugent.sel.studeez.screens.StudeezViewModel
 | 
			
		||||
import dagger.hilt.android.lifecycle.HiltViewModel
 | 
			
		||||
import javax.inject.Inject
 | 
			
		||||
 | 
			
		||||
@HiltViewModel
 | 
			
		||||
class SubjectFormViewModel @Inject constructor(
 | 
			
		||||
    private val subjectDAO: SubjectDAO,
 | 
			
		||||
    private val selectedSubject: SelectedSubject,
 | 
			
		||||
    logService: LogService,
 | 
			
		||||
) : StudeezViewModel(logService) {
 | 
			
		||||
    var uiState = mutableStateOf(
 | 
			
		||||
        if (selectedSubject.isSet()) SubjectFormUiState(
 | 
			
		||||
            name = selectedSubject().name,
 | 
			
		||||
            color = selectedSubject().argb_color
 | 
			
		||||
        )
 | 
			
		||||
        else SubjectFormUiState()
 | 
			
		||||
    )
 | 
			
		||||
        private set
 | 
			
		||||
 | 
			
		||||
    private val name: String
 | 
			
		||||
        get() = uiState.value.name
 | 
			
		||||
 | 
			
		||||
    private val color: Long
 | 
			
		||||
        get() = uiState.value.color
 | 
			
		||||
 | 
			
		||||
    fun onNameChange(newValue: String) {
 | 
			
		||||
        uiState.value = uiState.value.copy(name = newValue)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun onColorChange(newValue: Long) {
 | 
			
		||||
        uiState.value = uiState.value.copy(color = newValue)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun onDelete(openAndPopUp: (String, String) -> Unit) {
 | 
			
		||||
        subjectDAO.deleteSubject(selectedSubject())
 | 
			
		||||
        openAndPopUp(StudeezDestinations.SUBJECT_SCREEN, StudeezDestinations.EDIT_SUBJECT_FORM)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun onCreate(openAndPopUp: (String, String) -> Unit) {
 | 
			
		||||
        val newSubject = Subject(
 | 
			
		||||
            name = name,
 | 
			
		||||
            argb_color = color,
 | 
			
		||||
        )
 | 
			
		||||
        subjectDAO.saveSubject(
 | 
			
		||||
            newSubject
 | 
			
		||||
        )
 | 
			
		||||
        // TODO open newly created subject
 | 
			
		||||
//        selectedSubject.set(newSubject)
 | 
			
		||||
//        open(StudeezDestinations.TASKS_SCREEN)
 | 
			
		||||
        openAndPopUp(StudeezDestinations.SUBJECT_SCREEN, StudeezDestinations.ADD_SUBJECT_FORM)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun onEdit(openAndPopUp: (String, String) -> Unit) {
 | 
			
		||||
        val newSubject = selectedSubject().copy(
 | 
			
		||||
            name = name,
 | 
			
		||||
            argb_color = color,
 | 
			
		||||
        )
 | 
			
		||||
        subjectDAO.updateSubject(newSubject)
 | 
			
		||||
        openAndPopUp(StudeezDestinations.TASKS_SCREEN, StudeezDestinations.EDIT_SUBJECT_FORM)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,113 @@
 | 
			
		|||
package be.ugent.sel.studeez.screens.tasks.forms
 | 
			
		||||
 | 
			
		||||
import androidx.annotation.StringRes
 | 
			
		||||
import androidx.compose.foundation.layout.Column
 | 
			
		||||
import androidx.compose.material.OutlinedTextField
 | 
			
		||||
import androidx.compose.material.Text
 | 
			
		||||
import androidx.compose.runtime.Composable
 | 
			
		||||
import androidx.compose.runtime.getValue
 | 
			
		||||
import androidx.compose.ui.Modifier
 | 
			
		||||
import androidx.compose.ui.res.stringResource
 | 
			
		||||
import androidx.compose.ui.tooling.preview.Preview
 | 
			
		||||
import be.ugent.sel.studeez.common.composable.BasicButton
 | 
			
		||||
import be.ugent.sel.studeez.common.composable.DeleteButton
 | 
			
		||||
import be.ugent.sel.studeez.common.composable.SecondaryScreenTemplate
 | 
			
		||||
import be.ugent.sel.studeez.common.ext.basicButton
 | 
			
		||||
import be.ugent.sel.studeez.common.ext.fieldModifier
 | 
			
		||||
import be.ugent.sel.studeez.resources
 | 
			
		||||
import be.ugent.sel.studeez.R.string as AppText
 | 
			
		||||
 | 
			
		||||
@Composable
 | 
			
		||||
fun TaskAddRoute(
 | 
			
		||||
    goBack: () -> Unit,
 | 
			
		||||
    openAndPopUp: (String, String) -> Unit,
 | 
			
		||||
    viewModel: TaskFormViewModel,
 | 
			
		||||
) {
 | 
			
		||||
    val uiState by viewModel.uiState
 | 
			
		||||
    TaskForm(
 | 
			
		||||
        title = AppText.new_task,
 | 
			
		||||
        goBack = goBack,
 | 
			
		||||
        uiState = uiState,
 | 
			
		||||
        onConfirm = { viewModel.onCreate(openAndPopUp) },
 | 
			
		||||
        onNameChange = viewModel::onNameChange
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Composable
 | 
			
		||||
fun TaskEditRoute(
 | 
			
		||||
    goBack: () -> Unit,
 | 
			
		||||
    openAndPopUp: (String, String) -> Unit,
 | 
			
		||||
    viewModel: TaskFormViewModel,
 | 
			
		||||
) {
 | 
			
		||||
    val uiState by viewModel.uiState
 | 
			
		||||
    TaskForm(
 | 
			
		||||
        title = AppText.edit_task,
 | 
			
		||||
        goBack = goBack,
 | 
			
		||||
        uiState = uiState,
 | 
			
		||||
        onConfirm = { viewModel.onEdit(openAndPopUp) },
 | 
			
		||||
        onNameChange = viewModel::onNameChange
 | 
			
		||||
    ) {
 | 
			
		||||
        DeleteButton(text = AppText.delete_task) {
 | 
			
		||||
            viewModel.onDelete(openAndPopUp)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Composable
 | 
			
		||||
fun TaskForm(
 | 
			
		||||
    @StringRes title: Int,
 | 
			
		||||
    goBack: () -> Unit,
 | 
			
		||||
    uiState: TaskFormUiState,
 | 
			
		||||
    onConfirm: () -> Unit,
 | 
			
		||||
    onNameChange: (String) -> Unit,
 | 
			
		||||
    extraButton: @Composable () -> Unit = {}
 | 
			
		||||
) {
 | 
			
		||||
    SecondaryScreenTemplate(
 | 
			
		||||
        title = resources().getString(title),
 | 
			
		||||
        popUp = goBack,
 | 
			
		||||
    ) {
 | 
			
		||||
        Column {
 | 
			
		||||
            OutlinedTextField(
 | 
			
		||||
                singleLine = true,
 | 
			
		||||
                value = uiState.name,
 | 
			
		||||
                onValueChange = onNameChange,
 | 
			
		||||
                placeholder = { Text(stringResource(id = AppText.name)) },
 | 
			
		||||
                modifier = Modifier.fieldModifier(),
 | 
			
		||||
            )
 | 
			
		||||
            BasicButton(
 | 
			
		||||
                text = AppText.confirm,
 | 
			
		||||
                modifier = Modifier.basicButton(),
 | 
			
		||||
                onClick = onConfirm,
 | 
			
		||||
            )
 | 
			
		||||
            extraButton()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Preview
 | 
			
		||||
@Composable
 | 
			
		||||
fun AddTaskFormPreview() {
 | 
			
		||||
    TaskForm(
 | 
			
		||||
        title = AppText.new_task,
 | 
			
		||||
        goBack = {},
 | 
			
		||||
        uiState = TaskFormUiState(),
 | 
			
		||||
        onConfirm = {},
 | 
			
		||||
        onNameChange = {},
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Preview
 | 
			
		||||
@Composable
 | 
			
		||||
fun EditTaskFormPreview() {
 | 
			
		||||
    TaskForm(
 | 
			
		||||
        title = AppText.edit_task,
 | 
			
		||||
        goBack = {},
 | 
			
		||||
        uiState = TaskFormUiState(
 | 
			
		||||
            name = "Test Task",
 | 
			
		||||
        ),
 | 
			
		||||
        onConfirm = {},
 | 
			
		||||
        onNameChange = {},
 | 
			
		||||
    ) {
 | 
			
		||||
        DeleteButton(text = AppText.delete_task) {}
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,5 @@
 | 
			
		|||
package be.ugent.sel.studeez.screens.tasks.forms
 | 
			
		||||
 | 
			
		||||
data class TaskFormUiState(
 | 
			
		||||
    val name: String = "",
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,49 @@
 | 
			
		|||
package be.ugent.sel.studeez.screens.tasks.forms
 | 
			
		||||
 | 
			
		||||
import androidx.compose.runtime.mutableStateOf
 | 
			
		||||
import be.ugent.sel.studeez.data.SelectedSubject
 | 
			
		||||
import be.ugent.sel.studeez.data.SelectedTask
 | 
			
		||||
import be.ugent.sel.studeez.data.local.models.task.Task
 | 
			
		||||
import be.ugent.sel.studeez.domain.LogService
 | 
			
		||||
import be.ugent.sel.studeez.domain.TaskDAO
 | 
			
		||||
import be.ugent.sel.studeez.navigation.StudeezDestinations
 | 
			
		||||
import be.ugent.sel.studeez.screens.StudeezViewModel
 | 
			
		||||
import dagger.hilt.android.lifecycle.HiltViewModel
 | 
			
		||||
import javax.inject.Inject
 | 
			
		||||
 | 
			
		||||
@HiltViewModel
 | 
			
		||||
class TaskFormViewModel @Inject constructor(
 | 
			
		||||
    private val taskDAO: TaskDAO,
 | 
			
		||||
    private val selectedSubject: SelectedSubject,
 | 
			
		||||
    private val selectedTask: SelectedTask,
 | 
			
		||||
    logService: LogService,
 | 
			
		||||
) : StudeezViewModel(logService) {
 | 
			
		||||
    var uiState = mutableStateOf(
 | 
			
		||||
        if (selectedTask.isSet()) TaskFormUiState(selectedTask().name) else TaskFormUiState()
 | 
			
		||||
    )
 | 
			
		||||
        private set
 | 
			
		||||
 | 
			
		||||
    private val name: String
 | 
			
		||||
        get() = uiState.value.name
 | 
			
		||||
 | 
			
		||||
    fun onNameChange(newValue: String) {
 | 
			
		||||
        uiState.value = uiState.value.copy(name = newValue)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun onDelete(openAndPopUp: (String, String) -> Unit) {
 | 
			
		||||
        taskDAO.deleteTask(selectedTask())
 | 
			
		||||
        openAndPopUp(StudeezDestinations.TASKS_SCREEN, StudeezDestinations.EDIT_TASK_FORM)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun onCreate(openAndPopUp: (String, String) -> Unit) {
 | 
			
		||||
        val newTask = Task(name = name, subjectId = selectedSubject().id)
 | 
			
		||||
        taskDAO.saveTask(newTask)
 | 
			
		||||
        openAndPopUp(StudeezDestinations.TASKS_SCREEN, StudeezDestinations.ADD_TASK_FORM)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun onEdit(openAndPopUp: (String, String) -> Unit) {
 | 
			
		||||
        val newTask = Task(name = name)
 | 
			
		||||
        taskDAO.updateTask(newTask)
 | 
			
		||||
        openAndPopUp(StudeezDestinations.TASKS_SCREEN, StudeezDestinations.EDIT_TASK_FORM)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -6,7 +6,11 @@ import androidx.compose.foundation.layout.fillMaxHeight
 | 
			
		|||
import androidx.compose.foundation.layout.fillMaxWidth
 | 
			
		||||
import androidx.compose.foundation.rememberScrollState
 | 
			
		||||
import androidx.compose.foundation.verticalScroll
 | 
			
		||||
import androidx.compose.runtime.*
 | 
			
		||||
import androidx.compose.runtime.Composable
 | 
			
		||||
import androidx.compose.runtime.getValue
 | 
			
		||||
import androidx.compose.runtime.mutableStateOf
 | 
			
		||||
import androidx.compose.runtime.remember
 | 
			
		||||
import androidx.compose.runtime.setValue
 | 
			
		||||
import androidx.compose.ui.Alignment
 | 
			
		||||
import androidx.compose.ui.Modifier
 | 
			
		||||
import be.ugent.sel.studeez.R
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Reference in a new issue