From 3f85aec6dab6370d7bccda0723904c7520f4ec2d Mon Sep 17 00:00:00 2001 From: flash159483 Date: Mon, 8 Jul 2024 20:28:55 +0900 Subject: [PATCH 1/6] =?UTF-8?q?[FEAT]#21:=20=ED=95=99=EA=B5=90=20=EC=84=A0?= =?UTF-8?q?=ED=83=9D=20=ED=99=94=EB=A9=B4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 3 +- .../kotlin/com/bff/wespot/MainActivity.kt | 4 +- .../kotlin/com/bff/wespot/model/SchoolItem.kt | 7 + .../main/kotlin/com/bff/wespot/model/empty | 1 - .../com/bff/wespot/ui/SchoolListItem.kt | 123 +++++++++++++++ core/ui/src/main/res/drawable/exclude.xml | 10 ++ core/ui/src/main/res/values/string.xml | 4 + .../bff/wespot/auth/screen/SchoolScreen.kt | 149 ++++++++++++++++++ .../com/bff/wespot/auth/state/AuthAction.kt | 8 + .../bff/wespot/auth/state/AuthSideEffect.kt | 5 + .../com/bff/wespot/auth/state/AuthUiState.kt | 10 ++ .../wespot/auth/viewmodel/AuthViewModel.kt | 40 +++++ feature/auth/src/main/res/values/string.xml | 10 ++ 13 files changed, 370 insertions(+), 4 deletions(-) create mode 100644 core/model/src/main/kotlin/com/bff/wespot/model/SchoolItem.kt delete mode 100644 core/model/src/main/kotlin/com/bff/wespot/model/empty create mode 100644 core/ui/src/main/kotlin/com/bff/wespot/ui/SchoolListItem.kt create mode 100644 core/ui/src/main/res/drawable/exclude.xml create mode 100644 core/ui/src/main/res/values/string.xml create mode 100644 feature/auth/src/main/kotlin/com/bff/wespot/auth/screen/SchoolScreen.kt create mode 100644 feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthAction.kt create mode 100644 feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthSideEffect.kt create mode 100644 feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthUiState.kt create mode 100644 feature/auth/src/main/kotlin/com/bff/wespot/auth/viewmodel/AuthViewModel.kt create mode 100644 feature/auth/src/main/res/values/string.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 855bafe3..7ee8309a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -16,7 +16,8 @@ android:name=".MainActivity" android:exported="true" android:label="@string/app_name" - android:theme="@style/Theme.WeSpot"> + android:theme="@style/Theme.WeSpot" + android:windowSoftInputMode="adjustResize"> diff --git a/app/src/main/kotlin/com/bff/wespot/MainActivity.kt b/app/src/main/kotlin/com/bff/wespot/MainActivity.kt index fff46e95..c6770b32 100644 --- a/app/src/main/kotlin/com/bff/wespot/MainActivity.kt +++ b/app/src/main/kotlin/com/bff/wespot/MainActivity.kt @@ -5,8 +5,8 @@ import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.Surface -import androidx.compose.material3.Text import androidx.compose.ui.Modifier +import com.bff.wespot.auth.screen.SchoolScreen import com.bff.wespot.designsystem.theme.WeSpotTheme class MainActivity : ComponentActivity() { @@ -18,7 +18,7 @@ class MainActivity : ComponentActivity() { Surface( modifier = Modifier.fillMaxSize(), ) { - Text(text = "Hello, World!") + SchoolScreen() } } } diff --git a/core/model/src/main/kotlin/com/bff/wespot/model/SchoolItem.kt b/core/model/src/main/kotlin/com/bff/wespot/model/SchoolItem.kt new file mode 100644 index 00000000..6bc4d597 --- /dev/null +++ b/core/model/src/main/kotlin/com/bff/wespot/model/SchoolItem.kt @@ -0,0 +1,7 @@ +package com.bff.wespot.model + +data class SchoolItem( + val id: String, + val name: String, + val address: String, +) \ No newline at end of file diff --git a/core/model/src/main/kotlin/com/bff/wespot/model/empty b/core/model/src/main/kotlin/com/bff/wespot/model/empty deleted file mode 100644 index e5f106f7..00000000 --- a/core/model/src/main/kotlin/com/bff/wespot/model/empty +++ /dev/null @@ -1 +0,0 @@ -model module \ No newline at end of file diff --git a/core/ui/src/main/kotlin/com/bff/wespot/ui/SchoolListItem.kt b/core/ui/src/main/kotlin/com/bff/wespot/ui/SchoolListItem.kt new file mode 100644 index 00000000..af611c7f --- /dev/null +++ b/core/ui/src/main/kotlin/com/bff/wespot/ui/SchoolListItem.kt @@ -0,0 +1,123 @@ +package com.bff.wespot.ui + +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.wrapContentHeight +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.School +import androidx.compose.material3.Icon +import androidx.compose.material3.Surface +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.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import com.bff.wespot.designsystem.theme.StaticTypeScale +import com.bff.wespot.designsystem.theme.WeSpotTheme +import com.bff.wespot.designsystem.theme.WeSpotThemeManager +import com.bff.wespot.designsystem.util.OrientationPreviews + +@Composable +fun SchoolListItem( + schoolName: String, + address: String, + selected: Boolean, + onClick: () -> Unit = { } +) { + Box( + modifier = Modifier + .fillMaxWidth() + .wrapContentHeight() + .padding(vertical = 8.dp) + .clip(WeSpotThemeManager.shapes.medium) + .border( + width = 1.dp, + color = if(selected) { + WeSpotThemeManager.colors.primaryColor + } else { + WeSpotThemeManager.colors.cardBackgroundColor + }, + shape = WeSpotThemeManager.shapes.medium + ) + .background(WeSpotThemeManager.colors.cardBackgroundColor) + .clickable { onClick.invoke() } + ) { + Row( + modifier = Modifier.padding(horizontal = 24.dp, vertical = 16.dp), + ) { + Box( + modifier = Modifier + .size(56.dp) + .clip(CircleShape) + .background(Color.White), + contentAlignment = Alignment.Center + ) { + Icon( + imageVector = Icons.Default.School, + contentDescription = stringResource(id = R.string.school_icon) + ) + } + + Column( + modifier = Modifier.padding(top = 4.dp, bottom = 4.dp, start = 16.dp), + verticalArrangement = Arrangement.spacedBy(4.dp) + ) { + Text(text = schoolName, style = StaticTypeScale.Default.body2, maxLines = 1) + Text( + text = address, + style = StaticTypeScale.Default.body6, + color = WeSpotThemeManager.colors.txtSubColor, + maxLines = 1 + ) + } + } + Box( + modifier = Modifier + .fillMaxWidth() + .padding(end = 14.dp, top = 14.dp), + contentAlignment = Alignment.TopEnd + ) { + Icon( + painter = painterResource(id = R.drawable.exclude), + contentDescription = "", + tint = if (selected) { + WeSpotThemeManager.colors.primaryColor + } else { + WeSpotThemeManager.colors.disableIcnColor + } + ) + } + } +} + +@OrientationPreviews +@Composable +private fun SchoolListItemPreview() { + WeSpotTheme { + Surface(modifier = Modifier.fillMaxSize()) { + Column { + repeat(10) { + SchoolListItem( + schoolName = "역삼 중학교", + address = "서울특별시 강남구 도곡로 43길 10", + selected = false + ) + } + } + } + } +} \ No newline at end of file diff --git a/core/ui/src/main/res/drawable/exclude.xml b/core/ui/src/main/res/drawable/exclude.xml new file mode 100644 index 00000000..4d82e563 --- /dev/null +++ b/core/ui/src/main/res/drawable/exclude.xml @@ -0,0 +1,10 @@ + + + diff --git a/core/ui/src/main/res/values/string.xml b/core/ui/src/main/res/values/string.xml new file mode 100644 index 00000000..22ec7b9b --- /dev/null +++ b/core/ui/src/main/res/values/string.xml @@ -0,0 +1,4 @@ + + + school icon + \ No newline at end of file diff --git a/feature/auth/src/main/kotlin/com/bff/wespot/auth/screen/SchoolScreen.kt b/feature/auth/src/main/kotlin/com/bff/wespot/auth/screen/SchoolScreen.kt new file mode 100644 index 00000000..5d5ab91a --- /dev/null +++ b/feature/auth/src/main/kotlin/com/bff/wespot/auth/screen/SchoolScreen.kt @@ -0,0 +1,149 @@ +package com.bff.wespot.auth.screen + +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.imePadding +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalSoftwareKeyboardController +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel +import com.bff.wespot.auth.R +import com.bff.wespot.auth.state.AuthAction +import com.bff.wespot.auth.viewmodel.AuthViewModel +import com.bff.wespot.designsystem.component.button.WSButton +import com.bff.wespot.designsystem.component.button.WSTextButton +import com.bff.wespot.designsystem.component.button.WSTextButtonType +import com.bff.wespot.designsystem.component.header.WSTopBar +import com.bff.wespot.designsystem.component.input.WsTextField +import com.bff.wespot.designsystem.component.input.WsTextFieldType +import com.bff.wespot.designsystem.theme.StaticTypeScale +import com.bff.wespot.designsystem.theme.WeSpotTheme +import com.bff.wespot.designsystem.theme.WeSpotThemeManager +import com.bff.wespot.designsystem.util.OrientationPreviews +import com.bff.wespot.ui.SchoolListItem +import kotlinx.coroutines.delay +import org.orbitmvi.orbit.compose.collectAsState + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun SchoolScreen(viewModel: AuthViewModel = viewModel()) { + val keyboard = LocalSoftwareKeyboardController.current + val focusRequester = remember { FocusRequester() } + + val state by viewModel.collectAsState() + val action = viewModel::onAction + + Scaffold( + topBar = { + WSTopBar(title = stringResource(id = R.string.register)) + } + ) { + Column( + modifier = Modifier + .fillMaxSize() + .padding(it) + .padding(horizontal = 24.dp) + ) { + Text( + stringResource(id = R.string.search_school), + style = StaticTypeScale.Default.header1 + ) + Spacer(modifier = Modifier.padding(8.dp)) + Text( + stringResource(id = R.string.search_base_on_your_school), + style = StaticTypeScale.Default.body8, + color = Color(0xFF7A7A7A) + ) + Spacer(modifier = Modifier.padding(12.dp)) + + WsTextField( + value = state.schoolName, + onValueChange = { + action(AuthAction.OnSchoolSearchChanged(it)) + }, + placeholder = stringResource(id = R.string.search_with_school_name), + textFieldType = WsTextFieldType.Search, + focusRequester = focusRequester, + singleLine = true + ) + + Spacer(modifier = Modifier.padding(vertical = 8.dp)) + if (state.schoolName.length >= 20) { + Text( + stringResource(id = R.string.within_20_characters), + style = StaticTypeScale.Default.body8, + color = WeSpotThemeManager.colors.dangerColor + ) + } + + if (state.schoolSearchList.isEmpty()) { + Box(modifier = Modifier.fillMaxWidth(), contentAlignment = Alignment.Center) { + WSTextButton( + text = stringResource(id = R.string.no_school_found), + onClick = { }, + buttonType = WSTextButtonType.Underline + ) + } + } + + LazyColumn() { + items(state.schoolSearchList, key = { school -> + school.id + }) { school -> + SchoolListItem( + schoolName = school.name, + address = school.address, + selected = state.selectedSchool?.name == school.name + ) { + action(AuthAction.OnSchoolSelected(school)) + } + } + } + } + } + + Box( + modifier = Modifier + .fillMaxSize() + .imePadding(), + contentAlignment = Alignment.BottomCenter + ) { + WSButton(onClick = { }, enabled = false, text = stringResource(id = R.string.next)) { + it() + } + } + + LaunchedEffect(focusRequester) { + focusRequester.requestFocus() + delay(10) + keyboard?.show() + } +} + +@OrientationPreviews +@Composable +private fun SchoolScreenPreview() { + WeSpotTheme { + Surface(modifier = Modifier.fillMaxSize()) { + SchoolScreen() + } + } +} \ No newline at end of file diff --git a/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthAction.kt b/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthAction.kt new file mode 100644 index 00000000..9aaaf278 --- /dev/null +++ b/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthAction.kt @@ -0,0 +1,8 @@ +package com.bff.wespot.auth.state + +import com.bff.wespot.model.SchoolItem + +sealed class AuthAction { + data class OnSchoolSearchChanged(val text: String) : AuthAction() + data class OnSchoolSelected(val school: SchoolItem) : AuthAction() +} \ No newline at end of file diff --git a/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthSideEffect.kt b/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthSideEffect.kt new file mode 100644 index 00000000..9264ac19 --- /dev/null +++ b/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthSideEffect.kt @@ -0,0 +1,5 @@ +package com.bff.wespot.auth.state + +sealed class AuthSideEffect { + +} \ No newline at end of file diff --git a/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthUiState.kt b/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthUiState.kt new file mode 100644 index 00000000..74cc2e87 --- /dev/null +++ b/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthUiState.kt @@ -0,0 +1,10 @@ +package com.bff.wespot.auth.state + +import com.bff.wespot.model.SchoolItem + +data class AuthUiState( + val schoolName: String = "", + val schoolList: List = emptyList(), + val schoolSearchList: List = emptyList(), + val selectedSchool: SchoolItem? = null, +) diff --git a/feature/auth/src/main/kotlin/com/bff/wespot/auth/viewmodel/AuthViewModel.kt b/feature/auth/src/main/kotlin/com/bff/wespot/auth/viewmodel/AuthViewModel.kt new file mode 100644 index 00000000..eab3513e --- /dev/null +++ b/feature/auth/src/main/kotlin/com/bff/wespot/auth/viewmodel/AuthViewModel.kt @@ -0,0 +1,40 @@ +package com.bff.wespot.auth.viewmodel + +import androidx.lifecycle.ViewModel +import com.bff.wespot.auth.state.AuthAction +import com.bff.wespot.auth.state.AuthSideEffect +import com.bff.wespot.auth.state.AuthUiState +import com.bff.wespot.model.SchoolItem +import org.orbitmvi.orbit.ContainerHost +import org.orbitmvi.orbit.syntax.simple.intent +import org.orbitmvi.orbit.syntax.simple.reduce +import org.orbitmvi.orbit.viewmodel.container + +class AuthViewModel: ViewModel() , ContainerHost { + override val container = container(AuthUiState()) + + fun onAction(action: AuthAction) { + when (action) { + is AuthAction.OnSchoolSearchChanged -> handleSchoolSearchChanged(action.text) + is AuthAction.OnSchoolSelected -> handleSchoolSelected(action.school) + else -> {} + } + } + + private fun handleSchoolSearchChanged(text: String) = intent { + reduce { + state.copy( + schoolName = text, + schoolSearchList = state.schoolList.filter { it.name.contains(text, ignoreCase = true) } + ) + } + } + + private fun handleSchoolSelected(school: SchoolItem) = intent { + reduce { + state.copy( + selectedSchool = school + ) + } + } +} \ No newline at end of file diff --git a/feature/auth/src/main/res/values/string.xml b/feature/auth/src/main/res/values/string.xml new file mode 100644 index 00000000..e16a6c19 --- /dev/null +++ b/feature/auth/src/main/res/values/string.xml @@ -0,0 +1,10 @@ + + + 회원가입 + 학교 검색 + 현재 재학 중인 학교 기준으로 검색해 주세요 + 20자 이내로 검색해 주세요 + 학교 이름으로 검색해 보세요 + 찾는 학교가 없다면? + 다음 + \ No newline at end of file From 2a4890a106fb901250fc6373b003de826f41d46a Mon Sep 17 00:00:00 2001 From: flash159483 Date: Mon, 8 Jul 2024 21:25:07 +0900 Subject: [PATCH 2/6] =?UTF-8?q?[FEAT]#21:=20=ED=95=99=EB=85=84=20=EC=84=A0?= =?UTF-8?q?=ED=83=9D=20=ED=99=94=EB=A9=B4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/com/bff/wespot/ui/WSBottomSheet.kt | 31 +++ .../com/bff/wespot/auth/screen/GradeScreen.kt | 187 ++++++++++++++++++ .../com/bff/wespot/auth/state/AuthAction.kt | 2 + .../com/bff/wespot/auth/state/AuthUiState.kt | 2 + .../wespot/auth/viewmodel/AuthViewModel.kt | 18 ++ feature/auth/src/main/res/values/string.xml | 5 + 6 files changed, 245 insertions(+) create mode 100644 core/ui/src/main/kotlin/com/bff/wespot/ui/WSBottomSheet.kt create mode 100644 feature/auth/src/main/kotlin/com/bff/wespot/auth/screen/GradeScreen.kt diff --git a/core/ui/src/main/kotlin/com/bff/wespot/ui/WSBottomSheet.kt b/core/ui/src/main/kotlin/com/bff/wespot/ui/WSBottomSheet.kt new file mode 100644 index 00000000..f020bf04 --- /dev/null +++ b/core/ui/src/main/kotlin/com/bff/wespot/ui/WSBottomSheet.kt @@ -0,0 +1,31 @@ +package com.bff.wespot.ui + +import androidx.compose.foundation.layout.navigationBarsPadding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.ModalBottomSheet +import androidx.compose.material3.SheetState +import androidx.compose.material3.rememberStandardBottomSheetState +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import com.bff.wespot.designsystem.theme.WeSpotThemeManager + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun WSBottomSheet( + closeSheet: () -> Unit, + sheetState: SheetState = rememberStandardBottomSheetState(), + content: @Composable () -> Unit +) { + ModalBottomSheet( + onDismissRequest = closeSheet, + sheetState = sheetState, + shape = RoundedCornerShape(topStart = 25.dp, topEnd = 25.dp), + containerColor = WeSpotThemeManager.colors.bottomSheetColor, + dragHandle = null, + modifier = Modifier.navigationBarsPadding() + ) { + content.invoke() + } +} \ No newline at end of file diff --git a/feature/auth/src/main/kotlin/com/bff/wespot/auth/screen/GradeScreen.kt b/feature/auth/src/main/kotlin/com/bff/wespot/auth/screen/GradeScreen.kt new file mode 100644 index 00000000..cb31f488 --- /dev/null +++ b/feature/auth/src/main/kotlin/com/bff/wespot/auth/screen/GradeScreen.kt @@ -0,0 +1,187 @@ +package com.bff.wespot.auth.screen + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.material3.rememberModalBottomSheetState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel +import com.bff.wespot.auth.R +import com.bff.wespot.auth.state.AuthAction +import com.bff.wespot.auth.viewmodel.AuthViewModel +import com.bff.wespot.designsystem.component.button.WSButton +import com.bff.wespot.designsystem.component.button.WSOutlineButton +import com.bff.wespot.designsystem.component.header.WSTopBar +import com.bff.wespot.designsystem.theme.StaticTypeScale +import com.bff.wespot.designsystem.theme.WeSpotTheme +import com.bff.wespot.designsystem.theme.WeSpotThemeManager +import com.bff.wespot.designsystem.util.OrientationPreviews +import com.bff.wespot.ui.WSBottomSheet +import org.orbitmvi.orbit.compose.collectAsState + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun GradeScreen(viewModel: AuthViewModel = viewModel()) { + val state by viewModel.collectAsState() + val action = viewModel::onAction + + Scaffold( + topBar = { + WSTopBar(title = stringResource(id = R.string.register), canNavigateBack = true) + }, + ) { + Column( + modifier = Modifier.padding(it), + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + Text( + text = stringResource(id = R.string.grade), + style = StaticTypeScale.Default.header1, + modifier = Modifier.padding(horizontal = 20.dp) + ) + + Text( + text = stringResource(id = R.string.cannot_change_after_register), + style = StaticTypeScale.Default.body6, + color = Color(0xFF7A7A7A), + modifier = Modifier.padding(horizontal = 20.dp) + ) + + Box( + modifier = Modifier + .fillMaxWidth() + .clickable { + action(AuthAction.OnGradeBottomSheetChanged(true)) + } + ) { + WSOutlineButton( + text = "", + onClick = { + action(AuthAction.OnGradeBottomSheetChanged(true)) + } + ) { + Box(modifier = Modifier + .fillMaxWidth() + .padding(20.dp)) { + Text( + text = if (state.grade == -1) { + stringResource(id = R.string.select_grade) + } else { + "${state.grade}${stringResource(id = R.string.grade)}" + }, + style = StaticTypeScale.Default.body4, + color = if (state.grade == -1) { + WeSpotThemeManager.colors.disableBtnColor + } else { + WeSpotThemeManager.colors.txtTitleColor + } + ) + } + } + } + + if (state.gradeBottomSheet) { + WSBottomSheet( + closeSheet = { action(AuthAction.OnGradeBottomSheetChanged(false)) }, + sheetState = rememberModalBottomSheetState( + skipPartiallyExpanded = true + ) + ) { + BottomSheetContent(currentGrade = state.grade, onGradeSelected = { grade -> + action(AuthAction.OnGradeChanged(grade)) + }) + } + } + } + + Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.BottomCenter) { + WSButton(onClick = { }, text = stringResource(id = R.string.next)) { + it.invoke() + } + } + } +} + +@Composable +private fun BottomSheetContent( + currentGrade: Int, + onGradeSelected: (Int) -> Unit +) { + Column( + modifier = Modifier.padding(vertical = 28.dp, horizontal = 32.dp) + ) { + Text( + text = stringResource(id = R.string.select_grade), + style = StaticTypeScale.Default.body1 + ) + Spacer(modifier = Modifier.padding(vertical = 4.dp)) + + Text( + text = stringResource(id = R.string.more_than_14_to_register), + style = StaticTypeScale.Default.body6, + color = Color(0xFF7A7A7A) + ) + + Spacer(modifier = Modifier.padding(vertical = 8.dp)) + + Column( + modifier = Modifier.fillMaxWidth() + ) { + repeat(3) { + Row( + horizontalArrangement = Arrangement.SpaceBetween, + modifier = Modifier + .clickable { onGradeSelected(it + 1) } + .padding(vertical = 12.dp) + .fillMaxWidth() + ) { + Text( + text = "${it + 1}${stringResource(id = R.string.grade)}", + style = StaticTypeScale.Default.body3 + ) + + Icon( + painter = painterResource(id = com.bff.wespot.ui.R.drawable.exclude), + contentDescription = stringResource(id = R.string.check_icon), + tint = if (it == currentGrade - 1) { + WeSpotThemeManager.colors.primaryColor + } else { + WeSpotThemeManager.colors.disableBtnColor + } + ) + } + } + } + } +} + + +@OrientationPreviews +@Composable +private fun GradeScreenPreview() { + WeSpotTheme { + Surface( + modifier = Modifier.fillMaxSize() + ) { + GradeScreen() + } + } +} \ No newline at end of file diff --git a/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthAction.kt b/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthAction.kt index 9aaaf278..f1004833 100644 --- a/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthAction.kt +++ b/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthAction.kt @@ -5,4 +5,6 @@ import com.bff.wespot.model.SchoolItem sealed class AuthAction { data class OnSchoolSearchChanged(val text: String) : AuthAction() data class OnSchoolSelected(val school: SchoolItem) : AuthAction() + data class OnGradeChanged(val grade: Int) : AuthAction() + data class OnGradeBottomSheetChanged(val isOpen: Boolean) : AuthAction() } \ No newline at end of file diff --git a/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthUiState.kt b/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthUiState.kt index 74cc2e87..37074d41 100644 --- a/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthUiState.kt +++ b/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthUiState.kt @@ -7,4 +7,6 @@ data class AuthUiState( val schoolList: List = emptyList(), val schoolSearchList: List = emptyList(), val selectedSchool: SchoolItem? = null, + val grade: Int = -1, + val gradeBottomSheet: Boolean = true, ) diff --git a/feature/auth/src/main/kotlin/com/bff/wespot/auth/viewmodel/AuthViewModel.kt b/feature/auth/src/main/kotlin/com/bff/wespot/auth/viewmodel/AuthViewModel.kt index eab3513e..de6b2da7 100644 --- a/feature/auth/src/main/kotlin/com/bff/wespot/auth/viewmodel/AuthViewModel.kt +++ b/feature/auth/src/main/kotlin/com/bff/wespot/auth/viewmodel/AuthViewModel.kt @@ -17,6 +17,8 @@ class AuthViewModel: ViewModel() , ContainerHost { when (action) { is AuthAction.OnSchoolSearchChanged -> handleSchoolSearchChanged(action.text) is AuthAction.OnSchoolSelected -> handleSchoolSelected(action.school) + is AuthAction.OnGradeBottomSheetChanged -> handleGradeBottomSheetChanged(action.isOpen) + is AuthAction.OnGradeChanged -> handleGradeChanged(action.grade) else -> {} } } @@ -37,4 +39,20 @@ class AuthViewModel: ViewModel() , ContainerHost { ) } } + + private fun handleGradeBottomSheetChanged(isOpen: Boolean) = intent { + reduce { + state.copy( + gradeBottomSheet = isOpen + ) + } + } + + private fun handleGradeChanged(grade: Int) = intent { + reduce { + state.copy( + grade = grade + ) + } + } } \ No newline at end of file diff --git a/feature/auth/src/main/res/values/string.xml b/feature/auth/src/main/res/values/string.xml index e16a6c19..50c4142d 100644 --- a/feature/auth/src/main/res/values/string.xml +++ b/feature/auth/src/main/res/values/string.xml @@ -7,4 +7,9 @@ 학교 이름으로 검색해 보세요 찾는 학교가 없다면? 다음 + 학년 + 회원가입 이후에는 변경할 수 없어요 + 햔재 학년을 선택해 주세요 + 만 14세 미만 학생은 가입이 어려워요 + 체크 아이콘 \ No newline at end of file From 6087dc3e653e8c81d069a0c57047c25a6959d11f Mon Sep 17 00:00:00 2001 From: flash159483 Date: Mon, 8 Jul 2024 21:45:16 +0900 Subject: [PATCH 3/6] =?UTF-8?q?[FEAT]#21:=20=EB=B0=98=20=EC=84=A0=ED=83=9D?= =?UTF-8?q?=20=ED=99=94=EB=A9=B4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/bff/wespot/auth/screen/ClassScreen.kt | 119 ++++++++++++++++++ .../com/bff/wespot/auth/screen/GradeScreen.kt | 2 +- .../com/bff/wespot/auth/state/AuthAction.kt | 1 + .../com/bff/wespot/auth/state/AuthUiState.kt | 1 + .../wespot/auth/viewmodel/AuthViewModel.kt | 9 ++ feature/auth/src/main/res/values/string.xml | 6 +- 6 files changed, 136 insertions(+), 2 deletions(-) create mode 100644 feature/auth/src/main/kotlin/com/bff/wespot/auth/screen/ClassScreen.kt diff --git a/feature/auth/src/main/kotlin/com/bff/wespot/auth/screen/ClassScreen.kt b/feature/auth/src/main/kotlin/com/bff/wespot/auth/screen/ClassScreen.kt new file mode 100644 index 00000000..23973e3d --- /dev/null +++ b/feature/auth/src/main/kotlin/com/bff/wespot/auth/screen/ClassScreen.kt @@ -0,0 +1,119 @@ +package com.bff.wespot.auth.screen + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.imePadding +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalSoftwareKeyboardController +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel +import com.bff.wespot.auth.R +import com.bff.wespot.auth.state.AuthAction +import com.bff.wespot.auth.viewmodel.AuthViewModel +import com.bff.wespot.designsystem.component.button.WSButton +import com.bff.wespot.designsystem.component.header.WSTopBar +import com.bff.wespot.designsystem.component.input.WsTextField +import com.bff.wespot.designsystem.theme.StaticTypeScale +import com.bff.wespot.designsystem.theme.WeSpotThemeManager +import kotlinx.coroutines.delay +import org.orbitmvi.orbit.compose.collectAsState + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun ClassScreen( + viewModel: AuthViewModel = viewModel() +) { + val keyboard = LocalSoftwareKeyboardController.current + + val state by viewModel.collectAsState() + val action = viewModel::onAction + val focusRequester = remember { FocusRequester() } + + Scaffold( + topBar = { + WSTopBar(title = stringResource(id = R.string.register), canNavigateBack = true) + }, + modifier = Modifier.padding(horizontal = 20.dp) + ) { + Column( + modifier = Modifier + .fillMaxSize() + .padding(it), + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + Text( + text = stringResource(id = R.string.get_class), + style = StaticTypeScale.Default.header1 + ) + + Text( + text = stringResource(id = R.string.cannot_change_class_after_register), + style = StaticTypeScale.Default.body6, + color = Color(0xFF7A7A7A) + ) + + WsTextField( + value = if (state.classNumber != -1) { + state.classNumber.toString() + } else { + "" + }, + onValueChange = { classNumber -> + if (classNumber.isEmpty()) { + action(AuthAction.OnClassNumberChanged(-1)) + return@WsTextField + } + action(AuthAction.OnClassNumberChanged(classNumber.toInt())) + }, + placeholder = stringResource(id = R.string.enter_number), + focusRequester = focusRequester, + keyBoardOption = KeyboardOptions(keyboardType = KeyboardType.Number) + ) + + if (state.classNumber != -1 && state.classNumber !in 1..20) { + Text( + text = stringResource(id = R.string.class_number_error), + color = WeSpotThemeManager.colors.dangerColor, + style = StaticTypeScale.Default.body8 + ) + } + } + } + + Box( + modifier = Modifier + .fillMaxSize() + .imePadding(), + contentAlignment = Alignment.BottomCenter + ) { + WSButton( + onClick = { }, + text = stringResource(id = R.string.next), + enabled = state.classNumber in 1..20 + ) { + it.invoke() + } + } + + LaunchedEffect(focusRequester) { + focusRequester.requestFocus() + delay(10) + keyboard?.show() + } +} \ No newline at end of file diff --git a/feature/auth/src/main/kotlin/com/bff/wespot/auth/screen/GradeScreen.kt b/feature/auth/src/main/kotlin/com/bff/wespot/auth/screen/GradeScreen.kt index cb31f488..c4c5c0de 100644 --- a/feature/auth/src/main/kotlin/com/bff/wespot/auth/screen/GradeScreen.kt +++ b/feature/auth/src/main/kotlin/com/bff/wespot/auth/screen/GradeScreen.kt @@ -59,7 +59,7 @@ fun GradeScreen(viewModel: AuthViewModel = viewModel()) { ) Text( - text = stringResource(id = R.string.cannot_change_after_register), + text = stringResource(id = R.string.cannot_change_grade_after_register), style = StaticTypeScale.Default.body6, color = Color(0xFF7A7A7A), modifier = Modifier.padding(horizontal = 20.dp) diff --git a/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthAction.kt b/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthAction.kt index f1004833..c9112080 100644 --- a/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthAction.kt +++ b/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthAction.kt @@ -7,4 +7,5 @@ sealed class AuthAction { data class OnSchoolSelected(val school: SchoolItem) : AuthAction() data class OnGradeChanged(val grade: Int) : AuthAction() data class OnGradeBottomSheetChanged(val isOpen: Boolean) : AuthAction() + data class OnClassNumberChanged(val number: Int) : AuthAction() } \ No newline at end of file diff --git a/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthUiState.kt b/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthUiState.kt index 37074d41..1f977c50 100644 --- a/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthUiState.kt +++ b/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthUiState.kt @@ -9,4 +9,5 @@ data class AuthUiState( val selectedSchool: SchoolItem? = null, val grade: Int = -1, val gradeBottomSheet: Boolean = true, + val classNumber: Int = -1, ) diff --git a/feature/auth/src/main/kotlin/com/bff/wespot/auth/viewmodel/AuthViewModel.kt b/feature/auth/src/main/kotlin/com/bff/wespot/auth/viewmodel/AuthViewModel.kt index de6b2da7..4d75fcc4 100644 --- a/feature/auth/src/main/kotlin/com/bff/wespot/auth/viewmodel/AuthViewModel.kt +++ b/feature/auth/src/main/kotlin/com/bff/wespot/auth/viewmodel/AuthViewModel.kt @@ -19,6 +19,7 @@ class AuthViewModel: ViewModel() , ContainerHost { is AuthAction.OnSchoolSelected -> handleSchoolSelected(action.school) is AuthAction.OnGradeBottomSheetChanged -> handleGradeBottomSheetChanged(action.isOpen) is AuthAction.OnGradeChanged -> handleGradeChanged(action.grade) + is AuthAction.OnClassNumberChanged -> handleClassNumberChanged(action.number) else -> {} } } @@ -55,4 +56,12 @@ class AuthViewModel: ViewModel() , ContainerHost { ) } } + + private fun handleClassNumberChanged(number: Int) = intent { + reduce { + state.copy( + classNumber = number + ) + } + } } \ No newline at end of file diff --git a/feature/auth/src/main/res/values/string.xml b/feature/auth/src/main/res/values/string.xml index 50c4142d..6c9e4fdc 100644 --- a/feature/auth/src/main/res/values/string.xml +++ b/feature/auth/src/main/res/values/string.xml @@ -8,8 +8,12 @@ 찾는 학교가 없다면? 다음 학년 - 회원가입 이후에는 변경할 수 없어요 + 회원가입 이후에는 변경할 수 없어요 햔재 학년을 선택해 주세요 만 14세 미만 학생은 가입이 어려워요 체크 아이콘 + + 회원가입 이후에는 변경할 수 없어요 + 숫자로 입력해 주세요 + 정확한 반을 입력해주세요 \ No newline at end of file From df0cbd4e058ef747320cb3d5c7d10db52a0f2159 Mon Sep 17 00:00:00 2001 From: flash159483 Date: Mon, 8 Jul 2024 22:06:44 +0900 Subject: [PATCH 4/6] =?UTF-8?q?[FEAT]#21:=20=EC=84=B1=EB=B3=84=20=EC=84=A0?= =?UTF-8?q?=ED=83=9D=20=ED=99=94=EB=A9=B4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/res/drawable/female_student.png | Bin 0 -> 4099 bytes .../ui/src/main/res/drawable/male_student.png | Bin 0 -> 3805 bytes .../bff/wespot/auth/screen/GenderScreen.kt | 125 ++++++++++++++++++ .../com/bff/wespot/auth/state/AuthAction.kt | 1 + .../com/bff/wespot/auth/state/AuthUiState.kt | 1 + .../wespot/auth/viewmodel/AuthViewModel.kt | 18 ++- feature/auth/src/main/res/values/string.xml | 9 +- 7 files changed, 150 insertions(+), 4 deletions(-) create mode 100644 core/ui/src/main/res/drawable/female_student.png create mode 100644 core/ui/src/main/res/drawable/male_student.png create mode 100644 feature/auth/src/main/kotlin/com/bff/wespot/auth/screen/GenderScreen.kt diff --git a/core/ui/src/main/res/drawable/female_student.png b/core/ui/src/main/res/drawable/female_student.png new file mode 100644 index 0000000000000000000000000000000000000000..7580db859853a25142efb0033a286c720368ac6c GIT binary patch literal 4099 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 Tj2-vu00000NkvXXu0mjf>Y+DN literal 0 HcmV?d00001 diff --git a/feature/auth/src/main/kotlin/com/bff/wespot/auth/screen/GenderScreen.kt b/feature/auth/src/main/kotlin/com/bff/wespot/auth/screen/GenderScreen.kt new file mode 100644 index 00000000..b1c025a3 --- /dev/null +++ b/feature/auth/src/main/kotlin/com/bff/wespot/auth/screen/GenderScreen.kt @@ -0,0 +1,125 @@ +package com.bff.wespot.auth.screen + +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.RowScope +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.painter.Painter +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel +import com.bff.wespot.auth.R +import com.bff.wespot.auth.state.AuthAction +import com.bff.wespot.auth.viewmodel.AuthViewModel +import com.bff.wespot.designsystem.component.header.WSTopBar +import com.bff.wespot.designsystem.theme.StaticTypeScale +import com.bff.wespot.designsystem.theme.WeSpotThemeManager +import org.orbitmvi.orbit.compose.collectAsState + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun GenderScreen(viewModel: AuthViewModel = viewModel()) { + val state by viewModel.collectAsState() + val action = viewModel::onAction + + Scaffold( + topBar = { + WSTopBar(title = stringResource(id = R.string.register), canNavigateBack = true) + }, + modifier = Modifier.padding(horizontal = 20.dp) + ) { + Column( + modifier = Modifier.padding(it), + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + Text( + text = stringResource(id = R.string.gender), + style = StaticTypeScale.Default.header1 + ) + Text( + text = stringResource(id = R.string.cannot_change_gender_after_register), + style = StaticTypeScale.Default.body6, + color = Color(0xFF7A7A7A), + ) + + Row( + horizontalArrangement = Arrangement.spacedBy(10.dp) + ) { + GenderBox( + title = stringResource(id = R.string.male_student), + icon = painterResource( + id = com.bff.wespot.ui.R.drawable.male_student + ), + selected = "male" == state.gender, + onClicked = { + action(AuthAction.OnGenderChanged("male")) + } + ) + GenderBox( + title = stringResource(id = R.string.female_student), + icon = painterResource( + id = com.bff.wespot.ui.R.drawable.female_student + ), + selected = "female" == state.gender, + onClicked = { + action(AuthAction.OnGenderChanged("female")) + } + ) + } + } + } +} + +@Composable +private fun RowScope.GenderBox( + title: String, + icon: Painter, + selected: Boolean = false, + onClicked: () -> Unit, +) { + Box( + modifier = Modifier + .weight(1f) + .clip(WeSpotThemeManager.shapes.medium) + .border( + width = 1.dp, + color = if (selected) WeSpotThemeManager.colors.primaryColor else Color.Transparent, + shape = WeSpotThemeManager.shapes.medium + ) + .clickable { onClicked() } + .background(WeSpotThemeManager.colors.cardBackgroundColor), + contentAlignment = Alignment.Center + ) { + Column( + modifier = Modifier.padding(start = 30.dp, end = 30.dp, top = 30.dp, bottom = 17.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Image( + painter = icon, + contentDescription = stringResource(id = R.string.gender_icon), + modifier = Modifier.size(90.dp) + ) + Spacer(modifier = Modifier.height(16.dp)) + Text(text = title, style = StaticTypeScale.Default.header2) + } + } +} \ No newline at end of file diff --git a/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthAction.kt b/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthAction.kt index c9112080..24d14382 100644 --- a/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthAction.kt +++ b/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthAction.kt @@ -8,4 +8,5 @@ sealed class AuthAction { data class OnGradeChanged(val grade: Int) : AuthAction() data class OnGradeBottomSheetChanged(val isOpen: Boolean) : AuthAction() data class OnClassNumberChanged(val number: Int) : AuthAction() + data class OnGenderChanged(val gender: String) : AuthAction() } \ No newline at end of file diff --git a/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthUiState.kt b/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthUiState.kt index 1f977c50..d6df6641 100644 --- a/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthUiState.kt +++ b/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthUiState.kt @@ -10,4 +10,5 @@ data class AuthUiState( val grade: Int = -1, val gradeBottomSheet: Boolean = true, val classNumber: Int = -1, + val gender: String = "" ) diff --git a/feature/auth/src/main/kotlin/com/bff/wespot/auth/viewmodel/AuthViewModel.kt b/feature/auth/src/main/kotlin/com/bff/wespot/auth/viewmodel/AuthViewModel.kt index 4d75fcc4..fa1cbd43 100644 --- a/feature/auth/src/main/kotlin/com/bff/wespot/auth/viewmodel/AuthViewModel.kt +++ b/feature/auth/src/main/kotlin/com/bff/wespot/auth/viewmodel/AuthViewModel.kt @@ -10,7 +10,7 @@ import org.orbitmvi.orbit.syntax.simple.intent import org.orbitmvi.orbit.syntax.simple.reduce import org.orbitmvi.orbit.viewmodel.container -class AuthViewModel: ViewModel() , ContainerHost { +class AuthViewModel : ViewModel(), ContainerHost { override val container = container(AuthUiState()) fun onAction(action: AuthAction) { @@ -20,6 +20,7 @@ class AuthViewModel: ViewModel() , ContainerHost { is AuthAction.OnGradeBottomSheetChanged -> handleGradeBottomSheetChanged(action.isOpen) is AuthAction.OnGradeChanged -> handleGradeChanged(action.grade) is AuthAction.OnClassNumberChanged -> handleClassNumberChanged(action.number) + is AuthAction.OnGenderChanged -> handleGenderChanged(action.gender) else -> {} } } @@ -28,7 +29,12 @@ class AuthViewModel: ViewModel() , ContainerHost { reduce { state.copy( schoolName = text, - schoolSearchList = state.schoolList.filter { it.name.contains(text, ignoreCase = true) } + schoolSearchList = state.schoolList.filter { + it.name.contains( + text, + ignoreCase = true + ) + } ) } } @@ -64,4 +70,12 @@ class AuthViewModel: ViewModel() , ContainerHost { ) } } + + private fun handleGenderChanged(gender: String) = intent { + reduce { + state.copy( + gender = gender + ) + } + } } \ No newline at end of file diff --git a/feature/auth/src/main/res/values/string.xml b/feature/auth/src/main/res/values/string.xml index 6c9e4fdc..ee6515ad 100644 --- a/feature/auth/src/main/res/values/string.xml +++ b/feature/auth/src/main/res/values/string.xml @@ -8,12 +8,17 @@ 찾는 학교가 없다면? 다음 학년 - 회원가입 이후에는 변경할 수 없어요 + 회원가입 이후에는 학년을 변경할 수 없어요 햔재 학년을 선택해 주세요 만 14세 미만 학생은 가입이 어려워요 체크 아이콘 - 회원가입 이후에는 변경할 수 없어요 + 회원가입 이후에는 반을 변경할 수 없어요 숫자로 입력해 주세요 정확한 반을 입력해주세요 + 성병 + 회원가입 이후에는 성별을 변경할 수 없어요 + 성별 아이콘 + 남학생 + 여학생 \ No newline at end of file From 5c717142c8b054343f773963c83e021d156d4a26 Mon Sep 17 00:00:00 2001 From: flash159483 Date: Mon, 8 Jul 2024 22:18:55 +0900 Subject: [PATCH 5/6] =?UTF-8?q?[FEAT]#21:=20=EC=9D=B4=EB=A6=84=20=EC=84=A0?= =?UTF-8?q?=ED=83=9D=20=ED=99=94=EB=A9=B4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/bff/wespot/auth/screen/NameScreen.kt | 123 ++++++++++++++++++ .../com/bff/wespot/auth/state/AuthAction.kt | 1 + .../com/bff/wespot/auth/state/AuthUiState.kt | 3 +- .../wespot/auth/viewmodel/AuthViewModel.kt | 9 ++ feature/auth/src/main/res/values/string.xml | 4 + 5 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 feature/auth/src/main/kotlin/com/bff/wespot/auth/screen/NameScreen.kt diff --git a/feature/auth/src/main/kotlin/com/bff/wespot/auth/screen/NameScreen.kt b/feature/auth/src/main/kotlin/com/bff/wespot/auth/screen/NameScreen.kt new file mode 100644 index 00000000..516c054d --- /dev/null +++ b/feature/auth/src/main/kotlin/com/bff/wespot/auth/screen/NameScreen.kt @@ -0,0 +1,123 @@ +package com.bff.wespot.auth.screen + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +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 +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalSoftwareKeyboardController +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel +import com.bff.wespot.auth.R +import com.bff.wespot.auth.state.AuthAction +import com.bff.wespot.auth.viewmodel.AuthViewModel +import com.bff.wespot.designsystem.component.button.WSButton +import com.bff.wespot.designsystem.component.header.WSTopBar +import com.bff.wespot.designsystem.component.input.WsTextField +import com.bff.wespot.designsystem.theme.StaticTypeScale +import com.bff.wespot.designsystem.theme.WeSpotThemeManager +import kotlinx.coroutines.delay +import org.orbitmvi.orbit.compose.collectAsState + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun NameScreen( + viewModel: AuthViewModel = viewModel() +) { + val keyboard = LocalSoftwareKeyboardController.current + + val state by viewModel.collectAsState() + val action = viewModel::onAction + + val focusRequester = remember { + FocusRequester() + } + + var error by remember { + mutableStateOf(false) + } + + Scaffold( + topBar = { + WSTopBar(title = stringResource(id = R.string.register), canNavigateBack = true) + }, + modifier = Modifier.padding(horizontal = 20.dp) + ) { + Column( + modifier = Modifier.padding(it), + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + Text( + text = stringResource(id = R.string.name), + style = StaticTypeScale.Default.header1 + ) + + Text( + text = stringResource(id = R.string.cannot_change_name_after_register), + style = StaticTypeScale.Default.body6, + color = Color(0xFF7A7A7A), + ) + + WsTextField( + value = state.name, + onValueChange = { name -> + if (name.length > 5) { + error = true + return@WsTextField + } + error = false + action(AuthAction.OnNameChanged(name)) + }, + placeholder = stringResource(id = R.string.enter_name), + focusRequester = focusRequester, + ) + + if (error) { + Text( + text = stringResource(id = R.string.name_error), + color = WeSpotThemeManager.colors.dangerColor, + style = StaticTypeScale.Default.body6 + ) + } + + Box(modifier = Modifier.fillMaxWidth(), contentAlignment = Alignment.TopEnd) { + Text( + text = "${state.name.length} / 5", + color = Color(0xFF7A7A7A), + style = StaticTypeScale.Default.body7 + ) + } + } + } + + Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.BottomCenter) { + WSButton( + onClick = {}, + text = stringResource(id = R.string.next), + enabled = state.name.length in 2..5 + ) { + it.invoke() + } + } + + LaunchedEffect(key1 = focusRequester) { + focusRequester.requestFocus() + delay(10) + keyboard?.show() + } +} \ No newline at end of file diff --git a/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthAction.kt b/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthAction.kt index 24d14382..44836db5 100644 --- a/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthAction.kt +++ b/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthAction.kt @@ -9,4 +9,5 @@ sealed class AuthAction { data class OnGradeBottomSheetChanged(val isOpen: Boolean) : AuthAction() data class OnClassNumberChanged(val number: Int) : AuthAction() data class OnGenderChanged(val gender: String) : AuthAction() + data class OnNameChanged(val name: String) : AuthAction() } \ No newline at end of file diff --git a/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthUiState.kt b/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthUiState.kt index d6df6641..d6448e70 100644 --- a/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthUiState.kt +++ b/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthUiState.kt @@ -10,5 +10,6 @@ data class AuthUiState( val grade: Int = -1, val gradeBottomSheet: Boolean = true, val classNumber: Int = -1, - val gender: String = "" + val gender: String = "", + val name: String = "" ) diff --git a/feature/auth/src/main/kotlin/com/bff/wespot/auth/viewmodel/AuthViewModel.kt b/feature/auth/src/main/kotlin/com/bff/wespot/auth/viewmodel/AuthViewModel.kt index fa1cbd43..c7f3b5eb 100644 --- a/feature/auth/src/main/kotlin/com/bff/wespot/auth/viewmodel/AuthViewModel.kt +++ b/feature/auth/src/main/kotlin/com/bff/wespot/auth/viewmodel/AuthViewModel.kt @@ -21,6 +21,7 @@ class AuthViewModel : ViewModel(), ContainerHost { is AuthAction.OnGradeChanged -> handleGradeChanged(action.grade) is AuthAction.OnClassNumberChanged -> handleClassNumberChanged(action.number) is AuthAction.OnGenderChanged -> handleGenderChanged(action.gender) + is AuthAction.OnNameChanged -> handleNameChanged(action.name) else -> {} } } @@ -78,4 +79,12 @@ class AuthViewModel : ViewModel(), ContainerHost { ) } } + + private fun handleNameChanged(name: String) = intent { + reduce { + state.copy( + name = name + ) + } + } } \ No newline at end of file diff --git a/feature/auth/src/main/res/values/string.xml b/feature/auth/src/main/res/values/string.xml index ee6515ad..63b5b6d6 100644 --- a/feature/auth/src/main/res/values/string.xml +++ b/feature/auth/src/main/res/values/string.xml @@ -21,4 +21,8 @@ 성별 아이콘 남학생 여학생 + 이름 + 회원가입 이후에는 이름을 변경할 수 없어요 + 실명을 입력해 주세요 + 2~5자의 한글만 입력 가능해요 \ No newline at end of file From 67ad16c92210afaafcebfa8f13045f0d5db0f942 Mon Sep 17 00:00:00 2001 From: flash159483 Date: Tue, 9 Jul 2024 21:01:59 +0900 Subject: [PATCH 6/6] =?UTF-8?q?[FEAT]#21:=20Lint=20=ED=98=95=EC=8B=9D=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/com/bff/wespot/model/SchoolItem.kt | 2 +- .../com/bff/wespot/auth/screen/ClassScreen.kt | 47 ++++---- .../bff/wespot/auth/screen/GenderScreen.kt | 55 ++++----- .../com/bff/wespot/auth/screen/GradeScreen.kt | 94 +++++++++------- .../com/bff/wespot/auth/screen/NameScreen.kt | 25 ++--- .../bff/wespot/auth/screen/SchoolScreen.kt | 36 +++--- .../com/bff/wespot/auth/state/AuthAction.kt | 8 +- .../bff/wespot/auth/state/AuthSideEffect.kt | 4 +- .../com/bff/wespot/auth/state/AuthUiState.kt | 2 +- .../wespot/auth/viewmodel/AuthViewModel.kt | 106 ++++++++++-------- feature/auth/src/main/res/values/string.xml | 4 +- 11 files changed, 205 insertions(+), 178 deletions(-) diff --git a/core/model/src/main/kotlin/com/bff/wespot/model/SchoolItem.kt b/core/model/src/main/kotlin/com/bff/wespot/model/SchoolItem.kt index 6bc4d597..4c031fbd 100644 --- a/core/model/src/main/kotlin/com/bff/wespot/model/SchoolItem.kt +++ b/core/model/src/main/kotlin/com/bff/wespot/model/SchoolItem.kt @@ -4,4 +4,4 @@ data class SchoolItem( val id: String, val name: String, val address: String, -) \ No newline at end of file +) diff --git a/feature/auth/src/main/kotlin/com/bff/wespot/auth/screen/ClassScreen.kt b/feature/auth/src/main/kotlin/com/bff/wespot/auth/screen/ClassScreen.kt index 23973e3d..99d85b62 100644 --- a/feature/auth/src/main/kotlin/com/bff/wespot/auth/screen/ClassScreen.kt +++ b/feature/auth/src/main/kotlin/com/bff/wespot/auth/screen/ClassScreen.kt @@ -36,9 +36,7 @@ import org.orbitmvi.orbit.compose.collectAsState @OptIn(ExperimentalMaterial3Api::class) @Composable -fun ClassScreen( - viewModel: AuthViewModel = viewModel() -) { +fun ClassScreen(viewModel: AuthViewModel = viewModel()) { val keyboard = LocalSoftwareKeyboardController.current val state by viewModel.collectAsState() @@ -49,31 +47,33 @@ fun ClassScreen( topBar = { WSTopBar(title = stringResource(id = R.string.register), canNavigateBack = true) }, - modifier = Modifier.padding(horizontal = 20.dp) + modifier = Modifier.padding(horizontal = 20.dp), ) { Column( - modifier = Modifier - .fillMaxSize() - .padding(it), - verticalArrangement = Arrangement.spacedBy(12.dp) + modifier = + Modifier + .fillMaxSize() + .padding(it), + verticalArrangement = Arrangement.spacedBy(12.dp), ) { Text( text = stringResource(id = R.string.get_class), - style = StaticTypeScale.Default.header1 + style = StaticTypeScale.Default.header1, ) Text( text = stringResource(id = R.string.cannot_change_class_after_register), style = StaticTypeScale.Default.body6, - color = Color(0xFF7A7A7A) + color = Color(0xFF7A7A7A), ) WsTextField( - value = if (state.classNumber != -1) { - state.classNumber.toString() - } else { - "" - }, + value = + if (state.classNumber != -1) { + state.classNumber.toString() + } else { + "" + }, onValueChange = { classNumber -> if (classNumber.isEmpty()) { action(AuthAction.OnClassNumberChanged(-1)) @@ -83,29 +83,30 @@ fun ClassScreen( }, placeholder = stringResource(id = R.string.enter_number), focusRequester = focusRequester, - keyBoardOption = KeyboardOptions(keyboardType = KeyboardType.Number) + keyBoardOption = KeyboardOptions(keyboardType = KeyboardType.Number), ) if (state.classNumber != -1 && state.classNumber !in 1..20) { Text( text = stringResource(id = R.string.class_number_error), color = WeSpotThemeManager.colors.dangerColor, - style = StaticTypeScale.Default.body8 + style = StaticTypeScale.Default.body8, ) } } } Box( - modifier = Modifier - .fillMaxSize() - .imePadding(), - contentAlignment = Alignment.BottomCenter + modifier = + Modifier + .fillMaxSize() + .imePadding(), + contentAlignment = Alignment.BottomCenter, ) { WSButton( onClick = { }, text = stringResource(id = R.string.next), - enabled = state.classNumber in 1..20 + enabled = state.classNumber in 1..20, ) { it.invoke() } @@ -116,4 +117,4 @@ fun ClassScreen( delay(10) keyboard?.show() } -} \ No newline at end of file +} diff --git a/feature/auth/src/main/kotlin/com/bff/wespot/auth/screen/GenderScreen.kt b/feature/auth/src/main/kotlin/com/bff/wespot/auth/screen/GenderScreen.kt index b1c025a3..fcb03b6c 100644 --- a/feature/auth/src/main/kotlin/com/bff/wespot/auth/screen/GenderScreen.kt +++ b/feature/auth/src/main/kotlin/com/bff/wespot/auth/screen/GenderScreen.kt @@ -45,15 +45,15 @@ fun GenderScreen(viewModel: AuthViewModel = viewModel()) { topBar = { WSTopBar(title = stringResource(id = R.string.register), canNavigateBack = true) }, - modifier = Modifier.padding(horizontal = 20.dp) + modifier = Modifier.padding(horizontal = 20.dp), ) { Column( modifier = Modifier.padding(it), - verticalArrangement = Arrangement.spacedBy(12.dp) + verticalArrangement = Arrangement.spacedBy(12.dp), ) { Text( text = stringResource(id = R.string.gender), - style = StaticTypeScale.Default.header1 + style = StaticTypeScale.Default.header1, ) Text( text = stringResource(id = R.string.cannot_change_gender_after_register), @@ -62,27 +62,29 @@ fun GenderScreen(viewModel: AuthViewModel = viewModel()) { ) Row( - horizontalArrangement = Arrangement.spacedBy(10.dp) + horizontalArrangement = Arrangement.spacedBy(10.dp), ) { GenderBox( title = stringResource(id = R.string.male_student), - icon = painterResource( - id = com.bff.wespot.ui.R.drawable.male_student - ), + icon = + painterResource( + id = com.bff.wespot.ui.R.drawable.male_student, + ), selected = "male" == state.gender, onClicked = { action(AuthAction.OnGenderChanged("male")) - } + }, ) GenderBox( title = stringResource(id = R.string.female_student), - icon = painterResource( - id = com.bff.wespot.ui.R.drawable.female_student - ), + icon = + painterResource( + id = com.bff.wespot.ui.R.drawable.female_student, + ), selected = "female" == state.gender, onClicked = { action(AuthAction.OnGenderChanged("female")) - } + }, ) } } @@ -97,29 +99,30 @@ private fun RowScope.GenderBox( onClicked: () -> Unit, ) { Box( - modifier = Modifier - .weight(1f) - .clip(WeSpotThemeManager.shapes.medium) - .border( - width = 1.dp, - color = if (selected) WeSpotThemeManager.colors.primaryColor else Color.Transparent, - shape = WeSpotThemeManager.shapes.medium - ) - .clickable { onClicked() } - .background(WeSpotThemeManager.colors.cardBackgroundColor), - contentAlignment = Alignment.Center + modifier = + Modifier + .weight(1f) + .clip(WeSpotThemeManager.shapes.medium) + .border( + width = 1.dp, + color = if (selected) WeSpotThemeManager.colors.primaryColor else Color.Transparent, + shape = WeSpotThemeManager.shapes.medium, + ) + .clickable { onClicked() } + .background(WeSpotThemeManager.colors.cardBackgroundColor), + contentAlignment = Alignment.Center, ) { Column( modifier = Modifier.padding(start = 30.dp, end = 30.dp, top = 30.dp, bottom = 17.dp), - horizontalAlignment = Alignment.CenterHorizontally + horizontalAlignment = Alignment.CenterHorizontally, ) { Image( painter = icon, contentDescription = stringResource(id = R.string.gender_icon), - modifier = Modifier.size(90.dp) + modifier = Modifier.size(90.dp), ) Spacer(modifier = Modifier.height(16.dp)) Text(text = title, style = StaticTypeScale.Default.header2) } } -} \ No newline at end of file +} diff --git a/feature/auth/src/main/kotlin/com/bff/wespot/auth/screen/GradeScreen.kt b/feature/auth/src/main/kotlin/com/bff/wespot/auth/screen/GradeScreen.kt index c4c5c0de..bb2df36c 100644 --- a/feature/auth/src/main/kotlin/com/bff/wespot/auth/screen/GradeScreen.kt +++ b/feature/auth/src/main/kotlin/com/bff/wespot/auth/screen/GradeScreen.kt @@ -50,49 +50,55 @@ fun GradeScreen(viewModel: AuthViewModel = viewModel()) { ) { Column( modifier = Modifier.padding(it), - verticalArrangement = Arrangement.spacedBy(12.dp) + verticalArrangement = Arrangement.spacedBy(12.dp), ) { Text( text = stringResource(id = R.string.grade), style = StaticTypeScale.Default.header1, - modifier = Modifier.padding(horizontal = 20.dp) + modifier = Modifier.padding(horizontal = 20.dp), ) Text( text = stringResource(id = R.string.cannot_change_grade_after_register), style = StaticTypeScale.Default.body6, color = Color(0xFF7A7A7A), - modifier = Modifier.padding(horizontal = 20.dp) + modifier = Modifier.padding(horizontal = 20.dp), ) Box( - modifier = Modifier - .fillMaxWidth() - .clickable { - action(AuthAction.OnGradeBottomSheetChanged(true)) - } + modifier = + Modifier + .fillMaxWidth() + .clickable { + action(AuthAction.OnGradeBottomSheetChanged(true)) + }, ) { WSOutlineButton( text = "", onClick = { action(AuthAction.OnGradeBottomSheetChanged(true)) - } + }, ) { - Box(modifier = Modifier - .fillMaxWidth() - .padding(20.dp)) { + Box( + modifier = + Modifier + .fillMaxWidth() + .padding(20.dp), + ) { Text( - text = if (state.grade == -1) { - stringResource(id = R.string.select_grade) - } else { - "${state.grade}${stringResource(id = R.string.grade)}" - }, + text = + if (state.grade == -1) { + stringResource(id = R.string.select_grade) + } else { + "${state.grade}${stringResource(id = R.string.grade)}" + }, style = StaticTypeScale.Default.body4, - color = if (state.grade == -1) { - WeSpotThemeManager.colors.disableBtnColor - } else { - WeSpotThemeManager.colors.txtTitleColor - } + color = + if (state.grade == -1) { + WeSpotThemeManager.colors.disableBtnColor + } else { + WeSpotThemeManager.colors.txtTitleColor + }, ) } } @@ -101,9 +107,10 @@ fun GradeScreen(viewModel: AuthViewModel = viewModel()) { if (state.gradeBottomSheet) { WSBottomSheet( closeSheet = { action(AuthAction.OnGradeBottomSheetChanged(false)) }, - sheetState = rememberModalBottomSheetState( - skipPartiallyExpanded = true - ) + sheetState = + rememberModalBottomSheetState( + skipPartiallyExpanded = true, + ), ) { BottomSheetContent(currentGrade = state.grade, onGradeSelected = { grade -> action(AuthAction.OnGradeChanged(grade)) @@ -123,49 +130,51 @@ fun GradeScreen(viewModel: AuthViewModel = viewModel()) { @Composable private fun BottomSheetContent( currentGrade: Int, - onGradeSelected: (Int) -> Unit + onGradeSelected: (Int) -> Unit, ) { Column( - modifier = Modifier.padding(vertical = 28.dp, horizontal = 32.dp) + modifier = Modifier.padding(vertical = 28.dp, horizontal = 32.dp), ) { Text( text = stringResource(id = R.string.select_grade), - style = StaticTypeScale.Default.body1 + style = StaticTypeScale.Default.body1, ) Spacer(modifier = Modifier.padding(vertical = 4.dp)) Text( text = stringResource(id = R.string.more_than_14_to_register), style = StaticTypeScale.Default.body6, - color = Color(0xFF7A7A7A) + color = Color(0xFF7A7A7A), ) Spacer(modifier = Modifier.padding(vertical = 8.dp)) Column( - modifier = Modifier.fillMaxWidth() + modifier = Modifier.fillMaxWidth(), ) { repeat(3) { Row( horizontalArrangement = Arrangement.SpaceBetween, - modifier = Modifier - .clickable { onGradeSelected(it + 1) } - .padding(vertical = 12.dp) - .fillMaxWidth() + modifier = + Modifier + .clickable { onGradeSelected(it + 1) } + .padding(vertical = 12.dp) + .fillMaxWidth(), ) { Text( text = "${it + 1}${stringResource(id = R.string.grade)}", - style = StaticTypeScale.Default.body3 + style = StaticTypeScale.Default.body3, ) Icon( painter = painterResource(id = com.bff.wespot.ui.R.drawable.exclude), contentDescription = stringResource(id = R.string.check_icon), - tint = if (it == currentGrade - 1) { - WeSpotThemeManager.colors.primaryColor - } else { - WeSpotThemeManager.colors.disableBtnColor - } + tint = + if (it == currentGrade - 1) { + WeSpotThemeManager.colors.primaryColor + } else { + WeSpotThemeManager.colors.disableBtnColor + }, ) } } @@ -173,15 +182,14 @@ private fun BottomSheetContent( } } - @OrientationPreviews @Composable private fun GradeScreenPreview() { WeSpotTheme { Surface( - modifier = Modifier.fillMaxSize() + modifier = Modifier.fillMaxSize(), ) { GradeScreen() } } -} \ No newline at end of file +} diff --git a/feature/auth/src/main/kotlin/com/bff/wespot/auth/screen/NameScreen.kt b/feature/auth/src/main/kotlin/com/bff/wespot/auth/screen/NameScreen.kt index 516c054d..3fc614d4 100644 --- a/feature/auth/src/main/kotlin/com/bff/wespot/auth/screen/NameScreen.kt +++ b/feature/auth/src/main/kotlin/com/bff/wespot/auth/screen/NameScreen.kt @@ -36,17 +36,16 @@ import org.orbitmvi.orbit.compose.collectAsState @OptIn(ExperimentalMaterial3Api::class) @Composable -fun NameScreen( - viewModel: AuthViewModel = viewModel() -) { +fun NameScreen(viewModel: AuthViewModel = viewModel()) { val keyboard = LocalSoftwareKeyboardController.current val state by viewModel.collectAsState() val action = viewModel::onAction - val focusRequester = remember { - FocusRequester() - } + val focusRequester = + remember { + FocusRequester() + } var error by remember { mutableStateOf(false) @@ -56,15 +55,15 @@ fun NameScreen( topBar = { WSTopBar(title = stringResource(id = R.string.register), canNavigateBack = true) }, - modifier = Modifier.padding(horizontal = 20.dp) + modifier = Modifier.padding(horizontal = 20.dp), ) { Column( modifier = Modifier.padding(it), - verticalArrangement = Arrangement.spacedBy(12.dp) + verticalArrangement = Arrangement.spacedBy(12.dp), ) { Text( text = stringResource(id = R.string.name), - style = StaticTypeScale.Default.header1 + style = StaticTypeScale.Default.header1, ) Text( @@ -91,7 +90,7 @@ fun NameScreen( Text( text = stringResource(id = R.string.name_error), color = WeSpotThemeManager.colors.dangerColor, - style = StaticTypeScale.Default.body6 + style = StaticTypeScale.Default.body6, ) } @@ -99,7 +98,7 @@ fun NameScreen( Text( text = "${state.name.length} / 5", color = Color(0xFF7A7A7A), - style = StaticTypeScale.Default.body7 + style = StaticTypeScale.Default.body7, ) } } @@ -109,7 +108,7 @@ fun NameScreen( WSButton( onClick = {}, text = stringResource(id = R.string.next), - enabled = state.name.length in 2..5 + enabled = state.name.length in 2..5, ) { it.invoke() } @@ -120,4 +119,4 @@ fun NameScreen( delay(10) keyboard?.show() } -} \ No newline at end of file +} diff --git a/feature/auth/src/main/kotlin/com/bff/wespot/auth/screen/SchoolScreen.kt b/feature/auth/src/main/kotlin/com/bff/wespot/auth/screen/SchoolScreen.kt index 5d5ab91a..54afc217 100644 --- a/feature/auth/src/main/kotlin/com/bff/wespot/auth/screen/SchoolScreen.kt +++ b/feature/auth/src/main/kotlin/com/bff/wespot/auth/screen/SchoolScreen.kt @@ -54,23 +54,24 @@ fun SchoolScreen(viewModel: AuthViewModel = viewModel()) { Scaffold( topBar = { WSTopBar(title = stringResource(id = R.string.register)) - } + }, ) { Column( - modifier = Modifier - .fillMaxSize() - .padding(it) - .padding(horizontal = 24.dp) + modifier = + Modifier + .fillMaxSize() + .padding(it) + .padding(horizontal = 24.dp), ) { Text( stringResource(id = R.string.search_school), - style = StaticTypeScale.Default.header1 + style = StaticTypeScale.Default.header1, ) Spacer(modifier = Modifier.padding(8.dp)) Text( stringResource(id = R.string.search_base_on_your_school), style = StaticTypeScale.Default.body8, - color = Color(0xFF7A7A7A) + color = Color(0xFF7A7A7A), ) Spacer(modifier = Modifier.padding(12.dp)) @@ -82,7 +83,7 @@ fun SchoolScreen(viewModel: AuthViewModel = viewModel()) { placeholder = stringResource(id = R.string.search_with_school_name), textFieldType = WsTextFieldType.Search, focusRequester = focusRequester, - singleLine = true + singleLine = true, ) Spacer(modifier = Modifier.padding(vertical = 8.dp)) @@ -90,7 +91,7 @@ fun SchoolScreen(viewModel: AuthViewModel = viewModel()) { Text( stringResource(id = R.string.within_20_characters), style = StaticTypeScale.Default.body8, - color = WeSpotThemeManager.colors.dangerColor + color = WeSpotThemeManager.colors.dangerColor, ) } @@ -99,19 +100,19 @@ fun SchoolScreen(viewModel: AuthViewModel = viewModel()) { WSTextButton( text = stringResource(id = R.string.no_school_found), onClick = { }, - buttonType = WSTextButtonType.Underline + buttonType = WSTextButtonType.Underline, ) } } - LazyColumn() { + LazyColumn { items(state.schoolSearchList, key = { school -> school.id }) { school -> SchoolListItem( schoolName = school.name, address = school.address, - selected = state.selectedSchool?.name == school.name + selected = state.selectedSchool?.name == school.name, ) { action(AuthAction.OnSchoolSelected(school)) } @@ -121,10 +122,11 @@ fun SchoolScreen(viewModel: AuthViewModel = viewModel()) { } Box( - modifier = Modifier - .fillMaxSize() - .imePadding(), - contentAlignment = Alignment.BottomCenter + modifier = + Modifier + .fillMaxSize() + .imePadding(), + contentAlignment = Alignment.BottomCenter, ) { WSButton(onClick = { }, enabled = false, text = stringResource(id = R.string.next)) { it() @@ -146,4 +148,4 @@ private fun SchoolScreenPreview() { SchoolScreen() } } -} \ No newline at end of file +} diff --git a/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthAction.kt b/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthAction.kt index 44836db5..6528adca 100644 --- a/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthAction.kt +++ b/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthAction.kt @@ -4,10 +4,16 @@ import com.bff.wespot.model.SchoolItem sealed class AuthAction { data class OnSchoolSearchChanged(val text: String) : AuthAction() + data class OnSchoolSelected(val school: SchoolItem) : AuthAction() + data class OnGradeChanged(val grade: Int) : AuthAction() + data class OnGradeBottomSheetChanged(val isOpen: Boolean) : AuthAction() + data class OnClassNumberChanged(val number: Int) : AuthAction() + data class OnGenderChanged(val gender: String) : AuthAction() + data class OnNameChanged(val name: String) : AuthAction() -} \ No newline at end of file +} diff --git a/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthSideEffect.kt b/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthSideEffect.kt index 9264ac19..996b90d8 100644 --- a/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthSideEffect.kt +++ b/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthSideEffect.kt @@ -1,5 +1,3 @@ package com.bff.wespot.auth.state -sealed class AuthSideEffect { - -} \ No newline at end of file +sealed class AuthSideEffect diff --git a/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthUiState.kt b/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthUiState.kt index d6448e70..b7c652f8 100644 --- a/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthUiState.kt +++ b/feature/auth/src/main/kotlin/com/bff/wespot/auth/state/AuthUiState.kt @@ -11,5 +11,5 @@ data class AuthUiState( val gradeBottomSheet: Boolean = true, val classNumber: Int = -1, val gender: String = "", - val name: String = "" + val name: String = "", ) diff --git a/feature/auth/src/main/kotlin/com/bff/wespot/auth/viewmodel/AuthViewModel.kt b/feature/auth/src/main/kotlin/com/bff/wespot/auth/viewmodel/AuthViewModel.kt index c7f3b5eb..f106c77e 100644 --- a/feature/auth/src/main/kotlin/com/bff/wespot/auth/viewmodel/AuthViewModel.kt +++ b/feature/auth/src/main/kotlin/com/bff/wespot/auth/viewmodel/AuthViewModel.kt @@ -26,65 +26,73 @@ class AuthViewModel : ViewModel(), ContainerHost { } } - private fun handleSchoolSearchChanged(text: String) = intent { - reduce { - state.copy( - schoolName = text, - schoolSearchList = state.schoolList.filter { - it.name.contains( - text, - ignoreCase = true - ) - } - ) + private fun handleSchoolSearchChanged(text: String) = + intent { + reduce { + state.copy( + schoolName = text, + schoolSearchList = + state.schoolList.filter { + it.name.contains( + text, + ignoreCase = true, + ) + }, + ) + } } - } - private fun handleSchoolSelected(school: SchoolItem) = intent { - reduce { - state.copy( - selectedSchool = school - ) + private fun handleSchoolSelected(school: SchoolItem) = + intent { + reduce { + state.copy( + selectedSchool = school, + ) + } } - } - private fun handleGradeBottomSheetChanged(isOpen: Boolean) = intent { - reduce { - state.copy( - gradeBottomSheet = isOpen - ) + private fun handleGradeBottomSheetChanged(isOpen: Boolean) = + intent { + reduce { + state.copy( + gradeBottomSheet = isOpen, + ) + } } - } - private fun handleGradeChanged(grade: Int) = intent { - reduce { - state.copy( - grade = grade - ) + private fun handleGradeChanged(grade: Int) = + intent { + reduce { + state.copy( + grade = grade, + ) + } } - } - private fun handleClassNumberChanged(number: Int) = intent { - reduce { - state.copy( - classNumber = number - ) + private fun handleClassNumberChanged(number: Int) = + intent { + reduce { + state.copy( + classNumber = number, + ) + } } - } - private fun handleGenderChanged(gender: String) = intent { - reduce { - state.copy( - gender = gender - ) + private fun handleGenderChanged(gender: String) = + intent { + reduce { + state.copy( + gender = gender, + ) + } } - } - private fun handleNameChanged(name: String) = intent { - reduce { - state.copy( - name = name - ) + private fun handleNameChanged(name: String) = + intent { + reduce { + state.copy( + name = name, + ) + } } - } -} \ No newline at end of file +} diff --git a/feature/auth/src/main/res/values/string.xml b/feature/auth/src/main/res/values/string.xml index 63b5b6d6..aa3c32f0 100644 --- a/feature/auth/src/main/res/values/string.xml +++ b/feature/auth/src/main/res/values/string.xml @@ -6,6 +6,7 @@ 20자 이내로 검색해 주세요 학교 이름으로 검색해 보세요 찾는 학교가 없다면? + 학교 다음 학년 회원가입 이후에는 학년을 변경할 수 없어요 @@ -16,7 +17,7 @@ 회원가입 이후에는 반을 변경할 수 없어요 숫자로 입력해 주세요 정확한 반을 입력해주세요 - 성병 + 성별 회원가입 이후에는 성별을 변경할 수 없어요 성별 아이콘 남학생 @@ -25,4 +26,5 @@ 회원가입 이후에는 이름을 변경할 수 없어요 실명을 입력해 주세요 2~5자의 한글만 입력 가능해요 + 확인 \ No newline at end of file