/** * Bookings API * * Endpoints for managing container bookings */ import { get, post, patch, upload } from './client'; import type { CreateBookingRequest, BookingResponse, BookingListResponse, SuccessResponse, } from '@/types/api'; // TODO: These types should be moved to @/types/api.ts export interface BookingSearchRequest { query?: string; status?: string; originPort?: string; destinationPort?: string; startDate?: string; endDate?: string; organizationId?: string; } export interface BookingSearchResponse { bookings: BookingResponse[]; total: number; } export interface UpdateBookingStatusRequest { status: string; notes?: string; } /** * CSV Booking types */ export interface CsvBookingResponse { id: string; bookingId: string; carrierName: string; carrierEmail: string; origin: string; destination: string; volumeCBM: number; weightKG: number; palletCount: number; priceUSD: number; priceEUR: number; primaryCurrency: string; transitDays: number; containerType: string; status: 'PENDING' | 'ACCEPTED' | 'REJECTED'; documents: Array<{ type: string; fileName: string; url: string; }>; notes?: string; confirmationToken: string; emailSentAt?: string; acceptedAt?: string; rejectedAt?: string; createdAt: string; updatedAt: string; } export interface CsvBookingListResponse { bookings: CsvBookingResponse[]; // Changed from 'items' to match backend response total: number; page: number; limit: number; totalPages: number; } export interface CsvBookingStatsResponse { total: number; pending: number; accepted: number; rejected: number; } /** * Create a new booking * POST /api/v1/bookings */ export async function createBooking(data: CreateBookingRequest): Promise { return post('/api/v1/bookings', data); } /** * Get booking by ID * GET /api/v1/bookings/:id */ export async function getBooking(id: string): Promise { return get(`/api/v1/bookings/${id}`); } /** * Get booking by booking number * GET /api/v1/bookings/number/:bookingNumber */ export async function getBookingByNumber(bookingNumber: string): Promise { return get(`/api/v1/bookings/number/${bookingNumber}`); } /** * List bookings with pagination * GET /api/v1/bookings?page=1&limit=20&status=CONFIRMED&organizationId=xxx */ export async function listBookings(params?: { page?: number; limit?: number; status?: string; organizationId?: string; }): Promise { const queryParams = new URLSearchParams(); if (params?.page) queryParams.append('page', params.page.toString()); if (params?.limit) queryParams.append('limit', params.limit.toString()); if (params?.status) queryParams.append('status', params.status); if (params?.organizationId) queryParams.append('organizationId', params.organizationId); const queryString = queryParams.toString(); return get(`/api/v1/bookings${queryString ? `?${queryString}` : ''}`); } /** * Fuzzy search bookings * GET /api/v1/bookings/search?q=WCM-2024&limit=10 */ export async function fuzzySearchBookings(params: { q: string; limit?: number; }): Promise { const queryParams = new URLSearchParams(); queryParams.append('q', params.q); if (params.limit) queryParams.append('limit', params.limit.toString()); return get(`/api/v1/bookings/search?${queryParams.toString()}`); } /** * Advanced search bookings * POST /api/v1/bookings/search/advanced */ export async function advancedSearchBookings( data: BookingSearchRequest ): Promise { return post('/api/v1/bookings/search/advanced', data); } /** * Export bookings (CSV/PDF) * GET /api/v1/bookings/export?format=csv&status=CONFIRMED * Returns blob for download */ export async function exportBookings(params: { format: 'csv' | 'pdf'; status?: string; organizationId?: string; startDate?: string; endDate?: string; }): Promise { const queryParams = new URLSearchParams(); queryParams.append('format', params.format); if (params.status) queryParams.append('status', params.status); if (params.organizationId) queryParams.append('organizationId', params.organizationId); if (params.startDate) queryParams.append('startDate', params.startDate); if (params.endDate) queryParams.append('endDate', params.endDate); const response = await fetch( `${process.env.NEXT_PUBLIC_API_URL}/api/v1/bookings/export?${queryParams.toString()}`, { method: 'GET', headers: { Authorization: `Bearer ${ typeof window !== 'undefined' ? localStorage.getItem('access_token') : '' }`, }, } ); if (!response.ok) { throw new Error(`Export failed: ${response.statusText}`); } return response.blob(); } /** * Update booking status * PATCH /api/v1/bookings/:id/status */ export async function updateBookingStatus( id: string, data: UpdateBookingStatusRequest ): Promise { return patch(`/api/v1/bookings/${id}/status`, data); } // ============================================================================ // CSV BOOKINGS API // ============================================================================ /** * Create a new CSV booking with document uploads * POST /api/v1/csv-bookings * * Uses multipart/form-data for file uploads */ export async function createCsvBooking(formData: FormData): Promise { return upload('/api/v1/csv-bookings', formData); } /** * Get CSV booking by ID * GET /api/v1/csv-bookings/:id */ export async function getCsvBooking(id: string): Promise { return get(`/api/v1/csv-bookings/${id}`); } /** * List CSV bookings with pagination and filters * GET /api/v1/csv-bookings?page=1&limit=20&status=PENDING */ export async function listCsvBookings(params?: { page?: number; limit?: number; status?: 'PENDING' | 'ACCEPTED' | 'REJECTED'; startDate?: string; endDate?: string; }): Promise { const queryParams = new URLSearchParams(); if (params?.page) queryParams.append('page', params.page.toString()); if (params?.limit) queryParams.append('limit', params.limit.toString()); if (params?.status) queryParams.append('status', params.status); if (params?.startDate) queryParams.append('startDate', params.startDate); if (params?.endDate) queryParams.append('endDate', params.endDate); const queryString = queryParams.toString(); return get( `/api/v1/csv-bookings${queryString ? `?${queryString}` : ''}` ); } /** * Get CSV booking statistics for current user * GET /api/v1/csv-bookings/stats */ export async function getCsvBookingStats(): Promise { return get('/api/v1/csv-bookings/stats'); } /** * Cancel a pending CSV booking * PATCH /api/v1/csv-bookings/:id/cancel */ export async function cancelCsvBooking(id: string): Promise { return patch(`/api/v1/csv-bookings/${id}/cancel`, {}); } /** * Accept a CSV booking (public endpoint, no auth required) * POST /api/v1/csv-bookings/:token/accept */ export async function acceptCsvBooking(token: string): Promise { return post( `/api/v1/csv-bookings/${token}/accept`, {}, false // includeAuth = false ); } /** * Reject a CSV booking with reason (public endpoint, no auth required) * POST /api/v1/csv-bookings/:token/reject */ export async function rejectCsvBooking( token: string, reason?: string ): Promise { return post( `/api/v1/csv-bookings/${token}/reject`, { reason }, false // includeAuth = false ); }