import React, { useState, useRef } from 'react'; const UploadFolderModal = ({ disableBackgroundClose = true }) => { const [active, setActive] = useState(false); const [folderName, setFolderName] = useState(''); const [fileList, setFileList] = useState([]); const [uploadProgress, setUploadProgress] = useState({}); const dropArea = useRef(null); const fileInput = useRef(null); const handleDrop = (e) => { e.preventDefault(); e.stopPropagation(); dropArea.current.classList.remove('dragging'); const items = e.dataTransfer.items; if (items.length > 0) { const folder = items[0].webkitGetAsEntry(); if (folder?.isDirectory) { handleFolder(folder); } else { alert('Please drop a folder!'); } } }; const handleFolder = async (folder, parentPath = '') => { setFolderName(folder.name || 'Root'); const reader = folder.createReader(); const entries = await readEntries(reader); for (const entry of entries) { if (entry.isFile) { const file = await new Promise((resolve) => entry.file(resolve)); setFileList((prevFileList) => [ ...prevFileList, { name: file.name, size: file.size, type: file.type, folderPath: parentPath }, ]); } else if (entry.isDirectory) { await handleFolder(entry, `${parentPath}/${entry.name}`); } } if (fileList.length > 0) startUpload(); }; const readEntries = (reader) => new Promise((resolve, reject) => { reader.readEntries(resolve, reject); }); const uploadFileToS3 = (file, index) => { const formData = new FormData(); formData.append('file', file); return new Promise((resolve, reject) => { const xhr = new XMLHttpRequest(); xhr.open('POST', '/api/v1/upload', true); xhr.upload.onprogress = (e) => { if (e.lengthComputable) { const percent = (e.loaded / e.total) * 100; setUploadProgress((prevProgress) => ({ ...prevProgress, [index]: Math.round(percent), })); } }; xhr.onload = () => xhr.status === 200 ? resolve(JSON.parse(xhr.responseText).fileUrl) : reject('Error uploading file'); xhr.onerror = () => reject('Error uploading file'); xhr.send(formData); }); }; const handleFileSelect = (e) => { const files = Array.from(e.target.files).map((file) => ({ name: file.name, size: file.size, type: file.type, folderPath: 'Root', })); setFileList(files); }; const startUpload = async () => { for (let i = 0; i < fileList.length; i++) { await uploadFileToS3(fileList[i], i); } }; const closeModal = () => { setActive(false); setTimeout(() => {}, 200); }; const handleDragOver = (e) => { e.preventDefault(); e.stopPropagation(); dropArea.current.classList.add('dragging'); }; const handleDragLeave = (e) => { e.preventDefault(); e.stopPropagation(); dropArea.current.classList.remove('dragging'); }; return ( <div className={`wrap-upload-modal${active ? ' active' : ''}`}> <div className="wrap-modal d-flex align-items-center justify-content-center"> <div className="wrap-content"> <div className="body-modal"> <div ref={dropArea} className="wrap-area-drop" onDrop={handleDrop} onDragOver={handleDragOver} onDragLeave={handleDragLeave} > <p className="text-center main">Kéo và thả thư mục vào đây để lấy thông tin và các tệp bên trong</p> <p className="text-center sub">Chỉ thả thư mục vào đây</p> </div> <div className="text-center"> <button onClick={() => fileInput.current.click()} className="btn btn-primary">Tải tệp lên</button> <input ref={fileInput} type="file" multiple onChange={handleFileSelect} style={{ display: 'none' }} /> </div> <div className="text-center"> <button onClick={startUpload} className="btn btn-success mt-3">Bắt đầu tải lên</button> </div> </div> <div className="footer-modal"> <div><strong>Folder Name:</strong> {folderName}</div> <div><strong>List of Files:</strong> {fileList.length > 0 ? ( fileList.map((file, index) => ( <div key={index}> {file.name} - {file.size} bytes - {file.type} - <strong> Folder: {file.folderPath}</strong> <div> <progress value={uploadProgress[index] || 0} max={100}></progress> <span>{uploadProgress[index] ? `${uploadProgress[index]}%` : 'Đang chờ'}</span> </div> </div> )) ) : ( <p>No files to display</p> )} </div> </div> </div> </div> </div> ); }; export default UploadFolderModal;