"#22 styling of task overview"
This commit is contained in:
parent
1a2e192227
commit
e1c05bb0d4
9 changed files with 140 additions and 37 deletions
|
@ -158,7 +158,8 @@ fun StudeezNavGraph(
|
||||||
|
|
||||||
composable(StudeezDestinations.TASKS_SCREEN) {
|
composable(StudeezDestinations.TASKS_SCREEN) {
|
||||||
TaskRoute(
|
TaskRoute(
|
||||||
viewModel = hiltViewModel()
|
goBack = goBack,
|
||||||
|
viewModel = hiltViewModel(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,6 @@ import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.layout.width
|
|
||||||
import androidx.compose.foundation.shape.CircleShape
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
import androidx.compose.material.Card
|
import androidx.compose.material.Card
|
||||||
import androidx.compose.material.Icon
|
import androidx.compose.material.Icon
|
||||||
|
@ -31,6 +30,7 @@ import be.ugent.sel.studeez.data.local.models.timer_functional.HoursMinutesSecon
|
||||||
@Composable
|
@Composable
|
||||||
fun SubjectEntry(
|
fun SubjectEntry(
|
||||||
subject: Subject,
|
subject: Subject,
|
||||||
|
onViewSubject: () -> Unit,
|
||||||
) {
|
) {
|
||||||
Card(
|
Card(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
@ -40,12 +40,13 @@ fun SubjectEntry(
|
||||||
Row(
|
Row(
|
||||||
horizontalArrangement = Arrangement.SpaceBetween,
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
// modifier = Modifier.fillMaxWidth(),
|
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
modifier = Modifier.padding(start = 10.dp).weight(3f)
|
modifier = Modifier
|
||||||
|
.padding(start = 10.dp)
|
||||||
|
.weight(3f)
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
@ -61,8 +62,6 @@ fun SubjectEntry(
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
// modifier = Modifier.fillMaxWidth(),
|
|
||||||
// modifier = Modifier.width(200.dp)
|
|
||||||
)
|
)
|
||||||
Row(
|
Row(
|
||||||
horizontalArrangement = Arrangement.spacedBy(10.dp),
|
horizontalArrangement = Arrangement.spacedBy(10.dp),
|
||||||
|
@ -78,16 +77,18 @@ fun SubjectEntry(
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = Icons.Default.List, contentDescription = "tasks"
|
imageVector = Icons.Default.List, contentDescription = "tasks"
|
||||||
)
|
)
|
||||||
Text(text = "4/9")
|
Text(text = subject.tasks.size.toString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StealthButton(
|
StealthButton(
|
||||||
text = R.string.view_task,
|
text = R.string.view_task,
|
||||||
modifier = Modifier.padding(start = 10.dp, end = 5.dp).weight(1f)
|
modifier = Modifier
|
||||||
) {
|
.padding(start = 10.dp, end = 5.dp)
|
||||||
|
.weight(1f)
|
||||||
|
) {
|
||||||
|
onViewSubject()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,10 +99,9 @@ fun SubjectEntry(
|
||||||
fun SubjectEntryPreview() {
|
fun SubjectEntryPreview() {
|
||||||
SubjectEntry(
|
SubjectEntry(
|
||||||
subject = Subject(
|
subject = Subject(
|
||||||
name = "Test Subject longgggggggggggggggggggggggggggggggggggggggg",
|
name = "Test Subject",
|
||||||
// name = "Test Subject",
|
|
||||||
argb_color = 0xFFF44336,
|
argb_color = 0xFFF44336,
|
||||||
time = 60
|
time = 60
|
||||||
)
|
),
|
||||||
)
|
) {}
|
||||||
}
|
}
|
|
@ -1,11 +1,12 @@
|
||||||
package be.ugent.sel.studeez.domain
|
package be.ugent.sel.studeez.domain
|
||||||
|
|
||||||
|
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.data.local.models.task.Task
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
interface TaskDAO {
|
interface TaskDAO {
|
||||||
|
|
||||||
fun getTasks(): Flow<List<Task>>
|
fun getTasks(subject: Subject): Flow<List<Task>>
|
||||||
|
|
||||||
fun saveTask(newTask: Task)
|
fun saveTask(newTask: Task)
|
||||||
|
|
||||||
|
|
|
@ -1,18 +1,31 @@
|
||||||
package be.ugent.sel.studeez.domain.implementation
|
package be.ugent.sel.studeez.domain.implementation
|
||||||
|
|
||||||
|
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.data.local.models.task.Task
|
||||||
import be.ugent.sel.studeez.domain.AccountDAO
|
import be.ugent.sel.studeez.domain.AccountDAO
|
||||||
import be.ugent.sel.studeez.domain.TaskDAO
|
import be.ugent.sel.studeez.domain.TaskDAO
|
||||||
import com.google.firebase.firestore.FirebaseFirestore
|
import com.google.firebase.firestore.FirebaseFirestore
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.flowOf
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class FireBaseTaskDAO @Inject constructor(
|
class FireBaseTaskDAO @Inject constructor(
|
||||||
private val firestore: FirebaseFirestore,
|
private val firestore: FirebaseFirestore,
|
||||||
private val auth: AccountDAO,
|
private val auth: AccountDAO,
|
||||||
) : TaskDAO {
|
) : TaskDAO {
|
||||||
override fun getTasks(): Flow<List<Task>> {
|
override fun getTasks(subject: Subject): Flow<List<Task>> {
|
||||||
TODO("Not yet implemented")
|
return flowOf(
|
||||||
|
listOf(
|
||||||
|
Task(
|
||||||
|
name = "Test Task",
|
||||||
|
completed = false,
|
||||||
|
),
|
||||||
|
Task(
|
||||||
|
name = "Test Task 2",
|
||||||
|
completed = true,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun saveTask(newTask: Task) {
|
override fun saveTask(newTask: Task) {
|
||||||
|
|
|
@ -31,7 +31,9 @@ fun SubjectRoute(
|
||||||
drawerActions = drawerActions,
|
drawerActions = drawerActions,
|
||||||
navigationBarActions = navigationBarActions,
|
navigationBarActions = navigationBarActions,
|
||||||
addSubject = { viewModel.addSubject() },
|
addSubject = { viewModel.addSubject() },
|
||||||
) { viewModel.getSubjects() }
|
getSubjects = viewModel::getSubjects,
|
||||||
|
onViewSubject = { viewModel.onViewSubject(Subject(), open) },
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
@ -40,6 +42,7 @@ fun SubjectScreen(
|
||||||
navigationBarActions: NavigationBarActions,
|
navigationBarActions: NavigationBarActions,
|
||||||
addSubject: () -> Unit,
|
addSubject: () -> Unit,
|
||||||
getSubjects: () -> Flow<List<Subject>>,
|
getSubjects: () -> Flow<List<Subject>>,
|
||||||
|
onViewSubject: () -> Unit,
|
||||||
) {
|
) {
|
||||||
PrimaryScreenTemplate(
|
PrimaryScreenTemplate(
|
||||||
title = resources().getString(R.string.tasks),
|
title = resources().getString(R.string.tasks),
|
||||||
|
@ -66,7 +69,10 @@ fun SubjectScreen(
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
items(subjects.value) {
|
items(subjects.value) {
|
||||||
SubjectEntry(subject = it)
|
SubjectEntry(
|
||||||
|
subject = it,
|
||||||
|
onViewSubject = onViewSubject,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NewTaskSubjectButton(onClick = addSubject, R.string.new_subject)
|
NewTaskSubjectButton(onClick = addSubject, R.string.new_subject)
|
||||||
|
@ -80,6 +86,8 @@ fun SubjectScreenPreview() {
|
||||||
SubjectScreen(
|
SubjectScreen(
|
||||||
drawerActions = DrawerActions({}, {}, {}, {}, {}),
|
drawerActions = DrawerActions({}, {}, {}, {}, {}),
|
||||||
navigationBarActions = NavigationBarActions({ false }, {}, {}, {}, {}),
|
navigationBarActions = NavigationBarActions({ false }, {}, {}, {}, {}),
|
||||||
{},
|
addSubject = {},
|
||||||
) { flowOf() }
|
getSubjects = { flowOf() },
|
||||||
|
onViewSubject = {},
|
||||||
|
)
|
||||||
}
|
}
|
|
@ -3,6 +3,7 @@ package be.ugent.sel.studeez.screens.tasks
|
||||||
import be.ugent.sel.studeez.data.local.models.task.Subject
|
import be.ugent.sel.studeez.data.local.models.task.Subject
|
||||||
import be.ugent.sel.studeez.domain.LogService
|
import be.ugent.sel.studeez.domain.LogService
|
||||||
import be.ugent.sel.studeez.domain.SubjectDAO
|
import be.ugent.sel.studeez.domain.SubjectDAO
|
||||||
|
import be.ugent.sel.studeez.navigation.StudeezDestinations
|
||||||
import be.ugent.sel.studeez.screens.StudeezViewModel
|
import be.ugent.sel.studeez.screens.StudeezViewModel
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
@ -27,4 +28,8 @@ class SubjectViewModel @Inject constructor(
|
||||||
fun getSubjects(): Flow<List<Subject>> {
|
fun getSubjects(): Flow<List<Subject>> {
|
||||||
return subjectDAO.getSubjects()
|
return subjectDAO.getSubjects()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun onViewSubject(subject: Subject, open: (String) -> Unit) {
|
||||||
|
open(StudeezDestinations.TASKS_SCREEN)
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,34 +1,115 @@
|
||||||
package be.ugent.sel.studeez.screens.tasks
|
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.ButtonDefaults
|
||||||
|
import androidx.compose.material.Icon
|
||||||
|
import androidx.compose.material.IconButton
|
||||||
|
import androidx.compose.material.Text
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.Edit
|
||||||
import androidx.compose.runtime.Composable
|
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.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.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.data.local.models.task.Task
|
||||||
|
import be.ugent.sel.studeez.resources
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.flowOf
|
import kotlinx.coroutines.flow.flowOf
|
||||||
|
|
||||||
|
data class TaskActions(
|
||||||
|
val addTask: () -> Unit,
|
||||||
|
val getSubject: () -> Subject,
|
||||||
|
val getTasks: () -> Flow<List<Task>>,
|
||||||
|
val deleteSubject: () -> Unit,
|
||||||
|
)
|
||||||
|
|
||||||
|
fun getTaskActions(viewModel: TaskViewModel): TaskActions {
|
||||||
|
return TaskActions(
|
||||||
|
addTask = viewModel::addTask,
|
||||||
|
getTasks = viewModel::getTasks,
|
||||||
|
getSubject = { Subject(name = "Test Subject") },
|
||||||
|
deleteSubject = {},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun TaskRoute(
|
fun TaskRoute(
|
||||||
|
goBack: () -> Unit,
|
||||||
viewModel: TaskViewModel,
|
viewModel: TaskViewModel,
|
||||||
) {
|
) {
|
||||||
TaskScreen(
|
TaskScreen(
|
||||||
addTask = viewModel::addTask,
|
goBack = goBack,
|
||||||
getTasks = viewModel::getTasks,
|
taskActions = getTaskActions(viewModel = viewModel),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun TaskScreen(
|
fun TaskScreen(
|
||||||
addTask: () -> Unit,
|
goBack: () -> Unit,
|
||||||
getTasks: () -> Flow<List<Task>>,
|
taskActions: TaskActions,
|
||||||
) {
|
) {
|
||||||
|
SecondaryScreenTemplate(
|
||||||
|
title = taskActions.getSubject().name,
|
||||||
|
popUp = goBack,
|
||||||
|
barAction = { EditAction {} } // TODO implement
|
||||||
|
) {
|
||||||
|
val tasks = taskActions.getTasks().collectAsState(initial = emptyList())
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.padding(top = 5.dp)
|
||||||
|
) {
|
||||||
|
LazyColumn {
|
||||||
|
items(tasks.value) {
|
||||||
|
Text(text = it.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NewTaskSubjectButton(onClick = taskActions.addTask, R.string.new_task)
|
||||||
|
BasicButton(
|
||||||
|
text = R.string.delete_subject,
|
||||||
|
modifier = Modifier.basicButton(),
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
backgroundColor = Color.Red,
|
||||||
|
contentColor = Color.White,
|
||||||
|
),
|
||||||
|
onClick = taskActions.deleteSubject,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun EditAction(
|
||||||
|
onClick: () -> Unit
|
||||||
|
) {
|
||||||
|
IconButton(onClick = onClick) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Default.Edit,
|
||||||
|
contentDescription = resources().getString(R.string.edit_task)
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Preview
|
@Preview
|
||||||
@Composable
|
@Composable
|
||||||
fun TaskScreenPreview() {
|
fun TaskScreenPreview() {
|
||||||
TaskScreen(
|
TaskScreen(
|
||||||
addTask = {},
|
goBack = {},
|
||||||
getTasks = { flowOf() }
|
taskActions = TaskActions(
|
||||||
|
{},
|
||||||
|
{ Subject(name = "Test Subject") },
|
||||||
|
{ flowOf() },
|
||||||
|
{},
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
package be.ugent.sel.studeez.screens.tasks
|
package be.ugent.sel.studeez.screens.tasks
|
||||||
|
|
||||||
|
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.data.local.models.task.Task
|
||||||
import be.ugent.sel.studeez.domain.LogService
|
import be.ugent.sel.studeez.domain.LogService
|
||||||
import be.ugent.sel.studeez.domain.TaskDAO
|
import be.ugent.sel.studeez.domain.TaskDAO
|
||||||
|
@ -19,15 +20,6 @@ class TaskViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getTasks() : Flow<List<Task>> {
|
fun getTasks() : Flow<List<Task>> {
|
||||||
return flowOf(listOf(
|
return taskDAO.getTasks(Subject())
|
||||||
Task(
|
|
||||||
name = "Test Task",
|
|
||||||
completed = false,
|
|
||||||
),
|
|
||||||
Task(
|
|
||||||
name = "Test Task 2",
|
|
||||||
completed = true,
|
|
||||||
)
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -45,6 +45,8 @@
|
||||||
<string name="new_subject">New Subject</string>
|
<string name="new_subject">New Subject</string>
|
||||||
<string name="new_task">New Task</string>
|
<string name="new_task">New Task</string>
|
||||||
<string name="view_task">View</string>
|
<string name="view_task">View</string>
|
||||||
|
<string name="edit_task">Edit Task</string>
|
||||||
|
<string name="delete_subject">Delete Subject</string>
|
||||||
|
|
||||||
<!-- Sessions -->
|
<!-- Sessions -->
|
||||||
<string name="sessions">Sessions</string>
|
<string name="sessions">Sessions</string>
|
||||||
|
|
Reference in a new issue