Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat-fe: 지원자 정렬 기능 #824

Merged
merged 11 commits into from
Oct 17, 2024
6 changes: 3 additions & 3 deletions frontend/src/api/domain/process.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { ProcessResponse } from '@customTypes/process';
import { ProcessQueryParams, ProcessResponse } from '@customTypes/process';
import { PROCESSES } from '../endPoint';
import { createParams } from '../utils';
import APIClient from '../APIClient';

const apiClient = new APIClient(PROCESSES);

const processApis = {
get: async ({ dashboardId }: { dashboardId: string }): Promise<ProcessResponse> =>
get: async ({ dashboardId, ...params }: ProcessQueryParams): Promise<ProcessResponse> =>
apiClient.get({
path: `?${createParams({ dashboardId })}`,
path: `?${createParams({ dashboardId, ...params })}`,
}),

create: async (params: { dashboardId: number; orderIndex: number; name: string; description?: string }) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const Header = styled.div<{ isOpen: boolean; size: 'sm' | 'md' }>`
justify-content: space-between;
align-items: center;

padding: ${({ size }) => (size === 'md' ? '16px 24px' : '12px 4px 12px 8px ')};
padding: ${({ size }) => (size === 'md' ? '16px 24px' : '8px 4px 8px 8px ')};

border: 1px solid ${({ theme }) => theme.baseColors.grayscale[400]};

Expand Down
46 changes: 46 additions & 0 deletions frontend/src/components/dashboard/ApplicantSortDropdown/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import Dropdown from '@components/_common/molecules/Dropdown';
import DropdownItemRenderer from '@components/_common/molecules/DropdownItemRenderer';
import { ProcessSortOption, SortOption } from '@customTypes/process';
import { SortOptionState } from '@hooks/useProcess/useSortApplicant';

interface ApplicantSortDropdownProps {
sortOption: SortOptionState;
updateSortOption: (option?: SortOptionState) => void;
}

interface SortOptionsType {
id: ProcessSortOption;
name: string;
value: SortOption;
}

const sortOptions: SortOptionsType[] = [
{ id: 'sortByScore', name: '평점 높은 순', value: 'DESC' },
{ id: 'sortByScore', name: '평점 낮은 순', value: 'ASC' },
{ id: 'sortByCreatedAt', name: '지원일 최신 순', value: 'DESC' },
{ id: 'sortByCreatedAt', name: '지원일 오래된 순', value: 'ASC' },
];
Comment on lines +17 to +22
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍


export default function ApplicantSortDropdown({ sortOption, updateSortOption }: ApplicantSortDropdownProps) {
const selectedOption = sortOptions.find(
(option) => sortOption && option.id && option.value === sortOption[option.id],
);

return (
<Dropdown
initValue={selectedOption?.name || '정렬'}
size="sm"
isShadow={false}
width={118}
>
<DropdownItemRenderer
items={sortOptions.map(({ id, name, value }) => ({
type: 'clickable',
id,
name,
onClick: () => updateSortOption({ [id]: value } as SortOptionState),
}))}
/>
</Dropdown>
);
}
31 changes: 27 additions & 4 deletions frontend/src/hooks/useProcess/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import type { Process, ProcessResponse } from '@customTypes/process';

import processApis from '@api/domain/process';
import QUERY_KEYS from '@hooks/queryKeys';
import useSortApplicant from '@hooks/useProcess/useSortApplicant';
import { routes } from '@router/path';
import { useEffect } from 'react';
import { DOMAIN_URL } from '../../constants/constants';

export interface SimpleProcess {
Expand All @@ -13,8 +15,8 @@ export interface SimpleProcess {
}

interface UseProcessProps {
dashboardId: string;
applyFormId: string;
dashboardId: string;
}

interface UseProcessReturn {
Expand All @@ -28,15 +30,34 @@ interface UseProcessReturn {
endDate: string;
}

export default function useProcess({ dashboardId, applyFormId }: UseProcessProps): UseProcessReturn {
const { data, error, isLoading } = useQuery<ProcessResponse>({
export default function useProcess({
dashboardId,
applyFormId,
}: UseProcessProps): UseProcessReturn & ReturnType<typeof useSortApplicant> {
const { sortOption, updateSortOption } = useSortApplicant();

const { data, error, isLoading, refetch } = useQuery<ProcessResponse>({
// [10.17-lesser]
// sortOption을 queryKey에 추가하면 기존 요청까지 다시 보내게 되어
// queryKey에 sortOption을 추가하지 않고, refetch로 재요청 보내도록 수정합니다.
// eslint-disable-next-line
queryKey: [QUERY_KEYS.DASHBOARD, dashboardId, applyFormId],
queryFn: () => processApis.get({ dashboardId }),
queryFn: () =>
processApis.get({
dashboardId,
...sortOption,
// ...(filterOption && { filterOption: filterOption as ProcessFilterOptions }),
}),
});

useEffect(() => {
refetch();
}, [sortOption]);

Comment on lines +53 to +56
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

멋진 💡 아이디어 👍

const processes = data?.processes || [];

const processList = processes.map((p) => ({ processName: p.name, processId: p.processId }));

return {
title: data?.title ?? '',
postUrl: `${DOMAIN_URL}${routes.post({ applyFormId: data?.applyFormId ?? '' })}`,
Expand All @@ -46,5 +67,7 @@ export default function useProcess({ dashboardId, applyFormId }: UseProcessProps
isLoading,
startDate: data?.startDate ?? '0',
endDate: data?.endDate ?? '0',
sortOption,
updateSortOption,
};
}
17 changes: 17 additions & 0 deletions frontend/src/hooks/useProcess/useSortApplicant.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { SortParams } from '@customTypes/process';
import { useCallback, useState } from 'react';

export type SortOptionState = Partial<SortParams> | undefined;

export default function useSortApplicant() {
const [sortOption, setSortOption] = useState<SortOptionState>();

const updateSortOption = useCallback((option?: SortOptionState) => {
setSortOption(option);
}, []);

return {
sortOption,
updateSortOption,
};
}
27 changes: 19 additions & 8 deletions frontend/src/pages/Dashboard/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,42 @@
import { useParams } from 'react-router-dom';

import Tab from '@components/_common/molecules/Tab';
import ProcessBoard from '@components/dashboard/ProcessBoard';
import ApplyManagement from '@components/applyManagement';
import ProcessManageBoard from '@components/processManagement/ProcessManageBoard';
import PostManageBoard from '@components/postManagement/PostManageBoard';
import DashboardHeader from '@components/dashboard/DashboardHeader';
import ProcessBoard from '@components/dashboard/ProcessBoard';
import PostManageBoard from '@components/postManagement/PostManageBoard';
import ProcessManageBoard from '@components/processManagement/ProcessManageBoard';

import useProcess from '@hooks/useProcess';
import useTab from '@components/_common/molecules/Tab/useTab';
import { useSearchApplicant } from '@components/dashboard/useSearchApplicant';
import useProcess from '@hooks/useProcess';

import { DASHBOARD_TAB_MENUS } from '@constants/constants';
import { FloatingEmailFormProvider } from '@contexts/FloatingEmailFormContext';
import { MultiApplicantContextProvider } from '@contexts/MultiApplicantContext';
import { SpecificProcessIdProvider } from '@contexts/SpecificProcessIdContext';
import { SpecificApplicantIdProvider } from '@contexts/SpecificApplicnatIdContext';
import { SpecificProcessIdProvider } from '@contexts/SpecificProcessIdContext';

import S from './style';

export type DashboardTabItems = '지원자 관리' | '모집 과정 관리' | '불합격자 관리' | '공고 관리' | '지원서 관리';

export default function Dashboard() {
const { dashboardId, applyFormId } = useParams() as { dashboardId: string; applyFormId: string };
const { processes, title, postUrl, startDate, endDate } = useProcess({ dashboardId, applyFormId });

const { currentMenu, moveTab } = useTab<DashboardTabItems>({ defaultValue: '지원자 관리' });

const { debouncedName } = useSearchApplicant();
// TODO: [10.15-lesser] sub tab이 구현되면 아래 코드를 사용합니다.
// const { debouncedName, name, updateName } = useSearchApplicant();
// const { processes, title, postUrl, startDate, endDate, sortOption, updateSortOption } = useProcess({
// dashboardId,
// applyFormId,
// });

const { dashboardId, applyFormId } = useParams() as { dashboardId: string; applyFormId: string };
const { processes, title, postUrl, startDate, endDate } = useProcess({
dashboardId,
applyFormId,
});

return (
<S.AppContainer>
Expand Down Expand Up @@ -66,6 +73,10 @@ export default function Dashboard() {
value={name}
onChange={(e) => updateName(e.target.value)}
/> */}
{/* <ApplicantSortDropdown
sortOption={sortOption}
updateSortOption={updateSortOption}
/> */}

<SpecificApplicantIdProvider>
<SpecificProcessIdProvider>
Expand Down
21 changes: 21 additions & 0 deletions frontend/src/types/process.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,24 @@ export interface ProcessResponse {
startDate: string;
endDate: string;
}

export type EvaluationStatus = 'ALL' | 'NOT_EVALUATION' | 'EVALUATED';

type FilterParams = {
minScore?: string;
maxScore?: string;
evaluationStatus?: EvaluationStatus;
};
export type ProcessFilterOptions = FilterParams;

export type SortOption = 'ASC' | 'DESC';
export type SortParams = {
sortByCreatedAt?: SortOption;
sortByScore?: SortOption;
};
export type ProcessSortOption = keyof SortParams;

export type ProcessQueryParams = {
dashboardId: string;
} & FilterParams &
SortParams;
4 changes: 4 additions & 0 deletions frontend/src/types/utilTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,7 @@ type Brand<B> = { [__brand]: B };
export type Branded<T, B> = T & Brand<B>;

export type KeyedStrings<T> = Record<keyof T, string>;

export type Entries<T> = {
[K in keyof T]: [K, T[K]];
}[keyof T][];
Comment on lines +26 to +29
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Loading