Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions src/api/datetest/datetest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
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).


import { axiosInstance } from '../axiosInstance';

export const getDateQuestions = async () => {
const res = await axiosInstance.get<TDateTestQuestion>('/api/v1/dates/preferences/questions');
return res.data.result.questions;
};

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 getRelationTypes = async (type: string): Promise<TRelationTypeResponse> => {
const res = await axiosInstance.get(`/api/v1/dates/preferences/relations`, {
params: { type },
});
return res.data;
};
64 changes: 40 additions & 24 deletions src/pages/dateTest/DateTestStep.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,12 @@
import { useEffect, useState } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import { useQuery } from '@tanstack/react-query';

interface IQuestion {
id: number;
title: string;
options: string[];
}
import type { IDateTestQuestion } from '@/types/datetest/datetest';

import { getDateQuestions, submitDateTestAnswers } from '@/api/datetest/datetest';

const TOTAL_QUESTIONS = 40;
const dummyQuestions: IQuestion[] = Array.from({ length: TOTAL_QUESTIONS }, (_, i) => ({
id: i + 1,
title: `당신의 데이트 스타일은 어떤가요?`,
options: ['야외 활동 좋아해요', '집에서 쉬는 게 좋아요'],
}));

function ProgressBar({ step, total }: { step: number; total: number }) {
const percentage = (step / total) * 100;
Expand All @@ -26,19 +20,29 @@ function ProgressBar({ step, total }: { step: number; total: number }) {
export default function DateTestStep() {
const { step } = useParams<{ step: string }>();
const navigate = useNavigate();

const currentStep = Number(step);
const question = dummyQuestions[currentStep - 1];
const currentStep = parseInt(step ?? '1', 10);

const [selectedOptions, setSelectedOptions] = useState<number[]>([]);
const [allAnswers, setAllAnswers] = useState<number[]>(Array(TOTAL_QUESTIONS).fill(0));

const { data, isLoading, isError } = useQuery<IDateTestQuestion[]>({
queryKey: ['dateTestQuestions'],
queryFn: getDateQuestions,
staleTime: 1000 * 60 * 5,
});

useEffect(() => {
setSelectedOptions([]);
const prevAnswer = allAnswers[currentStep - 1];
setSelectedOptions(prevAnswer ? [prevAnswer - 1] : []);
window.scrollTo(0, 0);
}, [currentStep]);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

useEffect 의존성 배열 누락

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

-    }, [currentStep]);
+    }, [currentStep, allAnswers]);
📝 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
}, [currentStep]);
// …inside your useEffect…
}, [currentStep, allAnswers]);
🤖 Prompt for AI Agents
In src/pages/dateTest/DateTestStep.tsx around line 38, the useEffect uses
allAnswers but does not include it in the dependency array; add allAnswers to
the dependency array (or memoize/stabilize it) so the effect re-runs when
answers change, and if adding it could cause unwanted loops ensure the effect
logic uses stable references or guards (e.g., compare previous value or
useCallback/useMemo) to prevent infinite re-renders.


const handleSelect = (idx: number) => {
setSelectedOptions([idx]); // 항상 하나만 선택되도록
const answerValue = idx + 1; // 0 -> 1, 1 -> 2
const updatedAnswers = [...allAnswers];
updatedAnswers[currentStep - 1] = answerValue;
setAllAnswers(updatedAnswers);
setSelectedOptions([idx]);
};

const handlePrev = () => {
Expand All @@ -49,18 +53,27 @@ export default function DateTestStep() {
}
};

const handleNext = () => {
const handleNext = async () => {
if (selectedOptions.length !== 1) return;

if (currentStep < TOTAL_QUESTIONS) {
navigate(`/datetest/${currentStep + 1}`);
} else {
navigate('/datetest/result');
try {
const response = await submitDateTestAnswers({ answers: allAnswers });
console.log('결과 응답:', response);
navigate('/datetest/result', { state: response.result });
} catch (error) {
console.error('결과 제출 실패:', error);
alert('결과를 제출하는 중 오류가 발생했습니다.');
}
}
};

if (!question) {
return <div>질문을 불러올 수 없습니다.</div>;
}
if (isLoading) return <div className="text-center mt-20">질문을 불러오는 중입니다...</div>;
if (isError || !data || !data[currentStep - 1]) return <div>질문을 불러올 수 없습니다.</div>;

const question = data[currentStep - 1];

return (
<div className="flex flex-col px-6 max-w-3xl mx-auto py-[156px]">
Expand Down Expand Up @@ -88,16 +101,19 @@ export default function DateTestStep() {
</div>

{/* 질문 */}
<h2 className="text-2xl font-bold mb-6 text-left w-full">{question.title}</h2>
<h2 className="text-2xl font-bold mb-6 text-left w-full">{question.question}</h2>

{/* 선택지 */}
<div className="flex flex-col gap-4 w-full">
{question.options.map((opt, idx) => (
{[question.firstAnswer, question.secondAnswer].map((opt, idx) => (
<button
key={idx}
onClick={() => handleSelect(idx)}
className={`w-full text-left px-5 py-3 rounded-lg border border-[#C3C3C3]
${selectedOptions.includes(idx) ? 'bg-primary-700 text-white border-primary-700' : 'bg-white text-gray-800 hover:bg-primary-100 border border-[#c3c3c3]'}`}
className={`w-full text-left px-5 py-3 rounded-lg border ${
selectedOptions.includes(idx)
? 'bg-primary-700 text-white border-primary-700'
: 'bg-white text-gray-800 hover:bg-primary-100 border-[#c3c3c3]'
}`}
aria-pressed={selectedOptions.includes(idx)}
type="button"
>
Expand Down
Loading