`;
stepsList.appendChild(li);
});
}
/**
* Adds a new step to the list. (Global for form submit)
*/
window.csoAddStep = () => {
const text = stepTextInput.value.trim();
const time = stepTimeInput.value ? parseInt(stepTimeInput.value) : null;
if (!text) {
showMessage("Step description cannot be empty.", true);
return;
}
if (time !== null && (isNaN(time) || time <= 0)) {
showMessage("Please enter a valid positive number for time.", true);
return;
}
steps.push({
id: 's' + Date.now() + Math.random().toString(16).slice(2),
text: text,
time: time,
completed: false
});
stepTextInput.value = '';
stepTimeInput.value = '';
showMessage(null); // Clear errors
renderSteps();
};
/**
* Toggles the completion status of a step. (Global for button click)
*/
window.csoToggleComplete = (id) => {
const step = steps.find(s => s.id === id);
if (step) {
step.completed = !step.completed;
renderSteps();
}
};
/**
* Deletes a step from the list. (Global for button click)
*/
window.csoDeleteStep = (id) => {
if (!confirm('Are you sure you want to delete this step?')) return;
steps = steps.filter(s => s.id !== id);
renderSteps();
};
/**
* Moves a step up or down in the list. (Global for button click)
*/
window.csoMoveStep = (id, direction) => {
const index = steps.findIndex(s => s.id === id);
if (index === -1) return;
const newIndex = index + direction;
if (newIndex < 0 || newIndex >= steps.length) return; // Cannot move outside bounds
// Simple swap
[steps[index], steps[newIndex]] = [steps[newIndex], steps[index]];
renderSteps();
};
/**
* Clears all steps from the list.
*/
function clearAllSteps() {
if (steps.length === 0) {
showMessage("The list is already empty.", false);
return;
}
if (!confirm('Are you sure you want to clear all steps?')) return;
steps = [];
renderSteps();
showMessage(null);
}
/**
* Downloads the steps list as a PDF.
*/
function downloadPDF() {
if (!jsPDF || !jsPDF.autoTable) { showMessage("PDF library not loaded.", true); return; }
if (steps.length === 0) { showMessage("Add some steps before downloading.", true); return; }
showLoader(true);
showMessage(null);
try {
const doc = new jsPDF();
const pageMargin = 15;
const pageWidth = doc.internal.pageSize.getWidth();
let y = 20;
// 1. Title
doc.setFontSize(20);
doc.text("Cooking Steps", pageWidth / 2, y, { align: 'center' });
y += 20;
// 2. Steps Table
const tableHead = [["#", "Status", "Step Description", "Est. Time (min)"]];
const tableBody = steps.map((step, index) => [
index + 1,
step.completed ? 'Done' : 'To Do',
step.text,
step.time ? step.time.toString() : '-'
]);
doc.autoTable({
startY: y,
head: tableHead,
body: tableBody,
theme: 'striped',
headStyles: { fillColor: [0, 95, 204] }, // Primary color
columnStyles: {
0: { cellWidth: 15 }, // Step number
1: { cellWidth: 25 }, // Status
3: { cellWidth: 35, halign: 'right' } // Time
},
didParseCell: function (data) {
// Style completed rows
if (data.row.section === 'body' && data.row.raw[1] === 'Done') {
data.cell.styles.fillColor = '#e8f5e9'; // Light green
data.cell.styles.textColor = '#666';
data.cell.styles.fontStyle = 'italic';
}
}
});
doc.save("Cooking_Steps.pdf");
} catch (e) {
console.error("Error generating PDF:", e);
showMessage("An error occurred while generating the PDF.", true);
} finally {
showLoader(false);
}
}
/** Basic HTML escaping */
function escapeHtml(unsafe) {
if (!unsafe) return '';
return unsafe
.replace(/&/g, "&")
.replace(//g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
}
/** Shows or hides loader */
function showLoader(show) { loaderOverlay.style.display = show ? 'flex' : 'none'; }
/** Displays messages */
function showMessage(message, isError = false) {
if (!message) { messageArea.style.display = 'none'; return; }
messageArea.textContent = message;
messageArea.className = `mt-4 text-center font-medium ${isError ? 'text-red-600' : 'text-blue-600'}`;
messageArea.style.display = 'block';
setTimeout(() => { if(messageArea.textContent === message) { messageArea.style.display = 'none'; } }, 4000);
}
// === Event Listeners ===
clearBtn.addEventListener('click', clearAllSteps);
downloadBtn.addEventListener('click', downloadPDF);
// === Initial Render ===
renderSteps();
});