This commit is contained in:
natib21
2026-07-06 12:05:52 +00:00
parent e13720a32d
commit 998a6801ab
46 changed files with 5026 additions and 5 deletions

View File

@@ -0,0 +1,73 @@
import { api as apiClient } from '../auth/http';
export type ComplianceType =
| 'INSPECTION'
| 'INSURANCE'
| 'ROADWORTHINESS'
| 'PERMIT'
| 'TAX';
export type ComplianceStatus = 'VALID' | 'EXPIRING' | 'EXPIRED';
export type AlertSeverity = 'OVERDUE' | 'DUE_SOON';
export interface ComplianceRecord {
id: string;
vehicleId: string;
vehicle?: {
id: string;
plateNumber?: string | null;
manufacturer?: string | null;
model?: string | null;
};
type: ComplianceType;
documentNumber?: string | null;
issuedDate?: string | null;
expiryDate: string;
status: ComplianceStatus;
notes?: string | null;
createdAt: string;
updatedAt: string;
}
export interface ComplianceAlert {
vehicleId: string;
vehiclePlate?: string;
kind: string;
label: string;
expiryDate: string;
daysUntil: number;
severity: AlertSeverity;
}
export interface ComplianceListFilters {
vehicleId?: string;
type?: ComplianceType;
}
export interface SaveCompliancePayload {
vehicleId: string;
type: ComplianceType;
documentNumber?: string;
issuedDate?: string;
expiryDate: string;
status?: ComplianceStatus;
notes?: string;
}
export const complianceService = {
list: (filters: ComplianceListFilters = {}) => {
const params = new URLSearchParams();
if (filters.vehicleId) params.set('vehicleId', filters.vehicleId);
if (filters.type) params.set('type', filters.type);
const qs = params.toString();
return apiClient.get<ComplianceRecord[]>(`/compliance${qs ? `?${qs}` : ''}`);
},
getAlerts: () => apiClient.get<ComplianceAlert[]>('/compliance/alerts'),
getById: (id: string) => apiClient.get<ComplianceRecord>(`/compliance/${id}`),
create: (data: SaveCompliancePayload) =>
apiClient.post<ComplianceRecord>('/compliance', data),
update: (id: string, data: Partial<SaveCompliancePayload>) =>
apiClient.patch<ComplianceRecord>(`/compliance/${id}`, data),
remove: (id: string) => apiClient.delete(`/compliance/${id}`),
};

View File

@@ -0,0 +1,87 @@
import { api } from '@/auth/http';
export type IncidentType = 'ACCIDENT' | 'BREAKDOWN' | 'TRAFFIC_VIOLATION' | 'THEFT' | 'OTHER';
export type IncidentSeverity = 'MINOR' | 'MODERATE' | 'MAJOR' | 'CRITICAL';
export type IncidentStatus =
| 'REPORTED'
| 'UNDER_REVIEW'
| 'CLAIM_FILED'
| 'RESOLVED'
| 'CLOSED';
export interface Incident {
id: string;
vehicleId?: string | null;
driverId?: string | null;
bookingId?: string | null;
type: IncidentType;
severity: IncidentSeverity;
occurredAt: string;
location?: string | null;
description: string;
/** API sends numeric as string; coerce with Number. */
damageEstimate?: number | string | null;
status: IncidentStatus;
insuranceClaimNumber?: string | null;
reportedBy?: string | null;
vehicle?: {
id: string;
plateNumber?: string | null;
registrationNumber?: string | null;
} | null;
driver?: {
id: string;
firstName?: string | null;
lastName?: string | null;
} | null;
createdAt: string;
updatedAt: string;
}
export interface IncidentFilters {
vehicleId?: string;
driverId?: string;
status?: IncidentStatus;
type?: IncidentType;
}
export interface DriverIncidentStats {
total: number;
byType: Record<string, number>;
lastIncidentAt: string | null;
}
export interface SaveIncidentPayload {
vehicleId?: string;
driverId?: string;
bookingId?: string;
type: IncidentType;
severity: IncidentSeverity;
occurredAt: string;
location?: string;
description: string;
damageEstimate?: number;
status?: IncidentStatus;
insuranceClaimNumber?: string;
reportedBy?: string;
}
export const incidentsService = {
getAll: (filters: IncidentFilters = {}) => {
const params = new URLSearchParams();
if (filters.vehicleId) params.set('vehicleId', filters.vehicleId);
if (filters.driverId) params.set('driverId', filters.driverId);
if (filters.status) params.set('status', filters.status);
if (filters.type) params.set('type', filters.type);
const qs = params.toString();
return api.get<Incident[]>(`/incidents${qs ? `?${qs}` : ''}`);
},
getByDriver: (driverId: string) => api.get<Incident[]>(`/incidents/driver/${driverId}`),
getDriverStats: (driverId: string) =>
api.get<DriverIncidentStats>(`/incidents/driver/${driverId}/stats`),
getById: (id: string) => api.get<Incident>(`/incidents/${id}`),
create: (data: SaveIncidentPayload) => api.post<Incident>('/incidents', data),
update: (id: string, data: Partial<SaveIncidentPayload>) =>
api.patch<Incident>(`/incidents/${id}`, data),
delete: (id: string) => api.delete(`/incidents/${id}`),
};

