117 lines
4.7 KiB
TypeScript
117 lines
4.7 KiB
TypeScript
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;
|