Skip to content

Commit 0916c3c

Browse files
committed
Add/Edit/Delete scores
1 parent 25fa92c commit 0916c3c

2 files changed

Lines changed: 88 additions & 110 deletions

File tree

src/api/fetchScores.ts

Lines changed: 57 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -9,34 +9,41 @@ const scoreSchema = z.object({
99
presentation: z.number(),
1010
innovation: z.number(),
1111
teamwork: z.number(),
12-
comment: z.string(),
13-
round: z.number(),
12+
comment: z.string(),
13+
round: z.number(),
1414
});
15+
1516
const scoresResponseSchema = z.object({
16-
status: z.string(),
1717
message: z.string(),
18-
data: z.object({
19-
message: z.string(),
20-
scores: z.array(scoreSchema).optional(),
21-
}),
18+
data: z.object({
19+
scores: z.array(scoreSchema)
20+
}).optional()
2221
});
22+
2323
const createUpdateResponseSchema = z.object({
24-
status: z.string(),
2524
message: z.string(),
25+
data: z.object({
26+
message: z.string()
27+
}).optional()
2628
});
2729

2830
const deleteResponseSchema = z.object({
2931
status: z.string(),
30-
message: z.string()
32+
message: z.string()
3133
});
3234

35+
type ScoreResponse = z.infer<typeof scoreSchema>;
3336