View File

@@ -0,0 +1,130 @@
import { api } from '@/auth/http';
export type WorkOrderStatus = 'OPEN' | 'IN_PROGRESS' | 'COMPLETED' | 'CANCELLED';
export type WorkOrderPriority = 'LOW' | 'MEDIUM' | 'HIGH' | 'URGENT';
export interface WorkOrder {
id: string;
vehicleId: string;
title: string;
description?: string | null;
status: WorkOrderStatus;
priority: WorkOrderPriority;
assignedTo?: string | null;
openedAt: string;
closedAt?: string | null;
/** API sends numeric as string; coerce with Number. */
laborCost?: number | string | null;
partsCost?: number | string | null;
createdAt: string;
updatedAt: string;
}
export interface SaveWorkOrderPayload {
vehicleId: string;
title: string;
description?: string;
status?: WorkOrderStatus;
priority?: WorkOrderPriority;
assignedTo?: string;
openedAt?: string;
closedAt?: string;
laborCost?: number;
partsCost?: number;
}
export interface WorkOrderFilters {
vehicleId?: string;
status?: WorkOrderStatus;
}
export interface Part {
id: string;
name: string;
sku?: string | null;
category?: string | null;
quantityInStock: number;
reorderLevel: number;
/** API sends numeric as string; coerce with Number. */
unitCost?: number | string | null;
location?: string | null;
createdAt: string;
updatedAt: string;
}
export interface SavePartPayload {
name: string;
sku?: string;
category?: string;
quantityInStock?: number;
reorderLevel?: number;
unitCost?: number;
location?: string;
}
export interface PartFilters {
category?: string;
lowStock?: boolean;
}
export interface Warranty {
id: string;
vehicleId: string;
component: string;
provider?: string | null;
startDate?: string | null;
expiryDate: string;
coverageNotes?: string | null;
createdAt: string;
updatedAt: string;
}
export interface SaveWarrantyPayload {
vehicleId: string;
component: string;
provider?: string;
startDate?: string;
expiryDate: string;
coverageNotes?: string;
}
export const maintenanceDepthService = {
// Work Orders
getWorkOrders: (filters: WorkOrderFilters = {}) => {
const params = new URLSearchParams();
if (filters.vehicleId) params.set('vehicleId', filters.vehicleId);
if (filters.status) params.set('status', filters.status);
const qs = params.toString();
return api.get<WorkOrder[]>(`/maintenance/work-orders${qs ? `?${qs}` : ''}`);
},
getWorkOrder: (id: string) => api.get<WorkOrder>(`/maintenance/work-orders/${id}`),
createWorkOrder: (data: SaveWorkOrderPayload) =>
api.post<WorkOrder>('/maintenance/work-orders', data),
updateWorkOrder: (id: string, data: Partial<SaveWorkOrderPayload>) =>
api.patch<WorkOrder>(`/maintenance/work-orders/${id}`, data),
deleteWorkOrder: (id: string) => api.delete(`/maintenance/work-orders/${id}`),
// Parts / Tires
getParts: (filters: PartFilters = {}) => {
const params = new URLSearchParams();
if (filters.category) params.set('category', filters.category);
if (filters.lowStock) params.set('lowStock', 'true');
const qs = params.toString();
return api.get<Part[]>(`/maintenance/parts${qs ? `?${qs}` : ''}`);
},
createPart: (data: SavePartPayload) => api.post<Part>('/maintenance/parts', data),
updatePart: (id: string, data: Partial<SavePartPayload>) =>
api.patch<Part>(`/maintenance/parts/${id}`, data),
deletePart: (id: string) => api.delete(`/maintenance/parts/${id}`),
// Warranties
getWarranties: (vehicleId?: string) => {
const params = new URLSearchParams();
if (vehicleId) params.set('vehicleId', vehicleId);
const qs = params.toString();
return api.get<Warranty[]>(`/maintenance/warranties${qs ? `?${qs}` : ''}`);
},
createWarranty: (data: SaveWarrantyPayload) =>
api.post<Warranty>('/maintenance/warranties', data),
deleteWarranty: (id: string) => api.delete(`/maintenance/warranties/${id}`),
};

