From 361551a022b30947d3d773dc60a10fa0395670f8 Mon Sep 17 00:00:00 2001 From: Chneemann Date: Fri, 21 Aug 2026 04:44:09 +0200 Subject: [PATCH] feat(auth): add guest login option with environment variables and distinct loading states --- app/(auth)/login/page.tsx | 95 ++++++++++++++++++++++++++++++--------- 1 file changed, 73 insertions(+), 22 deletions(-) diff --git a/app/(auth)/login/page.tsx b/app/(auth)/login/page.tsx index 633ec55..4263dbc 100644 --- a/app/(auth)/login/page.tsx +++ b/app/(auth)/login/page.tsx @@ -1,5 +1,5 @@ /** - * @file LoginPage.tsx + * @file (auth)/login/page.tsx * @description Client component providing a user login interface with NextAuth credentials authentication. */ @@ -19,28 +19,30 @@ import Link from "next/link"; export default function LoginPage() { const router = useRouter(); const [error, setError] = useState(null); - const [loading, setLoading] = useState(false); + const [loadingType, setLoadingType] = useState< + "credentials" | "guest" | null + >(null); /** - * Handles the submission of the login form, validates credentials via NextAuth, - * and manages loading/error states or redirects upon success. + * Universal sign-in handler for both manual credentials and guest login. * * @async - * @param {React.SubmitEvent} e - The form submission event. + * @param {string} email - The user email. + * @param {string} password - The user password. + * @param {"credentials" | "guest"} type - The login method type for specific loading states. * @returns {Promise} */ - const handleSubmit = async (e: React.SubmitEvent) => { - e.preventDefault(); + const handleSignIn = async ( + email: string, + password: string, + type: "credentials" | "guest", + ) => { setError(null); - setLoading(true); + setLoadingType(type); - const formData = new FormData(e.currentTarget); - const email = formData.get("email") as string; - const password = formData.get("password") as string; const defaultErrorMessage = "An unexpected error has occurred."; try { - // Attempt to sign in using Auth.js credentials provider const res = await signIn("credentials", { email, password, @@ -48,33 +50,63 @@ export default function LoginPage() { }); if (res?.error) { - // Handle specific authentication errors if (res.error === "CredentialsSignin") { setError("Incorrect email address or password."); } else { setError(defaultErrorMessage); } } else { - // Redirect user router.push("/summary"); return; } } catch (err: any) { - // Handle network or connection errors vs unexpected errors if (err?.message?.includes("fetch") || err?.name === "TypeError") { setError("Server error: API endpoint not available"); } else { setError(defaultErrorMessage); } } finally { - setLoading(false); + setLoadingType(null); } }; + /** + * Handles regular form submission. + * + * @async + * @param {React.SubmitEvent} e - The form submission event. + * @returns {Promise} + */ + const handleSubmit = async (e: React.SubmitEvent) => { + e.preventDefault(); + const formData = new FormData(e.currentTarget); + const email = formData.get("email") as string; + const password = formData.get("password") as string; + await handleSignIn(email, password, "credentials"); + }; + + /** + * Handles quick guest login using environment variables. + * + * @async + * @returns {Promise} + */ + const handleGuestLogin = async () => { + const guestEmail = process.env.NEXT_PUBLIC_GUEST_EMAIL; + const guestPassword = process.env.NEXT_PUBLIC_GUEST_PASSWORD; + + if (!guestEmail || !guestPassword) { + setError("Guest login is not configured."); + return; + } + + await handleSignIn(guestEmail, guestPassword, "guest"); + }; + return (
{/* Login Card Container */} -
+
{/* Header Section */}

Flowstate Login

@@ -101,7 +133,6 @@ export default function LoginPage() { name="email" type="email" placeholder="name@example.com" - defaultValue="test@flowstate.io" required className="w-full px-3 py-2 text-sm rounded-lg border border-border bg-background focus:outline-none focus:border-foreground" /> @@ -114,8 +145,7 @@ export default function LoginPage() { @@ -123,13 +153,34 @@ export default function LoginPage() { + {/* Divider */} +
+
+ + or + +
+
+ + {/* Guest Login Button */} + + {/* Registration Link Footer */}
Don't have an account yet?{" "}