"use client"; import React, { useState, useEffect, useCallback } from "react"; import { getTripList, getTripDetail, formatDistance, formatDuration, getStatusLabel, getStatusColor, TripSummary, TripDetail, TripListFilters, } from "@/lib/api/vehicleTrip"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table"; import { Dialog, DialogContent, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { Search, RefreshCw, MapPin, Clock, Route, ChevronLeft, ChevronRight, Eye, } from "lucide-react"; import { format } from "date-fns"; import { ko } from "date-fns/locale"; const PAGE_SIZE = 20; export default function VehicleTripHistory() { // 상태 const [trips, setTrips] = useState([]); const [total, setTotal] = useState(0); const [loading, setLoading] = useState(false); const [page, setPage] = useState(1); // 필터 const [filters, setFilters] = useState({ status: "", startDate: "", endDate: "", departure: "", arrival: "", }); // 상세 모달 const [selectedTrip, setSelectedTrip] = useState(null); const [detailModalOpen, setDetailModalOpen] = useState(false); const [detailLoading, setDetailLoading] = useState(false); // 데이터 로드 const loadTrips = useCallback(async () => { setLoading(true); try { const response = await getTripList({ ...filters, status: filters.status || undefined, startDate: filters.startDate || undefined, endDate: filters.endDate || undefined, departure: filters.departure || undefined, arrival: filters.arrival || undefined, limit: PAGE_SIZE, offset: (page - 1) * PAGE_SIZE, }); if (response.success) { setTrips(response.data || []); setTotal(response.total || 0); } } catch (error) { console.error("운행 이력 조회 실패:", error); } finally { setLoading(false); } }, [filters, page]); useEffect(() => { loadTrips(); }, [loadTrips]); // 상세 조회 const handleViewDetail = async (tripId: string) => { setDetailLoading(true); setDetailModalOpen(true); try { const response = await getTripDetail(tripId); if (response.success && response.data) { setSelectedTrip(response.data); } } catch (error) { console.error("운행 상세 조회 실패:", error); } finally { setDetailLoading(false); } }; // 필터 변경 const handleFilterChange = (key: keyof TripListFilters, value: string) => { setFilters((prev) => ({ ...prev, [key]: value })); setPage(1); }; // 검색 const handleSearch = () => { setPage(1); loadTrips(); }; // 초기화 const handleReset = () => { setFilters({ status: "", startDate: "", endDate: "", departure: "", arrival: "", }); setPage(1); }; // 페이지네이션 const totalPages = Math.ceil(total / PAGE_SIZE); return (
{/* 필터 영역 */} 검색 조건
{/* 상태 */}
{/* 시작일 */}
handleFilterChange("startDate", e.target.value)} className="h-9" />
{/* 종료일 */}
handleFilterChange("endDate", e.target.value)} className="h-9" />
{/* 출발지 */}
handleFilterChange("departure", e.target.value)} className="h-9" />
{/* 도착지 */}
handleFilterChange("arrival", e.target.value)} className="h-9" />
{/* 목록 */}
운행 이력 ({total.toLocaleString()}건)
운행ID 운전자 출발지 도착지 시작 시간 종료 시간 거리 시간 상태 {loading ? ( 로딩 중... ) : trips.length === 0 ? ( 운행 이력이 없습니다. ) : ( trips.map((trip) => ( {trip.trip_id.substring(0, 15)}... {trip.user_name || trip.user_id} {trip.departure_name || trip.departure || "-"} {trip.destination_name || trip.arrival || "-"} {format(new Date(trip.start_time), "MM/dd HH:mm", { locale: ko, })} {trip.end_time ? format(new Date(trip.end_time), "MM/dd HH:mm", { locale: ko, }) : "-"} {trip.total_distance ? formatDistance(Number(trip.total_distance)) : "-"} {trip.duration_minutes ? formatDuration(trip.duration_minutes) : "-"} {getStatusLabel(trip.status)} )) )}
{/* 페이지네이션 */} {totalPages > 1 && (
{page} / {totalPages}
)}
{/* 상세 모달 */} 운행 상세 정보 {detailLoading ? (
로딩 중...
) : selectedTrip ? (
{/* 요약 정보 */}
출발지
{selectedTrip.summary.departure_name || selectedTrip.summary.departure || "-"}
도착지
{selectedTrip.summary.destination_name || selectedTrip.summary.arrival || "-"}
총 거리
{selectedTrip.summary.total_distance ? formatDistance(Number(selectedTrip.summary.total_distance)) : "-"}
운행 시간
{selectedTrip.summary.duration_minutes ? formatDuration(selectedTrip.summary.duration_minutes) : "-"}
{/* 운행 정보 */}

운행 정보

운행 ID {selectedTrip.summary.trip_id}
운전자 {selectedTrip.summary.user_name || selectedTrip.summary.user_id}
시작 시간 {format( new Date(selectedTrip.summary.start_time), "yyyy-MM-dd HH:mm:ss", { locale: ko } )}
종료 시간 {selectedTrip.summary.end_time ? format( new Date(selectedTrip.summary.end_time), "yyyy-MM-dd HH:mm:ss", { locale: ko } ) : "-"}
상태 {getStatusLabel(selectedTrip.summary.status)}
위치 기록 수 {selectedTrip.summary.location_count}개
{/* 경로 데이터 */} {selectedTrip.route && selectedTrip.route.length > 0 && (

경로 데이터 ({selectedTrip.route.length}개 지점)

# 위도 경도 정확도 이전 거리 기록 시간 {selectedTrip.route.map((loc, idx) => ( {idx + 1} {loc.latitude.toFixed(6)} {loc.longitude.toFixed(6)} {loc.accuracy ? `${loc.accuracy.toFixed(0)}m` : "-"} {loc.distance_from_prev ? formatDistance(Number(loc.distance_from_prev)) : "-"} {format(new Date(loc.recorded_at), "HH:mm:ss", { locale: ko, })} ))}
)}
) : (
데이터를 불러올 수 없습니다.
)}
); }