리스트 카드 렌더링 문제 해결
This commit is contained in:
@@ -352,6 +352,10 @@ export function WidgetConfigSidebar({ element, isOpen, onClose, onApply }: Widge
|
||||
|
||||
console.log("🔧 [WidgetConfigSidebar] handleApply 호출:", {
|
||||
subtype: element.subtype,
|
||||
isMultiDataSourceWidget,
|
||||
dataSources,
|
||||
listConfig,
|
||||
finalChartConfig,
|
||||
customMetricConfig,
|
||||
updatedElement,
|
||||
});
|
||||
|
||||
@@ -37,8 +37,19 @@ export function ListTestWidget({ element }: ListTestWidgetProps) {
|
||||
// // console.log("🧪 ListTestWidget 렌더링!", element);
|
||||
|
||||
const dataSources = useMemo(() => {
|
||||
return element?.dataSources || element?.chartConfig?.dataSources;
|
||||
}, [element?.dataSources, element?.chartConfig?.dataSources]);
|
||||
// 다중 데이터 소스 우선
|
||||
const multiSources = element?.dataSources || element?.chartConfig?.dataSources;
|
||||
if (multiSources && multiSources.length > 0) {
|
||||
return multiSources;
|
||||
}
|
||||
|
||||
// 단일 데이터 소스 fallback (배열로 변환)
|
||||
if (element?.dataSource) {
|
||||
return [element.dataSource];
|
||||
}
|
||||
|
||||
return [];
|
||||
}, [element?.dataSources, element?.chartConfig?.dataSources, element?.dataSource]);
|
||||
|
||||
// // console.log("📊 dataSources 확인:", {
|
||||
// hasDataSources: !!dataSources,
|
||||
@@ -58,6 +69,27 @@ export function ListTestWidget({ element }: ListTestWidgetProps) {
|
||||
cardColumns: 3,
|
||||
};
|
||||
|
||||
// visible 컬럼 설정 객체 배열 (field + label)
|
||||
const visibleColumnConfigs = useMemo(() => {
|
||||
if (config.columns && config.columns.length > 0 && typeof config.columns[0] === "object") {
|
||||
return config.columns.filter((col: any) => col.visible !== false);
|
||||
}
|
||||
return [];
|
||||
}, [config.columns]);
|
||||
|
||||
// 표시할 컬럼 필드명 (데이터 접근용)
|
||||
const displayColumns = useMemo(() => {
|
||||
if (!data?.columns) return [];
|
||||
|
||||
// 컬럼 설정이 있으면 field 사용
|
||||
if (visibleColumnConfigs.length > 0) {
|
||||
return visibleColumnConfigs.map((col: any) => col.field);
|
||||
}
|
||||
|
||||
// 자동 모드: 모든 컬럼 표시
|
||||
return data.columns;
|
||||
}, [data?.columns, visibleColumnConfigs]);
|
||||
|
||||
// 다중 데이터 소스 로딩
|
||||
const loadMultipleDataSources = useCallback(async () => {
|
||||
if (!dataSources || dataSources.length === 0) {
|
||||
@@ -313,50 +345,66 @@ export function ListTestWidget({ element }: ListTestWidgetProps) {
|
||||
const paginatedRows = data?.rows.slice(startIndex, endIndex) || [];
|
||||
|
||||
// 테이블 뷰
|
||||
const renderTable = () => (
|
||||
<div className="overflow-auto">
|
||||
<Table>
|
||||
{config.showHeader && (
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
{data?.columns.map((col) => (
|
||||
<TableHead key={col} className="whitespace-nowrap">
|
||||
{col}
|
||||
</TableHead>
|
||||
))}
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
)}
|
||||
<TableBody>
|
||||
{paginatedRows.map((row, idx) => (
|
||||
<TableRow key={idx} className={config.stripedRows && idx % 2 === 0 ? "bg-muted/50" : ""}>
|
||||
{data?.columns.map((col) => (
|
||||
<TableCell key={col} className="whitespace-nowrap">
|
||||
{String(row[col] ?? "")}
|
||||
</TableCell>
|
||||
))}
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
);
|
||||
const renderTable = () => {
|
||||
// 헤더명 가져오기 (label 우선, 없으면 field 그대로)
|
||||
const getHeaderLabel = (field: string) => {
|
||||
const colConfig = visibleColumnConfigs.find((col: any) => col.field === field);
|
||||
return colConfig?.label || field;
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="overflow-auto">
|
||||
<Table>
|
||||
{config.showHeader && (
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
{displayColumns.map((field) => (
|
||||
<TableHead key={field} className="whitespace-nowrap">
|
||||
{getHeaderLabel(field)}
|
||||
</TableHead>
|
||||
))}
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
)}
|
||||
<TableBody>
|
||||
{paginatedRows.map((row, idx) => (
|
||||
<TableRow key={idx} className={config.stripedRows && idx % 2 === 0 ? "bg-muted/50" : ""}>
|
||||
{displayColumns.map((field) => (
|
||||
<TableCell key={field} className="whitespace-nowrap">
|
||||
{String(row[field] ?? "")}
|
||||
</TableCell>
|
||||
))}
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
// 카드 뷰
|
||||
const renderCards = () => (
|
||||
<div className={`grid gap-4 grid-cols-1 md:grid-cols-${config.cardColumns || 3}`}>
|
||||
{paginatedRows.map((row, idx) => (
|
||||
<Card key={idx} className="p-4">
|
||||
{data?.columns.map((col) => (
|
||||
<div key={col} className="mb-2">
|
||||
<span className="font-semibold">{col}: </span>
|
||||
<span>{String(row[col] ?? "")}</span>
|
||||
</div>
|
||||
))}
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
const renderCards = () => {
|
||||
// 헤더명 가져오기 (label 우선, 없으면 field 그대로)
|
||||
const getLabel = (field: string) => {
|
||||
const colConfig = visibleColumnConfigs.find((col: any) => col.field === field);
|
||||
return colConfig?.label || field;
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={`grid gap-4 grid-cols-1 md:grid-cols-${config.cardColumns || 3}`}>
|
||||
{paginatedRows.map((row, idx) => (
|
||||
<Card key={idx} className="p-4">
|
||||
{displayColumns.map((field) => (
|
||||
<div key={field} className="mb-2">
|
||||
<span className="font-semibold">{getLabel(field)}: </span>
|
||||
<span>{String(row[field] ?? "")}</span>
|
||||
</div>
|
||||
))}
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex h-full flex-col bg-card shadow-sm">
|
||||
@@ -396,7 +444,7 @@ export function ListTestWidget({ element }: ListTestWidgetProps) {
|
||||
<div className="flex h-full items-center justify-center">
|
||||
<p className="text-sm text-destructive">{error}</p>
|
||||
</div>
|
||||
) : !(element?.dataSources || element?.chartConfig?.dataSources) || (element?.dataSources || element?.chartConfig?.dataSources)?.length === 0 ? (
|
||||
) : !dataSources || dataSources.length === 0 ? (
|
||||
<div className="flex h-full items-center justify-center">
|
||||
<p className="text-sm text-muted-foreground">
|
||||
데이터 소스를 연결해주세요
|
||||
|
||||
Reference in New Issue
Block a user