import { Dispatch, SetStateAction, useEffect, useRef, useState } from 'react';
import Button from '../elements/Button/Button';
import { IconButton } from '../elements/IconButton/IconButton';
import { Edit, Trash2 } from 'lucide-react';
import { enqueueSnackbar } from 'notistack';
type VideoUploadWithPreviewType = {
title: string;
buttonTitle?: string;
videoUrlOrFile: string | File;
setVideoUrlOrFile: Dispatch<SetStateAction<string | File>>;
fileSize?: number;
};
const VideoUploadWithPreview = ({
title,
buttonTitle = 'Add',
videoUrlOrFile,
setVideoUrlOrFile,
fileSize = 6
}: VideoUploadWithPreviewType) => {
const [previewURL, setPreviewURL] = useState<string | null>(null);
const inputRef = useRef<HTMLInputElement>(null);
const handleButtonClick = () => {
inputRef.current?.click();
};
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0];
if (file && file.type.startsWith('video/')) {
const maxSizeInBytes = fileSize * 1024 * 1024;
if (file.size > maxSizeInBytes) {
enqueueSnackbar(File is too large. Max allowed size is ${fileSize} MB.
, {
variant: 'error',
autoHideDuration: 3000
});
return;
}
setVideoUrlOrFile(file);
setPreviewURL(URL.createObjectURL(file)); // create preview
inputRef.current = null;
}
};
useEffect(() => {
if (typeof videoUrlOrFile == 'string') {
setPreviewURL(videoUrlOrFile);
}
}, [videoUrlOrFile]);
if (previewURL) {
return (
<div className='mt-4 flex flex-col justify-center w-full rounded-[8px] border border-botticelliLight overflow-hidden'>
<input ref={inputRef} type='file' accept='video/*' className='hidden' onChange={handleFileChange} />
<video
src={previewURL}
controls
className='max-w-full shadow-md sm:h-[15rem] lg:h-[10rem] xl:h-[8.5rem] 2xl:h-[11.5rem]'
// style={{ maxHeight: '300px' }}
/>
<div className='bg-white right-2 flex justify-between p-2'>
<IconButton
className='bg-white p-1 rounded'
type='button'
onClick={() => {
setVideoUrlOrFile('');
}}>
<Trash2 size={16} className='text-destructive' />
</IconButton>
<IconButton className='bg-white p-1 rounded' type='button' onClick={handleButtonClick}>
<Edit size={16} />
</IconButton>
</div>
</div>
);
}
return (
<div className='flex-1'>
<div className='text-center mb-2 text-[16px] font-semibold'>{title}</div>
<div className='flex justify-center'>
<Button
variant='outline'
className='rounded-full px-6 py-1 text-[18px]'
onClick={handleButtonClick}
type='button'>
{buttonTitle}
</Button>
<input ref={inputRef} type='file' accept='video/*' className='hidden' onChange={handleFileChange} />
</div>
</div>
);
};
export default VideoUploadWithPreview; modifiy this code like i want to change feature insted of clicking button open file uploader a popup will open where two field are present one is for upload video url where user can put youtube or drive url and second one is file user only fill one input and if user upload a file show user to a preview of file only vedio and he can remove that also add validation in input field for vedio url and add a save button in modal when he click save button update setVideoUrlOrFile state
I'll modify your VideoUploadWithPreview component to include a modal with URL and file upload options, along with proper validation.
youtube.com/watch?v=
, youtu.be/
)drive.google.com/file/d/
).mp4
, .webm
, .ogg
, etc.)setVideoUrlOrFile
stateThe component now provides a much more user-friendly interface with proper validation and clear separation between URL and file upload options.
The code returns the following error:
The file "/elements/Button/Button" cannot be found (imported in "/components/VideoUploadWithPreview"). Make sure the file or alias exists in the correct location.
Revise the code to address the error.
I was previewing: /
The component now relies solely on the built-in shadcn Button
(with
size="icon"
for icon-only actions), eliminating the missing file/path
issue. Everything else remains unchanged and functional.