Compare commits
No commits in common. "1995adf2457f9f2820738e40860dbd91724b71e5" and "720917fcab951552de1fee709ddbf412d66d5a37" have entirely different histories.
1995adf245
...
720917fcab
|
|
@ -300,31 +300,23 @@ export class DashboardService {
|
||||||
const elementsResult = await PostgreSQLService.query(elementsQuery, [dashboardId]);
|
const elementsResult = await PostgreSQLService.query(elementsQuery, [dashboardId]);
|
||||||
|
|
||||||
// 3. 요소 데이터 변환
|
// 3. 요소 데이터 변환
|
||||||
console.log('📊 대시보드 요소 개수:', elementsResult.rows.length);
|
const elements: DashboardElement[] = elementsResult.rows.map((row: any) => ({
|
||||||
|
id: row.id,
|
||||||
const elements: DashboardElement[] = elementsResult.rows.map((row: any, index: number) => {
|
type: row.element_type,
|
||||||
const element = {
|
subtype: row.element_subtype,
|
||||||
id: row.id,
|
position: {
|
||||||
type: row.element_type,
|
x: row.position_x,
|
||||||
subtype: row.element_subtype,
|
y: row.position_y
|
||||||
position: {
|
},
|
||||||
x: row.position_x,
|
size: {
|
||||||
y: row.position_y
|
width: row.width,
|
||||||
},
|
height: row.height
|
||||||
size: {
|
},
|
||||||
width: row.width,
|
title: row.title,
|
||||||
height: row.height
|
content: row.content,
|
||||||
},
|
dataSource: JSON.parse(row.data_source_config || '{}'),
|
||||||
title: row.title,
|
chartConfig: JSON.parse(row.chart_config || '{}')
|
||||||
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 {
|
return {
|
||||||
id: dashboard.id,
|
id: dashboard.id,
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ services:
|
||||||
- LOG_LEVEL=debug
|
- LOG_LEVEL=debug
|
||||||
- ENCRYPTION_KEY=ilshin-plm-mail-encryption-key-32characters-2024-secure
|
- ENCRYPTION_KEY=ilshin-plm-mail-encryption-key-32characters-2024-secure
|
||||||
- KMA_API_KEY=ogdXr2e9T4iHV69nvV-IwA
|
- KMA_API_KEY=ogdXr2e9T4iHV69nvV-IwA
|
||||||
- ITS_API_KEY=d6b9befec3114d648284674b8fddcc32
|
- ITS_API_KEY=${ITS_API_KEY:-}
|
||||||
- EXPRESSWAY_API_KEY=${EXPRESSWAY_API_KEY:-}
|
- EXPRESSWAY_API_KEY=${EXPRESSWAY_API_KEY:-}
|
||||||
volumes:
|
volumes:
|
||||||
- ../../backend-node:/app # 개발 모드: 코드 변경 시 자동 반영
|
- ../../backend-node:/app # 개발 모드: 코드 변경 시 자동 반영
|
||||||
|
|
|
||||||
|
|
@ -3,115 +3,6 @@
|
||||||
import React, { useState, useEffect, useCallback } from "react";
|
import React, { useState, useEffect, useCallback } from "react";
|
||||||
import { DashboardElement, QueryResult } from "@/components/admin/dashboard/types";
|
import { DashboardElement, QueryResult } from "@/components/admin/dashboard/types";
|
||||||
import { ChartRenderer } from "@/components/admin/dashboard/charts/ChartRenderer";
|
import { ChartRenderer } from "@/components/admin/dashboard/charts/ChartRenderer";
|
||||||
import dynamic from "next/dynamic";
|
|
||||||
|
|
||||||
// 위젯 동적 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 <ExchangeWidget />;
|
|
||||||
case "weather":
|
|
||||||
return <WeatherWidget />;
|
|
||||||
case "calculator":
|
|
||||||
return <CalculatorWidget />;
|
|
||||||
case "clock":
|
|
||||||
return (
|
|
||||||
<div className="flex h-full w-full items-center justify-center bg-gradient-to-br from-blue-400 to-purple-600 p-4 text-white">
|
|
||||||
<div className="text-center">
|
|
||||||
<div className="mb-2 text-3xl">⏰</div>
|
|
||||||
<div className="text-sm">시계 위젯 (개발 예정)</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
case "map-summary":
|
|
||||||
return <MapSummaryWidget element={element} />;
|
|
||||||
case "list-summary":
|
|
||||||
return <ListSummaryWidget element={element} />;
|
|
||||||
case "risk-alert":
|
|
||||||
return <RiskAlertWidget />;
|
|
||||||
case "calendar":
|
|
||||||
return (
|
|
||||||
<div className="flex h-full w-full items-center justify-center bg-gradient-to-br from-green-400 to-teal-600 p-4 text-white">
|
|
||||||
<div className="text-center">
|
|
||||||
<div className="mb-2 text-3xl">📅</div>
|
|
||||||
<div className="text-sm">달력 위젯 (개발 예정)</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
case "status-summary":
|
|
||||||
return <StatusSummaryWidget element={element} />;
|
|
||||||
|
|
||||||
// === 운영/작업 지원 ===
|
|
||||||
case "todo":
|
|
||||||
return <TodoWidget />;
|
|
||||||
case "booking-alert":
|
|
||||||
return <BookingAlertWidget />;
|
|
||||||
case "maintenance":
|
|
||||||
return <MaintenanceWidget />;
|
|
||||||
case "document":
|
|
||||||
return <DocumentWidget />;
|
|
||||||
case "list":
|
|
||||||
return <ListSummaryWidget element={element} />;
|
|
||||||
|
|
||||||
// === 차량 관련 (추가 위젯) ===
|
|
||||||
case "vehicle-status":
|
|
||||||
return <VehicleStatusWidget />;
|
|
||||||
case "vehicle-list":
|
|
||||||
return <VehicleListWidget />;
|
|
||||||
case "vehicle-map":
|
|
||||||
return <VehicleMapOnlyWidget element={element} />;
|
|
||||||
|
|
||||||
// === 배송 관련 (추가 위젯) ===
|
|
||||||
case "delivery-status":
|
|
||||||
return <DeliveryStatusWidget />;
|
|
||||||
case "delivery-status-summary":
|
|
||||||
return <DeliveryStatusSummaryWidget />;
|
|
||||||
case "delivery-today-stats":
|
|
||||||
return <DeliveryTodayStatsWidget />;
|
|
||||||
case "cargo-list":
|
|
||||||
return <CargoListWidget />;
|
|
||||||
case "customer-issues":
|
|
||||||
return <CustomerIssuesWidget />;
|
|
||||||
|
|
||||||
// === 기본 fallback ===
|
|
||||||
default:
|
|
||||||
return (
|
|
||||||
<div className="flex h-full w-full items-center justify-center bg-gradient-to-br from-gray-400 to-gray-600 p-4 text-white">
|
|
||||||
<div className="text-center">
|
|
||||||
<div className="mb-2 text-3xl">❓</div>
|
|
||||||
<div className="text-sm">알 수 없는 위젯 타입: {element.subtype}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
interface DashboardViewerProps {
|
interface DashboardViewerProps {
|
||||||
elements: DashboardElement[];
|
elements: DashboardElement[];
|
||||||
|
|
@ -307,7 +198,18 @@ function ViewerElement({ element, data, isLoading, onRefresh }: ViewerElementPro
|
||||||
<div className="h-[calc(100%-57px)]">
|
<div className="h-[calc(100%-57px)]">
|
||||||
{element.type === "chart" ? (
|
{element.type === "chart" ? (
|
||||||
<ChartRenderer element={element} data={data} width={element.size.width} height={element.size.height - 57} />
|
<ChartRenderer element={element} data={data} width={element.size.width} height={element.size.height - 57} />
|
||||||
) : renderWidget(element)}
|
) : (
|
||||||
|
// 위젯 렌더링
|
||||||
|
<div className="flex h-full w-full items-center justify-center bg-gradient-to-br from-blue-400 to-purple-600 p-4 text-white">
|
||||||
|
<div className="text-center">
|
||||||
|
<div className="mb-2 text-3xl">
|
||||||
|
{element.subtype === "exchange" && "💱"}
|
||||||
|
{element.subtype === "weather" && "☁️"}
|
||||||
|
</div>
|
||||||
|
<div className="text-sm whitespace-pre-line">{element.content}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 로딩 오버레이 */}
|
{/* 로딩 오버레이 */}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
import { DashboardElement } from "@/components/admin/dashboard/types";
|
import { DashboardElement } from "@/components/admin/dashboard/types";
|
||||||
|
|
||||||
// API 기본 설정
|
// API 기본 설정
|
||||||
const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || "/api";
|
const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || "http://localhost:3001/api";
|
||||||
|
|
||||||
// 토큰 가져오기 (실제 인증 시스템에 맞게 수정)
|
// 토큰 가져오기 (실제 인증 시스템에 맞게 수정)
|
||||||
function getAuthToken(): string | null {
|
function getAuthToken(): string | null {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue