Skip to content

Commit e9831d7

Browse files
committed
fix: 오류 수정
1 parent d836968 commit e9831d7

File tree

7 files changed

+195
-38
lines changed

7 files changed

+195
-38
lines changed

.env

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
VITE_API_SERVER_URL=https://stage.solid-connection.com
1+
VITE_API_SERVER_URL=https://stage.solid-connection.com
2+
VITE_S3_BASE_URL=https://solid-connection-uploaded.s3.ap-northeast-2.amazonaws.com/

package-lock.json

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"axios": "^1.7.9",
1717
"class-variance-authority": "^0.7.1",
1818
"clsx": "^2.1.1",
19+
"date-fns": "^4.1.0",
1920
"lucide-react": "^0.475.0",
2021
"next-themes": "^0.4.4",
2122
"react": "^19.0.0",

src/api/auth.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ export const adminSignInApi = (
66
email: string,
77
password: string,
88
): Promise<AxiosResponse<AdminSignInResponse>> =>
9-
publicAxiosInstance.post("/admin/auth/sign-in", { email, password });
9+
publicAxiosInstance.post("/auth/email/sign-in", { email, password });
1010

1111
export const reissueAccessTokenApi = (
1212
refreshToken: string,

src/components/scores/gpa/GpaScoreTable.tsx

Lines changed: 57 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
import { useEffect, useState } from "react";
22
import { scoreApi } from "@/api/scores";
3-
import type { GpaScore, VerifyStatus } from "@/types/scores";
3+
import type { GpaScoreWithUser, VerifyStatus } from "@/types/scores";
44
import { ScoreVerifyButton } from "../ScoreVerifyButton";
5+
import { format } from "date-fns";
56

67
interface Props {
78
verifyFilter: VerifyStatus;
89
}
910

11+
const S3_BASE_URL = import.meta.env.VITE_S3_BASE_URL;
12+
1013
export function GpaScoreTable({ verifyFilter }: Props) {
11-
const [scores, setScores] = useState<GpaScore[]>([]);
14+
const [scores, setScores] = useState<GpaScoreWithUser[]>([]);
1215
const [page] = useState(1);
1316
const [loading, setLoading] = useState(false);
1417

@@ -41,7 +44,7 @@ export function GpaScoreTable({ verifyFilter }: Props) {
4144
verifyStatus: status,
4245
rejectedReason: reason,
4346
});
44-
fetchScores(); // 데이터 새로고침
47+
fetchScores();
4548
} catch (error) {
4649
console.error("Failed to update GPA score:", error);
4750
}
@@ -57,6 +60,9 @@ export function GpaScoreTable({ verifyFilter }: Props) {
5760
<th className="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">
5861
ID
5962
</th>
63+
<th className="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">
64+
닉네임
65+
</th>
6066
<th className="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">
6167
GPA
6268
</th>
@@ -66,33 +72,73 @@ export function GpaScoreTable({ verifyFilter }: Props) {
6672
<th className="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">
6773
상태
6874
</th>
75+
<th className="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">
76+
제출일
77+
</th>
6978
<th className="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">
7079
거절사유
7180
</th>
81+
<th className="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">
82+
인증파일
83+
</th>
7284
<th className="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">
7385
작업
7486
</th>
7587
</tr>
7688
</thead>
7789
<tbody className="divide-y divide-gray-200 bg-white">
7890
{scores.map((score) => (
79-
<tr key={score.id}>
80-
<td className="whitespace-nowrap px-6 py-4">{score.id}</td>
81-
<td className="whitespace-nowrap px-6 py-4">{score.gpa}</td>
91+
<tr key={score.gpaScoreStatusResponse.id}>
92+
<td className="whitespace-nowrap px-6 py-4">
93+
{score.gpaScoreStatusResponse.id}
94+
</td>
95+
<td className="whitespace-nowrap px-6 py-4">
96+
<div className="flex items-center">
97+
<img
98+
src={score.siteUserResponse.profileImageUrl}
99+
alt="프로필"
100+
className="mr-2 h-8 w-8 rounded-full"
101+
/>
102+
{score.siteUserResponse.nickname}
103+
</div>
104+
</td>
105+
<td className="whitespace-nowrap px-6 py-4">
106+
{score.gpaScoreStatusResponse.gpaResponse.gpa}
107+
</td>
108+
<td className="whitespace-nowrap px-6 py-4">
109+
{score.gpaScoreStatusResponse.gpaResponse.gpaCriteria}
110+
</td>
111+
<td className="whitespace-nowrap px-6 py-4">
112+
{score.gpaScoreStatusResponse.verifyStatus}
113+
</td>
82114
<td className="whitespace-nowrap px-6 py-4">
83-
{score.gpaCriteria}
115+
{format(
116+
new Date(score.gpaScoreStatusResponse.createdAt),
117+
"yyyy-MM-dd HH:mm",
118+
)}
84119
</td>
85120
<td className="whitespace-nowrap px-6 py-4">
86-
{score.verifyStatus}
121+
{score.gpaScoreStatusResponse.rejectedReason || "-"}
87122
</td>
88123
<td className="whitespace-nowrap px-6 py-4">
89-
{score.rejectedReason || "-"}
124+
<a
125+
href={`${S3_BASE_URL}${score.gpaScoreStatusResponse.gpaResponse.gpaReportUrl}`}
126+
target="_blank"
127+
rel="noopener noreferrer"
128+
className="text-blue-600 hover:text-blue-800 hover:underline"
129+
>
130+
파일 보기
131+
</a>
90132
</td>
91133
<td className="whitespace-nowrap px-6 py-4">
92134
<ScoreVerifyButton
93-
currentStatus={score.verifyStatus}
135+
currentStatus={score.gpaScoreStatusResponse.verifyStatus}
94136
onVerifyChange={(status, reason) =>
95-
handleVerifyStatus(score.id, status, reason)
137+
handleVerifyStatus(
138+
score.gpaScoreStatusResponse.id,
139+
status,
140+
reason,
141+
)
96142
}
97143
/>
98144
</td>

src/components/scores/language/LanguageScoreTable.tsx

Lines changed: 66 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
import { useEffect, useState } from "react";
22
import { scoreApi } from "@/api/scores";
3-
import type { LanguageTestScore, VerifyStatus } from "@/types/scores";
3+
import type { LanguageScoreWithUser, VerifyStatus } from "@/types/scores";
44
import { ScoreVerifyButton } from "../ScoreVerifyButton";
5+
import { format } from "date-fns";
56

67
interface Props {
78
verifyFilter: VerifyStatus;
89
}
910

11+
const S3_BASE_URL = import.meta.env.VITE_S3_BASE_URL;
12+
1013
export function LanguageScoreTable({ verifyFilter }: Props) {
11-
const [scores, setScores] = useState<LanguageTestScore[]>([]);
14+
const [scores, setScores] = useState<LanguageScoreWithUser[]>([]);
1215
const [page] = useState(1);
1316
const [loading, setLoading] = useState(false);
1417

@@ -21,7 +24,7 @@ export function LanguageScoreTable({ verifyFilter }: Props) {
2124
);
2225
setScores(response.content);
2326
} catch (error) {
24-
console.error("Failed to fetch Language Test scores:", error);
27+
console.error("Failed to fetch Language scores:", error);
2528
} finally {
2629
setLoading(false);
2730
}
@@ -41,9 +44,9 @@ export function LanguageScoreTable({ verifyFilter }: Props) {
4144
verifyStatus: status,
4245
rejectedReason: reason,
4346
});
44-
fetchScores(); // 데이터 새로고침
47+
fetchScores();
4548
} catch (error) {
46-
console.error("Failed to update Language Test score:", error);
49+
console.error("Failed to update Language score:", error);
4750
}
4851
};
4952

@@ -58,43 +61,92 @@ export function LanguageScoreTable({ verifyFilter }: Props) {
5861
ID
5962
</th>
6063
<th className="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">
61-
시험 종류
64+
닉네임
65+
</th>
66+
<th className="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">
67+
시험종류
6268
</th>
6369
<th className="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">
6470
점수
6571
</th>
6672
<th className="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">
6773
상태
6874
</th>
75+
<th className="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">
76+
제출일
77+
</th>
6978
<th className="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">
7079
거절사유
7180
</th>
81+
<th className="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">
82+
인증파일
83+
</th>
7284
<th className="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">
7385
작업
7486
</th>
7587
</tr>
7688
</thead>
7789
<tbody className="divide-y divide-gray-200 bg-white">
7890
{scores.map((score) => (
79-
<tr key={score.id}>
80-
<td className="whitespace-nowrap px-6 py-4">{score.id}</td>
91+
<tr key={score.languageTestScoreStatusResponse.id}>
92+
<td className="whitespace-nowrap px-6 py-4">
93+
{score.languageTestScoreStatusResponse.id}
94+
</td>
95+
<td className="whitespace-nowrap px-6 py-4">
96+
<div className="flex items-center">
97+
<img
98+
src={score.siteUserResponse.profileImageUrl}
99+
alt="프로필"
100+
className="mr-2 h-8 w-8 rounded-full"
101+
/>
102+
{score.siteUserResponse.nickname}
103+
</div>
104+
</td>
105+
<td className="whitespace-nowrap px-6 py-4">
106+
{
107+
score.languageTestScoreStatusResponse.languageTestResponse
108+
.languageTestType
109+
}
110+
</td>
111+
<td className="whitespace-nowrap px-6 py-4">
112+
{
113+
score.languageTestScoreStatusResponse.languageTestResponse
114+
.languageTestScore
115+
}
116+
</td>
81117
<td className="whitespace-nowrap px-6 py-4">
82-
{score.languageTestType}
118+
{score.languageTestScoreStatusResponse.verifyStatus}
83119
</td>
84120
<td className="whitespace-nowrap px-6 py-4">
85-
{score.languageTestScore}
121+
{format(
122+
new Date(score.languageTestScoreStatusResponse.createdAt),
123+
"yyyy-MM-dd HH:mm",
124+
)}
86125
</td>
87126
<td className="whitespace-nowrap px-6 py-4">
88-
{score.verifyStatus}
127+
{score.languageTestScoreStatusResponse.rejectedReason || "-"}
89128
</td>
90129
<td className="whitespace-nowrap px-6 py-4">
91-
{score.rejectedReason || "-"}
130+
<a
131+
href={`${S3_BASE_URL}${score.languageTestScoreStatusResponse.languageTestResponse.languageTestReportUrl}`}
132+
target="_blank"
133+
rel="noopener noreferrer"
134+
className="text-blue-600 hover:text-blue-800 hover:underline"
135+
>
136+
파일 보기
137+
</a>
92138
</td>
93139
<td className="whitespace-nowrap px-6 py-4">
94140
<ScoreVerifyButton
95-
currentStatus={score.verifyStatus}
141+
currentStatus={
142+
score.languageTestScoreStatusResponse.verifyStatus
143+
}
96144
onVerifyChange={(status, reason) =>
97-
handleVerifyStatus(score.id, status, reason)
145+
handleVerifyStatus(
146+
score.languageTestScoreStatusResponse.id,
147+
status,
148+
reason,
149+
)
98150
}
99151
/>
100152
</td>

src/types/scores.ts

Lines changed: 57 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,75 @@ export type VerifyStatus = "PENDING" | "APPROVED" | "REJECTED";
22

33
export interface ScoreSearchCondition {
44
verifyStatus?: VerifyStatus;
5-
// 추가 검색 조건이 있다면 여기에 추가
65
}
76

8-
export interface GpaScore {
9-
id: number;
7+
export interface GpaResponse {
108
gpa: number;
119
gpaCriteria: number;
12-
verifyStatus: VerifyStatus;
13-
rejectedReason?: string;
10+
gpaReportUrl: string;
1411
}
1512

16-
export interface LanguageTestScore {
13+
export interface GpaScoreStatusResponse {
1714
id: number;
18-
languageTestType: string;
19-
languageTestScore: string;
15+
gpaResponse: GpaResponse;
2016
verifyStatus: VerifyStatus;
21-
rejectedReason?: string;
17+
rejectedReason: string | null;
18+
createdAt: string;
19+
updatedAt: string;
20+
}
21+
22+
export interface SiteUserResponse {
23+
id: number;
24+
nickname: string;
25+
profileImageUrl: string;
26+
}
27+
28+
export interface GpaScoreWithUser {
29+
gpaScoreStatusResponse: GpaScoreStatusResponse;
30+
siteUserResponse: SiteUserResponse;
2231
}
2332

2433
export interface PageResponse<T> {
2534
content: T[];
35+
pageNumber: number;
36+
pageSize: number;
2637
totalElements: number;
2738
totalPages: number;
28-
size: number;
29-
number: number;
39+
}
40+
41+
export interface LanguageResponse {
42+
languageType: string;
43+
score: number;
44+
testDate: string;
45+
expireDate: string;
46+
languageReportUrl: string;
47+
}
48+
49+
export interface LanguageScoreStatusResponse {
50+
id: number;
51+
languageResponse: LanguageResponse;
52+
verifyStatus: VerifyStatus;
53+
rejectedReason: string | null;
54+
createdAt: string;
55+
updatedAt: string;
56+
}
57+
58+
export interface LanguageScoreWithUser {
59+
languageTestScoreStatusResponse: LanguageTestScoreStatusResponse;
60+
siteUserResponse: SiteUserResponse;
61+
}
62+
63+
export interface LanguageTestResponse {
64+
languageTestType: string;
65+
languageTestScore: string;
66+
languageTestReportUrl: string;
67+
}
68+
69+
export interface LanguageTestScoreStatusResponse {
70+
id: number;
71+
languageTestResponse: LanguageTestResponse;
72+
verifyStatus: VerifyStatus;
73+
rejectedReason: string | null;
74+
createdAt: string;
75+
updatedAt: string;
3076
}

0 commit comments

Comments
 (0)