138 lines
4.9 KiB
TypeScript
138 lines
4.9 KiB
TypeScript
'use client';
|
|
|
|
import { AuthCard } from '@/components/auth/AuthCard';
|
|
import { AuthFooterLinks } from '@/components/auth/AuthFooterLinks';
|
|
import { AuthForm } from '@/components/auth/AuthForm';
|
|
import { ResetPasswordViewData } from '@/lib/builders/view-data/types/ResetPasswordViewData';
|
|
import { routes } from '@/lib/routing/RouteConfig';
|
|
import { Button } from '@/ui/Button';
|
|
import { Group } from '@/ui/Group';
|
|
import { Icon } from '@/ui/Icon';
|
|
import { Link } from '@/ui/Link';
|
|
import { LoadingSpinner } from '@/ui/LoadingSpinner';
|
|
import { PasswordField } from '@/ui/PasswordField';
|
|
import { Text } from '@/ui/Text';
|
|
import { AlertCircle, ArrowLeft, CheckCircle2, Shield } from 'lucide-react';
|
|
import React from 'react';
|
|
|
|
interface ResetPasswordTemplateProps {
|
|
viewData: ResetPasswordViewData;
|
|
formActions: {
|
|
handleChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
|
handleSubmit: (e: React.FormEvent<HTMLFormElement>) => Promise<void>;
|
|
setShowSuccess: (show: boolean) => void;
|
|
setShowPassword: (show: boolean) => void;
|
|
setShowConfirmPassword: (show: boolean) => void;
|
|
};
|
|
uiState: {
|
|
showPassword: boolean;
|
|
showConfirmPassword: boolean;
|
|
};
|
|
mutationState: {
|
|
isPending: boolean;
|
|
error: string | null;
|
|
};
|
|
}
|
|
|
|
export function ResetPasswordTemplate({
|
|
viewData,
|
|
formActions,
|
|
uiState,
|
|
mutationState,
|
|
}: ResetPasswordTemplateProps) {
|
|
const isSubmitting = mutationState.isPending;
|
|
|
|
return (
|
|
<AuthCard
|
|
title="Reset Password"
|
|
description={viewData.showSuccess ? undefined : "Create a new secure password for your account"}
|
|
>
|
|
{!viewData.showSuccess ? (
|
|
<AuthForm onSubmit={formActions.handleSubmit}>
|
|
<Group direction="column" gap={4} fullWidth>
|
|
<PasswordField
|
|
label="New Password"
|
|
id="newPassword"
|
|
name="newPassword"
|
|
value={viewData.formState.fields.newPassword.value}
|
|
onChange={formActions.handleChange}
|
|
errorMessage={viewData.formState.fields.newPassword.error}
|
|
placeholder="••••••••"
|
|
disabled={isSubmitting}
|
|
autoComplete="new-password"
|
|
showPassword={uiState.showPassword}
|
|
onTogglePassword={() => formActions.setShowPassword(!uiState.showPassword)}
|
|
/>
|
|
|
|
<PasswordField
|
|
label="Confirm Password"
|
|
id="confirmPassword"
|
|
name="confirmPassword"
|
|
value={viewData.formState.fields.confirmPassword.value}
|
|
onChange={formActions.handleChange}
|
|
errorMessage={viewData.formState.fields.confirmPassword.error}
|
|
placeholder="••••••••"
|
|
disabled={isSubmitting}
|
|
autoComplete="new-password"
|
|
showPassword={uiState.showConfirmPassword}
|
|
onTogglePassword={() => formActions.setShowConfirmPassword(!uiState.showConfirmPassword)}
|
|
/>
|
|
</Group>
|
|
|
|
{mutationState.error && (
|
|
<Group direction="row" align="start" gap={3} fullWidth>
|
|
<Icon icon={AlertCircle} size={4.5} color="var(--color-critical)" />
|
|
<Text size="sm" color="text-critical-red">{mutationState.error}</Text>
|
|
</Group>
|
|
)}
|
|
|
|
<Button
|
|
type="submit"
|
|
variant="primary"
|
|
disabled={isSubmitting}
|
|
fullWidth
|
|
icon={isSubmitting ? <LoadingSpinner size={4} /> : <Shield size={16} />}
|
|
>
|
|
{isSubmitting ? 'Resetting...' : 'Reset Password'}
|
|
</Button>
|
|
|
|
<Group justify="center" fullWidth>
|
|
<Link href={routes.auth.login}>
|
|
<Group direction="row" align="center" justify="center" gap={2}>
|
|
<Icon icon={ArrowLeft} size={3.5} color="var(--color-primary)" />
|
|
<Text size="sm" weight="bold" color="text-primary-accent">Back to Login</Text>
|
|
</Group>
|
|
</Link>
|
|
</Group>
|
|
</AuthForm>
|
|
) : (
|
|
<Group direction="column" gap={6} fullWidth>
|
|
<Group direction="row" align="start" gap={3} fullWidth>
|
|
<Icon icon={CheckCircle2} size={5} color="var(--color-success)" />
|
|
<Group direction="column" gap={1}>
|
|
<Text size="sm" color="text-success-green" weight="bold" block>Password Reset</Text>
|
|
<Text size="xs" color="text-gray-400" block>{viewData.successMessage}</Text>
|
|
</Group>
|
|
</Group>
|
|
|
|
<Button
|
|
type="button"
|
|
variant="secondary"
|
|
onClick={() => window.location.href = '/auth/login'}
|
|
fullWidth
|
|
>
|
|
Return to Login
|
|
</Button>
|
|
</Group>
|
|
)}
|
|
|
|
<AuthFooterLinks>
|
|
<Text size="xs" color="text-gray-600">
|
|
Need help?{' '}
|
|
<Link href="/support">Contact support</Link>
|
|
</Text>
|
|
</AuthFooterLinks>
|
|
</AuthCard>
|
|
);
|
|
}
|