diff --git a/src/actions/contact.ts b/src/actions/contact.ts index 1e5241a..807288a 100644 --- a/src/actions/contact.ts +++ b/src/actions/contact.ts @@ -61,16 +61,20 @@ const sendMsgAction = z.object({ captcha: captcha_input, }); +const resetAction = z.object({ + action: z.literal("reset"), +}); + const formAction = z.discriminatedUnion("action", [ sendOtpAction, sendMsgAction, + resetAction, ]); const submitActionDefinition = { input: formAction, handler: async (input: any, context: ActionAPIContext) => { if (!OTP_SUPER_SECRET_SALT || !ANDROID_SMS_GATEWAY_RECIPIENT_PHONE) { - console.log("Server variables are missing."); throw new ActionError({ code: "INTERNAL_SERVER_ERROR", message: "Server variables are missing.", @@ -83,10 +87,9 @@ const submitActionDefinition = { (await CapServer.validateToken(input.captcha)) ) ) { - console.log("Invalid Captcha Token"); throw new ActionError({ code: "BAD_REQUEST", - message: "Invalid Captcha Token", + message: "Invalid Captcha Token.", }); } @@ -103,7 +106,7 @@ const submitActionDefinition = { }`; const result = await new SmsClient().sendSMS(phone, message); - console.log(JSON.stringify(result)); + if (result.success) { context.session?.set("phone", phone); context.session?.set("name", name); @@ -113,12 +116,9 @@ const submitActionDefinition = { nextAction: "send_msg", }; } else { - console.log( - "Verification code failed to send. Please try again later.", - ); throw new ActionError({ code: "SERVICE_UNAVAILABLE", - message: "Verification code failed to send. Please try again later.", + message: "Verification code failed to send: " + result.message, }); } } else if (input.action === "send_msg") { @@ -128,7 +128,6 @@ const submitActionDefinition = { const msg = await context.session?.get("msg"); if (!name || !otp || !msg || !phone) { - console.log("Missing required fields."); throw new ActionError({ code: "BAD_REQUEST", message: "Missing required fields.", @@ -137,11 +136,15 @@ const submitActionDefinition = { const isVerified = verifyOtp(phone, OTP_SUPER_SECRET_SALT, otp); if (!isVerified) { - console.log("Invalid or expired verification code."); - throw new ActionError({ - code: "BAD_REQUEST", - message: "Invalid or expired verification code.", - }); + return { + nextAction: "send_msg", + error: "Invalid or expired verification code.", + field: "otp", + }; + // throw new ActionError({ + // code: "BAD_REQUEST", + // message: "Invalid or expired verification code.", + // }); } const message = `Web message from ${name} ( ${phone} ):\n\n${msg}`; @@ -162,9 +165,16 @@ const submitActionDefinition = { return { nextAction: "complete", }; + } else if (input.action === "reset") { + context.session?.delete("phone"); + context.session?.delete("name"); + context.session?.delete("msg"); + + return { + nextAction: "send_otp", + }; } - console.log("Message failed to send."); throw new ActionError({ code: "SERVICE_UNAVAILABLE", message: "Message failed to send.", diff --git a/src/pages/contact.astro b/src/pages/contact.astro index fdbbd47..0a0a7f3 100644 --- a/src/pages/contact.astro +++ b/src/pages/contact.astro @@ -4,17 +4,16 @@ import { actions, isInputError } from "astro:actions"; export const prerender = false; const result = Astro.getActionResult(actions.contact.submitForm); -// FIX (might be fixed with below change): if user types in invalid otp code, it returns an error -// and then nextAction is set to "send_otp". It needs to be set -// to "send_msg" if the error is caused by invalid otp code -// -// ALSO: change it maybe so user can always fill out all fields -// in one go, including otp code (have verify number swap with code field when sent) -// text me button should be disabled if otp code is invalid or missing -const nextAction = result?.data?.nextAction || "send_otp"; -const error = isInputError(result?.error) ? result.error.fields : {}; -const formDraft = (await Astro.session?.get("contactFormDraft")) ?? undefined; +const error = isInputError(result?.error) + ? result.error.fields + : result?.data?.error + ? { [result?.data?.field]: [result?.data?.error] } + : {}; + +const nextAction = result?.data?.nextAction ?? "send_otp"; + +const formDraft = await Astro.session?.get("contactFormDraft"); if (formDraft && Object.keys(formDraft).length) { Astro.session?.delete("contactFormDraft"); } @@ -51,7 +50,8 @@ const msgValue = pickValue("msg"); progressIcon ) { cap.addEventListener("solve", function (e) { - statusText.textContent = "You seem human enough!"; + const humanness = Math.round((85 + Math.random() * 14.9) * 10) / 10; + statusText.textContent = `${humanness}% human. Good enough!`; progressIcon.classList.add("hidden"); errorIcon.classList.add("hidden"); initIcon.classList.add("hidden"); @@ -73,7 +73,7 @@ const msgValue = pickValue("msg"); }); } if (captchaInput && "value" in captchaInput) { - const {token} = await cap.solve(); + const { token } = await cap.solve(); captchaInput.value = token; } @@ -88,8 +88,8 @@ const msgValue = pickValue("msg"); "header header" "name phone" "msg msg" - "otp captcha" - "send_otp send_msg"; + "captcha otp" + "lbtn rbtn"; } .hidden { display: none; @@ -124,11 +124,17 @@ const msgValue = pickValue("msg"); height: 39px; padding: 8px 12px; } + button#reset { + grid-area: lbtn; + } button#send_otp { - grid-area: send_otp; + grid-area: lbtn; } button#send_msg { - grid-area: send_msg; + grid-area: rbtn; + } + fieldset { + display: contents; } .spin { animation: spin 4s linear infinite; @@ -154,24 +160,78 @@ const msgValue = pickValue("msg"); {(result?.error && (
{result?.error.message} - Please correct any errors and try again. + Please correct any errors and try again.
)) ||Use the below form to shoot me a quick text!
} - + + - - - - - )) ||Your message has been sent successfully!
}