Files
delivery-tracker/frontend/src/api/deliveries.ts
Egor Pozharov c39bde0b10
Some checks failed
Build and Push Docker Images / build-backend (push) Has been cancelled
Build and Push Docker Images / build-frontend (push) Has been cancelled
add warehouse_request_source and warehouse_request_source_2 fields to deliveries table with validation and normalization logic
2026-05-04 17:32:03 +06:00

182 lines
5.9 KiB
TypeScript

import { api } from './client';
import { backendDateToFrontend } from '../utils/date';
import type { Delivery, DeliveryRequestSource, PickupLocation, DeliveryStatus } from '../types';
// Types matching backend responses
interface BackendDelivery {
id: string;
date: string; // YYYY-MM-DD from pgtype.Date
pickup_location: PickupLocation;
pickup_location_2: PickupLocation | null;
warehouse_request_source: DeliveryRequestSource | null;
warehouse_request_source_2: DeliveryRequestSource | null;
product_name: string;
product_name_2: string | null;
customer_name: string;
address: string;
street: string;
house: string;
apartment: string | null;
entrance: string | null;
floor: string | null;
phone: string;
additional_phone: string | null;
has_elevator: boolean;
service_info: string | null;
comment: string;
status: DeliveryStatus;
created_at: string; // ISO timestamp
updated_at: string; // ISO timestamp
}
interface DeliveryCount {
date: string; // YYYY-MM-DD
count: number;
}
// API Response types
interface GetDeliveriesResponse {
deliveries: BackendDelivery[];
}
interface GetDeliveryResponse {
delivery: BackendDelivery;
}
interface GetDeliveryCountResponse {
counts: DeliveryCount[];
}
interface CreateDeliveryResponse {
message: string;
id: string;
}
interface UpdateDeliveryResponse {
message: string;
}
// Map backend delivery to frontend delivery
function mapBackendToFrontend(backend: BackendDelivery): Delivery {
return {
id: backend.id,
date: backendDateToFrontend(backend.date),
pickupLocation: backend.pickup_location,
pickupLocation2: backend.pickup_location_2 || undefined,
warehouseRequestSource: backend.warehouse_request_source || undefined,
warehouseRequestSource2: backend.warehouse_request_source_2 || undefined,
productName: backend.product_name,
productName2: backend.product_name_2 || undefined,
customerName: backend.customer_name,
address: backend.address,
street: backend.street,
house: backend.house,
apartment: backend.apartment || undefined,
entrance: backend.entrance || undefined,
floor: backend.floor || undefined,
phone: backend.phone,
additionalPhone: backend.additional_phone || undefined,
hasElevator: backend.has_elevator,
serviceInfo: backend.service_info || undefined,
comment: backend.comment,
status: backend.status,
createdAt: new Date(backend.created_at).getTime(),
updatedAt: new Date(backend.updated_at).getTime(),
};
}
// Delivery API methods
export const deliveriesApi = {
// Get deliveries by date (DD-MM-YYYY)
getByDate: async (date: string): Promise<Delivery[]> => {
const response = await api.get<GetDeliveriesResponse>(
`/api/deliveries?date=${encodeURIComponent(date)}`
);
return response.deliveries.map(mapBackendToFrontend);
},
// Get single delivery by ID
getById: async (id: string): Promise<Delivery> => {
const response = await api.get<GetDeliveryResponse>(`/api/deliveries/${id}`);
return mapBackendToFrontend(response.delivery);
},
// Get delivery counts by date
getCounts: async (): Promise<Record<string, number>> => {
const response = await api.get<GetDeliveryCountResponse>('/api/deliveries/count');
const counts: Record<string, number> = {};
response.counts.forEach(({ date, count }) => {
counts[backendDateToFrontend(date)] = count;
});
return counts;
},
// Create delivery
create: async (
data: Omit<Delivery, 'id' | 'createdAt' | 'updatedAt'>
): Promise<string> => {
const payload = {
date: data.date,
pickup_location: data.pickupLocation,
pickup_location_2: data.pickupLocation2 || null,
warehouse_request_source: data.pickupLocation === 'warehouse' ? data.warehouseRequestSource || null : null,
warehouse_request_source_2: data.pickupLocation2 === 'warehouse' ? data.warehouseRequestSource2 || null : null,
product_name: data.productName,
product_name_2: data.productName2 || null,
customer_name: data.customerName,
address: data.address,
street: data.street,
house: data.house,
apartment: data.apartment || null,
entrance: data.entrance || null,
floor: data.floor || null,
phone: data.phone,
additional_phone: data.additionalPhone || null,
has_elevator: data.hasElevator,
service_info: data.serviceInfo || null,
comment: data.comment,
};
const response = await api.post<CreateDeliveryResponse>('/api/deliveries', payload);
return response.id;
},
// Update delivery
update: async (
id: string,
data: Omit<Delivery, 'id' | 'createdAt' | 'updatedAt'>
): Promise<void> => {
const payload = {
date: data.date,
pickup_location: data.pickupLocation,
pickup_location_2: data.pickupLocation2 || null,
warehouse_request_source: data.pickupLocation === 'warehouse' ? data.warehouseRequestSource || null : null,
warehouse_request_source_2: data.pickupLocation2 === 'warehouse' ? data.warehouseRequestSource2 || null : null,
product_name: data.productName,
product_name_2: data.productName2 || null,
customer_name: data.customerName,
address: data.address,
street: data.street,
house: data.house,
apartment: data.apartment || null,
entrance: data.entrance || null,
floor: data.floor || null,
phone: data.phone,
additional_phone: data.additionalPhone || null,
has_elevator: data.hasElevator,
service_info: data.serviceInfo || null,
comment: data.comment,
};
await api.patch<UpdateDeliveryResponse>(`/api/deliveries/${id}`, payload);
},
// Update delivery status
updateStatus: async (id: string, status: DeliveryStatus): Promise<void> => {
await api.patch(`/api/deliveries/${id}/status`, { status });
},
// Delete delivery
delete: async (id: string): Promise<void> => {
await api.delete(`/api/deliveries/${id}`);
},
};