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

[Fix] 회원가입 학번 입력 로직 수정 #280

Merged
merged 8 commits into from
Jun 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import javax.inject.Inject
class DeptRepositoryImpl @Inject constructor(
private val deptRemoteDataSource: DeptRemoteDataSource,
private val deptLocalDataSource: DeptLocalDataSource
) : DeptRepository{
) : DeptRepository {
override suspend fun getDeptNameFromDeptCode(deptCode: String): String {
return try {
val deptResponse = deptRemoteDataSource.getDeptFromDeptCode(deptCode)
Expand All @@ -28,4 +28,14 @@ class DeptRepositoryImpl @Inject constructor(
)
}
}

override suspend fun getDeptNames(): List<String> {
return try {
deptRemoteDataSource.getAllDepts().map {
it.name
}
} catch (t: Throwable) {
deptLocalDataSource.getDeptNames()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,17 @@ class DeptLocalDataSource @Inject constructor(
else -> throw IllegalArgumentException()
}
)

fun getDeptNames() = with(context) {
listOf(
getString(R.string.major_architectural_engineering),
getString(R.string.major_employment_service_policy),
getString(R.string.major_mechanical_engineering),
getString(R.string.major_architectural_engineering),
getString(R.string.major_architectural_engineering),
getString(R.string.major_architectural_engineering),
getString(R.string.major_architectural_engineering),
getString(R.string.major_architectural_engineering),
)
}
}
18 changes: 16 additions & 2 deletions data/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
<string name="error_internal_server_error">서버 오류가 발생했습니다.</string>
<string name="error_network_connection">네트워크 연결을 확인해 주세요.</string>
<string name="error_network_unknown">알 수 없는 오류가 발생했습니다.</string>
<string name="error_login_incorrect">아이디 또는 비밀번호가 올바르지 않습니다.</string>
<string name="error_network">서버 오류가 발생했습니다.</string>

<!-- Forgot password error-->
<string name="error_forgotpassword_no_user">가입되지 않은 아이디입니다.</string>
Expand Down Expand Up @@ -43,6 +45,7 @@
<string name="bus_name_shuttle">셔틀버스</string>
<string name="bus_name_school_shuttle">학교셔틀</string>
<string name="city_bus_number_format">%1$d번 버스</string>

<!-- dept -->
<string name="dept_mechanical_engineering">기계공학부</string>
<string name="dept_mechatronics_engineering">메카트로닉스공학부</string>
Expand All @@ -56,8 +59,19 @@
<string name="dept_hrd">HRD</string>
<string name="dept_department_of_future_technology">융합</string>
<string name="dept_liberal_arts">교양학부</string>
<string name="error_login_incorrect">아이디 또는 비밀번호가 올바르지 않습니다.</string>
<string name="error_network">서버 오류가 발생했습니다.</string>

<!--major-->
<string name="major_architectural_engineering">건축공학부</string>
<string name="major_employment_service_policy">고용서비스정책학과</string>
<string name="major_mechanical_engineering">기계공학부</string>
<string name="major_industrial_design">디자인공학부</string>
<string name="major_mechatronics_engineering">메카트로닉스공학부</string>
<string name="major_industrial_management">산업경영학부</string>
<string name="major_electrical_electronics_and_communication_engineering">전기전자통신공학부</string>
<string name="major_computer_science_and_engineering">컴퓨터공학부</string>
<string name="major_chemical_engineering">화학생명공학부</string>
<string name="major_energy_meterials_chemical_engineering">에너지신소재화학공학부</string>

<!-- dining -->
<string name="dining_breakfast">아침</string>
<string name="dining_lunch">점심</string>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package `in`.koreatech.koin.domain.model.user

data class Dept(
private val name: String,
private val curriculumUrl: String,
private val codes: List<String>
val name: String,
val curriculumUrl: String,
val codes: List<String>
)
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ import `in`.koreatech.koin.domain.model.user.Dept
interface DeptRepository {
suspend fun getDeptNameFromDeptCode(deptCode: String): String
suspend fun getDepts(): List<Dept>
suspend fun getDeptNames(): List<String>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package `in`.koreatech.koin.domain.usecase.dept

import `in`.koreatech.koin.domain.repository.DeptRepository
import javax.inject.Inject

class GetDeptNamesUseCase @Inject constructor(
private val deptRepository: DeptRepository,
) {
suspend operator fun invoke(): List<String> {
return deptRepository.getDeptNames()
}
}
4 changes: 4 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ hiltComposeVersion="1.0.0"
markermanVersion="2.3.0"
coilVersion = "2.6.0"
napier = "2.6.1"
powerSpinner = "1.2.7"
nodobi marked this conversation as resolved.
Show resolved Hide resolved
firebaseCrashlyticsBuildtoolsVersion = "2.9.9"

[libraries]
Expand Down Expand Up @@ -142,6 +143,9 @@ coil ={module = "io.coil-kt:coil", version.ref ="coilVersion"}
coil-compose = {module = "io.coil-kt:coil-compose", version.ref = "coilVersion"}
coil-svg = {module = "io.coil-kt:coil-svg", version.ref ="coilVersion"}

powerSpinner = {module = "com.github.skydoves:powerspinner", version.ref = "powerSpinner"}


[plugins]
android-application = { id = "com.android.application", version.ref = "androidGradleVersion" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlinVersion" }
Expand Down
1 change: 1 addition & 0 deletions koin/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -130,4 +130,5 @@ dependencies {
implementation(libs.coil)

implementation(libs.napier)
implementation(libs.powerSpinner)
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import androidx.core.widget.addTextChangedListener
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.flowWithLifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import dagger.hilt.android.AndroidEntryPoint
import `in`.koreatech.koin.R
import `in`.koreatech.koin.core.activity.ActivityBase
Expand All @@ -23,7 +24,6 @@ import `in`.koreatech.koin.ui.signup.SignupActivity.Companion.SIGN_UP_PASSWORD
import `in`.koreatech.koin.ui.signup.viewmodel.SignupViewModel
import `in`.koreatech.koin.util.SnackbarUtil
import `in`.koreatech.koin.util.ext.hideKeyboard
import `in`.koreatech.koin.util.ext.observeLiveData
import `in`.koreatech.koin.util.ext.textString
import `in`.koreatech.koin.util.ext.withLoading
import kotlinx.coroutines.launch
Expand All @@ -50,26 +50,29 @@ class SignupWithDetailInfoActivity : ActivityBase() {
getUserDataFromSignupActivity()
checkNickname()
continueSignup()
addTextChangedListenerWithNicknameAndDept()
autoInputMajor()
}
initSpinner()
// addTextChangedListenerWithNicknameAndDept()
nodobi marked this conversation as resolved.
Show resolved Hide resolved
// autoInputMajor()


private fun autoInputMajor() {
binding.signupUserEdittextMajor.apply {
isEnabled = false
hint = context.getString(R.string.user_info_id_hint)
}
}

// private fun autoInputMajor() {
// binding.signupUserEdittextMajor.apply {
// isEnabled = false
// hint = context.getString(R.string.user_info_id_hint)
// }
// }

private fun addTextChangedListenerWithNicknameAndDept() {
binding.signupUserEdittextNickName.addTextChangedListener {
if (signupViewModel.isCheckedNickname) signupViewModel.isCheckedNickname = false
}

binding.signupUserEdittextStudentId.addTextChangedListener {
if (signupViewModel.isPerformDept) signupViewModel.isPerformDept = false
signupViewModel.getDept(it.toString())
}
// binding.signupUserEdittextStudentId.addTextChangedListener {
// if (signupViewModel.isPerformDept) signupViewModel.isPerformDept = false
// signupViewModel.getDept(it.toString())
// }
}

private fun continueSignup() {
Expand All @@ -87,7 +90,7 @@ class SignupWithDetailInfoActivity : ActivityBase() {
signupUserRadiobuttonStudent.isChecked -> Graduated.Student
else -> null
},
major = signupUserEdittextMajor.text.toString(),
major = spinnerSignupUserMajor.text.toString(),
name = signupUserEdittextName.text.toString().trim(),
nickName = signupUserEdittextNickName.text.toString().trim(),
password = signupViewModel.password.trim(),
Expand All @@ -104,6 +107,11 @@ class SignupWithDetailInfoActivity : ActivityBase() {
}
}

private fun initSpinner() = with(binding.spinnerSignupUserMajor) {
lifecycleOwner = this@SignupWithDetailInfoActivity
}


private fun checkNickname() {
binding.signupUserButtonNicknameCheck.setOnClickListener {
if (binding.signupUserEdittextNickName.text.toString() != "") {
Expand All @@ -130,19 +138,19 @@ class SignupWithDetailInfoActivity : ActivityBase() {
when (state) {
SignupContinuationState.InitName -> SnackbarUtil.makeShortSnackbar(binding.root, getString(R.string.signup_init_name))

SignupContinuationState.InitPhoneNumber -> SnackbarUtil.makeShortSnackbar(binding.root,getString(R.string.signup_init_phone_number))
SignupContinuationState.InitPhoneNumber -> SnackbarUtil.makeShortSnackbar(binding.root, getString(R.string.signup_init_phone_number))

SignupContinuationState.InitStudentId -> SnackbarUtil.makeShortSnackbar(binding.root, getString(R.string.signup_init_student_id))

SignupContinuationState.CheckNickName -> SnackbarUtil.makeShortSnackbar(binding.root,getString(R.string.signup_check_nickname))
SignupContinuationState.CheckNickName -> SnackbarUtil.makeShortSnackbar(binding.root, getString(R.string.signup_check_nickname))

SignupContinuationState.CheckGender -> SnackbarUtil.makeShortSnackbar(binding.root,getString(R.string.signup_check_gender))
SignupContinuationState.CheckGender -> SnackbarUtil.makeShortSnackbar(binding.root, getString(R.string.signup_check_gender))

SignupContinuationState.CheckGraduate -> SnackbarUtil.makeShortSnackbar(binding.root, getString(R.string.signup_check_graduate))

SignupContinuationState.CheckDept -> SnackbarUtil.makeShortSnackbar(binding.root, getString(R.string.user_info_no_major))

SignupContinuationState.NicknameDuplicated -> SnackbarUtil.makeShortSnackbar(binding.root,getString(R.string.error_nickname_duplicated))
SignupContinuationState.NicknameDuplicated -> SnackbarUtil.makeShortSnackbar(binding.root, getString(R.string.error_nickname_duplicated))

SignupContinuationState.AvailableNickname -> SnackbarUtil.makeShortSnackbar(binding.root, getString(R.string.signup_nickname_available))

Expand All @@ -164,13 +172,12 @@ class SignupWithDetailInfoActivity : ActivityBase() {
}
}

observeLiveData(dept) {
binding.signupUserEdittextMajor.setText(it)
binding.signupUserEdittextMajorError.text = ""
}

observeLiveData(getDeptErrorMessage) {
binding.signupUserEdittextMajorError.text = it
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
signupViewModel.depts.collect { deptNames ->
binding.spinnerSignupUserMajor.setItems(deptNames)
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
package `in`.koreatech.koin.ui.signup.viewmodel

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import `in`.koreatech.koin.core.viewmodel.BaseViewModel
import `in`.koreatech.koin.core.viewmodel.SingleLiveEvent
import `in`.koreatech.koin.domain.model.user.Gender
import `in`.koreatech.koin.domain.model.user.Graduated
import `in`.koreatech.koin.domain.state.signup.SignupContinuationState
import `in`.koreatech.koin.domain.usecase.dept.GetDeptNameFromStudentIdUseCase
import `in`.koreatech.koin.domain.usecase.dept.GetDeptNamesUseCase
import `in`.koreatech.koin.domain.usecase.signup.CheckEmailValidationUseCase
import `in`.koreatech.koin.domain.usecase.signup.SignupCheckingUseCase
import `in`.koreatech.koin.domain.usecase.signup.SignupRequestEmailVerificationUseCase
import `in`.koreatech.koin.domain.usecase.user.CheckNicknameValidationUseCase
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import javax.inject.Inject

Expand All @@ -26,21 +27,25 @@ class SignupViewModel @Inject constructor(
private val signupRequestEmailVerificationUseCase: SignupRequestEmailVerificationUseCase,
private val checkNicknameValidationUseCase: CheckNicknameValidationUseCase,
private val checkEmailValidationUseCase: CheckEmailValidationUseCase,
private val deptNameFromStudentIdUseCase: GetDeptNameFromStudentIdUseCase,
private val getDeptNamesUseCase: GetDeptNamesUseCase,
) : BaseViewModel() {
var portalEmail: String = ""
var password: String = ""
var isCheckedNickname: Boolean = false
var isPerformDept: Boolean = false
// var isPerformDept: Boolean = false

private val _signupContinuationState = MutableSharedFlow<SignupContinuationState>()
val signupContinuationState: SharedFlow<SignupContinuationState> = _signupContinuationState.asSharedFlow()

private val _dept = MutableLiveData<String>()
val dept: LiveData<String> get() = _dept
// 학부 선택을 Spinner 로 구현하도록 변경되며 주석처리
// private val _dept = MutableLiveData<String>()
// val dept: LiveData<String> get() = _dept

private val _getDeptErrorMessage = MutableLiveData<String>()
val getDeptErrorMessage: LiveData<String> get() = _getDeptErrorMessage
val depts: StateFlow<List<String>> = flow { emit(getDeptNamesUseCase()) }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

backing property 에 대해서 알아봐도 좋을 것 같아요!
https://stackoverflow.com/questions/53050257/viewmodel-backing-properties-kotlin

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

해당 부분을 Flow가 아닌 StateFlow로 했어야 하는 이유가 혹시 무엇인가요?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Flow 로 하게 되는 경우 화면을 다시 불러오게 되는 경우 depts 가 다시 collect 되면서 getDeptNamesUseCase() 가 다시 호출되는거로 알고 있어요.
학과명은 유저가 테스크를 진행하는 동안 바뀔 일이 적은 것이라 생각해서 불필요한 API 호출을 줄이려고 했습니다!

.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), listOf())

// private val _getDeptErrorMessage = MutableLiveData<String>()
// val getDeptErrorMessage: LiveData<String> get() = _getDeptErrorMessage

fun setAccount(portalEmail: String, password: String) {
this.portalEmail = portalEmail
Expand All @@ -54,9 +59,9 @@ class SignupViewModel @Inject constructor(
isAgreedPrivacyTerms: Boolean,
isAgreedKoinTerms: Boolean,
) {

viewModelScope.launch {
signupCheckingUseCase(portalAccount, password, passwordConfirm, isAgreedPrivacyTerms, isAgreedKoinTerms
signupCheckingUseCase(
portalAccount, password, passwordConfirm, isAgreedPrivacyTerms, isAgreedKoinTerms
).let {
_signupContinuationState.emit(it)
}
Expand All @@ -78,16 +83,7 @@ class SignupViewModel @Inject constructor(
if (isLoading.value == false) {
viewModelScope.launch {
signupRequestEmailVerificationUseCase(
portalAccount,
gender,
isGraduated,
major,
name,
nickName,
password,
phoneNumber,
studentNumber,
isCheckNickname
portalAccount, gender, isGraduated, major, name, nickName, password, phoneNumber, studentNumber, isCheckNickname
).onSuccess {
_signupContinuationState.emit(it)
}.onFailure {
Expand Down Expand Up @@ -128,7 +124,9 @@ class SignupViewModel @Inject constructor(
}
}

fun getDept(studentId: String) = viewModelScope.launchIgnoreCancellation {
/* 학부 선택을 Spinner 로 구현하도록 변경되며 주석처리
* TODO:: Spinner 자동 입력되도록 변경
fun getDept(studentId: String) = viewModelScope.launchIgnoreCancellation {
deptNameFromStudentIdUseCase(studentId).let { (deptName, error) ->
deptName?.let {
_dept.value = it
Expand All @@ -137,4 +135,5 @@ class SignupViewModel @Inject constructor(
error?.let { _getDeptErrorMessage.value = error.message }
}
}
*/
}
12 changes: 12 additions & 0 deletions koin/src/main/res/drawable/background_round_square.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<!-- TODO::색상 변경 -->
<stroke
android:width="1dp"
android:color="@color/neutral_500" />
<corners android:radius="3dp" />
</shape>
</item>
</layer-list>
Loading