From c28e27f3e83422c04f1df1b84a1ba95fef8b68c6 Mon Sep 17 00:00:00 2001 From: leeheejin Date: Thu, 25 Sep 2025 18:54:25 +0900 Subject: [PATCH] =?UTF-8?q?=ED=99=94=EB=A9=B4=EA=B4=80=EB=A6=AC=EC=9D=98?= =?UTF-8?q?=20=ED=85=8C=EC=9D=B4=EB=B8=94=20=EB=A6=AC=EC=8A=A4=ED=8A=B8,?= =?UTF-8?q?=20=EC=B9=B4=EB=93=9C=20=EB=94=94=EC=8A=A4=ED=94=8C=EB=A0=88?= =?UTF-8?q?=EC=9D=B4=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/(main)/screens/[screenId]/page.tsx | 20 +- frontend/components/screen/ScreenDesigner.tsx | 19 ++ .../screen/panels/ComponentsPanel.tsx | 25 +- .../card-display/CardDisplayComponent.tsx | 245 +++++++++++++++--- .../table-list/TableListComponent.tsx | 24 ++ .../table-list/TableListConfigPanel.tsx | 183 +++++++++++++ .../table-list/TableListRenderer.tsx | 13 + .../registry/components/table-list/index.ts | 14 +- .../registry/components/table-list/types.ts | 25 +- 9 files changed, 512 insertions(+), 56 deletions(-) diff --git a/frontend/app/(main)/screens/[screenId]/page.tsx b/frontend/app/(main)/screens/[screenId]/page.tsx index 86dd77df..dd48479d 100644 --- a/frontend/app/(main)/screens/[screenId]/page.tsx +++ b/frontend/app/(main)/screens/[screenId]/page.tsx @@ -275,16 +275,16 @@ export default function ScreenViewPage() { zIndex: component.position.z || 1, }} onMouseEnter={() => { - console.log("๐ŸŽฏ ํ• ๋‹น๋œ ํ™”๋ฉด ์ปดํฌ๋„ŒํŠธ:", { - id: component.id, - type: component.type, - position: component.position, - size: component.size, - styleWidth: component.style?.width, - styleHeight: component.style?.height, - finalWidth: `${component.size.width}px`, - finalHeight: `${component.size.height}px`, - }); + // console.log("๐ŸŽฏ ํ• ๋‹น๋œ ํ™”๋ฉด ์ปดํฌ๋„ŒํŠธ:", { + // id: component.id, + // type: component.type, + // position: component.position, + // size: component.size, + // styleWidth: component.style?.width, + // styleHeight: component.style?.height, + // finalWidth: `${component.size.width}px`, + // finalHeight: `${component.size.height}px`, + // }); }} > {/* ์œ„์ ฏ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์•„๋‹Œ ๊ฒฝ์šฐ DynamicComponentRenderer ์‚ฌ์šฉ */} diff --git a/frontend/components/screen/ScreenDesigner.tsx b/frontend/components/screen/ScreenDesigner.tsx index 39c8e34e..a0f6ad09 100644 --- a/frontend/components/screen/ScreenDesigner.tsx +++ b/frontend/components/screen/ScreenDesigner.tsx @@ -1809,6 +1809,25 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD filters: [], displayFormat: "simple" as const, }; + case "table": + return { + tableName: "", + displayMode: "table" as const, + showHeader: true, + showFooter: true, + pagination: { + enabled: true, + pageSize: 10, + showPageSizeSelector: true, + showPageInfo: true, + showFirstLast: true, + }, + columns: [], + searchable: true, + sortable: true, + filterable: true, + exportable: true, + }; default: return undefined; } diff --git a/frontend/components/screen/panels/ComponentsPanel.tsx b/frontend/components/screen/panels/ComponentsPanel.tsx index d6daef4e..a779d484 100644 --- a/frontend/components/screen/panels/ComponentsPanel.tsx +++ b/frontend/components/screen/panels/ComponentsPanel.tsx @@ -20,7 +20,30 @@ export function ComponentsPanel({ className }: ComponentsPanelProps) { // ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ์—์„œ ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ ์กฐํšŒ const allComponents = useMemo(() => { - return ComponentRegistry.getAllComponents(); + const components = ComponentRegistry.getAllComponents(); + console.log("๐Ÿ” ComponentsPanel - ๋กœ๋“œ๋œ ์ปดํฌ๋„ŒํŠธ:", components.map(c => ({ id: c.id, name: c.name, category: c.category }))); + + // ์ˆ˜๋™์œผ๋กœ table-list ์ปดํฌ๋„ŒํŠธ ์ถ”๊ฐ€ (์ž„์‹œ) + const hasTableList = components.some(c => c.id === 'table-list'); + if (!hasTableList) { + console.log("โš ๏ธ table-list ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์—†์–ด์„œ ์ˆ˜๋™ ์ถ”๊ฐ€"); + components.push({ + id: "table-list", + name: "ํ…Œ์ด๋ธ” ๋ฆฌ์ŠคํŠธ", + nameEng: "TableList Component", + description: "๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ด๋ธ”์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ชฉ๋ก์œผ๋กœ ํ‘œ์‹œํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ", + category: "display", + webType: "text", + defaultConfig: {}, + defaultSize: { width: 800, height: 400 }, + icon: "Table", + tags: ["ํ…Œ์ด๋ธ”", "๋ฐ์ดํ„ฐ", "๋ชฉ๋ก", "๊ทธ๋ฆฌ๋“œ"], + version: "1.0.0", + author: "๊ฐœ๋ฐœํŒ€", + }); + } + + return components; }, []); // ์นดํ…Œ๊ณ ๋ฆฌ๋ณ„ ๋ถ„๋ฅ˜ (input ์นดํ…Œ๊ณ ๋ฆฌ ์ œ์™ธ) diff --git a/frontend/lib/registry/components/card-display/CardDisplayComponent.tsx b/frontend/lib/registry/components/card-display/CardDisplayComponent.tsx index 2cd69c54..318ca587 100644 --- a/frontend/lib/registry/components/card-display/CardDisplayComponent.tsx +++ b/frontend/lib/registry/components/card-display/CardDisplayComponent.tsx @@ -4,6 +4,10 @@ import React, { useEffect, useState, useMemo } from "react"; import { ComponentRendererProps } from "@/types/component"; import { CardDisplayConfig } from "./types"; import { tableTypeApi } from "@/lib/api/screen"; +import { filterDOMProps } from "@/lib/utils/domPropsFilter"; +import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog"; +import { Input } from "@/components/ui/input"; +import { Button } from "@/components/ui/button"; export interface CardDisplayComponentProps extends ComponentRendererProps { config?: CardDisplayConfig; @@ -39,6 +43,59 @@ export const CardDisplayComponent: React.FC = ({ const [loadedTableColumns, setLoadedTableColumns] = useState([]); const [loading, setLoading] = useState(false); + // ์ƒ์„ธ๋ณด๊ธฐ ๋ชจ๋‹ฌ ์ƒํƒœ + const [viewModalOpen, setViewModalOpen] = useState(false); + const [selectedData, setSelectedData] = useState(null); + + // ํŽธ์ง‘ ๋ชจ๋‹ฌ ์ƒํƒœ + const [editModalOpen, setEditModalOpen] = useState(false); + const [editData, setEditData] = useState(null); + + // ์นด๋“œ ์•ก์…˜ ํ•ธ๋“ค๋Ÿฌ + const handleCardView = (data: any) => { + // console.log("๐Ÿ‘€ ์ƒ์„ธ๋ณด๊ธฐ ํด๋ฆญ:", data); + setSelectedData(data); + setViewModalOpen(true); + }; + + const handleCardEdit = (data: any) => { + // console.log("โœ๏ธ ํŽธ์ง‘ ํด๋ฆญ:", data); + setEditData({ ...data }); // ๋ณต์‚ฌ๋ณธ ์ƒ์„ฑ + setEditModalOpen(true); + }; + + // ํŽธ์ง‘ ํผ ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ ํ•ธ๋“ค๋Ÿฌ + const handleEditFormChange = (key: string, value: string) => { + setEditData((prev: any) => ({ + ...prev, + [key]: value + })); + }; + + // ํŽธ์ง‘ ์ €์žฅ ํ•ธ๋“ค๋Ÿฌ + const handleEditSave = async () => { + // console.log("๐Ÿ’พ ํŽธ์ง‘ ์ €์žฅ:", editData); + + try { + // TODO: ์‹ค์ œ API ํ˜ธ์ถœ๋กœ ๋ฐ์ดํ„ฐ ์—…๋ฐ์ดํŠธ + // await tableTypeApi.updateTableData(tableName, editData); + + // console.log("โœ… ํŽธ์ง‘ ์ €์žฅ ์™„๋ฃŒ"); + alert("โœ… ์ €์žฅ๋˜์—ˆ์Šต๋‹ˆ๋‹ค!"); + + // ๋ชจ๋‹ฌ ๋‹ซ๊ธฐ + setEditModalOpen(false); + setEditData(null); + + // ๋ฐ์ดํ„ฐ ์ƒˆ๋กœ๊ณ ์นจ (ํ•„์š”์‹œ) + // loadTableData(); + + } catch (error) { + console.error("โŒ ํŽธ์ง‘ ์ €์žฅ ์‹คํŒจ:", error); + alert("โŒ ์ €์žฅ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค."); + } + }; + // ํ…Œ์ด๋ธ” ๋ฐ์ดํ„ฐ ๋กœ๋”ฉ useEffect(() => { const loadTableData = async () => { @@ -48,19 +105,25 @@ export const CardDisplayComponent: React.FC = ({ } // tableName ํ™•์ธ (props์—์„œ ์ „๋‹ฌ๋ฐ›์€ tableName ์‚ฌ์šฉ) - const tableNameToUse = tableName || component.componentConfig?.tableName; + const tableNameToUse = tableName || component.componentConfig?.tableName || 'user_info'; // ๊ธฐ๋ณธ ํ…Œ์ด๋ธ”๋ช… ์„ค์ • if (!tableNameToUse) { - console.log("๐Ÿ“‹ CardDisplay: ํ…Œ์ด๋ธ”๋ช…์ด ์„ค์ •๋˜์ง€ ์•Š์Œ", { - tableName, - componentTableName: component.componentConfig?.tableName, - }); + // console.log("๐Ÿ“‹ CardDisplay: ํ…Œ์ด๋ธ”๋ช…์ด ์„ค์ •๋˜์ง€ ์•Š์Œ", { + // tableName, + // componentTableName: component.componentConfig?.tableName, + // }); return; } + // console.log("๐Ÿ“‹ CardDisplay: ์‚ฌ์šฉํ•  ํ…Œ์ด๋ธ”๋ช…", { + // tableName, + // componentTableName: component.componentConfig?.tableName, + // finalTableName: tableNameToUse, + // }); + try { setLoading(true); - console.log(`๐Ÿ“‹ CardDisplay: ${tableNameToUse} ํ…Œ์ด๋ธ” ๋ฐ์ดํ„ฐ ๋กœ๋”ฉ ์‹œ์ž‘`); + // console.log(`๐Ÿ“‹ CardDisplay: ${tableNameToUse} ํ…Œ์ด๋ธ” ๋ฐ์ดํ„ฐ ๋กœ๋”ฉ ์‹œ์ž‘`); // ํ…Œ์ด๋ธ” ๋ฐ์ดํ„ฐ์™€ ์ปฌ๋Ÿผ ์ •๋ณด๋ฅผ ๋ณ‘๋ ฌ๋กœ ๋กœ๋“œ const [dataResponse, columnsResponse] = await Promise.all([ @@ -71,13 +134,13 @@ export const CardDisplayComponent: React.FC = ({ tableTypeApi.getColumns(tableNameToUse), ]); - console.log(`๐Ÿ“‹ CardDisplay: ${tableNameToUse} ๋ฐ์ดํ„ฐ ๋กœ๋”ฉ ์™„๋ฃŒ`, { - total: dataResponse.total, - dataLength: dataResponse.data.length, - columnsLength: columnsResponse.length, - sampleData: dataResponse.data.slice(0, 2), - sampleColumns: columnsResponse.slice(0, 3), - }); + // console.log(`๐Ÿ“‹ CardDisplay: ${tableNameToUse} ๋ฐ์ดํ„ฐ ๋กœ๋”ฉ ์™„๋ฃŒ`, { + // total: dataResponse.total, + // dataLength: dataResponse.data.length, + // columnsLength: columnsResponse.length, + // sampleData: dataResponse.data.slice(0, 2), + // sampleColumns: columnsResponse.slice(0, 3), + // }); setLoadedTableData(dataResponse.data); setLoadedTableColumns(columnsResponse); @@ -130,32 +193,32 @@ export const CardDisplayComponent: React.FC = ({ // ํ‘œ์‹œํ•  ๋ฐ์ดํ„ฐ ๊ฒฐ์ • (๋กœ๋“œ๋œ ํ…Œ์ด๋ธ” ๋ฐ์ดํ„ฐ ์šฐ์„  ์‚ฌ์šฉ) const displayData = useMemo(() => { - console.log("๐Ÿ“‹ CardDisplay: displayData ๊ฒฐ์ • ์ค‘", { - dataSource: componentConfig.dataSource, - loadedTableDataLength: loadedTableData.length, - tableDataLength: tableData.length, - staticDataLength: componentConfig.staticData?.length || 0, - }); + // console.log("๐Ÿ“‹ CardDisplay: displayData ๊ฒฐ์ • ์ค‘", { + // dataSource: componentConfig.dataSource, + // loadedTableDataLength: loadedTableData.length, + // tableDataLength: tableData.length, + // staticDataLength: componentConfig.staticData?.length || 0, + // }); // ๋กœ๋“œ๋œ ํ…Œ์ด๋ธ” ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ์œผ๋ฉด ํ•ญ์ƒ ์šฐ์„  ์‚ฌ์šฉ (dataSource ์„ค์ • ๋ฌด์‹œ) if (loadedTableData.length > 0) { - console.log("๐Ÿ“‹ CardDisplay: ๋กœ๋“œ๋œ ํ…Œ์ด๋ธ” ๋ฐ์ดํ„ฐ ์‚ฌ์šฉ", loadedTableData.slice(0, 2)); + // console.log("๐Ÿ“‹ CardDisplay: ๋กœ๋“œ๋œ ํ…Œ์ด๋ธ” ๋ฐ์ดํ„ฐ ์‚ฌ์šฉ", loadedTableData.slice(0, 2)); return loadedTableData; } // props๋กœ ์ „๋‹ฌ๋ฐ›์€ ํ…Œ์ด๋ธ” ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ์œผ๋ฉด ์‚ฌ์šฉ if (tableData.length > 0) { - console.log("๐Ÿ“‹ CardDisplay: props ํ…Œ์ด๋ธ” ๋ฐ์ดํ„ฐ ์‚ฌ์šฉ", tableData.slice(0, 2)); + // console.log("๐Ÿ“‹ CardDisplay: props ํ…Œ์ด๋ธ” ๋ฐ์ดํ„ฐ ์‚ฌ์šฉ", tableData.slice(0, 2)); return tableData; } if (componentConfig.staticData && componentConfig.staticData.length > 0) { - console.log("๐Ÿ“‹ CardDisplay: ์ •์  ๋ฐ์ดํ„ฐ ์‚ฌ์šฉ", componentConfig.staticData.slice(0, 2)); + // console.log("๐Ÿ“‹ CardDisplay: ์ •์  ๋ฐ์ดํ„ฐ ์‚ฌ์šฉ", componentConfig.staticData.slice(0, 2)); return componentConfig.staticData; } // ๋ฐ์ดํ„ฐ๊ฐ€ ์—†์œผ๋ฉด ๋นˆ ๋ฐฐ์—ด ๋ฐ˜ํ™˜ - console.log("๐Ÿ“‹ CardDisplay: ํ‘œ์‹œํ•  ๋ฐ์ดํ„ฐ๊ฐ€ ์—†์Œ"); + // console.log("๐Ÿ“‹ CardDisplay: ํ‘œ์‹œํ•  ๋ฐ์ดํ„ฐ๊ฐ€ ์—†์Œ"); return []; }, [componentConfig.dataSource, loadedTableData, tableData, componentConfig.staticData]); @@ -260,23 +323,8 @@ export const CardDisplayComponent: React.FC = ({ } }; - // DOM์— ์ „๋‹ฌํ•˜๋ฉด ์•ˆ ๋˜๋Š” React-specific props ํ•„ํ„ฐ๋ง - const { - selectedScreen, - onZoneComponentDrop, - onZoneClick, - componentConfig: _componentConfig, - component: _component, - isSelected: _isSelected, - onClick: _onClick, - onDragStart: _onDragStart, - onDragEnd: _onDragEnd, - size: _size, - position: _position, - style: _style, - onRefresh: _onRefresh, // React DOM ์†์„ฑ์ด ์•„๋‹ˆ๋ฏ€๋กœ ํ•„ํ„ฐ๋ง - ...domProps - } = props; + // DOM ์•ˆ์ „ํ•œ props๋งŒ ํ•„ํ„ฐ๋ง (filterDOMProps ์œ ํ‹ธ๋ฆฌํ‹ฐ ์‚ฌ์šฉ) + const safeDomProps = filterDOMProps(props); return ( <> @@ -301,7 +349,7 @@ export const CardDisplayComponent: React.FC = ({ onClick={handleClick} onDragStart={onDragStart} onDragEnd={onDragEnd} - {...domProps} + {...safeDomProps} >
{displayData.length === 0 ? ( @@ -393,8 +441,24 @@ export const CardDisplayComponent: React.FC = ({ {/* ์นด๋“œ ์•ก์…˜ (์„ ํƒ์‚ฌํ•ญ) */}
- - + +
); @@ -402,6 +466,101 @@ export const CardDisplayComponent: React.FC = ({ )} + + {/* ์ƒ์„ธ๋ณด๊ธฐ ๋ชจ๋‹ฌ */} + + + + + ๐Ÿ“‹ + ์ƒ์„ธ ์ •๋ณด + + + + {selectedData && ( +
+
+ {Object.entries(selectedData) + .filter(([key, value]) => value !== null && value !== undefined && value !== '') + .map(([key, value]) => ( +
+
+ {key.replace(/_/g, ' ')} +
+
+ {String(value)} +
+
+ )) + } +
+ +
+ +
+
+ )} +
+
+ + {/* ํŽธ์ง‘ ๋ชจ๋‹ฌ */} + + + + + โœ๏ธ + ๋ฐ์ดํ„ฐ ํŽธ์ง‘ + + + + {editData && ( +
+
+ {Object.entries(editData) + .filter(([key, value]) => value !== null && value !== undefined) + .map(([key, value]) => ( +
+ + handleEditFormChange(key, e.target.value)} + className="w-full" + placeholder={`${key} ์ž…๋ ฅ`} + /> +
+ )) + } +
+ +
+ + +
+
+ )} +
+
); }; diff --git a/frontend/lib/registry/components/table-list/TableListComponent.tsx b/frontend/lib/registry/components/table-list/TableListComponent.tsx index e78d5c21..03754e7f 100644 --- a/frontend/lib/registry/components/table-list/TableListComponent.tsx +++ b/frontend/lib/registry/components/table-list/TableListComponent.tsx @@ -24,6 +24,7 @@ import { Checkbox } from "@/components/ui/checkbox"; import { cn } from "@/lib/utils"; import { AdvancedSearchFilters } from "@/components/screen/filters/AdvancedSearchFilters"; import { SingleTableWithSticky } from "./SingleTableWithSticky"; +import { CardModeRenderer } from "./CardModeRenderer"; export interface TableListComponentProps { component: any; @@ -1290,6 +1291,29 @@ export const TableListComponent: React.FC = ({
{error}
+ ) : tableConfig.displayMode === "card" ? ( + // ์นด๋“œ ๋ชจ๋“œ ๋ Œ๋”๋ง +
+ { + const rowIndex = data.findIndex(d => d === row); + const rowKey = getRowKey(row, rowIndex); + handleRowSelection(rowKey, selected); + }} + selectedRows={Array.from(selectedRows)} + showActions={tableConfig.actions?.showActions} + /> +
) : needsHorizontalScroll ? ( // ๊ฐ€๋กœ ์Šคํฌ๋กค์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ - ๋‹จ์ผ ํ…Œ์ด๋ธ”์—์„œ sticky ์ปฌ๋Ÿผ ์‚ฌ์šฉ
diff --git a/frontend/lib/registry/components/table-list/TableListConfigPanel.tsx b/frontend/lib/registry/components/table-list/TableListConfigPanel.tsx index e78dcce5..34bf0e2f 100644 --- a/frontend/lib/registry/components/table-list/TableListConfigPanel.tsx +++ b/frontend/lib/registry/components/table-list/TableListConfigPanel.tsx @@ -10,6 +10,7 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { ScrollArea } from "@/components/ui/scroll-area"; +import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; import { TableListConfig, ColumnConfig } from "./types"; import { entityJoinApi } from "@/lib/api/entityJoin"; import { tableTypeApi } from "@/lib/api/screen"; @@ -755,6 +756,188 @@ export const TableListConfigPanel: React.FC = ({ {/* ๊ธฐ๋ณธ ์„ค์ • ํƒญ */} + {/* ํ‘œ์‹œ ๋ชจ๋“œ ์„ค์ • */} + + + ํ‘œ์‹œ ๋ชจ๋“œ + ๋ฐ์ดํ„ฐ๋ฅผ ์–ด๋–ค ํ˜•ํƒœ๋กœ ํ‘œ์‹œํ• ์ง€ ์„ ํƒํ•˜์„ธ์š” + + +
+ + handleChange("displayMode", value)} + > +
+ + +
+
+ + +
+
+
+ + {/* ์นด๋“œ ๋ชจ๋“œ ์„ค์ • */} + {config.displayMode === "card" && ( +
+
+ + +
+
+ + +
+ +
+ + + handleNestedChange("cardConfig", "cardSpacing", parseInt(e.target.value)) + } + min="0" + max="50" + /> +
+
+ +
+ + +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+
+ +
+ + handleNestedChange("cardConfig", "showActions", checked as boolean) + } + /> + +
+
+
+ )} +
+
+ ์—ฐ๊ฒฐ๋œ ํ…Œ์ด๋ธ” diff --git a/frontend/lib/registry/components/table-list/TableListRenderer.tsx b/frontend/lib/registry/components/table-list/TableListRenderer.tsx index 84569200..05f75319 100644 --- a/frontend/lib/registry/components/table-list/TableListRenderer.tsx +++ b/frontend/lib/registry/components/table-list/TableListRenderer.tsx @@ -67,3 +67,16 @@ export class TableListRenderer extends AutoRegisteringComponentRenderer { // ์ž๋™ ๋“ฑ๋ก ์‹คํ–‰ TableListRenderer.registerSelf(); + +// ๊ฐ•์ œ ๋“ฑ๋ก (๋””๋ฒ„๊น…์šฉ) +if (typeof window !== "undefined") { + setTimeout(() => { + try { + console.log("๐Ÿ”„ TableList ๊ฐ•์ œ ๋“ฑ๋ก ์‹œ๋„..."); + TableListRenderer.registerSelf(); + console.log("โœ… TableList ๊ฐ•์ œ ๋“ฑ๋ก ์™„๋ฃŒ"); + } catch (error) { + console.error("โŒ TableList ๊ฐ•์ œ ๋“ฑ๋ก ์‹คํŒจ:", error); + } + }, 1000); +} diff --git a/frontend/lib/registry/components/table-list/index.ts b/frontend/lib/registry/components/table-list/index.ts index 5236b80f..b846e9f6 100644 --- a/frontend/lib/registry/components/table-list/index.ts +++ b/frontend/lib/registry/components/table-list/index.ts @@ -18,9 +18,21 @@ export const TableListDefinition = createComponentDefinition({ nameEng: "TableList Component", description: "๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ด๋ธ”์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ชฉ๋ก์œผ๋กœ ํ‘œ์‹œํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ", category: ComponentCategory.DISPLAY, - webType: "table", + webType: "text", component: TableListWrapper, defaultConfig: { + // ํ‘œ์‹œ ๋ชจ๋“œ ์„ค์ • + displayMode: "table" as const, + + // ์นด๋“œ ๋ชจ๋“œ ๊ธฐ๋ณธ ์„ค์ • + cardConfig: { + idColumn: "id", + titleColumn: "name", + cardsPerRow: 3, + cardSpacing: 16, + showActions: true, + }, + // ํ…Œ์ด๋ธ” ๊ธฐ๋ณธ ์„ค์ • showHeader: true, showFooter: true, diff --git a/frontend/lib/registry/components/table-list/types.ts b/frontend/lib/registry/components/table-list/types.ts index 1067bade..fc120b7c 100644 --- a/frontend/lib/registry/components/table-list/types.ts +++ b/frontend/lib/registry/components/table-list/types.ts @@ -74,6 +74,21 @@ export interface ColumnConfig { autoGeneration?: AutoGenerationConfig; // ์ž๋™์ƒ์„ฑ ์„ค์ • } +/** + * ์นด๋“œ ๋””์Šคํ”Œ๋ ˆ์ด ์„ค์ • + */ +export interface CardDisplayConfig { + idColumn: string; // ID ์ปฌ๋Ÿผ (์‚ฌ๋ฒˆ ๋“ฑ) + titleColumn: string; // ์ œ๋ชฉ ์ปฌ๋Ÿผ (์ด๋ฆ„ ๋“ฑ) + subtitleColumn?: string; // ๋ถ€์ œ๋ชฉ ์ปฌ๋Ÿผ (๋ถ€์„œ ๋“ฑ) + descriptionColumn?: string; // ์„ค๋ช… ์ปฌ๋Ÿผ + imageColumn?: string; // ์ด๋ฏธ์ง€ ์ปฌ๋Ÿผ + cardsPerRow: number; // ํ•œ ํ–‰๋‹น ์นด๋“œ ์ˆ˜ (๊ธฐ๋ณธ: 3) + cardSpacing: number; // ์นด๋“œ ๊ฐ„๊ฒฉ (๊ธฐ๋ณธ: 16px) + showActions: boolean; // ์•ก์…˜ ๋ฒ„ํŠผ ํ‘œ์‹œ ์—ฌ๋ถ€ + cardHeight?: number; // ์นด๋“œ ๋†’์ด (๊ธฐ๋ณธ: auto) +} + /** * ํ•„ํ„ฐ ์„ค์ • */ @@ -147,6 +162,12 @@ export interface CheckboxConfig { * TableList ์ปดํฌ๋„ŒํŠธ ์„ค์ • ํƒ€์ž… */ export interface TableListConfig extends ComponentConfig { + // ํ‘œ์‹œ ๋ชจ๋“œ ์„ค์ • + displayMode?: "table" | "card"; // ๊ธฐ๋ณธ: "table" + + // ์นด๋“œ ๋””์Šคํ”Œ๋ ˆ์ด ์„ค์ • (displayMode๊ฐ€ "card"์ผ ๋•Œ ์‚ฌ์šฉ) + cardConfig?: CardDisplayConfig; + // ํ…Œ์ด๋ธ” ๊ธฐ๋ณธ ์„ค์ • selectedTable?: string; tableName?: string; @@ -175,7 +196,9 @@ export interface TableListConfig extends ComponentConfig { }; // ํŽ˜์ด์ง€๋„ค์ด์…˜ - pagination: PaginationConfig; + pagination: PaginationConfig & { + currentPage?: number; // ํ˜„์žฌ ํŽ˜์ด์ง€ (์ถ”๊ฐ€) + }; // ํ•„ํ„ฐ ์„ค์ • filter: FilterConfig;