ERP-node/frontend/components/v2/V2List.tsx

177 lines
5.2 KiB
TypeScript
Raw Normal View History

2025-12-19 15:44:38 +09:00
"use client";
/**
* V2List
2025-12-23 13:53:22 +09:00
*
2025-12-19 15:44:38 +09:00
*
2025-12-23 13:53:22 +09:00
* TableListComponent를
2025-12-19 15:44:38 +09:00
*/
2025-12-23 13:53:22 +09:00
import React, { forwardRef, useMemo } from "react";
import { TableListComponent } from "@/lib/registry/components/table-list/TableListComponent";
import { V2ListProps } from "@/types/v2-components";
2025-12-19 15:44:38 +09:00
/**
* V2List
2025-12-23 13:53:22 +09:00
* TableListComponent의
2025-12-19 15:44:38 +09:00
*/
export const V2List = forwardRef<HTMLDivElement, V2ListProps>((props, ref) => {
2025-12-23 13:53:22 +09:00
const { id, style, size, config: configProp, onRowSelect } = props;
// config가 없으면 기본값 사용
const config = configProp || {
viewMode: "table" as const,
source: "static" as const,
columns: [],
};
2025-12-24 13:54:24 +09:00
// 테이블명 추출 (여러 가능한 경로에서 시도)
const tableName = config.dataSource?.table || (config as any).tableName || (props as any).tableName;
2025-12-23 13:53:22 +09:00
// columns 형식 변환 (V2ListConfigPanel 형식 -> TableListComponent 형식)
2025-12-23 13:53:22 +09:00
const tableColumns = useMemo(
() =>
(config.columns || []).map((col: any, index: number) => ({
columnName: col.key || col.field || "",
displayName: col.title || col.header || col.key || col.field || "",
width: col.width ? parseInt(col.width, 10) : undefined,
visible: true,
sortable: true,
searchable: true,
align: "left" as const,
order: index,
isEntityJoin: col.isJoinColumn || false,
2026-01-05 15:35:19 +09:00
thousandSeparator: col.thousandSeparator !== false, // 천단위 구분자 (기본: true)
2025-12-23 13:53:22 +09:00
})),
[config.columns],
2025-12-19 15:44:38 +09:00
);
2025-12-23 13:53:22 +09:00
// TableListComponent에 전달할 component 객체 생성
const componentObj = useMemo(
() => ({
id: id || "v2-list",
2025-12-23 13:53:22 +09:00
type: "table-list",
config: {
selectedTable: tableName,
tableName: tableName,
columns: tableColumns,
displayMode: config.viewMode === "card" ? "card" : "table",
cardConfig: {
idColumn: config.cardConfig?.titleColumn || tableColumns[0]?.columnName || "id",
titleColumn: config.cardConfig?.titleColumn || tableColumns[0]?.columnName || "",
subtitleColumn: config.cardConfig?.subtitleColumn || undefined,
descriptionColumn: config.cardConfig?.descriptionColumn || undefined,
imageColumn: config.cardConfig?.imageColumn || undefined,
cardsPerRow: config.cardConfig?.cardsPerRow || 3,
2025-12-23 13:53:22 +09:00
cardSpacing: 16,
showActions: false,
},
showHeader: config.viewMode !== "card", // 카드 모드에서는 테이블 헤더 숨김
2025-12-23 13:53:22 +09:00
showFooter: false,
checkbox: {
2026-01-05 17:44:32 +09:00
enabled: true, // 항상 체크박스 활성화 (modalDataStore에 자동 저장)
2025-12-23 13:53:22 +09:00
position: "left" as const,
showHeader: true,
},
height: "auto" as const, // auto로 변경하여 스크롤 가능하게
2025-12-23 13:53:22 +09:00
autoWidth: true,
stickyHeader: true,
autoLoad: true,
horizontalScroll: {
enabled: true,
minColumnWidth: 100,
maxColumnWidth: 300,
},
pagination: {
2026-01-05 15:30:57 +09:00
enabled: config.pagination !== false,
pageSize: config.pageSize || 10,
2025-12-23 13:53:22 +09:00
position: "bottom" as const,
2026-01-05 15:30:57 +09:00
showPageSize: true, // 사용자가 실제 화면에서 페이지 크기 변경 가능
pageSizeOptions: [5, 10, 20, 50, 100],
2025-12-23 13:53:22 +09:00
},
filter: {
enabled: false, // 필터 비활성화 (필요시 활성화)
2025-12-23 13:53:22 +09:00
position: "top" as const,
searchPlaceholder: "검색...",
},
actions: {
enabled: false,
items: [],
},
tableStyle: {
striped: false,
bordered: true,
hover: true,
compact: false,
},
toolbar: {
showRefresh: true,
showExport: false,
showColumnToggle: false,
},
},
style: {},
gridColumns: 1,
}),
[
2025-12-19 15:44:38 +09:00
id,
2025-12-23 13:53:22 +09:00
tableName,
tableColumns,
config.viewMode,
2026-01-05 15:30:57 +09:00
config.pagination,
2025-12-23 13:53:22 +09:00
config.pageSize,
config.cardConfig,
2025-12-19 15:44:38 +09:00
onRowSelect,
2025-12-23 13:53:22 +09:00
],
);
2025-12-19 15:44:38 +09:00
2025-12-23 13:53:22 +09:00
// 테이블이 없으면 안내 메시지
if (!tableName) {
2025-12-19 15:44:38 +09:00
return (
<div
ref={ref}
id={id}
2025-12-23 13:53:22 +09:00
className="bg-muted/20 flex items-center justify-center rounded-lg border p-8"
2025-12-19 15:44:38 +09:00
style={{
2025-12-23 13:53:22 +09:00
width: size?.width || style?.width || "100%",
height: size?.height || style?.height || "100%",
2025-12-19 15:44:38 +09:00
}}
>
2025-12-23 13:53:22 +09:00
<p className="text-muted-foreground text-sm"> .</p>
2025-12-19 15:44:38 +09:00
</div>
);
}
2025-12-23 13:53:22 +09:00
return (
<div
ref={ref}
id={id}
className="flex flex-col overflow-auto"
2025-12-23 13:53:22 +09:00
style={{
width: size?.width || style?.width || "100%",
height: size?.height || style?.height || "100%",
2025-12-23 13:53:22 +09:00
}}
>
<TableListComponent
component={componentObj}
tableName={tableName}
style={{
width: "100%",
minHeight: "100%",
2025-12-23 13:53:22 +09:00
display: "flex",
flexDirection: "column",
}}
onSelectedRowsChange={
onRowSelect
? (_, selectedData) => {
onRowSelect(selectedData);
}
: undefined
}
/>
</div>
);
});
2025-12-19 15:44:38 +09:00
V2List.displayName = "V2List";