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

Feature/mz 199 마이페이지 - 내정보 편집, 앱 버전, 개인정보처리방침 #91

Merged
merged 10 commits into from
Jan 25, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ fun SusuLimitDatePickerBottomSheet(
initialMonth == criteriaMonth && initialDay > criteriaDay
)
-> criteriaDay

else -> initialDay
},
)
Expand Down Expand Up @@ -334,7 +335,8 @@ fun SusuYearPickerBottomSheet(
) {
val currentYear = remember { LocalDate.now().year }
var selectedYear by remember { mutableIntStateOf(initialYear ?: currentYear) }
val yearList = yearRange.map { stringResource(id = R.string.word_year_format, it) }.toImmutableList()
val yearList =
(yearRange.map { stringResource(id = R.string.word_year_format, it) } + listOf(stringResource(R.string.word_not_select))).toImmutableList()
SusuBottomSheet(
sheetState = sheetState,
containerHeight = minOf(maximumContainerHeight, itemHeight * numberOfDisplayedItems + 32.dp),
Expand All @@ -350,10 +352,10 @@ fun SusuYearPickerBottomSheet(
itemHeight = itemHeight,
numberOfDisplayedItems = numberOfDisplayedItems,
onItemSelected = { _, item ->
selectedYear = item.dropLast(1).toIntOrNull() ?: currentYear
selectedYear = item.dropLast(1).toIntOrNull() ?: 0
onItemSelected(selectedYear)
},
onItemClicked = { onItemClicked(it.dropLast(1).toIntOrNull() ?: currentYear) },
onItemClicked = { onItemClicked(it.dropLast(1).toIntOrNull() ?: 0) },
)
}
}
Expand Down
1 change: 1 addition & 0 deletions core/designsystem/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@
<string name="content_description_logo_image">로고 이미지</string>
<string name="content_description_notification_icon">알림 아이콘</string>
<string name="content_description_filter_icon">필터 아이콘</string>
<string name="word_not_select">미선택</string>
</resources>
16 changes: 3 additions & 13 deletions core/ui/src/main/java/com/susu/core/ui/Consts.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ val alignList
const val USER_NAME_MAX_LENGTH = 10
val nameRegex = Regex("[a-zA-Z가-힣]{0,10}")

const val INTENT_ACTION_DOWNLOAD_COMPLETE = "android.intent.action.DOWNLOAD_COMPLETE"
val USER_BIRTH_RANGE = 1930..2030

const val INTENT_ACTION_DOWNLOAD_COMPLETE = "android.intent.action.DOWNLOAD_COMPLETE"
const val PRIVACY_POLICY_URL = "https://sites.google.com/view/team-oksusu/%ED%99%88"
enum class SnsProviders(
val path: String,
@StringRes val nameId: Int,
Expand All @@ -32,18 +34,6 @@ enum class SnsProviders(
iconId = R.drawable.ic_kakao_login,
backgroundColor = Color(0xFFFEE500),
),
Naver(
path = "",
nameId = R.string.sns_naver,
iconId = R.drawable.ic_kakao_login,
backgroundColor = Color.Unspecified,
),
Google(
path = "",
nameId = R.string.sns_google,
iconId = R.drawable.ic_kakao_login,
backgroundColor = Color.Unspecified,
),
}

