Skip to content

Commit

Permalink
Merge branch 'feature/show_executions_for_task' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
braiso-22 committed Apr 26, 2024
2 parents 97094b3 + 34580b7 commit 51699aa
Show file tree
Hide file tree
Showing 14 changed files with 478 additions and 20 deletions.
17 changes: 11 additions & 6 deletions app/src/main/java/com/braiso_22/cozycave/di/AppModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,7 @@ import com.braiso_22.cozycave.feature_execution.domain.use_case.GetExecutionsByR
import com.braiso_22.cozycave.feature_task.data.TaskRepositoryImpl
import com.braiso_22.cozycave.feature_task.data.local.dao.TaskDao
import com.braiso_22.cozycave.feature_task.domain.TaskRepository
import com.braiso_22.cozycave.feature_task.domain.use_case.AddTaskUseCase
import com.braiso_22.cozycave.feature_task.domain.use_case.DeleteTaskUseCase
import com.braiso_22.cozycave.feature_task.domain.use_case.GetTaskByIdUseCase
import com.braiso_22.cozycave.feature_task.domain.use_case.GetTasksUseCase
import com.braiso_22.cozycave.feature_task.domain.use_case.*
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
Expand Down Expand Up @@ -106,5 +103,13 @@ object AppModule {
repository: ExecutionRepository,
): GetExecutionByIdUseCase = GetExecutionByIdUseCase(repository)


}
@Provides
@Singleton
fun provideGetTaskWithExecutionsUseCase(
getTaskByIdUseCase: GetTaskByIdUseCase,
getExecutionsByRelatedIdUseCase: GetExecutionsByRelatedIdUseCase,
): GetTaskWithExecutionsUseCase = GetTaskWithExecutionsUseCase(
getTaskByIdUseCase,
getExecutionsByRelatedIdUseCase
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,21 @@ class AddEditExecutionViewModel @Inject constructor(
Log.i(TAG, "$TAG created")
savedStateHandle.get<Int>("executionId").let { executionId ->
viewModelScope.launch {
val execution = getExecutionByIdUseCase(executionId ?: return@launch)
val execution = getExecutionByIdUseCase(
executionId ?: return@launch
)
_state.value = execution.toUiState()
savedStateHandle.get<Boolean>("edit").let { isEdit ->
_state.value = _state.value.copy(
isEditExecution = isEdit ?: return@launch
)
}
savedStateHandle.get<Int>("relatedId").let { id ->
_state.value = _state.value.copy(relatedId = id ?: return@launch)
}

}
}
savedStateHandle.get<Boolean>("edit").let { isEdit ->
_state.value = _state.value.copy(
isEditExecution = isEdit ?: return@let
)
}
savedStateHandle.get<Int>("relatedId").let { id ->
_state.value = _state.value.copy(relatedId = id ?: return@let)
}
}

fun onEvent(changeState: AddEditExecutionEvent) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ fun Execution.toUiState() = AddEditExecutionUiState(

fun LocalDateTime.toFormatedDate(): String {
return this.format(
DateTimeFormatter.ofPattern("dd-MM-yyyy")
DateTimeFormatter.ofPattern("dd/MM/yyyy")
)
}

Expand All @@ -40,11 +40,11 @@ fun LocalDateTime.toFormatedTime(): String {
fun AddEditExecutionUiState.asExecution(): Execution {
return Execution(
startDateTime = LocalDateTime.of(
LocalDate.parse(startDate, DateTimeFormatter.ofPattern("dd-MM-yyyy")),
LocalDate.parse(startDate, DateTimeFormatter.ofPattern("dd/MM/yyyy")),
LocalTime.parse(startTime)
),
endDateTime = LocalDateTime.of(
LocalDate.parse(endDate, DateTimeFormatter.ofPattern("dd-MM-yyyy")),
LocalDate.parse(endDate, DateTimeFormatter.ofPattern("dd/MM/yyyy")),
LocalTime.parse(endTime)
),
relatedId = relatedId,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.braiso_22.cozycave.feature_task.domain

import com.braiso_22.cozycave.feature_execution.domain.Execution

data class TaskWithExecutions(
val task: Task,
val executions: List<Execution>,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.braiso_22.cozycave.feature_task.domain.use_case

import com.braiso_22.cozycave.feature_execution.domain.use_case.GetExecutionsByRelatedIdUseCase
import com.braiso_22.cozycave.feature_task.domain.TaskWithExecutions
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map

class GetTaskWithExecutionsUseCase(
private val getTaskByIdUseCase: GetTaskByIdUseCase,
private val getExecutionsByRelatedIdUseCase: GetExecutionsByRelatedIdUseCase,
) {
suspend operator fun invoke(taskId: Int): Flow<TaskWithExecutions> {
val task = getTaskByIdUseCase(taskId)
return getExecutionsByRelatedIdUseCase(id = task.id).map {
TaskWithExecutions(task, it)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
package com.braiso_22.cozycave.feature_task.presentation.show_task_detail

import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material3.*
import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi
import androidx.compose.material3.windowsizeclass.WindowSizeClass
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import com.braiso_22.cozycave.R
import com.braiso_22.cozycave.feature_task.presentation.show_task_detail.components.CompletedExecutionComponent
import com.braiso_22.cozycave.feature_task.presentation.show_task_detail.components.UnCompletedExecutionComponent
import com.braiso_22.cozycave.feature_task.presentation.show_task_detail.state.TaskDetailUiState

@Composable
fun TaskDetailScreen(
windowSizeClass: WindowSizeClass,
onBack: () -> Unit,
modifier: Modifier = Modifier,
viewModel: TaskDetailViewModel = hiltViewModel(),
) {
val state = viewModel.state.value
TaskDetailScreenContent(
state = state,
windowSizeClass = windowSizeClass,
onBack = onBack,
modifier = modifier,
)
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TaskDetailScreenContent(
state: TaskDetailUiState,
windowSizeClass: WindowSizeClass,
onBack: () -> Unit,
modifier: Modifier = Modifier,
) {
Scaffold(
modifier = modifier,
topBar = {
TopAppBar(
title = {
Text(
stringResource(R.string.task_detail)
)
},
colors = TopAppBarDefaults.topAppBarColors(
containerColor = MaterialTheme.colorScheme.primaryContainer,
titleContentColor = MaterialTheme.colorScheme.primary
),
navigationIcon = {
IconButton(onClick = onBack) {
Icon(
Icons.AutoMirrored.Filled.ArrowBack,
contentDescription = stringResource(R.string.back)
)
}
},
)
},
) { padding ->
LazyColumn(
modifier = Modifier
.fillMaxSize()
.padding(padding)
) {
item {
Text(
text = state.name,
style = MaterialTheme.typography.titleLarge,
modifier = Modifier.padding(8.dp)
)
Spacer(modifier = Modifier.padding(8.dp))
if (state.completedExecutions.isEmpty() && state.unFinishedExecutions.isEmpty()) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.fillMaxWidth(),
) {
Text(
text = "No executions",
Modifier.padding(8.dp)
)
}
}
}

item {
if (state.unFinishedExecutions.isNotEmpty()) {
Text(
text = "Not finished executions",
style = MaterialTheme.typography.titleMedium,
modifier = Modifier.padding(8.dp)
)
Spacer(modifier = Modifier.padding(8.dp))

}
}
itemsIndexed(state.unFinishedExecutions) { index, execution ->
UnCompletedExecutionComponent(
state = execution,
modifier = Modifier
.fillMaxSize()
.padding(16.dp)
)
if (index != state.unFinishedExecutions.lastIndex)
HorizontalDivider(
modifier = Modifier
.fillMaxSize()
.padding(horizontal = 8.dp)
)
}

item {
if (state.completedExecutions.isNotEmpty()) {
Text(
text = "Finished executions",
style = MaterialTheme.typography.titleMedium,
modifier = Modifier.padding(16.dp)
)
Spacer(modifier = Modifier.padding(8.dp))
}
}

itemsIndexed(state.completedExecutions) { index, execution ->
CompletedExecutionComponent(
state = execution,
modifier = Modifier
.fillMaxSize()
.padding(8.dp)
)
if (index != state.completedExecutions.lastIndex)
HorizontalDivider(
modifier = Modifier
.fillMaxSize()
.padding(horizontal = 8.dp)
)
}
}
}
}

@OptIn(ExperimentalMaterial3WindowSizeClassApi::class)
@Composable
private fun TaskDetailScreenContentPreview(dpSize: DpSize) {
val state = remember {
mutableStateOf(
TaskDetailUiState(),
)
}
TaskDetailScreenContent(
state = state.value,
windowSizeClass = WindowSizeClass.calculateFromSize(dpSize),
onBack = {},
modifier = Modifier.fillMaxSize()
)
}

@Preview(showBackground = true, widthDp = 360, heightDp = 720)
@Composable
private fun TaskDetailScreenContentVerticalPreview() {
TaskDetailScreenContentPreview(DpSize(360.dp, 720.dp))
}

@Preview(showBackground = true, widthDp = 720, heightDp = 360)
@Composable
private fun TaskDetailScreenContentHorizontalPreview() {
TaskDetailScreenContentPreview(DpSize(720.dp, 360.dp))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.braiso_22.cozycave.feature_task.presentation.show_task_detail

import android.util.Log
import androidx.compose.runtime.State
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.braiso_22.cozycave.feature_task.domain.use_case.GetTaskWithExecutionsUseCase
import com.braiso_22.cozycave.feature_task.presentation.show_task_detail.state.TaskDetailUiState
import com.braiso_22.cozycave.feature_task.presentation.show_task_detail.state.toUiState
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import javax.inject.Inject

const val TAG = "TaskDetailViewModel"

@HiltViewModel
class TaskDetailViewModel @Inject constructor(
private val getTaskWithExecutionsUseCase: GetTaskWithExecutionsUseCase,
private val savedStateHandle: SavedStateHandle,
) : ViewModel() {

private val _state = mutableStateOf(TaskDetailUiState())
val state: State<TaskDetailUiState> = _state

private val _taskId = mutableIntStateOf(0)

init {
Log.i(TAG, "$TAG created")
savedStateHandle.get<Int>("taskId").let { taskId ->
_taskId.intValue = taskId ?: return@let
}
viewModelScope.launch {
getTaskWithExecutionsUseCase(_taskId.intValue).collectLatest { detail ->
_state.value = detail.toUiState()
Log.i(TAG, "TaskDetail data loaded")
}
}
}
}
Loading

0 comments on commit 51699aa

Please sign in to comment.