Skip to content

Commit 25cb7ad

Browse files
authored
[Feat, Refector] D&D 적용 및 파일수정
[Feat, Refector] D&D 적용 및 파일수정
2 parents 5bd46c9 + 373ec96 commit 25cb7ad

File tree

5 files changed

+202
-55
lines changed

5 files changed

+202
-55
lines changed

package-lock.json

Lines changed: 70 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
"lint": "next lint"
1010
},
1111
"dependencies": {
12+
"@dnd-kit/core": "^6.3.1",
13+
"@dnd-kit/modifiers": "^9.0.0",
14+
"@dnd-kit/sortable": "^10.0.0",
1215
"@tanstack/react-query": "^5.68.0",
1316
"axios": "^1.8.3",
1417
"clsx": "^2.1.1",

src/components/button/CardButton.tsx

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { useRouter } from "next/router";
33
import clsx from "clsx";
44
import Image from "next/image";
55

6-
interface CardButtonProps extends React.ButtonHTMLAttributes<HTMLDivElement> {
6+
interface CardButtonProps extends React.HTMLAttributes<HTMLDivElement> {
77
title?: string;
88
showCrown?: boolean;
99
color?: string;
@@ -12,29 +12,31 @@ interface CardButtonProps extends React.ButtonHTMLAttributes<HTMLDivElement> {
1212
createdByMe?: boolean;
1313
onDeleteClick?: (id: number) => void;
1414
onLeaveClick?: (id: number) => void;
15+
attributes?: React.HTMLAttributes<HTMLDivElement>;
16+
listeners?: React.HTMLAttributes<HTMLDivElement>;
1517
}
1618

1719
const CardButton: React.FC<CardButtonProps> = ({
1820
className,
1921
title = "비브리지",
2022
showCrown = true,
21-
color = "#7ac555", // 기본 색상
23+
color = "#7ac555",
2224
isEditMode = false,
2325
dashboardId,
2426
createdByMe,
2527
onDeleteClick,
2628
onLeaveClick,
29+
attributes,
30+
listeners,
2731
...props
2832
}) => {
2933
const router = useRouter();
3034

3135
const handleCardClick = (e: React.MouseEvent<HTMLDivElement>) => {
32-
// 관리 상태에서 카드 클릭 이벤트 차단
3336
if (isEditMode) {
3437
e.preventDefault();
3538
return;
3639
}
37-
// 카드 클릭 시 해당 대시보드로 이동
3840
router.push(`/dashboard/${dashboardId}`);
3941
};
4042

@@ -46,16 +48,16 @@ const CardButton: React.FC<CardButtonProps> = ({
4648
const handleDelete = (e: React.MouseEvent) => {
4749
e.stopPropagation();
4850
if (createdByMe) {
49-
// 실제 삭제 API 요청
50-
if (onDeleteClick) onDeleteClick(dashboardId);
51+
onDeleteClick?.(dashboardId);
5152
} else {
52-
// 나만 탈퇴
53-
if (onLeaveClick) onLeaveClick(dashboardId);
53+
onLeaveClick?.(dashboardId);
5454
}
5555
};
5656

5757
return (
5858
<div
59+
{...attributes}
60+
{...listeners}
5961
{...props}
6062
onClick={handleCardClick}
6163
className={clsx(
@@ -64,7 +66,7 @@ const CardButton: React.FC<CardButtonProps> = ({
6466
"border border-[var(--color-gray3)]",
6567
"min-w-0 w-full max-w-[260px] md:max-w-[247px] lg:max-w-[332px]",
6668
"h-[58px] md:h-[68px] lg:h-[70px]",
67-
"mt-[2px]", // 카드 세로 간격
69+
"mt-[2px]",
6870
"text-lg md:text-2lg lg:text-2lg",
6971
isEditMode
7072
? "cursor-default hover:border-gray-300"
@@ -74,30 +76,25 @@ const CardButton: React.FC<CardButtonProps> = ({
7476
>
7577
{/* 왼쪽: 색상 도트 + 제목 + 왕관 */}
7678
<div className="flex items-center overflow-hidden font-semibold gap-[10px]">
77-
{/* 색상 원 */}
7879
<svg width="8" height="8" viewBox="0 0 8 8" fill={color}>
7980
<circle cx="4" cy="4" r="4" />
8081
</svg>
81-
82-
{/* 제목 */}
8382
<span className="text-black3 text-[14px] sm:text-[16px] truncate max-w-[120px]">
8483
{title}
8584
</span>
86-
87-
{/* 왕관 */}
88-
<div className="relative w-[15px] h-[12px] md:w-[17px] md:h-[14px]">
89-
{showCrown && (
85+
{showCrown && (
86+
<div className="relative w-[15px] h-[12px] md:w-[17px] md:h-[14px]">
9087
<Image
9188
src="/svgs/icon-crown.svg"
9289
alt="crown Icon"
9390
fill
9491
className="object-contain"
9592
/>
96-
)}
97-
</div>
93+
</div>
94+
)}
9895
</div>
9996

100-
{/* 오른쪽: 화살표 아이콘 or 수정/삭제 버튼 */}
97+
{/* 오른쪽: 수정/삭제 버튼 또는 아이콘 */}
10198
{isEditMode ? (
10299
<div className="flex flex-col gap-2">
103100
{createdByMe && (
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { useSortable } from "@dnd-kit/sortable";
2+
import { CSS } from "@dnd-kit/utilities";
3+
import CardButton from "./CardButton";
4+
import { Dashboard } from "@/api/dashboards";
5+
6+
export default function SortableCardButton({
7+
dashboard,
8+
...rest
9+
}: {
10+
dashboard: Dashboard;
11+
isEditMode?: boolean;
12+
onDeleteClick?: (id: number) => void;
13+
onLeaveClick?: (id: number) => void;
14+
}) {
15+
const { attributes, listeners, setNodeRef, transform, transition } =
16+
useSortable({
17+
id: dashboard.id,
18+
});
19+
20+
const style = {
21+
transform: CSS.Transform.toString(transform),
22+
transition,
23+
zIndex: 10,
24+
};
25+
26+
return (
27+
<div ref={setNodeRef} style={style}>
28+
<CardButton
29+
dashboardId={dashboard.id}
30+
title={dashboard.title}
31+
showCrown={dashboard.createdByMe}
32+
color={dashboard.color}
33+
createdByMe={dashboard.createdByMe}
34+
{...rest}
35+
attributes={attributes}
36+
listeners={listeners}
37+
/>
38+
</div>
39+
);
40+
}

0 commit comments

Comments
 (0)