diff --git a/backend/src/main/java/com/example/Piroin/project/domain/question/dto/QuestionResDTO.java b/backend/src/main/java/com/example/Piroin/project/domain/question/dto/QuestionResDTO.java index 37f18ba..ca5b1e8 100644 --- a/backend/src/main/java/com/example/Piroin/project/domain/question/dto/QuestionResDTO.java +++ b/backend/src/main/java/com/example/Piroin/project/domain/question/dto/QuestionResDTO.java @@ -145,6 +145,8 @@ public record UnderstandingCheckResponse( Integer understoodCount, // 오른쪽 X 뱃지 숫자 Integer notUnderstoodCount, + // 현재 로그인 유저가 누른 선택지. 누르지 않았거나 취소한 상태면 null + UnderstandResChoice selectedChoice, LocalDateTime createdAt ) { } diff --git a/backend/src/main/java/com/example/Piroin/project/domain/question/service/QuestionService.java b/backend/src/main/java/com/example/Piroin/project/domain/question/service/QuestionService.java index af58000..636222f 100644 --- a/backend/src/main/java/com/example/Piroin/project/domain/question/service/QuestionService.java +++ b/backend/src/main/java/com/example/Piroin/project/domain/question/service/QuestionService.java @@ -59,7 +59,7 @@ public QuestionResDTO.QuestionRoomResponse getQuestionRoom(Long sessionId, int u User loginUser = findLoginUser(userId); return new QuestionResDTO.QuestionRoomResponse( toSessionResponse(session), - getUnderstandingSlice(session, understandingIndex), + getUnderstandingSlice(session, understandingIndex, loginUser), getQuestionGroups(session, loginUser) ); } @@ -543,7 +543,11 @@ private QuestionResDTO.SessionResponse toSessionResponse(StudySession session) { ); } - private QuestionResDTO.UnderstandingSliceResponse getUnderstandingSlice(StudySession session, int understandingIndex) { + private QuestionResDTO.UnderstandingSliceResponse getUnderstandingSlice( + StudySession session, + int understandingIndex, + User loginUser + ) { Page understandingPage = understandingCheckRepository .findBySessionOrderByCreatedAtDesc(session, PageRequest.of(understandingIndex, UNDERSTANDING_PAGE_SIZE)); @@ -559,17 +563,17 @@ private QuestionResDTO.UnderstandingSliceResponse getUnderstandingSlice(StudySes // attendanceCount는 프론트 화면의 "13/29" 중 29에 해당한다. int attendanceCount = attendanceService.countAttendedBySession(session); return new QuestionResDTO.UnderstandingSliceResponse( - toUnderstandingCheckResponse(current, attendanceCount), understandingIndex, totalCount, + toUnderstandingCheckResponse(current, attendanceCount, loginUser), understandingIndex, totalCount, understandingIndex < totalCount - 1, understandingIndex > 0 ); } private QuestionResDTO.UnderstandingCheckResponse toUnderstandingCheckResponse(UnderstandingCheck check) { - return toUnderstandingCheckResponse(check, null); + return toUnderstandingCheckResponse(check, null, null); } private QuestionResDTO.UnderstandingCheckResponse toUnderstandingCheckResponse( - UnderstandingCheck check, Integer attendanceCount + UnderstandingCheck check, Integer attendanceCount, User loginUser ) { // understoodCount/notUnderstoodCount는 오른쪽 O/X 뱃지 숫자로 그대로 사용한다. int understoodCount = understandingResponseRepository.countByCheckAndChoice( @@ -585,10 +589,20 @@ private QuestionResDTO.UnderstandingCheckResponse toUnderstandingCheckResponse( attendanceCount, understoodCount, notUnderstoodCount, + getSelectedChoice(check, loginUser), check.getCreatedAt() ); } + private UnderstandResChoice getSelectedChoice(UnderstandingCheck check, User loginUser) { + if (loginUser == null) { + return null; + } + return understandingResponseRepository.findByCheckAndUser(check, loginUser) + .map(UnderstandingResponse::getChoice) + .orElse(null); + } + private QuestionResDTO.QuestionGroupsResponse getQuestionGroups(StudySession session, User loginUser) { List questions = questionRepository.findBySessionAndDeletedAtIsNull(session); QuestionSummaryContext summaryContext = getQuestionSummaryContext(questions, loginUser); diff --git a/frontend/src/pages/qna/QnAListPage.js b/frontend/src/pages/qna/QnAListPage.js index 635d97c..ef9f10d 100644 --- a/frontend/src/pages/qna/QnAListPage.js +++ b/frontend/src/pages/qna/QnAListPage.js @@ -62,6 +62,13 @@ function QnAListPage() { setSessionTitle(`${session.week}주차 ${DAY_OF_WEEK_KO[session.dayOfWeek]}요일 ${DAY_PART_KO[session.dayPart]} (${session.title})`); setUnderstanding(understanding); + const currentCheck = understanding?.current; + if (currentCheck?.checkId) { + setMyChoices(prev => ({ + ...prev, + [currentCheck.checkId]: currentCheck.selectedChoice ?? null, + })); + } const allQ = [ ...(questions.popularQuestions ?? []), @@ -116,29 +123,31 @@ function QnAListPage() { const handleUnderstandChoice = async (choice) => { if (!understanding?.current?.checkId) return; const checkId = understanding.current.checkId; - const newChoice = myChoices[checkId] === choice ? null : choice; + const previousChoice = myChoices[checkId] ?? null; + const newChoice = previousChoice === choice ? null : choice; setMyChoices(prev => ({ ...prev, [checkId]: newChoice })); - if (!newChoice) return; try { const res = await authFetch( `/api/sessions/${sessionId}/understanding-checks/${checkId}/responses`, - { method: 'POST', body: JSON.stringify({ choice: newChoice }) } + { method: 'POST', body: JSON.stringify({ choice }) } ); if (!res.ok) throw new Error(); const json = await res.json(); - if (json.isSuccess) { - setUnderstanding(prev => ({ - ...prev, - current: { - ...prev.current, - understoodCount: json.result.understoodCount, - notUnderstoodCount: json.result.notUnderstoodCount, - attendanceCount: json.result.attendanceCount, - respondedCount: json.result.respondedCount, - } - })); - } + if (!json.isSuccess) throw new Error(json.message); + setMyChoices(prev => ({ ...prev, [checkId]: json.result.selectedChoice ?? null })); + setUnderstanding(prev => ({ + ...prev, + current: { + ...prev.current, + understoodCount: json.result.understoodCount, + notUnderstoodCount: json.result.notUnderstoodCount, + attendanceCount: json.result.attendanceCount, + respondedCount: json.result.respondedCount, + selectedChoice: json.result.selectedChoice, + } + })); } catch (err) { + setMyChoices(prev => ({ ...prev, [checkId]: previousChoice })); console.error('이해도 응답 실패:', err); } }; @@ -593,4 +602,4 @@ function QnAListPage() { ); } -export default QnAListPage; \ No newline at end of file +export default QnAListPage;