feat: synchronize recipe completion controls

Fixes #5\nRefs #1, #2
This commit is contained in:
2026-08-14 13:28:57 -05:00
parent b61ca70bed
commit 6f28f83f4a
10 changed files with 334 additions and 29 deletions
+49 -6
View File
@@ -123,11 +123,11 @@ Module.register("MMM-NextcloudCookbook", {
return root;
}
root.appendChild(this.renderRecipe(this.state.recipe));
root.appendChild(this.renderRecipe(this.state.recipe, this.state.progress));
return root;
},
renderRecipe(recipe) {
renderRecipe(recipe, progress = {}) {
const article = document.createElement("article");
article.className = "ncc-recipe";
@@ -138,6 +138,7 @@ Module.register("MMM-NextcloudCookbook", {
const metadata = [
["Yield", recipe.recipeYield],
["Original yield", recipe.originalRecipeYield !== recipe.recipeYield ? recipe.originalRecipeYield : null],
["Prep", NCCFormatDuration(recipe.prepTime)],
["Cook", NCCFormatDuration(recipe.cookTime)],
["Total", NCCFormatDuration(recipe.totalTime)]
@@ -168,9 +169,34 @@ Module.register("MMM-NextcloudCookbook", {
ingredientsTitle.textContent = "Ingredients";
ingredients.appendChild(ingredientsTitle);
const ingredientList = document.createElement("ul");
(recipe.recipeIngredient || []).forEach((ingredient) => {
(recipe.recipeIngredient || []).forEach((ingredient, index) => {
const item = document.createElement("li");
item.textContent = ingredient;
const status = recipe.recipeIngredientStatus?.[index];
if (status === "unquantified") {
item.classList.add("ncc-quantity-warning");
item.setAttribute("aria-label", `Verify quantity: ${ingredient}`);
} else if (status === "unscalable" || status === "approximate") {
item.classList.add("ncc-quantity-error");
item.setAttribute("aria-label", `Scaling warning: ${ingredient}`);
}
const completed = progress.completedIngredients?.includes(index);
if (completed) item.classList.add("ncc-completed");
const label = document.createElement("label");
label.className = "ncc-progress-control";
const checkbox = document.createElement("input");
checkbox.type = "checkbox";
checkbox.checked = completed;
checkbox.setAttribute("aria-label", `Mark ingredient complete: ${ingredient}`);
checkbox.addEventListener("change", () => {
checkbox.disabled = true;
this.sendSocketNotification("UPDATE_PROGRESS", {
kind: "ingredient", index, completed: checkbox.checked
});
});
const text = document.createElement("span");
text.textContent = ingredient;
label.append(checkbox, text);
item.appendChild(label);
ingredientList.appendChild(item);
});
ingredients.appendChild(ingredientList);
@@ -180,9 +206,26 @@ Module.register("MMM-NextcloudCookbook", {
instructionsTitle.textContent = "Instructions";
instructions.appendChild(instructionsTitle);
const instructionList = document.createElement("ol");
this.flattenInstructions(recipe.recipeInstructions || []).forEach((step) => {
this.flattenInstructions(recipe.recipeInstructions || []).forEach((step, index) => {
const item = document.createElement("li");
item.textContent = step;
const completed = progress.completedSteps?.includes(index);
if (completed) item.classList.add("ncc-completed");
const label = document.createElement("label");
label.className = "ncc-progress-control";
const checkbox = document.createElement("input");
checkbox.type = "checkbox";
checkbox.checked = completed;
checkbox.setAttribute("aria-label", `Mark step complete: ${step}`);
checkbox.addEventListener("change", () => {
checkbox.disabled = true;
this.sendSocketNotification("UPDATE_PROGRESS", {
kind: "step", index, completed: checkbox.checked
});
});
const text = document.createElement("span");
text.textContent = step;
label.append(checkbox, text);
item.appendChild(label);
instructionList.appendChild(item);
});
instructions.appendChild(instructionList);