Skip to content

Commit 860eeb0

Browse files
Merge pull request #152 from codeit-6team/fix/142-modal-table
🐛 fix: Table Modal 오류 수정
2 parents 6cbd9a9 + cd28863 commit 860eeb0

File tree

2 files changed

+148
-147
lines changed

2 files changed

+148
-147
lines changed

src/components/common/table/Table.tsx

Lines changed: 119 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ import { useEffect, useState } from 'react';
22
import TableStatus from './TableStatus';
33
import TableButtons from './TableButtons';
44
import Pagination from '../Pagination';
5+
import Modal from '../Modal';
56
import formatWorkTime from '@/utils/formatWorkTime';
67
import {
78
getNoticeApplications,
89
getUserApplications,
10+
putNoticeApplications,
911
} from '@/api/applicationApi';
1012

1113
interface UserProps {
@@ -32,6 +34,53 @@ export default function Table(props: UserProps | NoticeProps) {
3234
);
3335
const [page, setPage] = useState(1);
3436
const [totalPage, setTotalPage] = useState(1);
37+
const [modal, setModal] = useState<{
38+
isOpen: boolean;
39+
status: 'accepted' | 'rejected';
40+
dataIndex: number;
41+
}>({
42+
isOpen: false,
43+
status: 'accepted',
44+
dataIndex: 0,
45+
});
46+
47+
const closeModal = () =>
48+
setModal((prev) => {
49+
return { ...prev, isOpen: false };
50+
});
51+
52+
const clickButton = (dataIndex: number, status: 'accepted' | 'rejected') => {
53+
setModal({
54+
isOpen: true,
55+
status,
56+
dataIndex,
57+
});
58+
};
59+
60+
const handleModalClick = async () => {
61+
closeModal();
62+
if (mode === 'user') return;
63+
64+
setDatas((prev) => {
65+
prev[modal.dataIndex][3] = modal.status;
66+
return prev;
67+
});
68+
try {
69+
await putNoticeApplications(
70+
props.shopId,
71+
props.noticeId,
72+
datas[modal.dataIndex][4] ?? '',
73+
{
74+
status: modal.status,
75+
},
76+
);
77+
} catch {
78+
setDatas((prev) => {
79+
prev[modal.dataIndex][3] = 'pending';
80+
return prev;
81+
});
82+
}
83+
};
3584

3685
useEffect(() => {
3786
(async () => {
@@ -97,68 +146,77 @@ export default function Table(props: UserProps | NoticeProps) {
97146
}, [mode, page]);
98147

99148
return (
100-
<div
101-
className={`@container scrollbar-hide overflow-x-auto rounded-[10px] border border-gray-20 bg-white ${className}`}
102-
>
103-
<table className="w-full min-w-888 border-separate border-spacing-0 text-left md:min-w-946">
104-
<thead className="h-39 bg-red-10 text-caption/16 md:h-49 md:text-body2/22">
105-
<tr>
106-
<th className="w-227 border-b border-gray-20 px-7 font-regular md:px-11">
107-
{headers[0]}
108-
</th>
109-
<th className="w-300 border-b border-gray-20 px-8 font-regular md:px-12">
110-
{headers[1]}
111-
</th>
112-
<th className="w-200 border-b border-gray-20 px-8 font-regular md:px-12">
113-
{headers[2]}
114-
</th>
115-
<th className="sticky right-0 border-b border-l border-gray-20 bg-red-10 px-7 font-regular md:px-11 @min-[947px]:border-l-transparent">
116-
{headers[3]}
117-
</th>
118-
</tr>
119-
</thead>
120-
<tbody className="text-body2/22 font-regular md:text-body1/26">
121-
{datas.map((data, index) => (
122-
<tr key={index}>
123-
<td className="border-b border-gray-20 pt-12 pr-8 pb-11 pl-7 md:pt-20 md:pr-12 md:pb-19 md:pl-11">
124-
<div className="line-clamp-1 max-h-22 overflow-hidden md:line-clamp-2 md:max-h-51">
125-
{data[0]}
126-
</div>
127-
</td>
128-
<td className="border-b border-gray-20 px-8 pt-12 pb-11 md:px-12 md:pt-20 md:pb-19">
129-
<div className="line-clamp-1 max-h-22 overflow-hidden md:line-clamp-2 md:max-h-51">
130-
{data[1]}
131-
</div>
132-
</td>
133-
<td className="border-b border-gray-20 px-8 pt-12 pb-11 md:px-12 md:pt-20 md:pb-19">
134-
<div className="line-clamp-1 max-h-22 overflow-hidden md:line-clamp-2 md:max-h-51">
135-
{data[2]}
136-
</div>
137-
</td>
138-
<td className="sticky right-0 border-b border-l border-gray-20 bg-white px-7 pt-1 md:px-11 @min-[947px]:border-l-transparent">
139-
<div className="min-h-44 content-center md:min-h-67">
140-
{mode === 'notice' && data[3] === 'pending' ? (
141-
<TableButtons
142-
shopId={props.shopId}
143-
noticeId={props.noticeId}
144-
applicaitonId={data[4] ?? ''}
145-
/>
146-
) : (
147-
<TableStatus status={data[3] ?? ''} />
148-
)}
149-
</div>
150-
</td>
149+
<>
150+
<div
151+
className={`@container scrollbar-hide overflow-x-auto rounded-[10px] border border-gray-20 bg-white ${className}`}
152+
>
153+
<table className="w-full min-w-888 border-separate border-spacing-0 text-left md:min-w-946">
154+
<thead className="h-39 bg-red-10 text-caption/16 md:h-49 md:text-body2/22">
155+
<tr>
156+
<th className="w-227 border-b border-gray-20 px-7 font-regular md:px-11">
157+
{headers[0]}
158+
</th>
159+
<th className="w-300 border-b border-gray-20 px-8 font-regular md:px-12">
160+
{headers[1]}
161+
</th>
162+
<th className="w-200 border-b border-gray-20 px-8 font-regular md:px-12">
163+
{headers[2]}
164+
</th>
165+
<th className="sticky right-0 border-b border-l border-gray-20 bg-red-10 px-7 font-regular md:px-11 @min-[947px]:border-l-transparent">
166+
{headers[3]}
167+
</th>
151168
</tr>
152-
))}
153-
</tbody>
154-
</table>
155-
<div className="sticky right-0 bottom-0 left-0">
156-
<Pagination
157-
currentPage={page}
158-
setCurrentPage={setPage}
159-
totalPages={totalPage}
160-
/>
169+
</thead>
170+
<tbody className="text-body2/22 font-regular md:text-body1/26">
171+
{datas.map((data, index) => (
172+
<tr key={index}>
173+
<td className="border-b border-gray-20 pt-12 pr-8 pb-11 pl-7 md:pt-20 md:pr-12 md:pb-19 md:pl-11">
174+
<div className="line-clamp-1 max-h-22 overflow-hidden md:line-clamp-2 md:max-h-51">
175+
{data[0]}
176+
</div>
177+
</td>
178+
<td className="border-b border-gray-20 px-8 pt-12 pb-11 md:px-12 md:pt-20 md:pb-19">
179+
<div className="line-clamp-1 max-h-22 overflow-hidden md:line-clamp-2 md:max-h-51">
180+
{data[1]}
181+
</div>
182+
</td>
183+
<td className="border-b border-gray-20 px-8 pt-12 pb-11 md:px-12 md:pt-20 md:pb-19">
184+
<div className="line-clamp-1 max-h-22 overflow-hidden md:line-clamp-2 md:max-h-51">
185+
{data[2]}
186+
</div>
187+
</td>
188+
<td className="sticky right-0 border-b border-l border-gray-20 bg-white px-7 pt-1 md:px-11 @min-[947px]:border-l-transparent">
189+
<div className="min-h-44 content-center md:min-h-67">
190+
{mode === 'notice' && data[3] === 'pending' ? (
191+
<TableButtons index={index} click={clickButton} />
192+
) : (
193+
<TableStatus status={data[3] ?? ''} />
194+
)}
195+
</div>
196+
</td>
197+
</tr>
198+
))}
199+
</tbody>
200+
</table>
201+
<div className="sticky right-0 bottom-0 left-0">
202+
<Pagination
203+
currentPage={page}
204+
setCurrentPage={setPage}
205+
totalPages={totalPage}
206+
/>
207+
</div>
161208
</div>
162-
</div>
209+
{modal.isOpen && (
210+
<Modal
211+
option="action"
212+
yesButtonContent="예"
213+
onYesButtonClick={handleModalClick}
214+
onButtonClick={closeModal}
215+
onClose={closeModal}
216+
>
217+
신청을 {modal.status === 'accepted' ? '승인' : '거절'}하시겠어요?
218+
</Modal>
219+
)}
220+
</>
163221
);
164222
}
Lines changed: 29 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,14 @@
1-
import { useEffect, useState, type MouseEvent } from 'react';
1+
import { useEffect, useState } from 'react';
22
import Button from '../Button';
3-
import TableStatus from './TableStatus';
4-
import { putNoticeApplications } from '@/api/applicationApi';
5-
import Modal from '../Modal';
63

74
interface Props {
8-
shopId: string;
9-
noticeId: string;
10-
applicaitonId: string;
5+
index: number;
6+
click: (dataIndex: number, status: 'accepted' | 'rejected') => void;
117
}
128

13-
export default function TableButtons({
14-
shopId,
15-
noticeId,
16-
applicaitonId,
17-
}: Props) {
18-
const [status, setStatus] = useState<'pending' | 'accepted' | 'rejected'>(
19-
'pending',
20-
);
21-
const [modal, setModal] = useState<{
22-
isOpen: boolean;
23-
status: 'accepted' | 'rejected';
24-
}>({
25-
isOpen: false,
26-
status: 'accepted',
27-
});
9+
export default function TableButtons({ index, click }: Props) {
2810
const [isMobile, setIsMobile] = useState(window.innerWidth < 768);
2911

30-
const closeModal = () =>
31-
setModal((prev) => {
32-
return { ...prev, isOpen: false };
33-
});
34-
35-
const handleModalClick = async () => {
36-
closeModal();
37-
setStatus(modal.status);
38-
try {
39-
await putNoticeApplications(shopId, noticeId, applicaitonId, {
40-
status: modal.status,
41-
});
42-
} catch {
43-
setStatus('pending');
44-
}
45-
};
46-
47-
const handleClick = (e: MouseEvent<HTMLButtonElement>) => {
48-
setModal({
49-
isOpen: true,
50-
status: e.currentTarget.value as 'accepted' | 'rejected',
51-
});
52-
};
53-
5412
useEffect(() => {
5513
const handleResize = () => {
5614
setIsMobile(window.innerWidth < 768);
@@ -59,45 +17,30 @@ export default function TableButtons({
5917
return () => window.removeEventListener('resize', handleResize);
6018
}, []);
6119

62-
return status === 'pending' ? (
63-
<>
64-
<div className="flex gap-8 md:gap-12">
65-
<Button
66-
solid={false}
67-
size={isMobile ? 'small' : 'medium'}
68-
className="w-69 md:w-92"
69-
value="rejected"
70-
onClick={handleClick}
71-
>
72-
거절하기
73-
</Button>
74-
<Button
75-
solid={false}
76-
size={isMobile ? 'small' : 'medium'}
77-
className="w-69 md:w-92"
78-
style={{
79-
color: 'var(--color-blue-20)',
80-
borderColor: 'var(--color-blue-20)',
81-
}}
82-
value="accepted"
83-
onClick={handleClick}
84-
>
85-
승인하기
86-
</Button>
87-
</div>
88-
{modal.isOpen && (
89-
<Modal
90-
option="action"
91-
onButtonClick={closeModal}
92-
onYesButtonClick={handleModalClick}
93-
yesButtonContent="예"
94-
onClose={closeModal}
95-
>
96-
신청을 {modal.status === 'accepted' ? '승인' : '거절'}하시겠어요?
97-
</Modal>
98-
)}
99-
</>
100-
) : (
101-
<TableStatus status={status} />
20+
return (
21+
<div className="flex gap-8 md:gap-12">
22+
<Button
23+
solid={false}
24+
size={isMobile ? 'small' : 'medium'}
25+
className="w-69 md:w-92"
26+
value="rejected"
27+
onClick={() => click(index, 'rejected')}
28+
>
29+
거절하기
30+
</Button>
31+
<Button
32+
solid={false}
33+
size={isMobile ? 'small' : 'medium'}
34+
className="w-69 md:w-92"
35+
style={{
36+
color: 'var(--color-blue-20)',
37+
borderColor: 'var(--color-blue-20)',
38+
}}
39+
value="accepted"
40+
onClick={() => click(index, 'accepted')}
41+
>
42+
승인하기
43+
</Button>
44+
</div>
10245
);
10346
}

0 commit comments

Comments
 (0)