Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/jaino/#94 #111

Merged
merged 22 commits into from
Feb 3, 2024
Merged

Feature/jaino/#94 #111

merged 22 commits into from
Feb 3, 2024

Conversation

jeongjaino
Copy link
Member

@jeongjaino jeongjaino commented Jan 22, 2024

1. 📄 관련된 이슈 및 소개

#94 설문 정보 소개 페이지 구현

2. 🔥 변경된 점

  1. 설문 정보 소개 페이지 구현
image
  1. 설문 이전 페이지 전환 로직 구현
 onClickLeftButton = {
                    when (surveyAnswerState) {
                        SurveyAnswerState.SURVEY_OVERVIEW -> navigateToSurvey()
                        SurveyAnswerState.SURVEY_ANSWER -> viewModel.setSurveyAnswerState(
                            SurveyAnswerState.SURVEY_OVERVIEW,
                        )
                    }
                }, 

설문 응답 페이지 -> 설문 정보 페이지 -> 설문 홈 의 전환이 되도록 구현

  1. 이전 항목 답변 수정 기능 구현
    이전 보내드린 영상 참고 부탁드립니다잇!

  2. 설문 응답 페이지 컬럼 속성 변경

  • 피그마와 동일하게 구현
  • SpaceBetween -> padding + weight로 변경

3. ✅ 꼭 확인해줬으면 하는 점

SurveyAnswerScreen

when (surveyFormUiState) {
            is SurveyFormUiState.Init -> {}

            is SurveyFormUiState.Success -> {
                SurveyAnswerContent(
                    surveyAnswerState = surveyAnswerState,
                    surveyForm = surveyFormUiState.surveyForm,
                    eventName = eventName,
                    questionNumber = questionNumber,
                    subjectiveAnswer = subjectiveAnswer,
                    objectiveAnswer = objectiveAnswer,
                    onSubjectiveAnswerChanged = viewModel::setSubjectiveAnswer,
                    onObjectiveAnswerSelected = viewModel::setObjectiveAnswer,
                    onStartSurveyButtonClicked = {
                        viewModel.setSurveyAnswerState(SurveyAnswerState.SURVEY_ANSWER)
                    },
                    onNextQuestionButtonClicked = {
                        if (questionNumber < surveyAnswerList.size) { // 작성한 답변을 수정하는 경우
                            viewModel.editSurveyAnswer()
                        } else {
                            viewModel.addSurveyAnswer()
                        }

                        val lastQuestionNumber =
                            surveyFormUiState.surveyForm.surveyQuestionList.lastIndex
                        if (questionNumber == lastQuestionNumber) { // 마지막 질문에 답변을 한 경우
                            viewModel.submitSurvey()
                            return@SurveyAnswerContent
                        }

                        viewModel.setNextQuestionAndAnswer() // 다음 질문 불러오기
                    },
                    onPreviousQuestionButtonClicked = {
                        // 응답의 갯수가 질문의 갯수보다 작은 경우
                        if (questionNumber >= surveyAnswerList.size) {
                            viewModel.addSurveyAnswer()
                        }
                        viewModel.setPreviousQuestionAndAnswer()
                    },
                    modifier = Modifier
                        .fillMaxSize()
                        .padding(paddingValues)
                        .padding(16.dp),
                )
            }
        }

중요 로직 설명

  1. onNextQuestionButtonClicked -> 다음 질문 버튼 클릭시 발생 콜백 함수
  • 현재 질문 번호가, 작성된 응답 목록의 전체 크기보다 작은 경우 : 응답 수정 (작성된 응답이므로)
  • 현재 질문 번호가, 작성된 응답 목록의 전체 크기보다 큰 경우 : 응답 추가 (첫 응답이므로)
  • 현재 질문 번호가, 전체 질문의 마지막 번호와 같은 경우 : 설문 등록 (마지막 질문에서, 등록 버튼을 누른 것이므로)
  • 마지막 질문 번호가 아닌 경우, 다음 질문을 불러오기
  1. onPreviousQuestionButtonClicked -> 이전 질문 버튼 클릭시 발생 콜백 함수
  • 현재 질문 번호가, 작성된 응답 목록의 전체 크기보다 크거나 같은 경우 : 응답 추가 (상태를 저장하고, 이전 질문을 불러와야 하기 때문)
  • 이전 질문 불러오기

