<div class="why-head">
<span class="why-index">${index + 1}</span>
<strong>${title}</strong>
</div>
<div class="why-body">
<label for="fw-why-${index}">${title}</label>
<textarea id="fw-why-${index}" placeholder="Answer why ${index + 1} here..."></textarea>
</div>
`;
const input = card.querySelector("textarea");
input.value = state.whys[index];
input.addEventListener("input", (event) => {
state.whys[index] = event.target.value;
renderDerived();
});
els.whyList.appendChild(card);
});
}
function renderActions() {
els.actionRows.innerHTML = "";
state.actions.forEach((item, index) => {
const row = document.createElement("tr");
row.innerHTML = `
<td><input type="text" aria-label="Action ${index + 1}" placeholder="Define the corrective action" value="${escapeHtml(item.action)}"></td>
<td><input type="text" aria-label="Owner ${index + 1}" placeholder="Owner" value="${escapeHtml(item.owner)}"></td>
<td><input type="date" aria-label="Due date ${index + 1}" value="${escapeHtml(item.dueDate)}"></td>
<td><button class="icon-btn" type="button" aria-label="Remove action ${index + 1}">×</button></td>
`;
const inputs = row.querySelectorAll("input");
const removeButton = row.querySelector("button");
inputs[0].addEventListener("input", (event) => {
state.actions[index].action = event.target.value;
renderDerived();
});
inputs[1].addEventListener("input", (event) => {
state.actions[index].owner = event.target.value;
renderDerived();
});
inputs[2].addEventListener("input", (event) => {
state.actions[index].dueDate = event.target.value;
renderDerived();
});
removeButton.addEventListener("click", () => {
state.actions.splice(index, 1);
if (!state.actions.length) {
state.actions.push({ action: "", owner: "", dueDate: "" });
}
renderActions();
renderDerived();
});
els.actionRows.appendChild(row);
});
}
function renderDerived() {
const completedWhys = state.whys.filter((value) => value.trim()).length;
const plannedActions = state.actions.filter((item) => item.action.trim()).length;
const assignedOwners = state.actions.filter((item) => item.owner.trim()).length;
const rootCause = state.whys[4].trim() || [...state.whys].reverse().find((value) => value.trim()) || "";
els.metricWhys.textContent = `${completedWhys}/5`;
els.metricActions.textContent = String(plannedActions);
els.metricOwners.textContent = String(assignedOwners);
els.rootCause.textContent = rootCause || "Complete the five why fields to surface the root cause here.";
els.thereforeList.innerHTML = "";
thereforeTitles.forEach((title, index) => {
const answer = state.whys[index].trim();
const line = document.createElement("div");
line.className = "summary-line";
line.innerHTML = `
<strong>${title}</strong>
<div>${answer ? `Therefore, ${escapeHtml(answer)}` : "<span style='color: var(--muted);'>Waiting for this step.</span>"}</div>
`;
els.thereforeList.appendChild(line);
});
}
function exportJson() {
const payload = {
exportedAt: new Date().toISOString(),
title: "Quality In Practice - 5 Whys Root Cause Analysis",
problemStatement: state.problemStatement,
whys: state.whys,
rootCause: state.whys[4] || [...state.whys].reverse().find(Boolean) || "",
actions: state.actions
};
const blob = new Blob([JSON.stringify(payload, null, 2)], { type: "application/json" });
const url = URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.download = "quality-in-practice-5-whys.json";
link.click();
URL.revokeObjectURL(url);
setStatus("JSON export downloaded.");
}
function resetAll() {
if (!window.confirm("Clear the current 5 Whys analysis?")) return;
state.problemStatement = "";
state.whys = ["", "", "", "", ""];
state.actions = structuredClone(defaultState.actions);
els.problem.value = "";
renderWhys();
renderActions();
renderDerived();
const cleared = clearStoredState();
setStatus(cleared ? "Form cleared." : "Form cleared for this session.");
}
root.addEventListener("click", (event) => {
const action = event.target.getAttribute("data-action");
if (!action) return;
if (action === "save") saveState("Progress saved on this device.");
if (action === "export") exportJson();
if (action === "print") {
saveState("Progress saved before printing.");
window.print();
}
if (action === "clear") resetAll();
if (action === "add-action") {
state.actions.push({ action: "", owner: "", dueDate: "" });
renderActions();
renderDerived();
}
});
els.problem.value = state.problemStatement;
els.problem.addEventListener("input", (event) => {
state.problemStatement = event.target.value;
});
window.addEventListener("beforeunload", () => {
writeStoredState(JSON.stringify(state));
});
renderWhys();
renderActions();
renderDerived();
setStatus(readStoredState() ? "Restored saved progress from this device." : "Nothing saved yet.");
})();
</script>