140 lines
4.3 KiB
TypeScript
140 lines
4.3 KiB
TypeScript
"use client";
|
|
|
|
/**
|
|
* pop-string-list 디자이너 미리보기
|
|
*
|
|
* 디자인 모드에서 캔버스에 표시되는 간략한 미리보기.
|
|
* 실제 데이터는 가져오지 않고 더미 데이터로 레이아웃만 시각화.
|
|
*/
|
|
|
|
import type { PopStringListConfig } from "./types";
|
|
|
|
interface PopStringListPreviewProps {
|
|
config?: PopStringListConfig;
|
|
}
|
|
|
|
export function PopStringListPreviewComponent({ config }: PopStringListPreviewProps) {
|
|
const displayMode = config?.displayMode || "list";
|
|
const header = config?.header;
|
|
const tableName = config?.dataSource?.tableName;
|
|
const listColumns = config?.listColumns || [];
|
|
const cardGrid = config?.cardGrid;
|
|
|
|
// 테이블 미선택
|
|
if (!tableName) {
|
|
return (
|
|
<div className="flex h-full w-full items-center justify-center p-2">
|
|
<span className="text-muted-foreground text-[10px]">테이블을 선택하세요</span>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="flex h-full w-full flex-col overflow-hidden">
|
|
{/* 헤더 */}
|
|
{header?.enabled && (
|
|
<div className="shrink-0 border-b px-2 py-1">
|
|
<span className="text-[10px] font-medium">{header.label || "리스트 목록"}</span>
|
|
</div>
|
|
)}
|
|
|
|
{/* 모드별 미리보기 */}
|
|
<div className="flex-1 overflow-hidden p-1">
|
|
{displayMode === "list" ? <ListPreview columns={listColumns} /> : <CardPreview cardGrid={cardGrid} />}
|
|
</div>
|
|
|
|
{/* 모드 라벨 */}
|
|
<div className="shrink-0 border-t px-2 py-0.5">
|
|
<span className="text-muted-foreground text-[8px]">
|
|
{displayMode === "list" ? "리스트" : "카드"} | {tableName}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
// ===== 리스트 미리보기 =====
|
|
|
|
function ListPreview({ columns }: { columns: PopStringListConfig["listColumns"] }) {
|
|
const cols = columns || [];
|
|
|
|
if (cols.length === 0) {
|
|
return (
|
|
<div className="flex h-full items-center justify-center">
|
|
<span className="text-muted-foreground text-[8px]">컬럼 미설정</span>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
const gridCols = cols.map((c) => c.width || "1fr").join(" ");
|
|
const dummyRows = 3;
|
|
|
|
return (
|
|
<div className="w-full">
|
|
{/* 헤더 */}
|
|
<div className="bg-muted/50 border-b" style={{ display: "grid", gridTemplateColumns: gridCols }}>
|
|
{cols.map((col) => (
|
|
<div key={col.columnName} className="text-muted-foreground truncate px-1 py-0.5 text-[8px] font-medium">
|
|
{col.label}
|
|
</div>
|
|
))}
|
|
</div>
|
|
{/* 더미 행 */}
|
|
{Array.from({ length: dummyRows }).map((_, i) => (
|
|
<div key={i} className="border-b last:border-b-0" style={{ display: "grid", gridTemplateColumns: gridCols }}>
|
|
{cols.map((col) => (
|
|
<div key={col.columnName} className="px-1 py-0.5">
|
|
<div className="bg-muted h-2 w-3/4 animate-pulse rounded" />
|
|
</div>
|
|
))}
|
|
</div>
|
|
))}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
// ===== 카드 미리보기 =====
|
|
|
|
function CardPreview({ cardGrid }: { cardGrid: PopStringListConfig["cardGrid"] }) {
|
|
if (!cardGrid || cardGrid.cells.length === 0) {
|
|
return (
|
|
<div className="flex h-full items-center justify-center">
|
|
<span className="text-muted-foreground text-[8px]">카드 레이아웃 미설정</span>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
// 더미 카드 2장
|
|
return (
|
|
<div className="space-y-1">
|
|
{[0, 1].map((i) => (
|
|
<div
|
|
key={i}
|
|
className="rounded border"
|
|
style={{
|
|
display: "grid",
|
|
gridTemplateColumns: cardGrid.colWidths.join(" "),
|
|
gridTemplateRows: cardGrid.rowHeights?.join(" ") || `repeat(${cardGrid.rows}, 1fr)`,
|
|
gap: `${cardGrid.gap}px`,
|
|
minHeight: "24px",
|
|
}}
|
|
>
|
|
{cardGrid.cells.map((cell) => (
|
|
<div
|
|
key={cell.id}
|
|
className="flex items-center justify-center"
|
|
style={{
|
|
gridColumn: `${cell.col} / span ${cell.colSpan}`,
|
|
gridRow: `${cell.row} / span ${cell.rowSpan}`,
|
|
border: cardGrid.showBorder ? "1px dashed hsl(var(--border))" : "none",
|
|
}}
|
|
>
|
|
<div className="bg-muted h-2 w-3/4 animate-pulse rounded" />
|
|
</div>
|
|
))}
|
|
</div>
|
|
))}
|
|
</div>
|
|
);
|
|
}
|