Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Qa/72 인물 봉투 상세에서 봉투 생성 플로우 추가 #154

Merged
merged 3 commits into from
Feb 16, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -11,6 +11,7 @@ import androidx.navigation.navOptions
import com.susu.core.designsystem.theme.SusuTheme
import com.susu.core.model.Envelope
import com.susu.core.model.EnvelopeDetail
import com.susu.core.model.Friend
import com.susu.core.model.Ledger
import com.susu.core.model.Vote
import com.susu.feature.community.navigation.CommunityRoute
@@ -123,8 +124,8 @@ internal class MainNavigator(
navController.navigateSentEnvelopeEdit(envelopeDetail)
}

fun navigateSentEnvelopeAdd() {
navController.navigateSentEnvelopeAdd()
fun navigateSentEnvelopeAdd(friend: Friend? = null) {
navController.navigateSentEnvelopeAdd(friend)
}

fun navigateSentEnvelopeSearch() {
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.susu.feature.envelope

import com.susu.core.model.EnvelopeSearch
import com.susu.core.model.Friend
import com.susu.core.model.FriendStatistics
import com.susu.core.ui.base.SideEffect
import com.susu.core.ui.base.UiState
@@ -15,6 +16,7 @@ data class SentEnvelopeState(

sealed interface SentEnvelopeSideEffect : SideEffect {
data class NavigateEnvelopeDetail(val id: Long) : SentEnvelopeSideEffect
data class NavigateEnvelopeAdd(val friend: Friend) : SentEnvelopeSideEffect
data object PopBackStack : SentEnvelopeSideEffect
data class PopBackStackWithDeleteFriendId(val id: Long) : SentEnvelopeSideEffect
}
Original file line number Diff line number Diff line change
@@ -39,13 +39,15 @@ import com.susu.core.designsystem.component.appbar.icon.BackIcon
import com.susu.core.designsystem.component.badge.BadgeColor
import com.susu.core.designsystem.component.badge.BadgeStyle
import com.susu.core.designsystem.component.badge.SusuBadge
import com.susu.core.designsystem.component.button.SusuFloatingButton
import com.susu.core.designsystem.theme.Gray10
import com.susu.core.designsystem.theme.Gray100
import com.susu.core.designsystem.theme.Gray20
import com.susu.core.designsystem.theme.Gray60
import com.susu.core.designsystem.theme.Gray90
import com.susu.core.designsystem.theme.Orange20
import com.susu.core.designsystem.theme.SusuTheme
import com.susu.core.model.Friend
import com.susu.core.ui.extension.OnBottomReached
import com.susu.core.ui.extension.collectWithLifecycle
import com.susu.core.ui.extension.toMoneyFormat
@@ -63,6 +65,7 @@ fun SentEnvelopeRoute(
popBackStackWithEditedFriendId: (Long) -> Unit,
editedFriendId: Long?,
navigateSentEnvelopeDetail: (Long) -> Unit,
navigateSentEnvelopeAdd: (Friend) -> Unit,
) {
val uiState = viewModel.uiState.collectAsStateWithLifecycle().value
val historyListState = rememberLazyListState()
@@ -79,6 +82,7 @@ fun SentEnvelopeRoute(

is SentEnvelopeSideEffect.NavigateEnvelopeDetail -> navigateSentEnvelopeDetail(sideEffect.id)
is SentEnvelopeSideEffect.PopBackStackWithDeleteFriendId -> popBackStackWithDeleteFriendId(sideEffect.id)
is SentEnvelopeSideEffect.NavigateEnvelopeAdd -> navigateSentEnvelopeAdd(sideEffect.friend)
}
}

@@ -107,6 +111,7 @@ fun SentEnvelopeRoute(
refreshState = refreshState,
onClickBackIcon = viewModel::popBackStack,
onClickEnvelopeDetail = viewModel::navigateSentEnvelopeDetail,
onClickAddEnvelope = viewModel::navigateSentEnvelopeAdd,
)
}

@@ -119,6 +124,7 @@ fun SentEnvelopeScreen(
historyListState: LazyListState = rememberLazyListState(),
onClickBackIcon: () -> Unit = {},
onClickEnvelopeDetail: (Long) -> Unit = {},
onClickAddEnvelope: () -> Unit = {},
) {
val sent = uiState.envelopeInfo.sentAmounts
val received = uiState.envelopeInfo.receivedAmounts
@@ -234,6 +240,13 @@ fun SentEnvelopeScreen(
state = refreshState,
containerColor = Gray10,
)

SusuFloatingButton(
modifier = Modifier
.align(Alignment.BottomEnd)
.padding(SusuTheme.spacing.spacing_l),
onClick = onClickAddEnvelope,
)
}
}

Original file line number Diff line number Diff line change
@@ -58,6 +58,7 @@ class SentEnvelopeViewModel @Inject constructor(
}
}

