summaryrefslogtreecommitdiff
path: root/src-migrate/modules/register/components
diff options
context:
space:
mode:
Diffstat (limited to 'src-migrate/modules/register/components')
-rw-r--r--src-migrate/modules/register/components/Form.tsx252
-rw-r--r--src-migrate/modules/register/components/FormBisnis.tsx715
-rw-r--r--src-migrate/modules/register/components/RegistrasiBisnis.tsx197
-rw-r--r--src-migrate/modules/register/components/RegistrasiIndividu.tsx34
-rw-r--r--src-migrate/modules/register/components/TermCondition.tsx2
5 files changed, 1068 insertions, 132 deletions
diff --git a/src-migrate/modules/register/components/Form.tsx b/src-migrate/modules/register/components/Form.tsx
index b834f97a..38e9c810 100644
--- a/src-migrate/modules/register/components/Form.tsx
+++ b/src-migrate/modules/register/components/Form.tsx
@@ -1,179 +1,169 @@
-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";
-
-const Form = () => {
- const {
- form,
- isCheckedTNC,
- isValidCaptcha,
- errors,
- updateForm,
- validate,
- } = useRegisterStore()
-
- const isFormValid = useMemo(() => Object.keys(errors).length === 0, [errors])
-
- const router = useRouter()
- const toast = useToast()
+import { ChangeEvent, useMemo, useEffect, useRef, useState } 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;
+ buttonSubmitClick: boolean;
+}
+
+const Form: React.FC<FormProps> = ({
+ type,
+ required,
+ isBisnisRegist = false,
+ chekValid,
+ buttonSubmitClick,
+}) => {
+ const { form, isCheckedTNC, isValidCaptcha, errors, updateForm, validate } =
+ useRegisterStore();
+ const isFormValid = useMemo(() => Object.keys(errors).length === 0, [errors]);
+
+ const router = useRouter();
+ const toast = useToast();
+
+ const emailRef = useRef<HTMLInputElement>(null);
+ const nameRef = useRef<HTMLInputElement>(null);
+ const passwordRef = useRef<HTMLInputElement>(null);
+ const phoneRef = useRef<HTMLInputElement>(null);
const handleInputChange = (event: ChangeEvent<HTMLInputElement>) => {
const { name, value } = event.target;
- updateForm(name, value)
- validate()
- }
-
- const mutation = useMutation({
- mutationFn: (data: RegisterProps) => registerUser(data)
- })
-
- const handleSubmit = async (e: ChangeEvent<HTMLFormElement>) => {
- e.preventDefault()
-
- 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}`)
- }
-
- const toastProps: UseToastOptions = {
- duration: 5000,
- isClosable: true
- }
-
- switch (response?.reason) {
- case 'EMAIL_USED':
- toast({
- ...toastProps,
- title: 'Email sudah digunakan',
- status: 'warning'
- })
- break;
- case 'NOT_ACTIVE':
- 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
- }
- }
+ updateForm(name, value);
+ validate();
+ };
+ useEffect(() => {
+ const loadIndustries = async () => {
+ if (!isFormValid) {
+ const options: ScrollIntoViewOptions = {
+ behavior: 'smooth',
+ block: 'center',
+ };
+
+ if (errors.email_partner && emailRef.current) {
+ emailRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errors.name && nameRef.current) {
+ nameRef.current.scrollIntoView(options);
+ return;
+ }
+
+ if (errors.password && passwordRef.current) {
+ passwordRef.current.scrollIntoView(options);
+ return;
+ }
+
+ if (errors.phone && phoneRef.current) {
+ phoneRef.current.scrollIntoView(options);
+ return;
+ }
+ }
+ };
+ loadIndustries();
+ }, [buttonSubmitClick, chekValid]);
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'>
<div>
- <label htmlFor="company">
- Nama Perusahaan <span className='text-gray_r-11'>(opsional)</span>
+ <label htmlFor='name' className='text-black font-bold'>
+ Nama Lengkap
</label>
<input
- type="text"
- name="company"
- id="company"
- className="form-input mt-3"
- placeholder="cth: INDOTEKNIK DOTCOM GEMILANG"
- autoCapitalize="true"
- value={form.company}
- onChange={handleInputChange}
- />
- </div>
-
- <div>
- <label htmlFor='name'>Nama Lengkap</label>
-
- <input
type='text'
id='name'
name='name'
- className='form-input mt-3'
+ className='form-input mt-3 transition-all duration-700'
placeholder='Masukan nama lengkap anda'
value={form.name}
+ ref={nameRef}
onChange={handleInputChange}
- aria-invalid={!!errors.name}
- />
-
- {!!errors.name && <span className="form-msg-danger">{errors.name}</span>}
- </div>
-
- <div>
- <label htmlFor='phone'>No Handphone</label>
-
- <input
- type='tel'
- id='phone'
- name='phone'
- className='form-input mt-3'
- placeholder='08xxxxxxxx'
- value={form.phone}
- onChange={handleInputChange}
- aria-invalid={!!errors.phone}
+ aria-invalid={chekValid && !!errors.name}
/>
- {!!errors.phone && <span className="form-msg-danger">{errors.phone}</span>}
+ {chekValid && !!errors.name && (
+ <span className='form-msg-danger'>{errors.name}</span>
+ )}
</div>
<div>
- <label htmlFor='email'>Alamat Email</label>
+ <label htmlFor='email' className='text-black font-bold'>
+ Alamat Email
+ </label>
<input
type='text'
id='email'
name='email'
- className='form-input mt-3'
+ className='form-input mt-3 transition-all duration-500'
placeholder='Masukan alamat email anda'
value={form.email}
+ ref={emailRef}
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'>Kata Sandi</label>
+ <label htmlFor='password' className='text-black font-bold'>
+ Kata Sandi
+ </label>
<input
type='password'
name='password'
id='password'
- className='form-input mt-3'
+ className='form-input mt-3 transition-all duration-500'
placeholder='••••••••••••'
value={form.password}
+ ref={passwordRef}
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>
- <FormCaptcha />
+ <div>
+ <label htmlFor='phone' className='text-black font-bold'>
+ No Handphone
+ </label>
- <TermCondition />
+ <input
+ type='tel'
+ id='phone'
+ name='phone'
+ className='form-input mt-3 transition-all duration-500'
+ placeholder='08xxxxxxxx'
+ value={form.phone}
+ ref={phoneRef}
+ onChange={handleInputChange}
+ aria-invalid={chekValid && !!errors.phone}
+ />
- <button
- type="submit"
- className="btn-yellow w-full mt-2"
- disabled={!isFormValid || !isCheckedTNC || mutation.isLoading || !isValidCaptcha}
- >
- {mutation.isLoading ? 'Loading...' : 'Daftar'}
- </button>
+ {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
new file mode 100644
index 00000000..5ee19e58
--- /dev/null
+++ b/src-migrate/modules/register/components/FormBisnis.tsx
@@ -0,0 +1,715 @@
+import { ChangeEvent, useEffect, useMemo, useRef, 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 { 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';
+interface FormProps {
+ type: string;
+ required: boolean;
+ isPKP: boolean;
+ chekValid: boolean;
+ buttonSubmitClick: boolean;
+}
+
+interface industry_id {
+ label: string;
+ value: string;
+ category: string;
+}
+
+interface companyType {
+ value: string;
+ label: string;
+}
+
+const form: React.FC<FormProps> = ({
+ type,
+ required,
+ isPKP,
+ chekValid,
+ buttonSubmitClick,
+}) => {
+ 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();
+ // Inside your component
+ 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[]>([]);
+
+ const router = useRouter();
+ const toast = useToast();
+
+ const emailRef = useRef<HTMLInputElement>(null);
+ const businessNameRef = useRef<HTMLInputElement>(null);
+ const companyTypeRef = useRef<HTMLInputElement>(null);
+ const industryRef = useRef<HTMLDivElement>(null);
+ const addressRef = useRef<HTMLInputElement>(null);
+ const namaWajibPajakRef = useRef<HTMLInputElement>(null);
+ const alamatWajibPajakRef = useRef<HTMLInputElement>(null);
+ const npwpRef = useRef<HTMLInputElement>(null);
+ const sppkpRef = useRef<HTMLInputElement>(null);
+ const docsSppkpRef = useRef<HTMLInputElement>(null);
+ const docsNpwpRef = useRef<HTMLInputElement>(null);
+
+ 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,
+ }))
+ );
+ };
+ loadCompanyTypes();
+ }, []);
+
+ useEffect(() => {
+ const selectedCompanyType = companyTypes.find(
+ (company) => company.value === watch('companyType')
+ );
+ if (selectedCompanyType) {
+ updateForm('company_type_id', `${selectedCompanyType?.value}`);
+ validate();
+ }
+ }, [watch('companyType'), companyTypes]);
+
+ useEffect(() => {
+ const selectedIndustryType = industries.find(
+ (industry) => industry.value === watch('industry_id')
+ );
+ if (selectedIndustryType) {
+ updateForm('industry_id', `${selectedIndustryType?.value}`);
+ setSelectedCategory(selectedIndustryType.category);
+ validate();
+ }
+ }, [watch('industry_id'), industries]);
+
+ 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,
+ }))
+ );
+ };
+ loadIndustries();
+ }, []);
+
+ const handleInputChange = (event: ChangeEvent<HTMLInputElement>) => {
+ const { name, value } = event.target;
+
+ updateForm('type_acc', 'business');
+ updateForm('is_pkp', `${isPKP}`);
+
+ // Update form dengan nilai terbaru dari input yang berubah
+ updateForm(name, value);
+
+ // Jika checkbox aktif, sinkronisasi alamat_wajib_pajak dengan alamat_bisnis
+ if (isChekBox) {
+ if (name === 'alamat_wajib_pajak') {
+ updateForm('alamat_bisnis', value);
+ } else if (name === 'alamat_bisnis') {
+ updateForm('alamat_wajib_pajak', value);
+ }
+ }
+
+ // Validasi setelah perubahan dilakukan
+ validate();
+ };
+
+ const handleInputChangeNpwp = (event: ChangeEvent<HTMLInputElement>) => {
+ const { name, value } = event.target;
+ updateForm('type_acc', `business`);
+ updateForm('is_pkp', `${isPKP}`);
+ updateForm('npwp', value);
+ validate();
+ };
+
+ const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
+ 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})$/
+ );
+ }
+
+ if (match) {
+ return [
+ match[1],
+ match[2] ? '.' : '',
+ match[2],
+ match[3] ? '.' : '',
+ match[3],
+ match[4] ? '.' : '',
+ match[4],
+ match[5] ? '-' : '',
+ match[5],
+ match[6] ? '.' : '',
+ match[6],
+ ].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);
+ return value;
+ }
+ };
+
+ useEffect(() => {
+ if (isChekBox) {
+ updateForm('isChekBox', 'true');
+ updateForm('alamat_wajib_pajak', `${form.alamat_bisnis}`);
+ validate();
+ } else {
+ updateForm('isChekBox', 'false');
+ validate();
+ }
+ }, [isChekBox]);
+
+ const handleFileChange = async (event: ChangeEvent<HTMLInputElement>) => {
+ const toastProps: UseToastOptions = {
+ duration: 5000,
+ isClosable: true,
+ position: 'top',
+ };
+
+ let fileBase64 = '';
+ const { name } = event.target;
+ const file = event.target.files?.[0];
+
+ // Allowed file extensions
+ const allowedExtensions = ['pdf', 'doc', 'docx', 'png', 'jpg', 'jpeg'];
+
+ if (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;
+ }
+
+ // 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 isFormValid = useMemo(() => Object.keys(errors).length === 0, [errors]);
+
+ useEffect(() => {
+ const loadIndustries = async () => {
+ if (!isFormValid) {
+ const options: ScrollIntoViewOptions = {
+ behavior: 'smooth',
+ block: 'center',
+ };
+ if (errors.email_partner && emailRef.current) {
+ emailRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errors.company_type_id && companyTypeRef.current) {
+ companyTypeRef.current.scrollIntoView(options);
+ return;
+ }
+
+ if (errors.business_name && businessNameRef.current) {
+ businessNameRef.current.scrollIntoView(options);
+ return;
+ }
+
+ if (errors.industry_id && industryRef.current) {
+ industryRef.current.scrollIntoView(options);
+ return;
+ }
+
+ if (errors.alamat_bisnis && addressRef.current) {
+ addressRef.current.scrollIntoView(options);
+ return;
+ }
+
+ if (errors.npwp && npwpRef.current) {
+ npwpRef.current.scrollIntoView(options);
+ return;
+ }
+
+ if (errors.sppkp && sppkpRef.current) {
+ sppkpRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errors.sppkp_document && docsSppkpRef.current) {
+ docsSppkpRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errors.npwp_document && docsNpwpRef.current) {
+ docsNpwpRef.current.scrollIntoView(options);
+ return;
+ }
+ }
+ };
+ loadIndustries();
+ }, [buttonSubmitClick, chekValid]);
+ return (
+ <>
+ <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}
+ />
+ </div>
+ </BottomPopup>
+ <form
+ className={` ${
+ type === 'bisnis'
+ ? 'mt-6 grid grid-cols-1 gap-y-4'
+ : 'mt-6 grid grid-cols-2 gap-x-4 gap-y-2'
+ }`}
+ >
+ <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 max-h-11 mt-3 transition-all duration-500 ${
+ required ? 'cursor-no-drop' : ''
+ }`}
+ disabled={required}
+ contentEditable={required}
+ readOnly={required}
+ onChange={handleInputChange}
+ autoComplete='username'
+ ref={emailRef}
+ 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>
+ <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 mt-3'>
+ <div
+ className='w-4/5 pr-1 max-h-11 transition-all duration-500'
+ ref={companyTypeRef}
+ >
+ <Controller
+ name='companyType'
+ control={control}
+ render={(props) => (
+ <HookFormSelect
+ {...props}
+ options={companyTypes}
+ disabled={required}
+ placeholder='Badan Usaha'
+ />
+ )}
+ />
+ {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 max-h-11 transition-all duration-500'
+ placeholder='Nama Perusahaan'
+ autoCapitalize='true'
+ value={form.business_name}
+ ref={businessNameRef}
+ aria-invalid={chekValid && !!errors.business_name}
+ onChange={handleInputChange}
+ />
+
+ {chekValid && !!errors.business_name && (
+ <span className='form-msg-danger'>{errors.business_name}</span>
+ )}
+ </div>
+ </div>
+ </div>
+
+ <div className='mt-8 md:mt-0'>
+ <label className='font-bold' htmlFor='business_name'>
+ Klasifikasi Jenis Usaha
+ </label>
+ <div
+ className='max-h-10 transition-all duration-500'
+ ref={industryRef}
+ >
+ <Controller
+ name='industry_id'
+ control={control}
+ render={(props) => (
+ <HookFormSelect
+ {...props}
+ options={industries}
+ disabled={required}
+ placeholder={'Select industry'}
+ />
+ )}
+ />
+ </div>
+ {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 max-h-11 transition-all duration-500 ${
+ required ? 'cursor-no-drop' : ''
+ }`}
+ disabled={required}
+ contentEditable={required}
+ readOnly={required}
+ ref={addressRef}
+ 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 max-h-11 transition-all duration-500${
+ required ? 'cursor-no-drop' : ''
+ }`}
+ disabled={required}
+ contentEditable={required}
+ readOnly={required}
+ onChange={handleInputChange}
+ ref={namaWajibPajakRef}
+ aria-invalid={
+ chekValid && isPKP && !required && !!errors.nama_wajib_pajak
+ }
+ />
+
+ {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'
+ isChecked={isChekBox}
+ onChange={handleChange}
+ />
+ <span className='text-caption-2 ml-2 font-normal italic'>
+ 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 max-h-11 mt-3 transition-all duration-500 ${
+ required ? 'cursor-no-drop' : ''
+ }`}
+ disabled={isChekBox || required}
+ contentEditable={required}
+ readOnly={required}
+ onChange={handleInputChange}
+ ref={alamatWajibPajakRef}
+ aria-invalid={
+ chekValid && isPKP && !required && !!errors.alamat_wajib_pajak
+ }
+ />
+
+ {chekValid && 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 max-h-11 mt-3 transition-all duration-500 ${
+ required ? 'cursor-no-drop' : ''
+ }`}
+ disabled={required}
+ contentEditable={required}
+ readOnly={required}
+ ref={npwpRef}
+ 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>
+ }
+ </label>
+
+ <input
+ type='tel'
+ id='sppkp'
+ name='sppkp'
+ className={`form-input max-h-11 mt-3 transition-all duration-500 ${
+ required ? 'cursor-no-drop' : ''
+ }`}
+ disabled={required}
+ contentEditable={required}
+ readOnly={required}
+ ref={sppkpRef}
+ 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>
+
+ <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 transition-all duration-500 ${
+ type === 'bisnis' ? '' : 'border-none'
+ } mt-3 ${required ? 'cursor-no-drop' : ''}`}
+ disabled={required}
+ contentEditable={required}
+ ref={docsNpwpRef}
+ 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 transition-all duration-500 ${
+ type === 'bisnis' ? '' : 'border-none'
+ } mt-3 ${required ? 'cursor-no-drop' : ''}`}
+ disabled={required}
+ contentEditable={required}
+ ref={docsSppkpRef}
+ 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
new file mode 100644
index 00000000..ce4d3972
--- /dev/null
+++ b/src-migrate/modules/register/components/RegistrasiBisnis.tsx
@@ -0,0 +1,197 @@
+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;
+ buttonSubmitClick: boolean;
+}
+const RegistrasiBisnis: React.FC<FormProps> = ({
+ chekValid,
+ buttonSubmitClick,
+}) => {
+ 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 mutation = useMutation({
+ mutationFn: (data: RegisterProps) => registerUser(data),
+ });
+
+ useEffect(() => {
+ if (selectedValue === 'PKP') {
+ updateForm('is_pkp', 'true');
+ validate();
+ } else {
+ updateForm('is_pkp', 'false');
+ validate();
+ }
+ }, [selectedValue]);
+
+ useEffect(() => {
+ if (isTerdaftar) {
+ updateForm('is_terdaftar', 'true');
+ validate();
+ } else {
+ updateForm('is_terdaftar', 'false');
+ validate();
+ }
+ }, [isTerdaftar]);
+
+ const handleChange = (value: string) => {
+ setSelectedValue(value);
+ if (value === 'PKP') {
+ validate();
+ setIsPKP(true);
+ } else {
+ validate();
+ setIsPKP(false);
+ setIsPKP(false);
+ }
+ };
+
+ const handleChangeBisnis = (value: string) => {
+ setSelectedValueBisnis(value);
+ if (value === 'true') {
+ validate();
+ setIsTerdaftar(true);
+ } else {
+ validate();
+ setIsTerdaftar(false);
+ }
+ };
+
+ const handleClick = () => {
+ setIsDropIndividu(!isDropIndividu);
+ };
+
+ const handleClickBisnis = () => {
+ 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'>
+ Data Akun
+ </p>
+ {isDropIndividu ? (
+ <div className='flex'>
+ <ChevronDownIcon
+ onClick={handleClick}
+ className='h-6 w-6 text-black'
+ />
+ </div>
+ ) : (
+ <ChevronRightIcon
+ onClick={handleClick}
+ className='h-6 w-6 text-black'
+ />
+ )}
+ </div>
+ {isDropIndividu && (
+ <div>
+ <Divider my={4} />
+ <Form
+ type='bisnis'
+ required={true}
+ isBisnisRegist={true}
+ chekValid={chekValid}
+ buttonSubmitClick={buttonSubmitClick}
+ />
+ </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'>
+ Data Bisnis
+ </p>
+ {isBisnisClicked ? (
+ <div className='flex'>
+ <ChevronDownIcon
+ onClick={handleClickBisnis}
+ className='h-6 w-6 text-black'
+ />
+ </div>
+ ) : (
+ <ChevronRightIcon
+ onClick={handleClickBisnis}
+ className='h-6 w-6 text-black'
+ />
+ )}
+ </div>
+ {isBisnisClicked && (
+ <div>
+ <Divider my={4} />
+ <div>
+ <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>
+ </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}
+ chekValid={chekValid}
+ buttonSubmitClick={buttonSubmitClick}
+ />
+ </div>
+ )}
+ </div>
+ </div>
+
+ <h1 className=''></h1>
+ </>
+ );
+};
+
+export default RegistrasiBisnis;
diff --git a/src-migrate/modules/register/components/RegistrasiIndividu.tsx b/src-migrate/modules/register/components/RegistrasiIndividu.tsx
new file mode 100644
index 00000000..84049065
--- /dev/null
+++ b/src-migrate/modules/register/components/RegistrasiIndividu.tsx
@@ -0,0 +1,34 @@
+import Form from './Form';
+import { useRegisterStore } from '../stores/useRegisterStore';
+import { useEffect } from 'react';
+interface FormProps {
+ chekValid: boolean;
+ buttonSubmitClick: boolean;
+}
+const RegistrasiIndividu: React.FC<FormProps> = ({
+ chekValid,
+ buttonSubmitClick,
+}) => {
+ const { form, errors, updateForm, validate } = useRegisterStore();
+
+ useEffect(() => {
+ updateForm('is_pkp', 'false');
+ updateForm('is_terdaftar', 'false');
+ updateForm('type_acc', 'individu');
+ validate();
+ }, []);
+
+ return (
+ <>
+ <Form
+ type='individu'
+ required={false}
+ isBisnisRegist={false}
+ chekValid={chekValid}
+ buttonSubmitClick={buttonSubmitClick}
+ />
+ </>
+ );
+};
+
+export default RegistrasiIndividu;
diff --git a/src-migrate/modules/register/components/TermCondition.tsx b/src-migrate/modules/register/components/TermCondition.tsx
index b7729deb..d54fe921 100644
--- a/src-migrate/modules/register/components/TermCondition.tsx
+++ b/src-migrate/modules/register/components/TermCondition.tsx
@@ -10,7 +10,7 @@ const TermCondition = () => {
return (
<>
<div className="mt-4 flex items-center gap-x-2">
- <Checkbox id='tnc' name='tnc' isChecked={isCheckedTNC} onChange={toggleCheckTNC} />
+ <Checkbox id='tnc' name='tnc' colorScheme='red' isChecked={isCheckedTNC} onChange={toggleCheckTNC} />
<div>
<label htmlFor="tnc" className="cursor-pointer">Dengan ini saya menyetujui</label>
{' '}