ERP-node/frontend/lib/registry/pop-components/pop-card-list/PopCardListPreview.tsx

161 lines
5.3 KiB
TypeScript

"use client";
/**
* pop-card-list 디자인 모드 미리보기 컴포넌트 (V2)
*
* 디자이너 캔버스에서 표시되는 미리보기
* 이미지 참조 기반 카드 구조 반영
*/
import React from "react";
import { LayoutGrid, Package } from "lucide-react";
import type { PopCardListConfig } from "../types";
import { CARD_SCROLL_DIRECTION_LABELS, CARD_SIZE_LABELS, DEFAULT_CARD_IMAGE } from "../types";
interface PopCardListPreviewProps {
config?: PopCardListConfig;
}
export function PopCardListPreviewComponent({ config }: PopCardListPreviewProps) {
const scrollDirection = config?.scrollDirection || "vertical";
const cardSize = config?.cardSize || "medium";
const dataSource = config?.dataSource;
const template = config?.cardTemplate;
const hasTable = !!dataSource?.tableName;
const hasHeader = !!template?.header?.codeField || !!template?.header?.titleField;
const hasImage = template?.image?.enabled ?? true;
const fieldCount = template?.body?.fields?.length || 0;
const sampleCardCount = 2;
return (
<div className="bg-muted/30 flex h-full w-full flex-col p-3">
{/* 헤더 */}
<div className="mb-2 flex items-center justify-between">
<div className="text-muted-foreground flex items-center gap-2">
<LayoutGrid className="h-4 w-4" />
<span className="text-xs font-medium"> </span>
</div>
{/* 설정 배지 */}
<div className="flex gap-1">
<span className="bg-primary/10 text-primary rounded px-1.5 py-0.5 text-[9px]">
{CARD_SCROLL_DIRECTION_LABELS[scrollDirection]}
</span>
<span className="bg-secondary text-secondary-foreground rounded px-1.5 py-0.5 text-[9px]">
{CARD_SIZE_LABELS[cardSize]}
</span>
</div>
</div>
{/* 테이블 미선택 시 안내 */}
{!hasTable ? (
<div className="flex flex-1 items-center justify-center">
<div className="text-center">
<Package className="text-muted-foreground/50 mx-auto mb-2 h-8 w-8" />
<p className="text-muted-foreground text-xs"> </p>
</div>
</div>
) : (
<>
{/* 테이블 정보 */}
<div className="mb-2 text-center">
<span className="bg-muted text-muted-foreground rounded px-2 py-0.5 text-[10px]">
{dataSource.tableName}
</span>
</div>
{/* 카드 미리보기 */}
<div
className={`flex flex-1 gap-2 ${scrollDirection === "vertical" ? "flex-col" : "flex-row overflow-x-auto"}`}
>
{Array.from({ length: sampleCardCount }).map((_, idx) => (
<PreviewCard
key={idx}
index={idx}
hasHeader={hasHeader}
hasImage={hasImage}
fieldCount={fieldCount}
cardSize={cardSize}
scrollDirection={scrollDirection}
/>
))}
</div>
{/* 필드 정보 */}
{fieldCount > 0 && (
<div className="mt-2 text-center">
<span className="text-muted-foreground text-[10px]">{fieldCount} </span>
</div>
)}
</>
)}
</div>
);
}
// ===== 미리보기 카드 컴포넌트 =====
function PreviewCard({
index,
hasHeader,
hasImage,
fieldCount,
cardSize,
scrollDirection,
}: {
index: number;
hasHeader: boolean;
hasImage: boolean;
fieldCount: number;
cardSize: string;
scrollDirection: string;
}) {
const sizeClass = cardSize === "small" ? "min-h-[60px]" : cardSize === "large" ? "min-h-[100px]" : "min-h-[80px]";
const widthClass = scrollDirection === "vertical" ? "w-full" : "min-w-[140px] flex-shrink-0";
return (
<div className={`bg-card overflow-hidden rounded-md border ${sizeClass} ${widthClass}`}>
{/* 헤더 */}
{hasHeader && (
<div className="bg-muted/30 border-b px-2 py-1">
<div className="flex items-center gap-1">
<span className="bg-muted-foreground/20 h-2 w-8 rounded" />
<span className="bg-muted-foreground/30 h-2 w-12 rounded" />
</div>
</div>
)}
{/* 본문 */}
<div className="flex gap-2 p-2">
{/* 이미지 */}
{hasImage && (
<div className="flex-shrink-0">
<div className="bg-muted/30 flex h-10 w-10 items-center justify-center rounded border">
<img src={DEFAULT_CARD_IMAGE} alt="" className="h-6 w-6 opacity-50" />
</div>
</div>
)}
{/* 필드 목록 */}
<div className="flex-1 space-y-1">
{fieldCount > 0 ? (
Array.from({ length: Math.min(fieldCount, 3) }).map((_, i) => (
<div key={i} className="flex items-center gap-1">
<span className="bg-muted-foreground/20 h-1.5 w-6 rounded" />
<span className="bg-muted-foreground/30 h-1.5 w-10 rounded" />
</div>
))
) : (
<div className="flex h-full items-center justify-center">
<span className="text-muted-foreground text-[8px]"> </span>
</div>
)}
</div>
</div>
</div>
);
}