Skip to content

Commit 0bad8e2

Browse files
committed
FEAT: 모임 주기 설정 화면 추가 및 API 연동
1 parent c463429 commit 0bad8e2

File tree

11 files changed

+296
-31
lines changed

11 files changed

+296
-31
lines changed

core/ui-navigation/src/main/java/com/plottwist/core/ui/navigation/Route.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,4 +77,10 @@ sealed interface Route {
7777

7878
@Serializable
7979
data class CompleteProposal(val encodedUrl : String): Route
80+
81+
@Serializable
82+
data class GatheringAlarmSetting(
83+
val gatheringId: Long,
84+
val selectedIntervalDays : Long
85+
): Route
8086
}

feature/create_gathering/src/main/java/com/plottwist/create_gathering/page/IntervalDaysPage.kt

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,20 @@
11
package com.plottwist.create_gathering.page
22

3-
import androidx.compose.foundation.clickable
43
import androidx.compose.foundation.layout.Arrangement
5-
import androidx.compose.foundation.layout.Column
64
import androidx.compose.foundation.layout.Row
7-
import androidx.compose.foundation.layout.Spacer
8-
import androidx.compose.foundation.layout.fillMaxSize
95
import androidx.compose.foundation.layout.fillMaxWidth
10-
import androidx.compose.foundation.layout.height
116
import androidx.compose.foundation.layout.padding
12-
import androidx.compose.foundation.lazy.items
137
import androidx.compose.foundation.lazy.itemsIndexed
14-
import androidx.compose.material3.Text
158
import androidx.compose.runtime.Composable
16-
import androidx.compose.ui.Alignment
179
import androidx.compose.ui.Modifier
18-
import androidx.compose.ui.graphics.Color
19-
import androidx.compose.ui.text.TextStyle
20-
import androidx.compose.ui.text.style.TextDecoration
2110
import androidx.compose.ui.tooling.preview.Preview
2211
import androidx.compose.ui.unit.dp
23-
import androidx.compose.ui.unit.sp
2412
import com.plottwist.core.designsystem.component.TukOutlinedButton
2513
import com.plottwist.core.designsystem.component.TukSolidButton
2614
import com.plottwist.core.designsystem.component.TukSolidButtonType
27-
import com.plottwist.core.designsystem.foundation.type.TukPretendardTypography
15+
import com.plottwist.core.domain.model.gatheringIntervalDaysOptions
2816
import com.plottwist.core.ui.component.RadioButtonItem
29-
import com.plottwist.core.ui.component.StableImage
3017
import com.plottwist.core.ui.component.TukScaffold
31-
import com.plottwist.tuk.feature.create_gathering.R
3218

