diff options
author | Miodec <[email protected]> | 2024-08-05 14:28:31 +0200 |
---|---|---|
committer | Miodec <[email protected]> | 2024-08-05 14:28:31 +0200 |
commit | 7306cf8a9fc74a942385b0e4ad6f92a6c77ef889 (patch) | |
tree | bbe26f8a4a13f1789c2d6ab8f39941a2656fcd8d | |
parent | ddebf57454b5bfe1270d0af2c3a0c20c39b64487 (diff) | |
download | monkeytype-7306cf8a9fc74a942385b0e4ad6f92a6c77ef889.tar.gz monkeytype-7306cf8a9fc74a942385b0e4ad6f92a6c77ef889.zip |
feat: last signed out result modal
the website will now show the last signed out result
and ask the user if they want to save or discard it
(instead of always saving)
-rw-r--r-- | frontend/src/html/popups.html | 38 | ||||
-rw-r--r-- | frontend/src/styles/popups.scss | 39 | ||||
-rw-r--r-- | frontend/src/ts/controllers/account-controller.ts | 17 | ||||
-rw-r--r-- | frontend/src/ts/modals/last-signed-out-result.ts | 147 |
4 files changed, 227 insertions, 14 deletions
diff --git a/frontend/src/html/popups.html b/frontend/src/html/popups.html index 0622dffb8..e5dabb7a7 100644 --- a/frontend/src/html/popups.html +++ b/frontend/src/html/popups.html @@ -4,6 +4,44 @@ </div> </dialog> +<dialog id="lastSignedOutResult" class="modalWrapper hidden"> + <div class="modal"> + <div class="title">Last signed out result</div> + <div class="question">Would you like to save it?</div> + <div class="divider"></div> + <div class="result"> + <div class="group wpm"> + <div class="sub">wpm</div> + <div class="val">-</div> + </div> + <div class="group acc"> + <div class="sub">accuracy</div> + <div class="val">-</div> + </div> + <div class="group raw"> + <div class="sub">raw</div> + <div class="val">-</div> + </div> + <div class="group con"> + <div class="sub">consistency</div> + <div class="val">-</div> + </div> + <div class="group chardata"> + <div class="sub">characters</div> + <div class="val">-</div> + </div> + <div class="group testType"> + <div class="sub">test type</div> + <div class="val">-</div> + </div> + </div> + <div class="buttons"> + <button class="save">save</button> + <button class="discard">discard</button> + </div> + </div> +</dialog> + <dialog id="devOptionsModal" class="modalWrapper hidden"> <div class="modal"> <div class="title">Dev options</div> diff --git a/frontend/src/styles/popups.scss b/frontend/src/styles/popups.scss index 734d15b7f..1c9d4848f 100644 --- a/frontend/src/styles/popups.scss +++ b/frontend/src/styles/popups.scss @@ -635,6 +635,45 @@ body.darkMode { } } +#lastSignedOutResult { + .modal { + max-width: 600px; + + .buttons { + display: flex; + flex-direction: row-reverse; + gap: 0.5rem; + button { + flex-grow: 1; + } + } + .result { + display: grid; + gap: 0.5rem; + grid-template-columns: 1fr 1fr; + } + .divider { + background: var(--sub-alt-color); + width: 100%; + height: 0.25rem; + border-radius: var(--roundness); + } + .group { + .sub { + font-size: 0.75em; + color: var(--sub-color); + } + &.testType { + grid-column: 1; + } + &.wpm, + &.acc { + font-size: 2em; + } + } + } +} + #devOptionsModal { .modal { max-width: 400px; diff --git a/frontend/src/ts/controllers/account-controller.ts b/frontend/src/ts/controllers/account-controller.ts index 44c3c2326..89c6794d0 100644 --- a/frontend/src/ts/controllers/account-controller.ts +++ b/frontend/src/ts/controllers/account-controller.ts @@ -15,6 +15,7 @@ import * as LoginPage from "../pages/login"; import * as ResultFilters from "../elements/account/result-filters"; import * as TagController from "./tag-controller"; import * as RegisterCaptchaModal from "../modals/register-captcha"; +import * as LastSignedOutResultModal from "../modals/last-signed-out-result"; import * as URLHandler from "../utils/url-handler"; import * as Account from "../pages/account"; import * as Alerts from "../elements/alerts"; @@ -45,8 +46,6 @@ import * as ConnectionState from "../states/connection"; import { navigate } from "./route-controller"; import { getHtmlByUserFlags } from "./user-flag-controller"; -let signedOutThisSession = false; - export const gmailProvider = new GoogleAuthProvider(); export const githubProvider = new GithubAuthProvider(); @@ -209,18 +208,9 @@ export async function loadUser(user: UserType): Promise<void> { // showFavouriteThemesAtTheTop(); - if (TestLogic.notSignedInLastResult !== null && !signedOutThisSession) { + if (TestLogic.notSignedInLastResult !== null) { TestLogic.setNotSignedInUid(user.uid); - - const response = await Ape.results.save(TestLogic.notSignedInLastResult); - - if (response.status !== 200) { - Notifications.add("Failed to save last result: " + response.message, -1); - return; - } - - TestLogic.clearNotSignedInResult(); - Notifications.add("Last test result saved", 1); + LastSignedOutResultModal.show(); } } @@ -647,7 +637,6 @@ $("header .signInOut").on("click", () => { } if (isAuthenticated()) { signOut(); - signedOutThisSession = true; } else { navigate("/login"); } diff --git a/frontend/src/ts/modals/last-signed-out-result.ts b/frontend/src/ts/modals/last-signed-out-result.ts new file mode 100644 index 000000000..fe399323e --- /dev/null +++ b/frontend/src/ts/modals/last-signed-out-result.ts @@ -0,0 +1,147 @@ +import AnimatedModal from "../utils/animated-modal"; +import Ape from "../ape"; +import * as TestLogic from "../test/test-logic"; +import * as Notifications from "../elements/notifications"; +import { CompletedEvent } from "@monkeytype/shared-types"; + +function reset(): void { + (modal.getModal().querySelector(".result") as HTMLElement).innerHTML = ` + <div class="group wpm"> + <div class="sub">wpm</div> + <div class="val">-</div> + </div> + <div class="group acc"> + <div class="sub">accuracy</div> + <div class="val">-</div> + </div> + <div class="group raw"> + <div class="sub">raw</div> + <div class="val">-</div> + </div> + <div class="group con"> + <div class="sub">consistency</div> + <div class="val">-</div> + </div> + <div class="group chardata"> + <div class="sub">characters</div> + <div class="val">-</div> + </div> + <div class="group testType"> + <div class="sub">test type</div> + <div class="val">-</div> + </div>`; +} + +function fillData(): void { + //safe because we check if it exists before showing the modal + const r = TestLogic.notSignedInLastResult as CompletedEvent; + + // const r: CompletedEvent = { + // wpm: 100, + // acc: 100, + // rawWpm: 100, + // consistency: 100, + // mode: "time", + // mode2: "60", + // numbers: true, + // punctuation: true, + // difficulty: "master", + // language: "english", + // blindMode: true, + // lazyMode: true, + // funbox: "read_ahead", + // tags: ["asdf", "sdfsdf"], + // charStats: [10, 10, 10, 10], + // }; + + fillGroup("wpm", r.wpm); + fillGroup("acc", r.acc + "%"); + fillGroup("raw", r.rawWpm); + fillGroup("con", r.consistency + "%"); + fillGroup("chardata", r.charStats.join("/")); + + let tt = r.mode + " " + r.mode2; + + tt += "<br>" + r.language; + + if (r.numbers) tt += "<br>numbers"; + if (r.punctuation) tt += "<br>punctuation"; + if (r.blindMode) tt += "<br>blind"; + if (r.lazyMode) tt += "<br>lazy"; + if (r.funbox !== "none") { + tt += "<br>" + r.funbox.replace(/_/g, " ").replace(/#/g, ", "); + } + if (r.difficulty !== "normal") tt += "<br>" + r.difficulty; + if (r.tags.length > 0) tt += "<br>" + r.tags.length + " tags"; + + fillGroup("testType", tt, true); +} + +function fillGroup( + groupClass: string, + text: string | number, + html = false +): void { + if (html) { + $(modal.getModal()).find(`.group.${groupClass} .val`).html(`${text}`); + } else { + $(modal.getModal()).find(`.group.${groupClass} .val`).text(text); + } +} + +export function show(): void { + if (!TestLogic.notSignedInLastResult) { + Notifications.add( + "Failed to show last signed out result modal: no last result", + -1 + ); + return; + } + reset(); + void modal.show({ + beforeAnimation: async (): Promise<void> => { + fillData(); + }, + }); +} + +function hide(): void { + void modal.hide(); +} + +async function saveLastResult(): Promise<void> { + //safe because we check if it exists before showing the modal + const response = await Ape.results.save( + TestLogic.notSignedInLastResult as CompletedEvent + ); + if (response.status !== 200) { + Notifications.add("Failed to save last result: " + response.message, -1); + return; + } + + TestLogic.clearNotSignedInResult(); + Notifications.add( + `Last test result saved ${response.data?.isPb ? `(new pb!)` : ""}`, + 1 + ); +} + +const modal = new AnimatedModal({ + dialogId: "lastSignedOutResult", + setup: async (modalEl): Promise<void> => { + modalEl + .querySelector("button.save") + ?.addEventListener("click", async (e) => { + void saveLastResult(); + hide(); + }); + modalEl.querySelector("button.discard")?.addEventListener("click", (e) => { + TestLogic.clearNotSignedInResult(); + Notifications.add("Last test result discarded", 0); + hide(); + }); + }, + customWrapperClickHandler: (): void => { + //do nothing + }, +}); |