View File

@@ -0,0 +1,138 @@
import { api } from "@/auth/http";
export type VendorType = "DEALER" | "LEASING" | "PARTS" | "SERVICE" | "OTHER";
export type AcquisitionType = "PURCHASE" | "LEASE" | "RENTAL";
export type AcquisitionStatus = "ACTIVE" | "LEASE_EXPIRING" | "DISPOSED";
export type DisposalMethod = "SALE" | "SCRAP" | "RETURN_LEASE" | "TRADE_IN";
export interface Vendor {
id: string;
name: string;
type?: VendorType | null;
contactPerson?: string | null;
phone?: string | null;
email?: string | null;
address?: string | null;
isActive: boolean;
createdAt: string;
updatedAt: string;
}
export interface AssetAcquisition {
id: string;
vehicleId?: string | null;
vendorId?: string | null;
acquisitionType: AcquisitionType;
acquisitionDate: string;
cost?: number | null;
usefulLifeMonths?: number | null;
salvageValue?: number | null;
leaseStart?: string | null;
leaseEnd?: string | null;
monthlyPayment?: number | null;
status: AcquisitionStatus;
notes?: string | null;
vehicle?: {
id: string;
plateNumber?: string | null;
registrationNumber?: string | null;
manufacturer?: string | null;
model?: string | null;
} | null;
vendor?: Vendor | null;
createdAt: string;
updatedAt: string;
}
export interface AssetDisposal {
id: string;
vehicleId: string;
disposalDate: string;
method: DisposalMethod;
salePrice?: number | null;
buyer?: string | null;
notes?: string | null;
createdAt: string;
updatedAt: string;
}
export interface DepreciationResult {
method: "STRAIGHT_LINE";
cost: number;
salvageValue: number;
usefulLifeMonths: number;
monthsElapsed: number;
monthlyDepreciation: number;
bookValue: number;
}
export interface LifecycleResult {
vehicleId: string;
acquisition: AssetAcquisition | null;
disposal: AssetDisposal | null;
depreciation: DepreciationResult | null;
}
export interface CreateVendorPayload {
name: string;
type?: VendorType;
contactPerson?: string;
phone?: string;
email?: string;
address?: string;
isActive?: boolean;
}
export interface CreateAcquisitionPayload {
vehicleId?: string;
vendorId?: string;
acquisitionType: AcquisitionType;
acquisitionDate: string;
cost?: number;
usefulLifeMonths?: number;
salvageValue?: number;
leaseStart?: string;
leaseEnd?: string;
monthlyPayment?: number;
status?: AcquisitionStatus;
notes?: string;
}
export interface CreateDisposalPayload {
vehicleId: string;
disposalDate: string;
method: DisposalMethod;
salePrice?: number;
buyer?: string;
notes?: string;
}
export const procurementService = {
// Vendors
listVendors: () => api.get<Vendor[]>("/procurement/vendors"),
createVendor: (data: CreateVendorPayload) => api.post("/procurement/vendors", data),
updateVendor: (id: string, data: Partial<CreateVendorPayload>) =>
api.patch(`/procurement/vendors/${id}`, data),
deleteVendor: (id: string) => api.delete(`/procurement/vendors/${id}`),
// Acquisitions
listAcquisitions: (vehicleId?: string) =>
api.get<AssetAcquisition[]>(
`/procurement/acquisitions${vehicleId ? `?vehicleId=${vehicleId}` : ""}`,
),
getAcquisition: (id: string) => api.get<AssetAcquisition>(`/procurement/acquisitions/${id}`),
createAcquisition: (data: CreateAcquisitionPayload) =>
api.post("/procurement/acquisitions", data),
updateAcquisition: (id: string, data: Partial<CreateAcquisitionPayload>) =>
api.patch(`/procurement/acquisitions/${id}`, data),
deleteAcquisition: (id: string) => api.delete(`/procurement/acquisitions/${id}`),
// Disposals
listDisposals: () => api.get<AssetDisposal[]>("/procurement/disposals"),
createDisposal: (data: CreateDisposalPayload) => api.post("/procurement/disposals", data),
deleteDisposal: (id: string) => api.delete(`/procurement/disposals/${id}`),
// Lifecycle
lifecycle: (vehicleId: string) =>
api.get<LifecycleResult>(`/procurement/lifecycle/${vehicleId}`),
};