34-
type ScoreResponse = z.infer<typeof scoreSchema>
35-
interface CreateScoreRequest extends Omit<z.infer<typeof scoreSchema>, 'id'>{
36-
team_id: string;
37+
interface CreateScoreRequest extends Omit<z.infer<typeof scoreSchema>, 'id'> {
38+
team_id: string;
3739
}
3840

39-
export const fetchScores = async (teamId: string) => {
41+
interface UpdateScoreRequest extends Partial<Omit<CreateScoreRequest, 'team_id'>> {
42+
scoreId: string;
43+
team_id?: string;
44+
}
45+
46+
export const fetchScores = async (teamId: string): Promise<ScoreResponse[]> => {
4047
try {
4148
const response = await axios.get<{
4249
status: string;
@@ -48,111 +55,63 @@ export const fetchScores = async (teamId: string) => {
4855
}>(`panel/getscore/${teamId}`, {
4956
withCredentials: true,
5057
});
51-
const parsedResponse = scoresResponseSchema.parse(response.data);
52-
return parsedResponse.data?.scores ?? [];
53-
} catch (err:any) {
54-
if (err.response.status === 404) {
55-
return [];
56-
}
57-
throw err;
58+
const parsedResponse = scoresResponseSchema.parse(response.data);
59+
return parsedResponse.data?.scores ?? [];
60+
} catch (err: any) {
61+
if (err.response?.status === 404) {
62+
return [];
63+
}
64+
throw new Error(err.response?.data?.message || 'Failed to fetch scores');
5865
}
5966
};
60-
const createResponseSchema = z.object({
61-
status: z.string(),
62-
message: z.string(),
63-
});
6467

65-
export const createScore = async ({
66-
team_id,
67-
design,
68-
implementation,
69-
presentation,
70-
innovation,
71-
teamwork,
72-
comment,
73-
round,
74-
}: CreateScoreRequest) => {
68+
export const createScore = async (data: CreateScoreRequest) => {
7569
try {
76-
const response = await axios.post(
77-
`panel/createscore`,
70+
const response = await axios.post(
71+
'panel/createscore',
72+
data,
7873
{
79-
design,
80-
implementation,
81-
presentation,
82-
innovation,
83-
teamwork,
84-
comment,
85-
team_id,
86-
round,
87-
},
88-
{
89-
withCredentials: true,
90-
}
74+
withCredentials: true,
75+
}
9176
);
92-
const parsedResponse = createResponseSchema.parse(response.data);
77+
const parsedResponse = createUpdateResponseSchema.parse(response.data);
9378
return parsedResponse;
94-
} catch (err) {
95-
console.error(err);
96-
throw err;
79+
} catch (error: any) {
80+
if (error.response?.data?.message) {
81+
throw new Error(error.response.data.message);
82+
}
83+
throw new Error('Failed to create score');
9784
}
9885
};
9986

10087
export const deleteScore = async (scoreId: string) => {
10188
try {
102-
const response = await axios.delete(`panel/deletescore/${scoreId}`,{
103-
withCredentials: true,
104-
});
105-
106-
const parsedResponse = deleteResponseSchema.parse(response.data);
107-
return parsedResponse;
108-
} catch (err) {
109-
console.error(err);
110-
throw err;
89+
const response = await axios.delete(`panel/deletescore/${scoreId}`, {
90+
withCredentials: true,
91+
});
92+
93+
const parsedResponse = deleteResponseSchema.parse(response.data);
94+
return parsedResponse;
95+
} catch (err: any) {
96+
throw new Error(err.response?.data?.message || 'Failed to delete score');
11197
}
11298
};
11399

114-
export const updateScore = async ({
115-
scoreId,
116-
design,
117-
implementation,
118-
presentation,
119-
innovation,
120-
teamwork,
121-
comment,
122-
round,
123-
team_id
124-
}: {
125-
scoreId:string,
126-
design:number,
127-
implementation:number,
128-
presentation:number,
129-
innovation:number,
130-
teamwork:number,
131-
comment:string,
132-
round:number,
133-
team_id:string
134-
}) => {
100+
export const updateScore = async (data: UpdateScoreRequest) => {
135101
try {
136-
const response = await axios.put(`panel/updatescore/${scoreId}`,
137-
{
138-
design,
139-
implementation,
140-
presentation,
141-
innovation,
142-
teamwork,
143-
comment,
144-
round,
145-
team_id
146-
},
102+
const response = await axios.put(
103+
`panel/updatescore/${data.scoreId}`,
104+
data,
147105
{
148106
withCredentials: true,
149107
}
150108
);
151-
152109
const parsedResponse = createUpdateResponseSchema.parse(response.data);
153-
return parsedResponse;
154-
} catch (err) {
155-
console.error(err);
156-
throw err;
110+
return parsedResponse;
111+
} catch (error: any) {
112+
if (error.response?.data?.message) {
113+
throw new Error(error.response.data.message);
114+
}
115+
throw new Error('Failed to update score');
157116
}
158117
};

src/app/team/[id]/page.tsx

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import Link from "next/link";
77
import { Button } from "@/components/ui/button";
88
import { Input } from "@/components/ui/input";
99
import { Label } from "@/components/ui/label";
10-
import { useState } from "react";
10+
import { useEffect, useState } from "react";
1111
import useToast from "@/lib/toast";
1212
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
1313
import { createScore, deleteScore, fetchScores, updateScore } from "@/api/fetchScores";
@@ -43,10 +43,11 @@ function ScoreSection({ teamId }: { teamId: string }) {
4343
const queryClient = useQueryClient();
4444
const { create } = useToast();
4545

46-
const { data: scores = [], isLoading: scoresLoading, isError: scoresError } = useQuery({
46+
const { data: scores = [], isLoading: scoresLoading, isError: scoresError, refetch } = useQuery({
4747
queryKey: ["scores", teamId],
4848
queryFn: () => fetchScores(teamId ?? ""),
4949
enabled: !!teamId,
50+
staleTime: 0,
5051
});
5152

5253
const createScoreMutation = useMutation({
@@ -60,12 +61,15 @@ function ScoreSection({ teamId }: { teamId: string }) {
6061
comment: string;
6162
round: number;
6263
}) => createScore({ team_id: teamId, design, implementation, presentation, innovation, teamwork, comment, round }),
63-
onError: (err: ApiError) => {
64-
create(`Error creating score: ${err?.message ?? "unknown error"}`, "error");
64+
onError: (err: any) => {
65+
const errorMessage = err.response?.data?.message || err.message || "Unknown error occurred";
66+
create(errorMessage, "error");
6567
},
66-
onSuccess: () => {
67-
void queryClient.invalidateQueries({ queryKey: ["scores", teamId] });
68+
onSuccess: async() => {
69+
create("Score created successfully!", "success");
70+
await refetch();
6871
resetForm();
72+
setEditMode(false);
6973
},
7074
});
7175

@@ -111,16 +115,31 @@ function ScoreSection({ teamId }: { teamId: string }) {
111115
round,
112116
team_id: teamId || ''
113117
}),
114-
onError: (err: ApiError) => {
115-
create(`Error updating score: ${err?.message ?? "unknown error"}`, "error");
118+
onError: (err: any) => {
119+
const errorMessage = err.response?.data?.message || err.message || "Unknown error occurred";
120+
create(errorMessage, "error");
116121
},
117-
onSuccess: () => {
118-
void queryClient.invalidateQueries({ queryKey: ["scores", teamId] });
119-
setEditMode(false);
122+
onSuccess: async() => {
123+
create("Score updated successfully!", "success");
124+
await refetch();
120125
resetForm();
126+
setEditMode(false);
121127
},
122128
});
123129

130+
useEffect(() => {
131+
if (createScoreMutation.isSuccess || updateScoreMutation.isSuccess) {
132+
resetForm();
133+
setEditMode(false);
134+
}
135+
}, [createScoreMutation.isSuccess, updateScoreMutation.isSuccess]);
136+
137+
useEffect(() => {
138+
if (teamId) {
139+
refetch();
140+
}
141+
}, [teamId, refetch]);
142+
124143
const resetForm = () => {
125144
setDesign(0);
126145
setImplementation(0);
@@ -191,7 +210,7 @@ function ScoreSection({ teamId }: { teamId: string }) {
191210
if (scoresLoading) return <div>Loading scores...</div>;
192211
if (scoresError) return <div>Error loading scores</div>;
193212

194-
const showForm = !scores || scores.length === 0 || editMode;
213+
const showForm = scores.length===0 || editMode
195214

196215
return (
197216
<div className="mt-8">

0 commit comments

Comments
 (0)