enum class Gender(val content: String?) {
Expand Down
1 change: 1 addition & 0 deletions core/ui/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
<string name="content_description_add_button">더하기 버튼</string>
<string name="content_description_close_icon">닫기 아이콘</string>
<string name="word_input_yourself">직접 입력</string>
<string name="word_name">이름</string>
<string name="word_gender">성별</string>
<string name="word_male">남성</string>
<string name="word_female">여성</string>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.susu.feature.mypage

import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.viewinterop.AndroidView
import com.susu.core.ui.PRIVACY_POLICY_URL

@Composable
fun MyPagePrivacyPolicyScreen(
modifier: Modifier = Modifier,
) {
AndroidView(
modifier = modifier.fillMaxSize(),
factory = { context ->
return@AndroidView WebView(context).apply {
webViewClient = WebViewClient()
}
},
update = {
it.loadUrl(PRIVACY_POLICY_URL)
},
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.susu.core.ui.nameRegex

sealed interface MyPageInfoEffect : SideEffect {
data object PopBackStack : MyPageInfoEffect
data object ShowNameNotValidSnackBar : MyPageInfoEffect
data class ShowSnackBar(val msg: String) : MyPageInfoEffect
data class HandleException(val throwable: Throwable, val retry: () -> Unit) : MyPageInfoEffect
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
Expand All @@ -37,9 +37,11 @@ import com.susu.core.designsystem.component.button.SusuFilledButton
import com.susu.core.designsystem.component.textfield.SusuBasicTextField
import com.susu.core.designsystem.theme.Gray100
import com.susu.core.designsystem.theme.Gray40
import com.susu.core.designsystem.theme.Gray50
import com.susu.core.designsystem.theme.SusuTheme
import com.susu.core.ui.Gender
import com.susu.core.ui.SnackbarToken
import com.susu.core.ui.USER_BIRTH_RANGE
import com.susu.core.ui.extension.collectWithLifecycle
import com.susu.core.ui.extension.susuClickable
import com.susu.feature.mypage.R
Expand All @@ -53,11 +55,16 @@ fun MyPageInfoRoute(
onShowSnackbar: (SnackbarToken) -> Unit,
handleException: (Throwable, () -> Unit) -> Unit,
) {
val context = LocalContext.current

viewModel.sideEffect.collectWithLifecycle { sideEffect ->
when (sideEffect) {
MyPageInfoEffect.PopBackStack -> popBackStack()
is MyPageInfoEffect.ShowSnackBar -> onShowSnackbar(SnackbarToken(message = sideEffect.msg))
is MyPageInfoEffect.HandleException -> handleException(sideEffect.throwable, sideEffect.retry)
MyPageInfoEffect.ShowNameNotValidSnackBar -> onShowSnackbar(
SnackbarToken(message = context.getString(R.string.mypage_my_info_snackbar_invalid_name)),
)
}
}

Expand Down Expand Up @@ -123,20 +130,19 @@ fun MyPageInfoScreen(
if (uiState.isEditing) {
Text(
modifier = Modifier
.padding(end = SusuTheme.spacing.spacing_m)
.susuClickable(
runIf = uiState.isEditNameValid,
onClick = onEditComplete,
)
.padding(end = SusuTheme.spacing.spacing_m),
),
text = stringResource(id = com.susu.core.ui.R.string.word_enrollment),
style = SusuTheme.typography.title_xxs,
color = Gray100,
color = if (uiState.isEditNameValid) Gray100 else Gray50,
)
} else {
Text(
modifier = Modifier
.susuClickable(onClick = onEditStart)
.padding(end = SusuTheme.spacing.spacing_m),
.padding(end = SusuTheme.spacing.spacing_m)
.susuClickable(onClick = onEditStart),
text = stringResource(id = com.susu.core.ui.R.string.word_edit),
style = SusuTheme.typography.title_xxs,
color = Gray100,
Expand All @@ -154,7 +160,8 @@ fun MyPageInfoScreen(
)
Spacer(modifier = Modifier.height(SusuTheme.spacing.spacing_m))
MyPageInfoItem(
title = "이름",
title = stringResource(id = com.susu.core.ui.R.string.word_name),
isWrong = uiState.isEditing && !uiState.isEditNameValid,
) {
if (uiState.isEditing) {
SusuBasicTextField(
Expand All @@ -181,12 +188,24 @@ fun MyPageInfoScreen(
modifier = Modifier.susuClickable(
onClick = onBirthClick,
),
text = uiState.editBirth.toString(),
text = if (uiState.editBirth in USER_BIRTH_RANGE) {
uiState.editBirth.toString()
} else {
stringResource(id = com.susu.core.ui.R.string.word_not_select)
},
style = SusuTheme.typography.title_xs,
color = if (uiState.birthEdited) Gray100 else Gray40,
)
} else {
Text(text = uiState.userBirth.toString(), style = SusuTheme.typography.title_xs, color = Gray100)
Text(
text = if (uiState.userBirth in USER_BIRTH_RANGE) {
uiState.userBirth.toString()
} else {
stringResource(id = com.susu.core.ui.R.string.word_not_select)
},
style = SusuTheme.typography.title_xs,
color = Gray100,
)
}
}
MyPageInfoItem(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class MyPageInfoViewModel @Inject constructor(
intent {
copy(
isEditing = true,
editName = "",
editName = uiState.value.userName,
editGender = uiState.value.userGender,
editBirth = uiState.value.userBirth,
)
Expand Down Expand Up @@ -78,6 +78,11 @@ class MyPageInfoViewModel @Inject constructor(
}

fun completeEdit() {
if (!uiState.value.isEditNameValid) {
postSideEffect(MyPageInfoEffect.ShowNameNotValidSnackBar)
return
}

viewModelScope.launch {
intent { copy(isLoading = true) }
patchUserUseCase(name = uiState.value.editName, gender = uiState.value.editGender.content, birth = uiState.value.editBirth)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,75 @@ package com.susu.feature.mypage.info.component

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.susu.core.designsystem.theme.Gray60
import com.susu.core.designsystem.theme.Red60
import com.susu.core.designsystem.theme.SusuTheme

@Composable
fun MyPageInfoItem(
modifier: Modifier = Modifier,
title: String = "",
isWrong: Boolean = false,
content: @Composable () -> Unit,
) {
Row(
modifier = modifier.fillMaxWidth().padding(SusuTheme.spacing.spacing_m),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
) {
Text(text = title, style = SusuTheme.typography.title_xxs, color = Gray60)
Row {
Text(text = title, style = SusuTheme.typography.title_xxs, color = Gray60)
if (isWrong) {
Spacer(modifier = Modifier.width(SusuTheme.spacing.spacing_xxxxs))
WrongDot()
}
}

content()
}
}

@Composable
fun WrongDot(
modifier: Modifier = Modifier,
dotRadius: Dp = 2.dp,
color: Color = Red60,
) {
Spacer(
modifier = modifier.width(4.dp).wrapContentHeight()
.drawBehind {
drawCircle(
color = color,
radius = dotRadius.toPx(),
center = Offset(0f, 8.dp.toPx()),
)
},
)
}

@Preview
@Composable
fun MyPageInfoItemPreview() {
SusuTheme {
MyPageInfoItem(
title = "이름",
isWrong = true,
) {
}
}
}
Loading
Loading