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

@ -0,0 +1,229 @@
import {
articlesStore,
authStore,
Language,
mediaStore,
MEDIA_TYPE_LABELS,
API_URL,
} from "@shared";
import { observer } from "mobx-react-lite";
import { useEffect, useRef, useState, useCallback } from "react";
import {
Dialog,
DialogTitle,
DialogContent,
DialogActions,
Button,
TextField,
Paper,
Box,
Typography,
CircularProgress,
Alert,
Snackbar,
} from "@mui/material";
import { Download, Save } from "lucide-react";
import { ReactMarkdownComponent, MediaViewer } from "@widgets";
import { authInstance } from "@shared";
interface PreviewMediaDialogProps {
open: boolean;
onClose: () => void;
mediaId: string;
}
export const PreviewMediaDialog = observer(
({ open, onClose, mediaId }: PreviewMediaDialogProps) => {
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const [success, setSuccess] = useState(false);
const media = mediaId
? mediaStore.media.find((m) => m.id === mediaId)
: null;
const [mediaName, setMediaName] = useState(media?.media_name ?? "");
const [mediaFilename, setMediaFilename] = useState(media?.filename ?? "");
// Reset form when media changes
useEffect(() => {
if (media) {
setMediaName(media.media_name);
setMediaFilename(media.filename);
}
}, [media]);
useEffect(() => {
const handleKeyPress = (event: KeyboardEvent) => {
if (event.key.toLowerCase() === "enter" && !event.ctrlKey) {
event.preventDefault();
onClose();
}
};
window.addEventListener("keydown", handleKeyPress);
return () => window.removeEventListener("keydown", handleKeyPress);
}, [onClose]);
const handleSave = async () => {
if (!mediaId) return;
setIsLoading(true);
setError(null);
try {
await authInstance.patch(`/media/${mediaId}`, {
media_name: mediaName,
filename: mediaFilename,
type: media?.media_type,
});
// Update local store
await mediaStore.getMedia();
setSuccess(true);
} catch (err) {
setError(err instanceof Error ? err.message : "Failed to save media");
} finally {
setIsLoading(false);
}
};
const handleClose = () => {
setError(null);
setSuccess(false);
onClose();
};
if (!media) {
return null;
}
return (
<>
<Dialog open={open} onClose={handleClose} maxWidth="md" fullWidth>
<DialogTitle>Просмотр медиа</DialogTitle>
<DialogContent
className="flex gap-4"
dividers
sx={{
height: "600px",
display: "flex",
flexDirection: "column",
gap: 2,
pt: 2,
}}
>
<Box className="flex flex-col gap-4">
<Box className="flex gap-2">
<TextField
fullWidth
value={mediaName}
onChange={(e) => setMediaName(e.target.value)}
label="Название медиа"
disabled={isLoading}
/>
<TextField
fullWidth
value={mediaFilename}
onChange={(e) => setMediaFilename(e.target.value)}
label="Название файла"
disabled={isLoading}
/>
</Box>
<TextField
fullWidth
label="Тип медиа"
value={
MEDIA_TYPE_LABELS[
media.media_type as keyof typeof MEDIA_TYPE_LABELS
]
}
disabled
sx={{ width: "50%" }}
/>
<Box className="flex gap-4 h-full">
<Paper
elevation={2}
sx={{
flex: 1,
p: 2,
display: "flex",
alignItems: "center",
justifyContent: "center",
minHeight: 400,
}}
>
<MediaViewer
media={{
id: mediaId,
media_type: media.media_type,
filename: media.filename,
}}
/>
</Paper>
<Box className="flex flex-col gap-2 self-end">
<Button
variant="contained"
color="primary"
startIcon={<Download size={16} />}
component="a"
href={`${
import.meta.env.VITE_KRBL_MEDIA
}${mediaId}/download?token=${localStorage.getItem(
"token"
)}`}
target="_blank"
disabled={isLoading}
>
Скачать
</Button>
<Button
variant="contained"
color="success"
startIcon={
isLoading ? (
<CircularProgress size={16} />
) : (
<Save size={16} />
)
}
onClick={handleSave}
disabled={isLoading || (!mediaName && !mediaFilename)}
>
Сохранить
</Button>
</Box>
</Box>
</Box>
</DialogContent>
<DialogActions>
<Button onClick={handleClose} disabled={isLoading}>
Отмена
</Button>
</DialogActions>
</Dialog>
<Snackbar
open={!!error}
autoHideDuration={6000}
onClose={() => setError(null)}
>
<Alert severity="error" onClose={() => setError(null)}>
{error}
</Alert>
</Snackbar>
<Snackbar
open={success}
autoHideDuration={3000}
onClose={() => setSuccess(false)}
>
<Alert severity="success" onClose={() => setSuccess(false)}>
Медиа успешно сохранено
</Alert>
</Snackbar>
</>
);
}
);