Skip to content

Commit 3d2208c

Browse files
authored
Merge pull request #248 from manNomi/refactor/applicant
Refactor/applicant
2 parents 76a6c45 + ad7aae4 commit 3d2208c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+1008
-1068
lines changed

src/api/mentor/client/useGetMentoringUncheckedCount.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ const useGetMentoringUncheckedCount = (isEnable: boolean) =>
2121
queryFn: getMentoringUncheckedCount,
2222
enabled: isEnable,
2323
refetchInterval: 1000 * 60 * 10, // ⏱️ 10분마다 자동 재요청
24-
refetchOnWindowFocus: true, // 탭 돌아올 때도 최신화
2524
staleTime: 1000 * 60 * 5, // fresh 상태 유지
2625
select: (data) => data.uncheckedCount, // 필요한 데이터만 반환
2726
});

src/api/reports/client/usePostReport.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ const usePostReports = () => {
2525
mutationFn: postReports,
2626
onSuccess: () => {
2727
alert("신고가 성공적으로 등록되었습니다.");
28-
router.push("/mentor"); // 신고 후 리다이렉트
28+
router.back(); // 신고 후 뒤로 이동
2929
},
3030
onError: (error) => {
3131
alert("신고 등록에 실패했습니다. 잠시 후 다시 시도해주세요.");

src/api/score.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export const postGpaScoreApi = (request: SubmitGpaScoreRequest): Promise<AxiosRe
1616
new Blob([JSON.stringify(request.gpaScoreRequest)], { type: "application/json" }),
1717
);
1818
convertedRequest.append("file", request.file);
19-
return axiosInstance.post("/scores/gpas", convertedRequest, { headers: { "Content-Type": "multipart/form-data" } });
19+
return axiosInstance.post("/scores/gpas", convertedRequest);
2020
};
2121

2222
export const postLanguageTestScoreApi = (request: SubmitLanguageTestScoreRequest): Promise<AxiosResponse<null>> => {
@@ -26,9 +26,7 @@ export const postLanguageTestScoreApi = (request: SubmitLanguageTestScoreRequest
2626
new Blob([JSON.stringify(request.languageTestScoreRequest)], { type: "application/json" }),
2727
);
2828
convertedRequest.append("file", request.file);
29-
return axiosInstance.post("/scores/language-tests", convertedRequest, {
30-
headers: { "Content-Type": "multipart/form-data" },
31-
});
29+
return axiosInstance.post("/scores/language-tests", convertedRequest);
3230
};
3331

