summaryrefslogtreecommitdiff
path: root/http/public/scripts/contact
diff options
context:
space:
mode:
Diffstat (limited to 'http/public/scripts/contact')
-rw-r--r--http/public/scripts/contact/actions.js60
-rw-r--r--http/public/scripts/contact/post-error-message.js34
-rw-r--r--http/public/scripts/contact/resend-otp.js31
-rw-r--r--http/public/scripts/contact/reset-resend-button.js32
-rw-r--r--http/public/scripts/contact/selectors.js25
-rw-r--r--http/public/scripts/contact/submit-contact-form.js53
-rw-r--r--http/public/scripts/contact/submit-otp-form.js77
7 files changed, 0 insertions, 312 deletions
diff --git a/http/public/scripts/contact/actions.js b/http/public/scripts/contact/actions.js
deleted file mode 100644
index 5a7e32a..0000000
--- a/http/public/scripts/contact/actions.js
+++ /dev/null
@@ -1,60 +0,0 @@
-export const actions = {
- /**
- * @param {{type: 'email', name: string, email: string}}
- * @returns {Promise<void>}
- */
- sendOtp: async ({ type, name, email }) => {
- const url = "/do/send_otp.php";
- const req = new Request(url, {
- method: "POST",
- body: JSON.stringify({ type, name, email }),
- });
- const res = await fetch(req);
- if (!res.ok) {
- throw new Error(
- `Request to ${url} failed: ${res.status} ${res.statusText} ${await res.text()}`,
- );
- }
- },
-
- /**
- * @param {{guess: string, lenient?: bool, userId: string}}
- * @returns {Promise<string | false>}
- */
- verifyOtp: async ({ guess, lenient, userId }) => {
- const url = "/do/verify_otp.php";
- const req = new Request(url, {
- method: "POST",
- body: JSON.stringify({ guess, lenient, userId }),
- });
- const res = await fetch(req);
-
- if (res.status === 400) {
- return false;
- } else if (!res.ok) {
- throw new Error(
- `Request to ${url} failed: ${res.status} ${res.statusText} ${await res.text()}`,
- );
- }
-
- return res.text();
- },
-
- /**
- * @param {{email: string, message: string, name: string, userId: string, token: string}}
- * @returns {Promise<void>}
- */
- sendEmail: async ({ email, message, name, userId, token }) => {
- const url = "/do/send_email.php";
- const req = new Request(url, {
- method: "POST",
- body: JSON.stringify({ email, message, name, userId, token }),
- });
- const res = await fetch(req);
- if (!res.ok) {
- throw new Error(
- `Request to ${url} failed: ${res.status} ${res.statusText} ${await res.text()}`,
- );
- }
- },
-};
diff --git a/http/public/scripts/contact/post-error-message.js b/http/public/scripts/contact/post-error-message.js
deleted file mode 100644
index 121cbb6..0000000
--- a/http/public/scripts/contact/post-error-message.js
+++ /dev/null
@@ -1,34 +0,0 @@
-/** @typedef {import("./selectors.js").Selectors} Selectors */
-
-/**
- * @param {{contactForm: Selectors}} contactForm
- * @param {string} errorMsg
- */
-export function postErrorMessageOnContactForm({ contactForm }, errorMsg) {
- const errorElem = contactForm.errorElem();
- if (errorElem) {
- errorElem.textContent = errorMsg;
- errorElem.removeAttribute("hidden");
- } else {
- alert(errorMsg);
- }
-}
-
-/**
- * @param {{otpDialog: Selectors}} otpDialog
- * @param {string} errorMsg
- */
-export function postErrorMessageOnOtpForm({ otpDialog }, errorMsg) {
- const errorElem = otpDialog.errorElem();
- if (errorElem) {
- errorElem.textContent = errorMsg;
- errorElem.removeAttribute("hidden");
- } else {
- alert(errorMsg);
- }
- /** @type NodeListOf<HTMLInputElement> */
- const inputs = otpDialog.allOtpInputs();
- for (const input of inputs) {
- input.value = "";
- }
-}
diff --git a/http/public/scripts/contact/resend-otp.js b/http/public/scripts/contact/resend-otp.js
deleted file mode 100644
index e083d95..0000000
--- a/http/public/scripts/contact/resend-otp.js
+++ /dev/null
@@ -1,31 +0,0 @@
-/** @typedef {import("./selectors.js").Selectors} Selectors */
-
-import { actions } from "./actions.js";
-import { resetResendButton } from "./reset-resend-button.js";
-import { postErrorMessageOnOtpForm } from "./post-error-message.js";
-
-/** @typedef {{ resendButtonInterval: NodeJS.Timeout | undefined }} Result */
-
-const fallbackErrorMsg =
- "No can do. I'm afraid joeac.net is a bit broken right now - sorry about that.";
-
-/**
- * @param {Selectors} selectors
- * @param {NodeJS.Timeout | undefined} resetButtonInterval
- * @returns {Promise<Result>}
- */
-export async function resendOtp(selectors, resetButtonInterval) {
- const result = resetResendButton(selectors, resetButtonInterval);
- const name = selectors.contactForm.nameElem()?.value;
- const email = selectors.contactForm.emailElem().value;
-
- try {
- await actions.sendOtp({ type: "email", name, email });
- } catch (sendOtpError) {
- const errorMsg = sendOtpError?.toString() ?? fallbackErrorMsg;
- postErrorMessageOnOtpForm(selectors, errorMsg);
- throw sendOtpError;
- }
-
- return result;
-}
diff --git a/http/public/scripts/contact/reset-resend-button.js b/http/public/scripts/contact/reset-resend-button.js
deleted file mode 100644
index 47bc9ac..0000000
--- a/http/public/scripts/contact/reset-resend-button.js
+++ /dev/null
@@ -1,32 +0,0 @@
-/** @typedef {import("./selectors.js").Selectors} Selectors */
-
-/** @typedef {{ resendButtonInterval: NodeJS.Timeout | undefined }} Result */
-
-/**
- * @param {Selectors} selectors
- * @param {NodeJS.Timeout | undefined} resetButtonInterval
- * @returns {Result}
- */
-export function resetResendButton({ otpDialog }, resendButtonInterval) {
- clearInterval(resendButtonInterval);
-
- const resendButton = otpDialog.resendButton();
- if (resendButton) {
- resendButton.setAttribute("data-countdown", "60");
- resendButton.setAttribute("disabled", "");
-
- resendButtonInterval = setInterval(() => {
- const countdown = +(resendButton.getAttribute("data-countdown") ?? 1) - 1;
- resendButton.setAttribute("data-countdown", countdown.toString());
- resendButton.textContent = `Resend (${countdown}s)`;
- }, 1000);
-
- setTimeout(() => {
- clearInterval(resendButtonInterval);
- resendButton.textContent = "Resend";
- resendButton.removeAttribute("disabled");
- }, 1000 * 60);
- }
-
- return { resendButtonInterval };
-}
diff --git a/http/public/scripts/contact/selectors.js b/http/public/scripts/contact/selectors.js
deleted file mode 100644
index 7676414..0000000
--- a/http/public/scripts/contact/selectors.js
+++ /dev/null
@@ -1,25 +0,0 @@
-/**
- * @typedef {Object} Selectors
- * @property {Object} contactForm
- * @property {() => HTMLInputElement} contactForm.emailElem
- * @property {() => Element | null} contactForm.errorElem
- * @property {() => HTMLInputElement} contactForm.nameElem
- * @property {() => HTMLTextAreaElement} contactForm.messageElem
- * @property {() => HTMLFormElement | null} contactForm.self
- * @property {() => HTMLInputElement | null} contactForm.submitButton
- * @property {Object} otpDialog
- * @property {() => NodeListOf<HTMLInputElement>} otpDialog.allOtpInputs
- * @property {() => Element | null} otpDialog.errorElem
- * @property {() => HTMLInputElement | null} otpDialog.firstOtpInput
- * @property {() => HTMLFormElement | null} otpDialog.otpForm
- * @property {() => Element | null} otpDialog.otpRecipient
- * @property {() => Element | null} otpDialog.otpValidUntil
- * @property {() => HTMLButtonElement | null} otpDialog.resendButton
- * @property {() => HTMLDialogElement} otpDialog.self
- * @property {() => HTMLInputElement | null} otpDialog.submitButton
- * @property {Object} successSection
- * @property {() => Element | null} successSection.email
- * @property {() => Element | null} successSection.message
- * @property {() => Element | null} successSection.name
- * @property {() => Element | null} successSection.self
- */
diff --git a/http/public/scripts/contact/submit-contact-form.js b/http/public/scripts/contact/submit-contact-form.js
deleted file mode 100644
index a90f420..0000000
--- a/http/public/scripts/contact/submit-contact-form.js
+++ /dev/null
@@ -1,53 +0,0 @@
-import { actions } from "./actions.js";
-import { postErrorMessageOnContactForm } from "./post-error-message.js";
-import { resetResendButton } from "./reset-resend-button.js";
-
-/** @typedef {import("./selectors.js").Selectors} Selectors */
-
-const fallbackErrorMsg =
- "No can do. I'm afraid joeac.net is a bit broken right now - sorry about that.";
-
-/**
- * @param {Selectors} selectors
- * @param {NodeJS.Timeout | undefined} resetButtonInterval
- * @returns {Promise<Result>}
- */
-export async function submitContactForm(selectors, resendButtonInterval) {
- const { contactForm, otpDialog } = selectors;
-
- const name = contactForm.nameElem()?.value;
- const email = contactForm.emailElem().value;
-
- contactForm.submitButton()?.setAttribute("disabled", "");
- try {
- await actions.sendOtp({ type: "email", name, email });
- } catch (sendOtpError) {
- const errorMsg = sendOtpError?.toString() ?? fallbackErrorMsg;
- postErrorMessageOnContactForm(selectors, errorMsg);
- throw sendOtpError;
- }
-
- const otpRecipient = otpDialog.otpRecipient();
- email && otpRecipient && (otpRecipient.textContent = `<${email}>`);
- const otpValidUntil = otpDialog.otpValidUntil();
- const validUntil = new Date(Date.now() + 1000 * 60 * 5);
- otpValidUntil &&
- (otpValidUntil.textContent = `until ${validUntil.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })}`);
-
- const dialog = otpDialog.self();
- dialog.showModal();
- contactForm.submitButton()?.removeAttribute("disabled");
- dialog.addEventListener("click", function (event) {
- const rect = dialog.getBoundingClientRect();
- const isInDialog =
- rect.top <= event.clientY &&
- event.clientY <= rect.top + rect.height &&
- rect.left <= event.clientX &&
- event.clientX <= rect.left + rect.width;
- if (!isInDialog) {
- dialog.close();
- }
- });
-
- return resetResendButton(selectors, resendButtonInterval);
-}
diff --git a/http/public/scripts/contact/submit-otp-form.js b/http/public/scripts/contact/submit-otp-form.js
deleted file mode 100644
index 8c09314..0000000
--- a/http/public/scripts/contact/submit-otp-form.js
+++ /dev/null
@@ -1,77 +0,0 @@
-import { actions } from "./actions.js";
-import { postErrorMessageOnOtpForm } from "./post-error-message.js";
-
-/** @typedef {import("./selectors.js").Selectors} Selectors */
-
-const fallbackErrorMsg =
- "No can do. I'm afraid joeac.net is a bit broken right now - sorry about that.";
-
-/**
- * @param {Selectors} selectors
- */
-export async function submitOtpForm(selectors) {
- const { contactForm, otpDialog, successSection } = selectors;
- const otpForm = otpDialog.otpForm();
- otpDialog.submitButton()?.setAttribute("disabled", "");
-
- const otpFormData = new FormData(otpForm ?? undefined);
- const guess = [
- otpFormData.get("1"),
- otpFormData.get("2"),
- otpFormData.get("3"),
- otpFormData.get("4"),
- otpFormData.get("5"),
- otpFormData.get("6"),
- ].join("");
-
- const name = contactForm.nameElem()?.value;
- const email = contactForm.emailElem().value;
- const message = contactForm.messageElem()?.value;
-
- let verifyResult;
- try {
- verifyResult = await actions.verifyOtp({ guess, userId: email });
- } catch (verifyError) {
- otpDialog.submitButton()?.removeAttribute("disabled");
- postErrorMessageOnOtpForm(
- selectors,
- verifyError?.toString() ?? fallbackErrorMsg,
- );
- return;
- }
-
- if (verifyResult === false) {
- otpDialog.submitButton()?.removeAttribute("disabled");
- postErrorMessageOnOtpForm(selectors, "Incorrect OTP. Check your email?");
- otpDialog.firstOtpInput()?.focus();
- return;
- }
- const sendmailToken = verifyResult;
-
- try {
- await actions.sendEmail({
- email,
- message: message,
- name: name,
- userId: email,
- token: sendmailToken,
- });
- } catch (sendEmailError) {
- const errorMsg = sendEmailError?.toString() ?? fallbackErrorMsg;
- postErrorMessageOnOtpForm(selectors, errorMsg);
- otpDialog.submitButton()?.removeAttribute("disabled");
- return;
- }
-
- const sentName = successSection.name();
- const sentEmail = successSection.email();
- const sentMessage = successSection.message();
- sentName && (sentName.textContent = name ?? "???");
- sentEmail && (sentEmail.textContent = email ?? "???");
- sentMessage && (sentMessage.textContent = message ?? "???");
-
- contactForm.self()?.remove();
- successSection.self()?.removeAttribute("hidden");
- otpDialog.submitButton()?.removeAttribute("disabled");
- otpDialog.self().close();
-}