summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/pengajuan-tempo/api/createPengajuanTempoApi.js14
-rw-r--r--src/lib/pengajuan-tempo/component/Dokumen.jsx952
-rw-r--r--src/lib/pengajuan-tempo/component/FinishTempo.jsx78
-rw-r--r--src/lib/pengajuan-tempo/component/Konfirmasi.jsx263
-rw-r--r--src/lib/pengajuan-tempo/component/KonfirmasiDokumen.jsx1202
-rw-r--r--src/lib/pengajuan-tempo/component/KontakPerusahaan.jsx586
-rw-r--r--src/lib/pengajuan-tempo/component/PengajuanTempo.jsx352
-rw-r--r--src/lib/pengajuan-tempo/component/Pengiriman.jsx1489
-rw-r--r--src/lib/pengajuan-tempo/component/Referensi.jsx548
-rw-r--r--src/lib/pengajuan-tempo/component/Stepper.jsx65
-rw-r--r--src/lib/pengajuan-tempo/component/informasiPerusahaan.jsx1401
11 files changed, 6950 insertions, 0 deletions
diff --git a/src/lib/pengajuan-tempo/api/createPengajuanTempoApi.js b/src/lib/pengajuan-tempo/api/createPengajuanTempoApi.js
new file mode 100644
index 00000000..af1d6c3a
--- /dev/null
+++ b/src/lib/pengajuan-tempo/api/createPengajuanTempoApi.js
@@ -0,0 +1,14 @@
+import odooApi from '@/core/api/odooApi';
+import { getAuth } from '@/core/utils/auth';
+
+const createPengajuanTempoApi = async (data) => {
+ const auth = getAuth();
+ const dataPengajuanTempo = await odooApi(
+ 'POST',
+ `/api/v1/partner/pengajuan_tempo`,
+ data
+ );
+ return dataPengajuanTempo;
+};
+
+export default createPengajuanTempoApi;
diff --git a/src/lib/pengajuan-tempo/component/Dokumen.jsx b/src/lib/pengajuan-tempo/component/Dokumen.jsx
new file mode 100644
index 00000000..0873df66
--- /dev/null
+++ b/src/lib/pengajuan-tempo/component/Dokumen.jsx
@@ -0,0 +1,952 @@
+import React, { useState, useEffect, useMemo, useRef } from 'react';
+import { Controller, set, useForm } from 'react-hook-form';
+import { usePengajuanTempoStoreDokumen } from '../../../../src-migrate/modules/register/stores/usePengajuanTempoStore';
+import ProgressBar from '@ramonak/react-progress-bar';
+import { UseToastOptions } from '@chakra-ui/react';
+import { toast } from 'react-hot-toast';
+import getFileBase64 from '@/core/utils/getFileBase64';
+import useDevice from '@/core/hooks/useDevice';
+const Dokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => {
+ const { control, watch } = useForm();
+ const {
+ formDokumen,
+ errorsDokumen,
+ validateDokumen,
+ updateFormDokumen,
+ getJumlahDokumenDiisi,
+ } = usePengajuanTempoStoreDokumen();
+ const { isDesktop, isMobile } = useDevice();
+ // const handleInputChange = (event) => {
+ // const { name, value } = event.target;
+ // updateFormDokumen(name, value);
+ // validateDokumen();
+ // };
+ const handleInputChange = async (event) => {
+ let fileBase64 = '';
+ const { name } = event.target;
+ const file = event.target.files?.[0];
+ // Allowed file extensions
+ const allowedExtensions = ['pdf', 'png', 'jpg', 'jpeg'];
+ let fileExtension = '';
+ if (file) {
+ fileExtension = file.name.split('.').pop()?.toLowerCase(); // Extract file extension
+
+ // Check if the file extension is allowed
+ if (!fileExtension || !allowedExtensions.includes(fileExtension)) {
+ toast.error(
+ 'Format file yang diijinkan adalah .pdf, .png, .jpg, atau .jpeg',
+ { duration: 4000 }
+ );
+
+ event.target.value = '';
+ return;
+ }
+
+ // Check for file size
+ if (file.size > 2000000) {
+ toast.error('Maksimal ukuran file adalah 2MB', { duration: 4000 });
+
+ event.target.value = '';
+ return;
+ }
+
+ // Convert file to Base64
+ fileBase64 = await getFileBase64(file);
+ updateFormDokumen(name, file.name, fileExtension, fileBase64);
+ validateDokumen();
+ }
+ };
+
+ const isFormValid = useMemo(
+ () => Object.keys(errorsDokumen).length === 0,
+ [errorsDokumen]
+ );
+ const dokumenNibRef = useRef(null);
+ const dokumenNpwpRef = useRef(null);
+ const dokumenSppkpRef = useRef(null);
+ const dokumenAktaPerubahanRef = useRef(null);
+ const dokumenKtpDirutRef = useRef(null);
+ const dokumenAktaPendirianRef = useRef(null);
+ const dokumenLaporanKeuanganRef = useRef(null);
+ const dokumenFotoKantorRef = useRef(null);
+ const dokumenTempatBekerjaRef = useRef(null);
+
+ useEffect(() => {
+ const loadIndustries = async () => {
+ if (!isFormValid) {
+ const options = {
+ behavior: 'smooth',
+ block: 'center',
+ };
+ if (errorsDokumen.dokumenNib && dokumenNibRef.current) {
+ dokumenNibRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errorsDokumen.dokumenNpwp && dokumenNpwpRef.current) {
+ dokumenNpwpRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errorsDokumen.dokumenSppkp && dokumenSppkpRef.current) {
+ dokumenSppkpRef.current.scrollIntoView(options);
+ return;
+ }
+ if (
+ errorsDokumen.dokumenAktaPerubahan &&
+ dokumenAktaPerubahanRef.current
+ ) {
+ dokumenAktaPerubahanRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errorsDokumen.dokumenKtpDirut && dokumenKtpDirutRef.current) {
+ dokumenKtpDirutRef.current.scrollIntoView(options);
+ return;
+ }
+ if (
+ errorsDokumen.dokumenAktaPendirian &&
+ dokumenAktaPendirianRef.current
+ ) {
+ dokumenAktaPendirianRef.current.scrollIntoView(options);
+ return;
+ }
+ if (
+ errorsDokumen.dokumenLaporanKeuangan &&
+ dokumenLaporanKeuanganRef.current
+ ) {
+ dokumenLaporanKeuanganRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errorsDokumen.dokumenFotoKantor && dokumenFotoKantorRef.current) {
+ dokumenFotoKantorRef.current.scrollIntoView(options);
+ return;
+ }
+ if (
+ errorsDokumen.dokumenTempatBekerja &&
+ dokumenTempatBekerjaRef.current
+ ) {
+ dokumenTempatBekerjaRef.current.scrollIntoView(options);
+ return;
+ }
+ }
+ };
+ loadIndustries();
+ }, [buttonSubmitClick, chekValid]);
+
+ useEffect(() => {
+ validateDokumen();
+ }, [buttonSubmitClick]);
+ return (
+ <>
+ {isDesktop && (
+ <div>
+ <h1 className={`font-bold ${isKonfirmasi ? 'text-xl' : ''}`}>
+ Dokumen
+ </h1>
+ <form className='flex mt-4 flex-col w-full '>
+ <div className='w-full grid grid-cols-[1fr_auto_1fr] gap-5'>
+ <div className='kolom-kiri w-full grid grid-rows-2 gap-7 '>
+ <div className='w-full grid grid-cols-2 gap-5'>
+ <div>
+ <label className='form-label text-nowrap'>
+ NIB (SIUP/TDP/SKDP)
+ </label>
+ <span className='text-xs opacity-60'>
+ Pastikan dokumen yang anda upload sudah benar
+ </span>
+ </div>
+ <div className=''>
+ <div className='flex flex-col items-start'>
+ <label
+ htmlFor='dokumenNib'
+ className='cursor-pointer bg-gray-200 hover:bg-gray-300 text-gray-700 py-2 px-4 rounded'
+ >
+ Upload Dokumen
+ </label>
+ <input
+ // value={formDokumen?.dokumenNib?.name}
+ id='dokumenNib'
+ name='dokumenNib'
+ type='file'
+ title=' '
+ ref={dokumenNibRef}
+ className='hidden'
+ aria-invalid={errorsDokumen.dokumenNib}
+ onChange={handleInputChange}
+ accept='.pdf,.png,.jpg,.jpeg'
+ />
+ <span className='mt-2 text-gray-600'>
+ {formDokumen?.dokumenNib?.name}
+ </span>
+ </div>
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsDokumen.dokumenNib}
+ </div>
+ )}
+ </div>
+ </div>
+ <div className='w-full grid grid-cols-2 gap-5'>
+ <div>
+ <label className='form-label text-nowrap'>
+ NPWP Perusahaan
+ </label>
+ <span className='text-xs opacity-60'>
+ Pastikan dokumen yang anda upload sudah benar
+ </span>
+ </div>
+ <div className=''>
+ <div className='flex flex-col items-start'>
+ <label
+ htmlFor='dokumenNpwp'
+ className='cursor-pointer bg-gray-200 hover:bg-gray-300 text-gray-700 py-2 px-4 rounded'
+ >
+ Upload Dokumen
+ </label>
+ <input
+ // value={formDokumen.dokumenNpwp}
+ id='dokumenNpwp'
+ name='dokumenNpwp'
+ type='file'
+ ref={dokumenNpwpRef}
+ title=' '
+ className='hidden'
+ aria-invalid={errorsDokumen.dokumenNpwp}
+ onChange={handleInputChange}
+ accept='.pdf,.png,.jpg,.jpeg'
+ />
+ <span className='mt-2 text-gray-600'>
+ {formDokumen?.dokumenNpwp?.name}
+ </span>
+ </div>
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsDokumen.dokumenNpwp}
+ </div>
+ )}
+ </div>
+ </div>
+ <div className='w-full grid grid-cols-2 gap-5'>
+ <div>
+ <label className='form-label text-nowrap'>SPPKP</label>
+ <span className='text-xs opacity-60'>
+ Pastikan dokumen yang anda upload sudah benar
+ </span>
+ </div>
+ <div className=''>
+ <div className='flex flex-col items-start'>
+ <label
+ htmlFor='dokumenSppkp'
+ className='cursor-pointer bg-gray-200 hover:bg-gray-300 text-gray-700 py-2 px-4 rounded'
+ >
+ Upload Dokumen
+ </label>
+ <input
+ // value={formDokumen.dokumenSppkp}
+ id='dokumenSppkp'
+ name='dokumenSppkp'
+ type='file'
+ ref={dokumenSppkpRef}
+ className='hidden'
+ aria-invalid={errorsDokumen.dokumenSppkp}
+ onChange={handleInputChange}
+ accept='.pdf,.png,.jpg,.jpeg'
+ />
+ <span className='mt-2 text-gray-600'>
+ {formDokumen?.dokumenSppkp?.name}
+ </span>
+ </div>
+
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsDokumen.dokumenSppkp}
+ </div>
+ )}
+ </div>
+ </div>
+ <div className='w-full grid grid-cols-2 gap-5'>
+ <div>
+ <label className='form-label text-nowrap'>
+ Akta Perubahan{' '}
+ <span className=' opacity-60'>(Opsional)</span>
+ </label>
+ <span className='text-xs opacity-60'>
+ Pastikan dokumen yang anda upload sudah benar
+ </span>
+ </div>
+ <div className=''>
+ <div className='flex flex-col items-start'>
+ <label
+ htmlFor='dokumenAktaPerubahan'
+ className='cursor-pointer bg-gray-200 hover:bg-gray-300 text-gray-700 py-2 px-4 rounded'
+ >
+ Upload Dokumen
+ </label>
+ <input
+ // value={formDokumen.dokumenAktaPerubahan}
+ id='dokumenAktaPerubahan'
+ name='dokumenAktaPerubahan'
+ type='file'
+ ref={dokumenAktaPerubahanRef}
+ className='hidden'
+ aria-invalid={errorsDokumen.dokumenAktaPerubahan}
+ onChange={handleInputChange}
+ accept='.pdf,.png,.jpg,.jpeg'
+ />
+ <span className='mt-2 text-gray-600'>
+ {formDokumen?.dokumenAktaPerubahan?.name}
+ </span>
+ </div>
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsDokumen.dokumenAktaPerubahan}
+ </div>
+ )}
+ </div>
+ </div>
+ <div className='w-full grid grid-cols-2 gap-5'>
+ <div>
+ <label className='form-label text-nowrap'>
+ KTP Dirut/Direktur{' '}
+ <span className=' opacity-60'>(Opsional)</span>
+ </label>
+ <span className='text-xs opacity-60'>
+ Pastikan dokumen yang anda upload sudah benar
+ </span>
+ </div>
+ <div className=''>
+ <div className='flex flex-col items-start'>
+ <label
+ htmlFor='dokumenKtpDirut'
+ className='cursor-pointer bg-gray-200 hover:bg-gray-300 text-gray-700 py-2 px-4 rounded'
+ >
+ Upload Dokumen
+ </label>
+ <input
+ // value={formDokumen.dokumenKtpDirut}
+ id='dokumenKtpDirut'
+ name='dokumenKtpDirut'
+ type='file'
+ ref={dokumenKtpDirutRef}
+ className='hidden'
+ aria-invalid={errorsDokumen.dokumenKtpDirut}
+ onChange={handleInputChange}
+ accept='.pdf,.png,.jpg,.jpeg'
+ />
+ <span className='mt-2 text-gray-600'>
+ {formDokumen?.dokumenKtpDirut?.name}
+ </span>
+ </div>
+
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsDokumen.dokumenKtpDirut}
+ </div>
+ )}
+ </div>
+ </div>
+ </div>
+ <div className='w-px bg-gray-300'></div>
+ <div className='kolom kanan w-full grid grid-rows-2 gap-10 '>
+ <div className='w-full grid grid-cols-2 gap-5'>
+ <div>
+ <label className='form-label text-nowrap'>
+ Akta Pendirian{' '}
+ <span className=' opacity-60'>(Opsional)</span>
+ </label>
+ <span className='text-xs opacity-60'>
+ Pastikan dokumen yang anda upload sudah benar
+ </span>
+ </div>
+ <div className=''>
+ <div className='flex flex-col items-start'>
+ <label
+ htmlFor='dokumenAktaPendirian'
+ className='cursor-pointer bg-gray-200 hover:bg-gray-300 text-gray-700 py-2 px-4 rounded'
+ >
+ Upload Dokumen
+ </label>
+ <input
+ // value={formDokumen.dokumenAktaPendirian}
+ id='dokumenAktaPendirian'
+ name='dokumenAktaPendirian'
+ type='file'
+ ref={dokumenAktaPendirianRef}
+ className='hidden'
+ aria-invalid={errorsDokumen.dokumenAktaPendirian}
+ onChange={handleInputChange}
+ accept='.pdf,.png,.jpg,.jpeg'
+ />
+ <span className='mt-2 text-gray-600'>
+ {formDokumen?.dokumenAktaPendirian?.name}
+ </span>
+ </div>
+
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsDokumen.dokumenAktaPendirian}
+ </div>
+ )}
+ </div>
+ </div>
+ <div className='w-full grid grid-cols-2 gap-5'>
+ <div>
+ <label className='form-label text-nowrap'>
+ Laporan Keuangan
+ <span className=' opacity-60'>(Opsional)</span>
+ </label>
+ <span className='text-xs opacity-60'>
+ Pastikan dokumen yang anda upload sudah benar
+ </span>
+ </div>
+ <div className=''>
+ <div className='flex flex-col items-start'>
+ <label
+ htmlFor='dokumenLaporanKeuangan'
+ className='cursor-pointer bg-gray-200 hover:bg-gray-300 text-gray-700 py-2 px-4 rounded'
+ >
+ Upload Dokumen
+ </label>
+ <input
+ // value={formDokumen.dokumenLaporanKeuangan}
+ id='dokumenLaporanKeuangan'
+ name='dokumenLaporanKeuangan'
+ type='file'
+ ref={dokumenLaporanKeuanganRef}
+ className='hidden'
+ aria-invalid={errorsDokumen.dokumenLaporanKeuangan}
+ onChange={handleInputChange}
+ accept='.pdf,.png,.jpg,.jpeg'
+ />
+ <span className='mt-2 text-gray-600'>
+ {formDokumen?.dokumenLaporanKeuangan?.name}
+ </span>
+ </div>
+
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsDokumen.dokumenLaporanKeuangan}
+ </div>
+ )}
+ </div>
+ </div>
+ <div className='w-full grid grid-cols-2 gap-5'>
+ <div>
+ <label className='form-label text-nowrap'>
+ Foto Kantor (Tampak Depan)
+ </label>
+ <span className='text-xs opacity-60'>
+ Pastikan dokumen yang anda upload sudah benar
+ </span>
+ </div>
+ <div className=''>
+ <div className='flex flex-col items-start'>
+ <label
+ htmlFor='dokumenFotoKantor'
+ className='cursor-pointer bg-gray-200 hover:bg-gray-300 text-gray-700 py-2 px-4 rounded'
+ >
+ Upload Dokumen
+ </label>
+ <input
+ // value={formDokumen.dokumenFotoKantor}
+ id='dokumenFotoKantor'
+ name='dokumenFotoKantor'
+ type='file'
+ ref={dokumenFotoKantorRef}
+ className='hidden'
+ aria-invalid={errorsDokumen.dokumenFotoKantor}
+ onChange={handleInputChange}
+ accept='.pdf,.png,.jpg,.jpeg'
+ />
+ <span className='mt-2 text-gray-600'>
+ {formDokumen?.dokumenFotoKantor?.name}
+ </span>
+ </div>
+
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsDokumen.dokumenFotoKantor}
+ </div>
+ )}
+ </div>
+ </div>
+ <div className='w-full grid grid-cols-2 gap-5'>
+ <div>
+ <label className='form-label text-nowrap'>
+ Tempat Bekerja
+ </label>
+ <span className='text-xs opacity-60'>
+ Pastikan dokumen yang anda upload sudah benar
+ </span>
+ </div>
+ <div className=''>
+ <div className='flex flex-col items-start'>
+ <label
+ htmlFor='dokumenTempatBekerja'
+ className='cursor-pointer bg-gray-200 hover:bg-gray-300 text-gray-700 py-2 px-4 rounded'
+ >
+ Upload Dokumen
+ </label>
+ <input
+ // value={formDokumen.dokumenTempatBekerja}
+ id='dokumenTempatBekerja'
+ name='dokumenTempatBekerja'
+ type='file'
+ ref={dokumenTempatBekerjaRef}
+ className='hidden'
+ aria-invalid={errorsDokumen.dokumenTempatBekerja}
+ onChange={handleInputChange}
+ accept='.pdf,.png,.jpg,.jpeg'
+ />
+ <span className='mt-2 text-gray-600'>
+ {formDokumen?.dokumenTempatBekerja?.name}
+ </span>
+ </div>
+
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsDokumen.dokumenTempatBekerja}
+ </div>
+ )}
+ </div>
+ </div>
+ <div></div>
+ </div>
+ </div>
+ </form>
+ <div className='w-1/2 mt-8 flex gap-3 flex-col'>
+ <div className='flex justify-between'>
+ <p className='font-bold'>Upload Progress</p>
+ <p>
+ <span className='text-red-500 font-bold'>
+ {parseInt((getJumlahDokumenDiisi() / 9) * 100)} %
+ </span>
+ <span className='ml-2 opacity-60'>
+ {getJumlahDokumenDiisi() >= 4
+ ? getJumlahDokumenDiisi() == 9
+ ? 'Selesai'
+ : 'Sedikit Lagi'
+ : ''}
+ </span>
+ </p>
+ </div>
+ {/* 50 keatas baru muncul kata kata sedikit lagi */}
+ <ProgressBar
+ completed={getJumlahDokumenDiisi()}
+ bgColor='#ef4444'
+ labelAlignment='outside'
+ isLabelVisible={false}
+ baseBgColor='#E5E7EB'
+ labelColor='#e80909'
+ labelSize='0'
+ maxCompleted={9}
+ height='14 px'
+ />
+ <span className='opacity-75'>
+ Tingkatin sedikit lagi agar pengajuan tempo kamu dapat kami proses
+ dengan cepat
+ </span>
+ </div>
+ </div>
+ )}
+ {isMobile && (
+ <div>
+ <h1
+ className={`font-bold py-4 mt-8 ${
+ isKonfirmasi ? 'text-xl' : 'text-xl'
+ }`}
+ >
+ Dokumen
+ </h1>
+ <form className='flex mt-4 flex-col w-full '>
+ <div className='w-full flex flex-col gap-4'>
+ <div className='w-full flex flex-col gap-2'>
+ <label className='form-label text-nowrap'>
+ NIB (SIUP/TDP/SKDP)
+ </label>
+ <div className='flex flex-row gap-2'>
+ <label
+ htmlFor='dokumenNib'
+ className='cursor-pointer bg-gray-200 hover:bg-gray-300 text-gray-700 py-2 px-4 rounded w-fit min-w-40 text-nowrap text-center flex items-center justify-center'
+ >
+ {formDokumen?.dokumenNib?.name
+ ? 'Sudah Upload'
+ : 'Upload Dokumen'}
+ </label>
+ <input
+ // value={formDokumen?.dokumenNib?.name}
+ id='dokumenNib'
+ name='dokumenNib'
+ type='file'
+ title=' '
+ ref={dokumenNibRef}
+ className='hidden'
+ aria-invalid={errorsDokumen.dokumenNib}
+ onChange={handleInputChange}
+ accept='.pdf,.png,.jpg,.jpeg'
+ />
+ <span className='mt-2 text-gray-600 truncate'>
+ {formDokumen?.dokumenNib?.name}
+ </span>
+ </div>
+ <span className='text-xs opacity-60 text-red-500'>
+ Format: pdf, jpeg, jpg, png. max file size 2MB
+ </span>
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsDokumen.dokumenNib}
+ </div>
+ )}
+ </div>
+
+ <div className='w-full flex flex-col gap-2'>
+ <label className='form-label text-nowrap'>
+ NPWP Perusahaan
+ </label>
+ <div className='flex flex-row gap-2'>
+ <label
+ htmlFor='dokumenNpwp'
+ className='cursor-pointer bg-gray-200 hover:bg-gray-300 text-gray-700 py-2 px-4 rounded w-fit min-w-40 text-nowrap text-center flex items-center justify-center'
+ >
+ {formDokumen?.dokumenNpwp?.name
+ ? 'Sudah Upload'
+ : 'Upload Dokumen'}
+ </label>
+ <input
+ // value={formDokumen.dokumenNpwp}
+ id='dokumenNpwp'
+ name='dokumenNpwp'
+ type='file'
+ ref={dokumenNpwpRef}
+ title=' '
+ className='hidden'
+ aria-invalid={errorsDokumen.dokumenNpwp}
+ onChange={handleInputChange}
+ accept='.pdf,.png,.jpg,.jpeg'
+ />
+ <span className='mt-2 text-gray-600 truncate'>
+ {formDokumen?.dokumenNpwp?.name}
+ </span>
+ </div>
+ <span className='text-xs opacity-60 text-red-500'>
+ Format: pdf, jpeg, jpg, png. max file size 2MB
+ </span>
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsDokumen.dokumenNpwp}
+ </div>
+ )}
+ </div>
+
+ <div className='w-full flex flex-col gap-2'>
+ <label className='form-label text-nowrap'>SPPKP</label>
+ <div className='flex flex-row gap-2'>
+ <label
+ htmlFor='dokumenSppkp'
+ className='cursor-pointer bg-gray-200 hover:bg-gray-300 text-gray-700 py-2 px-4 rounded w-fit min-w-40 text-nowrap text-center flex items-center justify-center'
+ >
+ {formDokumen?.dokumenSppkp?.name
+ ? 'Sudah Upload'
+ : 'Upload Dokumen'}
+ </label>
+ <input
+ // value={formDokumen.dokumenNpwp}
+ id='dokumenSppkp'
+ name='dokumenSppkp'
+ type='file'
+ ref={dokumenSppkpRef}
+ title=' '
+ className='hidden'
+ aria-invalid={errorsDokumen.dokumenSppkp}
+ onChange={handleInputChange}
+ accept='.pdf,.png,.jpg,.jpeg'
+ />
+ <span className='mt-2 text-gray-600 truncate'>
+ {formDokumen?.dokumenSppkp?.name}
+ </span>
+ </div>
+ <span className='text-xs opacity-60 text-red-500'>
+ Format: pdf, jpeg, jpg, png. max file size 2MB
+ </span>
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsDokumen.dokumenSppkp}
+ </div>
+ )}
+ </div>
+
+ <div className='w-full flex flex-col gap-2'>
+ <label className='form-label text-nowrap'>
+ Akta Perubahan <span className=' opacity-60'>(Opsional)</span>
+ </label>
+ <div className='flex flex-row gap-2'>
+ <label
+ htmlFor='dokumenAktaPerubahan'
+ className='cursor-pointer bg-gray-200 hover:bg-gray-300 text-gray-700 py-2 px-4 rounded w-fit min-w-40 text-nowrap text-center flex items-center justify-center'
+ >
+ {formDokumen?.dokumenAktaPerubahan?.name
+ ? 'Sudah Upload'
+ : 'Upload Dokumen'}
+ </label>
+ <input
+ // value={formDokumen.dokumenNpwp}
+ id='dokumenAktaPerubahan'
+ name='dokumenAktaPerubahan'
+ type='file'
+ ref={dokumenAktaPerubahanRef}
+ title=' '
+ className='hidden'
+ aria-invalid={errorsDokumen.dokumenAktaPerubahan}
+ onChange={handleInputChange}
+ accept='.pdf,.png,.jpg,.jpeg'
+ />
+ <span className='mt-2 text-gray-600 truncate'>
+ {formDokumen?.dokumenAktaPerubahan?.name}
+ </span>
+ </div>
+ <span className='text-xs opacity-60 text-red-500'>
+ Format: pdf, jpeg, jpg, png. max file size 2MB
+ </span>
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsDokumen.dokumenAktaPerubahan}
+ </div>
+ )}
+ </div>
+
+ <div className='w-full flex flex-col gap-2'>
+ <label className='form-label text-nowrap'>
+ KTP Dirut/Direktur{' '}
+ <span className=' opacity-60'>(Opsional)</span>
+ </label>
+ <div className='flex flex-row gap-2'>
+ <label
+ htmlFor='dokumenKtpDirut'
+ className='cursor-pointer bg-gray-200 hover:bg-gray-300 text-gray-700 py-2 px-4 rounded w-fit min-w-40 text-nowrap text-center flex items-center justify-center'
+ >
+ {formDokumen?.dokumenKtpDirut?.name
+ ? 'Sudah Upload'
+ : 'Upload Dokumen'}
+ </label>
+ <input
+ // value={formDokumen.dokumenNpwp}
+ id='dokumenKtpDirut'
+ name='dokumenKtpDirut'
+ type='file'
+ ref={dokumenKtpDirutRef}
+ title=' '
+ className='hidden'
+ aria-invalid={errorsDokumen.dokumenKtpDirut}
+ onChange={handleInputChange}
+ accept='.pdf,.png,.jpg,.jpeg'
+ />
+ <span className='mt-2 text-gray-600 truncate'>
+ {formDokumen?.dokumenKtpDirut?.name}
+ </span>
+ </div>
+ <span className='text-xs opacity-60 text-red-500'>
+ Format: pdf, jpeg, jpg, png. max file size 2MB
+ </span>
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsDokumen.dokumenKtpDirut}
+ </div>
+ )}
+ </div>
+
+ <div className='w-full flex flex-col gap-2'>
+ <label className='form-label text-nowrap'>
+ Akta Pendirian <span className=' opacity-60'>(Opsional)</span>
+ </label>
+ <div className='flex flex-row gap-2'>
+ <label
+ htmlFor='dokumenAktaPendirian'
+ className='cursor-pointer bg-gray-200 hover:bg-gray-300 text-gray-700 py-2 px-4 rounded w-fit min-w-40 text-nowrap text-center flex items-center justify-center'
+ >
+ {formDokumen?.dokumenAktaPendirian?.name
+ ? 'Sudah Upload'
+ : 'Upload Dokumen'}
+ </label>
+ <input
+ // value={formDokumen.dokumenNpwp}
+ id='dokumenAktaPendirian'
+ name='dokumenAktaPendirian'
+ type='file'
+ ref={dokumenAktaPendirianRef}
+ title=' '
+ className='hidden'
+ aria-invalid={errorsDokumen.dokumenAktaPendirian}
+ onChange={handleInputChange}
+ accept='.pdf,.png,.jpg,.jpeg'
+ />
+ <span className='mt-2 text-gray-600 truncate'>
+ {formDokumen?.dokumenAktaPendirian?.name}
+ </span>
+ </div>
+ <span className='text-xs opacity-60 text-red-500'>
+ Format: pdf, jpeg, jpg, png. max file size 2MB
+ </span>
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsDokumen.dokumenAktaPendirian}
+ </div>
+ )}
+ </div>
+
+ <div className='w-full flex flex-col gap-2'>
+ <label className='form-label text-nowrap'>
+ Laporan Keuangan{' '}
+ <span className=' opacity-60'>(Opsional)</span>
+ </label>
+ <div className='flex flex-row gap-2'>
+ <label
+ htmlFor='dokumenLaporanKeuangan'
+ className='cursor-pointer bg-gray-200 hover:bg-gray-300 text-gray-700 py-2 px-4 rounded w-fit min-w-40 text-nowrap text-center flex items-center justify-center'
+ >
+ {formDokumen?.dokumenLaporanKeuangan?.name
+ ? 'Sudah Upload'
+ : 'Upload Dokumen'}
+ </label>
+ <input
+ // value={formDokumen.dokumenNpwp}
+ id='dokumenLaporanKeuangan'
+ name='dokumenLaporanKeuangan'
+ type='file'
+ ref={dokumenLaporanKeuanganRef}
+ title=' '
+ className='hidden'
+ aria-invalid={errorsDokumen.dokumenLaporanKeuangan}
+ onChange={handleInputChange}
+ accept='.pdf,.png,.jpg,.jpeg'
+ />
+ <span className='mt-2 text-gray-600 truncate'>
+ {formDokumen?.dokumenLaporanKeuangan?.name}
+ </span>
+ </div>
+ <span className='text-xs opacity-60 text-red-500'>
+ Format: pdf, jpeg, jpg, png. max file size 2MB
+ </span>
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsDokumen.dokumenLaporanKeuangan}
+ </div>
+ )}
+ </div>
+
+ <div className='w-full flex flex-col gap-2'>
+ <label className='form-label text-nowrap'>
+ Foto Kantor (Tampak Depan)
+ </label>
+ <div className='flex flex-row gap-2'>
+ <label
+ htmlFor='dokumenFotoKantor'
+ className='cursor-pointer bg-gray-200 hover:bg-gray-300 text-gray-700 py-2 px-4 rounded w-fit min-w-40 text-nowrap text-center flex items-center justify-center'
+ >
+ {formDokumen?.dokumenFotoKantor?.name
+ ? 'Sudah Upload'
+ : 'Upload Dokumen'}
+ </label>
+ <input
+ // value={formDokumen.dokumenNpwp}
+ id='dokumenFotoKantor'
+ name='dokumenFotoKantor'
+ type='file'
+ ref={dokumenFotoKantorRef}
+ title=' '
+ className='hidden'
+ aria-invalid={errorsDokumen.dokumenFotoKantor}
+ onChange={handleInputChange}
+ accept='.pdf,.png,.jpg,.jpeg'
+ />
+ <span className='mt-2 text-gray-600 truncate'>
+ {formDokumen?.dokumenFotoKantor?.name}
+ </span>
+ </div>
+ <span className='text-xs opacity-60 text-red-500'>
+ Format: pdf, jpeg, jpg, png. max file size 2MB
+ </span>
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsDokumen.dokumenFotoKantor}
+ </div>
+ )}
+ </div>
+
+ <div className='w-full flex flex-col gap-2'>
+ <label className='form-label text-nowrap'>
+ Tempat Bekerja
+ </label>
+ <div className='flex flex-row gap-2'>
+ <label
+ htmlFor='dokumenTempatBekerja'
+ className='cursor-pointer bg-gray-200 hover:bg-gray-300 text-gray-700 py-2 px-4 rounded w-fit min-w-40 text-nowrap text-center flex items-center justify-center'
+ >
+ {formDokumen?.dokumenTempatBekerja?.name
+ ? 'Sudah Upload'
+ : 'Upload Dokumen'}
+ </label>
+ <input
+ // value={formDokumen.dokumenNpwp}
+ id='dokumenTempatBekerja'
+ name='dokumenTempatBekerja'
+ type='file'
+ ref={dokumenTempatBekerjaRef}
+ title=' '
+ className='hidden'
+ aria-invalid={errorsDokumen.dokumenTempatBekerja}
+ onChange={handleInputChange}
+ accept='.pdf,.png,.jpg,.jpeg'
+ />
+ <span className='mt-2 text-gray-600 truncate'>
+ {formDokumen?.dokumenTempatBekerja?.name}
+ </span>
+ </div>
+ <span className='text-xs opacity-60 text-red-500'>
+ Format: pdf, jpeg, jpg, png. max file size 2MB
+ </span>
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsDokumen.dokumenTempatBekerja}
+ </div>
+ )}
+ </div>
+ </div>
+ </form>
+ <div className='w-full mt-8 flex gap-3 flex-col'>
+ <div className='flex justify-between'>
+ <p className='font-bold'>Upload Progress</p>
+ <p>
+ <span className='text-red-500 font-bold'>
+ {parseInt((getJumlahDokumenDiisi() / 9) * 100)} %
+ </span>
+ <span className='ml-2 opacity-60'>
+ {getJumlahDokumenDiisi() >= 4
+ ? getJumlahDokumenDiisi() == 9
+ ? 'Selesai'
+ : 'Sedikit Lagi'
+ : ''}
+ </span>
+ </p>
+ </div>
+ {/* 50 keatas baru muncul kata kata sedikit lagi */}
+ <ProgressBar
+ completed={getJumlahDokumenDiisi()}
+ bgColor='#ef4444'
+ labelAlignment='outside'
+ isLabelVisible={false}
+ baseBgColor='#E5E7EB'
+ labelColor='#e80909'
+ labelSize='0'
+ maxCompleted={9}
+ height='10px'
+ />
+ <span className='opacity-75 text-xs text-red-500'>
+ Tingkatin sedikit lagi agar pengajuan tempo kamu dapat kami proses
+ dengan cepat
+ </span>
+ </div>
+ </div>
+ )}
+ </>
+ );
+};
+
+export default Dokumen;
diff --git a/src/lib/pengajuan-tempo/component/FinishTempo.jsx b/src/lib/pengajuan-tempo/component/FinishTempo.jsx
new file mode 100644
index 00000000..1670314d
--- /dev/null
+++ b/src/lib/pengajuan-tempo/component/FinishTempo.jsx
@@ -0,0 +1,78 @@
+import Link from 'next/link';
+import Image from '~/components/ui/image';
+import whatsappUrl from '@/core/utils/whatsappUrl';
+import { useEffect, useState } from 'react';
+import odooApi from '@/core/api/odooApi';
+import useDevice from '@/core/hooks/useDevice';
+import useAuth from '@/core/hooks/useAuth';
+import axios from 'axios';
+import { toast } from 'react-hot-toast';
+import { ChevronRightIcon, ChevronLeftIcon } from '@heroicons/react/24/outline';
+
+const FinishTempo = ({ query }) => {
+ const [data, setData] = useState();
+ const [transactionData, setTransactionData] = useState();
+ const { isDesktop, isMobile } = useDevice();
+ const auth = useAuth();
+
+ const so_order = query?.order_id?.replaceAll('-', '/');
+ useEffect(() => {
+ const fetchData = async () => {
+ const fetchedData = await odooApi(
+ 'GET',
+ `/api/v1/sale_order_number?sale_number=${so_order}`
+ );
+ setData(fetchedData[0]);
+ };
+ fetchData();
+ }, [query]);
+
+ // Kirim email ketika komponen ini dimount atau sesuai kondisi
+ const sendEmail = async () => {
+ try {
+ const send = await axios.post(
+ `${process.env.NEXT_PUBLIC_SELF_HOST}/api/shop/finish-checkout?orderName=${query?.order_id}`,
+ {}
+ );
+ if (send.status === 200) {
+ toast.success('Berhasil mengirim rincian pesanan');
+ } else {
+ toast.error('Gagal mengirimkan rincian pesanan');
+ }
+ } catch (error) {
+ console.error(error);
+ toast.error('Gagal mengirimkan rincian pesanan');
+ }
+ };
+
+ return (
+ <div className='container flex flex-col items-center gap-4'>
+ <div className='flex w-2/3 justify-center items-center'>
+ <h1 className='text-red-500 text-center font-semibold text-3xl'>
+ Form Pengajuan Tempo kamu Telah Berhasil Didaftarkan Mohon menunggu
+ hingga Proses Selesai
+ </h1>
+ </div>
+ <Image
+ src='/images/REGISTRASI-TEMPO.svg'
+ alt='Checkout Pesanan'
+ width={isMobile ? 300 : 450}
+ height={isMobile ? 300 : 450}
+ />
+
+ <div className='mt-2 text-center leading-6 text-base p-4 md:p-0 w-4/5'>
+ Mohon menunggu untuk verifikasi dokumen dan kelengkapan data yang telah
+ anda berikan. Proses approval pembayaran tempo kamu berhasil atau tidak
+ akan diinfokan melalui email perusahaan / email yang mendaftar
+ </div>
+ <Link
+ href={`/my/quotations/${data?.id}`}
+ className='btn-solid-red rounded-md text-base flex flex-row'
+ >
+ Lihat Status Pendaftaran <ChevronRightIcon className='w-5' />
+ </Link>
+ </div>
+ );
+};
+
+export default FinishTempo;
diff --git a/src/lib/pengajuan-tempo/component/Konfirmasi.jsx b/src/lib/pengajuan-tempo/component/Konfirmasi.jsx
new file mode 100644
index 00000000..80845a8f
--- /dev/null
+++ b/src/lib/pengajuan-tempo/component/Konfirmasi.jsx
@@ -0,0 +1,263 @@
+import React, { useState, useEffect, useMemo, useRef } from 'react';
+import { Controller, set, useForm } from 'react-hook-form';
+import HookFormSelect from '@/core/components/elements/Select/HookFormSelect';
+import {
+ usePengajuanTempoStoreDokumen,
+ usePengajuanTempoStore,
+} from '../../../../src-migrate/modules/register/stores/usePengajuanTempoStore';
+import KontakPerusahaan from './KontakPerusahaan';
+import ProgressBar from '@ramonak/react-progress-bar';
+import { UseToastOptions } from '@chakra-ui/react';
+import odooApi from '~/libs/odooApi';
+import { toast } from 'react-hot-toast';
+import getFileBase64 from '@/core/utils/getFileBase64';
+import { CheckCircleIcon } from '@heroicons/react/24/outline';
+import InformasiPerusahaan from './informasiPerusahaan';
+import Pengiriman from './Pengiriman';
+import KonfirmasiDokumen from './KonfirmasiDokumen';
+import useDevice from '@/core/hooks/useDevice';
+import { ChevronDownIcon, ChevronUpIcon } from '@heroicons/react/24/outline';
+const Konfirmasi = ({ chekValid, buttonSubmitClick }) => {
+ const { control, watch, setValue, getValues } = useForm();
+ const { isDesktop, isMobile } = useDevice();
+ const [isOpen, setIsOpen] = useState(false);
+ const [industries, setIndustries] = useState([]);
+ const {
+ formDokumen,
+ errorsDokumen,
+ validateDokumen,
+ updateFormDokumen,
+ getJumlahDokumenDiisi,
+ } = usePengajuanTempoStoreDokumen();
+ const { form, errors, validate, updateForm } = usePengajuanTempoStore();
+ const handleInputChange = async (event) => {
+ let fileBase64 = '';
+ const { name } = event.target;
+ const file = event.target.files?.[0];
+ // Allowed file extensions
+ const allowedExtensions = ['pdf', 'png', 'jpg', 'jpeg'];
+ let fileExtension = '';
+ if (file) {
+ fileExtension = file.name.split('.').pop()?.toLowerCase();
+
+ if (!fileExtension || !allowedExtensions.includes(fileExtension)) {
+ toast.error(
+ 'Format file yang diijinkan adalah .pdf, .png, .jpg, atau .jpeg',
+ { duration: 4000 }
+ );
+
+ event.target.value = '';
+ return;
+ }
+ if (file.size > 2000000) {
+ toast.error('Maksimal ukuran file adalah 2MB', { duration: 4000 });
+
+ event.target.value = '';
+ return;
+ }
+
+ fileBase64 = await getFileBase64(file);
+ updateFormDokumen(name, file.name, fileExtension, fileBase64);
+ validateDokumen();
+ }
+ };
+
+ const isFormValid = useMemo(
+ () => Object.keys(errorsDokumen).length === 0,
+ [errorsDokumen]
+ );
+ const dokumenNibRef = useRef(null);
+ const dokumenNpwpRef = useRef(null);
+ const dokumenSppkpRef = useRef(null);
+ const dokumenAktaPerubahanRef = useRef(null);
+ const dokumenKtpDirutRef = useRef(null);
+ const dokumenAktaPendirianRef = useRef(null);
+ const dokumenLaporanKeuanganRef = useRef(null);
+ const dokumenFotoKantorRef = useRef(null);
+ const dokumenTempatBekerjaRef = useRef(null);
+
+ useEffect(() => {
+ const loadIndustries = async () => {
+ if (!isFormValid) {
+ const options = {
+ behavior: 'smooth',
+ block: 'center',
+ };
+ if (errorsDokumen.dokumenNib && dokumenNibRef.current) {
+ dokumenNibRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errorsDokumen.dokumenNpwp && dokumenNpwpRef.current) {
+ dokumenNpwpRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errorsDokumen.dokumenSppkp && dokumenSppkpRef.current) {
+ dokumenSppkpRef.current.scrollIntoView(options);
+ return;
+ }
+ if (
+ errorsDokumen.dokumenAktaPerubahan &&
+ dokumenAktaPerubahanRef.current
+ ) {
+ dokumenAktaPerubahanRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errorsDokumen.dokumenKtpDirut && dokumenKtpDirutRef.current) {
+ dokumenKtpDirutRef.current.scrollIntoView(options);
+ return;
+ }
+ if (
+ errorsDokumen.dokumenAktaPendirian &&
+ dokumenAktaPendirianRef.current
+ ) {
+ dokumenAktaPendirianRef.current.scrollIntoView(options);
+ return;
+ }
+ if (
+ errorsDokumen.dokumenLaporanKeuangan &&
+ dokumenLaporanKeuanganRef.current
+ ) {
+ dokumenLaporanKeuanganRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errorsDokumen.dokumenFotoKantor && dokumenFotoKantorRef.current) {
+ dokumenFotoKantorRef.current.scrollIntoView(options);
+ return;
+ }
+ if (
+ errorsDokumen.dokumenTempatBekerja &&
+ dokumenTempatBekerjaRef.current
+ ) {
+ dokumenTempatBekerjaRef.current.scrollIntoView(options);
+ return;
+ }
+ }
+ };
+ loadIndustries();
+ }, [buttonSubmitClick, chekValid]);
+
+ useEffect(() => {
+ validateDokumen();
+ }, [buttonSubmitClick]);
+
+ useEffect(() => {
+ const loadIndustries = async () => {
+ const dataIndustries = await odooApi('GET', '/api/v1/partner/industry');
+ setIndustries(
+ dataIndustries?.map((o) => ({
+ value: o.id,
+ label: o.name,
+ category: o.category,
+ }))
+ );
+ };
+ loadIndustries();
+ }, []);
+
+ useEffect(() => {
+ const selectedIndustryType = industries.find(
+ (industry) => industry.value === watch('industry_id')
+ );
+ if (selectedIndustryType) {
+ updateForm('industry_id', `${selectedIndustryType?.value}`);
+ validate();
+ }
+ }, [watch('industry_id'), industries]);
+
+ useEffect(() => {
+ if (form.industry_id) {
+ setValue('industry_id', parseInt(form.industry_id));
+ }
+ }, [form]);
+ const handleLabelClick = () => {
+ setIndustriesOpen(!industriesOpen);
+ };
+ return (
+ <>
+ {isDesktop && (
+ <form className='flex mt-4 flex-col w-full '>
+ <div className='w-full grid grid-cols-[1fr_auto_1fr] gap-5'>
+ <div className='w-full flex flex-col gap-5 '>
+ <div className=''>
+ <InformasiPerusahaan isKonfirmasi={true} />
+ </div>
+ <div className='h-px bg-gray-300'></div>
+ <div className=''>
+ <KontakPerusahaan isKonfirmasi={true} />
+ </div>
+ </div>
+
+ <div className='w-px bg-gray-300'></div>
+ <div className='w-full grid grid-rows-[1fc_auto_1fc] gap-5'>
+ <div>
+ <Pengiriman isKonfirmasi={true} />
+ </div>
+ <div className='h-px bg-gray-300'></div>
+ <div>
+ <KonfirmasiDokumen isKonfirmasi={true} />
+ </div>
+ </div>
+ </div>
+ </form>
+ )}
+ {isMobile && (
+ <form className='flex mt-8 py-4 flex-col w-full gap-4'>
+ <div className='flex flex-col gap-4'>
+ <div className='flex flex-row justify-between'>
+ <p className='font-semibold text-lg'>Informasi Perusahaan</p>
+ <div className='p-2 bg-gray-200'>
+ {isOpen ? (
+ <ChevronUpIcon className='w-4' />
+ ) : (
+ <ChevronDownIcon className='w-4' />
+ )}
+ </div>
+ </div>
+ <InformasiPerusahaan isKonfirmasi={true} />
+ </div>
+ <div className='flex flex-col gap-4'>
+ <div className='flex flex-row justify-between'>
+ <p className='font-semibold text-lg'>Kontak Person</p>
+ <div className='p-2 bg-gray-200'>
+ {isOpen ? (
+ <ChevronUpIcon className='w-4' />
+ ) : (
+ <ChevronDownIcon className='w-4' />
+ )}
+ </div>
+ </div>
+ <KontakPerusahaan isKonfirmasi={true} />
+ </div>
+ <div className='flex flex-col gap-4'>
+ <div className='flex flex-row justify-between'>
+ <p className='font-semibold text-lg'>Pengiriman</p>
+ <div className='p-2 bg-gray-200'>
+ {isOpen ? (
+ <ChevronUpIcon className='w-4' />
+ ) : (
+ <ChevronDownIcon className='w-4' />
+ )}
+ </div>
+ </div>
+ <Pengiriman isKonfirmasi={true} />
+ </div>
+ <div className='flex flex-col gap-4'>
+ <div className='flex flex-row justify-between'>
+ <p className='font-semibold text-lg'>Dokumen</p>
+ <div className='p-2 bg-gray-200'>
+ {isOpen ? (
+ <ChevronUpIcon className='w-4' />
+ ) : (
+ <ChevronDownIcon className='w-4' />
+ )}
+ </div>
+ </div>
+ <KonfirmasiDokumen isKonfirmasi={true} />
+ </div>
+ </form>
+ )}
+ </>
+ );
+};
+
+export default Konfirmasi;
diff --git a/src/lib/pengajuan-tempo/component/KonfirmasiDokumen.jsx b/src/lib/pengajuan-tempo/component/KonfirmasiDokumen.jsx
new file mode 100644
index 00000000..9b0f1d8f
--- /dev/null
+++ b/src/lib/pengajuan-tempo/component/KonfirmasiDokumen.jsx
@@ -0,0 +1,1202 @@
+import React, { useState, useEffect, useMemo, useRef } from 'react';
+import { Controller, set, useForm } from 'react-hook-form';
+import { usePengajuanTempoStoreDokumen } from '../../../../src-migrate/modules/register/stores/usePengajuanTempoStore';
+import ProgressBar from '@ramonak/react-progress-bar';
+import { UseToastOptions } from '@chakra-ui/react';
+import { toast } from 'react-hot-toast';
+import getFileBase64 from '@/core/utils/getFileBase64';
+import Image from 'next/image';
+import BottomPopup from '@/core/components/elements/Popup/BottomPopup';
+import { EyeIcon } from '@heroicons/react/24/outline';
+import useDevice from '@/core/hooks/useDevice';
+const KonfirmasiDokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => {
+ const { control, watch } = useForm();
+ const [isExample, setIsExample] = useState(false);
+ const { isDesktop, isMobile } = useDevice();
+ const [base64, setBase64] = useState();
+ const [pdfData, setPdfData] = useState();
+ const [format, setFormat] = useState();
+ const [popUpSource, setSource] = useState();
+ const {
+ formDokumen,
+ errorsDokumen,
+ validateDokumen,
+ updateFormDokumen,
+ getJumlahDokumenDiisi,
+ } = usePengajuanTempoStoreDokumen();
+
+ const handleConfirmSubmit = (format, base64) => {
+ if (format == 'pdf') {
+ setFormat(`application/${format}`);
+ } else {
+ setFormat(`image/${format}`);
+ }
+ setBase64(
+ base64.trim().replace(/^"+/, '').replace(/"+$/, '').replaceAll('\\', '')
+ );
+ setIsExample(!isExample);
+ };
+ const handleInputChange = async (event) => {
+ let fileBase64 = '';
+ const { name } = event.target;
+ const file = event.target.files?.[0];
+ const allowedExtensions = ['pdf', 'png', 'jpg', 'jpeg'];
+ let fileExtension = '';
+ if (file) {
+ fileExtension = file.name.split('.').pop()?.toLowerCase();
+
+ if (!fileExtension || !allowedExtensions.includes(fileExtension)) {
+ toast.error(
+ 'Format file yang diijinkan adalah .pdf, .png, .jpg, atau .jpeg',
+ { duration: 4000 }
+ );
+
+ event.target.value = '';
+ return;
+ }
+
+ if (file.size > 2000000) {
+ toast.error('Maksimal ukuran file adalah 2MB', { duration: 4000 });
+
+ event.target.value = '';
+ return;
+ }
+
+ fileBase64 = await getFileBase64(file);
+ updateFormDokumen(name, file.name, fileExtension, fileBase64);
+ validateDokumen();
+ }
+ };
+
+ const isFormValid = useMemo(
+ () => Object.keys(errorsDokumen).length === 0,
+ [errorsDokumen]
+ );
+ const dokumenNibRef = useRef(null);
+ const dokumenNpwpRef = useRef(null);
+ const dokumenSppkpRef = useRef(null);
+ const dokumenAktaPerubahanRef = useRef(null);
+ const dokumenKtpDirutRef = useRef(null);
+ const dokumenAktaPendirianRef = useRef(null);
+ const dokumenLaporanKeuanganRef = useRef(null);
+ const dokumenFotoKantorRef = useRef(null);
+ const dokumenTempatBekerjaRef = useRef(null);
+
+ useEffect(() => {
+ const loadIndustries = async () => {
+ if (!isFormValid) {
+ const options = {
+ behavior: 'smooth',
+ block: 'center',
+ };
+ if (errorsDokumen.dokumenNib && dokumenNibRef.current) {
+ dokumenNibRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errorsDokumen.dokumenNpwp && dokumenNpwpRef.current) {
+ dokumenNpwpRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errorsDokumen.dokumenSppkp && dokumenSppkpRef.current) {
+ dokumenSppkpRef.current.scrollIntoView(options);
+ return;
+ }
+ if (
+ errorsDokumen.dokumenAktaPerubahan &&
+ dokumenAktaPerubahanRef.current
+ ) {
+ dokumenAktaPerubahanRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errorsDokumen.dokumenKtpDirut && dokumenKtpDirutRef.current) {
+ dokumenKtpDirutRef.current.scrollIntoView(options);
+ return;
+ }
+ if (
+ errorsDokumen.dokumenAktaPendirian &&
+ dokumenAktaPendirianRef.current
+ ) {
+ dokumenAktaPendirianRef.current.scrollIntoView(options);
+ return;
+ }
+ if (
+ errorsDokumen.dokumenLaporanKeuangan &&
+ dokumenLaporanKeuanganRef.current
+ ) {
+ dokumenLaporanKeuanganRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errorsDokumen.dokumenFotoKantor && dokumenFotoKantorRef.current) {
+ dokumenFotoKantorRef.current.scrollIntoView(options);
+ return;
+ }
+ if (
+ errorsDokumen.dokumenTempatBekerja &&
+ dokumenTempatBekerjaRef.current
+ ) {
+ dokumenTempatBekerjaRef.current.scrollIntoView(options);
+ return;
+ }
+ }
+ };
+ loadIndustries();
+ }, [buttonSubmitClick, chekValid]);
+
+ useEffect(() => {
+ validateDokumen();
+ }, [buttonSubmitClick]);
+
+ return (
+ <>
+ {isDesktop && (
+ <div>
+ <h1 className={`font-bold ${isKonfirmasi ? 'text-xl' : ''}`}>
+ Dokumen
+ </h1>
+ <form className='flex flex-col w-full gap-5'>
+ <div className='w-full flex flex-row items-center '>
+ <div className='w-2/5'>
+ <label className='form-label text-nowrap'>
+ NIB (SIUP/TDP/SKDP)
+ </label>
+ </div>
+ <div className='w-3/5'>
+ <div className='flex flex-row items-start justify-between'>
+ <span className='w-3/5 text-gray-600 truncate'>
+ {formDokumen?.dokumenNib?.name}
+ </span>
+ <div className='w-2/5 flex flex-row gap-2'>
+ <label
+ htmlFor='dokumenNib'
+ className='cursor-pointer bg-red-500 hover:bg-red-600 text-white py-1 px-3 text-sm rounded'
+ >
+ Ubah
+ </label>
+ <input
+ // value={formDokumen?.dokumenNib?.name}
+ id='dokumenNib'
+ name='dokumenNib'
+ type='file'
+ title=' '
+ ref={dokumenNibRef}
+ className='hidden'
+ aria-invalid={errorsDokumen.dokumenNib}
+ onChange={handleInputChange}
+ accept='.pdf,.png,.jpg,.jpeg'
+ />
+ <button
+ className='rounded text-white p-2 flex flex-row bg-red-500 hover:cursor-pointer hover:bg-red-400'
+ type='button'
+ onClick={() =>
+ handleConfirmSubmit(
+ formDokumen.dokumenNib.format,
+ formDokumen.dokumenNib.base64
+ )
+ }
+ >
+ <EyeIcon className={`w-4 ${isDesktop && ''}`} />
+ </button>
+ </div>
+ </div>
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsDokumen.dokumenNib}
+ </div>
+ )}
+ </div>
+ </div>
+ <div className='w-full flex flex-row items-center '>
+ <div className='w-2/5'>
+ <label className='form-label text-nowrap'>
+ NPWP Perusahaan
+ </label>
+ </div>
+ <div className='w-3/5'>
+ <div className='flex flex-row items-start justify-between'>
+ <span className='w-3/5 text-gray-600 truncate'>
+ {formDokumen?.dokumenNpwp?.name}
+ </span>
+ <div className='w-2/5 flex flex-row gap-2'>
+ <label
+ htmlFor='dokumenNpwp'
+ className='cursor-pointer bg-red-500 hover:bg-red-600 text-white py-1 px-3 text-sm rounded'
+ >
+ Ubah
+ </label>
+ <input
+ // value={formDokumen?.dokumenNib?.name}
+ id='dokumenNpwp'
+ name='dokumenNpwp'
+ type='file'
+ title=' '
+ ref={dokumenNpwpRef}
+ className='hidden'
+ aria-invalid={errorsDokumen.dokumenNpwp}
+ onChange={handleInputChange}
+ accept='.pdf,.png,.jpg,.jpeg'
+ />
+ <button
+ className='rounded text-white p-2 flex flex-row bg-red-500 hover:cursor-pointer hover:bg-red-400'
+ type='button'
+ onClick={() =>
+ handleConfirmSubmit(
+ formDokumen.dokumenNpwp.format,
+ formDokumen.dokumenNpwp.base64
+ )
+ }
+ >
+ <EyeIcon className={`w-4 ${isDesktop && ''}`} />
+ </button>
+ </div>
+ </div>
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsDokumen.dokumenNpwp}
+ </div>
+ )}
+ </div>
+ </div>
+ <div className='w-full flex flex-row items-center '>
+ <div className='w-2/5'>
+ <label className='form-label text-nowrap'>SPPKP</label>
+ </div>
+ <div className='w-3/5'>
+ <div className='flex flex-row items-start justify-between'>
+ <span className='w-3/5 text-gray-600 truncate'>
+ {formDokumen?.dokumenSppkp?.name}
+ </span>
+ <div className='w-2/5 flex flex-row gap-2'>
+ <label
+ htmlFor='dokumenSppkp'
+ className='cursor-pointer bg-red-500 hover:bg-red-600 text-white py-1 px-3 text-sm rounded'
+ >
+ Ubah
+ </label>
+ <input
+ // value={formDokumen?.dokumenNib?.name}
+ id='dokumenSppkp'
+ name='dokumenSppkp'
+ type='file'
+ title=' '
+ ref={dokumenSppkpRef}
+ className='hidden'
+ aria-invalid={errorsDokumen.dokumenSppkp}
+ onChange={handleInputChange}
+ accept='.pdf,.png,.jpg,.jpeg'
+ />
+ <button
+ className='rounded text-white p-2 flex flex-row bg-red-500 hover:cursor-pointer hover:bg-red-400'
+ type='button'
+ onClick={() =>
+ handleConfirmSubmit(
+ formDokumen.dokumenSppkp.format,
+ formDokumen.dokumenSppkp.base64
+ )
+ }
+ >
+ <EyeIcon className={`w-4 ${isDesktop && ''}`} />
+ </button>
+ </div>
+ </div>
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsDokumen.dokumenSppkp}
+ </div>
+ )}
+ </div>
+ </div>
+
+ <div className='w-full flex flex-row items-center '>
+ <div className='w-2/5'>
+ <label className='form-label text-nowrap'>
+ {' '}
+ Akta Perubahan <span className=' opacity-60'>(Opsional)</span>
+ </label>
+ </div>
+ <div className='w-3/5'>
+ <div className='flex flex-row items-start justify-between'>
+ <span className='w-3/5 text-gray-600 truncate'>
+ {formDokumen?.dokumenAktaPerubahan?.name}
+ </span>
+ <div className='w-2/5 flex flex-row gap-2'>
+ <label
+ htmlFor='dokumenAktaPerubahan'
+ className='cursor-pointer bg-red-500 hover:bg-red-600 text-white py-1 px-3 text-sm rounded'
+ >
+ Ubah
+ </label>
+ <input
+ // value={formDokumen?.dokumenNib?.name}
+ id='dokumenAktaPerubahan'
+ name='dokumendokumenAktaPerubahanSppkp'
+ type='file'
+ title=' '
+ ref={dokumenAktaPerubahanRef}
+ className='hidden'
+ aria-invalid={errorsDokumen.dokumenAktaPerubahan}
+ onChange={handleInputChange}
+ accept='.pdf,.png,.jpg,.jpeg'
+ />
+ <button
+ className='rounded text-white p-2 flex flex-row bg-red-500 hover:cursor-pointer hover:bg-red-400'
+ type='button'
+ onClick={() =>
+ handleConfirmSubmit(
+ formDokumen.dokumenAktaPerubahan.format,
+ formDokumen.dokumenAktaPerubahan.base64
+ )
+ }
+ >
+ <EyeIcon className={`w-4 ${isDesktop && ''}`} />
+ </button>
+ </div>
+ </div>
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsDokumen.dokumenAktaPerubahan}
+ </div>
+ )}
+ </div>
+ </div>
+
+ <div className='w-full flex flex-row items-center '>
+ <div className='w-2/5'>
+ <label className='form-label text-nowrap'>
+ KTP Dirut/Direktur{' '}
+ <span className=' opacity-60'>(Opsional)</span>
+ </label>
+ </div>
+ <div className='w-3/5'>
+ <div className='flex flex-row items-start justify-between'>
+ <span className='w-3/5 text-gray-600 truncate'>
+ {formDokumen?.dokumenKtpDirut?.name}
+ </span>
+ <div className='w-2/5 flex flex-row gap-2'>
+ <label
+ htmlFor='dokumenKtpDirut'
+ className='cursor-pointer bg-red-500 hover:bg-red-600 text-white py-1 px-3 text-sm rounded'
+ >
+ Ubah
+ </label>
+ <input
+ // value={formDokumen?.dokumenNib?.name}
+ id='dokumenKtpDirut'
+ name='dokumenKtpDirut'
+ type='file'
+ title=' '
+ ref={dokumenKtpDirutRef}
+ className='hidden'
+ aria-invalid={errorsDokumen.dokumenKtpDirut}
+ onChange={handleInputChange}
+ accept='.pdf,.png,.jpg,.jpeg'
+ />
+ <button
+ className='rounded text-white p-2 flex flex-row bg-red-500 hover:cursor-pointer hover:bg-red-400'
+ type='button'
+ onClick={() =>
+ handleConfirmSubmit(
+ formDokumen.dokumenKtpDirut.format,
+ formDokumen.dokumenKtpDirut.base64
+ )
+ }
+ >
+ <EyeIcon className={`w-4 ${isDesktop && ''}`} />
+ </button>
+ </div>
+ </div>
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsDokumen.dokumenKtpDirut}
+ </div>
+ )}
+ </div>
+ </div>
+
+ <div className='w-full flex flex-row items-center '>
+ <div className='w-2/5'>
+ <label className='form-label text-nowrap'>
+ Akta Pendirian <span className=' opacity-60'>(Opsional)</span>
+ </label>
+ </div>
+ <div className='w-3/5'>
+ <div className='flex flex-row items-start justify-between'>
+ <span className='w-3/5 text-gray-600 truncate'>
+ {formDokumen?.dokumenAktaPendirian?.name}
+ </span>
+ <div className='w-2/5 flex flex-row gap-2'>
+ <label
+ htmlFor='dokumenAktaPendirian'
+ className='cursor-pointer bg-red-500 hover:bg-red-600 text-white py-1 px-3 text-sm rounded'
+ >
+ Ubah
+ </label>
+ <input
+ // value={formDokumen?.dokumenNib?.name}
+ id='dokumenAktaPendirian'
+ name='dokumenAktaPendirian'
+ type='file'
+ title=' '
+ ref={dokumenAktaPendirianRef}
+ className='hidden'
+ aria-invalid={errorsDokumen.dokumenAktaPendirian}
+ onChange={handleInputChange}
+ accept='.pdf,.png,.jpg,.jpeg'
+ />
+ <button
+ className='rounded text-white p-2 flex flex-row bg-red-500 hover:cursor-pointer hover:bg-red-400'
+ type='button'
+ onClick={() =>
+ handleConfirmSubmit(
+ formDokumen.dokumenAktaPendirian.format,
+ formDokumen.dokumenAktaPendirian.base64
+ )
+ }
+ >
+ <EyeIcon className={`w-4 ${isDesktop && ''}`} />
+ </button>
+ </div>
+ </div>
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsDokumen.dokumenAktaPendirian}
+ </div>
+ )}
+ </div>
+ </div>
+
+ <div className='w-full flex flex-row items-center '>
+ <div className='w-2/5'>
+ <label className='form-label text-nowrap'>
+ Laporan Keuangan
+ <span className=' opacity-60'>(Opsional)</span>
+ </label>
+ </div>
+ <div className='w-3/5'>
+ <div className='flex flex-row items-start justify-between'>
+ <span className='w-3/5 text-gray-600 truncate'>
+ {formDokumen?.dokumenLaporanKeuangan?.name}
+ </span>
+ <div className='w-2/5 flex flex-row gap-2'>
+ <label
+ htmlFor='dokumenLaporanKeuangan'
+ className='cursor-pointer bg-red-500 hover:bg-red-600 text-white py-1 px-3 text-sm rounded'
+ >
+ Ubah
+ </label>
+ <input
+ // value={formDokumen?.dokumenNib?.name}
+ id='dokumenLaporanKeuangan'
+ name='dokumenLaporanKeuangan'
+ type='file'
+ title=' '
+ ref={dokumenLaporanKeuanganRef}
+ className='hidden'
+ aria-invalid={errorsDokumen.dokumenLaporanKeuangan}
+ onChange={handleInputChange}
+ accept='.pdf,.png,.jpg,.jpeg'
+ />
+ <button
+ className='rounded text-white p-2 flex flex-row bg-red-500 hover:cursor-pointer hover:bg-red-400'
+ type='button'
+ onClick={() =>
+ handleConfirmSubmit(
+ formDokumen.dokumenLaporanKeuangan.format,
+ formDokumen.dokumenLaporanKeuangan.base64
+ )
+ }
+ >
+ <EyeIcon className={`w-4 ${isDesktop && ''}`} />
+ </button>
+ </div>
+ </div>
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsDokumen.dokumenLaporanKeuangan}
+ </div>
+ )}
+ </div>
+ </div>
+
+ <div className='w-full flex flex-row items-center '>
+ <div className='w-2/5'>
+ <label className='form-label text-nowrap'>
+ Foto Kantor (Tampak Depan)
+ </label>
+ </div>
+ <div className='w-3/5'>
+ <div className='flex flex-row items-start justify-between'>
+ <span className='w-3/5 text-gray-600 truncate'>
+ {formDokumen?.dokumenFotoKantor?.name}
+ </span>
+ <div className='w-2/5 flex flex-row gap-2'>
+ <label
+ htmlFor='dokumenFotoKantor'
+ className='cursor-pointer bg-red-500 hover:bg-red-600 text-white py-1 px-3 text-sm rounded'
+ >
+ Ubah
+ </label>
+ <input
+ // value={formDokumen?.dokumenNib?.name}
+ id='dokumenFotoKantor'
+ name='dokumenFotoKantor'
+ type='file'
+ title=' '
+ ref={dokumenFotoKantorRef}
+ className='hidden'
+ aria-invalid={errorsDokumen.dokumenFotoKantor}
+ onChange={handleInputChange}
+ accept='.pdf,.png,.jpg,.jpeg'
+ />
+ <button
+ className='rounded text-white p-2 flex flex-row bg-red-500 hover:cursor-pointer hover:bg-red-400'
+ type='button'
+ onClick={() =>
+ handleConfirmSubmit(
+ formDokumen.dokumenFotoKantor.format,
+ formDokumen.dokumenFotoKantor.base64
+ )
+ }
+ >
+ <EyeIcon className={`w-4 ${isDesktop && ''}`} />
+ </button>
+ </div>
+ </div>
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsDokumen.dokumenFotoKantor}
+ </div>
+ )}
+ </div>
+ </div>
+
+ <div className='w-full flex flex-row items-center '>
+ <div className='w-2/5'>
+ <label className='form-label text-nowrap'>
+ Tempat Bekerja
+ </label>
+ </div>
+ <div className='w-3/5'>
+ <div className='flex flex-row items-start justify-between'>
+ <span className='w-3/5 text-gray-600 truncate'>
+ {formDokumen?.dokumenTempatBekerja?.name}
+ </span>
+ <div className='w-2/5 flex flex-row gap-2'>
+ <label
+ htmlFor='dokumenTempatBekerja'
+ className='cursor-pointer bg-red-500 hover:bg-red-600 text-white py-1 px-3 text-sm rounded'
+ >
+ Ubah
+ </label>
+ <input
+ // value={formDokumen?.dokumenNib?.name}
+ id='dokumenTempatBekerja'
+ name='dokumenTempatBekerja'
+ type='file'
+ title=' '
+ ref={dokumenTempatBekerjaRef}
+ className='hidden'
+ aria-invalid={errorsDokumen.dokumenTempatBekerja}
+ onChange={handleInputChange}
+ accept='.pdf,.png,.jpg,.jpeg'
+ />
+ <button
+ className='rounded text-white p-2 flex flex-row bg-red-500 hover:cursor-pointer hover:bg-red-400'
+ type='button'
+ onClick={() =>
+ handleConfirmSubmit(
+ formDokumen.dokumenTempatBekerja.format,
+ formDokumen.dokumenTempatBekerja.base64
+ )
+ }
+ >
+ <EyeIcon className={`w-4 ${isDesktop && ''}`} />
+ </button>
+ </div>
+ {/* <Image
+ src={`data:image/png;base64, ${formDokumen.dokumenNib.base64}`}
+ alt='Contoh SPPKP'
+ className='w-full h-full '
+ width={800}
+ height={800}
+ quality={85}
+ /> */}
+ </div>
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsDokumen.dokumenTempatBekerja}
+ </div>
+ )}
+ </div>
+ </div>
+ </form>
+ </div>
+ )}
+ {isMobile && (
+ <div>
+ <h1 className={`font-bold ${isKonfirmasi ? 'hidden' : 'text-xl'}`}>
+ Dokumen
+ </h1>
+ <form className='flex flex-col w-full gap-5 text-sm'>
+ <div className='w-full flex flex-row items-center '>
+ <div className='w-2/5'>
+ <label className='form-label text-wrap'>
+ NIB (SIUP/TDP/SKDP)
+ </label>
+ </div>
+ <div className='w-3/5'>
+ <div className='flex flex-row items-center justify-start'>
+ <span className='w-3/5 text-gray-600 truncate'>
+ {formDokumen?.dokumenNib?.name}
+ </span>
+ <div className='w-2/5 flex flex-row gap-2'>
+ <label
+ htmlFor='dokumenNib'
+ className='cursor-pointer bg-red-500 hover:bg-red-600 text-white py-1 px-3 text-sm rounded'
+ >
+ Ubah
+ </label>
+ <input
+ // value={formDokumen?.dokumenNib?.name}
+ id='dokumenNib'
+ name='dokumenNib'
+ type='file'
+ title=' '
+ ref={dokumenNibRef}
+ className='hidden'
+ aria-invalid={errorsDokumen.dokumenNib}
+ onChange={handleInputChange}
+ accept='.pdf,.png,.jpg,.jpeg'
+ />
+ <button
+ className='rounded text-white p-2 flex flex-row bg-red-500 hover:cursor-pointer hover:bg-red-400'
+ type='button'
+ onClick={() =>
+ handleConfirmSubmit(
+ formDokumen.dokumenNib.format,
+ formDokumen.dokumenNib.base64
+ )
+ }
+ >
+ <EyeIcon className={`w-4 ${isDesktop && ''}`} />
+ </button>
+ </div>
+ </div>
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsDokumen.dokumenNib}
+ </div>
+ )}
+ </div>
+ </div>
+ <div className='w-full flex flex-row items-center '>
+ <div className='w-2/5'>
+ <label className='form-label text-wrap'>NPWP Perusahaan</label>
+ </div>
+ <div className='w-3/5'>
+ <div className='flex flex-row items-start justify-between'>
+ <span className='w-3/5 text-gray-600 truncate'>
+ {formDokumen?.dokumenNpwp?.name}
+ </span>
+ <div className='w-2/5 flex flex-row gap-2'>
+ <label
+ htmlFor='dokumenNpwp'
+ className='cursor-pointer bg-red-500 hover:bg-red-600 text-white py-1 px-3 text-sm rounded'
+ >
+ Ubah
+ </label>
+ <input
+ // value={formDokumen?.dokumenNib?.name}
+ id='dokumenNpwp'
+ name='dokumenNpwp'
+ type='file'
+ title=' '
+ ref={dokumenNpwpRef}
+ className='hidden'
+ aria-invalid={errorsDokumen.dokumenNpwp}
+ onChange={handleInputChange}
+ accept='.pdf,.png,.jpg,.jpeg'
+ />
+ <button
+ className='rounded text-white p-2 flex flex-row bg-red-500 hover:cursor-pointer hover:bg-red-400'
+ type='button'
+ onClick={() =>
+ handleConfirmSubmit(
+ formDokumen.dokumenNpwp.format,
+ formDokumen.dokumenNpwp.base64
+ )
+ }
+ >
+ <EyeIcon className={`w-4 ${isDesktop && ''}`} />
+ </button>
+ </div>
+ </div>
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsDokumen.dokumenNpwp}
+ </div>
+ )}
+ </div>
+ </div>
+ <div className='w-full flex flex-row items-center '>
+ <div className='w-2/5'>
+ <label className='form-label text-wrap'>SPPKP</label>
+ </div>
+ <div className='w-3/5'>
+ <div className='flex flex-row items-start justify-between'>
+ <span className='w-3/5 text-gray-600 truncate'>
+ {formDokumen?.dokumenSppkp?.name}
+ </span>
+ <div className='w-2/5 flex flex-row gap-2'>
+ <label
+ htmlFor='dokumenSppkp'
+ className='cursor-pointer bg-red-500 hover:bg-red-600 text-white py-1 px-3 text-sm rounded'
+ >
+ Ubah
+ </label>
+ <input
+ // value={formDokumen?.dokumenNib?.name}
+ id='dokumenSppkp'
+ name='dokumenSppkp'
+ type='file'
+ title=' '
+ ref={dokumenSppkpRef}
+ className='hidden'
+ aria-invalid={errorsDokumen.dokumenSppkp}
+ onChange={handleInputChange}
+ accept='.pdf,.png,.jpg,.jpeg'
+ />
+ <button
+ className='rounded text-white p-2 flex flex-row bg-red-500 hover:cursor-pointer hover:bg-red-400'
+ type='button'
+ onClick={() =>
+ handleConfirmSubmit(
+ formDokumen.dokumenSppkp.format,
+ formDokumen.dokumenSppkp.base64
+ )
+ }
+ >
+ <EyeIcon className={`w-4 ${isDesktop && ''}`} />
+ </button>
+ </div>
+ </div>
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsDokumen.dokumenSppkp}
+ </div>
+ )}
+ </div>
+ </div>
+
+ <div className='w-full flex flex-row items-center '>
+ <div className='w-2/5'>
+ <label className='form-label text-wrap'>
+ {' '}
+ Akta Perubahan <span className=' opacity-60'>(Opsional)</span>
+ </label>
+ </div>
+ <div className='w-3/5'>
+ <div className='flex flex-row items-start justify-between'>
+ <span className='w-3/5 text-gray-600 truncate'>
+ {formDokumen?.dokumenAktaPerubahan?.name}
+ </span>
+ <div className='w-2/5 flex flex-row gap-2'>
+ <label
+ htmlFor='dokumenAktaPerubahan'
+ className='cursor-pointer bg-red-500 hover:bg-red-600 text-white py-1 px-3 text-sm rounded'
+ >
+ Ubah
+ </label>
+ <input
+ // value={formDokumen?.dokumenNib?.name}
+ id='dokumenAktaPerubahan'
+ name='dokumendokumenAktaPerubahanSppkp'
+ type='file'
+ title=' '
+ ref={dokumenAktaPerubahanRef}
+ className='hidden'
+ aria-invalid={errorsDokumen.dokumenAktaPerubahan}
+ onChange={handleInputChange}
+ accept='.pdf,.png,.jpg,.jpeg'
+ />
+ <button
+ className='rounded text-white p-2 flex flex-row bg-red-500 hover:cursor-pointer hover:bg-red-400'
+ type='button'
+ onClick={() =>
+ handleConfirmSubmit(
+ formDokumen.dokumenAktaPerubahan.format,
+ formDokumen.dokumenAktaPerubahan.base64
+ )
+ }
+ >
+ <EyeIcon className={`w-4 ${isDesktop && ''}`} />
+ </button>
+ </div>
+ </div>
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsDokumen.dokumenAktaPerubahan}
+ </div>
+ )}
+ </div>
+ </div>
+
+ <div className='w-full flex flex-row items-center '>
+ <div className='w-2/5'>
+ <label className='form-label text-wrap'>
+ KTP Dirut/Direktur{' '}
+ <span className=' opacity-60'>(Opsional)</span>
+ </label>
+ </div>
+ <div className='w-3/5'>
+ <div className='flex flex-row items-start justify-between'>
+ <span className='w-3/5 text-gray-600 truncate'>
+ {formDokumen?.dokumenKtpDirut?.name}
+ </span>
+ <div className='w-2/5 flex flex-row gap-2'>
+ <label
+ htmlFor='dokumenKtpDirut'
+ className='cursor-pointer bg-red-500 hover:bg-red-600 text-white py-1 px-3 text-sm rounded'
+ >
+ Ubah
+ </label>
+ <input
+ // value={formDokumen?.dokumenNib?.name}
+ id='dokumenKtpDirut'
+ name='dokumenKtpDirut'
+ type='file'
+ title=' '
+ ref={dokumenKtpDirutRef}
+ className='hidden'
+ aria-invalid={errorsDokumen.dokumenKtpDirut}
+ onChange={handleInputChange}
+ accept='.pdf,.png,.jpg,.jpeg'
+ />
+ <button
+ className='rounded text-white p-2 flex flex-row bg-red-500 hover:cursor-pointer hover:bg-red-400'
+ type='button'
+ onClick={() =>
+ handleConfirmSubmit(
+ formDokumen.dokumenKtpDirut.format,
+ formDokumen.dokumenKtpDirut.base64
+ )
+ }
+ >
+ <EyeIcon className={`w-4 ${isDesktop && ''}`} />
+ </button>
+ </div>
+ </div>
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsDokumen.dokumenKtpDirut}
+ </div>
+ )}
+ </div>
+ </div>
+
+ <div className='w-full flex flex-row items-center '>
+ <div className='w-2/5'>
+ <label className='form-label text-wrap'>
+ Akta Pendirian <span className=' opacity-60'>(Opsional)</span>
+ </label>
+ </div>
+ <div className='w-3/5'>
+ <div className='flex flex-row items-start justify-between'>
+ <span className='w-3/5 text-gray-600 truncate'>
+ {formDokumen?.dokumenAktaPendirian?.name}
+ </span>
+ <div className='w-2/5 flex flex-row gap-2'>
+ <label
+ htmlFor='dokumenAktaPendirian'
+ className='cursor-pointer bg-red-500 hover:bg-red-600 text-white py-1 px-3 text-sm rounded'
+ >
+ Ubah
+ </label>
+ <input
+ // value={formDokumen?.dokumenNib?.name}
+ id='dokumenAktaPendirian'
+ name='dokumenAktaPendirian'
+ type='file'
+ title=' '
+ ref={dokumenAktaPendirianRef}
+ className='hidden'
+ aria-invalid={errorsDokumen.dokumenAktaPendirian}
+ onChange={handleInputChange}
+ accept='.pdf,.png,.jpg,.jpeg'
+ />
+ <button
+ className='rounded text-white p-2 flex flex-row bg-red-500 hover:cursor-pointer hover:bg-red-400'
+ type='button'
+ onClick={() =>
+ handleConfirmSubmit(
+ formDokumen.dokumenAktaPendirian.format,
+ formDokumen.dokumenAktaPendirian.base64
+ )
+ }
+ >
+ <EyeIcon className={`w-4 ${isDesktop && ''}`} />
+ </button>
+ </div>
+ </div>
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsDokumen.dokumenAktaPendirian}
+ </div>
+ )}
+ </div>
+ </div>
+
+ <div className='w-full flex flex-row items-center '>
+ <div className='w-2/5'>
+ <label className='form-label text-wrap'>
+ Laporan Keuangan
+ <span className=' opacity-60'>(Opsional)</span>
+ </label>
+ </div>
+ <div className='w-3/5'>
+ <div className='flex flex-row items-start justify-between'>
+ <span className='w-3/5 text-gray-600 truncate'>
+ {formDokumen?.dokumenLaporanKeuangan?.name}
+ </span>
+ <div className='w-2/5 flex flex-row gap-2'>
+ <label
+ htmlFor='dokumenLaporanKeuangan'
+ className='cursor-pointer bg-red-500 hover:bg-red-600 text-white py-1 px-3 text-sm rounded'
+ >
+ Ubah
+ </label>
+ <input
+ // value={formDokumen?.dokumenNib?.name}
+ id='dokumenLaporanKeuangan'
+ name='dokumenLaporanKeuangan'
+ type='file'
+ title=' '
+ ref={dokumenLaporanKeuanganRef}
+ className='hidden'
+ aria-invalid={errorsDokumen.dokumenLaporanKeuangan}
+ onChange={handleInputChange}
+ accept='.pdf,.png,.jpg,.jpeg'
+ />
+ <button
+ className='rounded text-white p-2 flex flex-row bg-red-500 hover:cursor-pointer hover:bg-red-400'
+ type='button'
+ onClick={() =>
+ handleConfirmSubmit(
+ formDokumen.dokumenLaporanKeuangan.format,
+ formDokumen.dokumenLaporanKeuangan.base64
+ )
+ }
+ >
+ <EyeIcon className={`w-4 ${isDesktop && ''}`} />
+ </button>
+ </div>
+ </div>
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsDokumen.dokumenLaporanKeuangan}
+ </div>
+ )}
+ </div>
+ </div>
+
+ <div className='w-full flex flex-row items-center '>
+ <div className='w-2/5'>
+ <label className='form-label text-wrap'>
+ Foto Kantor (Tampak Depan)
+ </label>
+ </div>
+ <div className='w-3/5'>
+ <div className='flex flex-row items-start justify-between'>
+ <span className='w-3/5 text-gray-600 truncate'>
+ {formDokumen?.dokumenFotoKantor?.name}
+ </span>
+ <div className='w-2/5 flex flex-row gap-2'>
+ <label
+ htmlFor='dokumenFotoKantor'
+ className='cursor-pointer bg-red-500 hover:bg-red-600 text-white py-1 px-3 text-sm rounded'
+ >
+ Ubah
+ </label>
+ <input
+ // value={formDokumen?.dokumenNib?.name}
+ id='dokumenFotoKantor'
+ name='dokumenFotoKantor'
+ type='file'
+ title=' '
+ ref={dokumenFotoKantorRef}
+ className='hidden'
+ aria-invalid={errorsDokumen.dokumenFotoKantor}
+ onChange={handleInputChange}
+ accept='.pdf,.png,.jpg,.jpeg'
+ />
+ <button
+ className='rounded text-white p-2 flex flex-row bg-red-500 hover:cursor-pointer hover:bg-red-400'
+ type='button'
+ onClick={() =>
+ handleConfirmSubmit(
+ formDokumen.dokumenFotoKantor.format,
+ formDokumen.dokumenFotoKantor.base64
+ )
+ }
+ >
+ <EyeIcon className={`w-4 ${isDesktop && ''}`} />
+ </button>
+ </div>
+ </div>
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsDokumen.dokumenFotoKantor}
+ </div>
+ )}
+ </div>
+ </div>
+
+ <div className='w-full flex flex-row items-center '>
+ <div className='w-2/5'>
+ <label className='form-label text-wrap'>Tempat Bekerja</label>
+ </div>
+ <div className='w-3/5'>
+ <div className='flex flex-row items-start justify-between'>
+ <span className='w-3/5 text-gray-600 truncate'>
+ {formDokumen?.dokumenTempatBekerja?.name}
+ </span>
+ <div className='w-2/5 flex flex-row gap-2'>
+ <label
+ htmlFor='dokumenTempatBekerja'
+ className='cursor-pointer bg-red-500 hover:bg-red-600 text-white py-1 px-3 text-sm rounded'
+ >
+ Ubah
+ </label>
+ <input
+ // value={formDokumen?.dokumenNib?.name}
+ id='dokumenTempatBekerja'
+ name='dokumenTempatBekerja'
+ type='file'
+ title=' '
+ ref={dokumenTempatBekerjaRef}
+ className='hidden'
+ aria-invalid={errorsDokumen.dokumenTempatBekerja}
+ onChange={handleInputChange}
+ accept='.pdf,.png,.jpg,.jpeg'
+ />
+ <button
+ className='rounded text-white p-2 flex flex-row bg-red-500 hover:cursor-pointer hover:bg-red-400'
+ type='button'
+ onClick={() =>
+ handleConfirmSubmit(
+ formDokumen.dokumenTempatBekerja.format,
+ formDokumen.dokumenTempatBekerja.base64
+ )
+ }
+ >
+ <EyeIcon className={`w-4 ${isDesktop && ''}`} />
+ </button>
+ </div>
+ {/* <Image
+ src={`data:image/png;base64, ${formDokumen.dokumenNib.base64}`}
+ alt='Contoh SPPKP'
+ className='w-full h-full '
+ width={800}
+ height={800}
+ quality={85}
+ /> */}
+ </div>
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsDokumen.dokumenTempatBekerja}
+ </div>
+ )}
+ </div>
+ </div>
+ </form>
+ </div>
+ )}
+ {isDesktop && (
+ <BottomPopup
+ className='!container'
+ title='Dokumen'
+ active={isExample}
+ close={() => setIsExample(false)}
+ >
+ <div className='flex justify-center items-center p-2'>
+ {/* <embed
+ src={`data:${format};base64,${base64}`}
+ type={format}
+ width='100%'
+ height='600px'
+ /> */}
+ <iframe
+ src={`data:${format};base64,${base64}`}
+ width='100%'
+ height='100%'
+ title='Document'
+ ></iframe>
+ </div>
+ </BottomPopup>
+ )}
+ {isMobile && (
+ <BottomPopup
+ className='!container'
+ title='Dokumen'
+ active={isExample}
+ close={() => setIsExample(false)}
+ >
+ <div className='flex justify-center items-center p-2'>
+ {/* <embed
+ src={`data:${format};base64,${base64}`}
+ type={format}
+ width='100%'
+ height='100%'
+ /> */}
+ <object
+ data={`data:${format};base64,${base64}`}
+ type={format}
+ width='100%'
+ height='100%'
+ onError={(e) => {
+ // Jika <object> gagal menampilkan PDF, unduh otomatis
+ const link = document.createElement('a');
+ link.href = `data:${format};base64,${base64}`;
+ link.download = 'document.pdf';
+ link.click();
+ }}
+ >
+ PDF tidak dapat ditampilkan.
+ <a
+ href={`data:${format};base64,${base64}`}
+ download='document.pdf'
+ >
+ {' '}
+ Klik <span className='text-red-500'>di sini</span> untuk
+ mengunduh PDF
+ </a>
+ </object>
+ </div>
+ </BottomPopup>
+ )}
+ </>
+ );
+};
+
+export default KonfirmasiDokumen;
+
+{
+ /* <iframe
+ src={`data:application/octet-stream;base64, ${base64}`}
+ // src={`data:application/${format};base64, ${base64}`}
+ width='800px'
+ height='600px'
+ title='NPWP File'
+ frameBorder='0'
+ sandbox
+></iframe> */
+}
+{
+ /* <Image
+ src={`data:image/${format};base64, ${base64}`}
+ alt='Contoh SPPKP'
+ className='w-full h-full '
+ width={1200}
+ height={1200}
+ quality={85}
+/> */
+}
diff --git a/src/lib/pengajuan-tempo/component/KontakPerusahaan.jsx b/src/lib/pengajuan-tempo/component/KontakPerusahaan.jsx
new file mode 100644
index 00000000..e7bfdbbe
--- /dev/null
+++ b/src/lib/pengajuan-tempo/component/KontakPerusahaan.jsx
@@ -0,0 +1,586 @@
+import React, { useEffect, useMemo, useRef } from 'react';
+import { usePengajuanTempoStoreKontakPerson } from '../../../../src-migrate/modules/register/stores/usePengajuanTempoStore';
+import useDevice from '@/core/hooks/useDevice';
+const KontakPerusahaan = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => {
+ const {
+ formKontakPerson,
+ errorsKontakPerson,
+ validateKontakPerson,
+ updateFormKontakPerson,
+ } = usePengajuanTempoStoreKontakPerson();
+ const { isDesktop, isMobile } = useDevice();
+ const handleInputChange = (event) => {
+ const { name, value } = event.target;
+ updateFormKontakPerson(name, value);
+ validateKontakPerson();
+ };
+
+ const isFormValid = useMemo(
+ () => Object.keys(errorsKontakPerson).length === 0,
+ [errorsKontakPerson]
+ );
+
+ const direkturNameRef = useRef(null);
+ const direkturMobileRef = useRef(null);
+ const direkturEmailRef = useRef(null);
+ const purchasingNameRef = useRef(null);
+ const purchasingEmailRef = useRef(null);
+ const purchasingMobileRef = useRef(null);
+ const financeNameRef = useRef(null);
+ const financeMobileRef = useRef(null);
+ const financeEmailRef = useRef(null);
+
+ useEffect(() => {
+ const loadIndustries = async () => {
+ if (!isFormValid) {
+ const options = {
+ behavior: 'smooth',
+ block: 'center',
+ };
+ if (errorsKontakPerson.direkturName && direkturNameRef.current) {
+ direkturNameRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errorsKontakPerson.direkturMobile && direkturMobileRef.current) {
+ direkturMobileRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errorsKontakPerson.direkturEmail && direkturEmailRef.current) {
+ direkturEmailRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errorsKontakPerson.purchasingName && purchasingNameRef.current) {
+ purchasingNameRef.current.scrollIntoView(options);
+ return;
+ }
+ if (
+ errorsKontakPerson.purchasingMobile &&
+ purchasingMobileRef.current
+ ) {
+ purchasingMobileRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errorsKontakPerson.purchasingEmail && purchasingEmailRef.current) {
+ purchasingEmailRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errorsKontakPerson.financeName && financeNameRef.current) {
+ financeNameRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errorsKontakPerson.financeMobile && financeMobileRef.current) {
+ financeMobileRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errorsKontakPerson.financeEmail && financeEmailRef.current) {
+ financeEmailRef.current.scrollIntoView(options);
+ return;
+ }
+ }
+ };
+ loadIndustries();
+ }, [buttonSubmitClick, chekValid]);
+
+ useEffect(() => {
+ validateKontakPerson();
+ }, [buttonSubmitClick]);
+ return (
+ <>
+ {isDesktop && (
+ <div className=''>
+ <h1 className={`font-bold ${isKonfirmasi ? 'text-xl' : ''}`}>
+ Kontak Person
+ </h1>
+ <form className='flex flex-col w-full '>
+ <div className='w-full grid grid-row-2 gap-5'>
+ <div className='flex flex-row justify-between items-start'>
+ <div className='w-2/5'>
+ <label className='form-label text-nowrap'>
+ Nama Lengkap Direktur
+ </label>
+ </div>
+ <div className='w-3/5'>
+ <input
+ value={formKontakPerson.direkturName}
+ id='direkturName'
+ name='direkturName'
+ placeholder='Masukkan nama direktur anda'
+ type='text'
+ className='form-input'
+ aria-invalid={errorsKontakPerson.direkturName}
+ ref={direkturNameRef}
+ onChange={handleInputChange}
+ />
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsKontakPerson.direkturName}
+ </div>
+ )}
+ </div>
+ </div>
+
+ <div className='flex flex-row justify-between items-start'>
+ <div className='w-2/5'>
+ <label className='form-label text-nowrap'>
+ No. Telpon Direktur
+ </label>
+ {!isKonfirmasi && (
+ <span className='text-xs opacity-60'>
+ isi nomor telpon direktur di perusahaan kamu
+ </span>
+ )}
+ </div>
+ <div className='w-3/5'>
+ <input
+ id='direkturMobile'
+ name='direkturMobile'
+ ref={direkturMobileRef}
+ placeholder='Masukkan nomor direktur anda'
+ type='tel'
+ value={formKontakPerson.direkturMobile}
+ className='form-input'
+ aria-invalid={errorsKontakPerson.direkturMobile}
+ onChange={handleInputChange}
+ />
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsKontakPerson.direkturMobile}
+ </div>
+ )}
+ </div>
+ </div>
+
+ <div className='flex flex-row justify-between items-start'>
+ <div className='w-2/5'>
+ <label className='form-label text-nowrap'>
+ Email Direktur
+ </label>
+ {!isKonfirmasi && (
+ <span className='text-xs opacity-60'>
+ isi email Direktur yang sesuai
+ </span>
+ )}
+ </div>
+ <div className='w-3/5'>
+ <input
+ id='direkturEmail'
+ name='direkturEmail'
+ ref={direkturEmailRef}
+ placeholder='contoh@email.com'
+ type='email'
+ value={formKontakPerson.direkturEmail}
+ className='form-input'
+ aria-invalid={errorsKontakPerson.direkturEmail}
+ onChange={handleInputChange}
+ />
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsKontakPerson.direkturEmail}
+ </div>
+ )}
+ </div>
+ </div>
+
+ <div className='flex flex-row justify-between items-start'>
+ <div className='w-2/5'>
+ <label className='form-label text-nowrap'>
+ Nama Purchasing
+ </label>
+ {!isKonfirmasi && (
+ <span className='text-xs opacity-60'>
+ isi nama purchasing yang bertanggung jawab di perusahaan
+ anda
+ </span>
+ )}
+ </div>
+ <div className='w-3/5'>
+ <input
+ id='purchasingName'
+ name='purchasingName'
+ ref={purchasingNameRef}
+ placeholder='Masukkan nama purchasing anda'
+ value={formKontakPerson.purchasingName}
+ type='text'
+ className='form-input'
+ aria-invalid={errorsKontakPerson.purchasingName}
+ onChange={handleInputChange}
+ />
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsKontakPerson.purchasingName}
+ </div>
+ )}
+ </div>
+ </div>
+
+ <div className='flex flex-row justify-between items-start'>
+ <div className='w-2/5'>
+ <label className='form-label text-nowrap'>
+ No. Telpon Purchasing
+ </label>
+ {!isKonfirmasi && (
+ <span className='text-xs opacity-60'>
+ isi nomor purchasing yang bertanggung jawab di perusahaan
+ anda
+ </span>
+ )}
+ </div>
+ <div className='w-3/5'>
+ <input
+ id='purchasingMobile'
+ name='purchasingMobile'
+ ref={financeMobileRef}
+ placeholder='Masukkan nomor purchasing anda'
+ value={formKontakPerson.purchasingMobile}
+ type='tel'
+ className='form-input'
+ aria-invalid={errorsKontakPerson.purchasingMobile}
+ onChange={handleInputChange}
+ />
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsKontakPerson.purchasingMobile}
+ </div>
+ )}
+ </div>
+ </div>
+
+ <div className='flex flex-row justify-between items-start'>
+ <div className='w-2/5'>
+ <label className='form-label text-nowrap'>
+ Email Purchasing
+ </label>
+ {!isKonfirmasi && (
+ <span className='text-xs opacity-60'>
+ isi email purchasing dengan benar
+ </span>
+ )}
+ </div>
+ <div className='w-3/5'>
+ <input
+ id='purchasingEmail'
+ name='purchasingEmail'
+ ref={purchasingEmailRef}
+ placeholder='contoh@email.com'
+ value={formKontakPerson.purchasingEmail}
+ type='email'
+ className='form-input'
+ aria-invalid={errorsKontakPerson.purchasingEmail}
+ onChange={handleInputChange}
+ />
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsKontakPerson.purchasingEmail}
+ </div>
+ )}
+ </div>
+ </div>
+
+ <div className='flex flex-row justify-between items-start'>
+ <div className='w-2/5'>
+ <label className='form-label text-nowrap'>
+ Nama Finance
+ </label>
+ {!isKonfirmasi && (
+ <span className='text-xs opacity-60'>
+ isi nama finance yang bertanggung jawab di perusahaan anda
+ </span>
+ )}
+ </div>
+ <div className='w-3/5'>
+ <input
+ id='financeName'
+ name='financeName'
+ ref={financeNameRef}
+ placeholder='Masukkan nama finance'
+ value={formKontakPerson.financeName}
+ type='text'
+ className='form-input'
+ aria-invalid={errorsKontakPerson.financeName}
+ onChange={handleInputChange}
+ />
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsKontakPerson.financeName}
+ </div>
+ )}
+ </div>
+ </div>
+ <div className='flex flex-row justify-between items-start'>
+ <div className='w-2/5'>
+ <label className='form-label text-nowrap'>
+ No. Telpon Finance
+ </label>
+ {!isKonfirmasi && (
+ <span className='text-xs opacity-60'>
+ isi nomor finance yang bertanggung jawab di perusahaan
+ anda
+ </span>
+ )}
+ </div>
+ <div className='w-3/5'>
+ <input
+ id='financeMobile'
+ name='financeMobile'
+ ref={financeMobileRef}
+ placeholder='Masukkan nomor finance'
+ value={formKontakPerson.financeMobile}
+ type='tel'
+ className='form-input'
+ aria-invalid={errorsKontakPerson.financeMobile}
+ onChange={handleInputChange}
+ />
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsKontakPerson.financeMobile}
+ </div>
+ )}
+ </div>
+ </div>
+
+ <div className='flex flex-row justify-between items-start'>
+ <div className='w-2/5'>
+ <label className='form-label text-nowrap'>
+ Email Finance
+ </label>
+ {!isKonfirmasi && (
+ <span className='text-xs opacity-60'>
+ isi email finance dengan benar
+ </span>
+ )}
+ </div>
+ <div className='w-3/5'>
+ <input
+ id='financeEmail'
+ name='financeEmail'
+ ref={financeEmailRef}
+ placeholder='contoh@email.com'
+ type='email'
+ value={formKontakPerson.financeEmail}
+ className='form-input'
+ aria-invalid={errorsKontakPerson.financeEmail}
+ onChange={handleInputChange}
+ />
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsKontakPerson.financeEmail}
+ </div>
+ )}
+ </div>
+ </div>
+ </div>
+ </form>
+ </div>
+ )}
+ {isMobile && (
+ <div className='text-sm'>
+ <h1
+ className={`font-bold py-4 mt-8 ${
+ isKonfirmasi ? 'hidden' : 'text-xl'
+ }`}
+ >
+ Kontak Person
+ </h1>
+ <form className='flex flex-col w-full '>
+ <div className='w-full grid grid-row-2 gap-4'>
+ <div className='flex flex-col gap-2 justify-between items-start'>
+ <label className='form-label text-nowrap'>
+ Nama Lengkap Direktur
+ </label>
+ <input
+ value={formKontakPerson.direkturName}
+ id='direkturName'
+ name='direkturName'
+ placeholder='Masukkan nama direktur anda'
+ type='text'
+ className='form-input'
+ aria-invalid={errorsKontakPerson.direkturName}
+ ref={direkturNameRef}
+ onChange={handleInputChange}
+ />
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsKontakPerson.direkturName}
+ </div>
+ )}
+ </div>
+
+ <div className='flex flex-col gap-2 justify-between items-start'>
+ <label className='form-label text-nowrap'>
+ No. Telpon Direktur
+ </label>
+ <input
+ id='direkturMobile'
+ name='direkturMobile'
+ ref={direkturMobileRef}
+ placeholder='Masukkan nomor direktur anda'
+ type='tel'
+ value={formKontakPerson.direkturMobile}
+ className='form-input'
+ aria-invalid={errorsKontakPerson.direkturMobile}
+ onChange={handleInputChange}
+ />
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsKontakPerson.direkturMobile}
+ </div>
+ )}
+ </div>
+
+ <div className='flex flex-col gap-2 justify-between items-start'>
+ <label className='form-label text-nowrap'>
+ Email Direktur
+ </label>
+ <input
+ id='direkturEmail'
+ name='direkturEmail'
+ ref={direkturEmailRef}
+ placeholder='contoh@email.com'
+ type='email'
+ value={formKontakPerson.direkturEmail}
+ className='form-input'
+ aria-invalid={errorsKontakPerson.direkturEmail}
+ onChange={handleInputChange}
+ />
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsKontakPerson.direkturEmail}
+ </div>
+ )}
+ </div>
+
+ <div className='flex flex-col gap-2 justify-between items-start'>
+ <label className='form-label text-nowrap'>
+ Nama Purchasing
+ </label>
+ <input
+ id='purchasingName'
+ name='purchasingName'
+ ref={purchasingNameRef}
+ placeholder='Masukkan nama purchasing anda'
+ value={formKontakPerson.purchasingName}
+ type='text'
+ className='form-input'
+ aria-invalid={errorsKontakPerson.purchasingName}
+ onChange={handleInputChange}
+ />
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsKontakPerson.purchasingName}
+ </div>
+ )}
+ </div>
+
+ <div className='flex flex-col gap-2 justify-between items-start'>
+ <label className='form-label text-nowrap'>
+ No. Telpon Purchasing
+ </label>
+ <input
+ id='purchasingMobile'
+ name='purchasingMobile'
+ ref={financeMobileRef}
+ placeholder='Masukkan nomor purchasing anda'
+ value={formKontakPerson.purchasingMobile}
+ type='tel'
+ className='form-input'
+ aria-invalid={errorsKontakPerson.purchasingMobile}
+ onChange={handleInputChange}
+ />
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsKontakPerson.purchasingMobile}
+ </div>
+ )}
+ </div>
+
+ <div className='flex flex-col gap-2 justify-between items-start'>
+ <label className='form-label text-nowrap'>
+ Email Purchasing
+ </label>
+ <input
+ id='purchasingEmail'
+ name='purchasingEmail'
+ ref={purchasingEmailRef}
+ placeholder='contoh@email.com'
+ value={formKontakPerson.purchasingEmail}
+ type='email'
+ className='form-input'
+ aria-invalid={errorsKontakPerson.purchasingEmail}
+ onChange={handleInputChange}
+ />
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsKontakPerson.purchasingEmail}
+ </div>
+ )}
+ </div>
+
+ <div className='flex flex-col gap-2 justify-between items-start'>
+ <label className='form-label text-nowrap'>Nama Finance</label>
+ <input
+ id='financeName'
+ name='financeName'
+ ref={financeNameRef}
+ placeholder='Masukkan nama finance'
+ value={formKontakPerson.financeName}
+ type='text'
+ className='form-input'
+ aria-invalid={errorsKontakPerson.financeName}
+ onChange={handleInputChange}
+ />
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsKontakPerson.financeName}
+ </div>
+ )}
+ </div>
+ <div className='flex flex-col gap-2 justify-between items-start'>
+ <label className='form-label text-nowrap'>
+ No. Telpon Finance
+ </label>
+ <input
+ id='financeMobile'
+ name='financeMobile'
+ ref={financeMobileRef}
+ placeholder='Masukkan nomor finance'
+ value={formKontakPerson.financeMobile}
+ type='tel'
+ className='form-input'
+ aria-invalid={errorsKontakPerson.financeMobile}
+ onChange={handleInputChange}
+ />
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsKontakPerson.financeMobile}
+ </div>
+ )}
+ </div>
+
+ <div className='flex flex-col gap-2 justify-between items-start'>
+ <label className='form-label text-nowrap'>Email Finance</label>
+ <input
+ id='financeEmail'
+ name='financeEmail'
+ ref={financeEmailRef}
+ placeholder='contoh@email.com'
+ type='email'
+ value={formKontakPerson.financeEmail}
+ className='form-input'
+ aria-invalid={errorsKontakPerson.financeEmail}
+ onChange={handleInputChange}
+ />
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsKontakPerson.financeEmail}
+ </div>
+ )}
+ </div>
+ </div>
+ </form>
+ </div>
+ )}
+ </>
+ );
+};
+
+export default KontakPerusahaan;
diff --git a/src/lib/pengajuan-tempo/component/PengajuanTempo.jsx b/src/lib/pengajuan-tempo/component/PengajuanTempo.jsx
new file mode 100644
index 00000000..d0e1fcc6
--- /dev/null
+++ b/src/lib/pengajuan-tempo/component/PengajuanTempo.jsx
@@ -0,0 +1,352 @@
+import React from 'react';
+import { useMemo, useState, useEffect, useRef } from 'react';
+import Stepper from './Stepper';
+import InformasiPerusahaan from './informasiPerusahaan';
+import KontakPerusahaan from './KontakPerusahaan';
+import Pengiriman from './Pengiriman';
+import Referensi from './Referensi';
+import Dokumen from './Dokumen';
+import Konfirmasi from './Konfirmasi';
+import useAuth from '@/core/hooks/useAuth';
+import { useRouter } from 'next/router';
+import { Controller, useForm } from 'react-hook-form';
+import {
+ usePengajuanTempoStore,
+ usePengajuanTempoStoreKontakPerson,
+ usePengajuanTempoStorePengiriman,
+ usePengajuanTempoStoreSupplier,
+ usePengajuanTempoStoreDokumen,
+} from '../../../../src-migrate/modules/register/stores/usePengajuanTempoStore';
+import { ChevronRightIcon, ChevronLeftIcon } from '@heroicons/react/24/outline';
+import createPengajuanTempoApi from '../api/createPengajuanTempoApi';
+import { Button, Checkbox, Spinner, Tooltip } from '@chakra-ui/react';
+import clsxm from '~/libs/clsxm';
+import { toast } from 'react-hot-toast';
+import useDevice from '@/core/hooks/useDevice';
+const PengajuanTempo = () => {
+ const { isDesktop, isMobile } = useDevice();
+ const [currentStep, setCurrentStep] = React.useState(0);
+ const NUMBER_OF_STEPS = 6;
+ const [isLoading, setIsLoading] = useState(false);
+ const { form, errors, validate, updateForm } = usePengajuanTempoStore();
+ const { control, watch, setValue } = useForm();
+ const auth = useAuth();
+ const router = useRouter();
+ const { formDokumen, errorsDokumen, validateDokumen, updateFormDokumen } =
+ usePengajuanTempoStoreDokumen();
+ const {
+ formKontakPerson,
+ errorsKontakPerson,
+ validateKontakPerson,
+ updateFormKontakPerson,
+ } = usePengajuanTempoStoreKontakPerson();
+ const {
+ formSupplier,
+ errorsSupplier,
+ validateSupplier,
+ updateFormSupplier,
+ hasSavedata,
+ updateHasSave,
+ } = usePengajuanTempoStoreSupplier();
+ const {
+ formPengiriman,
+ errorsPengiriman,
+ validatePengiriman,
+ updateFormPengiriman,
+ } = usePengajuanTempoStorePengiriman();
+ const [notValid, setNotValid] = useState(false);
+ const [buttonSubmitClick, setButtonSubmitClick] = useState(false);
+ const stepDivs = [
+ <InformasiPerusahaan
+ key='informasi-perusahaan'
+ chekValid={notValid}
+ buttonSubmitClick={buttonSubmitClick}
+ />,
+ <KontakPerusahaan
+ key='kontak-perusahaan'
+ chekValid={notValid}
+ buttonSubmitClick={buttonSubmitClick}
+ />,
+ <Pengiriman
+ key='pengiriman'
+ chekValid={notValid}
+ buttonSubmitClick={buttonSubmitClick}
+ />,
+ <Referensi
+ key='referensi'
+ chekValid={notValid}
+ buttonSubmitClick={buttonSubmitClick}
+ />,
+ <Dokumen
+ key='dokumen'
+ chekValid={notValid}
+ buttonSubmitClick={buttonSubmitClick}
+ />,
+ <Konfirmasi
+ key='konfirmasi'
+ chekValid={notValid}
+ buttonSubmitClick={buttonSubmitClick}
+ />,
+ ];
+
+ const stepDivsError = [
+ errors,
+ errorsKontakPerson,
+ errorsPengiriman,
+ errorsSupplier,
+ errorsDokumen,
+ <div key='konfirmasi'>Konfirmasi</div>,
+ ];
+ const stepDivsForm = [
+ form,
+ formKontakPerson,
+ formPengiriman,
+ formSupplier,
+ formDokumen,
+ '',
+ ];
+ const stepDivsUpdateForm = [
+ updateForm,
+ updateFormKontakPerson,
+ updateFormPengiriman,
+ updateFormSupplier,
+ updateFormDokumen,
+ <div key='konfirmasi'>Konfirmasi</div>,
+ ];
+ const stepLabels = [
+ 'informasi_perusahaan',
+ 'kontak_person',
+ 'Pengiriman',
+ 'Referensi',
+ 'Dokumen',
+ 'Konfirmasi',
+ ];
+ const isFormValid = useMemo(
+ () => Object.keys(stepDivsError[currentStep]).length === 0,
+ [stepDivsError[currentStep]]
+ );
+ useEffect(() => {
+ validate();
+ validateKontakPerson();
+ validatePengiriman();
+ validateDokumen();
+ updateHasSave(false);
+
+ window.scrollTo({
+ top: 0,
+ behavior: 'smooth',
+ });
+ }, [currentStep, buttonSubmitClick]);
+
+ useEffect(() => {
+ const cachedData = getFromLocalStorage(stepLabels[currentStep]);
+ if (cachedData) {
+ if (currentStep == 3) {
+ stepDivsUpdateForm[currentStep](cachedData);
+ } else if (currentStep == 4) {
+ Object.keys(cachedData).forEach((key) => {
+ const { name, format, base64 } = cachedData[key];
+ stepDivsUpdateForm[currentStep](key, name, format, base64);
+ });
+ } else {
+ Object.keys(cachedData).forEach((key) => {
+ stepDivsUpdateForm[currentStep](key, cachedData[key]);
+ });
+ }
+ }
+ validate();
+ validateKontakPerson();
+ validatePengiriman();
+ validateDokumen();
+ updateHasSave(false);
+ }, [currentStep]);
+ const goToNextStep = () => {
+ if (!isFormValid) {
+ setNotValid(true);
+ setButtonSubmitClick(!buttonSubmitClick);
+ return;
+ } else {
+ saveToLocalStorage(stepLabels[currentStep], stepDivsForm[currentStep]);
+ setButtonSubmitClick(!buttonSubmitClick);
+ setNotValid(false);
+ }
+ setCurrentStep((prev) => (prev === NUMBER_OF_STEPS - 1 ? prev : prev + 1));
+ };
+
+ const handleDaftarTempo = async () => {
+ for (const error of stepDivsError) {
+ if (error.length > 0) {
+ return;
+ }
+ }
+ const productOrder = formSupplier.map((product) => ({
+ supplier: product.supplier,
+ pic: product.pic,
+ telepon: product.telepon,
+ durasiTempo: product.durasiTempo,
+ creditLimit: product.creditLimit,
+ }));
+
+ const formattedDokumen = Object.entries(formDokumen).map(([key, doc]) => ({
+ documentName: key,
+ details: {
+ name: doc.name,
+ format: doc.format,
+ base64: doc.base64,
+ },
+ }));
+
+ const data2 = {
+ user_id: auth.id,
+ ...form,
+ ...formKontakPerson,
+ ...formPengiriman,
+ formDocs: JSON.stringify(formattedDokumen),
+ formSupplier: JSON.stringify(productOrder),
+ };
+ const toastId = toast.loading('Mengirimkan formulir pengajuan tempo...');
+ setIsLoading(true);
+ try {
+ let address5;
+ const address = await createPengajuanTempoApi({
+ id: '0',
+ user_id: auth.id,
+ ...form,
+ });
+ if (address.id) {
+ const address2 = await createPengajuanTempoApi({
+ id: address.id,
+ user_id: address.userId,
+ ...formKontakPerson,
+ });
+ if (address2.id) {
+ const address3 = await createPengajuanTempoApi({
+ id: address2.id,
+ user_id: address2.userId,
+ ...formPengiriman,
+ });
+ if (address3.id) {
+ const address4 = await createPengajuanTempoApi({
+ id: address3.id,
+ user_id: address3.userId,
+ formDocs: JSON.stringify(formattedDokumen),
+ });
+ if (address4.id) {
+ address5 = await createPengajuanTempoApi({
+ id: address4.id,
+ user_id: address4.userId,
+ tempo_request: true,
+ formSupplier: JSON.stringify(productOrder),
+ });
+ }
+ }
+ }
+ }
+ toast.dismiss(toastId);
+ setIsLoading(false);
+
+ if (address5.id) {
+ toast.success('Pengajuan tempo berhasil dilakukan');
+ // removeFromLocalStorage();
+ router.push('/pengajuan-tempo/finish?tempo_id=SO-2023-06480');
+ }
+ } catch (error) {
+ toast.dismiss(toastId);
+ setIsLoading(false);
+
+ toast.error('Terjadi kesalahan dalam pengiriman formulir');
+ console.error(error);
+ }
+ };
+
+ const goToPreviousStep = () => {
+ setCurrentStep((prev) => (prev <= 0 ? prev : prev - 1));
+ };
+
+ const saveToLocalStorage = (key, form) => {
+ localStorage.setItem(key, JSON.stringify(form));
+ };
+
+ const getFromLocalStorage = (key) => {
+ const itemStr = localStorage.getItem(key);
+ if (!itemStr) return null;
+
+ const item = JSON.parse(itemStr);
+ return item;
+ };
+ const removeFromLocalStorage = () => {
+ for (const key of stepLabels) {
+ localStorage.removeItem(key);
+ }
+ };
+
+ return (
+ <>
+ <div className='container flex flex-col items-center '>
+ <h1 className='text-h-sm md:text-title-sm font-semibold text-center mb-6'>
+ Form Pengajuan Tempo
+ </h1>
+ <p className='text-center mb-4'>
+ Lorem ipsum dolor sit amet consectetur. Commodo suspendisse at enim
+ magnis ut quisque rhoncus. Felis volutpat fringilla sollicitudin
+ ultricies. Enim non eget in lorem netus. Nisl pharetra accumsan diam
+ suspendisse.
+ </p>
+ </div>
+ <div className='h-[2px] w-full mb-20 bg-gray_r-3' />
+
+ <div className='container mt-10 flex flex-col'>
+ <div className='flex items-center justify-center'>
+ <Stepper currentStep={currentStep} numberOfSteps={NUMBER_OF_STEPS} />
+ </div>
+ <div>{stepDivs[currentStep]}</div>
+ {isDesktop && <section className='flex gap-10 mt-10'></section>}
+ {isMobile && (
+ <div className='h-[2px] bg-gray-300 w-[120%] inset-0 mt-4 mb-4 relative transform -translate-x-5'></div>
+ )}
+ <div
+ className={`flex ${
+ isMobile
+ ? 'flex-col justify-start items-start'
+ : 'flex-row justify-end items-center'
+ } gap-4 mb-8`}
+ >
+ <span className='text-xs opacity-60'>
+ *Pastikan data yang anda masukan sudah benar dan sesuai
+ </span>
+ {currentStep < 5 && (
+ <Tooltip
+ label={clsxm({
+ 'Klik simpan data terlebih dahulu':
+ currentStep === 3 && !hasSavedata,
+ })}
+ >
+ <Button
+ colorScheme='red'
+ w={`${isMobile ? 'full' : 'fit'}`}
+ isDisabled={
+ (currentStep === 3 && !hasSavedata) ||
+ currentStep === NUMBER_OF_STEPS - 1
+ }
+ onClick={goToNextStep}
+ >
+ Langkah Selanjutnya {<ChevronRightIcon className='w-5' />}
+ </Button>
+ </Tooltip>
+ )}
+ {currentStep == 5 && (
+ <Button
+ colorScheme='red'
+ w={`${isMobile ? 'full' : 'fit'}`}
+ onClick={handleDaftarTempo}
+ >
+ Daftar Tempo {<ChevronRightIcon className='w-5' />}
+ </Button>
+ )}
+ </div>
+ </div>
+ </>
+ );
+};
+
+export default PengajuanTempo;
diff --git a/src/lib/pengajuan-tempo/component/Pengiriman.jsx b/src/lib/pengajuan-tempo/component/Pengiriman.jsx
new file mode 100644
index 00000000..842e43ef
--- /dev/null
+++ b/src/lib/pengajuan-tempo/component/Pengiriman.jsx
@@ -0,0 +1,1489 @@
+import React, { useState, useEffect, useMemo, useRef } from 'react';
+import { Controller, set, useForm } from 'react-hook-form';
+import HookFormSelect from '@/core/components/elements/Select/HookFormSelect';
+import odooApi from '~/libs/odooApi';
+import stateApi from '@/lib/address/api/stateApi.js';
+import cityApi from '@/lib/address/api/cityApi';
+import { Radio, RadioGroup, Stack, Checkbox } from '@chakra-ui/react';
+import { usePengajuanTempoStorePengiriman } from '../../../../src-migrate/modules/register/stores/usePengajuanTempoStore';
+import useDevice from '@/core/hooks/useDevice';
+const Pengiriman = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => {
+ const { control, watch, setValue } = useForm();
+ const { isDesktop, isMobile } = useDevice();
+ const {
+ formPengiriman,
+ errorsPengiriman,
+ validatePengiriman,
+ updateFormPengiriman,
+ } = usePengajuanTempoStorePengiriman();
+ const [states, setState] = useState([]);
+ const [cities, setCities] = useState([]);
+ const [sameAddress, setSameAddress] = useState(false);
+ const [everyWeekday, setEveryWeekday] = useState(false);
+ const [everyWeek, setEveryWeek] = useState(false);
+ const [tukarInvoice, setTukarInvoice] = useState(false);
+ const [everyWeekdayPembayaran, setEveryWeekdayPembayaran] = useState(false);
+ const [everyWeekPembayaran, setEveryWeekPembayaran] = useState(false);
+ const [tukarInvoicePembayaran, setTukarInvoicePembayaran] = useState(false);
+ const [selectedIds, setSelectedIds] = useState(
+ formPengiriman.dokumenPengiriman
+ ? formPengiriman.dokumenPengiriman.split(',').map(Number)
+ : []
+ );
+ const [selectedIdsDokumenInvoice, setSelectedIdsselectedIdsDokumenInvoice] =
+ useState(
+ formPengiriman.dokumenPengirimanInvoice
+ ? formPengiriman.dokumenPengirimanInvoice.split(',').map(Number)
+ : []
+ );
+
+ const handleCheckboxChange = (id) => {
+ const updatedSelected = selectedIds.includes(id)
+ ? selectedIds.filter((selectedId) => selectedId !== id)
+ : [...selectedIds, id];
+
+ setSelectedIds(updatedSelected);
+
+ // Jika checkbox 'Lainnya' dipilih, aktifkan input custom
+
+ updateFormPengiriman('dokumenPengiriman', updatedSelected.join(','));
+ validatePengiriman();
+ };
+ const handleCheckboxChangeDokumenPengirimanInvoice = (id) => {
+ const updatedSelected = selectedIdsDokumenInvoice.includes(id)
+ ? selectedIdsDokumenInvoice.filter((selectedId) => selectedId !== id)
+ : [...selectedIdsDokumenInvoice, id];
+
+ setSelectedIdsselectedIdsDokumenInvoice(updatedSelected);
+
+ // Jika checkbox 'Lainnya' dipilih, aktifkan input custom
+
+ updateFormPengiriman('dokumenPengirimanInvoice', updatedSelected.join(','));
+ validatePengiriman();
+ };
+
+ useEffect(() => {
+ if (formPengiriman.dokumenPengiriman) {
+ setSelectedIds(formPengiriman.dokumenPengiriman.split(',').map(Number)); // Parse string menjadi array angka
+ }
+ }, [formPengiriman.dokumenPengiriman]);
+ useEffect(() => {
+ if (formPengiriman.dokumenPengirimanInvoice) {
+ setSelectedIdsselectedIdsDokumenInvoice(
+ formPengiriman.dokumenPengirimanInvoice.split(',').map(Number)
+ ); // Parse string menjadi array angka
+ }
+ }, [formPengiriman.dokumenPengirimanInvoice]);
+
+ // Fungsi untuk memeriksa apakah item sudah dipilih
+ const isChecked = (id) => selectedIds.includes(id);
+ const isCheckedInvoice = (id) => selectedIdsDokumenInvoice.includes(id);
+
+ useEffect(() => {
+ const loadState = async () => {
+ let dataState = await stateApi();
+ dataState = dataState.map((state) => ({
+ value: state.id,
+ label: state.name,
+ }));
+ setState(dataState);
+ };
+ loadState();
+ }, []);
+
+ const watchState = watch('statePengiriman');
+ useEffect(() => {
+ updateFormPengiriman('cityPengiriman', '');
+ if (watchState) {
+ updateFormPengiriman('statePengiriman', `${watchState}`);
+ validatePengiriman();
+ const loadCities = async () => {
+ let dataCities = await cityApi({ stateId: watchState });
+ dataCities = dataCities.map((city) => ({
+ value: city.id,
+ label: city.name,
+ }));
+ setCities(dataCities);
+ };
+ loadCities();
+ }
+ }, [watchState]);
+
+ const watchCity = watch('cityPengiriman');
+ useEffect(() => {
+ if (watchCity) {
+ updateFormPengiriman('cityPengiriman', `${watchCity}`);
+ validatePengiriman();
+ }
+ }, [watchCity]);
+ const handleInputChange = (event) => {
+ const { name, value } = event.target;
+ updateFormPengiriman(name, value);
+ validatePengiriman();
+ };
+
+ const handleEveryWeekday = () => {
+ setEveryWeekday(!everyWeekday);
+ };
+ const handleEveryWeek = () => {
+ setEveryWeek(!everyWeek);
+ };
+ const handleTukarInvoice = () => {
+ setTukarInvoice(!tukarInvoice);
+ };
+ const handleEveryWeekdayPembayaran = () => {
+ setEveryWeekdayPembayaran(!everyWeekdayPembayaran);
+ };
+ const handleEveryWeekPembayaran = () => {
+ setEveryWeekPembayaran(!everyWeekPembayaran);
+ };
+ const handleTukarInvoicePembayaran = () => {
+ setTukarInvoicePembayaran(!tukarInvoicePembayaran);
+ };
+
+ useEffect(() => {
+ updateFormPengiriman('everyWeekday', everyWeekday);
+ updateFormPengiriman('everyWeek', everyWeek);
+ updateFormPengiriman('tukarInvoice', tukarInvoice);
+ updateFormPengiriman('everyWeekdayPembayaran', everyWeekdayPembayaran);
+ updateFormPengiriman('everyWeekPembayaran', everyWeekPembayaran);
+ updateFormPengiriman('tukarInvoicePembayaran', tukarInvoicePembayaran);
+ validatePengiriman();
+ }, [
+ everyWeekday,
+ everyWeek,
+ tukarInvoice,
+ everyWeekdayPembayaran,
+ everyWeekPembayaran,
+ tukarInvoicePembayaran,
+ ]);
+
+ const isFormValid = useMemo(
+ () => Object.keys(errorsPengiriman).length === 0,
+ [errorsPengiriman]
+ );
+
+ const PICNameRef = useRef(null);
+ const streetPengirimanRef = useRef(null);
+ const statePengirimanRef = useRef(null);
+ const cityPengirimanRef = useRef(null);
+ const zipRef = useRef(null);
+ const invoicePicRef = useRef(null);
+ const streetInvoiceRef = useRef(null);
+ const stateInvoiceRef = useRef(null);
+ const cityInvoiceRef = useRef(null);
+ const everyWeekdayInputRef = useRef(null);
+ const everyWeekInputRef = useRef(null);
+ const dokumenPengirimanRef = useRef(null);
+ const dokumenPengirimanInputRef = useRef(null);
+ const dokumenPengirimanInvoiceRef = useRef(null);
+ const dokumenPengirimanInvoiceInputRef = useRef(null);
+
+ useEffect(() => {
+ const loadIndustries = async () => {
+ if (!isFormValid) {
+ const options = {
+ behavior: 'smooth',
+ block: 'center',
+ };
+ if (errorsPengiriman.PICName && PICNameRef.current) {
+ PICNameRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errorsPengiriman.streetPengiriman && streetPengirimanRef.current) {
+ streetPengirimanRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errorsPengiriman.statePengiriman && statePengirimanRef.current) {
+ statePengirimanRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errorsPengiriman.cityPengiriman && cityPengirimanRef.current) {
+ cityPengirimanRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errorsPengiriman.zip && zipRef.current) {
+ zipRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errorsPengiriman.invoicePic && invoicePicRef.current) {
+ invoicePicRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errorsPengiriman.streetInvoice && streetInvoiceRef.current) {
+ streetInvoiceRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errorsPengiriman.stateInvoice && stateInvoiceRef.current) {
+ stateInvoiceRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errorsPengiriman.cityInvoice && cityInvoiceRef.current) {
+ cityInvoiceRef.current.scrollIntoView(options);
+ return;
+ }
+ if (
+ errorsPengiriman.everyWeekdayInput &&
+ everyWeekdayInputRef.current
+ ) {
+ everyWeekdayInputRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errorsPengiriman.everyWeekInput && everyWeekInputRef.current) {
+ everyWeekInputRef.current.scrollIntoView(options);
+ return;
+ }
+ if (
+ errorsPengiriman.dokumenPengiriman &&
+ dokumenPengirimanRef.current
+ ) {
+ dokumenPengirimanRef.current.scrollIntoView(options);
+ return;
+ }
+ if (
+ errorsPengiriman.dokumenInvoice &&
+ dokumenPengirimanInvoiceRef.current
+ ) {
+ dokumenPengirimanInvoiceRef.current.scrollIntoView(options);
+ return;
+ }
+ if (
+ selectedIds &&
+ formPengiriman.dokumenPengirimanInput === '' &&
+ dokumenPengirimanInputRef.current
+ ) {
+ dokumenPengirimanInputRef.current.scrollIntoView(options);
+ return;
+ }
+ if (
+ selectedIdsDokumenInvoice &&
+ formPengiriman.dokumenPengirimanInvoiceInput === '' &&
+ dokumenPengirimanInvoiceInputRef.current
+ ) {
+ dokumenPengirimanInvoiceInputRef.current.scrollIntoView(options);
+ return;
+ }
+ }
+ };
+ loadIndustries();
+ }, [buttonSubmitClick, chekValid]);
+
+ useEffect(() => {
+ validatePengiriman();
+ if (formPengiriman.isSameAddrees) {
+ const isSame = formPengiriman.isSameAddrees;
+ if (isSame == 'true') {
+ setSameAddress(true);
+ } else {
+ setSameAddress(false);
+ }
+ }
+ }, [buttonSubmitClick]);
+ useEffect(() => {
+ if (formPengiriman.isSameAddrees) {
+ const isSame = formPengiriman.isSameAddrees;
+ if (isSame == 'true') {
+ setSameAddress(true);
+ } else {
+ setSameAddress(false);
+ }
+ }
+ }, [formPengiriman.isSameAddrees]);
+ useEffect(() => {
+ if (sameAddress) {
+ updateFormPengiriman('streetInvoice', formPengiriman.streetPengiriman);
+ updateFormPengiriman('stateInvoice', formPengiriman.statePengiriman);
+ updateFormPengiriman('cityInvoice', formPengiriman.cityPengiriman);
+ } else {
+ updateFormPengiriman('streetInvoice', '');
+ updateFormPengiriman('stateInvoice', '');
+ updateFormPengiriman('cityInvoice', '');
+ setValue('streetInvoice', '');
+ setValue('stateInvoice', '');
+ setValue('cityInvoice', '');
+ }
+ updateFormPengiriman('isSameAddrees', `${sameAddress}`);
+ validatePengiriman();
+ }, [sameAddress]);
+
+ const getFromLocalStorage = (key) => {
+ const itemStr = localStorage.getItem(key);
+ if (!itemStr) return null;
+
+ const item = JSON.parse(itemStr);
+ return item;
+ };
+
+ const cachedData = getFromLocalStorage('Pengiriman');
+ useEffect(() => {
+ if (cachedData) {
+ setValue('cityPengiriman', parseInt(cachedData?.cityPengiriman));
+ updateFormPengiriman('cityPengiriman', `${cachedData?.cityPengiriman}`);
+ }
+ if (cachedData?.statePengiriman) {
+ setValue('statePengiriman', parseInt(cachedData?.statePengiriman));
+ }
+ if (cachedData?.stateInvoice) {
+ setValue('stateInvoice', parseInt(cachedData?.stateInvoice));
+ }
+ if (cachedData?.cityInvoice) {
+ setValue('cityInvoice', parseInt(cachedData?.cityInvoice));
+ }
+ if (cachedData?.isSameAddrees) {
+ updateFormPengiriman('isSameAddrees', `${cachedData?.isSameAddrees}`);
+ }
+ validatePengiriman();
+ }, [cachedData?.cityPengiriman]);
+ useEffect(() => {
+ if (cachedData?.everyWeek) {
+ updateFormPengiriman('everyWeek', cachedData?.everyWeek);
+ setEveryWeek(cachedData?.everyWeek);
+ }
+ if (cachedData?.everyWeekday) {
+ updateFormPengiriman('everyWeekday', cachedData?.everyWeekday);
+ setEveryWeekday(cachedData?.everyWeekday);
+ }
+ if (cachedData?.tukarInvoice) {
+ updateFormPengiriman('tukarInvoice', cachedData?.tukarInvoice);
+ setTukarInvoice(cachedData?.tukarInvoice);
+ }
+ if (cachedData?.everyWeekPembayaran) {
+ updateFormPengiriman(
+ 'everyWeekPembayaran',
+ cachedData?.everyWeekPembayaran
+ );
+ setEveryWeekPembayaran(cachedData?.everyWeekPembayaran);
+ }
+ if (cachedData?.everyWeekdayPembayaran) {
+ updateFormPengiriman(
+ 'everyWeekdayPembayaran',
+ cachedData?.everyWeekdayPembayaran
+ );
+ setEveryWeekdayPembayaran(cachedData?.everyWeekdayPembayaran);
+ }
+ if (cachedData?.tukarInvoicePembayaran) {
+ updateFormPengiriman(
+ 'tukarInvoicePembayaran',
+ cachedData?.tukarInvoicePembayaran
+ );
+ setTukarInvoicePembayaran(cachedData?.tukarInvoicePembayaran);
+ }
+ validatePengiriman();
+ }, [
+ cachedData?.everyWeek,
+ cachedData?.everyWeekday,
+ cachedData?.tukarInvoice,
+ cachedData?.everyWeekdayPembayaran,
+ cachedData?.everyWeekPembayaran,
+ cachedData?.tukarInvoicePembayaran,
+ ]);
+ const handleChangeSameAddress = () => {
+ setSameAddress(!sameAddress);
+ };
+ return (
+ <>
+ {isDesktop && (
+ <div>
+ <h1 className={`font-bold ${isKonfirmasi ? 'text-xl' : ''}`}>
+ Pengiriman
+ </h1>
+ <form className='flex flex-col w-full '>
+ <div className='w-full grid grid-row-2 gap-5'>
+ <div className='flex flex-row justify-between items-start'>
+ <div className='w-2/5'>
+ <label className='form-label text-nowrap'>
+ Nama PIC Penerimaan Barang
+ </label>
+ </div>
+ <div className='w-3/5'>
+ <input
+ value={formPengiriman.PICName}
+ id='PICName'
+ name='PICName'
+ placeholder='Masukkan nama pic pengiriman disini'
+ type='text'
+ className='form-input'
+ aria-invalid={errorsPengiriman.PICName}
+ ref={PICNameRef}
+ onChange={handleInputChange}
+ />
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsPengiriman.PICName}
+ </div>
+ )}
+ </div>
+ </div>
+
+ <div className='flex flex-row justify-between items-start'>
+ <div className='w-2/5'>
+ <label className='form-label text-nowrap'>
+ Alamat Pengiriman Barang
+ </label>
+ {!isKonfirmasi && (
+ <span className='text-xs opacity-60'>
+ pastikan alamat yang anda isi sesuai dengan alamat kirim
+ barang
+ </span>
+ )}
+ </div>
+ <div className='w-3/5 flex gap-3 flex-col'>
+ <div>
+ <input
+ id='streetPengiriman'
+ name='streetPengiriman'
+ ref={streetPengirimanRef}
+ placeholder='Masukkan alamat lengkap pengiriman barang'
+ type='text'
+ value={formPengiriman.streetPengiriman}
+ className='form-input'
+ onChange={handleInputChange}
+ />
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsPengiriman.streetPengiriman}
+ </div>
+ )}
+ </div>
+ <div className='sub-alamat flex flex-row w-full gap-3'>
+ <div className='w-2/5' ref={statePengirimanRef}>
+ <Controller
+ name='statePengiriman'
+ control={control}
+ render={(props) => (
+ <HookFormSelect
+ {...props}
+ options={states}
+ placeholder='Provinsi'
+ />
+ )}
+ />
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsPengiriman.statePengiriman}
+ </div>
+ )}
+ </div>
+ <div className='w-1/3' ref={cityPengirimanRef}>
+ <Controller
+ name='cityPengiriman'
+ control={control}
+ render={(props) => (
+ <HookFormSelect
+ {...props}
+ options={cities}
+ disabled={!watchState}
+ placeholder='Kota'
+ />
+ )}
+ />
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsPengiriman.cityPengiriman}
+ </div>
+ )}
+ </div>
+ <div className='w-1/3'>
+ <input
+ id='zipPengiriman'
+ name='zipPengiriman'
+ ref={zipRef}
+ placeholder='Kode Pos'
+ type='number'
+ value={formPengiriman.zipPengiriman}
+ className='form-input'
+ onChange={handleInputChange}
+ />
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsPengiriman.zipPengiriman}
+ </div>
+ )}
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <div className='flex flex-row justify-between items-start'>
+ <div className='w-2/5'>
+ <label className='form-label text-nowrap'>
+ Nama PIC Penerimaan Invoice
+ </label>
+ </div>
+ <div className='w-3/5'>
+ <input
+ value={formPengiriman.invoicePic}
+ id='invoicePic'
+ name='invoicePic'
+ placeholder='Masukkan nama pic invoice disini'
+ type='text'
+ className='form-input'
+ aria-invalid={errorsPengiriman.invoicePic}
+ ref={invoicePicRef}
+ onChange={handleInputChange}
+ />
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsPengiriman.invoicePic}
+ </div>
+ )}
+ </div>
+ </div>
+
+ <div className='flex flex-row justify-between items-start'>
+ <div className='w-2/5'>
+ <label className='form-label text-nowrap'>
+ Alamat Pengiriman Invoice
+ </label>
+ {!isKonfirmasi && (
+ <span className='text-xs opacity-60'>
+ Pastikan alamat yang anda isi sesuai dengan alamat kirim
+ invoice
+ </span>
+ )}
+ </div>
+ <div className='w-3/5 flex gap-3 flex-col'>
+ <div>
+ <Checkbox
+ colorScheme='red'
+ isChecked={sameAddress}
+ onChange={handleChangeSameAddress}
+ >
+ Alamat invoice sama dengan alamat pengiriman
+ </Checkbox>
+ </div>
+ {!sameAddress && (
+ <>
+ <div>
+ <input
+ id='streetInvoice'
+ name='streetInvoice'
+ ref={streetInvoiceRef}
+ placeholder='Masukkan alamat lengkap pengiriman invoice'
+ type='text'
+ value={formPengiriman.streetInvoice}
+ className='form-input'
+ onChange={handleInputChange}
+ />
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsPengiriman.streetInvoice}
+ </div>
+ )}
+ </div>
+ <div className='sub-alamat flex flex-row w-full gap-3'>
+ <div className='w-3/5' ref={stateInvoiceRef}>
+ <Controller
+ name='stateInvoice'
+ control={control}
+ render={(props) => (
+ <HookFormSelect
+ {...props}
+ options={states}
+ placeholder='Provinsi'
+ />
+ )}
+ />
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsPengiriman.stateInvoice}
+ </div>
+ )}
+ </div>
+ <div className='w-2/5' ref={cityInvoiceRef}>
+ <Controller
+ name='cityInvoice'
+ control={control}
+ render={(props) => (
+ <HookFormSelect
+ {...props}
+ options={cities}
+ disabled={!watchState}
+ placeholder='Kota'
+ />
+ )}
+ />
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsPengiriman.cityInvoice}
+ </div>
+ )}
+ </div>
+ </div>
+ </>
+ )}
+ </div>
+ </div>
+
+ <div className='flex flex-row justify-between items-start'>
+ <div className='w-2/5'>
+ <label className='form-label text-wrap'>
+ Jadwal Penukaran Invoice{' '}
+ <span className=' opacity-60'>(Opsional)</span>
+ </label>
+ {!isKonfirmasi && (
+ <span className='text-xs opacity-60'>
+ Pilih jika bisnis anda memiliki jadwal penukaran invoice
+ </span>
+ )}
+ </div>
+ <div className='w-3/5 flex gap-3 flex-col'>
+ <div className='flex gap-3 flex-col'>
+ <Checkbox
+ colorScheme='red'
+ isChecked={everyWeekday}
+ onChange={handleEveryWeekday}
+ >
+ Setiap Minggu dihari
+ </Checkbox>
+ <input
+ id='everyWeekdayInput'
+ name='everyWeekdayInput'
+ ref={everyWeekdayInputRef}
+ placeholder='Format: Senin, Selasa, Rabu, Kamis, Jumat, Sabtu, Minggu'
+ type='text'
+ value={formPengiriman.everyWeekdayInput}
+ className='form-input'
+ onChange={handleInputChange}
+ />
+ </div>
+ <div className='flex gap-3 flex-col'>
+ <Checkbox
+ colorScheme='red'
+ isChecked={everyWeek}
+ onChange={handleEveryWeek}
+ >
+ Setiap Bulan di minggu ke
+ </Checkbox>
+ <input
+ id='everyWeekInput'
+ name='everyWeekInput'
+ ref={everyWeekInputRef}
+ placeholder='Format: Minggu 1 & Minggu 2'
+ type='text'
+ value={formPengiriman.everyWeekInput}
+ className='form-input'
+ onChange={handleInputChange}
+ />
+ </div>
+ <div className='flex gap-3 flex-col'>
+ <Checkbox
+ colorScheme='red'
+ isChecked={tukarInvoice}
+ onChange={handleTukarInvoice}
+ >
+ Lainnya
+ </Checkbox>
+ <textarea
+ id='tukarInvoiceInput'
+ name='tukarInvoiceInput'
+ placeholder='isi manual dokumen yang anda mau'
+ type='textarea'
+ value={formPengiriman.tukarInvoiceInput}
+ className='form-input'
+ rows={4}
+ cols={40}
+ onChange={handleInputChange}
+ />
+ </div>
+ </div>
+ </div>
+
+ <div className='flex flex-row justify-between items-start'>
+ <div className='w-2/5'>
+ <label className='form-label text-nowrap'>
+ Jadwal Pembayaran{' '}
+ <span className=' opacity-60'>(Opsional)</span>
+ </label>
+ {!isKonfirmasi && (
+ <span className='text-xs opacity-60'>
+ Pilih jika bisnis anda memiliki jadwal pembayaran
+ </span>
+ )}
+ </div>
+ <div className='w-3/5 flex gap-3 flex-col'>
+ <div className='flex gap-3 flex-col'>
+ <Checkbox
+ colorScheme='red'
+ isChecked={everyWeekdayPembayaran}
+ onChange={handleEveryWeekdayPembayaran}
+ >
+ Setiap Minggu dihari
+ </Checkbox>
+ <input
+ id='everyWeekdayInputPembayaran'
+ name='everyWeekdayInputPembayaran'
+ placeholder='Format: Senin, Selasa, Rabu, Kamis, Jumat, Sabtu, Minggu'
+ type='text'
+ value={formPengiriman.everyWeekdayInputPembayaran}
+ className='form-input'
+ onChange={handleInputChange}
+ />
+ </div>
+ <div className='flex gap-3 flex-col'>
+ <Checkbox
+ colorScheme='red'
+ isChecked={everyWeekPembayaran}
+ onChange={handleEveryWeekPembayaran}
+ >
+ Setiap Bulan di minggu ke
+ </Checkbox>
+ <input
+ id='everyWeekInputPembayaran'
+ name='everyWeekInputPembayaran'
+ placeholder='Format: Minggu 1 & Minggu 2'
+ type='text'
+ value={formPengiriman.everyWeekInputPembayaran}
+ className='form-input'
+ onChange={handleInputChange}
+ />
+ </div>
+ <div className='flex gap-3 flex-col'>
+ <Checkbox
+ colorScheme='red'
+ isChecked={tukarInvoicePembayaran}
+ onChange={handleTukarInvoicePembayaran}
+ >
+ Lainnya
+ </Checkbox>
+ <textarea
+ id='tukarInvoiceInputPembayaran'
+ name='tukarInvoiceInputPembayaran'
+ placeholder='isi manual dokumen yang anda mau'
+ type='textarea'
+ value={formPengiriman.tukarInvoiceInputPembayaran}
+ className='form-input'
+ rows={4}
+ cols={40}
+ onChange={handleInputChange}
+ />
+ </div>
+ </div>
+ </div>
+
+ <div className='flex flex-row justify-between items-start'>
+ <div className='w-2/5'>
+ <label className='form-label text-wrap'>
+ Dokumen saat Pengiriman Barang
+ </label>
+ {!isKonfirmasi && (
+ <span className='text-xs opacity-60'>
+ Pilih dokumen lampiran saat pengiriman barang
+ </span>
+ )}
+ </div>
+ <div
+ className='w-3/5 flex gap-3 flex-col'
+ ref={dokumenPengirimanRef}
+ >
+ <Checkbox
+ colorScheme='red'
+ key='0'
+ isChecked={isChecked(0)}
+ onChange={() => handleCheckboxChange(0)}
+ >
+ Surat Tanda Terima Barang (STTB)
+ </Checkbox>
+ <Checkbox
+ colorScheme='red'
+ key='1'
+ isChecked={isChecked(1)}
+ onChange={() => handleCheckboxChange(1)}
+ >
+ Good Receipt (GR)
+ </Checkbox>
+ <Checkbox
+ colorScheme='red'
+ key='2'
+ isChecked={isChecked(2)}
+ onChange={() => handleCheckboxChange(2)}
+ >
+ Surat Terima Barang (STB)
+ </Checkbox>
+ <Checkbox
+ colorScheme='red'
+ key='3'
+ isChecked={isChecked(3)}
+ onChange={() => handleCheckboxChange(3)}
+ >
+ Lembar Penerimaan Barang (LPB)
+ </Checkbox>
+
+ <div className='flex gap-3 flex-col'>
+ <Checkbox
+ colorScheme='red'
+ key='4'
+ isChecked={isChecked(4)}
+ onChange={() => handleCheckboxChange(4)}
+ >
+ Lainnya
+ </Checkbox>
+ <textarea
+ id='dokumenPengirimanInput'
+ name='dokumenPengirimanInput'
+ placeholder='isi manual dokumen yang anda mau'
+ type='textarea'
+ ref={dokumenPengirimanInputRef}
+ value={formPengiriman.dokumenPengirimanInput}
+ className='form-input'
+ rows={4}
+ cols={40}
+ onChange={handleInputChange}
+ />
+ </div>
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsPengiriman.dokumenPengiriman}
+ </div>
+ )}
+ </div>
+ </div>
+
+ <div className='flex flex-row justify-between items-start'>
+ <div className='w-2/5'>
+ <label className='form-label text-wrap'>
+ Dokumen yang dilampirkan saat Pengiriman Invoice
+ </label>
+ <span className='text-xs opacity-60'>
+ Dokumen akan dikirimkan sesuai dengan yang anda pilih
+ </span>
+ </div>
+ <div
+ className='w-3/5 flex gap-3 flex-col'
+ ref={dokumenPengirimanInvoiceRef}
+ >
+ <Checkbox
+ colorScheme='red'
+ key='0'
+ isChecked={isCheckedInvoice(0)}
+ onChange={() =>
+ handleCheckboxChangeDokumenPengirimanInvoice(0)
+ }
+ >
+ Invoice Pembelian
+ </Checkbox>
+ <Checkbox
+ colorScheme='red'
+ key='1'
+ isChecked={isCheckedInvoice(1)}
+ onChange={() =>
+ handleCheckboxChangeDokumenPengirimanInvoice(1)
+ }
+ >
+ Surat Jalan
+ </Checkbox>
+ <Checkbox
+ colorScheme='red'
+ key='2'
+ isChecked={isCheckedInvoice(2)}
+ onChange={() =>
+ handleCheckboxChangeDokumenPengirimanInvoice(2)
+ }
+ >
+ Berita Acara Serah Terima (BAST)
+ </Checkbox>
+ <Checkbox
+ colorScheme='red'
+ key='3'
+ isChecked={isCheckedInvoice(3)}
+ onChange={() =>
+ handleCheckboxChangeDokumenPengirimanInvoice(3)
+ }
+ >
+ Faktur Pajak
+ </Checkbox>
+ <Checkbox
+ colorScheme='red'
+ key='4'
+ isChecked={isCheckedInvoice(4)}
+ onChange={() =>
+ handleCheckboxChangeDokumenPengirimanInvoice(4)
+ }
+ >
+ Good Receipt (GR)
+ </Checkbox>
+
+ <div className='flex gap-3 flex-col'>
+ <Checkbox
+ colorScheme='red'
+ key='5'
+ isChecked={isCheckedInvoice(5)}
+ onChange={() =>
+ handleCheckboxChangeDokumenPengirimanInvoice(5)
+ }
+ >
+ Lainnya
+ </Checkbox>
+ <textarea
+ id='dokumenPengirimanInvoiceInput'
+ name='dokumenPengirimanInvoiceInput'
+ placeholder='isi manual dokumen yang anda mau'
+ type='textarea'
+ ref={dokumenPengirimanInvoiceInputRef}
+ value={formPengiriman.dokumenPengirimanInvoiceInput}
+ className='form-input'
+ rows={4}
+ cols={40}
+ onChange={handleInputChange}
+ />
+ </div>
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsPengiriman.dokumenInvoicePengiriman}
+ </div>
+ )}
+ </div>
+ </div>
+ </div>
+ </form>
+ </div>
+ )}
+ {isMobile && (
+ <div className='text-sm'>
+ <h1
+ className={`font-bold py-4 mt-8 ${
+ isKonfirmasi ? 'hidden' : 'text-xl'
+ }`}
+ >
+ Pengiriman
+ </h1>
+ <form className='flex flex-col w-full '>
+ <div className='w-full grid grid-row-2 gap-2'>
+ <div className='flex flex-col gap-2 justify-between items-start'>
+ <label className='form-label text-nowrap'>
+ Nama PIC Penerimaan Barang
+ </label>
+ <input
+ value={formPengiriman.PICName}
+ id='PICName'
+ name='PICName'
+ placeholder='Masukkan nama pic pengiriman disini'
+ type='text'
+ className='form-input'
+ aria-invalid={errorsPengiriman.PICName}
+ ref={PICNameRef}
+ onChange={handleInputChange}
+ />
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsPengiriman.PICName}
+ </div>
+ )}
+ </div>
+
+ <div className='flex flex-col gap-2 justify-between items-start'>
+ <label className='form-label text-nowrap'>
+ Alamat Pengiriman Barang
+ </label>
+ <div className='w-full'>
+ <input
+ id='streetPengiriman'
+ name='streetPengiriman'
+ ref={streetPengirimanRef}
+ placeholder='Masukkan alamat lengkap pengiriman barang'
+ type='text'
+ value={formPengiriman.streetPengiriman}
+ className='form-input'
+ onChange={handleInputChange}
+ />
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsPengiriman.streetPengiriman}
+ </div>
+ )}
+ </div>
+ <div className='sub-alamat flex flex-row w-full gap-2'>
+ <div className='w-2/5' ref={statePengirimanRef}>
+ <Controller
+ name='statePengiriman'
+ control={control}
+ render={(props) => (
+ <HookFormSelect
+ {...props}
+ options={states}
+ placeholder='Provinsi'
+ />
+ )}
+ />
+ </div>
+ <div className='w-1/3' ref={cityPengirimanRef}>
+ <Controller
+ name='cityPengiriman'
+ control={control}
+ render={(props) => (
+ <HookFormSelect
+ {...props}
+ options={cities}
+ disabled={!watchState}
+ placeholder='Kota'
+ />
+ )}
+ />
+ </div>
+ <div className='w-1/3'>
+ <input
+ id='zipPengiriman'
+ name='zipPengiriman'
+ ref={zipRef}
+ placeholder='Kode Pos'
+ type='number'
+ value={formPengiriman.zipPengiriman}
+ className='form-input'
+ onChange={handleInputChange}
+ />
+ </div>
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsPengiriman.statePengiriman}
+ </div>
+ )}
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsPengiriman.cityPengiriman}
+ </div>
+ )}
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsPengiriman.zipPengiriman}
+ </div>
+ )}
+ </div>
+ </div>
+
+ <div className='flex flex-col gap-2 justify-between items-start'>
+ <label className='form-label text-nowrap'>
+ Nama PIC Penerimaan Invoice
+ </label>
+ <input
+ value={formPengiriman.invoicePic}
+ id='invoicePic'
+ name='invoicePic'
+ placeholder='Masukkan nama pic invoice disini'
+ type='text'
+ className='form-input'
+ aria-invalid={errorsPengiriman.invoicePic}
+ ref={invoicePicRef}
+ onChange={handleInputChange}
+ />
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsPengiriman.invoicePic}
+ </div>
+ )}
+ </div>
+
+ <div className='flex flex-col gap-2 justify-between items-start'>
+ <label className='form-label text-nowrap'>
+ Alamat Pengiriman Invoice
+ </label>
+ <div>
+ <Checkbox
+ colorScheme='red'
+ isChecked={sameAddress}
+ onChange={handleChangeSameAddress}
+ size='sm'
+ >
+ Alamat invoice sama dengan alamat pengiriman
+ </Checkbox>
+ </div>
+ {!sameAddress && (
+ <>
+ <div className='w-full'>
+ <input
+ id='streetInvoice'
+ name='streetInvoice'
+ ref={streetInvoiceRef}
+ placeholder='Masukkan alamat lengkap pengiriman invoice'
+ type='text'
+ value={formPengiriman.streetInvoice}
+ className='form-input'
+ onChange={handleInputChange}
+ />
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsPengiriman.streetInvoice}
+ </div>
+ )}
+ </div>
+ <div className='sub-alamat flex flex-row w-full gap-3'>
+ <div className='w-3/5' ref={stateInvoiceRef}>
+ <Controller
+ name='stateInvoice'
+ control={control}
+ render={(props) => (
+ <HookFormSelect
+ {...props}
+ options={states}
+ placeholder='Provinsi'
+ />
+ )}
+ />
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsPengiriman.stateInvoice}
+ </div>
+ )}
+ </div>
+ <div className='w-2/5' ref={cityInvoiceRef}>
+ <Controller
+ name='cityInvoice'
+ control={control}
+ render={(props) => (
+ <HookFormSelect
+ {...props}
+ options={cities}
+ disabled={!watchState}
+ placeholder='Kota'
+ />
+ )}
+ />
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsPengiriman.cityInvoice}
+ </div>
+ )}
+ </div>
+ </div>
+ </>
+ )}
+ </div>
+
+ <div className='flex flex-col gap-2 justify-between items-start'>
+ <label className='form-label text-wrap'>
+ Jadwal Penukaran Invoice
+ <span className=' opacity-60'>(Opsional)</span>
+ </label>
+ {!isKonfirmasi && (
+ <span className='text-xs opacity-60'>
+ Pilih jika bisnis anda memiliki jadwal penukaran invoice
+ </span>
+ )}
+ <div className='w-full flex gap-2 flex-col'>
+ <div className='flex gap-2 flex-col'>
+ <Checkbox
+ size='sm'
+ colorScheme='red'
+ isChecked={everyWeekday}
+ onChange={handleEveryWeekday}
+ >
+ Setiap Minggu dihari
+ </Checkbox>
+ <input
+ id='everyWeekdayInput'
+ name='everyWeekdayInput'
+ ref={everyWeekdayInputRef}
+ placeholder='Format: Senin, Selasa, Rabu, Kamis, Jumat, Sabtu, Minggu'
+ type='text'
+ value={formPengiriman.everyWeekdayInput}
+ className='form-input'
+ onChange={handleInputChange}
+ />
+ </div>
+ <div className='flex gap-2 w-full flex-col'>
+ <Checkbox
+ size='sm'
+ colorScheme='red'
+ isChecked={everyWeek}
+ onChange={handleEveryWeek}
+ >
+ Setiap Bulan di minggu ke
+ </Checkbox>
+ <input
+ id='everyWeekInput'
+ name='everyWeekInput'
+ ref={everyWeekInputRef}
+ placeholder='Format: Minggu 1 & Minggu 2'
+ type='text'
+ value={formPengiriman.everyWeekInput}
+ className='form-input'
+ onChange={handleInputChange}
+ />
+ </div>
+ <div className='flex gap-2 flex-col'>
+ <Checkbox
+ size='sm'
+ colorScheme='red'
+ isChecked={tukarInvoice}
+ onChange={handleTukarInvoice}
+ >
+ Lainnya
+ </Checkbox>
+ <textarea
+ id='tukarInvoiceInput'
+ name='tukarInvoiceInput'
+ placeholder='isi manual dokumen yang anda mau'
+ type='textarea'
+ value={formPengiriman.tukarInvoiceInput}
+ className='form-input'
+ rows={4}
+ cols={40}
+ onChange={handleInputChange}
+ />
+ </div>
+ </div>
+ <div className='w-2/5'></div>
+ </div>
+
+ <div className='flex flex-col gap-2 justify-between items-start'>
+ <label className='form-label text-nowrap'>
+ Jadwal Pembayaran
+ <span className=' opacity-60'>(Opsional)</span>
+ </label>
+ {!isKonfirmasi && (
+ <span className='text-xs opacity-60'>
+ Pilih jika bisnis anda memiliki jadwal pembayaran
+ </span>
+ )}
+ <div className='w-full flex gap-2 flex-col'>
+ <div className='flex gap-2 flex-col'>
+ <Checkbox
+ size='sm'
+ colorScheme='red'
+ isChecked={everyWeekdayPembayaran}
+ onChange={handleEveryWeekdayPembayaran}
+ >
+ Setiap Minggu dihari
+ </Checkbox>
+ <input
+ id='everyWeekdayInputPembayaran'
+ name='everyWeekdayInputPembayaran'
+ placeholder='Format: Senin, Selasa, Rabu, Kamis, Jumat, Sabtu, Minggu'
+ type='text'
+ value={formPengiriman.everyWeekdayInputPembayaran}
+ className='form-input'
+ onChange={handleInputChange}
+ />
+ </div>
+ <div className='flex gap-2 flex-col'>
+ <Checkbox
+ size='sm'
+ colorScheme='red'
+ isChecked={everyWeekPembayaran}
+ onChange={handleEveryWeekPembayaran}
+ >
+ Setiap Bulan di minggu ke
+ </Checkbox>
+ <input
+ id='everyWeekInputPembayaran'
+ name='everyWeekInputPembayaran'
+ placeholder='Format: Minggu 1 & Minggu 2'
+ type='text'
+ value={formPengiriman.everyWeekInputPembayaran}
+ className='form-input'
+ onChange={handleInputChange}
+ />
+ </div>
+ <div className='flex gap-2 flex-col'>
+ <Checkbox
+ size='sm'
+ colorScheme='red'
+ isChecked={tukarInvoicePembayaran}
+ onChange={handleTukarInvoicePembayaran}
+ >
+ Lainnya
+ </Checkbox>
+ <textarea
+ id='tukarInvoiceInputPembayaran'
+ name='tukarInvoiceInputPembayaran'
+ placeholder='isi manual dokumen yang anda mau'
+ type='textarea'
+ value={formPengiriman.tukarInvoiceInputPembayaran}
+ className='form-input'
+ rows={4}
+ cols={40}
+ onChange={handleInputChange}
+ />
+ </div>
+ </div>
+ </div>
+
+ <div className='flex flex-col gap-2 justify-between items-start'>
+ <label className='form-label text-wrap'>
+ Dokumen saat Pengiriman Barang
+ </label>
+ {!isKonfirmasi && (
+ <span className='text-xs opacity-60'>
+ Pilih dokumen lampiran saat pengiriman barang
+ </span>
+ )}
+ <div
+ className='w-full flex gap-2 flex-col'
+ ref={dokumenPengirimanRef}
+ >
+ <Checkbox
+ size='sm'
+ colorScheme='red'
+ key='0'
+ isChecked={isChecked(0)}
+ onChange={() => handleCheckboxChange(0)}
+ >
+ Surat Tanda Terima Barang (STTB)
+ </Checkbox>
+ <Checkbox
+ size='sm'
+ colorScheme='red'
+ key='1'
+ isChecked={isChecked(1)}
+ onChange={() => handleCheckboxChange(1)}
+ >
+ Good Receipt (GR)
+ </Checkbox>
+ <Checkbox
+ size='sm'
+ colorScheme='red'
+ key='2'
+ isChecked={isChecked(2)}
+ onChange={() => handleCheckboxChange(2)}
+ >
+ Surat Terima Barang (STB)
+ </Checkbox>
+ <Checkbox
+ size='sm'
+ colorScheme='red'
+ key='3'
+ isChecked={isChecked(3)}
+ onChange={() => handleCheckboxChange(3)}
+ >
+ Lembar Penerimaan Barang (LPB)
+ </Checkbox>
+
+ <div className='flex gap-3 flex-col'>
+ <Checkbox
+ size='sm'
+ colorScheme='red'
+ key='4'
+ isChecked={isChecked(4)}
+ onChange={() => handleCheckboxChange(4)}
+ >
+ Lainnya
+ </Checkbox>
+ <textarea
+ id='dokumenPengirimanInput'
+ name='dokumenPengirimanInput'
+ placeholder='isi manual dokumen yang anda mau'
+ type='textarea'
+ ref={dokumenPengirimanInputRef}
+ value={formPengiriman.dokumenPengirimanInput}
+ className='form-input'
+ rows={4}
+ cols={40}
+ onChange={handleInputChange}
+ />
+ </div>
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsPengiriman.dokumenPengiriman}
+ </div>
+ )}
+ </div>
+ </div>
+
+ <div className='flex flex-col gap-2 justify-between items-start'>
+ <label className='form-label text-wrap'>
+ Dokumen yang dilampirkan saat Pengiriman Invoice
+ </label>
+ <span className='text-xs opacity-60'>
+ Pilih dokumen lampiran saat pengiriman invoice
+ </span>
+ <div
+ className='w-full flex gap-2 flex-col'
+ ref={dokumenPengirimanInvoiceRef}
+ >
+ <Checkbox
+ size='sm'
+ colorScheme='red'
+ key='0'
+ isChecked={isCheckedInvoice(0)}
+ onChange={() =>
+ handleCheckboxChangeDokumenPengirimanInvoice(0)
+ }
+ >
+ Invoice Pembelian
+ </Checkbox>
+ <Checkbox
+ size='sm'
+ colorScheme='red'
+ key='1'
+ isChecked={isCheckedInvoice(1)}
+ onChange={() =>
+ handleCheckboxChangeDokumenPengirimanInvoice(1)
+ }
+ >
+ Surat Jalan
+ </Checkbox>
+ <Checkbox
+ size='sm'
+ colorScheme='red'
+ key='2'
+ isChecked={isCheckedInvoice(2)}
+ onChange={() =>
+ handleCheckboxChangeDokumenPengirimanInvoice(2)
+ }
+ >
+ Berita Acara Serah Terima (BAST)
+ </Checkbox>
+ <Checkbox
+ size='sm'
+ colorScheme='red'
+ key='3'
+ isChecked={isCheckedInvoice(3)}
+ onChange={() =>
+ handleCheckboxChangeDokumenPengirimanInvoice(3)
+ }
+ >
+ Faktur Pajak
+ </Checkbox>
+ <Checkbox
+ size='sm'
+ colorScheme='red'
+ key='4'
+ isChecked={isCheckedInvoice(4)}
+ onChange={() =>
+ handleCheckboxChangeDokumenPengirimanInvoice(4)
+ }
+ >
+ Good Receipt (GR)
+ </Checkbox>
+
+ <div className='flex gap-3 flex-col'>
+ <Checkbox
+ size='sm'
+ colorScheme='red'
+ key='5'
+ isChecked={isCheckedInvoice(5)}
+ onChange={() =>
+ handleCheckboxChangeDokumenPengirimanInvoice(5)
+ }
+ >
+ Lainnya
+ </Checkbox>
+ <textarea
+ id='dokumenPengirimanInvoiceInput'
+ name='dokumenPengirimanInvoiceInput'
+ placeholder='isi manual dokumen yang anda mau'
+ type='textarea'
+ ref={dokumenPengirimanInvoiceInputRef}
+ value={formPengiriman.dokumenPengirimanInvoiceInput}
+ className='form-input'
+ rows={4}
+ cols={40}
+ onChange={handleInputChange}
+ />
+ </div>
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errorsPengiriman.dokumenInvoicePengiriman}
+ </div>
+ )}
+ </div>
+ <div className='w-2/5'></div>
+ </div>
+ </div>
+ </form>
+ </div>
+ )}
+ </>
+ );
+};
+
+export default Pengiriman;
diff --git a/src/lib/pengajuan-tempo/component/Referensi.jsx b/src/lib/pengajuan-tempo/component/Referensi.jsx
new file mode 100644
index 00000000..8cb3b0c3
--- /dev/null
+++ b/src/lib/pengajuan-tempo/component/Referensi.jsx
@@ -0,0 +1,548 @@
+import React, { useState, useEffect, useMemo, useRef } from 'react';
+import { useForm } from 'react-hook-form';
+import { usePengajuanTempoStoreSupplier } from '../../../../src-migrate/modules/register/stores/usePengajuanTempoStore';
+import * as Yup from 'yup';
+import { yupResolver } from '@hookform/resolvers/yup';
+import { PlusCircleIcon } from '@heroicons/react/24/outline';
+import useDevice from '@/core/hooks/useDevice';
+import { Trash2Icon } from 'lucide-react';
+import { ChevronDownIcon, ChevronUpIcon } from '@heroicons/react/24/outline';
+const initialData = [];
+const Referensi = ({ chekValid, buttonSubmitClick }) => {
+ const { isDesktop, isMobile } = useDevice();
+ const [openIndexes, setOpenIndexes] = useState([]);
+
+ const {
+ register,
+ formState: { errors },
+ handleSubmit,
+ watch,
+ setValue,
+ control,
+ } = useForm({
+ resolver: yupResolver(validationSchema),
+ defaultValues,
+ });
+ const { formSupplier, updateFormSupplier, updateHasSave } =
+ usePengajuanTempoStoreSupplier();
+ const [formData, setFormData] = useState([
+ {
+ supplier: '',
+ pic: '',
+ telepon: '',
+ durasiTempo: '',
+ creditLimit: '',
+ },
+ ]);
+
+ const [buttonSubmit, setButtonSubmit] = useState(false);
+ const [supplierData, setSupplierData] = useState(initialData);
+ const [newSupplier, setNewSupplier] = useState({
+ supplier: '',
+ pic: '',
+ telepon: '',
+ durasiTempo: '',
+ creditLimit: '',
+ });
+ const onChangeInput = (e, index) => {
+ const { name, value } = e.target;
+
+ let formattedValue = value;
+
+ if (name === 'durasiTempo') {
+ formattedValue = value.replace(/\s*Hari\s*/g, '');
+ } else if (name === 'creditLimit') {
+ formattedValue = value.replace(/^Rp\s*/, '');
+ }
+
+ const editData = supplierData.map((item, i) =>
+ i === index ? { ...item, [name]: formattedValue } : item
+ );
+
+ setSupplierData(editData);
+ updateHasSave(false);
+ };
+
+ const handleNewSupplierChange = (e) => {
+ const { name, value } = e.target;
+
+ let formattedValue = value;
+
+ if (name === 'durasiTempo') {
+ formattedValue = value.replace(/\s*Hari\s*/g, '');
+ } else if (name === 'creditLimit') {
+ formattedValue = value.replace(/^Rp\s*/, '');
+ }
+
+ const updatedSupplier = { ...newSupplier, [name]: formattedValue };
+ setNewSupplier(updatedSupplier);
+ updateHasSave(false);
+ };
+
+ const handleAddNewSupplier = () => {
+ if (Object.values(newSupplier).every((val) => val.trim() !== '')) {
+ setSupplierData((prevData) => {
+ const newData = [...prevData, newSupplier];
+ return newData;
+ });
+
+ setNewSupplier({
+ supplier: '',
+ pic: '',
+ telepon: '',
+ durasiTempo: '',
+ creditLimit: '',
+ });
+ }
+ updateHasSave(false);
+ };
+
+ useEffect(() => {
+ handleAddNewSupplier();
+ updateFormSupplier(supplierData);
+ setButtonSubmit(!buttonSubmit);
+ }, [buttonSubmitClick]);
+ const simpanData = () => {
+ setButtonSubmit(!buttonSubmit);
+ if (Object.values(newSupplier).every((val) => val.trim() !== '')) {
+ setSupplierData((prevData) => {
+ const newData = [...prevData, newSupplier];
+ return newData;
+ });
+
+ setNewSupplier({
+ supplier: '',
+ pic: '',
+ telepon: '',
+ durasiTempo: '',
+ creditLimit: '',
+ });
+ }
+ updateHasSave(true);
+ };
+ const formatRupiah = (value) => {
+ if (!value) return '';
+ const numberString = value.replace(/[^0-9]/g, '');
+ return numberString
+ ? 'Rp ' + new Intl.NumberFormat('id-ID').format(numberString)
+ : '';
+ };
+ const formatHari = (value) => {
+ if (!value) return '';
+
+ const numberString = value.replace(/[^0-9]/g, '');
+
+ return numberString ? numberString.replace(/Hari/g, '') + ' Hari' : '';
+ };
+
+ useEffect(() => {
+ updateFormSupplier(supplierData);
+ }, [buttonSubmit]);
+ const getFromLocalStorage = (key) => {
+ const itemStr = localStorage.getItem(key);
+ if (!itemStr) return null;
+
+ const item = JSON.parse(itemStr);
+ return item;
+ };
+ useEffect(() => {
+ const cachedData = getFromLocalStorage('Referensi');
+ if (cachedData) {
+ setSupplierData(cachedData);
+ updateFormSupplier(cachedData);
+ }
+ }, [buttonSubmitClick]);
+
+ useEffect(() => {
+ setOpenIndexes(supplierData.map((_, index) => index));
+ }, [supplierData]);
+
+ const toggleOpen = (index) => {
+ setOpenIndexes((prev) =>
+ prev.includes(index) ? prev.filter((i) => i !== index) : [...prev, index]
+ );
+ };
+ return (
+ <>
+ {isDesktop && (
+ <div className='py-4'>
+ <div className='flex flex-col justify-start'>
+ <h1 className='font-bold text-2xl'>
+ Referensi Supplier / Rekanan Bisnis Perusahaan{' '}
+ <span className=' opacity-60 text-xl'>(Opsional)</span>
+ </h1>
+ <p className='opacity-60'>
+ Data yang anda berikan hanya untuk bahan referensi internal kami
+ untuk memberikan anda credit limit dan durasi tempo
+ </p>
+ </div>
+ <form className='flex mt-4 flex-col w-full '>
+ <table className='border' border='1' cellPadding='10'>
+ <thead>
+ <tr className='border '>
+ <th className='text-left px-5 py-2'>
+ Nama Supplier / Rekanan
+ </th>
+ <th className='text-left px-5 py-2'>PIC</th>
+ <th className='text-left px-5 py-2'>Telepon</th>
+ <th className='text-left px-5 py-2'>Durasi Tempo</th>
+ <th className='text-left px-5 py-2'>Credit Limit</th>
+ </tr>
+ </thead>
+ <tbody>
+ {supplierData.map((supplier, index) => (
+ <tr key={index}>
+ <td>
+ <input
+ name='supplier'
+ value={supplier.supplier}
+ type='text'
+ onChange={(e) => onChangeInput(e, index)}
+ className='form-input border px-4 py-2'
+ placeholder='Type Supplier'
+ />
+ </td>
+ <td>
+ <input
+ name='pic'
+ value={supplier.pic}
+ type='text'
+ className='form-input border px-4 py-2'
+ onChange={(e) => onChangeInput(e, index)}
+ placeholder='Type PIC'
+ />
+ </td>
+ <td>
+ <input
+ name='telepon'
+ type='text'
+ className='form-input border px-4 py-2'
+ value={supplier.telepon}
+ onChange={(e) => onChangeInput(e, index)}
+ placeholder='Type Telepon'
+ />
+ </td>
+ <td>
+ <input
+ name='durasiTempo'
+ type='text'
+ className='form-input border px-4 py-2'
+ value={formatHari(supplier.durasiTempo)}
+ onChange={(e) => onChangeInput(e, index)}
+ placeholder='Type Durasi Tempo'
+ />
+ </td>
+ <td>
+ <input
+ name='creditLimit'
+ type='text'
+ value={formatRupiah(supplier.creditLimit)}
+ className='form-input border px-4 py-2'
+ onChange={(e) => onChangeInput(e, index)}
+ placeholder='Type Credit Limit'
+ />
+ </td>
+ </tr>
+ ))}
+ <tr>
+ <td>
+ <input
+ name='supplier'
+ value={newSupplier.supplier}
+ type='text'
+ className='form-input border px-4 py-2'
+ onChange={handleNewSupplierChange}
+ placeholder='Isi nama supplier anda'
+ />
+ </td>
+ <td>
+ <input
+ name='pic'
+ value={newSupplier.pic}
+ type='text'
+ className='form-input border px-4 py-2'
+ onChange={handleNewSupplierChange}
+ placeholder='Isi PIC supplier anda'
+ />
+ </td>
+ <td>
+ <input
+ name='telepon'
+ value={newSupplier.telepon}
+ type='text'
+ onChange={handleNewSupplierChange}
+ placeholder='Isi telepon supplier anda'
+ className='form-input border px-4 py-2'
+ />
+ </td>
+ <td>
+ <input
+ name='durasiTempo'
+ value={formatHari(newSupplier.durasiTempo)}
+ type='text'
+ onChange={handleNewSupplierChange}
+ className='form-input border px-4 py-2'
+ placeholder='Durasi jatuh tempo'
+ />
+ </td>
+ <td>
+ <input
+ name='creditLimit'
+ value={formatRupiah(newSupplier.creditLimit)}
+ type='text'
+ className='form-input border px-4 py-2'
+ onChange={handleNewSupplierChange}
+ placeholder='limit kredit'
+ />
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </form>
+ <div className='flex items-center gap-4 mt-8'>
+ <button
+ onClick={handleAddNewSupplier}
+ className='bg-gray-200 border border-gray-500 rounded-md text-sm text-gray-500 p-2 h-11 mb-1 content-center flex flex-row justify-center items-center'
+ >
+ {<PlusCircleIcon className='w-5 mr-2' />}
+ {''} Tambah data baru
+ </button>
+ <button
+ onClick={simpanData}
+ className='bg-gray-200 border border-gray-500 rounded-md text-sm text-gray-500 p-2 h-11 mb-1 content-center flex flex-row justify-center items-center'
+ >
+ simpan data
+ </button>
+ <span className='text-sm opacity-60 text-red-500'>
+ *Klik simpan sebelum lanjut ke tahap selanjutnya
+ </span>
+ </div>
+ </div>
+ )}
+ {isMobile && (
+ <div className='text-sm'>
+ <div className='flex flex-col py-4 mt-8 justify-start'>
+ <h1 className='font-bold text-xl'>
+ Referensi Supplier / Rekanan Bisnis Perusahaan{' '}
+ <span className=' opacity-60 text-xl'>(Opsional)</span>
+ </h1>
+ <p className='opacity-60'>
+ Data yang anda berikan hanya untuk bahan referensi internal kami
+ untuk memberikan anda credit limit dan durasi tempo
+ </p>
+ </div>
+ <div className='flex gap-4 flex-col'>
+ <div className='h-[2px] bg-gray-300 w-[120%] inset-0 relative transform -translate-x-5'></div>
+ <h2 className='py-2 font-semibold text-base'>
+ Daftar Nama Supplier
+ </h2>
+ <div className='h-[2px] bg-gray-300 w-[120%] inset-0 relative transform -translate-x-5'></div>
+ <div className=''>
+ {supplierData.map((supplier, index) => (
+ <div key={index}>
+ <div
+ className='flex flex-row justify-center items-center py-4'
+ onClick={() => toggleOpen(index)}
+ >
+ <p className='font-semibold text-base w-4/5'>
+ {supplier.supplier}
+ </p>
+ <div className='w-1/5 flex justify-end items-center gap-2'>
+ <Trash2Icon size={16} color='red' />
+ {openIndexes.includes(index) ? (
+ <ChevronUpIcon className='w-4' />
+ ) : (
+ <ChevronDownIcon className='w-4' />
+ )}
+ </div>
+ </div>
+ {openIndexes.includes(index) && (
+ <form className='flex flex-col w-full'>
+ <div className='w-full grid grid-row-2 gap-4'>
+ <div className='flex flex-row justify-start items-start'>
+ <div className='w-2/5'>
+ <label className='form-label text-nowrap'>
+ Nama Supplier
+ </label>
+ </div>
+ <div className='w-3/5 opacity-70'>
+ {supplier.supplier}
+ </div>
+ </div>
+
+ <div className='flex flex-row justify-start items-start'>
+ <div className='w-2/5'>
+ <label className='form-label text-nowrap'>
+ PIC
+ </label>
+ </div>
+ <div className='w-3/5 opacity-70'>{supplier.pic}</div>
+ </div>
+
+ <div className='flex flex-row justify-start items-start'>
+ <div className='w-2/5'>
+ <label className='form-label text-nowrap'>
+ Telepon
+ </label>
+ </div>
+ <div className='w-3/5 opacity-70'>
+ {supplier.telepon}
+ </div>
+ </div>
+
+ <div className='flex flex-row justify-start items-start'>
+ <div className='w-2/5'>
+ <label className='form-label text-nowrap'>
+ Durasi Tempo
+ </label>
+ </div>
+ <div className='w-3/5 opacity-70'>
+ {formatHari(supplier.durasiTempo)}
+ </div>
+ </div>
+
+ <div className='flex flex-row justify-start items-start'>
+ <div className='w-2/5'>
+ <label className='form-label text-nowrap'>
+ Kredit Limit
+ </label>
+ </div>
+ <div className='w-3/5 opacity-70'>
+ {formatRupiah(supplier.creditLimit)}
+ </div>
+ </div>
+ </div>
+ </form>
+ )}
+ </div>
+ ))}
+ </div>
+ <div className='h-[2px] bg-gray-300 w-[120%] inset-0 relative transform -translate-x-5'></div>
+ <h2 className='py-2 font-semibold text-base text-red-500 flex flex-row'>
+ <PlusCircleIcon className='w-5 mr-2' />
+ Tambah Data Baru
+ </h2>
+ <div className='h-[2px] bg-gray-300 w-[120%] inset-0 relative transform -translate-x-5'></div>
+ <form className='flex flex-col w-full'>
+ <div className='w-full grid grid-row-2 gap-2'>
+ <div className='flex flex-row justify-start items-start'>
+ <div className='w-2/5'>
+ <label className='form-label text-nowrap'>
+ Nama Supplier
+ </label>
+ </div>
+ <div className='w-3/5 opacity-70'>
+ <input
+ name='supplier'
+ value={newSupplier.supplier}
+ type='text'
+ className='form-input border px-4 py-2'
+ onChange={handleNewSupplierChange}
+ placeholder='Format: PT. ABC TESTING INDONESIA'
+ />
+ </div>
+ </div>
+
+ <div className='flex flex-row justify-start items-start'>
+ <div className='w-2/5'>
+ <label className='form-label text-nowrap'>PIC</label>
+ </div>
+ <div className='w-3/5 opacity-70'>
+ <input
+ name='pic'
+ value={newSupplier.pic}
+ type='text'
+ className='form-input border px-4 py-2'
+ onChange={handleNewSupplierChange}
+ placeholder='John Doe'
+ />
+ </div>
+ </div>
+
+ <div className='flex flex-row justify-start items-start'>
+ <div className='w-2/5'>
+ <label className='form-label text-nowrap'>Telepon</label>
+ </div>
+ <div className='w-3/5 opacity-70'>
+ <input
+ name='telepon'
+ value={newSupplier.telepon}
+ type='text'
+ onChange={handleNewSupplierChange}
+ placeholder='Format: 08123456789'
+ className='form-input border px-4 py-2'
+ />
+ </div>
+ </div>
+
+ <div className='flex flex-row justify-start items-start'>
+ <div className='w-2/5'>
+ <label className='form-label text-nowrap'>
+ Durasi Tempo
+ </label>
+ </div>
+ <div className='w-3/5 opacity-70'>
+ <input
+ name='durasiTempo'
+ value={formatHari(newSupplier.durasiTempo)}
+ type='text'
+ onChange={handleNewSupplierChange}
+ className='form-input border px-4 py-2'
+ placeholder='Isi durasi tempo supplier anda (hari)'
+ />
+ </div>
+ </div>
+
+ <div className='flex flex-row justify-start items-start'>
+ <div className='w-2/5'>
+ <label className='form-label text-nowrap'>
+ Kredit Limit
+ </label>
+ </div>
+ <div className='w-3/5 opacity-70'>
+ <input
+ name='creditLimit'
+ value={formatRupiah(newSupplier.creditLimit)}
+ type='text'
+ className='form-input border px-4 py-2'
+ onChange={handleNewSupplierChange}
+ placeholder='Rp 999.999.999'
+ />
+ </div>
+ </div>
+ </div>
+ </form>
+ </div>
+ <div className='flex flex-col justify-start items-start gap-4 mt-8'>
+ <span className='text-xs opacity-60 text-red-500'>
+ *Klik simpan sebelum lanjut ke tahap selanjutnya
+ </span>
+ <button
+ onClick={simpanData}
+ className='bg-gray-200 border border-gray-500 rounded-md w-full text-sm text-gray-500 p-2 h-11 mb-1 content-center flex flex-row justify-center items-center'
+ >
+ simpan data
+ </button>
+ </div>
+ </div>
+ )}
+ </>
+ );
+};
+
+const validationSchema = Yup.object().shape({
+ supplier: Yup.string().required('Harus di-isi'),
+ pic: Yup.string().required('Harus di-isi'),
+ telepon: Yup.string().required('Harus di-isi'),
+ durasiTempo: Yup.string().required('Harus di-isi'),
+ creditLimit: Yup.string().required('Harus di-isi'),
+});
+
+const defaultValues = {
+ supplier: '',
+ pic: '',
+ telepon: '',
+ durasiTempo: '',
+ creditLimit: '',
+};
+export default Referensi;
diff --git a/src/lib/pengajuan-tempo/component/Stepper.jsx b/src/lib/pengajuan-tempo/component/Stepper.jsx
new file mode 100644
index 00000000..539fe3f3
--- /dev/null
+++ b/src/lib/pengajuan-tempo/component/Stepper.jsx
@@ -0,0 +1,65 @@
+import React from 'react';
+import useDevice from '@/core/hooks/useDevice';
+const Stepper = ({ currentStep, numberOfSteps }) => {
+ const { isDesktop, isMobile } = useDevice();
+ const stepLabels = [
+ 'Informasi Perusahaan',
+ 'Kontak Person',
+ 'Pengiriman',
+ 'Referensi',
+ 'Dokumen',
+ 'Konfirmasi',
+ ];
+ const activeColor = (index) =>
+ currentStep >= index ? 'bg-red-500' : 'bg-gray-300';
+ const activeColorBullet = (index) =>
+ currentStep >= index ? 'bg-red-500 ' : 'bg-white border-gray-300 border';
+ const isFinalStep = (index) => index === numberOfSteps - 1;
+ const isFirstStep = (index) => index === 0;
+ return (
+ <div className='flex items-center'>
+ {Array.from({ length: numberOfSteps }).map((_, index) => (
+ <React.Fragment key={index}>
+ {isFirstStep(index) ? null : (
+ <div
+ className={`${isMobile ? 'w-12' : 'w-48'} h-[0.8px] ${activeColor(
+ index
+ )}`}
+ ></div>
+ )}
+ <div
+ className={`w-6 h-6 ${
+ currentStep == index
+ ? 'border-red-500 border'
+ : `${activeColorBullet(index)} `
+ } rounded-full flex justify-center items-center text-nowrap`}
+ >
+ <div className='relative text-xs'>
+ <div
+ className={`absolute z-10 ${
+ isMobile
+ ? `w-12 h-full top-4 ${
+ isFinalStep(index) ? '-left-16' : '-left-4'
+ }`
+ : 'w-48 h-full -top-14 -left-24'
+ } `}
+ >
+ <div
+ className={`relative w-full max-w-md p-2 text-center ${
+ currentStep == index
+ ? 'text-red-500'
+ : `${isMobile ? 'hidden' : ''}`
+ } text-nowrap`}
+ >
+ {stepLabels[index]}
+ </div>
+ </div>
+ </div>
+ </div>
+ </React.Fragment>
+ ))}
+ </div>
+ );
+};
+
+export default Stepper;
diff --git a/src/lib/pengajuan-tempo/component/informasiPerusahaan.jsx b/src/lib/pengajuan-tempo/component/informasiPerusahaan.jsx
new file mode 100644
index 00000000..8a1b3508
--- /dev/null
+++ b/src/lib/pengajuan-tempo/component/informasiPerusahaan.jsx
@@ -0,0 +1,1401 @@
+import React, { useState, useEffect, useMemo, useRef } from 'react';
+import { Controller, set, useForm } from 'react-hook-form';
+import HookFormSelect from '@/core/components/elements/Select/HookFormSelect';
+import odooApi from '~/libs/odooApi';
+import stateApi from '@/lib/address/api/stateApi.js';
+import cityApi from '@/lib/address/api/cityApi';
+import { Radio, RadioGroup, Stack, Checkbox } from '@chakra-ui/react';
+import { usePengajuanTempoStore } from '../../../../src-migrate/modules/register/stores/usePengajuanTempoStore';
+import useDevice from '@/core/hooks/useDevice';
+import Divider from '@/core/components/elements/Divider/Divider';
+const InformasiPerusahaan = ({
+ chekValid,
+ buttonSubmitClick,
+ isKonfirmasi,
+}) => {
+ const { isDesktop, isMobile } = useDevice();
+ const { control, watch, setValue, getValues } = useForm();
+ const { form, errors, validate, updateForm } = usePengajuanTempoStore();
+ const [industries, setIndustries] = useState([]);
+ const [selectedCategory, setSelectedCategory] = useState('');
+ const [states, setState] = useState([]);
+ const [cities, setCities] = useState([]);
+ const [bersedia, setBersedia] = useState(null);
+ const category_produk = [
+ { id: 2040, name: 'Pengaman, Kesehatan & Keamanan' },
+ { id: 2097, name: 'Perkakas Tangan, Listrik & Pneumatic' },
+ { id: 2161, name: 'Mesin Industrial' },
+ { id: 2222, name: 'Mesin Pertanian & Perkebunan' },
+ { id: 2246, name: 'Mesin Pembersih & Janitorial' },
+ { id: 2273, name: 'Cairan Berbahan Kimia' },
+ { id: 2315, name: 'Perlengkapan Pengukuran & Pengujian' },
+ { id: 2354, name: 'Peralatan Listrik & Elektronik' },
+ { id: 2394, name: 'Perlengkapan Logistik & Gudang' },
+ { id: 2420, name: 'Peralatan Kantor & Stationery' },
+ { id: 2445, name: 'Komponen & Aksesoris' },
+ { id: 2477, name: 'Peralatan Horeca & Food Service' },
+ ];
+ const radioOptions = [
+ { label: '5.000.000', value: '5000000' },
+ { label: '10.000.000', value: '10000000' },
+ { label: '15.000.000', value: '15000000' },
+ { label: '20.000.000', value: '20000000' },
+ { label: '25.000.000', value: '25000000' },
+ { label: '30.000.000', value: '30000000' },
+ { label: '35.000.000', value: '35000000' },
+ ];
+
+ useEffect(() => {
+ const loadState = async () => {
+ let dataState = await stateApi();
+ dataState = dataState.map((state) => ({
+ value: state.id,
+ label: state.name,
+ }));
+ setState(dataState);
+ };
+ loadState();
+ }, []);
+
+ const watchState = watch('state');
+ useEffect(() => {
+ updateForm('city', '');
+ if (watchState) {
+ updateForm('state', `${watchState}`);
+ validate();
+ const loadCities = async () => {
+ let dataCities = await cityApi({ stateId: watchState });
+ dataCities = dataCities.map((city) => ({
+ value: city.id,
+ label: city.name,
+ }));
+ setCities(dataCities);
+ };
+ loadCities();
+ }
+ }, [watchState]);
+
+ const watchCity = watch('city');
+ useEffect(() => {
+ if (watchCity) {
+ updateForm('city', `${watchCity}`);
+ validate();
+ }
+ }, [watchCity]);
+
+ useEffect(() => {
+ const loadIndustries = async () => {
+ const dataIndustries = await odooApi('GET', '/api/v1/partner/industry');
+ setIndustries(
+ dataIndustries?.map((o) => ({
+ value: o.id,
+ label: o.name,
+ category: o.category,
+ }))
+ );
+ };
+ loadIndustries();
+ }, []);
+
+ useEffect(() => {
+ const selectedIndustryType = industries.find(
+ (industry) => industry.value === watch('industry_id')
+ );
+ if (selectedIndustryType) {
+ updateForm('industry_id', `${selectedIndustryType?.value}`);
+ validate();
+ setSelectedCategory(selectedIndustryType.category);
+ }
+ }, [watch('industry_id'), industries]);
+
+ const estimasiValue = watch('estimasi');
+ const tempoLimitValue = watch('tempoLimit');
+
+ // Memformat angka menjadi format rupiah
+ const formatRupiah = (value) => {
+ if (!value) return '';
+ const numberString = value.replace(/[^0-9]/g, ''); // Menghapus karakter non-digit
+ return numberString
+ ? 'Rp ' + new Intl.NumberFormat('id-ID').format(numberString)
+ : '';
+ };
+
+ const handleChange = (e) => {
+ const value = e.target.value;
+ const formattedValue = formatRupiah(value);
+ updateForm('estimasi', formattedValue.replace(/^Rp\s*/, ''));
+ validate();
+ };
+ const onChangeTempoDuration = (e) => {
+ updateForm('tempoDuration', `${e}`);
+ validate();
+ };
+
+ const onChangeTempoLimit = (e) => {
+ updateForm('tempoLimit', `${e}`);
+ validate();
+ };
+ const [isCustom, setIsCustom] = React.useState(false);
+ const [tempoLimitValueEx, setTempoLimitValueEx] = React.useState('');
+ const handleCheckboxBersediaChange = (value) => {
+ // if (value === 'bersedia') {
+ // setBersedia(true);
+ // } else if (value === 'tidakBersedia') {
+ // setBersedia(false);
+ // }
+ // updateForm('bersedia', `${value === 'bersedia'}`);
+ updateForm('bersedia', `${value}`);
+ validate();
+ };
+ const [selectedIds, setSelectedIds] = useState(
+ form.categoryProduk ? form.categoryProduk.split(',').map(Number) : [] // Parse string menjadi array angka
+ );
+
+ const handleCheckboxChange = (id) => {
+ const updatedSelected = selectedIds.includes(id)
+ ? selectedIds.filter((selectedId) => selectedId !== id)
+ : [...selectedIds, id];
+
+ setSelectedIds(updatedSelected);
+
+ // Mengubah array kembali menjadi string yang dipisahkan oleh koma
+ updateForm('categoryProduk', updatedSelected.join(','));
+ validate();
+ };
+
+ useEffect(() => {
+ if (form.categoryProduk) {
+ setSelectedIds(form.categoryProduk.split(',').map(Number)); // Parse string menjadi array angka
+ }
+ }, [form.categoryProduk]);
+ const isChecked = (id) => selectedIds.includes(id);
+
+ const handleInputChange = (event) => {
+ const { name, value } = event.target;
+ updateForm(name, value);
+ validate();
+ };
+
+ const midIndex = Math.ceil(category_produk.length / 2);
+ const firstColumn = category_produk.slice(0, midIndex);
+ const secondColumn = category_produk.slice(midIndex);
+ const isFormValid = useMemo(() => Object.keys(errors).length === 0, [errors]);
+
+ const nameRef = useRef(null);
+ const industry_idRef = useRef(null);
+ const streetRef = useRef(null);
+ const stateRef = useRef(null);
+ const cityRef = useRef(null);
+ const zipRef = useRef(null);
+ const mobileRef = useRef(null);
+ const bankNameRef = useRef(null);
+ const accountNameRef = useRef(null);
+ const accountNumberRef = useRef(null);
+ const estimasiRef = useRef(null);
+ const tempoDurationRef = useRef(null);
+ const bersediaRef = useRef(null);
+ const categoryProdukRef = useRef(null);
+ const tempoLimitRef = useRef(null);
+ useEffect(() => {
+ const loadIndustries = async () => {
+ if (!isFormValid) {
+ const options = {
+ behavior: 'smooth',
+ block: 'center',
+ };
+ if (errors.name && nameRef.current) {
+ nameRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errors.industry_id && industry_idRef.current) {
+ industry_idRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errors.street && streetRef.current) {
+ streetRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errors.state && stateRef.current) {
+ stateRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errors.city && cityRef.current) {
+ cityRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errors.zip && zipRef.current) {
+ zipRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errors.mobile && mobileRef.current) {
+ mobileRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errors.bankName && bankNameRef.current) {
+ bankNameRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errors.accountName && accountNameRef.current) {
+ accountNameRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errors.accountNumber && accountNumberRef.current) {
+ accountNumberRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errors.estimasi && estimasiRef.current) {
+ estimasiRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errors.tempoDuration && tempoDurationRef.current) {
+ tempoDurationRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errors.bersedia && bersediaRef.current) {
+ bersediaRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errors.categoryProduk && categoryProdukRef.current) {
+ categoryProdukRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errors.tempoLimit && tempoLimitRef.current) {
+ tempoLimitRef.current.scrollIntoView(options);
+ return;
+ }
+ }
+ };
+ loadIndustries();
+ }, [buttonSubmitClick, chekValid]);
+ useEffect(() => {
+ if (form.industry_id) {
+ setValue('industry_id', parseInt(form.industry_id));
+ }
+ if (form.state) {
+ setValue('state', parseInt(form.state));
+ }
+ if (form.city) {
+ setValue('city', parseInt(form.city));
+ }
+ if (form.tempoDuration) {
+ setValue('tempoDuration', form.tempoDuration);
+ }
+ if (form.tempoLimit) {
+ setValue('tempoLimit', form.tempoLimit);
+ }
+ if (form.tempoLimit) {
+ const isValueInOptions = radioOptions.some(
+ (option) => option.value === form.tempoLimit
+ );
+
+ if (isValueInOptions) {
+ setValue('tempoLimit', form.tempoLimit); // Set value dari radio options
+ setIsCustom(false); // Pastikan custom tidak aktif
+ } else {
+ setValue('tempoLimit', 'custom'); // Set value ke custom jika tidak termasuk dalam options
+ setIsCustom(true); // Aktifkan custom input
+ setTempoLimitValueEx(form.tempoLimit); // Set nilai input custom ke form.tempoLimit
+ }
+ }
+ }, [form]);
+ return (
+ <>
+ {isDesktop && (
+ <div className=''>
+ <h1 className={`font-bold ${isKonfirmasi ? 'text-xl' : ''}`}>
+ Informasi Perusahaan
+ </h1>
+ <form className='flex flex-col w-full '>
+ <div className='w-full grid grid-row-2 gap-5'>
+ <div className='flex flex-row justify-between items-start'>
+ <div className='w-2/5'>
+ <label className='form-label text-nowrap'>
+ Nama Perusahaan
+ </label>
+ {!isKonfirmasi && (
+ <span className='text-xs opacity-60'>
+ isi detail perusahaan sesuai dengan nama yang terdaftar{' '}
+ </span>
+ )}
+ </div>
+ <div className='w-3/5'>
+ <input
+ id='name'
+ name='name'
+ placeholder='Masukkan nama perusahaan'
+ type='text'
+ className='form-input'
+ aria-invalid={errors.name}
+ value={form.name}
+ ref={nameRef}
+ onChange={handleInputChange}
+ />
+ {!isKonfirmasi && (
+ <span className='text-xs opacity-60'>
+ Format: PT. INDOTEKNIK DOTCOM GEMILANG
+ </span>
+ )}
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.name}
+ </div>
+ )}
+ </div>
+ </div>
+ <div className='flex flex-row justify-between items-start'>
+ <div className='w-2/5' ref={industry_idRef}>
+ <label className='form-label text-nowrap'>Industri</label>
+ {!isKonfirmasi && (
+ <span className='text-xs opacity-60'>
+ isi detail perusahaan sesuai dengan nama yang terdaftar
+ </span>
+ )}
+ </div>
+ <div className='w-3/5'>
+ <Controller
+ name='industry_id'
+ control={control}
+ render={(props) => (
+ <HookFormSelect
+ {...props}
+ options={industries}
+ placeholder={'Pilih industri bisnis anda'}
+ />
+ )}
+ />
+ {!isKonfirmasi && selectedCategory && (
+ <span className='text-gray_r-11 text-xs opacity-60'>
+ Kategori : {selectedCategory}
+ </span>
+ )}
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.industry_id}
+ </div>
+ )}
+ </div>
+ </div>
+
+ <div className='flex flex-row justify-between items-start'>
+ <div className='w-2/5 text-nowrap'>
+ <label className='form-label '>Alamat Perusahaan</label>
+ {!isKonfirmasi && (
+ <span className='text-xs opacity-60'>
+ alamat sesuai dengan alamat kantor pusat
+ </span>
+ )}
+ </div>
+ <div className='w-3/5 flex gap-3 flex-col'>
+ <div>
+ <input
+ id='street'
+ name='street'
+ ref={streetRef}
+ placeholder='Masukkan alamat lengkap perusahaan'
+ type='text'
+ value={form.street}
+ className='form-input'
+ onChange={handleInputChange}
+ />
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.street}
+ </div>
+ )}
+ </div>
+ <div className='sub-alamat flex flex-row w-full gap-3'>
+ <div className='w-2/5' ref={stateRef}>
+ <Controller
+ name='state'
+ control={control}
+ render={(props) => (
+ <HookFormSelect
+ {...props}
+ options={states}
+ placeholder='Provinsi'
+ />
+ )}
+ />
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.state}
+ </div>
+ )}
+ </div>
+ <div className='w-1/3' ref={cityRef}>
+ <Controller
+ name='city'
+ control={control}
+ render={(props) => (
+ <HookFormSelect
+ {...props}
+ options={cities}
+ disabled={!watchState}
+ placeholder='Kota'
+ />
+ )}
+ />
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.city}
+ </div>
+ )}
+ </div>
+ <div className='w-1/3'>
+ <input
+ id='zip'
+ name='zip'
+ ref={zipRef}
+ placeholder='Kode Pos'
+ type='number'
+ value={form.zip}
+ className='form-input'
+ onChange={handleInputChange}
+ />
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.zip}
+ </div>
+ )}
+ </div>
+ </div>
+ </div>
+ </div>
+ <div className='flex flex-row justify-between items-start'>
+ <div className='w-2/5 text-nowrap'>
+ <label className='form-label '>No. Telfon Perusahaan</label>
+ {!isKonfirmasi && (
+ <span className='text-xs opacity-60'>
+ isi no telfon perusahaan yang sesuai
+ </span>
+ )}
+ </div>
+ <div className='w-3/5'>
+ <input
+ id='mobile'
+ name='mobile'
+ ref={mobileRef}
+ placeholder='Masukkan nomor telfon perusahaan'
+ type='tel'
+ value={form.mobile}
+ className='form-input'
+ aria-invalid={errors.mobile}
+ onChange={handleInputChange}
+ />
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.mobile}
+ </div>
+ )}
+ </div>
+ </div>
+
+ <div className='flex flex-row justify-between items-start'>
+ <div className=' w-2/5 text-nowrap'>
+ <label className='form-label'>Data Bank</label>
+ {!isKonfirmasi && (
+ <span className='text-xs opacity-60'>
+ Isi detail data bank perusahaan anda
+ </span>
+ )}
+ </div>
+ <div className='w-3/5 flex gap-3 flex-row'>
+ <div>
+ <input
+ id='bankName'
+ name='bankName'
+ ref={bankNameRef}
+ placeholder='Nama bank'
+ type='text'
+ value={form.bankName}
+ className='form-input'
+ onChange={handleInputChange}
+ />
+ {!isKonfirmasi && (
+ <span className='text-xs opacity-60'>
+ Format: BCA, Mandiri, CIMB, BNI dll
+ </span>
+ )}
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.bankName}
+ </div>
+ )}
+ </div>
+ <div>
+ <input
+ id='accountName'
+ name='accountName'
+ ref={accountNameRef}
+ placeholder='Nama Rekening'
+ type='text'
+ value={form.accountName}
+ className='form-input'
+ onChange={handleInputChange}
+ />
+ {!isKonfirmasi && (
+ <span className='text-xs opacity-60'>
+ Format: John Doe
+ </span>
+ )}
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.accountName}
+ </div>
+ )}
+ </div>
+ <div>
+ <input
+ id='accountNumber'
+ name='accountNumber'
+ ref={accountNumberRef}
+ placeholder='Nomor Rekening Bank'
+ type='text'
+ value={form.accountNumber}
+ className='form-input'
+ onChange={handleInputChange}
+ />
+ {!isKonfirmasi && (
+ <span className='text-xs opacity-60'>
+ Format: 01234567896
+ </span>
+ )}
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.accountNumber}
+ </div>
+ )}
+ </div>
+ </div>
+ </div>
+
+ <div className='flex flex-row justify-between items-start'>
+ <div className='w-2/5 text-nowrap'>
+ <label className='form-label '>
+ Website <span className=' opacity-60'>(Opsional)</span>
+ </label>
+ </div>
+ <div className='w-3/5'>
+ <input
+ id='website'
+ name='website'
+ placeholder='www.indoteknik.com'
+ type='text'
+ value={form.website}
+ className='form-input'
+ onChange={handleInputChange}
+ />
+ </div>
+ </div>
+
+ <div className='flex flex-row justify-between items-start'>
+ <div className='w-2/5 text-nowrap'>
+ <label className='form-label '>
+ Estimasi Pembelian pertahun
+ </label>
+ </div>
+ <div className='w-3/5'>
+ <div className='relative'>
+ <input
+ id='estimasi'
+ name='estimasi'
+ ref={estimasiRef}
+ // {...register('estimasi', {
+ // setValueAs: (value) => value.replace(/^Rp\s*/, ''), // Menyimpan hanya angka
+ // })}
+ placeholder='Isi estimasi pembelian produk pertahun'
+ type='text'
+ className='form-input' // padding untuk memberi ruang untuk "RP"
+ value={formatRupiah(form.estimasi)}
+ onChange={handleChange} // Mengatur perubahan input
+ />
+ </div>
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.estimasi}
+ </div>
+ )}
+ </div>
+ </div>
+
+ <div className='flex flex-row justify-between items-center'>
+ <div className='w-2/5'>
+ <label className='form-label text-nowrap'>Durasi Tempo</label>
+ <span className='text-xs opacity-60'>
+ Pilih durasi tempo yang anda inginkan
+ </span>
+ </div>
+ <div className='w-3/5 flex flex-row items-center'>
+ <div className='w-1/5' ref={tempoDurationRef}>
+ <RadioGroup
+ onChange={onChangeTempoDuration}
+ value={form.tempoDuration}
+ >
+ <Stack direction='column' className=''>
+ <Radio colorScheme='red' value='7'>
+ 7 Hari
+ </Radio>
+ <Radio colorScheme='red' value='14' className=''>
+ 14 Hari
+ </Radio>
+ <Radio colorScheme='red' value='30' className=''>
+ 30 Hari
+ </Radio>
+ </Stack>
+ </RadioGroup>
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.tempoDuration}
+ </div>
+ )}
+ </div>
+ {!isKonfirmasi && (
+ <div className='w-4/5 flex flex-row justify-between items-center'>
+ <div className='w-2/5 text-nowrap'>
+ <label className='form-label '>Limit Tempo</label>
+ <span className='text-xs opacity-60'>
+ Ajukan nilai limit yang anda mau
+ </span>
+ </div>
+ <div
+ className='flex flex-col justify-start items-start'
+ ref={tempoLimitRef}
+ >
+ <RadioGroup
+ onChange={(value) => {
+ if (value === 'custom') {
+ setIsCustom(true);
+ updateForm('tempoLimit', tempoLimitValue); // Update dengan nilai input custom jika dipilih
+ } else {
+ setIsCustom(false);
+ onChangeTempoLimit(value); // Update dengan nilai radio button yang dipilih
+ }
+ }}
+ className='flex items-center justify-between'
+ value={isCustom ? 'custom' : form.tempoLimit}
+ >
+ <Stack direction='row'>
+ {/* Kolom 1 */}
+ <Stack
+ direction='column'
+ spacing={2}
+ className='mr-4'
+ >
+ {radioOptions.slice(0, 4).map((option) => (
+ <Radio
+ key={option.value}
+ colorScheme='red'
+ value={option.value}
+ >
+ {option.label}
+ </Radio>
+ ))}
+ </Stack>
+
+ {/* Kolom 2 */}
+ <Stack
+ direction='column'
+ className='ml-8'
+ spacing={2}
+ >
+ {radioOptions.slice(4).map((option) => (
+ <Radio
+ key={option.value}
+ colorScheme='red'
+ value={option.value}
+ >
+ {option.label}
+ </Radio>
+ ))}
+ <div className='flex flex-row items-center'>
+ <Radio colorScheme='red' value='custom'></Radio>
+
+ <input
+ placeholder='Isi limit yang anda inginkan'
+ type='text'
+ className='border ml-2 p-1' // padding untuk memberi ruang untuk "RP"
+ value={formatRupiah(tempoLimitValueEx)} // Menampilkan nilai terformat
+ onChange={(e) => {
+ const value = e.target.value;
+ const formattedValue = formatRupiah(value);
+ setTempoLimitValueEx(formattedValue);
+ updateForm(
+ 'tempoLimit',
+ formattedValue.replace(/^Rp\s*/, '')
+ ); // Mengupdate nilai di react-hook-form
+ }}
+ />
+ </div>
+ </Stack>
+ </Stack>
+ </RadioGroup>
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.tempoLimit}
+ </div>
+ )}
+ </div>
+ </div>
+ )}
+ </div>
+ </div>
+ {isKonfirmasi && (
+ <div className='flex flex-row justify-between items-center'>
+ <div className='w-2/5'>
+ <label className='form-label w-2/5 text-nowrap'>
+ Limit Tempo
+ </label>
+ <span className='text-xs opacity-60'>
+ Ajukan nilai limit yang anda mau
+ </span>
+ </div>
+ <div
+ className='w-3/5 flex flex-col justify-start items-start'
+ ref={tempoLimitRef}
+ >
+ <RadioGroup
+ onChange={(value) => {
+ if (value === 'custom') {
+ setIsCustom(true);
+ updateForm('tempoLimit', tempoLimitValue); // Update dengan nilai input custom jika dipilih
+ } else {
+ setIsCustom(false);
+ onChangeTempoLimit(value); // Update dengan nilai radio button yang dipilih
+ }
+ }}
+ className='flex items-center justify-between'
+ value={isCustom ? 'custom' : form.tempoLimit}
+ >
+ <Stack direction='row'>
+ {/* Kolom 1 */}
+ <Stack direction='column' spacing={2} className='mr-4'>
+ {radioOptions.slice(0, 4).map((option) => (
+ <Radio
+ key={option.value}
+ colorScheme='red'
+ value={option.value}
+ >
+ {option.label}
+ </Radio>
+ ))}
+ </Stack>
+
+ {/* Kolom 2 */}
+ <Stack direction='column' className='ml-8' spacing={2}>
+ {radioOptions.slice(4).map((option) => (
+ <Radio
+ key={option.value}
+ colorScheme='red'
+ value={option.value}
+ >
+ {option.label}
+ </Radio>
+ ))}
+ <div className='flex flex-row items-center'>
+ <Radio colorScheme='red' value='custom'></Radio>
+
+ <input
+ placeholder='Isi limit yang anda inginkan'
+ type='text'
+ className='border ml-2 p-1' // padding untuk memberi ruang untuk "RP"
+ value={formatRupiah(tempoLimitValueEx)} // Menampilkan nilai terformat
+ onChange={(e) => {
+ const value = e.target.value;
+ const formattedValue = formatRupiah(value);
+ setTempoLimitValueEx(formattedValue);
+ updateForm(
+ 'tempoLimit',
+ formattedValue.replace(/^Rp\s*/, '')
+ ); // Mengupdate nilai di react-hook-form
+ }}
+ />
+ </div>
+ </Stack>
+ </Stack>
+ </RadioGroup>
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.tempoLimit}
+ </div>
+ )}
+ </div>
+ </div>
+ )}
+
+ <div className='text-red-500'>
+ *Durasi dan limit dapat berbeda sesuai dengan verifikasi oleh
+ tim Indoteknik.com
+ </div>
+
+ <div className='flex flex-row justify-between items-start'>
+ <div className='w-2/5'>
+ <label className='form-label text-wrap '>
+ Apakah bersedia transaksi via website?
+ </label>
+ {!isKonfirmasi && (
+ <span className='text-xs opacity-60'>
+ Pilih produk bisa lebih dari 1
+ </span>
+ )}
+ </div>
+ <div className='w-3/5 flex flex-col justify-start'>
+ <div className='flex gap-x-4' ref={bersediaRef}>
+ <RadioGroup
+ onChange={handleCheckboxBersediaChange}
+ value={form.bersedia}
+ >
+ <Stack direction='row'>
+ <Radio colorScheme='red' value='bersedia'>
+ Saya bersedia
+ </Radio>
+ <Radio colorScheme='red' value='tidakBersedia'>
+ Tidak bersedia
+ </Radio>
+ </Stack>
+ </RadioGroup>
+ {/* <Checkbox
+ name='bersedia'
+ borderColor='gray.600'
+ colorScheme='red'
+ isChecked={bersedia === true} // Checked when bersedia is true
+ onChange={() => handleCheckboxBersediaChange('bersedia')}
+ value={true}
+ size='md'
+ >
+ Saya bersedia
+ </Checkbox>
+ <Checkbox
+ name='bersedia'
+ borderColor='gray.600'
+ colorScheme='red'
+ isChecked={bersedia === false} // Checked when bersedia is false
+ onChange={() => handleCheckboxBersediaChange('tidakBersedia')}
+ value={false}
+ size='md'
+ >
+ Tidak bersedia
+ </Checkbox> */}
+ </div>
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.estimasi}
+ </div>
+ )}
+ </div>
+ </div>
+
+ <div
+ className={`flex flex-row justify-between ${
+ isKonfirmasi ? 'items-center' : 'items-start'
+ }`}
+ >
+ <div className='w-2/5 text-nowrap'>
+ <label className='form-label '>
+ Kategori Produk yang Digunakan
+ </label>
+ {!isKonfirmasi && (
+ <span className='text-xs opacity-60'>
+ Pilih produk bisa lebih dari 1
+ </span>
+ )}
+ </div>
+ <div className='w-3/5 flex flex-col'>
+ <div className='flex flex-row justify-between'>
+ <div
+ className='flex flex-col gap-2'
+ ref={categoryProdukRef}
+ >
+ {firstColumn.map((item) => (
+ <Checkbox
+ colorScheme='red'
+ key={item.id}
+ onChange={() => handleCheckboxChange(item.id)}
+ isChecked={isChecked(item.id)}
+ >
+ {item.name}
+ </Checkbox>
+ ))}
+ </div>
+ <div className='flex flex-col gap-2'>
+ {secondColumn.map((item) => (
+ <Checkbox
+ colorScheme='red'
+ key={item.id}
+ isChecked={isChecked(item.id)}
+ onChange={() => handleCheckboxChange(item.id)}
+ >
+ {item.name}
+ </Checkbox>
+ ))}
+ </div>
+ </div>
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.categoryProduk}
+ </div>
+ )}
+ </div>
+ </div>
+ </div>
+ </form>
+ </div>
+ )}
+ {isMobile && (
+ <div className='text-sm'>
+ <h1
+ className={`font-bold py-4 mt-8 ${
+ isKonfirmasi ? 'hidden' : 'text-xl'
+ }`}
+ >
+ Informasi Perusahaan
+ </h1>
+ <form className='flex flex-col w-full '>
+ <div className='w-full grid grid-row-2 gap-4'>
+ <div className='flex flex-col gap-2 justify-between items-start'>
+ <label className='form-label text-nowrap'>
+ Nama Perusahaan
+ </label>
+ <input
+ id='name'
+ name='name'
+ placeholder='Format: PT. INDOTEKNIK DOTCOM GEMILANG'
+ type='text'
+ className='form-input'
+ aria-invalid={errors.name}
+ value={form.name}
+ ref={nameRef}
+ onChange={handleInputChange}
+ />
+ {!isKonfirmasi && (
+ <span className='text-xs opacity-60'>
+ isi detail perusahaan sesuai dengan nama yang terdaftar{' '}
+ </span>
+ )}
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.name}
+ </div>
+ )}
+ </div>
+
+ <div className='flex flex-col gap-2 justify-between items-start'>
+ <label className='form-label text-nowrap'>Industri</label>
+ <div className='w-full' ref={industry_idRef}>
+ <Controller
+ name='industry_id'
+ control={control}
+ render={(props) => (
+ <HookFormSelect
+ {...props}
+ options={industries}
+ placeholder={
+ 'Pilih Industri yang sesuai dengan perusahaan'
+ }
+ />
+ )}
+ />
+ </div>
+ {!isKonfirmasi && selectedCategory && (
+ <span className='text-gray_r-11 text-xs opacity-60'>
+ Kategori : {selectedCategory}
+ </span>
+ )}
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.industry_id}
+ </div>
+ )}
+ </div>
+
+ <div className='flex flex-col gap-2 justify-between items-start'>
+ <label className='form-label '>Alamat Perusahaan</label>
+ <input
+ id='street'
+ name='street'
+ ref={streetRef}
+ placeholder='Masukkan alamat lengkap perusahaan'
+ type='text'
+ value={form.street}
+ className='form-input'
+ onChange={handleInputChange}
+ />
+ <div className='w-full text-nowrap'>
+ <div className='sub-alamat flex flex-row w-full gap-3'>
+ <div className='w-2/5' ref={stateRef}>
+ <Controller
+ name='state'
+ control={control}
+ render={(props) => (
+ <HookFormSelect
+ {...props}
+ options={states}
+ placeholder='Provinsi'
+ />
+ )}
+ />
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.state}
+ </div>
+ )}
+ </div>
+ <div className='w-1/3' ref={cityRef}>
+ <Controller
+ name='city'
+ control={control}
+ render={(props) => (
+ <HookFormSelect
+ {...props}
+ options={cities}
+ disabled={!watchState}
+ placeholder='Kota'
+ />
+ )}
+ />
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.city}
+ </div>
+ )}
+ </div>
+ <div className='w-1/3'>
+ <input
+ id='zip'
+ name='zip'
+ ref={zipRef}
+ placeholder='Kode Pos'
+ type='number'
+ value={form.zip}
+ className='form-input'
+ onChange={handleInputChange}
+ />
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.zip}
+ </div>
+ )}
+ </div>
+ </div>
+ </div>
+ {!isKonfirmasi && (
+ <span className='text-xs opacity-60'>
+ Isi detail alamat sesuai dengan yang terdaftar
+ </span>
+ )}
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.street}
+ </div>
+ )}
+ </div>
+
+ <div className='flex flex-col gap-2 justify-between items-start'>
+ <label className='form-label '>No. Telfon Perusahaan</label>
+ <input
+ id='mobile'
+ name='mobile'
+ ref={mobileRef}
+ placeholder='Format: 08123456789 / (021) 123 4567'
+ type='tel'
+ value={form.mobile}
+ className='form-input'
+ aria-invalid={errors.mobile}
+ onChange={handleInputChange}
+ />
+ {!isKonfirmasi && (
+ <span className='text-xs opacity-60'>
+ Isi detail perusahaan sesuai dengan nama yang terdaftar
+ </span>
+ )}
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.mobile}
+ </div>
+ )}
+ </div>
+
+ <div className='flex flex-col gap-2 justify-between items-start'>
+ <label className='form-label'>Data Bank</label>
+ <div className='flex gap-3 flex-row'>
+ <div>
+ <input
+ id='bankName'
+ name='bankName'
+ ref={bankNameRef}
+ placeholder='Nama bank'
+ type='text'
+ value={form.bankName}
+ className='form-input'
+ onChange={handleInputChange}
+ />
+ </div>
+ <div>
+ <input
+ id='accountName'
+ name='accountName'
+ ref={accountNameRef}
+ placeholder='Nama Rekening'
+ type='text'
+ value={form.accountName}
+ className='form-input'
+ onChange={handleInputChange}
+ />
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.accountName}
+ </div>
+ )}
+ </div>
+ <div>
+ <input
+ id='accountNumber'
+ name='accountNumber'
+ ref={accountNumberRef}
+ placeholder='Nomor Rekening'
+ type='text'
+ value={form.accountNumber}
+ className='form-input'
+ onChange={handleInputChange}
+ />
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.accountNumber}
+ </div>
+ )}
+ </div>
+ </div>
+ {!isKonfirmasi && (
+ <span className='text-xs opacity-60'>
+ Isi data bank perusahaan sesuai dengan yang terdaftar
+ </span>
+ )}
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.bankName}
+ </div>
+ )}
+ </div>
+
+ <div className='flex flex-col gap-2 justify-between items-start'>
+ <label className='form-label '>
+ Website <span className=' opacity-60'>(Opsional)</span>
+ </label>
+ <input
+ id='website'
+ name='website'
+ placeholder='Format: www.indoteknik.com'
+ type='text'
+ value={form.website}
+ className='form-input'
+ onChange={handleInputChange}
+ />
+ </div>
+
+ <div className='flex flex-col gap-2 justify-between items-start'>
+ <label className='form-label '>
+ Estimasi Pembelian pertahun
+ </label>
+ <input
+ id='estimasi'
+ name='estimasi'
+ ref={estimasiRef}
+ // {...register('estimasi', {
+ // setValueAs: (value) => value.replace(/^Rp\s*/, ''), // Menyimpan hanya angka
+ // })}
+ placeholder='Isi estimasi pembelian produk pertahun'
+ type='text'
+ className='form-input' // padding untuk memberi ruang untuk "RP"
+ value={formatRupiah(form.estimasi)}
+ onChange={handleChange} // Mengatur perubahan input
+ />
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.estimasi}
+ </div>
+ )}
+ </div>
+ <div className='h-[2px] bg-gray-300 w-[120%] inset-0 relative transform -translate-x-5'></div>
+ <div className='flex flex-col gap-2 justify-start items-start'>
+ <label className='form-label text-nowrap'>Durasi Tempo</label>
+ <div className='' ref={tempoDurationRef}>
+ <RadioGroup
+ size='sm'
+ onChange={onChangeTempoDuration}
+ value={form.tempoDuration}
+ >
+ <Stack direction='row' className=''>
+ <Radio colorScheme='red' value='7'>
+ 7 Hari
+ </Radio>
+ <Radio colorScheme='red' value='14' className=''>
+ 14 Hari
+ </Radio>
+ <Radio colorScheme='red' value='30' className=''>
+ 30 Hari
+ </Radio>
+ </Stack>
+ </RadioGroup>
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.tempoDuration}
+ </div>
+ )}
+ </div>
+ </div>
+ <div className='flex flex-col gap-2 justify-start items-start'>
+ <label className='form-label '>Limit Tempo</label>
+ <div
+ className='flex justify-between items-center '
+ ref={tempoLimitRef}
+ >
+ <RadioGroup
+ size='sm'
+ onChange={(value) => {
+ if (value === 'custom') {
+ setIsCustom(true);
+ updateForm('tempoLimit', tempoLimitValue); // Update dengan nilai input custom jika dipilih
+ } else {
+ setIsCustom(false);
+ onChangeTempoLimit(value); // Update dengan nilai radio button yang dipilih
+ }
+ }}
+ className='flex items-center justify-between'
+ value={isCustom ? 'custom' : form.tempoLimit}
+ >
+ <Stack direction='row'>
+ {/* Kolom 1 */}
+ <Stack direction='row' spacing={2} className='mr-4'>
+ {radioOptions.slice(0, 3).map((option) => (
+ <Radio
+ key={option.value}
+ colorScheme='red'
+ value={option.value}
+ >
+ {option.label}
+ </Radio>
+ ))}
+ <Radio colorScheme='red' value='custom'></Radio>
+
+ <input
+ placeholder='Isi limit'
+ type='text'
+ className='border ml-1 p-1 w-full ' // padding untuk memberi ruang untuk "RP"
+ value={formatRupiah(tempoLimitValueEx)} // Menampilkan nilai terformat
+ onChange={(e) => {
+ const value = e.target.value;
+ const formattedValue = formatRupiah(value);
+ setTempoLimitValueEx(formattedValue);
+ updateForm(
+ 'tempoLimit',
+ formattedValue.replace(/^Rp\s*/, '')
+ ); // Mengupdate nilai di react-hook-form
+ }}
+ />
+ </Stack>
+
+ {/* Kolom 2 */}
+ {/* <Stack direction='column' className='ml-8' spacing={2}>
+ {radioOptions.slice(4).map((option) => (
+ <Radio
+ key={option.value}
+ colorScheme='red'
+ value={option.value}
+ >
+ {option.label}
+ </Radio>
+ ))}
+ <div className='flex flex-row items-center'></div>
+ </Stack> */}
+ </Stack>
+ </RadioGroup>
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.tempoLimit}
+ </div>
+ )}
+ </div>
+ </div>
+ <div className='text-red-500 text-xs'>
+ **Durasi & Limit dapat berbeda dengan verifikasi oleh tim
+ indoteknik.com
+ </div>
+ <div className='h-[2px] bg-gray-300 w-[120%] inset-0 relative transform -translate-x-5'></div>
+ <div className='flex flex-col gap justify-between items-start'>
+ <label className='form-label text-wrap '>
+ Apakah bersedia transaksi via website?
+ </label>
+ <div className='flex gap-x-4' ref={bersediaRef}>
+ <RadioGroup
+ size='sm'
+ onChange={handleCheckboxBersediaChange}
+ value={form.bersedia}
+ >
+ <Stack direction='col'>
+ <Radio colorScheme='red' value='bersedia'>
+ Saya bersedia
+ </Radio>
+ <Radio colorScheme='red' value='tidakBersedia'>
+ Tidak bersedia
+ </Radio>
+ </Stack>
+ </RadioGroup>
+ </div>
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.estimasi}
+ </div>
+ )}
+ </div>
+ <div className='h-[2px] bg-gray-300 w-[120%] inset-0 relative transform -translate-x-5'></div>
+
+ <div
+ className={`flex flex-col gap-2 justify-between ${
+ isKonfirmasi ? 'items-start' : 'items-start'
+ }`}
+ >
+ <label className='form-label '>
+ Kategori Produk yang Digunakan
+ </label>
+ <div className='flex flex-col justify-between gap-2 '>
+ <div className='flex flex-col gap-2' ref={categoryProdukRef}>
+ {firstColumn.map((item) => (
+ <Checkbox
+ size='sm'
+ colorScheme='red'
+ key={item.id}
+ onChange={() => handleCheckboxChange(item.id)}
+ isChecked={isChecked(item.id)}
+ >
+ {item.name}
+ </Checkbox>
+ ))}
+ </div>
+ <div className='flex flex-col gap-2'>
+ {secondColumn.map((item) => (
+ <Checkbox
+ size='sm'
+ colorScheme='red'
+ key={item.id}
+ isChecked={isChecked(item.id)}
+ onChange={() => handleCheckboxChange(item.id)}
+ >
+ {item.name}
+ </Checkbox>
+ ))}
+ </div>
+ </div>
+ {chekValid && (
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.categoryProduk}
+ </div>
+ )}
+ </div>
+ </div>
+ </form>
+ </div>
+ )}
+ </>
+ );
+};
+
+export default InformasiPerusahaan;