summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src-migrate/validations/tempo.ts124
-rw-r--r--src/lib/pengajuan-tempo/component/PengajuanTempo.jsx250
2 files changed, 218 insertions, 156 deletions
diff --git a/src-migrate/validations/tempo.ts b/src-migrate/validations/tempo.ts
index f0623b6a..38380d5a 100644
--- a/src-migrate/validations/tempo.ts
+++ b/src-migrate/validations/tempo.ts
@@ -13,7 +13,8 @@ export const TempoSchema = z.object({
.string()
.min(1, { message: 'Nomor telepon harus diisi' })
.refine((val) => /^\d{10,12}$/.test(val), {
- message: 'Format nomor telepon tidak valid, contoh: 081234567890 atau 021234567890',
+ message:
+ 'Format nomor telepon tidak valid, contoh: 081234567890 atau 021234567890',
}),
bankName: z.string().min(1, { message: 'Nama bank harus diisi' }),
accountName: z.string().min(1, { message: 'Nama rekening harus diisi' }),
@@ -69,8 +70,8 @@ export const TempoSchemaKontakPerson = z
})
.refine(
(data) =>
- !data.financeEmail || // Jika financeEmail kosong, tidak perlu validasi
- data.financeEmail !== data.purchasingEmail, // Validasi jika financeEmail ada
+ !data.financeEmail ||
+ data.financeEmail !== data.purchasingEmail,
{
message: 'Email Finance tidak boleh sama dengan Email Purchasing',
path: ['financeEmail'],
@@ -86,70 +87,37 @@ export const TempoSchemaKontakPerson = z
'Email Direktur tidak boleh sama dengan Email Finance atau Purchasing',
path: ['direkturEmail'],
}
- );
-export const TempoSchemaPengiriman = z.object({
- PICTittle: z.string().min(1, { message: 'Tittle harus dipilih' }),
- PICName: z.string().min(1, { message: 'Nama harus diisi' }),
- streetPengiriman: z.string().min(1, { message: 'Alamat harus diisi' }),
- statePengiriman: z.string().min(1, { message: 'Provinsi harus dipilih' }),
- cityPengiriman: z.string().min(1, { message: 'Kota harus dipilih' }),
- districtPengiriman: z.string().min(1, { message: 'Kecamatan harus dipilih' }),
- subDistrictPengiriman: z.string().optional(),
- zipPengiriman: z.string().min(1, { message: 'Kode pos harus diisi' }),
- PICBarangMobile: z
- .string()
- .min(1, { message: 'Nomor telepon harus diisi' })
- .refine((val) => /^\d{10,12}$/.test(val), {
- message: 'Format nomor telepon tidak valid, contoh: 081234567890 atau 021234567890',
- }),
- invoicePicMobile: z
- .string()
- .min(1, { message: 'Nomor telepon harus diisi' })
- .refine((val) => /^\d{10,12}$/.test(val), {
- message: 'Format nomor telepon tidak valid, contoh: 081234567890 atau 021234567890',
- }),
- invoicePicTittle: z.string().min(1, { message: 'Tittle harus dipilih' }),
- invoicePic: z.string().min(1, { message: 'Nama pic invoice harus diisi' }),
- streetInvoice: z.string().min(1, { message: 'Alamat invoice harus diisi' }),
- stateInvoice: z
- .string()
- .min(1, { message: 'Provinsi invoice harus dipilih' }),
- cityInvoice: z.string().min(1, { message: 'Kota invoice harus dipilih' }),
- districtInvoice: z
- .string()
- .min(1, { message: 'Kecamatan invoice harus dipilih' }),
- subDistrictInvoice: z.string().optional(),
- zipInvoice: z.string().min(1, { message: 'Kode pos harus diisi' }),
- isSameAddrees: z.string(),
- isSameAddreesStreet: z.string(),
- tukarInvoiceInput: z
- .string()
- .min(1, { message: 'Jadwal Penukaran Invoice Harus Diisi' }),
- tukarInvoiceInputPembayaran: z
- .string()
- .min(1, { message: 'Jadwal Pembayaran Harus Diisi' }),
- dokumenPengiriman: z.string().optional(),
- dokumenPengirimanInput: z.string().optional(),
- dokumenKirimInput: z.string().optional(),
- dokumenPengirimanInvoiceInput: z.string().optional(),
- dokumenProsedur: z.object({
- name: z.string().optional(),
- format: z.string().optional(),
- base64: z.string().optional(),
- }),
-});
-export const TempoSchemaSupplier = z.object({
- supplier: z.string().min(1, { message: 'Nama supplier harus diisi' }),
- pic: z.string().min(1, { message: 'Nama PIC harus diisi' }),
- telepon: z
- .string()
- .min(1, { message: 'Nomor telepon harus diisi' })
- .refine((val) => /^\d{10,12}$/.test(val), {
- message: 'Format nomor telepon tidak valid, contoh: 081234567890 atau 021234567890',
- }),
- durasiTempo: z.string().min(1, { message: 'Durasi tempo harus diisi' }),
- creditLimit: z.string().min(1, { message: 'Limit Kredit harus diisi' }),
-});
+ )
+ .superRefine((data, ctx) => {
+ const phones = [
+ { key: 'direkturMobile', label: 'No. HP Direktur', value: data.direkturMobile },
+ { key: 'purchasingMobile', label: 'No. HP Purchasing', value: data.purchasingMobile },
+ { key: 'financeMobile', label: 'No. HP Finance', value: data.financeMobile },
+ ];
+
+ const seen = new Map<string, { key: string; label: string }>();
+
+ for (const phone of phones) {
+ if (!phone.value) continue;
+
+ if (!seen.has(phone.value)) {
+ seen.set(phone.value, { key: phone.key, label: phone.label });
+ } else {
+ const first = seen.get(phone.value)!;
+ ctx.addIssue({
+ code: 'custom',
+ path: [phone.key],
+ message: `${phone.label} tidak boleh sama dengan ${first.label}`,
+ });
+ ctx.addIssue({
+ code: 'custom',
+ path: [first.key],
+ message: `${first.label} tidak boleh sama dengan ${phone.label}`,
+ });
+ }
+ }
+ });
+
export const TempoSchemaDokumen = z.object({
dokumenNib: z.object({
name: z.string().min(1, { message: 'Nama file harus diisi' }),
@@ -217,3 +185,25 @@ export const TempoSchemaDokumen = z.object({
base64: z.string().optional(),
}),
});
+
+export const TempoSchemaPengiriman = z
+ .object({
+ PICBarangMobile: z
+ .string()
+ .min(1, { message: 'Nomor telepon harus diisi' })
+ .refine((val) => /^\d{10,12}$/.test(val), {
+ message:
+ 'Format nomor telepon tidak valid, contoh: 081234567890 atau 021234567890',
+ }),
+ invoicePicMobile: z
+ .string()
+ .min(1, { message: 'Nomor telepon harus diisi' })
+ .refine((val) => /^\d{10,12}$/.test(val), {
+ message:
+ 'Format nomor telepon tidak valid, contoh: 081234567890 atau 021234567890',
+ }),
+ });
+ // .refine((data) => data.PICBarangMobile !== data.invoicePicMobile, {
+ // message: 'Nomor HP PIC Barang tidak boleh sama dengan Nomor HP PIC Invoice',
+ // path: ['invoicePicMobile'], // error akan tampil di bawah field invoicePicMobile
+ // });
diff --git a/src/lib/pengajuan-tempo/component/PengajuanTempo.jsx b/src/lib/pengajuan-tempo/component/PengajuanTempo.jsx
index d59bfd75..5f3dd08c 100644
--- a/src/lib/pengajuan-tempo/component/PengajuanTempo.jsx
+++ b/src/lib/pengajuan-tempo/component/PengajuanTempo.jsx
@@ -38,7 +38,7 @@ const PengajuanTempo = () => {
const [bigData, setBigData] = useState();
const [idTempo, setIdTempo] = useState(0);
const { form, errors, validate, updateForm } = usePengajuanTempoStore();
- const { control, watch, setValue } = useForm();
+ const { control, watch, setValue, setError } = useForm();
const auth = useAuth();
const router = useRouter();
const [BannerTempo, setBannerTempo] = useState();
@@ -426,111 +426,185 @@ const PengajuanTempo = () => {
}
};
- const handleDaftarTempo = async () => {
- for (const error of stepDivsError) {
- if (error.length > 0) {
- return;
+const handleDaftarTempo = async () => {
+ const phones = [
+ { key: 'mobile', label: 'No. HP Perusahaan', value: form.mobile },
+ {
+ key: 'direkturMobile',
+ label: 'No. HP Direktur',
+ value: formKontakPerson.direkturMobile,
+ },
+ {
+ key: 'purchasingMobile',
+ label: 'No. HP Purchasing',
+ value: formKontakPerson.purchasingMobile,
+ },
+ {
+ key: 'financeMobile',
+ label: 'No. HP Finance',
+ value: formKontakPerson.financeMobile,
+ },
+ {
+ key: 'PICBarangMobile',
+ label: 'No. HP PIC Barang',
+ value: formKontakPerson.PICBarangMobile,
+ },
+ {
+ key: 'invoicePicMobile',
+ label: 'No. HP PIC Invoice',
+ value: formKontakPerson.invoicePicMobile,
+ },
+ ].filter((p) => p.value);
+
+ const seen = new Map();
+ let firstErrorField = null;
+
+ // 🔹 Reset error manual sebelum cek ulang
+ phones.forEach((p) => setError(p.key, { type: 'manual', message: '' }));
+
+ for (const phone of phones) {
+ if (!seen.has(phone.value)) {
+ seen.set(phone.value, phone);
+ } else {
+ const first = seen.get(phone.value);
+
+ // 🔹 Tampilkan toast
+ toast.error(`${phone.label} tidak boleh sama dengan ${first.label}`);
+
+ // 🔹 Tampilkan error merah di bawah input
+ setError(phone.key, {
+ type: 'manual',
+ message: `${phone.label} tidak boleh sama dengan ${first.label}`,
+ });
+
+ // 🔹 Juga beri error untuk pasangan duplikat pertama
+ setError(first.key, {
+ type: 'manual',
+ message: `${first.label} tidak boleh sama dengan ${phone.label}`,
+ });
+
+ // 🔹 Simpan field pertama yang salah untuk scroll
+ if (!firstErrorField) {
+ firstErrorField = phone.key;
}
}
+ }
+
+ if (firstErrorField) {
+ setTimeout(() => {
+ const el = document.querySelector(`[name="${firstErrorField}"]`);
+ if (el) {
+ el.scrollIntoView({ behavior: 'smooth', block: 'center' });
+ el.focus();
+ }
+ }, 100);
+ return; // â›” hentikan proses submit
+ }
- // 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,
- },
- }));
+ for (const error of stepDivsError) {
+ if (error.length > 0) {
+ return;
+ }
+ }
+
+ const formattedDokumen = Object.entries(formDokumen)
+ .filter(([_, doc]) => doc.format !== undefined)
+ .map(([key, doc]) => ({
+ documentName: key,
+ details: {
+ name: doc.name,
+ format: doc.format,
+ base64: doc.base64,
+ },
+ }));
- const toastId = toast.loading('Mengirimkan formulir pengajuan tempo...');
- setIsLoading(true);
- try {
- let address4;
- let address3;
- const address = await createPengajuanTempoApi({
- id: 0,
+ const toastId = toast.loading('Mengirimkan formulir pengajuan tempo...');
+ setIsLoading(true);
+
+ try {
+ let address4;
+ let address3;
+ const address = await createPengajuanTempoApi({
+ id: 0,
+ partner_id: auth.partnerId,
+ user_id: auth.parentId ? auth.parentId : auth.partnerId,
+ tempo_request: false,
+ ...form,
+ });
+
+ if (address.id) {
+ const address2 = await createPengajuanTempoApi({
+ id: address.id,
partner_id: auth.partnerId,
- user_id: auth.parentId ? auth.parentId : auth.partnerId,
+ user_id: address.userId,
tempo_request: false,
- ...form,
+ ...formKontakPerson,
});
- if (address.id) {
- const address2 = await createPengajuanTempoApi({
- id: address.id,
+
+ if (address2.id) {
+ address3 = await createPengajuanTempoApi({
+ id: address2.id,
partner_id: auth.partnerId,
- user_id: address.userId,
+ user_id: address2.userId,
tempo_request: false,
- ...formKontakPerson,
- });
- if (address2.id) {
- address3 = await createPengajuanTempoApi({
- id: address2.id,
- partner_id: auth.partnerId,
- user_id: address2.userId,
- tempo_request: false,
- ...formPengiriman,
- formDokumenProsedur: formPengiriman.dokumenProsedur
+ ...formPengiriman,
+ formDokumenProsedur: formPengiriman.dokumenProsedur
? JSON.stringify(formPengiriman.dokumenProsedur)
: false,
+ });
+
+ if (address3.id && formattedDokumen.length > 0) {
+ address4 = await createPengajuanTempoApi({
+ id: address3.id,
+ partner_id: auth.partnerId,
+ user_id: address3.userId,
+ tempo_request: true,
+ formDocs: JSON.stringify(formattedDokumen),
+ });
+ } else {
+ address4 = await createPengajuanTempoApi({
+ id: address3.id,
+ partner_id: auth.partnerId,
+ user_id: address3.userId,
+ tempo_request: true,
});
- 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: true,
- formDocs: JSON.stringify(formattedDokumen),
- });
- } else {
- address4 = await createPengajuanTempoApi({
- id: address3.id,
- partner_id: auth.partnerId,
- user_id: address3.userId,
- tempo_request: true,
- });
- }
}
}
+ }
- if (address4?.id) {
- toast.success('Pengajuan tempo berhasil dilakukan');
- const toastId = toast.loading('Mengubah status akun...');
- const isUpdated = await editAuthTempo();
- if (isUpdated?.user) {
- const update = await setAuth(isUpdated.user);
- if (update) {
- toast.dismiss(toastId);
- setIsLoading(false);
- toast.success('Berhasil mengubah status akun', { duration: 1000 });
- router.push('/pengajuan-tempo/finish');
- } else {
- toast.dismiss(toastId);
- setIsLoading(false);
- toast.success('Pengajuan tempo berhasil dilakukan');
- toast.error('Gagal mengubah status akun', { duration: 1000 });
- router.push('/pengajuan-tempo');
- }
- removeFromLocalStorage();
- return;
+ if (address4?.id) {
+ toast.success('Pengajuan tempo berhasil dilakukan');
+ const toastId2 = toast.loading('Mengubah status akun...');
+ const isUpdated = await editAuthTempo();
+ if (isUpdated?.user) {
+ const update = await setAuth(isUpdated.user);
+ if (update) {
+ toast.dismiss(toastId2);
+ setIsLoading(false);
+ toast.success('Berhasil mengubah status akun', { duration: 1000 });
+ router.push('/pengajuan-tempo/finish');
+ } else {
+ toast.dismiss(toastId2);
+ setIsLoading(false);
+ toast.success('Pengajuan tempo berhasil dilakukan');
+ toast.error('Gagal mengubah status akun', { duration: 1000 });
+ router.push('/pengajuan-tempo');
}
- } else {
- toast.dismiss(toastId);
- setIsLoading(false);
-
- toast.error('Terjadi kesalahan dalam pengiriman formulir');
+ removeFromLocalStorage();
+ return;
}
- } catch (error) {
+ } else {
toast.dismiss(toastId);
setIsLoading(false);
-
toast.error('Terjadi kesalahan dalam pengiriman formulir');
- console.error(error);
}
- };
+ } catch (error) {
+ toast.dismiss(toastId);
+ setIsLoading(false);
+ toast.error('Terjadi kesalahan dalam pengiriman formulir');
+ console.error(error);
+ }
+};
const removeFromLocalStorage = () => {
for (const key of stepLabels) {
@@ -660,10 +734,8 @@ const PengajuanTempo = () => {
isDisabled={!isCheckedTNC || isLoading}
onClick={handleDaftarTempo}
>
- {isLoading
- ? 'Loading...'
- : 'Daftar Tempo'}
- {!isLoading && <ChevronRightIcon className='w-5' />}
+ {isLoading ? 'Loading...' : 'Daftar Tempo'}
+ {!isLoading && <ChevronRightIcon className='w-5' />}
</Button>
</div>
)}