Skip to content

Commit 88a5afd

Browse files
authored
Merge pull request #169 from codeit-sprint-part3-6team/#59_페이지_대시보드_수정
2 parents 148ebcb + 5f3883c commit 88a5afd

File tree

9 files changed

+385
-27
lines changed

9 files changed

+385
-27
lines changed

src/components/product/edit/InviteTitle/InviteList.module.css

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,50 @@
1818
border-top: 1px solid var(--gray-bright);
1919
}
2020

21+
.modal-container {
22+
position: fixed;
23+
top: 0;
24+
left: 0;
25+
width: 100vw;
26+
height: 100vh;
27+
background: rgba(0, 0, 0, 0.5);
28+
display: flex;
29+
justify-content: center;
30+
align-items: center;
31+
z-index: 1000;
32+
}
33+
34+
.modal-section {
35+
background: var(--gray-bright);
36+
padding: 20px;
37+
border-radius: 8px;
38+
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
39+
text-align: center;
40+
}
41+
42+
.modal-button {
43+
margin-top: 20px;
44+
display: flex;
45+
justify-content: space-around;
46+
}
47+
48+
.cancel-button {
49+
background: var(--gray-medium);
50+
border: none;
51+
padding: 10px 20px;
52+
border-radius: 4px;
53+
cursor: pointer;
54+
}
55+
56+
.confirm-button {
57+
background: var(--violet);
58+
color: var(--white);
59+
border: none;
60+
padding: 10px 20px;
61+
border-radius: 4px;
62+
cursor: pointer;
63+
}
64+
2165
@media screen and (max-width: 743px) {
2266
.container {
2367
padding-left: 20px;
Lines changed: 56 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,38 @@
1+
import { useState } from 'react';
12
import CDSButton from '@/components/common/button/CDSButton';
23
import { Invitaion } from '@/type/dashboard';
34
import deleteInvitation from '@/lib/editdashboard/deleteDashboardsInvitations';
45
import { useRouter } from 'next/router';
56
import styles from './InviteList.module.css';
67

8+
function ConfirmModal({
9+
isOpen,
10+
onClose,
11+
onConfirm,
12+
}: {
13+
isOpen: boolean;
14+
onClose: () => void;
15+
onConfirm: () => void;
16+
}) {
17+
if (!isOpen) return null;
18+
19+
return (
20+
<div className={styles['modal-container']}>
21+
<div className={styles['modal-section']}>
22+
<h3>정말 초대를 취소하시겠습니까?</h3>
23+
<div className={styles['modal-button']}>
24+
<button onClick={onClose} className={styles['cancel-button']}>
25+
취소
26+
</button>
27+
<button onClick={onConfirm} className={styles['confirm-button']}>
28+
확인
29+
</button>
30+
</div>
31+
</div>
32+
</div>
33+
);
34+
}
35+
736
interface InviteListProps {
837
members: Invitaion[];
938
setMembers: React.Dispatch<React.SetStateAction<Invitaion[]>>;
@@ -12,34 +41,54 @@ interface InviteListProps {
1241
export default function InviteList({ members, setMembers }: InviteListProps) {
1342
const router = useRouter();
1443
const dashboardId = Number(router.query.id);
44+
const [isModalOpen, setIsModalOpen] = useState(false);
45+
const [selectedInvitationId, setSelectedInvitationId] = useState<
46+
number | null
47+
>(null);
48+
49+
const handleDeleteClick = async () => {
50+
if (selectedInvitationId === null) return;
1551

16-
const handleDeleteClick = async (invitationId: number) => {
1752
try {
18-
await deleteInvitation(dashboardId, invitationId);
53+
await deleteInvitation(dashboardId, selectedInvitationId);
1954
setMembers((prevMembers) =>
20-
prevMembers.filter((member) => member.id !== invitationId),
55+
prevMembers.filter((member) => member.id !== selectedInvitationId),
2156
);
2257
} catch (error) {
2358
throw new Error(`${error}`);
59+
} finally {
60+
closeModal();
2461
}
2562
};
2663

64+
const openModal = (invitationId: number) => {
65+
setSelectedInvitationId(invitationId);
66+
setIsModalOpen(true);
67+
};
68+
69+
const closeModal = () => {
70+
setIsModalOpen(false);
71+
setSelectedInvitationId(null);
72+
};
73+
2774
return (
2875
<div>
2976
{members?.map((member, index) => (
3077
<div key={member.id}>
3178
<div className={styles.container}>
3279
<h1 className={styles.title}>{member.invitee.email}</h1>
33-
<CDSButton
34-
btnType="delete"
35-
onClick={() => handleDeleteClick(member.id)}
36-
>
80+
<CDSButton btnType="delete" onClick={() => openModal(member.id)}>
3781
취소
3882
</CDSButton>
3983
</div>
4084
{index < members.length - 1 && <hr className={styles.line} />}
4185
</div>
4286
))}
87+
<ConfirmModal
88+
isOpen={isModalOpen}
89+
onClose={closeModal}
90+
onConfirm={handleDeleteClick}
91+
/>
4392
</div>
4493
);
4594
}

src/components/product/edit/InviteTitle/InviteTitle.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ export default function InviteTitle() {
5353
fetchInvitations();
5454
}, [router.query.id, currentPage, isModalOpen]);
5555

56-
// 초대 요청을 보내고 alert
5756
useEffect(() => {
5857
if (!isModalOpen && alertMessage) {
5958
toast.success(alertMessage);
@@ -126,7 +125,7 @@ export default function InviteTitle() {
126125
<div className={styles['name-section']}>
127126
<h2 className={styles['sub-title']}>이메일</h2>
128127
<div className={styles['list']}>
129-
<InviteList members={members} setMembers={setMembers} />
128+
<InviteList members={members} setMembers={setMembers} />
130129
</div>
131130
</div>
132131
<InviteModal

src/components/product/edit/MainTitle/MainTitle.module.css

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,50 @@
4040
max-width: 100%;
4141
}
4242

43+
.modal-container {
44+
position: fixed;
45+
top: 0;
46+
left: 0;
47+
width: 100vw;
48+
height: 100vh;
49+
background: rgba(0, 0, 0, 0.5);
50+
display: flex;
51+
justify-content: center;
52+
align-items: center;
53+
z-index: 1000;
54+
}
55+
56+
.modal-section {
57+
background: white;
58+
padding: 20px;
59+
border-radius: 8px;
60+
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
61+
text-align: center;
62+
}
63+
64+
.modal-button {
65+
margin-top: 20px;
66+
display: flex;
67+
justify-content: space-around;
68+
}
69+
70+
.cancel-button {
71+
background: var(--gray-medium);
72+
border: none;
73+
padding: 10px 20px;
74+
border-radius: 4px;
75+
cursor: pointer;
76+
}
77+
78+
.confirm-button {
79+
background: var(--violet);
80+
color: var(--white);
81+
border: none;
82+
padding: 10px 20px;
83+
border-radius: 4px;
84+
cursor: pointer;
85+
}
86+
4387
@media screen and (max-width: 1199px) {
4488
.title-container {
4589
width: 544px;

src/components/product/edit/MainTitle/MainTitle.tsx

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useEffect, useState } from 'react';
1+
import { useState } from 'react';
22
import { useRouter } from 'next/router';
33
import CDSButton from '@/components/common/button/CDSButton';
44
import TitleTagInput from '@/components/common/input/info-input/TitleTagInput';
@@ -8,6 +8,36 @@ import styles from './MainTitle.module.css';
88
import { toast } from 'react-toastify';
99
import useSidebarDashboards from '@/hooks/useSidebar';
1010

11+
function EditConfirmModal({
12+
isOpen,
13+
onClose,
14+
onConfirm,
15+
}: {
16+
isOpen: boolean;
17+
onClose: () => void;
18+
onConfirm: () => void;
19+
}) {
20+
if (!isOpen) {
21+
return null;
22+
}
23+
24+
return (
25+
<div className={styles['modal-container']}>
26+
<div className={styles['modal-section']}>
27+
<h3>제목 또는 색상을 변경하시겠습니까?</h3>
28+
<div className={styles['modal-button']}>
29+
<button onClick={onClose} className={styles['cancel-button']}>
30+
취소
31+
</button>
32+
<button onClick={onConfirm} className={styles['confirm-button']}>
33+
확인
34+
</button>
35+
</div>
36+
</div>
37+
</div>
38+
);
39+
}
40+
1141
interface MainTitleProps {
1242
dashboardtitle: string | null;
1343
dashboardColor: string | null;
@@ -20,31 +50,40 @@ export default function MainTitle({
2050
const [selectedColor, setSelectedColor] = useState<string>(dashboardColor);
2151
const [title, setTitle] = useState(dashboardtitle || '');
2252
const [newTitle, setNewTitle] = useState(dashboardtitle || '');
53+
const [isModalOpen, setIsModalOpen] = useState(false);
2354
const router = useRouter();
2455
const dashboardId = Number(router.query.id);
25-
2656
const { fetchSidebarDashboards } = useSidebarDashboards();
2757

2858
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
2959
setTitle(e.target.value);
3060
};
3161

32-
const handleEditClick = async () => {
62+
const handleEditClick = () => {
63+
setIsModalOpen(true);
64+
};
65+
66+
const closeModal = () => {
67+
setIsModalOpen(false);
68+
};
69+
70+
const confirmEdit = async () => {
3371
try {
3472
const updatedDashboard = await putDashboards({
3573
title,
3674
color: selectedColor,
3775
dashboardId,
3876
});
39-
4077
setNewTitle(updatedDashboard.title);
4178
setTitle(updatedDashboard.title);
4279
setSelectedColor(updatedDashboard.color);
43-
4480
toast.success('변경 사항이 저장되었습니다.');
4581
fetchSidebarDashboards(1);
4682
} catch (error) {
83+
toast.error('변경에 실패했습니다.');
4784
throw new Error(`${error}`);
85+
} finally {
86+
closeModal();
4887
}
4988
};
5089

@@ -78,6 +117,11 @@ export default function MainTitle({
78117
</CDSButton>
79118
</div>
80119
</div>
120+
<EditConfirmModal
121+
isOpen={isModalOpen}
122+
onClose={closeModal}
123+
onConfirm={confirmEdit}
124+
/>
81125
</div>
82126
);
83127
}

src/components/product/edit/MemberTitle/MemberList.module.css

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,50 @@
1818
border-top: 1px solid var(--gray-bright);
1919
}
2020

21+
.modal-container {
22+
position: fixed;
23+
top: 0;
24+
left: 0;
25+
width: 100vw;
26+
height: 100vh;
27+
background: rgba(0, 0, 0, 0.5);
28+
display: flex;
29+
justify-content: center;
30+
align-items: center;
31+
z-index: 1000;
32+
}
33+
34+
.modal-section {
35+
background: var(--gray-bright);
36+
padding: 20px;
37+
border-radius: 8px;
38+
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
39+
text-align: center;
40+
}
41+
42+
.modal-button {
43+
margin-top: 20px;
44+
display: flex;
45+
justify-content: space-around;
46+
}
47+
48+
.cancel-button {
49+
background: var(--gray-medium);
50+
border: none;
51+
padding: 10px 20px;
52+
border-radius: 4px;
53+
cursor: pointer;
54+
}
55+
56+
.confirm-button {
57+
background: var(--violet);
58+
color: var(--white);
59+
border: none;
60+
padding: 10px 20px;
61+
border-radius: 4px;
62+
cursor: pointer;
63+
}
64+
2165
@media screen and (max-width: 743px) {
2266
.container {
2367
margin-bottom: 12px;

0 commit comments

Comments
 (0)