3319
@Composable
3420
fun CreateGatheringSelectIntervalDays(
@@ -37,12 +23,6 @@ fun CreateGatheringSelectIntervalDays(
3723
onClickPrev: () -> Unit,
3824
onNext: () -> Unit
3925
) {
40-
val options = listOf(
41-
Triple(30, "한달", "매월 만남"),
42-
Triple(60, "2개월", "2개월 마다 만남"),
43-
Triple(90, "3개월", "분기별 만남"),
44-
Triple(180, "6개월", "6개월 마다 만남")
45-
)
4626
TukScaffold(
4727
title = "앞으로는 얼마나\n자주 만나면 좋을까요?",
4828
description = "부담없는 주기가 제일 오래가요",
@@ -71,13 +51,13 @@ fun CreateGatheringSelectIntervalDays(
7151
}
7252
) {
7353

74-
itemsIndexed(options) { index, (days, title, subtitle) ->
54+
itemsIndexed(gatheringIntervalDaysOptions) { index, (days, title, subtitle) ->
7555
RadioButtonItem(
7656
title = title,
7757
subtitle = subtitle,
7858
selected = selectedOption == days,
7959
onClick = { onOptionSelected(days) },
80-
hasDivider = index < options.lastIndex
60+
hasDivider = index < gatheringIntervalDaysOptions.lastIndex
8161
)
8262
}
8363
}

feature/gathering-detail/src/main/java/com/plottwist/feature/gathering_detail/GatheringDetailContract.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ sealed class GatheringDetailAction {
1212
data object ClickReceivedProposal: GatheringDetailAction()
1313
data object ClickInviteMember: GatheringDetailAction()
1414
data object ClickProposal: GatheringDetailAction()
15+
data object ClickAlarmSetting: GatheringDetailAction()
1516
}
1617

1718
sealed class GatheringDetailSideEffect {
@@ -22,4 +23,8 @@ sealed class GatheringDetailSideEffect {
2223
val gatheringId: Long,
2324
val gatheringName: String
2425
): GatheringDetailSideEffect()
26+
data class NavigateToGatheringDetailAlarmSetting(
27+
val gatheringId: Long,
28+
val selectedIntervalDays: Long
29+
): GatheringDetailSideEffect()
2530
}

feature/gathering-detail/src/main/java/com/plottwist/feature/gathering_detail/GatheringDetailScreen.kt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ fun GatheringDetailScreen(
4242
navigateToWebViewScreen: (String) -> Unit,
4343
navigateToInviteGathering: (String) -> Unit,
4444
navigateToCreateGatheringProposal: (Long, String) -> Unit,
45+
navigateToGatheringDetailAlarmSetting: (Long, Long) -> Unit,
4546
modifier: Modifier = Modifier,
4647
viewModel: GatheringDetailViewModel = hiltViewModel()
4748
) {
@@ -64,6 +65,13 @@ fun GatheringDetailScreen(
6465
is GatheringDetailSideEffect.NavigateToCreateGatheringProposal -> {
6566
navigateToCreateGatheringProposal(sideEffect.gatheringId, sideEffect.gatheringName)
6667
}
68+
69+
is GatheringDetailSideEffect.NavigateToGatheringDetailAlarmSetting -> {
70+
navigateToGatheringDetailAlarmSetting(
71+
sideEffect.gatheringId,
72+
sideEffect.selectedIntervalDays
73+
)
74+
}
6775
}
6876
}
6977

@@ -74,7 +82,9 @@ fun GatheringDetailScreen(
7482
lastAlarm = state.gatheringDetail.lastPushRelativeTime,
7583
sentProposalCount = state.gatheringDetail.sentProposalCount,
7684
receivedProposalCount = state.gatheringDetail.receivedProposalCount,
77-
onAlarmSettingClick = {},
85+
onAlarmSettingClick = {
86+
viewModel.handleAction(GatheringDetailAction.ClickAlarmSetting)
87+
},
7888
onProposalClick = {
7989
viewModel.handleAction(GatheringDetailAction.ClickProposal)
8090
},

feature/gathering-detail/src/main/java/com/plottwist/feature/gathering_detail/GatheringDetailViewModel.kt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ class GatheringDetailViewModel @Inject constructor(
4646
GatheringDetailAction.ClickProposal -> {
4747
handleCreateGatheringProposalClick()
4848
}
49+
50+
GatheringDetailAction.ClickAlarmSetting -> {
51+
handleAlarmSettingClick()
52+
}
4953
}
5054
}
5155

@@ -89,4 +93,13 @@ class GatheringDetailViewModel @Inject constructor(
8993
)
9094
)
9195
}
96+
97+
private fun handleAlarmSettingClick() = intent {
98+
postSideEffect(
99+
GatheringDetailSideEffect.NavigateToGatheringDetailAlarmSetting(
100+
gatheringId = state.gatheringDetail.gatheringId,
101+
selectedIntervalDays = state.gatheringDetail.gatheringIntervalDays
102+
)
103+
)
104+
}
92105
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.plottwist.feature.gathering_detail.alarm
2+
3+
data class GatheringDetailAlarmSettingState(
4+
val gatheringId: Long = 0,
5+
val selectedIntervalDays: Int = 0
6+
)
7+
8+
sealed class GatheringDetailAlarmSettingAction {
9+
data object ClickBack: GatheringDetailAlarmSettingAction()
10+
data class ClickOption(val days: Int): GatheringDetailAlarmSettingAction()
11+
data object ClickSave: GatheringDetailAlarmSettingAction()
12+
}
13+
14+
sealed class GatheringDetailAlarmSettingSideEffect {
15+
data object NavigateBack: GatheringDetailAlarmSettingSideEffect()
16+
data class NavigateGatheringDetail(val gatheringId: Long) : GatheringDetailAlarmSettingSideEffect()
17+
}
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
package com.plottwist.feature.gathering_detail.alarm
2+
3+
import androidx.compose.foundation.layout.Arrangement
4+
import androidx.compose.foundation.layout.Row
5+
import androidx.compose.foundation.layout.fillMaxWidth
6+
import androidx.compose.foundation.layout.padding
7+
import androidx.compose.foundation.lazy.itemsIndexed
8+
import androidx.compose.runtime.Composable
9+
import androidx.compose.runtime.getValue
10+
import androidx.compose.ui.Modifier
11+
import androidx.compose.ui.unit.dp
12+
import androidx.hilt.navigation.compose.hiltViewModel
13+
import com.plottwist.core.designsystem.component.TukSolidButton
14+
import com.plottwist.core.designsystem.component.TukSolidButtonType
15+
import com.plottwist.core.designsystem.component.TukTopAppBar
16+
import com.plottwist.core.domain.model.gatheringIntervalDaysOptions
17+
import com.plottwist.core.ui.component.RadioButtonItem
18+
import com.plottwist.core.ui.component.TopAppBarCloseButton
19+
import com.plottwist.core.ui.component.TukScaffold
20+
import org.orbitmvi.orbit.compose.collectAsState
21+
import org.orbitmvi.orbit.compose.collectSideEffect
22+
23+
@Composable
24+
fun GatheringDetailAlarmSettingScreen(
25+
onNavigateBack: () -> Unit,
26+
onNavigateGatheringDetail: (Long) -> Unit,
27+
modifier: Modifier = Modifier,
28+
viewModel: GatheringDetailAlarmSettingViewModel = hiltViewModel()
29+
) {
30+
31+
val state by viewModel.collectAsState()
32+
33+
viewModel.collectSideEffect { sideEffect ->
34+
when(sideEffect) {
35+
GatheringDetailAlarmSettingSideEffect.NavigateBack -> {
36+
onNavigateBack()
37+
}
38+
39+
is GatheringDetailAlarmSettingSideEffect.NavigateGatheringDetail -> {
40+
onNavigateGatheringDetail(sideEffect.gatheringId)
41+
}
42+
}
43+
}
44+
45+
GatheringDetailAlarmSettingScreen(
46+
modifier = modifier,
47+
selectedIntervalDays = state.selectedIntervalDays,
48+
onBackClick = {
49+
viewModel.handleAction(GatheringDetailAlarmSettingAction.ClickBack)
50+
},
51+
onOptionSelected = {
52+
viewModel.handleAction(GatheringDetailAlarmSettingAction.ClickOption(it))
53+
},
54+
onSaveClick = {
55+
viewModel.handleAction(GatheringDetailAlarmSettingAction.ClickSave)
56+
}
57+
)
58+
}
59+
60+
@Composable
61+
private fun GatheringDetailAlarmSettingScreen(
62+
selectedIntervalDays: Int,
63+
onBackClick : () -> Unit,
64+
onOptionSelected: (Int) -> Unit,
65+
onSaveClick: () -> Unit,
66+
modifier: Modifier = Modifier
67+
) {
68+
TukScaffold(
69+
modifier = modifier,
70+
topBar = {
71+
TukTopAppBar(
72+
modifier = modifier,
73+
actionButtons = {
74+
TopAppBarCloseButton(
75+
onCloseClicked = onBackClick
76+
)
77+
}
78+
)
79+
},
80+
title = "앞으로는 얼마나\n자주 만나면 좋을까요?",
81+
description = "부담없는 주기가 제일 오래가요",
82+
bottomBar = {
83+
Row(
84+
modifier = Modifier
85+
.fillMaxWidth().padding(
86+
vertical = 17.dp,
87+
horizontal = 20.dp
88+
),
89+
horizontalArrangement = Arrangement.spacedBy(8.dp)
90+
) {
91+
TukSolidButton(
92+
modifier = Modifier.fillMaxWidth(),
93+
text = "저장하기",
94+
buttonType = TukSolidButtonType.from(selectedIntervalDays != 0),
95+
onClick = onSaveClick
96+
)
97+
}
98+
}
99+
) {
100+
101+
itemsIndexed(gatheringIntervalDaysOptions) { index, (days, title, subtitle) ->
102+
RadioButtonItem(
103+
title = title,
104+
subtitle = subtitle,
105+
selected = selectedIntervalDays == days,
106+
onClick = { onOptionSelected(days) },
107+
hasDivider = index < gatheringIntervalDaysOptions.lastIndex
108+
)
109+
}
110+
}
111+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package com.plottwist.feature.gathering_detail.alarm
2+
3+
import androidx.lifecycle.SavedStateHandle
4+
import androidx.lifecycle.ViewModel
5+
import androidx.navigation.toRoute
6+
import com.plottwist.core.domain.gathering.usecase.UpdateGatheringUseCase
7+
import com.plottwist.core.ui.navigation.Route
8+
import dagger.hilt.android.lifecycle.HiltViewModel
9+
import org.orbitmvi.orbit.ContainerHost
10+
import org.orbitmvi.orbit.viewmodel.container
11+
import javax.inject.Inject
12+
13+
@HiltViewModel
14+
class GatheringDetailAlarmSettingViewModel @Inject constructor(
15+
private val updateGatheringUseCase: UpdateGatheringUseCase,
16+
savedStateHandle: SavedStateHandle
17+
) : ViewModel(),
18+
ContainerHost<GatheringDetailAlarmSettingState, GatheringDetailAlarmSettingSideEffect> {
19+
override val container =
20+
container<GatheringDetailAlarmSettingState, GatheringDetailAlarmSettingSideEffect>(
21+
savedStateHandle.toRoute<Route.GatheringAlarmSetting>().let {
22+
GatheringDetailAlarmSettingState(
23+
selectedIntervalDays = it.selectedIntervalDays.toInt(),
24+
gatheringId = it.gatheringId
25+
)
26+
}
27+
)
28+
29+
fun handleAction(action: GatheringDetailAlarmSettingAction) {
30+
when (action) {
31+
GatheringDetailAlarmSettingAction.ClickBack -> {
32+
navigateBack()
33+
}
34+
35+
is GatheringDetailAlarmSettingAction.ClickOption -> {
36+
handleOptionClick(action.days)
37+
}
38+
39+
GatheringDetailAlarmSettingAction.ClickSave -> {
40+
handleSaveClick()
41+
}
42+
}
43+
}
44+
45+
private fun navigateBack() = intent {
46+
postSideEffect(GatheringDetailAlarmSettingSideEffect.NavigateBack)
47+
}
48+
49+
private fun handleOptionClick(days: Int) = intent {
50+
reduce {
51+
state.copy(
52+
selectedIntervalDays = days
53+
)
54+
}
55+
}
56+
57+
private fun handleSaveClick() = intent {
58+
updateGatheringUseCase(
59+
gatheringId = state.gatheringId,
60+
intervalDays = state.selectedIntervalDays
61+
).onSuccess {
62+
postSideEffect(
63+
GatheringDetailAlarmSettingSideEffect.NavigateGatheringDetail(
64+
state.gatheringId
65+
)
66+
)
67+
}.onFailure {
68+
69+
}
70+
}
71+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.plottwist.feature.gathering_detail.navigation
2+
3+
import androidx.navigation.NavController
4+
import androidx.navigation.NavGraphBuilder
5+
import androidx.navigation.NavOptions
6+
import androidx.navigation.compose.composable
7+
import com.plottwist.core.ui.navigation.Route
8+
import com.plottwist.feature.gathering_detail.alarm.GatheringDetailAlarmSettingScreen
9+
10+
fun NavController.navigateToGatheringDetailAlarmSetting(
11+
gatheringId: Long,
12+
selectedIntervalDays: Long,
13+
navOptions: NavOptions? = null
14+
) {
15+
this.navigate(
16+
route = Route.GatheringAlarmSetting(gatheringId, selectedIntervalDays),
17+
navOptions = navOptions
18+
)
19+
}
20+
21+
fun NavGraphBuilder.gatheringDetailAlarmSettingNavGraph(
22+
onBack: () -> Unit,
23+
onNavigateGatheringDetail : (Long) -> Unit
24+
) {
25+
composable<Route.GatheringAlarmSetting> {
26+
GatheringDetailAlarmSettingScreen(
27+
onNavigateBack = onBack,
28+
onNavigateGatheringDetail = onNavigateGatheringDetail
29+
)
30+
}
31+
}

0 commit comments

Comments
 (0)