Skip to content

Commit

Permalink
Open tag detail from list
Browse files Browse the repository at this point in the history
  • Loading branch information
Faltenreich committed Jan 7, 2024
1 parent dd48d22 commit 5a32a64
Show file tree
Hide file tree
Showing 11 changed files with 105 additions and 28 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
package com.faltenreich.diaguard.navigation.screen

class TagDetailScreen {
import androidx.compose.runtime.Composable
import com.faltenreich.diaguard.shared.di.getViewModel
import com.faltenreich.diaguard.tag.Tag
import com.faltenreich.diaguard.tag.detail.TagDetail
import org.koin.core.parameter.parametersOf

data class TagDetailScreen(private val tag: Tag) : Screen {

@Composable
override fun Content() {
TagDetail(viewModel = getViewModel { parametersOf(tag) })
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ data object TagListScreen : Screen {
get() = BottomAppBarStyle.Visible(
floatingActionButton = {
val viewModel = getViewModel<TagListViewModel>()
FloatingActionButton(onClick = { viewModel.dispatchIntent(TagListIntent.Create) }) {
FloatingActionButton(onClick = { viewModel.dispatchIntent(TagListIntent.CreateTag) }) {
Icon(
painter = painterResource(MR.images.ic_add),
contentDescription = getString(MR.strings.tag_new),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,52 @@
package com.faltenreich.diaguard.tag.detail

class TagDetail {
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.Divider
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import com.faltenreich.diaguard.MR
import com.faltenreich.diaguard.entry.list.EntryListItem
import com.faltenreich.diaguard.shared.di.inject
import com.faltenreich.diaguard.shared.localization.getString
import com.faltenreich.diaguard.shared.view.FormRow
import com.faltenreich.diaguard.shared.view.TextInput
import com.faltenreich.diaguard.tag.EntryTag

@Composable
fun TagDetail(
modifier: Modifier = Modifier,
viewModel: TagDetailViewModel = inject(),
) {
val state = viewModel.collectState()
var name by rememberSaveable { mutableStateOf("") }

LazyColumn(modifier = modifier) {
stickyHeader {
FormRow {
TextInput(
input = name,
onInputChange = { name = it },
label = getString(MR.strings.name),
modifier = Modifier.fillMaxWidth(),
supportingText = { Text(state?.inputError ?: "") },
isError = state?.inputError != null,
)
}
}
item { Divider() }
items(
items = state?.entryTags ?: emptyList(),
key = EntryTag::id,
) { entryTag ->
EntryListItem(entry = entryTag.entry)
Divider()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ import com.faltenreich.diaguard.tag.Tag
data class TagDetailState(
val tag: Tag,
val entryTags: List<EntryTag>,
val inputError: String?,
)
Original file line number Diff line number Diff line change
@@ -1,34 +1,57 @@
package com.faltenreich.diaguard.tag.detail

import com.faltenreich.diaguard.MR
import com.faltenreich.diaguard.navigation.NavigateToScreenUseCase
import com.faltenreich.diaguard.navigation.OpenModalUseCase
import com.faltenreich.diaguard.navigation.modal.TagDeleteModal
import com.faltenreich.diaguard.navigation.screen.EntryFormScreen
import com.faltenreich.diaguard.shared.architecture.ViewModel
import com.faltenreich.diaguard.shared.di.inject
import com.faltenreich.diaguard.shared.localization.getString
import com.faltenreich.diaguard.shared.validation.ValidateUseCase
import com.faltenreich.diaguard.tag.Tag
import com.faltenreich.diaguard.tag.form.RedundantTagException
import com.faltenreich.diaguard.tag.form.UniqueTagRule
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flowOf

class TagDetailViewModel(
tag: Tag,
getEntriesOfTag: GetEntriesOfTagUseCase = inject(),
private val validate: ValidateUseCase = inject(),
private val openModal: OpenModalUseCase = inject(),
private val navigateToScreen: NavigateToScreenUseCase = inject(),
) : ViewModel<TagDetailState, TagDetailIntent>() {

private val error = MutableStateFlow<String?>(null)

override val state: Flow<TagDetailState> = combine(
flowOf(tag),
getEntriesOfTag(tag),
error,
::TagDetailState,
)

override fun onIntent(intent: TagDetailIntent) {
when (intent) {
is TagDetailIntent.EditTag -> Unit
is TagDetailIntent.EditTag -> editTagIfValid(intent.tag, intent.name)
is TagDetailIntent.DeleteTag -> openModal(TagDeleteModal(intent.tag))
is TagDetailIntent.OpenEntry -> navigateToScreen(EntryFormScreen(intent.entry))
}
}

private fun editTagIfValid(tag: Tag, name: String) {
val result = validate(name, UniqueTagRule())
if (result.isSuccess) {
// TODO
error.value = null
} else {
error.value = when (result.exceptionOrNull()) {
is RedundantTagException -> getString(MR.strings.tag_already_taken)
else -> getString(MR.strings.error_unknown)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package com.faltenreich.diaguard.tag.form

data class TagFormViewState(
data class TagFormState(
val inputError: String?,
)
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ class TagFormViewModel(
private val validate: ValidateUseCase,
private val createTag: CreateTagUseCase,
private val closeModal: CloseModalUseCase,
) : ViewModel<TagFormViewState, TagFormIntent>() {
) : ViewModel<TagFormState, TagFormIntent>() {

private val error = MutableStateFlow<String?>(null)

override val state = error.map(::TagFormViewState)
override val state = error.map(::TagFormState)

override fun onIntent(intent: TagFormIntent) {
when (intent) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.faltenreich.diaguard.tag.list

import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.Divider
Expand All @@ -20,8 +22,10 @@ fun TagList(
items(viewState.tags, key = Tag::id) { tag ->
TagListItem(
tag = tag,
onDelete = { viewModel.dispatchIntent(TagListIntent.Delete(tag)) },
modifier = Modifier.animateItemPlacement(),
modifier = Modifier
.animateItemPlacement()
.fillMaxWidth()
.clickable { viewModel.dispatchIntent(TagListIntent.OpenTag(tag)) },
)
Divider()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,7 @@ import com.faltenreich.diaguard.tag.Tag

sealed interface TagListIntent {

data object Create : TagListIntent
data object CreateTag : TagListIntent

data class OpenTag(val tag: Tag) : TagListIntent
}
Original file line number Diff line number Diff line change
@@ -1,31 +1,17 @@
package com.faltenreich.diaguard.tag.list

import androidx.compose.material3.IconButton
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.faltenreich.diaguard.MR
import com.faltenreich.diaguard.shared.localization.getString
import com.faltenreich.diaguard.shared.view.FormRow
import com.faltenreich.diaguard.shared.view.ResourceIcon
import com.faltenreich.diaguard.tag.Tag

@Composable
fun TagListItem(
tag: Tag,
onDelete: () -> Unit,
modifier: Modifier = Modifier,
) {
FormRow(modifier = modifier) {
Text(
text = tag.name,
modifier = Modifier.weight(1f),
)
IconButton(onClick = { onDelete() }) {
ResourceIcon(
imageResource = MR.images.ic_delete,
contentDescription = getString(MR.strings.tag_delete),
)
}
Text(tag.name)
}
}
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
package com.faltenreich.diaguard.tag.list

import com.faltenreich.diaguard.navigation.NavigateToScreenUseCase
import com.faltenreich.diaguard.navigation.OpenModalUseCase
import com.faltenreich.diaguard.navigation.modal.TagDeleteModal
import com.faltenreich.diaguard.navigation.modal.TagFormModal
import com.faltenreich.diaguard.navigation.screen.TagDetailScreen
import com.faltenreich.diaguard.shared.architecture.ViewModel
import kotlinx.coroutines.flow.map

class TagListViewModel(
getTags: GetTagsUseCase,
private val openModal: OpenModalUseCase,
private val navigateToScreen: NavigateToScreenUseCase,
) : ViewModel<TagListViewState, TagListIntent>() {

private val tags = getTags()
override val state = tags.map(::TagListViewState)

override fun onIntent(intent: TagListIntent) {
when (intent) {
is TagListIntent.Create -> openModal(TagFormModal)
is TagListIntent.Delete -> openModal(TagDeleteModal(intent.tag))
is TagListIntent.CreateTag -> openModal(TagFormModal)
is TagListIntent.OpenTag -> navigateToScreen(TagDetailScreen(intent.tag))
}
}
}

0 comments on commit 5a32a64

Please sign in to comment.