SurveyAnswerViewModel

 fun setNextQuestionAndAnswer() {
        _questionNumber.value += 1
        if (_questionNumber.value < _surveyAnswerList.value.size) { //  <------ 여기가 문제
            setSurveyAnswer()
        }
    }

    fun setPreviousQuestionAndAnswer() {
        _questionNumber.value -= 1
        setSurveyAnswer()
    }

    private fun setSurveyAnswer() {
        val surveyAnswer = _surveyAnswerList.value[_questionNumber.value]
        when (surveyAnswer.questionType) {
            QuestionType.SUBJECTIVE -> {
                setSubjectiveAnswer(surveyAnswer.questionAnswer)
            }

            QuestionType.OBJECTIVE -> {
                when (surveyAnswer.questionAnswer) {
                    "GOOD" -> setObjectiveAnswer(Rating.GOOD)
                    "MEDIOCRE" -> setObjectiveAnswer(Rating.MEDIOCRE)
                    "BAD" -> setObjectiveAnswer(Rating.BAD)
                }
            }
        }
    }

Screen(View)에서 해당 setSurveyAnswer를 각각 호출하지 않고, ViewModel에서 호출한 이유

  • 컴포즈 지식이 미흡해, 원인 파악이 어려움 ㅠ.ㅠ
  • 해당 로직을 View로 옮기면, 다음과 같은 로직이 됨.
    • ViewModel의 QuestionNumber를 조작하는 함수를 호출 (문제가 되는 로직이 다음 번호 로직이니, QuestionNumber를 1 증가시키는 함수를 호출했다고 가정.)
    • View에서 QuestionNumber State와 (ViewModel QuestionNumber를 Collect하는) SurveyAnswerSize (마찬가지로 ViewModel에서 Collect하는)와 비교
    • 문제는 여기서 발생. ViewModel에서 QuestionNumber를 증가하는 함수를 호출 했음에도 불구하고, 비교되는 (Collected State) QuestionNumber 는 업데이트 되지 않은채로 비교가 됨.
  • 따라서 위와 같이, State가 아닌, ViewModel의 상태를 가져와 비교하는 로직으로 대체하게 됨.
  • 리컴포지션은 낙관적이라며 !!!!!!!!!!!!!! 바로 다음 로직이라 반응 못하는 것 같아요 ,,

4. 📸 스크린샷(선택)

5. 💡알게된 혹은 궁금한 사항들

@jeongjaino jeongjaino added 🚀진호🚀 ESTP 정진호 23세 🌱기능🌱 새로운 기능 두두둥장! 🎨유아이🎨 피그마, 엑세멜, 컴포즈 유아이/유엑스 작업 🔥리뷰 기다리는 중🔥 PR을 올리고 코드리뷰를 기다리고 있는 상태입니다. labels Jan 22, 2024
@jeongjaino jeongjaino self-assigned this Jan 22, 2024
@jeongjaino jeongjaino linked an issue Jan 22, 2024 that may be closed by this pull request
2 tasks
@jeongjaino jeongjaino closed this Jan 22, 2024
@jeongjaino jeongjaino reopened this Jan 22, 2024
@tgyuuAn tgyuuAn self-requested a review January 22, 2024 14:03
Copy link
Member

@tgyuuAn tgyuuAn left a comment

Choose a reason for hiding this comment

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

진호상 고생했어요!

취업 전 마지막 주에 누가 과연 스프린트를 돌리고 있을까요...

너무 고생하셨습니다. 👍👍👍😁😁😁

Comment on lines 11 to 12

internal fun getSeoulDateTimeNow() = LocalDateTime.now(ZoneId.of("Asia/Seoul"))
Copy link
Member

