Skip to content

Commit b412f60

Browse files
committed
feat(getcloser): short answers
1 parent c6baa77 commit b412f60

2 files changed

Lines changed: 59 additions & 27 deletions

File tree

getcloser/frontend/src/app/pages/Page3.tsx

Lines changed: 44 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
'use client';
22

33
import { Button } from '@/components/ui/button';
4-
import { Label } from '@/components/ui/label';
5-
import { Textarea } from '@/components/ui/textarea';
6-
import React, { useEffect } from 'react';
4+
import React, { useEffect, useState } from 'react';
75
import { useFormStore } from '../../store/formStore';
86
import { authenticatedFetch } from '../../lib/api';
97
import { useNavigationStore } from '../../store/navigationStore';
@@ -18,11 +16,18 @@ interface TeamMember {
1816
}
1917

2018
const questions = [
21-
{ category: '1', keyword: '관심사', problem: '사용자의 관심사를 맞춰주세요. 예: 기술, 예술, 환경 등' },
22-
{ category: '2', keyword: '취미', problem: '사용자의 취미를 맞춰주세요. 예: 등산, 독서, 요리 등' },
23-
{ category: '3', keyword: 'MBTI', problem: '사용자의 MBTI 유형을 맞춰주세요. 예: INFP, ESTJ 등' },
19+
{ category: '1', keyword: '관심사', problem: '님의 관심사를 맞춰주세요.', options: [ 'Agentic AI', 'AI Ethics', 'AI Security', 'Causal Inference', 'Computer Graphics', 'Computer Vision', 'Efficient AI', 'LLM/Multimodal', 'Physical AI', 'XAI' ]},
20+
{ category: '2', keyword: '계절', problem: '님이 좋아하는 계절을 맞춰주세요.', options: ['봄', '여름', '가을', '겨울'] },
21+
{ category: '3', keyword: 'MBTI', problem: '님의 MBTI 유형을 맞춰주세요.', options: ['INFP', 'ENFP', 'INFJ', 'ENFJ', 'INTJ', 'ENTJ', 'INTP', 'ENTP', 'ISFP', 'ESFP', 'ISTP', 'ESTP', 'ISFJ', 'ESFJ', 'ISTJ', 'ESTJ'] },
2422
];
2523

