From dc3f969ddf78f02a0e9f91e4ebca091b73aa14d5 Mon Sep 17 00:00:00 2001 From: Sangmin Park Date: Wed, 20 Mar 2024 21:14:05 +0900 Subject: [PATCH 1/4] =?UTF-8?q?[feat]=20=EC=A7=80=EC=9B=90=EC=9E=90=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=20=EA=B8=B0=EB=B3=B8=20=EA=B5=AC?= =?UTF-8?q?=EC=84=B1=20#1254?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DetailRecruitUserList.tsx | 106 +++++++++++------- .../recruitmentsuser/NotificationResults.tsx | 2 +- constants/admin/table.ts | 9 +- pages/api/pingpong/admin/recruitments/[id].ts | 42 +++++-- .../recruitments/RecruitmentsUser.module.scss | 78 +++++++++++++ types/admin/adminRecruitmentsTypes.ts | 14 +-- 6 files changed, 182 insertions(+), 69 deletions(-) create mode 100644 styles/admin/recruitments/RecruitmentsUser.module.scss diff --git a/components/admin/recruitments/recruitmentsuser/DetailRecruitUserList.tsx b/components/admin/recruitments/recruitmentsuser/DetailRecruitUserList.tsx index 0d310e2b1..e0566da5a 100644 --- a/components/admin/recruitments/recruitmentsuser/DetailRecruitUserList.tsx +++ b/components/admin/recruitments/recruitmentsuser/DetailRecruitUserList.tsx @@ -4,6 +4,7 @@ import { Paper, Table, TableBody, + TableHead, TableCell, TableContainer, TableRow, @@ -15,34 +16,32 @@ import { // import { instanceInManage } from 'utils/axios'; import { mockInstance } from 'utils/mockAxios'; import { toastState } from 'utils/recoil/toast'; +import { tableFormat } from 'constants/admin/table'; import { AdminEmptyItem, AdminTableHead, AdminContent, } from 'components/admin/common/AdminTable'; import PageNation from 'components/Pagination'; -import styles from 'styles/admin/recruitments/Recruitments.module.scss'; - +import styles from 'styles/admin/recruitments/RecruitmentsUser.module.scss'; //무한 스크롤로 변경 //필터 추가 /* 추가할 기능 가로세로 길이 조절 가로세로 위치 변경 +호버 기능? */ export interface IrecruitTable { - applications: IrecruitUserTable['applications']; + applications: IrecruitUserTable[]; totalPage: number; currentPage: number; } const tableTitle: { [key: string]: string } = { - id: 'ID', - usedAt: '적용 시간', - title: '제목', + intraId: 'intraId', status: '상태', - detailRecruitment: '공고 상세보기', - detaillUser: '지원자 보기', + question: '질문', }; function DetailRecruitUserList({ recruitId }: { recruitId: number }) { @@ -80,36 +79,7 @@ function DetailRecruitUserList({ recruitId }: { recruitId: number }) { getRecruitUserHandler(); }, [currentPage]); - const renderTableCell = ( - recruit: IrecruitUserTable['applications'][number] - ) => { - return ( - - - - - {recruit.form?.map((formItem: Iquestion, index: number) => ( - - item.content).join(', ') || - '' - } - maxLen={16} - /> - - ))} - - ); - }; - - if (!recruitUserData.applications.length) { + if (!recruitUserData.applications) { return ( @@ -122,13 +92,69 @@ function DetailRecruitUserList({ recruitId }: { recruitId: number }) { ); } + const questions = recruitUserData.applications.reduce( + (acc: string[], application: { form: { question: string }[] }) => { + application.form.forEach(({ question }) => { + if (acc.indexOf(question) === -1) { + acc.push(question); + } + }); + return acc; + }, + [] + ); + + const renderTableCells = (recruit: IrecruitUserTable) => { + const answers = questions.map((question) => { + const formItem = recruit.form.find((form) => form.question === question); + if (!formItem) return 'N/A'; + + switch (formItem.inputType) { + case 'TEXT': + return formItem.answer; + case 'SINGLE_CHECK': + return formItem.checkedList?.map((item) => item.content).join(', '); + case 'MULTI_CHECK': + return formItem.checkedList + ?.flatMap((item) => + item.content.map((c: { content: string }) => c.content) + ) + .join(', '); + } + }); + + return ( + + + {recruit.intraId} + + {recruit.status} + {answers.map((answer, index) => ( + + {answer} + + ))} + + ); + }; + return ( <>
- + + + intraId + status + {questions.map((question, index) => ( + + {question} + + ))} + + - {recruitUserData.applications.map(renderTableCell)} + {recruitUserData.applications.map(renderTableCells)}
diff --git a/components/admin/recruitments/recruitmentsuser/NotificationResults.tsx b/components/admin/recruitments/recruitmentsuser/NotificationResults.tsx index a94586f91..05b2b4142 100644 --- a/components/admin/recruitments/recruitmentsuser/NotificationResults.tsx +++ b/components/admin/recruitments/recruitmentsuser/NotificationResults.tsx @@ -26,7 +26,7 @@ import { AdminTableHead, } from 'components/admin/common/AdminTable'; import PageNation from 'components/Pagination'; -import styles from 'styles/admin/recruitments/Recruitments.module.scss'; +import styles from 'styles/admin/recruitments/RecruitmentsUser.module.scss'; import 'react-datepicker/dist/react-datepicker.css'; const tableTitle: { [key: string]: string } = { diff --git a/constants/admin/table.ts b/constants/admin/table.ts index 2fc12ee69..8628b65dd 100644 --- a/constants/admin/table.ts +++ b/constants/admin/table.ts @@ -174,14 +174,7 @@ export const tableFormat: TableFormat = { }, recruitUserList: { name: '지원자 목록', - columns: [ - 'id', - 'intraId', - 'status', - 'createdAt', - 'detailUser', - 'detailRecruit', - ], + columns: ['intraId', 'status', 'question'], }, recruitEditTitle: { name: '공고 수정', diff --git a/pages/api/pingpong/admin/recruitments/[id].ts b/pages/api/pingpong/admin/recruitments/[id].ts index 529b35f96..9d9128867 100644 --- a/pages/api/pingpong/admin/recruitments/[id].ts +++ b/pages/api/pingpong/admin/recruitments/[id].ts @@ -4,29 +4,47 @@ const fullRecruitData1 = { applications: [ { applicationId: 1, - intraId: 'test1', + intraId: + 'test1213412342134231412412423142142142134213423421341243123412341234124124124123', status: '합격', form: [ { questionId: 1, - question: '이름', + question: '질문 1', inputType: 'TEXT', - answer: '홍길동', + answer: '답변 1', }, { questionId: 2, - question: '나이', + question: '질문 2', inputType: 'SINGLE_CHECK', - answer: '20', + checkedList: [{ checkId: 1, content: '선택지 1' }], }, { questionId: 3, - question: '성별', + question: '질문 3', + inputType: 'MULTI_CHECK', + checkedList: [ + { + checkId: 1, + content: [ + { checkId: 1, content: '선택지 1' }, + { checkId: 2, content: '선택지 2' }, + ], + }, + ], + }, + { + questionId: 4, + question: '질문 4', inputType: 'MULTI_CHECK', - checkList: [ + checkedList: [ { checkId: 1, - content: '남', + content: [ + { checkId: 1, content: '선택지 1' }, + { checkId: 2, content: '123456789012345678901234567890' }, + ], }, ], }, @@ -52,8 +70,8 @@ const fullRecruitData1 = { { questionId: 3, question: '성별', - inputType: 'TEXT', - checkList: [ + inputType: 'SINGLE_CHECK', + checkedList: [ { checkId: 1, content: '여', @@ -82,8 +100,8 @@ const fullRecruitData1 = { { questionId: 3, question: '성별', - inputType: 'TEXT', - checkList: [ + inputType: 'SINGLE_CHECK', + checkedList: [ { checkId: 1, content: '여', diff --git a/styles/admin/recruitments/RecruitmentsUser.module.scss b/styles/admin/recruitments/RecruitmentsUser.module.scss new file mode 100644 index 000000000..8bbcc6727 --- /dev/null +++ b/styles/admin/recruitments/RecruitmentsUser.module.scss @@ -0,0 +1,78 @@ +@import 'styles/admin/common/Pagination.module.scss'; +@import 'styles/common.scss'; +@import 'styles/admin/common.scss'; + +.tableContainer { + width: 100px; + margin: auto; + + .table { + width: max-content; + .tableHeader { + background-color: lightgray; + .tableHeaderItem { + padding: 0.5rem; + font-size: $small-font; + font-weight: 600; + line-height: 150%; + text-align: center; + } + } + .tableBody { + overflow-x: auto; + .tableRow { + &:nth-child(odd) { + background-color: #f9fafb; + } + &:nth-child(even) { + background-color: #fff; + } + .tableBodyItem { + padding: 10px; + font-size: $small-font; + line-height: 150%; + text-align: center; + } + } + } + } +} +.searchWrap { + display: flex; + justify-content: flex-end; + align-items: center; + padding-bottom: 0.3rem; + :nth-child(2) { + margin: 0 0 0 20px; + } +} + +.deleteBtn { + width: 5rem; + height: 1.5rem; + color: #ffffff; + cursor: pointer; + background: #2678f3; + border: none; + border-radius: 8px; + justify-content: center; + align-items: center; + &:disabled { + cursor: not-allowed; + background-color: #929fb3; + } +} + +.interview { + display: flex; + justify-content: center; + align-items: center; +} + +.button { + @include admin-button('PALE-BLUE'); + padding: 0.5rem 1.3rem; + margin-top: 1rem; +} + +@include pagination; diff --git a/types/admin/adminRecruitmentsTypes.ts b/types/admin/adminRecruitmentsTypes.ts index 72ca82b4f..ab3e6ccdf 100644 --- a/types/admin/adminRecruitmentsTypes.ts +++ b/types/admin/adminRecruitmentsTypes.ts @@ -21,12 +21,12 @@ export interface Iquestion { question: string; inputType: 'TEXT' | 'SINGLE_CHECK' | 'MULTI_CHECK'; answer?: string; - checkList?: Array; + checkedList?: Array; } export interface IcheckItem { checkId?: number; - content: string; + content: Array<{ checkId: number; content: string }>; } export interface Inotication { @@ -47,10 +47,8 @@ export interface InoticationTable { } export interface IrecruitUserTable { - applications: { - applicationId: number; - intraId: string; - status?: '합격' | '불합격' | '심사중'; - form: Array; - }[]; + applicationId: number; + intraId: string; + status?: '합격' | '불합격' | '심사중'; + form: Iquestion[]; } From b006a7f22abcae661aea2356c4a15f2e405196ae Mon Sep 17 00:00:00 2001 From: Sangmin Park Date: Thu, 21 Mar 2024 23:11:02 +0900 Subject: [PATCH 2/4] =?UTF-8?q?[Feat]=20=EC=A7=80=EC=9B=90=EC=9E=90=20?= =?UTF-8?q?=EB=A6=AC=EC=8A=A4=ED=8A=B8=20=EC=83=81=EC=84=B8=EB=B3=B4?= =?UTF-8?q?=EA=B8=B0,=20=ED=98=B8=EB=B2=84=EA=B8=B0=EB=8A=A5,=20=ED=95=84?= =?UTF-8?q?=ED=84=B0=EB=A0=88=EC=9D=B4=EC=95=84=EC=9B=83=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20#1254?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/admin/common/AdminTable.tsx | 21 +++ .../DetailRecruitUserList.tsx | 167 ++++++++++++++++-- .../recruitmentsuser/RecruitSearchBar.tsx | 58 ++++++ constants/admin/table.ts | 2 +- styles/admin/common/AdminTable.module.scss | 25 +++ 5 files changed, 261 insertions(+), 12 deletions(-) create mode 100644 components/admin/recruitments/recruitmentsuser/RecruitSearchBar.tsx diff --git a/components/admin/common/AdminTable.tsx b/components/admin/common/AdminTable.tsx index afff054ba..bb3b39a1c 100644 --- a/components/admin/common/AdminTable.tsx +++ b/components/admin/common/AdminTable.tsx @@ -71,3 +71,24 @@ export function AdminContent({
{content?.toString()}
); } + +export function DetailContentHover({ + content, + maxLen, +}: { + content?: string; + maxLen: number; +}) { + if (!content) return
N/A
; + + return content?.length > maxLen ? ( +
+
+ {(content?.toString() || '').slice(0, maxLen)}... +
+
{content}
+
+ ) : ( +
{content?.toString()}
+ ); +} diff --git a/components/admin/recruitments/recruitmentsuser/DetailRecruitUserList.tsx b/components/admin/recruitments/recruitmentsuser/DetailRecruitUserList.tsx index e0566da5a..430cdbaad 100644 --- a/components/admin/recruitments/recruitmentsuser/DetailRecruitUserList.tsx +++ b/components/admin/recruitments/recruitmentsuser/DetailRecruitUserList.tsx @@ -1,5 +1,7 @@ import { useCallback, useEffect, useState } from 'react'; import { useSetRecoilState } from 'recoil'; +import ChevronRightIcon from '@mui/icons-material/ChevronRight'; +import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; import { Paper, Table, @@ -8,7 +10,8 @@ import { TableCell, TableContainer, TableRow, -} from '@mui/material'; + IconButton } from '@mui/material'; +import { TableRowProps } from '@mui/material/TableRow'; import { IrecruitUserTable, Iquestion, @@ -16,16 +19,20 @@ import { // import { instanceInManage } from 'utils/axios'; import { mockInstance } from 'utils/mockAxios'; import { toastState } from 'utils/recoil/toast'; -import { tableFormat } from 'constants/admin/table'; import { AdminEmptyItem, AdminTableHead, - AdminContent, + // AdminContent, + DetailContentHover, } from 'components/admin/common/AdminTable'; import PageNation from 'components/Pagination'; import styles from 'styles/admin/recruitments/RecruitmentsUser.module.scss'; -//무한 스크롤로 변경 -//필터 추가 +import RecruitSearchBar from './RecruitSearchBar'; +//TODO: 테이블 헤더, 테이블 바디, 페이지네이션 컴포넌트 분리 +// 기본적인 부분 +// 3. 페이지네이션 추가 +// 4. 필터 추가 + /* 추가할 기능 가로세로 길이 조절 @@ -38,12 +45,46 @@ export interface IrecruitTable { currentPage: number; } +interface ExpandableTableRowProps extends TableRowProps { + children: React.ReactNode; + expandComponent: React.ReactNode; +} + const tableTitle: { [key: string]: string } = { + id: '', intraId: 'intraId', status: '상태', question: '질문', }; +const ExpandableTableRow: React.FC = ({ + children, + expandComponent, + ...otherProps +}) => { + const [isExpanded, setIsExpanded] = useState(false); + + return ( + <> + + + setIsExpanded(!isExpanded)}> + {isExpanded ? : } + + + {children} + + {isExpanded && ( + + + {expandComponent} + + + )} + + ); +}; + function DetailRecruitUserList({ recruitId }: { recruitId: number }) { const [recruitUserData, setRecruitUserData] = useState({ applications: [], @@ -52,12 +93,46 @@ function DetailRecruitUserList({ recruitId }: { recruitId: number }) { }); const [currentPage, setCurrentPage] = useState(1); const setSnackBar = useSetRecoilState(toastState); + const [questionId, setQuestionId] = useState(''); + const [checklistIds, setChecklistIds] = useState>([]); + const [searchString, setSearchString] = useState(''); + + const initSearch = useCallback((searchString?: string) => { + setSearchString(searchString || ''); + setCurrentPage(1); + }, []); + + const handleQuestionChange = ( + event: React.ChangeEvent + ) => { + setQuestionId(event.target.value); + }; + + const handleChecklistChange = ( + event: React.ChangeEvent + ) => { + const value = event.target.value; + if (event.target.checked) { + setChecklistIds([...checklistIds, value]); + } else { + setChecklistIds(checklistIds.filter((id) => id !== value)); + } + }; const getRecruitUserHandler = useCallback(async () => { try { // const res = await instanceInManage.get( - // `/recruitments/${recruitId}/applications` + // `/recruitments/${recruitId}/applications`, { + // params: { + // page: currentPage, + // size: 20, + // question: questionId, + // checks: checklistIds.join(','), + // search: searchString, + // } + // } // ); + console.log('searchString', searchString); const id = recruitId; const res = await mockInstance.get(`/admin/recruitments/${id}`); setRecruitUserData({ @@ -73,11 +148,17 @@ function DetailRecruitUserList({ recruitId }: { recruitId: number }) { clicked: true, }); } - }, [currentPage]); + }, [currentPage, recruitId, questionId, checklistIds, searchString]); useEffect(() => { getRecruitUserHandler(); - }, [currentPage]); + }, [ + getRecruitUserHandler, + currentPage, + questionId, + checklistIds, + searchString, + ]); if (!recruitUserData.applications) { return ( @@ -92,6 +173,48 @@ function DetailRecruitUserList({ recruitId }: { recruitId: number }) { ); } + // const handleSearchChange = (event: React.ChangeEvent) => { + // setSearchString(event.target.value); + // } + + const FilterQptionsUI = () => ( +
+
+ +
+ +
+ + +
+
+ ); + const questions = recruitUserData.applications.reduce( (acc: string[], application: { form: { question: string }[] }) => { application.form.forEach(({ question }) => { @@ -124,26 +247,48 @@ function DetailRecruitUserList({ recruitId }: { recruitId: number }) { }); return ( - + +
+ intraId: {recruit.intraId} +
+
+ status: {recruit.status} +
+ {recruit.form.map((form, index) => ( +
+ {form.question}:{' '} + {form.answer ? form.answer : 'N/A'} +
+ ))} + + } + > {recruit.intraId} {recruit.status} {answers.map((answer, index) => ( - {answer} +
+ +
))} -
+ ); }; return ( <> + + intraId status {questions.map((question, index) => ( diff --git a/components/admin/recruitments/recruitmentsuser/RecruitSearchBar.tsx b/components/admin/recruitments/recruitmentsuser/RecruitSearchBar.tsx new file mode 100644 index 000000000..61716e770 --- /dev/null +++ b/components/admin/recruitments/recruitmentsuser/RecruitSearchBar.tsx @@ -0,0 +1,58 @@ +import { GoSearch } from 'react-icons/go'; +import { IoIosCloseCircle } from 'react-icons/io'; +import useSearchBar from 'hooks/useSearchBar'; +import styles from 'styles/admin/common/AdminSearchBar.module.scss'; + +const MAX_SEARCH_LENGTH = 15; + +export default function RecruitSearchBar({ + initSearch, +}: { + initSearch: (searchString?: string) => void; +}) { + const { keyword, setKeyword, keywordHandler, searchResult, searchBarRef } = + useSearchBar(); + + const adminhandleKeyDown = (event: React.KeyboardEvent) => { + if (event.key === 'Enter') { + if (keyword === searchResult[0]) { + event.currentTarget.blur(); + initSearch(keyword); + } + } + }; + + return ( +
+ +
+ {keyword ? ( + { + initSearch(); + setKeyword(''); + }} + > + + + ) : ( + { + initSearch(); + }} + > + + + )} +
+
+ ); +} diff --git a/constants/admin/table.ts b/constants/admin/table.ts index 8628b65dd..8962b4b57 100644 --- a/constants/admin/table.ts +++ b/constants/admin/table.ts @@ -174,7 +174,7 @@ export const tableFormat: TableFormat = { }, recruitUserList: { name: '지원자 목록', - columns: ['intraId', 'status', 'question'], + columns: ['', 'intraId', 'status', 'question'], }, recruitEditTitle: { name: '공고 수정', diff --git a/styles/admin/common/AdminTable.module.scss b/styles/admin/common/AdminTable.module.scss index 8480a9890..4535ea778 100644 --- a/styles/admin/common/AdminTable.module.scss +++ b/styles/admin/common/AdminTable.module.scss @@ -28,3 +28,28 @@ text-align: center; } } + +.tableBodyItemHover { + position: relative; + cursor: pointer; +} + +.hoverInfo { + position: absolute; + bottom: 0.5rem; + left: 50%; + box-sizing: border-box; + display: block; + visibility: hidden; + opacity: 0; + transition: visibility 0s, opacity 0.5s linear; + transform: translate3d(-50%, -20px, 0); + transform: translate3d(0, 0, 0); +} + +.tableBodyItemHover:hover .hoverInfo { + visibility: visible; + background-color: #676869; + border-width: 10rem; + opacity: 1; +} From b908babc780494ebf9f23fb4a94f83259f7b9920 Mon Sep 17 00:00:00 2001 From: Sangmin Park Date: Fri, 29 Mar 2024 12:26:10 +0900 Subject: [PATCH 3/4] =?UTF-8?q?[Feat]=20=ED=95=84=ED=84=B0=EC=98=B5?= =?UTF-8?q?=EC=85=98=EC=B6=94=EA=B0=80=20#1254?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/admin/common/AdminTable.tsx | 2 +- .../DetailRecruitUserList.tsx | 194 +----------------- .../recruitmentsuser/FilterOptions.tsx | 98 +++++++++ .../recruitmentsuser/renderTableCells.tsx | 101 +++++++++ pages/api/pingpong/admin/recruitments/[id].ts | 33 +-- styles/admin/common/AdminTable.module.scss | 13 +- .../recruitments/RecruitmentsUser.module.scss | 10 +- types/admin/adminRecruitmentsTypes.ts | 10 +- 8 files changed, 253 insertions(+), 208 deletions(-) create mode 100644 components/admin/recruitments/recruitmentsuser/FilterOptions.tsx create mode 100644 components/admin/recruitments/recruitmentsuser/renderTableCells.tsx diff --git a/components/admin/common/AdminTable.tsx b/components/admin/common/AdminTable.tsx index bb3b39a1c..44d328221 100644 --- a/components/admin/common/AdminTable.tsx +++ b/components/admin/common/AdminTable.tsx @@ -86,7 +86,7 @@ export function DetailContentHover({
{(content?.toString() || '').slice(0, maxLen)}...
-
{content}
+ {/*
{content}
*/} ) : (
{content?.toString()}
diff --git a/components/admin/recruitments/recruitmentsuser/DetailRecruitUserList.tsx b/components/admin/recruitments/recruitmentsuser/DetailRecruitUserList.tsx index 430cdbaad..02ca07d51 100644 --- a/components/admin/recruitments/recruitmentsuser/DetailRecruitUserList.tsx +++ b/components/admin/recruitments/recruitmentsuser/DetailRecruitUserList.tsx @@ -1,7 +1,5 @@ import { useCallback, useEffect, useState } from 'react'; import { useSetRecoilState } from 'recoil'; -import ChevronRightIcon from '@mui/icons-material/ChevronRight'; -import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; import { Paper, Table, @@ -10,24 +8,19 @@ import { TableCell, TableContainer, TableRow, - IconButton } from '@mui/material'; -import { TableRowProps } from '@mui/material/TableRow'; -import { - IrecruitUserTable, - Iquestion, -} from 'types/admin/adminRecruitmentsTypes'; +} from '@mui/material'; +import { IrecruitArrayTable } from 'types/admin/adminRecruitmentsTypes'; // import { instanceInManage } from 'utils/axios'; import { mockInstance } from 'utils/mockAxios'; import { toastState } from 'utils/recoil/toast'; import { AdminEmptyItem, AdminTableHead, - // AdminContent, - DetailContentHover, } from 'components/admin/common/AdminTable'; import PageNation from 'components/Pagination'; import styles from 'styles/admin/recruitments/RecruitmentsUser.module.scss'; -import RecruitSearchBar from './RecruitSearchBar'; +import FilterQptionsUI from './FilterOptions'; +import renderTableCells from './renderTableCells'; //TODO: 테이블 헤더, 테이블 바디, 페이지네이션 컴포넌트 분리 // 기본적인 부분 // 3. 페이지네이션 추가 @@ -39,16 +32,6 @@ import RecruitSearchBar from './RecruitSearchBar'; 가로세로 위치 변경 호버 기능? */ -export interface IrecruitTable { - applications: IrecruitUserTable[]; - totalPage: number; - currentPage: number; -} - -interface ExpandableTableRowProps extends TableRowProps { - children: React.ReactNode; - expandComponent: React.ReactNode; -} const tableTitle: { [key: string]: string } = { id: '', @@ -57,67 +40,14 @@ const tableTitle: { [key: string]: string } = { question: '질문', }; -const ExpandableTableRow: React.FC = ({ - children, - expandComponent, - ...otherProps -}) => { - const [isExpanded, setIsExpanded] = useState(false); - - return ( - <> - - - setIsExpanded(!isExpanded)}> - {isExpanded ? : } - - - {children} - - {isExpanded && ( - - - {expandComponent} - - - )} - - ); -}; - function DetailRecruitUserList({ recruitId }: { recruitId: number }) { - const [recruitUserData, setRecruitUserData] = useState({ + const [recruitUserData, setRecruitUserData] = useState({ applications: [], totalPage: 0, currentPage: 0, }); const [currentPage, setCurrentPage] = useState(1); const setSnackBar = useSetRecoilState(toastState); - const [questionId, setQuestionId] = useState(''); - const [checklistIds, setChecklistIds] = useState>([]); - const [searchString, setSearchString] = useState(''); - - const initSearch = useCallback((searchString?: string) => { - setSearchString(searchString || ''); - setCurrentPage(1); - }, []); - - const handleQuestionChange = ( - event: React.ChangeEvent - ) => { - setQuestionId(event.target.value); - }; - - const handleChecklistChange = ( - event: React.ChangeEvent - ) => { - const value = event.target.value; - if (event.target.checked) { - setChecklistIds([...checklistIds, value]); - } else { - setChecklistIds(checklistIds.filter((id) => id !== value)); - } - }; const getRecruitUserHandler = useCallback(async () => { try { @@ -132,7 +62,6 @@ function DetailRecruitUserList({ recruitId }: { recruitId: number }) { // } // } // ); - console.log('searchString', searchString); const id = recruitId; const res = await mockInstance.get(`/admin/recruitments/${id}`); setRecruitUserData({ @@ -148,17 +77,11 @@ function DetailRecruitUserList({ recruitId }: { recruitId: number }) { clicked: true, }); } - }, [currentPage, recruitId, questionId, checklistIds, searchString]); + }, [currentPage, recruitId]); useEffect(() => { getRecruitUserHandler(); - }, [ - getRecruitUserHandler, - currentPage, - questionId, - checklistIds, - searchString, - ]); + }, [getRecruitUserHandler, currentPage]); if (!recruitUserData.applications) { return ( @@ -173,48 +96,6 @@ function DetailRecruitUserList({ recruitId }: { recruitId: number }) { ); } - // const handleSearchChange = (event: React.ChangeEvent) => { - // setSearchString(event.target.value); - // } - - const FilterQptionsUI = () => ( -
-
- -
- -
- - -
-
- ); - const questions = recruitUserData.applications.reduce( (acc: string[], application: { form: { question: string }[] }) => { application.form.forEach(({ question }) => { @@ -226,64 +107,9 @@ function DetailRecruitUserList({ recruitId }: { recruitId: number }) { }, [] ); - - const renderTableCells = (recruit: IrecruitUserTable) => { - const answers = questions.map((question) => { - const formItem = recruit.form.find((form) => form.question === question); - if (!formItem) return 'N/A'; - - switch (formItem.inputType) { - case 'TEXT': - return formItem.answer; - case 'SINGLE_CHECK': - return formItem.checkedList?.map((item) => item.content).join(', '); - case 'MULTI_CHECK': - return formItem.checkedList - ?.flatMap((item) => - item.content.map((c: { content: string }) => c.content) - ) - .join(', '); - } - }); - - return ( - -
- intraId: {recruit.intraId} -
-
- status: {recruit.status} -
- {recruit.form.map((form, index) => ( -
- {form.question}:{' '} - {form.answer ? form.answer : 'N/A'} -
- ))} - - } - > - - {recruit.intraId} - - {recruit.status} - {answers.map((answer, index) => ( - -
- -
-
- ))} -
- ); - }; - return ( <> - + {FilterQptionsUI(recruitUserData.applications, questions)}
@@ -299,7 +125,9 @@ function DetailRecruitUserList({ recruitId }: { recruitId: number }) { - {recruitUserData.applications.map(renderTableCells)} + {recruitUserData.applications.map((recruit) => + renderTableCells(recruit, questions) + )}
diff --git a/components/admin/recruitments/recruitmentsuser/FilterOptions.tsx b/components/admin/recruitments/recruitmentsuser/FilterOptions.tsx new file mode 100644 index 000000000..236b4f106 --- /dev/null +++ b/components/admin/recruitments/recruitmentsuser/FilterOptions.tsx @@ -0,0 +1,98 @@ +import React, { useState, useEffect, useCallback } from 'react'; +import { + FormControl, + Select, + OutlinedInput, + MenuItem, + Checkbox, + ListItemText, + SelectChangeEvent, + TableRowProps } from '@mui/material'; +import { + IcheckItem, + IrecruitUserTable, +} from 'types/admin/adminRecruitmentsTypes'; +import styles from 'styles/admin/recruitments/RecruitmentsUser.module.scss'; +import RecruitSearchBar from './RecruitSearchBar'; +const ITEM_HEIGHT = 48; +const ITEM_PADDING_TOP = 8; +const MenuProps = { + PaperProps: { + style: { + maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP, + width: 250, + }, + }, +}; + +function FilterQptionsUI( + recruitUserData: IrecruitUserTable[], + questions: string[] +) { + const [answers, setAnswers] = useState>([]); + const [checklistIds, setChecklistIds] = useState>([]); + const [searchString, setSearchString] = useState(''); + const [currentPage, setCurrentPage] = useState(1); + + const initSearch = useCallback((searchString?: string) => { + setSearchString(searchString || ''); + setCurrentPage(1); + }, []); + + const handleChecklistChange = ( + event: SelectChangeEvent + ) => { + const { + target: { value }, + } = event; + typeof value !== 'string' ? setChecklistIds(value) : value; + }; + + useEffect(() => { + const newAnswers: Array = []; + + recruitUserData.forEach((recruit) => { + recruit.form.forEach((formItem) => { + if (formItem.inputType !== 'TEXT') { + formItem.checkedList?.forEach((item) => { + if (!newAnswers.some((answer) => answer.checkId === item.checkId)) { + newAnswers.push(item); + } + }); + } + }); + }); + + setAnswers(newAnswers); + }, [recruitUserData, questions]); + + return ( +
+
+ +
+
+ + + +
+
+ ); +} + +export default FilterQptionsUI; diff --git a/components/admin/recruitments/recruitmentsuser/renderTableCells.tsx b/components/admin/recruitments/recruitmentsuser/renderTableCells.tsx new file mode 100644 index 000000000..81ee30ed0 --- /dev/null +++ b/components/admin/recruitments/recruitmentsuser/renderTableCells.tsx @@ -0,0 +1,101 @@ +import React, { useState } from 'react'; +import ChevronRightIcon from '@mui/icons-material/ChevronRight'; +import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; +import { TableCell, TableRow, IconButton, TableRowProps } from '@mui/material'; +import { IrecruitUserTable } from 'types/admin/adminRecruitmentsTypes'; +import { DetailContentHover } from 'components/admin/common/AdminTable'; +import styles from 'styles/admin/recruitments/RecruitmentsUser.module.scss'; + +interface ExpandableTableRowProps extends TableRowProps { + children: React.ReactNode; + expandComponent: React.ReactNode; +} + +const ExpandableTableRow: React.FC = ({ + children, + expandComponent, + ...otherProps +}) => { + const [isExpanded, setIsExpanded] = useState(false); + const childrenCount = React.Children.count(children); + + const expandedClickHandler = () => { + setIsExpanded(!isExpanded); + }; + + return ( + <> + + + + {isExpanded ? : } + + + {children} + + {isExpanded && ( + + + {expandComponent} + + + )} + + ); +}; + +function renderTableCells(recruit: IrecruitUserTable, questions: string[]) { + const answers = questions.map((question) => { + const formItem = recruit.form.find((form) => form.question === question); + if (!formItem) return 'N/A'; + + switch (formItem.inputType) { + case 'TEXT': + return formItem.answer; + case 'SINGLE_CHECK': + return formItem.checkedList?.map((item) => item.content).join(', '); + case 'MULTI_CHECK': + return formItem.checkedList?.map((item) => item.content).join(', '); + default: + return 'N/A'; + } + }); + + return ( + +
+ intraId: {recruit.intraId} +
+
+ status: {recruit.status} +
+ {recruit.form.map((form, index) => ( +
+ {form.question}:{' '} + {form.answer + ? form.answer + : form.checkedList?.map((item) => item.content).join(', ')} +
+ ))} + + } + > + {recruit.intraId} + {recruit.status} + {answers.map( + (answer: string | undefined, index: React.Key | null | undefined) => ( + +
+ +
+
+ ) + )} +
+ ); +} + +export default renderTableCells; diff --git a/pages/api/pingpong/admin/recruitments/[id].ts b/pages/api/pingpong/admin/recruitments/[id].ts index 9d9128867..4e331bc33 100644 --- a/pages/api/pingpong/admin/recruitments/[id].ts +++ b/pages/api/pingpong/admin/recruitments/[id].ts @@ -4,8 +4,7 @@ const fullRecruitData1 = { applications: [ { applicationId: 1, - intraId: - 'test1213412342134231412412423142142142134213423421341243123412341234124124124123', + intraId: 'test1', status: '합격', form: [ { @@ -26,11 +25,13 @@ const fullRecruitData1 = { inputType: 'MULTI_CHECK', checkedList: [ { - checkId: 1, - content: [ - { checkId: 1, content: '선택지 1' }, - { checkId: 2, content: '선택지 2' }, - ], + checkId: 2, + content: '선택지 2', + }, + { + checkId: 3, + content: + '선택지 3ㅁㄴㅇㄹㄴㅁㅇㄹㅁㄴㅇㄹㅁㄴㅇㄹㅁㄴㄹㅁㄴㄹㅁㄴㅁㄴㄹㅁ', }, ], }, @@ -40,11 +41,13 @@ const fullRecruitData1 = { inputType: 'MULTI_CHECK', checkedList: [ { - checkId: 1, - content: [ - { checkId: 1, content: '선택지 1' }, - { checkId: 2, content: '123456789012345678901234567890' }, - ], + checkId: 2, + content: '선택지 2', + }, + { + checkId: 4, + content: + '선택지 2sadfsadfasdfasfsadfasfasdㅁㄴㅇㄹㅁㄴㄹㅁㄴㅇㄹㅁㄴㅇㄹㅁㄴㅇㄹㄴㅁㅇㄹㅁㄴㄹㅁㄴㄹㄴㅁㄹㅁㄴㄹㅁㄴㄹㅁㄴㄹㅁㄹ', }, ], }, @@ -73,8 +76,8 @@ const fullRecruitData1 = { inputType: 'SINGLE_CHECK', checkedList: [ { - checkId: 1, - content: '여', + checkId: 6, + content: '남', }, ], }, @@ -103,7 +106,7 @@ const fullRecruitData1 = { inputType: 'SINGLE_CHECK', checkedList: [ { - checkId: 1, + checkId: 5, content: '여', }, ], diff --git a/styles/admin/common/AdminTable.module.scss b/styles/admin/common/AdminTable.module.scss index 4535ea778..ffcf1cecf 100644 --- a/styles/admin/common/AdminTable.module.scss +++ b/styles/admin/common/AdminTable.module.scss @@ -31,25 +31,26 @@ .tableBodyItemHover { position: relative; - cursor: pointer; } .hoverInfo { position: absolute; bottom: 0.5rem; - left: 50%; box-sizing: border-box; display: block; + width: 200%; + padding: 16px; + cursor: pointer; visibility: hidden; + border-radius: 1rem; opacity: 0; transition: visibility 0s, opacity 0.5s linear; - transform: translate3d(-50%, -20px, 0); - transform: translate3d(0, 0, 0); + transform: translate3d(0, 105%, 0); } .tableBodyItemHover:hover .hoverInfo { + z-index: 1; visibility: visible; - background-color: #676869; - border-width: 10rem; + background-color: #cbced1; opacity: 1; } diff --git a/styles/admin/recruitments/RecruitmentsUser.module.scss b/styles/admin/recruitments/RecruitmentsUser.module.scss index 8bbcc6727..f004f3c8a 100644 --- a/styles/admin/recruitments/RecruitmentsUser.module.scss +++ b/styles/admin/recruitments/RecruitmentsUser.module.scss @@ -5,9 +5,11 @@ .tableContainer { width: 100px; margin: auto; + overflow-x: scroll; .table { width: max-content; + min-width: 100%; .tableHeader { background-color: lightgray; .tableHeaderItem { @@ -19,7 +21,6 @@ } } .tableBody { - overflow-x: auto; .tableRow { &:nth-child(odd) { background-color: #f9fafb; @@ -75,4 +76,11 @@ margin-top: 1rem; } +.filterWrap { + display: flex; + justify-content: space-between; + align-items: center; + padding-bottom: 0.3rem; +} + @include pagination; diff --git a/types/admin/adminRecruitmentsTypes.ts b/types/admin/adminRecruitmentsTypes.ts index ab3e6ccdf..fe7d9db0f 100644 --- a/types/admin/adminRecruitmentsTypes.ts +++ b/types/admin/adminRecruitmentsTypes.ts @@ -25,8 +25,8 @@ export interface Iquestion { } export interface IcheckItem { - checkId?: number; - content: Array<{ checkId: number; content: string }>; + checkId: number; + content: string; } export interface Inotication { @@ -52,3 +52,9 @@ export interface IrecruitUserTable { status?: '합격' | '불합격' | '심사중'; form: Iquestion[]; } + +export interface IrecruitArrayTable { + applications: IrecruitUserTable[]; + totalPage: number; + currentPage: number; +} From 01910d65ab8f69d4dd980aa0f24ada487b1a718f Mon Sep 17 00:00:00 2001 From: Sangmin Park Date: Fri, 29 Mar 2024 18:09:11 +0900 Subject: [PATCH 4/4] =?UTF-8?q?[Feat]=20=ED=95=84=ED=84=B0=20api=EC=97=B0?= =?UTF-8?q?=EA=B2=B0=20=20#1254?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DetailRecruitUserList.tsx | 76 ++------------- .../recruitmentsuser/FilterOptions.tsx | 63 +++++-------- .../recruitmentsuser/RecruitSearchBar.tsx | 22 ++--- .../recruitments/useRecruitmentUserFilter.ts | 93 +++++++++++++++++++ 4 files changed, 132 insertions(+), 122 deletions(-) create mode 100644 hooks/recruitments/useRecruitmentUserFilter.ts diff --git a/components/admin/recruitments/recruitmentsuser/DetailRecruitUserList.tsx b/components/admin/recruitments/recruitmentsuser/DetailRecruitUserList.tsx index 02ca07d51..17b76fc95 100644 --- a/components/admin/recruitments/recruitmentsuser/DetailRecruitUserList.tsx +++ b/components/admin/recruitments/recruitmentsuser/DetailRecruitUserList.tsx @@ -1,5 +1,4 @@ -import { useCallback, useEffect, useState } from 'react'; -import { useSetRecoilState } from 'recoil'; +import { useState } from 'react'; import { Paper, Table, @@ -9,29 +8,15 @@ import { TableContainer, TableRow, } from '@mui/material'; -import { IrecruitArrayTable } from 'types/admin/adminRecruitmentsTypes'; -// import { instanceInManage } from 'utils/axios'; -import { mockInstance } from 'utils/mockAxios'; -import { toastState } from 'utils/recoil/toast'; import { AdminEmptyItem, AdminTableHead, } from 'components/admin/common/AdminTable'; import PageNation from 'components/Pagination'; +import useRecruitmentUserFilter from 'hooks/recruitments/useRecruitmentUserFilter'; import styles from 'styles/admin/recruitments/RecruitmentsUser.module.scss'; import FilterQptionsUI from './FilterOptions'; import renderTableCells from './renderTableCells'; -//TODO: 테이블 헤더, 테이블 바디, 페이지네이션 컴포넌트 분리 -// 기본적인 부분 -// 3. 페이지네이션 추가 -// 4. 필터 추가 - -/* -추가할 기능 -가로세로 길이 조절 -가로세로 위치 변경 -호버 기능? -*/ const tableTitle: { [key: string]: string } = { id: '', @@ -41,47 +26,11 @@ const tableTitle: { [key: string]: string } = { }; function DetailRecruitUserList({ recruitId }: { recruitId: number }) { - const [recruitUserData, setRecruitUserData] = useState({ - applications: [], - totalPage: 0, - currentPage: 0, - }); const [currentPage, setCurrentPage] = useState(1); - const setSnackBar = useSetRecoilState(toastState); - - const getRecruitUserHandler = useCallback(async () => { - try { - // const res = await instanceInManage.get( - // `/recruitments/${recruitId}/applications`, { - // params: { - // page: currentPage, - // size: 20, - // question: questionId, - // checks: checklistIds.join(','), - // search: searchString, - // } - // } - // ); - const id = recruitId; - const res = await mockInstance.get(`/admin/recruitments/${id}`); - setRecruitUserData({ - applications: res.data.applications, - totalPage: res.data.totalPages, - currentPage: res.data.number + 1, - }); - } catch (e: any) { - setSnackBar({ - toastName: 'get recruitment', - severity: 'error', - message: `API 요청에 문제가 발생했습니다.`, - clicked: true, - }); - } - }, [currentPage, recruitId]); - - useEffect(() => { - getRecruitUserHandler(); - }, [getRecruitUserHandler, currentPage]); + const { recruitUserData, questions } = useRecruitmentUserFilter( + recruitId, + currentPage + ); if (!recruitUserData.applications) { return ( @@ -96,20 +45,9 @@ function DetailRecruitUserList({ recruitId }: { recruitId: number }) { ); } - const questions = recruitUserData.applications.reduce( - (acc: string[], application: { form: { question: string }[] }) => { - application.form.forEach(({ question }) => { - if (acc.indexOf(question) === -1) { - acc.push(question); - } - }); - return acc; - }, - [] - ); return ( <> - {FilterQptionsUI(recruitUserData.applications, questions)} + {FilterQptionsUI(recruitUserData.applications)} diff --git a/components/admin/recruitments/recruitmentsuser/FilterOptions.tsx b/components/admin/recruitments/recruitmentsuser/FilterOptions.tsx index 236b4f106..ee44cf0bb 100644 --- a/components/admin/recruitments/recruitmentsuser/FilterOptions.tsx +++ b/components/admin/recruitments/recruitmentsuser/FilterOptions.tsx @@ -4,16 +4,17 @@ import { Select, OutlinedInput, MenuItem, - Checkbox, ListItemText, SelectChangeEvent, - TableRowProps } from '@mui/material'; +} from '@mui/material'; import { IcheckItem, IrecruitUserTable, } from 'types/admin/adminRecruitmentsTypes'; +import useRecruitmentUserFilter from 'hooks/recruitments/useRecruitmentUserFilter'; import styles from 'styles/admin/recruitments/RecruitmentsUser.module.scss'; import RecruitSearchBar from './RecruitSearchBar'; + const ITEM_HEIGHT = 48; const ITEM_PADDING_TOP = 8; const MenuProps = { @@ -25,51 +26,31 @@ const MenuProps = { }, }; -function FilterQptionsUI( - recruitUserData: IrecruitUserTable[], - questions: string[] -) { +function FilterQptionsUI(recruitUserData: IrecruitUserTable[]) { const [answers, setAnswers] = useState>([]); - const [checklistIds, setChecklistIds] = useState>([]); - const [searchString, setSearchString] = useState(''); - const [currentPage, setCurrentPage] = useState(1); - - const initSearch = useCallback((searchString?: string) => { - setSearchString(searchString || ''); - setCurrentPage(1); - }, []); - - const handleChecklistChange = ( - event: SelectChangeEvent - ) => { - const { - target: { value }, - } = event; - typeof value !== 'string' ? setChecklistIds(value) : value; - }; + const { checklistIds, handleChecklistChange } = useRecruitmentUserFilter(); useEffect(() => { - const newAnswers: Array = []; - - recruitUserData.forEach((recruit) => { - recruit.form.forEach((formItem) => { - if (formItem.inputType !== 'TEXT') { - formItem.checkedList?.forEach((item) => { - if (!newAnswers.some((answer) => answer.checkId === item.checkId)) { - newAnswers.push(item); - } - }); - } - }); - }); - - setAnswers(newAnswers); - }, [recruitUserData, questions]); + setAnswers( + recruitUserData.reduce((acc, recruit) => { + recruit.form.forEach((formItem) => { + if (formItem.inputType !== 'TEXT') { + formItem.checkedList?.forEach((item) => { + if (!acc.some((answer) => answer.checkId === item.checkId)) { + acc.push(item); + } + }); + } + }); + return acc; + }, [] as Array) + ); + }, [recruitUserData]); return (
- +
@@ -84,7 +65,7 @@ function FilterQptionsUI( MenuProps={MenuProps} > {answers.map((answer: IcheckItem, index) => ( - + ))} diff --git a/components/admin/recruitments/recruitmentsuser/RecruitSearchBar.tsx b/components/admin/recruitments/recruitmentsuser/RecruitSearchBar.tsx index 61716e770..25dc602d0 100644 --- a/components/admin/recruitments/recruitmentsuser/RecruitSearchBar.tsx +++ b/components/admin/recruitments/recruitmentsuser/RecruitSearchBar.tsx @@ -1,24 +1,20 @@ import { GoSearch } from 'react-icons/go'; import { IoIosCloseCircle } from 'react-icons/io'; +import useRecruitmentUserFilter from 'hooks/recruitments/useRecruitmentUserFilter'; import useSearchBar from 'hooks/useSearchBar'; import styles from 'styles/admin/common/AdminSearchBar.module.scss'; const MAX_SEARCH_LENGTH = 15; -export default function RecruitSearchBar({ - initSearch, -}: { - initSearch: (searchString?: string) => void; -}) { - const { keyword, setKeyword, keywordHandler, searchResult, searchBarRef } = - useSearchBar(); +export default function RecruitSearchBar() { + const { keyword, setKeyword, searchBarRef } = useSearchBar(); + + const { initSearch } = useRecruitmentUserFilter(); const adminhandleKeyDown = (event: React.KeyboardEvent) => { if (event.key === 'Enter') { - if (keyword === searchResult[0]) { - event.currentTarget.blur(); - initSearch(keyword); - } + event.currentTarget.blur(); + initSearch(keyword); } }; @@ -26,7 +22,9 @@ export default function RecruitSearchBar({
{ + setKeyword(e.target.value); + }} onKeyDown={adminhandleKeyDown} placeholder='검색하기...' maxLength={MAX_SEARCH_LENGTH} diff --git a/hooks/recruitments/useRecruitmentUserFilter.ts b/hooks/recruitments/useRecruitmentUserFilter.ts new file mode 100644 index 000000000..8ee2bca7b --- /dev/null +++ b/hooks/recruitments/useRecruitmentUserFilter.ts @@ -0,0 +1,93 @@ +import { useCallback, useEffect, useState } from 'react'; +import { useSetRecoilState } from 'recoil'; +import { SelectChangeEvent } from '@mui/material'; +import { + IcheckItem, + IrecruitArrayTable, +} from 'types/admin/adminRecruitmentsTypes'; +import { mockInstance } from 'utils/mockAxios'; +import { toastState } from 'utils/recoil/toast'; + +const useRucruitmentUserFilter = (currentPage?: number, recruitId?: number) => { + const [recruitUserData, setRecruitUserData] = useState({ + applications: [], + totalPage: 0, + currentPage: 0, + }); + const setSnackBar = useSetRecoilState(toastState); + const [checklistIds, setChecklistIds] = useState>([]); + const [searchString, setSearchString] = useState(''); + + const getRecruitUserHandler = useCallback(async () => { + try { + // const res = await instanceInManage.get( + // `/recruitments/${recruitId}/applications`, { + // params: { + // page: currentPage, + // size: 20, + // question: questionId, + // checks: checklistIds.map((check) => check).join(','), + // search: search, + // } + // } + // ); + const id = recruitId; + const res = await mockInstance.get(`/admin/recruitments/${id}`); + setRecruitUserData({ + applications: res.data.applications, + totalPage: res.data.totalPages, + currentPage: res.data.number + 3, + }); + } catch (e: any) { + setSnackBar({ + toastName: 'get recruitment', + severity: 'error', + message: `API 요청에 문제가 발생했습니다.`, + clicked: true, + }); + } + }, [currentPage, searchString, checklistIds]); + + useEffect(() => { + getRecruitUserHandler(); + }, [currentPage, searchString, checklistIds]); + + const questions = recruitUserData.applications.reduce( + (acc: string[], application: { form: { question: string }[] }) => { + application.form.forEach(({ question }) => { + if (acc.indexOf(question) === -1) { + acc.push(question); + } + }); + return acc; + }, + [] + ); + + const handleChecklistChange = ( + event: SelectChangeEvent + ) => { + const { + target: { value }, + } = event; + typeof value !== 'string' ? setChecklistIds(value) : value; + }; + + const initSearch = useCallback((searchString?: string) => { + setSearchString(searchString || ''); + }, []); + + return { + checklistIds, + searchString, + setChecklistIds, + setSearchString, + getRecruitUserHandler, + recruitUserData, + questions, + initSearch, + handleChecklistChange, + }; +}; + +export default useRucruitmentUserFilter;