Skip to content

Commit 37d1b35

Browse files
committed
[BOOK-186] feat: 약관 동의 구현 및 약관 동의 화면 컴포넌트 분리
1 parent dd8a590 commit 37d1b35

File tree

5 files changed

+142
-57
lines changed

5 files changed

+142
-57
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package com.ninecraft.booket.feature.termsagreement
2+
3+
import android.widget.Toast
4+
import androidx.compose.runtime.Composable
5+
import androidx.compose.runtime.remember
6+
import androidx.compose.ui.platform.LocalContext
7+
import com.ninecraft.booket.feature.login.KakaoLoginClient
8+
import com.ninecraft.booket.feature.login.LoginSideEffect
9+
import com.ninecraft.booket.feature.login.LoginUiEvent
10+
import com.ninecraft.booket.feature.login.LoginUiState
11+
import com.skydoves.compose.effects.RememberedEffect
12+
13+
@Composable
14+
internal fun HandleTermsAgreementSideEffects(
15+
state: TermsAgreementUiState,
16+
) {
17+
val context = LocalContext.current
18+
19+
RememberedEffect(state.sideEffect) {
20+
when (state.sideEffect) {
21+
is TermsAgreementSideEffect.ShowToast -> {
22+
Toast.makeText(context, state.sideEffect.message, Toast.LENGTH_SHORT).show()
23+
}
24+
25+
null -> {}
26+
}
27+
}
28+
}

feature/login/src/main/kotlin/com/ninecraft/booket/feature/termsagreement/TermsAgreementPresenter.kt

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,17 @@ import androidx.compose.runtime.derivedStateOf
55
import androidx.compose.runtime.getValue
66
import androidx.compose.runtime.mutableStateOf
77
import androidx.compose.runtime.remember
8+
import androidx.compose.runtime.rememberCoroutineScope
89
import androidx.compose.runtime.setValue
910
import com.ninecraft.booket.core.common.constants.WebViewConstants
11+
import com.ninecraft.booket.core.data.api.repository.AuthRepository
1012
import com.ninecraft.booket.core.data.api.repository.UserRepository
13+
import com.ninecraft.booket.feature.login.LoginSideEffect
1114
import com.ninecraft.booket.feature.screens.BottomNavigationScreen
1215
import com.ninecraft.booket.feature.screens.OnboardingScreen
1316
import com.ninecraft.booket.feature.screens.TermsAgreementScreen
1417
import com.ninecraft.booket.feature.screens.WebViewScreen
18+
import com.orhanobut.logger.Logger
1519
import com.slack.circuit.codegen.annotations.CircuitInject
1620
import com.slack.circuit.retained.collectAsRetainedState
1721
import com.slack.circuit.retained.rememberRetained
@@ -23,14 +27,20 @@ import dagger.assisted.AssistedInject
2327
import dagger.hilt.android.components.ActivityRetainedComponent
2428
import kotlinx.collections.immutable.persistentListOf
2529
import kotlinx.collections.immutable.toPersistentList
30+
import kotlinx.coroutines.coroutineScope
31+
import kotlinx.coroutines.launch
2632

