Skip to content

Commit

Permalink
[FE] fix : 리뷰 모아보기 쿼리 캐시로 인한 변경된 형광펜 데이터 반영 오류 수정 (#976)
Browse files Browse the repository at this point in the history
* docs: 질문별 모아보기 목 데이터 주관식 답변 변경

* feat : 현재 sectionId sessionSotrage에 저장하고, 모아보기 페이지 언마운트 시 삭제하는 기능 추가

* feat : 형광펜 API 요청 성공 후, 해당 질문 쿼리 무효화하는 기능 추가

* feat : 형광펜 데이터 로컬 스토리지에 저장한 코드 삭제

* feat : ReviewCollectionPage 에서 clearEditorAnswerMapStorage 코드 삭제
  • Loading branch information
BadaHertz52 authored Nov 19, 2024
1 parent 1b87993 commit 90646b6
Show file tree
Hide file tree
Showing 7 changed files with 39 additions and 50 deletions.
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
import { useEffect, useState } from 'react';
import { useState } from 'react';

import {
EDITOR_ANSWER_CLASS_NAME,
HIGHLIGHT_EVENT_NAME,
HIGHLIGHT_SPAN_CLASS_NAME,
SESSION_STORAGE_KEY,
} from '@/constants';
import { EDITOR_ANSWER_CLASS_NAME, HIGHLIGHT_EVENT_NAME, HIGHLIGHT_SPAN_CLASS_NAME } from '@/constants';
import { EditorAnswerMap, EditorLine, HighlightResponseData, ReviewAnswerResponseData } from '@/types';
import {
getEndLineOffset,
Expand Down Expand Up @@ -76,14 +71,6 @@ const useHighlight = ({
handleModalMessage,
}: UseHighlightProps) => {
const [editorAnswerMap, setEditorAnswerMap] = useState<EditorAnswerMap>(makeInitialEditorAnswerMap(answerList));
const storageKey = `${SESSION_STORAGE_KEY.editorAnswerMap}-${questionId}`;

useEffect(() => {
const item = localStorage.getItem(storageKey);
if (item) {
setEditorAnswerMap(new Map(JSON.parse(item)) as EditorAnswerMap);
}
}, []);

// span 클릭 시, 제공되는 형광펜 삭제 기능 타겟
const [longPressRemovalTarget, setLongPressRemovalTarget] = useState<RemovalTarget | null>(null);
Expand All @@ -92,8 +79,6 @@ const useHighlight = ({

const updateEditorAnswerMap = (newEditorAnswerMap: EditorAnswerMap) => {
setEditorAnswerMap(newEditorAnswerMap);
// editorAnswerMap이 변경될 때 새로운 값을 로컬 스토리지에 저장
localStorage.setItem(storageKey, JSON.stringify(Array.from(newEditorAnswerMap)));
};

const resetHighlightMenu = () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useMutation } from '@tanstack/react-query';
import { useMutation, useQueryClient } from '@tanstack/react-query';

import { postHighlight } from '@/apis/highlight';
import { LOCAL_STORAGE_KEY } from '@/constants';
import { LOCAL_STORAGE_KEY, REVIEW_QUERY_KEY, SESSION_STORAGE_KEY } from '@/constants';
import { EditorAnswerMap } from '@/types';

export interface UseMutateHighlightProps {
Expand All @@ -17,6 +17,21 @@ const useMutateHighlight = ({
updateEditorAnswerMap,
resetHighlightMenu,
}: UseMutateHighlightProps) => {
const queryClient = useQueryClient();
/**
* 형광펜 API 성공 후, 현재 질문에 대한 쿼리 캐시 무효화해서, 변경된 형광펜 데이터 불러오도록 함
*/
const invalidateCurrentSectionQuery = () => {
const sectionId = sessionStorage.getItem(SESSION_STORAGE_KEY.currentReviewCollectionSectionId);

if (sectionId) {
queryClient.invalidateQueries({
predicate: (query) =>
query.queryKey[0] === REVIEW_QUERY_KEY.groupedReviews && query.queryKey[1] === Number(sectionId),
});
}
};

const mutation = useMutation({
mutationFn: (newEditorAnswerMap: EditorAnswerMap) => postHighlight(newEditorAnswerMap, questionId),
onMutate: () => {
Expand All @@ -28,6 +43,8 @@ const useMutateHighlight = ({
// 토스트 모달 지우기
handleErrorModal(false);
localStorage.removeItem(LOCAL_STORAGE_KEY.isHighlightError);
// 해당 질문 쿼리 캐시 무효화
invalidateCurrentSectionQuery();
},
onError: (error) => {
//토스트 모달 띄움
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/constants/storageKey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ export const LOCAL_STORAGE_KEY = {
};

export const SESSION_STORAGE_KEY = {
editorAnswerMap: 'editorAnswerMap-question',
currentReviewCollectionSectionId: 'currentReviewCollectionSectionId',
};
12 changes: 6 additions & 6 deletions frontend/src/mocks/mockData/reviewCollection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ export const GROUPED_REVIEWS_MOCK_DATA: GroupedReviews[] = [
{
id: 2,
content:
'http://localhost:3000/user/review-zone/5WkYQLqW1http://localhost:3000/user/review-zone/5WkYQLqW2http://localhost:3000/user/review-zone/5WkYQLqW3http://localhost:3000/user/review-zone/5WkYQLqW4http://localhost:3000/user/review-zone/5WkYQLqW5http://localhost:3000/user/review-zone/5WkYQLqW6http://localhost:3000/user/review-zone/5WkYQLqW7http://localhost:3000/user/review-zone/5WkYQLqW8http://localhost:3000/user/review-zone/5WkYQLqW9http://localhost:3000/user/review-zone/5WkYQLqW10',
' 복잡한 문제를 체계적으로 분석하고, 창의적인 해결책을 제안하며 이를 실행하는 데 뛰어난 역량을 보여줍니다. 특히, 제한된 시간과 자원 속에서도 효과적으로 우선순위를 정하고 문제를 해결하는 모습을 통해 팀에 큰 신뢰를 주었습니다. 이러한 능력은 팀의 목표 달성과 성장에 큰 기여를 하며, 앞으로도 더 많은 성과를 낼 수 있을 것으로 기대됩니다.!!!!!',
highlights: [
{
lineIndex: 0,
Expand All @@ -132,13 +132,13 @@ export const GROUPED_REVIEWS_MOCK_DATA: GroupedReviews[] = [
{
id: 3,
content:
'장의 시작부분은 짧고 직접적이며, 뒤따라 나올 복잡한 정보를 어떻게 해석해야 할 것인지 프레임을 짜주는 역할을 해야 한다. 그러면 아무리 긴 문장이라도 쉽게 읽힌다.',
'문제의 핵심 원인을 빠르게 파악하고, 이를 바탕으로 실행 가능한 솔루션을 제시하며 팀의 목표를 달성하는 데 큰 기여를 했습니다. 특히, 예상치 못한 상황에서도 냉철한 판단과 적극적인 태도로 해결책을 찾아가는 모습은 팀원들에게 좋은 자극이 되었습니다.',
highlights: [],
},
{
id: 4,
content:
'고액공제건강보험과 건강저축계좌를 만들어 노동자와 고용주가 세금공제를 받을 수 있도록 하면 결과적으로 노동자의 의료보험 부담이 커진다. 세금공제를 받을 수 있도록 하면------------------------------------------- 결과적으로 노동자의 의료보험 부담이 커진다.',
'문제를 다양한 관점에서 바라보며 가장 적합한 해결책을 찾아내는 능력이 뛰어납니다. 특히, 여러 이해관계자 간의 의견을 조율하며 모두가 만족할 수 있는 방안을 제안한 점이 돋보였습니다. 이 과정에서 보여준 적극적인 소통과 논리적인 접근법은 팀의 신뢰를 더욱 높였고, 어려운 과제를 성공적으로 마무리할 수 있는 원동력이 되었습니다.',
highlights: [],
},
],
Expand Down Expand Up @@ -181,7 +181,7 @@ export const GROUPED_REVIEWS_MOCK_DATA: GroupedReviews[] = [
{
id: 2,
content:
'http://localhost:3000/user/review-zone/5WkYQLqW1http://localhost:3000/user/review-zone/5WkYQLqW2http://localhost:3000/user/review-zone/5WkYQLqW3http://localhost:3000/user/review-zone/5WkYQLqW4http://localhost:3000/user/review-zone/5WkYQLqW5http://localhost:3000/user/review-zone/5WkYQLqW6http://localhost:3000/user/review-zone/5WkYQLqW7http://localhost:3000/user/review-zone/5WkYQLqW8http://localhost:3000/user/review-zone/5WkYQLqW9http://localhost:3000/user/review-zone/5WkYQLqW10',
'효율적인 시간 관리 능력을 통해 중요한 작업을 기한 내에 완수하는 모습이 매우 인상적이었습니다. 특히, 작업의 우선순위를 명확히 구분하고 이를 기반으로 체계적으로 계획을 세워 진행하는 점이 돋보였습니다. 이러한 능력 덕분에 팀 전체의 생산성이 향상되었고, 예상치 못한 문제가 발생했을 때도 유연하게 대처하며 프로젝트를 성공적으로 이끌었습니다.',
highlights: [
{
lineIndex: 0,
Expand All @@ -198,13 +198,13 @@ export const GROUPED_REVIEWS_MOCK_DATA: GroupedReviews[] = [
{
id: 3,
content:
'장의 시작부분은 짧고 직접적이며, 뒤따라 나올 복잡한 정보를 어떻게 해석해야 할 것인지 프레임을 짜주는 역할을 해야 한다. 그러면 아무리 긴 문장이라도 쉽게 읽힌다.',
'시간을 효율적으로 활용하는 뛰어난 능력을 보여주셨습니다. 작업 초기부터 명확한 계획을 수립하고 이를 끝까지 유지하는 모습이 인상적이었으며, 예상치 못한 변수에도 침착하게 대처하며 프로젝트의 일정과 품질을 모두 충족시켰습니다. 이러한 점은 팀에 큰 안정감을 주었고, 함께 일하는 사람들에게도 좋은 본보기가 되었습니다.',
highlights: [],
},
{
id: 4,
content:
'고액공제건강보험과 건강저축계좌를 만들어 노동자와 고용주가 세금공제를 받을 수 있도록 하면 결과적으로 노동자의 의료보험 부담이 커진다. 세금공제를 받을 수 있도록 하면------------------------------------------- 결과적으로 노동자의 의료보험 부담이 커진다.',
'타이트한 일정 속에서도 주어진 목표를 체계적으로 달성하며, 동시에 세부적인 디테일까지 놓치지 않는 모습을 보여주셨습니다. 특히, 작업 과정에서 우선순위를 명확히 설정하고, 불필요한 시간 낭비를 줄이는 효율적인 접근 방식은 팀의 전반적인 속도와 성과에 크게 기여했습니다. 앞으로도 이런 시간 관리 능력을 통해 더 많은 성과를 이루시리라 믿습니다.',
highlights: [],
},
],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import React, { useContext, useState } from 'react';
import { useContext, useEffect, useState } from 'react';

import { Accordion, Dropdown, HighlightEditorContainer } from '@/components';
import { DropdownItem } from '@/components/common/Dropdown';
import ReviewEmptySection from '@/components/common/ReviewEmptySection';
import { ReviewInfoDataContext } from '@/components/layouts/ReviewDisplayLayout/ReviewInfoDataProvider';
import { REVIEW_EMPTY } from '@/constants';
import { REVIEW_EMPTY, SESSION_STORAGE_KEY } from '@/constants';
import { GroupedReview } from '@/types';
import { substituteString } from '@/utils';

Expand All @@ -18,6 +18,7 @@ const ReviewCollectionPageContents = () => {
const { revieweeName, projectName, totalReviewCount } = useContext(ReviewInfoDataContext);

const { data: reviewSectionList } = useGetSectionList();

const dropdownSectionList = reviewSectionList.sections.map((section) => {
return { text: section.name, value: section.id };
});
Expand All @@ -29,6 +30,12 @@ const ReviewCollectionPageContents = () => {
review.votes?.sort((voteA, voteB) => voteB.count - voteA.count);
});

useEffect(() => {
return () => {
sessionStorage.removeItem(SESSION_STORAGE_KEY.currentReviewCollectionSectionId);
};
}, []);

const renderContent = (review: GroupedReview) => {
if (review.question.type === 'CHECKBOX') {
const hasNoCheckboxAnswer = review.votes?.every((vote) => vote.count === 0);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useSuspenseQuery } from '@tanstack/react-query';

import { getGroupedReviews } from '@/apis/review';
import { REVIEW_QUERY_KEY } from '@/constants';
import { REVIEW_QUERY_KEY, SESSION_STORAGE_KEY } from '@/constants';
import { GroupedReviews } from '@/types';

interface UseGetGroupedReviewsProps {
Expand All @@ -11,6 +11,7 @@ interface UseGetGroupedReviewsProps {
const useGetGroupedReviews = ({ sectionId }: UseGetGroupedReviewsProps) => {
const fetchGroupedReviews = async () => {
const result = await getGroupedReviews({ sectionId });
sessionStorage.setItem(SESSION_STORAGE_KEY.currentReviewCollectionSectionId, sectionId.toString());
return result;
};

Expand Down
21 changes: 0 additions & 21 deletions frontend/src/pages/ReviewCollectionPage/index.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,9 @@
import { useEffect } from 'react';

import { AuthAndServerErrorFallback, ErrorSuspenseContainer, TopButton } from '@/components';
import ReviewDisplayLayout from '@/components/layouts/ReviewDisplayLayout';
import { SESSION_STORAGE_KEY } from '@/constants';

import ReviewCollectionPageContents from './components/ReviewCollectionPageContents';

const ReviewCollectionPage = () => {
const clearEditorAnswerMapStorage = () => {
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);

// 키에 특정 문자열이 포함되어 있는지 확인
if (key?.includes(SESSION_STORAGE_KEY.editorAnswerMap)) {
localStorage.removeItem(key); // 해당 키 삭제
i--; // removeItem 후에 인덱스가 변경되므로 i를 감소시켜야 함
}
}
};

useEffect(() => {
return () => {
clearEditorAnswerMapStorage();
};
}, []);

return (
<ErrorSuspenseContainer fallback={AuthAndServerErrorFallback}>
<ReviewDisplayLayout isReviewList={false}>
Expand Down

0 comments on commit 90646b6

Please sign in to comment.