2025-06-30 19:41:12 +03:00
|
|
|
import "../common/prototypes.js";
|
2025-11-02 23:26:28 +02:00
|
|
|
import * as storage from "../common/storage.js";
|
2025-06-30 19:41:12 +03:00
|
|
|
|
2025-11-02 22:56:37 +02:00
|
|
|
const RECIPE_STORAGE_NAME = "/synth/";
|
2025-11-02 23:26:28 +02:00
|
|
|
const LIST_STORAGE_NAME = "/synth/finished-mats";
|
2025-10-24 22:16:11 +03:00
|
|
|
|
2025-06-30 19:41:12 +03:00
|
|
|
let markedNeededMaterials = [];
|
|
|
|
|
|
2025-06-29 14:03:58 +03:00
|
|
|
document.addEventListener("DOMContentLoaded", (event) => {
|
|
|
|
|
const recipes = document.querySelectorAll(".recipe");
|
|
|
|
|
|
|
|
|
|
for (const recipe of recipes) {
|
|
|
|
|
recipe.checked =
|
2025-11-02 23:26:28 +02:00
|
|
|
storage.get(RECIPE_STORAGE_NAME + recipe.id) === "true" ?? false;
|
2025-06-30 19:41:12 +03:00
|
|
|
updateSynthRecipeState(recipe);
|
2025-06-29 14:03:58 +03:00
|
|
|
|
|
|
|
|
recipe.addEventListener("input", function () {
|
2025-07-01 14:47:08 +03:00
|
|
|
// Change the recipe's state and update and needed materials list based on the remaining recipes
|
2025-11-02 23:26:28 +02:00
|
|
|
storage.set(RECIPE_STORAGE_NAME + this.id, this.checked);
|
2025-06-30 19:41:12 +03:00
|
|
|
updateSynthRecipeState(this);
|
|
|
|
|
calcNeededMats();
|
2025-06-29 14:03:58 +03:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-30 19:41:12 +03:00
|
|
|
const recipesLabels = document.querySelectorAll(".recipe-wrapper > label");
|
|
|
|
|
for (const label of recipesLabels) {
|
2025-06-29 22:40:04 +03:00
|
|
|
label.addEventListener("mouseenter", function () {
|
2025-06-30 19:41:12 +03:00
|
|
|
highlightNeededMats(this);
|
2025-06-29 22:40:04 +03:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-01 14:47:08 +03:00
|
|
|
// Turn the single saved string into an array with each material
|
2025-11-02 23:26:28 +02:00
|
|
|
if (storage.get(LIST_STORAGE_NAME) != null) {
|
|
|
|
|
let saved = storage.get(LIST_STORAGE_NAME);
|
2025-07-01 14:47:08 +03:00
|
|
|
saved = saved.split(",");
|
|
|
|
|
markedNeededMaterials = saved;
|
|
|
|
|
markedNeededMaterials = markedNeededMaterials.filter(
|
|
|
|
|
(n) => n && n !== "",
|
|
|
|
|
);
|
|
|
|
|
} else {
|
|
|
|
|
markedNeededMaterials = new Array();
|
|
|
|
|
}
|
2025-06-30 19:41:12 +03:00
|
|
|
|
|
|
|
|
calcNeededMats();
|
2025-06-29 14:03:58 +03:00
|
|
|
});
|
|
|
|
|
|
2025-06-30 19:41:12 +03:00
|
|
|
function updateSynthRecipeState(recipe) {
|
2025-06-29 14:03:58 +03:00
|
|
|
if (recipe.checked) {
|
|
|
|
|
recipe.parentElement.classList.add("complete");
|
|
|
|
|
} else {
|
|
|
|
|
recipe.parentElement.classList.remove("complete");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-30 19:41:12 +03:00
|
|
|
function highlightNeededMats(label) {
|
2025-06-29 22:40:04 +03:00
|
|
|
let mats = [];
|
2025-06-29 23:02:50 +03:00
|
|
|
const ingredients = label.querySelectorAll("ul li");
|
|
|
|
|
const checkbox = label.parentElement.querySelectorAll(".recipe")[0];
|
|
|
|
|
|
2025-06-29 22:40:04 +03:00
|
|
|
for (const ingredient of ingredients) {
|
|
|
|
|
const name = ingredient.dataset["synthItemName"];
|
|
|
|
|
mats.push(name);
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-30 19:41:12 +03:00
|
|
|
const elems = document.querySelectorAll("#mats ul li");
|
2025-06-29 22:40:04 +03:00
|
|
|
for (const elem of elems) {
|
|
|
|
|
const isCrossed = elem.style.textDecoration === "line-through";
|
|
|
|
|
if (isCrossed) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
elem.style.color = "#fff";
|
|
|
|
|
for (const mat of mats) {
|
|
|
|
|
if (elem.innerHTML.includes(mat)) {
|
|
|
|
|
elem.style.color = "limegreen";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-30 19:41:12 +03:00
|
|
|
function calcNeededMats() {
|
2025-06-29 14:03:58 +03:00
|
|
|
const needed = new Map();
|
|
|
|
|
const recipes = document.querySelectorAll(".recipe");
|
|
|
|
|
|
|
|
|
|
for (const recipe of recipes) {
|
|
|
|
|
const isComplete = recipe.checked;
|
|
|
|
|
if (isComplete) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const ingredients =
|
|
|
|
|
recipe.parentElement.querySelectorAll("label ul li");
|
|
|
|
|
for (const ingredient of ingredients) {
|
|
|
|
|
let name = ingredient.dataset["synthItemName"];
|
|
|
|
|
let amount = Number(ingredient.dataset["synthItemAmount"]);
|
|
|
|
|
|
|
|
|
|
if (needed.has(name)) {
|
2025-06-30 19:41:12 +03:00
|
|
|
let newAmount = Number(needed.get(name)) + amount;
|
|
|
|
|
needed.set(name, newAmount);
|
2025-06-29 14:03:58 +03:00
|
|
|
} else {
|
|
|
|
|
needed.set(name, amount);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const sortedMap = new Map([...needed].sort((a, b) => b[1] - a[1]));
|
|
|
|
|
|
|
|
|
|
// generating the new list with materials needed
|
|
|
|
|
const matsList = document.getElementById("mats");
|
|
|
|
|
matsList.innerHTML = "<h1>Materials Needed</h1>";
|
|
|
|
|
const uiList = document.createElement("ul");
|
|
|
|
|
for (const entry of sortedMap) {
|
|
|
|
|
const liElem = document.createElement("li");
|
|
|
|
|
liElem.innerHTML = entry[0] + " x" + entry[1];
|
2025-06-29 22:40:04 +03:00
|
|
|
liElem.addEventListener("click", function () {
|
2025-06-30 19:41:12 +03:00
|
|
|
updateMarkedNeededMats(entry[0]);
|
|
|
|
|
markNeededMat(this);
|
2025-06-29 22:40:04 +03:00
|
|
|
});
|
|
|
|
|
|
2025-06-30 19:41:12 +03:00
|
|
|
if (markedNeededMaterials.includes(entry[0])) {
|
|
|
|
|
markNeededMat(liElem);
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-29 14:03:58 +03:00
|
|
|
uiList.appendChild(liElem);
|
|
|
|
|
}
|
|
|
|
|
matsList.appendChild(uiList);
|
|
|
|
|
}
|
2025-06-30 19:41:12 +03:00
|
|
|
|
|
|
|
|
function updateMarkedNeededMats(ingredient) {
|
|
|
|
|
if (markedNeededMaterials.includes(ingredient)) {
|
|
|
|
|
markedNeededMaterials.remove(ingredient);
|
|
|
|
|
} else {
|
|
|
|
|
markedNeededMaterials.push(ingredient);
|
|
|
|
|
}
|
2025-07-01 14:47:08 +03:00
|
|
|
markedNeededMaterials = markedNeededMaterials.filter((n) => n && n !== "");
|
2025-11-02 23:26:28 +02:00
|
|
|
storage.set(LIST_STORAGE_NAME, markedNeededMaterials);
|
2025-06-30 19:41:12 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function markNeededMat(mat) {
|
|
|
|
|
const isCrossed = mat.style.textDecoration === "line-through";
|
|
|
|
|
mat.style.textDecoration = isCrossed ? "none" : "line-through";
|
|
|
|
|
mat.style.color = isCrossed ? "#fff" : "#f00";
|
|
|
|
|
}
|