Files
mwitnessing/components/FileUploadWithPreview .tsx
2024-02-23 21:28:56 +02:00

117 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 React, { useState, useEffect, useCallback } from 'react';
import axiosInstance from '../src/axiosSecure'; // Adjust the import path as needed
import { CircularProgress } from '@mui/material'; // Import MUI CircularProgress for loading indicator
const FileUploadWithPreview = ({ name, value, prefix, onUpload, label }) => {
// Function to transform the original image URL to its corresponding thumbnail URL
function transformToThumbnailUrl(originalUrl) {
if (!originalUrl) return null;
if (originalUrl.includes("thumb")) return originalUrl; // If the URL already contains 'thumb', return it as-is
const parts = originalUrl.split('/');
parts.splice(parts.length - 1, 0, 'thumb'); // Insert 'thumb' before the filename
return parts.join('/');
}
// State for the thumbnail URL
const [thumbnail, setThumbnail] = useState(value ? transformToThumbnailUrl(value) : null);
const [isDragging, setIsDragging] = useState(false);
const [isUploading, setIsUploading] = useState(false); // New state for tracking upload status
useEffect(() => {
setThumbnail(value ? transformToThumbnailUrl(value) : null);
}, [value]);
const handleDragEnter = useCallback((e) => {
e.preventDefault();
e.stopPropagation();
setIsDragging(true);
}, []);
const handleDragLeave = useCallback((e) => {
e.preventDefault();
e.stopPropagation();
setIsDragging(false);
}, []);
const handleDragOver = useCallback((e) => {
e.preventDefault();
e.stopPropagation();
}, []);
const handleDrop = useCallback((e) => {
e.preventDefault();
e.stopPropagation();
setIsDragging(false);
const { files: droppedFiles } = e.dataTransfer;
processFile(droppedFiles[0]); // Process only the first dropped file
}, []);
const processFile = async (file) => {
if (!file) return;
setIsUploading(true); // Start uploading
const formData = new FormData();
formData.append('image', file);
formData.append('prefix', prefix);
setThumbnail("/");
try {
const response = await axiosInstance.post('upload', formData);
const uploadedFile = response.data[0];
// Update state with the new thumbnail URL
setThumbnail(uploadedFile.thumbUrl);
// Invoke callback if provided
if (onUpload) {
onUpload(name, uploadedFile.originalUrl);
}
} catch (error) {
console.error('Error uploading image:', error);
} finally {
setIsUploading(false); // End uploading
}
};
const handleFilesChange = (e) => {
processFile(e.target.files[0]); // Process only the first selected file
};
return (
<div className="p-2 border-dashed border-2 border-gray-200 dark:border-gray-600 rounded-lg">
<label htmlFor={`${name}-file-upload`} className="block text-sm font-medium text-gray-700 mb-1">
{label || 'Upload Image'}
</label>
<input id={`${name}-file-upload`} type="file" accept="image/*" onChange={handleFilesChange} className="hidden" />
<div className={`flex flex-col items-center justify-center p-4 ${isDragging ? 'bg-gray-100 dark:bg-gray-700' : 'bg-white dark:bg-gray-800'}`}
onDragEnter={handleDragEnter}
onDragLeave={handleDragLeave}
onDragOver={handleDragOver}
onDrop={handleDrop}>
{isUploading ? (
<CircularProgress /> // Show loading indicator while uploading
) : (
<>
<p className="text-gray-600 dark:text-gray-300 text-xs mb-2">Поставете сникма тук, или изберете файл с бутона</p>
<button className="btn bg-blue-500 hover:bg-blue-700 text-white font-bold text-xs py-1 px-2 rounded"
onClick={(e) => { e.preventDefault(); document.getElementById(`${name}-file-upload`).click(); }}>
Избери сникма
</button>
</>
)}
{
thumbnail && (
<div className="mt-2 flex justify-center">
<div className="max-w-xs max-h-64 overflow-hidden rounded-md">
<img src={thumbnail} alt="Thumbnail" className="object-contain w-full h-full" />
</div>
</div>
)
}
</div>
</div>
);
};
export default FileUploadWithPreview;