import { authInstance, languageInstance, mobxFetch } from "@shared"; import { makeAutoObservable, runInAction } from "mobx"; import { getVehicleSessionsApi } from "./api"; import { Vehicle, VehicleMaintenanceSession } from "./types"; export type { Vehicle, VehicleMaintenanceSession } from "./types"; class VehicleStore { vehicles: { data: Vehicle[]; loaded: boolean; } = { data: [], loaded: false, }; vehicle: Record = {}; vehicleSessions: VehicleMaintenanceSession[] | null = null; vehicleSessionsLoading = false; vehicleSessionsError: string | null = null; constructor() { makeAutoObservable(this); } private normalizeVehicleItem = (item: any): Vehicle => { if (item && typeof item === "object" && "vehicle" in item) { return { vehicle: item.vehicle ?? {}, device_status: item.device_status, } as Vehicle; } return { vehicle: item ?? {}, } as Vehicle; }; private mergeVehicleInCaches = (updatedVehicle: any) => { if (!updatedVehicle) return; const updatedId = updatedVehicle.id; const updatedUuid = updatedVehicle.uuid; const mergeItem = (item: Vehicle): Vehicle => ({ ...item, vehicle: { ...item.vehicle, ...updatedVehicle, }, }); this.vehicles.data = this.vehicles.data.map((item) => { const sameId = updatedId != null && item.vehicle.id === updatedId; const sameUuid = updatedUuid != null && item.vehicle.uuid != null && item.vehicle.uuid === updatedUuid; if (!sameId && !sameUuid) return item; return mergeItem(item); }); if (updatedId != null) { const existing = this.vehicle[updatedId]; this.vehicle[updatedId] = existing ? mergeItem(existing) : ({ vehicle: updatedVehicle } as Vehicle); return; } if (updatedUuid != null) { const entry = Object.entries(this.vehicle).find( ([, item]) => item.vehicle.uuid === updatedUuid, ); if (entry) { const [key, item] = entry; this.vehicle[key] = mergeItem(item); } } }; getVehicles = async () => { const response = await languageInstance("ru").get(`/vehicle`); const vehiclesList = Array.isArray(response.data) ? response.data : Array.isArray(response.data?.vehicles) ? response.data.vehicles : []; runInAction(() => { this.vehicles.data = vehiclesList.map(this.normalizeVehicleItem); this.vehicles.loaded = true; }); }; deleteVehicle = async (id: number) => { await languageInstance("ru").delete(`/vehicle/${id}`); runInAction(() => { this.vehicles.data = this.vehicles.data.filter( (vehicle) => vehicle.vehicle.id !== id, ); }); }; getVehicle = async (id: number) => { const response = await languageInstance("ru").get(`/vehicle/${id}`); const normalizedVehicle = this.normalizeVehicleItem(response.data); runInAction(() => { this.vehicle[id] = normalizedVehicle; }); }; createVehicle = async ( tailNumber: string, type: number, carrier: string, carrierId: number, model?: string, ) => { const payload: Record = { tail_number: tailNumber, type, carrier, carrier_id: carrierId, }; // TODO: когда будет бекенд — добавить model в payload и в ответ if (model != null && model !== "") payload.model = model; const response = await languageInstance("ru").post("/vehicle", payload); const normalizedVehicle = this.normalizeVehicleItem(response.data); runInAction(() => { this.vehicles.data.push(normalizedVehicle); if (normalizedVehicle.vehicle?.id != null) { this.vehicle[normalizedVehicle.vehicle.id] = normalizedVehicle; } }); }; editVehicleData: { tail_number: string; type: number; carrier: string; carrier_id: number; model: string; snapshot_update_blocked: boolean; } = { tail_number: "", type: 0, carrier: "", carrier_id: 0, model: "", snapshot_update_blocked: false, }; setEditVehicleData = (data: { tail_number: string; type: number; carrier: string; carrier_id: number; model?: string; snapshot_update_blocked?: boolean; }) => { this.editVehicleData = { ...this.editVehicleData, ...data, }; }; editVehicle = async ( id: number, data: { tail_number: string; type: number; carrier: string; carrier_id: number; model?: string; snapshot_update_blocked?: boolean; }, ) => { const payload: Record = { tail_number: data.tail_number, type: data.type, carrier: data.carrier, carrier_id: data.carrier_id, }; if (data.model != null && data.model !== "") payload.model = data.model; if (data.snapshot_update_blocked != null) payload.snapshot_update_blocked = data.snapshot_update_blocked; const response = await languageInstance("ru").patch( `/vehicle/${id}`, payload, ); const normalizedVehicle = this.normalizeVehicleItem(response.data); const updatedVehiclePayload = { ...normalizedVehicle.vehicle, model: normalizedVehicle.vehicle.model ?? data.model, snapshot_update_blocked: normalizedVehicle.vehicle.snapshot_update_blocked ?? data.snapshot_update_blocked, }; runInAction(() => { this.mergeVehicleInCaches({ ...updatedVehiclePayload, id, }); }); }; setMaintenanceMode = async (uuid: string, enabled: boolean) => { const response = await authInstance.post( `/devices/${uuid}/maintenance-mode`, { enabled, }, ); const normalizedVehicle = this.normalizeVehicleItem(response.data); runInAction(() => { this.mergeVehicleInCaches({ ...normalizedVehicle.vehicle, uuid, maintenance_mode_on: normalizedVehicle.vehicle.maintenance_mode_on ?? enabled, }); }); }; setDemoMode = async (uuid: string, enabled: boolean) => { const response = await authInstance.post(`/devices/${uuid}/demo-mode`, { enabled, }); const normalizedVehicle = this.normalizeVehicleItem(response.data); runInAction(() => { this.mergeVehicleInCaches({ ...normalizedVehicle.vehicle, uuid, demo_mode_enabled: normalizedVehicle.vehicle.demo_mode_enabled ?? enabled, }); }); }; getVehicleSessions = mobxFetch< number, VehicleMaintenanceSession[], VehicleStore >({ store: this, value: "vehicleSessions", loading: "vehicleSessionsLoading", error: "vehicleSessionsError", resetValue: true, fn: getVehicleSessionsApi, }); } export const vehicleStore = new VehicleStore();