fun navigateSentEnvelopeAdd() = postSideEffect(SentEnvelopeSideEffect.NavigateEnvelopeAdd(currentState.envelopeInfo.friend))
fun navigateSentEnvelopeDetail(id: Long) = postSideEffect(SentEnvelopeSideEffect.NavigateEnvelopeDetail(id = id))
fun popBackStack() = postSideEffect(SentEnvelopeSideEffect.PopBackStack)
}
Original file line number Diff line number Diff line change
@@ -9,11 +9,16 @@ sealed interface EnvelopeAddEffect : SideEffect {
data class HandleException(val throwable: Throwable, val retry: () -> Unit) : EnvelopeAddEffect
}

/**
* @param fromEnvelope 보내요 봉투 화면에서 추가 화면으로 진입할 시 true. MORE STEP에서 전화번호를 감추기 위함.
* */
data class EnvelopeAddState(
val isLoading: Boolean = false,
val buttonEnabled: Boolean = false,
val currentStep: EnvelopeAddStep = EnvelopeAddStep.MONEY,
val lastPage: Boolean = false,
val friendName: String = "",
val fromEnvelope: Boolean = false,
) : UiState {
val buttonResId = if (lastPage) {
com.susu.core.ui.R.string.word_done
Original file line number Diff line number Diff line change
@@ -1,24 +1,34 @@
package com.susu.feature.envelopeadd

import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.viewModelScope
import com.susu.core.model.Category
import com.susu.core.model.Friend
import com.susu.core.model.Relationship
import com.susu.core.ui.MONEY_MAX_VALUE
import com.susu.core.ui.base.BaseViewModel
import com.susu.core.ui.extension.decodeFromUri
import com.susu.domain.usecase.envelope.CreateSentEnvelopeUseCase
import com.susu.feature.sent.navigation.SentRoute
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import kotlinx.datetime.toKotlinLocalDateTime
import kotlinx.serialization.json.Json
import java.time.LocalDateTime
import javax.inject.Inject

@HiltViewModel
class EnvelopeAddViewModel @Inject constructor(
private val createSentEnvelopeUseCase: CreateSentEnvelopeUseCase,
savedStateHandle: SavedStateHandle,
) : BaseViewModel<EnvelopeAddState, EnvelopeAddEffect>(EnvelopeAddState()) {
private val friendArgument = runCatching {
savedStateHandle.get<String>(SentRoute.FRIEND_ARGUMENT_NAME)?.let {
Json.decodeFromUri<Friend>(it)
}
}.getOrNull()

private var money: Long = 0
private var name: String = ""
private var friendId: Long? = null
private var relationShip: Relationship? = null
private var category: Category? = null
@@ -29,12 +39,21 @@ class EnvelopeAddViewModel @Inject constructor(
private var phoneNumber: String? = null
private var memo: String? = null

fun initData() {
friendArgument?.let {
updateFriendId(it.id)
updateName(it.name)
updatePhoneNumber(it.phoneNumber.ifEmpty { null })
intent { copy(fromEnvelope = true) }
} ?: intent { copy(fromEnvelope = false) }
}

private fun createEnvelope() {
viewModelScope.launch {
createSentEnvelopeUseCase(
param = CreateSentEnvelopeUseCase.Param(
friendId = friendId,
friendName = name,
friendName = currentState.friendName,
phoneNumber = phoneNumber,
relationshipId = relationShip?.id,
customRelation = relationShip?.customRelation,
@@ -55,7 +74,14 @@ class EnvelopeAddViewModel @Inject constructor(

fun goNextStep() {
when (uiState.value.currentStep) {
EnvelopeAddStep.MONEY -> intent { copy(currentStep = EnvelopeAddStep.NAME) }
EnvelopeAddStep.MONEY -> {
if (friendArgument == null) {
intent { copy(currentStep = EnvelopeAddStep.NAME) }
} else {
intent { copy(currentStep = EnvelopeAddStep.EVENT) }
}
}

EnvelopeAddStep.NAME -> {
intent {
if (friendId == null) {
@@ -89,13 +115,12 @@ class EnvelopeAddViewModel @Inject constructor(
EnvelopeAddStep.NAME -> intent { copy(currentStep = EnvelopeAddStep.MONEY) }
EnvelopeAddStep.RELATIONSHIP -> intent { copy(currentStep = EnvelopeAddStep.NAME) }
EnvelopeAddStep.EVENT -> {
intent {
if (friendId == null) {
copy(currentStep = EnvelopeAddStep.RELATIONSHIP)
} else {
copy(currentStep = EnvelopeAddStep.NAME)
}
val prevStep = when {
friendId == null -> EnvelopeAddStep.RELATIONSHIP
friendArgument != null -> EnvelopeAddStep.MONEY
else -> EnvelopeAddStep.NAME
}
intent { copy(currentStep = prevStep) }
}

EnvelopeAddStep.DATE -> intent { copy(currentStep = EnvelopeAddStep.EVENT) }
@@ -125,8 +150,7 @@ class EnvelopeAddViewModel @Inject constructor(
}

fun updateName(name: String) = intent {
this@EnvelopeAddViewModel.name = name
copy(buttonEnabled = name.isNotEmpty())
copy(friendName = name, buttonEnabled = name.isNotEmpty())
}

fun updateFriendId(friendId: Long?) {
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.imePadding
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
@@ -59,12 +60,12 @@ fun SentEnvelopeAddRoute(
}
}

var friendName by remember {
var categoryName by remember {
mutableStateOf("")
}

var categoryName by remember {
mutableStateOf("")
LaunchedEffect(key1 = Unit) {
viewModel.initData()
}

BackHandler {
@@ -73,15 +74,11 @@ fun SentEnvelopeAddRoute(

SentEnvelopeAddScreen(
uiState = uiState,
friendName = friendName,
categoryName = categoryName,
onClickBack = viewModel::goPrevStep,
onClickNext = viewModel::goNextStep,
updateParentMoney = viewModel::updateMoney,
updateParentName = { name ->
viewModel.updateName(name)
friendName = name
},
updateParentName = viewModel::updateName,
updateParentFriendId = viewModel::updateFriendId,
updateParentSelectedRelation = viewModel::updateSelectedRelationShip,
updateParentCategory = { category ->
@@ -101,7 +98,6 @@ fun SentEnvelopeAddRoute(
@Composable
fun SentEnvelopeAddScreen(
uiState: EnvelopeAddState = EnvelopeAddState(),
friendName: String = "",
onClickBack: () -> Unit = {},
onClickNext: () -> Unit = {},
updateParentMoney: (Long) -> Unit = {},
@@ -165,11 +161,12 @@ fun SentEnvelopeAddScreen(
)

EnvelopeAddStep.DATE -> DateContentRoute(
friendName = friendName,
friendName = uiState.friendName,
updateParentDate = updateParentDate,
)

EnvelopeAddStep.MORE -> MoreContentRoute(
fromEnvelope = uiState.fromEnvelope,
updateParentMoreStep = updateParentMoreStep,
)

@@ -184,7 +181,7 @@ fun SentEnvelopeAddScreen(
)

EnvelopeAddStep.PHONE -> PhoneContentRoute(
friendName = friendName,
friendName = uiState.friendName,
updateParentPhone = updateParentPhoneNumber,
onShowSnackbar = onShowSnackbar,
)
Original file line number Diff line number Diff line change
@@ -34,6 +34,7 @@ import com.susu.feature.sent.R
@Composable
fun MoreContentRoute(
viewModel: MoreViewModel = hiltViewModel(),
fromEnvelope: Boolean,
updateParentMoreStep: (List<EnvelopeAddStep>) -> Unit,
) {
val uiState = viewModel.uiState.collectAsStateWithLifecycle().value
@@ -45,6 +46,7 @@ fun MoreContentRoute(

MoreContent(
uiState = uiState,
fromEnvelope = fromEnvelope,
onClickStepButton = viewModel::toggleStep,
)
}
@@ -57,6 +59,7 @@ fun MoreContent(
vertical = SusuTheme.spacing.spacing_xl,
),
uiState: MoreState = MoreState(),
fromEnvelope: Boolean = false,
onClickStepButton: (EnvelopeAddStep) -> Unit = {},
) {
val scrollState = rememberScrollState()
@@ -88,7 +91,9 @@ fun MoreContent(
Column(
verticalArrangement = Arrangement.spacedBy(SusuTheme.spacing.spacing_xxs),
) {
moreStep.forEach { (step, stringRes) ->
for ((step, stringRes) in moreStep) {
if (fromEnvelope && step == EnvelopeAddStep.PHONE) continue

if (step in uiState.selectedMoreStop) {
SusuFilledButton(
color = FilledButtonColor.Orange,
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@ import androidx.navigation.NavType
import androidx.navigation.compose.composable
import androidx.navigation.navArgument
import com.susu.core.model.EnvelopeDetail
import com.susu.core.model.Friend
import com.susu.core.ui.DialogToken
import com.susu.core.ui.SnackbarToken
import com.susu.core.ui.extension.encodeToUri
@@ -36,8 +37,8 @@ fun NavController.navigateSentEnvelopeEdit(envelopeDetail: EnvelopeDetail) {
navigate(SentRoute.sentEnvelopeEditRoute(Json.encodeToUri(envelopeDetail)))
}

fun NavController.navigateSentEnvelopeAdd() {
navigate(SentRoute.sentEnvelopeAddRoute)
fun NavController.navigateSentEnvelopeAdd(friend: Friend?) {
navigate(SentRoute.sentEnvelopeAddRoute(Json.encodeToUri(friend)))
}

fun NavController.navigateSentEnvelopeSearch() {
@@ -57,7 +58,7 @@ fun NavGraphBuilder.sentNavGraph(
navigateSentEnvelope: (Long) -> Unit,
navigateSentEnvelopeDetail: (Long) -> Unit,
navigateSentEnvelopeEdit: (EnvelopeDetail) -> Unit,
navigateSentEnvelopeAdd: () -> Unit,
navigateSentEnvelopeAdd: (Friend?) -> Unit,
navigateSentEnvelopeSearch: () -> Unit,
navigateEnvelopeFilter: (String) -> Unit,
onShowSnackbar: (SnackbarToken) -> Unit,
@@ -81,7 +82,7 @@ fun NavGraphBuilder.sentNavGraph(
editedFriendId = editedFriendId,
refresh = refresh,
navigateSentEnvelope = navigateSentEnvelope,
navigateSentEnvelopeAdd = navigateSentEnvelopeAdd,
navigateSentEnvelopeAdd = { navigateSentEnvelopeAdd(null) },
navigateSentEnvelopeSearch = navigateSentEnvelopeSearch,
navigateEnvelopeFilter = navigateEnvelopeFilter,
)
@@ -102,6 +103,7 @@ fun NavGraphBuilder.sentNavGraph(
popBackStackWithEditedFriendId = popBackStackWithEditedFriendId,
navigateSentEnvelopeDetail = navigateSentEnvelopeDetail,
popBackStackWithDeleteFriendId = popBackStackWithDeleteFriendId,
navigateSentEnvelopeAdd = navigateSentEnvelopeAdd,
)
}

@@ -134,7 +136,7 @@ fun NavGraphBuilder.sentNavGraph(
)
}

composable(route = SentRoute.sentEnvelopeAddRoute) {
composable(route = SentRoute.sentEnvelopeAddRoute("{${SentRoute.FRIEND_ARGUMENT_NAME}}")) {
SentEnvelopeAddRoute(
popBackStack = popBackStack,
popBackStackWithRefresh = popBackStackWithRefresh,
@@ -163,8 +165,10 @@ fun NavGraphBuilder.sentNavGraph(

object SentRoute {
const val route = "sent"
const val sentEnvelopeAddRoute = "sent-envelope-add"
const val SENT_REFRESH_ARGUMENT_NAME = "sent-refresh"
fun sentEnvelopeAddRoute(friend: String) = "sent-envelope-add/$friend"
const val FRIEND_ARGUMENT_NAME = "sent-friend"

fun sentEnvelopeRoute(id: String) = "sent-envelope/$id"
const val FRIEND_ID_ARGUMENT_NAME = "sent-envelope-id"
const val EDITED_FRIEND_ID_ARGUMENT_NAME = "edited-friend-id"