24+
interface QuestionInfo {
25+
category: string;
26+
keyword: string;
27+
problem: string;
28+
options: string[];
29+
}
30+
2631
const getJsonFromResponse = async (response: Response) => {
2732
try {
2833
const text = await response.text();
@@ -36,13 +41,21 @@ const getJsonFromResponse = async (response: Response) => {
3641
};
3742

3843
export default function Page3() {
39-
const { question, answer, challengeId, setAnswer, id, teamId, memberIds, setQuestion, setChallengeId, setIsCorrect, reset } = useFormStore(); // Destructure new state
44+
const { question, answer, challengeId, setAnswer, id, teamId, memberIds, setQuestion, setChallengeId, setProgressStatus, reset } = useFormStore(); // Destructure new state
4045
const { setCurrentPage } = useNavigationStore();
46+
const [currentQuestionInfo, setCurrentQuestionInfo] = useState<QuestionInfo | null>(null);
4147

4248
useEffect(() => {
4349
const initializeChallenge = async () => {
4450
// If a question is already loaded, do nothing.
4551
if (question) {
52+
// Still need to set the question info for rendering options
53+
if (!currentQuestionInfo) {
54+
const loadedQuestionCategory = questions.find(q => question.includes(q.problem));
55+
if(loadedQuestionCategory) {
56+
setCurrentQuestionInfo(loadedQuestionCategory as QuestionInfo); // Cast to QuestionInfo
57+
}
58+
}
4659
console.log('Question already exists, skipping initialization.');
4760
return;
4861
}
@@ -102,6 +115,7 @@ export default function Page3() {
102115
const memberName = findMemberName(userId);
103116
setQuestion([memberName, questionInfo.problem].join(' '));
104117
setChallengeId(assigned_challenge_id);
118+
setCurrentQuestionInfo(questionInfo as QuestionInfo); // Cast to QuestionInfo
105119
} else {
106120
throw new Error(`Could not find question for category: ${category}`);
107121
}
@@ -120,15 +134,13 @@ export default function Page3() {
120134
initializeChallenge();
121135
// Added challengeId to dependency array to react to changes if needed,
122136
// though the main trigger is the absence of `question`.
123-
}, [id, teamId, question, memberIds, setQuestion, setChallengeId, reset, setCurrentPage, challengeId]);
124-
125-
const handleSubmit = async (e: React.FormEvent) => {
126-
e.preventDefault();
137+
}, [id, teamId, question, memberIds, setQuestion, setChallengeId, reset, setCurrentPage, challengeId, currentQuestionInfo]);
127138

139+
const submitAnswer = async (submittedAnswer: string) => {
128140
const requestBody = {
129141
user_id: id,
130142
challenge_id: challengeId,
131-
submitted_answer: answer,
143+
submitted_answer: submittedAnswer,
132144
};
133145

134146
try {
@@ -147,7 +159,7 @@ export default function Page3() {
147159

148160
const responseData = await response.json();
149161
console.log('Challenge submission successful:', responseData);
150-
setIsCorrect(responseData.is_correct);
162+
setProgressStatus(responseData.is_correct);
151163
setCurrentPage('page4');
152164
} catch (error: unknown) {
153165
console.error('Error submitting challenge:', error);
@@ -159,25 +171,31 @@ export default function Page3() {
159171
}
160172
};
161173

174+
const handleOptionClick = async (option: string) => {
175+
setAnswer(option); // Update the store
176+
await submitAnswer(option); // Submit the answer immediately
177+
};
178+
162179
return (
163180
<div className="container mx-auto p-4">
164181
<main className="max-w-md mx-auto bg-card text-card-foreground p-6 rounded-lg shadow-md mt-8">
165182
<h2 className="text-xl font-semibold mb-4">질문:</h2>
166183
<p className="mb-4 p-2 border rounded bg-muted">{question || '질문이 입력되지 않았습니다.'}</p>
167184

168-
<form className="space-y-4" onSubmit={handleSubmit}>
169-
<div>
170-
<Label htmlFor="answer">답변 입력</Label>
171-
<Textarea
172-
id="answer"
173-
placeholder="질문에 대한 답변을 입력해주세요."
174-
required
175-
value={answer}
176-
onChange={(e) => setAnswer(e.target.value)}
177-
/>
185+
{currentQuestionInfo && currentQuestionInfo.options && (
186+
<div className="grid grid-cols-2 gap-4 mt-4">
187+
{currentQuestionInfo.options.map((option) => (
188+
<Button
189+
key={option}
190+
onClick={() => handleOptionClick(option)}
191+
variant="outline"
192+
className="justify-start text-left h-auto py-3"
193+
>
194+
{option}
195+
</Button>
196+
))}
178197
</div>
179-
<Button type="submit" className="w-full">제출 하기</Button>
180-
</form>
198+
)}
181199
</main>
182200

183201
<nav className="flex justify-between mt-8">
@@ -187,4 +205,4 @@ export default function Page3() {
187205
</nav>
188206
</div>
189207
);
190-
}
208+
}

getcloser/frontend/src/app/pages/Page4.tsx

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ const getJsonFromResponse = async (response: Response) => {
4646
};
4747

4848
export default function Page4() {
49-
const { id, progressStatus, teamId, memberIds, reset, setQuestion, setChallengeId } = useFormStore(); // Use progressStatus
49+
const { id, progressStatus, teamId, memberIds, reset, setQuestion, setChallengeId, setTeamId, setProgressStatus } = useFormStore(); // Use progressStatus
5050
const { setCurrentPage } = useNavigationStore();
5151

5252
const [result, setResult] = useState<string>('');
@@ -132,6 +132,20 @@ export default function Page4() {
132132
errorMessage = error.message;
133133
}
134134
alert(`재도전 실패: ${errorMessage}`);
135+
136+
try {
137+
console.log(`Canceling team ${teamId} due to challenge assignment failure.`);
138+
await authenticatedFetch(`/api/v1/teams/${teamId}/cancel`, {
139+
method: 'POST',
140+
headers: { 'Content-Type': 'application/json' },
141+
});
142+
setTeamId(0);
143+
setProgressStatus('NONE_TEAM');
144+
reset();
145+
} catch (cancelError: unknown) {
146+
console.error('Failed to cancel team:', cancelError);
147+
}
148+
135149
setCurrentPage('page2'); // Fallback to page2 if something goes wrong
136150
}
137151
};

0 commit comments

Comments
 (0)