Files
WhiteNightsAdminPanel/src/widgets/MediaAreaForSight/index.tsx
2025-11-20 20:17:52 +03:00

160 lines
4.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { Box, Button } from "@mui/material";
import {
editSightStore,
SelectMediaDialog,
UploadMediaDialog,
filterValidFiles,
getAllAcceptString,
} from "@shared";
import { Upload } from "lucide-react";
import { observer } from "mobx-react-lite";
import { useState, DragEvent, useRef } from "react";
import { toast } from "react-toastify";
type ContextType =
| "sight"
| "city"
| "carrier"
| "country"
| "vehicle"
| "station";
interface MediaAreaForSightProps {
onFilesDrop?: (files: File[]) => void;
onFinishUpload?: (mediaId: string) => void;
contextObjectName?: string;
contextType?: ContextType;
isArticle?: boolean;
articleName?: string;
}
export const MediaAreaForSight = observer(
({
onFilesDrop,
onFinishUpload,
contextObjectName,
contextType,
isArticle,
articleName,
}: MediaAreaForSightProps) => {
const [selectMediaDialogOpen, setSelectMediaDialogOpen] =
useState<boolean>(false);
const [uploadMediaDialogOpen, setUploadMediaDialogOpen] =
useState<boolean>(false);
const [isDragging, setIsDragging] = useState<boolean>(false);
const fileInputRef = useRef<HTMLInputElement>(null);
const { setFileToUpload } = editSightStore;
const processFiles = (files: File[]) => {
if (!files.length) {
return;
}
const { validFiles, errors } = filterValidFiles(files);
if (errors.length > 0) {
errors.forEach((error: string) => toast.error(error));
}
if (validFiles.length > 0) {
// Сохраняем первый файл для загрузки
setFileToUpload(validFiles[0]);
// Вызываем колбэк, если он передан
if (onFilesDrop) {
onFilesDrop(validFiles);
}
// Открываем диалог загрузки
setUploadMediaDialogOpen(true);
}
};
const handleDrop = (e: DragEvent<HTMLDivElement>) => {
e.preventDefault();
e.stopPropagation();
setIsDragging(false);
const files = Array.from(e.dataTransfer.files);
processFiles(files);
};
const handleDragOver = (e: DragEvent<HTMLDivElement>) => {
e.preventDefault();
setIsDragging(true);
};
const handleDragLeave = () => {
setIsDragging(false);
};
const handleClick = () => {
fileInputRef.current?.click();
};
const handleFileSelect = (event: React.ChangeEvent<HTMLInputElement>) => {
const files = Array.from(event.target.files || []);
processFiles(files);
// Сбрасываем значение input, чтобы можно было выбрать тот же файл снова
if (event.target) {
event.target.value = "";
}
};
return (
<>
<input
type="file"
ref={fileInputRef}
onChange={handleFileSelect}
accept={getAllAcceptString()}
multiple
style={{ display: "none" }}
/>
<Box className="w-full flex flex-col items-center justify-center border rounded-md p-4">
<div className="w-full flex flex-col items-center justify-center">
<div
className={`w-full h-40 flex flex-col justify-center items-center text-gray-400 border-dashed border-2 rounded-md border-gray-400 p-4 cursor-pointer hover:bg-gray-50 transition-colors ${
isDragging ? "bg-blue-100 border-blue-400" : ""
}`}
onDrop={handleDrop}
onDragOver={handleDragOver}
onDragLeave={handleDragLeave}
onClick={handleClick}
>
<Upload size={32} className="mb-2" />
<span className="text-center">
Перетащите медиа файлы сюда или нажмите для выбора
</span>
</div>
<div className="my-2">или</div>
<Button
variant="contained"
color="primary"
onClick={() => setSelectMediaDialogOpen(true)}
>
Выбрать существующие медиа файлы
</Button>
</div>
</Box>
<UploadMediaDialog
open={uploadMediaDialogOpen}
onClose={() => setUploadMediaDialogOpen(false)}
contextObjectName={contextObjectName}
contextType={contextType}
isArticle={isArticle}
articleName={articleName}
afterUploadSight={onFinishUpload}
/>
<SelectMediaDialog
open={selectMediaDialogOpen}
onClose={() => setSelectMediaDialogOpen(false)}
onSelectForSightMedia={onFinishUpload}
/>
</>
);
}
);