diff --git a/frontend/src/app/(client)/(withSidebar)/milestone/page.tsx b/frontend/src/app/(client)/(withSidebar)/milestone/page.tsx index addbccbf..7a51e510 100644 --- a/frontend/src/app/(client)/(withSidebar)/milestone/page.tsx +++ b/frontend/src/app/(client)/(withSidebar)/milestone/page.tsx @@ -1,6 +1,7 @@ import Image from 'next/image'; import * as S from './styled'; +import Link from 'next/link'; const Page = () => ( @@ -14,6 +15,15 @@ const Page = () => ( 학생들은 교내외 여러 활동들을 통하여 실전적 SW역량, 글로벌 역량, 커뮤니케이션 역량을 균형있게 함양하고 SW중심대학사업단에서는 학생들의 적립된 마일스톤 점수에 따라 매년 장학생을 선발하고 있습니다. +
+ + 마일스톤 등록하러 가기 + +
diff --git a/frontend/src/app/(client)/(withSidebar)/milestone/styled.ts b/frontend/src/app/(client)/(withSidebar)/milestone/styled.ts index bfdc6c3b..f074a49b 100644 --- a/frontend/src/app/(client)/(withSidebar)/milestone/styled.ts +++ b/frontend/src/app/(client)/(withSidebar)/milestone/styled.ts @@ -25,7 +25,6 @@ export const Title = styled.div` export const Description = styled.div` text-align: center; - margin-bottom: 50px; `; export const InformationList = styled.ul` diff --git a/frontend/src/app/(client)/(withSidebar)/my-page/components/MilestoneHistorySection/index.tsx b/frontend/src/app/(client)/(withSidebar)/my-page/components/MilestoneHistorySection/index.tsx index 8118a25d..b2931673 100644 --- a/frontend/src/app/(client)/(withSidebar)/my-page/components/MilestoneHistorySection/index.tsx +++ b/frontend/src/app/(client)/(withSidebar)/my-page/components/MilestoneHistorySection/index.tsx @@ -32,7 +32,7 @@ const MilestoneHistorySection = async () => { return (
- +
{milestoneHistoriesOfStudent ? ( milestoneHistoriesOfStudent.content.map((milestoneHistory) => ( diff --git a/frontend/src/app/(client)/(withSidebar)/my-page/components/StudentInfoSection/index.tsx b/frontend/src/app/(client)/(withSidebar)/my-page/components/StudentInfoSection/index.tsx index 31c87e21..5ba8760d 100644 --- a/frontend/src/app/(client)/(withSidebar)/my-page/components/StudentInfoSection/index.tsx +++ b/frontend/src/app/(client)/(withSidebar)/my-page/components/StudentInfoSection/index.tsx @@ -13,7 +13,12 @@ import StudentInfoLabel from './StudentInfoLabel'; const StudentInfoSection = () => { // TODO - 관리자가 로그인한 경우에 대한 처린 const auth = useAppSelector((state) => state.auth).value; - const { data: member } = useStudentMemberQuery(auth.id); + let member; + try { + member = useStudentMemberQuery(auth.id).data; + } catch (err) { + // TODO: server api error handling + } return (
diff --git a/frontend/src/app/admin/milestone/list/[slug]/page.tsx b/frontend/src/app/admin/milestone/list/[slug]/page.tsx index 65d3073b..92ea9b8e 100644 --- a/frontend/src/app/admin/milestone/list/[slug]/page.tsx +++ b/frontend/src/app/admin/milestone/list/[slug]/page.tsx @@ -97,6 +97,12 @@ const Page = async ({ params: { slug } }: MilestoneHistoryDetailPageProps) => { 승인 상태 {convertMilestoneHistoryStatus(history.status)}

+ {history.rejectReason && ( +

+ 반려 이유 + {history.rejectReason} +

+ )}
diff --git a/frontend/src/app/admin/milestone/list/page.tsx b/frontend/src/app/admin/milestone/list/page.tsx index af521a30..8abc9ffb 100644 --- a/frontend/src/app/admin/milestone/list/page.tsx +++ b/frontend/src/app/admin/milestone/list/page.tsx @@ -10,6 +10,8 @@ import MilestoneHistoryTable from './components/MilestoneHistoryTable'; import MilestoneHistoryExcelFileDownloadButton from './components/MilestoneHistoryTable/MilestoneHistoryExcelFileDownloadButton.tsx'; import { AuthSliceState } from '@/store/auth.slice'; import { getAuthFromCookie } from '@/lib/utils/auth'; +import { BusinessError } from '@/types/error'; +import { redirect } from 'next/navigation'; const Page = async ({ searchParams }: { searchParams?: { [key: string]: string | undefined } }) => { const headersList = headers(); @@ -21,7 +23,12 @@ const Page = async ({ searchParams }: { searchParams?: { [key: string]: string | const field = searchParams?.field ? parseInt(searchParams.field, 10) : 0; const keyword = searchParams?.keyword ? searchParams.keyword : ''; - const milestoneHistories = await getMilestoneHistories(auth.token, field, keyword, page - 1); + let milestoneHistories; + try { + milestoneHistories = await getMilestoneHistories(auth.token, field, keyword, page - 1); + } catch (err) { + // TODO: server api error handling... + } return (
diff --git a/frontend/src/lib/api/server.api.ts b/frontend/src/lib/api/server.api.ts index 81023286..cd95202b 100644 --- a/frontend/src/lib/api/server.api.ts +++ b/frontend/src/lib/api/server.api.ts @@ -13,6 +13,7 @@ import { MilestoneHistorySortCriteria, SortDirection } from '@/types/milestone'; import { mockHackathonPrize } from '@/mocks/hackathon'; import { removeEmptyField } from '../utils/utils'; +import { BusinessError } from '@/types/error'; export async function getMilestoneHistoriesOfStudent( token: string, @@ -60,7 +61,10 @@ export async function getMilestoneHistories( }), }) .then((res) => res.data) - .catch((err) => Promise.reject(err)); + .catch((err) => { + location.replace('/sign-out'); + return Promise.reject(err); + }); } export async function getMilestoneHistory(historyId: number, token: string) { diff --git a/frontend/src/lib/hooks/useApi.ts b/frontend/src/lib/hooks/useApi.ts index b90360b1..a70931ec 100644 --- a/frontend/src/lib/hooks/useApi.ts +++ b/frontend/src/lib/hooks/useApi.ts @@ -109,7 +109,11 @@ export function useStudentMemberQuery(memberId: number, options?: { enabled?: bo return useAxiosQuery({ ...options, queryKey: QueryKeys.STUDENT(memberId), - queryFn: async (): Promise => await client.get(`/members/${memberId}`), + queryFn: async (): Promise => + await client + .get(`/members/${memberId}`) + .then((res) => res.data) + .catch((err) => Promise.reject(err)), }); } diff --git a/frontend/src/types/error.ts b/frontend/src/types/error.ts index 53e666e2..20798dae 100644 --- a/frontend/src/types/error.ts +++ b/frontend/src/types/error.ts @@ -20,7 +20,7 @@ export class BusinessError extends Error { super(); this.originalError = error; this.name = 'BusinessError'; - this.message = message ? message : 'MemberRoleNotMatchedError'; + this.message = message ? message : 'BusinessError'; } } @@ -28,7 +28,7 @@ export class AuthError extends BusinessError { constructor(error?: AxiosError, message?: string) { super(error, message); this.name = 'AuthError'; - this.message = message ? message : 'MemberRoleNotMatchedError'; + this.message = message ? message : 'AuthError'; } } @@ -36,7 +36,7 @@ export class NotFoundError extends AuthError { constructor(error?: AxiosError, message?: string) { super(error, message); this.name = 'NotFoundError'; - this.message = message ? message : 'MemberRoleNotMatchedError'; + this.message = message ? message : 'NotFoundError'; } } @@ -44,7 +44,7 @@ export class AccessDeniedError extends AuthError { constructor(error?: AxiosError, message?: string) { super(error, message); this.name = 'AccessDeniedError'; - this.message = message ? message : 'MemberRoleNotMatchedError'; + this.message = message ? message : 'AccessDeniedError'; } } @@ -52,7 +52,7 @@ export class UnauthorizedError extends AuthError { constructor(error?: AxiosError, message?: string) { super(error, message); this.name = 'UnauthorizedError'; - this.message = message ? message : 'MemberRoleNotMatchedError'; + this.message = message ? message : 'UnauthorizedError'; } }