From 7c1f6123ce36d9821950b90385d943fa8de3c30b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Thu, 5 Sep 2024 20:07:06 +0900 Subject: [PATCH 001/141] :sparkles: :: Create asResult() Function(Use ViewModel - UiState) --- .../src/main/java/com/msg/common/result/Result.kt | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 core/common/src/main/java/com/msg/common/result/Result.kt diff --git a/core/common/src/main/java/com/msg/common/result/Result.kt b/core/common/src/main/java/com/msg/common/result/Result.kt new file mode 100644 index 00000000..346973bf --- /dev/null +++ b/core/common/src/main/java/com/msg/common/result/Result.kt @@ -0,0 +1,13 @@ +package com.msg.common.result + +import kotlinx.coroutines.flow.* + +sealed interface Result { + data class Success(val data: T): Result + data class Error(val exception: Throwable): Result + data object Loading: Result +} + +fun Flow.asResult(): Flow> = map> { Result.Success(it) } + .onStart { emit(Result.Loading) } + .catch { emit(Result.Error(it)) } \ No newline at end of file From 532eac01026fb52b8042c1b556eea12ed414e37b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Thu, 5 Sep 2024 20:09:10 +0900 Subject: [PATCH 002/141] :fire: :: Fire Unused Import --- .../main/java/com/msg/certification/AddCertificationScreen.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/feature/certification/src/main/java/com/msg/certification/AddCertificationScreen.kt b/feature/certification/src/main/java/com/msg/certification/AddCertificationScreen.kt index 12d83507..e6244ce1 100644 --- a/feature/certification/src/main/java/com/msg/certification/AddCertificationScreen.kt +++ b/feature/certification/src/main/java/com/msg/certification/AddCertificationScreen.kt @@ -9,7 +9,6 @@ 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.padding import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf From 37c632a1b4d6bb09b4e2320600f59f00b931cb60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Fri, 6 Sep 2024 10:16:38 +0900 Subject: [PATCH 003/141] :fire: :: Unused Code(File) --- .../GetCertificationListForStudentUseCase.kt | 12 ------------ .../GetCertificationListForTeacherUseCase.kt | 13 ------------- 2 files changed, 25 deletions(-) delete mode 100644 core/domain/src/main/java/com/msg/domain/usecase/certification/GetCertificationListForStudentUseCase.kt delete mode 100644 core/domain/src/main/java/com/msg/domain/usecase/certification/GetCertificationListForTeacherUseCase.kt diff --git a/core/domain/src/main/java/com/msg/domain/usecase/certification/GetCertificationListForStudentUseCase.kt b/core/domain/src/main/java/com/msg/domain/usecase/certification/GetCertificationListForStudentUseCase.kt deleted file mode 100644 index 38b520b8..00000000 --- a/core/domain/src/main/java/com/msg/domain/usecase/certification/GetCertificationListForStudentUseCase.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.msg.domain.usecase.certification - -import com.msg.data.repository.certification.CertificationRepository -import javax.inject.Inject - -class GetCertificationListForStudentUseCase @Inject constructor( - private val certificationRepository: CertificationRepository, -) { - suspend operator fun invoke() = runCatching { - certificationRepository.getCertificationListForStudent() - } -} \ No newline at end of file diff --git a/core/domain/src/main/java/com/msg/domain/usecase/certification/GetCertificationListForTeacherUseCase.kt b/core/domain/src/main/java/com/msg/domain/usecase/certification/GetCertificationListForTeacherUseCase.kt deleted file mode 100644 index 8f028a72..00000000 --- a/core/domain/src/main/java/com/msg/domain/usecase/certification/GetCertificationListForTeacherUseCase.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.msg.domain.usecase.certification - -import com.msg.data.repository.certification.CertificationRepository -import java.util.UUID -import javax.inject.Inject - -class GetCertificationListForTeacherUseCase @Inject constructor( - private val certificationRepository: CertificationRepository, -) { - suspend operator fun invoke(studentId: UUID) = runCatching { - certificationRepository.getCertificationListForTeacher(studentId = studentId) - } -} \ No newline at end of file From bd6767817d25a286232a1b17f6e8e72f951d10e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Fri, 6 Sep 2024 10:18:09 +0900 Subject: [PATCH 004/141] :recycle: :: Combine The Use Cases Into One --- .../GetCertificationListUseCase.kt | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 core/domain/src/main/java/com/msg/domain/usecase/certification/GetCertificationListUseCase.kt diff --git a/core/domain/src/main/java/com/msg/domain/usecase/certification/GetCertificationListUseCase.kt b/core/domain/src/main/java/com/msg/domain/usecase/certification/GetCertificationListUseCase.kt new file mode 100644 index 00000000..695267aa --- /dev/null +++ b/core/domain/src/main/java/com/msg/domain/usecase/certification/GetCertificationListUseCase.kt @@ -0,0 +1,18 @@ +package com.msg.domain.usecase.certification + +import com.msg.data.repository.certification.CertificationRepository +import com.msg.model.entity.certification.CertificationListEntity +import kotlinx.coroutines.flow.Flow +import java.util.UUID +import javax.inject.Inject + +class GetCertificationListUseCase @Inject constructor( + private val certificationRepository: CertificationRepository, +) { + operator fun invoke(role: String, studentId: UUID): Flow> { + return when (role) { + "ROLE_STUDENT" -> certificationRepository.getCertificationListForStudent() + else -> certificationRepository.getCertificationListForTeacher(studentId = studentId) + } + } +} \ No newline at end of file From 2d55ff6fd13128523af84ca85731911d446c5244 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Fri, 6 Sep 2024 10:18:41 +0900 Subject: [PATCH 005/141] :sparkles: :: Create GetCertificationListUiState --- .../viewmodel/uistate/GetCertificationListUiState.kt | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetCertificationListUiState.kt diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetCertificationListUiState.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetCertificationListUiState.kt new file mode 100644 index 00000000..63d22f6c --- /dev/null +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetCertificationListUiState.kt @@ -0,0 +1,10 @@ +package com.msg.certification.viewmodel.uistate + +import com.msg.model.entity.certification.CertificationListEntity + +sealed interface GetCertificationListUiState { + data class Success(val data: List): GetCertificationListUiState + data object Error: GetCertificationListUiState + data object Loading: GetCertificationListUiState + data object Empty: GetCertificationListUiState +} \ No newline at end of file From f77bb0fe3714eea5b49f0758da116d92d64a4428 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Fri, 6 Sep 2024 10:19:12 +0900 Subject: [PATCH 006/141] :recycle: :: Simplify ViewModel Code And Apply UiState --- .../viewmodel/CertificationViewModel.kt | 45 +++++++++---------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt index 268815d9..7fbed016 100644 --- a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt @@ -5,11 +5,14 @@ import androidx.compose.runtime.mutableStateOf import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.msg.certification.viewmodel.uistate.GetCertificationListUiState import com.msg.common.event.Event import com.msg.common.errorhandling.errorHandling +import com.msg.common.result.Result +import com.msg.common.result.asResult import com.msg.domain.usecase.auth.GetAuthorityUseCase import com.msg.domain.usecase.certification.* -import com.msg.domain.usecase.certification.GetCertificationListForTeacherUseCase +import com.msg.domain.usecase.certification.GetCertificationListUseCase import com.msg.domain.usecase.certification.WriteCertificationUseCase import com.msg.domain.usecase.club.GetStudentBelongClubUseCase import com.msg.domain.usecase.lecture.GetLectureSignUpHistoryUseCase @@ -18,16 +21,17 @@ import com.msg.model.entity.club.StudentBelongClubEntity import com.msg.model.entity.lecture.GetLectureSignUpHistoryEntity import com.msg.model.param.certification.WriteCertificationParam import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.catch +import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch import java.time.LocalDate import java.util.UUID import javax.inject.Inject class CertificationViewModel @Inject constructor( - private val getCertificationListForTeacherUseCase: GetCertificationListForTeacherUseCase, - private val getCertificationListForStudentUseCase: GetCertificationListForStudentUseCase, + private val getCertificationListUseCase: GetCertificationListUseCase, private val writeCertificationUseCase: WriteCertificationUseCase, private val editCertificationUseCase: EditCertificationUseCase, private val getStudentBelongClubUseCase: GetStudentBelongClubUseCase, @@ -41,6 +45,9 @@ class CertificationViewModel @Inject constructor( private val role = getRole().toString() + private val _getCertificationListUiState = MutableStateFlow(GetCertificationListUiState.Loading) + val getCertificationListUiState: StateFlow = _getCertificationListUiState.asStateFlow() + private val _getCertificationListResponse = MutableStateFlow>>( Event.Loading) val getCertificationListResponse = _getCertificationListResponse.asStateFlow() @@ -91,29 +98,21 @@ class CertificationViewModel @Inject constructor( private set internal fun getCertificationList() = viewModelScope.launch { - if (role == "ROLE_STUDENT") { - getCertificationListForStudentUseCase().onSuccess { - it.catch { remoteError -> - _getCertificationListResponse.value = remoteError.errorHandling() - }.collect { response -> - _getCertificationListResponse.value = Event.Success(data = response) - } - }.onFailure { error -> - _getCertificationListResponse.value = error.errorHandling() - } - } else { - if (studentId != null) { - getCertificationListForTeacherUseCase(studentId).onSuccess { - it.catch { remoteError -> - _getCertificationListResponse.value = remoteError.errorHandling() - }.collect { response -> - _getCertificationListResponse.value = Event.Success(data = response) + getCertificationListUseCase(role = role, studentId = studentId) + .asResult() + .collectLatest { result -> + when(result) { + is Result.Loading -> { _getCertificationListUiState.value = GetCertificationListUiState.Loading } + is Result.Success -> { + if (result.data.isEmpty()) { + _getCertificationListUiState.value = GetCertificationListUiState.Empty + } else { + _getCertificationListUiState.value = GetCertificationListUiState.Success(result.data) + } } - }.onFailure { error -> - _getCertificationListResponse.value = error.errorHandling() + is Result.Error -> { _getCertificationListUiState.value = GetCertificationListUiState.Error } } } - } } internal fun writeCertification( From 946d74e44f2cee74f3848e1565104ecf6cabb812 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Fri, 6 Sep 2024 10:19:39 +0900 Subject: [PATCH 007/141] :recycle: :: Apply ViewModel Changed(Apply UiState) --- .../msg/certification/CertificationScreen.kt | 60 ++++++++++++++++--- 1 file changed, 51 insertions(+), 9 deletions(-) diff --git a/feature/certification/src/main/java/com/msg/certification/CertificationScreen.kt b/feature/certification/src/main/java/com/msg/certification/CertificationScreen.kt index a6d2f7da..cd8ef4f8 100644 --- a/feature/certification/src/main/java/com/msg/certification/CertificationScreen.kt +++ b/feature/certification/src/main/java/com/msg/certification/CertificationScreen.kt @@ -11,22 +11,26 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.IconButton import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.msg.certification.component.CertificationSection import com.msg.certification.component.FinishedLectureSection import com.msg.certification.component.StudentInfoSection import com.msg.common.event.Event import com.msg.certification.viewmodel.CertificationViewModel +import com.msg.certification.viewmodel.uistate.GetCertificationListUiState import com.msg.design_system.R import com.msg.design_system.component.icon.HumanIcon import com.msg.design_system.theme.BitgoeulAndroidTheme @@ -44,6 +48,8 @@ internal fun CertificationScreenRoute( onHumanIconClicked: () -> Unit, onEditClicked: () -> Unit ) { + val getCertificationListUiState by viewModel.getCertificationListUiState.collectAsStateWithLifecycle() + viewModel.getCertificationList() viewModel.getStudentBelong() viewModel.getLectureSignUpHistory() @@ -83,7 +89,8 @@ internal fun CertificationScreenRoute( onPlusClicked = onEditClicked, studentData = viewModel.studentData.value, certificationData = viewModel.certificationList, - lectureData = viewModel.lectureData.value + lectureData = viewModel.lectureData.value, + getCertificationListUiState = getCertificationListUiState ) } @@ -135,6 +142,7 @@ private suspend fun getLectureData( @Composable internal fun CertificationScreen( modifier: Modifier = Modifier, + getCertificationListUiState: GetCertificationListUiState, onHumanIconClicked: () -> Unit, onEditClicked: (id: UUID, title: String, date: LocalDate) -> Unit, onPlusClicked: () -> Unit, @@ -179,13 +187,46 @@ internal fun CertificationScreen( color = colors.G9 ) Spacer(modifier = modifier.height(24.dp)) - CertificationSection( - onPlusClicked = onPlusClicked, - onEditClicked = { id, title, date -> - onEditClicked(id, title, date) - }, - data = certificationData - ) + when(getCertificationListUiState) { + is GetCertificationListUiState.Success -> { + CertificationSection( + onPlusClicked = onPlusClicked, + onEditClicked = { id, title, date -> + onEditClicked(id, title, date) + }, + data = certificationData + ) + } + + is GetCertificationListUiState.Loading -> { + Box( + modifier = modifier.fillMaxWidth(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator( + modifier = modifier.then(Modifier.size(27.dp)), + color = colors.G2, + strokeWidth = 2.dp + ) + } + } + + is GetCertificationListUiState.Error -> { + Text( + modifier = modifier.align(Alignment.CenterHorizontally), + text = "통신이 원활하지 않습니다..", + style = typography.titleSmall + ) + } + + is GetCertificationListUiState.Empty -> { + Text( + modifier = modifier.align(Alignment.CenterHorizontally), + text = "자격증이 없습니다..", + style = typography.titleSmall + ) + } + } Spacer(modifier = modifier.height(12.dp)) FinishedLectureSection(data = lectureData) } @@ -232,6 +273,7 @@ fun CertificationScreenPre() { isComplete = true ) ) - ) + ), + getCertificationListUiState = GetCertificationListUiState.Loading ) } \ No newline at end of file From 19c1a630f83453ca0723c5699a3c81e5ec4358fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Fri, 6 Sep 2024 10:19:12 +0900 Subject: [PATCH 008/141] :recycle: :: Simplify ViewModel Code And Apply UiState - getCertificationList Function --- .../viewmodel/CertificationViewModel.kt | 45 +++++++++---------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt index 268815d9..7fbed016 100644 --- a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt @@ -5,11 +5,14 @@ import androidx.compose.runtime.mutableStateOf import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.msg.certification.viewmodel.uistate.GetCertificationListUiState import com.msg.common.event.Event import com.msg.common.errorhandling.errorHandling +import com.msg.common.result.Result +import com.msg.common.result.asResult import com.msg.domain.usecase.auth.GetAuthorityUseCase import com.msg.domain.usecase.certification.* -import com.msg.domain.usecase.certification.GetCertificationListForTeacherUseCase +import com.msg.domain.usecase.certification.GetCertificationListUseCase import com.msg.domain.usecase.certification.WriteCertificationUseCase import com.msg.domain.usecase.club.GetStudentBelongClubUseCase import com.msg.domain.usecase.lecture.GetLectureSignUpHistoryUseCase @@ -18,16 +21,17 @@ import com.msg.model.entity.club.StudentBelongClubEntity import com.msg.model.entity.lecture.GetLectureSignUpHistoryEntity import com.msg.model.param.certification.WriteCertificationParam import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.catch +import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch import java.time.LocalDate import java.util.UUID import javax.inject.Inject class CertificationViewModel @Inject constructor( - private val getCertificationListForTeacherUseCase: GetCertificationListForTeacherUseCase, - private val getCertificationListForStudentUseCase: GetCertificationListForStudentUseCase, + private val getCertificationListUseCase: GetCertificationListUseCase, private val writeCertificationUseCase: WriteCertificationUseCase, private val editCertificationUseCase: EditCertificationUseCase, private val getStudentBelongClubUseCase: GetStudentBelongClubUseCase, @@ -41,6 +45,9 @@ class CertificationViewModel @Inject constructor( private val role = getRole().toString() + private val _getCertificationListUiState = MutableStateFlow(GetCertificationListUiState.Loading) + val getCertificationListUiState: StateFlow = _getCertificationListUiState.asStateFlow() + private val _getCertificationListResponse = MutableStateFlow>>( Event.Loading) val getCertificationListResponse = _getCertificationListResponse.asStateFlow() @@ -91,29 +98,21 @@ class CertificationViewModel @Inject constructor( private set internal fun getCertificationList() = viewModelScope.launch { - if (role == "ROLE_STUDENT") { - getCertificationListForStudentUseCase().onSuccess { - it.catch { remoteError -> - _getCertificationListResponse.value = remoteError.errorHandling() - }.collect { response -> - _getCertificationListResponse.value = Event.Success(data = response) - } - }.onFailure { error -> - _getCertificationListResponse.value = error.errorHandling() - } - } else { - if (studentId != null) { - getCertificationListForTeacherUseCase(studentId).onSuccess { - it.catch { remoteError -> - _getCertificationListResponse.value = remoteError.errorHandling() - }.collect { response -> - _getCertificationListResponse.value = Event.Success(data = response) + getCertificationListUseCase(role = role, studentId = studentId) + .asResult() + .collectLatest { result -> + when(result) { + is Result.Loading -> { _getCertificationListUiState.value = GetCertificationListUiState.Loading } + is Result.Success -> { + if (result.data.isEmpty()) { + _getCertificationListUiState.value = GetCertificationListUiState.Empty + } else { + _getCertificationListUiState.value = GetCertificationListUiState.Success(result.data) + } } - }.onFailure { error -> - _getCertificationListResponse.value = error.errorHandling() + is Result.Error -> { _getCertificationListUiState.value = GetCertificationListUiState.Error } } } - } } internal fun writeCertification( From 559e7a27d6d609513d1981db962c2c27404f4cf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Fri, 6 Sep 2024 10:19:39 +0900 Subject: [PATCH 009/141] :recycle: :: Apply ViewModel Changed(Apply UiState) --- .../msg/certification/CertificationScreen.kt | 60 ++++++++++++++++--- 1 file changed, 51 insertions(+), 9 deletions(-) diff --git a/feature/certification/src/main/java/com/msg/certification/CertificationScreen.kt b/feature/certification/src/main/java/com/msg/certification/CertificationScreen.kt index a6d2f7da..cd8ef4f8 100644 --- a/feature/certification/src/main/java/com/msg/certification/CertificationScreen.kt +++ b/feature/certification/src/main/java/com/msg/certification/CertificationScreen.kt @@ -11,22 +11,26 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.IconButton import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.msg.certification.component.CertificationSection import com.msg.certification.component.FinishedLectureSection import com.msg.certification.component.StudentInfoSection import com.msg.common.event.Event import com.msg.certification.viewmodel.CertificationViewModel +import com.msg.certification.viewmodel.uistate.GetCertificationListUiState import com.msg.design_system.R import com.msg.design_system.component.icon.HumanIcon import com.msg.design_system.theme.BitgoeulAndroidTheme @@ -44,6 +48,8 @@ internal fun CertificationScreenRoute( onHumanIconClicked: () -> Unit, onEditClicked: () -> Unit ) { + val getCertificationListUiState by viewModel.getCertificationListUiState.collectAsStateWithLifecycle() + viewModel.getCertificationList() viewModel.getStudentBelong() viewModel.getLectureSignUpHistory() @@ -83,7 +89,8 @@ internal fun CertificationScreenRoute( onPlusClicked = onEditClicked, studentData = viewModel.studentData.value, certificationData = viewModel.certificationList, - lectureData = viewModel.lectureData.value + lectureData = viewModel.lectureData.value, + getCertificationListUiState = getCertificationListUiState ) } @@ -135,6 +142,7 @@ private suspend fun getLectureData( @Composable internal fun CertificationScreen( modifier: Modifier = Modifier, + getCertificationListUiState: GetCertificationListUiState, onHumanIconClicked: () -> Unit, onEditClicked: (id: UUID, title: String, date: LocalDate) -> Unit, onPlusClicked: () -> Unit, @@ -179,13 +187,46 @@ internal fun CertificationScreen( color = colors.G9 ) Spacer(modifier = modifier.height(24.dp)) - CertificationSection( - onPlusClicked = onPlusClicked, - onEditClicked = { id, title, date -> - onEditClicked(id, title, date) - }, - data = certificationData - ) + when(getCertificationListUiState) { + is GetCertificationListUiState.Success -> { + CertificationSection( + onPlusClicked = onPlusClicked, + onEditClicked = { id, title, date -> + onEditClicked(id, title, date) + }, + data = certificationData + ) + } + + is GetCertificationListUiState.Loading -> { + Box( + modifier = modifier.fillMaxWidth(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator( + modifier = modifier.then(Modifier.size(27.dp)), + color = colors.G2, + strokeWidth = 2.dp + ) + } + } + + is GetCertificationListUiState.Error -> { + Text( + modifier = modifier.align(Alignment.CenterHorizontally), + text = "통신이 원활하지 않습니다..", + style = typography.titleSmall + ) + } + + is GetCertificationListUiState.Empty -> { + Text( + modifier = modifier.align(Alignment.CenterHorizontally), + text = "자격증이 없습니다..", + style = typography.titleSmall + ) + } + } Spacer(modifier = modifier.height(12.dp)) FinishedLectureSection(data = lectureData) } @@ -232,6 +273,7 @@ fun CertificationScreenPre() { isComplete = true ) ) - ) + ), + getCertificationListUiState = GetCertificationListUiState.Loading ) } \ No newline at end of file From 95d670e64ccd3d0d6b4956cd2d1b5aca93fbb6f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Fri, 6 Sep 2024 10:22:09 +0900 Subject: [PATCH 010/141] :fire: :: Line Spacing --- .../msg/certification/viewmodel/CertificationViewModel.kt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt index 7fbed016..df5c6c45 100644 --- a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt @@ -48,8 +48,7 @@ class CertificationViewModel @Inject constructor( private val _getCertificationListUiState = MutableStateFlow(GetCertificationListUiState.Loading) val getCertificationListUiState: StateFlow = _getCertificationListUiState.asStateFlow() - private val _getCertificationListResponse = MutableStateFlow>>( - Event.Loading) + private val _getCertificationListResponse = MutableStateFlow>>(Event.Loading) val getCertificationListResponse = _getCertificationListResponse.asStateFlow() private val _writeCertificationResponse = MutableStateFlow>(Event.Loading) @@ -61,8 +60,7 @@ class CertificationViewModel @Inject constructor( private val _getStudentBelongResponse = MutableStateFlow>(Event.Loading) val getStudentBelongResponse = _getStudentBelongResponse.asStateFlow() - private val _getLectureSignUpHistoryResponse = MutableStateFlow>( - Event.Loading) + private val _getLectureSignUpHistoryResponse = MutableStateFlow>(Event.Loading) val getLectureSignUpHistoryResponse = _getLectureSignUpHistoryResponse.asStateFlow() private val studentId = UUID.fromString(savedStateHandle.get("studentId")) From 65517f25e02f9a6f7c63e9736310ff2a7add8610 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 11:41:35 +0900 Subject: [PATCH 011/141] :memo: :: Modify Use Flow And Fire Unused Code --- .../domain/usecase/lecture/GetLectureSignUpHistoryUseCase.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/domain/src/main/java/com/msg/domain/usecase/lecture/GetLectureSignUpHistoryUseCase.kt b/core/domain/src/main/java/com/msg/domain/usecase/lecture/GetLectureSignUpHistoryUseCase.kt index 93454000..5db48700 100644 --- a/core/domain/src/main/java/com/msg/domain/usecase/lecture/GetLectureSignUpHistoryUseCase.kt +++ b/core/domain/src/main/java/com/msg/domain/usecase/lecture/GetLectureSignUpHistoryUseCase.kt @@ -1,13 +1,14 @@ package com.msg.domain.usecase.lecture import com.msg.data.repository.lecture.LectureRepository +import com.msg.model.entity.lecture.GetLectureSignUpHistoryEntity +import kotlinx.coroutines.flow.Flow import java.util.UUID import javax.inject.Inject class GetLectureSignUpHistoryUseCase @Inject constructor( private val lectureRepository: LectureRepository ) { - suspend operator fun invoke(studentId: UUID) = runCatching { + operator fun invoke(studentId: UUID): Flow = lectureRepository.getLectureSignUpHistory(studentId = studentId) - } } \ No newline at end of file From 7ceb43b3cd42c1781fed03c70231d000f3be1a34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 11:42:02 +0900 Subject: [PATCH 012/141] :sparkles: :: Create GetLectureSignUpHistoryUiState --- .../viewmodel/uistate/GetLectureSignUpHistoryUiState.kt | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetLectureSignUpHistoryUiState.kt diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetLectureSignUpHistoryUiState.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetLectureSignUpHistoryUiState.kt new file mode 100644 index 00000000..e82ac2c5 --- /dev/null +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetLectureSignUpHistoryUiState.kt @@ -0,0 +1,9 @@ +package com.msg.certification.viewmodel.uistate + +import com.msg.model.entity.lecture.GetLectureSignUpHistoryEntity + +sealed interface GetLectureSignUpHistoryUiState { + data class Success(val data: GetLectureSignUpHistoryEntity): GetLectureSignUpHistoryUiState + data object Loading: GetLectureSignUpHistoryUiState + data object Error: GetLectureSignUpHistoryUiState +} \ No newline at end of file From 5686d41a92ec497ba7caab9069ca45533d0b67bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 15:58:10 +0900 Subject: [PATCH 013/141] :recycle: :: Changed TextStyle And Color && Apply UiState To Screen --- .../msg/certification/CertificationScreen.kt | 38 ++++++++++++++++--- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/feature/certification/src/main/java/com/msg/certification/CertificationScreen.kt b/feature/certification/src/main/java/com/msg/certification/CertificationScreen.kt index cd8ef4f8..90134785 100644 --- a/feature/certification/src/main/java/com/msg/certification/CertificationScreen.kt +++ b/feature/certification/src/main/java/com/msg/certification/CertificationScreen.kt @@ -31,6 +31,7 @@ import com.msg.certification.component.StudentInfoSection import com.msg.common.event.Event import com.msg.certification.viewmodel.CertificationViewModel import com.msg.certification.viewmodel.uistate.GetCertificationListUiState +import com.msg.certification.viewmodel.uistate.GetLectureSignUpHistoryUiState import com.msg.design_system.R import com.msg.design_system.component.icon.HumanIcon import com.msg.design_system.theme.BitgoeulAndroidTheme @@ -49,6 +50,7 @@ internal fun CertificationScreenRoute( onEditClicked: () -> Unit ) { val getCertificationListUiState by viewModel.getCertificationListUiState.collectAsStateWithLifecycle() + val getLectureSignUpHistoryUiState by viewModel.getLectureSignUpHistoryUiState.collectAsStateWithLifecycle() viewModel.getCertificationList() viewModel.getStudentBelong() @@ -90,7 +92,8 @@ internal fun CertificationScreenRoute( studentData = viewModel.studentData.value, certificationData = viewModel.certificationList, lectureData = viewModel.lectureData.value, - getCertificationListUiState = getCertificationListUiState + getCertificationListUiState = getCertificationListUiState, + getLectureSignUpHistoryUiState = getLectureSignUpHistoryUiState ) } @@ -143,6 +146,7 @@ private suspend fun getLectureData( internal fun CertificationScreen( modifier: Modifier = Modifier, getCertificationListUiState: GetCertificationListUiState, + getLectureSignUpHistoryUiState: GetLectureSignUpHistoryUiState, onHumanIconClicked: () -> Unit, onEditClicked: (id: UUID, title: String, date: LocalDate) -> Unit, onPlusClicked: () -> Unit, @@ -215,7 +219,7 @@ internal fun CertificationScreen( Text( modifier = modifier.align(Alignment.CenterHorizontally), text = "통신이 원활하지 않습니다..", - style = typography.titleSmall + style = typography.bodySmall ) } @@ -223,12 +227,35 @@ internal fun CertificationScreen( Text( modifier = modifier.align(Alignment.CenterHorizontally), text = "자격증이 없습니다..", - style = typography.titleSmall + style = typography.bodySmall, + color = colors.G4 ) } } Spacer(modifier = modifier.height(12.dp)) - FinishedLectureSection(data = lectureData) + when(getLectureSignUpHistoryUiState) { + is GetLectureSignUpHistoryUiState.Success -> { FinishedLectureSection(data = lectureData) } + is GetLectureSignUpHistoryUiState.Loading -> { + Box( + modifier = modifier.fillMaxWidth(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator( + modifier = modifier.then(Modifier.size(27.dp)), + color = colors.G2, + strokeWidth = 2.dp + ) + } + } + is GetLectureSignUpHistoryUiState.Error -> { + Text( + modifier = modifier.align(Alignment.CenterHorizontally).padding(top = 50.dp), + text = "통신이 원할하지 않습니다..", + style = typography.bodySmall, + color = colors.G4 + ) + } + } } } } @@ -274,6 +301,7 @@ fun CertificationScreenPre() { ) ) ), - getCertificationListUiState = GetCertificationListUiState.Loading + getCertificationListUiState = GetCertificationListUiState.Empty, + getLectureSignUpHistoryUiState = GetLectureSignUpHistoryUiState.Error ) } \ No newline at end of file From d380added03eb4535ccbd45b233e404a8cfc8286 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 15:58:52 +0900 Subject: [PATCH 014/141] :recycle: :: Apply UiState To CertificationViewModel(getLectureSignUpHistory) --- .../viewmodel/CertificationViewModel.kt | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt index df5c6c45..ffbce139 100644 --- a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt @@ -6,6 +6,7 @@ import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.msg.certification.viewmodel.uistate.GetCertificationListUiState +import com.msg.certification.viewmodel.uistate.GetLectureSignUpHistoryUiState import com.msg.common.event.Event import com.msg.common.errorhandling.errorHandling import com.msg.common.result.Result @@ -48,6 +49,9 @@ class CertificationViewModel @Inject constructor( private val _getCertificationListUiState = MutableStateFlow(GetCertificationListUiState.Loading) val getCertificationListUiState: StateFlow = _getCertificationListUiState.asStateFlow() + private val _getLectureSignUpHistoryUiState = MutableStateFlow(GetLectureSignUpHistoryUiState.Loading) + val getLectureSignUpHistoryUiState: StateFlow = _getLectureSignUpHistoryUiState.asStateFlow() + private val _getCertificationListResponse = MutableStateFlow>>(Event.Loading) val getCertificationListResponse = _getCertificationListResponse.asStateFlow() @@ -173,17 +177,15 @@ class CertificationViewModel @Inject constructor( internal fun getLectureSignUpHistory() = viewModelScope.launch { if (studentId != null) { - getLectureSignUpHistoryUseCase( - studentId = studentId - ).onSuccess { - it.catch { remoteError -> - _getLectureSignUpHistoryResponse.value = remoteError.errorHandling() - }.collect { response -> - _getLectureSignUpHistoryResponse.value = Event.Success(data = response) + getLectureSignUpHistoryUseCase(studentId = studentId) + .asResult() + .collectLatest { result -> + when(result) { + is Result.Loading -> { _getLectureSignUpHistoryUiState.value = GetLectureSignUpHistoryUiState.Loading } + is Result.Success -> { _getLectureSignUpHistoryUiState.value = GetLectureSignUpHistoryUiState.Success(result.data) } + is Result.Error -> { _getLectureSignUpHistoryUiState.value = GetLectureSignUpHistoryUiState.Error } + } } - }.onFailure { error -> - _getLectureSignUpHistoryResponse.value = error.errorHandling() - } } } From a31bd098a4ba179bb3b8b168c4c90a563edde89c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 16:19:04 +0900 Subject: [PATCH 015/141] :recycle: :: Use Flow To WriteCertificationUseCase --- .../domain/usecase/certification/WriteCertificationUseCase.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/domain/src/main/java/com/msg/domain/usecase/certification/WriteCertificationUseCase.kt b/core/domain/src/main/java/com/msg/domain/usecase/certification/WriteCertificationUseCase.kt index ddd3e643..93db9a6b 100644 --- a/core/domain/src/main/java/com/msg/domain/usecase/certification/WriteCertificationUseCase.kt +++ b/core/domain/src/main/java/com/msg/domain/usecase/certification/WriteCertificationUseCase.kt @@ -2,12 +2,12 @@ package com.msg.domain.usecase.certification import com.msg.data.repository.certification.CertificationRepository import com.msg.model.param.certification.WriteCertificationParam +import kotlinx.coroutines.flow.Flow import javax.inject.Inject class WriteCertificationUseCase @Inject constructor( private val certificationRepository: CertificationRepository ) { - suspend operator fun invoke(body: WriteCertificationParam) = runCatching { + operator fun invoke(body: WriteCertificationParam): Flow = certificationRepository.writeCertification(body = body) - } } \ No newline at end of file From a2d13ac0aea73d4c6d8c2916822522ef32d2473c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 16:19:26 +0900 Subject: [PATCH 016/141] :sparkles: :: Create WriteCertificationUiState --- .../viewmodel/uistate/WriteCertificationUiState.kt | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/WriteCertificationUiState.kt diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/WriteCertificationUiState.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/WriteCertificationUiState.kt new file mode 100644 index 00000000..ff0a3391 --- /dev/null +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/WriteCertificationUiState.kt @@ -0,0 +1,7 @@ +package com.msg.certification.viewmodel.uistate + +sealed interface WriteCertificationUiState { + data object Success: WriteCertificationUiState + data object Loading: WriteCertificationUiState + data class Error(val exception: Throwable): WriteCertificationUiState +} \ No newline at end of file From 0768955575397462146091d4a89a1239b5bc659b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 16:19:56 +0900 Subject: [PATCH 017/141] :recycle: :: Apply WriteCertificationUiState To CertificationViewModel --- .../viewmodel/CertificationViewModel.kt | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt index ffbce139..5a7bf44d 100644 --- a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt @@ -7,6 +7,7 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.msg.certification.viewmodel.uistate.GetCertificationListUiState import com.msg.certification.viewmodel.uistate.GetLectureSignUpHistoryUiState +import com.msg.certification.viewmodel.uistate.WriteCertificationUiState import com.msg.common.event.Event import com.msg.common.errorhandling.errorHandling import com.msg.common.result.Result @@ -52,6 +53,9 @@ class CertificationViewModel @Inject constructor( private val _getLectureSignUpHistoryUiState = MutableStateFlow(GetLectureSignUpHistoryUiState.Loading) val getLectureSignUpHistoryUiState: StateFlow = _getLectureSignUpHistoryUiState.asStateFlow() + private val _writeCertificationUiState = MutableStateFlow(WriteCertificationUiState.Loading) + val writeCertificationUiState: StateFlow = _writeCertificationUiState.asStateFlow() + private val _getCertificationListResponse = MutableStateFlow>>(Event.Loading) val getCertificationListResponse = _getCertificationListResponse.asStateFlow() @@ -126,15 +130,15 @@ class CertificationViewModel @Inject constructor( name = name, acquisitionDate = acquisitionDate ) - ).onSuccess { - it.catch { remoteError -> - _writeCertificationResponse.value = remoteError.errorHandling() - }.collect { - _writeCertificationResponse.value = Event.Success() + ) + .asResult() + .collectLatest { result -> + when(result) { + is Result.Loading -> { _writeCertificationUiState.value = WriteCertificationUiState.Loading } + is Result.Success -> { _writeCertificationUiState.value = WriteCertificationUiState.Success } + is Result.Error -> { _writeCertificationUiState.value = WriteCertificationUiState.Error(result.exception) } + } } - }.onFailure { error -> - _writeCertificationResponse.value = error.errorHandling() - } } internal fun editCertification( From 47f2da4567a5f43ec10268b1b7017495b778f7f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 22:51:20 +0900 Subject: [PATCH 018/141] :memo: :: Add strings.xml To Other Strings --- .../src/main/res/values/strings.xml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/core/design-system/src/main/res/values/strings.xml b/core/design-system/src/main/res/values/strings.xml index b6ec9ab5..6663340c 100644 --- a/core/design-system/src/main/res/values/strings.xml +++ b/core/design-system/src/main/res/values/strings.xml @@ -83,4 +83,20 @@ 강의 구분 검색... 전체 학생정보 + \'뒤로\'버튼 한번 더 누르시면 종료됩니다. + 학생회 권한인 학생만 요청 가능해요 + 서버 응답이 지연되고 있습니다, 잠시 후 다시 시도해주세요 + 서버 에러, 관리자에게 문의하세요 + 네트워크가 불안정합니다, 데이터나 와이파이 연결 상태를 확인해주세요 + 알 수 없는 오류가 발생했습니다 + 예상치 못한 오류가 발생했습니다 + 오류가 발생했습니다 + 자격증 등록을 완료되었습니다. + 자격증 등록을 실패하였습니다. + 자격증 수정을 완료하였습니다. + 자격증 수정을 실패하였습니다. + 학생정보를 불러오지 못했습니다. + 자격증 정보를 불러오지 못했습니다. + 데이터가 없습니다. + 강의 정보를 불러오지 못했습니다. \ No newline at end of file From ff10373931eb2f262ca016714fb00ecf626dd0f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 22:53:06 +0900 Subject: [PATCH 019/141] :heavy_plus_sign: :: Add Implementation To build.gradle.kts(:app) --- app/build.gradle.kts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 92a0641a..b41372ea 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -15,6 +15,8 @@ android { } dependencies { + implementation(project(":core:ui")) + implementation(project(":core:common")) implementation(project(":core:design-system")) implementation(project(":feature:login")) implementation(project(":feature:sign-up")) From b76176902bb1bec7f545fce0e7bfab5da9e773a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 22:54:00 +0900 Subject: [PATCH 020/141] :sparkles: :: Create errorToast(BitgoeulNavHost) --- .../navigation/BitgoeulNavHost.kt | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/msg/bitgoeul_android/navigation/BitgoeulNavHost.kt b/app/src/main/java/com/msg/bitgoeul_android/navigation/BitgoeulNavHost.kt index 13353029..f4dee234 100644 --- a/app/src/main/java/com/msg/bitgoeul_android/navigation/BitgoeulNavHost.kt +++ b/app/src/main/java/com/msg/bitgoeul_android/navigation/BitgoeulNavHost.kt @@ -2,6 +2,7 @@ package com.msg.bitgoeul_android.navigation import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext import androidx.navigation.compose.NavHost import com.bitgoeul.email.navigation.emailSendInformScreen import com.bitgoeul.email.navigation.inputEmailScreen @@ -18,6 +19,7 @@ import com.example.my_page.navigation.changePasswordScreen import com.example.my_page.navigation.myPageScreen import com.example.my_page.navigation.navigateToMyPage import com.example.my_page.navigation.navigateToPasswordChange +import com.msg.design_system.R import com.msg.bitgoeul_android.ui.BitgoeulAppState import com.msg.bitgoeul_android.ui.navigateWithPopUpToLogin import com.msg.certification.navigation.addCertificationScreen @@ -26,6 +28,12 @@ import com.msg.certification.navigation.navigateToAddCertificationPage import com.msg.club.navigation.clubDetailScreen import com.msg.club.navigation.clubScreen import com.msg.club.navigation.navigateToClubDetailPage +import com.msg.common.exception.ForBiddenException +import com.msg.common.exception.NetworkException +import com.msg.common.exception.OtherException +import com.msg.common.exception.ServerException +import com.msg.common.exception.TimeOutException +import com.msg.common.exception.UnknownException import com.msg.lecture.navigation.lectureDetailScreen import com.msg.lecture.navigation.lectureListScreen import com.msg.lecture.navigation.lectureTakingStudentListScreen @@ -46,6 +54,7 @@ import com.msg.student_activity.navigation.studentActivityScreen import com.msg.student_activity.navigation.studentAddActivityScreen import com.msg.student_activity.navigation.studentDetailActivityScreen import com.msg.student_activity.navigation.studentDetailSettingActivityScreen +import com.msg.ui.makeToast @Composable fun BitgoeulNavHost( @@ -53,7 +62,24 @@ fun BitgoeulNavHost( modifier: Modifier = Modifier, startDestination: String = loginRoute, ) { + val context = LocalContext.current val navController = appState.navController + + val createErrorToast: (throwable: Throwable?, message: Int?) -> Unit = { throwable, message -> + val errorMessage = throwable?.let { + when(it) { + is ForBiddenException -> R.string.error_for_bidden + is TimeOutException -> R.string.error_time_out + is ServerException -> R.string.error_server + is NetworkException -> R.string.error_no_internet + is OtherException -> R.string.error_other_http + is UnknownException -> R.string.error_un_known + else -> message + } + } ?: message ?: R.string.error_default + makeToast(context, context.getString(errorMessage)) + } + NavHost( navController = navController, startDestination = startDestination, @@ -139,7 +165,8 @@ fun BitgoeulNavHost( ) certificationScreen( onHumanClicked = navController::navigateToMyPage, - onEditClicked = navController::navigateToAddCertificationPage + onEditClicked = navController::navigateToAddCertificationPage, + createErrorToast = createErrorToast ) addCertificationScreen( onBackClicked = navController::navigateUp From 4a1fdd8b60cc013f23d77626e4f30c1985877386 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 22:55:23 +0900 Subject: [PATCH 021/141] :recycle: :: Use Flow - EditCertificationUseCase --- .../domain/usecase/certification/EditCertificationUseCase.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/domain/src/main/java/com/msg/domain/usecase/certification/EditCertificationUseCase.kt b/core/domain/src/main/java/com/msg/domain/usecase/certification/EditCertificationUseCase.kt index 41cc0676..f2a54eb7 100644 --- a/core/domain/src/main/java/com/msg/domain/usecase/certification/EditCertificationUseCase.kt +++ b/core/domain/src/main/java/com/msg/domain/usecase/certification/EditCertificationUseCase.kt @@ -2,13 +2,13 @@ package com.msg.domain.usecase.certification import com.msg.data.repository.certification.CertificationRepository import com.msg.model.param.certification.WriteCertificationParam +import kotlinx.coroutines.flow.Flow import java.util.UUID import javax.inject.Inject class EditCertificationUseCase @Inject constructor( private val certificationRepository: CertificationRepository ) { - suspend operator fun invoke(id: UUID, body: WriteCertificationParam) = runCatching { + operator fun invoke(id: UUID, body: WriteCertificationParam): Flow = certificationRepository.editCertification(id = id, body = body) - } } \ No newline at end of file From 3939251faad2dbd576498794d0e646d39f68682c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 22:55:23 +0900 Subject: [PATCH 022/141] :recycle: :: Use Coroutine Flow - EditCertificationUseCase --- .../domain/usecase/certification/EditCertificationUseCase.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/domain/src/main/java/com/msg/domain/usecase/certification/EditCertificationUseCase.kt b/core/domain/src/main/java/com/msg/domain/usecase/certification/EditCertificationUseCase.kt index 41cc0676..f2a54eb7 100644 --- a/core/domain/src/main/java/com/msg/domain/usecase/certification/EditCertificationUseCase.kt +++ b/core/domain/src/main/java/com/msg/domain/usecase/certification/EditCertificationUseCase.kt @@ -2,13 +2,13 @@ package com.msg.domain.usecase.certification import com.msg.data.repository.certification.CertificationRepository import com.msg.model.param.certification.WriteCertificationParam +import kotlinx.coroutines.flow.Flow import java.util.UUID import javax.inject.Inject class EditCertificationUseCase @Inject constructor( private val certificationRepository: CertificationRepository ) { - suspend operator fun invoke(id: UUID, body: WriteCertificationParam) = runCatching { + operator fun invoke(id: UUID, body: WriteCertificationParam): Flow = certificationRepository.editCertification(id = id, body = body) - } } \ No newline at end of file From 0b11882eaa48e5e1a3203e2027f79beddf1f56ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 22:55:55 +0900 Subject: [PATCH 023/141] :recycle: :: Use Coroutine Flow(GetStudentBelongClubUseCase) --- .../msg/domain/usecase/club/GetStudentBelongClubUseCase.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/domain/src/main/java/com/msg/domain/usecase/club/GetStudentBelongClubUseCase.kt b/core/domain/src/main/java/com/msg/domain/usecase/club/GetStudentBelongClubUseCase.kt index e7bbdc6a..5d8fd5ab 100644 --- a/core/domain/src/main/java/com/msg/domain/usecase/club/GetStudentBelongClubUseCase.kt +++ b/core/domain/src/main/java/com/msg/domain/usecase/club/GetStudentBelongClubUseCase.kt @@ -1,13 +1,14 @@ package com.msg.domain.usecase.club import com.msg.data.repository.club.ClubRepository +import com.msg.model.entity.club.StudentBelongClubEntity +import kotlinx.coroutines.flow.Flow import java.util.UUID import javax.inject.Inject class GetStudentBelongClubUseCase @Inject constructor( private val clubRepository: ClubRepository ) { - suspend operator fun invoke(id: Long, studentId: UUID) = runCatching { + operator fun invoke(id: Long, studentId: UUID): Flow = clubRepository.getStudentBelongClubDetail(id = id, studentId = studentId) - } } \ No newline at end of file From 78b3c200c0ae42b3267cb0171a08d931707e56cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 22:56:44 +0900 Subject: [PATCH 024/141] :fire: :: Fire Unused Import --- feature/login/src/main/java/com/bitgoeul/login/LoginScreen.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/feature/login/src/main/java/com/bitgoeul/login/LoginScreen.kt b/feature/login/src/main/java/com/bitgoeul/login/LoginScreen.kt index 61a59169..06cad962 100644 --- a/feature/login/src/main/java/com/bitgoeul/login/LoginScreen.kt +++ b/feature/login/src/main/java/com/bitgoeul/login/LoginScreen.kt @@ -16,7 +16,6 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Alignment From d21c9efb94d383c15c9d170364f217ddbc459431 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 22:57:18 +0900 Subject: [PATCH 025/141] :sparkles: :: Create GetStudentBelongClubDetailUiState --- .../uistate/GetStudentBelongClubDetailUiState.kt | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetStudentBelongClubDetailUiState.kt diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetStudentBelongClubDetailUiState.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetStudentBelongClubDetailUiState.kt new file mode 100644 index 00000000..3bbf4801 --- /dev/null +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetStudentBelongClubDetailUiState.kt @@ -0,0 +1,10 @@ +package com.msg.certification.viewmodel.uistate + +import android.content.Context +import com.msg.model.entity.club.StudentBelongClubEntity + +sealed interface GetStudentBelongClubDetailUiState { + data class Success(val data: StudentBelongClubEntity): GetStudentBelongClubDetailUiState + data object Loading: GetStudentBelongClubDetailUiState + data class Error(val expectation: Throwable): GetStudentBelongClubDetailUiState +} \ No newline at end of file From c382f801e75f229961ec35b53787be8be8c63532 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 22:57:35 +0900 Subject: [PATCH 026/141] :sparkles: :: Create EditCertificationUiState --- .../viewmodel/uistate/EditCertificationUiState.kt | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/EditCertificationUiState.kt diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/EditCertificationUiState.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/EditCertificationUiState.kt new file mode 100644 index 00000000..cc88f112 --- /dev/null +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/EditCertificationUiState.kt @@ -0,0 +1,6 @@ +package com.msg.certification.viewmodel.uistate + +sealed interface EditCertificationUiState { + data object Success: EditCertificationUiState + data class Error(val exception: Throwable): EditCertificationUiState +} \ No newline at end of file From 775271bfdb41e45da945c198f724907601466998 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 22:58:35 +0900 Subject: [PATCH 027/141] :recycle: :: Apply createErrorToast To Certification Navigation --- .../navigation/CertificationNavigation.kt | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/feature/certification/src/main/java/com/msg/certification/navigation/CertificationNavigation.kt b/feature/certification/src/main/java/com/msg/certification/navigation/CertificationNavigation.kt index d34ac30f..404e44a3 100644 --- a/feature/certification/src/main/java/com/msg/certification/navigation/CertificationNavigation.kt +++ b/feature/certification/src/main/java/com/msg/certification/navigation/CertificationNavigation.kt @@ -16,7 +16,11 @@ fun NavController.navigateToCertificationPage(navOptions: NavOptions? = null, cl this.navigate("$certificationRoute/$clubId/$studentId", navOptions) } -fun NavGraphBuilder.certificationScreen(onHumanClicked: () -> Unit, onEditClicked: () -> Unit) { +fun NavGraphBuilder.certificationScreen( + onHumanClicked: () -> Unit, + onEditClicked: () -> Unit, + createErrorToast: (throwable: Throwable?, message: Int?) -> Unit +) { composable( route = "certificationRoute/{clubId}/{studentId}", arguments = listOf( @@ -30,7 +34,8 @@ fun NavGraphBuilder.certificationScreen(onHumanClicked: () -> Unit, onEditClicke ) { CertificationScreenRoute( onHumanIconClicked = onHumanClicked, - onEditClicked = onEditClicked + onEditClicked = onEditClicked, + createErrorToast = createErrorToast ) } } @@ -39,11 +44,15 @@ fun NavController.navigateToAddCertificationPage(navOptions: NavOptions? = null) this.navigate(addCertificationRoute, navOptions) } -fun NavGraphBuilder.addCertificationScreen(onBackClicked: () -> Unit) { +fun NavGraphBuilder.addCertificationScreen( + onBackClicked: () -> Unit, + createErrorToast: (throwable: Throwable?, message: Int?) -> Unit +) { composable(route = addCertificationRoute) { AddCertificationScreenRoute( onBackClicked = onBackClicked, - onAddClicked = onBackClicked + onAddClicked = onBackClicked, + createErrorToast = createErrorToast ) } } \ No newline at end of file From 668dfc5c34bae8b232b9cf9192654967ddcff5e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 22:59:08 +0900 Subject: [PATCH 028/141] :recycle: :: Use data class - GetCertificationListUiState --- .../viewmodel/uistate/GetCertificationListUiState.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetCertificationListUiState.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetCertificationListUiState.kt index 63d22f6c..1516cb71 100644 --- a/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetCertificationListUiState.kt +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetCertificationListUiState.kt @@ -4,7 +4,7 @@ import com.msg.model.entity.certification.CertificationListEntity sealed interface GetCertificationListUiState { data class Success(val data: List): GetCertificationListUiState - data object Error: GetCertificationListUiState + data class Error(val expectation: Throwable): GetCertificationListUiState data object Loading: GetCertificationListUiState data object Empty: GetCertificationListUiState } \ No newline at end of file From ef2d7ea59034d4a1ffe674d3a75fea5fa5c8a911 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 22:59:41 +0900 Subject: [PATCH 029/141] :recycle: :: Use data class State Error - GetLectureSignUpHistoryUiState --- .../viewmodel/uistate/GetLectureSignUpHistoryUiState.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetLectureSignUpHistoryUiState.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetLectureSignUpHistoryUiState.kt index e82ac2c5..daeaa956 100644 --- a/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetLectureSignUpHistoryUiState.kt +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetLectureSignUpHistoryUiState.kt @@ -5,5 +5,5 @@ import com.msg.model.entity.lecture.GetLectureSignUpHistoryEntity sealed interface GetLectureSignUpHistoryUiState { data class Success(val data: GetLectureSignUpHistoryEntity): GetLectureSignUpHistoryUiState data object Loading: GetLectureSignUpHistoryUiState - data object Error: GetLectureSignUpHistoryUiState + data class Error(val expectation: Throwable?): GetLectureSignUpHistoryUiState } \ No newline at end of file From a0f73c3ad6d9b126e033992b1831bcac8bdeb1a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 22:59:08 +0900 Subject: [PATCH 030/141] :recycle: :: Use data class State Error - GetCertificationListUiState --- .../viewmodel/uistate/GetCertificationListUiState.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetCertificationListUiState.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetCertificationListUiState.kt index 63d22f6c..1516cb71 100644 --- a/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetCertificationListUiState.kt +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetCertificationListUiState.kt @@ -4,7 +4,7 @@ import com.msg.model.entity.certification.CertificationListEntity sealed interface GetCertificationListUiState { data class Success(val data: List): GetCertificationListUiState - data object Error: GetCertificationListUiState + data class Error(val expectation: Throwable): GetCertificationListUiState data object Loading: GetCertificationListUiState data object Empty: GetCertificationListUiState } \ No newline at end of file From 46d7d21d61a007acf571cca691334eb84b4b1ec3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 22:59:41 +0900 Subject: [PATCH 031/141] :recycle: :: Use data class State Error - GetLectureSignUpHistoryUiState --- .../viewmodel/uistate/GetLectureSignUpHistoryUiState.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetLectureSignUpHistoryUiState.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetLectureSignUpHistoryUiState.kt index e82ac2c5..daeaa956 100644 --- a/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetLectureSignUpHistoryUiState.kt +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetLectureSignUpHistoryUiState.kt @@ -5,5 +5,5 @@ import com.msg.model.entity.lecture.GetLectureSignUpHistoryEntity sealed interface GetLectureSignUpHistoryUiState { data class Success(val data: GetLectureSignUpHistoryEntity): GetLectureSignUpHistoryUiState data object Loading: GetLectureSignUpHistoryUiState - data object Error: GetLectureSignUpHistoryUiState + data class Error(val expectation: Throwable?): GetLectureSignUpHistoryUiState } \ No newline at end of file From 97a5be40e287f21065edd4c1cd4cbc297fe7b062 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 23:00:44 +0900 Subject: [PATCH 032/141] :recycle: :: Apply Before Changed(Apply UiState, Changed Logic) - CertificationViewModel --- .../viewmodel/CertificationViewModel.kt | 134 +++++++++++++----- 1 file changed, 95 insertions(+), 39 deletions(-) diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt index 5a7bf44d..5e0fd69e 100644 --- a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt @@ -5,8 +5,10 @@ import androidx.compose.runtime.mutableStateOf import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.msg.certification.viewmodel.uistate.EditCertificationUiState import com.msg.certification.viewmodel.uistate.GetCertificationListUiState import com.msg.certification.viewmodel.uistate.GetLectureSignUpHistoryUiState +import com.msg.certification.viewmodel.uistate.GetStudentBelongClubDetailUiState import com.msg.certification.viewmodel.uistate.WriteCertificationUiState import com.msg.common.event.Event import com.msg.common.errorhandling.errorHandling @@ -47,16 +49,33 @@ class CertificationViewModel @Inject constructor( private val role = getRole().toString() - private val _getCertificationListUiState = MutableStateFlow(GetCertificationListUiState.Loading) - val getCertificationListUiState: StateFlow = _getCertificationListUiState.asStateFlow() + private val _getCertificationListUiState = + MutableStateFlow(GetCertificationListUiState.Loading) + val getCertificationListUiState: StateFlow = + _getCertificationListUiState.asStateFlow() - private val _getLectureSignUpHistoryUiState = MutableStateFlow(GetLectureSignUpHistoryUiState.Loading) - val getLectureSignUpHistoryUiState: StateFlow = _getLectureSignUpHistoryUiState.asStateFlow() + private val _getLectureSignUpHistoryUiState = + MutableStateFlow(GetLectureSignUpHistoryUiState.Loading) + val getLectureSignUpHistoryUiState: StateFlow = + _getLectureSignUpHistoryUiState.asStateFlow() - private val _writeCertificationUiState = MutableStateFlow(WriteCertificationUiState.Loading) - val writeCertificationUiState: StateFlow = _writeCertificationUiState.asStateFlow() + private val _writeCertificationUiState = + MutableStateFlow(WriteCertificationUiState.Success) + val writeCertificationUiState: StateFlow = + _writeCertificationUiState.asStateFlow() - private val _getCertificationListResponse = MutableStateFlow>>(Event.Loading) + private val _editCertificationUiState = + MutableStateFlow(EditCertificationUiState.Success) + val editCertificationUiState: StateFlow = + _editCertificationUiState.asStateFlow() + + private val _getStudentBelongClubDetailUiState = + MutableStateFlow(GetStudentBelongClubDetailUiState.Loading) + val getStudentBelongClubDetailUiState: StateFlow = + _getStudentBelongClubDetailUiState.asStateFlow() + + private val _getCertificationListResponse = + MutableStateFlow>>(Event.Loading) val getCertificationListResponse = _getCertificationListResponse.asStateFlow() private val _writeCertificationResponse = MutableStateFlow>(Event.Loading) @@ -65,10 +84,12 @@ class CertificationViewModel @Inject constructor( private val _editCertificationResponse = MutableStateFlow>(Event.Loading) val editCertificationResponse = _editCertificationResponse.asStateFlow() - private val _getStudentBelongResponse = MutableStateFlow>(Event.Loading) + private val _getStudentBelongResponse = + MutableStateFlow>(Event.Loading) val getStudentBelongResponse = _getStudentBelongResponse.asStateFlow() - private val _getLectureSignUpHistoryResponse = MutableStateFlow>(Event.Loading) + private val _getLectureSignUpHistoryResponse = + MutableStateFlow>(Event.Loading) val getLectureSignUpHistoryResponse = _getLectureSignUpHistoryResponse.asStateFlow() private val studentId = UUID.fromString(savedStateHandle.get("studentId")) @@ -78,7 +99,8 @@ class CertificationViewModel @Inject constructor( var selectedCertificationId = mutableStateOf(null) private set - internal var selectedTitle = savedStateHandle.getStateFlow(key = SELECTED_TITLE, initialValue = "") + internal var selectedTitle = + savedStateHandle.getStateFlow(key = SELECTED_TITLE, initialValue = "") var selectedDate = mutableStateOf(null) private set @@ -107,16 +129,23 @@ class CertificationViewModel @Inject constructor( getCertificationListUseCase(role = role, studentId = studentId) .asResult() .collectLatest { result -> - when(result) { - is Result.Loading -> { _getCertificationListUiState.value = GetCertificationListUiState.Loading } + when (result) { + is Result.Loading -> { + _getCertificationListUiState.value = GetCertificationListUiState.Loading + } + is Result.Success -> { if (result.data.isEmpty()) { _getCertificationListUiState.value = GetCertificationListUiState.Empty } else { - _getCertificationListUiState.value = GetCertificationListUiState.Success(result.data) + _getCertificationListUiState.value = + GetCertificationListUiState.Success(result.data) } } - is Result.Error -> { _getCertificationListUiState.value = GetCertificationListUiState.Error } + + is Result.Error -> { + _getCertificationListUiState.value = GetCertificationListUiState.Error + } } } } @@ -133,10 +162,17 @@ class CertificationViewModel @Inject constructor( ) .asResult() .collectLatest { result -> - when(result) { - is Result.Loading -> { _writeCertificationUiState.value = WriteCertificationUiState.Loading } - is Result.Success -> { _writeCertificationUiState.value = WriteCertificationUiState.Success } - is Result.Error -> { _writeCertificationUiState.value = WriteCertificationUiState.Error(result.exception) } + when (result) { + is Result.Success -> { + _writeCertificationUiState.value = WriteCertificationUiState.Success + } + + is Result.Error -> { + _writeCertificationUiState.value = + WriteCertificationUiState.Error(result.exception) + } + + else -> {} } } } @@ -151,15 +187,22 @@ class CertificationViewModel @Inject constructor( name = name, acquisitionDate = acquisitionDate ) - ).onSuccess { - it.catch { remoteError -> - _editCertificationResponse.value = remoteError.errorHandling() - }.collect { - _editCertificationResponse.value = Event.Success() + ) + .asResult() + .collectLatest { result -> + when (result) { + is Result.Success -> { + _editCertificationUiState.value = EditCertificationUiState.Success + } + + is Result.Error -> { + _editCertificationUiState.value = + EditCertificationUiState.Error(result.exception) + } + + else -> {} + } } - }.onFailure { error -> - _editCertificationResponse.value = error.errorHandling() - } } internal fun getStudentBelong() = viewModelScope.launch { @@ -167,15 +210,15 @@ class CertificationViewModel @Inject constructor( getStudentBelongClubUseCase( id = clubId, studentId = studentId - ).onSuccess { - it.catch { remoteError -> - _getStudentBelongResponse.value = remoteError.errorHandling() - }.collect { response -> - _getStudentBelongResponse.value = Event.Success(data = response) + ) + .asResult() + .collectLatest { result -> + when (result) { + is Result.Loading -> { _getStudentBelongClubDetailUiState.value = GetStudentBelongClubDetailUiState.Loading } + is Result.Success -> { _getStudentBelongClubDetailUiState.value = GetStudentBelongClubDetailUiState.Success(result.data) } + is Result.Error -> { _getStudentBelongClubDetailUiState.value = GetStudentBelongClubDetailUiState.Error(result.exception) } + } } - }.onFailure { error -> - _getStudentBelongResponse.value = error.errorHandling() - } } } @@ -184,10 +227,21 @@ class CertificationViewModel @Inject constructor( getLectureSignUpHistoryUseCase(studentId = studentId) .asResult() .collectLatest { result -> - when(result) { - is Result.Loading -> { _getLectureSignUpHistoryUiState.value = GetLectureSignUpHistoryUiState.Loading } - is Result.Success -> { _getLectureSignUpHistoryUiState.value = GetLectureSignUpHistoryUiState.Success(result.data) } - is Result.Error -> { _getLectureSignUpHistoryUiState.value = GetLectureSignUpHistoryUiState.Error } + when (result) { + is Result.Loading -> { + _getLectureSignUpHistoryUiState.value = + GetLectureSignUpHistoryUiState.Loading + } + + is Result.Success -> { + _getLectureSignUpHistoryUiState.value = + GetLectureSignUpHistoryUiState.Success(result.data) + } + + is Result.Error -> { + _getLectureSignUpHistoryUiState.value = + GetLectureSignUpHistoryUiState.Error + } } } } @@ -197,5 +251,7 @@ class CertificationViewModel @Inject constructor( getAuthorityUseCase() } - internal fun onSelectedTitleChange(value: String) { savedStateHandle[SELECTED_TITLE] = value } + internal fun onSelectedTitleChange(value: String) { + savedStateHandle[SELECTED_TITLE] = value + } } \ No newline at end of file From 39f0211438e1ed3b961fdac4f3097ea04798e65e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 23:01:39 +0900 Subject: [PATCH 033/141] :fire: :: Fire Unused State(Loading) - WriteCertificationUiState --- .../certification/viewmodel/uistate/WriteCertificationUiState.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/WriteCertificationUiState.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/WriteCertificationUiState.kt index ff0a3391..7d53ab74 100644 --- a/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/WriteCertificationUiState.kt +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/WriteCertificationUiState.kt @@ -2,6 +2,5 @@ package com.msg.certification.viewmodel.uistate sealed interface WriteCertificationUiState { data object Success: WriteCertificationUiState - data object Loading: WriteCertificationUiState data class Error(val exception: Throwable): WriteCertificationUiState } \ No newline at end of file From d6e90244d8b7cb897c77fff2c3f7a6493719bfca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 23:02:20 +0900 Subject: [PATCH 034/141] :recycle: :: Apply ViewModel Changed(Check Before Commit) --- .../certification/AddCertificationScreen.kt | 43 +++++++++++++++++-- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/feature/certification/src/main/java/com/msg/certification/AddCertificationScreen.kt b/feature/certification/src/main/java/com/msg/certification/AddCertificationScreen.kt index e6244ce1..281c1831 100644 --- a/feature/certification/src/main/java/com/msg/certification/AddCertificationScreen.kt +++ b/feature/certification/src/main/java/com/msg/certification/AddCertificationScreen.kt @@ -24,6 +24,9 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.msg.certification.component.AddAcquisitionDateSection import com.msg.certification.component.AddCertificationSection import com.msg.certification.viewmodel.CertificationViewModel +import com.msg.certification.viewmodel.uistate.EditCertificationUiState +import com.msg.certification.viewmodel.uistate.WriteCertificationUiState +import com.msg.design_system.R import com.msg.design_system.component.button.BitgoeulButton import com.msg.design_system.component.modifier.padding.paddingHorizontal import com.msg.design_system.component.topbar.DetailSettingTopBar @@ -37,11 +40,17 @@ import java.time.LocalDate internal fun AddCertificationScreenRoute( viewModel: CertificationViewModel = hiltViewModel(LocalContext.current as ComponentActivity), onBackClicked: () -> Unit, - onAddClicked: () -> Unit + onAddClicked: () -> Unit, + createErrorToast: (throwable: Throwable?, message: Int?) -> Unit ) { + val writeCertificationUiState by viewModel.writeCertificationUiState.collectAsStateWithLifecycle() + val editCertificationUiState by viewModel.editCertificationUiState.collectAsStateWithLifecycle() + val selectedTitle by viewModel.selectedTitle.collectAsStateWithLifecycle() AddCertificationScreen( + writeCertificationUiState = writeCertificationUiState, + editCertificationUiState = editCertificationUiState, selectedName = selectedTitle, selectedDate = viewModel.selectedDate.value, onSelectedNameChange = viewModel::onSelectedTitleChange, @@ -51,22 +60,46 @@ internal fun AddCertificationScreenRoute( viewModel.editCertification(name = name, acquisitionDate = acquisitionDate) } ?: viewModel.writeCertification(name = name, acquisitionDate = acquisitionDate) onAddClicked() - } + }, + createErrorToast = createErrorToast ) } @Composable internal fun AddCertificationScreen( modifier: Modifier = Modifier, + writeCertificationUiState: WriteCertificationUiState, + editCertificationUiState: EditCertificationUiState, focusManager: FocusManager = LocalFocusManager.current, selectedName: String, onSelectedNameChange: (String) -> Unit, onBackClicked: () -> Unit, selectedDate: LocalDate?, - onAddClicked: (name: String, acquisitionDate: LocalDate) -> Unit + onAddClicked: (name: String, acquisitionDate: LocalDate) -> Unit, + createErrorToast: (throwable: Throwable?, message: Int?) -> Unit ) { + val context = LocalContext.current + val (isDate, setIsDate) = rememberSaveable { mutableStateOf(selectedDate) } + when(writeCertificationUiState) { + is WriteCertificationUiState.Success -> { + makeToast(context, R.string.success_certification_write.toString()) + } + is WriteCertificationUiState.Error -> { + createErrorToast(writeCertificationUiState.exception, R.string.fail_certification_write) + } + } + + when(editCertificationUiState) { + is EditCertificationUiState.Success -> { + makeToast(context, R.string.success_certification_edit.toString()) + } + is EditCertificationUiState.Error -> { + createErrorToast(editCertificationUiState.exception, R.string.fail_certification_edit) + } + } + BitgoeulAndroidTheme { colors, _ -> Box( modifier = modifier @@ -78,7 +111,6 @@ internal fun AddCertificationScreen( } } ) { - val context = LocalContext.current Column( modifier = modifier .fillMaxSize() @@ -131,5 +163,8 @@ fun AddCertificationScreenPre() { selectedDate = null, focusManager = LocalFocusManager.current, onSelectedNameChange = {}, + writeCertificationUiState = WriteCertificationUiState.Success, + editCertificationUiState = EditCertificationUiState.Success, + createErrorToast = {_, _ -> } ) } \ No newline at end of file From fea0264e7742fda08a6b09e837818203b6788b7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 23:03:01 +0900 Subject: [PATCH 035/141] :recycle: :: Apply ViewModel Changed And Change Logic --- .../msg/certification/CertificationScreen.kt | 61 +++++++++++-------- 1 file changed, 36 insertions(+), 25 deletions(-) diff --git a/feature/certification/src/main/java/com/msg/certification/CertificationScreen.kt b/feature/certification/src/main/java/com/msg/certification/CertificationScreen.kt index 90134785..76d35b0e 100644 --- a/feature/certification/src/main/java/com/msg/certification/CertificationScreen.kt +++ b/feature/certification/src/main/java/com/msg/certification/CertificationScreen.kt @@ -32,6 +32,7 @@ import com.msg.common.event.Event import com.msg.certification.viewmodel.CertificationViewModel import com.msg.certification.viewmodel.uistate.GetCertificationListUiState import com.msg.certification.viewmodel.uistate.GetLectureSignUpHistoryUiState +import com.msg.certification.viewmodel.uistate.GetStudentBelongClubDetailUiState import com.msg.design_system.R import com.msg.design_system.component.icon.HumanIcon import com.msg.design_system.theme.BitgoeulAndroidTheme @@ -40,6 +41,7 @@ import com.msg.model.entity.club.StudentBelongClubEntity import com.msg.model.entity.lecture.GetLectureSignUpHistoryEntity import com.msg.model.entity.lecture.SignUpLectures import com.msg.ui.DevicePreviews +import com.msg.ui.makeToast import java.time.LocalDate import java.util.UUID @@ -47,10 +49,12 @@ import java.util.UUID internal fun CertificationScreenRoute( viewModel: CertificationViewModel = hiltViewModel(LocalContext.current as ComponentActivity), onHumanIconClicked: () -> Unit, - onEditClicked: () -> Unit + onEditClicked: () -> Unit, + createErrorToast: (throwable: Throwable?, message: Int?) -> Unit ) { val getCertificationListUiState by viewModel.getCertificationListUiState.collectAsStateWithLifecycle() val getLectureSignUpHistoryUiState by viewModel.getLectureSignUpHistoryUiState.collectAsStateWithLifecycle() + val getStudentBelongClubDetailUiState by viewModel.getStudentBelongClubDetailUiState.collectAsStateWithLifecycle() viewModel.getCertificationList() viewModel.getStudentBelong() @@ -93,7 +97,9 @@ internal fun CertificationScreenRoute( certificationData = viewModel.certificationList, lectureData = viewModel.lectureData.value, getCertificationListUiState = getCertificationListUiState, - getLectureSignUpHistoryUiState = getLectureSignUpHistoryUiState + getLectureSignUpHistoryUiState = getLectureSignUpHistoryUiState, + getStudentBelongClubDetailUiState = getStudentBelongClubDetailUiState, + createErrorToast = createErrorToast ) } @@ -145,14 +151,16 @@ private suspend fun getLectureData( @Composable internal fun CertificationScreen( modifier: Modifier = Modifier, + createErrorToast: (throwable: Throwable?, message: Int?) -> Unit, getCertificationListUiState: GetCertificationListUiState, getLectureSignUpHistoryUiState: GetLectureSignUpHistoryUiState, + getStudentBelongClubDetailUiState: GetStudentBelongClubDetailUiState, onHumanIconClicked: () -> Unit, onEditClicked: (id: UUID, title: String, date: LocalDate) -> Unit, onPlusClicked: () -> Unit, studentData: StudentBelongClubEntity, certificationData: List, - lectureData: GetLectureSignUpHistoryEntity + lectureData: GetLectureSignUpHistoryEntity, ) { BitgoeulAndroidTheme { colors, typography -> Box( @@ -160,6 +168,7 @@ internal fun CertificationScreen( .fillMaxSize() .background(color = colors.WHITE) ) { + val context = LocalContext.current Column( modifier = modifier .fillMaxSize() @@ -183,7 +192,24 @@ internal fun CertificationScreen( ) } Spacer(modifier = modifier.height(24.dp)) - StudentInfoSection(data = studentData) + when(getStudentBelongClubDetailUiState) { + is GetStudentBelongClubDetailUiState.Success -> { StudentInfoSection(data = studentData) } + is GetStudentBelongClubDetailUiState.Loading -> { + Box( + modifier = modifier.fillMaxWidth(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator( + modifier = modifier.then(Modifier.size(27.dp)), + color = colors.G2, + strokeWidth = 2.dp + ) + } + } + is GetStudentBelongClubDetailUiState.Error -> { + createErrorToast(getStudentBelongClubDetailUiState.expectation, R.string.fail_get_student_club_detail) + } + } Spacer(modifier = modifier.height(24.dp)) HorizontalDivider( modifier = modifier.fillMaxWidth(), @@ -201,7 +227,6 @@ internal fun CertificationScreen( data = certificationData ) } - is GetCertificationListUiState.Loading -> { Box( modifier = modifier.fillMaxWidth(), @@ -214,22 +239,11 @@ internal fun CertificationScreen( ) } } - is GetCertificationListUiState.Error -> { - Text( - modifier = modifier.align(Alignment.CenterHorizontally), - text = "통신이 원활하지 않습니다..", - style = typography.bodySmall - ) + createErrorToast(getCertificationListUiState.expectation, R.string.fail_get_certification_list) } - is GetCertificationListUiState.Empty -> { - Text( - modifier = modifier.align(Alignment.CenterHorizontally), - text = "자격증이 없습니다..", - style = typography.bodySmall, - color = colors.G4 - ) + makeToast(context, R.string.empty_state.toString()) } } Spacer(modifier = modifier.height(12.dp)) @@ -248,12 +262,7 @@ internal fun CertificationScreen( } } is GetLectureSignUpHistoryUiState.Error -> { - Text( - modifier = modifier.align(Alignment.CenterHorizontally).padding(top = 50.dp), - text = "통신이 원할하지 않습니다..", - style = typography.bodySmall, - color = colors.G4 - ) + createErrorToast(getLectureSignUpHistoryUiState.expectation, R.string.fail_get_lecture_list) } } } @@ -302,6 +311,8 @@ fun CertificationScreenPre() { ) ), getCertificationListUiState = GetCertificationListUiState.Empty, - getLectureSignUpHistoryUiState = GetLectureSignUpHistoryUiState.Error + getLectureSignUpHistoryUiState = GetLectureSignUpHistoryUiState.Error(expectation = Throwable("통신이 원할하지 않습니다.")), + getStudentBelongClubDetailUiState = GetStudentBelongClubDetailUiState.Error(expectation = Throwable("통신이 원할하지 않습니다.")), + createErrorToast = { _, _ -> } ) } \ No newline at end of file From fb9d26f0134024515b64e5ea97c8654ae18d1a3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 23:15:09 +0900 Subject: [PATCH 036/141] :recycle: :: Fire Line Spacing And Changed Error State Logic --- .../viewmodel/CertificationViewModel.kt | 42 ++++--------------- 1 file changed, 9 insertions(+), 33 deletions(-) diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt index 5e0fd69e..d4f3ed8c 100644 --- a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt @@ -138,14 +138,9 @@ class CertificationViewModel @Inject constructor( if (result.data.isEmpty()) { _getCertificationListUiState.value = GetCertificationListUiState.Empty } else { - _getCertificationListUiState.value = - GetCertificationListUiState.Success(result.data) - } - } - - is Result.Error -> { - _getCertificationListUiState.value = GetCertificationListUiState.Error + _getCertificationListUiState.value = GetCertificationListUiState.Success(result.data) } } + is Result.Error -> { _getCertificationListUiState.value = GetCertificationListUiState.Error(result.exception) } } } } @@ -163,15 +158,8 @@ class CertificationViewModel @Inject constructor( .asResult() .collectLatest { result -> when (result) { - is Result.Success -> { - _writeCertificationUiState.value = WriteCertificationUiState.Success - } - - is Result.Error -> { - _writeCertificationUiState.value = - WriteCertificationUiState.Error(result.exception) - } - + is Result.Success -> { _writeCertificationUiState.value = WriteCertificationUiState.Success } + is Result.Error -> { _writeCertificationUiState.value = WriteCertificationUiState.Error(result.exception) } else -> {} } } @@ -191,15 +179,8 @@ class CertificationViewModel @Inject constructor( .asResult() .collectLatest { result -> when (result) { - is Result.Success -> { - _editCertificationUiState.value = EditCertificationUiState.Success - } - - is Result.Error -> { - _editCertificationUiState.value = - EditCertificationUiState.Error(result.exception) - } - + is Result.Success -> { _editCertificationUiState.value = EditCertificationUiState.Success } + is Result.Error -> { _editCertificationUiState.value = EditCertificationUiState.Error(result.exception) } else -> {} } } @@ -229,18 +210,13 @@ class CertificationViewModel @Inject constructor( .collectLatest { result -> when (result) { is Result.Loading -> { - _getLectureSignUpHistoryUiState.value = - GetLectureSignUpHistoryUiState.Loading + _getLectureSignUpHistoryUiState.value = GetLectureSignUpHistoryUiState.Loading } - is Result.Success -> { - _getLectureSignUpHistoryUiState.value = - GetLectureSignUpHistoryUiState.Success(result.data) + _getLectureSignUpHistoryUiState.value = GetLectureSignUpHistoryUiState.Success(result.data) } - is Result.Error -> { - _getLectureSignUpHistoryUiState.value = - GetLectureSignUpHistoryUiState.Error + _getLectureSignUpHistoryUiState.value = GetLectureSignUpHistoryUiState.Error(result.exception) } } } From d96282b76b31f89b7dcbcdd9ee61238c005f2066 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 23:15:23 +0900 Subject: [PATCH 037/141] :recycle: :: Add createErrorToast --- .../com/msg/bitgoeul_android/navigation/BitgoeulNavHost.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/msg/bitgoeul_android/navigation/BitgoeulNavHost.kt b/app/src/main/java/com/msg/bitgoeul_android/navigation/BitgoeulNavHost.kt index f4dee234..95c7fa1b 100644 --- a/app/src/main/java/com/msg/bitgoeul_android/navigation/BitgoeulNavHost.kt +++ b/app/src/main/java/com/msg/bitgoeul_android/navigation/BitgoeulNavHost.kt @@ -169,7 +169,8 @@ fun BitgoeulNavHost( createErrorToast = createErrorToast ) addCertificationScreen( - onBackClicked = navController::navigateUp + onBackClicked = navController::navigateUp, + createErrorToast = createErrorToast ) } } \ No newline at end of file From 1d278c8682e06b126ccae96011147585db7f4f54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 23:24:04 +0900 Subject: [PATCH 038/141] :fire: :: Fire Unused Import --- .../viewmodel/uistate/GetStudentBelongClubDetailUiState.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetStudentBelongClubDetailUiState.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetStudentBelongClubDetailUiState.kt index 3bbf4801..3dcae3e9 100644 --- a/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetStudentBelongClubDetailUiState.kt +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetStudentBelongClubDetailUiState.kt @@ -1,6 +1,5 @@ package com.msg.certification.viewmodel.uistate -import android.content.Context import com.msg.model.entity.club.StudentBelongClubEntity sealed interface GetStudentBelongClubDetailUiState { From 7016b259c48bad884779bc2a52ed132df7edce7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 23:32:40 +0900 Subject: [PATCH 039/141] :fire: :: Fire Line Spacing --- .../viewmodel/CertificationViewModel.kt | 62 +++++++------------ 1 file changed, 21 insertions(+), 41 deletions(-) diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt index d4f3ed8c..f3e7815f 100644 --- a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt @@ -49,33 +49,22 @@ class CertificationViewModel @Inject constructor( private val role = getRole().toString() - private val _getCertificationListUiState = - MutableStateFlow(GetCertificationListUiState.Loading) - val getCertificationListUiState: StateFlow = - _getCertificationListUiState.asStateFlow() - - private val _getLectureSignUpHistoryUiState = - MutableStateFlow(GetLectureSignUpHistoryUiState.Loading) - val getLectureSignUpHistoryUiState: StateFlow = - _getLectureSignUpHistoryUiState.asStateFlow() - - private val _writeCertificationUiState = - MutableStateFlow(WriteCertificationUiState.Success) - val writeCertificationUiState: StateFlow = - _writeCertificationUiState.asStateFlow() - - private val _editCertificationUiState = - MutableStateFlow(EditCertificationUiState.Success) - val editCertificationUiState: StateFlow = - _editCertificationUiState.asStateFlow() - - private val _getStudentBelongClubDetailUiState = - MutableStateFlow(GetStudentBelongClubDetailUiState.Loading) - val getStudentBelongClubDetailUiState: StateFlow = - _getStudentBelongClubDetailUiState.asStateFlow() - - private val _getCertificationListResponse = - MutableStateFlow>>(Event.Loading) + private val _getCertificationListUiState = MutableStateFlow(GetCertificationListUiState.Loading) + val getCertificationListUiState: StateFlow = _getCertificationListUiState.asStateFlow() + + private val _getLectureSignUpHistoryUiState = MutableStateFlow(GetLectureSignUpHistoryUiState.Loading) + val getLectureSignUpHistoryUiState: StateFlow = _getLectureSignUpHistoryUiState.asStateFlow() + + private val _writeCertificationUiState = MutableStateFlow(WriteCertificationUiState.Success) + val writeCertificationUiState: StateFlow = _writeCertificationUiState.asStateFlow() + + private val _editCertificationUiState = MutableStateFlow(EditCertificationUiState.Success) + val editCertificationUiState: StateFlow = _editCertificationUiState.asStateFlow() + + private val _getStudentBelongClubDetailUiState = MutableStateFlow(GetStudentBelongClubDetailUiState.Loading) + val getStudentBelongClubDetailUiState: StateFlow = _getStudentBelongClubDetailUiState.asStateFlow() + + private val _getCertificationListResponse = MutableStateFlow>>(Event.Loading) val getCertificationListResponse = _getCertificationListResponse.asStateFlow() private val _writeCertificationResponse = MutableStateFlow>(Event.Loading) @@ -84,12 +73,10 @@ class CertificationViewModel @Inject constructor( private val _editCertificationResponse = MutableStateFlow>(Event.Loading) val editCertificationResponse = _editCertificationResponse.asStateFlow() - private val _getStudentBelongResponse = - MutableStateFlow>(Event.Loading) + private val _getStudentBelongResponse = MutableStateFlow>(Event.Loading) val getStudentBelongResponse = _getStudentBelongResponse.asStateFlow() - private val _getLectureSignUpHistoryResponse = - MutableStateFlow>(Event.Loading) + private val _getLectureSignUpHistoryResponse = MutableStateFlow>(Event.Loading) val getLectureSignUpHistoryResponse = _getLectureSignUpHistoryResponse.asStateFlow() private val studentId = UUID.fromString(savedStateHandle.get("studentId")) @@ -133,7 +120,6 @@ class CertificationViewModel @Inject constructor( is Result.Loading -> { _getCertificationListUiState.value = GetCertificationListUiState.Loading } - is Result.Success -> { if (result.data.isEmpty()) { _getCertificationListUiState.value = GetCertificationListUiState.Empty @@ -209,15 +195,9 @@ class CertificationViewModel @Inject constructor( .asResult() .collectLatest { result -> when (result) { - is Result.Loading -> { - _getLectureSignUpHistoryUiState.value = GetLectureSignUpHistoryUiState.Loading - } - is Result.Success -> { - _getLectureSignUpHistoryUiState.value = GetLectureSignUpHistoryUiState.Success(result.data) - } - is Result.Error -> { - _getLectureSignUpHistoryUiState.value = GetLectureSignUpHistoryUiState.Error(result.exception) - } + is Result.Loading -> { _getLectureSignUpHistoryUiState.value = GetLectureSignUpHistoryUiState.Loading } + is Result.Success -> { _getLectureSignUpHistoryUiState.value = GetLectureSignUpHistoryUiState.Success(result.data) } + is Result.Error -> { _getLectureSignUpHistoryUiState.value = GetLectureSignUpHistoryUiState.Error(result.exception) } } } } From 3aa76fdfc72eb856890be128c628b0cad7061b8a Mon Sep 17 00:00:00 2001 From: Chaejongin12 Date: Wed, 11 Sep 2024 10:06:38 +0900 Subject: [PATCH 040/141] =?UTF-8?q?=E2=9C=A8::=20=EB=AC=B8=EC=9D=98?= =?UTF-8?q?=EC=82=AC=ED=95=AD=20=EB=AA=A8=EB=93=88=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- settings.gradle.kts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/settings.gradle.kts b/settings.gradle.kts index 79d23d73..3c63da60 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -37,4 +37,6 @@ include(":feature:post") include(":feature:club") include(":feature:email") include(":feature:certification") +include(":feature:inquiry") + gradle.startParameter.excludedTaskNames.addAll(listOf(":build-logic:convention:testClasses")) From 765ba7c2742c3992fbd87b5ff430cd8a5266fdd1 Mon Sep 17 00:00:00 2001 From: Chaejongin12 Date: Wed, 11 Sep 2024 10:22:04 +0900 Subject: [PATCH 041/141] =?UTF-8?q?=E2=9C=A8::=20G2=20=EC=83=89=EC=83=81?= =?UTF-8?q?=20FilterIcon=20=EC=B6=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../design_system/component/icon/BitgoeulIcon.kt | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/core/design-system/src/main/java/com/msg/design_system/component/icon/BitgoeulIcon.kt b/core/design-system/src/main/java/com/msg/design_system/component/icon/BitgoeulIcon.kt index 5b4eade3..e1841c2c 100644 --- a/core/design-system/src/main/java/com/msg/design_system/component/icon/BitgoeulIcon.kt +++ b/core/design-system/src/main/java/com/msg/design_system/component/icon/BitgoeulIcon.kt @@ -361,4 +361,16 @@ fun BigCheckIcon() { painter = painterResource(id = R.drawable.ic_big_check), contentDescription = "Big blue check icon" ) -} \ No newline at end of file +} + +@Composable +fun G2ColorFilterIcon( + modifier: Modifier = Modifier, +) { + Image( + modifier = modifier, + painter = painterResource(id = R.drawable.ic_g2_filter), + contentDescription = "G2 Color Filter Icon" + ) +} + From 0c87c1a4adf0fff2de1113072fb5f02279934027 Mon Sep 17 00:00:00 2001 From: Chaejongin12 Date: Wed, 11 Sep 2024 10:22:38 +0900 Subject: [PATCH 042/141] =?UTF-8?q?=E2=9C=A8::=20G2=20=EC=83=89=EC=83=81?= =?UTF-8?q?=20FilterIcon=EC=9D=84=20Content=EB=A1=9C=20=ED=95=98=EB=8A=94?= =?UTF-8?q?=20Button=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../component/button/BitgoeulButton.kt | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/core/design-system/src/main/java/com/msg/design_system/component/button/BitgoeulButton.kt b/core/design-system/src/main/java/com/msg/design_system/component/button/BitgoeulButton.kt index ec83eec7..21283fdf 100644 --- a/core/design-system/src/main/java/com/msg/design_system/component/button/BitgoeulButton.kt +++ b/core/design-system/src/main/java/com/msg/design_system/component/button/BitgoeulButton.kt @@ -192,6 +192,27 @@ fun ApplicationDoneButton( } } +@Composable +fun G2FilterIconButton( + modifier: Modifier = Modifier, + onClicked: () -> Unit, +) { + BitgoeulAndroidTheme { colors, _ -> + OutlinedButton( + modifier = modifier, + onClick = onClicked, + border = BorderStroke(1.dp, color = colors.G2), + colors = ButtonDefaults.outlinedButtonColors( + containerColor = colors.WHITE, + contentColor = colors.G2, + ), + shape = RoundedCornerShape(8.dp), + ) { + G2ColorFilterIcon() + } + } +} + @Preview @Composable fun BitgoeulButtonPre() { From 790b0dadd0920053b31f90225118ac761a7d8dc1 Mon Sep 17 00:00:00 2001 From: Chaejongin12 Date: Wed, 11 Sep 2024 10:22:51 +0900 Subject: [PATCH 043/141] =?UTF-8?q?=E2=9C=A8::=20G2=20=EC=83=89=EC=83=81?= =?UTF-8?q?=20FilterIcon=EC=9D=84=20Content=EB=A1=9C=20=ED=95=98=EB=8A=94?= =?UTF-8?q?=20Button=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../component/button/BitgoeulButton.kt | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/core/design-system/src/main/java/com/msg/design_system/component/button/BitgoeulButton.kt b/core/design-system/src/main/java/com/msg/design_system/component/button/BitgoeulButton.kt index 21283fdf..fe170494 100644 --- a/core/design-system/src/main/java/com/msg/design_system/component/button/BitgoeulButton.kt +++ b/core/design-system/src/main/java/com/msg/design_system/component/button/BitgoeulButton.kt @@ -18,6 +18,7 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import com.msg.design_system.component.icon.G2ColorFilterIcon import com.msg.design_system.component.icon.MainColorSettingIcon import com.msg.design_system.theme.BitgoeulAndroidTheme @@ -98,7 +99,7 @@ fun BitgoeulButton( fun DetailSettingButton( modifier: Modifier = Modifier, type: String, - onClicked: () -> Unit + onClicked: () -> Unit, ) { BitgoeulAndroidTheme { colors, typography -> OutlinedButton( @@ -130,7 +131,7 @@ fun NegativeBitgoeulButton( modifier: Modifier = Modifier, text: String, state: ButtonState = ButtonState.Enable, - onClicked: () -> Unit + onClicked: () -> Unit, ) { BitgoeulAndroidTheme { colors, typography -> @@ -182,7 +183,6 @@ fun ApplicationDoneButton( ), shape = RoundedCornerShape(8.dp), ) { - Text( text = text, color = colors.E5, @@ -254,5 +254,12 @@ fun BitgoeulButtonPre() { onClicked = {}, text = "수강 신청 취소" ) + + G2FilterIconButton( + modifier = Modifier + .width(319.dp) + .height(52.dp), + onClicked = {}, + ) } } From 51b36807d8f6b134b905afc3c3f0a06cef289d14 Mon Sep 17 00:00:00 2001 From: Chaejongin12 Date: Wed, 11 Sep 2024 10:23:08 +0900 Subject: [PATCH 044/141] =?UTF-8?q?=E2=9C=A8::=20strings.xml=20=EB=AC=B8?= =?UTF-8?q?=EC=9E=90=EC=97=B4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/design-system/src/main/res/values/strings.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/design-system/src/main/res/values/strings.xml b/core/design-system/src/main/res/values/strings.xml index b6ec9ab5..d5873fd5 100644 --- a/core/design-system/src/main/res/values/strings.xml +++ b/core/design-system/src/main/res/values/strings.xml @@ -81,6 +81,10 @@ 계열 검색 또는 임의로 추가... 학과 이름으로 검색... 강의 구분 검색... + 이름으로 검색... 전체 학생정보 + 문의사항 + 답변 됨 + 답변 대기 중 \ No newline at end of file From 65136f6870ddf34a18905bc9cd3006e72bf9873b Mon Sep 17 00:00:00 2001 From: Chaejongin12 Date: Wed, 11 Sep 2024 10:23:29 +0900 Subject: [PATCH 045/141] =?UTF-8?q?=E2=9C=A8::=20PositiveTag=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../component/tag/PositiveTag.kt | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 core/design-system/src/main/java/com/msg/design_system/component/tag/PositiveTag.kt diff --git a/core/design-system/src/main/java/com/msg/design_system/component/tag/PositiveTag.kt b/core/design-system/src/main/java/com/msg/design_system/component/tag/PositiveTag.kt new file mode 100644 index 00000000..a77bec9b --- /dev/null +++ b/core/design-system/src/main/java/com/msg/design_system/component/tag/PositiveTag.kt @@ -0,0 +1,42 @@ +package com.msg.design_system.component.tag + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.msg.design_system.theme.BitgoeulAndroidTheme + +@Composable +fun PositiveTag( + modifier: Modifier = Modifier, + text: String, +) { + BitgoeulAndroidTheme { colors, typography -> + Box( + modifier = modifier + .wrapContentSize() + .background(color = colors.P5, shape = RoundedCornerShape(18.dp)) + .padding(vertical = 4.dp, horizontal = 8.dp) + ) { + Text( + text = text, + style = typography.labelMedium, + color = colors.WHITE + ) + } + } +} + +@Preview +@Composable +fun PositiveTagPre() { + PositiveTag( + text = "답변 됨" + ) +} \ No newline at end of file From 929bd23c0ad920c3a2f4e6192548b13f88190225 Mon Sep 17 00:00:00 2001 From: Chaejongin12 Date: Wed, 11 Sep 2024 10:23:35 +0900 Subject: [PATCH 046/141] =?UTF-8?q?=E2=9C=A8::=20NegativeTag=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../component/tag/NegativeTag.kt | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 core/design-system/src/main/java/com/msg/design_system/component/tag/NegativeTag.kt diff --git a/core/design-system/src/main/java/com/msg/design_system/component/tag/NegativeTag.kt b/core/design-system/src/main/java/com/msg/design_system/component/tag/NegativeTag.kt new file mode 100644 index 00000000..b6704af7 --- /dev/null +++ b/core/design-system/src/main/java/com/msg/design_system/component/tag/NegativeTag.kt @@ -0,0 +1,42 @@ +package com.msg.design_system.component.tag + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.msg.design_system.theme.BitgoeulAndroidTheme + +@Composable +fun NegativeTag( + modifier: Modifier = Modifier, + text: String, +) { + BitgoeulAndroidTheme { colors, typography -> + Box( + modifier = modifier + .wrapContentSize() + .background(color = colors.E5, shape = RoundedCornerShape(18.dp)) + .padding(vertical = 4.dp, horizontal = 8.dp) + ) { + Text( + text = text, + style = typography.labelMedium, + color = colors.WHITE + ) + } + } +} + +@Preview +@Composable +fun NegativeTagPre() { + NegativeTag( + text = "답변 대기 중" + ) +} \ No newline at end of file From e39aafeec0879a9d71b1929e9f4c0cdbf30677f0 Mon Sep 17 00:00:00 2001 From: Chaejongin12 Date: Wed, 11 Sep 2024 10:23:47 +0900 Subject: [PATCH 047/141] =?UTF-8?q?=E2=9C=A8::=20G2=20=EC=83=89=EC=83=81?= =?UTF-8?q?=20Icon=20svg=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/ic_g2_filter.xml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 core/design-system/src/main/res/drawable/ic_g2_filter.xml diff --git a/core/design-system/src/main/res/drawable/ic_g2_filter.xml b/core/design-system/src/main/res/drawable/ic_g2_filter.xml new file mode 100644 index 00000000..afdd982f --- /dev/null +++ b/core/design-system/src/main/res/drawable/ic_g2_filter.xml @@ -0,0 +1,15 @@ + + + + + From 7c51aeaed9b82d92748f434676c10a8a8303596a Mon Sep 17 00:00:00 2001 From: Chaejongin12 Date: Wed, 11 Sep 2024 10:24:00 +0900 Subject: [PATCH 048/141] =?UTF-8?q?=E2=9C=A8::=20FilterDialog=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../component/dialog/FilterDialog.kt | 108 ++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 core/design-system/src/main/java/com/msg/design_system/component/dialog/FilterDialog.kt diff --git a/core/design-system/src/main/java/com/msg/design_system/component/dialog/FilterDialog.kt b/core/design-system/src/main/java/com/msg/design_system/component/dialog/FilterDialog.kt new file mode 100644 index 00000000..bc9a01e2 --- /dev/null +++ b/core/design-system/src/main/java/com/msg/design_system/component/dialog/FilterDialog.kt @@ -0,0 +1,108 @@ +package com.msg.design_system.component.dialog + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.IconButton +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.Dialog +import com.msg.design_system.R +import com.msg.design_system.component.checkbox.BitGoeulCheckBox +import com.msg.design_system.component.icon.CloseIcon +import com.msg.design_system.theme.BitgoeulAndroidTheme + + +@Composable +fun FilterDialog( + modifier: Modifier = Modifier, + filterItemList: List, + isVisible: Boolean, + onQuit: (Boolean) -> Unit, + onItemClicked: (String) -> Unit, +) { + if (isVisible) { + BitgoeulAndroidTheme { colors, typography -> + Dialog( + onDismissRequest = { onQuit(false) } + ) { + Column( + modifier = modifier + .background( + color = colors.WHITE, + shape = RoundedCornerShape(8.dp) + ) + .wrapContentSize() + .fillMaxWidth() + .padding(24.dp) + ) { + Row( + modifier = modifier.fillMaxWidth() + ) { + Text( + text = stringResource(id = R.string.inquiry), + style = typography.titleSmall, + color = colors.BLACK + ) + Spacer(modifier = modifier.weight(1f)) + IconButton( + modifier = modifier + .height(24.dp) + .width(24.dp), + onClick = { onQuit(false) }, + content = { CloseIcon() } + ) + } + + Spacer(modifier = modifier.height(24.dp)) + + LazyColumn { + items(filterItemList.size) { index -> + Row( + verticalAlignment = Alignment.CenterVertically + ) { + BitGoeulCheckBox( + modifier = modifier.wrapContentSize(), + onCheckedChange = { + onItemClicked(filterItemList[index]) + } + ) + + Spacer(modifier = modifier.width(8.dp)) + + Text(text = filterItemList[index]) + } + + Spacer(modifier = modifier.height(16.dp)) + } + } + } + } + } + } +} + +@Preview +@Composable +fun FilterDialogPreview() { + FilterDialog( + filterItemList = listOf("학교선택", "학년선택", "학기선택"), + isVisible = true, + onQuit = {}, + onItemClicked = {} + ) +} From 809add8de7454955c11a87879fe5b92457d2fe5d Mon Sep 17 00:00:00 2001 From: Chaejongin12 Date: Wed, 11 Sep 2024 10:24:16 +0900 Subject: [PATCH 049/141] =?UTF-8?q?=E2=9C=A8::=20=EB=AC=B8=EC=9D=98?= =?UTF-8?q?=EC=82=AC=ED=95=AD=20=EB=AA=A8=EB=93=88=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- feature/inquiry/.gitignore | 1 + feature/inquiry/build.gradle.kts | 8 +++++++ feature/inquiry/consumer-rules.pro | 0 feature/inquiry/proguard-rules.pro | 21 ++++++++++++++++ .../inquiry/ExampleInstrumentedTest.kt | 24 +++++++++++++++++++ .../com/bitgoeul/inquiry/ExampleUnitTest.kt | 17 +++++++++++++ 6 files changed, 71 insertions(+) create mode 100644 feature/inquiry/.gitignore create mode 100644 feature/inquiry/build.gradle.kts create mode 100644 feature/inquiry/consumer-rules.pro create mode 100644 feature/inquiry/proguard-rules.pro create mode 100644 feature/inquiry/src/androidTest/java/com/bitgoeul/inquiry/ExampleInstrumentedTest.kt create mode 100644 feature/inquiry/src/test/java/com/bitgoeul/inquiry/ExampleUnitTest.kt diff --git a/feature/inquiry/.gitignore b/feature/inquiry/.gitignore new file mode 100644 index 00000000..42afabfd --- /dev/null +++ b/feature/inquiry/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/feature/inquiry/build.gradle.kts b/feature/inquiry/build.gradle.kts new file mode 100644 index 00000000..15730cc8 --- /dev/null +++ b/feature/inquiry/build.gradle.kts @@ -0,0 +1,8 @@ +plugins { + id("bitgoeul.android.feature") + id("bitgoeul.android.hilt") +} + +android { + namespace = "com.bitgoeul.inquiry" +} diff --git a/feature/inquiry/consumer-rules.pro b/feature/inquiry/consumer-rules.pro new file mode 100644 index 00000000..e69de29b diff --git a/feature/inquiry/proguard-rules.pro b/feature/inquiry/proguard-rules.pro new file mode 100644 index 00000000..481bb434 --- /dev/null +++ b/feature/inquiry/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/feature/inquiry/src/androidTest/java/com/bitgoeul/inquiry/ExampleInstrumentedTest.kt b/feature/inquiry/src/androidTest/java/com/bitgoeul/inquiry/ExampleInstrumentedTest.kt new file mode 100644 index 00000000..7f1c3052 --- /dev/null +++ b/feature/inquiry/src/androidTest/java/com/bitgoeul/inquiry/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package com.bitgoeul.inquiry + +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.ext.junit.runners.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("com.bitgoeul.inquiry.test", appContext.packageName) + } +} \ No newline at end of file diff --git a/feature/inquiry/src/test/java/com/bitgoeul/inquiry/ExampleUnitTest.kt b/feature/inquiry/src/test/java/com/bitgoeul/inquiry/ExampleUnitTest.kt new file mode 100644 index 00000000..2b6b30be --- /dev/null +++ b/feature/inquiry/src/test/java/com/bitgoeul/inquiry/ExampleUnitTest.kt @@ -0,0 +1,17 @@ +package com.bitgoeul.inquiry + +import org.junit.Test + +import org.junit.Assert.* + +/** + * Example local unit test, which will execute on the development machine (host). + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +class ExampleUnitTest { + @Test + fun addition_isCorrect() { + assertEquals(4, 2 + 2) + } +} \ No newline at end of file From da672260860441ce7f987aa6b011364d8270f4fd Mon Sep 17 00:00:00 2001 From: Chaejongin12 Date: Wed, 11 Sep 2024 10:24:21 +0900 Subject: [PATCH 050/141] =?UTF-8?q?=E2=9C=A8::=20=EB=AC=B8=EC=9D=98?= =?UTF-8?q?=EC=82=AC=ED=95=AD=20=EB=AA=A8=EB=93=88=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- feature/inquiry/src/main/AndroidManifest.xml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 feature/inquiry/src/main/AndroidManifest.xml diff --git a/feature/inquiry/src/main/AndroidManifest.xml b/feature/inquiry/src/main/AndroidManifest.xml new file mode 100644 index 00000000..a5918e68 --- /dev/null +++ b/feature/inquiry/src/main/AndroidManifest.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file From 82e7fab200bc94451f9cb52d98e5590686495c00 Mon Sep 17 00:00:00 2001 From: Chaejongin12 Date: Wed, 11 Sep 2024 10:24:33 +0900 Subject: [PATCH 051/141] =?UTF-8?q?=E2=9C=A8::=20InquiryViewModel=20?= =?UTF-8?q?=EC=84=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/bitgoeul/inquiry/viewmodel/InquiryViewModel.kt | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 feature/inquiry/src/main/java/com/bitgoeul/inquiry/viewmodel/InquiryViewModel.kt diff --git a/feature/inquiry/src/main/java/com/bitgoeul/inquiry/viewmodel/InquiryViewModel.kt b/feature/inquiry/src/main/java/com/bitgoeul/inquiry/viewmodel/InquiryViewModel.kt new file mode 100644 index 00000000..5e87f28d --- /dev/null +++ b/feature/inquiry/src/main/java/com/bitgoeul/inquiry/viewmodel/InquiryViewModel.kt @@ -0,0 +1,10 @@ +package com.bitgoeul.inquiry.viewmodel + +import androidx.lifecycle.ViewModel +import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject + +@HiltViewModel +class InquiryViewModel @Inject constructor() : ViewModel() { + +} \ No newline at end of file From 252f4582c45c4a5f60c1f5106e8c63d35924fcb4 Mon Sep 17 00:00:00 2001 From: Chaejongin12 Date: Wed, 11 Sep 2024 10:24:51 +0900 Subject: [PATCH 052/141] =?UTF-8?q?=E2=9C=A8::=20InquiryScreen(=EB=AC=B8?= =?UTF-8?q?=EC=9D=98=20=EC=82=AC=ED=95=AD=20=ED=8E=98=EC=9D=B4=EC=A7=80)?= =?UTF-8?q?=20=EC=83=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/bitgoeul/inquiry/InquiryScreen.kt | 130 ++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 feature/inquiry/src/main/java/com/bitgoeul/inquiry/InquiryScreen.kt diff --git a/feature/inquiry/src/main/java/com/bitgoeul/inquiry/InquiryScreen.kt b/feature/inquiry/src/main/java/com/bitgoeul/inquiry/InquiryScreen.kt new file mode 100644 index 00000000..537d6770 --- /dev/null +++ b/feature/inquiry/src/main/java/com/bitgoeul/inquiry/InquiryScreen.kt @@ -0,0 +1,130 @@ +package com.bitgoeul.inquiry + +import androidx.compose.foundation.background +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.height +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.bitgoeul.inquiry.component.InquiryFilterButton +import com.bitgoeul.inquiry.component.InquiryList +import com.msg.design_system.component.topbar.GoBackTopBar +import com.msg.design_system.theme.BitgoeulAndroidTheme +import com.msg.design_system.R +import com.msg.design_system.component.dialog.FilterDialog +import com.msg.design_system.component.icon.GoBackIcon +import com.msg.design_system.component.icon.PlusIcon +import com.msg.design_system.component.textfield.TrailingIconTextField + +@Composable +fun InquiryRoute() { + val inquiryFilterList = remember { listOf("전체", "답변 된 문의사항만", "대기중인 문의사항만") } + + InquiryScreen( + onBackClicked = {}, + role = "", + inquiryFilterList = inquiryFilterList + ) +} + +@Composable +fun InquiryScreen( + modifier: Modifier = Modifier, + onBackClicked: () -> Unit, + inquiryFilterList: List, + role: String, +) { + val filterList = remember(inquiryFilterList) { inquiryFilterList } + val isFilterVisible = remember { mutableStateOf(false) } + + BitgoeulAndroidTheme { colors, typography -> + Column( + modifier = modifier + .fillMaxSize() + .background(color = colors.WHITE) + .padding(horizontal = 28.dp), + ) { + Spacer(modifier = modifier.height(20.dp)) + + GoBackTopBar( + icon = { GoBackIcon() }, + text = stringResource(id = R.string.go_back), + onClicked = onBackClicked + ) + + Spacer(modifier = modifier.height(8.dp)) + + Row( + modifier = modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = stringResource(id = R.string.inquiry), + style = typography.titleMedium, + color = colors.BLACK + ) + + Spacer(modifier = modifier.weight(1f)) + + if (role == "ROLE_STUDENT") { + PlusIcon( + modifier = modifier.padding(vertical = 4.dp) + ) + } + } + + Spacer(modifier = modifier.height(12.dp)) + + Row( + modifier = modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically + ) { + TrailingIconTextField( + modifier = modifier, + placeholder = stringResource(id = R.string.inquiry_search_placeholder), + onValueChange = {}, + isDisabled = false, + onButtonClicked = {} + ) + + Spacer(modifier = modifier.weight(1f)) + + InquiryFilterButton( + onClicked = { + isFilterVisible.value = true + } + ) + } + + Spacer(modifier = modifier.height(4.dp)) + + InquiryList() + } + + FilterDialog( + filterItemList = filterList, + isVisible = isFilterVisible.value, + onQuit = { isFilterVisible.value = false }, + onItemClicked = { + // 필터 클릭 처리 + } + ) + } +} + +@Preview +@Composable +fun InquiryScreenPre() { + InquiryRoute() +} \ No newline at end of file From de16bc51efbb41afd261d6d458460eea99f88179 Mon Sep 17 00:00:00 2001 From: Chaejongin12 Date: Wed, 11 Sep 2024 10:25:11 +0900 Subject: [PATCH 053/141] =?UTF-8?q?=E2=9C=A8::=20Navigation=20=EC=84=B8?= =?UTF-8?q?=ED=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/bitgoeul/inquiry/navigation/InquiryNavigation.kt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 feature/inquiry/src/main/java/com/bitgoeul/inquiry/navigation/InquiryNavigation.kt diff --git a/feature/inquiry/src/main/java/com/bitgoeul/inquiry/navigation/InquiryNavigation.kt b/feature/inquiry/src/main/java/com/bitgoeul/inquiry/navigation/InquiryNavigation.kt new file mode 100644 index 00000000..a8e03ff8 --- /dev/null +++ b/feature/inquiry/src/main/java/com/bitgoeul/inquiry/navigation/InquiryNavigation.kt @@ -0,0 +1,2 @@ +package com.bitgoeul.inquiry.navigation + From 27f864a84f25cca8c22b788846f42085594e7750 Mon Sep 17 00:00:00 2001 From: Chaejongin12 Date: Wed, 11 Sep 2024 10:25:32 +0900 Subject: [PATCH 054/141] =?UTF-8?q?=E2=9C=A8::=20InquiryList(=EB=AC=B8?= =?UTF-8?q?=EC=9D=98=20=EC=82=AC=ED=95=AD=20=EB=A6=AC=EC=8A=A4=ED=8A=B8)?= =?UTF-8?q?=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bitgoeul/inquiry/component/InquiryList.kt | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 feature/inquiry/src/main/java/com/bitgoeul/inquiry/component/InquiryList.kt diff --git a/feature/inquiry/src/main/java/com/bitgoeul/inquiry/component/InquiryList.kt b/feature/inquiry/src/main/java/com/bitgoeul/inquiry/component/InquiryList.kt new file mode 100644 index 00000000..5bafea82 --- /dev/null +++ b/feature/inquiry/src/main/java/com/bitgoeul/inquiry/component/InquiryList.kt @@ -0,0 +1,41 @@ +package com.bitgoeul.inquiry.component + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import com.msg.design_system.theme.BitgoeulAndroidTheme +import androidx.compose.ui.unit.dp + + +@Composable +fun InquiryList( + modifier: Modifier = Modifier, +) { + BitgoeulAndroidTheme { colors, typography -> + LazyColumn( + modifier = modifier + .background(color = colors.WHITE) + .fillMaxSize() + ) { + items(10) { + InquiryCard( + role = "ROLE_STUDENT", + answerStatus = true + ) + + Spacer(modifier = modifier.height(12.dp)) + } + } + } +} + +@Preview +@Composable +fun InquiryListPre() { + InquiryList() +} \ No newline at end of file From 31693667762b22ad0c49c0c69d6d2eecf1bf0476 Mon Sep 17 00:00:00 2001 From: Chaejongin12 Date: Wed, 11 Sep 2024 10:25:59 +0900 Subject: [PATCH 055/141] =?UTF-8?q?=E2=9C=A8::=20InquiryFilterButton(?= =?UTF-8?q?=EB=AC=B8=EC=9D=98=20=EC=82=AC=ED=95=AD=20=ED=95=84=ED=84=B0=20?= =?UTF-8?q?=EB=B2=84=ED=8A=BC)=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../inquiry/component/InquiryFilterButton.kt | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 feature/inquiry/src/main/java/com/bitgoeul/inquiry/component/InquiryFilterButton.kt diff --git a/feature/inquiry/src/main/java/com/bitgoeul/inquiry/component/InquiryFilterButton.kt b/feature/inquiry/src/main/java/com/bitgoeul/inquiry/component/InquiryFilterButton.kt new file mode 100644 index 00000000..c3e911cd --- /dev/null +++ b/feature/inquiry/src/main/java/com/bitgoeul/inquiry/component/InquiryFilterButton.kt @@ -0,0 +1,41 @@ +package com.bitgoeul.inquiry.component + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.msg.design_system.component.icon.G2ColorFilterIcon +import com.msg.design_system.theme.BitgoeulAndroidTheme + +@Composable +fun InquiryFilterButton( + modifier: Modifier = Modifier, + onClicked: () -> Unit, +) { + BitgoeulAndroidTheme { colors, _ -> + Box( + modifier = modifier + .clickable { + onClicked() + } + .border(shape = RoundedCornerShape(8.dp), border = BorderStroke(1.dp, color = colors.G2)) + .background(color = colors.WHITE) + .padding(horizontal = 10.dp, vertical = 15.dp), + ) { + G2ColorFilterIcon() + } + } +} + +@Preview +@Composable +fun InquiryFilterButtonPre() { + InquiryFilterButton {} +} \ No newline at end of file From ced61a815a40023fabdf4a5529ecccf4716e8eac Mon Sep 17 00:00:00 2001 From: Chaejongin12 Date: Wed, 11 Sep 2024 10:26:15 +0900 Subject: [PATCH 056/141] =?UTF-8?q?=E2=9C=A8::=20InquiryDetailScreen(?= =?UTF-8?q?=EB=AC=B8=EC=9D=98=20=EC=82=AC=ED=95=AD=20=EC=84=B8=EB=B6=80=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80)=20=EC=84=B8=ED=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/bitgoeul/inquiry/InquiryDetailScreen.kt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 feature/inquiry/src/main/java/com/bitgoeul/inquiry/InquiryDetailScreen.kt diff --git a/feature/inquiry/src/main/java/com/bitgoeul/inquiry/InquiryDetailScreen.kt b/feature/inquiry/src/main/java/com/bitgoeul/inquiry/InquiryDetailScreen.kt new file mode 100644 index 00000000..e16a0c76 --- /dev/null +++ b/feature/inquiry/src/main/java/com/bitgoeul/inquiry/InquiryDetailScreen.kt @@ -0,0 +1,2 @@ +package com.bitgoeul.inquiry + From b2cfe39e637d5b077a55368566c9f37467eff757 Mon Sep 17 00:00:00 2001 From: Chaejongin12 Date: Wed, 11 Sep 2024 10:26:29 +0900 Subject: [PATCH 057/141] =?UTF-8?q?=E2=9C=A8::=20InquiryCard(=EB=AC=B8?= =?UTF-8?q?=EC=9D=98=20=EC=82=AC=ED=95=AD=20=EC=95=84=EC=9D=B4=ED=85=9C)?= =?UTF-8?q?=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bitgoeul/inquiry/component/InquiryCard.kt | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 feature/inquiry/src/main/java/com/bitgoeul/inquiry/component/InquiryCard.kt diff --git a/feature/inquiry/src/main/java/com/bitgoeul/inquiry/component/InquiryCard.kt b/feature/inquiry/src/main/java/com/bitgoeul/inquiry/component/InquiryCard.kt new file mode 100644 index 00000000..86d531ea --- /dev/null +++ b/feature/inquiry/src/main/java/com/bitgoeul/inquiry/component/InquiryCard.kt @@ -0,0 +1,93 @@ +package com.bitgoeul.inquiry.component + +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.msg.design_system.component.tag.NegativeTag +import com.msg.design_system.R +import com.msg.design_system.component.tag.PositiveTag +import com.msg.design_system.theme.BitgoeulAndroidTheme + +@Composable +fun InquiryCard( + modifier: Modifier = Modifier, + role: String, + answerStatus: Boolean, +) { + BitgoeulAndroidTheme { colors, typography -> + Card( + modifier = modifier + .wrapContentSize() + .background(color = colors.WHITE, shape = RoundedCornerShape(8.dp)) + .border(width = 1.dp, color = colors.G1, shape = RoundedCornerShape(8.dp)) + .padding(16.dp), + colors = CardDefaults.cardColors(containerColor = colors.WHITE), + ) { + Text( + modifier = modifier.fillMaxWidth(), + text = "문의 사항 임시 문자열", + style = typography.bodyLarge, + color = colors.BLACK, + ) + + Text( + modifier = modifier.fillMaxWidth(), + text = "2023년 11월 11일", + style = typography.bodySmall, + color = colors.G1, + ) + + Text( + modifier = modifier.fillMaxWidth(), + text = "홍길동", + style = typography.bodySmall, + color = colors.G1, + ) + + Spacer(modifier = modifier.height(24.dp)) + + if (role == "ROLE_ADMIN") { + Row( + modifier = modifier.fillMaxWidth() + ) { + Spacer(modifier = modifier.weight(1f)) + + if (answerStatus) { + PositiveTag( + text = stringResource(id = R.string.answer_complete) + ) + } + + if (answerStatus) { + NegativeTag( + text = stringResource(id = R.string.waiting_for_answer) + ) + } + } + } + } + } +} + +@Preview +@Composable +fun InquiryCardPre() { + InquiryCard( + role = "ROLE_ADMIN", + answerStatus = true + ) +} \ No newline at end of file From bb415869a6b8af06ded10dc01c4298998149778c Mon Sep 17 00:00:00 2001 From: Chaejongin12 Date: Wed, 11 Sep 2024 10:26:48 +0900 Subject: [PATCH 058/141] =?UTF-8?q?=E2=99=BB=EF=B8=8F::=20=EC=9E=98?= =?UTF-8?q?=EB=AA=BB=20=EC=A7=80=EC=A0=95=EB=90=9C=20lineHeight=20?= =?UTF-8?q?=EC=88=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/msg/design_system/theme/Type.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/design-system/src/main/java/com/msg/design_system/theme/Type.kt b/core/design-system/src/main/java/com/msg/design_system/theme/Type.kt index b9a90b84..824cdb03 100644 --- a/core/design-system/src/main/java/com/msg/design_system/theme/Type.kt +++ b/core/design-system/src/main/java/com/msg/design_system/theme/Type.kt @@ -24,7 +24,7 @@ val Typography = Typography( fontFamily = pretendard, fontSize = 26.sp, fontWeight = FontWeight.SemiBold, - lineHeight = 31.sp + lineHeight = 32.sp ), titleSmall = TextStyle( fontFamily = pretendard, @@ -36,7 +36,7 @@ val Typography = Typography( fontFamily = pretendard, fontSize = 18.sp, fontWeight = FontWeight.SemiBold, - lineHeight = 25.sp + lineHeight = 26.sp ), bodyMedium = TextStyle( fontFamily = pretendard, From 6bb8a356036227a3df3ea6c807b4190c699d0d38 Mon Sep 17 00:00:00 2001 From: Chaejongin12 Date: Wed, 11 Sep 2024 10:27:29 +0900 Subject: [PATCH 059/141] =?UTF-8?q?=E2=99=BB=EF=B8=8F::=20BitGoeulCheckBox?= =?UTF-8?q?=20isChecked=20=EB=82=B4=EB=B6=80=20=EA=B4=80=EB=A6=AC=EB=A1=9C?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../design_system/component/checkbox/BitgoeulCheckBox.kt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/core/design-system/src/main/java/com/msg/design_system/component/checkbox/BitgoeulCheckBox.kt b/core/design-system/src/main/java/com/msg/design_system/component/checkbox/BitgoeulCheckBox.kt index de88e187..41520175 100644 --- a/core/design-system/src/main/java/com/msg/design_system/component/checkbox/BitgoeulCheckBox.kt +++ b/core/design-system/src/main/java/com/msg/design_system/component/checkbox/BitgoeulCheckBox.kt @@ -6,6 +6,8 @@ import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.runtime.Composable +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource @@ -15,20 +17,20 @@ import com.msg.design_system.R @Composable fun BitGoeulCheckBox( modifier: Modifier, - isChecked: Boolean, onCheckedChange: (Boolean) -> Unit, ) { + val isChecked = remember { mutableStateOf(false) } Box( modifier = modifier.background(color = Color.White, shape = RoundedCornerShape(8.dp)) ) { Image( - painter = if (isChecked) { + painter = if (isChecked.value) { painterResource(id = R.drawable.ic_checked_box) } else { painterResource(id = R.drawable.ic_unchecked_box) }, contentDescription = null, - modifier = modifier.clickable { onCheckedChange(!isChecked) } + modifier = modifier.clickable { onCheckedChange(!isChecked.value) } ) } } \ No newline at end of file From dc7f83178576b56ff7c9eccd44e2ac20766dce9f Mon Sep 17 00:00:00 2001 From: Chaejongin12 Date: Wed, 11 Sep 2024 10:28:07 +0900 Subject: [PATCH 060/141] =?UTF-8?q?=F0=9F=94=A5::=20LectureFilterBottomShe?= =?UTF-8?q?et(=EA=B0=95=EC=9D=98=20=ED=95=84=ED=84=B0=20=EB=B0=94=ED=85=80?= =?UTF-8?q?=EC=8B=9C=ED=8A=B8)=EB=A5=BC=20=EB=8D=94=EC=9D=B4=EC=83=81=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=ED=95=98=EC=A7=80=20=EC=95=8A=EA=B8=B0?= =?UTF-8?q?=EC=97=90=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bottomsheet/BitgoeulBottomSheet.kt | 120 ------------------ 1 file changed, 120 deletions(-) diff --git a/core/design-system/src/main/java/com/msg/design_system/component/bottomsheet/BitgoeulBottomSheet.kt b/core/design-system/src/main/java/com/msg/design_system/component/bottomsheet/BitgoeulBottomSheet.kt index b951e707..70979399 100644 --- a/core/design-system/src/main/java/com/msg/design_system/component/bottomsheet/BitgoeulBottomSheet.kt +++ b/core/design-system/src/main/java/com/msg/design_system/component/bottomsheet/BitgoeulBottomSheet.kt @@ -84,126 +84,6 @@ fun SelectorBottomSheet( } } -@Composable -@OptIn(ExperimentalMaterial3Api::class) -fun LectureFilterBottomSheet( - onQuit: () -> Unit, - isVisible: Boolean, -) { - val isChecked = remember { mutableStateListOf(false, false) } - - val bottomSheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true) - - if (isVisible) { - BitgoeulAndroidTheme { colors, type -> - ModalBottomSheet( - onDismissRequest = { - onQuit() - }, - sheetState = bottomSheetState - ) { - Column( - modifier = Modifier - .padding(horizontal = 28.dp) - ) { - Text( - text = stringResource(id = R.string.filter), - modifier = Modifier - .width(35.dp) - .height(26.dp), - color = colors.BLACK, - style = type.bodySmall, - fontSize = 20.sp - ) - - Spacer(modifier = Modifier.height(18.dp)) - - Text( - text = stringResource(id = R.string.lecture_category), - modifier = Modifier - .width(67.dp) - .height(26.dp), - color = colors.BLACK, - style = type.bodyLarge, - fontSize = 18.sp - ) - - Spacer(modifier = Modifier.height(8.dp)) - - Row( - modifier = Modifier - .wrapContentSize() - .padding(vertical = 8.dp, horizontal = 13.dp), - verticalAlignment = Alignment.CenterVertically - ) { - BitGoeulCheckBox( - isChecked = isChecked[0], - onCheckedChange = { isChecked[0] = it }, - modifier = Modifier - .width(24.dp) - .height(24.dp), - ) - - Spacer(modifier = Modifier.width(8.dp)) - - Text( - text = stringResource(id = R.string.mutual_credit_recognition_curriculum), - modifier = Modifier - .width(139.dp), - color = colors.BLACK, - style = type.bodySmall, - fontSize = 16.sp - ) - } - Row( - modifier = Modifier - .wrapContentSize() - .padding(vertical = 8.dp, horizontal = 13.dp), - verticalAlignment = Alignment.CenterVertically - ) { - BitGoeulCheckBox( - isChecked = isChecked[1], - onCheckedChange = { isChecked[1] = it }, - modifier = Modifier - .width(24.dp) - .height(24.dp), - ) - - Spacer(modifier = Modifier.width(8.dp)) - - Text( - text = stringResource(id = R.string.university_visit_program), - modifier = Modifier - .width(111.dp), - color = colors.BLACK, - style = type.bodySmall, - fontSize = 16.sp - ) - } - - Spacer(modifier = Modifier.height(16.dp)) - - BitgoeulButton( - text = stringResource(id = R.string.apply), - modifier = Modifier - .fillMaxWidth() - .height(52.dp), - state = ButtonState.Enable - ) { - // 클릭시 필터 적용 시키기 - } - - Box( - modifier = Modifier - .height(38.dp) - .fillMaxWidth() - ) - } - } - } - } -} - @Composable @OptIn(ExperimentalMaterial3Api::class) fun TimePickerBottomSheet( From 267cea6771ff85429da5db04b36a7b679be98b49 Mon Sep 17 00:00:00 2001 From: Chaejongin12 Date: Wed, 11 Sep 2024 11:59:15 +0900 Subject: [PATCH 061/141] =?UTF-8?q?:recycle:=20::=20BitGoeulCheckBox=20?= =?UTF-8?q?=EB=88=84=EB=9D=BD=EB=90=9C=20isChecked=20=EA=B0=92=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit :: BitGoeulCheckBox 누락된 isChecked 값 변경 로직 추가 --- .../msg/design_system/component/checkbox/BitgoeulCheckBox.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/design-system/src/main/java/com/msg/design_system/component/checkbox/BitgoeulCheckBox.kt b/core/design-system/src/main/java/com/msg/design_system/component/checkbox/BitgoeulCheckBox.kt index 41520175..dfc81ae7 100644 --- a/core/design-system/src/main/java/com/msg/design_system/component/checkbox/BitgoeulCheckBox.kt +++ b/core/design-system/src/main/java/com/msg/design_system/component/checkbox/BitgoeulCheckBox.kt @@ -30,7 +30,10 @@ fun BitGoeulCheckBox( painterResource(id = R.drawable.ic_unchecked_box) }, contentDescription = null, - modifier = modifier.clickable { onCheckedChange(!isChecked.value) } + modifier = modifier.clickable { + isChecked.value = !isChecked.value + onCheckedChange(!isChecked.value) + } ) } } \ No newline at end of file From ac790ddbbc4607307955b78b7f2ef1c54a2b53b1 Mon Sep 17 00:00:00 2001 From: Chaejongin12 Date: Wed, 11 Sep 2024 12:07:38 +0900 Subject: [PATCH 062/141] =?UTF-8?q?:recycle:=20::=20isChecked=EC=9D=98=20?= =?UTF-8?q?=EA=B0=92=EC=9D=84=20=EB=B0=94=EB=A1=9C=20=EB=B0=98=ED=99=98?= =?UTF-8?q?=ED=95=98=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit :: isChecked의 값을 바로 반환하도록 변경 --- .../msg/design_system/component/checkbox/BitgoeulCheckBox.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/design-system/src/main/java/com/msg/design_system/component/checkbox/BitgoeulCheckBox.kt b/core/design-system/src/main/java/com/msg/design_system/component/checkbox/BitgoeulCheckBox.kt index dfc81ae7..d209eeb3 100644 --- a/core/design-system/src/main/java/com/msg/design_system/component/checkbox/BitgoeulCheckBox.kt +++ b/core/design-system/src/main/java/com/msg/design_system/component/checkbox/BitgoeulCheckBox.kt @@ -32,7 +32,7 @@ fun BitGoeulCheckBox( contentDescription = null, modifier = modifier.clickable { isChecked.value = !isChecked.value - onCheckedChange(!isChecked.value) + onCheckedChange(isChecked.value) } ) } From d21f46b1c49dff6d797de3190fc36eceb20ea67e Mon Sep 17 00:00:00 2001 From: Chaejongin12 Date: Wed, 11 Sep 2024 13:37:08 +0900 Subject: [PATCH 063/141] =?UTF-8?q?:recycle:=20=20::=20=ED=98=B8=EC=9D=B4?= =?UTF-8?q?=EC=8A=A4=ED=8C=85=EC=9D=84=20=EC=9C=84=ED=95=9C=20Check=20?= =?UTF-8?q?=EC=83=81=ED=83=9C=EB=A5=BC=20=EC=99=B8=EB=B6=80=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EC=A3=BC=EC=9E=85=ED=95=98=EB=8A=94=20=ED=98=95?= =?UTF-8?q?=EC=8B=9D=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit :: 호이스팅을 위한 Check 상태를 외부에서 주입하는 형식으로 변경 --- .../component/checkbox/BitgoeulCheckBox.kt | 7 +++---- .../component/dialog/FilterDialog.kt | 9 ++++++--- .../com/bitgoeul/inquiry/InquiryScreen.kt | 19 ++++++++++++++----- .../com/msg/lecture/component/LectureCard.kt | 11 ++++++----- 4 files changed, 29 insertions(+), 17 deletions(-) diff --git a/core/design-system/src/main/java/com/msg/design_system/component/checkbox/BitgoeulCheckBox.kt b/core/design-system/src/main/java/com/msg/design_system/component/checkbox/BitgoeulCheckBox.kt index d209eeb3..ae753c2d 100644 --- a/core/design-system/src/main/java/com/msg/design_system/component/checkbox/BitgoeulCheckBox.kt +++ b/core/design-system/src/main/java/com/msg/design_system/component/checkbox/BitgoeulCheckBox.kt @@ -18,21 +18,20 @@ import com.msg.design_system.R fun BitGoeulCheckBox( modifier: Modifier, onCheckedChange: (Boolean) -> Unit, + isChecked: Boolean, ) { - val isChecked = remember { mutableStateOf(false) } Box( modifier = modifier.background(color = Color.White, shape = RoundedCornerShape(8.dp)) ) { Image( - painter = if (isChecked.value) { + painter = if (isChecked) { painterResource(id = R.drawable.ic_checked_box) } else { painterResource(id = R.drawable.ic_unchecked_box) }, contentDescription = null, modifier = modifier.clickable { - isChecked.value = !isChecked.value - onCheckedChange(isChecked.value) + onCheckedChange(!isChecked) } ) } diff --git a/core/design-system/src/main/java/com/msg/design_system/component/dialog/FilterDialog.kt b/core/design-system/src/main/java/com/msg/design_system/component/dialog/FilterDialog.kt index bc9a01e2..f28c7477 100644 --- a/core/design-system/src/main/java/com/msg/design_system/component/dialog/FilterDialog.kt +++ b/core/design-system/src/main/java/com/msg/design_system/component/dialog/FilterDialog.kt @@ -32,8 +32,9 @@ fun FilterDialog( modifier: Modifier = Modifier, filterItemList: List, isVisible: Boolean, + isChecked: List, onQuit: (Boolean) -> Unit, - onItemClicked: (String) -> Unit, + onFilterClicked: (Int) -> Unit, ) { if (isVisible) { BitgoeulAndroidTheme { colors, typography -> @@ -76,9 +77,10 @@ fun FilterDialog( verticalAlignment = Alignment.CenterVertically ) { BitGoeulCheckBox( + isChecked = isChecked[index], modifier = modifier.wrapContentSize(), onCheckedChange = { - onItemClicked(filterItemList[index]) + onFilterClicked(index) } ) @@ -102,7 +104,8 @@ fun FilterDialogPreview() { FilterDialog( filterItemList = listOf("학교선택", "학년선택", "학기선택"), isVisible = true, + isChecked = listOf(false), onQuit = {}, - onItemClicked = {} + onFilterClicked = {} ) } diff --git a/feature/inquiry/src/main/java/com/bitgoeul/inquiry/InquiryScreen.kt b/feature/inquiry/src/main/java/com/bitgoeul/inquiry/InquiryScreen.kt index 537d6770..61143bcc 100644 --- a/feature/inquiry/src/main/java/com/bitgoeul/inquiry/InquiryScreen.kt +++ b/feature/inquiry/src/main/java/com/bitgoeul/inquiry/InquiryScreen.kt @@ -10,8 +10,11 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource @@ -30,11 +33,16 @@ import com.msg.design_system.component.textfield.TrailingIconTextField @Composable fun InquiryRoute() { val inquiryFilterList = remember { listOf("전체", "답변 된 문의사항만", "대기중인 문의사항만") } + var isChecked by rememberSaveable { mutableStateOf(List(inquiryFilterList.size) { false }) } InquiryScreen( - onBackClicked = {}, role = "", - inquiryFilterList = inquiryFilterList + inquiryFilterList = inquiryFilterList, + isChecked = isChecked, + onBackClicked = {}, + onFilterClicked = { index -> + isChecked = isChecked.toMutableList().also { it[index] = !it[index] } + } ) } @@ -42,7 +50,9 @@ fun InquiryRoute() { fun InquiryScreen( modifier: Modifier = Modifier, onBackClicked: () -> Unit, + onFilterClicked: (Int) -> Unit, inquiryFilterList: List, + isChecked: List, role: String, ) { val filterList = remember(inquiryFilterList) { inquiryFilterList } @@ -115,10 +125,9 @@ fun InquiryScreen( FilterDialog( filterItemList = filterList, isVisible = isFilterVisible.value, + isChecked = isChecked, onQuit = { isFilterVisible.value = false }, - onItemClicked = { - // 필터 클릭 처리 - } + onFilterClicked = onFilterClicked // 추후 클릭 이벤트 처리 ) } } diff --git a/feature/lecture/src/main/java/com/msg/lecture/component/LectureCard.kt b/feature/lecture/src/main/java/com/msg/lecture/component/LectureCard.kt index 836cae9a..c5644996 100644 --- a/feature/lecture/src/main/java/com/msg/lecture/component/LectureCard.kt +++ b/feature/lecture/src/main/java/com/msg/lecture/component/LectureCard.kt @@ -187,11 +187,12 @@ fun LectureTakingStudentCard( ) { BitGoeulCheckBox( modifier = modifier, - isChecked = isComplete.value - ) { isCompleteValue -> - onChangeCompleteState(isCompleteValue, data.id) - isComplete.value = isCompleteValue - } + isChecked = isComplete.value, + onCheckedChange = { isCompleteValue -> + onChangeCompleteState(isCompleteValue, data.id) + isComplete.value = isCompleteValue + } + ) Spacer(modifier = modifier.width(24.dp)) From 2a3a3ff40ba897512a6969f8289ac568c5780c07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Wed, 11 Sep 2024 17:12:50 +0900 Subject: [PATCH 064/141] :green_heart: :: Changed Color Code Type --- .github/workflows/android.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 8e43f08f..66da514c 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -49,7 +49,7 @@ jobs: with: title: ✅ Bitgouel-Android-CI 성공! ✅ webhook: ${{ secrets.BITGOUEL_DISCORD_WEBHOOK }} - color: 00FF00 + color: 65280 - name: Bitgouel Android CI Discord Notification uses: sarisia/actions-status-discord@v1 @@ -57,4 +57,4 @@ jobs: with: title: ❗️ Bitgouel-Android-CI 실패! ❗️ webhook: ${{ secrets.BITGOUEL_DISCORD_WEBHOOK }} - color: FF0000 + color: 16711680 From 68b04b2a5c0e6c43c83c6f0a3207c60806ae0209 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Thu, 5 Sep 2024 20:07:06 +0900 Subject: [PATCH 065/141] :sparkles: :: Create asResult() Function(Use ViewModel - UiState) --- .../src/main/java/com/msg/common/result/Result.kt | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 core/common/src/main/java/com/msg/common/result/Result.kt diff --git a/core/common/src/main/java/com/msg/common/result/Result.kt b/core/common/src/main/java/com/msg/common/result/Result.kt new file mode 100644 index 00000000..346973bf --- /dev/null +++ b/core/common/src/main/java/com/msg/common/result/Result.kt @@ -0,0 +1,13 @@ +package com.msg.common.result + +import kotlinx.coroutines.flow.* + +sealed interface Result { + data class Success(val data: T): Result + data class Error(val exception: Throwable): Result + data object Loading: Result +} + +fun Flow.asResult(): Flow> = map> { Result.Success(it) } + .onStart { emit(Result.Loading) } + .catch { emit(Result.Error(it)) } \ No newline at end of file From a063cc4aabe0551cbcec5ff0eb877d9f3d0ac31a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Thu, 5 Sep 2024 20:09:10 +0900 Subject: [PATCH 066/141] :fire: :: Fire Unused Import --- .../main/java/com/msg/certification/AddCertificationScreen.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/feature/certification/src/main/java/com/msg/certification/AddCertificationScreen.kt b/feature/certification/src/main/java/com/msg/certification/AddCertificationScreen.kt index 12d83507..e6244ce1 100644 --- a/feature/certification/src/main/java/com/msg/certification/AddCertificationScreen.kt +++ b/feature/certification/src/main/java/com/msg/certification/AddCertificationScreen.kt @@ -9,7 +9,6 @@ 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.padding import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf From 5c429f571983b4707907b5a7a5bf4a69dc39ebbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Fri, 6 Sep 2024 10:16:38 +0900 Subject: [PATCH 067/141] :fire: :: Unused Code(File) --- .../GetCertificationListForStudentUseCase.kt | 12 ------------ .../GetCertificationListForTeacherUseCase.kt | 13 ------------- 2 files changed, 25 deletions(-) delete mode 100644 core/domain/src/main/java/com/msg/domain/usecase/certification/GetCertificationListForStudentUseCase.kt delete mode 100644 core/domain/src/main/java/com/msg/domain/usecase/certification/GetCertificationListForTeacherUseCase.kt diff --git a/core/domain/src/main/java/com/msg/domain/usecase/certification/GetCertificationListForStudentUseCase.kt b/core/domain/src/main/java/com/msg/domain/usecase/certification/GetCertificationListForStudentUseCase.kt deleted file mode 100644 index 38b520b8..00000000 --- a/core/domain/src/main/java/com/msg/domain/usecase/certification/GetCertificationListForStudentUseCase.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.msg.domain.usecase.certification - -import com.msg.data.repository.certification.CertificationRepository -import javax.inject.Inject - -class GetCertificationListForStudentUseCase @Inject constructor( - private val certificationRepository: CertificationRepository, -) { - suspend operator fun invoke() = runCatching { - certificationRepository.getCertificationListForStudent() - } -} \ No newline at end of file diff --git a/core/domain/src/main/java/com/msg/domain/usecase/certification/GetCertificationListForTeacherUseCase.kt b/core/domain/src/main/java/com/msg/domain/usecase/certification/GetCertificationListForTeacherUseCase.kt deleted file mode 100644 index 8f028a72..00000000 --- a/core/domain/src/main/java/com/msg/domain/usecase/certification/GetCertificationListForTeacherUseCase.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.msg.domain.usecase.certification - -import com.msg.data.repository.certification.CertificationRepository -import java.util.UUID -import javax.inject.Inject - -class GetCertificationListForTeacherUseCase @Inject constructor( - private val certificationRepository: CertificationRepository, -) { - suspend operator fun invoke(studentId: UUID) = runCatching { - certificationRepository.getCertificationListForTeacher(studentId = studentId) - } -} \ No newline at end of file From 79a55b0c275eef0ec6c6c37c324f93c6e0805d09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Fri, 6 Sep 2024 10:18:09 +0900 Subject: [PATCH 068/141] :recycle: :: Combine The Use Cases Into One --- .../GetCertificationListUseCase.kt | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 core/domain/src/main/java/com/msg/domain/usecase/certification/GetCertificationListUseCase.kt diff --git a/core/domain/src/main/java/com/msg/domain/usecase/certification/GetCertificationListUseCase.kt b/core/domain/src/main/java/com/msg/domain/usecase/certification/GetCertificationListUseCase.kt new file mode 100644 index 00000000..695267aa --- /dev/null +++ b/core/domain/src/main/java/com/msg/domain/usecase/certification/GetCertificationListUseCase.kt @@ -0,0 +1,18 @@ +package com.msg.domain.usecase.certification + +import com.msg.data.repository.certification.CertificationRepository +import com.msg.model.entity.certification.CertificationListEntity +import kotlinx.coroutines.flow.Flow +import java.util.UUID +import javax.inject.Inject + +class GetCertificationListUseCase @Inject constructor( + private val certificationRepository: CertificationRepository, +) { + operator fun invoke(role: String, studentId: UUID): Flow> { + return when (role) { + "ROLE_STUDENT" -> certificationRepository.getCertificationListForStudent() + else -> certificationRepository.getCertificationListForTeacher(studentId = studentId) + } + } +} \ No newline at end of file From 4b42ea2e4be304b74638a2e3bef90096dd0c5d60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Fri, 6 Sep 2024 10:18:41 +0900 Subject: [PATCH 069/141] :sparkles: :: Create GetCertificationListUiState --- .../viewmodel/uistate/GetCertificationListUiState.kt | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetCertificationListUiState.kt diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetCertificationListUiState.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetCertificationListUiState.kt new file mode 100644 index 00000000..63d22f6c --- /dev/null +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetCertificationListUiState.kt @@ -0,0 +1,10 @@ +package com.msg.certification.viewmodel.uistate + +import com.msg.model.entity.certification.CertificationListEntity + +sealed interface GetCertificationListUiState { + data class Success(val data: List): GetCertificationListUiState + data object Error: GetCertificationListUiState + data object Loading: GetCertificationListUiState + data object Empty: GetCertificationListUiState +} \ No newline at end of file From 2e86654322013442ccaace9682682916e244acea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Fri, 6 Sep 2024 10:19:12 +0900 Subject: [PATCH 070/141] :recycle: :: Simplify ViewModel Code And Apply UiState - getCertificationList Function --- .../viewmodel/CertificationViewModel.kt | 45 +++++++++---------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt index 268815d9..7fbed016 100644 --- a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt @@ -5,11 +5,14 @@ import androidx.compose.runtime.mutableStateOf import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.msg.certification.viewmodel.uistate.GetCertificationListUiState import com.msg.common.event.Event import com.msg.common.errorhandling.errorHandling +import com.msg.common.result.Result +import com.msg.common.result.asResult import com.msg.domain.usecase.auth.GetAuthorityUseCase import com.msg.domain.usecase.certification.* -import com.msg.domain.usecase.certification.GetCertificationListForTeacherUseCase +import com.msg.domain.usecase.certification.GetCertificationListUseCase import com.msg.domain.usecase.certification.WriteCertificationUseCase import com.msg.domain.usecase.club.GetStudentBelongClubUseCase import com.msg.domain.usecase.lecture.GetLectureSignUpHistoryUseCase @@ -18,16 +21,17 @@ import com.msg.model.entity.club.StudentBelongClubEntity import com.msg.model.entity.lecture.GetLectureSignUpHistoryEntity import com.msg.model.param.certification.WriteCertificationParam import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.catch +import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch import java.time.LocalDate import java.util.UUID import javax.inject.Inject class CertificationViewModel @Inject constructor( - private val getCertificationListForTeacherUseCase: GetCertificationListForTeacherUseCase, - private val getCertificationListForStudentUseCase: GetCertificationListForStudentUseCase, + private val getCertificationListUseCase: GetCertificationListUseCase, private val writeCertificationUseCase: WriteCertificationUseCase, private val editCertificationUseCase: EditCertificationUseCase, private val getStudentBelongClubUseCase: GetStudentBelongClubUseCase, @@ -41,6 +45,9 @@ class CertificationViewModel @Inject constructor( private val role = getRole().toString() + private val _getCertificationListUiState = MutableStateFlow(GetCertificationListUiState.Loading) + val getCertificationListUiState: StateFlow = _getCertificationListUiState.asStateFlow() + private val _getCertificationListResponse = MutableStateFlow>>( Event.Loading) val getCertificationListResponse = _getCertificationListResponse.asStateFlow() @@ -91,29 +98,21 @@ class CertificationViewModel @Inject constructor( private set internal fun getCertificationList() = viewModelScope.launch { - if (role == "ROLE_STUDENT") { - getCertificationListForStudentUseCase().onSuccess { - it.catch { remoteError -> - _getCertificationListResponse.value = remoteError.errorHandling() - }.collect { response -> - _getCertificationListResponse.value = Event.Success(data = response) - } - }.onFailure { error -> - _getCertificationListResponse.value = error.errorHandling() - } - } else { - if (studentId != null) { - getCertificationListForTeacherUseCase(studentId).onSuccess { - it.catch { remoteError -> - _getCertificationListResponse.value = remoteError.errorHandling() - }.collect { response -> - _getCertificationListResponse.value = Event.Success(data = response) + getCertificationListUseCase(role = role, studentId = studentId) + .asResult() + .collectLatest { result -> + when(result) { + is Result.Loading -> { _getCertificationListUiState.value = GetCertificationListUiState.Loading } + is Result.Success -> { + if (result.data.isEmpty()) { + _getCertificationListUiState.value = GetCertificationListUiState.Empty + } else { + _getCertificationListUiState.value = GetCertificationListUiState.Success(result.data) + } } - }.onFailure { error -> - _getCertificationListResponse.value = error.errorHandling() + is Result.Error -> { _getCertificationListUiState.value = GetCertificationListUiState.Error } } } - } } internal fun writeCertification( From 77c19cdd5afee25305ed580cbc0eede2400dd9c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Fri, 6 Sep 2024 10:19:39 +0900 Subject: [PATCH 071/141] :recycle: :: Apply ViewModel Changed(Apply UiState) --- .../msg/certification/CertificationScreen.kt | 60 ++++++++++++++++--- 1 file changed, 51 insertions(+), 9 deletions(-) diff --git a/feature/certification/src/main/java/com/msg/certification/CertificationScreen.kt b/feature/certification/src/main/java/com/msg/certification/CertificationScreen.kt index a6d2f7da..cd8ef4f8 100644 --- a/feature/certification/src/main/java/com/msg/certification/CertificationScreen.kt +++ b/feature/certification/src/main/java/com/msg/certification/CertificationScreen.kt @@ -11,22 +11,26 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.IconButton import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.msg.certification.component.CertificationSection import com.msg.certification.component.FinishedLectureSection import com.msg.certification.component.StudentInfoSection import com.msg.common.event.Event import com.msg.certification.viewmodel.CertificationViewModel +import com.msg.certification.viewmodel.uistate.GetCertificationListUiState import com.msg.design_system.R import com.msg.design_system.component.icon.HumanIcon import com.msg.design_system.theme.BitgoeulAndroidTheme @@ -44,6 +48,8 @@ internal fun CertificationScreenRoute( onHumanIconClicked: () -> Unit, onEditClicked: () -> Unit ) { + val getCertificationListUiState by viewModel.getCertificationListUiState.collectAsStateWithLifecycle() + viewModel.getCertificationList() viewModel.getStudentBelong() viewModel.getLectureSignUpHistory() @@ -83,7 +89,8 @@ internal fun CertificationScreenRoute( onPlusClicked = onEditClicked, studentData = viewModel.studentData.value, certificationData = viewModel.certificationList, - lectureData = viewModel.lectureData.value + lectureData = viewModel.lectureData.value, + getCertificationListUiState = getCertificationListUiState ) } @@ -135,6 +142,7 @@ private suspend fun getLectureData( @Composable internal fun CertificationScreen( modifier: Modifier = Modifier, + getCertificationListUiState: GetCertificationListUiState, onHumanIconClicked: () -> Unit, onEditClicked: (id: UUID, title: String, date: LocalDate) -> Unit, onPlusClicked: () -> Unit, @@ -179,13 +187,46 @@ internal fun CertificationScreen( color = colors.G9 ) Spacer(modifier = modifier.height(24.dp)) - CertificationSection( - onPlusClicked = onPlusClicked, - onEditClicked = { id, title, date -> - onEditClicked(id, title, date) - }, - data = certificationData - ) + when(getCertificationListUiState) { + is GetCertificationListUiState.Success -> { + CertificationSection( + onPlusClicked = onPlusClicked, + onEditClicked = { id, title, date -> + onEditClicked(id, title, date) + }, + data = certificationData + ) + } + + is GetCertificationListUiState.Loading -> { + Box( + modifier = modifier.fillMaxWidth(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator( + modifier = modifier.then(Modifier.size(27.dp)), + color = colors.G2, + strokeWidth = 2.dp + ) + } + } + + is GetCertificationListUiState.Error -> { + Text( + modifier = modifier.align(Alignment.CenterHorizontally), + text = "통신이 원활하지 않습니다..", + style = typography.titleSmall + ) + } + + is GetCertificationListUiState.Empty -> { + Text( + modifier = modifier.align(Alignment.CenterHorizontally), + text = "자격증이 없습니다..", + style = typography.titleSmall + ) + } + } Spacer(modifier = modifier.height(12.dp)) FinishedLectureSection(data = lectureData) } @@ -232,6 +273,7 @@ fun CertificationScreenPre() { isComplete = true ) ) - ) + ), + getCertificationListUiState = GetCertificationListUiState.Loading ) } \ No newline at end of file From 2edae1b1d02eade80e1318b367a4a182a514985e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Fri, 6 Sep 2024 10:22:09 +0900 Subject: [PATCH 072/141] :fire: :: Line Spacing --- .../msg/certification/viewmodel/CertificationViewModel.kt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt index 7fbed016..df5c6c45 100644 --- a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt @@ -48,8 +48,7 @@ class CertificationViewModel @Inject constructor( private val _getCertificationListUiState = MutableStateFlow(GetCertificationListUiState.Loading) val getCertificationListUiState: StateFlow = _getCertificationListUiState.asStateFlow() - private val _getCertificationListResponse = MutableStateFlow>>( - Event.Loading) + private val _getCertificationListResponse = MutableStateFlow>>(Event.Loading) val getCertificationListResponse = _getCertificationListResponse.asStateFlow() private val _writeCertificationResponse = MutableStateFlow>(Event.Loading) @@ -61,8 +60,7 @@ class CertificationViewModel @Inject constructor( private val _getStudentBelongResponse = MutableStateFlow>(Event.Loading) val getStudentBelongResponse = _getStudentBelongResponse.asStateFlow() - private val _getLectureSignUpHistoryResponse = MutableStateFlow>( - Event.Loading) + private val _getLectureSignUpHistoryResponse = MutableStateFlow>(Event.Loading) val getLectureSignUpHistoryResponse = _getLectureSignUpHistoryResponse.asStateFlow() private val studentId = UUID.fromString(savedStateHandle.get("studentId")) From 84d8052374ce32e8032c69f257f4233e39dcc080 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 11:41:35 +0900 Subject: [PATCH 073/141] :memo: :: Modify Use Flow And Fire Unused Code --- .../domain/usecase/lecture/GetLectureSignUpHistoryUseCase.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/domain/src/main/java/com/msg/domain/usecase/lecture/GetLectureSignUpHistoryUseCase.kt b/core/domain/src/main/java/com/msg/domain/usecase/lecture/GetLectureSignUpHistoryUseCase.kt index 93454000..5db48700 100644 --- a/core/domain/src/main/java/com/msg/domain/usecase/lecture/GetLectureSignUpHistoryUseCase.kt +++ b/core/domain/src/main/java/com/msg/domain/usecase/lecture/GetLectureSignUpHistoryUseCase.kt @@ -1,13 +1,14 @@ package com.msg.domain.usecase.lecture import com.msg.data.repository.lecture.LectureRepository +import com.msg.model.entity.lecture.GetLectureSignUpHistoryEntity +import kotlinx.coroutines.flow.Flow import java.util.UUID import javax.inject.Inject class GetLectureSignUpHistoryUseCase @Inject constructor( private val lectureRepository: LectureRepository ) { - suspend operator fun invoke(studentId: UUID) = runCatching { + operator fun invoke(studentId: UUID): Flow = lectureRepository.getLectureSignUpHistory(studentId = studentId) - } } \ No newline at end of file From e664c93c3a322193f63835ecb61005d778964f70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 11:42:02 +0900 Subject: [PATCH 074/141] :sparkles: :: Create GetLectureSignUpHistoryUiState --- .../viewmodel/uistate/GetLectureSignUpHistoryUiState.kt | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetLectureSignUpHistoryUiState.kt diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetLectureSignUpHistoryUiState.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetLectureSignUpHistoryUiState.kt new file mode 100644 index 00000000..e82ac2c5 --- /dev/null +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetLectureSignUpHistoryUiState.kt @@ -0,0 +1,9 @@ +package com.msg.certification.viewmodel.uistate + +import com.msg.model.entity.lecture.GetLectureSignUpHistoryEntity + +sealed interface GetLectureSignUpHistoryUiState { + data class Success(val data: GetLectureSignUpHistoryEntity): GetLectureSignUpHistoryUiState + data object Loading: GetLectureSignUpHistoryUiState + data object Error: GetLectureSignUpHistoryUiState +} \ No newline at end of file From 40b56a1484a33b4372e61cbc63c7c6fa588a5a79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 15:58:10 +0900 Subject: [PATCH 075/141] :recycle: :: Changed TextStyle And Color && Apply UiState To Screen --- .../msg/certification/CertificationScreen.kt | 38 ++++++++++++++++--- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/feature/certification/src/main/java/com/msg/certification/CertificationScreen.kt b/feature/certification/src/main/java/com/msg/certification/CertificationScreen.kt index cd8ef4f8..90134785 100644 --- a/feature/certification/src/main/java/com/msg/certification/CertificationScreen.kt +++ b/feature/certification/src/main/java/com/msg/certification/CertificationScreen.kt @@ -31,6 +31,7 @@ import com.msg.certification.component.StudentInfoSection import com.msg.common.event.Event import com.msg.certification.viewmodel.CertificationViewModel import com.msg.certification.viewmodel.uistate.GetCertificationListUiState +import com.msg.certification.viewmodel.uistate.GetLectureSignUpHistoryUiState import com.msg.design_system.R import com.msg.design_system.component.icon.HumanIcon import com.msg.design_system.theme.BitgoeulAndroidTheme @@ -49,6 +50,7 @@ internal fun CertificationScreenRoute( onEditClicked: () -> Unit ) { val getCertificationListUiState by viewModel.getCertificationListUiState.collectAsStateWithLifecycle() + val getLectureSignUpHistoryUiState by viewModel.getLectureSignUpHistoryUiState.collectAsStateWithLifecycle() viewModel.getCertificationList() viewModel.getStudentBelong() @@ -90,7 +92,8 @@ internal fun CertificationScreenRoute( studentData = viewModel.studentData.value, certificationData = viewModel.certificationList, lectureData = viewModel.lectureData.value, - getCertificationListUiState = getCertificationListUiState + getCertificationListUiState = getCertificationListUiState, + getLectureSignUpHistoryUiState = getLectureSignUpHistoryUiState ) } @@ -143,6 +146,7 @@ private suspend fun getLectureData( internal fun CertificationScreen( modifier: Modifier = Modifier, getCertificationListUiState: GetCertificationListUiState, + getLectureSignUpHistoryUiState: GetLectureSignUpHistoryUiState, onHumanIconClicked: () -> Unit, onEditClicked: (id: UUID, title: String, date: LocalDate) -> Unit, onPlusClicked: () -> Unit, @@ -215,7 +219,7 @@ internal fun CertificationScreen( Text( modifier = modifier.align(Alignment.CenterHorizontally), text = "통신이 원활하지 않습니다..", - style = typography.titleSmall + style = typography.bodySmall ) } @@ -223,12 +227,35 @@ internal fun CertificationScreen( Text( modifier = modifier.align(Alignment.CenterHorizontally), text = "자격증이 없습니다..", - style = typography.titleSmall + style = typography.bodySmall, + color = colors.G4 ) } } Spacer(modifier = modifier.height(12.dp)) - FinishedLectureSection(data = lectureData) + when(getLectureSignUpHistoryUiState) { + is GetLectureSignUpHistoryUiState.Success -> { FinishedLectureSection(data = lectureData) } + is GetLectureSignUpHistoryUiState.Loading -> { + Box( + modifier = modifier.fillMaxWidth(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator( + modifier = modifier.then(Modifier.size(27.dp)), + color = colors.G2, + strokeWidth = 2.dp + ) + } + } + is GetLectureSignUpHistoryUiState.Error -> { + Text( + modifier = modifier.align(Alignment.CenterHorizontally).padding(top = 50.dp), + text = "통신이 원할하지 않습니다..", + style = typography.bodySmall, + color = colors.G4 + ) + } + } } } } @@ -274,6 +301,7 @@ fun CertificationScreenPre() { ) ) ), - getCertificationListUiState = GetCertificationListUiState.Loading + getCertificationListUiState = GetCertificationListUiState.Empty, + getLectureSignUpHistoryUiState = GetLectureSignUpHistoryUiState.Error ) } \ No newline at end of file From 407d9cb0c78c0bd18b40cbfc97202c197d486c1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 15:58:52 +0900 Subject: [PATCH 076/141] :recycle: :: Apply UiState To CertificationViewModel(getLectureSignUpHistory) --- .../viewmodel/CertificationViewModel.kt | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt index df5c6c45..ffbce139 100644 --- a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt @@ -6,6 +6,7 @@ import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.msg.certification.viewmodel.uistate.GetCertificationListUiState +import com.msg.certification.viewmodel.uistate.GetLectureSignUpHistoryUiState import com.msg.common.event.Event import com.msg.common.errorhandling.errorHandling import com.msg.common.result.Result @@ -48,6 +49,9 @@ class CertificationViewModel @Inject constructor( private val _getCertificationListUiState = MutableStateFlow(GetCertificationListUiState.Loading) val getCertificationListUiState: StateFlow = _getCertificationListUiState.asStateFlow() + private val _getLectureSignUpHistoryUiState = MutableStateFlow(GetLectureSignUpHistoryUiState.Loading) + val getLectureSignUpHistoryUiState: StateFlow = _getLectureSignUpHistoryUiState.asStateFlow() + private val _getCertificationListResponse = MutableStateFlow>>(Event.Loading) val getCertificationListResponse = _getCertificationListResponse.asStateFlow() @@ -173,17 +177,15 @@ class CertificationViewModel @Inject constructor( internal fun getLectureSignUpHistory() = viewModelScope.launch { if (studentId != null) { - getLectureSignUpHistoryUseCase( - studentId = studentId - ).onSuccess { - it.catch { remoteError -> - _getLectureSignUpHistoryResponse.value = remoteError.errorHandling() - }.collect { response -> - _getLectureSignUpHistoryResponse.value = Event.Success(data = response) + getLectureSignUpHistoryUseCase(studentId = studentId) + .asResult() + .collectLatest { result -> + when(result) { + is Result.Loading -> { _getLectureSignUpHistoryUiState.value = GetLectureSignUpHistoryUiState.Loading } + is Result.Success -> { _getLectureSignUpHistoryUiState.value = GetLectureSignUpHistoryUiState.Success(result.data) } + is Result.Error -> { _getLectureSignUpHistoryUiState.value = GetLectureSignUpHistoryUiState.Error } + } } - }.onFailure { error -> - _getLectureSignUpHistoryResponse.value = error.errorHandling() - } } } From 6b02c9f1ea4c8276febb875a39bd8d0b58b23e4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 16:19:04 +0900 Subject: [PATCH 077/141] :recycle: :: Use Flow To WriteCertificationUseCase --- .../domain/usecase/certification/WriteCertificationUseCase.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/domain/src/main/java/com/msg/domain/usecase/certification/WriteCertificationUseCase.kt b/core/domain/src/main/java/com/msg/domain/usecase/certification/WriteCertificationUseCase.kt index ddd3e643..93db9a6b 100644 --- a/core/domain/src/main/java/com/msg/domain/usecase/certification/WriteCertificationUseCase.kt +++ b/core/domain/src/main/java/com/msg/domain/usecase/certification/WriteCertificationUseCase.kt @@ -2,12 +2,12 @@ package com.msg.domain.usecase.certification import com.msg.data.repository.certification.CertificationRepository import com.msg.model.param.certification.WriteCertificationParam +import kotlinx.coroutines.flow.Flow import javax.inject.Inject class WriteCertificationUseCase @Inject constructor( private val certificationRepository: CertificationRepository ) { - suspend operator fun invoke(body: WriteCertificationParam) = runCatching { + operator fun invoke(body: WriteCertificationParam): Flow = certificationRepository.writeCertification(body = body) - } } \ No newline at end of file From 81d7dd25f6f8c368751c6b3c7c8431f648777313 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 16:19:26 +0900 Subject: [PATCH 078/141] :sparkles: :: Create WriteCertificationUiState --- .../viewmodel/uistate/WriteCertificationUiState.kt | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/WriteCertificationUiState.kt diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/WriteCertificationUiState.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/WriteCertificationUiState.kt new file mode 100644 index 00000000..ff0a3391 --- /dev/null +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/WriteCertificationUiState.kt @@ -0,0 +1,7 @@ +package com.msg.certification.viewmodel.uistate + +sealed interface WriteCertificationUiState { + data object Success: WriteCertificationUiState + data object Loading: WriteCertificationUiState + data class Error(val exception: Throwable): WriteCertificationUiState +} \ No newline at end of file From 44225c47575616437a4ddb6e0c865c8b8ba399f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 16:19:56 +0900 Subject: [PATCH 079/141] :recycle: :: Apply WriteCertificationUiState To CertificationViewModel --- .../viewmodel/CertificationViewModel.kt | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt index ffbce139..5a7bf44d 100644 --- a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt @@ -7,6 +7,7 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.msg.certification.viewmodel.uistate.GetCertificationListUiState import com.msg.certification.viewmodel.uistate.GetLectureSignUpHistoryUiState +import com.msg.certification.viewmodel.uistate.WriteCertificationUiState import com.msg.common.event.Event import com.msg.common.errorhandling.errorHandling import com.msg.common.result.Result @@ -52,6 +53,9 @@ class CertificationViewModel @Inject constructor( private val _getLectureSignUpHistoryUiState = MutableStateFlow(GetLectureSignUpHistoryUiState.Loading) val getLectureSignUpHistoryUiState: StateFlow = _getLectureSignUpHistoryUiState.asStateFlow() + private val _writeCertificationUiState = MutableStateFlow(WriteCertificationUiState.Loading) + val writeCertificationUiState: StateFlow = _writeCertificationUiState.asStateFlow() + private val _getCertificationListResponse = MutableStateFlow>>(Event.Loading) val getCertificationListResponse = _getCertificationListResponse.asStateFlow() @@ -126,15 +130,15 @@ class CertificationViewModel @Inject constructor( name = name, acquisitionDate = acquisitionDate ) - ).onSuccess { - it.catch { remoteError -> - _writeCertificationResponse.value = remoteError.errorHandling() - }.collect { - _writeCertificationResponse.value = Event.Success() + ) + .asResult() + .collectLatest { result -> + when(result) { + is Result.Loading -> { _writeCertificationUiState.value = WriteCertificationUiState.Loading } + is Result.Success -> { _writeCertificationUiState.value = WriteCertificationUiState.Success } + is Result.Error -> { _writeCertificationUiState.value = WriteCertificationUiState.Error(result.exception) } + } } - }.onFailure { error -> - _writeCertificationResponse.value = error.errorHandling() - } } internal fun editCertification( From 8cc0ea89715c53beb3bb6f873734ce3ffb6a90b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 22:51:20 +0900 Subject: [PATCH 080/141] :memo: :: Add strings.xml To Other Strings --- .../src/main/res/values/strings.xml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/core/design-system/src/main/res/values/strings.xml b/core/design-system/src/main/res/values/strings.xml index d5873fd5..e80ed91c 100644 --- a/core/design-system/src/main/res/values/strings.xml +++ b/core/design-system/src/main/res/values/strings.xml @@ -84,6 +84,22 @@ 이름으로 검색... 전체 학생정보 + \'뒤로\'버튼 한번 더 누르시면 종료됩니다. + 학생회 권한인 학생만 요청 가능해요 + 서버 응답이 지연되고 있습니다, 잠시 후 다시 시도해주세요 + 서버 에러, 관리자에게 문의하세요 + 네트워크가 불안정합니다, 데이터나 와이파이 연결 상태를 확인해주세요 + 알 수 없는 오류가 발생했습니다 + 예상치 못한 오류가 발생했습니다 + 오류가 발생했습니다 + 자격증 등록을 완료되었습니다. + 자격증 등록을 실패하였습니다. + 자격증 수정을 완료하였습니다. + 자격증 수정을 실패하였습니다. + 학생정보를 불러오지 못했습니다. + 자격증 정보를 불러오지 못했습니다. + 데이터가 없습니다. + 강의 정보를 불러오지 못했습니다. 문의사항 답변 됨 답변 대기 중 From bbfca6b52135e2fa88f3b9d4a9b1bb692aa9c8fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 22:53:06 +0900 Subject: [PATCH 081/141] :heavy_plus_sign: :: Add Implementation To build.gradle.kts(:app) --- app/build.gradle.kts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 92a0641a..b41372ea 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -15,6 +15,8 @@ android { } dependencies { + implementation(project(":core:ui")) + implementation(project(":core:common")) implementation(project(":core:design-system")) implementation(project(":feature:login")) implementation(project(":feature:sign-up")) From df8d6fa6acb2c097eb506073ebe2d26c2754f836 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 22:54:00 +0900 Subject: [PATCH 082/141] :sparkles: :: Create errorToast(BitgoeulNavHost) --- .../navigation/BitgoeulNavHost.kt | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/msg/bitgoeul_android/navigation/BitgoeulNavHost.kt b/app/src/main/java/com/msg/bitgoeul_android/navigation/BitgoeulNavHost.kt index 13353029..f4dee234 100644 --- a/app/src/main/java/com/msg/bitgoeul_android/navigation/BitgoeulNavHost.kt +++ b/app/src/main/java/com/msg/bitgoeul_android/navigation/BitgoeulNavHost.kt @@ -2,6 +2,7 @@ package com.msg.bitgoeul_android.navigation import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext import androidx.navigation.compose.NavHost import com.bitgoeul.email.navigation.emailSendInformScreen import com.bitgoeul.email.navigation.inputEmailScreen @@ -18,6 +19,7 @@ import com.example.my_page.navigation.changePasswordScreen import com.example.my_page.navigation.myPageScreen import com.example.my_page.navigation.navigateToMyPage import com.example.my_page.navigation.navigateToPasswordChange +import com.msg.design_system.R import com.msg.bitgoeul_android.ui.BitgoeulAppState import com.msg.bitgoeul_android.ui.navigateWithPopUpToLogin import com.msg.certification.navigation.addCertificationScreen @@ -26,6 +28,12 @@ import com.msg.certification.navigation.navigateToAddCertificationPage import com.msg.club.navigation.clubDetailScreen import com.msg.club.navigation.clubScreen import com.msg.club.navigation.navigateToClubDetailPage +import com.msg.common.exception.ForBiddenException +import com.msg.common.exception.NetworkException +import com.msg.common.exception.OtherException +import com.msg.common.exception.ServerException +import com.msg.common.exception.TimeOutException +import com.msg.common.exception.UnknownException import com.msg.lecture.navigation.lectureDetailScreen import com.msg.lecture.navigation.lectureListScreen import com.msg.lecture.navigation.lectureTakingStudentListScreen @@ -46,6 +54,7 @@ import com.msg.student_activity.navigation.studentActivityScreen import com.msg.student_activity.navigation.studentAddActivityScreen import com.msg.student_activity.navigation.studentDetailActivityScreen import com.msg.student_activity.navigation.studentDetailSettingActivityScreen +import com.msg.ui.makeToast @Composable fun BitgoeulNavHost( @@ -53,7 +62,24 @@ fun BitgoeulNavHost( modifier: Modifier = Modifier, startDestination: String = loginRoute, ) { + val context = LocalContext.current val navController = appState.navController + + val createErrorToast: (throwable: Throwable?, message: Int?) -> Unit = { throwable, message -> + val errorMessage = throwable?.let { + when(it) { + is ForBiddenException -> R.string.error_for_bidden + is TimeOutException -> R.string.error_time_out + is ServerException -> R.string.error_server + is NetworkException -> R.string.error_no_internet + is OtherException -> R.string.error_other_http + is UnknownException -> R.string.error_un_known + else -> message + } + } ?: message ?: R.string.error_default + makeToast(context, context.getString(errorMessage)) + } + NavHost( navController = navController, startDestination = startDestination, @@ -139,7 +165,8 @@ fun BitgoeulNavHost( ) certificationScreen( onHumanClicked = navController::navigateToMyPage, - onEditClicked = navController::navigateToAddCertificationPage + onEditClicked = navController::navigateToAddCertificationPage, + createErrorToast = createErrorToast ) addCertificationScreen( onBackClicked = navController::navigateUp From c85cefa7b4dba6db33cd0d748949e3cda5d46aa2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 22:55:23 +0900 Subject: [PATCH 083/141] :recycle: :: Use Coroutine Flow - EditCertificationUseCase --- .../domain/usecase/certification/EditCertificationUseCase.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/domain/src/main/java/com/msg/domain/usecase/certification/EditCertificationUseCase.kt b/core/domain/src/main/java/com/msg/domain/usecase/certification/EditCertificationUseCase.kt index 41cc0676..f2a54eb7 100644 --- a/core/domain/src/main/java/com/msg/domain/usecase/certification/EditCertificationUseCase.kt +++ b/core/domain/src/main/java/com/msg/domain/usecase/certification/EditCertificationUseCase.kt @@ -2,13 +2,13 @@ package com.msg.domain.usecase.certification import com.msg.data.repository.certification.CertificationRepository import com.msg.model.param.certification.WriteCertificationParam +import kotlinx.coroutines.flow.Flow import java.util.UUID import javax.inject.Inject class EditCertificationUseCase @Inject constructor( private val certificationRepository: CertificationRepository ) { - suspend operator fun invoke(id: UUID, body: WriteCertificationParam) = runCatching { + operator fun invoke(id: UUID, body: WriteCertificationParam): Flow = certificationRepository.editCertification(id = id, body = body) - } } \ No newline at end of file From aada79578c283c01650e85216b7b8b97d2440b81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 22:55:55 +0900 Subject: [PATCH 084/141] :recycle: :: Use Coroutine Flow(GetStudentBelongClubUseCase) --- .../msg/domain/usecase/club/GetStudentBelongClubUseCase.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/domain/src/main/java/com/msg/domain/usecase/club/GetStudentBelongClubUseCase.kt b/core/domain/src/main/java/com/msg/domain/usecase/club/GetStudentBelongClubUseCase.kt index e7bbdc6a..5d8fd5ab 100644 --- a/core/domain/src/main/java/com/msg/domain/usecase/club/GetStudentBelongClubUseCase.kt +++ b/core/domain/src/main/java/com/msg/domain/usecase/club/GetStudentBelongClubUseCase.kt @@ -1,13 +1,14 @@ package com.msg.domain.usecase.club import com.msg.data.repository.club.ClubRepository +import com.msg.model.entity.club.StudentBelongClubEntity +import kotlinx.coroutines.flow.Flow import java.util.UUID import javax.inject.Inject class GetStudentBelongClubUseCase @Inject constructor( private val clubRepository: ClubRepository ) { - suspend operator fun invoke(id: Long, studentId: UUID) = runCatching { + operator fun invoke(id: Long, studentId: UUID): Flow = clubRepository.getStudentBelongClubDetail(id = id, studentId = studentId) - } } \ No newline at end of file From e234735deceaf94b4296decc2216fb1f5a7eccbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 22:56:44 +0900 Subject: [PATCH 085/141] :fire: :: Fire Unused Import --- feature/login/src/main/java/com/bitgoeul/login/LoginScreen.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/feature/login/src/main/java/com/bitgoeul/login/LoginScreen.kt b/feature/login/src/main/java/com/bitgoeul/login/LoginScreen.kt index 61a59169..06cad962 100644 --- a/feature/login/src/main/java/com/bitgoeul/login/LoginScreen.kt +++ b/feature/login/src/main/java/com/bitgoeul/login/LoginScreen.kt @@ -16,7 +16,6 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Alignment From 7560dc8c60d2f3874eab86e41f0a350daeebde3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 22:57:18 +0900 Subject: [PATCH 086/141] :sparkles: :: Create GetStudentBelongClubDetailUiState --- .../uistate/GetStudentBelongClubDetailUiState.kt | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetStudentBelongClubDetailUiState.kt diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetStudentBelongClubDetailUiState.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetStudentBelongClubDetailUiState.kt new file mode 100644 index 00000000..3bbf4801 --- /dev/null +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetStudentBelongClubDetailUiState.kt @@ -0,0 +1,10 @@ +package com.msg.certification.viewmodel.uistate + +import android.content.Context +import com.msg.model.entity.club.StudentBelongClubEntity + +sealed interface GetStudentBelongClubDetailUiState { + data class Success(val data: StudentBelongClubEntity): GetStudentBelongClubDetailUiState + data object Loading: GetStudentBelongClubDetailUiState + data class Error(val expectation: Throwable): GetStudentBelongClubDetailUiState +} \ No newline at end of file From 00c73c116f7b3b790dbda26e719cbcf96d7e1b50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 22:57:35 +0900 Subject: [PATCH 087/141] :sparkles: :: Create EditCertificationUiState --- .../viewmodel/uistate/EditCertificationUiState.kt | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/EditCertificationUiState.kt diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/EditCertificationUiState.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/EditCertificationUiState.kt new file mode 100644 index 00000000..cc88f112 --- /dev/null +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/EditCertificationUiState.kt @@ -0,0 +1,6 @@ +package com.msg.certification.viewmodel.uistate + +sealed interface EditCertificationUiState { + data object Success: EditCertificationUiState + data class Error(val exception: Throwable): EditCertificationUiState +} \ No newline at end of file From cd5f22030a5eff0c7181fb46beef448331578fd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 22:58:35 +0900 Subject: [PATCH 088/141] :recycle: :: Apply createErrorToast To Certification Navigation --- .../navigation/CertificationNavigation.kt | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/feature/certification/src/main/java/com/msg/certification/navigation/CertificationNavigation.kt b/feature/certification/src/main/java/com/msg/certification/navigation/CertificationNavigation.kt index d34ac30f..404e44a3 100644 --- a/feature/certification/src/main/java/com/msg/certification/navigation/CertificationNavigation.kt +++ b/feature/certification/src/main/java/com/msg/certification/navigation/CertificationNavigation.kt @@ -16,7 +16,11 @@ fun NavController.navigateToCertificationPage(navOptions: NavOptions? = null, cl this.navigate("$certificationRoute/$clubId/$studentId", navOptions) } -fun NavGraphBuilder.certificationScreen(onHumanClicked: () -> Unit, onEditClicked: () -> Unit) { +fun NavGraphBuilder.certificationScreen( + onHumanClicked: () -> Unit, + onEditClicked: () -> Unit, + createErrorToast: (throwable: Throwable?, message: Int?) -> Unit +) { composable( route = "certificationRoute/{clubId}/{studentId}", arguments = listOf( @@ -30,7 +34,8 @@ fun NavGraphBuilder.certificationScreen(onHumanClicked: () -> Unit, onEditClicke ) { CertificationScreenRoute( onHumanIconClicked = onHumanClicked, - onEditClicked = onEditClicked + onEditClicked = onEditClicked, + createErrorToast = createErrorToast ) } } @@ -39,11 +44,15 @@ fun NavController.navigateToAddCertificationPage(navOptions: NavOptions? = null) this.navigate(addCertificationRoute, navOptions) } -fun NavGraphBuilder.addCertificationScreen(onBackClicked: () -> Unit) { +fun NavGraphBuilder.addCertificationScreen( + onBackClicked: () -> Unit, + createErrorToast: (throwable: Throwable?, message: Int?) -> Unit +) { composable(route = addCertificationRoute) { AddCertificationScreenRoute( onBackClicked = onBackClicked, - onAddClicked = onBackClicked + onAddClicked = onBackClicked, + createErrorToast = createErrorToast ) } } \ No newline at end of file From 4d853ea1551337c1765d5f900685a83208f973e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 22:59:08 +0900 Subject: [PATCH 089/141] :recycle: :: Use data class State Error - GetCertificationListUiState --- .../viewmodel/uistate/GetCertificationListUiState.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetCertificationListUiState.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetCertificationListUiState.kt index 63d22f6c..1516cb71 100644 --- a/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetCertificationListUiState.kt +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetCertificationListUiState.kt @@ -4,7 +4,7 @@ import com.msg.model.entity.certification.CertificationListEntity sealed interface GetCertificationListUiState { data class Success(val data: List): GetCertificationListUiState - data object Error: GetCertificationListUiState + data class Error(val expectation: Throwable): GetCertificationListUiState data object Loading: GetCertificationListUiState data object Empty: GetCertificationListUiState } \ No newline at end of file From b9d6e1aac2cd79707f0c79ac64a1a8311c4473de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 22:59:41 +0900 Subject: [PATCH 090/141] :recycle: :: Use data class State Error - GetLectureSignUpHistoryUiState --- .../viewmodel/uistate/GetLectureSignUpHistoryUiState.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetLectureSignUpHistoryUiState.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetLectureSignUpHistoryUiState.kt index e82ac2c5..daeaa956 100644 --- a/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetLectureSignUpHistoryUiState.kt +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetLectureSignUpHistoryUiState.kt @@ -5,5 +5,5 @@ import com.msg.model.entity.lecture.GetLectureSignUpHistoryEntity sealed interface GetLectureSignUpHistoryUiState { data class Success(val data: GetLectureSignUpHistoryEntity): GetLectureSignUpHistoryUiState data object Loading: GetLectureSignUpHistoryUiState - data object Error: GetLectureSignUpHistoryUiState + data class Error(val expectation: Throwable?): GetLectureSignUpHistoryUiState } \ No newline at end of file From 988a6389af6101c00bdd00441a97569da4c78662 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 23:00:44 +0900 Subject: [PATCH 091/141] :recycle: :: Apply Before Changed(Apply UiState, Changed Logic) - CertificationViewModel --- .../viewmodel/CertificationViewModel.kt | 134 +++++++++++++----- 1 file changed, 95 insertions(+), 39 deletions(-) diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt index 5a7bf44d..5e0fd69e 100644 --- a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt @@ -5,8 +5,10 @@ import androidx.compose.runtime.mutableStateOf import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.msg.certification.viewmodel.uistate.EditCertificationUiState import com.msg.certification.viewmodel.uistate.GetCertificationListUiState import com.msg.certification.viewmodel.uistate.GetLectureSignUpHistoryUiState +import com.msg.certification.viewmodel.uistate.GetStudentBelongClubDetailUiState import com.msg.certification.viewmodel.uistate.WriteCertificationUiState import com.msg.common.event.Event import com.msg.common.errorhandling.errorHandling @@ -47,16 +49,33 @@ class CertificationViewModel @Inject constructor( private val role = getRole().toString() - private val _getCertificationListUiState = MutableStateFlow(GetCertificationListUiState.Loading) - val getCertificationListUiState: StateFlow = _getCertificationListUiState.asStateFlow() + private val _getCertificationListUiState = + MutableStateFlow(GetCertificationListUiState.Loading) + val getCertificationListUiState: StateFlow = + _getCertificationListUiState.asStateFlow() - private val _getLectureSignUpHistoryUiState = MutableStateFlow(GetLectureSignUpHistoryUiState.Loading) - val getLectureSignUpHistoryUiState: StateFlow = _getLectureSignUpHistoryUiState.asStateFlow() + private val _getLectureSignUpHistoryUiState = + MutableStateFlow(GetLectureSignUpHistoryUiState.Loading) + val getLectureSignUpHistoryUiState: StateFlow = + _getLectureSignUpHistoryUiState.asStateFlow() - private val _writeCertificationUiState = MutableStateFlow(WriteCertificationUiState.Loading) - val writeCertificationUiState: StateFlow = _writeCertificationUiState.asStateFlow() + private val _writeCertificationUiState = + MutableStateFlow(WriteCertificationUiState.Success) + val writeCertificationUiState: StateFlow = + _writeCertificationUiState.asStateFlow() - private val _getCertificationListResponse = MutableStateFlow>>(Event.Loading) + private val _editCertificationUiState = + MutableStateFlow(EditCertificationUiState.Success) + val editCertificationUiState: StateFlow = + _editCertificationUiState.asStateFlow() + + private val _getStudentBelongClubDetailUiState = + MutableStateFlow(GetStudentBelongClubDetailUiState.Loading) + val getStudentBelongClubDetailUiState: StateFlow = + _getStudentBelongClubDetailUiState.asStateFlow() + + private val _getCertificationListResponse = + MutableStateFlow>>(Event.Loading) val getCertificationListResponse = _getCertificationListResponse.asStateFlow() private val _writeCertificationResponse = MutableStateFlow>(Event.Loading) @@ -65,10 +84,12 @@ class CertificationViewModel @Inject constructor( private val _editCertificationResponse = MutableStateFlow>(Event.Loading) val editCertificationResponse = _editCertificationResponse.asStateFlow() - private val _getStudentBelongResponse = MutableStateFlow>(Event.Loading) + private val _getStudentBelongResponse = + MutableStateFlow>(Event.Loading) val getStudentBelongResponse = _getStudentBelongResponse.asStateFlow() - private val _getLectureSignUpHistoryResponse = MutableStateFlow>(Event.Loading) + private val _getLectureSignUpHistoryResponse = + MutableStateFlow>(Event.Loading) val getLectureSignUpHistoryResponse = _getLectureSignUpHistoryResponse.asStateFlow() private val studentId = UUID.fromString(savedStateHandle.get("studentId")) @@ -78,7 +99,8 @@ class CertificationViewModel @Inject constructor( var selectedCertificationId = mutableStateOf(null) private set - internal var selectedTitle = savedStateHandle.getStateFlow(key = SELECTED_TITLE, initialValue = "") + internal var selectedTitle = + savedStateHandle.getStateFlow(key = SELECTED_TITLE, initialValue = "") var selectedDate = mutableStateOf(null) private set @@ -107,16 +129,23 @@ class CertificationViewModel @Inject constructor( getCertificationListUseCase(role = role, studentId = studentId) .asResult() .collectLatest { result -> - when(result) { - is Result.Loading -> { _getCertificationListUiState.value = GetCertificationListUiState.Loading } + when (result) { + is Result.Loading -> { + _getCertificationListUiState.value = GetCertificationListUiState.Loading + } + is Result.Success -> { if (result.data.isEmpty()) { _getCertificationListUiState.value = GetCertificationListUiState.Empty } else { - _getCertificationListUiState.value = GetCertificationListUiState.Success(result.data) + _getCertificationListUiState.value = + GetCertificationListUiState.Success(result.data) } } - is Result.Error -> { _getCertificationListUiState.value = GetCertificationListUiState.Error } + + is Result.Error -> { + _getCertificationListUiState.value = GetCertificationListUiState.Error + } } } } @@ -133,10 +162,17 @@ class CertificationViewModel @Inject constructor( ) .asResult() .collectLatest { result -> - when(result) { - is Result.Loading -> { _writeCertificationUiState.value = WriteCertificationUiState.Loading } - is Result.Success -> { _writeCertificationUiState.value = WriteCertificationUiState.Success } - is Result.Error -> { _writeCertificationUiState.value = WriteCertificationUiState.Error(result.exception) } + when (result) { + is Result.Success -> { + _writeCertificationUiState.value = WriteCertificationUiState.Success + } + + is Result.Error -> { + _writeCertificationUiState.value = + WriteCertificationUiState.Error(result.exception) + } + + else -> {} } } } @@ -151,15 +187,22 @@ class CertificationViewModel @Inject constructor( name = name, acquisitionDate = acquisitionDate ) - ).onSuccess { - it.catch { remoteError -> - _editCertificationResponse.value = remoteError.errorHandling() - }.collect { - _editCertificationResponse.value = Event.Success() + ) + .asResult() + .collectLatest { result -> + when (result) { + is Result.Success -> { + _editCertificationUiState.value = EditCertificationUiState.Success + } + + is Result.Error -> { + _editCertificationUiState.value = + EditCertificationUiState.Error(result.exception) + } + + else -> {} + } } - }.onFailure { error -> - _editCertificationResponse.value = error.errorHandling() - } } internal fun getStudentBelong() = viewModelScope.launch { @@ -167,15 +210,15 @@ class CertificationViewModel @Inject constructor( getStudentBelongClubUseCase( id = clubId, studentId = studentId - ).onSuccess { - it.catch { remoteError -> - _getStudentBelongResponse.value = remoteError.errorHandling() - }.collect { response -> - _getStudentBelongResponse.value = Event.Success(data = response) + ) + .asResult() + .collectLatest { result -> + when (result) { + is Result.Loading -> { _getStudentBelongClubDetailUiState.value = GetStudentBelongClubDetailUiState.Loading } + is Result.Success -> { _getStudentBelongClubDetailUiState.value = GetStudentBelongClubDetailUiState.Success(result.data) } + is Result.Error -> { _getStudentBelongClubDetailUiState.value = GetStudentBelongClubDetailUiState.Error(result.exception) } + } } - }.onFailure { error -> - _getStudentBelongResponse.value = error.errorHandling() - } } } @@ -184,10 +227,21 @@ class CertificationViewModel @Inject constructor( getLectureSignUpHistoryUseCase(studentId = studentId) .asResult() .collectLatest { result -> - when(result) { - is Result.Loading -> { _getLectureSignUpHistoryUiState.value = GetLectureSignUpHistoryUiState.Loading } - is Result.Success -> { _getLectureSignUpHistoryUiState.value = GetLectureSignUpHistoryUiState.Success(result.data) } - is Result.Error -> { _getLectureSignUpHistoryUiState.value = GetLectureSignUpHistoryUiState.Error } + when (result) { + is Result.Loading -> { + _getLectureSignUpHistoryUiState.value = + GetLectureSignUpHistoryUiState.Loading + } + + is Result.Success -> { + _getLectureSignUpHistoryUiState.value = + GetLectureSignUpHistoryUiState.Success(result.data) + } + + is Result.Error -> { + _getLectureSignUpHistoryUiState.value = + GetLectureSignUpHistoryUiState.Error + } } } } @@ -197,5 +251,7 @@ class CertificationViewModel @Inject constructor( getAuthorityUseCase() } - internal fun onSelectedTitleChange(value: String) { savedStateHandle[SELECTED_TITLE] = value } + internal fun onSelectedTitleChange(value: String) { + savedStateHandle[SELECTED_TITLE] = value + } } \ No newline at end of file From 95b923d20521a8155b73494d72c702d2d921fddd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 23:01:39 +0900 Subject: [PATCH 092/141] :fire: :: Fire Unused State(Loading) - WriteCertificationUiState --- .../certification/viewmodel/uistate/WriteCertificationUiState.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/WriteCertificationUiState.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/WriteCertificationUiState.kt index ff0a3391..7d53ab74 100644 --- a/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/WriteCertificationUiState.kt +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/WriteCertificationUiState.kt @@ -2,6 +2,5 @@ package com.msg.certification.viewmodel.uistate sealed interface WriteCertificationUiState { data object Success: WriteCertificationUiState - data object Loading: WriteCertificationUiState data class Error(val exception: Throwable): WriteCertificationUiState } \ No newline at end of file From fd37b22e4a830315186fda6f62adf84a9e5d1334 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 23:02:20 +0900 Subject: [PATCH 093/141] :recycle: :: Apply ViewModel Changed(Check Before Commit) --- .../certification/AddCertificationScreen.kt | 43 +++++++++++++++++-- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/feature/certification/src/main/java/com/msg/certification/AddCertificationScreen.kt b/feature/certification/src/main/java/com/msg/certification/AddCertificationScreen.kt index e6244ce1..281c1831 100644 --- a/feature/certification/src/main/java/com/msg/certification/AddCertificationScreen.kt +++ b/feature/certification/src/main/java/com/msg/certification/AddCertificationScreen.kt @@ -24,6 +24,9 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.msg.certification.component.AddAcquisitionDateSection import com.msg.certification.component.AddCertificationSection import com.msg.certification.viewmodel.CertificationViewModel +import com.msg.certification.viewmodel.uistate.EditCertificationUiState +import com.msg.certification.viewmodel.uistate.WriteCertificationUiState +import com.msg.design_system.R import com.msg.design_system.component.button.BitgoeulButton import com.msg.design_system.component.modifier.padding.paddingHorizontal import com.msg.design_system.component.topbar.DetailSettingTopBar @@ -37,11 +40,17 @@ import java.time.LocalDate internal fun AddCertificationScreenRoute( viewModel: CertificationViewModel = hiltViewModel(LocalContext.current as ComponentActivity), onBackClicked: () -> Unit, - onAddClicked: () -> Unit + onAddClicked: () -> Unit, + createErrorToast: (throwable: Throwable?, message: Int?) -> Unit ) { + val writeCertificationUiState by viewModel.writeCertificationUiState.collectAsStateWithLifecycle() + val editCertificationUiState by viewModel.editCertificationUiState.collectAsStateWithLifecycle() + val selectedTitle by viewModel.selectedTitle.collectAsStateWithLifecycle() AddCertificationScreen( + writeCertificationUiState = writeCertificationUiState, + editCertificationUiState = editCertificationUiState, selectedName = selectedTitle, selectedDate = viewModel.selectedDate.value, onSelectedNameChange = viewModel::onSelectedTitleChange, @@ -51,22 +60,46 @@ internal fun AddCertificationScreenRoute( viewModel.editCertification(name = name, acquisitionDate = acquisitionDate) } ?: viewModel.writeCertification(name = name, acquisitionDate = acquisitionDate) onAddClicked() - } + }, + createErrorToast = createErrorToast ) } @Composable internal fun AddCertificationScreen( modifier: Modifier = Modifier, + writeCertificationUiState: WriteCertificationUiState, + editCertificationUiState: EditCertificationUiState, focusManager: FocusManager = LocalFocusManager.current, selectedName: String, onSelectedNameChange: (String) -> Unit, onBackClicked: () -> Unit, selectedDate: LocalDate?, - onAddClicked: (name: String, acquisitionDate: LocalDate) -> Unit + onAddClicked: (name: String, acquisitionDate: LocalDate) -> Unit, + createErrorToast: (throwable: Throwable?, message: Int?) -> Unit ) { + val context = LocalContext.current + val (isDate, setIsDate) = rememberSaveable { mutableStateOf(selectedDate) } + when(writeCertificationUiState) { + is WriteCertificationUiState.Success -> { + makeToast(context, R.string.success_certification_write.toString()) + } + is WriteCertificationUiState.Error -> { + createErrorToast(writeCertificationUiState.exception, R.string.fail_certification_write) + } + } + + when(editCertificationUiState) { + is EditCertificationUiState.Success -> { + makeToast(context, R.string.success_certification_edit.toString()) + } + is EditCertificationUiState.Error -> { + createErrorToast(editCertificationUiState.exception, R.string.fail_certification_edit) + } + } + BitgoeulAndroidTheme { colors, _ -> Box( modifier = modifier @@ -78,7 +111,6 @@ internal fun AddCertificationScreen( } } ) { - val context = LocalContext.current Column( modifier = modifier .fillMaxSize() @@ -131,5 +163,8 @@ fun AddCertificationScreenPre() { selectedDate = null, focusManager = LocalFocusManager.current, onSelectedNameChange = {}, + writeCertificationUiState = WriteCertificationUiState.Success, + editCertificationUiState = EditCertificationUiState.Success, + createErrorToast = {_, _ -> } ) } \ No newline at end of file From 4121cfc7f2aa3035e106d9ef7723a9687e479aeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 23:03:01 +0900 Subject: [PATCH 094/141] :recycle: :: Apply ViewModel Changed And Change Logic --- .../msg/certification/CertificationScreen.kt | 61 +++++++++++-------- 1 file changed, 36 insertions(+), 25 deletions(-) diff --git a/feature/certification/src/main/java/com/msg/certification/CertificationScreen.kt b/feature/certification/src/main/java/com/msg/certification/CertificationScreen.kt index 90134785..76d35b0e 100644 --- a/feature/certification/src/main/java/com/msg/certification/CertificationScreen.kt +++ b/feature/certification/src/main/java/com/msg/certification/CertificationScreen.kt @@ -32,6 +32,7 @@ import com.msg.common.event.Event import com.msg.certification.viewmodel.CertificationViewModel import com.msg.certification.viewmodel.uistate.GetCertificationListUiState import com.msg.certification.viewmodel.uistate.GetLectureSignUpHistoryUiState +import com.msg.certification.viewmodel.uistate.GetStudentBelongClubDetailUiState import com.msg.design_system.R import com.msg.design_system.component.icon.HumanIcon import com.msg.design_system.theme.BitgoeulAndroidTheme @@ -40,6 +41,7 @@ import com.msg.model.entity.club.StudentBelongClubEntity import com.msg.model.entity.lecture.GetLectureSignUpHistoryEntity import com.msg.model.entity.lecture.SignUpLectures import com.msg.ui.DevicePreviews +import com.msg.ui.makeToast import java.time.LocalDate import java.util.UUID @@ -47,10 +49,12 @@ import java.util.UUID internal fun CertificationScreenRoute( viewModel: CertificationViewModel = hiltViewModel(LocalContext.current as ComponentActivity), onHumanIconClicked: () -> Unit, - onEditClicked: () -> Unit + onEditClicked: () -> Unit, + createErrorToast: (throwable: Throwable?, message: Int?) -> Unit ) { val getCertificationListUiState by viewModel.getCertificationListUiState.collectAsStateWithLifecycle() val getLectureSignUpHistoryUiState by viewModel.getLectureSignUpHistoryUiState.collectAsStateWithLifecycle() + val getStudentBelongClubDetailUiState by viewModel.getStudentBelongClubDetailUiState.collectAsStateWithLifecycle() viewModel.getCertificationList() viewModel.getStudentBelong() @@ -93,7 +97,9 @@ internal fun CertificationScreenRoute( certificationData = viewModel.certificationList, lectureData = viewModel.lectureData.value, getCertificationListUiState = getCertificationListUiState, - getLectureSignUpHistoryUiState = getLectureSignUpHistoryUiState + getLectureSignUpHistoryUiState = getLectureSignUpHistoryUiState, + getStudentBelongClubDetailUiState = getStudentBelongClubDetailUiState, + createErrorToast = createErrorToast ) } @@ -145,14 +151,16 @@ private suspend fun getLectureData( @Composable internal fun CertificationScreen( modifier: Modifier = Modifier, + createErrorToast: (throwable: Throwable?, message: Int?) -> Unit, getCertificationListUiState: GetCertificationListUiState, getLectureSignUpHistoryUiState: GetLectureSignUpHistoryUiState, + getStudentBelongClubDetailUiState: GetStudentBelongClubDetailUiState, onHumanIconClicked: () -> Unit, onEditClicked: (id: UUID, title: String, date: LocalDate) -> Unit, onPlusClicked: () -> Unit, studentData: StudentBelongClubEntity, certificationData: List, - lectureData: GetLectureSignUpHistoryEntity + lectureData: GetLectureSignUpHistoryEntity, ) { BitgoeulAndroidTheme { colors, typography -> Box( @@ -160,6 +168,7 @@ internal fun CertificationScreen( .fillMaxSize() .background(color = colors.WHITE) ) { + val context = LocalContext.current Column( modifier = modifier .fillMaxSize() @@ -183,7 +192,24 @@ internal fun CertificationScreen( ) } Spacer(modifier = modifier.height(24.dp)) - StudentInfoSection(data = studentData) + when(getStudentBelongClubDetailUiState) { + is GetStudentBelongClubDetailUiState.Success -> { StudentInfoSection(data = studentData) } + is GetStudentBelongClubDetailUiState.Loading -> { + Box( + modifier = modifier.fillMaxWidth(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator( + modifier = modifier.then(Modifier.size(27.dp)), + color = colors.G2, + strokeWidth = 2.dp + ) + } + } + is GetStudentBelongClubDetailUiState.Error -> { + createErrorToast(getStudentBelongClubDetailUiState.expectation, R.string.fail_get_student_club_detail) + } + } Spacer(modifier = modifier.height(24.dp)) HorizontalDivider( modifier = modifier.fillMaxWidth(), @@ -201,7 +227,6 @@ internal fun CertificationScreen( data = certificationData ) } - is GetCertificationListUiState.Loading -> { Box( modifier = modifier.fillMaxWidth(), @@ -214,22 +239,11 @@ internal fun CertificationScreen( ) } } - is GetCertificationListUiState.Error -> { - Text( - modifier = modifier.align(Alignment.CenterHorizontally), - text = "통신이 원활하지 않습니다..", - style = typography.bodySmall - ) + createErrorToast(getCertificationListUiState.expectation, R.string.fail_get_certification_list) } - is GetCertificationListUiState.Empty -> { - Text( - modifier = modifier.align(Alignment.CenterHorizontally), - text = "자격증이 없습니다..", - style = typography.bodySmall, - color = colors.G4 - ) + makeToast(context, R.string.empty_state.toString()) } } Spacer(modifier = modifier.height(12.dp)) @@ -248,12 +262,7 @@ internal fun CertificationScreen( } } is GetLectureSignUpHistoryUiState.Error -> { - Text( - modifier = modifier.align(Alignment.CenterHorizontally).padding(top = 50.dp), - text = "통신이 원할하지 않습니다..", - style = typography.bodySmall, - color = colors.G4 - ) + createErrorToast(getLectureSignUpHistoryUiState.expectation, R.string.fail_get_lecture_list) } } } @@ -302,6 +311,8 @@ fun CertificationScreenPre() { ) ), getCertificationListUiState = GetCertificationListUiState.Empty, - getLectureSignUpHistoryUiState = GetLectureSignUpHistoryUiState.Error + getLectureSignUpHistoryUiState = GetLectureSignUpHistoryUiState.Error(expectation = Throwable("통신이 원할하지 않습니다.")), + getStudentBelongClubDetailUiState = GetStudentBelongClubDetailUiState.Error(expectation = Throwable("통신이 원할하지 않습니다.")), + createErrorToast = { _, _ -> } ) } \ No newline at end of file From ed84531f52d44fb55a3e43e8016c29e7aa6cdc94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 23:15:09 +0900 Subject: [PATCH 095/141] :recycle: :: Fire Line Spacing And Changed Error State Logic --- .../viewmodel/CertificationViewModel.kt | 42 ++++--------------- 1 file changed, 9 insertions(+), 33 deletions(-) diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt index 5e0fd69e..d4f3ed8c 100644 --- a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt @@ -138,14 +138,9 @@ class CertificationViewModel @Inject constructor( if (result.data.isEmpty()) { _getCertificationListUiState.value = GetCertificationListUiState.Empty } else { - _getCertificationListUiState.value = - GetCertificationListUiState.Success(result.data) - } - } - - is Result.Error -> { - _getCertificationListUiState.value = GetCertificationListUiState.Error + _getCertificationListUiState.value = GetCertificationListUiState.Success(result.data) } } + is Result.Error -> { _getCertificationListUiState.value = GetCertificationListUiState.Error(result.exception) } } } } @@ -163,15 +158,8 @@ class CertificationViewModel @Inject constructor( .asResult() .collectLatest { result -> when (result) { - is Result.Success -> { - _writeCertificationUiState.value = WriteCertificationUiState.Success - } - - is Result.Error -> { - _writeCertificationUiState.value = - WriteCertificationUiState.Error(result.exception) - } - + is Result.Success -> { _writeCertificationUiState.value = WriteCertificationUiState.Success } + is Result.Error -> { _writeCertificationUiState.value = WriteCertificationUiState.Error(result.exception) } else -> {} } } @@ -191,15 +179,8 @@ class CertificationViewModel @Inject constructor( .asResult() .collectLatest { result -> when (result) { - is Result.Success -> { - _editCertificationUiState.value = EditCertificationUiState.Success - } - - is Result.Error -> { - _editCertificationUiState.value = - EditCertificationUiState.Error(result.exception) - } - + is Result.Success -> { _editCertificationUiState.value = EditCertificationUiState.Success } + is Result.Error -> { _editCertificationUiState.value = EditCertificationUiState.Error(result.exception) } else -> {} } } @@ -229,18 +210,13 @@ class CertificationViewModel @Inject constructor( .collectLatest { result -> when (result) { is Result.Loading -> { - _getLectureSignUpHistoryUiState.value = - GetLectureSignUpHistoryUiState.Loading + _getLectureSignUpHistoryUiState.value = GetLectureSignUpHistoryUiState.Loading } - is Result.Success -> { - _getLectureSignUpHistoryUiState.value = - GetLectureSignUpHistoryUiState.Success(result.data) + _getLectureSignUpHistoryUiState.value = GetLectureSignUpHistoryUiState.Success(result.data) } - is Result.Error -> { - _getLectureSignUpHistoryUiState.value = - GetLectureSignUpHistoryUiState.Error + _getLectureSignUpHistoryUiState.value = GetLectureSignUpHistoryUiState.Error(result.exception) } } } From b21ddebd85b5ffab0308f255e4f9f427706a4394 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 23:15:23 +0900 Subject: [PATCH 096/141] :recycle: :: Add createErrorToast --- .../com/msg/bitgoeul_android/navigation/BitgoeulNavHost.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/msg/bitgoeul_android/navigation/BitgoeulNavHost.kt b/app/src/main/java/com/msg/bitgoeul_android/navigation/BitgoeulNavHost.kt index f4dee234..95c7fa1b 100644 --- a/app/src/main/java/com/msg/bitgoeul_android/navigation/BitgoeulNavHost.kt +++ b/app/src/main/java/com/msg/bitgoeul_android/navigation/BitgoeulNavHost.kt @@ -169,7 +169,8 @@ fun BitgoeulNavHost( createErrorToast = createErrorToast ) addCertificationScreen( - onBackClicked = navController::navigateUp + onBackClicked = navController::navigateUp, + createErrorToast = createErrorToast ) } } \ No newline at end of file From 875e71acd4d9beda867e64695a91bac4f1db21df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 23:24:04 +0900 Subject: [PATCH 097/141] :fire: :: Fire Unused Import --- .../viewmodel/uistate/GetStudentBelongClubDetailUiState.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetStudentBelongClubDetailUiState.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetStudentBelongClubDetailUiState.kt index 3bbf4801..3dcae3e9 100644 --- a/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetStudentBelongClubDetailUiState.kt +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetStudentBelongClubDetailUiState.kt @@ -1,6 +1,5 @@ package com.msg.certification.viewmodel.uistate -import android.content.Context import com.msg.model.entity.club.StudentBelongClubEntity sealed interface GetStudentBelongClubDetailUiState { From 5a29483a7a368085c782c1cd8d669a9537471e87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 23:32:40 +0900 Subject: [PATCH 098/141] :fire: :: Fire Line Spacing --- .../viewmodel/CertificationViewModel.kt | 62 +++++++------------ 1 file changed, 21 insertions(+), 41 deletions(-) diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt index d4f3ed8c..f3e7815f 100644 --- a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt @@ -49,33 +49,22 @@ class CertificationViewModel @Inject constructor( private val role = getRole().toString() - private val _getCertificationListUiState = - MutableStateFlow(GetCertificationListUiState.Loading) - val getCertificationListUiState: StateFlow = - _getCertificationListUiState.asStateFlow() - - private val _getLectureSignUpHistoryUiState = - MutableStateFlow(GetLectureSignUpHistoryUiState.Loading) - val getLectureSignUpHistoryUiState: StateFlow = - _getLectureSignUpHistoryUiState.asStateFlow() - - private val _writeCertificationUiState = - MutableStateFlow(WriteCertificationUiState.Success) - val writeCertificationUiState: StateFlow = - _writeCertificationUiState.asStateFlow() - - private val _editCertificationUiState = - MutableStateFlow(EditCertificationUiState.Success) - val editCertificationUiState: StateFlow = - _editCertificationUiState.asStateFlow() - - private val _getStudentBelongClubDetailUiState = - MutableStateFlow(GetStudentBelongClubDetailUiState.Loading) - val getStudentBelongClubDetailUiState: StateFlow = - _getStudentBelongClubDetailUiState.asStateFlow() - - private val _getCertificationListResponse = - MutableStateFlow>>(Event.Loading) + private val _getCertificationListUiState = MutableStateFlow(GetCertificationListUiState.Loading) + val getCertificationListUiState: StateFlow = _getCertificationListUiState.asStateFlow() + + private val _getLectureSignUpHistoryUiState = MutableStateFlow(GetLectureSignUpHistoryUiState.Loading) + val getLectureSignUpHistoryUiState: StateFlow = _getLectureSignUpHistoryUiState.asStateFlow() + + private val _writeCertificationUiState = MutableStateFlow(WriteCertificationUiState.Success) + val writeCertificationUiState: StateFlow = _writeCertificationUiState.asStateFlow() + + private val _editCertificationUiState = MutableStateFlow(EditCertificationUiState.Success) + val editCertificationUiState: StateFlow = _editCertificationUiState.asStateFlow() + + private val _getStudentBelongClubDetailUiState = MutableStateFlow(GetStudentBelongClubDetailUiState.Loading) + val getStudentBelongClubDetailUiState: StateFlow = _getStudentBelongClubDetailUiState.asStateFlow() + + private val _getCertificationListResponse = MutableStateFlow>>(Event.Loading) val getCertificationListResponse = _getCertificationListResponse.asStateFlow() private val _writeCertificationResponse = MutableStateFlow>(Event.Loading) @@ -84,12 +73,10 @@ class CertificationViewModel @Inject constructor( private val _editCertificationResponse = MutableStateFlow>(Event.Loading) val editCertificationResponse = _editCertificationResponse.asStateFlow() - private val _getStudentBelongResponse = - MutableStateFlow>(Event.Loading) + private val _getStudentBelongResponse = MutableStateFlow>(Event.Loading) val getStudentBelongResponse = _getStudentBelongResponse.asStateFlow() - private val _getLectureSignUpHistoryResponse = - MutableStateFlow>(Event.Loading) + private val _getLectureSignUpHistoryResponse = MutableStateFlow>(Event.Loading) val getLectureSignUpHistoryResponse = _getLectureSignUpHistoryResponse.asStateFlow() private val studentId = UUID.fromString(savedStateHandle.get("studentId")) @@ -133,7 +120,6 @@ class CertificationViewModel @Inject constructor( is Result.Loading -> { _getCertificationListUiState.value = GetCertificationListUiState.Loading } - is Result.Success -> { if (result.data.isEmpty()) { _getCertificationListUiState.value = GetCertificationListUiState.Empty @@ -209,15 +195,9 @@ class CertificationViewModel @Inject constructor( .asResult() .collectLatest { result -> when (result) { - is Result.Loading -> { - _getLectureSignUpHistoryUiState.value = GetLectureSignUpHistoryUiState.Loading - } - is Result.Success -> { - _getLectureSignUpHistoryUiState.value = GetLectureSignUpHistoryUiState.Success(result.data) - } - is Result.Error -> { - _getLectureSignUpHistoryUiState.value = GetLectureSignUpHistoryUiState.Error(result.exception) - } + is Result.Loading -> { _getLectureSignUpHistoryUiState.value = GetLectureSignUpHistoryUiState.Loading } + is Result.Success -> { _getLectureSignUpHistoryUiState.value = GetLectureSignUpHistoryUiState.Success(result.data) } + is Result.Error -> { _getLectureSignUpHistoryUiState.value = GetLectureSignUpHistoryUiState.Error(result.exception) } } } } From 1736dc50cb7eaf3c4d2c99037b2bcca54633cabc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Thu, 12 Sep 2024 20:09:35 +0900 Subject: [PATCH 099/141] :green_heart: :: Add Missing Strings - string.xml File --- core/design-system/src/main/res/values/strings.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/design-system/src/main/res/values/strings.xml b/core/design-system/src/main/res/values/strings.xml index 809fd3fc..e80ed91c 100644 --- a/core/design-system/src/main/res/values/strings.xml +++ b/core/design-system/src/main/res/values/strings.xml @@ -100,4 +100,7 @@ 자격증 정보를 불러오지 못했습니다. 데이터가 없습니다. 강의 정보를 불러오지 못했습니다. + 문의사항 + 답변 됨 + 답변 대기 중 \ No newline at end of file From 3581ba4bb779844684eed645a1f96e8e18836a7c Mon Sep 17 00:00:00 2001 From: Chaejongin12 Date: Fri, 13 Sep 2024 11:18:54 +0900 Subject: [PATCH 100/141] =?UTF-8?q?=E2=9C=A8::=20strings.xml=20=EB=AC=B8?= =?UTF-8?q?=EC=9E=90=EC=97=B4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/design-system/src/main/res/values/strings.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/design-system/src/main/res/values/strings.xml b/core/design-system/src/main/res/values/strings.xml index d5873fd5..be9b7822 100644 --- a/core/design-system/src/main/res/values/strings.xml +++ b/core/design-system/src/main/res/values/strings.xml @@ -87,4 +87,10 @@ 문의사항 답변 됨 답변 대기 중 + 문의 삭제 + 문의 답변 + 답변을 추가하시겠습니까? + 문의 사항을 삭제하시겠습니까? + 삭제 + 추가 \ No newline at end of file From 2dc30825f57628014700fe31add3f7b5022e107e Mon Sep 17 00:00:00 2001 From: Chaejongin12 Date: Fri, 13 Sep 2024 11:19:09 +0900 Subject: [PATCH 101/141] =?UTF-8?q?=E2=9C=A8::=20Type=20headlineSmall=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/msg/design_system/theme/Type.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/design-system/src/main/java/com/msg/design_system/theme/Type.kt b/core/design-system/src/main/java/com/msg/design_system/theme/Type.kt index 824cdb03..80241c82 100644 --- a/core/design-system/src/main/java/com/msg/design_system/theme/Type.kt +++ b/core/design-system/src/main/java/com/msg/design_system/theme/Type.kt @@ -80,4 +80,10 @@ val Typography = Typography( fontWeight = FontWeight.Normal, lineHeight = 26.sp ), + headlineSmall = TextStyle( + fontFamily = pretendard, + fontSize = 16.sp, + fontWeight = FontWeight.Normal, + lineHeight = 32.sp + ) ) \ No newline at end of file From 02d19ae72fc29bd3309e378e263ba5ac5195b95a Mon Sep 17 00:00:00 2001 From: Chaejongin12 Date: Thu, 19 Sep 2024 10:04:50 +0900 Subject: [PATCH 102/141] =?UTF-8?q?=E2=9C=A8::=20=EB=AC=B8=EC=9D=98=20?= =?UTF-8?q?=EC=82=AC=ED=95=AD=20=EC=84=B8=EB=B6=80=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=EC=A0=9C=EC=9E=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bitgoeul/inquiry/InquiryDetailScreen.kt | 176 ++++++++++++++++++ 1 file changed, 176 insertions(+) diff --git a/feature/inquiry/src/main/java/com/bitgoeul/inquiry/InquiryDetailScreen.kt b/feature/inquiry/src/main/java/com/bitgoeul/inquiry/InquiryDetailScreen.kt index e16a0c76..0dc2806a 100644 --- a/feature/inquiry/src/main/java/com/bitgoeul/inquiry/InquiryDetailScreen.kt +++ b/feature/inquiry/src/main/java/com/bitgoeul/inquiry/InquiryDetailScreen.kt @@ -1,2 +1,178 @@ package com.bitgoeul.inquiry +import androidx.compose.foundation.background +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.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.msg.design_system.component.icon.GoBackIcon +import com.msg.design_system.component.topbar.GoBackTopBar +import com.msg.design_system.theme.BitgoeulAndroidTheme +import com.msg.design_system.R +import com.msg.design_system.component.button.BitgoeulButton +import com.msg.design_system.component.button.NegativeBitgoeulButton +import com.msg.design_system.component.dialog.NegativeActionDialog +import com.msg.design_system.component.dialog.PositiveActionDialog + +@Composable +fun InquiryDetailRoute() { + InquiryDetailScreen() +} + +@Composable +fun InquiryDetailScreen( + modifier: Modifier = Modifier, +) { + val scrollState = rememberScrollState() + + BitgoeulAndroidTheme { colors, typography -> + Column( + modifier = modifier + .fillMaxSize() + .background(color = colors.WHITE) + .padding(horizontal = 28.dp) + .verticalScroll(scrollState), + ) { + Spacer(modifier = modifier.height(20.dp)) + + GoBackTopBar( + icon = { GoBackIcon() }, + text = stringResource(id = R.string.go_back) + ) { + + } + + Spacer(modifier = modifier.height(24.dp)) + + Row( + modifier = modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = "답변 대기 중", + style = typography.labelMedium, + color = colors.E5 + ) + + Spacer(modifier = modifier.weight(1f)) + + Text( + text = "2023 11월 11일 12:34에 수정됨", + style = typography.labelMedium, + color = colors.G1 + ) + } + + Spacer(modifier = modifier.height(4.dp)) + + Text( + text = "국가는 국민 모두의 생산 및 생활의 기반이 되는 국토의 효율적이고 균형있는 이용·개발과 보전을 위하여 법률이 정하는 바에 의하여 그에 관한 필요한 제한과 의무를 과할 수 있다.", + style = typography.bodyLarge, + color = colors.BLACK + ) + + Spacer(modifier = modifier.height(4.dp)) + + Row( + modifier = modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = "2023.10.31 활동", + style = typography.bodySmall, + color = colors.G2 + ) + + Spacer(modifier = modifier.weight(1f)) + + Text( + text = "게시자 홍길동", + style = typography.bodySmall, + color = colors.G1 + ) + } + + Spacer(modifier = modifier.height(24.dp)) + + Text( + text = "문의 사항 임시 문자열입니다. 문의 사항 임시 문자열입니다.문의 사항 임시 문자열입니다.문의 사항 임시 문자열입니다.문의 사항 임시 문자열입니다.문의 사항 임시 문자열입니다.문의 사항 임시 문자열입니다.문의 사항 임시 문자열입니다.문의 사항 임시 문자열입니다.문의 사항 임시 문자열입니다.문의 사항 임시 문자열입니다.", + style = typography.headlineSmall, + color = colors.BLACK + ) + + NegativeActionDialog( + title = stringResource(id = R.string.delete_inquiry_dialog_title), + negativeAction = stringResource(id = R.string.delete), + content = "임시", + isVisible = false, // 임시 + onQuit = { /*TODO*/ }) { + + } + + PositiveActionDialog( + title = stringResource(id = R.string.answer_inquiry_dialog_title), + positiveAction = stringResource(id = R.string.add), + content = "임시", + isVisible = false, // 임시 + onQuit = { /*TODO*/ }) { + + } + } + + // 추후 Role 처리 + Column( + modifier = modifier + .fillMaxSize() + .padding(horizontal = 28.dp), + verticalArrangement = Arrangement.Bottom + ) { + Box( + modifier = modifier + .fillMaxWidth() + ) { + Row( + modifier = modifier.fillMaxWidth() + ) { + NegativeBitgoeulButton( + modifier = modifier.weight(1f), + text = stringResource(id = R.string.delete_inquiry) + ) { + + } + + Spacer(modifier = modifier.width(8.dp)) + + BitgoeulButton( + modifier = modifier.weight(1f), + text = stringResource(id = R.string.answer_inquiry) + ) { + + } + } + } + + Spacer(modifier = modifier.height(24.dp)) + } + } +} + +@Preview +@Composable +fun InquiryDetailScreenPre() { + InquiryDetailScreen() +} \ No newline at end of file From 41f6e9cb0d47b052c276a42379f1866bd1f2ed95 Mon Sep 17 00:00:00 2001 From: Chaejongin12 Date: Fri, 20 Sep 2024 09:14:05 +0900 Subject: [PATCH 103/141] =?UTF-8?q?:recycle:=20::=20scrollState=20?= =?UTF-8?q?=ED=98=B8=EC=9D=B4=EC=8A=A4=ED=8C=85=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit :: scrollState 호이스팅 적용 --- .../java/com/bitgoeul/inquiry/InquiryDetailScreen.kt | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/feature/inquiry/src/main/java/com/bitgoeul/inquiry/InquiryDetailScreen.kt b/feature/inquiry/src/main/java/com/bitgoeul/inquiry/InquiryDetailScreen.kt index 0dc2806a..94a240c7 100644 --- a/feature/inquiry/src/main/java/com/bitgoeul/inquiry/InquiryDetailScreen.kt +++ b/feature/inquiry/src/main/java/com/bitgoeul/inquiry/InquiryDetailScreen.kt @@ -1,5 +1,6 @@ package com.bitgoeul.inquiry +import androidx.compose.foundation.ScrollState import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box @@ -31,14 +32,18 @@ import com.msg.design_system.component.dialog.PositiveActionDialog @Composable fun InquiryDetailRoute() { - InquiryDetailScreen() + val scrollState = rememberScrollState() + + InquiryDetailScreen( + scrollState = scrollState + ) } @Composable fun InquiryDetailScreen( modifier: Modifier = Modifier, + scrollState: ScrollState = rememberScrollState(), ) { - val scrollState = rememberScrollState() BitgoeulAndroidTheme { colors, typography -> Column( From e3d4c3180fd38d2e124d66ea4794e5ecc1344121 Mon Sep 17 00:00:00 2001 From: Chaejongin12 Date: Fri, 20 Sep 2024 09:24:02 +0900 Subject: [PATCH 104/141] =?UTF-8?q?:fire:=20::=20=ED=98=B8=EC=9D=B4?= =?UTF-8?q?=EC=8A=A4=ED=8C=85=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit :: 호이스팅 제거 --- .../main/java/com/bitgoeul/inquiry/InquiryDetailScreen.kt | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/feature/inquiry/src/main/java/com/bitgoeul/inquiry/InquiryDetailScreen.kt b/feature/inquiry/src/main/java/com/bitgoeul/inquiry/InquiryDetailScreen.kt index 94a240c7..9606ea04 100644 --- a/feature/inquiry/src/main/java/com/bitgoeul/inquiry/InquiryDetailScreen.kt +++ b/feature/inquiry/src/main/java/com/bitgoeul/inquiry/InquiryDetailScreen.kt @@ -32,11 +32,7 @@ import com.msg.design_system.component.dialog.PositiveActionDialog @Composable fun InquiryDetailRoute() { - val scrollState = rememberScrollState() - - InquiryDetailScreen( - scrollState = scrollState - ) + InquiryDetailScreen() } @Composable From cdd88ad4fd81377df395e0a70382b6bf0fe8a17e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Thu, 5 Sep 2024 20:07:06 +0900 Subject: [PATCH 105/141] :sparkles: :: Create asResult() Function(Use ViewModel - UiState) --- .../src/main/java/com/msg/common/result/Result.kt | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 core/common/src/main/java/com/msg/common/result/Result.kt diff --git a/core/common/src/main/java/com/msg/common/result/Result.kt b/core/common/src/main/java/com/msg/common/result/Result.kt new file mode 100644 index 00000000..346973bf --- /dev/null +++ b/core/common/src/main/java/com/msg/common/result/Result.kt @@ -0,0 +1,13 @@ +package com.msg.common.result + +import kotlinx.coroutines.flow.* + +sealed interface Result { + data class Success(val data: T): Result + data class Error(val exception: Throwable): Result + data object Loading: Result +} + +fun Flow.asResult(): Flow> = map> { Result.Success(it) } + .onStart { emit(Result.Loading) } + .catch { emit(Result.Error(it)) } \ No newline at end of file From 57e36a6cb79439c1920a720c5a215140110e0ed1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Thu, 5 Sep 2024 20:09:10 +0900 Subject: [PATCH 106/141] :fire: :: Fire Unused Import --- .../main/java/com/msg/certification/AddCertificationScreen.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/feature/certification/src/main/java/com/msg/certification/AddCertificationScreen.kt b/feature/certification/src/main/java/com/msg/certification/AddCertificationScreen.kt index 12d83507..e6244ce1 100644 --- a/feature/certification/src/main/java/com/msg/certification/AddCertificationScreen.kt +++ b/feature/certification/src/main/java/com/msg/certification/AddCertificationScreen.kt @@ -9,7 +9,6 @@ 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.padding import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf From cf1f15ee27442ab88658b6d63d6505522b7ead4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Fri, 6 Sep 2024 10:16:38 +0900 Subject: [PATCH 107/141] :fire: :: Unused Code(File) --- .../GetCertificationListForStudentUseCase.kt | 12 ------------ .../GetCertificationListForTeacherUseCase.kt | 13 ------------- 2 files changed, 25 deletions(-) delete mode 100644 core/domain/src/main/java/com/msg/domain/usecase/certification/GetCertificationListForStudentUseCase.kt delete mode 100644 core/domain/src/main/java/com/msg/domain/usecase/certification/GetCertificationListForTeacherUseCase.kt diff --git a/core/domain/src/main/java/com/msg/domain/usecase/certification/GetCertificationListForStudentUseCase.kt b/core/domain/src/main/java/com/msg/domain/usecase/certification/GetCertificationListForStudentUseCase.kt deleted file mode 100644 index 38b520b8..00000000 --- a/core/domain/src/main/java/com/msg/domain/usecase/certification/GetCertificationListForStudentUseCase.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.msg.domain.usecase.certification - -import com.msg.data.repository.certification.CertificationRepository -import javax.inject.Inject - -class GetCertificationListForStudentUseCase @Inject constructor( - private val certificationRepository: CertificationRepository, -) { - suspend operator fun invoke() = runCatching { - certificationRepository.getCertificationListForStudent() - } -} \ No newline at end of file diff --git a/core/domain/src/main/java/com/msg/domain/usecase/certification/GetCertificationListForTeacherUseCase.kt b/core/domain/src/main/java/com/msg/domain/usecase/certification/GetCertificationListForTeacherUseCase.kt deleted file mode 100644 index 8f028a72..00000000 --- a/core/domain/src/main/java/com/msg/domain/usecase/certification/GetCertificationListForTeacherUseCase.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.msg.domain.usecase.certification - -import com.msg.data.repository.certification.CertificationRepository -import java.util.UUID -import javax.inject.Inject - -class GetCertificationListForTeacherUseCase @Inject constructor( - private val certificationRepository: CertificationRepository, -) { - suspend operator fun invoke(studentId: UUID) = runCatching { - certificationRepository.getCertificationListForTeacher(studentId = studentId) - } -} \ No newline at end of file From fcdb6fd692e225f8aeb2a8e6fbcf091207ce05a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Fri, 6 Sep 2024 10:18:09 +0900 Subject: [PATCH 108/141] :recycle: :: Combine The Use Cases Into One --- .../GetCertificationListUseCase.kt | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 core/domain/src/main/java/com/msg/domain/usecase/certification/GetCertificationListUseCase.kt diff --git a/core/domain/src/main/java/com/msg/domain/usecase/certification/GetCertificationListUseCase.kt b/core/domain/src/main/java/com/msg/domain/usecase/certification/GetCertificationListUseCase.kt new file mode 100644 index 00000000..695267aa --- /dev/null +++ b/core/domain/src/main/java/com/msg/domain/usecase/certification/GetCertificationListUseCase.kt @@ -0,0 +1,18 @@ +package com.msg.domain.usecase.certification + +import com.msg.data.repository.certification.CertificationRepository +import com.msg.model.entity.certification.CertificationListEntity +import kotlinx.coroutines.flow.Flow +import java.util.UUID +import javax.inject.Inject + +class GetCertificationListUseCase @Inject constructor( + private val certificationRepository: CertificationRepository, +) { + operator fun invoke(role: String, studentId: UUID): Flow> { + return when (role) { + "ROLE_STUDENT" -> certificationRepository.getCertificationListForStudent() + else -> certificationRepository.getCertificationListForTeacher(studentId = studentId) + } + } +} \ No newline at end of file From 28cae03cd3ef3d593bc16cd68529831d46b495d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Fri, 6 Sep 2024 10:18:41 +0900 Subject: [PATCH 109/141] :sparkles: :: Create GetCertificationListUiState --- .../viewmodel/uistate/GetCertificationListUiState.kt | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetCertificationListUiState.kt diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetCertificationListUiState.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetCertificationListUiState.kt new file mode 100644 index 00000000..63d22f6c --- /dev/null +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetCertificationListUiState.kt @@ -0,0 +1,10 @@ +package com.msg.certification.viewmodel.uistate + +import com.msg.model.entity.certification.CertificationListEntity + +sealed interface GetCertificationListUiState { + data class Success(val data: List): GetCertificationListUiState + data object Error: GetCertificationListUiState + data object Loading: GetCertificationListUiState + data object Empty: GetCertificationListUiState +} \ No newline at end of file From 77fe0a3a32f91d31318a39e7ead894254688e1fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Fri, 6 Sep 2024 10:19:12 +0900 Subject: [PATCH 110/141] :recycle: :: Simplify ViewModel Code And Apply UiState - getCertificationList Function --- .../viewmodel/CertificationViewModel.kt | 45 +++++++++---------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt index 268815d9..7fbed016 100644 --- a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt @@ -5,11 +5,14 @@ import androidx.compose.runtime.mutableStateOf import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.msg.certification.viewmodel.uistate.GetCertificationListUiState import com.msg.common.event.Event import com.msg.common.errorhandling.errorHandling +import com.msg.common.result.Result +import com.msg.common.result.asResult import com.msg.domain.usecase.auth.GetAuthorityUseCase import com.msg.domain.usecase.certification.* -import com.msg.domain.usecase.certification.GetCertificationListForTeacherUseCase +import com.msg.domain.usecase.certification.GetCertificationListUseCase import com.msg.domain.usecase.certification.WriteCertificationUseCase import com.msg.domain.usecase.club.GetStudentBelongClubUseCase import com.msg.domain.usecase.lecture.GetLectureSignUpHistoryUseCase @@ -18,16 +21,17 @@ import com.msg.model.entity.club.StudentBelongClubEntity import com.msg.model.entity.lecture.GetLectureSignUpHistoryEntity import com.msg.model.param.certification.WriteCertificationParam import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.catch +import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch import java.time.LocalDate import java.util.UUID import javax.inject.Inject class CertificationViewModel @Inject constructor( - private val getCertificationListForTeacherUseCase: GetCertificationListForTeacherUseCase, - private val getCertificationListForStudentUseCase: GetCertificationListForStudentUseCase, + private val getCertificationListUseCase: GetCertificationListUseCase, private val writeCertificationUseCase: WriteCertificationUseCase, private val editCertificationUseCase: EditCertificationUseCase, private val getStudentBelongClubUseCase: GetStudentBelongClubUseCase, @@ -41,6 +45,9 @@ class CertificationViewModel @Inject constructor( private val role = getRole().toString() + private val _getCertificationListUiState = MutableStateFlow(GetCertificationListUiState.Loading) + val getCertificationListUiState: StateFlow = _getCertificationListUiState.asStateFlow() + private val _getCertificationListResponse = MutableStateFlow>>( Event.Loading) val getCertificationListResponse = _getCertificationListResponse.asStateFlow() @@ -91,29 +98,21 @@ class CertificationViewModel @Inject constructor( private set internal fun getCertificationList() = viewModelScope.launch { - if (role == "ROLE_STUDENT") { - getCertificationListForStudentUseCase().onSuccess { - it.catch { remoteError -> - _getCertificationListResponse.value = remoteError.errorHandling() - }.collect { response -> - _getCertificationListResponse.value = Event.Success(data = response) - } - }.onFailure { error -> - _getCertificationListResponse.value = error.errorHandling() - } - } else { - if (studentId != null) { - getCertificationListForTeacherUseCase(studentId).onSuccess { - it.catch { remoteError -> - _getCertificationListResponse.value = remoteError.errorHandling() - }.collect { response -> - _getCertificationListResponse.value = Event.Success(data = response) + getCertificationListUseCase(role = role, studentId = studentId) + .asResult() + .collectLatest { result -> + when(result) { + is Result.Loading -> { _getCertificationListUiState.value = GetCertificationListUiState.Loading } + is Result.Success -> { + if (result.data.isEmpty()) { + _getCertificationListUiState.value = GetCertificationListUiState.Empty + } else { + _getCertificationListUiState.value = GetCertificationListUiState.Success(result.data) + } } - }.onFailure { error -> - _getCertificationListResponse.value = error.errorHandling() + is Result.Error -> { _getCertificationListUiState.value = GetCertificationListUiState.Error } } } - } } internal fun writeCertification( From d01afc8c3d146d9ae3bfd458378e14bdd961a6be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Fri, 6 Sep 2024 10:19:39 +0900 Subject: [PATCH 111/141] :recycle: :: Apply ViewModel Changed(Apply UiState) --- .../msg/certification/CertificationScreen.kt | 60 ++++++++++++++++--- 1 file changed, 51 insertions(+), 9 deletions(-) diff --git a/feature/certification/src/main/java/com/msg/certification/CertificationScreen.kt b/feature/certification/src/main/java/com/msg/certification/CertificationScreen.kt index a6d2f7da..cd8ef4f8 100644 --- a/feature/certification/src/main/java/com/msg/certification/CertificationScreen.kt +++ b/feature/certification/src/main/java/com/msg/certification/CertificationScreen.kt @@ -11,22 +11,26 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.IconButton import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.msg.certification.component.CertificationSection import com.msg.certification.component.FinishedLectureSection import com.msg.certification.component.StudentInfoSection import com.msg.common.event.Event import com.msg.certification.viewmodel.CertificationViewModel +import com.msg.certification.viewmodel.uistate.GetCertificationListUiState import com.msg.design_system.R import com.msg.design_system.component.icon.HumanIcon import com.msg.design_system.theme.BitgoeulAndroidTheme @@ -44,6 +48,8 @@ internal fun CertificationScreenRoute( onHumanIconClicked: () -> Unit, onEditClicked: () -> Unit ) { + val getCertificationListUiState by viewModel.getCertificationListUiState.collectAsStateWithLifecycle() + viewModel.getCertificationList() viewModel.getStudentBelong() viewModel.getLectureSignUpHistory() @@ -83,7 +89,8 @@ internal fun CertificationScreenRoute( onPlusClicked = onEditClicked, studentData = viewModel.studentData.value, certificationData = viewModel.certificationList, - lectureData = viewModel.lectureData.value + lectureData = viewModel.lectureData.value, + getCertificationListUiState = getCertificationListUiState ) } @@ -135,6 +142,7 @@ private suspend fun getLectureData( @Composable internal fun CertificationScreen( modifier: Modifier = Modifier, + getCertificationListUiState: GetCertificationListUiState, onHumanIconClicked: () -> Unit, onEditClicked: (id: UUID, title: String, date: LocalDate) -> Unit, onPlusClicked: () -> Unit, @@ -179,13 +187,46 @@ internal fun CertificationScreen( color = colors.G9 ) Spacer(modifier = modifier.height(24.dp)) - CertificationSection( - onPlusClicked = onPlusClicked, - onEditClicked = { id, title, date -> - onEditClicked(id, title, date) - }, - data = certificationData - ) + when(getCertificationListUiState) { + is GetCertificationListUiState.Success -> { + CertificationSection( + onPlusClicked = onPlusClicked, + onEditClicked = { id, title, date -> + onEditClicked(id, title, date) + }, + data = certificationData + ) + } + + is GetCertificationListUiState.Loading -> { + Box( + modifier = modifier.fillMaxWidth(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator( + modifier = modifier.then(Modifier.size(27.dp)), + color = colors.G2, + strokeWidth = 2.dp + ) + } + } + + is GetCertificationListUiState.Error -> { + Text( + modifier = modifier.align(Alignment.CenterHorizontally), + text = "통신이 원활하지 않습니다..", + style = typography.titleSmall + ) + } + + is GetCertificationListUiState.Empty -> { + Text( + modifier = modifier.align(Alignment.CenterHorizontally), + text = "자격증이 없습니다..", + style = typography.titleSmall + ) + } + } Spacer(modifier = modifier.height(12.dp)) FinishedLectureSection(data = lectureData) } @@ -232,6 +273,7 @@ fun CertificationScreenPre() { isComplete = true ) ) - ) + ), + getCertificationListUiState = GetCertificationListUiState.Loading ) } \ No newline at end of file From 35332d30a7dc3bcc3caad43324f658fbe004f4b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Fri, 6 Sep 2024 10:22:09 +0900 Subject: [PATCH 112/141] :fire: :: Line Spacing --- .../msg/certification/viewmodel/CertificationViewModel.kt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt index 7fbed016..df5c6c45 100644 --- a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt @@ -48,8 +48,7 @@ class CertificationViewModel @Inject constructor( private val _getCertificationListUiState = MutableStateFlow(GetCertificationListUiState.Loading) val getCertificationListUiState: StateFlow = _getCertificationListUiState.asStateFlow() - private val _getCertificationListResponse = MutableStateFlow>>( - Event.Loading) + private val _getCertificationListResponse = MutableStateFlow>>(Event.Loading) val getCertificationListResponse = _getCertificationListResponse.asStateFlow() private val _writeCertificationResponse = MutableStateFlow>(Event.Loading) @@ -61,8 +60,7 @@ class CertificationViewModel @Inject constructor( private val _getStudentBelongResponse = MutableStateFlow>(Event.Loading) val getStudentBelongResponse = _getStudentBelongResponse.asStateFlow() - private val _getLectureSignUpHistoryResponse = MutableStateFlow>( - Event.Loading) + private val _getLectureSignUpHistoryResponse = MutableStateFlow>(Event.Loading) val getLectureSignUpHistoryResponse = _getLectureSignUpHistoryResponse.asStateFlow() private val studentId = UUID.fromString(savedStateHandle.get("studentId")) From 6a21b779a869c4b9ae5a2f81a2073338881d0848 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 11:41:35 +0900 Subject: [PATCH 113/141] :memo: :: Modify Use Flow And Fire Unused Code --- .../domain/usecase/lecture/GetLectureSignUpHistoryUseCase.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/domain/src/main/java/com/msg/domain/usecase/lecture/GetLectureSignUpHistoryUseCase.kt b/core/domain/src/main/java/com/msg/domain/usecase/lecture/GetLectureSignUpHistoryUseCase.kt index 93454000..5db48700 100644 --- a/core/domain/src/main/java/com/msg/domain/usecase/lecture/GetLectureSignUpHistoryUseCase.kt +++ b/core/domain/src/main/java/com/msg/domain/usecase/lecture/GetLectureSignUpHistoryUseCase.kt @@ -1,13 +1,14 @@ package com.msg.domain.usecase.lecture import com.msg.data.repository.lecture.LectureRepository +import com.msg.model.entity.lecture.GetLectureSignUpHistoryEntity +import kotlinx.coroutines.flow.Flow import java.util.UUID import javax.inject.Inject class GetLectureSignUpHistoryUseCase @Inject constructor( private val lectureRepository: LectureRepository ) { - suspend operator fun invoke(studentId: UUID) = runCatching { + operator fun invoke(studentId: UUID): Flow = lectureRepository.getLectureSignUpHistory(studentId = studentId) - } } \ No newline at end of file From 83c5b58673b53c6aa352847b76e61627c5152f6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 11:42:02 +0900 Subject: [PATCH 114/141] :sparkles: :: Create GetLectureSignUpHistoryUiState --- .../viewmodel/uistate/GetLectureSignUpHistoryUiState.kt | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetLectureSignUpHistoryUiState.kt diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetLectureSignUpHistoryUiState.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetLectureSignUpHistoryUiState.kt new file mode 100644 index 00000000..e82ac2c5 --- /dev/null +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetLectureSignUpHistoryUiState.kt @@ -0,0 +1,9 @@ +package com.msg.certification.viewmodel.uistate + +import com.msg.model.entity.lecture.GetLectureSignUpHistoryEntity + +sealed interface GetLectureSignUpHistoryUiState { + data class Success(val data: GetLectureSignUpHistoryEntity): GetLectureSignUpHistoryUiState + data object Loading: GetLectureSignUpHistoryUiState + data object Error: GetLectureSignUpHistoryUiState +} \ No newline at end of file From 98c8a90ef399bba419691610cabcc7c7bb3ada57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 15:58:10 +0900 Subject: [PATCH 115/141] :recycle: :: Changed TextStyle And Color && Apply UiState To Screen --- .../msg/certification/CertificationScreen.kt | 38 ++++++++++++++++--- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/feature/certification/src/main/java/com/msg/certification/CertificationScreen.kt b/feature/certification/src/main/java/com/msg/certification/CertificationScreen.kt index cd8ef4f8..90134785 100644 --- a/feature/certification/src/main/java/com/msg/certification/CertificationScreen.kt +++ b/feature/certification/src/main/java/com/msg/certification/CertificationScreen.kt @@ -31,6 +31,7 @@ import com.msg.certification.component.StudentInfoSection import com.msg.common.event.Event import com.msg.certification.viewmodel.CertificationViewModel import com.msg.certification.viewmodel.uistate.GetCertificationListUiState +import com.msg.certification.viewmodel.uistate.GetLectureSignUpHistoryUiState import com.msg.design_system.R import com.msg.design_system.component.icon.HumanIcon import com.msg.design_system.theme.BitgoeulAndroidTheme @@ -49,6 +50,7 @@ internal fun CertificationScreenRoute( onEditClicked: () -> Unit ) { val getCertificationListUiState by viewModel.getCertificationListUiState.collectAsStateWithLifecycle() + val getLectureSignUpHistoryUiState by viewModel.getLectureSignUpHistoryUiState.collectAsStateWithLifecycle() viewModel.getCertificationList() viewModel.getStudentBelong() @@ -90,7 +92,8 @@ internal fun CertificationScreenRoute( studentData = viewModel.studentData.value, certificationData = viewModel.certificationList, lectureData = viewModel.lectureData.value, - getCertificationListUiState = getCertificationListUiState + getCertificationListUiState = getCertificationListUiState, + getLectureSignUpHistoryUiState = getLectureSignUpHistoryUiState ) } @@ -143,6 +146,7 @@ private suspend fun getLectureData( internal fun CertificationScreen( modifier: Modifier = Modifier, getCertificationListUiState: GetCertificationListUiState, + getLectureSignUpHistoryUiState: GetLectureSignUpHistoryUiState, onHumanIconClicked: () -> Unit, onEditClicked: (id: UUID, title: String, date: LocalDate) -> Unit, onPlusClicked: () -> Unit, @@ -215,7 +219,7 @@ internal fun CertificationScreen( Text( modifier = modifier.align(Alignment.CenterHorizontally), text = "통신이 원활하지 않습니다..", - style = typography.titleSmall + style = typography.bodySmall ) } @@ -223,12 +227,35 @@ internal fun CertificationScreen( Text( modifier = modifier.align(Alignment.CenterHorizontally), text = "자격증이 없습니다..", - style = typography.titleSmall + style = typography.bodySmall, + color = colors.G4 ) } } Spacer(modifier = modifier.height(12.dp)) - FinishedLectureSection(data = lectureData) + when(getLectureSignUpHistoryUiState) { + is GetLectureSignUpHistoryUiState.Success -> { FinishedLectureSection(data = lectureData) } + is GetLectureSignUpHistoryUiState.Loading -> { + Box( + modifier = modifier.fillMaxWidth(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator( + modifier = modifier.then(Modifier.size(27.dp)), + color = colors.G2, + strokeWidth = 2.dp + ) + } + } + is GetLectureSignUpHistoryUiState.Error -> { + Text( + modifier = modifier.align(Alignment.CenterHorizontally).padding(top = 50.dp), + text = "통신이 원할하지 않습니다..", + style = typography.bodySmall, + color = colors.G4 + ) + } + } } } } @@ -274,6 +301,7 @@ fun CertificationScreenPre() { ) ) ), - getCertificationListUiState = GetCertificationListUiState.Loading + getCertificationListUiState = GetCertificationListUiState.Empty, + getLectureSignUpHistoryUiState = GetLectureSignUpHistoryUiState.Error ) } \ No newline at end of file From 905c21ff681fe7ef22090132de72c88a404bc04f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 15:58:52 +0900 Subject: [PATCH 116/141] :recycle: :: Apply UiState To CertificationViewModel(getLectureSignUpHistory) --- .../viewmodel/CertificationViewModel.kt | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt index df5c6c45..ffbce139 100644 --- a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt @@ -6,6 +6,7 @@ import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.msg.certification.viewmodel.uistate.GetCertificationListUiState +import com.msg.certification.viewmodel.uistate.GetLectureSignUpHistoryUiState import com.msg.common.event.Event import com.msg.common.errorhandling.errorHandling import com.msg.common.result.Result @@ -48,6 +49,9 @@ class CertificationViewModel @Inject constructor( private val _getCertificationListUiState = MutableStateFlow(GetCertificationListUiState.Loading) val getCertificationListUiState: StateFlow = _getCertificationListUiState.asStateFlow() + private val _getLectureSignUpHistoryUiState = MutableStateFlow(GetLectureSignUpHistoryUiState.Loading) + val getLectureSignUpHistoryUiState: StateFlow = _getLectureSignUpHistoryUiState.asStateFlow() + private val _getCertificationListResponse = MutableStateFlow>>(Event.Loading) val getCertificationListResponse = _getCertificationListResponse.asStateFlow() @@ -173,17 +177,15 @@ class CertificationViewModel @Inject constructor( internal fun getLectureSignUpHistory() = viewModelScope.launch { if (studentId != null) { - getLectureSignUpHistoryUseCase( - studentId = studentId - ).onSuccess { - it.catch { remoteError -> - _getLectureSignUpHistoryResponse.value = remoteError.errorHandling() - }.collect { response -> - _getLectureSignUpHistoryResponse.value = Event.Success(data = response) + getLectureSignUpHistoryUseCase(studentId = studentId) + .asResult() + .collectLatest { result -> + when(result) { + is Result.Loading -> { _getLectureSignUpHistoryUiState.value = GetLectureSignUpHistoryUiState.Loading } + is Result.Success -> { _getLectureSignUpHistoryUiState.value = GetLectureSignUpHistoryUiState.Success(result.data) } + is Result.Error -> { _getLectureSignUpHistoryUiState.value = GetLectureSignUpHistoryUiState.Error } + } } - }.onFailure { error -> - _getLectureSignUpHistoryResponse.value = error.errorHandling() - } } } From d7c0b5cacc25ed24e9ae4cf909b27917228111b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 16:19:04 +0900 Subject: [PATCH 117/141] :recycle: :: Use Flow To WriteCertificationUseCase --- .../domain/usecase/certification/WriteCertificationUseCase.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/domain/src/main/java/com/msg/domain/usecase/certification/WriteCertificationUseCase.kt b/core/domain/src/main/java/com/msg/domain/usecase/certification/WriteCertificationUseCase.kt index ddd3e643..93db9a6b 100644 --- a/core/domain/src/main/java/com/msg/domain/usecase/certification/WriteCertificationUseCase.kt +++ b/core/domain/src/main/java/com/msg/domain/usecase/certification/WriteCertificationUseCase.kt @@ -2,12 +2,12 @@ package com.msg.domain.usecase.certification import com.msg.data.repository.certification.CertificationRepository import com.msg.model.param.certification.WriteCertificationParam +import kotlinx.coroutines.flow.Flow import javax.inject.Inject class WriteCertificationUseCase @Inject constructor( private val certificationRepository: CertificationRepository ) { - suspend operator fun invoke(body: WriteCertificationParam) = runCatching { + operator fun invoke(body: WriteCertificationParam): Flow = certificationRepository.writeCertification(body = body) - } } \ No newline at end of file From 4903d846e3ece91261e64ed8fe1ea8ede160d34e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 16:19:26 +0900 Subject: [PATCH 118/141] :sparkles: :: Create WriteCertificationUiState --- .../viewmodel/uistate/WriteCertificationUiState.kt | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/WriteCertificationUiState.kt diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/WriteCertificationUiState.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/WriteCertificationUiState.kt new file mode 100644 index 00000000..ff0a3391 --- /dev/null +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/WriteCertificationUiState.kt @@ -0,0 +1,7 @@ +package com.msg.certification.viewmodel.uistate + +sealed interface WriteCertificationUiState { + data object Success: WriteCertificationUiState + data object Loading: WriteCertificationUiState + data class Error(val exception: Throwable): WriteCertificationUiState +} \ No newline at end of file From 3286f567f73087ac272148f65fb9bf2110f25957 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 16:19:56 +0900 Subject: [PATCH 119/141] :recycle: :: Apply WriteCertificationUiState To CertificationViewModel --- .../viewmodel/CertificationViewModel.kt | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt index ffbce139..5a7bf44d 100644 --- a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt @@ -7,6 +7,7 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.msg.certification.viewmodel.uistate.GetCertificationListUiState import com.msg.certification.viewmodel.uistate.GetLectureSignUpHistoryUiState +import com.msg.certification.viewmodel.uistate.WriteCertificationUiState import com.msg.common.event.Event import com.msg.common.errorhandling.errorHandling import com.msg.common.result.Result @@ -52,6 +53,9 @@ class CertificationViewModel @Inject constructor( private val _getLectureSignUpHistoryUiState = MutableStateFlow(GetLectureSignUpHistoryUiState.Loading) val getLectureSignUpHistoryUiState: StateFlow = _getLectureSignUpHistoryUiState.asStateFlow() + private val _writeCertificationUiState = MutableStateFlow(WriteCertificationUiState.Loading) + val writeCertificationUiState: StateFlow = _writeCertificationUiState.asStateFlow() + private val _getCertificationListResponse = MutableStateFlow>>(Event.Loading) val getCertificationListResponse = _getCertificationListResponse.asStateFlow() @@ -126,15 +130,15 @@ class CertificationViewModel @Inject constructor( name = name, acquisitionDate = acquisitionDate ) - ).onSuccess { - it.catch { remoteError -> - _writeCertificationResponse.value = remoteError.errorHandling() - }.collect { - _writeCertificationResponse.value = Event.Success() + ) + .asResult() + .collectLatest { result -> + when(result) { + is Result.Loading -> { _writeCertificationUiState.value = WriteCertificationUiState.Loading } + is Result.Success -> { _writeCertificationUiState.value = WriteCertificationUiState.Success } + is Result.Error -> { _writeCertificationUiState.value = WriteCertificationUiState.Error(result.exception) } + } } - }.onFailure { error -> - _writeCertificationResponse.value = error.errorHandling() - } } internal fun editCertification( From 792c1f7804dc24f604c3e8810c4a4a4cd11cd6a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 22:51:20 +0900 Subject: [PATCH 120/141] :memo: :: Add strings.xml To Other Strings --- .../src/main/res/values/strings.xml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/core/design-system/src/main/res/values/strings.xml b/core/design-system/src/main/res/values/strings.xml index be9b7822..4ecfecc1 100644 --- a/core/design-system/src/main/res/values/strings.xml +++ b/core/design-system/src/main/res/values/strings.xml @@ -84,6 +84,22 @@ 이름으로 검색... 전체 학생정보 + \'뒤로\'버튼 한번 더 누르시면 종료됩니다. + 학생회 권한인 학생만 요청 가능해요 + 서버 응답이 지연되고 있습니다, 잠시 후 다시 시도해주세요 + 서버 에러, 관리자에게 문의하세요 + 네트워크가 불안정합니다, 데이터나 와이파이 연결 상태를 확인해주세요 + 알 수 없는 오류가 발생했습니다 + 예상치 못한 오류가 발생했습니다 + 오류가 발생했습니다 + 자격증 등록을 완료되었습니다. + 자격증 등록을 실패하였습니다. + 자격증 수정을 완료하였습니다. + 자격증 수정을 실패하였습니다. + 학생정보를 불러오지 못했습니다. + 자격증 정보를 불러오지 못했습니다. + 데이터가 없습니다. + 강의 정보를 불러오지 못했습니다. 문의사항 답변 됨 답변 대기 중 From 606abea444784b414d8fb8694115cf505b300349 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 22:53:06 +0900 Subject: [PATCH 121/141] :heavy_plus_sign: :: Add Implementation To build.gradle.kts(:app) --- app/build.gradle.kts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 92a0641a..b41372ea 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -15,6 +15,8 @@ android { } dependencies { + implementation(project(":core:ui")) + implementation(project(":core:common")) implementation(project(":core:design-system")) implementation(project(":feature:login")) implementation(project(":feature:sign-up")) From fb13703a0c5a70c84547ba936092d06908a1de0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 22:54:00 +0900 Subject: [PATCH 122/141] :sparkles: :: Create errorToast(BitgoeulNavHost) --- .../navigation/BitgoeulNavHost.kt | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/msg/bitgoeul_android/navigation/BitgoeulNavHost.kt b/app/src/main/java/com/msg/bitgoeul_android/navigation/BitgoeulNavHost.kt index 13353029..f4dee234 100644 --- a/app/src/main/java/com/msg/bitgoeul_android/navigation/BitgoeulNavHost.kt +++ b/app/src/main/java/com/msg/bitgoeul_android/navigation/BitgoeulNavHost.kt @@ -2,6 +2,7 @@ package com.msg.bitgoeul_android.navigation import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext import androidx.navigation.compose.NavHost import com.bitgoeul.email.navigation.emailSendInformScreen import com.bitgoeul.email.navigation.inputEmailScreen @@ -18,6 +19,7 @@ import com.example.my_page.navigation.changePasswordScreen import com.example.my_page.navigation.myPageScreen import com.example.my_page.navigation.navigateToMyPage import com.example.my_page.navigation.navigateToPasswordChange +import com.msg.design_system.R import com.msg.bitgoeul_android.ui.BitgoeulAppState import com.msg.bitgoeul_android.ui.navigateWithPopUpToLogin import com.msg.certification.navigation.addCertificationScreen @@ -26,6 +28,12 @@ import com.msg.certification.navigation.navigateToAddCertificationPage import com.msg.club.navigation.clubDetailScreen import com.msg.club.navigation.clubScreen import com.msg.club.navigation.navigateToClubDetailPage +import com.msg.common.exception.ForBiddenException +import com.msg.common.exception.NetworkException +import com.msg.common.exception.OtherException +import com.msg.common.exception.ServerException +import com.msg.common.exception.TimeOutException +import com.msg.common.exception.UnknownException import com.msg.lecture.navigation.lectureDetailScreen import com.msg.lecture.navigation.lectureListScreen import com.msg.lecture.navigation.lectureTakingStudentListScreen @@ -46,6 +54,7 @@ import com.msg.student_activity.navigation.studentActivityScreen import com.msg.student_activity.navigation.studentAddActivityScreen import com.msg.student_activity.navigation.studentDetailActivityScreen import com.msg.student_activity.navigation.studentDetailSettingActivityScreen +import com.msg.ui.makeToast @Composable fun BitgoeulNavHost( @@ -53,7 +62,24 @@ fun BitgoeulNavHost( modifier: Modifier = Modifier, startDestination: String = loginRoute, ) { + val context = LocalContext.current val navController = appState.navController + + val createErrorToast: (throwable: Throwable?, message: Int?) -> Unit = { throwable, message -> + val errorMessage = throwable?.let { + when(it) { + is ForBiddenException -> R.string.error_for_bidden + is TimeOutException -> R.string.error_time_out + is ServerException -> R.string.error_server + is NetworkException -> R.string.error_no_internet + is OtherException -> R.string.error_other_http + is UnknownException -> R.string.error_un_known + else -> message + } + } ?: message ?: R.string.error_default + makeToast(context, context.getString(errorMessage)) + } + NavHost( navController = navController, startDestination = startDestination, @@ -139,7 +165,8 @@ fun BitgoeulNavHost( ) certificationScreen( onHumanClicked = navController::navigateToMyPage, - onEditClicked = navController::navigateToAddCertificationPage + onEditClicked = navController::navigateToAddCertificationPage, + createErrorToast = createErrorToast ) addCertificationScreen( onBackClicked = navController::navigateUp From 4424640a9c2c1e2140dcc406c564d278de85d6ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 22:55:23 +0900 Subject: [PATCH 123/141] :recycle: :: Use Coroutine Flow - EditCertificationUseCase --- .../domain/usecase/certification/EditCertificationUseCase.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/domain/src/main/java/com/msg/domain/usecase/certification/EditCertificationUseCase.kt b/core/domain/src/main/java/com/msg/domain/usecase/certification/EditCertificationUseCase.kt index 41cc0676..f2a54eb7 100644 --- a/core/domain/src/main/java/com/msg/domain/usecase/certification/EditCertificationUseCase.kt +++ b/core/domain/src/main/java/com/msg/domain/usecase/certification/EditCertificationUseCase.kt @@ -2,13 +2,13 @@ package com.msg.domain.usecase.certification import com.msg.data.repository.certification.CertificationRepository import com.msg.model.param.certification.WriteCertificationParam +import kotlinx.coroutines.flow.Flow import java.util.UUID import javax.inject.Inject class EditCertificationUseCase @Inject constructor( private val certificationRepository: CertificationRepository ) { - suspend operator fun invoke(id: UUID, body: WriteCertificationParam) = runCatching { + operator fun invoke(id: UUID, body: WriteCertificationParam): Flow = certificationRepository.editCertification(id = id, body = body) - } } \ No newline at end of file From 3569b6357cb16597b0466f7b3df284895f29005f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 22:55:55 +0900 Subject: [PATCH 124/141] :recycle: :: Use Coroutine Flow(GetStudentBelongClubUseCase) --- .../msg/domain/usecase/club/GetStudentBelongClubUseCase.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/domain/src/main/java/com/msg/domain/usecase/club/GetStudentBelongClubUseCase.kt b/core/domain/src/main/java/com/msg/domain/usecase/club/GetStudentBelongClubUseCase.kt index e7bbdc6a..5d8fd5ab 100644 --- a/core/domain/src/main/java/com/msg/domain/usecase/club/GetStudentBelongClubUseCase.kt +++ b/core/domain/src/main/java/com/msg/domain/usecase/club/GetStudentBelongClubUseCase.kt @@ -1,13 +1,14 @@ package com.msg.domain.usecase.club import com.msg.data.repository.club.ClubRepository +import com.msg.model.entity.club.StudentBelongClubEntity +import kotlinx.coroutines.flow.Flow import java.util.UUID import javax.inject.Inject class GetStudentBelongClubUseCase @Inject constructor( private val clubRepository: ClubRepository ) { - suspend operator fun invoke(id: Long, studentId: UUID) = runCatching { + operator fun invoke(id: Long, studentId: UUID): Flow = clubRepository.getStudentBelongClubDetail(id = id, studentId = studentId) - } } \ No newline at end of file From b75037859f624354866fe9d63813e7a44390fab0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 22:56:44 +0900 Subject: [PATCH 125/141] :fire: :: Fire Unused Import --- feature/login/src/main/java/com/bitgoeul/login/LoginScreen.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/feature/login/src/main/java/com/bitgoeul/login/LoginScreen.kt b/feature/login/src/main/java/com/bitgoeul/login/LoginScreen.kt index 61a59169..06cad962 100644 --- a/feature/login/src/main/java/com/bitgoeul/login/LoginScreen.kt +++ b/feature/login/src/main/java/com/bitgoeul/login/LoginScreen.kt @@ -16,7 +16,6 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Alignment From e001b7c4c782cd471211c301f7d3c7e66ca674a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 22:57:18 +0900 Subject: [PATCH 126/141] :sparkles: :: Create GetStudentBelongClubDetailUiState --- .../uistate/GetStudentBelongClubDetailUiState.kt | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetStudentBelongClubDetailUiState.kt diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetStudentBelongClubDetailUiState.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetStudentBelongClubDetailUiState.kt new file mode 100644 index 00000000..3bbf4801 --- /dev/null +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetStudentBelongClubDetailUiState.kt @@ -0,0 +1,10 @@ +package com.msg.certification.viewmodel.uistate + +import android.content.Context +import com.msg.model.entity.club.StudentBelongClubEntity + +sealed interface GetStudentBelongClubDetailUiState { + data class Success(val data: StudentBelongClubEntity): GetStudentBelongClubDetailUiState + data object Loading: GetStudentBelongClubDetailUiState + data class Error(val expectation: Throwable): GetStudentBelongClubDetailUiState +} \ No newline at end of file From 8b159e943dec1750150e67fcd738dbcac4de347a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 22:57:35 +0900 Subject: [PATCH 127/141] :sparkles: :: Create EditCertificationUiState --- .../viewmodel/uistate/EditCertificationUiState.kt | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/EditCertificationUiState.kt diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/EditCertificationUiState.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/EditCertificationUiState.kt new file mode 100644 index 00000000..cc88f112 --- /dev/null +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/EditCertificationUiState.kt @@ -0,0 +1,6 @@ +package com.msg.certification.viewmodel.uistate + +sealed interface EditCertificationUiState { + data object Success: EditCertificationUiState + data class Error(val exception: Throwable): EditCertificationUiState +} \ No newline at end of file From 2f55889aaaca05817ca9ac1630b4f7789ff96628 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 22:58:35 +0900 Subject: [PATCH 128/141] :recycle: :: Apply createErrorToast To Certification Navigation --- .../navigation/CertificationNavigation.kt | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/feature/certification/src/main/java/com/msg/certification/navigation/CertificationNavigation.kt b/feature/certification/src/main/java/com/msg/certification/navigation/CertificationNavigation.kt index d34ac30f..404e44a3 100644 --- a/feature/certification/src/main/java/com/msg/certification/navigation/CertificationNavigation.kt +++ b/feature/certification/src/main/java/com/msg/certification/navigation/CertificationNavigation.kt @@ -16,7 +16,11 @@ fun NavController.navigateToCertificationPage(navOptions: NavOptions? = null, cl this.navigate("$certificationRoute/$clubId/$studentId", navOptions) } -fun NavGraphBuilder.certificationScreen(onHumanClicked: () -> Unit, onEditClicked: () -> Unit) { +fun NavGraphBuilder.certificationScreen( + onHumanClicked: () -> Unit, + onEditClicked: () -> Unit, + createErrorToast: (throwable: Throwable?, message: Int?) -> Unit +) { composable( route = "certificationRoute/{clubId}/{studentId}", arguments = listOf( @@ -30,7 +34,8 @@ fun NavGraphBuilder.certificationScreen(onHumanClicked: () -> Unit, onEditClicke ) { CertificationScreenRoute( onHumanIconClicked = onHumanClicked, - onEditClicked = onEditClicked + onEditClicked = onEditClicked, + createErrorToast = createErrorToast ) } } @@ -39,11 +44,15 @@ fun NavController.navigateToAddCertificationPage(navOptions: NavOptions? = null) this.navigate(addCertificationRoute, navOptions) } -fun NavGraphBuilder.addCertificationScreen(onBackClicked: () -> Unit) { +fun NavGraphBuilder.addCertificationScreen( + onBackClicked: () -> Unit, + createErrorToast: (throwable: Throwable?, message: Int?) -> Unit +) { composable(route = addCertificationRoute) { AddCertificationScreenRoute( onBackClicked = onBackClicked, - onAddClicked = onBackClicked + onAddClicked = onBackClicked, + createErrorToast = createErrorToast ) } } \ No newline at end of file From 21019ebf5a146ba86722a295c2b25f6f121b8d73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 22:59:08 +0900 Subject: [PATCH 129/141] :recycle: :: Use data class State Error - GetCertificationListUiState --- .../viewmodel/uistate/GetCertificationListUiState.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetCertificationListUiState.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetCertificationListUiState.kt index 63d22f6c..1516cb71 100644 --- a/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetCertificationListUiState.kt +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetCertificationListUiState.kt @@ -4,7 +4,7 @@ import com.msg.model.entity.certification.CertificationListEntity sealed interface GetCertificationListUiState { data class Success(val data: List): GetCertificationListUiState - data object Error: GetCertificationListUiState + data class Error(val expectation: Throwable): GetCertificationListUiState data object Loading: GetCertificationListUiState data object Empty: GetCertificationListUiState } \ No newline at end of file From 828e38006e6549d12923b3932ff4042c8c98943c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 22:59:41 +0900 Subject: [PATCH 130/141] :recycle: :: Use data class State Error - GetLectureSignUpHistoryUiState --- .../viewmodel/uistate/GetLectureSignUpHistoryUiState.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetLectureSignUpHistoryUiState.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetLectureSignUpHistoryUiState.kt index e82ac2c5..daeaa956 100644 --- a/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetLectureSignUpHistoryUiState.kt +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetLectureSignUpHistoryUiState.kt @@ -5,5 +5,5 @@ import com.msg.model.entity.lecture.GetLectureSignUpHistoryEntity sealed interface GetLectureSignUpHistoryUiState { data class Success(val data: GetLectureSignUpHistoryEntity): GetLectureSignUpHistoryUiState data object Loading: GetLectureSignUpHistoryUiState - data object Error: GetLectureSignUpHistoryUiState + data class Error(val expectation: Throwable?): GetLectureSignUpHistoryUiState } \ No newline at end of file From 1121a1cb266b7e1f4e09cd52c59e4e3a69faa99e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 23:00:44 +0900 Subject: [PATCH 131/141] :recycle: :: Apply Before Changed(Apply UiState, Changed Logic) - CertificationViewModel --- .../viewmodel/CertificationViewModel.kt | 134 +++++++++++++----- 1 file changed, 95 insertions(+), 39 deletions(-) diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt index 5a7bf44d..5e0fd69e 100644 --- a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt @@ -5,8 +5,10 @@ import androidx.compose.runtime.mutableStateOf import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.msg.certification.viewmodel.uistate.EditCertificationUiState import com.msg.certification.viewmodel.uistate.GetCertificationListUiState import com.msg.certification.viewmodel.uistate.GetLectureSignUpHistoryUiState +import com.msg.certification.viewmodel.uistate.GetStudentBelongClubDetailUiState import com.msg.certification.viewmodel.uistate.WriteCertificationUiState import com.msg.common.event.Event import com.msg.common.errorhandling.errorHandling @@ -47,16 +49,33 @@ class CertificationViewModel @Inject constructor( private val role = getRole().toString() - private val _getCertificationListUiState = MutableStateFlow(GetCertificationListUiState.Loading) - val getCertificationListUiState: StateFlow = _getCertificationListUiState.asStateFlow() + private val _getCertificationListUiState = + MutableStateFlow(GetCertificationListUiState.Loading) + val getCertificationListUiState: StateFlow = + _getCertificationListUiState.asStateFlow() - private val _getLectureSignUpHistoryUiState = MutableStateFlow(GetLectureSignUpHistoryUiState.Loading) - val getLectureSignUpHistoryUiState: StateFlow = _getLectureSignUpHistoryUiState.asStateFlow() + private val _getLectureSignUpHistoryUiState = + MutableStateFlow(GetLectureSignUpHistoryUiState.Loading) + val getLectureSignUpHistoryUiState: StateFlow = + _getLectureSignUpHistoryUiState.asStateFlow() - private val _writeCertificationUiState = MutableStateFlow(WriteCertificationUiState.Loading) - val writeCertificationUiState: StateFlow = _writeCertificationUiState.asStateFlow() + private val _writeCertificationUiState = + MutableStateFlow(WriteCertificationUiState.Success) + val writeCertificationUiState: StateFlow = + _writeCertificationUiState.asStateFlow() - private val _getCertificationListResponse = MutableStateFlow>>(Event.Loading) + private val _editCertificationUiState = + MutableStateFlow(EditCertificationUiState.Success) + val editCertificationUiState: StateFlow = + _editCertificationUiState.asStateFlow() + + private val _getStudentBelongClubDetailUiState = + MutableStateFlow(GetStudentBelongClubDetailUiState.Loading) + val getStudentBelongClubDetailUiState: StateFlow = + _getStudentBelongClubDetailUiState.asStateFlow() + + private val _getCertificationListResponse = + MutableStateFlow>>(Event.Loading) val getCertificationListResponse = _getCertificationListResponse.asStateFlow() private val _writeCertificationResponse = MutableStateFlow>(Event.Loading) @@ -65,10 +84,12 @@ class CertificationViewModel @Inject constructor( private val _editCertificationResponse = MutableStateFlow>(Event.Loading) val editCertificationResponse = _editCertificationResponse.asStateFlow() - private val _getStudentBelongResponse = MutableStateFlow>(Event.Loading) + private val _getStudentBelongResponse = + MutableStateFlow>(Event.Loading) val getStudentBelongResponse = _getStudentBelongResponse.asStateFlow() - private val _getLectureSignUpHistoryResponse = MutableStateFlow>(Event.Loading) + private val _getLectureSignUpHistoryResponse = + MutableStateFlow>(Event.Loading) val getLectureSignUpHistoryResponse = _getLectureSignUpHistoryResponse.asStateFlow() private val studentId = UUID.fromString(savedStateHandle.get("studentId")) @@ -78,7 +99,8 @@ class CertificationViewModel @Inject constructor( var selectedCertificationId = mutableStateOf(null) private set - internal var selectedTitle = savedStateHandle.getStateFlow(key = SELECTED_TITLE, initialValue = "") + internal var selectedTitle = + savedStateHandle.getStateFlow(key = SELECTED_TITLE, initialValue = "") var selectedDate = mutableStateOf(null) private set @@ -107,16 +129,23 @@ class CertificationViewModel @Inject constructor( getCertificationListUseCase(role = role, studentId = studentId) .asResult() .collectLatest { result -> - when(result) { - is Result.Loading -> { _getCertificationListUiState.value = GetCertificationListUiState.Loading } + when (result) { + is Result.Loading -> { + _getCertificationListUiState.value = GetCertificationListUiState.Loading + } + is Result.Success -> { if (result.data.isEmpty()) { _getCertificationListUiState.value = GetCertificationListUiState.Empty } else { - _getCertificationListUiState.value = GetCertificationListUiState.Success(result.data) + _getCertificationListUiState.value = + GetCertificationListUiState.Success(result.data) } } - is Result.Error -> { _getCertificationListUiState.value = GetCertificationListUiState.Error } + + is Result.Error -> { + _getCertificationListUiState.value = GetCertificationListUiState.Error + } } } } @@ -133,10 +162,17 @@ class CertificationViewModel @Inject constructor( ) .asResult() .collectLatest { result -> - when(result) { - is Result.Loading -> { _writeCertificationUiState.value = WriteCertificationUiState.Loading } - is Result.Success -> { _writeCertificationUiState.value = WriteCertificationUiState.Success } - is Result.Error -> { _writeCertificationUiState.value = WriteCertificationUiState.Error(result.exception) } + when (result) { + is Result.Success -> { + _writeCertificationUiState.value = WriteCertificationUiState.Success + } + + is Result.Error -> { + _writeCertificationUiState.value = + WriteCertificationUiState.Error(result.exception) + } + + else -> {} } } } @@ -151,15 +187,22 @@ class CertificationViewModel @Inject constructor( name = name, acquisitionDate = acquisitionDate ) - ).onSuccess { - it.catch { remoteError -> - _editCertificationResponse.value = remoteError.errorHandling() - }.collect { - _editCertificationResponse.value = Event.Success() + ) + .asResult() + .collectLatest { result -> + when (result) { + is Result.Success -> { + _editCertificationUiState.value = EditCertificationUiState.Success + } + + is Result.Error -> { + _editCertificationUiState.value = + EditCertificationUiState.Error(result.exception) + } + + else -> {} + } } - }.onFailure { error -> - _editCertificationResponse.value = error.errorHandling() - } } internal fun getStudentBelong() = viewModelScope.launch { @@ -167,15 +210,15 @@ class CertificationViewModel @Inject constructor( getStudentBelongClubUseCase( id = clubId, studentId = studentId - ).onSuccess { - it.catch { remoteError -> - _getStudentBelongResponse.value = remoteError.errorHandling() - }.collect { response -> - _getStudentBelongResponse.value = Event.Success(data = response) + ) + .asResult() + .collectLatest { result -> + when (result) { + is Result.Loading -> { _getStudentBelongClubDetailUiState.value = GetStudentBelongClubDetailUiState.Loading } + is Result.Success -> { _getStudentBelongClubDetailUiState.value = GetStudentBelongClubDetailUiState.Success(result.data) } + is Result.Error -> { _getStudentBelongClubDetailUiState.value = GetStudentBelongClubDetailUiState.Error(result.exception) } + } } - }.onFailure { error -> - _getStudentBelongResponse.value = error.errorHandling() - } } } @@ -184,10 +227,21 @@ class CertificationViewModel @Inject constructor( getLectureSignUpHistoryUseCase(studentId = studentId) .asResult() .collectLatest { result -> - when(result) { - is Result.Loading -> { _getLectureSignUpHistoryUiState.value = GetLectureSignUpHistoryUiState.Loading } - is Result.Success -> { _getLectureSignUpHistoryUiState.value = GetLectureSignUpHistoryUiState.Success(result.data) } - is Result.Error -> { _getLectureSignUpHistoryUiState.value = GetLectureSignUpHistoryUiState.Error } + when (result) { + is Result.Loading -> { + _getLectureSignUpHistoryUiState.value = + GetLectureSignUpHistoryUiState.Loading + } + + is Result.Success -> { + _getLectureSignUpHistoryUiState.value = + GetLectureSignUpHistoryUiState.Success(result.data) + } + + is Result.Error -> { + _getLectureSignUpHistoryUiState.value = + GetLectureSignUpHistoryUiState.Error + } } } } @@ -197,5 +251,7 @@ class CertificationViewModel @Inject constructor( getAuthorityUseCase() } - internal fun onSelectedTitleChange(value: String) { savedStateHandle[SELECTED_TITLE] = value } + internal fun onSelectedTitleChange(value: String) { + savedStateHandle[SELECTED_TITLE] = value + } } \ No newline at end of file From d34336d19e84809dd08969ec821aac192e61901d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 23:01:39 +0900 Subject: [PATCH 132/141] :fire: :: Fire Unused State(Loading) - WriteCertificationUiState --- .../certification/viewmodel/uistate/WriteCertificationUiState.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/WriteCertificationUiState.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/WriteCertificationUiState.kt index ff0a3391..7d53ab74 100644 --- a/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/WriteCertificationUiState.kt +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/WriteCertificationUiState.kt @@ -2,6 +2,5 @@ package com.msg.certification.viewmodel.uistate sealed interface WriteCertificationUiState { data object Success: WriteCertificationUiState - data object Loading: WriteCertificationUiState data class Error(val exception: Throwable): WriteCertificationUiState } \ No newline at end of file From 8f76f47d5850c823b1aaf52192978f6dfd67d0b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 23:02:20 +0900 Subject: [PATCH 133/141] :recycle: :: Apply ViewModel Changed(Check Before Commit) --- .../certification/AddCertificationScreen.kt | 43 +++++++++++++++++-- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/feature/certification/src/main/java/com/msg/certification/AddCertificationScreen.kt b/feature/certification/src/main/java/com/msg/certification/AddCertificationScreen.kt index e6244ce1..281c1831 100644 --- a/feature/certification/src/main/java/com/msg/certification/AddCertificationScreen.kt +++ b/feature/certification/src/main/java/com/msg/certification/AddCertificationScreen.kt @@ -24,6 +24,9 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.msg.certification.component.AddAcquisitionDateSection import com.msg.certification.component.AddCertificationSection import com.msg.certification.viewmodel.CertificationViewModel +import com.msg.certification.viewmodel.uistate.EditCertificationUiState +import com.msg.certification.viewmodel.uistate.WriteCertificationUiState +import com.msg.design_system.R import com.msg.design_system.component.button.BitgoeulButton import com.msg.design_system.component.modifier.padding.paddingHorizontal import com.msg.design_system.component.topbar.DetailSettingTopBar @@ -37,11 +40,17 @@ import java.time.LocalDate internal fun AddCertificationScreenRoute( viewModel: CertificationViewModel = hiltViewModel(LocalContext.current as ComponentActivity), onBackClicked: () -> Unit, - onAddClicked: () -> Unit + onAddClicked: () -> Unit, + createErrorToast: (throwable: Throwable?, message: Int?) -> Unit ) { + val writeCertificationUiState by viewModel.writeCertificationUiState.collectAsStateWithLifecycle() + val editCertificationUiState by viewModel.editCertificationUiState.collectAsStateWithLifecycle() + val selectedTitle by viewModel.selectedTitle.collectAsStateWithLifecycle() AddCertificationScreen( + writeCertificationUiState = writeCertificationUiState, + editCertificationUiState = editCertificationUiState, selectedName = selectedTitle, selectedDate = viewModel.selectedDate.value, onSelectedNameChange = viewModel::onSelectedTitleChange, @@ -51,22 +60,46 @@ internal fun AddCertificationScreenRoute( viewModel.editCertification(name = name, acquisitionDate = acquisitionDate) } ?: viewModel.writeCertification(name = name, acquisitionDate = acquisitionDate) onAddClicked() - } + }, + createErrorToast = createErrorToast ) } @Composable internal fun AddCertificationScreen( modifier: Modifier = Modifier, + writeCertificationUiState: WriteCertificationUiState, + editCertificationUiState: EditCertificationUiState, focusManager: FocusManager = LocalFocusManager.current, selectedName: String, onSelectedNameChange: (String) -> Unit, onBackClicked: () -> Unit, selectedDate: LocalDate?, - onAddClicked: (name: String, acquisitionDate: LocalDate) -> Unit + onAddClicked: (name: String, acquisitionDate: LocalDate) -> Unit, + createErrorToast: (throwable: Throwable?, message: Int?) -> Unit ) { + val context = LocalContext.current + val (isDate, setIsDate) = rememberSaveable { mutableStateOf(selectedDate) } + when(writeCertificationUiState) { + is WriteCertificationUiState.Success -> { + makeToast(context, R.string.success_certification_write.toString()) + } + is WriteCertificationUiState.Error -> { + createErrorToast(writeCertificationUiState.exception, R.string.fail_certification_write) + } + } + + when(editCertificationUiState) { + is EditCertificationUiState.Success -> { + makeToast(context, R.string.success_certification_edit.toString()) + } + is EditCertificationUiState.Error -> { + createErrorToast(editCertificationUiState.exception, R.string.fail_certification_edit) + } + } + BitgoeulAndroidTheme { colors, _ -> Box( modifier = modifier @@ -78,7 +111,6 @@ internal fun AddCertificationScreen( } } ) { - val context = LocalContext.current Column( modifier = modifier .fillMaxSize() @@ -131,5 +163,8 @@ fun AddCertificationScreenPre() { selectedDate = null, focusManager = LocalFocusManager.current, onSelectedNameChange = {}, + writeCertificationUiState = WriteCertificationUiState.Success, + editCertificationUiState = EditCertificationUiState.Success, + createErrorToast = {_, _ -> } ) } \ No newline at end of file From 2b05a7e46164b4734bef364ca451082134848f4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 23:03:01 +0900 Subject: [PATCH 134/141] :recycle: :: Apply ViewModel Changed And Change Logic --- .../msg/certification/CertificationScreen.kt | 61 +++++++++++-------- 1 file changed, 36 insertions(+), 25 deletions(-) diff --git a/feature/certification/src/main/java/com/msg/certification/CertificationScreen.kt b/feature/certification/src/main/java/com/msg/certification/CertificationScreen.kt index 90134785..76d35b0e 100644 --- a/feature/certification/src/main/java/com/msg/certification/CertificationScreen.kt +++ b/feature/certification/src/main/java/com/msg/certification/CertificationScreen.kt @@ -32,6 +32,7 @@ import com.msg.common.event.Event import com.msg.certification.viewmodel.CertificationViewModel import com.msg.certification.viewmodel.uistate.GetCertificationListUiState import com.msg.certification.viewmodel.uistate.GetLectureSignUpHistoryUiState +import com.msg.certification.viewmodel.uistate.GetStudentBelongClubDetailUiState import com.msg.design_system.R import com.msg.design_system.component.icon.HumanIcon import com.msg.design_system.theme.BitgoeulAndroidTheme @@ -40,6 +41,7 @@ import com.msg.model.entity.club.StudentBelongClubEntity import com.msg.model.entity.lecture.GetLectureSignUpHistoryEntity import com.msg.model.entity.lecture.SignUpLectures import com.msg.ui.DevicePreviews +import com.msg.ui.makeToast import java.time.LocalDate import java.util.UUID @@ -47,10 +49,12 @@ import java.util.UUID internal fun CertificationScreenRoute( viewModel: CertificationViewModel = hiltViewModel(LocalContext.current as ComponentActivity), onHumanIconClicked: () -> Unit, - onEditClicked: () -> Unit + onEditClicked: () -> Unit, + createErrorToast: (throwable: Throwable?, message: Int?) -> Unit ) { val getCertificationListUiState by viewModel.getCertificationListUiState.collectAsStateWithLifecycle() val getLectureSignUpHistoryUiState by viewModel.getLectureSignUpHistoryUiState.collectAsStateWithLifecycle() + val getStudentBelongClubDetailUiState by viewModel.getStudentBelongClubDetailUiState.collectAsStateWithLifecycle() viewModel.getCertificationList() viewModel.getStudentBelong() @@ -93,7 +97,9 @@ internal fun CertificationScreenRoute( certificationData = viewModel.certificationList, lectureData = viewModel.lectureData.value, getCertificationListUiState = getCertificationListUiState, - getLectureSignUpHistoryUiState = getLectureSignUpHistoryUiState + getLectureSignUpHistoryUiState = getLectureSignUpHistoryUiState, + getStudentBelongClubDetailUiState = getStudentBelongClubDetailUiState, + createErrorToast = createErrorToast ) } @@ -145,14 +151,16 @@ private suspend fun getLectureData( @Composable internal fun CertificationScreen( modifier: Modifier = Modifier, + createErrorToast: (throwable: Throwable?, message: Int?) -> Unit, getCertificationListUiState: GetCertificationListUiState, getLectureSignUpHistoryUiState: GetLectureSignUpHistoryUiState, + getStudentBelongClubDetailUiState: GetStudentBelongClubDetailUiState, onHumanIconClicked: () -> Unit, onEditClicked: (id: UUID, title: String, date: LocalDate) -> Unit, onPlusClicked: () -> Unit, studentData: StudentBelongClubEntity, certificationData: List, - lectureData: GetLectureSignUpHistoryEntity + lectureData: GetLectureSignUpHistoryEntity, ) { BitgoeulAndroidTheme { colors, typography -> Box( @@ -160,6 +168,7 @@ internal fun CertificationScreen( .fillMaxSize() .background(color = colors.WHITE) ) { + val context = LocalContext.current Column( modifier = modifier .fillMaxSize() @@ -183,7 +192,24 @@ internal fun CertificationScreen( ) } Spacer(modifier = modifier.height(24.dp)) - StudentInfoSection(data = studentData) + when(getStudentBelongClubDetailUiState) { + is GetStudentBelongClubDetailUiState.Success -> { StudentInfoSection(data = studentData) } + is GetStudentBelongClubDetailUiState.Loading -> { + Box( + modifier = modifier.fillMaxWidth(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator( + modifier = modifier.then(Modifier.size(27.dp)), + color = colors.G2, + strokeWidth = 2.dp + ) + } + } + is GetStudentBelongClubDetailUiState.Error -> { + createErrorToast(getStudentBelongClubDetailUiState.expectation, R.string.fail_get_student_club_detail) + } + } Spacer(modifier = modifier.height(24.dp)) HorizontalDivider( modifier = modifier.fillMaxWidth(), @@ -201,7 +227,6 @@ internal fun CertificationScreen( data = certificationData ) } - is GetCertificationListUiState.Loading -> { Box( modifier = modifier.fillMaxWidth(), @@ -214,22 +239,11 @@ internal fun CertificationScreen( ) } } - is GetCertificationListUiState.Error -> { - Text( - modifier = modifier.align(Alignment.CenterHorizontally), - text = "통신이 원활하지 않습니다..", - style = typography.bodySmall - ) + createErrorToast(getCertificationListUiState.expectation, R.string.fail_get_certification_list) } - is GetCertificationListUiState.Empty -> { - Text( - modifier = modifier.align(Alignment.CenterHorizontally), - text = "자격증이 없습니다..", - style = typography.bodySmall, - color = colors.G4 - ) + makeToast(context, R.string.empty_state.toString()) } } Spacer(modifier = modifier.height(12.dp)) @@ -248,12 +262,7 @@ internal fun CertificationScreen( } } is GetLectureSignUpHistoryUiState.Error -> { - Text( - modifier = modifier.align(Alignment.CenterHorizontally).padding(top = 50.dp), - text = "통신이 원할하지 않습니다..", - style = typography.bodySmall, - color = colors.G4 - ) + createErrorToast(getLectureSignUpHistoryUiState.expectation, R.string.fail_get_lecture_list) } } } @@ -302,6 +311,8 @@ fun CertificationScreenPre() { ) ), getCertificationListUiState = GetCertificationListUiState.Empty, - getLectureSignUpHistoryUiState = GetLectureSignUpHistoryUiState.Error + getLectureSignUpHistoryUiState = GetLectureSignUpHistoryUiState.Error(expectation = Throwable("통신이 원할하지 않습니다.")), + getStudentBelongClubDetailUiState = GetStudentBelongClubDetailUiState.Error(expectation = Throwable("통신이 원할하지 않습니다.")), + createErrorToast = { _, _ -> } ) } \ No newline at end of file From 302a1d988e56db7086e72b4520f07d2e3320e355 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 23:15:09 +0900 Subject: [PATCH 135/141] :recycle: :: Fire Line Spacing And Changed Error State Logic --- .../viewmodel/CertificationViewModel.kt | 42 ++++--------------- 1 file changed, 9 insertions(+), 33 deletions(-) diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt index 5e0fd69e..d4f3ed8c 100644 --- a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt @@ -138,14 +138,9 @@ class CertificationViewModel @Inject constructor( if (result.data.isEmpty()) { _getCertificationListUiState.value = GetCertificationListUiState.Empty } else { - _getCertificationListUiState.value = - GetCertificationListUiState.Success(result.data) - } - } - - is Result.Error -> { - _getCertificationListUiState.value = GetCertificationListUiState.Error + _getCertificationListUiState.value = GetCertificationListUiState.Success(result.data) } } + is Result.Error -> { _getCertificationListUiState.value = GetCertificationListUiState.Error(result.exception) } } } } @@ -163,15 +158,8 @@ class CertificationViewModel @Inject constructor( .asResult() .collectLatest { result -> when (result) { - is Result.Success -> { - _writeCertificationUiState.value = WriteCertificationUiState.Success - } - - is Result.Error -> { - _writeCertificationUiState.value = - WriteCertificationUiState.Error(result.exception) - } - + is Result.Success -> { _writeCertificationUiState.value = WriteCertificationUiState.Success } + is Result.Error -> { _writeCertificationUiState.value = WriteCertificationUiState.Error(result.exception) } else -> {} } } @@ -191,15 +179,8 @@ class CertificationViewModel @Inject constructor( .asResult() .collectLatest { result -> when (result) { - is Result.Success -> { - _editCertificationUiState.value = EditCertificationUiState.Success - } - - is Result.Error -> { - _editCertificationUiState.value = - EditCertificationUiState.Error(result.exception) - } - + is Result.Success -> { _editCertificationUiState.value = EditCertificationUiState.Success } + is Result.Error -> { _editCertificationUiState.value = EditCertificationUiState.Error(result.exception) } else -> {} } } @@ -229,18 +210,13 @@ class CertificationViewModel @Inject constructor( .collectLatest { result -> when (result) { is Result.Loading -> { - _getLectureSignUpHistoryUiState.value = - GetLectureSignUpHistoryUiState.Loading + _getLectureSignUpHistoryUiState.value = GetLectureSignUpHistoryUiState.Loading } - is Result.Success -> { - _getLectureSignUpHistoryUiState.value = - GetLectureSignUpHistoryUiState.Success(result.data) + _getLectureSignUpHistoryUiState.value = GetLectureSignUpHistoryUiState.Success(result.data) } - is Result.Error -> { - _getLectureSignUpHistoryUiState.value = - GetLectureSignUpHistoryUiState.Error + _getLectureSignUpHistoryUiState.value = GetLectureSignUpHistoryUiState.Error(result.exception) } } } From 3f90b1dfad0a02dcf3404de5829823c794a6ccda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 23:15:23 +0900 Subject: [PATCH 136/141] :recycle: :: Add createErrorToast --- .../com/msg/bitgoeul_android/navigation/BitgoeulNavHost.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/msg/bitgoeul_android/navigation/BitgoeulNavHost.kt b/app/src/main/java/com/msg/bitgoeul_android/navigation/BitgoeulNavHost.kt index f4dee234..95c7fa1b 100644 --- a/app/src/main/java/com/msg/bitgoeul_android/navigation/BitgoeulNavHost.kt +++ b/app/src/main/java/com/msg/bitgoeul_android/navigation/BitgoeulNavHost.kt @@ -169,7 +169,8 @@ fun BitgoeulNavHost( createErrorToast = createErrorToast ) addCertificationScreen( - onBackClicked = navController::navigateUp + onBackClicked = navController::navigateUp, + createErrorToast = createErrorToast ) } } \ No newline at end of file From 0b9dcbc8aeeeae81a15fd28e992c7dc9d6290c00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 23:24:04 +0900 Subject: [PATCH 137/141] :fire: :: Fire Unused Import --- .../viewmodel/uistate/GetStudentBelongClubDetailUiState.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetStudentBelongClubDetailUiState.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetStudentBelongClubDetailUiState.kt index 3bbf4801..3dcae3e9 100644 --- a/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetStudentBelongClubDetailUiState.kt +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/uistate/GetStudentBelongClubDetailUiState.kt @@ -1,6 +1,5 @@ package com.msg.certification.viewmodel.uistate -import android.content.Context import com.msg.model.entity.club.StudentBelongClubEntity sealed interface GetStudentBelongClubDetailUiState { From 89be535cce2c5da4b1244f23027e19d569006849 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 23:32:40 +0900 Subject: [PATCH 138/141] :fire: :: Fire Line Spacing --- .../viewmodel/CertificationViewModel.kt | 62 +++++++------------ 1 file changed, 21 insertions(+), 41 deletions(-) diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt index d4f3ed8c..f3e7815f 100644 --- a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt @@ -49,33 +49,22 @@ class CertificationViewModel @Inject constructor( private val role = getRole().toString() - private val _getCertificationListUiState = - MutableStateFlow(GetCertificationListUiState.Loading) - val getCertificationListUiState: StateFlow = - _getCertificationListUiState.asStateFlow() - - private val _getLectureSignUpHistoryUiState = - MutableStateFlow(GetLectureSignUpHistoryUiState.Loading) - val getLectureSignUpHistoryUiState: StateFlow = - _getLectureSignUpHistoryUiState.asStateFlow() - - private val _writeCertificationUiState = - MutableStateFlow(WriteCertificationUiState.Success) - val writeCertificationUiState: StateFlow = - _writeCertificationUiState.asStateFlow() - - private val _editCertificationUiState = - MutableStateFlow(EditCertificationUiState.Success) - val editCertificationUiState: StateFlow = - _editCertificationUiState.asStateFlow() - - private val _getStudentBelongClubDetailUiState = - MutableStateFlow(GetStudentBelongClubDetailUiState.Loading) - val getStudentBelongClubDetailUiState: StateFlow = - _getStudentBelongClubDetailUiState.asStateFlow() - - private val _getCertificationListResponse = - MutableStateFlow>>(Event.Loading) + private val _getCertificationListUiState = MutableStateFlow(GetCertificationListUiState.Loading) + val getCertificationListUiState: StateFlow = _getCertificationListUiState.asStateFlow() + + private val _getLectureSignUpHistoryUiState = MutableStateFlow(GetLectureSignUpHistoryUiState.Loading) + val getLectureSignUpHistoryUiState: StateFlow = _getLectureSignUpHistoryUiState.asStateFlow() + + private val _writeCertificationUiState = MutableStateFlow(WriteCertificationUiState.Success) + val writeCertificationUiState: StateFlow = _writeCertificationUiState.asStateFlow() + + private val _editCertificationUiState = MutableStateFlow(EditCertificationUiState.Success) + val editCertificationUiState: StateFlow = _editCertificationUiState.asStateFlow() + + private val _getStudentBelongClubDetailUiState = MutableStateFlow(GetStudentBelongClubDetailUiState.Loading) + val getStudentBelongClubDetailUiState: StateFlow = _getStudentBelongClubDetailUiState.asStateFlow() + + private val _getCertificationListResponse = MutableStateFlow>>(Event.Loading) val getCertificationListResponse = _getCertificationListResponse.asStateFlow() private val _writeCertificationResponse = MutableStateFlow>(Event.Loading) @@ -84,12 +73,10 @@ class CertificationViewModel @Inject constructor( private val _editCertificationResponse = MutableStateFlow>(Event.Loading) val editCertificationResponse = _editCertificationResponse.asStateFlow() - private val _getStudentBelongResponse = - MutableStateFlow>(Event.Loading) + private val _getStudentBelongResponse = MutableStateFlow>(Event.Loading) val getStudentBelongResponse = _getStudentBelongResponse.asStateFlow() - private val _getLectureSignUpHistoryResponse = - MutableStateFlow>(Event.Loading) + private val _getLectureSignUpHistoryResponse = MutableStateFlow>(Event.Loading) val getLectureSignUpHistoryResponse = _getLectureSignUpHistoryResponse.asStateFlow() private val studentId = UUID.fromString(savedStateHandle.get("studentId")) @@ -133,7 +120,6 @@ class CertificationViewModel @Inject constructor( is Result.Loading -> { _getCertificationListUiState.value = GetCertificationListUiState.Loading } - is Result.Success -> { if (result.data.isEmpty()) { _getCertificationListUiState.value = GetCertificationListUiState.Empty @@ -209,15 +195,9 @@ class CertificationViewModel @Inject constructor( .asResult() .collectLatest { result -> when (result) { - is Result.Loading -> { - _getLectureSignUpHistoryUiState.value = GetLectureSignUpHistoryUiState.Loading - } - is Result.Success -> { - _getLectureSignUpHistoryUiState.value = GetLectureSignUpHistoryUiState.Success(result.data) - } - is Result.Error -> { - _getLectureSignUpHistoryUiState.value = GetLectureSignUpHistoryUiState.Error(result.exception) - } + is Result.Loading -> { _getLectureSignUpHistoryUiState.value = GetLectureSignUpHistoryUiState.Loading } + is Result.Success -> { _getLectureSignUpHistoryUiState.value = GetLectureSignUpHistoryUiState.Success(result.data) } + is Result.Error -> { _getLectureSignUpHistoryUiState.value = GetLectureSignUpHistoryUiState.Error(result.exception) } } } } From 3216beab1d6ae2e48b630a7b86884fefa50a50e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 23:00:44 +0900 Subject: [PATCH 139/141] :recycle: :: Apply Before Changed(Apply UiState, Changed Logic) - CertificationViewModel --- .../viewmodel/CertificationViewModel.kt | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt index f3e7815f..7c022103 100644 --- a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt @@ -49,11 +49,15 @@ class CertificationViewModel @Inject constructor( private val role = getRole().toString() - private val _getCertificationListUiState = MutableStateFlow(GetCertificationListUiState.Loading) - val getCertificationListUiState: StateFlow = _getCertificationListUiState.asStateFlow() + private val _getCertificationListUiState = + MutableStateFlow(GetCertificationListUiState.Loading) + val getCertificationListUiState: StateFlow = + _getCertificationListUiState.asStateFlow() - private val _getLectureSignUpHistoryUiState = MutableStateFlow(GetLectureSignUpHistoryUiState.Loading) - val getLectureSignUpHistoryUiState: StateFlow = _getLectureSignUpHistoryUiState.asStateFlow() + private val _getLectureSignUpHistoryUiState = + MutableStateFlow(GetLectureSignUpHistoryUiState.Loading) + val getLectureSignUpHistoryUiState: StateFlow = + _getLectureSignUpHistoryUiState.asStateFlow() private val _writeCertificationUiState = MutableStateFlow(WriteCertificationUiState.Success) val writeCertificationUiState: StateFlow = _writeCertificationUiState.asStateFlow() @@ -73,10 +77,12 @@ class CertificationViewModel @Inject constructor( private val _editCertificationResponse = MutableStateFlow>(Event.Loading) val editCertificationResponse = _editCertificationResponse.asStateFlow() - private val _getStudentBelongResponse = MutableStateFlow>(Event.Loading) + private val _getStudentBelongResponse = + MutableStateFlow>(Event.Loading) val getStudentBelongResponse = _getStudentBelongResponse.asStateFlow() - private val _getLectureSignUpHistoryResponse = MutableStateFlow>(Event.Loading) + private val _getLectureSignUpHistoryResponse = + MutableStateFlow>(Event.Loading) val getLectureSignUpHistoryResponse = _getLectureSignUpHistoryResponse.asStateFlow() private val studentId = UUID.fromString(savedStateHandle.get("studentId")) From ee7d9b434e2dc4b4037badebaf8af3a11747e4de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Mon, 9 Sep 2024 23:32:40 +0900 Subject: [PATCH 140/141] :fire: :: Fire Line Spacing --- .../viewmodel/CertificationViewModel.kt | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt index 7c022103..f3e7815f 100644 --- a/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt +++ b/feature/certification/src/main/java/com/msg/certification/viewmodel/CertificationViewModel.kt @@ -49,15 +49,11 @@ class CertificationViewModel @Inject constructor( private val role = getRole().toString() - private val _getCertificationListUiState = - MutableStateFlow(GetCertificationListUiState.Loading) - val getCertificationListUiState: StateFlow = - _getCertificationListUiState.asStateFlow() + private val _getCertificationListUiState = MutableStateFlow(GetCertificationListUiState.Loading) + val getCertificationListUiState: StateFlow = _getCertificationListUiState.asStateFlow() - private val _getLectureSignUpHistoryUiState = - MutableStateFlow(GetLectureSignUpHistoryUiState.Loading) - val getLectureSignUpHistoryUiState: StateFlow = - _getLectureSignUpHistoryUiState.asStateFlow() + private val _getLectureSignUpHistoryUiState = MutableStateFlow(GetLectureSignUpHistoryUiState.Loading) + val getLectureSignUpHistoryUiState: StateFlow = _getLectureSignUpHistoryUiState.asStateFlow() private val _writeCertificationUiState = MutableStateFlow(WriteCertificationUiState.Success) val writeCertificationUiState: StateFlow = _writeCertificationUiState.asStateFlow() @@ -77,12 +73,10 @@ class CertificationViewModel @Inject constructor( private val _editCertificationResponse = MutableStateFlow>(Event.Loading) val editCertificationResponse = _editCertificationResponse.asStateFlow() - private val _getStudentBelongResponse = - MutableStateFlow>(Event.Loading) + private val _getStudentBelongResponse = MutableStateFlow>(Event.Loading) val getStudentBelongResponse = _getStudentBelongResponse.asStateFlow() - private val _getLectureSignUpHistoryResponse = - MutableStateFlow>(Event.Loading) + private val _getLectureSignUpHistoryResponse = MutableStateFlow>(Event.Loading) val getLectureSignUpHistoryResponse = _getLectureSignUpHistoryResponse.asStateFlow() private val studentId = UUID.fromString(savedStateHandle.get("studentId")) From 07731900cfd5c1a636a6a8fc079c11d3eff9dfe2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AA=85=ED=9B=88?= Date: Sun, 22 Sep 2024 00:46:12 +0900 Subject: [PATCH 141/141] :recycle: :: Improve Code Readability(Apply Reviewer) --- app/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index b41372ea..356f23a8 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -15,9 +15,9 @@ android { } dependencies { - implementation(project(":core:ui")) implementation(project(":core:common")) implementation(project(":core:design-system")) + implementation(project(":core:ui")) implementation(project(":feature:login")) implementation(project(":feature:sign-up")) implementation(project(":feature:student-activity"))