diff options
| author | IT Fixcomart <it@fixcomart.co.id> | 2024-09-11 03:14:22 +0000 |
|---|---|---|
| committer | IT Fixcomart <it@fixcomart.co.id> | 2024-09-11 03:14:22 +0000 |
| commit | 7f2c4404adcde5fbaea32e895542d2c313bd507b (patch) | |
| tree | 27299ccf0a0babef8bfbb72db20e274797ba76ec /src-migrate/modules/register | |
| parent | 34f33b1cba1e4fbb6faacc151a3b59a1ba221d60 (diff) | |
| parent | 3dc26efc067799c1cf5492f412538c906ecfe5b1 (diff) | |
Merged in Feature/new-register (pull request #304)
Feature/new register
Diffstat (limited to 'src-migrate/modules/register')
| -rw-r--r-- | src-migrate/modules/register/components/Form.tsx | 152 | ||||
| -rw-r--r-- | src-migrate/modules/register/components/FormBisnis.tsx | 776 | ||||
| -rw-r--r-- | src-migrate/modules/register/components/RegistrasiBisnis.tsx | 190 | ||||
| -rw-r--r-- | src-migrate/modules/register/components/RegistrasiIndividu.tsx | 31 | ||||
| -rw-r--r-- | src-migrate/modules/register/index.tsx | 170 |
5 files changed, 764 insertions, 555 deletions
diff --git a/src-migrate/modules/register/components/Form.tsx b/src-migrate/modules/register/components/Form.tsx index 29c21f62..118d9d69 100644 --- a/src-migrate/modules/register/components/Form.tsx +++ b/src-migrate/modules/register/components/Form.tsx @@ -1,90 +1,98 @@ -import { ChangeEvent, useMemo } from "react"; -import { useMutation } from "react-query"; -import { useRegisterStore } from "../stores/useRegisterStore"; -import { RegisterProps } from "~/types/auth"; -import { registerUser } from "~/services/auth"; -import TermCondition from "./TermCondition"; -import FormCaptcha from "./FormCaptcha"; -import { useRouter } from "next/router"; -import { UseToastOptions, useToast } from "@chakra-ui/react"; -import Link from "next/link"; +import { ChangeEvent, useMemo } from 'react'; +import { useMutation } from 'react-query'; +import { useRegisterStore } from '../stores/useRegisterStore'; +import { RegisterProps } from '~/types/auth'; +import { registerUser } from '~/services/auth'; +import TermCondition from './TermCondition'; +import FormCaptcha from './FormCaptcha'; +import { useRouter } from 'next/router'; +import { UseToastOptions, useToast } from '@chakra-ui/react'; +import Link from 'next/link'; interface FormProps { type: string; required: boolean; isBisnisRegist: boolean; + chekValid: boolean; } -const Form: React.FC<FormProps> = ({ type, required, isBisnisRegist=false }) => { - const { - form, - isCheckedTNC, - isValidCaptcha, - errors, - updateForm, - validate, - } = useRegisterStore() +const Form: React.FC<FormProps> = ({ + type, + required, + isBisnisRegist = false, + chekValid = false, +}) => { + const { form, isCheckedTNC, isValidCaptcha, errors, updateForm, validate } = + useRegisterStore(); - const isFormValid = useMemo(() => Object.keys(errors).length === 0, [errors]) + const isFormValid = useMemo(() => Object.keys(errors).length === 0, [errors]); - const router = useRouter() - const toast = useToast() + const router = useRouter(); + const toast = useToast(); const handleInputChange = (event: ChangeEvent<HTMLInputElement>) => { const { name, value } = event.target; - updateForm(name, value) - validate() - } + updateForm(name, value); + validate(); + }; const mutation = useMutation({ - mutationFn: (data: RegisterProps) => registerUser(data) - }) + mutationFn: (data: RegisterProps) => registerUser(data), + }); const handleSubmit = async (e: ChangeEvent<HTMLFormElement>) => { - e.preventDefault() + e.preventDefault(); - const response = await mutation.mutateAsync(form) + const response = await mutation.mutateAsync(form); if (response?.register === true) { const urlParams = new URLSearchParams({ activation: 'otp', email: form.email, - redirect: (router.query?.next || '/') as string - }) - router.push(`${router.route}?${urlParams}`) + redirect: (router.query?.next || '/') as string, + }); + router.push(`${router.route}?${urlParams}`); } const toastProps: UseToastOptions = { duration: 5000, - isClosable: true - } + isClosable: true, + position: 'top', + }; switch (response?.reason) { case 'EMAIL_USED': toast({ ...toastProps, title: 'Email sudah digunakan', - status: 'warning' - }) + status: 'warning', + }); break; case 'NOT_ACTIVE': - const activationUrl = `${router.route}?activation=email` + const activationUrl = `${router.route}?activation=email`; toast({ ...toastProps, title: 'Akun belum aktif', - description: <>Akun sudah terdaftar namun belum aktif. <Link href={activationUrl} className="underline">Klik untuk aktivasi akun</Link></>, - status: 'warning' - }) - break + description: ( + <> + Akun sudah terdaftar namun belum aktif.{' '} + <Link href={activationUrl} className='underline'> + Klik untuk aktivasi akun + </Link> + </> + ), + status: 'warning', + }); + break; } - } - + }; return ( - <form className="mt-6 grid grid-cols-1 gap-y-4" onSubmit={handleSubmit}> - + <form className='mt-6 grid grid-cols-1 gap-y-4' onSubmit={handleSubmit}> <div> - <label htmlFor='name' className="text-black font-bold">Nama Lengkap</label> + <label htmlFor='name' className='text-black font-bold'> + Nama Lengkap + </label> <input type='text' @@ -94,14 +102,18 @@ const Form: React.FC<FormProps> = ({ type, required, isBisnisRegist=false }) => placeholder='Masukan nama lengkap anda' value={form.name} onChange={handleInputChange} - aria-invalid={!!errors.name} + aria-invalid={chekValid && !!errors.name} /> - {!!errors.name && <span className="form-msg-danger">{errors.name}</span>} + {chekValid && !!errors.name && ( + <span className='form-msg-danger'>{errors.name}</span> + )} </div> <div> - <label htmlFor='email' className="text-black font-bold">Alamat Email</label> + <label htmlFor='email' className='text-black font-bold'> + Alamat Email + </label> <input type='text' @@ -111,15 +123,19 @@ const Form: React.FC<FormProps> = ({ type, required, isBisnisRegist=false }) => placeholder='Masukan alamat email anda' value={form.email} onChange={handleInputChange} - autoComplete="username" - aria-invalid={!!errors.email} + autoComplete='username' + aria-invalid={chekValid && !!errors.email} /> - {!!errors.email && <span className="form-msg-danger">{errors.email}</span>} + {chekValid && !!errors.email && ( + <span className='form-msg-danger'>{errors.email}</span> + )} </div> - + <div> - <label htmlFor='password' className="text-black font-bold">Kata Sandi</label> + <label htmlFor='password' className='text-black font-bold'> + Kata Sandi + </label> <input type='password' name='password' @@ -128,15 +144,19 @@ const Form: React.FC<FormProps> = ({ type, required, isBisnisRegist=false }) => placeholder='••••••••••••' value={form.password} onChange={handleInputChange} - autoComplete="current-password" - aria-invalid={!!errors.password} + autoComplete='current-password' + aria-invalid={chekValid && !!errors.password} /> - {!!errors.password && <span className="form-msg-danger">{errors.password}</span>} + {chekValid && !!errors.password && ( + <span className='form-msg-danger'>{errors.password}</span> + )} </div> <div> - <label htmlFor='phone' className="text-black font-bold">No Handphone</label> + <label htmlFor='phone' className='text-black font-bold'> + No Handphone + </label> <input type='tel' @@ -146,17 +166,15 @@ const Form: React.FC<FormProps> = ({ type, required, isBisnisRegist=false }) => placeholder='08xxxxxxxx' value={form.phone} onChange={handleInputChange} - aria-invalid={!!errors.phone} + aria-invalid={chekValid && !!errors.phone} /> - {!!errors.phone && <span className="form-msg-danger">{errors.phone}</span>} + {chekValid && !!errors.phone && ( + <span className='form-msg-danger'>{errors.phone}</span> + )} </div> - - - - </form> - ) -} + ); +}; -export default Form
\ No newline at end of file +export default Form; diff --git a/src-migrate/modules/register/components/FormBisnis.tsx b/src-migrate/modules/register/components/FormBisnis.tsx index 1004d944..2080ae75 100644 --- a/src-migrate/modules/register/components/FormBisnis.tsx +++ b/src-migrate/modules/register/components/FormBisnis.tsx @@ -1,26 +1,31 @@ -import { ChangeEvent, useEffect, useMemo, useState } from "react"; -import { useMutation } from "react-query"; -import { useRegisterStore } from "../stores/useRegisterStore"; -import { RegisterProps } from "~/types/auth"; -import { registerUser } from "~/services/auth"; -import { useRouter } from "next/router"; -import { Button, Checkbox, UseToastOptions, color, useToast } from "@chakra-ui/react"; -import Link from "next/link"; -import getFileBase64 from '@/core/utils/getFileBase64' -import { Controller, useForm } from 'react-hook-form' -import HookFormSelect from '@/core/components/elements/Select/HookFormSelect' -import odooApi from "~/libs/odooApi"; -import { toast } from 'react-hot-toast'; +import { ChangeEvent, useEffect, useMemo, useState } from 'react'; +import { useMutation } from 'react-query'; +import { useRegisterStore } from '../stores/useRegisterStore'; +import { RegisterProps } from '~/types/auth'; +import { registerUser } from '~/services/auth'; +import { useRouter } from 'next/router'; import { - EyeIcon -} from '@heroicons/react/24/outline'; + Button, + Checkbox, + UseToastOptions, + color, + useToast, +} from '@chakra-ui/react'; +import Link from 'next/link'; +import getFileBase64 from '@/core/utils/getFileBase64'; +import { Controller, useForm } from 'react-hook-form'; +import HookFormSelect from '@/core/components/elements/Select/HookFormSelect'; +import odooApi from '~/libs/odooApi'; +import { toast } from 'react-hot-toast'; +import { EyeIcon } from '@heroicons/react/24/outline'; import BottomPopup from '@/core/components/elements/Popup/BottomPopup'; -import Image from 'next/image' -import useDevice from '@/core/hooks/useDevice' +import Image from 'next/image'; +import useDevice from '@/core/hooks/useDevice'; interface FormProps { type: string; required: boolean; isPKP: boolean; + chekValid: boolean; } interface industry_id { @@ -34,22 +39,16 @@ interface companyType { label: string; } -const form: React.FC<FormProps> = ({ type, required, isPKP }) => { - const { - form, - errors, - updateForm, - validate - } = useRegisterStore() +const form: React.FC<FormProps> = ({ type, required, isPKP, chekValid }) => { + const { form, errors, updateForm, validate } = useRegisterStore(); const { control, watch, setValue } = useForm(); const [selectedCategory, setSelectedCategory] = useState<string>(''); const [isChekBox, setIsChekBox] = useState<boolean>(false); const [isExample, setIsExample] = useState<boolean>(false); - const { isDesktop, isMobile } = useDevice() + const { isDesktop, isMobile } = useDevice(); // Inside your component - const [formattedNpwp, setFormattedNpwp] = useState<string>(""); // State for formatted NPWP - const [unformattedNpwp, setUnformattedNpwp] = useState<string>(""); // State for unformatted NPWP - + const [formattedNpwp, setFormattedNpwp] = useState<string>(''); // State for formatted NPWP + const [unformattedNpwp, setUnformattedNpwp] = useState<string>(''); // State for unformatted NPWP const [industries, setIndustries] = useState<industry_id[]>([]); const [companyTypes, setCompanyTypes] = useState<companyType[]>([]); @@ -59,24 +58,36 @@ const form: React.FC<FormProps> = ({ type, required, isPKP }) => { useEffect(() => { const loadCompanyTypes = async () => { - const dataCompanyTypes = await odooApi('GET', '/api/v1/partner/company_type'); - setCompanyTypes(dataCompanyTypes?.map((o: { id: any; name: any; }) => ({ value: o.id, label: o.name }))); + const dataCompanyTypes = await odooApi( + 'GET', + '/api/v1/partner/company_type' + ); + setCompanyTypes( + dataCompanyTypes?.map((o: { id: any; name: any }) => ({ + value: o.id, + label: o.name, + })) + ); }; loadCompanyTypes(); }, []); useEffect(() => { - const selectedCompanyType = companyTypes.find(company => company.value === watch('companyType')); + const selectedCompanyType = companyTypes.find( + (company) => company.value === watch('companyType') + ); if (selectedCompanyType) { - updateForm("company_type_id", `${selectedCompanyType?.value}`); + updateForm('company_type_id', `${selectedCompanyType?.value}`); validate(); } }, [watch('companyType'), companyTypes]); useEffect(() => { - const selectedIndustryType = industries.find(industry => industry.value === watch('industry_id')); + const selectedIndustryType = industries.find( + (industry) => industry.value === watch('industry_id') + ); if (selectedIndustryType) { - updateForm("industry_id", `${selectedIndustryType?.value}`); + updateForm('industry_id', `${selectedIndustryType?.value}`); setSelectedCategory(selectedIndustryType.category); validate(); } @@ -85,107 +96,135 @@ const form: React.FC<FormProps> = ({ type, required, isPKP }) => { useEffect(() => { const loadIndustries = async () => { const dataIndustries = await odooApi('GET', '/api/v1/partner/industry'); - setIndustries(dataIndustries?.map((o: { id: any; name: any; category: any; }) => ({ value: o.id, label: o.name, category: o.category }))); + setIndustries( + dataIndustries?.map((o: { id: any; name: any; category: any }) => ({ + value: o.id, + label: o.name, + category: o.category, + })) + ); }; loadIndustries(); }, []); const handleInputChange = (event: ChangeEvent<HTMLInputElement>) => { const { name, value } = event.target; - updateForm('type_acc',`business`) - updateForm('is_pkp',`${isPKP}`) + updateForm('type_acc', `business`); + updateForm('is_pkp', `${isPKP}`); updateForm(name, value); validate(); }; const handleInputChangeNpwp = (event: ChangeEvent<HTMLInputElement>) => { const { name, value } = event.target; - updateForm('type_acc',`business`) - updateForm('is_pkp',`${isPKP}`) + updateForm('type_acc', `business`); + updateForm('is_pkp', `${isPKP}`); updateForm('npwp', value); validate(); }; const handleChange = (event: ChangeEvent<HTMLInputElement>) => { - setIsChekBox(!isChekBox) + setIsChekBox(!isChekBox); }; - + const formatNpwp = (value: string) => { try { - const cleaned = ("" + value).replace(/\D/g, ""); - let match - if(cleaned.length <= 15){ - match = cleaned.match(/(\d{0,2})?(\d{0,3})?(\d{0,3})?(\d{0,1})?(\d{0,3})?(\d{0,3})$/); - }else{ - match = cleaned.match(/(\d{0,3})?(\d{0,3})?(\d{0,3})?(\d{0,1})?(\d{0,3})?(\d{0,3})$/); + const cleaned = ('' + value).replace(/\D/g, ''); + let match; + if (cleaned.length <= 15) { + match = cleaned.match( + /(\d{0,2})?(\d{0,3})?(\d{0,3})?(\d{0,1})?(\d{0,3})?(\d{0,3})$/ + ); + } else { + match = cleaned.match( + /(\d{0,3})?(\d{0,3})?(\d{0,3})?(\d{0,1})?(\d{0,3})?(\d{0,3})$/ + ); } - - + if (match) { return [ match[1], - match[2] ? "." : "", + match[2] ? '.' : '', match[2], - match[3] ? "." : "", + match[3] ? '.' : '', match[3], - match[4] ? "." : "", + match[4] ? '.' : '', match[4], - match[5] ? "-" : "", + match[5] ? '-' : '', match[5], - match[6] ? "." : "", + match[6] ? '.' : '', match[6], - ].join(""); + ].join(''); } - + // If match is null, return the original cleaned string or handle as needed return cleaned; - } catch (error) { // Handle error or return a default value - console.error("Error formatting NPWP:", error); + console.error('Error formatting NPWP:', error); return value; } }; - useEffect(() => { if (isChekBox) { - updateForm("isChekBox", 'true'); + updateForm('isChekBox', 'true'); validate(); } else { - updateForm("isChekBox", 'false'); + updateForm('isChekBox', 'false'); validate(); } - }, [isChekBox,]); + }, [isChekBox]); const handleFileChange = async (event: ChangeEvent<HTMLInputElement>) => { - const toastProps: UseToastOptions = { duration: 5000, - isClosable: true + isClosable: true, + position: 'top', }; + let fileBase64 = ''; - const { name} = event.target; + const { name } = event.target; const file = event.target.files?.[0]; + + // Allowed file extensions + const allowedExtensions = ['pdf', 'doc', 'docx', 'png', 'jpg', 'jpeg']; + if (file) { - if (typeof file !== 'undefined') { - if (file.size > 5000000) { - toast({ - ...toastProps, - title: 'Maksimal ukuran file adalah 5MB', - status: 'warning' - }); - return; - } - fileBase64 = await getFileBase64(file); + const fileExtension = file.name.split('.').pop()?.toLowerCase(); // Extract file extension + + // Check if the file extension is allowed + if (!fileExtension || !allowedExtensions.includes(fileExtension)) { + toast({ + ...toastProps, + title: + 'Format file yang diijinkan adalah .pdf, .doc, .docx, .png, .jpg, atau .jpeg', + status: 'error', + }); + event.target.value = ''; + return; } - updateForm(name, fileBase64); - validate(); + + // Check for file size + if (file.size > 5000000) { + toast({ + ...toastProps, + title: 'Maksimal ukuran file adalah 5MB', + status: 'error', + }); + event.target.value = ''; + return; + } + + // Convert file to Base64 + fileBase64 = await getFileBase64(file); + updateForm(name, fileBase64); // Update form with the Base64 string + validate(); // Perform form validation } }; const mutation = useMutation({ - mutationFn: (data: RegisterProps) => registerUser(data) + mutationFn: (data: RegisterProps) => registerUser(data), }); const handleSubmit = async (e: ChangeEvent<HTMLFormElement>) => { @@ -197,14 +236,15 @@ const form: React.FC<FormProps> = ({ type, required, isPKP }) => { const urlParams = new URLSearchParams({ activation: 'otp', email: form.email, - redirect: (router.query?.next || '/') as string + redirect: (router.query?.next || '/') as string, }); router.push(`${router.route}?${urlParams}`); } const toastProps: UseToastOptions = { duration: 5000, - isClosable: true + isClosable: true, + position: 'top', }; switch (response?.reason) { @@ -212,7 +252,7 @@ const form: React.FC<FormProps> = ({ type, required, isPKP }) => { toast({ ...toastProps, title: 'Email sudah digunakan', - status: 'warning' + status: 'warning', }); break; case 'NOT_ACTIVE': @@ -220,147 +260,205 @@ const form: React.FC<FormProps> = ({ type, required, isPKP }) => { toast({ ...toastProps, title: 'Akun belum aktif', - description: <>Akun sudah terdaftar namun belum aktif. <Link href={activationUrl} className="underline">Klik untuk aktivasi akun</Link></>, - status: 'warning' + description: ( + <> + Akun sudah terdaftar namun belum aktif.{' '} + <Link href={activationUrl} className='underline'> + Klik untuk aktivasi akun + </Link> + </> + ), + status: 'warning', }); break; } }; return ( <> - <BottomPopup + <BottomPopup className='' title='Contoh SPPKP' active={isExample} close={() => setIsExample(false)} > <div className='flex p-2'> - <Image - src='/images/NO-SPPKP-FORMAT-TEMPLATE.jpg' - alt='Contoh SPPKP' - className='w-full h-full ' - width={800} - height={800} - quality={100} - /> + <Image + src='/images/NO-SPPKP-FORMAT-TEMPLATE.jpg' + alt='Contoh SPPKP' + className='w-full h-full ' + width={800} + height={800} + quality={100} + /> </div> </BottomPopup> - <form className="mt-6 grid grid-cols-1 gap-y-4" onSubmit={handleSubmit}> - <div> - <label htmlFor='email' className="font-bold">Email Bisnis {!isPKP && !required && <span className='font-normal text-gray_r-11'>(opsional)</span>}</label> - - <input - type='text' - id='email_partner' - name='email_partner' - placeholder='example@email.com' - value={!required ? form.email_partner : ''} - className={`form-input mt-3 ${required ? 'cursor-no-drop' : ''}`} - disabled={required} - contentEditable={required} - readOnly={required} - onChange={handleInputChange} - autoComplete="username" - aria-invalid={!required && isPKP && !!errors.email_partner} - - /> - - {!required && isPKP && !!errors.email_partner && <span className="form-msg-danger">{errors.email_partner}</span>} - </div> - - <div className=""> - <label className="font-bold" htmlFor="company"> - Nama Bisnis - </label> - <div className="flex justify-between items-start gap-2 max-h-12 min-h-12 text-sm"> - <div className='w-4/5 pr-1'> - <Controller - name='companyType' - control={control} - render={(props) => <HookFormSelect {...props} options={companyTypes} disabled={required} placeholder="Badan Usaha"/>} + <form className='mt-6 grid grid-cols-1 gap-y-4' onSubmit={handleSubmit}> + <div> + <label htmlFor='email' className='font-bold'> + Email Bisnis{' '} + {!isPKP && !required && ( + <span className='font-normal text-gray_r-11'>(opsional)</span> + )} + </label> + + <input + type='text' + id='email_partner' + name='email_partner' + placeholder='example@email.com' + value={!required ? form.email_partner : ''} + className={`form-input mt-3 ${required ? 'cursor-no-drop' : ''}`} + disabled={required} + contentEditable={required} + readOnly={required} + onChange={handleInputChange} + autoComplete='username' + aria-invalid={ + chekValid && !required && isPKP && !!errors.email_partner + } + /> + + {chekValid && !required && isPKP && !!errors.email_partner && ( + <span className='form-msg-danger'>{errors.email_partner}</span> + )} + </div> + + <div className=''> + <label className='font-bold' htmlFor='company'> + Nama Bisnis + </label> + <div className='flex justify-between items-start gap-2 max-h-12 min-h-12 text-sm'> + <div className='w-4/5 pr-1'> + <Controller + name='companyType' + control={control} + render={(props) => ( + <HookFormSelect + {...props} + options={companyTypes} + disabled={required} + placeholder='Badan Usaha' + /> + )} /> - {!required && !!errors.company_type_id && <span className="form-msg-danger">{errors.company_type_id}</span>} - </div> - <div className="w-[120%]"> - <input - type="text" - name="business_name" - id="business_name" - className="form-input h-12 " - placeholder="Nama Perusahaan" - autoCapitalize="true" - value={form.business_name} - aria-invalid={!!errors.business_name} - onChange={handleInputChange} + {chekValid && !required && !!errors.company_type_id && ( + <span className='form-msg-danger'> + {errors.company_type_id} + </span> + )} + </div> + <div className='w-[120%]'> + <input + type='text' + name='business_name' + id='business_name' + className='form-input h-12 ' + placeholder='Nama Perusahaan' + autoCapitalize='true' + value={form.business_name} + aria-invalid={chekValid && !!errors.business_name} + onChange={handleInputChange} /> - { !!errors.business_name && <span className="form-msg-danger">{errors.business_name}</span>} + {chekValid && !!errors.business_name && ( + <span className='form-msg-danger'>{errors.business_name}</span> + )} + </div> </div> </div> - </div> - - <div className="mt-8 sm:mt-8"> - <label className="font-bold" htmlFor="business_name"> - Klasifikasi Jenis Usaha - </label> - <Controller - name='industry_id' - control={control} - render={(props) => <HookFormSelect {...props} options={industries} disabled={required} placeholder={'Select industry'}/>} + + <div className='mt-8 sm:mt-8'> + <label className='font-bold' htmlFor='business_name'> + Klasifikasi Jenis Usaha + </label> + <Controller + name='industry_id' + control={control} + render={(props) => ( + <HookFormSelect + {...props} + options={industries} + disabled={required} + placeholder={'Select industry'} + /> + )} + /> + {selectedCategory && ( + <span className='text-gray_r-11 text-xs'> + Kategori : {selectedCategory} + </span> + )} + {chekValid && !required && !!errors.industry_id && ( + <span className='form-msg-danger'>{errors.industry_id}</span> + )} + </div> + + <div> + <label htmlFor='alamat_bisnis' className='font-bold'> + Alamat Bisnis + </label> + + <input + type='text' + id='alamat_bisnis' + name='alamat_bisnis' + placeholder='Masukan alamat bisnis anda' + value={!required ? form.alamat_bisnis : ''} + className={`form-input mt-3 ${required ? 'cursor-no-drop' : ''}`} + disabled={required} + contentEditable={required} + readOnly={required} + onChange={handleInputChange} + aria-invalid={chekValid && !required && !!errors.alamat_bisnis} + /> + + {chekValid && !required && !!errors.alamat_bisnis && ( + <span className='form-msg-danger'>{errors.alamat_bisnis}</span> + )} + </div> + + <div> + <label htmlFor='nama_wajib_pajak' className='font-bold'> + Nama Wajib Pajak{' '} + {!isPKP && !required && ( + <span className='font-normal text-gray_r-11'>(opsional)</span> + )} + </label> + + <input + type='text' + id='nama_wajib_pajak' + name='nama_wajib_pajak' + placeholder='Masukan nama lengkap anda' + value={!required ? form.nama_wajib_pajak : ''} + className={`form-input mt-3 ${required ? 'cursor-no-drop' : ''}`} + disabled={required} + contentEditable={required} + readOnly={required} + onChange={handleInputChange} + aria-invalid={ + chekValid && isPKP && !required && !!errors.nama_wajib_pajak + } /> - {selectedCategory && - <span className='text-gray_r-11 text-xs'>Kategori : {selectedCategory}</span> - } - {!required && !!errors.industry_id && <span className="form-msg-danger">{errors.industry_id}</span>} - </div> - - <div> - <label htmlFor='alamat_bisnis' className="font-bold">Alamat Bisnis</label> - - <input - type='text' - id='alamat_bisnis' - name='alamat_bisnis' - placeholder='Masukan alamat bisnis anda' - value={!required? form.alamat_bisnis : ''} - className={`form-input mt-3 ${required ? 'cursor-no-drop' : ''}`} - disabled={required} - contentEditable={required} - readOnly={required} - onChange={handleInputChange} - aria-invalid={!required && !!errors.alamat_bisnis} - /> - - {!required && !!errors.alamat_bisnis && <span className="form-msg-danger">{errors.alamat_bisnis}</span>} - </div> - - <div> - <label htmlFor='nama_wajib_pajak' className="font-bold">Nama Wajib Pajak {!isPKP && !required && <span className='font-normal text-gray_r-11'>(opsional)</span>}</label> - - <input - type='text' - id='nama_wajib_pajak' - name='nama_wajib_pajak' - placeholder='Masukan nama lengkap anda' - value={!required? form.nama_wajib_pajak : ''} - className={`form-input mt-3 ${required ? 'cursor-no-drop' : ''}`} - disabled={required} - contentEditable={required} - readOnly={required} - onChange={handleInputChange} - aria-invalid={isPKP && !required && !!errors.nama_wajib_pajak} - /> - - {isPKP && !required && !!errors.nama_wajib_pajak && <span className="form-msg-danger">{errors.nama_wajib_pajak}</span>} - </div> - - <div> - <label htmlFor='alamat_wajib_pajak' className="font-bold flex items-center"> - <p> - Alamat Wajib Pajak {!isPKP && !required && <span className='font-normal text-gray_r-11'>(opsional)</span>} - </p> - <div className="flex items-center ml-2 mt-1"> - <Checkbox + + {chekValid && isPKP && !required && !!errors.nama_wajib_pajak && ( + <span className='form-msg-danger'>{errors.nama_wajib_pajak}</span> + )} + </div> + + <div> + <label + htmlFor='alamat_wajib_pajak' + className='font-bold flex items-center' + > + <p> + Alamat Wajib Pajak{' '} + {!isPKP && !required && ( + <span className='font-normal text-gray_r-11'>(opsional)</span> + )} + </p> + <div className='flex items-center ml-2 mt-1'> + <Checkbox borderColor='gray.600' colorScheme='red' size='md' @@ -368,128 +466,174 @@ const form: React.FC<FormProps> = ({ type, required, isPKP }) => { onChange={handleChange} /> <span className='text-caption-2 ml-2 font-normal italic'> - sama dengan alamat bisnis? + sama dengan alamat bisnis? </span> - </div> - </label> - - <input - type='text' - id='alamat_wajib_pajak' - name='alamat_wajib_pajak' - placeholder='Masukan alamat wajib pajak anda' - value={!required? (isChekBox?form.alamat_bisnis : form.alamat_wajib_pajak) : ''} - className={`form-input mt-3 ${required ? 'cursor-no-drop' : ''}`} - disabled={isChekBox || required} - contentEditable={required} - readOnly={required} - onChange={handleInputChange} - aria-invalid={isPKP && !required && !!errors.alamat_wajib_pajak} - /> - - {isPKP && !required && !!errors.alamat_wajib_pajak && <span className="form-msg-danger">{errors.alamat_wajib_pajak}</span>} - </div> - - <div> - <label htmlFor="npwp" className="font-bold"> - Nomor NPWP {!isPKP && !required && <span className="font-normal text-gray_r-11">(opsional)</span>} - </label> - - <input - type="tel" - id="npwp" - name="npwp" - className={`form-input mt-3 ${required ? "cursor-no-drop" : ""}`} - disabled={required} - contentEditable={required} - readOnly={required} - placeholder="000.000.000.0-000.000" - value={!required ? formattedNpwp : ""} - maxLength={21} // Set maximum length to 16 characters - onChange={(e) => { - if (!required) { - const unformatted = e.target.value.replace(/\D/g, ""); // Remove all non-digit characters - const formattedValue = formatNpwp(unformatted); // Format the value - setUnformattedNpwp(unformatted); // Store unformatted value - setFormattedNpwp(formattedValue); // Store formatted value - handleInputChangeNpwp({ ...e, target: { ...e.target, value: unformatted } }); // Update form state with unformatted value + </div> + </label> + + <input + type='text' + id='alamat_wajib_pajak' + name='alamat_wajib_pajak' + placeholder='Masukan alamat wajib pajak anda' + value={ + !required + ? isChekBox + ? form.alamat_bisnis + : form.alamat_wajib_pajak + : '' } - }} - aria-invalid={!required && !!errors.npwp} - /> + className={`form-input mt-3 ${required ? 'cursor-no-drop' : ''}`} + disabled={isChekBox || required} + contentEditable={required} + readOnly={required} + onChange={handleInputChange} + aria-invalid={ + chekValid && isPKP && !required && !!errors.alamat_wajib_pajak + } + /> - {!required && !!errors.npwp && <span className="form-msg-danger">{errors.npwp}</span>} - </div> + {chekValid && isPKP && !required && !!errors.alamat_wajib_pajak && ( + <span className='form-msg-danger'>{errors.alamat_wajib_pajak}</span> + )} + </div> - <div> - <label htmlFor='sppkp' className="font-bold flex flex-row items-center justify-between"> - <div className="flex flex-row items-center"> - Nomor SPPKP { !required && <span className='ml-2 font-normal text-gray_r-11'>(opsional) </span>} - </div> - {<div onClick={() => setIsExample(!isExample)} className="rounded text-white p-2 flex flex-row bg-red-500 hover:cursor-pointer hover:bg-red-400" > + <div> + <label htmlFor='npwp' className='font-bold'> + Nomor NPWP{' '} + {!isPKP && !required && ( + <span className='font-normal text-gray_r-11'>(opsional)</span> + )} + </label> + + <input + type='tel' + id='npwp' + name='npwp' + className={`form-input mt-3 ${required ? 'cursor-no-drop' : ''}`} + disabled={required} + contentEditable={required} + readOnly={required} + placeholder='000.000.000.0-000.000' + value={!required ? formattedNpwp : ''} + maxLength={21} // Set maximum length to 16 characters + onChange={(e) => { + if (!required) { + const unformatted = e.target.value.replace(/\D/g, ''); // Remove all non-digit characters + const formattedValue = formatNpwp(unformatted); // Format the value + setUnformattedNpwp(unformatted); // Store unformatted value + setFormattedNpwp(formattedValue); // Store formatted value + handleInputChangeNpwp({ + ...e, + target: { ...e.target, value: unformatted }, + }); // Update form state with unformatted value + } + }} + aria-invalid={chekValid && !required && !!errors.npwp} + /> + + {chekValid && !required && !!errors.npwp && ( + <span className='form-msg-danger'>{errors.npwp}</span> + )} + </div> + + <div> + <label + htmlFor='sppkp' + className='font-bold flex flex-row items-center justify-between' + > + <div className='flex flex-row items-center'> + Nomor SPPKP{' '} + {!required && ( + <span className='ml-2 font-normal text-gray_r-11'> + (opsional){' '} + </span> + )} + </div> + { + <div + onClick={() => setIsExample(!isExample)} + className='rounded text-white p-2 flex flex-row bg-red-500 hover:cursor-pointer hover:bg-red-400' + > <EyeIcon className={`w-4 ${isDesktop && 'mr-2'}`} /> - {isDesktop && - <p className="font-light text-xs">Lihat Contoh</p> - } - </div>} + {isDesktop && ( + <p className='font-light text-xs'>Lihat Contoh</p> + )} + </div> + } </label> + <input + type='tel' + id='sppkp' + name='sppkp' + className={`form-input mt-3 ${required ? 'cursor-no-drop' : ''}`} + disabled={required} + contentEditable={required} + readOnly={required} + placeholder='X-XXXPKP/WJPXXX/XX.XXXX/XXXX' + onChange={handleInputChange} + value={!required ? form.sppkp : ''} + aria-invalid={chekValid && !required && !!errors.sppkp} + /> + + {chekValid && !required && !!errors.sppkp && ( + <span className='form-msg-danger'>{errors.sppkp}</span> + )} + </div> - <input - type='tel' - id='sppkp' - name='sppkp' - className={`form-input mt-3 ${required ? 'cursor-no-drop' : ''}`} - disabled={required} - contentEditable={required} - readOnly={required} - placeholder='X-XXXPKP/WJPXXX/XX.XXXX/XXXX' - onChange={handleInputChange} - value={!required ? form.sppkp : ''} - aria-invalid={!required && !!errors.sppkp} - /> - - {!required && !!errors.sppkp && <span className="form-msg-danger">{errors.sppkp}</span>} - </div> - - <div> - <label htmlFor="npwp_document" className="font-bold">Dokumen NPWP {!isPKP && !required && <span className='font-normal text-gray_r-11'>(opsional)</span>}</label> - - <input - type="file" - id="npwp_document" - name="npwp_document" - className={`form-input mt-3 ${required ? 'cursor-no-drop' : ''}`} - disabled={required} - contentEditable={required} - readOnly={required} - onChange={handleFileChange} - accept=".pdf,.doc,.docx,.png,.jpg,.jpeg" // Filter file types - /> - - {isPKP && !required && !!errors.npwp_document && <span className="form-msg-danger">{errors.npwp_document}</span>} - </div> - - <div> - <label htmlFor="sppkp_document" className="font-bold">Dokumen SPPKP {!isPKP && !required && <span className='font-normal text-gray_r-11'>(opsional)</span>}</label> - - <input - type="file" - id="sppkp_document" - name="sppkp_document" - className={`form-input mt-3 ${required ? 'cursor-no-drop' : ''}`} - disabled={required} - contentEditable={required} - readOnly={required} - onChange={handleFileChange} - accept=".pdf,.doc,.docx,.png,.jpg,.jpeg" // Filter file types - /> - - {isPKP && !required && !!errors.sppkp_document && <span className="form-msg-danger">{errors.sppkp_document}</span>} - </div> - </form> + <div> + <label htmlFor='npwp_document' className='font-bold'> + Dokumen NPWP{' '} + {!isPKP && !required && ( + <span className='font-normal text-gray_r-11'>(opsional)</span> + )} + </label> + + <input + type='file' + id='npwp_document' + name='npwp_document' + className={`form-input mt-3 ${required ? 'cursor-no-drop' : ''}`} + disabled={required} + contentEditable={required} + readOnly={required} + onChange={handleFileChange} + accept='.pdf,.doc,.docx,.png,.jpg,.jpeg' // Filter file types + /> + + {chekValid && isPKP && !required && !!errors.npwp_document && ( + <span className='form-msg-danger'>{errors.npwp_document}</span> + )} + </div> + + <div> + <label htmlFor='sppkp_document' className='font-bold'> + Dokumen SPPKP{' '} + {!isPKP && !required && ( + <span className='font-normal text-gray_r-11'>(opsional)</span> + )} + </label> + + <input + type='file' + id='sppkp_document' + name='sppkp_document' + className={`form-input mt-3 ${required ? 'cursor-no-drop' : ''}`} + disabled={required} + contentEditable={required} + readOnly={required} + onChange={handleFileChange} + accept='.pdf,.doc,.docx,.png,.jpg,.jpeg' // Filter file types + /> + + {chekValid && isPKP && !required && !!errors.sppkp_document && ( + <span className='form-msg-danger'>{errors.sppkp_document}</span> + )} + </div> + </form> </> - ) -} + ); +}; export default form; diff --git a/src-migrate/modules/register/components/RegistrasiBisnis.tsx b/src-migrate/modules/register/components/RegistrasiBisnis.tsx index 1d8317f1..36476ab9 100644 --- a/src-migrate/modules/register/components/RegistrasiBisnis.tsx +++ b/src-migrate/modules/register/components/RegistrasiBisnis.tsx @@ -1,67 +1,60 @@ -import { ChangeEvent, useEffect, useMemo, useState } from "react"; -import FormBisnis from "./FormBisnis"; -import Form from "./Form"; -import TermCondition from "./TermCondition"; -import FormCaptcha from "./FormCaptcha"; -import { Radio, RadioGroup, Stack, Divider, Button } from '@chakra-ui/react' -import React from "react"; -import { - ChevronDownIcon, - ChevronRightIcon -} from '@heroicons/react/24/outline'; -import { useRegisterStore } from "../stores/useRegisterStore"; -import { useMutation } from "react-query"; -import { RegisterProps } from "~/types/auth"; -import { registerUser } from "~/services/auth"; -import router from "next/router"; -import { useRouter } from "next/router"; -import { UseToastOptions, useToast } from "@chakra-ui/react"; -import Link from "next/link"; - -const RegistrasiBisnis = () => { +import { ChangeEvent, useEffect, useMemo, useState } from 'react'; +import FormBisnis from './FormBisnis'; +import Form from './Form'; +import TermCondition from './TermCondition'; +import FormCaptcha from './FormCaptcha'; +import { Radio, RadioGroup, Stack, Divider, Button } from '@chakra-ui/react'; +import React from 'react'; +import { ChevronDownIcon, ChevronRightIcon } from '@heroicons/react/24/outline'; +import { useRegisterStore } from '../stores/useRegisterStore'; +import { useMutation } from 'react-query'; +import { RegisterProps } from '~/types/auth'; +import { registerUser } from '~/services/auth'; +import router from 'next/router'; +import { useRouter } from 'next/router'; +import { UseToastOptions, useToast } from '@chakra-ui/react'; +import Link from 'next/link'; +interface FormProps { + chekValid: boolean; +} +const RegistrasiBisnis: React.FC<FormProps> = ({ chekValid }) => { const [isPKP, setIsPKP] = useState(true); const [isTerdaftar, setIsTerdaftar] = useState(false); const [isDropIndividu, setIsDropIndividu] = useState(true); const [isBisnisClicked, setisBisnisClicked] = useState(true); const [selectedValue, setSelectedValue] = useState('PKP'); const [selectedValueBisnis, setSelectedValueBisnis] = useState('false'); - const { - form, - isCheckedTNC, - isValidCaptcha, - errors, - validate, - updateForm - } = useRegisterStore() - const isFormValid = useMemo(() => Object.keys(errors).length === 0, [errors]) - const toast = useToast() + const { form, isCheckedTNC, isValidCaptcha, errors, validate, updateForm } = + useRegisterStore(); + const isFormValid = useMemo(() => Object.keys(errors).length === 0, [errors]); + const toast = useToast(); const mutation = useMutation({ - mutationFn: (data: RegisterProps) => registerUser(data) - }) + mutationFn: (data: RegisterProps) => registerUser(data), + }); useEffect(() => { - if (selectedValue === "PKP") { - updateForm("is_pkp", 'true'); + if (selectedValue === 'PKP') { + updateForm('is_pkp', 'true'); validate(); } else { - updateForm("is_pkp", 'false'); + updateForm('is_pkp', 'false'); validate(); } - }, [selectedValue,]); - + }, [selectedValue]); + useEffect(() => { if (isTerdaftar) { - updateForm("is_terdaftar", 'true'); + updateForm('is_terdaftar', 'true'); validate(); } else { - updateForm("is_terdaftar", 'false'); + updateForm('is_terdaftar', 'false'); validate(); } - }, [isTerdaftar,]); + }, [isTerdaftar]); - const handleChange = (value: string) => { + const handleChange = (value: string) => { setSelectedValue(value); - if (value === "PKP") { + if (value === 'PKP') { validate(); setIsPKP(true); } else { @@ -70,10 +63,10 @@ const RegistrasiBisnis = () => { setIsPKP(false); } }; - + const handleChangeBisnis = (value: string) => { setSelectedValueBisnis(value); - if (value === "true") { + if (value === 'true') { validate(); setIsTerdaftar(true); } else { @@ -83,81 +76,114 @@ const RegistrasiBisnis = () => { }; const handleClick = () => { - setIsDropIndividu(!isDropIndividu) + setIsDropIndividu(!isDropIndividu); }; const handleClickBisnis = () => { - setisBisnisClicked(!isBisnisClicked) + setisBisnisClicked(!isBisnisClicked); }; return ( <> - - <div className="mt-4 border"> - <div className="p-4"> - <div onClick={handleClick} className="flex justify-between"> - <p className="text-2xl font-semibold text-center md:text-left"> + <div className='mt-4 border'> + <div className='p-4'> + <div onClick={handleClick} className='flex justify-between'> + <p className='text-2xl font-semibold text-center md:text-left'> Data Akun </p> {isDropIndividu ? ( - <div className="flex"> - <ChevronDownIcon onClick={handleClick} className='h-6 w-6 text-black' /> + <div className='flex'> + <ChevronDownIcon + onClick={handleClick} + className='h-6 w-6 text-black' + /> </div> ) : ( - <ChevronRightIcon onClick={handleClick} className='h-6 w-6 text-black' /> + <ChevronRightIcon + onClick={handleClick} + className='h-6 w-6 text-black' + /> )} </div> {isDropIndividu && ( <div> - <Divider my={4} /> - <Form type="bisnis" required={true} isBisnisRegist={true} /> + <Divider my={4} /> + <Form + type='bisnis' + required={true} + isBisnisRegist={true} + chekValid={chekValid} + /> </div> )} </div> </div> - <div className="mt-4 border"> - <div className="p-4"> - <div onClick={handleClickBisnis} className="flex justify-between"> - <p className="text-2xl font-semibold text-center md:text-left"> + <div className='mt-4 border'> + <div className='p-4'> + <div onClick={handleClickBisnis} className='flex justify-between'> + <p className='text-2xl font-semibold text-center md:text-left'> Data Bisnis </p> {isBisnisClicked ? ( - <div className="flex"> - <ChevronDownIcon onClick={handleClickBisnis} className='h-6 w-6 text-black' /> + <div className='flex'> + <ChevronDownIcon + onClick={handleClickBisnis} + className='h-6 w-6 text-black' + /> </div> ) : ( - <ChevronRightIcon onClick={handleClickBisnis} className='h-6 w-6 text-black' /> + <ChevronRightIcon + onClick={handleClickBisnis} + className='h-6 w-6 text-black' + /> )} </div> {isBisnisClicked && ( <div> - <Divider my={4} /> + <Divider my={4} /> <div> - <p className="text-black font-bold mb-2">Bisnis Terdaftar di Indoteknik?</p> - <RadioGroup onChange={handleChangeBisnis} value={selectedValueBisnis}> + <p className='text-black font-bold mb-2'> + Bisnis Terdaftar di Indoteknik? + </p> + <RadioGroup + onChange={handleChangeBisnis} + value={selectedValueBisnis} + > <Stack direction='row'> - <Radio colorScheme="red" value='true'>Sudah Terdaftar</Radio> - <Radio colorScheme="red" value='false' className="ml-2">Belum Terdaftar</Radio> + <Radio colorScheme='red' value='true'> + Sudah Terdaftar + </Radio> + <Radio colorScheme='red' value='false' className='ml-2'> + Belum Terdaftar + </Radio> </Stack> </RadioGroup> </div> - <div className="mt-4"> - <p className="text-black font-bold mb-2">Tipe Bisnis</p> - <RadioGroup onChange={handleChange} value={selectedValue}> - <Stack direction='row' className="font-bold"> - <Radio colorScheme="red" value='PKP'>PKP</Radio> - <Radio colorScheme="red" value='Non-PKP' className="ml-4">Non-PKP</Radio> - </Stack> - </RadioGroup> - </div> - <FormBisnis type="bisnis" required={isTerdaftar} isPKP={isPKP} /> + <div className='mt-4'> + <p className='text-black font-bold mb-2'>Tipe Bisnis</p> + <RadioGroup onChange={handleChange} value={selectedValue}> + <Stack direction='row' className='font-bold'> + <Radio colorScheme='red' value='PKP'> + PKP + </Radio> + <Radio colorScheme='red' value='Non-PKP' className='ml-4'> + Non-PKP + </Radio> + </Stack> + </RadioGroup> + </div> + <FormBisnis + type='bisnis' + required={isTerdaftar} + isPKP={isPKP} + chekValid={chekValid} + /> </div> )} </div> </div> - - <h1 className=""></h1> - + + <h1 className=''></h1> </> ); }; diff --git a/src-migrate/modules/register/components/RegistrasiIndividu.tsx b/src-migrate/modules/register/components/RegistrasiIndividu.tsx index 5503db2a..3997e767 100644 --- a/src-migrate/modules/register/components/RegistrasiIndividu.tsx +++ b/src-migrate/modules/register/components/RegistrasiIndividu.tsx @@ -1,24 +1,27 @@ -import Form from "./Form"; -import { useRegisterStore } from "../stores/useRegisterStore"; -import { useEffect } from "react"; -const RegistrasiIndividu = () => { - const { - form, - errors, - updateForm, - validate - } = useRegisterStore() +import Form from './Form'; +import { useRegisterStore } from '../stores/useRegisterStore'; +import { useEffect } from 'react'; +interface FormProps { + chekValid: boolean; +} +const RegistrasiIndividu: React.FC<FormProps> = ({ chekValid }) => { + const { form, errors, updateForm, validate } = useRegisterStore(); useEffect(() => { - updateForm("is_pkp", 'false'); - updateForm("is_terdaftar", 'false'); - updateForm("type_acc", 'individu'); + updateForm('is_pkp', 'false'); + updateForm('is_terdaftar', 'false'); + updateForm('type_acc', 'individu'); validate(); }, []); return ( <> - <Form type='individu' required={false} isBisnisRegist={false}/> + <Form + type='individu' + required={false} + isBisnisRegist={false} + chekValid={chekValid} + /> </> ); }; diff --git a/src-migrate/modules/register/index.tsx b/src-migrate/modules/register/index.tsx index 31e09088..d91af9e3 100644 --- a/src-migrate/modules/register/index.tsx +++ b/src-migrate/modules/register/index.tsx @@ -1,118 +1,130 @@ -import PageContent from "~/modules/page-content"; -import Form from "./components/Form"; -import RegistrasiIndividu from "./components/RegistrasiIndividu"; -import RegistrasiBisnis from "./components/RegistrasiBisnis"; -import FormBisnis from "./components/FormBisnis"; -import Link from "next/link"; -import Image from "next/image"; -import IndoteknikLogo from "~/images/logo.png"; -import AccountActivation from "../account-activation"; -import { useMemo, useState } from "react"; -import { useRegisterStore } from "./stores/useRegisterStore"; -import FormCaptcha from "./components/FormCaptcha"; -import TermCondition from "./components/TermCondition"; -import { Button } from '@chakra-ui/react' -import { useMutation } from "react-query"; -import { UseToastOptions, useToast } from "@chakra-ui/react"; -import { RegisterProps } from "~/types/auth"; -import { registerUser } from "~/services/auth"; -import { useRouter } from "next/router"; +import PageContent from '~/modules/page-content'; +import RegistrasiIndividu from './components/RegistrasiIndividu'; +import RegistrasiBisnis from './components/RegistrasiBisnis'; +import Link from 'next/link'; +import Image from 'next/image'; +import IndoteknikLogo from '~/images/logo.png'; +import AccountActivation from '../account-activation'; +import { useMemo, useState } from 'react'; +import { useRegisterStore } from './stores/useRegisterStore'; +import FormCaptcha from './components/FormCaptcha'; +import TermCondition from './components/TermCondition'; +import { Button } from '@chakra-ui/react'; +import { useMutation } from 'react-query'; +import { UseToastOptions, useToast } from '@chakra-ui/react'; +import { RegisterProps } from '~/types/auth'; +import { registerUser } from '~/services/auth'; +import { useRouter } from 'next/router'; const LOGO_WIDTH = 150; const LOGO_HEIGHT = LOGO_WIDTH / 3; const Register = () => { const [isIndividuClicked, setIsIndividuClicked] = useState(true); + const [notValid, setNotValid] = useState(false); const [isBisnisClicked, setIsBisnisClicked] = useState(false); - const {form, isCheckedTNC, isValidCaptcha, resetForm,errors, - updateForm - } = useRegisterStore() + const { form, isCheckedTNC, isValidCaptcha, resetForm, errors, updateForm } = + useRegisterStore(); - const isFormValid = useMemo(() => Object.keys(errors).length === 0, [errors]) - const toast = useToast() - const router = useRouter() + const isFormValid = useMemo(() => Object.keys(errors).length === 0, [errors]); + const toast = useToast(); + const router = useRouter(); const mutation = useMutation({ - mutationFn: (data: RegisterProps) => registerUser(data) - }) + mutationFn: (data: RegisterProps) => registerUser(data), + }); const handleIndividuClick = () => { resetForm(); setIsIndividuClicked(true); setIsBisnisClicked(false); }; - + const handleBisnisClick = () => { resetForm(); - updateForm("is_terdaftar", 'false') - updateForm("type_acc", 'business') + updateForm('is_terdaftar', 'false'); + updateForm('type_acc', 'business'); setIsIndividuClicked(false); setIsBisnisClicked(true); }; const handleSubmit = async () => { - const response = await mutation.mutateAsync(form) + if (!isFormValid) { + setNotValid(true); + return; + } else { + setNotValid(false); + } + const response = await mutation.mutateAsync(form); if (response?.register === true) { const urlParams = new URLSearchParams({ activation: 'otp', email: form.email, - redirect: (router.query?.next || '/') as string - }) - router.push(`${router.route}?${urlParams}`) + redirect: (router.query?.next || '/') as string, + }); + router.push(`${router.route}?${urlParams}`); } const toastProps: UseToastOptions = { duration: 5000, - isClosable: true - } + isClosable: true, + position: 'top', + }; switch (response?.reason) { case 'EMAIL_USED': toast({ ...toastProps, title: 'Email sudah digunakan', - status: 'warning' - }) + status: 'warning', + }); break; case 'NOT_ACTIVE': - const activationUrl = `${router.route}?activation=email` + const activationUrl = `${router.route}?activation=email`; toast({ ...toastProps, title: 'Akun belum aktif', - description: <>Akun sudah terdaftar namun belum aktif. <Link href={activationUrl} className="underline">Klik untuk aktivasi akun</Link></>, - status: 'warning' - }) - break + description: ( + <> + Akun sudah terdaftar namun belum aktif.{' '} + <Link href={activationUrl} className='underline'> + Klik untuk aktivasi akun + </Link> + </> + ), + status: 'warning', + }); + break; } }; return ( - <div className="container"> - <div className="grid grid-cols-1 md:grid-cols-2 gap-x-8 pt-10 px-2 md:pt-16"> - <section className=""> - <div className="px-8 py-4 border"> - <Link href="/" className="block md:hidden"> + <div className='container'> + <div className='grid grid-cols-1 md:grid-cols-2 gap-x-8 pt-10 px-2 md:pt-16'> + <section className=''> + <div className='px-8 py-4 border'> + <Link href='/' className='block md:hidden'> <Image src={IndoteknikLogo} - alt="Logo Indoteknik" + alt='Logo Indoteknik' width={LOGO_WIDTH} height={LOGO_HEIGHT} - className="mx-auto mb-4 w-auto h-auto" + className='mx-auto mb-4 w-auto h-auto' priority /> </Link> - <h1 className="text-2xl font-semibold text-center md:text-left"> + <h1 className='text-2xl font-semibold text-center md:text-left'> Daftar Akun Indoteknik </h1> - <h2 className="text-gray_r-11 mt-1 mb-4 text-center md:text-left"> + <h2 className='text-gray_r-11 mt-1 mb-4 text-center md:text-left'> Buat akun sekarang lebih mudah dan terverifikasi </h2> - <label htmlFor="name" className="text-black font-bold"> + <label htmlFor='name' className='text-black font-bold'> Tipe Akun </label> - <div className="grid grid-cols-2 gap-x-3 mt-2 h-14 font-bold text-black hover:cursor-pointer"> + <div className='grid grid-cols-2 gap-x-3 mt-2 h-14 font-bold text-black hover:cursor-pointer'> <div className={` border rounded-md flex justify-center items-center transition-colors duration-300 ease-in-out ${ - isIndividuClicked ? "bg-red-500 text-white" : "" + isIndividuClicked ? 'bg-red-500 text-white' : '' }`} onClick={handleIndividuClick} > @@ -120,50 +132,56 @@ const Register = () => { </div> <div className={` border rounded-md flex justify-center items-center transition-colors duration-300 ease-in-out ${ - isBisnisClicked ? "bg-red-500 text-white" : "" + isBisnisClicked ? 'bg-red-500 text-white' : '' }`} onClick={handleBisnisClick} > <p>Bisnis</p> </div> </div> - <div className="transition-opacity duration-300 ease-in-out"> + <div className='transition-opacity duration-300 ease-in-out'> {isIndividuClicked && ( - <div className="opacity-100"> - <RegistrasiIndividu /> + <div className='opacity-100'> + <RegistrasiIndividu chekValid={notValid} /> </div> )} {isBisnisClicked && ( - <div className="opacity-100"> - <RegistrasiBisnis /> + <div className='opacity-100'> + <RegistrasiBisnis chekValid={notValid} /> </div> )} </div> - <section className="mt-2"> + <section className='mt-2'> {/* <FormCaptcha /> */} <TermCondition /> <Button - type="submit" - colorScheme="red" - className="w-full mt-2" + type='submit' + colorScheme='red' + className='w-full mt-2' size='lg' onClick={handleSubmit} - // isDisabled = {!isFormValid || !isCheckedTNC || mutation.isLoading || !isValidCaptcha} - isDisabled = {!isFormValid || !isCheckedTNC || mutation.isLoading} + // isDisabled = {!isFormValid || !isCheckedTNC || mutation.isLoading || !isValidCaptcha} + isDisabled={!isCheckedTNC || mutation.isLoading} > {mutation.isLoading ? 'Loading...' : 'Daftar'} </Button> </section> - <section className="flex justify-center items-center flex-col"> - <div className="text-gray_r-11 mt-4 text-center md:text-left"> - Sudah punya akun Indoteknik?{" "} - <Link href="/login" className="inline font-medium text-danger-500"> + <section className='flex justify-center items-center flex-col'> + <div className='text-gray_r-11 mt-4 text-center md:text-left'> + Sudah punya akun Indoteknik?{' '} + <Link + href='/login' + className='inline font-medium text-danger-500' + > Masuk </Link> </div> - <div className="text-gray_r-11 mt-4 text-center md:text-left"> - Akun anda belum aktif?{" "} - <Link href="/register?activation=email" className="inline font-medium text-danger-500"> + <div className='text-gray_r-11 mt-4 text-center md:text-left'> + Akun anda belum aktif?{' '} + <Link + href='/register?activation=email' + className='inline font-medium text-danger-500' + > Aktivasi </Link> </div> @@ -171,8 +189,8 @@ const Register = () => { </div> </section> - <section className="my-10 md:my-0"> - <PageContent path="/register" /> + <section className='my-10 md:my-0'> + <PageContent path='/register' /> </section> </div> |
