From 4b52fe63941f809aac2e714019ec1f2494273e44 Mon Sep 17 00:00:00 2001 From: dohyeons Date: Fri, 24 Oct 2025 16:08:57 +0900 Subject: [PATCH] =?UTF-8?q?getApiUrl=20=EC=82=AC=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dashboard/widgets/CargoListWidget.tsx | 3 +- .../dashboard/widgets/CustomStatsWidget.tsx | 3 +- .../widgets/CustomerIssuesWidget.tsx | 3 +- .../widgets/DeliveryStatusSummaryWidget.tsx | 3 +- .../widgets/DeliveryStatusWidget.tsx | 101 +++++---- .../widgets/DeliveryTodayStatsWidget.tsx | 3 +- .../dashboard/widgets/ListSummaryWidget.tsx | 3 +- .../dashboard/widgets/MapSummaryWidget.tsx | 197 ++++++++++++------ .../dashboard/widgets/StatusSummaryWidget.tsx | 3 +- .../widgets/TransportStatsWidget.tsx | 3 +- .../dashboard/widgets/VehicleListWidget.tsx | 20 +- .../widgets/VehicleMapOnlyWidget.tsx | 3 +- .../dashboard/widgets/VehicleStatusWidget.tsx | 66 +++--- .../dashboard/widgets/WorkHistoryWidget.tsx | 3 +- 14 files changed, 245 insertions(+), 169 deletions(-) diff --git a/frontend/components/dashboard/widgets/CargoListWidget.tsx b/frontend/components/dashboard/widgets/CargoListWidget.tsx index 5c8682c6..0d763933 100644 --- a/frontend/components/dashboard/widgets/CargoListWidget.tsx +++ b/frontend/components/dashboard/widgets/CargoListWidget.tsx @@ -2,6 +2,7 @@ import React, { useState, useEffect } from "react"; import { DashboardElement } from "@/components/admin/dashboard/types"; +import { getApiUrl } from "@/lib/utils/apiUrl"; interface CargoListWidgetProps { element: DashboardElement; @@ -47,7 +48,7 @@ export default function CargoListWidget({ element }: CargoListWidgetProps) { try { setLoading(true); const token = localStorage.getItem("authToken"); - const response = await fetch("/api/dashboards/execute-query", { + const response = await fetch(getApiUrl("/api/dashboards/execute-query"), { method: "POST", headers: { "Content-Type": "application/json", diff --git a/frontend/components/dashboard/widgets/CustomStatsWidget.tsx b/frontend/components/dashboard/widgets/CustomStatsWidget.tsx index a42be32e..f2d5e2ff 100644 --- a/frontend/components/dashboard/widgets/CustomStatsWidget.tsx +++ b/frontend/components/dashboard/widgets/CustomStatsWidget.tsx @@ -9,6 +9,7 @@ import React, { useState, useEffect } from "react"; import { DashboardElement } from "@/components/admin/dashboard/types"; +import { getApiUrl } from "@/lib/utils/apiUrl"; interface CustomStatsWidgetProps { element?: DashboardElement; @@ -77,7 +78,7 @@ export default function CustomStatsWidget({ element, refreshInterval = 60000 }: // 쿼리 실행하여 통계 계산 const token = localStorage.getItem("authToken"); - const response = await fetch("/api/dashboards/execute-query", { + const response = await fetch(getApiUrl("/api/dashboards/execute-query"), { method: "POST", headers: { "Content-Type": "application/json", diff --git a/frontend/components/dashboard/widgets/CustomerIssuesWidget.tsx b/frontend/components/dashboard/widgets/CustomerIssuesWidget.tsx index 56879e29..2af5caef 100644 --- a/frontend/components/dashboard/widgets/CustomerIssuesWidget.tsx +++ b/frontend/components/dashboard/widgets/CustomerIssuesWidget.tsx @@ -2,6 +2,7 @@ import React, { useState, useEffect } from "react"; import { DashboardElement } from "@/components/admin/dashboard/types"; +import { getApiUrl } from "@/lib/utils/apiUrl"; interface CustomerIssuesWidgetProps { element: DashboardElement; @@ -49,7 +50,7 @@ export default function CustomerIssuesWidget({ element }: CustomerIssuesWidgetPr try { setLoading(true); const token = localStorage.getItem("authToken"); - const response = await fetch("/api/dashboards/execute-query", { + const response = await fetch(getApiUrl("/api/dashboards/execute-query"), { method: "POST", headers: { "Content-Type": "application/json", diff --git a/frontend/components/dashboard/widgets/DeliveryStatusSummaryWidget.tsx b/frontend/components/dashboard/widgets/DeliveryStatusSummaryWidget.tsx index 0d517afd..673a857a 100644 --- a/frontend/components/dashboard/widgets/DeliveryStatusSummaryWidget.tsx +++ b/frontend/components/dashboard/widgets/DeliveryStatusSummaryWidget.tsx @@ -2,6 +2,7 @@ import React, { useState, useEffect } from "react"; import { DashboardElement } from "@/components/admin/dashboard/types"; +import { getApiUrl } from "@/lib/utils/apiUrl"; interface DeliveryStatusSummaryWidgetProps { element: DashboardElement; @@ -39,7 +40,7 @@ export default function DeliveryStatusSummaryWidget({ element }: DeliveryStatusS try { setLoading(true); const token = localStorage.getItem("authToken"); - const response = await fetch("/api/dashboards/execute-query", { + const response = await fetch(getApiUrl("/api/dashboards/execute-query"), { method: "POST", headers: { "Content-Type": "application/json", diff --git a/frontend/components/dashboard/widgets/DeliveryStatusWidget.tsx b/frontend/components/dashboard/widgets/DeliveryStatusWidget.tsx index 45b4f839..fd9fe7b2 100644 --- a/frontend/components/dashboard/widgets/DeliveryStatusWidget.tsx +++ b/frontend/components/dashboard/widgets/DeliveryStatusWidget.tsx @@ -3,6 +3,7 @@ import React, { useState, useEffect } from "react"; import { Button } from "@/components/ui/button"; import { RefreshCw, Package, TruckIcon, AlertTriangle, CheckCircle, Clock, XCircle } from "lucide-react"; +import { getApiUrl } from "@/lib/utils/apiUrl"; interface DeliveryItem { id: string; @@ -50,7 +51,7 @@ export default function DeliveryStatusWidget({ element, refreshInterval = 60000 } try { - const response = await fetch("/api/dashboards/execute-query", { + const response = await fetch(getApiUrl("/api/dashboards/execute-query"), { method: "POST", headers: { "Content-Type": "application/json", @@ -266,14 +267,13 @@ export default function DeliveryStatusWidget({ element, refreshInterval = 60000 }; // 필터링된 배송 목록 - const filteredDeliveries = selectedStatus === "all" - ? deliveries - : deliveries.filter((d) => d.status === selectedStatus); + const filteredDeliveries = + selectedStatus === "all" ? deliveries : deliveries.filter((d) => d.status === selectedStatus); // 오늘 통계 계산 const today = new Date(); today.setHours(0, 0, 0, 0); - + const todayStats = { // 오늘 발송 건수 (created_at이 오늘인 것) shipped: deliveries.filter((d: any) => { @@ -293,22 +293,14 @@ export default function DeliveryStatusWidget({ element, refreshInterval = 60000 }; return ( -
+
{/* 헤더 */}

📦 배송 / 화물 처리 현황

-

- 마지막 업데이트: {lastUpdate.toLocaleTimeString("ko-KR")} -

+

마지막 업데이트: {lastUpdate.toLocaleTimeString("ko-KR")}

-
@@ -316,60 +308,60 @@ export default function DeliveryStatusWidget({ element, refreshInterval = 60000 {/* 배송 상태 요약 */}

배송 상태 요약 (클릭하여 필터링)

-
+
@@ -379,13 +371,13 @@ export default function DeliveryStatusWidget({ element, refreshInterval = 60000

오늘 처리 현황

-
-
발송 건수
+
+
발송 건수
{todayStats.shipped}
-
-
도착 건수
+
+
도착 건수
{todayStats.delivered}
@@ -394,7 +386,7 @@ export default function DeliveryStatusWidget({ element, refreshInterval = 60000 {/* 필터링된 화물 리스트 */}
-

+

{selectedStatus === "all" && `전체 화물 (${filteredDeliveries.length})`} {selectedStatus === "in_transit" && `배송 중인 화물 (${filteredDeliveries.length})`} @@ -402,31 +394,35 @@ export default function DeliveryStatusWidget({ element, refreshInterval = 60000 {selectedStatus === "delayed" && `지연 중인 화물 (${filteredDeliveries.length})`} {selectedStatus === "pickup_waiting" && `픽업 대기 (${filteredDeliveries.length})`}

-
+
{filteredDeliveries.length === 0 ? (
{selectedStatus === "all" ? "화물이 없습니다" : "해당 상태의 화물이 없습니다"}
) : ( -
+
{filteredDeliveries.map((delivery) => (
-
+
-
{delivery.customer}
+
{delivery.customer}
{delivery.trackingNumber}
- + {getStatusText(delivery.status)}
-
+
경로: - {delivery.origin} → {delivery.destination} + + {delivery.origin} → {delivery.destination} +
예정: @@ -449,37 +445,37 @@ export default function DeliveryStatusWidget({ element, refreshInterval = 60000 {/* 고객 클레임/이슈 리포트 */}
-

+

고객 클레임/이슈 ({issues.filter((i) => i.status !== "resolved").length})

-
+
{issues.length === 0 ? ( -
- 이슈가 없습니다 -
+
이슈가 없습니다
) : ( -
+
{issues.map((issue) => (
-
+
-
{issue.customer}
+
{issue.customer}
{issue.trackingNumber}
- + {getIssueTypeText(issue.issueType)} - + {getIssueStatusText(issue.status)}
-
+
{issue.description}
접수: {issue.reportedAt}
@@ -492,4 +488,3 @@ export default function DeliveryStatusWidget({ element, refreshInterval = 60000
); } - diff --git a/frontend/components/dashboard/widgets/DeliveryTodayStatsWidget.tsx b/frontend/components/dashboard/widgets/DeliveryTodayStatsWidget.tsx index bfc7d8a6..21fb96ff 100644 --- a/frontend/components/dashboard/widgets/DeliveryTodayStatsWidget.tsx +++ b/frontend/components/dashboard/widgets/DeliveryTodayStatsWidget.tsx @@ -2,6 +2,7 @@ import React, { useState, useEffect } from "react"; import { DashboardElement } from "@/components/admin/dashboard/types"; +import { getApiUrl } from "@/lib/utils/apiUrl"; interface DeliveryTodayStatsWidgetProps { element: DashboardElement; @@ -40,7 +41,7 @@ export default function DeliveryTodayStatsWidget({ element }: DeliveryTodayStats try { setLoading(true); const token = localStorage.getItem("authToken"); - const response = await fetch("/api/dashboards/execute-query", { + const response = await fetch(getApiUrl("/api/dashboards/execute-query"), { method: "POST", headers: { "Content-Type": "application/json", diff --git a/frontend/components/dashboard/widgets/ListSummaryWidget.tsx b/frontend/components/dashboard/widgets/ListSummaryWidget.tsx index dd5362c5..a1613cdf 100644 --- a/frontend/components/dashboard/widgets/ListSummaryWidget.tsx +++ b/frontend/components/dashboard/widgets/ListSummaryWidget.tsx @@ -8,6 +8,7 @@ import React, { useState, useEffect } from "react"; import { DashboardElement } from "@/components/admin/dashboard/types"; +import { getApiUrl } from "@/lib/utils/apiUrl"; interface ListSummaryWidgetProps { element: DashboardElement; @@ -128,7 +129,7 @@ export default function ListSummaryWidget({ element }: ListSummaryWidgetProps) { setTableName(extractedTableName); const token = localStorage.getItem("authToken"); - const response = await fetch("/api/dashboards/execute-query", { + const response = await fetch(getApiUrl("/api/dashboards/execute-query"), { method: "POST", headers: { "Content-Type": "application/json", diff --git a/frontend/components/dashboard/widgets/MapSummaryWidget.tsx b/frontend/components/dashboard/widgets/MapSummaryWidget.tsx index 683ccb56..58c49814 100644 --- a/frontend/components/dashboard/widgets/MapSummaryWidget.tsx +++ b/frontend/components/dashboard/widgets/MapSummaryWidget.tsx @@ -7,6 +7,7 @@ import { getWeather, WeatherData, getWeatherAlerts, WeatherAlert } from "@/lib/a import { Cloud, CloudRain, CloudSnow, Sun, Wind, AlertTriangle } from "lucide-react"; import turfUnion from "@turf/union"; import { polygon } from "@turf/helpers"; +import { getApiUrl } from "@/lib/utils/apiUrl"; import "leaflet/dist/leaflet.css"; // Leaflet 아이콘 경로 설정 (엑박 방지) @@ -72,80 +73,140 @@ const CITY_COORDINATES = [ { name: "광주", lat: 35.1595, lng: 126.8526 }, { name: "대전", lat: 36.3504, lng: 127.3845 }, { name: "울산", lat: 35.5384, lng: 129.3114 }, - { name: "세종", lat: 36.4800, lng: 127.2890 }, + { name: "세종", lat: 36.48, lng: 127.289 }, { name: "제주", lat: 33.4996, lng: 126.5312 }, ]; // 해상 구역 폴리곤 좌표 (기상청 특보 구역 기준 - 깔끔한 사각형) const MARITIME_ZONES: Record> = { // 제주도 해역 - "제주도남부앞바다": [ - [33.25, 126.0], [33.25, 126.85], [33.0, 126.85], [33.0, 126.0] + 제주도남부앞바다: [ + [33.25, 126.0], + [33.25, 126.85], + [33.0, 126.85], + [33.0, 126.0], ], - "제주도남쪽바깥먼바다": [ - [33.15, 125.7], [33.15, 127.3], [32.5, 127.3], [32.5, 125.7] + 제주도남쪽바깥먼바다: [ + [33.15, 125.7], + [33.15, 127.3], + [32.5, 127.3], + [32.5, 125.7], ], - "제주도동부앞바다": [ - [33.4, 126.7], [33.4, 127.25], [33.05, 127.25], [33.05, 126.7] + 제주도동부앞바다: [ + [33.4, 126.7], + [33.4, 127.25], + [33.05, 127.25], + [33.05, 126.7], ], - "제주도남동쪽안쪽먼바다": [ - [33.3, 126.85], [33.3, 127.95], [32.65, 127.95], [32.65, 126.85] + 제주도남동쪽안쪽먼바다: [ + [33.3, 126.85], + [33.3, 127.95], + [32.65, 127.95], + [32.65, 126.85], ], - "제주도남서쪽안쪽먼바다": [ - [33.3, 125.35], [33.3, 126.45], [32.7, 126.45], [32.7, 125.35] + 제주도남서쪽안쪽먼바다: [ + [33.3, 125.35], + [33.3, 126.45], + [32.7, 126.45], + [32.7, 125.35], ], - + // 남해 해역 - "남해동부앞바다": [ - [34.65, 128.3], [34.65, 129.65], [33.95, 129.65], [33.95, 128.3] + 남해동부앞바다: [ + [34.65, 128.3], + [34.65, 129.65], + [33.95, 129.65], + [33.95, 128.3], ], - "남해동부안쪽먼바다": [ - [34.25, 127.95], [34.25, 129.75], [33.45, 129.75], [33.45, 127.95] + 남해동부안쪽먼바다: [ + [34.25, 127.95], + [34.25, 129.75], + [33.45, 129.75], + [33.45, 127.95], ], - "남해동부바깥먼바다": [ - [33.65, 127.95], [33.65, 130.35], [32.45, 130.35], [32.45, 127.95] + 남해동부바깥먼바다: [ + [33.65, 127.95], + [33.65, 130.35], + [32.45, 130.35], + [32.45, 127.95], ], - + // 동해 해역 - "경북북부앞바다": [ - [36.65, 129.2], [36.65, 130.1], [35.95, 130.1], [35.95, 129.2] + 경북북부앞바다: [ + [36.65, 129.2], + [36.65, 130.1], + [35.95, 130.1], + [35.95, 129.2], ], - "경북남부앞바다": [ - [36.15, 129.1], [36.15, 129.95], [35.45, 129.95], [35.45, 129.1] + 경북남부앞바다: [ + [36.15, 129.1], + [36.15, 129.95], + [35.45, 129.95], + [35.45, 129.1], ], - "동해남부남쪽안쪽먼바다": [ - [35.65, 129.35], [35.65, 130.65], [34.95, 130.65], [34.95, 129.35] + 동해남부남쪽안쪽먼바다: [ + [35.65, 129.35], + [35.65, 130.65], + [34.95, 130.65], + [34.95, 129.35], ], - "동해남부남쪽바깥먼바다": [ - [35.25, 129.45], [35.25, 131.15], [34.15, 131.15], [34.15, 129.45] + 동해남부남쪽바깥먼바다: [ + [35.25, 129.45], + [35.25, 131.15], + [34.15, 131.15], + [34.15, 129.45], ], - "동해남부북쪽안쪽먼바다": [ - [36.6, 129.65], [36.6, 130.95], [35.85, 130.95], [35.85, 129.65] + 동해남부북쪽안쪽먼바다: [ + [36.6, 129.65], + [36.6, 130.95], + [35.85, 130.95], + [35.85, 129.65], ], - "동해남부북쪽바깥먼바다": [ - [36.65, 130.35], [36.65, 132.15], [35.85, 132.15], [35.85, 130.35] + 동해남부북쪽바깥먼바다: [ + [36.65, 130.35], + [36.65, 132.15], + [35.85, 132.15], + [35.85, 130.35], ], - + // 강원 해역 - "강원북부앞바다": [ - [38.15, 128.4], [38.15, 129.55], [37.45, 129.55], [37.45, 128.4] + 강원북부앞바다: [ + [38.15, 128.4], + [38.15, 129.55], + [37.45, 129.55], + [37.45, 128.4], ], - "강원중부앞바다": [ - [37.65, 128.7], [37.65, 129.6], [36.95, 129.6], [36.95, 128.7] + 강원중부앞바다: [ + [37.65, 128.7], + [37.65, 129.6], + [36.95, 129.6], + [36.95, 128.7], ], - "강원남부앞바다": [ - [37.15, 128.9], [37.15, 129.85], [36.45, 129.85], [36.45, 128.9] + 강원남부앞바다: [ + [37.15, 128.9], + [37.15, 129.85], + [36.45, 129.85], + [36.45, 128.9], ], - "동해중부안쪽먼바다": [ - [38.55, 129.35], [38.55, 131.15], [37.25, 131.15], [37.25, 129.35] + 동해중부안쪽먼바다: [ + [38.55, 129.35], + [38.55, 131.15], + [37.25, 131.15], + [37.25, 129.35], ], - "동해중부바깥먼바다": [ - [38.6, 130.35], [38.6, 132.55], [37.65, 132.55], [37.65, 130.35] + 동해중부바깥먼바다: [ + [38.6, 130.35], + [38.6, 132.55], + [37.65, 132.55], + [37.65, 130.35], ], - + // 울릉도·독도 "울릉도.독도": [ - [37.7, 130.7], [37.7, 132.0], [37.4, 132.0], [37.4, 130.7] + [37.7, 130.7], + [37.7, 132.0], + [37.4, 132.0], + [37.4, 130.7], ], }; @@ -156,10 +217,7 @@ const getDistance = (lat1: number, lng1: number, lat2: number, lng2: number): nu const dLng = ((lng2 - lng1) * Math.PI) / 180; const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + - Math.cos((lat1 * Math.PI) / 180) * - Math.cos((lat2 * Math.PI) / 180) * - Math.sin(dLng / 2) * - Math.sin(dLng / 2); + Math.cos((lat1 * Math.PI) / 180) * Math.cos((lat2 * Math.PI) / 180) * Math.sin(dLng / 2) * Math.sin(dLng / 2); const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); return R * c; }; @@ -235,7 +293,7 @@ export default function MapSummaryWidget({ element }: MapSummaryWidgetProps) { useEffect(() => { console.log("🗺️ MapSummaryWidget 초기화"); console.log("🗺️ showWeatherAlerts:", element.chartConfig?.showWeatherAlerts); - + // GeoJSON 데이터 로드 loadGeoJsonData(); @@ -390,7 +448,7 @@ export default function MapSummaryWidget({ element }: MapSummaryWidgetProps) { setTableName(extractedTableName); const token = localStorage.getItem("authToken"); - const response = await fetch("/api/dashboards/execute-query", { + const response = await fetch(getApiUrl("/api/dashboards/execute-query"), { method: "POST", headers: { "Content-Type": "application/json", @@ -557,13 +615,15 @@ export default function MapSummaryWidget({ element }: MapSummaryWidgetProps) { )} {/* 기상특보 영역 표시 (해상 - Polygon 레이어) - 개별 표시 */} - {element.chartConfig?.showWeatherAlerts && weatherAlerts && weatherAlerts.length > 0 && + {element.chartConfig?.showWeatherAlerts && + weatherAlerts && + weatherAlerts.length > 0 && weatherAlerts .filter((alert) => MARITIME_ZONES[alert.location]) .map((alert, idx) => { const coordinates = MARITIME_ZONES[alert.location]; const alertColor = getAlertColor(alert.severity); - + return (
-
+
⚠️ {alert.location}
-
-
- {alert.title} -
+
+
{alert.title}
{alert.description}
@@ -616,8 +690,7 @@ export default function MapSummaryWidget({ element }: MapSummaryWidgetProps) { ); - }) - } + })} {/* 마커 표시 */} {markers.map((marker, idx) => ( @@ -672,7 +745,7 @@ export default function MapSummaryWidget({ element }: MapSummaryWidgetProps) { {/* 범례 (특보가 있을 때만 표시) */} {element.chartConfig?.showWeatherAlerts && weatherAlerts && weatherAlerts.length > 0 && ( -
+
기상특보 @@ -691,9 +764,7 @@ export default function MapSummaryWidget({ element }: MapSummaryWidgetProps) { 약한 주의보
-
- 총 {weatherAlerts.length}건 발효 중 -
+
총 {weatherAlerts.length}건 발효 중
)}
diff --git a/frontend/components/dashboard/widgets/StatusSummaryWidget.tsx b/frontend/components/dashboard/widgets/StatusSummaryWidget.tsx index 69629bd9..e5c67009 100644 --- a/frontend/components/dashboard/widgets/StatusSummaryWidget.tsx +++ b/frontend/components/dashboard/widgets/StatusSummaryWidget.tsx @@ -2,6 +2,7 @@ import React, { useState, useEffect } from "react"; import { DashboardElement } from "@/components/admin/dashboard/types"; +import { getApiUrl } from "@/lib/utils/apiUrl"; interface StatusSummaryWidgetProps { element: DashboardElement; @@ -180,7 +181,7 @@ export default function StatusSummaryWidget({ setTableName(extractedTableName); const token = localStorage.getItem("authToken"); - const response = await fetch("/api/dashboards/execute-query", { + const response = await fetch(getApiUrl("/api/dashboards/execute-query"), { method: "POST", headers: { "Content-Type": "application/json", diff --git a/frontend/components/dashboard/widgets/TransportStatsWidget.tsx b/frontend/components/dashboard/widgets/TransportStatsWidget.tsx index 39fa6651..47501e48 100644 --- a/frontend/components/dashboard/widgets/TransportStatsWidget.tsx +++ b/frontend/components/dashboard/widgets/TransportStatsWidget.tsx @@ -10,6 +10,7 @@ import { useState, useEffect } from "react"; import { DashboardElement } from "@/components/admin/dashboard/types"; +import { getApiUrl } from "@/lib/utils/apiUrl"; interface TransportStatsWidgetProps { element?: DashboardElement; @@ -53,7 +54,7 @@ export default function TransportStatsWidget({ element, refreshInterval = 60000 // 쿼리 실행하여 통계 계산 const token = localStorage.getItem("authToken"); - const response = await fetch("/api/dashboards/execute-query", { + const response = await fetch(getApiUrl("/api/dashboards/execute-query"), { method: "POST", headers: { "Content-Type": "application/json", diff --git a/frontend/components/dashboard/widgets/VehicleListWidget.tsx b/frontend/components/dashboard/widgets/VehicleListWidget.tsx index d15d8ffa..701b46db 100644 --- a/frontend/components/dashboard/widgets/VehicleListWidget.tsx +++ b/frontend/components/dashboard/widgets/VehicleListWidget.tsx @@ -3,6 +3,7 @@ import React, { useState, useEffect } from "react"; import { RefreshCw, Truck, Navigation, Gauge } from "lucide-react"; import { Button } from "@/components/ui/button"; +import { getApiUrl } from "@/lib/utils/apiUrl"; interface Vehicle { id: string; @@ -35,11 +36,11 @@ export default function VehicleListWidget({ element, refreshInterval = 30000 }: setIsLoading(false); return; } - + const query = element.dataSource.query; try { - const response = await fetch("/api/dashboards/execute-query", { + const response = await fetch(getApiUrl("/api/dashboards/execute-query"), { method: "POST", headers: { "Content-Type": "application/json", @@ -109,7 +110,7 @@ export default function VehicleListWidget({ element, refreshInterval = 30000 }:
- + {getStatusText(vehicle.status)}
@@ -201,4 +204,3 @@ export default function VehicleListWidget({ element, refreshInterval = 30000 }:
); } - diff --git a/frontend/components/dashboard/widgets/VehicleMapOnlyWidget.tsx b/frontend/components/dashboard/widgets/VehicleMapOnlyWidget.tsx index 34f7a46b..1a41b815 100644 --- a/frontend/components/dashboard/widgets/VehicleMapOnlyWidget.tsx +++ b/frontend/components/dashboard/widgets/VehicleMapOnlyWidget.tsx @@ -4,6 +4,7 @@ import React, { useState, useEffect } from "react"; import dynamic from "next/dynamic"; import { Button } from "@/components/ui/button"; import { RefreshCw } from "lucide-react"; +import { getApiUrl } from "@/lib/utils/apiUrl"; import "leaflet/dist/leaflet.css"; // Leaflet 아이콘 경로 설정 (엑박 방지) @@ -66,7 +67,7 @@ export default function VehicleMapOnlyWidget({ element, refreshInterval = 30000 } try { - const response = await fetch("/api/dashboards/execute-query", { + const response = await fetch(getApiUrl("/api/dashboards/execute-query"), { method: "POST", headers: { "Content-Type": "application/json", diff --git a/frontend/components/dashboard/widgets/VehicleStatusWidget.tsx b/frontend/components/dashboard/widgets/VehicleStatusWidget.tsx index 3eaefdc6..bbf6ca53 100644 --- a/frontend/components/dashboard/widgets/VehicleStatusWidget.tsx +++ b/frontend/components/dashboard/widgets/VehicleStatusWidget.tsx @@ -3,6 +3,7 @@ import React, { useState, useEffect } from "react"; import { RefreshCw, TrendingUp, TrendingDown } from "lucide-react"; import { Button } from "@/components/ui/button"; +import { getApiUrl } from "@/lib/utils/apiUrl"; interface VehicleStatusWidgetProps { element?: any; // 대시보드 요소 (dataSource 포함) @@ -36,11 +37,11 @@ export default function VehicleStatusWidget({ element, refreshInterval = 30000 } setIsLoading(false); return; } - + const query = element.dataSource.query; try { - const response = await fetch("/api/dashboards/execute-query", { + const response = await fetch(getApiUrl("/api/dashboards/execute-query"), { method: "POST", headers: { "Content-Type": "application/json", @@ -150,53 +151,50 @@ export default function VehicleStatusWidget({ element, refreshInterval = 30000 }
가동률
-
- {activeRate}% -
+
{activeRate}%
{/* 상태별 카드 */}
- {/* 운행 중 */} -
-
-
-
운행
+ {/* 운행 중 */} +
+
+
+
운행
+
+
{statusData.active}
-
{statusData.active}
-
- {/* 대기 */} -
-
-
-
대기
+ {/* 대기 */} +
+
+
+
대기
+
+
{statusData.inactive}
-
{statusData.inactive}
-
- {/* 정비 */} -
-
-
-
정비
+ {/* 정비 */} +
+
+
+
정비
+
+
{statusData.maintenance}
-
{statusData.maintenance}
-
- {/* 고장 */} -
-
-
-
고장
+ {/* 고장 */} +
+
+
+
고장
+
+
{statusData.warning}
-
{statusData.warning}
-
); } - diff --git a/frontend/components/dashboard/widgets/WorkHistoryWidget.tsx b/frontend/components/dashboard/widgets/WorkHistoryWidget.tsx index ab333be6..1c8e0c28 100644 --- a/frontend/components/dashboard/widgets/WorkHistoryWidget.tsx +++ b/frontend/components/dashboard/widgets/WorkHistoryWidget.tsx @@ -10,6 +10,7 @@ import { useState, useEffect } from "react"; import { DashboardElement } from "@/components/admin/dashboard/types"; +import { getApiUrl } from "@/lib/utils/apiUrl"; import { WORK_TYPE_LABELS, WORK_STATUS_LABELS, WORK_STATUS_COLORS, WorkType, WorkStatus } from "@/types/workHistory"; interface WorkHistoryWidgetProps { @@ -33,7 +34,7 @@ export default function WorkHistoryWidget({ element, refreshInterval = 60000 }: // 쿼리가 설정되어 있으면 쿼리 실행 if (element.dataSource?.query) { const token = localStorage.getItem("authToken"); - const response = await fetch("/api/dashboards/execute-query", { + const response = await fetch(getApiUrl("/api/dashboards/execute-query"), { method: "POST", headers: { "Content-Type": "application/json",