3432
export const getMyGpaScoreApi = (): Promise<AxiosResponse<MyGpaScoreResponse>> => axiosInstance.get("/scores/gpas");
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { AxiosResponse } from "axios";
2+
3+
import { axiosInstance } from "@/utils/axiosInstance";
4+
5+
import { QueryKeys } from "./queryKey";
6+
7+
import { useMutation, useQueryClient } from "@tanstack/react-query";
8+
9+
interface UsePostGpaScoreRequest {
10+
gpaScoreRequest: {
11+
gpa: number;
12+
gpaCriteria: number;
13+
issueDate: string; // yyyy-MM-dd
14+
};
15+
file: Blob;
16+
}
17+
18+
export const postGpaScore = (request: UsePostGpaScoreRequest): Promise<AxiosResponse<null>> => {
19+
const convertedRequest: FormData = new FormData();
20+
convertedRequest.append(
21+
"gpaScoreRequest",
22+
new Blob([JSON.stringify(request.gpaScoreRequest)], { type: "application/json" }),
23+
);
24+
convertedRequest.append("file", request.file);
25+
return axiosInstance.post("/scores/gpas", convertedRequest);
26+
};
27+
28+
export const usePostGpaScore = () => {
29+
const queryClient = useQueryClient();
30+
31+
return useMutation({
32+
mutationFn: (request: UsePostGpaScoreRequest) => postGpaScore(request),
33+
34+
onSuccess: () => {
35+
alert("학점 정보가 성공적으로 제출되었습니다.");
36+
queryClient.invalidateQueries({ queryKey: [QueryKeys.myGpaScore] });
37+
},
38+
39+
onError: (error) => {
40+
console.error("학점 제출 중 오류 발생:", error);
41+
alert("오류가 발생했습니다. 다시 시도해주세요.");
42+
},
43+
});
44+
};
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { useRouter } from "next/navigation";
2+
3+
import { AxiosResponse } from "axios";
4+
5+
import { axiosInstance } from "@/utils/axiosInstance";
6+
7+
// 예시: 성공 후 페이지 이동
8+
import { QueryKeys } from "./queryKey";
9+
10+
import { LanguageTestEnum } from "@/types/score";
11+
12+
import { useMutation, useQueryClient } from "@tanstack/react-query";
13+
14+
// QueryKeys가 정의된 경로로 수정해주세요.
15+
16+
interface UsePostLanguageTestScoreRequest {
17+
languageTestScoreRequest: {
18+
languageTestType: LanguageTestEnum;
19+
languageTestScore: string;
20+
issueDate: string; // yyyy-MM-dd
21+
};
22+
file: File;
23+
}
24+
25+
export const postLanguageTestScore = (request: UsePostLanguageTestScoreRequest): Promise<AxiosResponse<null>> => {
26+
const convertedRequest: FormData = new FormData();
27+
convertedRequest.append(
28+
"languageTestScoreRequest",
29+
new Blob([JSON.stringify(request.languageTestScoreRequest)], { type: "application/json" }),
30+
);
31+
convertedRequest.append("file", request.file);
32+
return axiosInstance.post("/scores/language-tests", convertedRequest);
33+
};
34+
/**
35+
* 공인 어학 점수를 제출(POST)하기 위한 useMutation 훅입니다.
36+
*/
37+
export const usePostLanguageTestScore = () => {
38+
const queryClient = useQueryClient();
39+
40+
return useMutation({
41+
mutationFn: (request: UsePostLanguageTestScoreRequest) => postLanguageTestScore(request),
42+
43+
onSuccess: () => {
44+
alert("어학 성적이 성공적으로 제출되었습니다.");
45+
queryClient.invalidateQueries({ queryKey: [QueryKeys.myLanguageTestScore] });
46+
},
47+
48+
onError: (error) => {
49+
console.error("어학 성적 제출 중 오류 발생:", error);
50+
alert("오류가 발생했습니다. 다시 시도해주세요.");
51+
},
52+
});
53+
};

src/api/university/client/useGetUniversitySearchByText.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,12 @@ const getUniversitySearchByText = async (value: string): Promise<UniversitySearc
2828

2929
// --- 커스텀 훅 ---
3030
const useGetUniversitySearchByText = (searchValue: string) => {
31+
const staleTime = searchValue === "" ? Infinity : 1000 * 60 * 5;
32+
3133
return useQuery<UniversitySearchTextResponse, Error, ListUniversity[]>({
3234
queryKey: [QueryKeys.universitySearchText, searchValue],
3335
queryFn: () => getUniversitySearchByText(searchValue),
34-
// 검색어가 있을 때만 쿼리를 실행합니다.
35-
enabled: !!searchValue && searchValue.trim().length > 0,
36-
// 실제 컴포넌트에는 univApplyInfoPreviews 배열만 전달합니다.
36+
staleTime,
3737
select: (data) => data.univApplyInfoPreviews,
3838
});
3939
};
Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,45 @@
11
import serverFetch from "@/utils/serverFetchUtil";
22

3-
import { ListUniversity } from "@/types/university";
3+
import { AllRegionsUniversityList, ListUniversity, RegionEnumExtend } from "@/types/university";
44

5+
// --- 타입 정의 ---
56
interface UniversitySearchResponse {
67
univApplyInfoPreviews: ListUniversity[];
78
}
89

