diff --git a/feature/timetable/src/main/java/com/suwiki/feature/timetable/timetablelist/component/TimetableEditContainer.kt b/core/designsystem/src/main/java/com/suwiki/core/designsystem/component/container/SuwikiEditContainer.kt similarity index 82% rename from feature/timetable/src/main/java/com/suwiki/feature/timetable/timetablelist/component/TimetableEditContainer.kt rename to core/designsystem/src/main/java/com/suwiki/core/designsystem/component/container/SuwikiEditContainer.kt index 23faf7288..68672bb02 100644 --- a/feature/timetable/src/main/java/com/suwiki/feature/timetable/timetablelist/component/TimetableEditContainer.kt +++ b/core/designsystem/src/main/java/com/suwiki/core/designsystem/component/container/SuwikiEditContainer.kt @@ -1,4 +1,4 @@ -package com.suwiki.feature.timetable.timetablelist.component +package com.suwiki.core.designsystem.component.container import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement @@ -6,7 +6,6 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -26,13 +25,13 @@ import com.suwiki.core.designsystem.theme.Black import com.suwiki.core.designsystem.theme.GrayF6 import com.suwiki.core.designsystem.theme.SuwikiTheme import com.suwiki.core.designsystem.theme.White -import com.suwiki.core.model.timetable.Timetable import com.suwiki.core.ui.extension.suwikiClickable @Composable -fun TimetableEditContainer( +fun SuwikiEditContainer( modifier: Modifier = Modifier, - timetable: Timetable = Timetable(), + name: String, + semester: String, onClickEditButton: () -> Unit = {}, onClickDeleteButton: () -> Unit = {}, onClick: () -> Unit = {}, @@ -67,12 +66,12 @@ fun TimetableEditContainer( modifier = Modifier.weight(1f, false), maxLines = 1, overflow = TextOverflow.Ellipsis, - text = timetable.name, + text = name, style = SuwikiTheme.typography.header6, color = Black, ) - SuwikiBadge(color = BadgeColor.Gray, text = "${timetable.year}-${timetable.semester}") + SuwikiBadge(color = BadgeColor.Gray, text = semester) } Row( @@ -95,14 +94,9 @@ fun TimetableEditContainer( fun TimetableEditContainerPreview() { SuwikiTheme { Column { - TimetableEditContainer( - timetable = Timetable( - createTime = 0, - year = "2024", - semester = "1", - name = "시간표시간표시간표시간표시간표시간표시간표시간표", - cellList = listOf(), - ), + SuwikiEditContainer( + name = "시간표시간표시간표시간표시간표시간표시간표시간표", + semester = "1", ) } } diff --git a/core/designsystem/src/main/java/com/suwiki/core/designsystem/component/container/SuwikiReviewEditContainer.kt b/core/designsystem/src/main/java/com/suwiki/core/designsystem/component/container/SuwikiReviewEditContainer.kt deleted file mode 100644 index 2bf3383a6..000000000 --- a/core/designsystem/src/main/java/com/suwiki/core/designsystem/component/container/SuwikiReviewEditContainer.kt +++ /dev/null @@ -1,62 +0,0 @@ -package com.suwiki.core.designsystem.component.container - -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.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.width -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.suwiki.core.designsystem.R -import com.suwiki.core.designsystem.component.badge.BadgeColor -import com.suwiki.core.designsystem.component.badge.SuwikiBadge -import com.suwiki.core.designsystem.component.button.SuwikiContainedSmallButton -import com.suwiki.core.designsystem.theme.Black -import com.suwiki.core.designsystem.theme.SuwikiTheme -import com.suwiki.core.designsystem.theme.White - -@Composable -fun SuwikiReviewEditContainer( - modifier: Modifier = Modifier, - semesterText: String, - classNameText: String, - onClickEditButton: () -> Unit = {}, -) { - Row( - modifier = modifier - .fillMaxWidth() - .background(White) - .padding(24.dp), - verticalAlignment = Alignment.CenterVertically, - ) { - Text( - text = classNameText, - style = SuwikiTheme.typography.header6, - color = Black, - ) - Spacer(modifier = Modifier.width(6.dp)) - SuwikiBadge(color = BadgeColor.Gray, text = semesterText) - Spacer(modifier = Modifier.weight(1f)) - SuwikiContainedSmallButton(text = stringResource(id = R.string.word_edit), onClick = onClickEditButton) - } -} - -@Composable -@Preview -fun SuwikiReviewEditContainerPreview() { - SuwikiTheme { - Column { - SuwikiReviewEditContainer( - semesterText = "학기", - classNameText = "과목명", - ) - } - } -} diff --git a/core/model/src/main/java/com/suwiki/core/model/lectureevaluation/exam/MyExamEvaluation.kt b/core/model/src/main/java/com/suwiki/core/model/lectureevaluation/exam/MyExamEvaluation.kt index 980b8e6ff..d8534da76 100644 --- a/core/model/src/main/java/com/suwiki/core/model/lectureevaluation/exam/MyExamEvaluation.kt +++ b/core/model/src/main/java/com/suwiki/core/model/lectureevaluation/exam/MyExamEvaluation.kt @@ -6,14 +6,14 @@ import kotlinx.serialization.Serializable @Serializable @Stable data class MyExamEvaluation( - val id: Long? = null, - val lectureName: String? = null, // 과목 이름 - val professor: String? = null, // 교수이름 - val majorType: String? = null, // 개설학과 - val selectedSemester: String? = null, - val semesterList: String? = null, - val examInfo: List = listOf(), // 시험 유형 ex) "족보, 교재, PPT, 필기, 응용, 실습, 과제", - val examType: String? = null, // 시험 종류(바텀시트) ex) "중간고사", //기말고사, 쪽지, 기타 + val id: Long = -1L, + val lectureName: String = "", // 과목 이름 + val professor: String = "", // 교수이름 + val majorType: String = "", // 개설학과 + val selectedSemester: String = "", + val semesterList: List = emptyList(), + val examInfo: List = emptyList(), // 시험 유형 ex) "족보, 교재, PPT, 필기, 응용, 실습, 과제", + val examType: String = "", // 시험 종류(바텀시트) ex) "중간고사", //기말고사, 쪽지, 기타 val examDifficulty: String = "", // 시험 난이도 val content: String = "", -) : java.io.Serializable +) diff --git a/core/model/src/main/java/com/suwiki/core/model/lectureevaluation/lecture/MyLectureEvaluation.kt b/core/model/src/main/java/com/suwiki/core/model/lectureevaluation/lecture/MyLectureEvaluation.kt index 4de75472c..5b1af3dfd 100644 --- a/core/model/src/main/java/com/suwiki/core/model/lectureevaluation/lecture/MyLectureEvaluation.kt +++ b/core/model/src/main/java/com/suwiki/core/model/lectureevaluation/lecture/MyLectureEvaluation.kt @@ -17,4 +17,4 @@ data class MyLectureEvaluation( val difficulty: Int = 0, // 학점 잘주는가? (까다로움 == 0, 보통 == 1, 학점느님 ==2) val homework: Int = 0, // 과제양 (없음 ==0, 보통 == 1, 많음 == 2) val content: String = "", -) : java.io.Serializable +) diff --git a/core/network/src/main/java/com/suwiki/core/network/interceptor/AuthenticationInterceptor.kt b/core/network/src/main/java/com/suwiki/core/network/interceptor/AuthenticationInterceptor.kt index a257a4562..7f99d52c8 100644 --- a/core/network/src/main/java/com/suwiki/core/network/interceptor/AuthenticationInterceptor.kt +++ b/core/network/src/main/java/com/suwiki/core/network/interceptor/AuthenticationInterceptor.kt @@ -20,7 +20,7 @@ internal class AuthenticationInterceptor @Inject constructor( Timber.tag(RETROFIT_TAG) .d( "AuthenticationInterceptor - intercept() called / request header: %s", - request.headers, + accessToken, ) return@runBlocking chain.proceed(request) } diff --git a/core/ui/src/main/java/com/suwiki/core/ui/extension/LazyListState.kt b/core/ui/src/main/java/com/suwiki/core/ui/extension/LazyListState.kt index bec241235..fb43a61ef 100644 --- a/core/ui/src/main/java/com/suwiki/core/ui/extension/LazyListState.kt +++ b/core/ui/src/main/java/com/suwiki/core/ui/extension/LazyListState.kt @@ -6,6 +6,7 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.snapshotFlow +import kotlinx.coroutines.flow.collectLatest // https://manavtamboli.medium.com/infinite-list-paged-list-in-jetpack-compose-b10fc7e74768 @Composable @@ -26,9 +27,9 @@ fun LazyListState.OnBottomReached( lastVisibleItem.index >= layoutInfo.totalItemsCount - 1 - buffer } } - LaunchedEffect(shouldLoadMore.value) { + LaunchedEffect(shouldLoadMore) { snapshotFlow { shouldLoadMore.value } - .collect { + .collectLatest { if (it) { onLoadMore() } diff --git a/domain/lectureevaluation/editor/src/main/java/com/suwiki/domain/lectureevaluation/editor/usecase/lecture/UpdateLectureEvaluationUseCase.kt b/domain/lectureevaluation/editor/src/main/java/com/suwiki/domain/lectureevaluation/editor/usecase/lecture/UpdateLectureEvaluationUseCase.kt index 0cd9da94b..4aa2bd4b5 100644 --- a/domain/lectureevaluation/editor/src/main/java/com/suwiki/domain/lectureevaluation/editor/usecase/lecture/UpdateLectureEvaluationUseCase.kt +++ b/domain/lectureevaluation/editor/src/main/java/com/suwiki/domain/lectureevaluation/editor/usecase/lecture/UpdateLectureEvaluationUseCase.kt @@ -8,7 +8,7 @@ class UpdateLectureEvaluationUseCase @Inject constructor( private val lectureEditorRepository: LectureEditorRepository, ) { suspend operator fun invoke(param: Param): Result = runCatchingIgnoreCancelled { - param.run { + with(param) { lectureEditorRepository.updateLectureEvaluation( lectureId = lectureId, selectedSemester = selectedSemester, diff --git a/feature/lectureevaluation/editor/src/main/java/com/suwiki/feature/lectureevaluation/editor/examevaluation/MyExamEvaluationEditViewModel.kt b/feature/lectureevaluation/editor/src/main/java/com/suwiki/feature/lectureevaluation/editor/examevaluation/MyExamEvaluationEditViewModel.kt index c7b5e9d4f..9171cf062 100644 --- a/feature/lectureevaluation/editor/src/main/java/com/suwiki/feature/lectureevaluation/editor/examevaluation/MyExamEvaluationEditViewModel.kt +++ b/feature/lectureevaluation/editor/src/main/java/com/suwiki/feature/lectureevaluation/editor/examevaluation/MyExamEvaluationEditViewModel.kt @@ -6,12 +6,8 @@ import com.suwiki.core.model.enums.ExamInfo import com.suwiki.core.model.enums.ExamLevel import com.suwiki.core.model.enums.ExamType import com.suwiki.core.model.lectureevaluation.exam.MyExamEvaluation -import com.suwiki.core.model.user.User import com.suwiki.core.ui.extension.decodeFromUri -import com.suwiki.domain.lectureevaluation.editor.usecase.exam.DeleteExamEvaluationUseCase import com.suwiki.domain.lectureevaluation.editor.usecase.exam.UpdateExamEvaluationUseCase -import com.suwiki.domain.user.usecase.GetUserInfoUseCase -import com.suwiki.feature.lectureevaluation.editor.lectureevaluation.MINIMUM_DELETE_POINT import com.suwiki.feature.lectureevaluation.editor.navigation.MyEvaluationEditRoute import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.collections.immutable.toPersistentList @@ -29,8 +25,6 @@ import javax.inject.Inject @HiltViewModel class MyExamEvaluationEditViewModel @Inject constructor( savedStateHandle: SavedStateHandle, - val getUserInfoUseCase: GetUserInfoUseCase, - val deleteExamEvaluationUseCase: DeleteExamEvaluationUseCase, val updateExamEvaluationUseCase: UpdateExamEvaluationUseCase, ) : ContainerHost, ViewModel() { override val container: Container = @@ -41,14 +35,11 @@ class MyExamEvaluationEditViewModel @Inject constructor( suspend fun initData() = intent { showLoadingScreen() + with(myExamEvaluationItem) { - getUserInfoUseCase().collect(::getPoint).runCatching {} - .onFailure { - postSideEffect(MyExamEvaluationEditSideEffect.HandleException(it)) - } reduce { state.copy( - semesterList = semesterList!!.split(", ").toPersistentList(), + semesterList = semesterList.toPersistentList(), selectedSemester = selectedSemester, selectedExamType = examType, ) @@ -69,13 +60,10 @@ class MyExamEvaluationEditViewModel @Inject constructor( } hideLoadingScreen() } - - private fun getPoint(user: User) = intent { reduce { state.copy(point = user.point) } } - fun updateExamEvaluation() = intent { updateExamEvaluationUseCase( UpdateExamEvaluationUseCase.Param( - lectureId = myExamEvaluationItem.id!!, + lectureId = myExamEvaluationItem.id, selectedSemester = state.selectedSemester, examInfo = state.examInfo.filter { it.isNotBlank() }.joinToString(", "), examType = state.selectedExamType, @@ -84,18 +72,6 @@ class MyExamEvaluationEditViewModel @Inject constructor( ), ) .onSuccess { - showReviseToast() - popBackStack() - } - .onFailure { - postSideEffect(MyExamEvaluationEditSideEffect.HandleException(it)) - } - } - - fun deleteExamEvaluation() = intent { - deleteExamEvaluationUseCase(myExamEvaluationItem.id!!) - .onSuccess { - showDeleteToast() popBackStack() } .onFailure { @@ -116,9 +92,11 @@ class MyExamEvaluationEditViewModel @Inject constructor( } hideExamTypeBottomSheet() } + fun updateExamLevel(examLevel: ExamLevel) = intent { reduce { state.copy(examLevel = examLevel) } } + fun updateExamInfo(info: ExamInfo) = intent { val examInfoList = state.examInfo.toMutableList() @@ -135,26 +113,12 @@ class MyExamEvaluationEditViewModel @Inject constructor( reduce { state.copy(examEvaluation = examEvaluationValue) } } - fun showDeleteOrLackPointDialog() = intent { - if (state.point > MINIMUM_DELETE_POINT) { - showExamEvaluationDeleteDialog() - } else { - showLackPointDialog() - } - } - private fun showLoadingScreen() = intent { reduce { state.copy(isLoading = true) } } private fun hideLoadingScreen() = intent { reduce { state.copy(isLoading = false) } } - private fun showExamEvaluationDeleteDialog() = intent { reduce { state.copy(showDeleteExamEvaluationDialog = true) } } - fun hideExamEvaluationDeleteDialog() = intent { reduce { state.copy(showDeleteExamEvaluationDialog = false) } } - private fun showLackPointDialog() = intent { reduce { state.copy(showLackPointDialog = true) } } - fun hideLackPointDialog() = intent { reduce { state.copy(showLackPointDialog = false) } } fun showSemesterBottomSheet() = intent { reduce { state.copy(showSemesterBottomSheet = true) } } fun hideSemesterBottomSheet() = intent { reduce { state.copy(showSemesterBottomSheet = false) } } fun showExamTypeBottomSheet() = intent { reduce { state.copy(showExamTypeBottomSheet = true) } } fun hideExamTypeBottomSheet() = intent { reduce { state.copy(showExamTypeBottomSheet = false) } } fun popBackStack() = intent { postSideEffect(MyExamEvaluationEditSideEffect.PopBackStack) } - private fun showDeleteToast() = intent { postSideEffect(MyExamEvaluationEditSideEffect.ShowMyExamEvaluationDeleteToast) } - private fun showReviseToast() = intent { postSideEffect(MyExamEvaluationEditSideEffect.ShowMyExamEvaluationReviseToast) } } diff --git a/feature/lectureevaluation/editor/src/main/java/com/suwiki/feature/lectureevaluation/editor/examevaluation/MyExamEvalutionEditContract.kt b/feature/lectureevaluation/editor/src/main/java/com/suwiki/feature/lectureevaluation/editor/examevaluation/MyExamEvalutionEditContract.kt index cd9347a9c..e21557a04 100644 --- a/feature/lectureevaluation/editor/src/main/java/com/suwiki/feature/lectureevaluation/editor/examevaluation/MyExamEvalutionEditContract.kt +++ b/feature/lectureevaluation/editor/src/main/java/com/suwiki/feature/lectureevaluation/editor/examevaluation/MyExamEvalutionEditContract.kt @@ -17,13 +17,10 @@ data class MyExamEvaluationEditState( val examInfo: PersistentList = persistentListOf(), val showSemesterBottomSheet: Boolean = false, val showExamTypeBottomSheet: Boolean = false, - val showDeleteExamEvaluationDialog: Boolean = false, - val showLackPointDialog: Boolean = false, ) sealed interface MyExamEvaluationEditSideEffect { data object PopBackStack : MyExamEvaluationEditSideEffect data object ShowMyExamEvaluationDeleteToast : MyExamEvaluationEditSideEffect - data object ShowMyExamEvaluationReviseToast : MyExamEvaluationEditSideEffect data class HandleException(val throwable: Throwable) : MyExamEvaluationEditSideEffect } diff --git a/feature/lectureevaluation/editor/src/main/java/com/suwiki/feature/lectureevaluation/editor/examevaluation/MyExamEvalutionEditScreen.kt b/feature/lectureevaluation/editor/src/main/java/com/suwiki/feature/lectureevaluation/editor/examevaluation/MyExamEvalutionEditScreen.kt index fc5ea4d6a..7811ddb76 100644 --- a/feature/lectureevaluation/editor/src/main/java/com/suwiki/feature/lectureevaluation/editor/examevaluation/MyExamEvalutionEditScreen.kt +++ b/feature/lectureevaluation/editor/src/main/java/com/suwiki/feature/lectureevaluation/editor/examevaluation/MyExamEvalutionEditScreen.kt @@ -17,7 +17,6 @@ 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.ExperimentalMaterial3Api import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -33,7 +32,6 @@ import com.suwiki.core.designsystem.component.bottomsheet.SuwikiSelectBottomShee import com.suwiki.core.designsystem.component.button.SuwikiContainedMediumButton import com.suwiki.core.designsystem.component.chips.SuwikiOutlinedChip import com.suwiki.core.designsystem.component.container.SuwikiSelectionContainer -import com.suwiki.core.designsystem.component.dialog.SuwikiDialog import com.suwiki.core.designsystem.component.loading.LoadingScreen import com.suwiki.core.designsystem.component.textfield.SuwikiReviewInputBox import com.suwiki.core.designsystem.theme.SuwikiTheme @@ -64,9 +62,6 @@ fun MyExamEvaluationEditRoute( onShowToast(context.getString(R.string.exam_evaluation_delete_toast_msg)) } - MyExamEvaluationEditSideEffect.ShowMyExamEvaluationReviseToast -> { - onShowToast(context.getString(R.string.exam_evaluation_revise_toast_msg)) - } is MyExamEvaluationEditSideEffect.HandleException -> handleException(sideEffect.throwable) } } @@ -88,15 +83,11 @@ fun MyExamEvaluationEditRoute( onClickExamLevelChip = viewModel::updateExamLevel, onClickExamInfoChip = viewModel::updateExamInfo, onExamEvaluationValueChange = viewModel::updateMyExamEvaluationValue, - onClickExamEvaluationDeleteButton = viewModel::showDeleteOrLackPointDialog, - onDismissExamEvaluationDelete = viewModel::hideExamEvaluationDeleteDialog, - onDismissLackPoint = viewModel::hideLackPointDialog, - onClickExamEvaluationDeleteConfirm = viewModel::deleteExamEvaluation, onClickExamEvaluationReviseButton = viewModel::updateExamEvaluation, ) } -@OptIn(ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class) +@OptIn(ExperimentalLayoutApi::class) @Composable fun MyExamEvaluationEditScreen( scrollState: ScrollState, @@ -110,11 +101,8 @@ fun MyExamEvaluationEditScreen( onExamTypeBottomSheetDismissRequest: () -> Unit = {}, onClickExamLevelChip: (ExamLevel) -> Unit = {}, onClickExamInfoChip: (ExamInfo) -> Unit = {}, - onClickExamEvaluationDeleteButton: () -> Unit = {}, - onClickExamEvaluationDeleteConfirm: () -> Unit = {}, onExamEvaluationValueChange: (String) -> Unit = { _ -> }, - onDismissExamEvaluationDelete: () -> Unit = {}, - onDismissLackPoint: () -> Unit = {}, + onClickExamEvaluationReviseButton: () -> Unit = {}, ) { Column( @@ -194,50 +182,15 @@ fun MyExamEvaluationEditScreen( onValueChange = onExamEvaluationValueChange, ) } - Row( - horizontalArrangement = Arrangement.spacedBy(16.dp), + + SuwikiContainedMediumButton( modifier = Modifier - .fillMaxWidth() .padding(24.dp) + .fillMaxWidth() + .height(50.dp) .imePadding(), - ) { - SuwikiContainedMediumButton( - modifier = Modifier - .weight(1f) - .height(50.dp), - text = stringResource(R.string.text_delete), - enabled = false, - onClick = onClickExamEvaluationDeleteButton, - ) - SuwikiContainedMediumButton( - modifier = Modifier - .weight(1f) - .height(50.dp), - text = stringResource(R.string.text_revise), - onClick = onClickExamEvaluationReviseButton, - ) - } - } - - if (uiState.showDeleteExamEvaluationDialog) { - SuwikiDialog( - headerText = stringResource(R.string.delete_dialog_header), - bodyText = stringResource(R.string.delete_dialog_body, uiState.point), - confirmButtonText = stringResource(R.string.word_delete), - dismissButtonText = stringResource(R.string.word_cancel), - onDismissRequest = onDismissExamEvaluationDelete, - onClickConfirm = onClickExamEvaluationDeleteConfirm, - onClickDismiss = onDismissExamEvaluationDelete, - ) - } - - if (uiState.showLackPointDialog) { - SuwikiDialog( - headerText = stringResource(R.string.lack_point_dialog_header), - bodyText = stringResource(R.string.lack_point_dialog_body, uiState.point), - confirmButtonText = stringResource(R.string.word_confirm), - onDismissRequest = onDismissLackPoint, - onClickConfirm = onDismissLackPoint, + text = stringResource(R.string.text_complete), + onClick = onClickExamEvaluationReviseButton, ) } @@ -245,7 +198,7 @@ fun MyExamEvaluationEditScreen( isSheetOpen = uiState.showExamTypeBottomSheet, onDismissRequest = onExamTypeBottomSheetDismissRequest, onClickItem = { onClickExamTypeItem(it) }, - itemList = ExamType.values().map { it.value }.toPersistentList(), + itemList = ExamType.entries.map { it.value }.toPersistentList(), title = stringResource(R.string.word_choose_semester), selectedPosition = uiState.selectedExamTypePosition, ) @@ -286,7 +239,7 @@ fun LectureExamEditContainer( @Preview @Composable -fun MyExamEvalutionEditScreenPreview() { +fun MyExamEvaluationEditScreenPreview() { val scrollState = rememberScrollState() SuwikiTheme { diff --git a/feature/lectureevaluation/editor/src/main/java/com/suwiki/feature/lectureevaluation/editor/lectureevaluation/MyLectureEvaluationEditContract.kt b/feature/lectureevaluation/editor/src/main/java/com/suwiki/feature/lectureevaluation/editor/lectureevaluation/MyLectureEvaluationEditContract.kt index d4ecaf2b1..400fe8127 100644 --- a/feature/lectureevaluation/editor/src/main/java/com/suwiki/feature/lectureevaluation/editor/lectureevaluation/MyLectureEvaluationEditContract.kt +++ b/feature/lectureevaluation/editor/src/main/java/com/suwiki/feature/lectureevaluation/editor/lectureevaluation/MyLectureEvaluationEditContract.kt @@ -21,13 +21,10 @@ data class MyLectureEvaluationEditState( val teamLevel: TeamLevel? = null, val lectureEvaluation: String = "", val showSemesterBottomSheet: Boolean = false, - val showDeleteLectureEvaluationDialog: Boolean = false, - val showLackPointDialog: Boolean = false, ) sealed interface MyLectureEvaluationEditSideEffect { data object PopBackStack : MyLectureEvaluationEditSideEffect data object ShowMyLectureEvaluationDeleteToast : MyLectureEvaluationEditSideEffect - data object ShowMyLectureEvaluationReviseToast : MyLectureEvaluationEditSideEffect data class HandleException(val throwable: Throwable) : MyLectureEvaluationEditSideEffect } diff --git a/feature/lectureevaluation/editor/src/main/java/com/suwiki/feature/lectureevaluation/editor/lectureevaluation/MyLectureEvaluationEditScreen.kt b/feature/lectureevaluation/editor/src/main/java/com/suwiki/feature/lectureevaluation/editor/lectureevaluation/MyLectureEvaluationEditScreen.kt index 0004af2bc..782ea7d14 100644 --- a/feature/lectureevaluation/editor/src/main/java/com/suwiki/feature/lectureevaluation/editor/lectureevaluation/MyLectureEvaluationEditScreen.kt +++ b/feature/lectureevaluation/editor/src/main/java/com/suwiki/feature/lectureevaluation/editor/lectureevaluation/MyLectureEvaluationEditScreen.kt @@ -33,7 +33,6 @@ import com.suwiki.core.designsystem.component.button.SuwikiContainedMediumButton import com.suwiki.core.designsystem.component.chips.ChipColor import com.suwiki.core.designsystem.component.chips.SuwikiContainedChip import com.suwiki.core.designsystem.component.container.SuwikiSelectionContainer -import com.suwiki.core.designsystem.component.dialog.SuwikiDialog import com.suwiki.core.designsystem.component.loading.LoadingScreen import com.suwiki.core.designsystem.component.ratingbar.SuwikiRatingBar import com.suwiki.core.designsystem.component.slider.SuwikiSlider @@ -66,10 +65,6 @@ fun MyLectureEvaluationEditRoute( MyLectureEvaluationEditSideEffect.ShowMyLectureEvaluationDeleteToast -> { onShowToast(context.getString(R.string.lecture_evaluation_delete_toast_msg)) } - - MyLectureEvaluationEditSideEffect.ShowMyLectureEvaluationReviseToast -> { - onShowToast(context.getString(R.string.lecture_evaluation_revise_toast_msg)) - } is MyLectureEvaluationEditSideEffect.HandleException -> handleException(sideEffect.throwable) } } @@ -97,13 +92,9 @@ fun MyLectureEvaluationEditRoute( onLearningRatingValueChange = viewModel::updateLearningRating, onSatisfactionRatingValueChange = viewModel::updateSatisfactionRating, onLectureEvaluationValueChange = viewModel::updateMyLectureEvaluationValue, - onClickLectureEvaluationDeleteButton = viewModel::showDeleteOrLackPointDialog, - onDismissLectureEvaluationDelete = viewModel::hideLectureEvaluationDeleteDialog, - onDismissLackPoint = viewModel::hideLackPointDialog, onClickGradeChip = viewModel::updateGradeLevel, onClickHomeworkChip = viewModel::updateHomeworkLevel, onClickTeamChip = viewModel::updateTeamLevel, - onClickLectureEvaluationDeleteConfirm = viewModel::deleteLectureEvaluation, onClickLectureEvaluationReviseButton = viewModel::updateLectureEvaluation, ) } @@ -123,10 +114,6 @@ fun MyLectureEvaluationEditScreen( onClickHomeworkChip: (HomeworkLevel) -> Unit = {}, onClickTeamChip: (TeamLevel) -> Unit = {}, onLectureEvaluationValueChange: (String) -> Unit = { _ -> }, - onClickLectureEvaluationDeleteButton: () -> Unit = {}, - onClickLectureEvaluationDeleteConfirm: () -> Unit = {}, - onDismissLectureEvaluationDelete: () -> Unit = {}, - onDismissLackPoint: () -> Unit = {}, onClickLectureEvaluationReviseButton: () -> Unit = {}, ) { Column( @@ -280,50 +267,14 @@ fun MyLectureEvaluationEditScreen( ) } - Row( + SuwikiContainedMediumButton( modifier = Modifier + .padding(24.dp) .fillMaxWidth() - .padding(start = 24.dp, end = 24.dp, bottom = 24.dp) + .height(50.dp) .imePadding(), - horizontalArrangement = Arrangement.spacedBy(16.dp), - ) { - SuwikiContainedMediumButton( - modifier = Modifier - .weight(1f) - .height(50.dp), - text = stringResource(R.string.text_delete), - enabled = false, - onClick = onClickLectureEvaluationDeleteButton, - ) - SuwikiContainedMediumButton( - modifier = Modifier - .weight(1f) - .height(50.dp), - text = stringResource(R.string.text_revise), - onClick = onClickLectureEvaluationReviseButton, - ) - } - } - - if (uiState.showDeleteLectureEvaluationDialog) { - SuwikiDialog( - headerText = stringResource(R.string.delete_dialog_header), - bodyText = stringResource(R.string.delete_dialog_body, uiState.point), - confirmButtonText = stringResource(R.string.word_delete), - dismissButtonText = stringResource(R.string.word_cancel), - onDismissRequest = onDismissLectureEvaluationDelete, - onClickConfirm = onClickLectureEvaluationDeleteConfirm, - onClickDismiss = onDismissLectureEvaluationDelete, - ) - } - - if (uiState.showLackPointDialog) { - SuwikiDialog( - headerText = stringResource(R.string.lack_point_dialog_header), - bodyText = stringResource(R.string.lack_point_dialog_body, uiState.point), - confirmButtonText = stringResource(R.string.word_confirm), - onDismissRequest = onDismissLackPoint, - onClickConfirm = onDismissLackPoint, + text = stringResource(R.string.text_complete), + onClick = onClickLectureEvaluationReviseButton, ) } diff --git a/feature/lectureevaluation/editor/src/main/java/com/suwiki/feature/lectureevaluation/editor/lectureevaluation/MyLectureEvaluationEditViewModel.kt b/feature/lectureevaluation/editor/src/main/java/com/suwiki/feature/lectureevaluation/editor/lectureevaluation/MyLectureEvaluationEditViewModel.kt index ba4c5efa1..86097bef6 100644 --- a/feature/lectureevaluation/editor/src/main/java/com/suwiki/feature/lectureevaluation/editor/lectureevaluation/MyLectureEvaluationEditViewModel.kt +++ b/feature/lectureevaluation/editor/src/main/java/com/suwiki/feature/lectureevaluation/editor/lectureevaluation/MyLectureEvaluationEditViewModel.kt @@ -8,7 +8,6 @@ import com.suwiki.core.model.enums.TeamLevel import com.suwiki.core.model.lectureevaluation.lecture.MyLectureEvaluation import com.suwiki.core.model.user.User import com.suwiki.core.ui.extension.decodeFromUri -import com.suwiki.domain.lectureevaluation.editor.usecase.lecture.DeleteLectureEvaluationUseCase import com.suwiki.domain.lectureevaluation.editor.usecase.lecture.UpdateLectureEvaluationUseCase import com.suwiki.domain.user.usecase.GetUserInfoUseCase import com.suwiki.feature.lectureevaluation.editor.navigation.MyEvaluationEditRoute @@ -25,13 +24,10 @@ import org.orbitmvi.orbit.syntax.simple.reduce import org.orbitmvi.orbit.viewmodel.container import javax.inject.Inject -const val MINIMUM_DELETE_POINT = 30 - @HiltViewModel class MyLectureEvaluationEditViewModel @Inject constructor( savedStateHandle: SavedStateHandle, val getUserInfoUseCase: GetUserInfoUseCase, - val deleteLectureEvaluationUseCase: DeleteLectureEvaluationUseCase, val updateLectureEvaluationUseCase: UpdateLectureEvaluationUseCase, ) : ContainerHost, ViewModel() { override val container: Container = @@ -95,18 +91,6 @@ class MyLectureEvaluationEditViewModel @Inject constructor( ), ) .onSuccess { - showReviseToast() - popBackStack() - } - .onFailure { - postSideEffect(MyLectureEvaluationEditSideEffect.HandleException(it)) - } - } - - fun deleteLectureEvaluation() = intent { - deleteLectureEvaluationUseCase(myLectureEvaluationItem.id) - .onSuccess { - showDeleteToast() popBackStack() } .onFailure { @@ -149,24 +133,10 @@ class MyLectureEvaluationEditViewModel @Inject constructor( reduce { state.copy(teamLevel = teamLevel) } } - fun showDeleteOrLackPointDialog() = intent { - if (state.point > MINIMUM_DELETE_POINT) { - showLectureEvaluationDeleteDialog() - } else { - showLackPointDialog() - } - } - private fun showLoadingScreen() = intent { reduce { state.copy(isLoading = true) } } private fun hideLoadingScreen() = intent { reduce { state.copy(isLoading = false) } } - private fun showLectureEvaluationDeleteDialog() = intent { reduce { state.copy(showDeleteLectureEvaluationDialog = true) } } - fun hideLectureEvaluationDeleteDialog() = intent { reduce { state.copy(showDeleteLectureEvaluationDialog = false) } } - private fun showLackPointDialog() = intent { reduce { state.copy(showLackPointDialog = true) } } - fun hideLackPointDialog() = intent { reduce { state.copy(showLackPointDialog = false) } } fun showSemesterBottomSheet() = intent { reduce { state.copy(showSemesterBottomSheet = true) } } fun hideSemesterBottomSheet() = intent { reduce { state.copy(showSemesterBottomSheet = false) } } fun popBackStack() = intent { postSideEffect(MyLectureEvaluationEditSideEffect.PopBackStack) } - private fun showDeleteToast() = intent { postSideEffect(MyLectureEvaluationEditSideEffect.ShowMyLectureEvaluationDeleteToast) } - private fun showReviseToast() = intent { postSideEffect(MyLectureEvaluationEditSideEffect.ShowMyLectureEvaluationReviseToast) } } diff --git a/feature/lectureevaluation/editor/src/main/res/values/strings.xml b/feature/lectureevaluation/editor/src/main/res/values/strings.xml index e894ef103..28ae09297 100644 --- a/feature/lectureevaluation/editor/src/main/res/values/strings.xml +++ b/feature/lectureevaluation/editor/src/main/res/values/strings.xml @@ -10,11 +10,7 @@ 조모임 강의평가를 입력해주세요. 삭제하기 - 수정하기 - 30포인트가 차감됩니다. - 강의평가를 정말로 삭제하시겠습니까?\n현재 보유 포인트 : %dp - 포인트가 부족합니다. - 현재 보유 포인트 : %dp + 완료 삭제 취소 강의평가가 수정되었습니다. diff --git a/feature/lectureevaluation/my/build.gradle.kts b/feature/lectureevaluation/my/build.gradle.kts index 3c035a1d6..e89ae60ca 100644 --- a/feature/lectureevaluation/my/build.gradle.kts +++ b/feature/lectureevaluation/my/build.gradle.kts @@ -9,5 +9,8 @@ android { dependencies { implementation(projects.domain.lectureevaluation.my) + implementation(projects.domain.lectureevaluation.editor) + implementation(projects.domain.user) + implementation(libs.kotlinx.serialization.json) } diff --git a/feature/lectureevaluation/my/src/main/java/com/suwiki/feature/lectureevaluation/my/MyEvaluationContract.kt b/feature/lectureevaluation/my/src/main/java/com/suwiki/feature/lectureevaluation/my/MyEvaluationContract.kt index a22f5f6dc..3362afb52 100644 --- a/feature/lectureevaluation/my/src/main/java/com/suwiki/feature/lectureevaluation/my/MyEvaluationContract.kt +++ b/feature/lectureevaluation/my/src/main/java/com/suwiki/feature/lectureevaluation/my/MyEvaluationContract.kt @@ -7,9 +7,13 @@ import kotlinx.collections.immutable.persistentListOf data class MyEvaluationState( val isLoading: Boolean = false, + val point: Int = 0, val currentTabPage: Int = 0, val myLectureEvaluationList: PersistentList = persistentListOf(), val myExamEvaluationList: PersistentList = persistentListOf(), + val showDeleteLectureEvaluationDialog: Boolean = false, + val showDeleteExamEvaluationDialog: Boolean = false, + val showLackPointDialog: Boolean = false, ) sealed interface MyEvaluationSideEffect { diff --git a/feature/lectureevaluation/my/src/main/java/com/suwiki/feature/lectureevaluation/my/MyEvaluationScreen.kt b/feature/lectureevaluation/my/src/main/java/com/suwiki/feature/lectureevaluation/my/MyEvaluationScreen.kt index e0442984e..59b6484c4 100644 --- a/feature/lectureevaluation/my/src/main/java/com/suwiki/feature/lectureevaluation/my/MyEvaluationScreen.kt +++ b/feature/lectureevaluation/my/src/main/java/com/suwiki/feature/lectureevaluation/my/MyEvaluationScreen.kt @@ -1,13 +1,11 @@ package com.suwiki.feature.lectureevaluation.my -import android.annotation.SuppressLint import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.background import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.LazyListState import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.pager.HorizontalPager @@ -23,10 +21,10 @@ import androidx.compose.runtime.snapshotFlow 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.hilt.navigation.compose.hiltViewModel import com.suwiki.core.designsystem.component.appbar.SuwikiAppBarWithTitle -import com.suwiki.core.designsystem.component.container.SuwikiReviewEditContainer +import com.suwiki.core.designsystem.component.container.SuwikiEditContainer +import com.suwiki.core.designsystem.component.dialog.SuwikiDialog import com.suwiki.core.designsystem.component.loading.LoadingScreen import com.suwiki.core.designsystem.component.tabbar.SuwikiTabBar import com.suwiki.core.designsystem.component.tabbar.TabTitle @@ -38,8 +36,6 @@ import com.suwiki.core.ui.extension.OnBottomReached import com.suwiki.core.ui.extension.collectWithLifecycle import com.suwiki.core.ui.extension.encodeToUri import com.suwiki.feature.lectureevaluation.my.model.MyEvaluationTab -import com.suwiki.feature.lectureevaluation.my.model.MyExamEvaluationsSample -import com.suwiki.feature.lectureevaluation.my.model.MyLectureEvaluationsSample import kotlinx.collections.immutable.PersistentList import kotlinx.serialization.json.Json import org.orbitmvi.orbit.compose.collectAsState @@ -50,7 +46,6 @@ private val MY_EVALUATION_PAGE_COUNT = MyEvaluationTab.entries.size @OptIn(ExperimentalFoundationApi::class) @Composable fun MyEvaluationRoute( - padding: PaddingValues, viewModel: MyEvaluationViewModel = hiltViewModel(), popBackStack: () -> Unit = {}, navigateMyLectureEvaluation: (String) -> Unit = {}, @@ -92,31 +87,50 @@ fun MyEvaluationRoute( } MyEvaluationScreen( - padding = padding, uiState = uiState, pagerState = pagerState, + lectureEvaluationListState = lectureEvaluationListState, + examEvaluationListState = examEvaluationListState, onClickTab = viewModel::syncPager, onClickBack = viewModel::popBackStack, onClickLectureEvaluationEditButton = viewModel::navigateMyLectureEvaluation, onClickExamEvaluationEditButton = viewModel::navigateMyExamEvaluation, + onClickExamEvaluationDeleteButton = viewModel::showExamDeleteOrLackPointDialog, + onDismissExamEvaluationDelete = viewModel::hideExamEvaluationDeleteDialog, + onDismissLackPoint = viewModel::hideLackPointDialog, + onClickExamEvaluationDeleteConfirm = { + viewModel.deleteExamEvaluation() + viewModel.hideExamEvaluationDeleteDialog() + }, + onClickLectureEvaluationDeleteConfirm = { + viewModel.deleteLectureEvaluation() + viewModel.hideLectureEvaluationDeleteDialog() + }, + onClickLectureEvaluationDeleteButton = viewModel::showLectureDeleteOrLackPointDialog, ) } @OptIn(ExperimentalFoundationApi::class) -@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") @Composable fun MyEvaluationScreen( - padding: PaddingValues, uiState: MyEvaluationState, pagerState: PagerState = rememberPagerState(pageCount = { MY_EVALUATION_PAGE_COUNT }), + lectureEvaluationListState: LazyListState = rememberLazyListState(), + examEvaluationListState: LazyListState = rememberLazyListState(), onClickTab: (Int) -> Unit = {}, onClickBack: () -> Unit = {}, onClickLectureEvaluationEditButton: (String) -> Unit = {}, + onClickLectureEvaluationDeleteButton: (Long) -> Unit = {}, onClickExamEvaluationEditButton: (String) -> Unit = {}, + onDismissExamEvaluationDelete: () -> Unit = {}, + onDismissLackPoint: () -> Unit = {}, + onClickExamEvaluationDeleteConfirm: () -> Unit = {}, + onClickExamEvaluationDeleteButton: (Long) -> Unit = {}, + onClickLectureEvaluationDeleteConfirm: () -> Unit = {}, + onDismissLectureEvaluationDelete: () -> Unit = {}, ) { Column( modifier = Modifier - .padding(padding) .background(White) .fillMaxSize(), ) { @@ -146,56 +160,119 @@ fun MyEvaluationScreen( ) { page -> when (MyEvaluationTab.entries[page]) { MyEvaluationTab.LECTURE_EVALUATION -> { - MyEvaluationLazyColumn( -// itemList = uiState.myLectureEvaluationList, - itemList = MyLectureEvaluationsSample, + MyLectureEvaluationLazyColumn( + itemList = uiState.myLectureEvaluationList, + listState = lectureEvaluationListState, onClickLectureEditButton = onClickLectureEvaluationEditButton, + onClickDeleteButton = onClickLectureEvaluationDeleteButton, ) } + MyEvaluationTab.EXAM_INFO -> { - MyEvaluationLazyColumn( -// itemList = uiState.myExamEvaluationList, - itemList = MyExamEvaluationsSample, + MyExamEvaluationLazyColumn( + itemList = uiState.myExamEvaluationList, + listState = examEvaluationListState, onClickExamEditButton = onClickExamEvaluationEditButton, + onClickDeleteButton = onClickExamEvaluationDeleteButton, ) } } } } + + if (uiState.showDeleteExamEvaluationDialog) { + SuwikiDialog( + headerText = stringResource(R.string.delete_dialog_header), + bodyText = stringResource(R.string.delete_dialog_body, uiState.point), + confirmButtonText = stringResource(R.string.word_delete), + dismissButtonText = stringResource(R.string.word_cancel), + onDismissRequest = onDismissExamEvaluationDelete, + onClickConfirm = onClickExamEvaluationDeleteConfirm, + onClickDismiss = onDismissExamEvaluationDelete, + ) + } + + if (uiState.showLackPointDialog) { + SuwikiDialog( + headerText = stringResource(R.string.lack_point_dialog_header), + bodyText = stringResource(R.string.lack_point_dialog_body, uiState.point), + confirmButtonText = stringResource(R.string.word_confirm), + onDismissRequest = onDismissLackPoint, + onClickConfirm = onDismissLackPoint, + ) + } + + if (uiState.showDeleteLectureEvaluationDialog) { + SuwikiDialog( + headerText = stringResource(R.string.delete_dialog_header), + bodyText = stringResource(R.string.delete_dialog_body, uiState.point), + confirmButtonText = stringResource(R.string.word_delete), + dismissButtonText = stringResource(R.string.word_cancel), + onDismissRequest = onDismissLectureEvaluationDelete, + onClickConfirm = onClickLectureEvaluationDeleteConfirm, + onClickDismiss = onDismissLectureEvaluationDelete, + ) + } + if (uiState.isLoading) { LoadingScreen() } } @Composable -fun MyEvaluationLazyColumn( +fun MyLectureEvaluationLazyColumn( modifier: Modifier = Modifier, - itemList: PersistentList, + itemList: PersistentList, + listState: LazyListState, onClickLectureEditButton: (String) -> Unit = {}, + onClickDeleteButton: (Long) -> Unit = {}, +) { + LazyColumn( + modifier = modifier.fillMaxSize(), + state = listState, + ) { + items( + items = itemList, + key = { + it.id + }, + ) { item -> + SuwikiEditContainer( + semester = item.selectedSemester, + name = item.lectureInfo.lectureName, + onClickEditButton = { onClickLectureEditButton(Json.encodeToUri(item)) }, + onClickDeleteButton = { onClickDeleteButton(item.id) }, + ) + } + } +} + +@Composable +fun MyExamEvaluationLazyColumn( + modifier: Modifier = Modifier, + itemList: PersistentList, + listState: LazyListState, onClickExamEditButton: (String) -> Unit = {}, + onClickDeleteButton: (Long) -> Unit = {}, ) { LazyColumn( modifier = modifier.fillMaxSize(), + state = listState, ) { - items(items = itemList) { item -> - when (item) { - is MyLectureEvaluation -> { - SuwikiReviewEditContainer( - semesterText = item.selectedSemester, - classNameText = item.lectureInfo.lectureName, - onClickEditButton = { onClickLectureEditButton(Json.encodeToUri(item)) }, - ) - } - is MyExamEvaluation -> { - val (examSemester, examName) = item.selectedSemester to item.lectureName + items( + items = itemList, + key = { + it.id + }, + ) { item -> + val (examSemester, examName) = item.selectedSemester to item.lectureName - SuwikiReviewEditContainer( - semesterText = examSemester ?: stringResource(R.string.word_semester), - classNameText = examName ?: stringResource(R.string.word_lecture_name), - onClickEditButton = { onClickExamEditButton(Json.encodeToUri(item)) }, - ) - } - } + SuwikiEditContainer( + semester = examSemester, + name = examName, + onClickEditButton = { onClickExamEditButton(Json.encodeToUri(item)) }, + onClickDeleteButton = { onClickDeleteButton(item.id) }, + ) } } } @@ -207,7 +284,6 @@ fun MyEvaluationPreview() { var currentPage by remember { mutableIntStateOf(0) } SuwikiTheme { MyEvaluationScreen( - padding = PaddingValues(0.dp), uiState = MyEvaluationState( currentTabPage = currentPage, ), diff --git a/feature/lectureevaluation/my/src/main/java/com/suwiki/feature/lectureevaluation/my/MyEvaluationViewModel.kt b/feature/lectureevaluation/my/src/main/java/com/suwiki/feature/lectureevaluation/my/MyEvaluationViewModel.kt index 3d48a5484..36310cfd0 100644 --- a/feature/lectureevaluation/my/src/main/java/com/suwiki/feature/lectureevaluation/my/MyEvaluationViewModel.kt +++ b/feature/lectureevaluation/my/src/main/java/com/suwiki/feature/lectureevaluation/my/MyEvaluationViewModel.kt @@ -1,10 +1,19 @@ package com.suwiki.feature.lectureevaluation.my import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.suwiki.core.model.user.User +import com.suwiki.domain.lectureevaluation.editor.usecase.exam.DeleteExamEvaluationUseCase +import com.suwiki.domain.lectureevaluation.editor.usecase.lecture.DeleteLectureEvaluationUseCase import com.suwiki.domain.lectureevaluation.my.usecase.GetMyExamEvaluationListUseCase import com.suwiki.domain.lectureevaluation.my.usecase.GetMyLectureEvaluationListUseCase +import com.suwiki.domain.user.usecase.GetUserInfoUseCase import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toPersistentList +import kotlinx.coroutines.flow.catch +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.joinAll import org.orbitmvi.orbit.Container import org.orbitmvi.orbit.ContainerHost @@ -16,46 +25,114 @@ import javax.inject.Inject @HiltViewModel class MyEvaluationViewModel @Inject constructor( + private val getUserInfoUseCase: GetUserInfoUseCase, private val getMyLectureEvaluationListUseCase: GetMyLectureEvaluationListUseCase, private val getMyExamEvaluationListUseCase: GetMyExamEvaluationListUseCase, + private val deleteExamEvaluationUseCase: DeleteExamEvaluationUseCase, + private val deleteLectureEvaluationUseCase: DeleteLectureEvaluationUseCase, ) : ContainerHost, ViewModel() { override val container: Container = container(MyEvaluationState()) - private var currentLectureEvaluationPage = 1 - private var currentExamEvaluationPage = 1 + private var lectureEvaluationPage = 1 + private var isLastLectureEvaluation = false + private var examEvaluationPage = 1 + private var isLastExamEvaluation = false - fun getMyLectureEvaluations() = intent { - showLoadingScreen() - getMyLectureEvaluationListUseCase(currentLectureEvaluationPage) + private var toDeleteExamId: Long = 0 + private var toDeleteLectureId: Long = 0 + + fun getMyLectureEvaluations(needClear: Boolean = false) = intent { + val currentList = if (needClear) { + lectureEvaluationPage = 1 + isLastLectureEvaluation = false + persistentListOf() + } else { + state.myLectureEvaluationList + } + + if (isLastLectureEvaluation) return@intent + + getMyLectureEvaluationListUseCase(lectureEvaluationPage) .onSuccess { - reduce { state.copy(myLectureEvaluationList = state.myLectureEvaluationList.addAll(it.toPersistentList())) } - currentLectureEvaluationPage++ + reduce { + lectureEvaluationPage++ + isLastLectureEvaluation = it.isEmpty() + state.copy(myLectureEvaluationList = currentList.addAll(it).distinctBy { it.id }.toPersistentList()) + } } .onFailure { postSideEffect(MyEvaluationSideEffect.HandleException(it)) } - hideLoadingScreen() } - fun getMyExamEvaluations() = intent { - showLoadingScreen() - getMyExamEvaluationListUseCase(currentExamEvaluationPage) + fun getMyExamEvaluations(needClear: Boolean = false) = intent { + val currentList = if (needClear) { + examEvaluationPage = 1 + isLastExamEvaluation = false + persistentListOf() + } else { + state.myExamEvaluationList + } + + if (isLastExamEvaluation) return@intent + + getMyExamEvaluationListUseCase(examEvaluationPage) .onSuccess { - reduce { state.copy(myExamEvaluationList = state.myExamEvaluationList.addAll(it.toPersistentList())) } - currentExamEvaluationPage++ + reduce { + examEvaluationPage++ + isLastExamEvaluation = it.isEmpty() + state.copy(myExamEvaluationList = currentList.addAll(it).distinctBy { it.id }.toPersistentList()) + } } .onFailure { postSideEffect(MyEvaluationSideEffect.HandleException(it)) } - hideLoadingScreen() } fun initData() = intent { showLoadingScreen() - joinAll(getMyLectureEvaluations(), getMyExamEvaluations()) + + getUserInfoUseCase() + .onEach(::setPoint) + .catch { postSideEffect(MyEvaluationSideEffect.HandleException(it)) } + .launchIn(viewModelScope) + + joinAll(getMyLectureEvaluations(true), getMyExamEvaluations(true)) hideLoadingScreen() } + fun deleteExamEvaluation() = intent { + deleteExamEvaluationUseCase(toDeleteExamId) + .onSuccess { + reduce { + state.copy( + point = state.point - 30, + myExamEvaluationList = state.myExamEvaluationList.filter { it.id != toDeleteExamId }.toPersistentList(), + ) + } + } + .onFailure { + postSideEffect(MyEvaluationSideEffect.HandleException(it)) + } + } + + fun deleteLectureEvaluation() = intent { + deleteLectureEvaluationUseCase(toDeleteLectureId) + .onSuccess { + reduce { + state.copy( + point = state.point - 30, + myLectureEvaluationList = state.myLectureEvaluationList.filter { it.id != toDeleteLectureId }.toPersistentList(), + ) + } + } + .onFailure { + postSideEffect(MyEvaluationSideEffect.HandleException(it)) + } + } + + private fun setPoint(user: User) = intent { reduce { state.copy(point = user.point) } } + fun syncPager(currentPage: Int) = intent { reduce { state.copy(currentTabPage = currentPage) } } private fun showLoadingScreen() = intent { reduce { state.copy(isLoading = true) } } @@ -65,7 +142,33 @@ class MyEvaluationViewModel @Inject constructor( fun navigateMyLectureEvaluation(lectureEvaluation: String) = intent { postSideEffect(MyEvaluationSideEffect.NavigateMyLectureEvaluation(lectureEvaluation)) } + fun navigateMyExamEvaluation(examEvaluation: String) = intent { postSideEffect(MyEvaluationSideEffect.NavigateMyExamEvaluation(examEvaluation)) } + + fun showExamDeleteOrLackPointDialog(id: Long) = intent { + if (state.point >= 30) { + toDeleteExamId = id + showExamEvaluationDeleteDialog() + } else { + showLackPointDialog() + } + } + + fun showLectureDeleteOrLackPointDialog(id: Long) = intent { + if (state.point >= 30) { + toDeleteLectureId = id + showLectureEvaluationDeleteDialog() + } else { + showLackPointDialog() + } + } + + private fun showExamEvaluationDeleteDialog() = intent { reduce { state.copy(showDeleteExamEvaluationDialog = true) } } + fun hideExamEvaluationDeleteDialog() = intent { reduce { state.copy(showDeleteExamEvaluationDialog = false) } } + private fun showLectureEvaluationDeleteDialog() = intent { reduce { state.copy(showDeleteLectureEvaluationDialog = true) } } + fun hideLectureEvaluationDeleteDialog() = intent { reduce { state.copy(showDeleteLectureEvaluationDialog = false) } } + private fun showLackPointDialog() = intent { reduce { state.copy(showLackPointDialog = true) } } + fun hideLackPointDialog() = intent { reduce { state.copy(showLackPointDialog = false) } } } diff --git a/feature/lectureevaluation/my/src/main/java/com/suwiki/feature/lectureevaluation/my/model/MyExamEvaluationsSample.kt b/feature/lectureevaluation/my/src/main/java/com/suwiki/feature/lectureevaluation/my/model/MyExamEvaluationsSample.kt deleted file mode 100644 index 34e167669..000000000 --- a/feature/lectureevaluation/my/src/main/java/com/suwiki/feature/lectureevaluation/my/model/MyExamEvaluationsSample.kt +++ /dev/null @@ -1,37 +0,0 @@ -package com.suwiki.feature.lectureevaluation.my.model - -import com.suwiki.core.model.lectureevaluation.exam.MyExamEvaluation -import kotlinx.collections.immutable.persistentListOf - -val MyExamEvaluationsSample = persistentListOf( - MyExamEvaluation( - id = 0, - lectureName = "컴퓨터구조", - selectedSemester = "2023-2", - semesterList = "2023-2, 2023-1, 2022-2", - examDifficulty = "어려움", - examInfo = listOf("족보"), - examType = "중간고사", - content = "샘플 데이터", - ), - MyExamEvaluation( - id = 1, - lectureName = "인공지능", - selectedSemester = "2023-1", - semesterList = "2023-1, 2022-2, 2022-1", - examDifficulty = "보통", - examInfo = listOf("PPT"), - examType = "기말고사", - content = "샘플 데이터", - ), - MyExamEvaluation( - id = 2, - lectureName = "ICT개론", - selectedSemester = "2020-1", - semesterList = "2020-2, 2020-1, 2019-2", - examDifficulty = "쉬움", - examInfo = listOf("필기"), - examType = "쪽지", - content = "샘플 데이터", - ), -) diff --git a/feature/lectureevaluation/my/src/main/java/com/suwiki/feature/lectureevaluation/my/model/MyLectureEvaluationsSample.kt b/feature/lectureevaluation/my/src/main/java/com/suwiki/feature/lectureevaluation/my/model/MyLectureEvaluationsSample.kt deleted file mode 100644 index 9ea26d908..000000000 --- a/feature/lectureevaluation/my/src/main/java/com/suwiki/feature/lectureevaluation/my/model/MyLectureEvaluationsSample.kt +++ /dev/null @@ -1,53 +0,0 @@ -package com.suwiki.feature.lectureevaluation.my.model - -import com.suwiki.core.model.lectureevaluation.lecture.LectureInfo -import com.suwiki.core.model.lectureevaluation.lecture.MyLectureEvaluation -import kotlinx.collections.immutable.persistentListOf - -val MyLectureEvaluationsSample = persistentListOf( - MyLectureEvaluation( - lectureInfo = LectureInfo( - lectureName = "회로이론", - semesterList = listOf("2023-2", "2023-1", "2022-2"), - ), - selectedSemester = "2023-2", - totalAvg = 2.5f, - satisfaction = 2.5f, - learning = 0.5f, - honey = 3.5f, - team = 0, - difficulty = 0, - homework = 1, - content = "샘플 데이터", - ), - MyLectureEvaluation( - lectureInfo = LectureInfo( - lectureName = "신호 및 시스템", - semesterList = listOf("2022-2", "2022-1", "2021-2"), - ), - selectedSemester = "2022-1", - totalAvg = 2.5f, - satisfaction = 2.5f, - learning = 0.5f, - honey = 3.5f, - team = 0, - difficulty = 0, - homework = 1, - content = "샘플 데이터", - ), - MyLectureEvaluation( - lectureInfo = LectureInfo( - lectureName = "C언어", - semesterList = listOf("2021-2", "2021-1", "2020-2"), - ), - selectedSemester = "2021-1", - totalAvg = 2.5f, - satisfaction = 2.5f, - learning = 4.5f, - honey = 1.5f, - team = 0, - difficulty = 0, - homework = 1, - content = "샘플 데이터", - ), -) diff --git a/feature/lectureevaluation/my/src/main/java/com/suwiki/feature/lectureevaluation/my/navigation/MyEvaluationNavigation.kt b/feature/lectureevaluation/my/src/main/java/com/suwiki/feature/lectureevaluation/my/navigation/MyEvaluationNavigation.kt index f207d2be1..43d8f46a4 100644 --- a/feature/lectureevaluation/my/src/main/java/com/suwiki/feature/lectureevaluation/my/navigation/MyEvaluationNavigation.kt +++ b/feature/lectureevaluation/my/src/main/java/com/suwiki/feature/lectureevaluation/my/navigation/MyEvaluationNavigation.kt @@ -1,6 +1,5 @@ package com.suwiki.feature.lectureevaluation.my.navigation -import androidx.compose.foundation.layout.PaddingValues import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder import androidx.navigation.compose.composable @@ -11,15 +10,13 @@ fun NavController.navigateMyEvaluation() { } fun NavGraphBuilder.myEvaluationNavGraph( - padding: PaddingValues, popBackStack: () -> Unit = {}, navigateMyLectureEvaluationEdit: (String) -> Unit = {}, navigateMyExamEvaluationEdit: (String) -> Unit = {}, handleException: (Throwable) -> Unit, ) { - composable(route = MyEvaluationRoute.route) { + composable(route = MyEvaluationRoute.route) { navBackStackEntry -> MyEvaluationRoute( - padding = padding, popBackStack = popBackStack, navigateMyLectureEvaluation = navigateMyLectureEvaluationEdit, navigateMyExamEvaluation = navigateMyExamEvaluationEdit, diff --git a/feature/lectureevaluation/my/src/main/res/values/strings.xml b/feature/lectureevaluation/my/src/main/res/values/strings.xml index 6591647b1..57f867431 100644 --- a/feature/lectureevaluation/my/src/main/res/values/strings.xml +++ b/feature/lectureevaluation/my/src/main/res/values/strings.xml @@ -5,4 +5,8 @@ 과목명 강의평가 시험정보 + 30포인트가 차감됩니다. + 강의평가를 정말로 삭제하시겠습니까?\n현재 보유 포인트 : %dp + 포인트가 부족합니다. + 현재 보유 포인트 : %dp diff --git a/feature/navigator/src/main/java/com/suwiki/feature/navigator/MainScreen.kt b/feature/navigator/src/main/java/com/suwiki/feature/navigator/MainScreen.kt index f2303c800..dede1b871 100644 --- a/feature/navigator/src/main/java/com/suwiki/feature/navigator/MainScreen.kt +++ b/feature/navigator/src/main/java/com/suwiki/feature/navigator/MainScreen.kt @@ -113,7 +113,6 @@ internal fun MainScreen( ) myEvaluationNavGraph( - padding = innerPadding, popBackStack = navigator::popBackStackIfNotHome, navigateMyLectureEvaluationEdit = navigator::navigateMyLectureEvaluationEdit, navigateMyExamEvaluationEdit = navigator::navigateMyExamEvaluationEdit, diff --git a/feature/timetable/src/main/java/com/suwiki/feature/timetable/timetablelist/TimetableListScreen.kt b/feature/timetable/src/main/java/com/suwiki/feature/timetable/timetablelist/TimetableListScreen.kt index a6887f891..9ff0f4b06 100644 --- a/feature/timetable/src/main/java/com/suwiki/feature/timetable/timetablelist/TimetableListScreen.kt +++ b/feature/timetable/src/main/java/com/suwiki/feature/timetable/timetablelist/TimetableListScreen.kt @@ -17,6 +17,7 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import com.suwiki.core.designsystem.component.appbar.SuwikiAppBarWithTextButton +import com.suwiki.core.designsystem.component.container.SuwikiEditContainer import com.suwiki.core.designsystem.component.dialog.SuwikiDialog import com.suwiki.core.designsystem.theme.Gray95 import com.suwiki.core.designsystem.theme.SuwikiTheme @@ -24,7 +25,6 @@ import com.suwiki.core.designsystem.theme.White import com.suwiki.core.model.timetable.Timetable import com.suwiki.feature.timetable.R import com.suwiki.feature.timetable.navigation.argument.TimetableEditorArgument -import com.suwiki.feature.timetable.timetablelist.component.TimetableEditContainer import org.orbitmvi.orbit.compose.collectAsState import org.orbitmvi.orbit.compose.collectSideEffect @@ -98,8 +98,9 @@ fun TimetableListScreen( LazyColumn { items(items = uiState.timetableList, key = { it.createTime }) { timetable -> - TimetableEditContainer( - timetable = timetable, + SuwikiEditContainer( + name = timetable.name, + semester = "${timetable.year}-${timetable.semester}", onClickEditButton = { onClickTimetableEditButton(timetable) }, onClickDeleteButton = { onClickTimetableDeleteButton(timetable) }, onClick = { onClickTimetableContainer(timetable.createTime) }, diff --git a/remote/lectureevaluation/my/src/main/java/com/suwiki/remote/lectureevaluation/my/response/MyExamEvaluationResponse.kt b/remote/lectureevaluation/my/src/main/java/com/suwiki/remote/lectureevaluation/my/response/MyExamEvaluationResponse.kt index 05286b3d5..ea9ac72e4 100644 --- a/remote/lectureevaluation/my/src/main/java/com/suwiki/remote/lectureevaluation/my/response/MyExamEvaluationResponse.kt +++ b/remote/lectureevaluation/my/src/main/java/com/suwiki/remote/lectureevaluation/my/response/MyExamEvaluationResponse.kt @@ -5,14 +5,14 @@ import kotlinx.serialization.Serializable @Serializable data class MyExamEvaluationResponse( - val id: Long? = null, - val lectureName: String? = null, // 과목 이름 - val professor: String? = null, // 교수이름 - val majorType: String? = null, // 개설학과 - val selectedSemester: String? = null, - val semesterList: String? = null, + val id: Long = -1L, + val lectureName: String = "", // 과목 이름 + val professor: String = "", // 교수이름 + val majorType: String = "", // 개설학과 + val selectedSemester: String = "", + val semesterList: String = "", val examInfo: String, // 시험 방식 - val examType: String? = null, + val examType: String = "", val examDifficulty: String, // 시험 난이도 val content: String, ) @@ -23,8 +23,8 @@ internal fun MyExamEvaluationResponse.toModel() = MyExamEvaluation( professor = professor, majorType = majorType, selectedSemester = selectedSemester, - semesterList = semesterList, - examInfo = examInfo.split(","), + semesterList = semesterList.replace(" ", "").split(","), + examInfo = examInfo.replace(" ", "").split(","), examType = examType, examDifficulty = examDifficulty, content = content, diff --git a/remote/lectureevaluation/my/src/main/java/com/suwiki/remote/lectureevaluation/my/response/MyLectureEvaluationResponse.kt b/remote/lectureevaluation/my/src/main/java/com/suwiki/remote/lectureevaluation/my/response/MyLectureEvaluationResponse.kt index 61459428e..19c685c74 100644 --- a/remote/lectureevaluation/my/src/main/java/com/suwiki/remote/lectureevaluation/my/response/MyLectureEvaluationResponse.kt +++ b/remote/lectureevaluation/my/src/main/java/com/suwiki/remote/lectureevaluation/my/response/MyLectureEvaluationResponse.kt @@ -25,7 +25,7 @@ data class MyLectureEvaluationResponse( internal fun MyLectureEvaluationResponse.toModel() = MyLectureEvaluation( id = id, lectureInfo = LectureInfo( - semesterList = semesterList.split(","), + semesterList = semesterList.replace(" ", "").split(","), professor = professor, majorType = majorType, lectureType = null, diff --git a/remote/lectureevaluation/viewerreporter/src/main/java/com/suwiki/remote/lectureevaluation/viewerreporter/response/lecture/LectureEvaluationAverageResponse.kt b/remote/lectureevaluation/viewerreporter/src/main/java/com/suwiki/remote/lectureevaluation/viewerreporter/response/lecture/LectureEvaluationAverageResponse.kt index 3fb206f74..9dcb47450 100644 --- a/remote/lectureevaluation/viewerreporter/src/main/java/com/suwiki/remote/lectureevaluation/viewerreporter/response/lecture/LectureEvaluationAverageResponse.kt +++ b/remote/lectureevaluation/viewerreporter/src/main/java/com/suwiki/remote/lectureevaluation/viewerreporter/response/lecture/LectureEvaluationAverageResponse.kt @@ -21,7 +21,7 @@ data class LectureEvaluationAverageResponse( internal fun LectureEvaluationAverageResponse.toModel() = LectureEvaluationAverage( id = id, lectureInfo = LectureInfo( - semesterList = semesterList.split(","), + semesterList = semesterList.replace(" ", "").split(","), professor = professor, majorType = majorType, lectureType = lectureType, diff --git a/remote/lectureevaluation/viewerreporter/src/main/java/com/suwiki/remote/lectureevaluation/viewerreporter/response/lecture/LectureEvaluationExtraAverageResponse.kt b/remote/lectureevaluation/viewerreporter/src/main/java/com/suwiki/remote/lectureevaluation/viewerreporter/response/lecture/LectureEvaluationExtraAverageResponse.kt index 707929a37..1c60d1d94 100644 --- a/remote/lectureevaluation/viewerreporter/src/main/java/com/suwiki/remote/lectureevaluation/viewerreporter/response/lecture/LectureEvaluationExtraAverageResponse.kt +++ b/remote/lectureevaluation/viewerreporter/src/main/java/com/suwiki/remote/lectureevaluation/viewerreporter/response/lecture/LectureEvaluationExtraAverageResponse.kt @@ -24,7 +24,7 @@ data class LectureEvaluationExtraAverageResponse( internal fun LectureEvaluationExtraAverageResponse.toModel() = LectureEvaluationExtraAverage( id = id, lectureInfo = LectureInfo( - semesterList = semesterList.split(","), + semesterList = semesterList.replace(" ", "").split(","), professor = professor, majorType = majorType, lectureType = lectureType,