Skip to content

Conversation

@yujin5959
Copy link
Member

@yujin5959 yujin5959 commented Aug 13, 2025

🚨 관련 이슈

#82

✨ 변경사항

  • 🐞 BugFix Something isn't working
  • 💻 CrossBrowsing Browser compatibility
  • 🌏 Deploy Deploy
  • 🎨 Design Markup & styling
  • 📃 Docs Documentation writing and editing (README.md, etc.)
  • ✨ Feature Feature
  • 🔨 Refactor Code refactoring
  • ⚙️ Setting Development environment setup
  • ✅ Test Test related (storybook, jest, etc.)

✏️ 작업 내용

데이트 취향 테스트 관련 api 모두 연결 완료 했습니다!

2025-08-13.10.45.03.mov

😅 미완성 작업

N/A

📢 논의 사항 및 참고 사항

적은 퍼센테이지 일 경우 글씨가 밀리는 것 확인하고 수정을 하였고, 100 이상으로 초과하는 퍼센테이지 관련하여 수정완료 하였습니다

@yujin5959 yujin5959 requested a review from yeonjin719 August 13, 2025 06:41
@yujin5959 yujin5959 self-assigned this Aug 13, 2025
@coderabbitai
Copy link

coderabbitai bot commented Aug 13, 2025

Summary by CodeRabbit

  • New Features
    • 데이트 성향 테스트가 서버에서 실시간 질문을 불러오며, 최종 제출 시 결과 페이지로 이동합니다.
    • 결과 페이지에서 사용자 유형과 유형 간 궁합(잘 맞는/안 맞는 유형) 정보를 자동 표시합니다.
  • Improvements
    • 단계 이동 시 이전 응답이 유지되어 재선택이 필요 없습니다.
    • 로딩/에러 상태 안내가 추가되었습니다.
    • 점수 게이지, 특성 설명, 배지/이미지 등 결과 화면이 동적 데이터 기반으로 개선되었습니다.

Walkthrough

데이트 테스트 API 클라이언트와 타입이 추가되고, 스텝 페이지는 서버 문항을 로드해 전체 답안을 유지·제출하며, 결과 페이지는 제출 결과와 관계 유형을 추가 조회해 동적으로 렌더링합니다. 로딩·에러 처리가 추가되었습니다.

Changes

Cohort / File(s) Summary
API 클라이언트
src/api/datetest/datetest.ts
데이트 테스트 API 래퍼 추가: getDateQuestions, submitDateTestAnswers, postDateTestResult, getRelationTypes — axiosInstance 사용 및 응답 타입 지정.
타입 정의
src/types/datetest/datetest.ts
데이트 테스트 관련 타입 추가: IDateTestQuestion, 기본 IDateTestResult, IRelationTypeResult, TDateTestQuestion, TDateTestResultResponse, TRelationTypeResponse.
스텝 UI
src/pages/dateTest/DateTestStep.tsx
하드코딩 문항 제거, React Query로 문항 로드 및 로딩/에러 처리. 전체 답안 상태(allAnswers) 도입, 단계 전환 시 선택 복원, 마지막 단계에서 submitDateTestAnswers로 제출 후 결과 페이지로 네비게이션.
결과 UI
src/pages/dateTest/DatetestResult.tsx
라우터 state 기반 결과 사용으로 전환. getRelationTypes로 베스트/워스트 유형 조회(로딩/에러 처리) 및 동적 이미지·색상·점수·특성 렌더링으로 구조 변경.

Sequence Diagram(s)

sequenceDiagram
  actor User
  participant StepPage as DateTestStep.tsx
  participant Query as React Query
  participant API as axiosInstance
  participant BE as Backend
  participant ResultPage as DatetestResult.tsx

  User->>StepPage: 페이지 진입
  StepPage->>Query: useQuery(getDateQuestions)
  Query->>API: GET /api/v1/dates/preferences/questions
  API->>BE: 요청
  BE-->>API: { questions, size }
  API-->>Query: 응답
  Query-->>StepPage: questions 전달

  User->>StepPage: 마지막 문항 제출
  StepPage->>API: POST /api/v1/dates/preferences/tests (answers)
  API->>BE: 요청
  BE-->>API: { result, aPercentage..., partTypeDescriptions }
  API-->>StepPage: 응답
  StepPage->>ResultPage: navigate(state: resultData)

  ResultPage->>Query: useQuery(getRelationTypes(typeParam))
  Query->>API: GET /api/v1/dates/preferences/relations?type=...
  API->>BE: 요청
  BE-->>API: { bestType, worstType, ... }
  API-->>Query: 응답
  Query-->>ResultPage: relationTypes 전달
  ResultPage-->>User: 결과 및 베스트/워스트 유형 표시
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 13

