import { authInstance, languageInstance, Language, languageStore, countryStore, CashedCountries, } from "@shared"; import { makeAutoObservable, runInAction } from "mobx"; export type City = { id?: number; name: string; country: string; country_code: string; arms: string; }; export type CashedCities = { ru: { data: City[]; loaded: boolean; }; en: { data: City[]; loaded: boolean; }; zh: { data: City[]; loaded: boolean; }; }; export type CashedCity = { ru: City | null; en: City | null; zh: City | null; }; class CityStore { cities: CashedCities = { ru: { data: [], loaded: false, }, en: { data: [], loaded: false, }, zh: { data: [], loaded: false, }, }; city: Record = {}; constructor() { makeAutoObservable(this); } ruCities: { data: City[]; loaded: boolean; } = { data: [], loaded: false, }; getRuCities = async () => { if (this.ruCities.loaded) { return; } const response = await languageInstance("ru").get(`/city`); runInAction(() => { this.ruCities.data = response.data; this.ruCities.loaded = true; }); }; getCities = async (language: keyof CashedCities) => { if (this.cities[language].loaded) { return; } const response = await languageInstance(language).get(`/city`); runInAction(() => { this.cities[language].data = response.data; this.cities[language].loaded = true; }); }; getCity = async (code: string, language: keyof CashedCities) => { if (this.city[code]?.[language] && this.city[code][language] !== null) { return; } const response = await languageInstance(language).get(`/city/${code}`); runInAction(() => { if (!this.city[code]) { this.city[code] = { ru: null, en: null, zh: null, }; } this.city[code][language] = response.data; }); return response.data; }; deleteCity = async (code: string) => { await authInstance.delete(`/city/${code}`); runInAction(() => { for (const secondaryLanguage of ["ru", "en", "zh"] as Language[]) { this.cities[secondaryLanguage].data = this.cities[ secondaryLanguage ].data.filter((city) => city.id !== Number(code)); if (this.city[code]) { this.city[code][secondaryLanguage] = null; } } }); }; createCityData = { country_code: "", arms: "", ru: { name: "", }, en: { name: "", }, zh: { name: "", }, }; setCreateCityData = ( name: string, country_code: string, arms: string, language: keyof CashedCities ) => { this.createCityData = { ...this.createCityData, country_code: country_code, arms: arms, [language]: { name: name, }, }; }; async createCity() { const language = languageStore.language as Language; const { country_code, arms } = this.createCityData; const { name } = this.createCityData[language]; if (!name || !country_code) { return; } try { // Create city in primary language const cityPayload = { name, country: countryStore.countries[language as keyof CashedCountries]?.data.find( (c) => c.code === country_code )?.name || "", country_code, ...(arms ? { arms } : {}), }; const cityResponse = await languageInstance(language).post( "/city", cityPayload ); const cityId = cityResponse.data.id; // Create/update other language versions for (const secondaryLanguage of (["ru", "en", "zh"] as Language[]).filter( (l) => l !== language )) { const { name: secondaryName } = this.createCityData[secondaryLanguage]; // Get country name in secondary language const countryName = countryStore.countries[secondaryLanguage]?.data.find( (c) => c.code === country_code )?.name || ""; const patchPayload = { name: secondaryName || "", country: countryName, country_code: country_code || "", ...(arms ? { arms } : {}), }; const patchResponse = await languageInstance(secondaryLanguage).patch( `/city/${cityId}`, patchPayload ); runInAction(() => { this.cities[secondaryLanguage].data = [ ...this.cities[secondaryLanguage].data, patchResponse.data, ]; }); } // Update primary language data runInAction(() => { this.cities[language].data = [ ...this.cities[language].data, cityResponse.data, ]; }); // Reset form data runInAction(() => { this.createCityData = { country_code: "", arms: "", ru: { name: "" }, en: { name: "" }, zh: { name: "" }, }; }); } catch (error) { console.error("Error creating city:", error); throw error; } } editCityData = { country_code: "", arms: "", ru: { name: "", }, en: { name: "", }, zh: { name: "", }, }; setEditCityData = ( name: string, country_code: string, arms: string, language: keyof CashedCities ) => { this.editCityData = { ...this.editCityData, country_code: country_code, arms: arms, [language]: { name: name, }, }; }; editCity = async (code: string) => { for (const language of ["ru", "en", "zh"]) { const { country_code, arms } = this.editCityData; const { name } = this.editCityData[language as keyof CashedCities]; const { countries } = countryStore; const country = countries[language as keyof CashedCities].data.find( (country) => country.code === country_code ); await languageInstance(language as Language).patch(`/city/${code}`, { name, country: country?.name || "", country_code: country_code, arms, }); runInAction(() => { if (this.city[code]) { this.city[code][language as keyof CashedCities] = { name, country: country?.name || "", country_code: country_code, arms, }; } if (this.cities[language as keyof CashedCities]) { this.cities[language as keyof CashedCities].data = this.cities[ language as keyof CashedCities ].data.map((city) => city.id === Number(code) ? { id: city.id, name, country: country?.name || "", country_code: country_code, arms, } : city ); } }); } }; } export const cityStore = new CityStore();