Skip to content

Commit 46eaf94

Browse files
authored
Merge pull request #278 from Pseudo-Lab/feat/getcloser/frontend/display-member-info
feat(getcloser): display team members info
2 parents 863f3af + ff5915c commit 46eaf94

2 files changed

Lines changed: 96 additions & 5 deletions

File tree

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

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,15 @@ import { useFormStore } from '../../store/formStore';
88
import { authenticatedFetch } from '../../lib/api';
99
import { useNavigationStore } from '../../store/navigationStore';
1010

11+
interface TeamMember {
12+
id: number;
13+
user_id: number;
14+
name: string;
15+
email: string;
16+
github_url?: string;
17+
linkedin_url?: string;
18+
}
19+
1120
const questions = [
1221
{ category: '1', keyword: '관심사', problem: '사용자의 관심사를 맞춰주세요. 예: 기술, 예술, 환경 등' },
1322
{ category: '2', keyword: '취미', problem: '사용자의 취미를 맞춰주세요. 예: 등산, 독서, 요리 등' },
@@ -35,6 +44,30 @@ export default function Page3() {
3544

3645
const initializeChallenge = async () => {
3746
if (!question && id && teamId) {
47+
// Fetch team members to get their names
48+
let members: TeamMember[] = [];
49+
try {
50+
const teamResponse = await authenticatedFetch('/api/v1/teams/me', {
51+
method: 'GET',
52+
headers: { 'Content-Type': 'application/json' },
53+
});
54+
if (teamResponse.ok) {
55+
const teamData = await teamResponse.json();
56+
if (teamData && teamData.members) {
57+
members = teamData.members;
58+
}
59+
} else {
60+
console.error('Failed to fetch team data');
61+
}
62+
} catch (error) {
63+
console.error('Error fetching team members:', error);
64+
}
65+
66+
const findMemberName = (userId: number): string => {
67+
const member = members.find((m) => m.user_id === userId);
68+
return member ? member.name : String(userId); // Fallback to user_id as string
69+
};
70+
3871
// 1. Try to restore challenge from localStorage
3972
const savedChallengeJSON = localStorage.getItem(CHALLENGE_DATA_KEY);
4073
if (savedChallengeJSON) {
@@ -44,7 +77,8 @@ export default function Page3() {
4477
if (savedChallenge.category && savedChallenge.assigned_challenge_id) {
4578
const questionInfo = questions.find((q) => q.category === String(savedChallenge.category));
4679
if (questionInfo) {
47-
setQuestion(questionInfo.problem);
80+
const memberName = findMemberName(savedChallenge.user_id);
81+
setQuestion([memberName, questionInfo.problem].join(' '));
4882
setChallengeId(savedChallenge.assigned_challenge_id);
4983
return; // Challenge successfully restored
5084
}
@@ -61,7 +95,7 @@ export default function Page3() {
6195
const assignResponse = await authenticatedFetch('/api/v1/challenges/assign', {
6296
method: 'POST',
6397
headers: { 'Content-Type': 'application/json' },
64-
body: JSON.stringify({ team_id: teamId, my_id: id, members_ids: memberIds }),
98+
body: JSON.stringify({ team_id: teamId, my_id: id, members_ids: memberIds.filter((memberId) => memberId !== Number(id)) }),
6599
});
66100

67101
if (!assignResponse.ok) {
@@ -76,6 +110,7 @@ export default function Page3() {
76110
const dataToSave = {
77111
category: String(newChallengeData.my_assigned.category),
78112
assigned_challenge_id: newChallengeData.my_assigned.assigned_challenge_id,
113+
user_id: newChallengeData.my_assigned.user_id,
79114
};
80115

81116
// Save to localStorage for future restoration
@@ -85,7 +120,8 @@ export default function Page3() {
85120
// Set state from the new challenge data
86121
const questionInfo = questions.find((q) => q.category === dataToSave.category);
87122
if (questionInfo) {
88-
setQuestion(questionInfo.problem);
123+
const memberName = findMemberName(dataToSave.user_id);
124+
setQuestion([memberName, questionInfo.problem].join(' '));
89125
setChallengeId(dataToSave.assigned_challenge_id);
90126
}
91127
} else {

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

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@ import Image from 'next/image';
66
import { authenticatedFetch } from '../../lib/api';
77
import { useFormStore } from '../../store/formStore';
88
import { useNavigationStore } from '../../store/navigationStore';
9+
import Modal from '@/components/Modal';
910

1011
// Assuming a TeamMember interface for better typing
1112
interface TeamMember {
1213
id: number;
14+
user_id: number;
1315
name: string;
1416
email: string;
1517
github_url?: string; // Optional
@@ -18,10 +20,19 @@ interface TeamMember {
1820

1921
interface TeamData {
2022
id: number;
23+
team_id: number;
2124
name: string;
2225
members: TeamMember[];
2326
}
2427

28+
interface ChallengeResult {
29+
user_id: number;
30+
question: string;
31+
user_answer: string;
32+
correct_answer: string;
33+
is_correct: boolean;
34+
}
35+
2536
export default function Page4() {
2637
const { id, isCorrect } = useFormStore(); // Added isCorrect
2738
const { setCurrentPage } = useNavigationStore();
@@ -30,6 +41,8 @@ export default function Page4() {
3041
const [teamData, setTeamData] = useState<TeamData | null>(null); // State to store team data
3142
const [clickCount, setClickCount] = useState<number>(0);
3243
const [lastClickTime, setLastClickTime] = useState<number>(0);
44+
const [selectedMemberChallenge, setSelectedMemberChallenge] = useState<ChallengeResult | null>(null);
45+
const [isModalOpen, setIsModalOpen] = useState(false);
3346

3447
// This useEffect will set the initial success/failure based on isCorrect from the store
3548
useEffect(() => {
@@ -104,6 +117,34 @@ export default function Page4() {
104117
}
105118
};
106119

120+
const handleMemberClick = async (memberUserId: number) => {
121+
if (!teamData) return;
122+
try {
123+
const response = await authenticatedFetch(`/api/v1/teams/${teamData.team_id}/members/${memberUserId}/challenge`, {
124+
method: 'GET',
125+
headers: {
126+
'Content-Type': 'application/json',
127+
},
128+
});
129+
130+
if (!response.ok) {
131+
const errorData = await response.json();
132+
throw new Error(`HTTP error! status: ${response.status}, message: ${errorData.detail || response.statusText}`);
133+
}
134+
135+
const data: ChallengeResult = await response.json();
136+
setSelectedMemberChallenge(data);
137+
setIsModalOpen(true);
138+
} catch (error: unknown) {
139+
console.error('Error fetching challenge data:', error);
140+
if (error instanceof Error) {
141+
alert(`Error: ${error.message}`);
142+
} else {
143+
alert('An unknown error occurred.');
144+
}
145+
}
146+
};
147+
107148
return (
108149
<div className="container mx-auto p-4">
109150
<div className="mt-8 text-center">
@@ -126,9 +167,8 @@ export default function Page4() {
126167
<h3 className="text-2xl font-bold mb-4">우리 팀원들</h3>
127168
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
128169
{teamData.members.map((member) => (
129-
<div key={member.id} className="bg-muted p-4 rounded-lg shadow-md">
170+
<div key={member.user_id} className="bg-muted p-4 rounded-lg shadow-md cursor-pointer hover:bg-muted/80" onClick={() => handleMemberClick(member.user_id)}>
130171
<p className="text-lg font-semibold">{member.name}</p>
131-
<p className="text-sm text-gray-600">Email: {member.email}</p>
132172
{member.github_url && (
133173
<p className="text-sm text-gray-600">
134174
GitHub: <a href={member.github_url} target="_blank" rel="noopener noreferrer" className="text-blue-500 hover:underline">{member.github_url}</a>
@@ -153,6 +193,21 @@ export default function Page4() {
153193
</>
154194
)}
155195
</div>
196+
<Modal
197+
isOpen={isModalOpen}
198+
title="Challenge Result"
199+
content={
200+
selectedMemberChallenge
201+
? `
202+
<p class="mb-2"><strong>Question:</strong> ${selectedMemberChallenge.question}</p>
203+
<p class="mb-1"><strong>Your Answer:</strong> <span class="${selectedMemberChallenge.is_correct ? 'text-green-400' : 'text-red-400'}">${selectedMemberChallenge.user_answer}</span></p>
204+
${!selectedMemberChallenge.is_correct ? `<p class="mb-2"><strong>Correct Answer:</strong> <span class="text-green-400">${selectedMemberChallenge.correct_answer}</span></p>` : ''}
205+
`
206+
: ''
207+
}
208+
onConfirm={() => setIsModalOpen(false)}
209+
onDoNotShowAgain={() => setIsModalOpen(false)}
210+
/>
156211
</div>
157212
);
158213
}

0 commit comments

Comments
 (0)