diff --git a/backend-node/src/services/DashboardService.ts b/backend-node/src/services/DashboardService.ts
index 6b709235..c25efe4f 100644
--- a/backend-node/src/services/DashboardService.ts
+++ b/backend-node/src/services/DashboardService.ts
@@ -301,29 +301,30 @@ export class DashboardService {
// 3. 요소 데이터 변환
console.log('📊 대시보드 요소 개수:', elementsResult.rows.length);
- if (elementsResult.rows.length > 0) {
- console.log('📊 첫 번째 요소 raw data:', elementsResult.rows[0]);
- }
- const elements: DashboardElement[] = elementsResult.rows.map((row: any) => ({
- id: row.id,
- type: row.element_type,
- subtype: row.element_subtype,
- position: {
- x: row.position_x,
- y: row.position_y
- },
- size: {
- width: row.width,
- height: row.height
- },
- title: row.title,
- content: row.content,
- dataSource: JSON.parse(row.data_source_config || '{}'),
- chartConfig: JSON.parse(row.chart_config || '{}')
- }));
-
- console.log('📊 변환된 첫 번째 요소:', elements[0]);
+ const elements: DashboardElement[] = elementsResult.rows.map((row: any, index: number) => {
+ const element = {
+ id: row.id,
+ type: row.element_type,
+ subtype: row.element_subtype,
+ position: {
+ x: row.position_x,
+ y: row.position_y
+ },
+ size: {
+ width: row.width,
+ height: row.height
+ },
+ title: row.title,
+ content: row.content,
+ dataSource: JSON.parse(row.data_source_config || '{}'),
+ chartConfig: JSON.parse(row.chart_config || '{}')
+ };
+
+ console.log(`📊 위젯 #${index + 1}: type="${element.type}", subtype="${element.subtype}", title="${element.title}"`);
+
+ return element;
+ });
return {
id: dashboard.id,
diff --git a/frontend/components/dashboard/DashboardViewer.tsx b/frontend/components/dashboard/DashboardViewer.tsx
index e94d6fe5..036a18ac 100644
--- a/frontend/components/dashboard/DashboardViewer.tsx
+++ b/frontend/components/dashboard/DashboardViewer.tsx
@@ -5,8 +5,113 @@ import { DashboardElement, QueryResult } from "@/components/admin/dashboard/type
import { ChartRenderer } from "@/components/admin/dashboard/charts/ChartRenderer";
import dynamic from "next/dynamic";
-// 위젯 동적 import
+// 위젯 동적 import - 모든 위젯
const ListSummaryWidget = dynamic(() => import("./widgets/ListSummaryWidget"), { ssr: false });
+const MapSummaryWidget = dynamic(() => import("./widgets/MapSummaryWidget"), { ssr: false });
+const StatusSummaryWidget = dynamic(() => import("./widgets/StatusSummaryWidget"), { ssr: false });
+const RiskAlertWidget = dynamic(() => import("./widgets/RiskAlertWidget"), { ssr: false });
+const WeatherWidget = dynamic(() => import("./widgets/WeatherWidget"), { ssr: false });
+const ExchangeWidget = dynamic(() => import("./widgets/ExchangeWidget"), { ssr: false });
+const VehicleStatusWidget = dynamic(() => import("./widgets/VehicleStatusWidget"), { ssr: false });
+const VehicleListWidget = dynamic(() => import("./widgets/VehicleListWidget"), { ssr: false });
+const VehicleMapOnlyWidget = dynamic(() => import("./widgets/VehicleMapOnlyWidget"), { ssr: false });
+const CargoListWidget = dynamic(() => import("./widgets/CargoListWidget"), { ssr: false });
+const CustomerIssuesWidget = dynamic(() => import("./widgets/CustomerIssuesWidget"), { ssr: false });
+const DeliveryStatusWidget = dynamic(() => import("./widgets/DeliveryStatusWidget"), { ssr: false });
+const DeliveryStatusSummaryWidget = dynamic(() => import("./widgets/DeliveryStatusSummaryWidget"), { ssr: false });
+const DeliveryTodayStatsWidget = dynamic(() => import("./widgets/DeliveryTodayStatsWidget"), { ssr: false });
+const TodoWidget = dynamic(() => import("./widgets/TodoWidget"), { ssr: false });
+const DocumentWidget = dynamic(() => import("./widgets/DocumentWidget"), { ssr: false });
+const BookingAlertWidget = dynamic(() => import("./widgets/BookingAlertWidget"), { ssr: false });
+const MaintenanceWidget = dynamic(() => import("./widgets/MaintenanceWidget"), { ssr: false });
+const CalculatorWidget = dynamic(() => import("./widgets/CalculatorWidget"), { ssr: false });
+
+/**
+ * 위젯 렌더링 함수 - DashboardSidebar의 모든 subtype 처리
+ * ViewerElement에서 사용하기 위해 컴포넌트 외부에 정의
+ */
+function renderWidget(element: DashboardElement) {
+ switch (element.subtype) {
+ // 차트는 ChartRenderer에서 처리됨 (이 함수 호출 안됨)
+
+ // === 위젯 종류 ===
+ case "exchange":
+ return