fix: Language cache sight

This commit is contained in:
2025-05-31 21:17:27 +03:00
parent 2e6917406e
commit 0d9bbb140f
28 changed files with 2760 additions and 1013 deletions

View File

@ -1,36 +1,78 @@
import { authInstance } from "@shared";
import { makeAutoObservable, runInAction } from "mobx";
import { authInstance, editSightStore, Language, languageStore } from "@shared";
import { computed, makeAutoObservable, runInAction } from "mobx";
export type Article = {
id: string;
id: number;
heading: string;
body: string;
service_name: string;
};
type Media = {
id: string;
filename: string;
media_name: string;
media_type: number;
};
class ArticlesStore {
constructor() {
makeAutoObservable(this);
}
articles: Article[] = [];
articles: { [key in Language]: Article[] } = {
ru: [],
en: [],
zh: [],
};
articleData: Article | null = null;
articleMedia: Media | null = null;
articleLoading: boolean = false;
getArticles = async () => {
getArticles = async (language: Language) => {
this.articleLoading = true;
const response = await authInstance.get("/article");
runInAction(() => {
this.articles = response.data;
this.articles[language] = response.data;
});
this.articleLoading = false;
};
getArticle = async (id: string) => {
getArticle = async (id: number) => {
this.articleLoading = true;
const response = await authInstance.get(`/article/${id}`);
runInAction(() => {
this.articleData = response.data;
});
this.articleLoading = false;
};
getSightArticles = async (id: number) => {
const response = await authInstance.get(`/sight/${id}/article`);
runInAction(() => {
editSightStore.sightInfo[languageStore.language].right = response.data;
});
};
getArticleMedia = async (id: number) => {
const response = await authInstance.get(`/article/${id}/media`);
runInAction(() => {
this.articleMedia = response.data[0];
});
};
getArticleByArticleId = computed(() => {
if (editSightStore.sightInfo.left_article) {
return this.articles[languageStore.language].find(
(a) => a.id == editSightStore.sightInfo.left_article
);
}
return null;
});
}
export const articlesStore = new ArticlesStore();

View File

@ -0,0 +1,151 @@
// @shared/stores/editSightStore.ts
import { Language } from "@shared";
import { makeAutoObservable } from "mobx";
export interface MediaObject {
id: string;
filename: string;
media_type: number;
}
type SightBaseInfo = {
id: number;
city_id: number;
city: string;
latitude: number;
longitude: number;
thumbnail: string;
watermark_lu: string;
watermark_rd: string;
left_article: number;
preview_media: string;
video_preview: string;
};
export interface RightArticleBlock {
id: string;
type: "article" | "preview_media";
name: string;
linkedArticleId?: string;
heading: string;
body: string;
media: MediaObject | null;
}
type SightInfo = SightBaseInfo & {
[key in Language]: {
info: {
name: string;
address: string;
};
left: {
loaded: boolean; // Означает, что данные для этого языка были инициализированы/загружены
heading: string;
body: string;
media: MediaObject | null;
};
right: RightArticleBlock[];
};
};
class EditSightStore {
sightInfo: SightInfo = {
id: 0,
city_id: 0,
city: "",
latitude: 0,
longitude: 0,
thumbnail: "",
watermark_lu: "",
watermark_rd: "",
left_article: 0,
preview_media: "",
video_preview: "",
ru: {
info: { name: "", address: "" },
left: { loaded: false, heading: "", body: "", media: null },
right: [],
},
en: {
info: { name: "", address: "" },
left: { loaded: false, heading: "", body: "", media: null },
right: [],
},
zh: {
info: { name: "", address: "" },
left: { loaded: false, heading: "", body: "", media: null },
right: [],
},
};
constructor() {
makeAutoObservable(this);
}
// loadSightInfo: Используется для первоначальной загрузки данных для ЯЗЫКА.
// Она устанавливает loaded: true, чтобы в будущем не перезатирать данные.
loadSightInfo = (
language: Language,
heading: string,
body: string,
media: MediaObject | null
) => {
// Важно: если данные уже были загружены или изменены, не перезаписывайте их.
// Это предотвращает потерю пользовательского ввода при переключении языков.
// Если хотите принудительную загрузку, добавьте другой метод или параметр.
if (!this.sightInfo[language].left.loaded) {
// <--- Только если еще не загружено
this.sightInfo[language].left.heading = heading;
this.sightInfo[language].left.body = body;
this.sightInfo[language].left.media = media;
this.sightInfo[language].left.loaded = true; // <--- Устанавливаем loaded только при загрузке
}
};
// updateSightInfo: Используется для сохранения ЛЮБЫХ пользовательских изменений.
// Она НЕ должна влиять на флаг 'loaded', который управляется 'loadSightInfo'.
updateSightInfo = (
language: Language,
heading: string,
body: string,
media: MediaObject | null
) => {
this.sightInfo[language].left.heading = heading;
this.sightInfo[language].left.body = body;
this.sightInfo[language].left.media = media;
// this.sightInfo[language].left.loaded = true; // <-- УДАЛИТЕ эту строку
};
clearSightInfo = () => {
this.sightInfo = {
id: 0,
city_id: 0,
city: "",
latitude: 0,
longitude: 0,
thumbnail: "",
watermark_lu: "",
watermark_rd: "",
left_article: 0,
preview_media: "",
video_preview: "",
ru: {
info: { name: "", address: "" },
left: { loaded: false, heading: "", body: "", media: null },
right: [],
},
en: {
info: { name: "", address: "" },
left: { loaded: false, heading: "", body: "", media: null },
right: [],
},
zh: {
info: { name: "", address: "" },
left: { loaded: false, heading: "", body: "", media: null },
right: [],
},
};
};
}
export const editSightStore = new EditSightStore();

View File

@ -0,0 +1,27 @@
import { makeAutoObservable, runInAction } from "mobx";
import { authInstance } from "@shared";
type Media = {
id: string;
filename: string;
media_name: string;
media_type: number;
};
class MediaStore {
media: Media[] = [];
constructor() {
makeAutoObservable(this);
}
getMedia = async () => {
const response = await authInstance.get("/media");
runInAction(() => {
this.media = [...response.data];
});
};
}
export const mediaStore = new MediaStore();

View File

@ -1,12 +1,17 @@
import { authInstance, languageInstance, languageStore } from "@shared";
import { makeAutoObservable, runInAction } from "mobx";
import {
articlesStore,
authInstance,
languageInstance,
languageStore,
editSightStore,
} from "@shared";
import { computed, makeAutoObservable, runInAction } from "mobx";
export type Language = "ru" | "en" | "zh";
export type MultilingualContent = {
[key in Language]: {
name: string;
description: string;
address: string;
};
};
@ -30,7 +35,6 @@ export type Sight = {
export type CreateSight = {
[key in Language]: {
name: string;
description: string;
address: string;
};
};
@ -39,9 +43,9 @@ class SightsStore {
sights: Sight[] = [];
sight: Sight | null = null;
createSight: CreateSight = {
ru: { name: "", description: "", address: "" },
en: { name: "", description: "", address: "" },
zh: { name: "", description: "", address: "" },
ru: { name: "", address: "" },
en: { name: "", address: "" },
zh: { name: "", address: "" },
};
constructor() {
@ -60,6 +64,41 @@ class SightsStore {
runInAction(() => {
this.sight = response.data;
editSightStore.sightInfo = {
...editSightStore.sightInfo,
id: response.data.id,
city_id: response.data.city_id,
city: response.data.city,
latitude: response.data.latitude,
longitude: response.data.longitude,
thumbnail: response.data.thumbnail,
watermark_lu: response.data.watermark_lu,
watermark_rd: response.data.watermark_rd,
left_article: response.data.left_article,
preview_media: response.data.preview_media,
video_preview: response.data.video_preview,
[languageStore.language]: {
info: {
name: response.data.name,
address: response.data.address,
description: response.data.description,
},
left: {
heading: editSightStore.sightInfo[languageStore.language].left
.loaded
? editSightStore.sightInfo[languageStore.language].left.heading
: articlesStore.articles[languageStore.language].find(
(article) => article.id === response.data.left_article
)?.heading,
body: editSightStore.sightInfo[languageStore.language].left.loaded
? editSightStore.sightInfo[languageStore.language].left.body
: articlesStore.articles[languageStore.language].find(
(article) => article.id === response.data.left_article
)?.body,
},
},
};
console.log(editSightStore.sightInfo);
});
};
@ -70,7 +109,6 @@ class SightsStore {
const id = (
await authInstance.post("/sight", {
name: this.createSight[languageStore.language].name,
description: this.createSight[languageStore.language].description,
address: this.createSight[languageStore.language].address,
city_id: city,
latitude: coordinates.latitude,
@ -86,8 +124,6 @@ class SightsStore {
`/sight/${id}`,
{
name: this.createSight[anotherLanguages[0] as Language].name,
description:
this.createSight[anotherLanguages[0] as Language].description,
address: this.createSight[anotherLanguages[0] as Language].address,
city_id: city,
latitude: coordinates.latitude,
@ -99,8 +135,6 @@ class SightsStore {
`/sight/${id}`,
{
name: this.createSight[anotherLanguages[1] as Language].name,
description:
this.createSight[anotherLanguages[1] as Language].description,
address: this.createSight[anotherLanguages[1] as Language].address,
city_id: city,
latitude: coordinates.latitude,
@ -110,9 +144,9 @@ class SightsStore {
runInAction(() => {
this.createSight = {
ru: { name: "", description: "", address: "" },
en: { name: "", description: "", address: "" },
zh: { name: "", description: "", address: "" },
ru: { name: "", address: "" },
en: { name: "", address: "" },
zh: { name: "", address: "" },
};
});
};
@ -139,22 +173,41 @@ class SightsStore {
this.createSight = {
ru: {
name: "",
description: "",
address: "",
},
en: {
name: "",
description: "",
address: "",
},
zh: {
name: "",
description: "",
address: "",
},
};
});
};
sightData = computed(() => {
return {
name: this.sight?.name,
address: this.sight?.address,
city_id: this.sight?.city_id,
latitude: this.sight?.latitude,
longitude: this.sight?.longitude,
thumbnail: this.sight?.thumbnail,
watermark_lu: this.sight?.watermark_lu,
watermark_rd: this.sight?.watermark_rd,
left_article: this.sight?.left_article,
preview_media: this.sight?.preview_media,
video_preview: this.sight?.video_preview,
[languageStore.language]: {
info: {
name: this.sight?.name,
address: this.sight?.address,
},
},
};
});
}
export const sightsStore = new SightsStore();

View File

@ -6,3 +6,5 @@ export * from "./SnapshotStore";
export * from "./SightsStore";
export * from "./CityStore";
export * from "./ArticlesStore";
export * from "./EditSightStore";
export * from "./MediaStore";