feat: Add translation on 3 languages for sight page

This commit is contained in:
2025-06-01 00:34:59 +03:00
parent 0d9bbb140f
commit 87386c6a73
22 changed files with 768 additions and 732 deletions

View File

@ -53,7 +53,7 @@ class ArticlesStore {
const response = await authInstance.get(`/sight/${id}/article`);
runInAction(() => {
editSightStore.sightInfo[languageStore.language].right = response.data;
editSightStore.sight[languageStore.language].right = response.data;
});
};
@ -66,10 +66,14 @@ class ArticlesStore {
};
getArticleByArticleId = computed(() => {
if (editSightStore.sightInfo.left_article) {
return this.articles[languageStore.language].find(
(a) => a.id == editSightStore.sightInfo.left_article
if (editSightStore.sight.common.left_article) {
const language = languageStore.language;
const foundArticle = this.articles[language].find(
(a) => a.id == editSightStore.sight.common.left_article
);
editSightStore.sight[language].left.heading = foundArticle?.heading ?? "";
editSightStore.sight[language].left.body = foundArticle?.body ?? "";
return foundArticle;
}
return null;
});

View File

@ -79,7 +79,7 @@ class AuthStore {
};
get isAuthenticated() {
return this.payload?.token !== null;
return this.payload !== null;
}
get user() {

View File

@ -1,15 +1,16 @@
// @shared/stores/editSightStore.ts
import { Language } from "@shared";
import { makeAutoObservable } from "mobx";
import { authInstance, Language } from "@shared";
import { makeAutoObservable, runInAction } from "mobx";
export interface MediaObject {
id: string;
filename: string;
media_type: number;
}
type SightBaseInfo = {
export type SightLanguageInfo = {
id: number;
name: string;
address: string;
left: { heading: string; body: string };
right: { heading: string; body: string }[];
};
export type SightCommonInfo = {
city_id: number;
city: string;
latitude: number;
@ -22,103 +23,14 @@ type SightBaseInfo = {
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[];
};
export type SightBaseInfo = {
common: SightCommonInfo;
} & {
[key in Language]: SightLanguageInfo;
};
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,
sight: SightBaseInfo = {
common: {
city_id: 0,
city: "",
latitude: 0,
@ -129,23 +41,123 @@ class EditSightStore {
left_article: 0,
preview_media: "",
video_preview: "",
},
ru: {
id: 0,
name: "",
address: "",
left: { heading: "", body: "" },
right: [],
},
en: {
id: 0,
name: "",
address: "",
left: { heading: "", body: "" },
right: [],
},
zh: {
id: 0,
name: "",
address: "",
left: { heading: "", body: "" },
right: [],
},
};
constructor() {
makeAutoObservable(this);
}
hasLoadedCommon = false;
getSightInfo = async (id: number, language: Language) => {
if (this.sight[language].id === id) {
return;
}
const response = await authInstance.get(`/sight/${id}`);
const data = response.data;
runInAction(() => {
// Обновляем языковую часть
this.sight[language] = {
...this.sight[language],
...data,
};
// Только при первом запросе обновляем общую часть
if (!this.hasLoadedCommon) {
this.sight.common = {
...this.sight.common,
...data,
};
this.hasLoadedCommon = true;
}
});
};
updateLeftInfo = (language: Language, heading: string, body: string) => {
this.sight[language].left.heading = heading;
this.sight[language].left.body = body;
};
clearSightInfo = () => {
this.sight = {
common: {
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 },
id: 0,
name: "",
address: "",
left: { heading: "", body: "" },
right: [],
},
en: {
info: { name: "", address: "" },
left: { loaded: false, heading: "", body: "", media: null },
id: 0,
name: "",
address: "",
left: { heading: "", body: "" },
right: [],
},
zh: {
info: { name: "", address: "" },
left: { loaded: false, heading: "", body: "", media: null },
id: 0,
name: "",
address: "",
left: { heading: "", body: "" },
right: [],
},
};
};
updateSightInfo = (
language: Language,
content: Partial<SightLanguageInfo | SightCommonInfo>,
common: boolean = false
) => {
if (common) {
this.sight.common = {
...this.sight.common,
...content,
};
} else {
this.sight[language] = {
...this.sight[language],
...content,
};
}
};
}
export const editSightStore = new EditSightStore();

View File

@ -1,9 +1,8 @@
import {
articlesStore,
authInstance,
languageInstance,
languageStore,
editSightStore,
SightBaseInfo,
} from "@shared";
import { computed, makeAutoObservable, runInAction } from "mobx";
@ -59,48 +58,40 @@ class SightsStore {
});
};
getSight = async (id: number) => {
const response = await authInstance.get(`/sight/${id}`);
// getSight = async (id: number) => {
// const response = await authInstance.get(`/sight/${id}`);
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);
});
};
// 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,
// },
// left: {
// heading: articlesStore.articles[languageStore.language].find(
// (article) => article.id === response.data.left_article
// )?.heading,
// body: articlesStore.articles[languageStore.language].find(
// },
// },
// };
// });
// };
createSightAction = async (
city: number,
@ -160,12 +151,32 @@ class SightsStore {
language: Language,
content: Partial<CreateSight[Language]>
) => {
runInAction(() => {
this.createSight[language] = {
...this.createSight[language],
this.createSight[language] = {
...this.createSight[language],
...content,
};
};
updateSight = (
language: Language,
content: Partial<SightBaseInfo[Language]>,
common: boolean
) => {
if (common) {
// @ts-ignore
this.sight!.common = {
// @ts-ignore
...this.sight!.common,
...content,
};
});
} else {
// @ts-ignore
this.sight![language] = {
// @ts-ignore
...this.sight![language],
...content,
};
}
};
clearCreateSight = () => {