Refactor templates to externalize JavaScript: Moved inline scripts to separate JS files and added JSON data attributes for better maintainability and performance. Updated consumption, costs, equipment, maintenance, production, reporting, and simulations templates accordingly.

This commit is contained in:
2025-10-21 07:20:02 +02:00
parent 5a84445e90
commit 18f4ae7278
21 changed files with 1963 additions and 1986 deletions

243
static/js/maintenance.js Normal file
View File

@@ -0,0 +1,243 @@
document.addEventListener("DOMContentLoaded", () => {
const dataElement = document.getElementById("maintenance-data");
let equipmentByScenario = {};
let maintenanceByScenario = {};
if (dataElement) {
try {
const parsed = JSON.parse(dataElement.textContent || "{}");
if (parsed && typeof parsed === "object") {
if (parsed.equipment && typeof parsed.equipment === "object") {
equipmentByScenario = parsed.equipment;
}
if (parsed.maintenance && typeof parsed.maintenance === "object") {
maintenanceByScenario = parsed.maintenance;
}
}
} catch (error) {
console.error("Unable to parse maintenance data", error);
}
}
const filterSelect = document.getElementById("maintenance-scenario-filter");
const tableWrapper = document.getElementById("maintenance-table-wrapper");
const tableBody = document.getElementById("maintenance-table-body");
const emptyState = document.getElementById("maintenance-empty");
const form = document.getElementById("maintenance-form");
const feedbackEl = document.getElementById("maintenance-feedback");
const formScenarioSelect = document.getElementById(
"maintenance-form-scenario"
);
const equipmentSelect = document.getElementById("maintenance-form-equipment");
const equipmentEmptyState = document.getElementById(
"maintenance-equipment-empty"
);
const showFeedback = (message, type = "success") => {
if (!feedbackEl) {
return;
}
feedbackEl.textContent = message;
feedbackEl.classList.remove("hidden", "success", "error");
feedbackEl.classList.add(type);
};
const hideFeedback = () => {
if (!feedbackEl) {
return;
}
feedbackEl.classList.add("hidden");
feedbackEl.textContent = "";
};
const formatCost = (value) =>
Number(value).toLocaleString(undefined, {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
});
const formatDate = (value) => {
if (!value) {
return "—";
}
const parsed = new Date(value);
if (Number.isNaN(parsed.getTime())) {
return value;
}
return parsed.toLocaleDateString();
};
const renderMaintenanceRows = (scenarioId) => {
if (!tableBody || !tableWrapper || !emptyState) {
return;
}
const key = String(scenarioId);
const records = maintenanceByScenario[key] || [];
tableBody.innerHTML = "";
if (!records.length) {
emptyState.textContent =
"No maintenance entries recorded for this scenario yet.";
emptyState.classList.remove("hidden");
tableWrapper.classList.add("hidden");
return;
}
emptyState.classList.add("hidden");
tableWrapper.classList.remove("hidden");
records.forEach((record) => {
const row = document.createElement("tr");
row.innerHTML = `
<td>${formatDate(record.maintenance_date)}</td>
<td>${record.equipment_name || "—"}</td>
<td>${formatCost(record.cost)}</td>
<td>${record.description || "—"}</td>
`;
tableBody.appendChild(row);
});
};
const populateEquipmentOptions = (scenarioId) => {
if (!equipmentSelect) {
return;
}
equipmentSelect.innerHTML =
'<option value="" disabled selected>Select equipment</option>';
equipmentSelect.disabled = true;
if (equipmentEmptyState) {
equipmentEmptyState.classList.add("hidden");
}
if (!scenarioId) {
return;
}
const list = equipmentByScenario[String(scenarioId)] || [];
if (!list.length) {
if (equipmentEmptyState) {
equipmentEmptyState.textContent =
"Add equipment for this scenario before scheduling maintenance.";
equipmentEmptyState.classList.remove("hidden");
}
return;
}
list.forEach((item) => {
const option = document.createElement("option");
option.value = item.id;
option.textContent = item.name || `Equipment ${item.id}`;
equipmentSelect.appendChild(option);
});
equipmentSelect.disabled = false;
};
if (filterSelect) {
filterSelect.addEventListener("change", (event) => {
const value = event.target.value;
if (!value) {
if (emptyState && tableWrapper && tableBody) {
emptyState.textContent =
"Choose a scenario to review upcoming or completed maintenance.";
emptyState.classList.remove("hidden");
tableWrapper.classList.add("hidden");
tableBody.innerHTML = "";
}
return;
}
renderMaintenanceRows(value);
});
}
if (formScenarioSelect) {
formScenarioSelect.addEventListener("change", (event) => {
const value = event.target.value;
populateEquipmentOptions(value);
});
}
const submitMaintenance = async (event) => {
event.preventDefault();
hideFeedback();
if (!form) {
return;
}
const formData = new FormData(form);
const scenarioId = formData.get("scenario_id");
const equipmentId = formData.get("equipment_id");
const payload = {
scenario_id: scenarioId ? Number(scenarioId) : null,
equipment_id: equipmentId ? Number(equipmentId) : null,
maintenance_date: formData.get("maintenance_date"),
cost: Number(formData.get("cost")),
description: formData.get("description") || null,
};
if (!payload.scenario_id || !payload.equipment_id) {
showFeedback(
"Select a scenario and equipment before submitting.",
"error"
);
return;
}
try {
const response = await fetch("/api/maintenance/", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(payload),
});
if (!response.ok) {
const errorDetail = await response.json().catch(() => ({}));
throw new Error(
errorDetail.detail || "Unable to add maintenance entry."
);
}
const result = await response.json();
const mapKey = String(result.scenario_id);
if (!Array.isArray(maintenanceByScenario[mapKey])) {
maintenanceByScenario[mapKey] = [];
}
const equipmentList = equipmentByScenario[mapKey] || [];
const matchedEquipment = equipmentList.find(
(item) => Number(item.id) === Number(result.equipment_id)
);
result.equipment_name = matchedEquipment ? matchedEquipment.name : "";
maintenanceByScenario[mapKey].push(result);
form.reset();
populateEquipmentOptions(null);
showFeedback("Maintenance entry saved.", "success");
if (filterSelect && filterSelect.value === String(result.scenario_id)) {
renderMaintenanceRows(filterSelect.value);
}
} catch (error) {
showFeedback(error.message || "An unexpected error occurred.", "error");
}
};
if (form) {
form.addEventListener("submit", submitMaintenance);
}
if (filterSelect && filterSelect.value) {
renderMaintenanceRows(filterSelect.value);
}
if (formScenarioSelect && formScenarioSelect.value) {
populateEquipmentOptions(formScenarioSelect.value);
}
});