summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorit-fixcomart <it@fixcomart.co.id>2024-08-20 10:27:32 +0700
committerit-fixcomart <it@fixcomart.co.id>2024-08-20 10:27:32 +0700
commit00df44e6f25eaeabc56ebba8b4e9b1cb692928d7 (patch)
tree8a5c8aa1a0890aa2afa9966db457cd98a43fe625
parent6d302bb338e26810a7f90326b84086217f1f4ae0 (diff)
<iman> add new register
-rw-r--r--src-migrate/modules/register/components/Form.tsx89
-rw-r--r--src-migrate/modules/register/components/FormBisnis.tsx230
-rw-r--r--src-migrate/modules/register/components/RegistrasiBisnis.tsx105
-rw-r--r--src-migrate/modules/register/components/RegistrasiIndividu.tsx11
-rw-r--r--src-migrate/modules/register/index.tsx126
-rw-r--r--src-migrate/modules/register/stores/useRegisterStore.ts1
6 files changed, 481 insertions, 81 deletions
diff --git a/src-migrate/modules/register/components/Form.tsx b/src-migrate/modules/register/components/Form.tsx
index b834f97a..7d18f4ee 100644
--- a/src-migrate/modules/register/components/Form.tsx
+++ b/src-migrate/modules/register/components/Form.tsx
@@ -9,7 +9,12 @@ import { useRouter } from "next/router";
import { UseToastOptions, useToast } from "@chakra-ui/react";
import Link from "next/link";
-const Form = () => {
+interface FormProps {
+ type: string;
+ required: boolean;
+}
+
+const Form: React.FC<FormProps> = ({ type, required }) => {
const {
form,
isCheckedTNC,
@@ -75,25 +80,9 @@ const Form = () => {
return (
<form className="mt-6 grid grid-cols-1 gap-y-4" onSubmit={handleSubmit}>
- <div>
- <label htmlFor="company">
- Nama Perusahaan <span className='text-gray_r-11'>(opsional)</span>
- </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>
+ <label htmlFor='name' className="text-black font-bold">Nama Lengkap</label>
<input
type='text'
@@ -110,24 +99,7 @@ const Form = () => {
</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}
- />
-
- {!!errors.phone && <span className="form-msg-danger">{errors.phone}</span>}
- </div>
-
- <div>
- <label htmlFor='email'>Alamat Email</label>
+ <label htmlFor='email' className="text-black font-bold">Alamat Email</label>
<input
type='text'
@@ -143,9 +115,9 @@ const Form = () => {
{!!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'
@@ -161,17 +133,40 @@ const Form = () => {
{!!errors.password && <span className="form-msg-danger">{errors.password}</span>}
</div>
- <FormCaptcha />
+ <div>
+ <label htmlFor='phone' className="text-black font-bold">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}
+ />
+
+ {!!errors.phone && <span className="form-msg-danger">{errors.phone}</span>}
+ </div>
+
+ {type==='individu' && (
+ <>
+ <FormCaptcha />
+
+ <TermCondition />
+ <button
+ type="submit"
+ className="btn-yellow w-full mt-2"
+ disabled={!isFormValid || !isCheckedTNC || mutation.isLoading || !isValidCaptcha}
+ >
+ {mutation.isLoading ? 'Loading...' : 'Daftar'}
+ </button>
+ </>
+
+ )}
- <TermCondition />
- <button
- type="submit"
- className="btn-yellow w-full mt-2"
- disabled={!isFormValid || !isCheckedTNC || mutation.isLoading || !isValidCaptcha}
- >
- {mutation.isLoading ? 'Loading...' : 'Daftar'}
- </button>
</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..85e37875
--- /dev/null
+++ b/src-migrate/modules/register/components/FormBisnis.tsx
@@ -0,0 +1,230 @@
+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 { useRouter } from "next/router";
+import { UseToastOptions, useToast } from "@chakra-ui/react";
+import Link from "next/link";
+import getFileBase64 from '@/core/utils/getFileBase64'
+
+interface FormProps {
+ type: string;
+ required: boolean;
+}
+
+const Form: React.FC<FormProps> = ({ type, required }) => {
+ const {
+ form,
+ isCheckedTNC,
+ isValidCaptcha,
+ errors,
+ updateForm,
+ validate,
+ } = useRegisterStore()
+
+ const isFormValid = useMemo(() => Object.keys(errors).length === 0, [errors])
+
+ const router = useRouter()
+ const toast = useToast()
+
+ const handleInputChange = (event: ChangeEvent<HTMLInputElement>) => {
+ const { name, value } = event.target;
+ updateForm(name, value)
+ validate()
+ }
+
+ const handleFileChange = async (event: ChangeEvent<HTMLInputElement>) => {
+ let fileBase64 = ''
+ const file = event.target.files?.[0];
+ if (file) {
+ if (typeof file !== 'undefined') {
+ if (file.size > 5000000) {
+ // toast.error('Maksimal ukuran file adalah 5MB')
+ return
+ }
+ fileBase64 = await getFileBase64(file)
+ }
+ updateForm("document", fileBase64); // Menyimpan file ke dalam form state
+ 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
+ }
+ }
+
+
+ return (
+ <form className="mt-6 grid grid-cols-1 gap-y-4" onSubmit={handleSubmit}>
+ <div>
+ <label htmlFor='email'>Email Bisnis</label>
+
+ <input
+ type='text'
+ id='email'
+ name='email'
+ className='form-input mt-3'
+ placeholder='example@email.com'
+ value={form.email}
+ onChange={handleInputChange}
+ autoComplete="username"
+ aria-invalid={!!errors.email}
+ />
+
+ {!!errors.email && <span className="form-msg-danger">{errors.email}</span>}
+ </div>
+
+ <div>
+ <label htmlFor="company">
+ Nama Bisnis <span className='text-gray_r-11'>(opsional)</span>
+ </label>
+ <div className="flex justify-between items-center gap-2 h-12">
+ <select
+ className="w-3/4 border h-full rounded-sm"
+ >
+ <option value=''>Pilih Site</option>
+ </select>
+
+ <input
+ type="text"
+ name="company"
+ id="company"
+ className="form-input h-full w-[120%]"
+ placeholder="Nama Perusahaan"
+ autoCapitalize="true"
+ value={form.company}
+ onChange={handleInputChange}
+ />
+ </div>
+ </div>
+
+ <div>
+ <label htmlFor="company">
+ Klasifikasi Jenis Usaha <span className='text-gray_r-11'>(opsional)</span>
+ </label>
+ <div className="flex justify-between flex-col items-center h-12">
+ <select
+ className="w-full border h-full rounded-sm"
+ >
+ <option value=''>After Market Auto Shop</option>
+ </select>
+ </div>
+ <span className='text-gray_r-11 text-xs'>Kategori: Industri Otomotif, Bengkel, Car Wash</span>
+ </div>
+
+ <div>
+ <label htmlFor='name'>Nama Wajib Pajak</label>
+
+ <input
+ type='text'
+ id='name'
+ name='name'
+ className='form-input mt-3'
+ placeholder='Masukan nama lengkap anda'
+ value={form.name}
+ onChange={handleInputChange}
+ aria-invalid={!!errors.name}
+ />
+
+ {!!errors.name && <span className="form-msg-danger">{errors.name}</span>}
+ </div>
+
+ <div>
+ <label htmlFor='phone'>Nomor NPWP</label>
+
+ <input
+ type='tel'
+ id='phone'
+ name='phone'
+ className='form-input mt-3'
+ placeholder='08xxxxxxxx'
+ value={form.phone}
+ onChange={handleInputChange}
+ aria-invalid={!!errors.phone}
+ />
+
+ {!!errors.phone && <span className="form-msg-danger">{errors.phone}</span>}
+ </div>
+
+ <div>
+ <label htmlFor="document">Dokumen NPWP (opsional)</label>
+
+ <input
+ type="file"
+ id="document"
+ name="document"
+ className="form-input mt-3"
+ onChange={handleFileChange}
+ accept=".pdf,.doc,.docx,.png,.jpg,.jpeg" // Filter file types
+ />
+
+ {/* {!!errors.document && <span className="form-msg-danger">{errors.document}</span>} */}
+ </div>
+
+ <div>
+ <label htmlFor="document">Dokumen SPPKP (opsional)</label>
+
+ <input
+ type="file"
+ id="document"
+ name="document"
+ className="form-input mt-3"
+ onChange={handleFileChange}
+ accept=".pdf,.doc,.docx,.png,.jpg,.jpeg" // Filter file types
+ />
+
+ {/* {!!errors.document && <span className="form-msg-danger">{errors.document}</span>} */}
+ </div>
+
+ <button
+ type="submit"
+ className="btn-yellow w-full mt-2"
+ disabled={!isFormValid || !isCheckedTNC || mutation.isLoading || !isValidCaptcha}
+ >
+ {mutation.isLoading ? 'Loading...' : 'Daftar'}
+ </button>
+ </form>
+ )
+}
+
+export default Form \ No newline at end of file
diff --git a/src-migrate/modules/register/components/RegistrasiBisnis.tsx b/src-migrate/modules/register/components/RegistrasiBisnis.tsx
new file mode 100644
index 00000000..217b4c79
--- /dev/null
+++ b/src-migrate/modules/register/components/RegistrasiBisnis.tsx
@@ -0,0 +1,105 @@
+import { useState } from "react";
+import FormBisnis from "./FormBisnis";
+import Form from "./Form";
+import TermCondition from "./TermCondition";
+import FormCaptcha from "./FormCaptcha";
+import { Radio, RadioGroup, Stack, Divider } from '@chakra-ui/react'
+import React from "react";
+import {
+ ChevronDownIcon,
+ ChevronRightIcon
+} from '@heroicons/react/24/outline';
+
+const RegistrasiBisnis = () => {
+ const [isPKP, setIsPKP] = useState(false);
+ const [isTerdaftar, setIsTerdaftar] = useState(false);
+ const [isIndividuRequired, setIsIndividuRequired] = useState(true);
+ const [isBisnisRequired, setIsBisnisRequired] = useState(true);
+ const [selectedValue, setSelectedValue] = useState('PKP');
+
+ const handleChange = (value: string) => {
+ setSelectedValue(value);
+ if (value === "PKP") {
+ setIsPKP(true);
+ setIsIndividuRequired(true); // Show and require Individu form
+ } else {
+ setIsPKP(false);
+ setIsIndividuRequired(false); // Hide and make optional the Individu form
+ }
+ };
+
+ const handleClick = () => {
+ setIsIndividuRequired(!isIndividuRequired)
+ };
+
+ const handleClickBisnis = () => {
+ setIsBisnisRequired(!isBisnisRequired)
+ };
+
+ return (
+ <>
+ <div>
+ <p className="text-black font-bold">Tipe Bisnis</p>
+ <RadioGroup onChange={handleChange} value={selectedValue}>
+ <Stack direction='row'>
+ <Radio value='PKP'>PKP</Radio>
+ <Radio value='Non-PKP'>Non-PKP</Radio>
+ </Stack>
+ </RadioGroup>
+ </div>
+ <div className="mt-4 border">
+ <div className="p-4">
+ <div onClick={handleClick} className="flex justify-between">
+ <p>Data Akun</p>
+ {isIndividuRequired ? (
+ <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>
+ {isIndividuRequired && (
+ <div>
+ <Divider my={4} />
+ <Form type="bisnis" required={isIndividuRequired} />
+ </div>
+ )}
+ </div>
+ </div>
+ <div className="mt-4 border">
+ <div className="p-4">
+ <div onClick={handleClickBisnis} className="flex justify-between">
+ <p>Data Bisnis</p>
+ {isBisnisRequired ? (
+ <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>
+ {isBisnisRequired && (
+ <div>
+ <Divider my={4} />
+ <div>
+ <p className="text-black font-bold">Bisnis Terdaftar di Indoteknik?</p>
+ <RadioGroup onChange={handleChange} value={selectedValue}>
+ <Stack direction='row'>
+ <Radio value='true'>Sudah Terdaftar</Radio>
+ <Radio value='false'>Belum Terdaftar</Radio>
+ </Stack>
+ </RadioGroup>
+ </div>
+ <FormBisnis type="bisnis" required={isIndividuRequired} />
+ </div>
+ )}
+ </div>
+ </div>
+ <FormCaptcha />
+ <TermCondition />
+ </>
+ );
+};
+
+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..eff86124
--- /dev/null
+++ b/src-migrate/modules/register/components/RegistrasiIndividu.tsx
@@ -0,0 +1,11 @@
+import Form from "./Form";
+const RegistrasiIndividu = () => {
+
+ return (
+ <>
+ <Form type='individu' required={false}/>
+ </>
+ );
+};
+
+export default RegistrasiIndividu;
diff --git a/src-migrate/modules/register/index.tsx b/src-migrate/modules/register/index.tsx
index 00931284..9b3f5509 100644
--- a/src-migrate/modules/register/index.tsx
+++ b/src-migrate/modules/register/index.tsx
@@ -1,43 +1,101 @@
-import PageContent from "~/modules/page-content"
-import Form from "./components/Form"
-import Link from "next/link"
-import Image from "next/image"
-import IndoteknikLogo from "~/images/logo.png"
-import AccountActivation from "../account-activation"
+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 { useState } from "react";
const LOGO_WIDTH = 150;
const LOGO_HEIGHT = LOGO_WIDTH / 3;
const Register = () => {
+ const [isIndividuClicked, setIsIndividuClicked] = useState(true);
+ const [isBisnisClicked, setIsBisnisClicked] = useState(false);
+
+ const handleIndividuClick = () => {
+ setIsIndividuClicked(true);
+ setIsBisnisClicked(false);
+ };
+
+ const handleBisnisClick = () => {
+ setIsIndividuClicked(false);
+ setIsBisnisClicked(true);
+ };
+
return (
<div className="container">
- <div className="grid grid-cols-1 md:grid-cols-2 gap-x-10 pt-10 px-2 md:pt-16">
- <section>
- <Link href='/' className="block md:hidden">
- <Image src={IndoteknikLogo} alt='Logo Indoteknik' width={LOGO_WIDTH} height={LOGO_HEIGHT} className="mx-auto mb-4 w-auto h-auto" priority />
- </Link>
-
- <h1 className="text-2xl font-semibold text-center md:text-left">
- Daftar Akun Indoteknik
- </h1>
- <h2 className="text-gray_r-11 mt-1 mb-10 text-center md:text-left">
- Buat akun sekarang lebih mudah dan terverifikasi
- </h2>
-
- <Form />
-
- <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
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-x-8 pt-10 px-2 md:pt-16">
+ <section className="border">
+ <div className="px-8 py-4">
+ <Link href="/" className="block md:hidden">
+ <Image
+ src={IndoteknikLogo}
+ alt="Logo Indoteknik"
+ width={LOGO_WIDTH}
+ height={LOGO_HEIGHT}
+ className="mx-auto mb-4 w-auto h-auto"
+ priority
+ />
</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'>
- Aktivasi
- </Link>
+ <h1 className="text-2xl font-semibold text-center md:text-left">
+ Daftar Akun Indoteknik
+ </h1>
+ <h2 className="text-gray_r-11 mt-1 mb-10 text-center md:text-left">
+ Buat akun sekarang lebih mudah dan terverifikasi
+ </h2>
+
+ <label htmlFor="name" className="text-black font-bold">
+ Tipe Akun
+ </label>
+ <div className="grid grid-cols-2 gap-x-3 h-10 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" : ""
+ }`}
+ onClick={handleIndividuClick}
+ >
+ <p>Individu</p>
+ </div>
+ <div
+ className={` border rounded-md flex justify-center items-center transition-colors duration-300 ease-in-out ${
+ isBisnisClicked ? "bg-red-500 text-white" : ""
+ }`}
+ onClick={handleBisnisClick}
+ >
+ <p>Bisnis</p>
+ </div>
+ </div>
+ <div className="transition-opacity duration-300 ease-in-out">
+ {isIndividuClicked && (
+ <div className="opacity-100">
+ <RegistrasiIndividu />
+ </div>
+ )}
+ {isBisnisClicked && (
+ <div className="opacity-100">
+ <RegistrasiBisnis />
+ </div>
+ )}
+ </div>
+ <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">
+ Aktivasi
+ </Link>
+ </div>
+ </section>
</div>
</section>
@@ -48,7 +106,7 @@ const Register = () => {
<AccountActivation />
</div>
- )
-}
+ );
+};
-export default Register \ No newline at end of file
+export default Register;
diff --git a/src-migrate/modules/register/stores/useRegisterStore.ts b/src-migrate/modules/register/stores/useRegisterStore.ts
index d8abf52b..1438ccc2 100644
--- a/src-migrate/modules/register/stores/useRegisterStore.ts
+++ b/src-migrate/modules/register/stores/useRegisterStore.ts
@@ -29,6 +29,7 @@ export const useRegisterStore = create<State & Action>((set, get) => ({
email: '',
password: '',
phone: '',
+ document: File,
},
updateForm: (name, value) =>
set((state) => ({ form: { ...state.form, [name]: value } })),