Build Your Own Weather Station
My Weather Station Plan (Editable)
Go to the "Component Configuration" tab to select items and generate your plan.
Total Estimated Cost: $0.00
1. Select From Component Catalog
Microcontrollers
$10.00
$7.00
$25.00
Core Sensors
$12.00
$5.00
Weather Sensors
$45.00
$20.00
Power & Housing
$25.00
$12.00
$8.00
2. Add Custom Components
$
`;
dashboardList.appendChild(itemEl);
}
/**
* Calculates the total cost from the dashboard items
*/
function recalculateTotal() {
let total = 0;
const costInputs = dashboardList.querySelectorAll(".byows-dash-cost");
costInputs.forEach((input) => {
total += parseFloat(input.value) || 0;
});
totalCostEl.textContent = `Total Estimated Cost: $${total.toFixed(2)}`;
return total;
}
/**
* Handles clicks on dashboard list (for remove)
*/
function handleDashboardClick(e) {
if (e.target.dataset.action === "remove") {
e.target.closest(".byows-dash-item").remove();
recalculateTotal();
}
}
/**
* Handles clicks on custom list (for remove)
*/
function handleCustomListClick(e) {
if (e.target.dataset.action === "remove") {
e.target.closest(".byows-custom-item").remove();
}
}
/**
* Generates a PDF report from the dashboard data
*/
function downloadPDF() {
if (
typeof window.jspdf === "undefined" ||
typeof window.jspdf.jsPDF.autoTable === "undefined"
) {
alert("Error: PDF library could not be loaded. Please try again.");
return;
}
const { jsPDF } = window.jspdf;
const doc = new jsPDF("p", "pt", "a4");
const margin = 40;
const tableHead = [["Component", "Category", "Estimated Cost ($)"]];
const tableBody = [];
// Get data *from the dashboard*
const dashItems = dashboardList.querySelectorAll(".byows-dash-item");
dashItems.forEach((item) => {
const name = item.querySelector(".byows-dash-name").value;
const category = item.querySelector(".byows-dash-category").value;
const cost = parseFloat(
item.querySelector(".byows-dash-cost").value
).toFixed(2);
tableBody.push([name, category, cost]);
});
const total = recalculateTotal();
doc.setFontSize(18);
doc.text("My Weather Station Plan", margin, margin);
doc.autoTable({
startY: margin + 20,
head: tableHead,
body: tableBody,
theme: "striped",
headStyles: {
fillColor: [0, 115, 230],
textColor: [255, 255, 255],
},
columnStyles: {
0: { cellWidth: 200 },
1: { cellWidth: 150 },
2: { cellWidth: "auto", halign: "right" },
},
// Add footer row for total
didDrawPage: function (data) {
let str = `Total Estimated Cost: $${total.toFixed(2)}`;
doc.setFontSize(12);
doc.setFont(undefined, "bold");
doc.text(
str,
data.settings.margin.left + data.table.getWidth() - doc.getTextWidth(str),
data.table.finalY + 20
);
},
});
doc.save("Weather_Station_Plan.pdf");
}
/**
* Helper to escape HTML
*/
function escapeHTML(str) {
if (!str) return "";
return str
.replace(/&/g, "&")
.replace(//g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
}
// --- 3. INITIALIZATION & EVENT LISTENERS ---
// Tab Listeners
tabButtons.forEach((btn) => {
btn.addEventListener("click", () => showTab(btn.dataset.target));
});
navButtons.forEach((btn) => {
btn.addEventListener("click", () => showTab(btn.dataset.target));
});
// Config Tab Listeners
if (customForm) {
customForm.addEventListener("submit", handleAddCustom);
}
if (customListContainer) {
customListContainer.addEventListener("click", handleCustomListClick);
}
if (generateBtn) {
generateBtn.addEventListener("click", handleGeneratePlan);
}
// Dashboard Tab Listeners
if (recalculateBtn) {
recalculateBtn.addEventListener("click", recalculateTotal);
}
if (pdfBtn) {
pdfBtn.addEventListener("click", downloadPDF);
}
if (dashboardList) {
dashboardList.addEventListener("click", handleDashboardClick);
}
// Initial State
showTab("byows-tab-dashboard");
});