🔭 Outside diff range comments (1)
src/pages/dateTest/DatetestResult.tsx (1)

254-256: 버튼 type 속성 누락

마지막 버튼에도 type 속성이 없습니다.

-            <button onClick={() => navigate('/datetest')} className="mt-10 px-[48px] py-[16px] bg-[#212121] text-white rounded-[16px] transition">
+            <button type="button" onClick={() => navigate('/datetest')} className="mt-10 px-[48px] py-[16px] bg-[#212121] text-white rounded-[16px] transition">
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e29d228 and 0d7ab0a.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock, !**/*.lock
📒 Files selected for processing (4)
  • src/api/datetest/datetest.ts (1 hunks)
  • src/pages/dateTest/DateTestStep.tsx (4 hunks)
  • src/pages/dateTest/DatetestResult.tsx (4 hunks)
  • src/types/datetest/datetest.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
src/api/datetest/datetest.ts (3)
src/api/axiosInstance.ts (1)
  • axiosInstance (11-14)
src/types/datetest/datetest.ts (2)
  • TDateTestQuestion (52-55)
  • TRelationTypeResponse (57-57)
src/api/home/dateTimes.ts (1)
  • Promise (11-14)
src/types/datetest/datetest.ts (1)
src/types/common/common.ts (1)
  • TCommonResponse (4-9)
src/pages/dateTest/DatetestResult.tsx (3)
src/types/datetest/datetest.ts (2)
  • IDateTestResult (9-31)
  • TRelationTypeResponse (57-57)
src/api/datetest/datetest.ts (1)
  • getRelationTypes (20-25)
src/pages/dateTest/dateTest.tsx (1)
  • DateTest (4-116)
🪛 Biome (2.1.2)
src/pages/dateTest/DatetestResult.tsx

[error] 49-51: Provide an explicit type prop for the button element.

The default type of a button is submit, which causes the submission of a form when placed inside a form element. This is likely not the behaviour that you want inside a React application.
Allowed button types are: submit, button or reset

(lint/a11y/useButtonType)


[error] 65-65: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.

Hooks should not be called after an early return.

For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level

(lint/correctness/useHookAtTopLevel)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🔭 Outside diff range comments (1)
src/pages/dateTest/DatetestResult.tsx (1)

264-266: 하단 네비게이션 버튼에도 type="button" 추가

일관성과 예기치 않은 submit 방지를 위해 명시적 type을 지정하세요.

-            <button onClick={() => navigate('/datetest')} className="mt-10 px-[48px] py-[16px] bg-[#212121] text-white rounded-[16px] transition">
+            <button type="button" onClick={() => navigate('/datetest')} className="mt-10 px-[48px] py-[16px] bg-[#212121] text-white rounded-[16px] transition">
♻️ Duplicate comments (3)
src/pages/dateTest/DatetestResult.tsx (3)

45-69: React 훅 규칙 위반: early return 전에 useQuery를 호출하도록 재배치 필요

현재 useQuery가 early return 뒤에서 조건부로 호출되어 훅 규칙을 위반합니다. 훅은 컴포넌트 최상단에서 무조건 동일한 순서로 호출되어야 합니다. enabled: !!typeParam으로 호출 여부는 제어하되, 훅 자체는 early return 이전에 위치시키세요.

다음과 같이 if (!resultData) 블록을 useQuery 호출 뒤로 이동해 주세요.

-    if (!resultData) {
-        return (
-            <div className="p-6 max-w-3xl mx-auto text-center">
-                <p className="mb-4 text-lg">결과 데이터가 존재하지 않습니다.</p>
-                <button onClick={() => navigate('/datetest')} className="px-6 py-3 bg-gray-800 text-white rounded-lg hover:bg-gray-700 transition">
-                    테스트 화면으로 이동
-                </button>
-            </div>
-        );
-    }
-
-    // URL에서 preferenceType 추출하는 부분입니다
-    const typeParam = resultData?.preferenceType || resultData?.typeDescription?.preferenceType || '';
-
-    const {
-        data: relationData,
-        isLoading,
-        isError,
-    } = useQuery<TRelationTypeResponse>({
-        queryKey: ['relationTypes', typeParam],
-        queryFn: () => getRelationTypes(typeParam),
-        enabled: !!typeParam,
-        retry: false,
-    });
+    // URL에서 preferenceType 추출하는 부분입니다
+    const typeParam = resultData?.preferenceType || resultData?.typeDescription?.preferenceType || '';
+
+    const {
+        data: relationData,
+        isLoading,
+        isError,
+    } = useQuery<TRelationTypeResponse>({
+        queryKey: ['relationTypes', typeParam],
+        queryFn: () => getRelationTypes(typeParam),
+        enabled: !!typeParam,
+        retry: false,
+    });
+
+    if (!resultData) {
+        return (
+            <div className="p-6 max-w-3xl mx-auto text-center">
+                <p className="mb-4 text-lg">결과 데이터가 존재하지 않습니다.</p>
+                <button onClick={() => navigate('/datetest')} className="px-6 py-3 bg-gray-800 text-white rounded-lg hover:bg-gray-700 transition">
+                    테스트 화면으로 이동
+                </button>
+            </div>
+        );
+    }

49-51: 버튼에 type="button" 추가

명시적 type 속성이 없어 폼 내에서 submit 동작을 유발할 수 있습니다. a11y 규칙에도 부합하도록 수정하세요.

-                <button onClick={() => navigate('/datetest')} className="px-6 py-3 bg-gray-800 text-white rounded-lg hover:bg-gray-700 transition">
+                <button type="button" onClick={() => navigate('/datetest')} className="px-6 py-3 bg-gray-800 text-white rounded-lg hover:bg-gray-700 transition">

141-143: alert 사용 지양: 비활성화/토스트로 대체 권장

단순 alert는 사용자 경험을 해칩니다. 기능 준비 전에는 버튼을 비활성화하거나 토스트를 쓰는 편이 낫습니다.

-            <button onClick={() => alert('공유 기능은 추후 지원됩니다.')} className="mt-6 px-6 py-3 bg-black text-white rounded-xl hover:opacity-90 transition">
-                결과 공유하기
-            </button>
+            <button
+                type="button"
+                disabled
+                className="mt-6 px-6 py-3 bg-gray-400 text-gray-200 rounded-xl cursor-not-allowed"
+                title="공유 기능은 추후 지원됩니다"
+            >
+                결과 공유하기
+            </button>
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1ea7fb0 and c720731.

📒 Files selected for processing (1)
  • src/pages/dateTest/DatetestResult.tsx (4 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/pages/dateTest/DatetestResult.tsx (2)
src/types/datetest/datetest.ts (2)
  • IDateTestResult (9-31)
  • TRelationTypeResponse (57-57)
src/api/datetest/datetest.ts (1)
  • getRelationTypes (20-25)
🪛 Biome (2.1.2)
src/pages/dateTest/DatetestResult.tsx

[error] 49-51: Provide an explicit type prop for the button element.

The default type of a button is submit, which causes the submission of a form when placed inside a form element. This is likely not the behaviour that you want inside a React application.
Allowed button types are: submit, button or reset

(lint/a11y/useButtonType)


[error] 65-65: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.

Hooks should not be called after an early return.

For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level

(lint/correctness/useHookAtTopLevel)

🔇 Additional comments (1)
src/pages/dateTest/DatetestResult.tsx (1)

73-79: 퍼센트–타입 매핑 가정 검토 필요

현재 types.slice(0, 4)[aPercentage, bPercentage, cPercentage, dPercentage]의 인덱스 매칭은 서버에서 types 배열의 순서 및 최소 길이(4개 이상)를 보장한다는 전제하에 동작합니다. 만약 순서가 변경되거나 항목이 4개 미만일 경우, 잘못된 매핑이 발생할 수 있습니다.

검토 부탁드립니다:

  • 서버 API 문서나 스키마에서 types 배열의 순서 보장 및 최소 길이(≥4)가 명시되어 있는지 확인
  • 보장이 없다면 type.typeInitial 등을 키로 사용하는 명시적 매핑 객체(map)를 도입하여 퍼센트를 안전하게 결합하도록 로직 수정 고려

@yeonjin719
Copy link
Member

AI가 남기는 코멘트 전부 반영할 필요 없습니다! 적당히 거르면서 작업해주세요!

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (10)
src/api/datetest/datetest.ts (1)

13-16: 중복된 API 함수 통합 필요

submitDateTestAnswerspostDateTestResult이 동일한 엔드포인트를 호출하지만 반환 타입이 다릅니다. 하나의 함수로 통합하여 일관성을 유지하세요.

-export const submitDateTestAnswers = async (payload: { answers: number[] }) => {
-    const { data } = await axiosInstance.post('/api/v1/dates/preferences/tests', payload);
-    return data;
-};
-
-export const postDateTestResult = async (answers: number[]): Promise<TDateTestQuestion> => {
-    const res = await axiosInstance.post('/api/v1/dates/preferences/tests', { answers });
-    return res.data.result;
-};
+export const submitDateTestAnswers = async (payload: { answers: number[] }): Promise<TDateTestResultResponse> => {
+    const { data } = await axiosInstance.post<TDateTestResultResponse>('/api/v1/dates/preferences/tests', payload);
+    if (!data.isSuccess) {
+        throw new Error(data.message || '답안 제출에 실패했습니다');
+    }
+    return data;
+};

Also applies to: 18-21

src/pages/dateTest/DateTestStep.tsx (2)

34-38: useEffect 의존성 배열 누락

useEffect에서 allAnswers를 사용하지만 의존성 배열에 포함되지 않았습니다.

-    }, [currentStep]);
+    }, [currentStep, allAnswers]);

72-73: 로딩/에러 UI 중앙 정렬 필요

현재 로딩과 에러 메시지가 화면 상단에 표시되어 사용자 경험이 저하됩니다.

-    if (isLoading) return <div className="text-center mt-20">질문을 불러오는 중입니다...</div>;
-    if (isError || !data || !data[currentStep - 1]) return <div>질문을 불러올 수 없습니다.</div>;
+    if (isLoading) return (
+        <div className="flex items-center justify-center min-h-screen">
+            <div className="text-center">질문을 불러오는 중입니다...</div>
+        </div>
+    );
+    if (isError || !data || !data[currentStep - 1]) return (
+        <div className="flex items-center justify-center min-h-screen">
+            <div className="text-center">
+                <p className="mb-4">질문을 불러올 수 없습니다.</p>
+                <button 
+                    onClick={() => window.location.reload()} 
+                    className="px-4 py-2 bg-primary-500 text-white rounded"
+                >
+                    다시 시도
+                </button>
+            </div>
+        </div>
+    );
src/types/datetest/datetest.ts (1)

9-29: 인터페이스 export 방식 통일 필요

IDateTestResult만 default export로 되어 있어 다른 인터페이스들과 일관성이 없습니다.

-export default interface IDateTestResult {
+export interface IDateTestResult {

사용처에서도 named import로 변경하세요:

-import type IDateTestResult from '@/types/datetest/datetest';
+import type { IDateTestResult } from '@/types/datetest/datetest';
src/pages/dateTest/DatetestResult.tsx (6)

49-51: 버튼 타입 속성 명시 필요

버튼 요소에 명시적인 type 속성이 없어 폼 내부에서 의도치 않은 submit이 발생할 수 있습니다.

-                <button onClick={() => navigate('/datetest')} className="px-6 py-3 bg-gray-800 text-white rounded-lg hover:bg-gray-700 transition">
+                <button type="button" onClick={() => navigate('/datetest')} className="px-6 py-3 bg-gray-800 text-white rounded-lg hover:bg-gray-700 transition">

59-68: React Hook 규칙 위반 - useQuery 위치 조정 필요

조건부 반환 이후에 useQuery가 호출되어 React Hook 규칙을 위반합니다.

 export default function DateTestResultPage() {
     const navigate = useNavigate();
     const location = useLocation();
 
     const resultData = location.state as IDateTestResult | undefined;
+    const typeParam = resultData?.typeDescription?.preferenceType || '';
+
+    const {
+        data: relationData,
+        isLoading,
+        isError,
+    } = useQuery<TRelationTypeResponse>({
+        queryKey: ['relationTypes', typeParam],
+        queryFn: () => getRelationTypes(typeParam),
+        enabled: !!typeParam,
+        retry: false,
+    });
 
     if (!resultData) {
         return (
             // ... early return JSX
         );
     }
 
-    const typeParam = resultData?.typeDescription?.preferenceType || '';
-
-    const {
-        data: relationData,
-        isLoading,
-        isError,
-    } = useQuery<TRelationTypeResponse>({
-        queryKey: ['relationTypes', typeParam],
-        queryFn: () => getRelationTypes(typeParam),
-        enabled: !!typeParam,
-        retry: false,
-    });

80-86: 반대 퍼센트 계산 로직 수정 필요

현재 percent가 0일 때 oppositePercent도 0이 되는 문제가 있습니다. 100 - percent로 단순화하세요.

-        // 반대 퍼센트 계산 & 제한
-        const oppositePercent = percent > 0 ? Math.max(0, Math.min(100, 100 - percent)) : 0;
+        // 반대 퍼센트 계산
+        const oppositePercent = 100 - percent;

170-173: 우측 게이지 width 계산 오류

우측 게이지가 oppositePercent 대신 percent를 사용하여 시각화가 잘못되었습니다.

-                                style={{ width: `${Math.max(item.percent, 5)}%` }}
+                                style={{ width: `${Math.max(item.oppositePercent, 5)}%` }}

141-143: alert 대신 사용자 친화적 UI 적용

alert는 사용자 경험을 저해합니다. 버튼을 비활성화하거나 툴팁을 사용하세요.

-            <button onClick={() => alert('공유 기능은 추후 지원됩니다.')} className="mt-6 px-6 py-3 bg-black text-white rounded-xl hover:opacity-90 transition">
+            <button 
+                type="button"
+                disabled
+                className="mt-6 px-6 py-3 bg-gray-400 text-gray-200 rounded-xl cursor-not-allowed"
+                title="공유 기능은 추후 지원됩니다"
+            >
                 결과 공유하기
             </button>

215-223: 이미지 리소스 존재 여부 검증 필요

이미지 키가 존재하지 않을 경우 빈 src로 렌더링될 수 있습니다.

-                                {relationData.result?.bestType ? (
+                                {relationData.result?.bestType && 
+                                 componentImages[`../../images/testResults/${relationData.result.bestType}_Component.png`] ? (
                                     <img
                                         src={componentImages[`../../images/testResults/${relationData.result.bestType}_Component.png`]}
                                         alt={`${relationData.result.bestReason}`}
                                         className="max-h-[200px] w-auto object-contain"
                                     />
                                 ) : (
                                     <p>이미지를 찾을 수 없습니다.</p>
                                 )}

동일한 패턴을 worstType 이미지에도 적용하세요.

Also applies to: 241-249

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c720731 and 1f86f50.

📒 Files selected for processing (4)
  • src/api/datetest/datetest.ts (1 hunks)
  • src/pages/dateTest/DateTestStep.tsx (4 hunks)
  • src/pages/dateTest/DatetestResult.tsx (4 hunks)
  • src/types/datetest/datetest.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (4)
src/api/datetest/datetest.ts (2)
src/api/axiosInstance.ts (1)
  • axiosInstance (11-14)
src/types/datetest/datetest.ts (2)
  • TDateTestQuestion (50-53)
  • TRelationTypeResponse (55-55)
src/pages/dateTest/DateTestStep.tsx (2)
src/types/datetest/datetest.ts (1)
  • IDateTestQuestion (3-7)
src/api/datetest/datetest.ts (2)
  • getDateQuestions (5-11)
  • submitDateTestAnswers (13-16)
src/pages/dateTest/DatetestResult.tsx (2)
src/types/datetest/datetest.ts (2)
  • IDateTestResult (9-29)
  • TRelationTypeResponse (55-55)
src/api/datetest/datetest.ts (1)
  • getRelationTypes (23-31)
src/types/datetest/datetest.ts (1)
src/types/common/common.ts (1)
  • TCommonResponse (4-9)
🪛 Biome (2.1.2)
src/pages/dateTest/DatetestResult.tsx

[error] 49-51: Provide an explicit type prop for the button element.

The default type of a button is submit, which causes the submission of a form when placed inside a form element. This is likely not the behaviour that you want inside a React application.
Allowed button types are: submit, button or reset

(lint/a11y/useButtonType)


[error] 65-65: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.

Hooks should not be called after an early return.

For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level

(lint/correctness/useHookAtTopLevel)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

♻️ Duplicate comments (1)
src/api/datetest/datetest.ts (1)

21-24: 반환 타입 불일치 + 중복 함수: 제거 또는 타입 수정 필요

postDateTestResult는 시그니처상 Promise<TDateTestQuestion>를 반환한다고 선언했지만, 실제로는 res.data.result만 반환합니다. 또한 submitDateTestAnswers와 완전히 동일한 엔드포인트를 호출하는 중복입니다. 함수 하나로 통합하는 것을 권장합니다.

다음과 같이 중복 함수를 제거해 주세요:

-export const postDateTestResult = async (answers: number[]): Promise<TDateTestQuestion> => {
-    const res = await axiosInstance.post('/api/v1/dates/preferences/tests', { answers });
-    return res.data.result;
-};

만약 유지가 필요하다면, 최소한 타입 불일치를 아래처럼 수정해 주세요(그리고 submitDateTestAnswers와 동일한 반환 규약으로):

-export const postDateTestResult = async (answers: number[]): Promise<TDateTestQuestion> => {
-    const res = await axiosInstance.post('/api/v1/dates/preferences/tests', { answers });
-    return res.data.result;
-};
+export const postDateTestResult = async (
+    answers: number[]
+): Promise<TDateTestResultResponse['result']> => {
+    const res = await axiosInstance.post<TDateTestResultResponse>(
+        '/api/v1/dates/preferences/tests',
+        { answers }
+    );
+    if (!res.data.isSuccess) {
+        throw new Error(res.data.message || '답변 제출에 실패했습니다');
+    }
+    return res.data.result;
+};

중복 제거 시 호출부 영향 범위를 확인하려면 다음 스크립트를 실행해 주세요:

#!/bin/bash
# 중복 호출 함수 사용처 확인
rg -n "postDateTestResult|submitDateTestAnswers" -A 2 -B 2
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1f86f50 and 5da88ec.

📒 Files selected for processing (1)
  • src/api/datetest/datetest.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/api/datetest/datetest.ts (2)
src/api/axiosInstance.ts (1)
  • axiosInstance (11-14)
src/types/datetest/datetest.ts (2)
  • TDateTestQuestion (50-53)
  • TRelationTypeResponse (55-55)

@@ -0,0 +1,34 @@
import type { TDateTestQuestion, TRelationTypeResponse } from '@/types/datetest/datetest';
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

응답 타입 import 보강 제안 (POST 결과 타입 명시용)

POST 응답 결과 타입을 명확히 다루기 위해 TDateTestResultResponse(존재한다면)를 함께 import하는 것을 권장합니다. 없다면 타입 정의에 추가하거나, 아래 다른 코멘트의 대안(인라인 결과 타입)으로 가도 됩니다.

다음 diff는 TDateTestResultResponse가 이미 존재한다는 가정하에 제안합니다:

-import type { TDateTestQuestion, TRelationTypeResponse } from '@/types/datetest/datetest';
+import type { TDateTestQuestion, TRelationTypeResponse, TDateTestResultResponse } from '@/types/datetest/datetest';

🏁 Script executed:

#!/bin/bash
grep -R "TDateTestResultResponse" -n src/types/datetest

Length of output: 161


🏁 Script executed:

#!/bin/bash
sed -n '1,200p' src/api/datetest/datetest.ts

Length of output: 1309


src/api/datetest/datetest.ts – POST 응답 타입 보강 제안

TDateTestResultResponse가 이미 정의되어 있으므로, 상단 import에 함께 추가한 뒤 POST 요청 시 제네릭으로 지정해 응답 타입 안정성을 높이는 것을 권장합니다:

-import type { TDateTestQuestion, TRelationTypeResponse } from '@/types/datetest/datetest';
+import type { TDateTestQuestion, TRelationTypeResponse, TDateTestResultResponse } from '@/types/datetest/datetest';

추가로, POST 호출부를 아래처럼 수정하면 좋습니다:

- const { data } = await axiosInstance.post('/api/v1/dates/preferences/tests', payload);
+ const { data } = await axiosInstance.post<TDateTestResultResponse>('/api/v1/dates/preferences/tests', payload);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import type { TDateTestQuestion, TRelationTypeResponse } from '@/types/datetest/datetest';
// src/api/datetest/datetest.ts
-import type { TDateTestQuestion, TRelationTypeResponse } from '@/types/datetest/datetest';
+import type { TDateTestQuestion, TRelationTypeResponse, TDateTestResultResponse } from '@/types/datetest/datetest';
...
-export const submitDateTestAnswers = async (payload: { answers: number[] }) => {
- const { data } = await axiosInstance.post('/api/v1/dates/preferences/tests', payload);
+export const submitDateTestAnswers = async (payload: { answers: number[] }) => {
+ const { data } = await axiosInstance.post<TDateTestResultResponse>('/api/v1/dates/preferences/tests', payload);
if (!data.isSuccess) {
throw new Error(data.message || '답안 제출에 실패했습니다');
}
return data.result;
};
🤖 Prompt for AI Agents
In src/api/datetest/datetest.ts around line 1, the file imports
TDateTestQuestion and TRelationTypeResponse but omits TDateTestResultResponse;
add TDateTestResultResponse to the import list and then pass it as the generic
type to the POST request call so the response is strongly typed (e.g., update
the POST call to use the HTTP client’s generic parameter with
TDateTestResultResponse and adjust any variable typings accordingly).

Comment on lines +5 to +11
export const getDateQuestions = async () => {
const res = await axiosInstance.get<TDateTestQuestion>('/api/v1/dates/preferences/questions');
if (!res.data.isSuccess) {
throw new Error(res.data.message || '질문을 불러오는데 실패했습니다');
}
return res.data.result.questions;
};
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

성공/실패 분기 추가는 좋습니다. 반환 타입 명시로 API 계약을 더 분명히 해주세요

현재도 타입 추론은 되지만, 외부에 공개되는 함수 시그니처를 명시하면 유지보수성이 좋아집니다.

다음처럼 반환 타입을 명시해 주세요:

-export const getDateQuestions = async () => {
+export const getDateQuestions = async (): Promise<TDateTestQuestion['result']['questions']> => {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const getDateQuestions = async () => {
const res = await axiosInstance.get<TDateTestQuestion>('/api/v1/dates/preferences/questions');
if (!res.data.isSuccess) {
throw new Error(res.data.message || '질문을 불러오는데 실패했습니다');
}
return res.data.result.questions;
};
export const getDateQuestions = async (): Promise<TDateTestQuestion['result']['questions']> => {
const res = await axiosInstance.get<TDateTestQuestion>('/api/v1/dates/preferences/questions');
if (!res.data.isSuccess) {
throw new Error(res.data.message || '질문을 불러오는데 실패했습니다');
}
return res.data.result.questions;
};
🤖 Prompt for AI Agents
In src/api/datetest/datetest.ts around lines 5 to 11, the exported async
function lacks an explicit return type; add a Promise return type that matches
the API contract (for example Promise<TDateTestQuestion['result']['questions']>)
on the function signature, keep the axios call generic as-is, and ensure
TDateTestQuestion is imported/available so the function signature reads: export
const getDateQuestions = async ():
Promise<TDateTestQuestion['result']['questions']> => { ... }.

Comment on lines +13 to +19
export const submitDateTestAnswers = async (payload: { answers: number[] }) => {
const { data } = await axiosInstance.post('/api/v1/dates/preferences/tests', payload);
if (!data.isSuccess) {
throw new Error(data.message || '답변 제출에 실패했습니다');
}
return data;
};
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

응답 처리 일관성: result만 반환하도록 통일 + POST 제네릭/반환 타입 지정

이 모듈에서 일부 함수는 result만, 일부는 전체 data를 반환합니다. 일관성을 위해 result만 반환하도록 통일하는 것을 권장합니다. 또한 POST 응답 제네릭을 지정해 타입 안정성을 높여주세요.

다음 diff는 TDateTestResultResponse가 존재한다고 가정합니다(없다면 코멘트 하단의 대안 참고):

-export const submitDateTestAnswers = async (payload: { answers: number[] }) => {
-    const { data } = await axiosInstance.post('/api/v1/dates/preferences/tests', payload);
-    if (!data.isSuccess) {
-        throw new Error(data.message || '답변 제출에 실패했습니다');
-    }
-    return data;
-};
+export const submitDateTestAnswers = async (
+    payload: { answers: number[] }
+): Promise<TDateTestResultResponse['result']> => {
+    const { data } = await axiosInstance.post<TDateTestResultResponse>(
+        '/api/v1/dates/preferences/tests',
+        payload
+    );
+    if (!data.isSuccess) {
+        throw new Error(data.message || '답변 제출에 실패했습니다');
+    }
+    return data.result;
+};

대안: TDateTestResultResponse 타입이 없다면, 임시로 아래처럼 결과 타입을 인라인으로 명시할 수 있습니다.

type DateTestSubmitResult = TDateTestQuestion['result']; // 혹은 실제 결과 스키마에 맞는 타입
🤖 Prompt for AI Agents
In src/api/datetest/datetest.ts around lines 13 to 19, the function currently
returns the whole response data and lacks a POST generic; change it to use
axiosInstance.post<TDateTestResultResponse> to type the response, update the
function signature to return the result type (e.g.
Promise<TDateTestResultResponse>) and, on success, return data.result instead of
data; keep the existing error throw but preserve data.message for failure. If
TDateTestResultResponse doesn't exist, create a local type alias (e.g.
DateTestSubmitResult) matching the result shape and use that as the generic and
return type.

Comment on lines +26 to +34
export const getRelationTypes = async (type: string): Promise<TRelationTypeResponse> => {
const res = await axiosInstance.get(`/api/v1/dates/preferences/relations`, {
params: { type },
});
if (!res.data.isSuccess) {
throw new Error(res.data.message || '관계 유형을 불러오는데 실패했습니다');
}
return res.data;
};
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

axios 제네릭 누락 및 반환 형태 일관성 개선

GET 응답 제네릭을 지정하면 내부에서도 정확한 타입을 얻을 수 있습니다. 또한 모듈 내 일관성을 위해 result만 반환하는 규약으로 맞추는 것을 권장합니다.

다음과 같이 수정해 주세요:

-export const getRelationTypes = async (type: string): Promise<TRelationTypeResponse> => {
-    const res = await axiosInstance.get(`/api/v1/dates/preferences/relations`, {
-        params: { type },
-    });
-    if (!res.data.isSuccess) {
-        throw new Error(res.data.message || '관계 유형을 불러오는데 실패했습니다');
-    }
-    return res.data;
-};
+export const getRelationTypes = async (
+    type: string
+): Promise<TRelionTypeResponse['result']> => {
+    const res = await axiosInstance.get<TRelationTypeResponse>(
+        `/api/v1/dates/preferences/relations`,
+        { params: { type } }
+    );
+    if (!res.data.isSuccess) {
+        throw new Error(res.data.message || '관계 유형을 불러오는데 실패했습니다');
+    }
+    return res.data.result;
+};

참고: 위 변경이 어렵다면 최소한 axiosInstance.get<TRelationTypeResponse>(...) 제네릭 지정은 적용해 주세요.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/api/datetest/datetest.ts around lines 26-34, the axios GET call is
missing a response generic and the function returns the whole res.data instead
of the module's convention of returning only result; update the call to
axiosInstance.get<TRelationTypeResponse>(...) so TypeScript infers the correct
shape, change the function signature to return the type of res.data.result (e.g.
Promise<TRelationType[]> or the appropriate result type), and return
res.data.result (keeping the existing error throw using res.data.message or the
fallback message).

@yeonjin719
Copy link
Member

완성하셨으면 그냥 바로 머지 해주세요! 만약 문제 생기면 그때 다시 이슈 파고진행해도 되어서요!

@yujin5959
Copy link
Member Author

넵!!!!!!

@yujin5959 yujin5959 merged commit 0aa9d78 into develop Aug 14, 2025
3 checks passed
@yujin5959 yujin5959 deleted the feature/#82 branch August 14, 2025 05:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants