Files
WhiteNightsAdminPanel/src/shared/store/StationsStore/index.ts
2026-04-09 20:07:18 +03:00

635 lines
16 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { authInstance, languageInstance, languageStore } from "@shared";
import { makeAutoObservable, runInAction } from "mobx";
import { routeStore } from "../RouteStore";
type Language = "ru" | "en" | "zh";
type StationLanguageData = {
name: string;
system_name: string;
address: string;
loaded: boolean;
};
type StationCommonData = {
city_id: number;
description: string;
icon: string;
latitude: number;
longitude: number;
offset_x: number;
offset_y: number;
transfers: {
bus: string;
metro_blue: string;
metro_green: string;
metro_orange: string;
metro_purple: string;
metro_red: string;
train: string;
tram: string;
trolleybus: string;
};
city: string;
};
type EditStationData = {
[key in Language]: StationLanguageData;
} & { common: StationCommonData };
type Station = {
id: number;
address: string;
city: string;
city_id: number;
description: string;
icon: string;
latitude: number;
longitude: number;
name: string;
offset_x: number;
offset_y: number;
system_name: string;
transfers: {
bus: string;
metro_blue: string;
metro_green: string;
metro_orange: string;
metro_purple: string;
metro_red: string;
train: string;
tram: string;
trolleybus: string;
};
};
type CreateStationData = {
[key in Language]: StationLanguageData;
} & { common: StationCommonData };
class StationsStore {
stations: Station[] = [];
station: Station | null = null;
stationLists: {
[key in Language]: {
data: Station[];
loaded: boolean;
};
} = {
ru: {
data: [],
loaded: false,
},
en: {
data: [],
loaded: false,
},
zh: {
data: [],
loaded: false,
},
};
stationPreview: Record<
string,
Record<string, { loaded: boolean; data: Station }>
> = {};
editStationData: EditStationData = {
ru: {
name: "",
system_name: "",
address: "",
loaded: false,
},
en: {
name: "",
system_name: "",
address: "",
loaded: false,
},
zh: {
name: "",
system_name: "",
address: "",
loaded: false,
},
common: {
city: "",
city_id: 0,
description: "",
icon: "",
latitude: 0,
longitude: 0,
offset_x: 0,
offset_y: 0,
transfers: {
bus: "",
metro_blue: "",
metro_green: "",
metro_orange: "",
metro_purple: "",
metro_red: "",
train: "",
tram: "",
trolleybus: "",
},
},
};
createStationData: CreateStationData = {
ru: {
name: "",
system_name: "",
address: "",
loaded: false,
},
en: {
name: "",
system_name: "",
address: "",
loaded: false,
},
zh: {
name: "",
system_name: "",
address: "",
loaded: false,
},
common: {
city: "",
city_id: 0,
description: "",
icon: "",
latitude: 0,
longitude: 0,
offset_x: 0,
offset_y: 0,
transfers: {
bus: "",
metro_blue: "",
metro_green: "",
metro_orange: "",
metro_purple: "",
metro_red: "",
train: "",
tram: "",
trolleybus: "",
},
},
};
constructor() {
makeAutoObservable(this);
}
getStations = async () => {
const response = await authInstance.get("/station");
runInAction(() => {
this.stations = response.data;
});
};
getStationList = async () => {
const { language } = languageStore;
if (this.stationLists[language].loaded) {
return;
}
const response = await authInstance.get("/station");
runInAction(() => {
this.stationLists[language].data = response.data;
this.stationLists[language].loaded = true;
});
};
setEditCommonData = (data: Partial<StationCommonData>) => {
this.editStationData.common = {
...this.editStationData.common,
...data,
};
};
getEditStation = async (id: number) => {
const ruResponse = await languageInstance("ru").get(`/station/${id}`);
const enResponse = await languageInstance("en").get(`/station/${id}`);
const zhResponse = await languageInstance("zh").get(`/station/${id}`);
this.editStationData = {
ru: {
name: ruResponse.data.name,
system_name: ruResponse.data.system_name,
address: ruResponse.data.address,
loaded: true,
},
en: {
name: enResponse.data.name,
system_name: enResponse.data.system_name,
address: enResponse.data.address,
loaded: true,
},
zh: {
name: zhResponse.data.name,
system_name: zhResponse.data.system_name,
address: zhResponse.data.address,
loaded: true,
},
common: {
city: ruResponse.data.city,
city_id: ruResponse.data.city_id,
description: ruResponse.data.description,
icon: ruResponse.data.icon,
latitude: ruResponse.data.latitude,
longitude: ruResponse.data.longitude,
offset_x: ruResponse.data.offset_x,
offset_y: ruResponse.data.offset_y,
transfers: ruResponse.data.transfers,
},
};
};
setLanguageEditStationData = (
language: Language,
data: Partial<StationLanguageData>
) => {
this.editStationData[language] = {
...this.editStationData[language],
...data,
};
};
editStation = async (id: number) => {
const commonDataPayload = {
city_id: this.editStationData.common.city_id,
icon: this.editStationData.common.icon,
latitude: this.editStationData.common.latitude,
longitude: this.editStationData.common.longitude,
offset_x: this.editStationData.common.offset_x,
offset_y: this.editStationData.common.offset_y,
transfers: this.editStationData.common.transfers,
city: this.editStationData.common.city,
};
for (const language of ["ru", "en", "zh"] as const) {
const { name, address } = this.editStationData[language];
const description = this.editStationData.common.description;
const response = await languageInstance(language).patch(
`/station/${id}`,
{
name: (name || "").trim(),
system_name: (name || "").trim(),
description: (description || "").trim(),
address: (address || "").trim(),
...commonDataPayload,
}
);
runInAction(() => {
if (this.stationPreview[id]) {
this.stationPreview[id][language] = {
loaded: true,
data: {
...this.stationPreview[id][language].data,
id: response.data.id,
name: response.data.name,
system_name: response.data.system_name,
description: response.data.description,
address: response.data.address,
...commonDataPayload,
} as Station,
};
}
if (this.stationLists[language].data) {
this.stationLists[language].data = this.stationLists[
language
].data.map((station: Station) =>
station.id === id
? ({
...station,
name: response.data.name,
system_name: response.data.system_name,
description: description || "",
address: response.data.address,
...commonDataPayload,
} as Station)
: station
);
}
});
}
};
deleteStation = async (id: number) => {
await authInstance.delete(`/station/${id}`);
runInAction(() => {
this.stations = this.stations.filter((station) => station.id !== id);
if (this.stationPreview[id]) {
delete this.stationPreview[id];
}
for (const lang of ["ru", "en", "zh"] as const) {
if (this.stationLists[lang].data) {
this.stationLists[lang].data = this.stationLists[lang].data.filter(
(station) => station.id !== id
);
}
}
});
};
getStation = async (id: number) => {
const response = await authInstance.get(`/station/${id}`);
this.station = response.data;
};
getStationPreview = async (id: number) => {
const { language } = languageStore;
if (this.stationPreview[id]?.[language]?.loaded) {
return;
}
const response = await languageInstance(language).get(`/station/${id}`);
runInAction(() => {
if (!this.stationPreview[id]) {
this.stationPreview[id] = {
ru: { loaded: false, data: {} as Station },
en: { loaded: false, data: {} as Station },
zh: { loaded: false, data: {} as Station },
};
}
this.stationPreview[id][language] = {
loaded: true,
data: response.data as Station,
};
});
};
setCreateCommonData = (data: Partial<StationCommonData>) => {
this.createStationData.common = {
...this.createStationData.common,
...data,
};
};
setLanguageCreateStationData = (
language: Language,
data: Partial<StationLanguageData>
) => {
this.createStationData[language] = {
...this.createStationData[language],
...data,
};
};
createStation = async () => {
const { language } = languageStore;
let commonDataPayload: Partial<StationCommonData> = {
city_id: this.createStationData.common.city_id,
icon: this.createStationData.common.icon,
latitude: this.createStationData.common.latitude,
longitude: this.createStationData.common.longitude,
offset_x: this.createStationData.common.offset_x,
offset_y: this.createStationData.common.offset_y,
transfers: this.createStationData.common.transfers,
city: this.createStationData.common.city,
};
if (this.createStationData.common.icon === "") {
delete commonDataPayload.icon;
}
const { name, address } = this.createStationData[language];
const description = this.createStationData.common.description;
const response = await languageInstance(language).post("/station", {
name: (name || "").trim(),
system_name: (name || "").trim(),
description: (description || "").trim(),
address: (address || "").trim(),
...commonDataPayload,
});
runInAction(() => {
this.stationLists[language].data.push(response.data);
});
const stationId = response.data.id;
for (const lang of ["ru", "en", "zh"].filter(
(lang) => lang !== language
) as Language[]) {
const { name, address } = this.createStationData[lang];
const description = this.createStationData.common.description;
const response = await languageInstance(lang).patch(
`/station/${stationId}`,
{
name: (name || "").trim(),
system_name: (name || "").trim(),
description: (description || "").trim(),
address: (address || "").trim(),
...commonDataPayload,
}
);
runInAction(() => {
this.stationLists[lang].data.push(response.data);
});
}
runInAction(() => {
this.createStationData = {
ru: {
name: "",
system_name: "",
address: "",
loaded: false,
},
en: {
name: "",
system_name: "",
address: "",
loaded: false,
},
zh: {
name: "",
system_name: "",
address: "",
loaded: false,
},
common: {
city: "",
city_id: 0,
icon: "",
latitude: 0,
description: "",
longitude: 0,
offset_x: 0,
offset_y: 0,
transfers: {
bus: "",
metro_blue: "",
metro_green: "",
metro_orange: "",
metro_purple: "",
metro_red: "",
train: "",
tram: "",
trolleybus: "",
},
},
};
});
return response.data;
};
resetEditStationData = () => {
this.editStationData = {
ru: {
name: "",
system_name: "",
address: "",
loaded: false,
},
en: {
name: "",
system_name: "",
address: "",
loaded: false,
},
zh: {
name: "",
system_name: "",
address: "",
loaded: false,
},
common: {
city: "",
city_id: 0,
description: "",
icon: "",
latitude: 0,
longitude: 0,
offset_x: 0,
offset_y: 0,
transfers: {
bus: "",
metro_blue: "",
metro_green: "",
metro_orange: "",
metro_purple: "",
metro_red: "",
train: "",
tram: "",
trolleybus: "",
},
},
};
};
updateStationTransfers = async (
id: number,
transfers: {
bus: string;
metro_blue: string;
metro_green: string;
metro_orange: string;
metro_purple: string;
metro_red: string;
train: string;
tram: string;
trolleybus: string;
}
) => {
const { language } = languageStore;
const response = await languageInstance(language).get(`/station/${id}`);
const stationData = response.data as Station;
if (!stationData) {
throw new Error("Station not found");
}
// Формируем commonDataPayload как в editStation, с обновленными transfers
const commonDataPayload = {
city_id: stationData.city_id,
latitude: stationData.latitude,
longitude: stationData.longitude,
offset_x: stationData.offset_x,
offset_y: stationData.offset_y,
transfers: transfers,
city: stationData.city || "",
};
// Отправляем один PATCH запрос, так как пересадки общие для всех языков
const patchResponse = await languageInstance(language).patch(
`/station/${id}`,
{
name: stationData.name || "",
system_name: stationData.system_name || "",
description: stationData.description || "",
address: stationData.address || "",
...commonDataPayload,
}
);
// Обновляем данные для всех языков в локальном состоянии
runInAction(() => {
const updatedTransfers = patchResponse.data.transfers;
for (const lang of ["ru", "en", "zh"] as const) {
if (this.stationPreview[id]) {
this.stationPreview[id][lang] = {
...this.stationPreview[id][lang],
data: {
...this.stationPreview[id][lang].data,
transfers: updatedTransfers,
},
};
}
if (this.stationLists[lang].data) {
this.stationLists[lang].data = this.stationLists[lang].data.map(
(station: Station) =>
station.id === id
? {
...station,
transfers: updatedTransfers,
}
: station
);
}
}
// Обновляем пересадки в RouteStore.routeStations для всех маршрутов
if (routeStore?.routeStations) {
for (const routeId in routeStore.routeStations) {
routeStore.routeStations[routeId] = routeStore.routeStations[
routeId
].map((station: any) =>
station.id === id
? {
...station,
transfers: updatedTransfers,
}
: station
);
}
}
});
};
}
export const stationsStore = new StationsStore();