import { articlesStore, authInstance, Language, languageInstance, mediaStore, } from "@shared"; import { makeAutoObservable, runInAction } from "mobx"; export type SightLanguageInfo = { id: number; name: string; short_name: string; address: string; left: { heading: string; body: string; media: { id: string; media_type: number; filename: string }[]; }; right: { id: number; heading: string; body: string; media: { id: string; media_type: number; filename: string }[]; }[]; }; export type SightCommonInfo = { id: number; city_id: number; city: string; latitude: number; longitude: number; is_default_icon: boolean; thumbnail: string | null; icon: string | null; alt_icon: string | null; watermark_lu: string | null; watermark_rd: string | null; left_article: number; preview_media: string | null; video_preview: string | null; preview_font_size?: number; }; export type SightBaseInfo = { common: SightCommonInfo; } & { [key in Language]: SightLanguageInfo; }; class EditSightStore { sight: SightBaseInfo = { common: { id: 0, city_id: 0, city: "", latitude: 0, longitude: 0, is_default_icon: false, thumbnail: null, icon: null, alt_icon: null, watermark_lu: null, watermark_rd: null, left_article: 0, preview_media: null, video_preview: null, }, ru: { id: 0, name: "", short_name: "", address: "", left: { heading: "", body: "", media: [] }, right: [], }, en: { id: 0, name: "", short_name: "", address: "", left: { heading: "", body: "", media: [] }, right: [], }, zh: { id: 0, name: "", short_name: "", address: "", left: { heading: "", body: "", media: [] }, right: [], }, }; constructor() { makeAutoObservable(this); } hasLoadedCommon = false; isLoading = false; getSightInfo = async (id: number, language: Language) => { this.isLoading = true; try { const response = await languageInstance(language).get(`/sight/${id}`); const data = response.data; if (data.left_article != 0 && data.left_article != null) { await this.getLeftArticle(data.left_article); } runInAction(() => { this.sight[language] = { ...this.sight[language], ...data, }; if (!this.hasLoadedCommon) { this.sight.common = { ...this.sight.common, ...data, }; this.hasLoadedCommon = true; } }); } finally { this.isLoading = false; } }; updateLeftInfo = (language: Language, heading: string, body: string) => { this.sight[language].left.heading = heading; this.sight[language].left.body = body; }; getRightArticles = async (id: number) => { let responseRu = await languageInstance("ru").get(`/sight/${id}/article`); let responseEn = await languageInstance("en").get(`/sight/${id}/article`); let responseZh = await languageInstance("zh").get(`/sight/${id}/article`); const mediaMap = new Map(); for (const article of responseRu.data) { const responseMedia = await authInstance.get( `/article/${article.id}/media` ); mediaMap.set(article.id, responseMedia.data); } const addMediaToArticles = (articles: any[]) => { return articles.map((article) => ({ ...article, media: mediaMap.get(article.id), })); }; const data = { ru: { right: addMediaToArticles(responseRu.data), }, en: { right: addMediaToArticles(responseEn.data), }, zh: { right: addMediaToArticles(responseZh.data), }, }; runInAction(() => { this.sight = { ...this.sight, ru: { ...this.sight.ru, right: data.ru.right, }, en: { ...this.sight.en, right: data.en.right, }, zh: { ...this.sight.zh, right: data.zh.right, }, }; }); }; clearSightInfo = () => { this.needLeaveAgree = false; this.hasLoadedCommon = false; this.isLoading = false; this.sight = { common: { id: 0, city_id: 0, city: "", latitude: 0, longitude: 0, is_default_icon: false, thumbnail: null, icon: null, alt_icon: null, watermark_lu: null, watermark_rd: null, left_article: 0, preview_media: null, video_preview: null, }, ru: { id: 0, name: "", short_name: "", address: "", left: { heading: "", body: "", media: [] }, right: [], }, en: { id: 0, name: "", short_name: "", address: "", left: { heading: "", body: "", media: [] }, right: [], }, zh: { id: 0, name: "", short_name: "", address: "", left: { heading: "", body: "", media: [] }, right: [], }, }; }; updateSightInfo = ( language: Language, content: Partial, common: boolean = false ) => { this.needLeaveAgree = true; if (common) { this.sight.common = { ...this.sight.common, ...content, }; } else { this.sight[language] = { ...this.sight[language], ...content, }; } }; unlinkLeftArticle = async () => { this.sight.common.left_article = 0; this.sight.ru.left.heading = ""; this.sight.en.left.heading = ""; this.sight.zh.left.heading = ""; this.sight.ru.left.body = ""; this.sight.en.left.body = ""; this.sight.zh.left.body = ""; }; updateSight = async () => { let createdLeftArticleId = this.sight.common.left_article; if (this.sight.common.left_article == 10000000) { const response = await languageInstance("ru").post(`/article`, { heading: this.sight.ru.left.heading, body: this.sight.ru.left.body, }); createdLeftArticleId = response.data.id; await languageInstance("en").patch(`/article/${createdLeftArticleId}`, { heading: this.sight.en.left.heading, body: this.sight.en.left.body, }); await languageInstance("zh").patch(`/article/${createdLeftArticleId}`, { heading: this.sight.zh.left.heading, body: this.sight.zh.left.body, }); this.sight.common.left_article = createdLeftArticleId; } else if ( this.sight.common.left_article != 0 && this.sight.common.left_article != null ) { await authInstance.patch(`/article/${this.sight.common.left_article}`, { translations: { heading: { ru: this.sight.ru.left.heading, en: this.sight.en.left.heading, zh: this.sight.zh.left.heading, }, body: { ru: this.sight.ru.left.body, en: this.sight.en.left.body, zh: this.sight.zh.left.body, }, }, }); } await authInstance.patch(`/sight/${this.sight.common.id}`, { ...this.sight.common, translations: { name: { ru: (this.sight.ru.name || "").trim(), en: (this.sight.en.name || "").trim(), zh: (this.sight.zh.name || "").trim(), }, short_name: { ru: (this.sight.ru.short_name || "").trim(), en: (this.sight.en.short_name || "").trim(), zh: (this.sight.zh.short_name || "").trim(), }, address: { ru: this.sight.ru.address, en: this.sight.en.address, zh: this.sight.zh.address, }, }, }); for (let index = 0; index < this.sight.ru.right.length; index++) { const article = this.sight.ru.right[index]; if (article.id == 0 || article.id == null) { continue; } await authInstance.patch(`/article/${article.id}`, { translations: { heading: { ru: this.sight.ru.right[index].heading, en: this.sight.en.right[index].heading, zh: this.sight.zh.right[index].heading, }, body: { ru: this.sight.ru.right[index].body, en: this.sight.en.right[index].body, zh: this.sight.zh.right[index].body, }, }, }); } const articleIdsInObject = this.sight.ru.right.map((article) => ({ id: article.id, })); await authInstance.post(`/sight/${this.sight.common.id}/article/order`, { articles: articleIdsInObject, }); this.needLeaveAgree = false; }; getLeftArticle = async (id: number) => { const response = await languageInstance("ru").get(`/article/${id}`); const responseEn = await languageInstance("en").get(`/article/${id}`); const responseZh = await languageInstance("zh").get(`/article/${id}`); const mediaIds = await authInstance.get(`/article/${id}/media`); runInAction(() => { this.sight.ru.left = { heading: response.data.heading, body: response.data.body, media: mediaIds.data, }; this.sight.en.left = { heading: responseEn.data.heading, body: responseEn.data.body, media: mediaIds.data, }; this.sight.zh.left = { heading: responseZh.data.heading, body: responseZh.data.body, media: mediaIds.data, }; }); }; deleteLeftArticle = async (id: number) => { await authInstance.delete(`/article/${id}`); runInAction(() => { articlesStore.articles.ru = articlesStore.articles.ru.filter( (article) => article.id !== id ); articlesStore.articles.en = articlesStore.articles.en.filter( (article) => article.id !== id ); articlesStore.articles.zh = articlesStore.articles.zh.filter( (article) => article.id !== id ); }); this.sight.common.left_article = 0; this.sight.ru.left.heading = ""; this.sight.en.left.heading = ""; this.sight.zh.left.heading = ""; this.sight.ru.left.body = ""; this.sight.en.left.body = ""; this.sight.zh.left.body = ""; }; createLeftArticle = async () => { const ruName = (this.sight.ru.name || "").trim(); const enName = (this.sight.en.name || "").trim(); const zhName = (this.sight.zh.name || "").trim(); const hasAnyName = !!(ruName || enName || zhName); const response = await languageInstance("ru").post(`/article`, { heading: hasAnyName ? ruName : "", body: "", }); this.sight.common.left_article = response.data.id; await languageInstance("en").patch( `/article/${this.sight.common.left_article}`, { heading: hasAnyName ? enName : "", body: "", } ); await languageInstance("zh").patch( `/article/${this.sight.common.left_article}`, { heading: hasAnyName ? zhName : "", body: "", } ); this.sight.ru.left.heading = hasAnyName ? ruName : ""; this.sight.en.left.heading = hasAnyName ? enName : ""; this.sight.zh.left.heading = hasAnyName ? zhName : ""; this.sight.ru.left.body = ""; this.sight.en.left.body = ""; this.sight.zh.left.body = ""; }; deleteMedia = async (article_id: number, media_id: string) => { await authInstance.delete(`/article/${article_id}/media`, { data: { media_id: media_id, }, }); this.sight.ru.left.media = this.sight.ru.left.media.filter( (media) => media.id !== media_id ); this.sight.en.left.media = this.sight.en.left.media.filter( (media) => media.id !== media_id ); this.sight.zh.left.media = this.sight.zh.left.media.filter( (media) => media.id !== media_id ); }; unlinkRightArticle = async (article_id: number) => { await authInstance.delete(`/sight/${this.sight.common.id}/article`, { data: { article_id: article_id, }, }); this.sight.ru.right = this.sight.ru.right.filter( (article) => article.id !== article_id ); this.sight.en.right = this.sight.en.right.filter( (article) => article.id !== article_id ); this.sight.zh.right = this.sight.zh.right.filter( (article) => article.id !== article_id ); }; deleteRightArticle = async (article_id: number) => { this.sight.ru.right = this.sight.ru.right.filter( (article) => article.id !== article_id ); this.sight.en.right = this.sight.en.right.filter( (article) => article.id !== article_id ); this.sight.zh.right = this.sight.zh.right.filter( (article) => article.id !== article_id ); await authInstance.delete(`/article/${article_id}`); }; uploadMediaOpen = false; setUploadMediaOpen = (open: boolean) => { this.uploadMediaOpen = open; }; fileToUpload: File | null = null; setFileToUpload = (file: File | null) => { this.fileToUpload = file; }; uploadMedia = async ( filename: string, type: number, file: File, media_name?: string ) => { const formData = new FormData(); formData.append("file", file); formData.append("filename", filename); if (media_name) { formData.append("media_name", media_name); } formData.append("type", type.toString()); const response = await authInstance.post(`/media`, formData); this.fileToUpload = null; this.uploadMediaOpen = false; mediaStore.getMedia(); return { id: response.data.id, filename: filename, media_name: media_name, media_type: type, }; }; createLinkWithArticle = async (media: { id: string; filename: string; media_name?: string; media_type: number; }) => { await authInstance.post( `/article/${this.sight.common.left_article}/media`, { media_id: media.id, media_order: 1, } ); this.sight.ru.left.media.unshift({ id: media.id, media_type: media.media_type, filename: media.filename, }); this.sight.en.left.media.unshift({ id: media.id, media_type: media.media_type, filename: media.filename, }); this.sight.zh.left.media.unshift({ id: media.id, media_type: media.media_type, filename: media.filename, }); }; unlinkPreviewMedia = async () => { this.sight.common.preview_media = null; }; linkPreviewMedia = async (mediaId: string) => { this.sight.common.preview_media = mediaId; }; linkArticle = async (article_id: number) => { const response = await languageInstance("ru").get(`/article/${article_id}`); const responseEn = await languageInstance("en").get( `/article/${article_id}` ); const responseZh = await languageInstance("zh").get( `/article/${article_id}` ); const mediaIds = await authInstance.get(`/article/${article_id}/media`); runInAction(() => { this.sight.ru.right.push({ id: article_id, heading: response.data.heading, body: response.data.body, media: mediaIds.data, }); this.sight.en.right.push({ id: article_id, heading: responseEn.data.heading, body: responseEn.data.body, media: mediaIds.data, }); this.sight.zh.right.push({ id: article_id, heading: responseZh.data.heading, body: responseZh.data.body, media: mediaIds.data, }); }); return article_id; }; deleteRightArticleMedia = async (article_id: number, media_id: string) => { await authInstance.delete(`/article/${article_id}/media`, { data: { media_id: media_id, }, }); this.sight.ru.right = this.sight.ru.right.map((article) => { if (article.id === article_id) { article.media = article.media.filter((media) => media.id !== media_id); } return article; }); this.sight.en.right = this.sight.en.right.map((article) => { if (article.id === article_id) { article.media = article.media.filter((media) => media.id !== media_id); } return article; }); this.sight.zh.right = this.sight.zh.right.map((article) => { if (article.id === article_id) { article.media = article.media.filter((media) => media.id !== media_id); } return article; }); }; createNewRightArticle = async () => { const articleRuData = { heading: "Новый заголовок (RU)", body: "Новый текст (RU)", }; const articleEnData = { heading: "New Heading (EN)", body: "New Text (EN)", }; const articleZhData = { heading: "Новый заголовок (ZH)", body: "Новый текст (ZH)", }; const articleId = await authInstance.post("/article", { translations: { heading: { ru: articleRuData.heading, en: articleEnData.heading, zh: articleZhData.heading, }, body: { ru: articleRuData.body, en: articleEnData.body, zh: articleZhData.body, }, }, }); const { id } = articleId.data; await authInstance.post(`/sight/${this.sight.common.id}/article`, { article_id: id, page_num: this.sight.ru.right.length + 1, }); this.sight.ru.right.push({ id: id, heading: articleRuData.heading, body: articleRuData.body, media: [], }); this.sight.en.right.push({ id: id, heading: articleEnData.heading, body: articleEnData.body, media: [], }); this.sight.zh.right.push({ id: id, heading: articleZhData.heading, body: articleZhData.body, media: [], }); runInAction(() => { articlesStore.articles.ru.push({ id: id, heading: articleRuData.heading, body: articleRuData.body, service_name: articleRuData.heading, }); articlesStore.articles.en.push({ id: id, heading: articleEnData.heading, body: articleEnData.body, service_name: articleEnData.heading, }); articlesStore.articles.zh.push({ id: id, heading: articleZhData.heading, body: articleZhData.body, service_name: articleZhData.heading, }); }); return id; }; createLinkWithRightArticle = async ( media: { id: string; filename: string; media_name?: string; media_type: number; }, article_id: number ) => { await authInstance.post(`/article/${article_id}/media`, { media_id: media.id, media_order: 1, }); this.sight.ru.right = this.sight.ru.right.map((article) => { if (article.id === article_id) { article.media.unshift({ id: media.id, media_type: media.media_type, filename: media.filename, }); } return article; }); this.sight.en.right = this.sight.en.right.map((article) => { if (article.id === article_id) { article.media.unshift({ id: media.id, media_type: media.media_type, filename: media.filename, }); } return article; }); this.sight.zh.right = this.sight.zh.right.map((article) => { if (article.id === article_id) { article.media.unshift({ id: media.id, media_type: media.media_type, filename: media.filename, }); } return article; }); }; updateRightArticleInfo = ( index: number, language: Language, heading: string, body: string ) => { this.sight[language].right[index].heading = heading; this.sight[language].right[index].body = body; }; updateRightArticles = async (articles: any[]) => { const articlesIds = articles.map((article) => article.id); const sortArticles = (existing: any[]) => { const articleMap = new Map( existing.map((article) => [article.id, article]) ); return articlesIds .map((id) => articleMap.get(id)) .filter( (article): article is (typeof existing)[number] => article !== undefined ); }; this.sight.ru.right = sortArticles(this.sight.ru.right); this.sight.en.right = sortArticles(this.sight.en.right); this.sight.zh.right = sortArticles(this.sight.zh.right); this.needLeaveAgree = true; }; needLeaveAgree = false; setNeedLeaveAgree = (need: boolean) => { this.needLeaveAgree = need; }; } export const editSightStore = new EditSightStore();