document.addEventListener("DOMContentLoaded", () => {
loadQuests();
document.getElementById("new-quest").addEventListener("keypress", handleEnterKey(addQuest));
});
const curry = fn => (...args) =>
args.length >= fn.length
? fn(...args)
: curry(fn.bind(null, ...args));
const addQuest = () => {
const questText = getInputValue("new-quest");
if (!validateText(questText)) return;
const quest = createQuestObject(questText);
saveQuest(quest);
clearInput("new-quest")();
renderQuests();
};
const getInputValue = curry((id) => document.getElementById(id).value);
const validateText = text => text.trim() !== "";
const createQuestObject = text => ({
id: Date.now(),
text,
status: "new",
dateCreated: new Date().toISOString(),
dateCompleted: null
});
const saveQuest = quest => {
const quests = getStoredQuests().concat([quest]);
localStorage.setItem("quests", JSON.stringify(quests));
};
const getStoredQuests = () =>
JSON.parse(localStorage.getItem("quests")) || [];
const clearInput = curry((id) => () =>
document.getElementById(id).value = "");
const loadQuests = () => renderQuests();
const renderQuests = (showCompleted = false) => {
const quests = getStoredQuests();
const sortedQuests = sortByDateCreated(quests);
const filteredQuests = filterQuests(showCompleted, sortedQuests);
renderQuestList(filteredQuests);
};
const sortByDateCreated = quests =>
quests.sort((a, b) => new Date(b.dateCreated) - new Date(a.dateCreated));
const filterQuests = (showCompleted, quests) =>
quests.filter(quest => showCompleted || quest.status !== "complete");
const renderQuestList = quests => {
const questList = document.getElementById("quest-list");
questList.innerHTML = "";
quests.forEach(renderQuest(questList));
};
const renderQuest = curry((questList, quest) => {
const questDiv = document.createElement("div");
questDiv.className = `quest ${quest.status}`;
questDiv.innerHTML = `
<span contenteditable="true" onblur="editQuest(${quest.id}, this.innerText)">${quest.text}</span>
<span>
${quest.status !== "complete" ? `<button onclick="toggleStatus(${quest.id})">${getStatusButtonText(quest.status)}</button>` : ''}
${quest.status === "complete" ? `<button onclick="revertQuest(${quest.id})">Revert</button><button onclick="deleteQuest(${quest.id})">Delete</button>` : ''}
</span>
`;
questList.appendChild(questDiv);
});
const getStatusButtonText = status =>
status === "new" ? "Start Quest" : "Complete Quest";
const toggleStatus = id => {
const quests = getStoredQuests();
const updatedQuests = updateQuestStatus(id, quests);
saveAllQuests(updatedQuests);
renderQuests();
};
const updateQuestStatus = (id, quests) =>
quests.map(quest =>
quest.id === id ? updateQuest(quest) : quest
);
const updateQuest = quest => {
if (quest.status === "new") return { ...quest, status: "in-progress" };
if (quest.status === "in-progress")
return { ...quest, status: "complete", dateCompleted: new Date().toISOString() };
return quest;
};
const revertQuest = id => {
const quests = getStoredQuests();
const updatedQuests = revertQuestStatus(id, quests);
saveAllQuests(updatedQuests);
renderQuests(true);
};
const revertQuestStatus = (id, quests) =>
quests.map(quest =>
quest.id === id ? { ...quest, status: "in-progress", dateCompleted: null } : quest
);
const deleteQuest = id => {
const quests = getStoredQuests();
const updatedQuests = removeQuest(id, quests);
saveAllQuests(updatedQuests);
renderQuests(true);
};
const removeQuest = (id, quests) =>
quests.filter(quest => quest.id !== id);
const saveAllQuests = quests =>
localStorage.setItem("quests", JSON.stringify(quests));
const editQuest = (id, newText) => {
const quests = getStoredQuests();
const updatedQuests = updateQuestText(id, newText, quests);
saveAllQuests(updatedQuests);
};
const updateQuestText = (id, newText, quests) =>
quests.map(quest =>
quest.id === id ? { ...quest, text: newText } : quest
);
const handleEnterKey = curry((fn, event) => {
if (event.key === "Enter") fn();
});
const toggleCompleted = () => {
const showCompleted = getShowCompletedState();
renderQuests(showCompleted);
toggleCompletedButtonText(showCompleted);
};
const getShowCompletedState = () =>
document.querySelector("button[onclick='toggleCompleted()']").innerText === "View Completed Quests";
const toggleCompletedButtonText = showCompleted =>
document.querySelector("button[onclick='toggleCompleted()']").innerText = showCompleted ? "Hide Completed Quests" : "View Completed Quests";