9-
export const getSearchUniversitiesByText = async (value: string): Promise<ListUniversity[]> => {
10-
// 검색어가 없으면 빈 배열을 반환하여 불필요한 요청을 막습니다.
11-
if (!value || value.trim() === "") {
10+
export const getUniversitiesByText = async (value: string): Promise<ListUniversity[]> => {
11+
if (value === null || value === undefined) {
1212
return [];
1313
}
14-
1514
const endpoint = `/univ-apply-infos/search/text?value=${encodeURIComponent(value)}`;
1615
const response = await serverFetch<UniversitySearchResponse>(endpoint);
17-
1816
return response.ok ? response.data.univApplyInfoPreviews : [];
1917
};
18+
19+
export const getAllUniversities = async (): Promise<ListUniversity[]> => {
20+
return getUniversitiesByText("");
21+
};
22+
23+
export const getCategorizedUniversities = async (): Promise<AllRegionsUniversityList> => {
24+
// 1. 단 한 번의 API 호출로 모든 대학 데이터를 가져옵니다.
25+
const allUniversities = await getAllUniversities();
26+
27+
const categorizedList: AllRegionsUniversityList = {
28+
[RegionEnumExtend.ALL]: allUniversities,
29+
[RegionEnumExtend.AMERICAS]: [],
30+
[RegionEnumExtend.EUROPE]: [],
31+
[RegionEnumExtend.ASIA]: [],
32+
[RegionEnumExtend.CHINA]: [],
33+
};
34+
if (!allUniversities) return categorizedList;
35+
36+
for (const university of allUniversities) {
37+
const region = university.region as RegionEnumExtend; // API 응답의 region 타입을 enum으로 간주
38+
39+
if (region && categorizedList.hasOwnProperty(region)) {
40+
categorizedList[region].push(university);
41+
}
42+
}
43+
44+
return categorizedList;
45+
};

src/api/university/server/getUniversitiesByAllRegion.ts

Lines changed: 0 additions & 125 deletions
This file was deleted.

src/app/(home)/page.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import PopularUniversitySection from "./_ui/PopularUniversitySection";
88
import UniversityList from "./_ui/UniversityList";
99

1010
import getRecommendedUniversity from "@/api/university/server/getRecommendedUniversity";
11-
import { getUniversitiesByAllRegion } from "@/api/university/server/getUniversitiesByAllRegion";
11+
import { getCategorizedUniversities } from "@/api/university/server/getSearchUniversitiesByText";
1212
import { fetchAllNews } from "@/lib/firebaseNews";
1313
import { IconIdCard, IconMagnifyingGlass, IconMuseum, IconPaper } from "@/public/svgs/home";
1414

@@ -30,14 +30,14 @@ const HomePage = async () => {
3030
const { data } = await getRecommendedUniversity();
3131
const recommendedUniversities = data?.recommendedUniversities || [];
3232
// 권역별 전체 대학 리스트를 미리 가져와 빌드합니다
33-
const allRegionsUniversityList = await getUniversitiesByAllRegion();
33+
const allRegionsUniversityList = await getCategorizedUniversities();
3434

3535
return (
3636
<>
3737
<FindLastYearScoreBar />
3838
<div className="flex flex-col gap-2.5 px-5 py-3.5">
3939
<div className="flex gap-2">
40-
<Link className="h-26 flex flex-1 flex-col gap-2 rounded-lg bg-[#F0F5FF] p-2.5" href="/search">
40+
<Link className="h-26 flex flex-1 flex-col gap-2 rounded-lg bg-[#F0F5FF] p-2.5" href="/university">
4141
<div className="flex flex-col">
4242
<span className="text-sm font-bold text-secondary">학교 검색하기</span>
4343
<span className="text-xs font-medium leading-tight text-k-700">모든 학교 목록을 확인해보세요</span>
@@ -46,7 +46,7 @@ const HomePage = async () => {
4646
<IconMagnifyingGlass />
4747
</div>
4848
</Link>
49-
<Link className="h-26 flex flex-1 flex-col gap-2 rounded-lg bg-[#EBF8FF] p-2.5" href="/score">
49+
<Link className="h-26 flex flex-1 flex-col gap-2 rounded-lg bg-[#EBF8FF] p-2.5" href="/university/score">
5050
<div className="flex flex-col">
5151
<span className="text-sm font-bold text-sub-a">성적 입력하기</span>
5252
<span className="text-xs font-medium leading-tight text-k-700">성적을 입력해보세요</span>

0 commit comments

Comments
 (0)