Preventive Maintenance Schedule Generator

Preventive Maintenance Schedule Generator

Preventive Maintenance Schedule Generator

Maintenance Schedule by Frequency

No maintenance items added yet. Go to the 'Data Configuration' tab.

`; return; } // Group items by frequency const groupedItems = FREQUENCY_OPTIONS.reduce((acc, freq) => { acc[freq] = []; return acc; }, {}); pms_data.items.forEach(item => { if(groupedItems[item.frequency]) { groupedItems[item.frequency].push(item); } else { // Fallback for unexpected frequency if (!groupedItems['Other']) groupedItems['Other'] = []; groupedItems['Other'].push(item); } }); // Render each frequency group FREQUENCY_OPTIONS.forEach(freq => { if (groupedItems[freq].length > 0) { const sectionDiv = document.createElement('div'); const h3Class = "text-xl font-semibold text-blue-800 border-b border-gray-300 pb-2 mb-3"; const tableClass = "w-full text-left border-collapse"; const thClass = "p-3 bg-gray-100 text-sm font-semibold text-gray-600 border-b border-gray-300"; const tdClass = "p-3 border-b border-gray-200 text-sm"; let itemsHTML = groupedItems[freq].map(item => ` ${pms_escapeHTML(item.equipment)} ${pms_escapeHTML(item.task)} `).join(''); sectionDiv.innerHTML = `

${freq} Tasks

${itemsHTML}
Equipment / Asset Task
`; targetDiv.appendChild(sectionDiv); } }); // Handle 'Other' if it exists (shouldn't with current setup but good practice) if (groupedItems['Other'] && groupedItems['Other'].length > 0) { // Similar rendering logic as above for 'Other' category } } /** * Renders a clone for PDF generation */ function pms_renderPdfClone() { pms_pdfRenderClone.innerHTML = `

Preventive Maintenance Schedule

`; // Render data into the clone's content area const contentArea = pms_pdfRenderClone.querySelector('.space-y-6'); pms_renderDashboard(contentArea, true); } /** * Generates and downloads a PDF of the schedule */ async function pms_downloadPDF() { if (pms_data.items.length === 0) { alert("Please add some maintenance items before downloading."); return; } if (typeof jspdf === 'undefined' || typeof html2canvas === 'undefined') { console.error("PMS Tool Error: jsPDF or html2canvas library not loaded."); alert("Error: PDF libraries failed to load. Please check console."); return; } pms_renderPdfClone(); // Create and populate the clone const { jsPDF } = window.jspdf; try { // Target the entire clone div const canvas = await html2canvas(pms_pdfRenderClone, { scale: 1.5, // Increase resolution slightly useCORS: true, windowWidth: pms_pdfRenderClone.scrollWidth, windowHeight: pms_pdfRenderClone.scrollHeight // Capture full height }); const imgData = canvas.toDataURL('image/png'); const imgWidth = canvas.width; const imgHeight = canvas.height; const pdf = new jsPDF({ orientation: 'p', unit: 'pt', format: 'a4' }); const pdfWidth = pdf.internal.pageSize.getWidth(); const pdfHeight = pdf.internal.pageSize.getHeight(); // Scale image height to fit pdf width, handle multiple pages const margin = 40; const contentWidth = pdfWidth - (margin * 2); const contentHeight = (contentWidth * imgHeight) / imgWidth; let heightLeft = contentHeight; let position = 0; // y-position of the image slice on the page // Add the first page pdf.addImage(imgData, 'PNG', margin, position + margin, contentWidth, contentHeight); heightLeft -= (pdfHeight - margin * 2); // Add subsequent pages if needed while (heightLeft > 0) { position -= (pdfHeight - margin * 2); // Move the image's y-position up pdf.addPage(); pdf.addImage(imgData, 'PNG', margin, position + margin, contentWidth, contentHeight); heightLeft -= (pdfHeight - margin * 2); } pdf.save('Preventive_Maintenance_Schedule.pdf'); } catch (error) { console.error("PMS Tool Error: PDF generation failed.", error); alert("An error occurred while generating the PDF. Please try again."); } } // --- EVENT LISTENERS --- // Tab link clicks pms_tabLinks.forEach((link, index) => { link.addEventListener('click', () => pms_switchTab(index)); }); // Next/Prev button clicks if (pms_prevButton) { pms_prevButton.addEventListener('click', () => { if (pms_currentTab > 0) pms_switchTab(pms_currentTab - 1); }); } if (pms_nextButton) { pms_nextButton.addEventListener('click', () => { // If on the last tab (Config tab, index 1) if (pms_currentTab === pms_tabLinks.length - 1) { // Act as Submit: Save data and switch to Dashboard (index 0) pms_updateDataFromConfig(); pms_switchTab(0); } else { // Otherwise, just go to the next tab if (pms_currentTab < pms_tabLinks.length - 1) pms_switchTab(pms_currentTab + 1); } }); } // PDF download if (pms_downloadPdfButton) { pms_downloadPdfButton.addEventListener('click', pms_downloadPDF); } // --- Config Tab Listeners --- if (pms_addItemButton) { pms_addItemButton.addEventListener('click', () => { pms_itemsContainer.appendChild(pms_createItemInput()); }); } if (pms_configTab) { // Handle remove pms_configTab.addEventListener('click', (e) => { const removeButton = e.target.closest('.pms-remove-item'); if (removeButton) { removeButton.closest('.border[data-id]').remove(); // Prevent having zero rows if applicable if(pms_itemsContainer.children.length === 0){ pms_itemsContainer.appendChild(pms_createItemInput()); } } }); // Update data on change (no need for keyup here unless desired for live preview) pms_configTab.addEventListener('change', () => { pms_updateDataFromConfig(); // Optionally update dashboard live if on dashboard tab // if (pms_currentTab === 0) { pms_renderDashboard(); } }); } // --- INITIALIZATION --- pms_initSampleData(); pms_renderConfig(); // Populate config tab on load pms_renderDashboard(); // Show initial schedule on dashboard // Set initial tab state pms_tabPanes.forEach((pane, index) => { pane.classList.toggle('hidden', index !== 0); pane.classList.toggle('pms-active', index === 0); }); pms_tabLinks.forEach((link, index) => { TAB_CLASSES.active.forEach(cls => link.classList.remove(cls)); TAB_CLASSES.inactive.forEach(cls => link.classList.remove(cls)); if (index === 0) { TAB_CLASSES.active.forEach(cls => link.classList.add(cls)); } else { TAB_CLASSES.inactive.forEach(cls => link.classList.add(cls)); } }); });
Scroll to Top