parent
6a676c2fad
commit
6765229d37
14 changed files with 249 additions and 30 deletions
|
@ -44,6 +44,8 @@ import be.ugent.sel.studeez.screens.tasks.SubjectRoute
|
|||
import be.ugent.sel.studeez.screens.tasks.TaskRoute
|
||||
import be.ugent.sel.studeez.screens.tasks.forms.SubjectAddRoute
|
||||
import be.ugent.sel.studeez.screens.tasks.forms.SubjectEditRoute
|
||||
import be.ugent.sel.studeez.screens.tasks.forms.TaskAddRoute
|
||||
import be.ugent.sel.studeez.screens.tasks.forms.TaskEditRoute
|
||||
import be.ugent.sel.studeez.screens.timer_overview.TimerOverviewRoute
|
||||
import be.ugent.sel.studeez.screens.timer_selection.TimerSelectionRoute
|
||||
import be.ugent.sel.studeez.ui.theme.StudeezTheme
|
||||
|
@ -161,7 +163,7 @@ fun StudeezNavGraph(
|
|||
composable(StudeezDestinations.ADD_SUBJECT_FORM) {
|
||||
SubjectAddRoute(
|
||||
goBack = goBack,
|
||||
open = open,
|
||||
openAndPopUp = openAndPopUp,
|
||||
viewModel = hiltViewModel(),
|
||||
)
|
||||
}
|
||||
|
@ -169,7 +171,23 @@ fun StudeezNavGraph(
|
|||
composable(StudeezDestinations.EDIT_SUBJECT_FORM) {
|
||||
SubjectEditRoute(
|
||||
goBack = goBack,
|
||||
open = open,
|
||||
openAndPopUp = openAndPopUp,
|
||||
viewModel = hiltViewModel(),
|
||||
)
|
||||
}
|
||||
|
||||
composable(StudeezDestinations.ADD_TASK_FORM) {
|
||||
TaskAddRoute(
|
||||
goBack = goBack,
|
||||
openAndPopUp = openAndPopUp,
|
||||
viewModel = hiltViewModel(),
|
||||
)
|
||||
}
|
||||
|
||||
composable(StudeezDestinations.EDIT_TASK_FORM) {
|
||||
TaskEditRoute(
|
||||
goBack = goBack,
|
||||
openAndPopUp = openAndPopUp,
|
||||
viewModel = hiltViewModel(),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -91,10 +91,11 @@ fun StealthButtonCardPreview() {
|
|||
|
||||
@Composable
|
||||
fun DeleteButton(
|
||||
@StringRes text: Int,
|
||||
onClick: () -> Unit,
|
||||
) {
|
||||
BasicButton(
|
||||
text = R.string.delete_subject,
|
||||
text = text,
|
||||
modifier = Modifier.basicButton(),
|
||||
onClick = onClick,
|
||||
colors = ButtonDefaults.buttonColors(
|
||||
|
@ -107,7 +108,7 @@ fun DeleteButton(
|
|||
@Preview
|
||||
@Composable
|
||||
fun DeleteButtonPreview() {
|
||||
DeleteButton {}
|
||||
DeleteButton(text = R.string.delete_subject) {}
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
|
|
@ -5,7 +5,7 @@ import javax.inject.Inject
|
|||
import javax.inject.Singleton
|
||||
|
||||
/**
|
||||
* Used to communicate the selected subject from the subject overview to the task overview of that subject.
|
||||
* Used to communicate the selected subject from the subject overview other screens.
|
||||
* Because this is a singleton-class the view-models of both screens observe the same data.
|
||||
*/
|
||||
@Singleton
|
||||
|
@ -15,4 +15,6 @@ class SelectedSubject @Inject constructor() {
|
|||
fun set(subject: Subject) {
|
||||
this.subject = subject
|
||||
}
|
||||
|
||||
fun isSet() = this::subject.isInitialized
|
||||
}
|
21
app/src/main/java/be/ugent/sel/studeez/data/SelectedTask.kt
Normal file
21
app/src/main/java/be/ugent/sel/studeez/data/SelectedTask.kt
Normal file
|
@ -0,0 +1,21 @@
|
|||
package be.ugent.sel.studeez.data
|
||||
|
||||
import be.ugent.sel.studeez.data.local.models.task.Task
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
/**
|
||||
* Used to communicate the selected task from the task overview other screens.
|
||||
* Because this is a singleton-class the view-models of both screens observe the same data.
|
||||
*/
|
||||
@Singleton
|
||||
class SelectedTask @Inject constructor() {
|
||||
private lateinit var task: Task
|
||||
|
||||
operator fun invoke() = task
|
||||
fun set(task: Task) {
|
||||
this.task = task
|
||||
}
|
||||
|
||||
fun isSet() = this::task.isInitialized
|
||||
}
|
|
@ -10,6 +10,8 @@ interface TaskDAO {
|
|||
|
||||
fun saveTask(newTask: Task)
|
||||
|
||||
fun updateTask(newTask: Task)
|
||||
|
||||
fun deleteTask(oldTask: Task)
|
||||
|
||||
fun toggleTaskCompleted(task: Task, completed: Boolean)
|
||||
|
|
|
@ -22,7 +22,11 @@ class FireBaseTaskDAO @Inject constructor(
|
|||
}
|
||||
|
||||
override fun saveTask(newTask: Task) {
|
||||
TODO("Not yet implemented")
|
||||
selectedSubjectTasksCollection(newTask.subjectId).add(newTask)
|
||||
}
|
||||
|
||||
override fun updateTask(newTask: Task) {
|
||||
selectedSubjectTasksCollection(newTask.id).document(newTask.id).set(newTask)
|
||||
}
|
||||
|
||||
override fun deleteTask(oldTask: Task) {
|
||||
|
|
|
@ -15,6 +15,8 @@ object StudeezDestinations {
|
|||
const val ADD_SUBJECT_FORM = "add_subject"
|
||||
const val EDIT_SUBJECT_FORM = "edit_subject"
|
||||
const val TASKS_SCREEN = "tasks"
|
||||
const val ADD_TASK_FORM = "add_task"
|
||||
const val EDIT_TASK_FORM = "edit_task"
|
||||
|
||||
// const val SESSIONS_SCREEN = "sessions"
|
||||
const val PROFILE_SCREEN = "profile"
|
||||
|
|
|
@ -4,7 +4,6 @@ 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.ButtonDefaults
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material.IconButton
|
||||
import androidx.compose.material.icons.Icons
|
||||
|
@ -12,15 +11,12 @@ 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.graphics.Color
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import be.ugent.sel.studeez.R
|
||||
import be.ugent.sel.studeez.common.composable.BasicButton
|
||||
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.common.ext.basicButton
|
||||
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.resources
|
||||
|
@ -38,7 +34,7 @@ data class TaskActions(
|
|||
|
||||
fun getTaskActions(viewModel: TaskViewModel, open: (String) -> Unit): TaskActions {
|
||||
return TaskActions(
|
||||
addTask = viewModel::addTask,
|
||||
addTask = { viewModel.addTask(open) },
|
||||
getTasks = viewModel::getTasks,
|
||||
getSubject = viewModel::getSelectedSubject,
|
||||
deleteTask = viewModel::deleteTask,
|
||||
|
|
|
@ -19,8 +19,8 @@ class TaskViewModel @Inject constructor(
|
|||
private val selectedSubject: SelectedSubject,
|
||||
logService: LogService,
|
||||
) : StudeezViewModel(logService) {
|
||||
fun addTask() {
|
||||
|
||||
fun addTask(open: (String) -> Unit) {
|
||||
open(StudeezDestinations.ADD_TASK_FORM)
|
||||
}
|
||||
|
||||
fun getTasks(): Flow<List<Task>> {
|
||||
|
|
|
@ -21,7 +21,7 @@ import be.ugent.sel.studeez.resources
|
|||
@Composable
|
||||
fun SubjectAddRoute(
|
||||
goBack: () -> Unit,
|
||||
open: (String) -> Unit,
|
||||
openAndPopUp: (String, String) -> Unit,
|
||||
viewModel: SubjectFormViewModel,
|
||||
) {
|
||||
val uiState by viewModel.uiState
|
||||
|
@ -29,7 +29,7 @@ fun SubjectAddRoute(
|
|||
title = R.string.new_subject,
|
||||
goBack = goBack,
|
||||
uiState = uiState,
|
||||
onConfirm = { viewModel.onCreate(open) },
|
||||
onConfirm = { viewModel.onCreate(openAndPopUp) },
|
||||
onNameChange = viewModel::onNameChange,
|
||||
onColorChange = {},
|
||||
)
|
||||
|
@ -38,7 +38,7 @@ fun SubjectAddRoute(
|
|||
@Composable
|
||||
fun SubjectEditRoute(
|
||||
goBack: () -> Unit,
|
||||
open: (String) -> Unit,
|
||||
openAndPopUp: (String, String) -> Unit,
|
||||
viewModel: SubjectFormViewModel,
|
||||
) {
|
||||
val uiState by viewModel.uiState
|
||||
|
@ -46,11 +46,13 @@ fun SubjectEditRoute(
|
|||
title = R.string.edit_subject,
|
||||
goBack = goBack,
|
||||
uiState = uiState,
|
||||
onConfirm = { viewModel.onEdit(open) },
|
||||
onConfirm = { viewModel.onEdit(openAndPopUp) },
|
||||
onNameChange = viewModel::onNameChange,
|
||||
onColorChange = {},
|
||||
) {
|
||||
DeleteButton(onClick = { viewModel.onDelete(open) })
|
||||
DeleteButton(text = R.string.delete_subject) {
|
||||
viewModel.onDelete(openAndPopUp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -112,6 +114,6 @@ fun EditSubjectFormPreview() {
|
|||
onNameChange = {},
|
||||
onColorChange = {},
|
||||
) {
|
||||
DeleteButton {}
|
||||
DeleteButton(text = R.string.delete_subject) {}
|
||||
}
|
||||
}
|
|
@ -16,7 +16,13 @@ class SubjectFormViewModel @Inject constructor(
|
|||
private val selectedSubject: SelectedSubject,
|
||||
logService: LogService,
|
||||
) : StudeezViewModel(logService) {
|
||||
var uiState = mutableStateOf(SubjectFormUiState())
|
||||
var uiState = mutableStateOf(
|
||||
if (selectedSubject.isSet()) SubjectFormUiState(
|
||||
name = selectedSubject().name,
|
||||
color = selectedSubject().argb_color
|
||||
)
|
||||
else SubjectFormUiState()
|
||||
)
|
||||
private set
|
||||
|
||||
private val name: String
|
||||
|
@ -33,12 +39,12 @@ class SubjectFormViewModel @Inject constructor(
|
|||
uiState.value = uiState.value.copy(color = newValue)
|
||||
}
|
||||
|
||||
fun onDelete(open: (String) -> Unit) {
|
||||
fun onDelete(openAndPopUp: (String, String) -> Unit) {
|
||||
subjectDAO.deleteSubject(selectedSubject())
|
||||
open(StudeezDestinations.SUBJECT_SCREEN)
|
||||
openAndPopUp(StudeezDestinations.SUBJECT_SCREEN, StudeezDestinations.EDIT_SUBJECT_FORM)
|
||||
}
|
||||
|
||||
fun onCreate(open: (String) -> Unit) {
|
||||
fun onCreate(openAndPopUp: (String, String) -> Unit) {
|
||||
val newSubject = Subject(
|
||||
name = name,
|
||||
argb_color = color,
|
||||
|
@ -46,20 +52,18 @@ class SubjectFormViewModel @Inject constructor(
|
|||
subjectDAO.saveSubject(
|
||||
newSubject
|
||||
)
|
||||
selectedSubject.set(newSubject)
|
||||
// TODO open newly created subject
|
||||
// selectedSubject.set(newSubject)
|
||||
// open(StudeezDestinations.TASKS_SCREEN)
|
||||
open(StudeezDestinations.SUBJECT_SCREEN)
|
||||
openAndPopUp(StudeezDestinations.SUBJECT_SCREEN, StudeezDestinations.ADD_SUBJECT_FORM)
|
||||
}
|
||||
|
||||
fun onEdit(open: (String) -> Unit) {
|
||||
fun onEdit(openAndPopUp: (String, String) -> Unit) {
|
||||
val newSubject = selectedSubject().copy(
|
||||
name = name,
|
||||
argb_color = color,
|
||||
)
|
||||
subjectDAO.updateSubject(
|
||||
newSubject
|
||||
)
|
||||
open(StudeezDestinations.TASKS_SCREEN)
|
||||
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.R
|
||||
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
|
||||
|
||||
@Composable
|
||||
fun TaskAddRoute(
|
||||
goBack: () -> Unit,
|
||||
openAndPopUp: (String, String) -> Unit,
|
||||
viewModel: TaskFormViewModel,
|
||||
) {
|
||||
val uiState by viewModel.uiState
|
||||
TaskForm(
|
||||
title = R.string.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 = R.string.edit_task,
|
||||
goBack = goBack,
|
||||
uiState = uiState,
|
||||
onConfirm = { viewModel.onEdit(openAndPopUp) },
|
||||
onNameChange = viewModel::onNameChange
|
||||
) {
|
||||
DeleteButton(text = R.string.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 = R.string.name)) },
|
||||
modifier = Modifier.fieldModifier(),
|
||||
)
|
||||
BasicButton(
|
||||
text = R.string.confirm,
|
||||
modifier = Modifier.basicButton(),
|
||||
onClick = onConfirm,
|
||||
)
|
||||
extraButton()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun AddTaskFormPreview() {
|
||||
TaskForm(
|
||||
title = R.string.new_task,
|
||||
goBack = {},
|
||||
uiState = TaskFormUiState(),
|
||||
onConfirm = {},
|
||||
onNameChange = {},
|
||||
)
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun EditTaskFormPreview() {
|
||||
TaskForm(
|
||||
title = R.string.edit_task,
|
||||
goBack = {},
|
||||
uiState = TaskFormUiState(
|
||||
name = "Test Task",
|
||||
),
|
||||
onConfirm = {},
|
||||
onNameChange = {},
|
||||
) {
|
||||
DeleteButton(text = R.string.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)
|
||||
}
|
||||
}
|
Reference in a new issue