Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 11 additions & 17 deletions apps/web/src/apis/applications/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,25 @@ export interface UseSubmitApplicationRequest {
};
}

export interface CompetitorsResponse {
competitors: Array<{
id: number;
name: string;
score: number;
}>;
}

// ====== API Functions ======
export const applicationsApi = {
/**
* 지원 목록 조회
* 전체 지원자 현황 조회
*/
getApplicationsList: async (): Promise<AxiosResponse<ApplicationListResponse>> => {
return axiosInstance.get("/applications");
},

/**
* 내가 지원한 대학의 경쟁자 현황 조회
*
* 서버에서 현재 사용자의 지원 대학만 반환하므로, 클라이언트에서 소속 대학 기준으로
* 다시 필터링하지 않는다.
*/
getCompetitors: async (): Promise<AxiosResponse<ApplicationListResponse>> => {
return axiosInstance.get("/applications/competitors");
},

/**
* 지원자가 있는 대학의 제한 공개 정보 조회
*/
Expand All @@ -57,12 +59,4 @@ export const applicationsApi = {
): Promise<AxiosResponse<UseSubmitApplicationResponse>> => {
return axiosInstance.post("/applications", request);
},

/**
* 경쟁자 목록 조회
*/
getCompetitors: async (config?: { params?: Record<string, unknown> }): Promise<CompetitorsResponse> => {
const res = await axiosInstance.get<CompetitorsResponse>("/applications/competitors", config);
return res.data;
},
};
32 changes: 18 additions & 14 deletions apps/web/src/apis/applications/getApplicants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,20 @@ type UseGetApplicationsListOptions = Omit<
>;

/**
* @description 지원 목록 조회 훅
*
* `GET /applications` 는 전체 지원자 현황을 내려주고 소속 대학을 구분해주지 않는다.
* 그래서 access token 에서 파싱된 소속 대학(useAuthStore.homeUniversityId)으로
* 파견학교 목록을 따로 받아, 그 범위에 속한 항목만 남기도록 클라이언트에서 걸러낸다.
* 지원 기간에는 지원한 대학만, 기간 종료 후에는 소속 대학의 전체 현황을 공개한다.
* 전체 현황을 다시 공개할 때 반환값을 "applications"로 변경한다.
*/
type ApplicationStatusEndpoint = "applications" | "competitors";

const getApplicationStatusEndpoint = (): ApplicationStatusEndpoint => "competitors";

const applicationStatusEndpoint = getApplicationStatusEndpoint();
const shouldFilterByHomeUniversity = applicationStatusEndpoint === "applications";
const applicationStatusQueryFn =
applicationStatusEndpoint === "competitors" ? applicationsApi.getCompetitors : applicationsApi.getApplicationsList;

/**
* @description 내가 지원한 대학의 지원자 현황 조회 훅
*/
const useGetApplicationsList = (
props?: UseGetApplicationsListOptions,
Expand All @@ -28,28 +37,23 @@ const useGetApplicationsList = (

const applicationsQuery = useQuery({
queryKey: [ApplicationsQueryKeys.competitorsApplicationList],
queryFn: applicationsApi.getApplicationsList,
queryFn: applicationStatusQueryFn,
staleTime: 1000 * 60 * 5, // 5분간 캐시
select: (response) => response.data,
...props,
});

// 필터 기준이 되는 소속 대학의 파견학교 목록
// GET /applications를 사용할 때만 소속 대학의 파견학교 목록으로 범위를 제한한다.
const { data: scopedUniversities } = useQuery({
queryKey: [QueryKeys.universities.searchText, { homeUniversityId }],
queryFn: () => universitiesApi.getSearchText({ value: "", homeUniversityId: homeUniversityId ?? undefined }),
enabled: homeUniversityId !== null,
enabled: shouldFilterByHomeUniversity && homeUniversityId !== null,
staleTime: 1000 * 60 * 5,
select: (response) => response.univApplyInfoPreviews,
});

const scopedData = useMemo(() => {
if (!applicationsQuery.data) {
return applicationsQuery.data;
}

// 소속 대학을 모르면(비인증·학교 미인증) 기존과 동일하게 전체를 보여준다.
if (homeUniversityId === null) {
if (!applicationsQuery.data || !shouldFilterByHomeUniversity || homeUniversityId === null) {
return applicationsQuery.data;
}

Expand Down
23 changes: 16 additions & 7 deletions apps/web/src/apis/applications/getCompetitors.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
import { useQuery } from "@tanstack/react-query";
import type { AxiosError } from "axios";
import { type UseQueryOptions, useQuery } from "@tanstack/react-query";
import type { AxiosError, AxiosResponse } from "axios";

import type { ApplicationListResponse } from "@/types/application";
import { QueryKeys } from "../queryKeys";
import { applicationsApi, type CompetitorsResponse } from "./api";
import { applicationsApi } from "./api";

type UseGetCompetitorsOptions = Omit<
UseQueryOptions<AxiosResponse<ApplicationListResponse>, AxiosError<{ message: string }>, ApplicationListResponse>,
"queryKey" | "queryFn"
>;

const useGetCompetitors = (params?: Record<string, unknown>) => {
return useQuery<CompetitorsResponse, AxiosError>({
queryKey: [QueryKeys.applications.competitors, params],
queryFn: () => applicationsApi.getCompetitors(params ? { params } : {}),
const useGetCompetitors = (props?: UseGetCompetitorsOptions) => {
return useQuery({
queryKey: [QueryKeys.applications.competitors],
queryFn: applicationsApi.getCompetitors,
select: (response) => response.data,
...props,
});
};

Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/apis/applications/homeUniversityScope.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { ApplicationListResponse, ScoreSheet } from "@/types/application";
/**
* 지원자 현황 응답을 소속 대학 기준으로 걸러내기 위한 키.
*
* `GET /applications` 응답(ScoreSheet)에는 홈 대학 식별자도, 지원 정보 id 도 없다.
* GET /applications 응답(ScoreSheet)에는 홈 대학 식별자도, 지원 정보 id도 없다.
* 그래서 파견학교 목록과 겹치는 필드(파견학교명 + 국가 + 모집인원)를 합쳐 식별한다.
*
* 파견학교명만으로는 부족하다. 서로 다른 홈 대학이 같은 이름의 파견학교를 가질 수 있고
Expand Down
Loading