Online Workflow-Based Document Approval System

Online Workflow-Based Document Approval System

Step 1: Document and Approvers

Approval Workflow (in order)

Document:

Current Status:

Approval Steps

Approval History

Workflow Complete

Document:

Approval Summary

Generated on:

Approver Status Date

${statusText}

${actionButtons} `; workflowStepsEl.appendChild(stepDiv); // Add to history if action was taken if (approver.status !== 'pending') { const historyP = document.createElement('p'); const formattedDate = approver.date.toLocaleString('en-US', { year: 'numeric', month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' }); historyP.innerHTML = `${approver.name} ${approver.status} on ${formattedDate}.`; approvalHistoryEl.appendChild(historyP); } }); // Add event listeners to new action buttons document.querySelectorAll('.approve-btn').forEach(btn => btn.addEventListener('click', handleApproval)); document.querySelectorAll('.reject-btn').forEach(btn => btn.addEventListener('click', handleRejection)); } // Handle approval action function handleApproval(e) { const index = parseInt(e.target.dataset.index); const approver = workflow.approvers[index]; approver.status = 'approved'; approver.date = new Date(); if (index + 1 < workflow.approvers.length) { workflow.currentApproverIndex++; } else { workflow.isComplete = true; workflow.finalStatus = 'Fully Approved'; moveToFinalTab(); } renderDashboard(); } // Handle rejection action function handleRejection(e) { const index = parseInt(e.target.dataset.index); const approver = workflow.approvers[index]; approver.status = 'rejected'; approver.date = new Date(); workflow.isComplete = true; workflow.finalStatus = 'Rejected'; moveToFinalTab(); renderDashboard(); } // Update the overall workflow status display function updateWorkflowStatus() { const statusEl = document.getElementById('workflowStatus'); statusEl.textContent = workflow.finalStatus; if (workflow.finalStatus === 'In Progress') { statusEl.className = 'font-semibold px-2 py-1 rounded-full text-sm bg-yellow-100 text-yellow-800'; } else if (workflow.finalStatus === 'Fully Approved') { statusEl.className = 'font-semibold px-2 py-1 rounded-full text-sm bg-green-100 text-green-800'; } else { statusEl.className = 'font-semibold px-2 py-1 rounded-full text-sm bg-red-100 text-red-800'; } } // Move to the final tab and render its content function moveToFinalTab() { renderFinalSummary(); switchTab(3); } // Render the content of the final summary tab function renderFinalSummary() { document.getElementById('finalDocName').textContent = workflow.documentName; const finalStatusEl = document.getElementById('finalStatus'); finalStatusEl.textContent = workflow.finalStatus; if (workflow.finalStatus === 'Fully Approved') { finalStatusEl.className = 'text-3xl font-bold p-4 rounded-lg inline-block bg-green-100 text-green-800'; } else { finalStatusEl.className = 'text-3xl font-bold p-4 rounded-lg inline-block bg-red-100 text-red-800'; } // Populate PDF content document.getElementById('generationDate').textContent = new Date().toLocaleString('en-US'); const pdfTableBody = document.getElementById('pdfTableBody'); pdfTableBody.innerHTML = ''; workflow.approvers.forEach(approver => { const tr = document.createElement('tr'); tr.className = 'border-b'; const statusText = approver.status.charAt(0).toUpperCase() + approver.status.slice(1); const dateText = approver.date ? approver.date.toLocaleString('en-US') : 'N/A'; tr.innerHTML = ` ${approver.name} ${statusText} ${dateText} `; pdfTableBody.appendChild(tr); }); } // Generate and download the PDF async function generatePdf() { const { jsPDF } = window.jspdf; const pdfContent = document.getElementById('pdfContent'); // Temporarily make the content visible for capture if it's not const wasHidden = pdfContent.offsetParent === null; if(wasHidden) pdfContent.style.display = 'block'; try { const canvas = await html2canvas(pdfContent, { scale: 2, // Higher scale for better quality useCORS: true }); const imgData = canvas.toDataURL('image/png'); const pdf = new jsPDF({ orientation: 'portrait', unit: 'pt', format: 'a4' }); const pdfWidth = pdf.internal.pageSize.getWidth(); const pdfHeight = pdf.internal.pageSize.getHeight(); const imgWidth = canvas.width; const imgHeight = canvas.height; const ratio = imgWidth / imgHeight; let finalImgWidth = pdfWidth - 40; // with margin let finalImgHeight = finalImgWidth / ratio; if (finalImgHeight > pdfHeight - 40) { finalImgHeight = pdfHeight - 40; finalImgWidth = finalImgHeight * ratio; } const x = (pdfWidth - finalImgWidth) / 2; const y = 20; pdf.addImage(imgData, 'PNG', x, y, finalImgWidth, finalImgHeight); pdf.save(`approval-summary-${workflow.documentName.replace(/\s+/g, '-')}.pdf`); } catch (error) { console.error("Error generating PDF:", error); alert("Could not generate PDF. Please try again."); } finally { if(wasHidden) pdfContent.style.display = ''; // Hide it back if it was hidden } } // Initialize the view updateNavButtons(); });
Scroll to Top