init: initial commit

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Giuliano Silvestro
2026-04-30 08:26:35 +10:00
commit 24ed9b34f7
8 changed files with 605 additions and 0 deletions

View File

@@ -0,0 +1,88 @@
"use client";
import { useState, type CSSProperties, type FC, type ReactNode } from "react";
import { AuthCard, ForgotPasswordForm } from "@crema/auth-ui";
import { ArcadiaError, useArcadiaClient } from "@crema/arcadia-client";
export interface PasswordResetRequestFormProps {
/** Where to POST. Defaults to "/api/v1/password-reset/request". */
requestPath?: string;
onSuccess?: (email: string) => void | Promise<void>;
onBack?: () => void;
brand?: ReactNode;
heading?: string;
subhead?: ReactNode;
style?: CSSProperties;
}
export const PasswordResetRequestForm: FC<PasswordResetRequestFormProps> = ({
requestPath = "/api/v1/password-reset/request",
onSuccess,
onBack,
brand,
heading = "Reset your password",
subhead = "Enter the email associated with your account and we'll send you a reset link.",
style,
}) => {
const arcadia = useArcadiaClient();
const [sentTo, setSentTo] = useState<string | null>(null);
const [error, setError] = useState<string | null>(null);
async function handleSubmit(email: string) {
setError(null);
try {
await arcadia.POST(requestPath, { body: { email } });
setSentTo(email);
await onSuccess?.(email);
} catch (err) {
// Most deployments respond 200 even for unknown emails (anti-enumeration).
// We only land here on hard failures (rate limit, validation, server).
if (err instanceof ArcadiaError) setError(err.message);
else setError("Something went wrong. Please try again.");
throw err;
}
}
return (
<AuthCard
logo={brand}
title={heading}
description={subhead}
footer={
onBack ? (
<button
type="button"
data-action="auth-pwreset-back"
onClick={onBack}
className="text-sm text-primary underline underline-offset-2"
>
Back to sign in
</button>
) : undefined
}
>
<div data-action="auth-pwreset-request" style={style}>
{sentTo ? (
<div
role="status"
className="rounded-md border border-success/30 bg-success/10 px-3 py-2 text-sm"
style={{ color: "var(--success, currentColor)" }}
>
If an account exists for <strong>{sentTo}</strong>, we've sent a reset link.
</div>
) : (
<ForgotPasswordForm onSubmit={handleSubmit} onBack={onBack} />
)}
{error ? (
<div
role="alert"
className="mt-3 rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive"
data-action="auth-pwreset-error"
>
{error}
</div>
) : null}
</div>
</AuthCard>
);
};