diff options
Diffstat (limited to 'src/lib')
| -rw-r--r-- | src/lib/pengajuan-tempo/component/Konfirmasi.jsx | 524 | ||||
| -rw-r--r-- | src/lib/pengajuan-tempo/component/PengajuanTempo.jsx | 3 |
2 files changed, 526 insertions, 1 deletions
diff --git a/src/lib/pengajuan-tempo/component/Konfirmasi.jsx b/src/lib/pengajuan-tempo/component/Konfirmasi.jsx new file mode 100644 index 00000000..a03bc59e --- /dev/null +++ b/src/lib/pengajuan-tempo/component/Konfirmasi.jsx @@ -0,0 +1,524 @@ +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 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'; +const Dokumen = ({ chekValid, buttonSubmitClick }) => { + const { control, watch, setValue, getValues } = useForm(); + const [industries, setIndustries] = useState([]); + const [industriesOpen, setIndustriesOpen] = useState(false); + 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(); // 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 selectRef = useRef(null); + 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 ( + <> + <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 grid grid-rows-[1fc_auto_ifc] gap-5'> + <div className='kolom-kiri w-full grid grid-rows-2 gap-7 '> + <div className='flex justify-start'> + <h2 className='font-bold text-xl'>Informasi Usaha</h2> + </div> + <div className='w-full flex flex-row items-start gap-5'> + <div className='w-1/3'> + <label className='form-label text-nowrap'> + Nama Perusahaan + </label> + </div> + <div className='w-2/3'> + <div className='flex flex-row items-center gap-2'> + <div className='relative w-11/12'> + <input + value={form.name} + id='name' + name='name' + type='text' + className='form-input bg-gray_r-2 focus:bg-white new w-full pr-16' + aria-invalid={errors.name} + onChange={handleInputChange} + /> + <label + htmlFor='name' + className='absolute right-0 top-0 cursor-pointer text-red-500 py-2 px-4 ' + > + Ubah + </label> + </div> + <CheckCircleIcon className='w-6 text-green-700 ring-green-600/20 bg-green-50' /> + </div> + {chekValid && ( + <div className='text-caption-2 text-danger-500 mt-1'> + {errors.name} + </div> + )} + </div> + </div> + <div className='w-full flex flex-row items-start gap-5'> + <div className='w-1/3'> + <label className='form-label text-nowrap'>Industri</label> + </div> + <div className='w-2/3'> + <div className='flex flex-row items-center gap-2'> + <div className='relative w-11/12'> + <Controller + inputId='industry_id' + name='industry_id' + control={control} + render={(props) => ( + <HookFormSelect + {...props} + inputId='industry_id' + name='industry_id' + ref={selectRef} + options={industries} + menuIsOpen={industriesOpen} + placeholder={'Pilih industri bisnis anda'} + /> + )} + /> + <label + htmlFor='industry_id' + // onClick={handleLabelClick} + className='absolute right-0 top-0 cursor-pointer text-red-500 py-2 px-4 ' + > + Ubah + </label> + </div> + <CheckCircleIcon className='w-6 text-green-700 ring-green-600/20 bg-green-50' /> + </div> + {chekValid && ( + <div className='text-caption-2 text-danger-500 mt-1'> + {errors.industry_id} + </div> + )} + </div> + </div> + <div className='w-full flex flex-row items-start gap-5'> + <div className='w-1/3'> + <label className='form-label text-nowrap'> + Alamat Perusahaan + </label> + </div> + <div className='w-2/3'> + <div className='flex flex-row items-center gap-2'> + <div className='relative w-11/12'> + {/* Input field */} + <input + value={form.street} + id='street' + name='street' + type='text' + className='form-input bg-gray_r-2 focus:bg-white new w-full pr-16' // Tambah padding untuk memberi ruang bagi label + aria-invalid={errors.street} + onChange={handleInputChange} + /> + + {/* Label "ubah" di pojok kanan */} + <label + htmlFor='street' + className='absolute right-0 top-0 cursor-pointer text-red-500 py-2 px-4 ' + > + Ubah + </label> + + {/* Pesan kesalahan */} + </div> + <CheckCircleIcon className='w-6 text-green-700 ring-green-600/20 bg-green-50' /> + </div> + {chekValid && ( + <div className='text-caption-2 text-danger-500 mt-1'> + {errors.street} + </div> + )} + </div> + </div> + <div className='w-full flex flex-row items-start gap-5'> + <div className='w-1/3'> + <label className='form-label text-nowrap'> + No. Telfon Perusahaan + </label> + </div> + <div className='w-2/3'> + <div className='flex flex-row items-center gap-2'> + <div className='relative w-11/12'> + {/* Input field */} + <input + value={form.mobile} + id='mobile' + name='mobile' + type='text' + className='form-input bg-gray_r-2 focus:bg-white new w-full pr-16' // Tambah padding untuk memberi ruang bagi label + aria-invalid={errors.mobile} + onChange={handleInputChange} + /> + + {/* Label "ubah" di pojok kanan */} + <label + htmlFor='mobile' + className='absolute right-0 top-0 cursor-pointer text-red-500 py-2 px-4 ' + > + Ubah + </label> + + {/* Pesan kesalahan */} + </div> + <CheckCircleIcon className='w-6 text-green-700 ring-green-600/20 bg-green-50' /> + </div> + {chekValid && ( + <div className='text-caption-2 text-danger-500 mt-1'> + {errors.mobile} + </div> + )} + </div> + </div> + <div className='w-full flex flex-row items-start gap-5'> + <div className='w-1/3'> + <label className='form-label text-nowrap'>Data Bank</label> + </div> + <div className='w-2/3'> + <div className='flex flex-row items-center gap-2'> + <div className='relative w-11/12'> + {/* Input field */} + <input + value={form.accountName} + id='accountName' + name='accountName' + type='text' + className='form-input bg-gray_r-2 focus:bg-white new w-full pr-16' // Tambah padding untuk memberi ruang bagi label + aria-invalid={errors.accountName} + onChange={handleInputChange} + /> + + {/* Label "ubah" di pojok kanan */} + <label + htmlFor='accountName' + className='absolute right-0 top-0 cursor-pointer text-red-500 py-2 px-4 ' + > + Ubah + </label> + + {/* Pesan kesalahan */} + </div> + <CheckCircleIcon className='w-6 text-green-700 ring-green-600/20 bg-green-50' /> + </div> + {chekValid && ( + <div className='text-caption-2 text-danger-500 mt-1'> + {errors.accountName} + </div> + )} + </div> + </div> + </div> + <div className='h-px bg-gray-300'></div> + <div className='kolom-kiri w-full grid grid-rows-2 gap-7 '> + <div className='flex justify-start'> + <h2 className='font-bold text-xl'>Informasi Usaha</h2> + </div> + <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> + </div> + + <div className='w-px bg-gray-300'></div> + <div className='w-full grid grid-rows-[1fc_auto_ifc] gap-5'> + <div className='kolom kanan w-full grid grid-rows-2 gap-10 '> + <div className='flex justify-start'> + <h2 className='font-bold text-xl'>Pengiriman</h2> + </div> + <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></div> + </div> + <div className='h-px bg-gray-300'></div> + <div className='kolom kanan w-full grid grid-rows-2 gap-10 '> + <div className='flex justify-start'> + <h2 className='font-bold text-xl'>Pengiriman</h2> + </div> + <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></div> + </div> + </div> + </div> + </form> + </> + ); +}; + +export default Dokumen; diff --git a/src/lib/pengajuan-tempo/component/PengajuanTempo.jsx b/src/lib/pengajuan-tempo/component/PengajuanTempo.jsx index e6424e51..030583aa 100644 --- a/src/lib/pengajuan-tempo/component/PengajuanTempo.jsx +++ b/src/lib/pengajuan-tempo/component/PengajuanTempo.jsx @@ -6,6 +6,7 @@ import KontakPerusahaan from './KontakPerusahaan'; import Pengiriman from './Pengiriman'; import Referensi from './Referensi'; import Dokumen from './Dokumen'; +import Konfirmasi from './Konfirmasi'; import { Controller, useForm } from 'react-hook-form'; import { usePengajuanTempoStore, @@ -50,7 +51,7 @@ const PengajuanTempo = () => { <Pengiriman chekValid={notValid} buttonSubmitClick={buttonSubmitClick} />, <Referensi chekValid={notValid} buttonSubmitClick={buttonSubmitClick} />, <Dokumen chekValid={notValid} buttonSubmitClick={buttonSubmitClick} />, - <div>Konfirmasi</div>, + <Konfirmasi chekValid={notValid} buttonSubmitClick={buttonSubmitClick} />, ]; const stepDivsError = [ errors, |
