class DocUploader extends HTMLElement { connectedCallback() { this.attachShadow({ mode: 'open' }); this.render(); this.bindEvents(); window.addEventListener('stateChanged', () => this.checkTranslateButton()); } render() { this.shadowRoot.innerHTML = `

Document Translation

Click to upload or drag and drop

PDF, DOCX, TXT, MD, RTF (Max 10MB)

document.pdf

2.4 MB

`; } bindEvents() { const dropZone = this.shadowRoot.getElementById('drop-zone'); const fileInput = this.shadowRoot.getElementById('file-input'); const btnRemove = this.shadowRoot.getElementById('btn-remove-file'); const btnDownload = this.shadowRoot.getElementById('btn-download'); // Click to upload dropZone.addEventListener('click', () => fileInput.click()); // File selection fileInput.addEventListener('change', (e) => { if (e.target.files.length > 0) { this.handleFile(e.target.files[0]); } }); // Drag and drop dropZone.addEventListener('dragover', (e) => { e.preventDefault(); dropZone.classList.add('drag-active'); }); dropZone.addEventListener('dragleave', () => { dropZone.classList.remove('drag-active'); }); dropZone.addEventListener('drop', (e) => { e.preventDefault(); dropZone.classList.remove('drag-active'); if (e.dataTransfer.files.length > 0) { this.handleFile(e.dataTransfer.files[0]); } }); // Remove file btnRemove.addEventListener('click', () => { window.appState.file = null; window.appState.fileStatus = 'idle'; this.resetUI(); }); // Mock Download btnDownload.addEventListener('click', () => { window.showToast('Download started!', 'success'); }); } async handleFile(file) { // Validate const validTypes = ['.pdf', '.docx', '.txt', '.md', '.rtf']; const ext = '.' + file.name.split('.').pop().toLowerCase(); if (!validTypes.includes(ext)) { window.showToast('Invalid file type. Please upload PDF, DOCX, TXT, MD, or RTF.', 'error'); return; } window.appState.file = file; window.appState.fileStatus = 'uploading'; // Update UI to show file this.shadowRoot.getElementById('file-name').textContent = file.name; this.shadowRoot.getElementById('file-size').textContent = (file.size / 1024 / 1024).toFixed(2) + ' MB'; this.shadowRoot.getElementById('file-info').classList.add('active'); this.shadowRoot.getElementById('progress-container').style.display = 'block'; // Trigger global state update (to enable translate button) window.dispatchEvent(new CustomEvent('stateChanged', { detail: window.appState })); // Simulate Upload & Process await this.simulateProgress(); } async simulateProgress() { const progressBar = this.shadowRoot.getElementById('progress-bar'); // Upload Phase for(let i=0; i<=50; i+=5) { progressBar.style.width = i + '%'; await new Promise(r => setTimeout(r, 100)); } // Process Phase (Mock API) try { await window.mockApi.uploadFile(window.appState.file); // Process Phase Simulation for(let i=50; i<=100; i+=5) { progressBar.style.width = i + '%'; await new Promise(r => setTimeout(r, 100)); } window.appState.fileStatus = 'done'; window.showToast('Document processed successfully', 'success'); // Show Download this.shadowRoot.getElementById('drop-zone').style.display = 'none'; this.shadowRoot.getElementById('progress-container').style.display = 'none'; this.shadowRoot.getElementById('download-area').classList.add('active'); } catch (e) { window.showToast('Upload failed', 'error'); this.resetUI(); } } resetUI() { this.shadowRoot.getElementById('file-info').classList.remove('active'); this.shadowRoot.getElementById('progress-container').style.display = 'none'; this.shadowRoot.getElementById('progress-bar').style.width = '0%'; this.shadowRoot.getElementById('drop-zone').style.display = 'block'; this.shadowRoot.getElementById('download-area').classList.remove('active'); this.shadowRoot.getElementById('file-input').value = ''; window.dispatchEvent(new CustomEvent('stateChanged', { detail: window.appState })); } checkTranslateButton() { // Workspace component handles the button disable logic based on file existence // This is just a placeholder if we needed specific logic here } } customElements.define('doc-uploader', DocUploader);