Files
WhiteNightsAdminPanel/src/shared/store/VehicleStore/index.ts
2026-03-18 20:11:07 +03:00

264 lines
6.8 KiB
TypeScript

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<string, Vehicle> = {};
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<string, unknown> = {
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<string, unknown> = {
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();