Gardening Tracker Dashboard

Total Plants

0

Tasks Today

0

Most Recent Activity

-

My Plants

Select a plant to manage its logs

Status: ${statusText}

`; dashboardGrid.appendChild(card); }); summaryPlants.textContent = state.plants.length; summaryTasks.textContent = tasksToday; // Placeholder for now summaryActivity.textContent = recentActivity.text; }; const renderManagementView = () => { // Render plants list plantsList.innerHTML = ''; state.plants.forEach(plant => { const item = document.createElement('div'); item.className = 'gt-plant-item'; item.dataset.id = plant.id; if (plant.id === currentlyManagingPlantId) { item.classList.add('selected'); } item.innerHTML = ` ${plant.name} `; plantsList.appendChild(item); }); // Render logs for selected plant const plant = state.plants.find(p => p.id === currentlyManagingPlantId); if (plant) { logsTitle.textContent = `Logs for ${plant.name}`; logsContent.style.display = 'block'; logsBody.innerHTML = ''; const sortedLogs = [...plant.logs].sort((a,b) => new Date(b.date) - new Date(a.date)); sortedLogs.forEach(log => { const row = document.createElement('tr'); row.innerHTML = ` ${new Date(log.date).toLocaleDateString()} ${log.type} ${log.notes} `; logsBody.appendChild(row); }); } else { logsTitle.textContent = 'Select a plant to manage its logs'; logsContent.style.display = 'none'; } }; // --- Event Handlers --- plantForm.addEventListener('submit', e => { e.preventDefault(); const name = plantNameInput.value.trim(); if (name) { state.plants.push({ id: Date.now(), name, type: plantTypeInput.value.trim(), plantingDate: plantDateInput.value, logs: [] }); plantForm.reset(); render(); } }); plantsList.addEventListener('click', e => { const target = e.target; if (target.matches('.gt-button-danger')) { const plantId = parseInt(target.dataset.id); if (confirm('Are you sure you want to delete this plant and all its logs?')) { state.plants = state.plants.filter(p => p.id !== plantId); if (currentlyManagingPlantId === plantId) { currentlyManagingPlantId = null; } render(); } } else if (target.closest('.gt-plant-item')) { currentlyManagingPlantId = parseInt(target.closest('.gt-plant-item').dataset.id); renderManagementView(); } }); logForm.addEventListener('submit', e => { e.preventDefault(); const plant = state.plants.find(p => p.id === currentlyManagingPlantId); if (plant) { plant.logs.push({ id: Date.now(), type: logTypeInput.value, date: logDateInput.value, notes: logNotesInput.value.trim() }); logForm.reset(); logDateInput.valueAsDate = new Date(); render(); } }); logsBody.addEventListener('click', e => { if (e.target.matches('.gt-button-danger')) { const plant = state.plants.find(p => p.id === currentlyManagingPlantId); if (plant) { const logId = parseInt(e.target.dataset.id); plant.logs = plant.logs.filter(l => l.id !== logId); render(); } } }); // --- PDF Generation --- downloadPdfBtn.addEventListener('click', () => { if (state.plants.length === 0) { alert("No data to generate a report."); return; } const { jsPDF } = jspdf; const doc = new jsPDF({ orientation: 'p', unit: 'mm', format: 'a4' }); let yPos = 20; doc.setFontSize(20); doc.text("My Garden Report", doc.internal.pageSize.getWidth() / 2, yPos, { align: 'center' }); yPos += 15; state.plants.forEach(plant => { if (yPos > 250) { doc.addPage(); yPos = 20; } doc.setFontSize(16); doc.text(plant.name, 14, yPos); yPos += 8; doc.setFontSize(11); doc.text(`Type: ${plant.type || 'N/A'} | Planted on: ${new Date(plant.plantingDate).toLocaleDateString()}`, 14, yPos); yPos += 8; if (plant.logs.length > 0) { const tableData = plant.logs.map(l => [ new Date(l.date).toLocaleDateString(), l.type, l.notes ]); jspdf.autoTable(doc, { head: [['Date', 'Activity', 'Notes']], body: tableData, startY: yPos, theme: 'striped', headStyles: { fillColor: [64, 145, 108] } }); yPos = doc.lastAutoTable.finalY + 15; } else { doc.text('No activity logged for this plant.', 14, yPos); yPos += 15; } }); doc.save(`Gardening-Report-${new Date().toISOString().slice(0,10)}.pdf`); }); // --- Initial Load --- loadState(); plantDateInput.valueAsDate = new Date(); logDateInput.valueAsDate = new Date(); render(); });
Scroll to Top