103 lines
3.0 KiB
TypeScript
103 lines
3.0 KiB
TypeScript
"use client";
|
|
|
|
import React from "react";
|
|
import { LayoutRendererProps } from "../BaseLayoutRenderer";
|
|
|
|
/**
|
|
* 카드 레이아웃 컴포넌트
|
|
* 3x2 격자로 구성된 카드 대시보드 레이아웃
|
|
*/
|
|
export const CardLayoutLayout: React.FC<LayoutRendererProps> = ({
|
|
layout,
|
|
children,
|
|
onUpdateLayout,
|
|
onSelectComponent,
|
|
isDesignMode = false,
|
|
}) => {
|
|
const cardConfig = layout.layoutConfig?.cardLayout || {
|
|
columns: 3,
|
|
gap: 16,
|
|
aspectRatio: "4:3",
|
|
};
|
|
|
|
// 카드 레이아웃 스타일
|
|
const containerStyle: React.CSSProperties = {
|
|
display: "grid",
|
|
gridTemplateColumns: `repeat(${cardConfig.columns}, 1fr)`,
|
|
gridTemplateRows: "repeat(2, 300px)", // 2행 고정
|
|
gap: `${cardConfig.gap}px`,
|
|
padding: "16px",
|
|
width: "100%",
|
|
height: "100%",
|
|
background: "transparent",
|
|
};
|
|
|
|
// 카드 스타일
|
|
const cardStyle: React.CSSProperties = {
|
|
backgroundColor: "white",
|
|
border: "1px solid #e5e7eb",
|
|
borderRadius: "8px",
|
|
padding: "16px",
|
|
boxShadow: "0 1px 3px 0 rgba(0, 0, 0, 0.1)",
|
|
transition: "all 0.2s ease-in-out",
|
|
overflow: "hidden",
|
|
display: "flex",
|
|
flexDirection: "column",
|
|
position: "relative",
|
|
minHeight: "200px",
|
|
};
|
|
|
|
// 디자인 모드에서 호버 효과
|
|
const designModeCardStyle: React.CSSProperties = isDesignMode
|
|
? {
|
|
...cardStyle,
|
|
cursor: "pointer",
|
|
borderColor: "#d1d5db",
|
|
"&:hover": {
|
|
borderColor: "#3b82f6",
|
|
boxShadow: "0 4px 6px -1px rgba(0, 0, 0, 0.1)",
|
|
},
|
|
}
|
|
: cardStyle;
|
|
|
|
return (
|
|
<div style={containerStyle}>
|
|
{layout.zones?.map((zone, index) => {
|
|
const zoneChildren = children?.filter((child) => child.props.parentId === zone.id) || [];
|
|
|
|
return (
|
|
<div
|
|
key={zone.id}
|
|
style={designModeCardStyle}
|
|
onClick={() => isDesignMode && onSelectComponent?.(zone.id)}
|
|
className={isDesignMode ? "hover:border-blue-500 hover:shadow-md" : ""}
|
|
>
|
|
{/* 카드 헤더 */}
|
|
{isDesignMode && (
|
|
<div className="absolute top-2 left-2 z-10">
|
|
<div className="rounded bg-blue-500 px-2 py-1 text-xs text-white">{zone.name}</div>
|
|
</div>
|
|
)}
|
|
|
|
{/* 카드 내용 */}
|
|
<div className="flex flex-1 flex-col">
|
|
{zoneChildren.length > 0 ? (
|
|
<div className="flex-1">{zoneChildren}</div>
|
|
) : (
|
|
isDesignMode && (
|
|
<div className="flex flex-1 items-center justify-center rounded border-2 border-dashed border-gray-200 text-gray-400">
|
|
<div className="text-center">
|
|
<div className="text-sm font-medium">{zone.name}</div>
|
|
<div className="mt-1 text-xs">컴포넌트를 드래그하여 추가하세요</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
);
|
|
};
|