mirror of
https://github.com/Tria-plc/emaui.git
synced 2026-08-26 19:12:50 +00:00
139 lines
4.2 KiB
TypeScript
139 lines
4.2 KiB
TypeScript
import { useState } from 'react';
|
|
import { Alert, Button, PasswordInput, Stack, Text, ThemeIcon, Title } from '@mantine/core';
|
|
import { IconArrowRight, IconLock, IconLockOpen } from '@tabler/icons-react';
|
|
import { useForm } from 'react-hook-form';
|
|
import { zodResolver } from '@hookform/resolvers/zod';
|
|
import { z } from 'zod';
|
|
import { useNavigate } from 'react-router-dom';
|
|
import { useApiMutation } from '@ema-platform/api';
|
|
import { notify } from '@ema-platform/ui';
|
|
import { AuthShell } from '../components/AuthShell';
|
|
|
|
const schema = z
|
|
.object({
|
|
newPassword: z.string().min(8, { message: 'Password must be at least 8 characters' }),
|
|
confirmPassword: z.string().min(8, { message: 'Confirm your password' }),
|
|
})
|
|
.refine((data) => data.newPassword === data.confirmPassword, {
|
|
message: 'Passwords do not match',
|
|
path: ['confirmPassword'],
|
|
});
|
|
|
|
type FormValues = z.infer<typeof schema>;
|
|
|
|
export function SetPasswordPage() {
|
|
const navigate = useNavigate();
|
|
const [serverError, setServerError] = useState<string | null>(null);
|
|
const [setPasswordTrigger, { isLoading }] = useApiMutation();
|
|
|
|
const userId = sessionStorage.getItem('fayda_userId');
|
|
const userInfoRaw = sessionStorage.getItem('fayda_userInfo');
|
|
|
|
let userName = 'your account';
|
|
if (userInfoRaw) {
|
|
try {
|
|
const info = JSON.parse(userInfoRaw);
|
|
userName = info.name || 'your account';
|
|
} catch {
|
|
// ignore
|
|
}
|
|
}
|
|
|
|
const {
|
|
register,
|
|
handleSubmit,
|
|
formState: { errors },
|
|
} = useForm<FormValues>({
|
|
resolver: zodResolver(schema),
|
|
});
|
|
|
|
const onSubmit = async (values: FormValues) => {
|
|
if (!userId) {
|
|
notify.error('Session expired. Please sign up again.');
|
|
navigate('/signup', { replace: true });
|
|
return;
|
|
}
|
|
|
|
try {
|
|
await setPasswordTrigger({
|
|
url: '/v1/auth/set-fayda-password',
|
|
method: 'PATCH',
|
|
body: {
|
|
userId,
|
|
newPassword: values.newPassword,
|
|
confirmPassword: values.confirmPassword,
|
|
},
|
|
}).unwrap();
|
|
|
|
sessionStorage.removeItem('fayda_userId');
|
|
sessionStorage.removeItem('fayda_userInfo');
|
|
|
|
notify.success('Password set successfully');
|
|
navigate('/login', { replace: true });
|
|
} catch (err: unknown) {
|
|
const msg =
|
|
(err as { data?: { message?: string } })?.data?.message ??
|
|
(err instanceof Error ? err.message : 'Something went wrong');
|
|
setServerError(msg);
|
|
notify.error(msg);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<AuthShell
|
|
brandTitle="Set your account password."
|
|
brandSubtitle="Choose a strong password to secure your account and access all Portal features."
|
|
>
|
|
<Stack gap="lg">
|
|
<ThemeIcon size={56} radius="md" variant="light" color="emaPrimary">
|
|
<IconLockOpen size={30} />
|
|
</ThemeIcon>
|
|
|
|
<div>
|
|
<Title order={2} fz={30}>
|
|
Set your password
|
|
</Title>
|
|
<Text c="dimmed" mt={6}>
|
|
Welcome, <Text span fw={600}>{userName}</Text>. Your National ID has been verified successfully.
|
|
Choose a password to complete your account setup.
|
|
</Text>
|
|
</div>
|
|
|
|
{serverError && (
|
|
<Alert variant="light" color="red" withCloseButton onClose={() => setServerError(null)}>
|
|
{serverError}
|
|
</Alert>
|
|
)}
|
|
|
|
<form onSubmit={handleSubmit(onSubmit)}>
|
|
<Stack gap="md">
|
|
<PasswordInput
|
|
label="New password"
|
|
placeholder="At least 8 characters"
|
|
leftSection={<IconLock size={18} />}
|
|
error={errors.newPassword?.message}
|
|
{...register('newPassword')}
|
|
/>
|
|
<PasswordInput
|
|
label="Confirm password"
|
|
placeholder="Re-enter password"
|
|
leftSection={<IconLock size={18} />}
|
|
error={errors.confirmPassword?.message}
|
|
{...register('confirmPassword')}
|
|
/>
|
|
|
|
<Button
|
|
type="submit"
|
|
loading={isLoading}
|
|
fullWidth
|
|
size="md"
|
|
rightSection={<IconArrowRight size={18} />}
|
|
>
|
|
Set password & continue
|
|
</Button>
|
|
</Stack>
|
|
</form>
|
|
</Stack>
|
|
</AuthShell>
|
|
);
|
|
} |