diff --git a/src/components/common/table/Table.tsx b/src/components/common/table/Table.tsx new file mode 100644 index 00000000..d6537526 --- /dev/null +++ b/src/components/common/table/Table.tsx @@ -0,0 +1,164 @@ +import { useEffect, useState } from 'react'; +import TableStatus from './TableStatus'; +import TableButtons from './TableButtons'; +import Pagination from '../Pagination'; +import formatWorkTime from '@/utils/formatWorkTime'; +import { + getNoticeApplications, + getUserApplications, +} from '@/api/applicationApi'; + +interface UserProps { + className?: string; + mode: 'user'; + userId: string; +} + +interface NoticeProps { + className?: string; + mode: 'notice'; + shopId: string; + noticeId: string; +} + +export default function Table(props: UserProps | NoticeProps) { + const { className, mode } = props; + const headers = + mode === 'notice' + ? ['신청자', '소개', '전화번호', '상태'] + : ['가게', '일자', '시급', '상태']; + const [datas, setDatas] = useState<(string | undefined)[][]>( + Array(5).fill(['', '', '', '']), + ); + const [page, setPage] = useState(1); + const [totalPage, setTotalPage] = useState(1); + + useEffect(() => { + (async () => { + try { + if (mode === 'notice') { + const { items, count } = await getNoticeApplications( + props.shopId, + props.noticeId, + { + offset: (page - 1) * 5, + limit: 5, + }, + ); + + setTotalPage(count ? Math.ceil(count / 5) : 1); + setDatas( + [...items, ...[null, null, null, null, null]] + .slice(0, 5) + .map((element) => { + if (!element) return ['', '', '', '']; + + return [ + element.item.user.item.name, + element.item.user.item.bio, + element.item.user.item.phone, + element.item.status, + element.item.id, + ]; + }), + ); + } else { + const { items, count } = await getUserApplications(props.userId, { + offset: (page - 1) * 5, + limit: 5, + }); + + setTotalPage(count ? Math.ceil(count / 5) : 1); + setDatas( + [...items, ...[null, null, null, null, null]] + .slice(0, 5) + .map((element) => { + if (!element) return ['', '', '', '']; + + return [ + element.item.shop.item.name, + `${formatWorkTime({ + startsAt: element.item.notice.item.startsAt, + workhour: element.item.notice.item.workhour, + })} (${element.item.notice.item.workhour}시간)`, + element.item.notice.item.hourlyPay.toLocaleString('ko-KR') + + '원', + element.item.status, + ]; + }), + ); + } + } catch { + setDatas(Array(5).fill(['', '', '', ''])); + setPage(1); + setTotalPage(1); + } + })(); + }, [mode, page]); + + return ( +
+ + + + + + + + + + + {datas.map((data, index) => ( + + + + + + + ))} + +
+ {headers[0]} + + {headers[1]} + + {headers[2]} + + {headers[3]} +
+
+ {data[0]} +
+
+
+ {data[1]} +
+
+
+ {data[2]} +
+
+
+ {mode === 'notice' && data[3] === 'pending' ? ( + + ) : ( + + )} +
+
+
+ +
+
+ ); +} diff --git a/src/components/common/table/TableButtons.tsx b/src/components/common/table/TableButtons.tsx new file mode 100644 index 00000000..8a6f241c --- /dev/null +++ b/src/components/common/table/TableButtons.tsx @@ -0,0 +1,103 @@ +import { useEffect, useState, type MouseEvent } from 'react'; +import Button from '../Button'; +import TableStatus from './TableStatus'; +import { putNoticeApplications } from '@/api/applicationApi'; +import Modal from '../Modal'; + +interface Props { + shopId: string; + noticeId: string; + applicaitonId: string; +} + +export default function TableButtons({ + shopId, + noticeId, + applicaitonId, +}: Props) { + const [status, setStatus] = useState<'pending' | 'accepted' | 'rejected'>( + 'pending', + ); + const [modal, setModal] = useState<{ + isOpen: boolean; + status: 'accepted' | 'rejected'; + }>({ + isOpen: false, + status: 'accepted', + }); + const [isMobile, setIsMobile] = useState(window.innerWidth < 768); + + const closeModal = () => + setModal((prev) => { + return { ...prev, isOpen: false }; + }); + + const handleModalClick = async () => { + closeModal(); + setStatus(modal.status); + try { + await putNoticeApplications(shopId, noticeId, applicaitonId, { + status: modal.status, + }); + } catch { + setStatus('pending'); + } + }; + + const handleClick = (e: MouseEvent) => { + setModal({ + isOpen: true, + status: e.currentTarget.value as 'accepted' | 'rejected', + }); + }; + + useEffect(() => { + const handleResize = () => { + setIsMobile(window.innerWidth < 768); + }; + window.addEventListener('resize', handleResize); + return () => window.removeEventListener('resize', handleResize); + }, []); + + return status === 'pending' ? ( + <> +
+ + +
+ {modal.isOpen && ( + + 신청을 {modal.status === 'accepted' ? '승인' : '거절'}하시겠어요? + + )} + + ) : ( + + ); +} diff --git a/src/components/common/table/TableStatus.tsx b/src/components/common/table/TableStatus.tsx new file mode 100644 index 00000000..3e0d6822 --- /dev/null +++ b/src/components/common/table/TableStatus.tsx @@ -0,0 +1,19 @@ +export default function TableStatus({ status }: { status: string }) { + return status === 'pending' ? ( +
+ 대기중 +
+ ) : status === 'accepted' ? ( +
+ 승인 완료 +
+ ) : status === 'rejected' ? ( +
+ 거절 +
+ ) : status === 'canceled' ? ( +
+ 취소 +
+ ) : null; +}