Skip to content

Commit 9a0308e

Browse files
authored
Merge pull request #154 from gyoyeon-kim/card-table
[Fix] Page: edit 디자인 기능 수정 / axios 에러 핸들링
2 parents 7e4d3b2 + 2dbdfba commit 9a0308e

File tree

11 files changed

+132
-63
lines changed

11 files changed

+132
-63
lines changed

src/components/columnCard/Column.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ import Image from "next/image";
44
import { CardType } from "@/types/task";
55
import TodoModal from "@/components/modalInput/ToDoModal";
66
import TodoButton from "@/components/button/TodoButton";
7-
import ColumnManageModal from "@/components/columnCard/ColumnManageModal";
8-
import ColumnDeleteModal from "@/components/columnCard/ColumnDeleteModal";
7+
import ColumnManageModal from "@/components/columncard/ColumnManageModal";
8+
import ColumnDeleteModal from "@/components/columncard/ColumnDeleteModal";
99
import { updateColumn, deleteColumn } from "@/api/columns";
1010
import { getDashboardMembers, getCardDetail } from "@/api/card";
1111
import { MemberType } from "@/types/users";

src/components/modal/ChangeBebridge.tsx

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import "react-toastify/dist/ReactToastify.css";
99

1010
const ChangeBebridge = () => {
1111
const router = useRouter();
12-
const { dashboardId } = router.query; // dashboardId 쿼리값 받기
12+
const { dashboardId } = router.query;
1313
const [dashboardDetail, setdashboardDetail] = useState<{ title?: string }>(
1414
{}
1515
);
@@ -33,7 +33,6 @@ const ChangeBebridge = () => {
3333
if (res.data) {
3434
const dashboardData = res.data;
3535
setdashboardDetail(dashboardData);
36-
console.log("dashboardData", dashboardData);
3736
}
3837
} catch (error) {
3938
console.error("대시보드 상세내용 불러오는데 오류 발생:", error);
@@ -46,7 +45,7 @@ const ChangeBebridge = () => {
4645

4746
/* 대시보드 이름 변경 버튼 */
4847
const handleUpdate = async () => {
49-
const dashboardIdNumber = Number(dashboardId); // string dashboradId 값 number로 변경
48+
const dashboardIdNumber = Number(dashboardId);
5049
if (!dashboardId || selected === null) return;
5150

5251
const payload = {
@@ -55,32 +54,31 @@ const ChangeBebridge = () => {
5554
};
5655

5756
try {
58-
const response = await axiosInstance.put(
57+
await axiosInstance.put(
5958
apiRoutes.dashboardDetail(dashboardIdNumber),
6059
payload
6160
);
62-
console.log("업데이트 성공:", response.data);
61+
6362
toast.success("대시보드가 업데이트되었습니다!");
6463
setTimeout(() => {
6564
window.location.reload();
6665
}, 100);
6766
} catch (error) {
68-
console.error("업데이트 실패:", error);
6967
toast.error("업데이트에 실패했습니다.");
7068
}
7169
};
7270

7371
return (
74-
<div className="sm:w-[620px] sm:h-[344px] w-[327px] h-[312px] bg-white sm:rounded-[16px] rounded-[8px] p-[24px] flex flex-col">
72+
<div className="lg:w-[620px] lg:h-[344px] sm:w-[544px] sm:h-[344px] w-[284px] h-[312px] bg-white sm:rounded-[16px] rounded-[8px] p-[24px] flex flex-col">
7573
<ToastContainer position="top-center" />
76-
<h2 className="text-sm sm:text-[24px] font-bold">
74+
<h2 className="text-[20px] sm:text-[24px] font-bold">
7775
{dashboardDetail.title}
7876
</h2>
7977
<Input
8078
type="text"
8179
onChange={setTitle}
8280
label="대시보드 이름"
83-
labelClassName="text-lg sm:text-base text-black3 mt-6"
81+
labelClassName="text-[16px] sm:text-[18px] text-black3 mt-6"
8482
placeholder="뉴프로젝트"
8583
className="max-w-[620px] mb-1"
8684
/>
@@ -108,9 +106,9 @@ const ChangeBebridge = () => {
108106
</div>
109107
<div className="mt-8 flex">
110108
<button
111-
onClick={handleUpdate} // 버튼 클릭 시 handleUpdate 함수 호출
109+
onClick={handleUpdate}
112110
disabled={selected === null} // color가 없으면 버튼 비활성화
113-
className={`cursor-pointer sm:w-[564px] sm:h-[54px] w-[252px] h-[54px] rounded-[8px] border border-[var(--color-gray3)] bg-[var(--primary)] text-[var(--color-white)] ${selected === null ? "bg-gray-300 cursor-not-allowed" : "bg-[var(--primary)]"}`}
111+
className={`cursor-pointer sm:w-[572px] sm:h-[54px] w-[252px] h-[54px] rounded-[8px] border border-[var(--color-gray3)] bg-[var(--primary)] text-[var(--color-white)] ${selected === null ? "bg-gray-300 cursor-not-allowed" : "bg-[var(--primary)]"}`}
114112
>
115113
변경
116114
</button>

src/components/modal/DeleteDashboardModal.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { CustomBtn } from "../button/CustomButton";
33
import { useRouter } from "next/router";
44
import axiosInstance from "@/api/axiosInstance";
55
import { apiRoutes } from "@/api/apiRoutes";
6+
import { toast } from "react-toastify";
67

78
type DeleteDashboardProps = {
89
isOpen: boolean;
@@ -25,8 +26,7 @@ export default function DeleteDashboardModal({
2526
await axiosInstance.delete(apiRoutes.dashboardDetail(dashboardIdNumber));
2627
router.push(`/mydashboard`);
2728
} catch (error) {
28-
alert("대시보드 삭제에 실패하였습니다 .");
29-
console.error("초대 실패:", error);
29+
toast.error("대시보드 삭제에 실패하였습니다 .");
3030

3131
window.location.reload();
3232
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { Modal } from "./Modal";
2+
import { CustomBtn } from "../button/CustomButton";
3+
import axiosInstance from "@/api/axiosInstance";
4+
import { apiRoutes } from "@/api/apiRoutes";
5+
import { toast } from "react-toastify";
6+
import "react-toastify/dist/ReactToastify.css";
7+
8+
type DeleteMemberdProps = {
9+
isOpen: boolean;
10+
onClose: () => void;
11+
id: number;
12+
};
13+
14+
export default function DeleteDashboardModal({
15+
isOpen,
16+
onClose,
17+
id,
18+
}: DeleteMemberdProps) {
19+
/* 멤버삭제 */
20+
const handleDelete = async (id: number) => {
21+
try {
22+
await axiosInstance.delete(apiRoutes.memberDetail(id));
23+
window.location.reload();
24+
} catch (error) {
25+
toast.error("구성원 삭제에 실패하였습니다.");
26+
console.error("구성원 삭제 실패:", error);
27+
}
28+
};
29+
30+
return (
31+
<Modal
32+
isOpen={isOpen}
33+
onClose={onClose}
34+
width="w-[327px] sm:w-[568px]"
35+
height="h-[160px] sm:h-[174px]"
36+
backgroundClassName="bg-black/30 z-50"
37+
>
38+
<div className="flex flex-col sm:gap-10 gap-6 text-center ">
39+
<p className="text-xl mt-1.5">멤버를 삭제하시겠습니까?</p>
40+
<div className="flex justify-between gap-3">
41+
<CustomBtn variant="outlineDisabled" onClick={onClose}>
42+
취소
43+
</CustomBtn>
44+
<CustomBtn variant="primary" onClick={() => handleDelete(id)}>
45+
삭제
46+
</CustomBtn>
47+
</div>
48+
</div>
49+
</Modal>
50+
);
51+
}

src/components/modal/InviteDashboard.tsx

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ export default function InviteDashboard({ onClose }: { onClose?: () => void }) {
4040
})
4141
);
4242
setInviteList(inviteData);
43-
console.log("inviteData", inviteData);
4443
}
4544
} catch (error) {
4645
console.error("초대내역 불러오는데 오류 발생:", error);
@@ -66,30 +65,30 @@ export default function InviteDashboard({ onClose }: { onClose?: () => void }) {
6665
await axiosInstance.post(apiRoutes.dashboardInvite(dashboardIdNumber), {
6766
email,
6867
});
69-
onClose?.(); // 함수 있을때만 실행
70-
window.location.reload();
71-
} catch (error) {
72-
console.error("초대 실패:", error);
7368

69+
toast.success("초대를 성공했습니다.");
70+
71+
setTimeout(() => {
72+
window.location.reload();
73+
}, 1000);
74+
} catch (error) {
7475
if (error instanceof AxiosError) {
7576
if (error.response?.status === 403) {
7677
toast.error("초대 권한이 없습니다.");
78+
return;
7779
} else if (error.response?.status === 404) {
7880
toast.error("대시보드 또는 유저가 존재하지 않습니다.");
81+
return;
7982
} else if (error.response?.status === 409) {
8083
toast.error("이미 대시보드에 초대된 멤버입니다.");
84+
return;
8185
} else {
8286
toast.error("오류가 발생했습니다.");
87+
return;
8388
}
84-
85-
/** Next.js가 감지하기 전에 강제 새로고침 실행
86-
* @fixme 추후 더 좋은 방법 있으면 변경
87-
* setTimeout(() => {
88-
* window.location.reload();
89-
* }, 50);
90-
*/
9189
} else {
9290
toast.error("네트워크 오류가 발생했습니다.");
91+
return;
9392
}
9493
}
9594
};

src/components/modal/Modal.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ interface ModalProps {
2121
buttonContainerClassName?: string;
2222
width?: string;
2323
height?: string;
24+
backgroundClassName?: string; // 배경색 커스터마이징을 위한 클래스 추가
25+
backgroundStyle?: React.CSSProperties; // 배경 스타일을 직접 지정할 수 있는 스타일 추가
2426
}
2527

2628
export function Modal({
@@ -34,12 +36,15 @@ export function Modal({
3436
buttonContainerClassName = "",
3537
width = "w-[568px]", // 기본 너비 설정, 필요 시 변경 가능
3638
height = "h-[266px]", // 기본 높이 설정, 필요 시 변경 가능
39+
backgroundClassName = "bg-black/35",
40+
backgroundStyle = {},
3741
}: ModalProps) {
3842
if (!isOpen) return null;
3943

4044
return createPortal(
4145
<div
42-
className="fixed inset-0 flex items-center justify-center bg-black/35 z-50"
46+
className={`fixed inset-0 flex items-center justify-center ${backgroundClassName} z-50`}
47+
style={backgroundStyle} // 배경 스타일 적용
4348
onClick={onClose}
4449
>
4550
<div

src/components/table/InviteRecords.tsx

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ const InviteRecords = ({ dashboardId }: { dashboardId: string }) => {
3737
})
3838
);
3939
setInviteList(inviteData);
40-
console.log("inviteData", inviteData);
4140
}
4241
} catch (error) {
4342
console.error("초대내역 불러오는데 오류 발생:", error);
@@ -63,13 +62,17 @@ const InviteRecords = ({ dashboardId }: { dashboardId: string }) => {
6362
if (error instanceof AxiosError) {
6463
if (error.response?.status === 403) {
6564
toast.error("대시보드 초대 취소 권한이 없습니다.");
65+
return;
6666
} else if (error.response?.status === 404) {
6767
toast.error("대시보드가 존재하지 않습니다.");
68+
return;
6869
} else {
6970
toast.error("오류가 발생했습니다.");
71+
return;
7072
}
7173
} else {
7274
toast.error("네트워크 오류가 발생했습니다.");
75+
return;
7376
}
7477
}
7578
};
@@ -98,11 +101,13 @@ const InviteRecords = ({ dashboardId }: { dashboardId: string }) => {
98101
};
99102

100103
return (
101-
<div className="relative bg-white p-4 rounded-lg lg:w-[620px] lg:h-[477px] md:w-[544px] md:h-[477px] sm:w-[284px] h-[406px] ">
104+
<div className="relative bg-white p-4 rounded-lg lg:w-[620px] lg:h-[477px] w-[284px] h-[406px] sm:w-[544px] sm:h-[477px]">
102105
<ToastContainer position="top-center" autoClose={2000} />
103106
<div className="flex justify-between items-start sm:items-center">
104107
{/* 제목 */}
105-
<p className="sm:text-2xl text-xl font-bold">초대 내역</p>
108+
<p className="md:text-[24px] text-[20px] text-xl font-bold">
109+
초대 내역
110+
</p>
106111

107112
{/* 페이지네이션 + 초대하기 버튼 컨테이너 */}
108113
<div className="flex flex-col sm:flex-row items-end sm:items-center gap-2">
@@ -117,7 +122,7 @@ const InviteRecords = ({ dashboardId }: { dashboardId: string }) => {
117122
{/* 초대하기 버튼 (모바일에서 페이지네이션 아래로 이동) */}
118123
<button
119124
onClick={() => setIsModalOpen(true)}
120-
className="cursor-pointer sm:text-[14px] text-[12px] sm:w-[105px] w-[86px] sm:h-[32px] h-[26px] rounded-[4px] bg-[#5534DA] text-white flex items-center justify-center gap-2"
125+
className="cursor-pointer sm:text-[14px] text-[12px] sm:w-[105px] w-[86px] sm:h-[32px] h-[26px] rounded-[4px] bg-[#5534DA] text-white flex items-center justify-center gap-2 lg:mr-3 "
121126
>
122127
<img src="/svgs/add_white_box.svg" alt="icon" className="w-4 h-4" />
123128
초대하기
@@ -129,12 +134,12 @@ const InviteRecords = ({ dashboardId }: { dashboardId: string }) => {
129134
</div>
130135

131136
{/* 구성원 리스트 */}
132-
<p className="sm:text-base text-sm text-gray-500 mt-6 ml-4">이메일</p>
137+
<p className="sm:text-base text-sm text-gray-500 mt-6">이메일</p>
133138
<ul>
134139
{paginatedInvitation.map((invite, index) => (
135140
<li
136141
key={index}
137-
className={`flex items-center justify-between p-4 ${
142+
className={`flex items-center justify-between mt-3 pb-4 ${
138143
index !== paginatedInvitation.length - 1
139144
? "border-b border-gray-200"
140145
: ""
@@ -146,7 +151,7 @@ const InviteRecords = ({ dashboardId }: { dashboardId: string }) => {
146151
</div>
147152
<button
148153
onClick={() => handleCancel(invite.id)}
149-
className="cursor-pointer font-medium sm:text-sm text-xs h-[32px] sm:h-[32px] w-[52px] sm:w-[84px] md:w-[84px] border border-gray-300 text-indigo-600 px-2 py-1 rounded-md hover:bg-gray-100"
154+
className="cursor-pointer font-medium sm:text-sm text-xs h-[32px] sm:h-[32px] w-[52px] sm:w-[84px] md:w-[84px] border border-gray-300 text-indigo-600 px-2 py-1 rounded-md hover:bg-gray-100 lg:mr-3"
150155
>
151156
취소
152157
</button>

src/components/table/TablePagination.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const Pagination: React.FC<PaginationProps> = ({
1515
}) => {
1616
return (
1717
<div className="flex items-center">
18-
<p className="relative -translate-y-[10px] sm:text-sm text-xs text-gray-700 mt-4 text-center mr-3">
18+
<p className="relative -translate-y-[10px] sm:text-xs text-sm text-gray-700 mt-4 text-center mr-3">
1919
{totalPages} 페이지 중 {currentPage}
2020
</p>
2121
<div className="flex items-center border border-gray-300 rounded-lg overflow-hidden">

src/components/table/invited/InvitedDashBoard.tsx

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,13 +66,11 @@ function InvitedList({
6666
apiRoutes.invitationDetail(inviteId),
6767
payload
6868
);
69-
console.log("대시보드 수락 성공:", response.data);
7069
toast.success("대시보드 수락 성공");
7170
setTimeout(() => {
7271
window.location.reload();
7372
}, 100);
7473
} catch (error) {
75-
console.error("대시보드 수락 실패:", error);
7674
toast.error("대시보드 수락 실패");
7775
}
7876
};
@@ -88,13 +86,11 @@ function InvitedList({
8886
apiRoutes.invitationDetail(inviteId),
8987
payload
9088
);
91-
console.log("대시보드 거절 성공:", response.data);
9289
toast.success("대시보드 거절 성공");
9390
setTimeout(() => {
9491
window.location.reload();
9592
}, 100);
9693
} catch (error) {
97-
console.error("대시보드 거절 실패:", error);
9894
toast.error("대시보드 거절 실패");
9995
}
10096
};

0 commit comments

Comments
 (0)