/** * 차량 운행 이력 API 클라이언트 */ import { apiClient } from "./client"; // 타입 정의 export interface TripSummary { id: number; trip_id: string; user_id: string; user_name?: string; vehicle_id?: number; vehicle_number?: string; departure?: string; arrival?: string; departure_name?: string; destination_name?: string; start_time: string; end_time?: string; total_distance: number; duration_minutes?: number; status: "active" | "completed" | "cancelled"; location_count: number; company_code: string; created_at: string; } export interface TripLocation { id: number; latitude: number; longitude: number; accuracy?: number; speed?: number; distance_from_prev?: number; trip_status: "start" | "tracking" | "end"; recorded_at: string; } export interface TripDetail { summary: TripSummary; route: TripLocation[]; } export interface TripListFilters { userId?: string; vehicleId?: number; status?: string; startDate?: string; endDate?: string; departure?: string; arrival?: string; limit?: number; offset?: number; } export interface StartTripParams { vehicleId?: number; departure?: string; arrival?: string; departureName?: string; destinationName?: string; latitude: number; longitude: number; } export interface EndTripParams { tripId: string; latitude: number; longitude: number; } export interface AddLocationParams { tripId: string; latitude: number; longitude: number; accuracy?: number; speed?: number; } // API 함수들 /** * 운행 시작 */ export async function startTrip(params: StartTripParams) { const response = await apiClient.post("/vehicle/trip/start", params); return response.data; } /** * 운행 종료 */ export async function endTrip(params: EndTripParams) { const response = await apiClient.post("/vehicle/trip/end", params); return response.data; } /** * 위치 기록 추가 (연속 추적) */ export async function addTripLocation(params: AddLocationParams) { const response = await apiClient.post("/vehicle/trip/location", params); return response.data; } /** * 활성 운행 조회 */ export async function getActiveTrip() { const response = await apiClient.get("/vehicle/trip/active"); return response.data; } /** * 운행 취소 */ export async function cancelTrip(tripId: string) { const response = await apiClient.post("/vehicle/trip/cancel", { tripId }); return response.data; } /** * 운행 이력 목록 조회 */ export async function getTripList(filters?: TripListFilters) { const params = new URLSearchParams(); if (filters) { if (filters.userId) params.append("userId", filters.userId); if (filters.vehicleId) params.append("vehicleId", String(filters.vehicleId)); if (filters.status) params.append("status", filters.status); if (filters.startDate) params.append("startDate", filters.startDate); if (filters.endDate) params.append("endDate", filters.endDate); if (filters.departure) params.append("departure", filters.departure); if (filters.arrival) params.append("arrival", filters.arrival); if (filters.limit) params.append("limit", String(filters.limit)); if (filters.offset) params.append("offset", String(filters.offset)); } const queryString = params.toString(); const url = queryString ? `/vehicle/trips?${queryString}` : "/vehicle/trips"; const response = await apiClient.get(url); return response.data; } /** * 운행 상세 조회 (경로 포함) */ export async function getTripDetail(tripId: string): Promise<{ success: boolean; data?: TripDetail; message?: string }> { const response = await apiClient.get(`/vehicle/trips/${tripId}`); return response.data; } /** * 거리 포맷팅 (km) */ export function formatDistance(distanceKm: number): string { if (distanceKm < 1) { return `${Math.round(distanceKm * 1000)}m`; } return `${distanceKm.toFixed(2)}km`; } /** * 운행 시간 포맷팅 */ export function formatDuration(minutes: number): string { if (minutes < 60) { return `${minutes}분`; } const hours = Math.floor(minutes / 60); const mins = minutes % 60; return mins > 0 ? `${hours}시간 ${mins}분` : `${hours}시간`; } /** * 상태 한글 변환 */ export function getStatusLabel(status: string): string { switch (status) { case "active": return "운행 중"; case "completed": return "완료"; case "cancelled": return "취소됨"; default: return status; } } /** * 상태별 색상 */ export function getStatusColor(status: string): string { switch (status) { case "active": return "bg-green-100 text-green-800"; case "completed": return "bg-blue-100 text-blue-800"; case "cancelled": return "bg-gray-100 text-gray-800"; default: return "bg-gray-100 text-gray-800"; } } // ============== 리포트 API ============== export interface DailyStat { date: string; tripCount: number; completedCount: number; cancelledCount: number; totalDistance: number; totalDuration: number; avgDistance: number; avgDuration: number; } export interface WeeklyStat { weekNumber: number; weekStart: string; weekEnd: string; tripCount: number; completedCount: number; totalDistance: number; totalDuration: number; avgDistance: number; } export interface MonthlyStat { month: number; tripCount: number; completedCount: number; cancelledCount: number; totalDistance: number; totalDuration: number; avgDistance: number; avgDuration: number; driverCount: number; } export interface SummaryReport { period: string; totalTrips: number; completedTrips: number; activeTrips: number; cancelledTrips: number; completionRate: number; totalDistance: number; totalDuration: number; avgDistance: number; avgDuration: number; activeDrivers: number; } export interface DriverStat { userId: string; userName: string; tripCount: number; completedCount: number; totalDistance: number; totalDuration: number; avgDistance: number; } export interface RouteStat { departure: string; arrival: string; departureName: string; destinationName: string; tripCount: number; completedCount: number; totalDistance: number; avgDistance: number; avgDuration: number; } /** * 요약 통계 조회 (대시보드용) */ export async function getSummaryReport(period?: string) { const url = period ? `/vehicle/reports/summary?period=${period}` : "/vehicle/reports/summary"; const response = await apiClient.get(url); return response.data; } /** * 일별 통계 조회 */ export async function getDailyReport(filters?: { startDate?: string; endDate?: string; userId?: string }) { const params = new URLSearchParams(); if (filters?.startDate) params.append("startDate", filters.startDate); if (filters?.endDate) params.append("endDate", filters.endDate); if (filters?.userId) params.append("userId", filters.userId); const queryString = params.toString(); const url = queryString ? `/vehicle/reports/daily?${queryString}` : "/vehicle/reports/daily"; const response = await apiClient.get(url); return response.data; } /** * 주별 통계 조회 */ export async function getWeeklyReport(filters?: { year?: number; month?: number; userId?: string }) { const params = new URLSearchParams(); if (filters?.year) params.append("year", String(filters.year)); if (filters?.month) params.append("month", String(filters.month)); if (filters?.userId) params.append("userId", filters.userId); const queryString = params.toString(); const url = queryString ? `/vehicle/reports/weekly?${queryString}` : "/vehicle/reports/weekly"; const response = await apiClient.get(url); return response.data; } /** * 월별 통계 조회 */ export async function getMonthlyReport(filters?: { year?: number; userId?: string }) { const params = new URLSearchParams(); if (filters?.year) params.append("year", String(filters.year)); if (filters?.userId) params.append("userId", filters.userId); const queryString = params.toString(); const url = queryString ? `/vehicle/reports/monthly?${queryString}` : "/vehicle/reports/monthly"; const response = await apiClient.get(url); return response.data; } /** * 운전자별 통계 조회 */ export async function getDriverReport(filters?: { startDate?: string; endDate?: string; limit?: number }) { const params = new URLSearchParams(); if (filters?.startDate) params.append("startDate", filters.startDate); if (filters?.endDate) params.append("endDate", filters.endDate); if (filters?.limit) params.append("limit", String(filters.limit)); const queryString = params.toString(); const url = queryString ? `/vehicle/reports/by-driver?${queryString}` : "/vehicle/reports/by-driver"; const response = await apiClient.get(url); return response.data; } /** * 구간별 통계 조회 */ export async function getRouteReport(filters?: { startDate?: string; endDate?: string; limit?: number }) { const params = new URLSearchParams(); if (filters?.startDate) params.append("startDate", filters.startDate); if (filters?.endDate) params.append("endDate", filters.endDate); if (filters?.limit) params.append("limit", String(filters.limit)); const queryString = params.toString(); const url = queryString ? `/vehicle/reports/by-route?${queryString}` : "/vehicle/reports/by-route"; const response = await apiClient.get(url); return response.data; }