ERP-node/frontend/lib/registry/layouts/card-layout/CardLayoutLayout.tsx

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>
);
};