Skip to content

Commit 0e26c05

Browse files
authored
Merge pull request #193 from part3-4team-Taskify/minji
[Fix, Refactor] edit, mydashboard: 페이지 변경사항 즉시 반영 / edit_MemberList: 멤버 삭제 시 다른 멤버가 삭제되는 버그 fix
2 parents 130319c + fb31917 commit 0e26c05

File tree

9 files changed

+87
-52
lines changed

9 files changed

+87
-52
lines changed

src/components/modal/ChangeBebridge.tsx

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,14 @@ import { apiRoutes } from "@/api/apiRoutes";
77
import { toast } from "react-toastify";
88
import "react-toastify/dist/ReactToastify.css";
99

10-
const ChangeBebridge = () => {
10+
interface ChangeBebridgeProps {
11+
onUpdate?: () => void;
12+
}
13+
14+
const ChangeBebridge = ({ onUpdate }: ChangeBebridgeProps) => {
1115
const router = useRouter();
1216
const { dashboardId } = router.query;
13-
const [dashboardDetail, setdashboardDetail] = useState<{ title?: string }>(
17+
const [dashboardDetail, setDashboardDetail] = useState<{ title?: string }>(
1418
{}
1519
);
1620
const [title, setTitle] = useState("");
@@ -32,7 +36,7 @@ const ChangeBebridge = () => {
3236
);
3337
if (res.data) {
3438
const dashboardData = res.data;
35-
setdashboardDetail(dashboardData);
39+
setDashboardDetail(dashboardData);
3640
}
3741
} catch (error) {
3842
console.error("대시보드 상세내용 불러오는데 오류 발생:", error);
@@ -58,11 +62,14 @@ const ChangeBebridge = () => {
5862
apiRoutes.dashboardDetail(dashboardIdNumber),
5963
payload
6064
);
65+
setDashboardDetail((prev) => ({
66+
...prev,
67+
title: title,
68+
color: colors[selected],
69+
}));
6170

6271
toast.success("대시보드가 변경되었습니다!");
63-
setTimeout(() => {
64-
router.reload();
65-
}, 1500);
72+
if (onUpdate) onUpdate();
6673
} catch (error) {
6774
console.error("대시보드 변경 실패:", error);
6875
toast.error("대시보드 변경에 실패했습니다.");

src/components/modal/DeleteDashboardModal.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,6 @@ export default function DeleteDashboardModal({
2828
} catch (error) {
2929
console.error("대시보드 삭제 실패:", error);
3030
toast.error("대시보드 삭제에 실패하였습니다 .");
31-
32-
window.location.reload();
3331
}
3432
};
3533
return (

src/components/modal/DeleteMemberModal.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,26 @@ type DeleteMemberdProps = {
99
isOpen: boolean;
1010
onClose: () => void;
1111
id: number;
12+
memberDelete?: () => void;
1213
};
1314

1415
export default function DeleteDashboardModal({
1516
isOpen,
1617
onClose,
1718
id,
19+
memberDelete,
1820
}: DeleteMemberdProps) {
1921
/* 멤버삭제 */
2022
const handleDelete = async (id: number) => {
2123
try {
2224
await axiosInstance.delete(apiRoutes.memberDetail(id));
23-
window.location.reload();
25+
if (memberDelete) memberDelete();
26+
toast.success("멤버가 삭제되었습니다.");
2427
} catch (error) {
25-
toast.error("구성원 삭제에 실패했습니다.");
26-
console.error("구성원 삭제 실패:", error);
28+
toast.error("멤버 삭제에 실패했습니다.");
29+
console.error("멤버 삭제 실패:", error);
30+
} finally {
31+
onClose();
2732
}
2833
};
2934

src/components/table/InviteRecords.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ const InviteRecords = ({ dashboardId }: { dashboardId: string }) => {
3030
if (res.data && Array.isArray(res.data.invitations)) {
3131
// 이메일 리스트를 객체 배열로 저장
3232
const inviteData = res.data.invitations.map(
33-
(item: { id: number; invitee: { email: string } }) => ({
33+
(item: { id: number; invite: { email: string } }) => ({
3434
id: item.id,
35-
email: item.invitee.email,
35+
email: item.invite.email,
3636
})
3737
);
3838
setInviteList(inviteData);
@@ -55,12 +55,13 @@ const InviteRecords = ({ dashboardId }: { dashboardId: string }) => {
5555
await axiosInstance.delete(
5656
apiRoutes.dashboardInviteDelete(dashboardIdNumber, id)
5757
);
58-
window.location.reload();
58+
setInviteList((prev) => prev.filter((invite) => invite.id !== id));
59+
toast.success("초대가 취소되었습니다.");
5960
} catch (error) {
6061
console.error("초대 취소 실패:", error);
6162
if (error instanceof AxiosError) {
6263
if (error.response?.status === 403) {
63-
toast.error("초대 취소 권한이 없습니다.");
64+
toast.error("초대 취소에 실패했습니다.");
6465
return;
6566
} else if (error.response?.status === 404) {
6667
toast.error("대시보드가 존재하지 않습니다.");

src/components/table/invited/InvitedDashBoard.tsx

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,23 @@ import { Search } from "lucide-react";
1010

1111
const ITEMS_PER_PAGE = 6; // 한 번에 보여줄 개수
1212

13+
interface InvitedProps {
14+
searchTitle: string;
15+
invitationData: Invite[];
16+
fetchNextPage: () => void;
17+
hasMore: boolean;
18+
agreeInvitation?: () => void;
19+
onDecision?: (inviteId: number) => void;
20+
}
21+
1322
function InvitedList({
1423
searchTitle,
1524
invitationData: invitationData,
1625
fetchNextPage,
1726
hasMore,
18-
}: {
19-
searchTitle: string;
20-
invitationData: Invite[];
21-
fetchNextPage: () => void;
22-
hasMore: boolean;
23-
}) {
27+
agreeInvitation,
28+
onDecision,
29+
}: InvitedProps) {
2430
const observerRef = useRef<HTMLDivElement | null>(null);
2531

2632
/* IntersectionObserver 설정 */
@@ -62,10 +68,9 @@ function InvitedList({
6268
};
6369
try {
6470
await axiosInstance.put(apiRoutes.invitationDetail(inviteId), payload);
65-
toast.success("대시보드 수락 성공");
66-
setTimeout(() => {
67-
window.location.reload();
68-
}, 1500);
71+
if (agreeInvitation) agreeInvitation();
72+
if (onDecision) onDecision(inviteId);
73+
toast.success("초대가 수락되었습니다.");
6974
} catch (error) {
7075
console.error("수락 실패:", error);
7176
toast.error("초대 수락에 실패했습니다");
@@ -80,10 +85,8 @@ function InvitedList({
8085
};
8186
try {
8287
await axiosInstance.put(apiRoutes.invitationDetail(inviteId), payload);
83-
toast.success("대시보드 거절 성공");
84-
setTimeout(() => {
85-
window.location.reload();
86-
}, 1500);
88+
if (onDecision) onDecision(inviteId);
89+
toast.success("초대가 거절되었습니다.");
8790
} catch (error) {
8891
console.error("거절 실패:", error);
8992
toast.error("초대 거절에 실패했습니다");
@@ -187,8 +190,13 @@ function InvitedList({
187190
}
188191

189192
type CursorId = number;
193+
type InvitedDashBoardProps = {
194+
agreeInvitation?: () => void;
195+
};
190196

191-
export default function InvitedDashBoard() {
197+
export default function InvitedDashBoard({
198+
agreeInvitation,
199+
}: InvitedDashBoardProps) {
192200
const { user } = useUserStore();
193201
const [searchTitle, setSearchTitle] = useState("");
194202
const [invitationData, setInvitationData] = useState<Map<CursorId, Invite[]>>(
@@ -270,6 +278,19 @@ export default function InvitedDashBoard() {
270278

271279
const invitationArray = Array.from(invitationData.values()).flat();
272280

281+
const removeInvitation = (inviteId: number) => {
282+
setInvitationData((prev) => {
283+
const newMap = new Map();
284+
for (const [key, list] of prev) {
285+
newMap.set(
286+
key,
287+
list.filter((invite) => invite.id !== inviteId)
288+
);
289+
}
290+
return newMap;
291+
});
292+
};
293+
273294
return (
274295
<div>
275296
{invitationArray.length === 0 ? (
@@ -303,6 +324,8 @@ export default function InvitedDashBoard() {
303324
invitationData={invitationArray}
304325
fetchNextPage={fetchNextPage}
305326
hasMore={hasMore}
327+
agreeInvitation={agreeInvitation}
328+
onDecision={removeInvitation}
306329
/>
307330
</div>
308331
</div>

src/components/table/member/MemberList.tsx

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ interface HeaderBebridgeProps {
1212

1313
const MemberList: React.FC<HeaderBebridgeProps> = ({ dashboardId }) => {
1414
const [members, setMembers] = useState<MemberType[]>([]);
15+
const [selectedMemberId, setSelectedMemberId] = useState<number | null>(null);
1516
const [isModalOpen, setIsModalOpen] = useState(false);
1617

1718
/* 페이지네이션 */
@@ -24,7 +25,7 @@ const MemberList: React.FC<HeaderBebridgeProps> = ({ dashboardId }) => {
2425
currentPage * itemsPerPage
2526
);
2627

27-
/* 구성원 삭제 모달 */
28+
/* 멤버 삭제 모달 */
2829
const openModal = () => {
2930
setIsModalOpen(true);
3031
};
@@ -43,21 +44,20 @@ const MemberList: React.FC<HeaderBebridgeProps> = ({ dashboardId }) => {
4344
};
4445

4546
/*멤버 목록 api 호출*/
46-
useEffect(() => {
47-
const fetchMembers = async () => {
48-
try {
49-
if (dashboardId) {
50-
const members = await getMembers({
51-
dashboardId: Number(dashboardId),
52-
});
53-
setMembers(members);
54-
console.log("member_list", members);
55-
}
56-
} catch (error) {
57-
console.error("멤버 불러오기 실패:", error);
47+
const fetchMembers = async () => {
48+
try {
49+
if (dashboardId) {
50+
const members = await getMembers({
51+
dashboardId: Number(dashboardId),
52+
});
53+
setMembers(members);
5854
}
59-
};
55+
} catch (error) {
56+
console.error("멤버 불러오기 실패:", error);
57+
}
58+
};
6059

60+
useEffect(() => {
6161
fetchMembers();
6262
}, [dashboardId]);
6363

@@ -111,17 +111,21 @@ const MemberList: React.FC<HeaderBebridgeProps> = ({ dashboardId }) => {
111111
{!member.isOwner && (
112112
<>
113113
<button
114-
onClick={openModal}
114+
onClick={() => {
115+
setSelectedMemberId(member.id);
116+
setIsModalOpen(true);
117+
}}
115118
className="text-12m cursor-pointer sm:font-sm h-[32px] sm:h-[32px] w-[52px] sm:w-[84px] md:w-[84px] border border-[var(--color-gray3)] text-[var(--primary)] px-2 py-1 rounded-md hover:bg-gray-100"
116119
>
117120
삭제
118121
</button>
119122

120-
{isModalOpen && (
123+
{isModalOpen && selectedMemberId !== null && (
121124
<DelteMemberModal
122125
isOpen={isModalOpen}
123126
onClose={closeModal}
124-
id={member.id}
127+
id={selectedMemberId}
128+
memberDelete={fetchMembers}
125129
/>
126130
)}
127131
</>

src/pages/dashboard/[dashboardId]/edit.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ export default function EditDashboard() {
7272
</div>
7373
{/* 백버튼 아래 전체 아이템 컨테이너 */}
7474
<div className="flex flex-col items-center lg:items-start px-6 mt-6 gap-6">
75-
<ChangeBebridge />
75+
<ChangeBebridge onUpdate={fetchDashboards} />
7676
{/* MemberList는 아래쪽에 배치 */}
7777
<MemberList dashboardId={dashboardId} />
7878
<InviteRecords dashboardId={dashboardIdString || ""} />{" "}

src/pages/mydashboard.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ export default function MyDashboardPage() {
231231
)}
232232

233233
<div className="mt-[25px]">
234-
<InvitedDashBoard />
234+
<InvitedDashBoard agreeInvitation={fetchDashboards} />
235235
</div>
236236
</section>
237237
</main>

src/pages/mypage.tsx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,17 @@
11
import React, { useState, useEffect } from "react";
22
import { useAuthGuard } from "@/hooks/useAuthGuard";
3-
import useUserStore from "@/store/useUserStore";
43
import HeaderMyPage from "@/components/gnb/HeaderDashboard";
54
import SideMenu from "@/components/sideMenu/SideMenu";
65
import { ProfileCard } from "@/components/card/Profile";
76
import ChangePassword from "@/components/card/ChangePassword";
87
import BackButton from "@/components/button/BackButton";
98
import { Dashboard, getDashboards } from "@/api/dashboards";
10-
import { getUserInfo } from "@/api/users";
119
import { TEAM_ID } from "@/constants/team";
1210
import LoadingSpinner from "@/components/common/LoadingSpinner";
1311
import { toast } from "react-toastify";
1412

1513
export default function MyPage() {
1614
const { user, isInitialized } = useAuthGuard();
17-
const { setUser } = useUserStore();
1815
const [dashboards, setDashboards] = useState<Dashboard[]>([]);
1916

2017
// 사이드메뉴 대시보드 목록 api 호출

0 commit comments

Comments
 (0)