diff options
| author | it-fixcomart <it@fixcomart.co.id> | 2024-12-06 17:06:26 +0700 |
|---|---|---|
| committer | it-fixcomart <it@fixcomart.co.id> | 2024-12-06 17:06:26 +0700 |
| commit | e9cd13307f0095dc4edc5048752675d80c551564 (patch) | |
| tree | ba133ca989725bd225e3ed1517ddece8a33e3f32 /src | |
| parent | 9a49b8d84761781531cb417731cb9ef802f63541 (diff) | |
<iman> pengajuan tempo
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/address/components/EditAddress.jsx | 53 | ||||
| -rw-r--r-- | src/lib/pengajuan-tempo/component/Dokumen.jsx | 85 | ||||
| -rw-r--r-- | src/lib/pengajuan-tempo/component/FinishTempo.jsx | 16 | ||||
| -rw-r--r-- | src/lib/pengajuan-tempo/component/KonfirmasiDokumen.jsx | 118 | ||||
| -rw-r--r-- | src/lib/pengajuan-tempo/component/KontakPerusahaan.jsx | 245 | ||||
| -rw-r--r-- | src/lib/pengajuan-tempo/component/PengajuanTempo.jsx | 235 | ||||
| -rw-r--r-- | src/lib/pengajuan-tempo/component/Pengiriman.jsx | 1304 | ||||
| -rw-r--r-- | src/lib/pengajuan-tempo/component/Referensi.jsx | 14 | ||||
| -rw-r--r-- | src/lib/pengajuan-tempo/component/informasiPerusahaan.jsx | 359 | ||||
| -rw-r--r-- | src/lib/tempo/components/Tempo.jsx | 217 | ||||
| -rw-r--r-- | src/pages/pengajuan-tempo/index.jsx | 17 |
11 files changed, 1349 insertions, 1314 deletions
diff --git a/src/lib/address/components/EditAddress.jsx b/src/lib/address/components/EditAddress.jsx index 23cf72a9..dd5c27fd 100644 --- a/src/lib/address/components/EditAddress.jsx +++ b/src/lib/address/components/EditAddress.jsx @@ -34,7 +34,8 @@ const EditAddress = ({ id, defaultValues }) => { const [states, setStates] = useState([]); const [cities, setCities] = useState([]); const [districts, setDistricts] = useState([]); - const [subDistricts, setSubDistricts] = useState([]); + const [subDistricts, setSubDistricts] = useState([]); + const [isZipTrue, setIsZipTrue] = useState(false); useEffect(() => { const loadProfile = async () => { @@ -60,12 +61,12 @@ const EditAddress = ({ id, defaultValues }) => { setStates(dataStates); }; loadStates(); - },[]) + }, []); const watchState = watch('state'); useEffect(() => { setValue('city', ''); - if(watchState) { + if (watchState) { const loadCities = async () => { let dataCities = await cityApi({ stateId: watchState }); dataCities = dataCities.map((city) => ({ @@ -81,7 +82,6 @@ const EditAddress = ({ id, defaultValues }) => { }; loadCities(); } - }, [watchState, setValue, getValues]); const watchCity = watch('city'); @@ -128,7 +128,44 @@ const EditAddress = ({ id, defaultValues }) => { loadSubDistricts(); } }, [watchDistrict, setValue, getValues]); + + const watchZip = watch('zip'); const onSubmitHandler = async (values) => { + if (watchZip) { + const loadZip = async () => { + try { + const response = await fetch( + `https://alamat.thecloudalert.com/api/cari/index/?keyword=${watchZip}` + ); + + if (!response.ok) { + toast.error('Gagal memuat data alamat pos.'); + setValue('zip', ''); + return false; + } + + const result = await response.json(); + console.log('result', result); + + if (result.length === 0) { + toast.error('Alamat pos salah'); + setValue('zip', ''); + return false; + } + + return true; // Jika valid + } catch (error) { + toast.error('Terjadi kesalahan saat memeriksa alamat pos.'); + console.error('Error:', error); + return false; + } + }; + + const isValidZip = await loadZip(); + if (!isValidZip) { + return; // Menghentikan eksekusi jika alamat salah + } + } const data = { ...values, phone: values.mobile, @@ -287,7 +324,11 @@ const EditAddress = ({ id, defaultValues }) => { name='city' control={control} render={(props) => ( - <HookFormSelect {...props} options={cities} disabled={!watchState} /> + <HookFormSelect + {...props} + options={cities} + disabled={!watchState} + /> )} /> <div className='text-caption-2 text-danger-500 mt-1'> @@ -348,7 +389,7 @@ const validationSchema = Yup.object().shape({ mobile: Yup.string().required('Harus di-isi'), street: Yup.string().required('Harus di-isi'), zip: Yup.string().required('Harus di-isi'), - state : Yup.string().required('Harus di-pilih'), + state: Yup.string().required('Harus di-pilih'), city: Yup.string().required('Harus di-pilih'), district: Yup.string().required('Harus di-pilih'), }); diff --git a/src/lib/pengajuan-tempo/component/Dokumen.jsx b/src/lib/pengajuan-tempo/component/Dokumen.jsx index f05dc9ce..52217e56 100644 --- a/src/lib/pengajuan-tempo/component/Dokumen.jsx +++ b/src/lib/pengajuan-tempo/component/Dokumen.jsx @@ -6,6 +6,7 @@ import { UseToastOptions } from '@chakra-ui/react'; import { toast } from 'react-hot-toast'; import getFileBase64 from '@/core/utils/getFileBase64'; import useDevice from '@/core/hooks/useDevice'; +import imageCompression from 'browser-image-compression'; const Dokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { const { control, watch } = useForm(); const { @@ -44,15 +45,32 @@ const Dokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { // Check for file size if (file.size > 500000) { - toast.error('Maksimal ukuran file adalah 500Kb', { duration: 4000 }); - - event.target.value = ''; - return; + try { + const toastId = toast.loading('mencoba mengompresi file...'); + // Compress image file + const options = { + maxSizeMB: 0.5, // Target size in MB + maxWidthOrHeight: 1920, // Adjust as needed + useWebWorker: true, + }; + const compressedFile = await imageCompression(file, options); + toast.success('berhasil mengompresi file', { duration: 4000 }); + // Convert compressed file to Base64 + fileBase64 = await getFileBase64(compressedFile); + updateFormDokumen( + name, + compressedFile.name, + fileExtension, + fileBase64 + ); + } catch (error) { + toast.error('Gagal mengompresi file', { duration: 4000 }); + } + } else { + // Convert file to Base64 + fileBase64 = await getFileBase64(file); + updateFormDokumen(name, file.name, fileExtension, fileBase64); } - - // Convert file to Base64 - fileBase64 = await getFileBase64(file); - updateFormDokumen(name, file.name, fileExtension, fileBase64); validateDokumen(); } }; @@ -139,6 +157,7 @@ const Dokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { useEffect(() => { validateDokumen(); }, [buttonSubmitClick]); + console.log('formDokumen', formDokumen); return ( <> {isDesktop && ( @@ -155,7 +174,8 @@ const Dokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { > <div> <label className='form-label text-nowrap'> - NIB (SIUP/TDP/SKDP) + NIB (SIUP/TDP/SKDP){' '} + <span className='text-danger-500 text-xl'>*</span> </label> <span className='text-xs opacity-60'> Pastikan dokumen yang anda upload sudah benar @@ -286,7 +306,7 @@ const Dokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { <div> <label className='form-label text-nowrap'> Akta Perubahan{' '} - <span className=' opacity-60'>(Opsional)</span> + <span className=' opacity-60'>(Opsional)</span>{' '} </label> <span className='text-xs opacity-60'> Pastikan dokumen yang anda upload sudah benar @@ -330,7 +350,8 @@ const Dokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { <div> <label className='form-label text-nowrap'> KTP Dirut/Direktur{' '} - <span className=' opacity-60'>(Opsional)</span> + <span className=' opacity-60'>(Opsional)</span>{' '} + <span className='text-danger-500 text-xl'>*</span> </label> <span className='text-xs opacity-60'> Pastikan dokumen yang anda upload sudah benar @@ -378,7 +399,8 @@ const Dokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { <div> <label className='form-label text-nowrap'> Akta Pendirian{' '} - <span className=' opacity-60'>(Opsional)</span> + <span className=' opacity-60'>(Opsional)</span>{' '} + <span className='text-danger-500 text-xl'>*</span> </label> <span className='text-xs opacity-60'> Pastikan dokumen yang anda upload sudah benar @@ -511,7 +533,7 @@ const Dokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { > <div> <label className='form-label text-nowrap'> - Tempat Bekerja + Foto tempat kerja </label> <span className='text-xs opacity-60'> Pastikan dokumen yang anda upload sudah benar @@ -554,6 +576,10 @@ const Dokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { </div> </form> <div className='w-1/2 mt-8 flex gap-3 flex-col'> + <span className='opacity-75 text-danger-500 text-sm'> + *Jika anda ingin kredit limit lebih dari 25 Juta, harap lampirkan + dokumen yang diberi tanda bintang *) + </span> <div className='flex justify-between'> <p className='font-bold'>Upload Progress</p> <p> @@ -601,7 +627,8 @@ const Dokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { <div className='w-full flex flex-col gap-4'> <div className='w-full flex flex-col gap-2' ref={dokumenNibRef}> <label className='form-label text-nowrap'> - NIB (SIUP/TDP/SKDP) + NIB (SIUP/TDP/SKDP){' '} + <span className='text-danger-500 text-xl'>*</span> </label> <div className='flex flex-row gap-2'> <label @@ -609,7 +636,7 @@ const Dokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { 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' + ? 'Ubah Dokumen' : 'Upload Dokumen'} </label> <input @@ -647,7 +674,7 @@ const Dokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { 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' + ? 'Ubah Dokumen' : 'Upload Dokumen'} </label> <input @@ -683,7 +710,7 @@ const Dokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { 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' + ? 'Ubah Dokumen' : 'Upload Dokumen'} </label> <input @@ -724,7 +751,7 @@ const Dokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { 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' + ? 'Ubah Dokumen' : 'Upload Dokumen'} </label> <input @@ -758,7 +785,8 @@ const Dokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { > <label className='form-label text-nowrap'> KTP Dirut/Direktur{' '} - <span className=' opacity-60'>(Opsional)</span> + <span className=' opacity-60'>(Opsional)</span>{' '} + <span className='text-danger-500 text-xl'>*</span> </label> <div className='flex flex-row gap-2'> <label @@ -766,7 +794,7 @@ const Dokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { 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' + ? 'Ubah Dokumen' : 'Upload Dokumen'} </label> <input @@ -799,7 +827,8 @@ const Dokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { ref={dokumenAktaPendirianRef} > <label className='form-label text-nowrap'> - Akta Pendirian <span className=' opacity-60'>(Opsional)</span> + Akta Pendirian <span className=' opacity-60'>(Opsional)</span>{' '} + <span className='text-danger-500 text-xl'>*</span> </label> <div className='flex flex-row gap-2'> <label @@ -807,7 +836,7 @@ const Dokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { 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' + ? 'Ubah Dokumen' : 'Upload Dokumen'} </label> <input @@ -849,7 +878,7 @@ const Dokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { 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' + ? 'Ubah Dokumen' : 'Upload Dokumen'} </label> <input @@ -890,7 +919,7 @@ const Dokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { 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' + ? 'Ubah Dokumen' : 'Upload Dokumen'} </label> <input @@ -923,7 +952,7 @@ const Dokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { ref={dokumenTempatBekerjaRef} > <label className='form-label text-nowrap'> - Tempat Bekerja + Foto tempat kerja </label> <div className='flex flex-row gap-2'> <label @@ -931,7 +960,7 @@ const Dokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { 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' + ? 'Ubah Dokumen' : 'Upload Dokumen'} </label> <input @@ -961,6 +990,10 @@ const Dokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { </div> </form> <div className='w-full mt-8 flex gap-3 flex-col'> + <span className='opacity-75 text-danger-500 text-xs'> + *Jika anda ingin kredit limit lebih dari 25 Juta, harap lampirkan + dokumen yang diberi tanda bintang *) + </span> <div className='flex justify-between'> <p className='font-bold'>Upload Progress</p> <p> diff --git a/src/lib/pengajuan-tempo/component/FinishTempo.jsx b/src/lib/pengajuan-tempo/component/FinishTempo.jsx index ba28ab2a..933ede62 100644 --- a/src/lib/pengajuan-tempo/component/FinishTempo.jsx +++ b/src/lib/pengajuan-tempo/component/FinishTempo.jsx @@ -14,6 +14,7 @@ const FinishTempo = ({ query }) => { const [transactionData, setTransactionData] = useState(); const { isDesktop, isMobile } = useDevice(); const auth = useAuth(); + console.log('auth', auth); const so_order = query?.order_id?.replaceAll('-', '/'); useEffect(() => { const fetchData = async () => { @@ -62,6 +63,7 @@ const FinishTempo = ({ query }) => { 'Form Pengajuan Tempo Kamu Gagal Dilakukan'} {query?.status == 'review' && 'Pengajuan Tempo dalam Proses Verifikasi'} + {query?.status == 'approve' && 'Pengajuan Tempo Berhasil'} </h1> </div> {query?.status == 'finish' && ( @@ -88,6 +90,14 @@ const FinishTempo = ({ query }) => { height={isMobile ? 300 : 550} /> )} + {query?.status == 'approve' && ( + <Image + src='/images/ICON-WEBSITE-TELAH-MENDAFTAR-AKUN-TEMPO.svg' + alt='Registrasi Tempo' + width={isMobile ? 300 : 600} + height={isMobile ? 300 : 550} + /> + )} <div className={`mt-2 text-center opacity-75 leading-6 p-4 md:p-0 ${ @@ -100,6 +110,8 @@ const FinishTempo = ({ query }) => { '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'} {query?.status == 'review' && 'Proses pengajuan tempo anda saat ini sedang dalam tahapan proses verifikasi oleh tim indoteknik, mohon menunggu'} + {query?.status == 'approve' && + 'Proses pengajuan tempo anda sudah berhasil terdaftar di indoteknik.com. Nikmati pembelian anda di website indoteknik dengan menggunakan pembayaran tempo'} </div> <Link href={query?.status == 'switch-account' ? `/my/profile` : `/my/tempo/`} @@ -107,7 +119,9 @@ const FinishTempo = ({ query }) => { > {query?.status == 'switch-account' ? 'Ubah Akun' - : 'Lihat Status Pendaftaran'}{' '} + : query?.status == 'approve' + ? 'Lihat Detail Tempo' + : 'Lihat Status Pendaftaran'} <ChevronRightIcon className='w-5' /> </Link> </div> diff --git a/src/lib/pengajuan-tempo/component/KonfirmasiDokumen.jsx b/src/lib/pengajuan-tempo/component/KonfirmasiDokumen.jsx index c1f2d07c..e9ec01e1 100644 --- a/src/lib/pengajuan-tempo/component/KonfirmasiDokumen.jsx +++ b/src/lib/pengajuan-tempo/component/KonfirmasiDokumen.jsx @@ -9,6 +9,7 @@ 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'; +import imageCompression from 'browser-image-compression'; const KonfirmasiDokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { const { control, watch } = useForm(); const [isExample, setIsExample] = useState(false); @@ -16,6 +17,7 @@ const KonfirmasiDokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { const [base64, setBase64] = useState(); const [pdfData, setPdfData] = useState(); const [format, setFormat] = useState(); + const [url, setUrl] = useState(); const [popUpSource, setSource] = useState(); const { formDokumen, @@ -26,8 +28,12 @@ const KonfirmasiDokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { } = usePengajuanTempoStoreDokumen(); const handleConfirmSubmit = (format, base64) => { + console.log('format iman', format); if (format == 'pdf') { setFormat(`application/${format}`); + } else if (format == undefined) { + setFormat(null); + setUrl(`http://192.168.23.244:8069` + base64); } else { setFormat(`image/${format}`); } @@ -40,11 +46,13 @@ const KonfirmasiDokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { 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(); + 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', @@ -55,15 +63,34 @@ const KonfirmasiDokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { return; } - if (file.size > 2000000) { - toast.error('Maksimal ukuran file adalah 2MB', { duration: 4000 }); - - event.target.value = ''; - return; + // Check for file size + if (file.size > 500000) { + try { + const toastId = toast.loading('mencoba mengompresi file...'); + // Compress image file + const options = { + maxSizeMB: 0.5, // Target size in MB + maxWidthOrHeight: 1920, // Adjust as needed + useWebWorker: true, + }; + const compressedFile = await imageCompression(file, options); + toast.success('berhasil mengompresi file', { duration: 4000 }); + // Convert compressed file to Base64 + fileBase64 = await getFileBase64(compressedFile); + updateFormDokumen( + name, + compressedFile.name, + fileExtension, + fileBase64 + ); + } catch (error) { + toast.error('Gagal mengompresi file', { duration: 4000 }); + } + } else { + // Convert file to Base64 + fileBase64 = await getFileBase64(file); + updateFormDokumen(name, file.name, fileExtension, fileBase64); } - - fileBase64 = await getFileBase64(file); - updateFormDokumen(name, file.name, fileExtension, fileBase64); validateDokumen(); } }; @@ -145,6 +172,7 @@ const KonfirmasiDokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { useEffect(() => { validateDokumen(); }, [buttonSubmitClick]); + console.log('format', format); return ( <> {isDesktop && ( @@ -169,7 +197,7 @@ const KonfirmasiDokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { htmlFor='dokumenNib' className='cursor-pointer bg-red-500 hover:bg-red-600 text-white py-1 px-3 text-sm rounded min-w-20 text-center' > - Ubah + {formDokumen?.dokumenNib?.name ? 'Ubah' : 'Upload'} </label> <input // value={formDokumen?.dokumenNib?.name} @@ -220,7 +248,7 @@ const KonfirmasiDokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { htmlFor='dokumenNpwp' className='cursor-pointer bg-red-500 hover:bg-red-600 text-white py-1 px-3 text-sm rounded min-w-20 text-center' > - Ubah + {formDokumen?.dokumenNpwp?.name ? 'Ubah' : 'Upload'} </label> <input // value={formDokumen?.dokumenNib?.name} @@ -269,7 +297,9 @@ const KonfirmasiDokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { htmlFor='dokumenSppkp' className='cursor-pointer bg-red-500 hover:bg-red-600 text-white py-1 px-3 text-sm rounded min-w-20 text-center' > - Ubah + {formDokumen?.dokumenSppkp?.name.length > 0 + ? 'Ubah' + : 'Upload'} </label> <input // value={formDokumen?.dokumenNib?.name} @@ -323,8 +353,8 @@ const KonfirmasiDokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { className='cursor-pointer bg-red-500 hover:bg-red-600 text-white py-1 px-3 text-sm rounded min-w-20 text-center' > {formDokumen.dokumenAktaPerubahan.name - ? 'ubah' - : 'upload'} + ? 'Ubah' + : 'Upload'} </label> <input // value={formDokumen?.dokumenNib?.name} @@ -377,7 +407,7 @@ const KonfirmasiDokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { htmlFor='dokumenKtpDirut' className='cursor-pointer bg-red-500 hover:bg-red-600 text-white py-1 px-3 text-sm rounded min-w-20 text-center' > - Ubah + {formDokumen?.dokumenKtpDirut?.name ? 'Ubah' : 'Upload'} </label> <input // value={formDokumen?.dokumenNib?.name} @@ -429,7 +459,9 @@ const KonfirmasiDokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { htmlFor='dokumenAktaPendirian' className='cursor-pointer bg-red-500 hover:bg-red-600 text-white py-1 px-3 text-sm rounded min-w-20 text-center' > - Ubah + {formDokumen?.dokumenAktaPendirian?.name + ? 'Ubah' + : 'Upload'} </label> <input // value={formDokumen?.dokumenNib?.name} @@ -482,7 +514,9 @@ const KonfirmasiDokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { htmlFor='dokumenLaporanKeuangan' className='cursor-pointer bg-red-500 hover:bg-red-600 text-white py-1 px-3 text-sm rounded min-w-20 text-center' > - Ubah + {formDokumen?.dokumenLaporanKeuangan?.name + ? 'Ubah' + : 'Upload'} </label> <input // value={formDokumen?.dokumenNib?.name} @@ -534,7 +568,7 @@ const KonfirmasiDokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { htmlFor='dokumenFotoKantor' className='cursor-pointer bg-red-500 hover:bg-red-600 text-white py-1 px-3 text-sm rounded min-w-20 text-center' > - Ubah + {formDokumen?.dokumenFotoKantor?.name ? 'Ubah' : 'Upload'} </label> <input // value={formDokumen?.dokumenNib?.name} @@ -573,7 +607,7 @@ const KonfirmasiDokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { <div className='w-full flex flex-row items-center '> <div className='w-2/5'> <label className='form-label text-nowrap'> - Tempat Bekerja + Foto tempat kerja </label> </div> <div className='w-3/5'> @@ -586,7 +620,9 @@ const KonfirmasiDokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { htmlFor='dokumenTempatBekerja' className='cursor-pointer bg-red-500 hover:bg-red-600 text-white py-1 px-3 text-sm rounded min-w-20 text-center' > - Ubah + {formDokumen?.dokumenTempatBekerja?.name + ? 'Ubah' + : 'Upload'} </label> <input // value={formDokumen?.dokumenNib?.name} @@ -654,7 +690,7 @@ const KonfirmasiDokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { htmlFor='dokumenNib' className='cursor-pointer bg-red-500 hover:bg-red-600 text-white py-1 px-3 text-sm rounded min-w-20 text-center' > - Ubah + {formDokumen?.dokumenNib?.name ? 'Ubah' : 'Upload'} </label> <input // value={formDokumen?.dokumenNib?.name} @@ -703,7 +739,7 @@ const KonfirmasiDokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { htmlFor='dokumenNpwp' className='cursor-pointer bg-red-500 hover:bg-red-600 text-white py-1 px-3 text-sm rounded min-w-20 text-center' > - Ubah + {formDokumen?.dokumenNpwp?.name ? 'Sudah' : 'Upload'} </label> <input // value={formDokumen?.dokumenNib?.name} @@ -752,7 +788,7 @@ const KonfirmasiDokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { htmlFor='dokumenSppkp' className='cursor-pointer bg-red-500 hover:bg-red-600 text-white py-1 px-3 text-sm rounded min-w-20 text-center' > - Ubah + {formDokumen?.dokumenSppkp?.name ? 'Ubah' : 'Upload'} </label> <input // value={formDokumen?.dokumenNib?.name} @@ -805,7 +841,9 @@ const KonfirmasiDokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { htmlFor='dokumenAktaPerubahan' className='cursor-pointer bg-red-500 hover:bg-red-600 text-white py-1 px-3 text-sm rounded min-w-20 text-center' > - Ubah + {formDokumen?.dokumenAktaPerubahan?.name + ? 'Ubah' + : 'Upload'} </label> <input // value={formDokumen?.dokumenNib?.name} @@ -858,7 +896,7 @@ const KonfirmasiDokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { htmlFor='dokumenKtpDirut' className='cursor-pointer bg-red-500 hover:bg-red-600 text-white py-1 px-3 text-sm rounded min-w-20 text-center' > - Ubah + {formDokumen?.dokumenKtpDirut?.name ? 'Ubah' : 'Upload'} </label> <input // value={formDokumen?.dokumenNib?.name} @@ -910,7 +948,9 @@ const KonfirmasiDokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { htmlFor='dokumenAktaPendirian' className='cursor-pointer bg-red-500 hover:bg-red-600 text-white py-1 px-3 text-sm rounded min-w-20 text-center' > - Ubah + {formDokumen?.dokumenAktaPendirian?.name + ? 'Ubah' + : 'Upload'} </label> <input // value={formDokumen?.dokumenNib?.name} @@ -963,7 +1003,9 @@ const KonfirmasiDokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { htmlFor='dokumenLaporanKeuangan' className='cursor-pointer bg-red-500 hover:bg-red-600 text-white py-1 px-3 text-sm rounded min-w-20 text-center' > - Ubah + {formDokumen?.dokumenLaporanKeuangan?.name + ? 'Ubah' + : 'Upload'} </label> <input // value={formDokumen?.dokumenNib?.name} @@ -1015,7 +1057,7 @@ const KonfirmasiDokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { htmlFor='dokumenFotoKantor' className='cursor-pointer bg-red-500 hover:bg-red-600 text-white py-1 px-3 text-sm rounded min-w-20 text-center' > - Ubah + {formDokumen?.dokumenFotoKantor?.name ? 'Ubah' : 'Upload'} </label> <input // value={formDokumen?.dokumenNib?.name} @@ -1053,7 +1095,9 @@ const KonfirmasiDokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { <div className='w-full flex flex-row items-center '> <div className='w-2/5'> - <label className='form-label text-wrap'>Tempat Bekerja</label> + <label className='form-label text-wrap'> + Foto tempat kerja + </label> </div> <div className='w-3/5'> <div className='flex flex-row items-start justify-between'> @@ -1065,7 +1109,9 @@ const KonfirmasiDokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { htmlFor='dokumenTempatBekerja' className='cursor-pointer bg-red-500 hover:bg-red-600 text-white py-1 px-3 text-sm rounded min-w-20' > - Ubah + {formDokumen?.dokumenTempatBekerja?.name + ? 'Ubah' + : 'Upload'} </label> <input // value={formDokumen?.dokumenNib?.name} @@ -1113,16 +1159,20 @@ const KonfirmasiDokumen = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { )} {isDesktop && ( <BottomPopup - className='!container' + className='w-full h-full' title='Dokumen' active={isExample} close={() => setIsExample(false)} > <div className='flex justify-center items-center p-2'> <iframe - src={`data:${format};base64,${base64}`} - width='100%' - height='100%' + src={`${ + format == null ? url : `data:${format};base64,${base64}` + }`} + // src={`http://192.168.23.244:8069` + `${format}`} + // src={format} + width='800px' + height='600px' title='Document' ></iframe> </div> diff --git a/src/lib/pengajuan-tempo/component/KontakPerusahaan.jsx b/src/lib/pengajuan-tempo/component/KontakPerusahaan.jsx index e7bfdbbe..d5bb69fb 100644 --- a/src/lib/pengajuan-tempo/component/KontakPerusahaan.jsx +++ b/src/lib/pengajuan-tempo/component/KontakPerusahaan.jsx @@ -11,6 +11,7 @@ const KontakPerusahaan = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { const { isDesktop, isMobile } = useDevice(); const handleInputChange = (event) => { const { name, value } = event.target; + console.log('name', name, value); updateFormKontakPerson(name, value); validateKontakPerson(); }; @@ -84,6 +85,7 @@ const KontakPerusahaan = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { useEffect(() => { validateKontakPerson(); }, [buttonSubmitClick]); + console.log('formKontakPerson', formKontakPerson); return ( <> {isDesktop && ( @@ -93,24 +95,42 @@ const KontakPerusahaan = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { </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='flex flex-row justify-between items-start'> <div className='w-2/5'> - <label className='form-label text-nowrap'> + <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} - /> + <div className='flex items-center border border-gray-300 rounded-md'> + {/* Dropdown untuk memilih "Bpk" atau "Ibu" */} + <select + value={formKontakPerson.direkturTittle || ''} + id='direkturTittle' + name='direkturTittle' + className=' p-2 rounded-l-md' + onChange={handleInputChange} + > + <option value='' disabled> + Pilih + </option> + <option value='Bpk'>Bpk</option> + <option value='Ibu'>Ibu</option> + </select> + + {/* Input untuk nama */} + <input + value={formKontakPerson.direkturName} + id='direkturName' + name='direkturName' + placeholder='Masukkan nama direktur anda' + type='text' + className='form-input border-l border-r-0 border-t-0 border-b-0 border-gray-300 p-2 ml-2 flex-grow rounded-none' + aria-invalid={errorsKontakPerson.direkturName} + ref={direkturNameRef} + onChange={handleInputChange} + /> + </div> {chekValid && ( <div className='text-caption-2 text-danger-500 mt-1'> {errorsKontakPerson.direkturName} @@ -122,7 +142,8 @@ const KontakPerusahaan = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { <div className='flex flex-row justify-between items-start'> <div className='w-2/5'> <label className='form-label text-nowrap'> - No. Telpon Direktur + No. HP Direktur{' '} + <span className=' opacity-60'>(Opsional)</span> </label> {!isKonfirmasi && ( <span className='text-xs opacity-60'> @@ -194,17 +215,32 @@ const KontakPerusahaan = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { )} </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} - /> + <div className='flex items-center border border-gray-300 rounded-md'> + <select + value={formKontakPerson.purchasingTittle || ''} + id='purchasingTittle' + name='purchasingTittle' + className=' p-2 rounded-l-md' + onChange={handleInputChange} + > + <option value='' disabled> + Pilih + </option> + <option value='Bpk'>Bpk</option> + <option value='Ibu'>Ibu</option> + </select> + <input + id='purchasingName' + name='purchasingName' + ref={purchasingNameRef} + placeholder='Masukkan nama purchasing anda' + value={formKontakPerson.purchasingName} + type='text' + className='form-input border-l border-r-0 border-t-0 border-b-0 border-gray-300 p-2 ml-2 flex-grow rounded-none' + aria-invalid={errorsKontakPerson.purchasingName} + onChange={handleInputChange} + /> + </div> {chekValid && ( <div className='text-caption-2 text-danger-500 mt-1'> {errorsKontakPerson.purchasingName} @@ -216,7 +252,7 @@ const KontakPerusahaan = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { <div className='flex flex-row justify-between items-start'> <div className='w-2/5'> <label className='form-label text-nowrap'> - No. Telpon Purchasing + No. HP Purchasing </label> {!isKonfirmasi && ( <span className='text-xs opacity-60'> @@ -288,17 +324,32 @@ const KontakPerusahaan = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { )} </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} - /> + <div className='flex items-center border border-gray-300 rounded-md'> + <select + value={formKontakPerson.financeTittle || ''} + id='financeTittle' + name='financeTittle' + className=' p-2 rounded-l-md' + onChange={handleInputChange} + > + <option value='' disabled> + Pilih + </option> + <option value='Bpk'>Bpk</option> + <option value='Ibu'>Ibu</option> + </select> + <input + id='financeName' + name='financeName' + ref={financeNameRef} + placeholder='Masukkan nama finance' + value={formKontakPerson.financeName} + type='text' + className='form-input border-l border-r-0 border-t-0 border-b-0 border-gray-300 p-2 ml-2 flex-grow rounded-none' + aria-invalid={errorsKontakPerson.financeName} + onChange={handleInputChange} + /> + </div> {chekValid && ( <div className='text-caption-2 text-danger-500 mt-1'> {errorsKontakPerson.financeName} @@ -309,7 +360,7 @@ const KontakPerusahaan = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { <div className='flex flex-row justify-between items-start'> <div className='w-2/5'> <label className='form-label text-nowrap'> - No. Telpon Finance + No. HP Finance </label> {!isKonfirmasi && ( <span className='text-xs opacity-60'> @@ -387,17 +438,32 @@ const KontakPerusahaan = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { <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} - /> + <div className='flex items-center border border-gray-300 rounded-md w-full'> + <select + value={formKontakPerson.direkturTittle || ''} + id='direkturTittle' + name='direkturTittle' + className=' p-2 rounded-l-md' + onChange={handleInputChange} + > + <option value='' disabled> + Pilih + </option> + <option value='Bpk'>Bpk</option> + <option value='Ibu'>Ibu</option> + </select> + <input + value={formKontakPerson.direkturName} + id='direkturName' + name='direkturName' + placeholder='Masukkan nama direktur anda' + type='text' + className='form-input border-l border-r-0 border-t-0 border-b-0 border-gray-300 p-2 ml-2 flex-grow rounded-none' + aria-invalid={errorsKontakPerson.direkturName} + ref={direkturNameRef} + onChange={handleInputChange} + /> + </div> {chekValid && ( <div className='text-caption-2 text-danger-500 mt-1'> {errorsKontakPerson.direkturName} @@ -407,7 +473,8 @@ const KontakPerusahaan = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { <div className='flex flex-col gap-2 justify-between items-start'> <label className='form-label text-nowrap'> - No. Telpon Direktur + No. HP Direktur{' '} + <span className=' opacity-60'>(Opsional)</span> </label> <input id='direkturMobile' @@ -453,17 +520,32 @@ const KontakPerusahaan = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { <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} - /> + <div className='flex items-center border border-gray-300 rounded-md w-full'> + <select + value={formKontakPerson.purchasingTittle || ''} + id='purchasingTittle' + name='purchasingTittle' + className=' p-2 rounded-l-md' + onChange={handleInputChange} + > + <option value='' disabled> + Pilih + </option> + <option value='Bpk'>Bpk</option> + <option value='Ibu'>Ibu</option> + </select> + <input + id='purchasingName' + name='purchasingName' + ref={purchasingNameRef} + placeholder='Masukkan nama purchasing anda' + value={formKontakPerson.purchasingName} + type='text' + className='form-input border-l border-r-0 border-t-0 border-b-0 border-gray-300 p-2 ml-2 flex-grow rounded-none' + aria-invalid={errorsKontakPerson.purchasingName} + onChange={handleInputChange} + /> + </div> {chekValid && ( <div className='text-caption-2 text-danger-500 mt-1'> {errorsKontakPerson.purchasingName} @@ -473,7 +555,7 @@ const KontakPerusahaan = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { <div className='flex flex-col gap-2 justify-between items-start'> <label className='form-label text-nowrap'> - No. Telpon Purchasing + No. HP Purchasing </label> <input id='purchasingMobile' @@ -517,17 +599,32 @@ const KontakPerusahaan = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { <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} - /> + <div className='flex items-center border border-gray-300 rounded-md w-full'> + <select + value={formKontakPerson.financeTittle || ''} + id='financeTittle' + name='financeTittle' + className=' p-2 rounded-l-md' + onChange={handleInputChange} + > + <option value='' disabled> + Pilih + </option> + <option value='Bpk'>Bpk</option> + <option value='Ibu'>Ibu</option> + </select> + <input + id='financeName' + name='financeName' + ref={financeNameRef} + placeholder='Masukkan nama finance' + value={formKontakPerson.financeName} + type='text' + className='form-input border-l border-r-0 border-t-0 border-b-0 border-gray-300 p-2 ml-2 flex-grow rounded-none' + aria-invalid={errorsKontakPerson.financeName} + onChange={handleInputChange} + /> + </div> {chekValid && ( <div className='text-caption-2 text-danger-500 mt-1'> {errorsKontakPerson.financeName} @@ -536,7 +633,7 @@ const KontakPerusahaan = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { </div> <div className='flex flex-col gap-2 justify-between items-start'> <label className='form-label text-nowrap'> - No. Telpon Finance + No. HP Finance </label> <input id='financeMobile' diff --git a/src/lib/pengajuan-tempo/component/PengajuanTempo.jsx b/src/lib/pengajuan-tempo/component/PengajuanTempo.jsx index 1704556e..82b64df7 100644 --- a/src/lib/pengajuan-tempo/component/PengajuanTempo.jsx +++ b/src/lib/pengajuan-tempo/component/PengajuanTempo.jsx @@ -27,6 +27,8 @@ import { toast } from 'react-hot-toast'; import useDevice from '@/core/hooks/useDevice'; import odooApi from '~/libs/odooApi'; import editAuthTempo from '../api/editAuthTempo'; +import BottomPopup from '@/core/components/elements/Popup/BottomPopup'; +import PageContent from '@/lib/content/components/PageContent'; const PengajuanTempo = () => { const { isDesktop, isMobile } = useDevice(); const [currentStep, setCurrentStep] = React.useState(0); @@ -137,7 +139,7 @@ const PengajuanTempo = () => { validateKontakPerson(); validatePengiriman(); validateDokumen(); - updateHasSave(false); + updateHasSave(true); if (isFormValid) { window.scrollTo({ top: 0, @@ -175,7 +177,8 @@ const PengajuanTempo = () => { 'GET', `/api/v1/partner/detail-tempo/${auth.parentId}` ); - + console.log('original data', dataPaymentTerm); + const transformedData = transformKeysToCamelCase(dataPaymentTerm); setBigData(transformedData); } catch (error) { console.error('Error loading dataPaymentTerm:', error); @@ -213,6 +216,7 @@ const PengajuanTempo = () => { ? JSON.stringify(bigData[key]) // Untuk objek atau array : String(bigData[key]); // Untuk tipe primitif // Kirim data yang sudah diubah ke string ke stepDivsUpdateForm + console.log('key', key, stringData); stepDivsUpdateForm[currentStep](key, stringData); } }); @@ -225,7 +229,7 @@ const PengajuanTempo = () => { validatePengiriman(); validateDokumen(); validateSupplier(); - updateHasSave(false); + updateHasSave(true); }, [currentStep, bigData, auth]); const goToNextStep = () => { @@ -291,15 +295,25 @@ const PengajuanTempo = () => { return; } } - const formattedDokumen = Object.entries(formDokumen).map(([key, doc]) => ({ - documentName: key, - details: { - name: doc.name, - format: doc.format, - base64: doc.base64, - }, - })); + + // Filter hanya dokumen dengan `format` yang tidak undefined + const formattedDokumen = Object.entries(formDokumen) + .filter(([_, doc]) => doc.format !== undefined) // Hanya dokumen dengan `format` tidak undefined + .map(([key, doc]) => ({ + documentName: key, + details: { + name: doc.name, + format: doc.format, + base64: doc.base64, + }, + })); + const toastId = toast.loading('Mengirimkan formulir pengajuan tempo...'); + if (formattedDokumen.length === 0) { + // toast.error('Tidak ada dokumen valid untuk dikirim.'); + return; + } + setIsLoading(true); try { const address = await createPengajuanTempoApi({ @@ -321,12 +335,30 @@ const PengajuanTempo = () => { console.error(error); } }; + + const isSupplierDataChanged = (formSupplier, supplierIds) => { + if (formSupplier.length !== supplierIds.length) { + return true; + } + return formSupplier.some((supplier, index) => { + const original = supplierIds[index]; + return ( + supplier.supplier !== original.supplier || + supplier.pic !== original.pic || + supplier.telepon !== original.telepon || + supplier.durasiTempo !== original.durasiTempo || + supplier.creditLimit !== original.creditLimit + ); + }); + }; + const handleDaftarTempoSupplier = async () => { for (const error of stepDivsError) { if (error.length > 0) { return; } } + const productOrder = formSupplier.map((product) => ({ supplier: product.supplier, pic: product.pic, @@ -334,7 +366,13 @@ const PengajuanTempo = () => { durasiTempo: product.durasiTempo, creditLimit: product.creditLimit, })); + + // Periksa perubahan const toastId = toast.loading('Mengirimkan formulir pengajuan tempo...'); + if (!isSupplierDataChanged(productOrder, bigData.supplierIds)) { + return; + } + setIsLoading(true); try { const address = await createPengajuanTempoApi({ @@ -363,35 +401,23 @@ const PengajuanTempo = () => { 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, - }, - })); + // Filter hanya dokumen dengan `format` yang tidak undefined + const formattedDokumen = Object.entries(formDokumen) + .filter(([_, doc]) => doc.format !== undefined) // Hanya dokumen dengan `format` tidak undefined + .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; + let address4; const address = await createPengajuanTempoApi({ id: 0, partner_id: auth.partnerId, @@ -415,37 +441,29 @@ const PengajuanTempo = () => { tempo_request: false, ...formPengiriman, }); - if (address3.id) { - const address4 = await createPengajuanTempoApi({ + if (address3.id && formattedDokumen.length > 0) { + // Kirim dokumen yang sudah difilter + address4 = await createPengajuanTempoApi({ id: address3.id, partner_id: auth.partnerId, user_id: address3.userId, - tempo_request: false, + tempo_request: true, formDocs: JSON.stringify(formattedDokumen), }); - if (address4.id) { - address5 = await createPengajuanTempoApi({ - id: address4.id, - partner_id: auth.partnerId, - user_id: address4.userId, - tempo_request: true, - formSupplier: JSON.stringify(productOrder), - }); - } } } } - if (address5.id) { + if (address4?.id) { const isUpdated = await editAuthTempo(); toast.dismiss(toastId); - setIsLoading(false); - toast.success('Pengajuan tempo berhasil dilakukan'); if (isUpdated?.user) { setAuth(isUpdated.user); + setIsLoading(false); + toast.success('Pengajuan tempo berhasil dilakukan'); toast.success('Berhasil mengubah status akun', { duration: 1000 }); removeFromLocalStorage(); - router.push('/pengajuan-tempo/finish?tempo_id=SO-2023-06480'); + router.push('/pengajuan-tempo/finish'); return; } } @@ -479,6 +497,14 @@ const PengajuanTempo = () => { } }; + const [isCheckedTNC, setIsCheckedTNC] = useState(false); + + const handleCheckChange = (checked) => { + setIsCheckedTNC(checked); + }; + console.log('formSupplier', formSupplier); + console.log('!hassavedata', hasSavedata); + console.log('isCheckedTNC', isCheckedTNC); return ( <> <div className='container flex flex-col items-center '> @@ -507,45 +533,102 @@ const PengajuanTempo = () => { className={`flex ${ isMobile ? 'flex-col justify-start items-start' - : 'flex-row justify-end items-center' - } gap-4 mb-8`} + : 'flex-col justify-end items-end' + } mb-8 gap-2`} > <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, - })} - > + <> + <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 && ( + <div className='flex flex-col items-end justify-start gap-4'> + <TempoTermCondition onCheckChange={handleCheckChange} /> <Button colorScheme='red' - w={`${isMobile ? 'full' : 'fit'}`} - isDisabled={ - (currentStep === 3 && !hasSavedata) || - currentStep === NUMBER_OF_STEPS - 1 - } - onClick={goToNextStep} + w={`${isMobile ? 'full' : '36'}`} + isDisabled={!isCheckedTNC} + onClick={handleDaftarTempo} > - Langkah Selanjutnya {<ChevronRightIcon className='w-5' />} + Daftar Tempo {<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> </div> </> ); }; +const TempoTermCondition = ({ onCheckChange }) => { + const [isCheckedTNC, SetIsCheckedTNC] = useState(false); + const [openTNC, SetOpenTNC] = useState(false); + + const openTNCHandle = () => { + SetOpenTNC(!openTNC); + }; + + const toggleCheckTNC = () => { + const newValue = !isCheckedTNC; + SetIsCheckedTNC(newValue); + if (onCheckChange) { + onCheckChange(newValue); + } + }; + return ( + <> + <div className='flex items-center gap-x-2'> + <Checkbox + id='tnc' + name='tnc' + colorScheme='red' + isChecked={isCheckedTNC} + onChange={toggleCheckTNC} + /> + <div> + <label htmlFor='tnc' className='cursor-pointer'> + Dengan ini saya menyetujui + </label>{' '} + <span + className='font-medium text-danger-500 cursor-pointer' + onClick={openTNCHandle} + > + syarat dan ketentuan + </span> + <label htmlFor='tnc' className='ml-2 cursor-pointer'> + yang berlaku + </label> + </div> + </div> + + <BottomPopup + active={openTNC} + close={() => SetOpenTNC(false)} + title='Syarat & Ketentuan Pendaftaran Tempo' + > + <PageContent path='/tempoTnd' /> + </BottomPopup> + </> + ); +}; export default PengajuanTempo; diff --git a/src/lib/pengajuan-tempo/component/Pengiriman.jsx b/src/lib/pengajuan-tempo/component/Pengiriman.jsx index 8b8961c5..0352b54f 100644 --- a/src/lib/pengajuan-tempo/component/Pengiriman.jsx +++ b/src/lib/pengajuan-tempo/component/Pengiriman.jsx @@ -9,7 +9,7 @@ import { usePengajuanTempoStorePengiriman, usePengajuanTempoStore, } from '../../../../src-migrate/modules/register/stores/usePengajuanTempoStore'; - +import { toast } from 'react-hot-toast'; import useDevice from '@/core/hooks/useDevice'; const Pengiriman = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { const { control, watch, setValue } = useForm(); @@ -102,7 +102,7 @@ const Pengiriman = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { const watchState = watch('statePengiriman'); useEffect(() => { - updateFormPengiriman('cityPengiriman', ''); + // updateFormPengiriman('cityPengiriman', ''); if (watchState) { updateFormPengiriman('statePengiriman', `${watchState}`); validatePengiriman(); @@ -352,35 +352,63 @@ const Pengiriman = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { if (sameAddress) { updateFormPengiriman('streetInvoice', formPengiriman.streetPengiriman); updateFormPengiriman('stateInvoice', formPengiriman.statePengiriman); + setValue('stateInvoice', parseInt(formPengiriman.statePengiriman)); updateFormPengiriman('cityInvoice', formPengiriman.cityPengiriman); + setValue('cityInvoice', parseInt(formPengiriman.cityPengiriman)); + updateFormPengiriman('isSameAddrees', `${sameAddress}`); } else { - updateFormPengiriman('streetInvoice', ''); - updateFormPengiriman('stateInvoice', ''); - updateFormPengiriman('cityInvoice', ''); - setValue('streetInvoice', ''); - setValue('stateInvoice', ''); - setValue('cityInvoice', ''); + // updateFormPengiriman('streetInvoice', ''); + // updateFormPengiriman('stateInvoice', ''); + // updateFormPengiriman('cityInvoice', ''); + // setValue('streetInvoice', ''); + // setValue('stateInvoice', ''); + // setValue('cityInvoice', ''); } - updateFormPengiriman('isSameAddrees', `${sameAddress}`); validatePengiriman(); - }, [sameAddress]); + }, [ + sameAddress, + formPengiriman.streetPengiriman, + formPengiriman.statePengiriman, + formPengiriman.cityPengiriman, + ]); + useEffect(() => { + if (formPengiriman.sameAddressStreet?.toLowerCase().includes('true')) { + setSameAddressStreet(true); + } else { + setSameAddressStreet(false); + } + }, [formPengiriman.sameAddressStreet]); + useEffect(() => { + if (formPengiriman.statePengiriman) { + setValue('statePengiriman', parseInt(formPengiriman.statePengiriman)); + } + }, [formPengiriman.statePengiriman]); + useEffect(() => { + if (formPengiriman.cityPengiriman) { + setValue('cityPengiriman', parseInt(formPengiriman.cityPengiriman)); + } + }, [formPengiriman.cityPengiriman]); useEffect(() => { if (sameAddressStreet) { + console.log('form.state', form); updateFormPengiriman('streetPengiriman', form.street); updateFormPengiriman('statePengiriman', form.state); + setValue('statePengiriman', parseInt(form.state)); updateFormPengiriman('cityPengiriman', form.city); + setValue('cityPengiriman', parseInt(form.city)); updateFormPengiriman('zipPengiriman', form.zip); - } else { - updateFormPengiriman('streetPengiriman', ''); - updateFormPengiriman('statePengiriman', ''); - updateFormPengiriman('cityPengiriman', ''); - updateFormPengiriman('zipPengiriman', ''); - setValue('streetPengiriman', ''); - setValue('statePengiriman', ''); - setValue('cityPengiriman', ''); + updateFormPengiriman('isSameAddreesStreet', `${sameAddressStreet}`); } - updateFormPengiriman('isSameAddreesStreet', `${sameAddressStreet}`); + // else { + // updateFormPengiriman('streetPengiriman', ''); + // updateFormPengiriman('statePengiriman', ''); + // updateFormPengiriman('cityPengiriman', ''); + // updateFormPengiriman('zipPengiriman', ''); + // setValue('streetPengiriman', ''); + // setValue('statePengiriman', ''); + // setValue('cityPengiriman', ''); + // } validatePengiriman(); }, [sameAddressStreet]); @@ -459,8 +487,70 @@ const Pengiriman = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { setSameAddress(!sameAddress); }; const handleChangeSameAddressStreet = () => { + // updateFormPengiriman('sameAddressStreet', `${!sameAddressStreet}`); setSameAddressStreet(!sameAddressStreet); + if (sameAddressStreet == false) { + updateFormPengiriman('streetPengiriman', ''); + updateFormPengiriman('statePengiriman', ''); + updateFormPengiriman('cityPengiriman', ''); + updateFormPengiriman('zipPengiriman', ''); + setValue('streetPengiriman', ''); + setValue('statePengiriman', ''); + setValue('cityPengiriman', ''); + updateFormPengiriman('isSameAddreesStreet', `${sameAddressStreet}`); + validate(); + } }; + + useEffect(() => { + const options = { + behavior: 'smooth', + block: 'center', + }; + + const loadIndustries = async () => { + const watchZip = formPengiriman.zipPengiriman?.trim(); // Menghapus spasi berlebih + + // Validasi: hanya eksekusi jika watchZip valid (contoh: minimal 5 karakter) + if (watchZip && watchZip.length >= 5) { + const loadZip = async () => { + try { + const response = await fetch( + `https://alamat.thecloudalert.com/api/cari/index/?keyword=${watchZip}` + ); + + const result = await response.json(); + + if (!result.result.length > 0) { + toast.error('Alamat pos salah'); + updateFormPengiriman('zipPengiriman', ''); // Reset form.zip jika salah + validate(); // Memanggil validasi formulir + return false; + } else { + updateFormPengiriman('zipPengiriman', watchZip); + validate(); + return true; // Jika valid + } + } catch (error) { + toast.error('Terjadi kesalahan saat memeriksa alamat pos.'); + console.error('Error:', error); + return false; + } + }; + + const isValidZip = await loadZip(); + if (!isValidZip) { + zipRef.current.scrollIntoView(options); + } + } + }; + + loadIndustries(); + }, [formPengiriman.zipPengiriman]); + + console.log('formPengiriman', formPengiriman); + console.log('errorsPengiriman', errorsPengiriman); + return ( <> {isDesktop && ( @@ -477,18 +567,33 @@ const Pengiriman = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { </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} - aria-label='PICName' - onChange={handleInputChange} - /> + <div className='flex items-center border border-gray-300 rounded-md'> + <select + value={formPengiriman.PICTittle || ''} + id='PICTittle' + name='PICTittle' + className=' p-2 rounded-l-md' + onChange={handleInputChange} + > + <option value='' disabled> + Pilih + </option> + <option value='Bpk'>Bpk</option> + <option value='Ibu'>Ibu</option> + </select> + <input + value={formPengiriman.PICName} + id='PICName' + name='PICName' + placeholder='Masukkan nama pic penerimaan barang disini' + type='text' + className='form-input border-l border-r-0 border-t-0 border-b-0 border-gray-300 p-2 ml-2 flex-grow rounded-none' + aria-invalid={errorsPengiriman.PICName} + ref={PICNameRef} + aria-label='PICName' + onChange={handleInputChange} + /> + </div> {chekValid && ( <div className='text-caption-2 text-danger-500 mt-1'> {errorsPengiriman.PICName} @@ -515,92 +620,95 @@ const Pengiriman = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { isChecked={sameAddressStreet} onChange={handleChangeSameAddressStreet} > - Alamat Pengiriman sama dengan alamat pengiriman + Alamat Pengiriman sama dengan alamat bisnis </Checkbox> - {!sameAddressStreet && ( - <> - <div> + + <> + <div> + <input + id='streetPengiriman' + name='streetPengiriman' + ref={streetPengirimanRef} + aria-label='streetPengiriman' + placeholder='Masukkan alamat lengkap pengiriman barang' + type='text' + value={formPengiriman.streetPengiriman} + className='form-input' + onChange={handleInputChange} + disabled={sameAddressStreet} + /> + {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} + aria-label='statePengiriman' + > + <Controller + name='statePengiriman' + control={control} + render={(props) => ( + <HookFormSelect + {...props} + disabled={sameAddressStreet} + 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' + aria-label='cityPengiriman' + disabled={sameAddressStreet} + control={control} + render={(props) => ( + <HookFormSelect + {...props} + options={cities} + disabled={!watchState || sameAddressStreet} + placeholder='Kota' + /> + )} + /> + {chekValid && ( + <div className='text-caption-2 text-danger-500 mt-1'> + {errorsPengiriman.cityPengiriman} + </div> + )} + </div> + <div className='w-1/3'> <input - id='streetPengiriman' - name='streetPengiriman' - ref={streetPengirimanRef} - aria-label='streetPengiriman' - placeholder='Masukkan alamat lengkap pengiriman barang' - type='text' - value={formPengiriman.streetPengiriman} + id='zipPengiriman' + aria-label='zipPengiriman' + disabled={sameAddressStreet} + 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.streetPengiriman} + {errorsPengiriman.zipPengiriman} </div> )} </div> - <div className='sub-alamat flex flex-row w-full gap-3'> - <div - className='w-2/5' - ref={statePengirimanRef} - aria-label='statePengiriman' - > - <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' - aria-label='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' - aria-label='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> @@ -611,18 +719,33 @@ const Pengiriman = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { </label> </div> <div className='w-3/5'> - <input - value={formPengiriman.invoicePic} - id='invoicePic' - name='invoicePic' - aria-label='invoicePic' - placeholder='Masukkan nama pic invoice disini' - type='text' - className='form-input' - aria-invalid={errorsPengiriman.invoicePic} - ref={invoicePicRef} - onChange={handleInputChange} - /> + <div className='flex items-center border border-gray-300 rounded-md'> + <select + value={formPengiriman.invoicePicTittle || ''} + id='invoicePicTittle' + name='invoicePicTittle' + className=' p-2 rounded-l-md' + onChange={handleInputChange} + > + <option value='' disabled> + Pilih + </option> + <option value='Bpk'>Bpk</option> + <option value='Ibu'>Ibu</option> + </select> + <input + value={formPengiriman.invoicePic} + id='invoicePic' + name='invoicePic' + aria-label='invoicePic' + placeholder='Masukkan nama pic invoice disini' + type='text' + className='form-input border-l border-r-0 border-t-0 border-b-0 border-gray-300 p-2 ml-2 flex-grow rounded-none' + aria-invalid={errorsPengiriman.invoicePic} + ref={invoicePicRef} + onChange={handleInputChange} + /> + </div> {chekValid && ( <div className='text-caption-2 text-danger-500 mt-1'> {errorsPengiriman.invoicePic} @@ -653,75 +776,76 @@ const Pengiriman = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { Alamat invoice sama dengan alamat pengiriman </Checkbox> </div> - {!sameAddress && ( - <> - <div> - <input - id='streetInvoice' - name='streetInvoice' - aria-label='streetInvoice' - ref={streetInvoiceRef} - placeholder='Masukkan alamat lengkap pengiriman invoice' - type='text' - value={formPengiriman.streetInvoice} - className='form-input' - onChange={handleInputChange} + + <> + <div> + <input + id='streetInvoice' + name='streetInvoice' + aria-label='streetInvoice' + ref={streetInvoiceRef} + disabled={sameAddress} + 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} + aria-label='stateInvoice' + > + <Controller + name='stateInvoice' + control={control} + render={(props) => ( + <HookFormSelect + {...props} + options={states} + disabled={sameAddress} + placeholder='Provinsi' + /> + )} /> {chekValid && ( <div className='text-caption-2 text-danger-500 mt-1'> - {errorsPengiriman.streetInvoice} + {errorsPengiriman.stateInvoice} </div> )} </div> - <div className='sub-alamat flex flex-row w-full gap-3'> - <div - className='w-3/5' - ref={stateInvoiceRef} - aria-label='stateInvoice' - > - <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} - aria-label='cityInvoice' - > - <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 + className='w-2/5' + ref={cityInvoiceRef} + aria-label='cityInvoice' + > + <Controller + name='cityInvoice' + control={control} + render={(props) => ( + <HookFormSelect + {...props} + options={cities} + disabled={!watchState || sameAddress} + placeholder='Kota' + /> )} - </div> + /> + {chekValid && ( + <div className='text-caption-2 text-danger-500 mt-1'> + {errorsPengiriman.cityInvoice} + </div> + )} </div> - </> - )} + </div> + </> </div> </div> @@ -738,59 +862,17 @@ const Pengiriman = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { )} </div> <div className='w-3/5 flex gap-3 flex-col'> - <RadioGroup - onChange={handleRadioChange} - value={selectedRadio} - > - <div className='flex gap-3 flex-col'> - <Radio value='everyWeekday' colorScheme='red'> - Setiap Minggu di hari - </Radio> - <input - id='everyWeekdayInput' - aria-label='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'> - <Radio value='everyWeek' colorScheme='red'> - Setiap Bulan di minggu ke - </Radio> - <input - id='everyWeekInput' - aria-label='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'> - <Radio value='tukarInvoice' colorScheme='red'> - Lainnya - </Radio> - <textarea - id='tukarInvoiceInput' - name='tukarInvoiceInput' - aria-label='tukarInvoiceInput' - placeholder='Isi manual dokumen yang anda mau' - value={formPengiriman.tukarInvoiceInput} - className='form-input' - rows={4} - cols={40} - onChange={handleInputChange} - /> - </div> - </RadioGroup> + <textarea + id='tukarInvoiceInput' + name='tukarInvoiceInput' + aria-label='tukarInvoiceInput' + placeholder='Masukkan jadwal penukaran invoice' + value={formPengiriman.tukarInvoiceInput} + className='form-input' + rows={4} + cols={40} + onChange={handleInputChange} + /> </div> </div> @@ -807,65 +889,29 @@ const Pengiriman = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { )} </div> <div className='w-3/5 flex gap-3 flex-col'> - <RadioGroup - onChange={handleRadioChangeInvoice} - value={selectedRadioInvoice} - > - <div className='flex gap-3 flex-col'> - <Radio value='everyWeekdayPembayaran' colorScheme='red'> - Setiap Minggu di hari - </Radio> - <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'> - <Radio value='everyWeekPembayaran' colorScheme='red'> - Setiap Bulan di minggu ke - </Radio> - <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'> - <Radio value='tukarInvoicePembayaran' colorScheme='red'> - Lainnya - </Radio> - <textarea - id='tukarInvoiceInputPembayaran' - name='tukarInvoiceInputPembayaran' - placeholder='isi manual dokumen yang anda mau' - value={formPengiriman.tukarInvoiceInputPembayaran} - className='form-input' - rows={4} - cols={40} - onChange={handleInputChange} - /> - </div> - </RadioGroup> + <textarea + id='tukarInvoiceInputPembayaran' + name='tukarInvoiceInputPembayaran' + placeholder='Masukkan jadwal pembayaran' + value={formPengiriman.tukarInvoiceInputPembayaran} + className='form-input' + rows={4} + cols={40} + onChange={handleInputChange} + /> </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 + Apakah ada dokumen tanda terima yang diberikan pada saat + pengiriman barang?{' '} + <span className=' opacity-60'>(Opsional)</span> </label> {!isKonfirmasi && ( <span className='text-xs opacity-60'> - Pilih dokumen lampiran saat pengiriman barang + Pilih dokumen tanda terima saat pengiriman barang jika ada </span> )} </div> @@ -907,7 +953,7 @@ const Pengiriman = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { Lembar Penerimaan Barang (LPB) </Checkbox> - <div className='flex gap-3 flex-col'> + {/* <div className='flex gap-3 flex-col'> <Checkbox colorScheme='red' key='4' @@ -929,7 +975,41 @@ const Pengiriman = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { cols={40} onChange={handleInputChange} /> - </div> + </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 saat Pengiriman Barang{' '} + <span className=' opacity-60'>(Opsional)</span> + </label> + {!isKonfirmasi && ( + <span className='text-xs opacity-60'> + Dokumen lampiran saat pengiriman barang + </span> + )} + </div> + <div className='flex gap-3 flex-col w-3/5 '> + <textarea + id='dokumenPengirimanInput' + name='dokumenPengirimanInput' + aria-label='dokumenPengirimanInput' + placeholder='isi manual dokumen yang anda mau' + type='textarea' + ref={dokumenPengirimanInputRef} + value={formPengiriman.dokumenPengirimanInput} + className='form-input' + rows={4} + cols={40} + onChange={handleInputChange} + /> {chekValid && ( <div className='text-caption-2 text-danger-500 mt-1'> {errorsPengiriman.dokumenPengiriman} @@ -941,93 +1021,27 @@ const Pengiriman = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { <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 + Dokumen yang dilampirkan saat Pengiriman Invoice{' '} + <span className=' opacity-60'>(Opsional)</span> </label> <span className='text-xs opacity-60'> - Dokumen akan dikirimkan sesuai dengan yang anda pilih + Dokumen lampiran saat pengiriman invoice </span> </div> - <div - className='w-3/5 flex gap-3 flex-col' - ref={dokumenPengirimanInvoiceRef} - name='dokumenPengirimanInvoiceInput' - > - <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' - aria-label='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> + <div className='flex gap-3 flex-col w-3/5'> + <textarea + id='dokumenPengirimanInvoice' + aria-label='dokumenPengirimanInvoice' + name='dokumenPengirimanInvoice' + placeholder='isi manual dokumen yang anda mau' + type='textarea' + ref={dokumenPengirimanInvoiceRef} + value={formPengiriman.dokumenPengirimanInvoice} + className='form-input' + rows={4} + cols={40} + onChange={handleInputChange} + /> {chekValid && ( <div className='text-caption-2 text-danger-500 mt-1'> {errorsPengiriman.dokumenPengirimanInvoice} @@ -1054,18 +1068,33 @@ const Pengiriman = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { <label className='form-label text-nowrap'> Nama PIC Penerimaan Barang </label> - <input - value={formPengiriman.PICName} - id='PICName' - name='PICName' - aria-label='PICName' - placeholder='Masukkan nama pic pengiriman disini' - type='text' - className='form-input' - aria-invalid={errorsPengiriman.PICName} - ref={PICNameRef} - onChange={handleInputChange} - /> + <div className='flex items-center border border-gray-300 rounded-md w-full'> + <select + value={formPengiriman.PICTittle || ''} + id='PICTittle' + name='PICTittle' + className=' p-2 rounded-l-md' + onChange={handleInputChange} + > + <option value='' disabled> + Pilih + </option> + <option value='Bpk'>Bpk</option> + <option value='Ibu'>Ibu</option> + </select> + <input + value={formPengiriman.PICName} + id='PICName' + name='PICName' + aria-label='PICName' + placeholder='Masukkan nama pic penerima barang disini' + type='text' + className='form-input border-l border-r-0 border-t-0 border-b-0 border-gray-300 p-2 ml-2 flex-grow rounded-none' + aria-invalid={errorsPengiriman.PICName} + ref={PICNameRef} + onChange={handleInputChange} + /> + </div> {chekValid && ( <div className='text-caption-2 text-danger-500 mt-1'> {errorsPengiriman.PICName} @@ -1077,12 +1106,21 @@ const Pengiriman = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { <label className='form-label text-nowrap'> Alamat Pengiriman Barang </label> + <Checkbox + colorScheme='red' + isChecked={sameAddressStreet} + onChange={handleChangeSameAddressStreet} + size='sm' + > + Alamat Pengiriman sama dengan alamat bisnis + </Checkbox> <div className='w-full'> <input id='streetPengiriman' name='streetPengiriman' aria-label='streetPengiriman' ref={streetPengirimanRef} + disabled={sameAddressStreet} placeholder='Masukkan alamat lengkap pengiriman barang' type='text' value={formPengiriman.streetPengiriman} @@ -1107,11 +1145,17 @@ const Pengiriman = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { render={(props) => ( <HookFormSelect {...props} + disabled={sameAddressStreet} options={states} placeholder='Provinsi' /> )} /> + {chekValid && ( + <div className='text-caption-2 text-danger-500 mt-1'> + {errorsPengiriman.statePengiriman} + </div> + )} </div> <div className='w-1/3' @@ -1125,11 +1169,16 @@ const Pengiriman = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { <HookFormSelect {...props} options={cities} - disabled={!watchState} + disabled={!watchState || sameAddressStreet} placeholder='Kota' /> )} /> + {chekValid && ( + <div className='text-caption-2 text-danger-500 mt-1'> + {errorsPengiriman.cityPengiriman} + </div> + )} </div> <div className='w-1/3'> <input @@ -1138,27 +1187,18 @@ const Pengiriman = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { name='zipPengiriman' ref={zipRef} placeholder='Kode Pos' + disabled={sameAddressStreet} 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> - {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> @@ -1166,18 +1206,33 @@ const Pengiriman = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { <label className='form-label text-nowrap'> Nama PIC Penerimaan Invoice </label> - <input - value={formPengiriman.invoicePic} - id='invoicePic' - aria-label='invoicePic' - name='invoicePic' - placeholder='Masukkan nama pic invoice disini' - type='text' - className='form-input' - aria-invalid={errorsPengiriman.invoicePic} - ref={invoicePicRef} - onChange={handleInputChange} - /> + <div className='flex items-center border border-gray-300 rounded-md w-full'> + <select + value={formPengiriman.invoicePicTittle || ''} + id='invoicePicTittle' + name='invoicePicTittle' + className=' p-2 rounded-l-md' + onChange={handleInputChange} + > + <option value='' disabled> + Pilih + </option> + <option value='Bpk'>Bpk</option> + <option value='Ibu'>Ibu</option> + </select> + <input + value={formPengiriman.invoicePic} + id='invoicePic' + aria-label='invoicePic' + name='invoicePic' + placeholder='Masukkan nama pic invoice disini' + type='text' + className='form-input border-l border-r-0 border-t-0 border-b-0 border-gray-300 p-2 ml-2 flex-grow rounded-none' + aria-invalid={errorsPengiriman.invoicePic} + ref={invoicePicRef} + onChange={handleInputChange} + /> + </div> {chekValid && ( <div className='text-caption-2 text-danger-500 mt-1'> {errorsPengiriman.invoicePic} @@ -1199,75 +1254,76 @@ const Pengiriman = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { Alamat invoice sama dengan alamat pengiriman </Checkbox> </div> - {!sameAddress && ( - <> - <div className='w-full'> - <input - id='streetInvoice' - aria-label='streetInvoice' - name='streetInvoice' - ref={streetInvoiceRef} - placeholder='Masukkan alamat lengkap pengiriman invoice' - type='text' - value={formPengiriman.streetInvoice} - className='form-input' - onChange={handleInputChange} + + <> + <div className='w-full'> + <input + id='streetInvoice' + aria-label='streetInvoice' + name='streetInvoice' + ref={streetInvoiceRef} + disabled={sameAddress} + 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} + aria-label='stateInvoice' + > + <Controller + name='stateInvoice' + control={control} + render={(props) => ( + <HookFormSelect + {...props} + options={states} + disabled={sameAddress} + placeholder='Provinsi' + /> + )} /> {chekValid && ( <div className='text-caption-2 text-danger-500 mt-1'> - {errorsPengiriman.streetInvoice} + {errorsPengiriman.stateInvoice} </div> )} </div> - <div className='sub-alamat flex flex-row w-full gap-3'> - <div - className='w-3/5' - ref={stateInvoiceRef} - aria-label='stateInvoice' - > - <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} - aria-label='cityInvoice' - > - <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 + className='w-2/5' + ref={cityInvoiceRef} + aria-label='cityInvoice' + > + <Controller + name='cityInvoice' + control={control} + render={(props) => ( + <HookFormSelect + {...props} + options={cities} + disabled={!watchState || sameAddress} + placeholder='Kota' + /> )} - </div> + /> + {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'> @@ -1277,73 +1333,21 @@ const Pengiriman = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { </label> {!isKonfirmasi && ( <span className='text-xs opacity-60'> - Pilih jika bisnis anda memiliki jadwal penukaran invoice + Isi 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' - aria-label='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' - aria-label='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> + <textarea + id='tukarInvoiceInput' + name='tukarInvoiceInput' + placeholder='Masukkan jadwal penukaran invoice' + type='textarea' + value={formPengiriman.tukarInvoiceInput} + className='form-input' + rows={4} + cols={40} + onChange={handleInputChange} + /> </div> <div className='w-2/5'></div> </div> @@ -1355,75 +1359,29 @@ const Pengiriman = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { </label> {!isKonfirmasi && ( <span className='text-xs opacity-60'> - Pilih jika bisnis anda memiliki jadwal pembayaran + Isi 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> + <textarea + id='tukarInvoiceInputPembayaran' + name='tukarInvoiceInputPembayaran' + placeholder='Masukkan jadwal pembayaran' + type='textarea' + value={formPengiriman.tukarInvoiceInputPembayaran} + className='form-input' + rows={4} + cols={40} + onChange={handleInputChange} + /> </div> </div> <div className='flex flex-col gap-2 justify-between items-start'> <label className='form-label text-wrap'> - Dokumen saat Pengiriman Barang + Apakah ada dokumen tanda terima yang diberikan pada saat + pengiriman barang?{' '} + <span className=' opacity-60'>(Opsional)</span> </label> {!isKonfirmasi && ( <span className='text-xs opacity-60'> @@ -1472,30 +1430,36 @@ const Pengiriman = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { 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' - aria-label='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 saat Pengiriman Barang + </label> + {!isKonfirmasi && ( + <span className='text-xs opacity-60'> + Dokumen lampiran saat pengiriman barang + </span> + )} + <div className='flex gap-3 flex-col w-full'> + <textarea + id='dokumenPengirimanInput' + aria-label='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} + /> {chekValid && ( <div className='text-caption-2 text-danger-500 mt-1'> {errorsPengiriman.dokumenPengiriman} @@ -1507,97 +1471,25 @@ const Pengiriman = ({ chekValid, buttonSubmitClick, isKonfirmasi }) => { <div className='flex flex-col gap-2 justify-between items-start'> <label className='form-label text-wrap'> Dokumen yang dilampirkan saat Pengiriman Invoice + <span className=' opacity-60'>(Opsional)</span> </label> <span className='text-xs opacity-60'> - Pilih dokumen lampiran saat pengiriman invoice + Dokumen lampiran saat pengiriman invoice </span> - <div - className='w-full flex gap-2 flex-col' - ref={dokumenPengirimanInvoiceRef} - aria-label='dokumenPengirimanInvoiceInput' - > - <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' - aria-label='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> + <div className='flex gap-3 flex-col w-full'> + <textarea + id='dokumenPengirimanInvoice' + aria-label='dokumenPengirimanInvoice' + name='dokumenPengirimanInvoice' + placeholder='isi manual dokumen yang anda mau' + type='textarea' + ref={dokumenPengirimanInvoiceRef} + value={formPengiriman.dokumenPengirimanInvoice} + className='form-input' + rows={4} + cols={40} + onChange={handleInputChange} + /> {chekValid && ( <div className='text-caption-2 text-danger-500 mt-1'> {errorsPengiriman.dokumenInvoicePengiriman} diff --git a/src/lib/pengajuan-tempo/component/Referensi.jsx b/src/lib/pengajuan-tempo/component/Referensi.jsx index e285c2b9..6d9d0bd6 100644 --- a/src/lib/pengajuan-tempo/component/Referensi.jsx +++ b/src/lib/pengajuan-tempo/component/Referensi.jsx @@ -49,6 +49,7 @@ const Referensi = ({ chekValid, buttonSubmitClick, data }) => { creditLimit: '', }); const onChangeInput = (e, index) => { + updateHasSave(false); const { name, value } = e.target; let formattedValue = value; @@ -64,10 +65,13 @@ const Referensi = ({ chekValid, buttonSubmitClick, data }) => { ); setSupplierData(editData); - updateHasSave(false); + if (value == '') { + updateHasSave(true); + } }; const handleNewSupplierChange = (e) => { + updateHasSave(false); const { name, value } = e.target; let formattedValue = value; @@ -80,18 +84,21 @@ const Referensi = ({ chekValid, buttonSubmitClick, data }) => { const updatedSupplier = { ...newSupplier, [name]: formattedValue }; setNewSupplier(updatedSupplier); - updateHasSave(false); + if (value == '') { + updateHasSave(true); + } }; const handleDeleteSupplier = (index) => { + // updateHasSave(false); // Indikasi bahwa data telah berubah const updatedData = supplierData.filter((_, i) => i !== index); setSupplierData(updatedData); updateFormSupplier(updatedData); // Update store atau state terkait - updateHasSave(false); // Indikasi bahwa data telah berubah }; const handleAddNewSupplier = () => { + // updateHasSave(false); if (Object.values(newSupplier).every((val) => val.trim() !== '')) { setSupplierData((prevData) => { const newData = [...prevData, newSupplier]; @@ -106,7 +113,6 @@ const Referensi = ({ chekValid, buttonSubmitClick, data }) => { creditLimit: '', }); } - updateHasSave(false); }; useEffect(() => { diff --git a/src/lib/pengajuan-tempo/component/informasiPerusahaan.jsx b/src/lib/pengajuan-tempo/component/informasiPerusahaan.jsx index f641d8fa..19f46dec 100644 --- a/src/lib/pengajuan-tempo/component/informasiPerusahaan.jsx +++ b/src/lib/pengajuan-tempo/component/informasiPerusahaan.jsx @@ -10,6 +10,7 @@ import useDevice from '@/core/hooks/useDevice'; import Divider from '@/core/components/elements/Divider/Divider'; import { getAuth } from '~/libs/auth'; import addressApi from '@/lib/address/api/addressApi'; +import { toast } from 'react-hot-toast'; const InformasiPerusahaan = ({ chekValid, buttonSubmitClick, @@ -113,10 +114,12 @@ const InformasiPerusahaan = ({ useEffect(() => { const loadPaymentTerm = async () => { - const dataPaymentTerm = await odooApi( - 'GET', - '/api/v1/partner/payment_term' - ); + const dataPaymentTerm = [ + { id: 29, name: 'Tempo 7 Hari' }, + { id: 24, name: 'Tempo 14 Hari' }, + { id: 32, name: 'Tempo 21 Hari' }, + { id: 25, name: 'Tempo 30 Hari' }, + ]; setPaymentTerm( dataPaymentTerm?.map((o) => ({ value: o.id, @@ -224,13 +227,60 @@ const InformasiPerusahaan = ({ const bersediaRef = useRef(null); const categoryProdukRef = useRef(null); const tempoLimitRef = useRef(null); + useEffect(() => { + const options = { + behavior: 'smooth', + block: 'center', + }; + const loadIndustries = async () => { - if (!isFormValid) { - const options = { - behavior: 'smooth', - block: 'center', + const watchZip = form.zip?.trim(); // Menghapus spasi berlebih + + // Validasi: hanya eksekusi jika watchZip valid (contoh: minimal 5 karakter) + if (watchZip && watchZip.length >= 5) { + const loadZip = async () => { + try { + const response = await fetch( + `https://alamat.thecloudalert.com/api/cari/index/?keyword=${watchZip}` + ); + + const result = await response.json(); + + if (!result.result.length > 0) { + toast.error('Alamat pos salah'); + updateForm('zip', ''); // Reset form.zip jika salah + validate(); // Memanggil validasi formulir + return false; + } else { + updateForm('zip', watchZip); + validate(); + return true; // Jika valid + } + } catch (error) { + toast.error('Terjadi kesalahan saat memeriksa alamat pos.'); + console.error('Error:', error); + return false; + } }; + + const isValidZip = await loadZip(); + if (!isValidZip) { + zipRef.current.scrollIntoView(options); + } + } + }; + + loadIndustries(); + }, [form.zip]); + + useEffect(() => { + const options = { + behavior: 'smooth', + block: 'center', + }; + const loadIndustries = async () => { + if (!isFormValid) { if (errors.name && nameRef.current) { nameRef.current.scrollIntoView(options); return; @@ -356,8 +406,7 @@ const InformasiPerusahaan = ({ useEffect(() => { const loadProfile = async () => { try { - const dataProfile = await addressApi({ id: auth.parentId }); - + const dataProfile = await addressApi({ id: auth.partnerId }); setValue('industryId', parseInt(dataProfile.industryId)); setValue('state', parseInt(dataProfile.stateId.id)); setValue('city', parseInt(dataProfile.city.id)); @@ -664,7 +713,8 @@ const InformasiPerusahaan = ({ <div className='flex flex-row justify-between items-start'> <div className='w-2/5 text-nowrap'> <label className='form-label '> - Estimasi Pembelian pertahun + Estimasi Pembelian pertahun{' '} + <span className=' opacity-60'>(Opsional)</span> </label> </div> <div className='w-3/5'> @@ -738,187 +788,13 @@ const InformasiPerusahaan = ({ </div> )} </div> - {!isKonfirmasi && ( - <div className='w-[75%] flex flex-row justify-between items-center'> - <div className='w-2/5 text-nowrap flex justify-start items-start flex-col'> - <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 className='text-red-500'> - *Durasi dan limit dapat berbeda sesuai dengan verifikasi - oleh tim Indoteknik.com + <div className='text-red-500 text-xs mt-2'> + **Durasi tempo dapat berbeda sesuai dengan verifikasi oleh + tim Indoteknik.com </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='flex flex-row justify-between items-start'> <div className='w-2/5'> @@ -1286,7 +1162,8 @@ const InformasiPerusahaan = ({ <div className='flex flex-col gap-2 justify-between items-start'> <label className='form-label '> - Estimasi Pembelian pertahun + Estimasi Pembelian pertahun{' '} + <span className=' opacity-60'>(Opsional)</span> </label> <input id='estimasi' @@ -1310,24 +1187,18 @@ const InformasiPerusahaan = ({ <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> + <div className='w-full' ref={tempoDurationRef}> + <Controller + name='tempoDuration' + control={control} + render={(props) => ( + <HookFormSelect + {...props} + options={paymentTerm} + placeholder={'Pilih Durasi Tempo'} + /> + )} + /> {chekValid && ( <div className='text-caption-2 text-danger-500 mt-1'> {errors.tempoDuration} @@ -1335,81 +1206,9 @@ const InformasiPerusahaan = ({ )} </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 + **Durasi tempo 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> diff --git a/src/lib/tempo/components/Tempo.jsx b/src/lib/tempo/components/Tempo.jsx index e6c3959d..95eb461f 100644 --- a/src/lib/tempo/components/Tempo.jsx +++ b/src/lib/tempo/components/Tempo.jsx @@ -27,11 +27,13 @@ import odooApi from '@/core/api/odooApi'; import { getAuth } from '@/core/utils/auth'; import ProgressBar from '@ramonak/react-progress-bar'; import FooterBanner from '~/modules/footer-banner'; +import Image from '~/components/ui/image'; +import useDevice from '@/core/hooks/useDevice'; const Tempo = () => { const auth = getAuth(); const router = useRouter(); const { q = '', page = 1, limit = 15 } = router.query; - + const { isDesktop, isMobile } = useDevice(); const [pageNew, setPageNew] = useState(page); const [limitNew, setLimitNew] = useState(limit); @@ -173,116 +175,129 @@ const Tempo = () => { {getLabel()} </span> </div> - <div className='border p-4 rounded mt-4'> - <div className='flex mb-6 items-center justify-between mt-4'> - <form className='flex' onSubmit={handleSubmit}> - <button className='bg-gray_r-2 px-3' type='submit'> - <MagnifyingGlassIcon className='w-6' /> - </button> - <input - type='text' - className='form-input bg-gray_r-2 border-none' - placeholder='Cari Invoice...' - value={inputQuery} - onChange={(e) => setInputQuery(e.target.value)} - /> - </form> - {!invoices.isLoading && ( - <div className='flex flex-row gap-4 items-center justify-center'> - <p> - Menampilkan {startItem}-{endItem} dari{' '} - {invoices?.data?.invoiceTotal} - </p> - <select - id='limitSelect' - value={limitNew} - onChange={(e) => { - setLimitNew(Number(e.target.value)); - setPageNew(1); - }} - className='border p-2' - > - <option value={10}>10</option> - <option value={15}>15</option> - <option value={20}>20</option> - </select> - </div> - )} + {!invoices?.data?.invoices || + invoices?.data?.invoices?.length == 0 ? ( + <div className='flex justify-center'> + <Image + src='/images/ICON-DOKUMEN-VERIFIKASI.png' + alt='Registrasi Tempo' + width={isMobile ? 300 : 600} + height={isMobile ? 300 : 550} + /> </div> + ) : ( + <div className='border p-4 rounded mt-4'> + <div className='flex mb-6 items-center justify-between mt-4'> + <form className='flex' onSubmit={handleSubmit}> + <button className='bg-gray_r-2 px-3' type='submit'> + <MagnifyingGlassIcon className='w-6' /> + </button> + <input + type='text' + className='form-input bg-gray_r-2 border-none' + placeholder='Cari Invoice...' + value={inputQuery} + onChange={(e) => setInputQuery(e.target.value)} + /> + </form> + {!invoices.isLoading && ( + <div className='flex flex-row gap-4 items-center justify-center'> + <p> + Menampilkan {startItem}-{endItem} dari{' '} + {invoices?.data?.invoiceTotal} + </p> + <select + id='limitSelect' + value={limitNew} + onChange={(e) => { + setLimitNew(Number(e.target.value)); + setPageNew(1); + }} + className='border p-2' + > + <option value={10}>10</option> + <option value={15}>15</option> + <option value={20}>20</option> + </select> + </div> + )} + </div> - <table className='table-data'> - <thead> - <tr> - <th>No. Invoice</th> - <th>No. Transaksi</th> - <th className='!text-left'>Salesperson</th> - <th>Tanggal</th> - <th>Jatuh Tempo</th> - <th>Status</th> - <th className='!text-left'>Total</th> - </tr> - </thead> - <tbody> - {invoices.isLoading && ( + <table className='table-data'> + <thead> <tr> - <td colSpan={6}> - <div className='flex justify-center my-2'> - <Spinner className='w-6 text-gray_r-12/50 fill-gray_r-12' /> - </div> - </td> + <th>No. Invoice</th> + <th>No. Transaksi</th> + <th className='!text-left'>Salesperson</th> + <th>Tanggal</th> + <th>Jatuh Tempo</th> + <th>Status</th> + <th className='!text-left'>Total</th> </tr> - )} - {!invoices.isLoading && - (!invoices?.data?.invoices || - invoices?.data?.invoices?.length == 0) && ( + </thead> + <tbody> + {invoices.isLoading && ( <tr> - <td colSpan={6}>Tidak ada invoice</td> + <td colSpan={6}> + <div className='flex justify-center my-2'> + <Spinner className='w-6 text-gray_r-12/50 fill-gray_r-12' /> + </div> + </td> </tr> )} - {invoices.data?.invoices?.map((invoice) => ( - <tr key={invoice.id}> - <td> - <Link href={`/my/invoices/${invoice.id}`}> - {invoice.name} - </Link> - </td> - <td>{invoice.salesOrder || '-'}</td> - <td className='!text-left'>{invoice.sales}</td> - <td>{invoice.invoiceDate}</td> - <td>{invoice.invoiceDateDue}</td> - <td> - {invoice.amountResidual > 0 ? ( - new Date() > getDueDate(invoice.invoiceDateDue) ? ( - <div className='inline-flex items-center rounded-md bg-red-50 px-2 py-1 text-xs font-medium text-red-700 ring-1 ring-inset ring-red-600/20'> - Jatuh Tempo - </div> + {!invoices.isLoading && + (!invoices?.data?.invoices || + invoices?.data?.invoices?.length == 0) && ( + <tr> + <td colSpan={6}>Tidak ada Invoice</td> + </tr> + )} + {invoices.data?.invoices?.map((invoice) => ( + <tr key={invoice.id}> + <td> + <Link href={`/my/invoices/${invoice.id}`}> + {invoice.name} + </Link> + </td> + <td>{invoice.salesOrder || '-'}</td> + <td className='!text-left'>{invoice.sales}</td> + <td>{invoice.invoiceDate}</td> + <td>{invoice.invoiceDateDue}</td> + <td> + {invoice.amountResidual > 0 ? ( + new Date() > getDueDate(invoice.invoiceDateDue) ? ( + <div className='inline-flex items-center rounded-md bg-red-50 px-2 py-1 text-xs font-medium text-red-700 ring-1 ring-inset ring-red-600/20'> + Jatuh Tempo + </div> + ) : ( + <div className='badge-solid-red h-fit mx-auto'> + Belum Lunas + </div> + ) ) : ( - <div className='badge-solid-red h-fit mx-auto'> - Belum Lunas + <div className='badge-solid-green h-fit mx-auto'> + Lunas </div> - ) - ) : ( - <div className='badge-solid-green h-fit mx-auto'> - Lunas - </div> - )} - </td> - <td className='!text-left'> - {currencyFormat(invoice.amountTotal)} - </td> - </tr> - ))} - </tbody> - </table> + )} + </td> + <td className='!text-left'> + {currencyFormat(invoice.amountTotal)} + </td> + </tr> + ))} + </tbody> + </table> + + <Pagination + pageCount={pageCount} + currentPage={parseInt(pageNew)} + // url={`/my/tempo${pageQuery}`} + url={`/my/tempo?${toQuery(_.omit(query, ['page']))}`} + className='mt-2 mb-2' + /> + </div> + )} - <Pagination - pageCount={pageCount} - currentPage={parseInt(pageNew)} - // url={`/my/tempo${pageQuery}`} - url={`/my/tempo?${toQuery(_.omit(query, ['page']))}`} - className='mt-2 mb-2' - /> - </div> <div className=''> <FooterBanner /> </div> diff --git a/src/pages/pengajuan-tempo/index.jsx b/src/pages/pengajuan-tempo/index.jsx index 25db0c4b..271914c3 100644 --- a/src/pages/pengajuan-tempo/index.jsx +++ b/src/pages/pengajuan-tempo/index.jsx @@ -14,19 +14,24 @@ const PagePengajuanTempo = dynamic(() => export default function TrackingOrder() { const auth = getAuth(); + console.log('auth', auth); const router = useRouter(); const [isLoading, setIsLoading] = useState(true); // Set default isLoading to true useEffect(() => { - if (!auth) return; // Prevent unnecessary processing if auth is not ready + // if (!auth) return; // Prevent unnecessary processing if auth is not ready - if (auth.tempoProgres === 'review') { - router.push('/pengajuan-tempo/review'); - } else if (!auth.parentId) { - router.push('/pengajuan-tempo/switch-account'); - } else if (!auth) { + if (!auth) { const nextUrl = encodeURIComponent(router.asPath); router.push(`/login?next=${nextUrl}`); + } else if (!auth.parentId) { + router.push('/pengajuan-tempo/switch-account'); + } else if (auth.tempoProgres === 'review') { + router.push('/pengajuan-tempo/review'); + } else if (auth.tempoProgres === 'approve') { + router.push('/pengajuan-tempo/approve'); + } else if (auth.tempoProgres === 'rejected') { + router.push('/pengajuan-tempo/rejected'); } else { setIsLoading(false); // Set isLoading to false only when routing is not required } |
