import React, { useContext, useState } from "react"; import { logger } from "../../services/monitoring"; import api from "../../services/vehiclesAPI"; const VehicleContext = React.createContext(); const validateAdd = (vehicle) => { if (vehicle == null) { throw new Error("No vehicle data"); } if (!vehicle.vin || vehicle.vin.length === 0) { throw new Error("VIN required"); } if (vehicle.vin.length > 17) { throw new Error("VIN cannot be larger than 17 characters"); } if (!vehicle.model || vehicle.model.length === 0) { throw new Error("model required"); } if (!vehicle.year || vehicle.year < 2000 || vehicle.year > 9999) { throw new Error("year required"); } }; export const VehicleProvider = ({ children }) => { const [busy, setBusy] = useState(false); const [vehicle, setVehicle] = useState({}); const [vehicles, setVehicles] = useState([]); const [totalVehicles, setTotalVehicles] = useState(0); const [models, setModels] = useState([]); const [years, setYears] = useState([]); const addConnections = async (cars, token) => { try { if (cars.length === 0) return; const vins = cars.map((car) => car.vin); const result = await api.getConnections(vins, token); if (result.error) { throw new Error(`Add connections error. ${result.message}`); } cars.forEach((car) => { car.connected = result[car.vin] || false; }); } catch (e) { logger.error(e.stack); } }; const addVehicle = async (v, token) => { try { setBusy(true); validateAdd(v); const result = await api.addVehicle(v, token); if (result.error) throw new Error(`Add vehicle error. ${result.message}`); return result; } finally { setBusy(false); } }; const getConnections = async (vins, token) => { try { setBusy(true); const result = await api.getConnections(vins, token); if (result.error) throw new Error(`Get connections error. ${result.message}`); return result; } finally { setBusy(false); } }; const getECUs = async (search, token) => { try { setBusy(true); const result = await api.getECUs(search, token); if (result.error) throw new Error(`Get ECUs error. ${result.message}`); return result; } finally { setBusy(false); } }; const getLocations = async (token) => { try { setBusy(true); const result = await api.getLocations(token); if (result.error) throw new Error(`Get locations error. ${result.message}`); return result; } finally { setBusy(false); } }; const getModels = async (token) => { try { setBusy(true); const result = await api.getModels(token); if (result.error) throw new Error(`Get models error. ${result.message}`); setModels(result.data); } finally { setBusy(false); } }; const getState = async (token, vin) => { try { setBusy(true); const result = await api.getState(token, vin); if (result.error) throw new Error(`Get state error. ${result.message}`); return result; } finally { setBusy(false); } }; const getVehicle = async (vin, token) => { try { setBusy(true); validateVIN(vin); const result = await api.getVehicle(vin, token); if (result.error) throw new Error(`Get vehicle error. ${result.message}`); setVehicle(result ?? []); return result; } finally { setBusy(false); } }; const getVehicles = async (search, token) => { try { setBusy(true); const result = await api.getVehicles(search, token); if (result.error) { setVehicles([]); throw new Error(`Get vehicles error. ${result.message}`); } await addConnections(result.data, token); setVehicles(result.data ?? []); if (result.total) { setTotalVehicles(result.total); } } finally { setBusy(false); } }; const getYears = async (token) => { try { setBusy(true); const result = await api.getYears(token); if (result.error) throw new Error(`Get years error. ${result.message}`); setYears(result.data); } finally { setBusy(false); } }; const sendCommand = async (vins, command, parameters, token) => { try { setBusy(true); const result = await api.sendCommand(vins, command, parameters, token); if (result.error) throw new Error(`Send command error. ${result.message}`); return result; } finally { setBusy(false); } }; const updateVehicle = async (vin, v, token) => { try { setBusy(true); validateVIN(vin); validateVehicle(v); const result = await api.updateVehicle(vin, v, token); if (result.error) throw new Error(`Update vehicle error. ${result.message}`); return result; } finally { setBusy(false); } }; const deleteVehicle = async (vin, token) => { try { setBusy(true); validateVIN(vin); const result = await api.deleteVehicle(vin, token); if (result.error) throw new Error(`Delete vehicle error. ${result.message}`); return result; } finally { setBusy(false); } }; const getCANSignals = async (vin, token) => { try { setBusy(true); validateVIN(vin); const result = await api.getCANSignals(vin, token); if (result.error) throw new Error(`Get CAN signals error. ${result.message}`); return result; } finally { setBusy(false); } }; return ( {children} ); }; const validateVehicle = (v) => { if (v == null) { throw new Error("No vehicle data"); } validateVIN(v.vin); }; const validateVIN = (vin) => { if (vin == null || vin.length !== 17) { throw new Error("Invalid VIN"); } }; export const useVehicleContext = () => useContext(VehicleContext);