ERP-node/frontend/lib/registry/components/repeat-screen-modal/RepeatScreenModalComponent.tsx

237 lines
7.1 KiB
TypeScript

"use client";
import React from "react";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
interface ContentRow {
label?: string;
field?: string;
type?: string;
}
interface DataSource {
filterField?: string;
sourceTable?: string;
}
interface Grouping {
enabled?: boolean;
aggregations?: any[];
groupField?: string;
}
interface TableLayout {
headerRows?: any[];
tableColumns?: any[];
}
interface CardLayoutItem {
field?: string;
label?: string;
width?: string;
}
export interface RepeatScreenModalProps {
// 기본 props
id?: string;
label?: string;
style?: React.CSSProperties;
// 컴포넌트 설정
cardMode?: "simple" | "detailed";
cardSpacing?: string;
cardTitle?: string;
contentRows?: ContentRow[];
dataSource?: DataSource;
grouping?: Grouping;
saveMode?: "all" | "single";
showCardBorder?: boolean;
showCardTitle?: boolean;
tableLayout?: TableLayout;
cardLayout?: CardLayoutItem[];
// 컴포넌트 config (componentConfig에서 전달됨)
componentConfig?: {
type?: string;
webType?: string;
cardMode?: string;
cardSpacing?: string;
cardTitle?: string;
contentRows?: ContentRow[];
dataSource?: DataSource;
grouping?: Grouping;
saveMode?: string;
showCardBorder?: boolean;
showCardTitle?: boolean;
tableLayout?: TableLayout;
cardLayout?: CardLayoutItem[];
};
}
/**
* RepeatScreenModal 컴포넌트
* 카드/테이블 형태로 데이터를 반복 표시하고 편집할 수 있는 모달
*/
export function RepeatScreenModalComponent(props: RepeatScreenModalProps) {
const {
id,
label = "반복 화면 모달",
style,
componentConfig,
} = props;
// componentConfig에서 설정 가져오기
const config = componentConfig || {};
const {
cardMode = "simple",
cardSpacing = "24px",
cardTitle = "",
contentRows = [],
dataSource,
grouping,
saveMode = "all",
showCardBorder = true,
showCardTitle = true,
tableLayout,
cardLayout = [],
} = config;
// 스타일에서 width, height 추출
const { width, height, ...restStyle } = style || {};
return (
<div
id={id}
className="flex h-full w-full flex-col overflow-auto"
style={restStyle}
>
<Card className={`h-full w-full ${showCardBorder ? "" : "border-0 shadow-none"}`}>
{showCardTitle && (
<CardHeader className="pb-2">
<CardTitle className="text-lg">{label}</CardTitle>
{cardTitle && (
<p className="text-sm text-muted-foreground">{cardTitle}</p>
)}
</CardHeader>
)}
<CardContent className="flex-1 overflow-auto">
{/* 데이터 소스 정보 표시 */}
{dataSource?.sourceTable && (
<div className="mb-4 rounded-md bg-muted p-3">
<p className="text-sm">
<span className="font-medium"> :</span>{" "}
{dataSource.sourceTable}
</p>
{dataSource.filterField && (
<p className="text-sm">
<span className="font-medium"> :</span>{" "}
{dataSource.filterField}
</p>
)}
</div>
)}
{/* 카드 레이아웃 표시 */}
{cardLayout && cardLayout.length > 0 && (
<div
className="grid gap-4"
style={{
gridTemplateColumns: `repeat(auto-fill, minmax(250px, 1fr))`,
gap: cardSpacing,
}}
>
{cardLayout.map((item, index) => (
<div
key={index}
className="rounded-md border bg-card p-3"
>
<p className="text-xs text-muted-foreground">{item.label || item.field}</p>
<p className="text-sm font-medium">{item.field || "-"}</p>
</div>
))}
</div>
)}
{/* 컨텐츠 행 표시 */}
{contentRows && contentRows.length > 0 && (
<div className="space-y-2">
{contentRows.map((row, index) => (
<div
key={index}
className="flex items-center justify-between rounded-md border p-2"
>
<span className="text-sm text-muted-foreground">
{row.label || row.field || `Row ${index + 1}`}
</span>
<span className="text-sm font-medium">
{row.field || "-"}
</span>
</div>
))}
</div>
)}
{/* 테이블 레이아웃이 있으면 테이블 형태로 표시 */}
{tableLayout?.tableColumns && tableLayout.tableColumns.length > 0 && (
<div className="mt-4 overflow-auto">
<table className="w-full border-collapse">
<thead>
<tr className="bg-muted">
{tableLayout.tableColumns.map((col: any, index: number) => (
<th
key={index}
className="border px-3 py-2 text-left text-sm font-medium"
>
{col.label || col.field || `Column ${index + 1}`}
</th>
))}
</tr>
</thead>
<tbody>
<tr>
<td
colSpan={tableLayout.tableColumns.length}
className="border px-3 py-8 text-center text-sm text-muted-foreground"
>
</td>
</tr>
</tbody>
</table>
</div>
)}
{/* 빈 상태 표시 */}
{(!contentRows || contentRows.length === 0) &&
(!cardLayout || cardLayout.length === 0) &&
(!tableLayout?.tableColumns || tableLayout.tableColumns.length === 0) && (
<div className="flex h-48 items-center justify-center rounded-md border-2 border-dashed">
<div className="text-center">
<p className="text-sm font-medium text-muted-foreground">
</p>
<p className="mt-1 text-xs text-muted-foreground">
</p>
</div>
</div>
)}
{/* 그룹핑 정보 */}
{grouping?.enabled && (
<div className="mt-4 rounded-md bg-blue-50 p-2 text-xs text-blue-700">
{grouping.groupField && `(${grouping.groupField})`}
</div>
)}
{/* 저장 모드 표시 */}
<div className="mt-4 text-xs text-muted-foreground">
: {saveMode === "all" ? "전체 저장" : "개별 저장"}
</div>
</CardContent>
</Card>
</div>
);
}