Online Smart Team Collaboration Dashboard

Team Collaboration Dashboard

Session ID: Loading... (Share this with your team)

Shared To-Do List

Team Chat

Shared Files

${msg.text}

${msg.name}

`; container.appendChild(msgEl); }); container.scrollTop = container.scrollHeight; } function renderFiles(docs) { const container = document.getElementById('fileList'); container.innerHTML = ''; docs.forEach(doc => { const file = doc.data(); const fileEl = document.createElement('div'); fileEl.className = 'flex items-center justify-between p-2 bg-gray-100 rounded-md'; fileEl.innerHTML = `
${file.name}

Uploaded by ${file.uploaderName}

`; fileEl.querySelector('button').addEventListener('click', () => deleteFile(doc.id, file.path)); container.appendChild(fileEl); }); } // --- DATABASE OPERATIONS --- async function updateTaskStatus(taskId, completed) { await updateDoc(dashboardDocRef, { [`tasks.${taskId}.completed`]: completed }); } async function deleteTask(taskId) { await updateDoc(dashboardDocRef, { [`tasks.${taskId}`]: deleteField() }); } document.getElementById('addTaskBtn').addEventListener('click', async () => { const input = document.getElementById('taskInput'); if (input.value.trim() === '') return; const taskId = 'task_' + Date.now(); await updateDoc(dashboardDocRef, { [`tasks.${taskId}`]: { text: input.value, completed: false } }); input.value = ''; }); document.getElementById('sendMessageBtn').addEventListener('click', async () => { const input = document.getElementById('chatInput'); if (input.value.trim() === '') return; await addDoc(chatCollectionRef, { text: input.value, name: userName, uid: userId, timestamp: serverTimestamp() }); input.value = ''; }); async function deleteFile(docId, filePath) { const fileRef = ref(storage, filePath); try { await deleteObject(fileRef); await deleteDoc(doc(filesCollectionRef, docId)); showMessage("File deleted."); } catch (error) { console.error("Error deleting file:", error); showMessage("Could not delete file.", true); } } // --- FILE UPLOAD --- const fileInput = document.getElementById('fileInput'); const uploadBtn = document.getElementById('uploadFileBtn'); const progressContainer = document.getElementById('uploadProgress'); const progressBar = document.getElementById('progressBar'); uploadBtn.addEventListener('click', () => { const file = fileInput.files[0]; if (!file) return; const filePath = `artifacts/${appId}/public/files/${currentSessionId}/${Date.now()}_${file.name}`; const storageRef = ref(storage, filePath); const uploadTask = uploadBytesResumable(storageRef, file); uploadTask.on('state_changed', (snapshot) => { const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100; progressContainer.style.display = 'block'; progressBar.style.width = progress + '%'; }, (error) => { console.error("Upload failed:", error); showMessage("File upload failed.", true); progressContainer.style.display = 'none'; }, () => { getDownloadURL(uploadTask.snapshot.ref).then(async (downloadURL) => { await addDoc(filesCollectionRef, { name: file.name, url: downloadURL, path: filePath, uploaderId: userId, uploaderName: userName, uploadedAt: serverTimestamp() }); showMessage("File uploaded successfully!"); progressContainer.style.display = 'none'; fileInput.value = ''; }); } ); }); // --- UI & PDF --- const tabs = document.querySelectorAll('.tab-content'); const tabLinks = document.querySelectorAll('.tab-link'); window.showTab = (tabIndex) => { tabs.forEach((t, i) => { t.style.display = i === tabIndex ? 'block' : 'none'; }); tabLinks.forEach((l, i) => { l.classList.toggle('active', i === tabIndex); l.classList.toggle('inactive', i !== tabIndex); }); }; document.getElementById('downloadPdfBtn').addEventListener('click', async () => { const { jsPDF } = window.jspdf; const doc = new jsPDF(); const pageHeight = doc.internal.pageSize.height; const margin = 15; let y = margin; // Helper function to add text and manage page breaks const addWrappedText = (text, options) => { const lines = doc.splitTextToSize(text, doc.internal.pageSize.width - margin * 2); for (const line of lines) { if (y + 10 > pageHeight - margin) { doc.addPage(); y = margin; } doc.text(line, margin, y, options); y += 7; // Line height } }; // Title doc.setFontSize(22); doc.setFont("helvetica", "bold"); doc.text("Team Collaboration Dashboard", doc.internal.pageSize.width / 2, y, { align: 'center' }); y += 10; doc.setFontSize(12); doc.setFont("helvetica", "normal"); doc.text(`Session ID: ${currentSessionId}`, doc.internal.pageSize.width / 2, y, { align: 'center' }); y += 15; // --- To-Do List --- doc.setFontSize(16); doc.setFont("helvetica", "bold"); doc.text("Shared To-Do List", margin, y); y += 10; doc.setFontSize(12); doc.setFont("helvetica", "normal"); Object.values(dashboardData.tasks || {}).forEach(task => { const prefix = task.completed ? '[x] ' : '[ ] '; addWrappedText(prefix + task.text); }); y += 10; // --- Team Chat --- doc.setFontSize(16); doc.setFont("helvetica", "bold"); doc.text("Team Chat", margin, y); y += 10; doc.setFontSize(12); doc.setFont("helvetica", "normal"); const chatSnapshot = await getDocs(query(chatCollectionRef, orderBy("timestamp"))); chatSnapshot.docs.forEach(docSnap => { const msg = docSnap.data(); addWrappedText(`${msg.name}: ${msg.text}`); }); y += 10; // --- Shared Files --- doc.setFontSize(16); doc.setFont("helvetica", "bold"); doc.text("Shared Files", margin, y); y += 10; doc.setFontSize(12); doc.setFont("helvetica", "normal"); const filesSnapshot = await getDocs(query(filesCollectionRef, orderBy("uploadedAt"))); filesSnapshot.docs.forEach(docSnap => { const file = docSnap.data(); addWrappedText(`- ${file.name} (Uploaded by: ${file.uploaderName})`); }); doc.save(`dashboard-${currentSessionId}.pdf`); }); function showMessage(message, isError = false) { const box = document.getElementById('messageBox'); box.textContent = message; box.className = `fixed top-5 right-5 text-white py-2 px-4 rounded-lg shadow-lg ${isError ? 'bg-red-500' : 'bg-green-500'}`; setTimeout(() => { box.className += ' hidden'; }, 3000); }
Scroll to Top