This commit is contained in:
Estifo77
2026-07-29 10:07:49 +03:00
parent 53e2497756
commit 5ceb5da3c2
2 changed files with 54 additions and 43 deletions

View File

@@ -1,4 +1,4 @@
import { useState } from 'react';
import { useState } from "react";
import {
Alert,
Anchor,
@@ -12,7 +12,7 @@ import {
Text,
TextInput,
Title,
} from '@mantine/core';
} from "@mantine/core";
import {
IconArrowRight,
IconAt,
@@ -20,42 +20,47 @@ 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';
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';
} 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: 'credit', label: 'Credit' },
{ value: 'logistics', label: 'Logistics' },
{ value: 'registration', label: 'Registration' },
{ value: 'transfer', label: 'Transfer' },
{ value: "cadit", label: "Cadit" },
{ value: "logistics", label: "Logistics" },
{ value: "registration", label: "Registration" },
{ value: "transfer", label: "Transfer" },
];
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(['credit', 'logistics', 'registration', 'transfer'], {
message: 'User type 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.enum(["credit", "logistics", "registration", "transfer"], {
message: "User type is required",
}),
nameEn: z.string().min(1, { message: 'Name (English) is required' }),
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>;
@@ -103,14 +108,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();
@@ -122,13 +127,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,
@@ -157,7 +162,12 @@ 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>
)}
@@ -170,14 +180,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>
@@ -187,14 +197,14 @@ 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>
@@ -217,7 +227,7 @@ export function SignupPage() {
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">
@@ -226,14 +236,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>
@@ -243,7 +253,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}
@@ -269,7 +279,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>

View File

@@ -13,6 +13,7 @@ export interface AuthUser {
hasFinishedRegistration: boolean;
hasFinishedDMSOnboarding: boolean;
isPhoneNumberVerified: boolean;
userType: string;
}
export interface AuthState {