2733
class TermsAgreementPresenter @AssistedInject constructor(
2834
@Assisted private val navigator: Navigator,
29-
private val repository: UserRepository,
35+
private val userRepository: UserRepository,
36+
private val authRepository: AuthRepository,
3037
) : Presenter<TermsAgreementUiState> {
3138

3239
@Composable
3340
override fun present(): TermsAgreementUiState {
41+
val scope = rememberCoroutineScope()
42+
var sideEffect by rememberRetained { mutableStateOf<TermsAgreementSideEffect?>(null) }
43+
3444
var agreedTerms by rememberRetained {
3545
mutableStateOf(persistentListOf(false, false, false))
3646
}
@@ -41,7 +51,7 @@ class TermsAgreementPresenter @AssistedInject constructor(
4151
}
4252
}
4353

44-
val isOnboardingCompleted by repository.isOnboardingCompleted.collectAsRetainedState(initial = false)
54+
val isOnboardingCompleted by userRepository.isOnboardingCompleted.collectAsRetainedState(initial = false)
4555

4656
fun handleEvent(event: TermsAgreementUiEvent) {
4757
when (event) {
@@ -65,10 +75,20 @@ class TermsAgreementPresenter @AssistedInject constructor(
6575
}
6676

6777
is TermsAgreementUiEvent.OnStartButtonClick -> {
68-
if (isOnboardingCompleted) {
69-
navigator.resetRoot(BottomNavigationScreen)
70-
} else {
71-
navigator.resetRoot(OnboardingScreen)
78+
scope.launch {
79+
authRepository.agreeTerms(true)
80+
.onSuccess {
81+
if (isOnboardingCompleted) {
82+
navigator.resetRoot(BottomNavigationScreen)
83+
} else {
84+
navigator.resetRoot(OnboardingScreen)
85+
}
86+
}.onFailure { exception ->
87+
exception.message?.let { Logger.e(it) }
88+
sideEffect = exception.message?.let {
89+
TermsAgreementSideEffect.ShowToast(it)
90+
}
91+
}
7292
}
7393
}
7494
}

feature/login/src/main/kotlin/com/ninecraft/booket/feature/termsagreement/TermsAgreementUi.kt

Lines changed: 4 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -12,39 +12,36 @@ import androidx.compose.foundation.layout.padding
1212
import androidx.compose.foundation.layout.systemBarsPadding
1313
import androidx.compose.foundation.layout.width
1414
import androidx.compose.foundation.shape.RoundedCornerShape
15-
import androidx.compose.material3.Icon
1615
import androidx.compose.material3.Text
1716
import androidx.compose.runtime.Composable
1817
import androidx.compose.ui.Alignment
1918
import androidx.compose.ui.Modifier
20-
import androidx.compose.ui.graphics.Color
21-
import androidx.compose.ui.graphics.vector.ImageVector
2219
import androidx.compose.ui.res.stringArrayResource
2320
import androidx.compose.ui.res.stringResource
24-
import androidx.compose.ui.res.vectorResource
2521
import androidx.compose.ui.unit.dp
2622
import com.ninecraft.booket.core.common.extensions.noRippleClickable
2723
import com.ninecraft.booket.core.designsystem.DevicePreview
2824
import com.ninecraft.booket.core.designsystem.component.button.ReedButton
2925
import com.ninecraft.booket.core.designsystem.component.button.ReedButtonColorStyle
3026
import com.ninecraft.booket.core.designsystem.component.button.largeButtonStyle
3127
import com.ninecraft.booket.core.designsystem.component.checkbox.SquareCheckBox
32-
import com.ninecraft.booket.core.designsystem.component.checkbox.TickOnlyCheckBox
3328
import com.ninecraft.booket.core.designsystem.theme.ReedTheme
3429
import com.ninecraft.booket.core.designsystem.theme.White
3530
import com.ninecraft.booket.feature.login.R
3631
import com.ninecraft.booket.feature.screens.TermsAgreementScreen
32+
import com.ninecraft.booket.feature.termsagreement.component.TermItem
3733
import com.slack.circuit.codegen.annotations.CircuitInject
3834
import dagger.hilt.android.components.ActivityRetainedComponent
3935
import kotlinx.collections.immutable.persistentListOf
40-
import com.ninecraft.booket.core.designsystem.R as designR
4136

4237
@CircuitInject(TermsAgreementScreen::class, ActivityRetainedComponent::class)
4338
@Composable
4439
internal fun TermsAgreementUi(
4540
state: TermsAgreementUiState,
4641
modifier: Modifier = Modifier,
4742
) {
43+
HandleTermsAgreementSideEffects(state = state)
44+
4845
val termsTitles = stringArrayResource(id = R.array.terms_agreement_items)
4946

5047
Column(
@@ -53,8 +50,7 @@ internal fun TermsAgreementUi(
5350
.background(White)
5451
.systemBarsPadding(),
5552
) {
56-
Spacer(modifier = Modifier.height(ReedTheme.spacing.spacing16))
57-
Spacer(modifier = Modifier.height(ReedTheme.spacing.spacing3))
53+
Spacer(modifier = Modifier.height(76.dp))
5854
Column(
5955
modifier = Modifier
6056
.weight(1f)
@@ -147,49 +143,6 @@ internal fun TermsAgreementUi(
147143
}
148144
}
149145

150-
@Composable
151-
private fun TermItem(
152-
title: String,
153-
onCheckClick: () -> Unit,
154-
modifier: Modifier = Modifier,
155-
checked: Boolean = false,
156-
hasDetailAction: Boolean = true,
157-
onDetailClick: () -> Unit = {},
158-
) {
159-
Row(
160-
modifier = modifier
161-
.fillMaxWidth()
162-
.noRippleClickable { onDetailClick() }
163-
.padding(
164-
start = ReedTheme.spacing.spacing4 + ReedTheme.spacing.spacing05,
165-
end = ReedTheme.spacing.spacing3,
166-
top = ReedTheme.spacing.spacing2,
167-
bottom = ReedTheme.spacing.spacing2,
168-
),
169-
verticalAlignment = Alignment.CenterVertically,
170-
) {
171-
TickOnlyCheckBox(
172-
checked = checked,
173-
onCheckedChange = { onCheckClick() },
174-
)
175-
Spacer(modifier = Modifier.width(ReedTheme.spacing.spacing3 + ReedTheme.spacing.spacing05))
176-
Text(
177-
text = title,
178-
modifier = Modifier.weight(1f),
179-
color = ReedTheme.colors.contentPrimary,
180-
style = ReedTheme.typography.body1Medium,
181-
)
182-
183-
if (hasDetailAction) {
184-
Icon(
185-
imageVector = ImageVector.vectorResource(id = designR.drawable.ic_chevron_right),
186-
contentDescription = "Navigation Icon",
187-
tint = Color.Unspecified,
188-
)
189-
}
190-
}
191-
}
192-
193146
@DevicePreview
194147
@Composable
195148
private fun TermsAgreementPreview() {

feature/login/src/main/kotlin/com/ninecraft/booket/feature/termsagreement/TermsAgreementUiState.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,25 @@
11
package com.ninecraft.booket.feature.termsagreement
22

3+
import com.ninecraft.booket.feature.login.LoginSideEffect
34
import com.slack.circuit.runtime.CircuitUiEvent
45
import com.slack.circuit.runtime.CircuitUiState
56
import kotlinx.collections.immutable.ImmutableList
7+
import java.util.UUID
68

79
data class TermsAgreementUiState(
810
val isAllAgreed: Boolean,
911
val agreedTerms: ImmutableList<Boolean>,
12+
val sideEffect: TermsAgreementSideEffect? = null,
1013
val eventSink: (TermsAgreementUiEvent) -> Unit,
1114
) : CircuitUiState
1215

16+
sealed interface TermsAgreementSideEffect {
17+
data class ShowToast(
18+
val message: String,
19+
private val key: String = UUID.randomUUID().toString(),
20+
) : TermsAgreementSideEffect
21+
}
22+
1323
sealed interface TermsAgreementUiEvent : CircuitUiEvent {
1424
data object OnAllTermsAgreedClick : TermsAgreementUiEvent
1525
data class OnTermItemClick(val index: Int) : TermsAgreementUiEvent
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package com.ninecraft.booket.feature.termsagreement.component
2+
3+
import androidx.compose.foundation.layout.Row
4+
import androidx.compose.foundation.layout.Spacer
5+
import androidx.compose.foundation.layout.fillMaxWidth
6+
import androidx.compose.foundation.layout.padding
7+
import androidx.compose.foundation.layout.width
8+
import androidx.compose.material3.Icon
9+
import androidx.compose.material3.Text
10+
import androidx.compose.runtime.Composable
11+
import androidx.compose.ui.Alignment
12+
import androidx.compose.ui.Modifier
13+
import androidx.compose.ui.graphics.Color
14+
import androidx.compose.ui.graphics.vector.ImageVector
15+
import androidx.compose.ui.res.vectorResource
16+
import com.ninecraft.booket.core.common.extensions.noRippleClickable
17+
import com.ninecraft.booket.core.designsystem.ComponentPreview
18+
import com.ninecraft.booket.core.designsystem.component.checkbox.TickOnlyCheckBox
19+
import com.ninecraft.booket.core.designsystem.theme.ReedTheme
20+
import com.ninecraft.booket.core.designsystem.R as designR
21+
22+
@Composable
23+
internal fun TermItem(
24+
title: String,
25+
onCheckClick: () -> Unit,
26+
modifier: Modifier = Modifier,
27+
checked: Boolean = false,
28+
hasDetailAction: Boolean = true,
29+
onDetailClick: () -> Unit = {},
30+
) {
31+
Row(
32+
modifier = modifier
33+
.fillMaxWidth()
34+
.noRippleClickable { onDetailClick() }
35+
.padding(
36+
start = ReedTheme.spacing.spacing4 + ReedTheme.spacing.spacing05,
37+
end = ReedTheme.spacing.spacing3,
38+
top = ReedTheme.spacing.spacing2,
39+
bottom = ReedTheme.spacing.spacing2,
40+
),
41+
verticalAlignment = Alignment.CenterVertically,
42+
) {
43+
TickOnlyCheckBox(
44+
checked = checked,
45+
onCheckedChange = { onCheckClick() },
46+
)
47+
Spacer(modifier = Modifier.width(ReedTheme.spacing.spacing3 + ReedTheme.spacing.spacing05))
48+
Text(
49+
text = title,
50+
modifier = Modifier.weight(1f),
51+
color = ReedTheme.colors.contentPrimary,
52+
style = ReedTheme.typography.body1Medium,
53+
)
54+
55+
if (hasDetailAction) {
56+
Icon(
57+
imageVector = ImageVector.vectorResource(id = designR.drawable.ic_chevron_right),
58+
contentDescription = "Navigation Icon",
59+
tint = Color.Unspecified,
60+
)
61+
}
62+
}
63+
}
64+
65+
@ComponentPreview
66+
@Composable
67+
private fun TermItemPreview() {
68+
ReedTheme {
69+
TermItem(
70+
title = "(필수)서비스 이용약관",
71+
onCheckClick = {}
72+
)
73+
}
74+
}

0 commit comments

Comments
 (0)