"use client"; import React, { useState, useEffect } from "react"; import { DashboardElement } from "@/components/admin/dashboard/types"; import { getApiUrl } from "@/lib/utils/apiUrl"; interface CargoListWidgetProps { element: DashboardElement; } interface Cargo { id: string | number; tracking_number?: string; trackingNumber?: string; customer_name?: string; customerName?: string; destination?: string; status?: string; weight?: number; } /** * 화물 목록 위젯 * - 화물 목록 테이블 표시 * - 상태별 배지 표시 */ export default function CargoListWidget({ element }: CargoListWidgetProps) { const [cargoList, setCargoList] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [searchTerm, setSearchTerm] = useState(""); useEffect(() => { loadData(); // 자동 새로고침 (30초마다) const interval = setInterval(loadData, 30000); return () => clearInterval(interval); }, [element]); const loadData = async () => { if (!element?.dataSource?.query) { setError("쿼리가 설정되지 않았습니다"); setLoading(false); return; } try { setLoading(true); const token = localStorage.getItem("authToken"); const response = await fetch(getApiUrl("/api/dashboards/execute-query"), { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}`, }, body: JSON.stringify({ query: element.dataSource.query, connectionType: element.dataSource.connectionType || "current", connectionId: element.dataSource.connectionId, }), }); if (!response.ok) throw new Error("데이터 로딩 실패"); const result = await response.json(); if (result.success && result.data?.rows) { setCargoList(result.data.rows); } setError(null); } catch (err) { setError(err instanceof Error ? err.message : "데이터 로딩 실패"); } finally { setLoading(false); } }; const getStatusBadge = (status: string) => { const statusLower = status?.toLowerCase() || ""; if (statusLower.includes("배송중") || statusLower.includes("delivering")) { return "bg-primary text-primary-foreground"; } else if (statusLower.includes("완료") || statusLower.includes("delivered")) { return "bg-success/10 text-success dark:bg-success/20 dark:text-success"; } else if (statusLower.includes("지연") || statusLower.includes("delayed")) { return "bg-destructive text-destructive-foreground"; } else if (statusLower.includes("픽업") || statusLower.includes("pending")) { return "bg-warning/10 text-warning dark:bg-warning/20 dark:text-warning"; } return "bg-muted text-muted-foreground"; }; const filteredList = cargoList.filter((cargo) => { if (!searchTerm) return true; const trackingNum = cargo.tracking_number || cargo.trackingNumber || ""; const customerName = cargo.customer_name || cargo.customerName || ""; const destination = cargo.destination || ""; const searchLower = searchTerm.toLowerCase(); return ( trackingNum.toLowerCase().includes(searchLower) || customerName.toLowerCase().includes(searchLower) || destination.toLowerCase().includes(searchLower) ); }); if (loading) { return (

데이터 로딩 중...

); } if (error) { return (

⚠️ {error}

); } if (!element?.dataSource?.query) { return (

데이터를 연결하세요

); } return (
{/* 헤더 */}

📦 화물 목록

setSearchTerm(e.target.value)} className="border-input bg-background placeholder:text-muted-foreground focus:ring-ring rounded-md border px-3 py-1 text-sm focus:ring-2 focus:outline-none" />
{/* 총 건수 */}
{filteredList.length}
{/* 테이블 */}
{filteredList.length === 0 ? ( ) : ( filteredList.map((cargo, index) => ( )) )}
운송장번호 고객명 목적지 무게(kg) 상태
{searchTerm ? "검색 결과가 없습니다" : "화물이 없습니다"}
{cargo.tracking_number || cargo.trackingNumber || "-"} {cargo.customer_name || cargo.customerName || "-"} {cargo.destination || "-"} {cargo.weight ? `${cargo.weight}kg` : "-"} {cargo.status || "알 수 없음"}
); }