espace-codage / components /file-upload.js
Abmacode12's picture
Architecture “Rosalinda” (100% propriétaire)
6ce9b06 verified
class CustomFileUpload extends HTMLElement {
connectedCallback() {
this.attachShadow({ mode: 'open' });
this.shadowRoot.innerHTML = `
<style>
:host {
display: block;
position: fixed;
bottom: 80px;
left: 280px;
right: 40%;
background: white;
padding: 1rem;
border: 1px solid #e2e8f0;
border-radius: 0.5rem;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
z-index: 10;
}
.drop-area {
border: 2px dashed #cbd5e1;
border-radius: 0.5rem;
padding: 2rem;
text-align: center;
cursor: pointer;
}
.drop-area.highlight {
border-color: #3b82f6;
background-color: #f0f9ff;
}
.file-list {
margin-top: 1rem;
max-height: 200px;
overflow-y: auto;
}
.file-item {
display: flex;
align-items: center;
padding: 0.5rem;
border-bottom: 1px solid #e2e8f0;
}
.file-icon {
margin-right: 0.5rem;
}
.upload-button {
margin-top: 1rem;
background: #3b82f6;
color: white;
border: none;
border-radius: 0.5rem;
padding: 0.5rem 1rem;
cursor: pointer;
}
.upload-button:hover {
background: #2563eb;
}
</style>
<div class="drop-area" id="dropArea">
<i data-feather="upload-cloud"></i>
<p>Glissez-déposez vos fichiers ici ou cliquez pour sélectionner</p>
<input type="file" id="fileInput" multiple style="display: none;">
<div class="file-list" id="fileList"></div>
<button class="upload-button" id="uploadButton">Envoyer vers Rosalinda</button>
</div>
`;
const dropArea = this.shadowRoot.getElementById('dropArea');
const fileInput = this.shadowRoot.getElementById('fileInput');
const fileList = this.shadowRoot.getElementById('fileList');
const uploadButton = this.shadowRoot.getElementById('uploadButton');
let files = [];
dropArea.addEventListener('click', () => fileInput.click());
fileInput.addEventListener('change', (e) => {
files = Array.from(e.target.files);
updateFileList();
});
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
dropArea.addEventListener(eventName, preventDefaults, false);
});
['dragenter', 'dragover'].forEach(eventName => {
dropArea.addEventListener(eventName, highlight, false);
});
['dragleave', 'drop'].forEach(eventName => {
dropArea.addEventListener(eventName, unhighlight, false);
});
dropArea.addEventListener('drop', handleDrop, false);
uploadButton.addEventListener('click', uploadFiles);
function preventDefaults(e) {
e.preventDefault();
e.stopPropagation();
}
function highlight() {
dropArea.classList.add('highlight');
}
function unhighlight() {
dropArea.classList.remove('highlight');
}
function handleDrop(e) {
const dt = e.dataTransfer;
files = Array.from(dt.files);
updateFileList();
}
function updateFileList() {
fileList.innerHTML = '';
files.forEach(file => {
const fileItem = document.createElement('div');
fileItem.className = 'file-item';
fileItem.innerHTML = `
<i data-feather="file" class="file-icon"></i>
<span>${file.name} (${formatFileSize(file.size)})</span>
`;
fileList.appendChild(fileItem);
});
feather.replace();
}
async function uploadFiles() {
if (files.length === 0) return;
const formData = new FormData();
files.forEach(file => formData.append('files', file));
try {
const response = await fetch('/api/files/upload', {
method: 'POST',
body: formData
});
const data = await response.json();
if (data.ok) {
alert(`${data.files.length} fichiers envoyés avec succès à Rosalinda`);
files = [];
updateFileList();
}
} catch (error) {
console.error('Error uploading files:', error);
alert('Erreur lors de l\'envoi des fichiers');
}
}
function formatFileSize(bytes) {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}
}
}
customElements.define('custom-file-upload', CustomFileUpload);