Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
638b64b715 | ||
|
|
d61cb4a215 | ||
|
|
272db82c8c |
@@ -5,6 +5,7 @@ import { useRegister } from '../../_hooks/use-register';
|
|||||||
import { ControlledInputField } from '@imphnen-frontend-service/ui/organisms';
|
import { ControlledInputField } from '@imphnen-frontend-service/ui/organisms';
|
||||||
import { UseFormReturn } from 'react-hook-form';
|
import { UseFormReturn } from 'react-hook-form';
|
||||||
import { TRegisterRequest } from '@imphnen-frontend-service/service';
|
import { TRegisterRequest } from '@imphnen-frontend-service/service';
|
||||||
|
import { useEffect } from 'react';
|
||||||
|
|
||||||
interface IModalFormRegisterProps {
|
interface IModalFormRegisterProps {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
@@ -12,7 +13,7 @@ interface IModalFormRegisterProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const ModalFormRegister = ({ isOpen, onClose }: IModalFormRegisterProps) => {
|
const ModalFormRegister = ({ isOpen, onClose }: IModalFormRegisterProps) => {
|
||||||
const { form, onSubmit } = useRegister();
|
const { form, onSubmit, isStepOneValid } = useRegister();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
step: currentStep,
|
step: currentStep,
|
||||||
@@ -25,6 +26,12 @@ const ModalFormRegister = ({ isOpen, onClose }: IModalFormRegisterProps) => {
|
|||||||
minValue: 1,
|
minValue: 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isStepOneValid && currentStep === 2) {
|
||||||
|
prevStep();
|
||||||
|
}
|
||||||
|
}, [isStepOneValid, currentStep, prevStep]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
className="py-[45px] min-w-[400px] lg:min-w-[455px] px-7"
|
className="py-[45px] min-w-[400px] lg:min-w-[455px] px-7"
|
||||||
@@ -46,7 +53,11 @@ const ModalFormRegister = ({ isOpen, onClose }: IModalFormRegisterProps) => {
|
|||||||
<Modal.Content>
|
<Modal.Content>
|
||||||
<form onSubmit={onSubmit} className="space-y-6">
|
<form onSubmit={onSubmit} className="space-y-6">
|
||||||
{currentStep === 1 && (
|
{currentStep === 1 && (
|
||||||
<StepOne form={form} nextStep={nextStep} onClose={onClose} />
|
<StepOne
|
||||||
|
form={form}
|
||||||
|
nextStep={nextStep}
|
||||||
|
isStepOneValid={isStepOneValid}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
{currentStep === 2 && <StepTwo form={form} prevStep={prevStep} />}
|
{currentStep === 2 && <StepTwo form={form} prevStep={prevStep} />}
|
||||||
</form>
|
</form>
|
||||||
@@ -58,10 +69,11 @@ const ModalFormRegister = ({ isOpen, onClose }: IModalFormRegisterProps) => {
|
|||||||
interface IStepOneProps {
|
interface IStepOneProps {
|
||||||
form: UseFormReturn<TRegisterRequest, any, TRegisterRequest>;
|
form: UseFormReturn<TRegisterRequest, any, TRegisterRequest>;
|
||||||
nextStep: () => void;
|
nextStep: () => void;
|
||||||
onClose: () => void;
|
isStepOneValid: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const StepOne = ({ form, nextStep, onClose }: IStepOneProps) => (
|
const StepOne = ({ form, nextStep, isStepOneValid }: IStepOneProps) => {
|
||||||
|
return (
|
||||||
<>
|
<>
|
||||||
<ControlledInputField
|
<ControlledInputField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
@@ -99,11 +111,17 @@ const StepOne = ({ form, nextStep, onClose }: IStepOneProps) => (
|
|||||||
size="lg"
|
size="lg"
|
||||||
className="w-full"
|
className="w-full"
|
||||||
/>
|
/>
|
||||||
<Button size="md" className="w-full" onClick={nextStep}>
|
<Button
|
||||||
|
size="md"
|
||||||
|
className="w-full"
|
||||||
|
onClick={nextStep}
|
||||||
|
disabled={!isStepOneValid}
|
||||||
|
>
|
||||||
Selanjutnya
|
Selanjutnya
|
||||||
</Button>
|
</Button>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
};
|
||||||
|
|
||||||
interface IStepTwoProps {
|
interface IStepTwoProps {
|
||||||
form: UseFormReturn<TRegisterRequest, any, TRegisterRequest>;
|
form: UseFormReturn<TRegisterRequest, any, TRegisterRequest>;
|
||||||
|
|||||||
@@ -1,19 +1,48 @@
|
|||||||
import { useForm } from 'react-hook-form';
|
import { useForm } from 'react-hook-form';
|
||||||
import {
|
import {
|
||||||
authRegisterSchema,
|
authRegisterSchema,
|
||||||
|
stepOneRegisterSchema,
|
||||||
TRegisterRequest,
|
TRegisterRequest,
|
||||||
usePostRegister,
|
usePostRegister,
|
||||||
} from '@imphnen-frontend-service/service';
|
} from '@imphnen-frontend-service/service';
|
||||||
|
import { z } from 'zod';
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
export const useRegister = () => {
|
export const useRegister = () => {
|
||||||
const postRegister = usePostRegister();
|
const postRegister = usePostRegister();
|
||||||
const form = useForm<TRegisterRequest>({
|
const form = useForm<TRegisterRequest>({
|
||||||
resolver: zodResolver(authRegisterSchema),
|
resolver: zodResolver(authRegisterSchema),
|
||||||
mode: 'all',
|
mode: 'all',
|
||||||
|
defaultValues: {
|
||||||
|
fullname: '',
|
||||||
|
email: '',
|
||||||
|
password: '',
|
||||||
|
confirm_password: '',
|
||||||
|
phone_number: '',
|
||||||
|
referral_code: '',
|
||||||
|
referred_by: '',
|
||||||
|
student_type: '',
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const [stepValid, setStepValid] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const subscription = form.watch(() => {
|
||||||
|
const { fullname, email, password, confirm_password } = form.getValues();
|
||||||
|
const valid = stepOneRegisterSchema.safeParse({
|
||||||
|
fullname,
|
||||||
|
email,
|
||||||
|
password,
|
||||||
|
confirm_password,
|
||||||
|
}).success;
|
||||||
|
setStepValid(valid);
|
||||||
|
});
|
||||||
|
return () => subscription.unsubscribe();
|
||||||
|
}, [form]);
|
||||||
|
|
||||||
const onSubmit = form.handleSubmit((data) => {
|
const onSubmit = form.handleSubmit((data) => {
|
||||||
postRegister.mutate(data, {
|
postRegister.mutate(data, {
|
||||||
onSuccess: (data) => toast.success(data.message),
|
onSuccess: (data) => toast.success(data.message),
|
||||||
@@ -24,5 +53,6 @@ export const useRegister = () => {
|
|||||||
return {
|
return {
|
||||||
form,
|
form,
|
||||||
onSubmit,
|
onSubmit,
|
||||||
|
isStepOneValid: stepValid,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export const authLoginSchema = z.object({
|
|||||||
.min(1, 'Password tidak boleh kosong'),
|
.min(1, 'Password tidak boleh kosong'),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const authRegisterSchema = z
|
export const stepOneRegisterSchema = z
|
||||||
.object({
|
.object({
|
||||||
email: z
|
email: z
|
||||||
.string({
|
.string({
|
||||||
@@ -40,6 +40,19 @@ export const authRegisterSchema = z
|
|||||||
.min(1, 'Password tidak boleh kosong')
|
.min(1, 'Password tidak boleh kosong')
|
||||||
.min(8, 'Password harus lebih dari 8 karakter')
|
.min(8, 'Password harus lebih dari 8 karakter')
|
||||||
.max(50, 'Password tidak boleh lebih dari 50 karakter'),
|
.max(50, 'Password tidak boleh lebih dari 50 karakter'),
|
||||||
|
confirm_password: z
|
||||||
|
.string({
|
||||||
|
required_error: 'Konfirmasi password tidak boleh kosong',
|
||||||
|
})
|
||||||
|
.min(1, 'Konfirmasi password tidak boleh kosong')
|
||||||
|
.max(50, 'Konfirmasi password tidak boleh lebih dari 50 karakter'),
|
||||||
|
})
|
||||||
|
.refine((data) => data.password === data.confirm_password, {
|
||||||
|
message: 'Password dan Konfirmasi Password harus sama',
|
||||||
|
path: ['confirm_password'],
|
||||||
|
});
|
||||||
|
|
||||||
|
const stepTwoRegisterSchema = z.object({
|
||||||
phone_number: z
|
phone_number: z
|
||||||
.string({
|
.string({
|
||||||
required_error: 'Nomor telepon tidak boleh kosong',
|
required_error: 'Nomor telepon tidak boleh kosong',
|
||||||
@@ -58,19 +71,8 @@ export const authRegisterSchema = z
|
|||||||
.max(50, 'Kode referral tidak boleh lebih dari 50 karakter')
|
.max(50, 'Kode referral tidak boleh lebih dari 50 karakter')
|
||||||
.optional(),
|
.optional(),
|
||||||
student_type: z.string(),
|
student_type: z.string(),
|
||||||
confirm_password: z
|
});
|
||||||
.string({
|
|
||||||
required_error: 'Konfirmasi password tidak boleh kosong',
|
export const authRegisterSchema = stepOneRegisterSchema.and(
|
||||||
})
|
stepTwoRegisterSchema
|
||||||
.min(1, 'Konfirmasi password tidak boleh kosong')
|
);
|
||||||
.max(50, 'Konfirmasi password tidak boleh lebih dari 50 karakter'),
|
|
||||||
})
|
|
||||||
.superRefine((val, ctx) => {
|
|
||||||
if (val.password !== val.confirm_password) {
|
|
||||||
ctx.addIssue({
|
|
||||||
code: z.ZodIssueCode.custom,
|
|
||||||
path: ['confirm_password'],
|
|
||||||
message: `No duplicates allowed.`,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|||||||
Reference in New Issue
Block a user