fix: Update map with tables fixes

This commit is contained in:
2025-07-09 18:56:18 +03:00
parent 78800ee2ae
commit e2547cb571
87 changed files with 5392 additions and 1410 deletions

View File

@@ -31,7 +31,7 @@ import { toast } from "react-toastify";
export const CreateInformationTab = observer(
({ value, index }: { value: number; index: number }) => {
const { ruCities } = cityStore;
const { cities } = cityStore;
const [mediaId, setMediaId] = useState<string>("");
const [isPreviewMediaOpen, setIsPreviewMediaOpen] = useState(false);
const [isUploadMediaOpen, setIsUploadMediaOpen] = useState(false);
@@ -175,10 +175,11 @@ export const CreateInformationTab = observer(
/>
<Autocomplete
options={ruCities.data ?? []}
options={cities["ru"]?.data ?? []}
value={
ruCities.data.find((city) => city.id === sight.city_id) ??
null
cities["ru"]?.data?.find(
(city) => city.id === sight.city_id
) ?? null
}
getOptionLabel={(option) => option.name}
onChange={(_, value) => {
@@ -246,7 +247,7 @@ export const CreateInformationTab = observer(
}}
>
<ImageUploadCard
title="Логотип"
title="Иконка"
imageKey="thumbnail"
imageUrl={sight.thumbnail}
onImageClick={() => {
@@ -266,11 +267,10 @@ export const CreateInformationTab = observer(
setUploadMediaOpen={() => {
setIsUploadMediaOpen(true);
setActiveMenuType("thumbnail");
setHardcodeType("thumbnail");
}}
setHardcodeType={(type) => {
setHardcodeType(
type as "thumbnail" | "watermark_lu" | "watermark_rd"
);
setHardcodeType={() => {
setHardcodeType("thumbnail");
}}
/>
@@ -295,16 +295,15 @@ export const CreateInformationTab = observer(
setUploadMediaOpen={() => {
setIsUploadMediaOpen(true);
setActiveMenuType("watermark_lu");
setHardcodeType("watermark_lu");
}}
setHardcodeType={(type) => {
setHardcodeType(
type as "thumbnail" | "watermark_lu" | "watermark_rd"
);
setHardcodeType={() => {
setHardcodeType("watermark_lu");
}}
/>
<ImageUploadCard
title="Водяной знак (правый нижний)"
title="Водяной знак (правый верхний)"
imageKey="watermark_rd"
imageUrl={sight.watermark_rd}
onImageClick={() => {
@@ -324,11 +323,10 @@ export const CreateInformationTab = observer(
setUploadMediaOpen={() => {
setIsUploadMediaOpen(true);
setActiveMenuType("watermark_rd");
setHardcodeType("watermark_rd");
}}
setHardcodeType={(type) => {
setHardcodeType(
type as "thumbnail" | "watermark_lu" | "watermark_rd"
);
setHardcodeType={() => {
setHardcodeType("watermark_rd");
}}
/>
</Box>
@@ -412,6 +410,8 @@ export const CreateInformationTab = observer(
<UploadMediaDialog
open={isUploadMediaOpen}
onClose={() => setIsUploadMediaOpen(false)}
contextObjectName={sight[language].name}
contextType="sight"
afterUpload={(media) => {
handleChange({
[activeMenuType ?? "thumbnail"]: media.id,

View File

@@ -44,7 +44,7 @@ export const CreateLeftTab = observer(
} = editSightStore;
const { language } = languageStore;
const token = localStorage.getItem("token");
const [isSelectArticleDialogOpen, setIsSelectArticleDialogOpen] =
useState(false);
const [isSelectMediaDialogOpen, setIsSelectMediaDialogOpen] =
@@ -326,6 +326,7 @@ export const CreateLeftTab = observer(
<Box
sx={{
overflow: "hidden",
position: "relative",
width: "100%",
minHeight: 100,
padding: "3px",
@@ -343,15 +344,45 @@ export const CreateLeftTab = observer(
}}
>
{sight[language].left.media.length > 0 ? (
<MediaViewer
media={{
id: sight[language].left.media[0].id,
media_type:
sight[language].left.media[0].media_type,
filename: sight[language].left.media[0].filename,
}}
fullWidth
/>
<>
<MediaViewer
media={{
id: sight[language].left.media[0].id,
media_type:
sight[language].left.media[0].media_type,
filename: sight[language].left.media[0].filename,
}}
fullWidth
/>
{sight.watermark_lu && (
<img
src={`${import.meta.env.VITE_KRBL_MEDIA}${
sight.watermark_lu
}/download?token=${token}`}
alt="preview"
className="absolute top-4 left-4 z-10"
style={{
width: "30px",
height: "30px",
objectFit: "contain",
}}
/>
)}
{sight.watermark_rd && (
<img
src={`${import.meta.env.VITE_KRBL_MEDIA}${
sight.watermark_rd
}/download?token=${token}`}
alt="preview"
className="absolute bottom-4 right-4 z-10"
style={{
width: "30px",
height: "30px",
objectFit: "contain",
}}
/>
)}
</>
) : (
<ImagePlus size={48} color="white" />
)}
@@ -400,7 +431,13 @@ export const CreateLeftTab = observer(
sx={{
padding: 1,
maxHeight: "300px",
overflowY: "scroll",
overflowY: "auto",
"&::-webkit-scrollbar": {
display: "none",
},
"&": {
scrollbarWidth: "none",
},
background:
"#806c59 linear-gradient(90deg, rgba(255, 255, 255, 0.2) 12.5%, rgba(255, 255, 255, 0.2) 100%)",
flexGrow: 1,
@@ -451,6 +488,10 @@ export const CreateLeftTab = observer(
<UploadMediaDialog
open={uploadMediaOpen}
onClose={() => setUploadMediaOpen(false)}
contextObjectName={sight[language].name}
contextType="sight"
isArticle={true}
articleName={sight[language].left.heading || "Левая статья"}
afterUpload={async (media) => {
setUploadMediaOpen(false);
setFileToUpload(null);
@@ -466,6 +507,7 @@ export const CreateLeftTab = observer(
open={isDeleteModalOpen}
onDelete={() => {
deleteLeftArticle(sight.left_article);
setIsDeleteModalOpen(false);
toast.success("Статья откреплена");
}}
onCancel={() => setIsDeleteModalOpen(false)}

View File

@@ -153,10 +153,12 @@ export const CreateRightTab = observer(
selectedArticleId: number
) => {
try {
await linkExistingRightArticle(selectedArticleId);
const linkedArticleId = await linkExistingRightArticle(
selectedArticleId
);
setSelectArticleDialogOpen(false); // Close dialog
const newIndex = sight[language].right.findIndex(
(a) => a.id === selectedArticleId
(a) => a.id === linkedArticleId
);
if (newIndex > -1) {
setActiveArticleIndex(newIndex);
@@ -483,6 +485,9 @@ export const CreateRightTab = observer(
linkPreviewMedia(mediaId);
}}
onFilesDrop={() => {}}
contextObjectName={sight[language].name}
contextType="sight"
isArticle={false}
/>
)}
</Box>
@@ -495,6 +500,9 @@ export const CreateRightTab = observer(
linkPreviewMedia(mediaId);
}}
onFilesDrop={() => {}}
contextObjectName={sight[language].name}
contextType="sight"
isArticle={false}
/>
)}
</Box>
@@ -597,7 +605,13 @@ export const CreateRightTab = observer(
padding: 1,
minHeight: "200px",
maxHeight: "300px",
overflowY: "scroll",
overflowY: "auto",
"&::-webkit-scrollbar": {
display: "none",
},
"&": {
scrollbarWidth: "none",
},
background:
"rgba(179, 165, 152, 0.4), linear-gradient(180deg, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0.2) 100%)",
@@ -698,6 +712,14 @@ export const CreateRightTab = observer(
setFileToUpload(null); // Clear file if dialog is closed without upload
setMediaTarget(null);
}}
contextObjectName={sight[language].name}
contextType="sight"
isArticle={mediaTarget === "rightArticle"}
articleName={
mediaTarget === "rightArticle" && activeArticleIndex !== null
? sight[language].right[activeArticleIndex].heading
: undefined
}
afterUpload={handleMediaUploaded} // This will use the mediaTarget
/>
<SelectMediaDialog

View File

@@ -32,8 +32,6 @@ import { toast } from "react-toastify";
export const InformationTab = observer(
({ value, index }: { value: number; index: number }) => {
const { ruCities } = cityStore;
const [mediaId, setMediaId] = useState<string>("");
const [isPreviewMediaOpen, setIsPreviewMediaOpen] = useState(false);
const [isUploadMediaOpen, setIsUploadMediaOpen] = useState(false);
@@ -53,6 +51,7 @@ export const InformationTab = observer(
const [hardcodeType, setHardcodeType] = useState<
"thumbnail" | "watermark_lu" | "watermark_rd" | null
>(null);
const { cities } = cityStore;
useEffect(() => {
// Показывать только при инициализации (не менять при ошибках пользователя)
if (sight.common.latitude !== 0 || sight.common.longitude !== 0) {
@@ -89,7 +88,7 @@ export const InformationTab = observer(
},
true
);
setActiveMenuType(null);
setIsUploadMediaOpen(false);
};
@@ -163,9 +162,9 @@ export const InformationTab = observer(
/>
<Autocomplete
options={ruCities?.data ?? []}
options={cities["ru"]?.data ?? []}
value={
ruCities?.data?.find(
cities["ru"]?.data?.find(
(city) => city.id === sight.common.city_id
) ?? null
}
@@ -246,7 +245,7 @@ export const InformationTab = observer(
}}
>
<ImageUploadCard
title="Логотип"
title="Иконка"
imageKey="thumbnail"
imageUrl={sight.common.thumbnail}
onImageClick={() => {
@@ -270,11 +269,10 @@ export const InformationTab = observer(
setUploadMediaOpen={() => {
setIsUploadMediaOpen(true);
setActiveMenuType("thumbnail");
setHardcodeType("thumbnail");
}}
setHardcodeType={(type) => {
setHardcodeType(
type as "thumbnail" | "watermark_lu" | "watermark_rd"
);
setHardcodeType={() => {
setHardcodeType("thumbnail");
}}
/>
<ImageUploadCard
@@ -302,15 +300,14 @@ export const InformationTab = observer(
setUploadMediaOpen={() => {
setIsUploadMediaOpen(true);
setActiveMenuType("watermark_lu");
setHardcodeType("watermark_lu");
}}
setHardcodeType={(type) => {
setHardcodeType(
type as "thumbnail" | "watermark_lu" | "watermark_rd"
);
setHardcodeType={() => {
setHardcodeType("watermark_lu");
}}
/>
<ImageUploadCard
title="Водяной знак (правый нижний)"
title="Водяной знак (правый верхний)"
imageKey="watermark_rd"
imageUrl={sight.common.watermark_rd}
onImageClick={() => {
@@ -334,11 +331,10 @@ export const InformationTab = observer(
setUploadMediaOpen={() => {
setIsUploadMediaOpen(true);
setActiveMenuType("watermark_rd");
setHardcodeType("watermark_rd");
}}
setHardcodeType={(type) => {
setHardcodeType(
type as "thumbnail" | "watermark_lu" | "watermark_rd"
);
setHardcodeType={() => {
setHardcodeType("watermark_rd");
}}
/>
</Box>
@@ -399,7 +395,6 @@ export const InformationTab = observer(
open={isAddMediaOpen}
onClose={() => {
setIsAddMediaOpen(false);
setActiveMenuType(null);
}}
onSelectMedia={handleMediaSelect}
mediaType={
@@ -414,6 +409,8 @@ export const InformationTab = observer(
<UploadMediaDialog
open={isUploadMediaOpen}
onClose={() => setIsUploadMediaOpen(false)}
contextObjectName={sight[language].name}
contextType="sight"
afterUpload={(media) => {
handleChange(
language as Language,

View File

@@ -9,6 +9,7 @@ import {
SelectArticleModal,
UploadMediaDialog,
Language,
articlesStore,
} from "@shared";
import {
LanguageSwitcher,
@@ -43,7 +44,7 @@ export const LeftWidgetTab = observer(
const { language } = languageStore;
const data = sight[language];
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
const token = localStorage.getItem("token");
const [isSelectMediaDialogOpen, setIsSelectMediaDialogOpen] =
useState(false);
const [isSelectArticleDialogOpen, setIsSelectArticleDialogOpen] =
@@ -76,20 +77,40 @@ export const LeftWidgetTab = observer(
}, []);
const handleSelectArticle = useCallback(
(
articleId: number,
heading: string,
body: string,
media: { id: string; media_type: number; filename: string }[]
async (
articleId: number
// heading: string,
// body: string,
// media: { id: string; media_type: number; filename: string }[]
) => {
setIsSelectArticleDialogOpen(false);
updateSightInfo(languageStore.language, {
const ruArticle = await articlesStore.getArticle(articleId, "ru");
const enArticle = await articlesStore.getArticle(articleId, "en");
const zhArticle = await articlesStore.getArticle(articleId, "zh");
updateSightInfo("ru", {
left: {
heading,
body,
media,
heading: ruArticle.data.heading,
body: ruArticle.data.body,
media: ruArticle.data.media || [],
},
});
updateSightInfo("en", {
left: {
heading: enArticle.data.heading,
body: enArticle.data.body,
media: enArticle.data.media || [],
},
});
updateSightInfo("zh", {
left: {
heading: zhArticle.data.heading,
body: zhArticle.data.body,
media: zhArticle.data.media || [],
},
});
updateSightInfo(
languageStore.language,
{
@@ -271,6 +292,7 @@ export const LeftWidgetTab = observer(
width: "100%",
minHeight: 100,
padding: "3px",
position: "relative",
display: "flex",
alignItems: "center",
justifyContent: "center",
@@ -285,14 +307,41 @@ export const LeftWidgetTab = observer(
}}
>
{data.left.media.length > 0 ? (
<MediaViewer
media={{
id: data.left.media[0].id,
media_type: data.left.media[0].media_type,
filename: data.left.media[0].filename,
}}
fullWidth
/>
<>
<MediaViewer
media={{
id: data.left.media[0].id,
media_type: data.left.media[0].media_type,
filename: data.left.media[0].filename,
}}
fullWidth
/>
<img
src={`${import.meta.env.VITE_KRBL_MEDIA}${
sight.common.watermark_lu
}/download?token=${token}`}
alt="preview"
className="absolute top-4 left-4 z-10"
style={{
width: "30px",
height: "30px",
objectFit: "contain",
}}
/>
<img
src={`${import.meta.env.VITE_KRBL_MEDIA}${
sight.common.watermark_rd
}/download?token=${token}`}
alt="preview"
className="absolute bottom-4 right-4 z-10"
style={{
width: "30px",
height: "30px",
objectFit: "contain",
}}
/>
</>
) : (
<ImagePlus size={48} color="white" />
)}
@@ -341,7 +390,14 @@ export const LeftWidgetTab = observer(
sx={{
padding: 1,
maxHeight: "300px",
overflowY: "scroll",
overflowY: "auto",
width: "100%",
"&::-webkit-scrollbar": {
display: "none",
},
"&": {
scrollbarWidth: "none",
},
background:
"#806c59 linear-gradient(90deg, rgba(255, 255, 255, 0.2) 12.5%, rgba(255, 255, 255, 0.2) 100%)",
flexGrow: 1,
@@ -373,6 +429,12 @@ export const LeftWidgetTab = observer(
<UploadMediaDialog
open={uploadMediaOpen}
onClose={() => setUploadMediaOpen(false)}
contextObjectName={sight[languageStore.language].name}
contextType="sight"
isArticle={true}
articleName={
sight[languageStore.language].left.heading || "Левая статья"
}
afterUpload={async (media) => {
setUploadMediaOpen(false);
setFileToUpload(null);

View File

@@ -115,9 +115,21 @@ export const RightWidgetTab = observer(
setActiveArticleIndex(index);
};
const handleCreateNew = () => {
createNewRightArticle();
handleClose();
const handleCreateNew = async () => {
try {
const newArticleId = await createNewRightArticle();
handleClose();
// Automatically select the newly created article
const newIndex = sight[language].right.findIndex(
(article) => article.id === newArticleId
);
if (newIndex > -1) {
setActiveArticleIndex(newIndex);
setType("article");
}
} catch (error) {
console.error("Error creating new article:", error);
}
};
const handleSelectExisting = () => {
@@ -129,9 +141,21 @@ export const RightWidgetTab = observer(
setIsSelectModalOpen(false);
};
const handleArticleSelect = (id: number) => {
linkArticle(id);
handleCloseSelectModal();
const handleArticleSelect = async (id: number) => {
try {
const linkedArticleId = await linkArticle(id);
handleCloseSelectModal();
// Automatically select the newly linked article
const newIndex = sight[language].right.findIndex(
(article) => article.id === linkedArticleId
);
if (newIndex > -1) {
setActiveArticleIndex(newIndex);
setType("article");
}
} catch (error) {
console.error("Error linking article:", error);
}
};
const handleMediaSelected = async (media: {
@@ -417,6 +441,9 @@ export const RightWidgetTab = observer(
linkPreviewMedia(mediaId);
}}
onFilesDrop={() => {}}
contextObjectName={sight[language].name}
contextType="sight"
isArticle={false}
/>
)}
</Box>
@@ -441,6 +468,9 @@ export const RightWidgetTab = observer(
linkPreviewMedia(mediaId);
}}
onFilesDrop={() => {}}
contextObjectName={sight[language].name}
contextType="sight"
isArticle={false}
/>
</Box>
</Box>
@@ -539,7 +569,15 @@ export const RightWidgetTab = observer(
padding: 1,
minHeight: "200px",
maxHeight: "300px",
overflowY: "scroll",
overflowY: "auto",
width: "100%",
"&::-webkit-scrollbar": {
display: "none",
},
"&": {
scrollbarWidth: "none",
},
background:
"rgba(179, 165, 152, 0.4), linear-gradient(180deg, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0.2) 100%)",
@@ -565,13 +603,13 @@ export const RightWidgetTab = observer(
sx={{
p: 2,
display: "flex",
justifyContent: "space-between",
justifyContent: "center",
fontSize: "24px",
fontWeight: 700,
lineHeight: "120%",
flexWrap: "wrap",
gap: 1,
gap: "34px",
backdropFilter: "blur(12px)",
boxShadow:
"inset 4px 4px 12px 0 rgba(255,255,255,0.12)",
@@ -627,6 +665,14 @@ export const RightWidgetTab = observer(
<UploadMediaDialog
open={uploadMediaOpen}
onClose={() => setUploadMediaOpen(false)}
contextObjectName={sight[language].name}
contextType="sight"
isArticle={true}
articleName={
activeArticleIndex !== null
? sight[language].right[activeArticleIndex].heading
: "Правая статья"
}
afterUpload={async (media) => {
setUploadMediaOpen(false);
setFileToUpload(null);