Files
WhiteNightsAdminPanel/src/shared/store/StationsStore/index.ts

558 lines
14 KiB
TypeScript

import { authInstance, languageInstance, languageStore } from "@shared";
import { makeAutoObservable, runInAction } from "mobx";
type Language = "ru" | "en" | "zh";
type StationLanguageData = {
name: string;
system_name: string;
address: string;
loaded: boolean; // Indicates if this language's data has been loaded/modified
};
type StationCommonData = {
city_id: number;
direction: boolean;
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;
direction: boolean;
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,
},
};
// This will store the full station data, keyed by ID and then by language
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,
direction: false,
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,
direction: false,
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,
direction: ruResponse.data.direction,
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,
},
};
};
// Sets language-specific station data
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,
direction: this.editStationData.common.direction,
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 || "",
system_name: name || "", // system_name is often derived from name
description: description || "",
address: address || "",
...commonDataPayload,
}
);
runInAction(() => {
// Update the cached preview data and station lists after successful patch
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);
// Also clear from stationPreview cache
if (this.stationPreview[id]) {
delete this.stationPreview[id];
}
// Clear from stationLists as well for all languages
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,
direction: this.createStationData.common.direction,
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;
}
// First create station in Russian
const { name, address } = this.createStationData[language];
const description = this.createStationData.common.description;
const response = await languageInstance(language).post("/station", {
name: name || "",
system_name: name || "", // system_name is often derived from name
description: description || "",
address: address || "",
...commonDataPayload,
});
runInAction(() => {
this.stationLists[language].data.push(response.data);
});
const stationId = response.data.id;
// Then update for other languages
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 || "",
system_name: name || "", // system_name is often derived from name
description: description || "",
address: address || "",
...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,
direction: false,
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;
};
// Reset editStationData when navigating away or after saving
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,
direction: false,
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: "",
},
},
};
};
}
export const stationsStore = new StationsStore();