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

192 lines
5.5 KiB
TypeScript
Raw Normal View History

"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="flex h-full w-full flex-col bg-muted/30 p-3">
{/* 헤더 */}
<div className="mb-2 flex items-center justify-between">
<div className="flex items-center gap-2 text-muted-foreground">
<LayoutGrid className="h-4 w-4" />
<span className="text-xs font-medium"> </span>
</div>
{/* 설정 배지 */}
<div className="flex gap-1">
<span className="rounded bg-primary/10 px-1.5 py-0.5 text-[9px] text-primary">
{CARD_SCROLL_DIRECTION_LABELS[scrollDirection]}
</span>
<span className="rounded bg-secondary px-1.5 py-0.5 text-[9px] text-secondary-foreground">
{CARD_SIZE_LABELS[cardSize]}
</span>
</div>
</div>
{/* 테이블 미선택 시 안내 */}
{!hasTable ? (
<div className="flex flex-1 items-center justify-center">
<div className="text-center">
<Package className="mx-auto mb-2 h-8 w-8 text-muted-foreground/50" />
<p className="text-xs text-muted-foreground">
</p>
</div>
</div>
) : (
<>
{/* 테이블 정보 */}
<div className="mb-2 text-center">
<span className="rounded bg-muted px-2 py-0.5 text-[10px] text-muted-foreground">
{dataSource.tableName}
</span>
</div>
{/* 카드 미리보기 */}
<div
className={`flex-1 flex 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-[10px] text-muted-foreground">
{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={`rounded-md border bg-card overflow-hidden ${sizeClass} ${widthClass}`}
>
{/* 헤더 */}
{hasHeader && (
<div className="border-b bg-muted/30 px-2 py-1">
<div className="flex items-center gap-1">
<span className="h-2 w-8 rounded bg-muted-foreground/20" />
<span className="h-2 w-12 rounded bg-muted-foreground/30" />
</div>
</div>
)}
{/* 본문 */}
<div className="flex p-2 gap-2">
{/* 이미지 */}
{hasImage && (
<div className="flex-shrink-0">
<div className="h-10 w-10 rounded border bg-muted/30 flex items-center justify-center">
<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="h-1.5 w-6 rounded bg-muted-foreground/20" />
<span className="h-1.5 w-10 rounded bg-muted-foreground/30" />
</div>
))
) : (
<div className="flex h-full items-center justify-center">
<span className="text-[8px] text-muted-foreground">
</span>
</div>
)}
</div>
</div>
</div>
);
}