This commit is contained in:
estifanos
2026-07-29 07:55:14 +00:00
parent 6ca48cbb9a
commit 09d688b251

View File

@@ -1,4 +1,4 @@
import { useState } from "react";
import { useState } from 'react';
import {
Alert,
Anchor,
@@ -6,13 +6,12 @@ import {
Checkbox,
Group,
PasswordInput,
Select,
SimpleGrid,
Stack,
Text,
TextInput,
Title,
} from "@mantine/core";
} from '@mantine/core';
import {
IconArrowRight,
IconAt,
@@ -20,47 +19,33 @@ import {
IconLock,
IconMail,
IconUser,
} from "@tabler/icons-react";
import { Controller, useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import { useNavigate, Link } from "react-router-dom";
import { useDispatch } from "react-redux";
import { useApiMutation } from "@ema-platform/api";
// eslint-disable-next-line @nx/enforce-module-boundaries
import { useErrorHandler } from "@ema-platform/ui";
import { AuthShell } from "../components/AuthShell";
import { loginSuccess, setUser } from "../store/auth.slice";
import type { AuthUser } from "../types/auth.types";
import { useAuthConfig } from "../AuthConfig";
const USER_TYPE_OPTIONS = [
{ value: "cadet", label: "cadet" },
{ value: "logistics", label: "Logistics" },
{ value: "registration", label: "Registration" },
{ value: "transfer", label: "Transfer" },
];
} from '@tabler/icons-react';
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
import { useNavigate, Link } from 'react-router-dom';
import { useDispatch } from 'react-redux';
import { useApiMutation } from '@ema-platform/api';
import { useErrorHandler } from '@ema-platform/ui';
import { AuthShell } from '../components/AuthShell';
import { loginSuccess, setUser } from '../store/auth.slice';
import type { AuthUser } from '../types/auth.types';
import { useAuthConfig } from '../AuthConfig';
const schema = z
.object({
email: z.string().email(),
username: z
.string()
.min(3, { message: "Username must be at least 3 characters" }),
phoneNumber: z.string().min(1, { message: "Phone number is required" }),
userType: z.enum(["cadet", "logistics", "registration", "transfer"], {
message: "User type is required",
}),
nameEn: z.string().min(1, { message: "Name (English) is required" }),
username: z.string().min(3, { message: 'Username must be at least 3 characters' }),
phoneNumber: z.string().min(1, { message: 'Phone number is required' }),
userType: z.literal('individual'),
nameEn: z.string().min(1, { message: 'Name (English) is required' }),
nameAm: z.string().optional(),
password: z
.string()
.min(8, { message: "Password must be at least 8 characters" }),
confirmPassword: z.string().min(8, { message: "Confirm your password" }),
password: z.string().min(8, { message: 'Password must be at least 8 characters' }),
confirmPassword: z.string().min(8, { message: 'Confirm your password' }),
})
.refine((data) => data.password === data.confirmPassword, {
message: "Passwords do not match",
path: ["confirmPassword"],
message: 'Passwords do not match',
path: ['confirmPassword'],
});
type FormValues = z.infer<typeof schema>;
@@ -95,10 +80,10 @@ export function SignupPage() {
const {
register,
handleSubmit,
control,
formState: { errors },
} = useForm<FormValues>({
resolver: zodResolver(schema),
defaultValues: { userType: 'individual' },
});
const onSubmit = async (values: FormValues) => {
@@ -108,14 +93,14 @@ export function SignupPage() {
username: values.username,
phoneNumber: values.phoneNumber,
userType: values.userType,
name: { en: values.nameEn, am: values.nameAm ?? "" },
name: { en: values.nameEn, am: values.nameAm ?? '' },
password: values.password,
confirmPassword: values.confirmPassword,
};
const data = await signupTrigger({
url: "/auth/signup-with-pwd",
method: "POST",
url: '/auth/signup-with-pwd',
method: 'POST',
body: payload,
}).unwrap();
@@ -127,13 +112,13 @@ export function SignupPage() {
}),
);
const me = await meTrigger({ url: "/auth/me", method: "GET" }).unwrap();
const me = await meTrigger({ url: '/auth/me', method: 'GET' }).unwrap();
dispatch(setUser(me));
if (data.isPhoneNumberVerified) {
navigate("/profile-setup");
navigate('/profile-setup');
} else {
navigate("/otp-verify", {
navigate('/otp-verify', {
state: {
email: values.email,
phoneNumber: values.phoneNumber,
@@ -162,12 +147,7 @@ export function SignupPage() {
</div>
{serverError && (
<Alert
variant="light"
color="red"
withCloseButton
onClose={() => setServerError(null)}
>
<Alert variant="light" color="red" withCloseButton onClose={() => setServerError(null)}>
{serverError}
</Alert>
)}
@@ -180,14 +160,14 @@ export function SignupPage() {
placeholder="Abebe Bekele"
leftSection={<IconUser size={18} />}
error={errors.nameEn?.message}
{...register("nameEn")}
{...register('nameEn')}
/>
<TextInput
label="Name (Amharic)"
placeholder="ስም"
leftSection={<IconUser size={18} />}
error={errors.nameAm?.message}
{...register("nameAm")}
{...register('nameAm')}
/>
</SimpleGrid>
@@ -197,37 +177,23 @@ export function SignupPage() {
placeholder="you@example.com"
leftSection={<IconMail size={18} />}
error={errors.email?.message}
{...register("email")}
{...register('email')}
/>
<TextInput
label="Username"
placeholder="Choose a username"
leftSection={<IconAt size={18} />}
error={errors.username?.message}
{...register("username")}
{...register('username')}
/>
</SimpleGrid>
<Controller
control={control}
name="userType"
render={({ field }) => (
<Select
label="User type"
placeholder="Select user type"
data={USER_TYPE_OPTIONS}
error={errors.userType?.message}
{...field}
/>
)}
/>
<TextInput
label="Phone number"
placeholder="+251 911 234 567"
leftSection={<IconDeviceMobile size={18} />}
error={errors.phoneNumber?.message}
{...register("phoneNumber")}
{...register('phoneNumber')}
/>
<SimpleGrid cols={{ base: 1, xs: 2 }} spacing="md">
@@ -236,14 +202,14 @@ export function SignupPage() {
placeholder="At least 8 characters"
leftSection={<IconLock size={18} />}
error={errors.password?.message}
{...register("password")}
{...register('password')}
/>
<PasswordInput
label="Confirm password"
placeholder="Re-enter password"
leftSection={<IconLock size={18} />}
error={errors.confirmPassword?.message}
{...register("confirmPassword")}
{...register('confirmPassword')}
/>
</SimpleGrid>
@@ -253,7 +219,7 @@ export function SignupPage() {
onChange={(e) => setAgreed(e.currentTarget.checked)}
label={
<Text size="sm">
I agree to the{" "}
I agree to the{' '}
<Anchor
size="sm"
fw={600}
@@ -279,7 +245,7 @@ export function SignupPage() {
</form>
<Text ta="center" size="sm" c="dimmed">
Already have an account?{" "}
Already have an account?{' '}
<Anchor component={Link} to="/login" fw={700}>
Sign in
</Anchor>