first commit
This commit is contained in:
163
react/PasswordResetForms.tsx
Normal file
163
react/PasswordResetForms.tsx
Normal file
@@ -0,0 +1,163 @@
|
||||
import type { FormEvent, ReactNode } from "react";
|
||||
import {
|
||||
Alert,
|
||||
AlertDescription,
|
||||
AlertIcon,
|
||||
Button,
|
||||
FormControl,
|
||||
FormLabel,
|
||||
Input,
|
||||
Spinner,
|
||||
Stack,
|
||||
Text
|
||||
} from "@chakra-ui/react";
|
||||
import type { PasswordResetMode, PasswordResetTokenState } from "./types";
|
||||
|
||||
type PasswordResetRequestTexts = {
|
||||
emailLabel: string;
|
||||
submitLabel: string;
|
||||
requestSentMessage: string;
|
||||
};
|
||||
|
||||
type PasswordResetRequestFormProps = {
|
||||
texts: PasswordResetRequestTexts;
|
||||
helperText: ReactNode;
|
||||
loading?: boolean;
|
||||
requestSent?: boolean;
|
||||
onSubmit: (values: { email: string }) => void | Promise<void>;
|
||||
emailPlaceholder?: string;
|
||||
};
|
||||
|
||||
type PasswordResetConfirmTexts = {
|
||||
loadingLabel: string;
|
||||
passwordLabel: string;
|
||||
passwordConfirmLabel: string;
|
||||
invalidLinkLabel: string;
|
||||
resetSubmitLabel: string;
|
||||
createSubmitLabel: string;
|
||||
resetSuccessLabel: string;
|
||||
createSuccessLabel: string;
|
||||
};
|
||||
|
||||
type PasswordResetConfirmFormProps = {
|
||||
texts: PasswordResetConfirmTexts;
|
||||
tokenState: PasswordResetTokenState;
|
||||
loading?: boolean;
|
||||
completedMode?: PasswordResetMode | null;
|
||||
onSubmit: (values: { password: string; passwordConfirm: string }) => void | Promise<void>;
|
||||
};
|
||||
|
||||
export function PasswordResetRequestForm({
|
||||
texts,
|
||||
helperText,
|
||||
loading = false,
|
||||
requestSent = false,
|
||||
onSubmit,
|
||||
emailPlaceholder = "you@example.com"
|
||||
}: PasswordResetRequestFormProps) {
|
||||
function handleSubmit(event: FormEvent<HTMLFormElement>) {
|
||||
event.preventDefault();
|
||||
const form = new FormData(event.currentTarget);
|
||||
void onSubmit({
|
||||
email: String(form.get("email") ?? "")
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<Stack spacing={5}>
|
||||
{requestSent ? (
|
||||
<Alert status="success" borderRadius="md">
|
||||
<AlertIcon />
|
||||
<AlertDescription>{texts.requestSentMessage}</AlertDescription>
|
||||
</Alert>
|
||||
) : null}
|
||||
|
||||
<form onSubmit={handleSubmit}>
|
||||
<Stack spacing={4}>
|
||||
<FormControl isRequired>
|
||||
<FormLabel>{texts.emailLabel}</FormLabel>
|
||||
<Input name="email" type="email" placeholder={emailPlaceholder} />
|
||||
</FormControl>
|
||||
|
||||
<Text fontSize="sm" color="gray.600">
|
||||
{helperText}
|
||||
</Text>
|
||||
|
||||
<Button type="submit" isLoading={loading}>
|
||||
{texts.submitLabel}
|
||||
</Button>
|
||||
</Stack>
|
||||
</form>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
export function PasswordResetConfirmForm({
|
||||
texts,
|
||||
tokenState,
|
||||
loading = false,
|
||||
completedMode = null,
|
||||
onSubmit
|
||||
}: PasswordResetConfirmFormProps) {
|
||||
function handleSubmit(event: FormEvent<HTMLFormElement>) {
|
||||
event.preventDefault();
|
||||
const form = new FormData(event.currentTarget);
|
||||
void onSubmit({
|
||||
password: String(form.get("password") ?? ""),
|
||||
passwordConfirm: String(form.get("passwordConfirm") ?? "")
|
||||
});
|
||||
}
|
||||
|
||||
if (tokenState.status === "loading") {
|
||||
return (
|
||||
<Stack align="center" py={6} spacing={3}>
|
||||
<Spinner />
|
||||
<Text color="gray.600">{texts.loadingLabel}</Text>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
if (tokenState.status === "invalid") {
|
||||
return (
|
||||
<Alert status="error" borderRadius="md">
|
||||
<AlertIcon />
|
||||
<AlertDescription>{tokenState.error || texts.invalidLinkLabel}</AlertDescription>
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
|
||||
if (completedMode !== null) {
|
||||
return (
|
||||
<Alert status="success" borderRadius="md">
|
||||
<AlertIcon />
|
||||
<AlertDescription>{completedMode === "create" ? texts.createSuccessLabel : texts.resetSuccessLabel}</AlertDescription>
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Stack spacing={4}>
|
||||
<Text fontSize="sm" color="gray.600">
|
||||
{tokenState.email}
|
||||
</Text>
|
||||
|
||||
<form onSubmit={handleSubmit}>
|
||||
<Stack spacing={4}>
|
||||
<FormControl isRequired>
|
||||
<FormLabel>{texts.passwordLabel}</FormLabel>
|
||||
<Input name="password" type="password" minLength={8} />
|
||||
</FormControl>
|
||||
|
||||
<FormControl isRequired>
|
||||
<FormLabel>{texts.passwordConfirmLabel}</FormLabel>
|
||||
<Input name="passwordConfirm" type="password" minLength={8} />
|
||||
</FormControl>
|
||||
|
||||
<Button type="submit" isLoading={loading}>
|
||||
{tokenState.mode === "create" ? texts.createSubmitLabel : texts.resetSubmitLabel}
|
||||
</Button>
|
||||
</Stack>
|
||||
</form>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user