diff --git a/src/Mods/Reminder/reminder.js b/src/Mods/Reminder/reminder.js index 22d2a74f28eb4cc0faaeb61c6ced8ee90d3ff5da..1112e9fc965bf266277193da6b82608463820b2d 100644 --- a/src/Mods/Reminder/reminder.js +++ b/src/Mods/Reminder/reminder.js @@ -1,140 +1,163 @@ -/** - * @param {string|Node} message - * @param {number} week - * @param {string} [category] - */ -App.Reminders.add = function(message, week, category = "manual") { - if (message === "" || message === null) { - return; - } - const entry = {message: message, week: week, category: category}; - - // V.reminders is sorted by week from low to high, we insert at the correct place so it remains sorted. - const index = V.reminders.findIndex(e => e.week >= week); - if (index === -1) { - V.reminders.push(entry); - } else { - V.reminders.splice(index, 0, entry); - } -}; - -/** - * @param {Object} [obj] - * @param {number} [obj.maxFuture] how far into the future should reminders be displayed. - * @param {string} [obj.category] - * @param {boolean} [obj.link] show link to managePersonalAffairs.tw - * @returns {HTMLSpanElement|DocumentFragment} - */ -App.Reminders.list = function list({maxFuture = Number.POSITIVE_INFINITY, category = "all", link = false} = {}) { - if (V.reminders.length === 0) { - return document.createDocumentFragment(); - } +App.Reminders = (function() { + const fullDisplayDiv = document.createElement("div"); + const addDiv = document.createElement("div"); + return { + add: add, + list: list, + addField: addField, + fullDisplay: fullDisplay, + dialog: dialog, + }; /** - * @param {string} c - * @returns {boolean} + * @param {string|Node} message + * @param {number} week + * @param {string} [category] */ - const includedCategory = category === "all" ? () => true : c => c === category; - - const replace = () => App.UI.DOM.replace("#reminder-list", list({ - maxFuture: maxFuture, - category: category, - link: link - })); + function add(message, week, category = "manual") { + if (message === "" || message === null) { + return; + } + const entry = {message: message, week: week, category: category}; + + // V.reminders is sorted by week from low to high, we insert at the correct place so it remains sorted. + const index = V.reminders.findIndex(e => e.week >= week); + if (index === -1) { + V.reminders.push(entry); + } else { + V.reminders.splice(index, 0, entry); + } + } /** - * @param {{}} entry + * @param {Object} [obj] + * @param {number} [obj.maxFuture] how far into the future should reminders be displayed. + * @param {string} [obj.category] + * @param {boolean} [obj.link] show link to managePersonalAffairs.tw + * @returns {HTMLSpanElement|DocumentFragment} */ - function clearEntry(entry) { - V.reminders.splice(V.reminders.indexOf(entry), 1); - replace(); - } - - // We only want to remove visible entries - function clearOverdue() { - V.reminders = V.reminders.filter(e => e.week >= V.week || e.week > V.week + maxFuture || !includedCategory(e.category)); - replace(); - } + function list({maxFuture = Number.POSITIVE_INFINITY, category = "all", link = false} = {}) { + if (V.reminders.length === 0) { + return document.createDocumentFragment(); + } - function clearAll() { - V.reminders = V.reminders.filter(e => e.week > V.week + maxFuture || !includedCategory(e.category)); - replace(); - } + /** + * @param {string} c + * @returns {boolean} + */ + const includedCategory = category === "all" ? () => true : c => c === category; + + const replace = () => App.UI.DOM.replace("#reminder-list", list({ + maxFuture: maxFuture, + category: category, + link: link + })); + + /** + * @param {{}} entry + */ + function clearEntry(entry) { + V.reminders.splice(V.reminders.indexOf(entry), 1); + replace(); + } - let outerSpan = document.createElement("span"); - outerSpan.id = "reminder-list"; - - let overdue = 0, any = false; - - V.reminders.filter(e => e.week <= V.week + maxFuture && includedCategory(e.category)) - .forEach(entry => { - any = true; - let week; - let classes = []; // has to be an array, because makeElement takes no empty strings, but empty arrays. - if (entry.week < V.week) { - classes = ["red"]; - week = `${numberWithPluralOne(-(entry.week - V.week), 'week')} ago`; - overdue++; - } else if (entry.week === V.week) { - classes = ["orange"]; - week = "today"; - } else { - if (entry.week <= V.week + 5) { - classes = ["green"]; - } - week = `in ${numberWithPluralOne(entry.week - V.week, 'week')}`; - } - const div = document.createElement("div"); - div.append(entry.message, - " ", App.UI.DOM.makeElement("span", week.toString(), classes), - " ", App.UI.DOM.link("Clear", clearEntry, [entry])); - outerSpan.append(div); - }); - - if (overdue > 0) { - outerSpan.append(App.UI.DOM.makeElement("div", App.UI.DOM.link("Clear Overdue", clearOverdue))); - } - if (any) { - outerSpan.append(App.UI.DOM.makeElement("div", App.UI.DOM.link("Clear all", clearAll))); - if (link) { - outerSpan.append(App.UI.DOM.makeElement("div", App.UI.DOM.passageLink("Manage Reminders", "Manage Personal Affairs",))); + // We only want to remove visible entries + function clearOverdue() { + V.reminders = V.reminders.filter(e => e.week >= V.week || e.week > V.week + maxFuture || !includedCategory(e.category)); + replace(); } - } - return outerSpan; -}; + function clearAll() { + V.reminders = V.reminders.filter(e => e.week > V.week + maxFuture || !includedCategory(e.category)); + replace(); + } -/** - * @returns {HTMLDivElement} - */ -App.Reminders.addField = function() { - const div = document.createElement("div"); + let outerSpan = document.createElement("span"); + outerSpan.id = "reminder-list"; + + let overdue = 0, any = false; + + V.reminders.filter(e => e.week <= V.week + maxFuture && includedCategory(e.category)) + .forEach(entry => { + any = true; + let week; + let classes = []; // has to be an array, because makeElement takes no empty strings, but empty arrays. + if (entry.week < V.week) { + classes = ["red"]; + week = `${numberWithPluralOne(-(entry.week - V.week), 'week')} ago`; + overdue++; + } else if (entry.week === V.week) { + classes = ["orange"]; + week = "today"; + } else { + if (entry.week <= V.week + 5) { + classes = ["green"]; + } + week = `in ${numberWithPluralOne(entry.week - V.week, 'week')}`; + } + const div = document.createElement("div"); + div.append(entry.message, + " ", App.UI.DOM.makeElement("span", week.toString(), classes), + " ", App.UI.DOM.link("Clear", clearEntry, [entry])); + outerSpan.append(div); + }); + + if (overdue > 0) { + outerSpan.append(App.UI.DOM.makeElement("div", App.UI.DOM.link("Clear Overdue", clearOverdue))); + } + if (any) { + outerSpan.append(App.UI.DOM.makeElement("div", App.UI.DOM.link("Clear all", clearAll))); + } - let entry = ""; - let week = 0; + return outerSpan; + } - div.append(App.UI.DOM.makeTextBox("", v => { entry = v; }), - " in ", App.UI.DOM.makeTextBox(0, v => { week = v; }, true), " weeks.", - " ", App.UI.DOM.passageLink("Add", passage(), () => { App.Reminders.add(entry, V.week + week); })); + /** + * @returns {HTMLDivElement} + */ + function addField() { + jQuery(addDiv).empty(); + + let entry = ""; + let week = 0; + + addDiv.append( + App.UI.DOM.makeTextBox("", v => { entry = v; }), + " in ", App.UI.DOM.makeTextBox(0, v => { week = v; }, true), " weeks.", + " ", App.UI.DOM.link("Add", () => { + add(entry, V.week + week); + fullDisplay(); + jQuery(addDiv).append(addField()); + }) + ); + + return addDiv; + } - return div; -}; + /** + * @returns {HTMLElement} + */ + function fullDisplay() { + jQuery(fullDisplayDiv).empty(); + fullDisplayDiv.append(App.UI.DOM.makeElement("h2", "Reminders")); -/** - * @returns {DocumentFragment} - */ -App.Reminders.fullDisplay = function() { - let fragment = document.createDocumentFragment(); + const listEl = list(); + if (listEl !== null) { + fullDisplayDiv.append(App.UI.DOM.makeElement("p", listEl, "indent")); + } - fragment.append(App.UI.DOM.makeElement("h2", "Reminders")); + fullDisplayDiv.append(App.UI.DOM.makeElement("h3", "Add new")); + fullDisplayDiv.append(App.UI.DOM.makeElement("p", addField())); - let list = App.Reminders.list(); - if (list !== null) { - fragment.append(App.UI.DOM.makeElement("p", list, "indent")); + return fullDisplayDiv; } - fragment.append(App.UI.DOM.makeElement("h3", "Add new")); - fragment.append(App.UI.DOM.makeElement("p", App.Reminders.addField())); - - return fragment; -}; + function dialog() { + if (Dialog.isOpen()) { + Dialog.close(); + } + Dialog.setup("Reminders", "reminders"); + $(Dialog.body()).empty().append(fullDisplay()); + Dialog.open(); + } +})(); diff --git a/src/endWeek/endWeek.js b/src/endWeek/endWeek.js index 3acd838daedead1c9c1176302a877f9abddeb90c..89bc0b634c66679a9743558b906fb4d098db6a14 100644 --- a/src/endWeek/endWeek.js +++ b/src/endWeek/endWeek.js @@ -304,7 +304,11 @@ globalThis.endWeek = (function() { } function confirmEndWeek() { - if (!V.sideBarOptions.confirmWeekEnd || confirm("Are you sure you want to end the week?")) { + const expiredReminders = V.reminders.filter(r => r.week <= V.week); + if ( + (!V.sideBarOptions.confirmWeekEnd || confirm("Are you sure you want to end the week?")) && + (expiredReminders.length === 0 || confirm(`These reminders are due: ${toSentence(Array.from(expiredReminders, r => r.message))}. End the week anyway?`)) + ) { App.UI.EndWeekAnim.start(); setTimeout(doEndWeek, 0); // execute immediately, but after the event loop runs, so the loading screen gets shown } diff --git a/src/gui/storyCaption.js b/src/gui/storyCaption.js index 138447be6be60c49654539dbc4fdd925b13617e1..efaa0d3eb9ab8ec200264a68184ed966d9740ff3 100644 --- a/src/gui/storyCaption.js +++ b/src/gui/storyCaption.js @@ -71,6 +71,11 @@ App.UI.storyCaption = function() { fragment.append(startingGirls()); } + const reminders = App.UI.DOM.appendNewElement("div", fragment, App.UI.DOM.link("Reminders", () => App.Reminders.dialog())); + if (V.reminders.find(r => r.week <= V.week)) { + reminders.append(" ", App.UI.DOM.makeElement("span", "[!]", "noteworthy")); + } + const p = document.createElement("p"); p.append(App.UI.DOM.makeElement("span", "FCE", "bold"), ": ", App.Encyclopedia.Dialog.linkDOM(V.encyclopedia, V.encyclopedia)); diff --git a/src/js/main.js b/src/js/main.js index 0c7e90ce46aa5e67003dc1f28e07418b1dbaa722..3dea83aaadf60e85abf20ddc00ccf5d20a163e13 100644 --- a/src/js/main.js +++ b/src/js/main.js @@ -299,8 +299,6 @@ App.MainView.full = function() { App.UI.DOM.passageLink("Hide", "Main", () => { V.seeDesk = 0; }))); } - fragment.append(App.Reminders.list({maxFuture: 5, link: true})); - if (V.seeFCNN === 1) { const div = document.createElement("div"); div.classList.add("main-fcnn"); diff --git a/src/pregmod/managePersonalAffairs.tw b/src/pregmod/managePersonalAffairs.tw index b3004435d355e7e6301b9fb533dbcda13cf883a7..a8f47409f162b4e86de548ecf804db85f0c61b1f 100644 --- a/src/pregmod/managePersonalAffairs.tw +++ b/src/pregmod/managePersonalAffairs.tw @@ -142,15 +142,6 @@ </p> <</if>> -<span id="reminder"></span> -<<script>> - $(document).one(':passagedisplay', () => { - $('#reminder').append( - App.Reminders.fullDisplay() - ); - }); -<</script>> - <h2>Personal Skills</h2> <p>