embed css

This commit is contained in:
proddy
2025-10-20 22:19:33 +02:00
parent 0852502f52
commit 9172dd9181
2 changed files with 68 additions and 53 deletions

View File

@@ -1,16 +1,59 @@
// Code inspired by Prince Azubuike from https://medium.com/@dprincecoder/creating-a-drag-and-drop-file-upload-component-in-react-a-step-by-step-guide-4d93b6cc21e0 // Code inspired by Prince Azubuike from https://medium.com/@dprincecoder/creating-a-drag-and-drop-file-upload-component-in-react-a-step-by-step-guide-4d93b6cc21e0
import { type ChangeEvent, useRef, useState } from 'react'; import {
type ChangeEvent,
type DragEvent,
type MouseEvent,
useRef,
useState
} from 'react';
import CancelIcon from '@mui/icons-material/Cancel'; import CancelIcon from '@mui/icons-material/Cancel';
import CloudUploadIcon from '@mui/icons-material/CloudUpload'; import CloudUploadIcon from '@mui/icons-material/CloudUpload';
import UploadIcon from '@mui/icons-material/Upload'; import UploadIcon from '@mui/icons-material/Upload';
import { Box, Button } from '@mui/material'; import { Box, Button, Typography, styled } from '@mui/material';
import { useI18nContext } from 'i18n/i18n-react'; import { useI18nContext } from 'i18n/i18n-react';
import './dragNdrop.css'; const DocumentUploader = styled(Box)<{ active?: boolean }>(({ theme, active }) => ({
border: `2px dashed ${active ? '#6dc24b' : '#4282fe'}`,
backgroundColor: '#2e3339',
padding: theme.spacing(1.25),
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
position: 'relative',
borderRadius: theme.spacing(1),
cursor: 'pointer',
minHeight: '120px',
transition: 'border-color 0.2s ease-in-out'
}));
const DragNdrop = ({ text, onFileSelected }) => { const UploadInfo = styled(Box)({
display: 'flex',
alignItems: 'center'
});
const FileInfo = styled(Box)({
display: 'flex',
flexDirection: 'column',
width: '100%',
justifyContent: 'space-between',
alignItems: 'center'
});
const FileName = styled(Typography)(({ theme }) => ({
fontSize: '14px',
color: '#6dc24b',
margin: theme.spacing(1, 0)
}));
interface DragNdropProps {
text: string;
onFileSelected: (file: File) => void;
}
const DragNdrop = ({ text, onFileSelected }: DragNdropProps) => {
const [file, setFile] = useState<File>(); const [file, setFile] = useState<File>();
const [dragged, setDragged] = useState(false); const [dragged, setDragged] = useState(false);
const inputRef = useRef<HTMLInputElement | null>(null); const inputRef = useRef<HTMLInputElement | null>(null);
@@ -28,14 +71,17 @@ const DragNdrop = ({ text, onFileSelected }) => {
}; };
const handleFileChange = (e: ChangeEvent<HTMLInputElement>) => { const handleFileChange = (e: ChangeEvent<HTMLInputElement>) => {
if (!e.target.files) { if (!e.target.files || e.target.files.length === 0) {
return; return;
} }
checkFileExtension(e.target.files[0]); const selectedFile = e.target.files[0];
if (selectedFile) {
checkFileExtension(selectedFile);
}
e.target.value = ''; // this is to allow the same file to be selected again e.target.value = ''; // this is to allow the same file to be selected again
}; };
const handleDrop = (event) => { const handleDrop = (event: DragEvent<HTMLDivElement>) => {
event.preventDefault(); event.preventDefault();
const droppedFiles = event.dataTransfer.files; const droppedFiles = event.dataTransfer.files;
if (droppedFiles.length > 0) { if (droppedFiles.length > 0) {
@@ -43,38 +89,40 @@ const DragNdrop = ({ text, onFileSelected }) => {
} }
}; };
const handleRemoveFile = (event) => { const handleRemoveFile = (event: MouseEvent<HTMLButtonElement>) => {
event.stopPropagation(); event.stopPropagation();
setFile(undefined); setFile(undefined);
setDragged(false); setDragged(false);
}; };
const handleUploadClick = (event) => { const handleUploadClick = (event: MouseEvent<HTMLButtonElement>) => {
event.stopPropagation(); event.stopPropagation();
onFileSelected(file); if (file) {
onFileSelected(file);
}
}; };
const handleBrowseClick = () => { const handleBrowseClick = () => {
inputRef.current?.click(); inputRef.current?.click();
}; };
const handleDragOver = (event) => { const handleDragOver = (event: DragEvent<HTMLDivElement>) => {
event.preventDefault(); // prevent file from being opened event.preventDefault(); // prevent file from being opened
setDragged(true); setDragged(true);
}; };
return ( return (
<div <DocumentUploader
className={`document-uploader ${file || dragged ? 'active' : ''}`} active={!!(file || dragged)}
onDrop={handleDrop} onDrop={handleDrop}
onDragOver={handleDragOver} onDragOver={handleDragOver}
onDragLeave={() => setDragged(false)} onDragLeave={() => setDragged(false)}
onClick={handleBrowseClick} onClick={handleBrowseClick}
> >
<div className="upload-info"> <UploadInfo>
<CloudUploadIcon sx={{ marginRight: 4 }} color="primary" fontSize="large" /> <CloudUploadIcon sx={{ marginRight: 4 }} color="primary" fontSize="large" />
<p>{text}</p> <Typography>{text}</Typography>
</div> </UploadInfo>
<input <input
type="file" type="file"
@@ -88,9 +136,9 @@ const DragNdrop = ({ text, onFileSelected }) => {
{file && ( {file && (
<> <>
<div className="file-info"> <FileInfo>
<p>{file.name}</p> <FileName>{file.name}</FileName>
</div> </FileInfo>
<Box> <Box>
<Button <Button
startIcon={<CancelIcon />} startIcon={<CancelIcon />}
@@ -112,7 +160,7 @@ const DragNdrop = ({ text, onFileSelected }) => {
</Box> </Box>
</> </>
)} )}
</div> </DocumentUploader>
); );
}; };

View File

@@ -1,33 +0,0 @@
.document-uploader {
border: 2px dashed #4282fe;
background-color: #2e3339;
padding: 10px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
position: relative;
border-radius: 8px;
cursor: pointer;
&.active {
border-color: #6dc24b;
}
.upload-info {
display: flex;
align-items: center;
}
.file-info {
display: flex;
flex-direction: column;
width: 100%;
justify-content: space-between;
align-items: center;
p {
font-size: 14px;
color: #6dc24b;
}
}
}