Choose a reason for hiding this comment

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

👍👍👍

Comment on lines 42 to 44
fun getUserRole() {
viewModelScope.launch {
getUserRoleUseCase()
Copy link
Member

Choose a reason for hiding this comment

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

여기 바로 = 할 수 있을 것 같아요!

}
}

val isFirstQuestion = questionNumber > 0
Copy link
Member

Choose a reason for hiding this comment

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

isFirestQuestin 이면,

첫 번째 항목임을 물어보는 것 같은데

questionNumber > 0 이 0보다 클 때만 True를 뱉으므로,

사실 변수명과 반대로 로직이 돌아가는 것 아닐까요?!

val isFirstQuestion = questionNumber == 0

이지 않을까요?!

Copy link
Member Author

Choose a reason for hiding this comment

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

오호 완전히 제대로 반대로 잡았네요 ㄷㄷㄷ 수정해보겠습니다

questionType: QuestionType,
subjectiveAnswer: String,
): Boolean {
if (questionType == QuestionType.SUBJECTIVE) return subjectiveAnswer.length >= 10
Copy link
Member

Choose a reason for hiding this comment

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

여기 스코프를 넣어주는 것 보다 안넣어주는 것이 더 낫나요 ?!

사실 클린 코드책에서는 이렇게 단일 식이더라도 스코프를 넣어라고 말하긴 하는데,

이건 명확한 답이 없기 때문에 진호님의 의견이 궁금해요!

Copy link
Member Author

Choose a reason for hiding this comment

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

아마 블락을 사용하는게, 가독성 면에서도 확실히 다른 로직과 구분이 돼서 좋을 것 같아요 !

뒤에도 따로 복잡한 로직이 안들어 있어서, 단순히 코드 길이를 줄이기 위해서 다음과 같이 구현했어요 !

코드 길이와 가독성 측면에서의 항상 선택을 해야하는 것 같아요

@@ -53,7 +42,7 @@ internal fun SurveyAnswerScreen(
viewModel.surveyAnswerEvent.collectLatest {
when (it) {
is SurveyAnswerViewModel.SurveyAnswerUiEvent.SubmitSuccess -> {
Copy link
Member

Choose a reason for hiding this comment

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

여기는 스코프 빼도 될 것 같아요!

Comment on lines +58 to +69
contentWindowInsets = WindowInsets(0.dp),
topBar = {
WappSubTopBar(
titleRes = R.string.survey_answer,
showLeftButton = true,
modifier = Modifier.padding(top = 16.dp), // 하단은 Content Padding에 의존
onClickLeftButton = {
when (surveyAnswerState) {
SurveyAnswerState.SURVEY_OVERVIEW -> navigateToSurvey()
SurveyAnswerState.SURVEY_ANSWER -> viewModel.setSurveyAnswerState(
SurveyAnswerState.SURVEY_OVERVIEW,
)
Copy link
Member

Choose a reason for hiding this comment

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

👍👍👍👍😁😁

Comment on lines +133 to +153
when (surveyAnswerState) {
SurveyAnswerState.SURVEY_OVERVIEW -> {
SurveyOverview(
surveyForm = surveyForm,
modifier = modifier.padding(top = 16.dp),
eventName = eventName,
onStartSurveyButtonClicked = onStartSurveyButtonClicked,
)
}

val isLastQuestion = questionNumber == lastQuestionNumber // 마지막 응답일 경우, 완료로 변경
SurveyAnswerButton(
isLastQuestion = isLastQuestion,
onButtonClicked = onNextButtonClicked,
isEnabled = isButtonEnabled(surveyQuestion.questionType, subjectiveAnswer),
)
}
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun SurveyAnswerTopBar(
onBackButtonClicked: () -> Unit,
) {
CenterAlignedTopAppBar(
title = {
Text(
text = stringResource(R.string.survey_answer),
textAlign = TextAlign.Center,
modifier = Modifier.fillMaxWidth(),
style = WappTheme.typography.contentBold,
color = WappTheme.colors.white,
SurveyAnswerState.SURVEY_ANSWER -> {
SurveyAnswerForm(
surveyForm = surveyForm,
modifier = modifier,
questionNumber = questionNumber,
subjectiveAnswer = subjectiveAnswer,
objectiveAnswer = objectiveAnswer,
onSubjectiveAnswerChanged = onSubjectiveAnswerChanged,
onObjectiveAnswerSelected = onObjectiveAnswerSelected,
onNextQuestionButtonClicked = onNextQuestionButtonClicked,
onPreviousQuestionButtonClicked = onPreviousQuestionButtonClicked,
Copy link
Member

Choose a reason for hiding this comment

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

위에 when절은 개행이 없는데,

SURVEY_ANSWER은 개행이 하나 들어가있어요.

when절의 시작 구문은 개행이 필요없지 않을까요?!

Copy link
Member Author

Choose a reason for hiding this comment

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

그럼요 !!!

Comment on lines 72 to 76
private fun getEvent() {
viewModelScope.launch {
getEventUseCase(eventId = _surveyForm.value.eventId)
.onSuccess { event ->
_eventName.value = event.title
Copy link
Member

Choose a reason for hiding this comment

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

여기도 바로 = 넣을 수 있을 것 같아욥

Comment on lines 113 to 137
fun modifySurveyAnswer() {
val questionNumber = _questionNumber.value
val surveyQuestion = _surveyForm.value.surveyQuestionList[questionNumber]
val surveyAnswerList = _surveyAnswerList.value

when (surveyQuestion.questionType) { // 새로운 질문에 답변을 작성하는 경우
QuestionType.SUBJECTIVE -> {
surveyAnswerList[questionNumber] = SurveyAnswer(
questionType = surveyQuestion.questionType,
questionTitle = surveyQuestion.questionTitle,
questionAnswer = _subjectiveAnswer.value,
)
clearSubjectiveAnswer() // 질문 상태 초기화
}

QuestionType.OBJECTIVE -> {
surveyAnswerList[questionNumber] = SurveyAnswer(
questionType = surveyQuestion.questionType,
questionTitle = surveyQuestion.questionTitle,
questionAnswer = _objectiveAnswer.value.toString(),
)
clearObjectiveAnswer()
}
}
}
Copy link
Member

Choose a reason for hiding this comment

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

modfiy는 수정하다인가요 ?!

기존 패키지명으로 사용하고 있던 edit이나 HTTP 메소드로 사용되는 Update랑은 다른 개념일까요?

Copy link
Member Author

Choose a reason for hiding this comment

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

찾아보니

기존에 사용하는 edit이 더 좋을 것 같아요 !

네이밍 프리픽스도 고정할수 있고, edit이 약간 내용을 수정하는 느낌이고, Modfify는 개선하는 행위 자체를 의미한다고 하네요

image

@tgyuuAn tgyuuAn added ✏️수정 요청✏️ 코드 리뷰후 코드 수정 요청 and removed 🔥리뷰 기다리는 중🔥 PR을 올리고 코드리뷰를 기다리고 있는 상태입니다. labels Jan 22, 2024
@jeongjaino
Copy link
Member Author

마지막 화면에서 작성하고, 이전 버튼을 누르면 상태가 저장되지 않고 날라가는 버그 발견

@tgyuuAn
Copy link
Member

tgyuuAn commented Jan 23, 2024

마지막 화면에서 작성하고, 이전 버튼을 누르면 상태가 저장되지 않고 날라가는 버그 발견

이번 PR에서 해결하시나요?!

@jeongjaino
Copy link
Member Author

마지막 화면에서 작성하고, 이전 버튼을 누르면 상태가 저장되지 않고 날라가는 버그 발견

이번 PR에서 해결하시나요?!

그럼요 ~

@jeongjaino jeongjaino added 🔥리뷰 기다리는 중🔥 PR을 올리고 코드리뷰를 기다리고 있는 상태입니다. and removed ✏️수정 요청✏️ 코드 리뷰후 코드 수정 요청 labels Jan 30, 2024
@jeongjaino
Copy link
Member Author

태규상 변경내용 수정하고, 버그도 해결했습니다잇 !

…re/jaino/#94

# Conflicts:
#	core/network/src/main/java/com/wap/wapp/core/network/source/attendancestatus/AttendanceStatusDataSourceImpl.kt
#	core/network/src/main/java/com/wap/wapp/core/network/source/event/EventDataSourceImpl.kt
#	core/network/src/main/java/com/wap/wapp/core/network/utils/LocalDateTime.kt
Copy link
Member

@tgyuuAn tgyuuAn left a comment

Choose a reason for hiding this comment

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

LGTM 입니다 진호상.

몇개 잔잔바리들만 코멘트 남겨놨씁니다. 👍👍

이제 해당 기능에 자신감 100퍼신가요?

Comment on lines 43 to +45
viewModel.getUserRole() // 유저 권한 검색

viewModel.userRole.collectLatest { managerState ->
when (managerState) {
UserRole.GUEST -> { showGuestScreen = true }
UserRole.MEMBER -> { showValidationScreen = true }
UserRole.MANAGER -> viewModel.getEventSurveyList()
viewModel.userRole.collectLatest { userRoleUiState ->
Copy link
Member

Choose a reason for hiding this comment

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

viewModel.apply{
}

를 이용해서 반복되는 viewModel을 제거하는 것은 별로일까요?

근데 사실 2개 밖에 없어서 더 안 좋아보일 것 같기도 하고..🙃🙃

) {
Column(
modifier = Modifier.fillMaxWidth(),
Copy link
Member

Choose a reason for hiding this comment

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

👍👍👍

Comment on lines +89 to +103
if (isLastQuestion) {
WappButton(
textRes = R.string.submit,
onClick = { onButtonClicked() },
isEnabled = isEnabled,
modifier = modifier,
)
} else {
WappButton(
textRes = R.string.next,
onClick = { onButtonClicked() },
isEnabled = isEnabled,
modifier = modifier,
)
}
Copy link
Member

Choose a reason for hiding this comment

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

if (isLastQuestion) 부분이

지금 textRes 빼고는 나머지가 다 같은 것 같은데 textRes 안에서 분기문을 줘도 될 것 같아요!

@tgyuuAn tgyuuAn added ✏️수정 요청✏️ 코드 리뷰후 코드 수정 요청 🌟머지 해주세요🌟 코드 리뷰가 완료된 뒤 PR을 올린사람이 Merge를 하면 되는 단계입니다. and removed 🔥리뷰 기다리는 중🔥 PR을 올리고 코드리뷰를 기다리고 있는 상태입니다. ✏️수정 요청✏️ 코드 리뷰후 코드 수정 요청 labels Feb 2, 2024
@jeongjaino
Copy link
Member Author

다음 아슈에서 언급하신부분 수정하는 걸로 하겠습니다 !

@jeongjaino jeongjaino merged commit 7c41c14 into develop Feb 3, 2024
@jeongjaino
Copy link
Member Author

LGTM 입니다 진호상.

몇개 잔잔바리들만 코멘트 남겨놨씁니다. 👍👍

이제 해당 기능에 자신감 100퍼신가요?

완한드레드파센타입니다

@tgyuuAn tgyuuAn deleted the feature/jaino/#94 branch February 6, 2024 08:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🌟머지 해주세요🌟 코드 리뷰가 완료된 뒤 PR을 올린사람이 Merge를 하면 되는 단계입니다. 🌱기능🌱 새로운 기능 두두둥장! 🎨유아이🎨 피그마, 엑세멜, 컴포즈 유아이/유엑스 작업 🚀진호🚀 ESTP 정진호 23세
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[UI]: (회원) 설문 작성시 설문 형식 정보 소개 UI 추가 구현
2 participants