"use client"; import { useState, type CSSProperties, type FC, type ReactNode } from "react"; import { AuthCard, SignInForm, type SignInValues } from "@crema/auth-ui"; import { ArcadiaError, useArcadiaClient, type ArcadiaAuthTokens, type ArcadiaUser, } from "@crema/arcadia-core-client"; export interface LoginResult { tokens: ArcadiaAuthTokens; user?: ArcadiaUser; /** True if the API responded with a 2FA challenge instead of tokens. */ twoFactorRequired?: boolean; /** Opaque challenge token to pass to the 2FA step (when twoFactorRequired). */ twoFactorChallenge?: string; /** Whether the user asked to be remembered (from the form's checkbox). */ remember?: boolean; } export interface LoginFormProps { /** Where to POST. Defaults to "/api/v1/auth/login". */ loginPath?: string; /** Called on successful auth (or 2FA challenge — check twoFactorRequired). */ onSuccess: (result: LoginResult) => void | Promise; /** "Forgot password?" link click. If omitted, the link is hidden. */ onForgotPassword?: () => void; /** "Don't have an account?" link click. Rendered in the card footer. */ onSignup?: () => void; /** Optional brand row above the form (logo, app name). */ brand?: ReactNode; /** Heading text. Default: "Sign in". */ heading?: string; /** Subhead under the heading. */ subhead?: ReactNode; /** Pre-fill email (e.g. from query string after invitation accept). */ defaultEmail?: string; /** Override styles on the outer card. */ style?: CSSProperties; } export const LoginForm: FC = ({ loginPath = "/api/v1/auth/login", onSuccess, onForgotPassword, onSignup, brand, heading = "Sign in", subhead, defaultEmail, style, }) => { const arcadia = useArcadiaClient(); const [error, setError] = useState(null); async function handleSubmit({ email, password, remember }: SignInValues) { setError(null); try { const res = await arcadia.POST<{ data: ArcadiaAuthTokens & { user?: ArcadiaUser; two_factor_required?: boolean; two_factor_challenge?: string; }; }>(loginPath, { body: { email, password } }); const { user, two_factor_required, two_factor_challenge, ...tokens } = res.data; await onSuccess({ tokens, user, twoFactorRequired: two_factor_required, twoFactorChallenge: two_factor_challenge, remember, }); } catch (err) { // SignInForm catches and clears its own pending state when this throws. // We surface the message via local error state below the form. if (err instanceof ArcadiaError) setError(err.message); else setError("Something went wrong. Please try again."); throw err; } } return ( Don't have an account?{" "} ) : undefined } className="auth-arcadia-login" // style is forwarded via wrapper; AuthCard takes className not style >
{error ? (
{error}
) : null}
); };