diff options
| author | IT Fixcomart <it@fixcomart.co.id> | 2025-01-14 09:53:43 +0000 |
|---|---|---|
| committer | IT Fixcomart <it@fixcomart.co.id> | 2025-01-14 09:53:43 +0000 |
| commit | 3e037c57566d7fb0acad2cb71fedd075cb9ce462 (patch) | |
| tree | 1ec2ebdf700d3c9501a665a8f1e5351ddc80e5ef /src-migrate | |
| parent | a868498e7327593b40d1e02fd96531fefd9548d5 (diff) | |
| parent | 76afb8aaa5d2aaaf68529e11e9ed4d003d953f76 (diff) | |
Merged in Feature/pengajuan-tempo (pull request #401)
Feature/pengajuan tempo
Approved-by: trisusilo
Diffstat (limited to 'src-migrate')
| -rw-r--r-- | src-migrate/modules/register/index.tsx | 5 | ||||
| -rw-r--r-- | src-migrate/modules/register/stores/usePengajuanTempoStore.ts | 334 | ||||
| -rw-r--r-- | src-migrate/types/auth.ts | 3 | ||||
| -rw-r--r-- | src-migrate/types/tempo.ts | 117 | ||||
| -rw-r--r-- | src-migrate/validations/tempo.ts | 181 |
5 files changed, 637 insertions, 3 deletions
diff --git a/src-migrate/modules/register/index.tsx b/src-migrate/modules/register/index.tsx index 0308e397..39f4771c 100644 --- a/src-migrate/modules/register/index.tsx +++ b/src-migrate/modules/register/index.tsx @@ -163,7 +163,7 @@ const Register = () => { )} </div> <section className='mt-2'> - <FormCaptcha /> + {/* <FormCaptcha /> */} <TermCondition /> <Button type='submit' @@ -172,7 +172,8 @@ const Register = () => { size='lg' onClick={handleSubmit} isDisabled={ - !isCheckedTNC || mutation.isLoading || !isValidCaptcha + // !isCheckedTNC || mutation.isLoading || !isValidCaptcha + !isCheckedTNC || mutation.isLoading } > {mutation.isLoading ? 'Loading...' : 'Daftar'} diff --git a/src-migrate/modules/register/stores/usePengajuanTempoStore.ts b/src-migrate/modules/register/stores/usePengajuanTempoStore.ts new file mode 100644 index 00000000..1e086c06 --- /dev/null +++ b/src-migrate/modules/register/stores/usePengajuanTempoStore.ts @@ -0,0 +1,334 @@ +import { create } from 'zustand'; +import { + TempoProps, + TempoPropsKontakPerson, + TempoPropsPengiriman, + TempoPropsSupplier, + TempoPropsDokumen, +} from '~/types/tempo'; +import { + TempoSchema, + TempoSchemaKontakPerson, + TempoSchemaPengiriman, + TempoSchemaSupplier, + TempoSchemaDokumen, +} from '~/validations/tempo'; +import { boolean, ZodError } from 'zod'; + +type State = { + form: TempoProps; + errors: { + [key in keyof TempoProps]?: string; + }; + isCheckedTNC: boolean; + isOpenTNC: boolean; + isValidCaptcha: boolean; +}; + +type Action = { + updateForm: (name: string, value: string) => void; + updateValidCaptcha: (value: boolean) => void; + toggleCheckTNC: () => void; + openTNC: () => void; + closeTNC: () => void; + validate: () => void; + resetForm: () => void; +}; + +export const usePengajuanTempoStore = create<State & Action>((set, get) => ({ + form: { + name: '', + industryId: '', + street: '', + state: '', + city: '', + district: '', + subDistrict: '', + zip: '', + mobile: '', + bankName: '', + accountName: '', + accountNumber: '', + estimasi: '', + tempoDuration: '', + bersedia: '', + portal: '', + website: '', + categoryProduk: '', + tempoLimit: '', + }, + updateForm: (name, value) => + set((state) => ({ form: { ...state.form, [name]: value } })), + + errors: {}, + validate: () => { + try { + TempoSchema.parse(get().form); + set({ errors: {} }); + } catch (error) { + if (error instanceof ZodError) { + const errors: State['errors'] = {}; + error.errors.forEach( + (e) => (errors[e.path[0] as keyof TempoProps] = e.message) + ); + set({ errors }); + } + } + }, + + isCheckedTNC: false, + toggleCheckTNC: () => set((state) => ({ isCheckedTNC: !state.isCheckedTNC })), + + isOpenTNC: false, + openTNC: () => set(() => ({ isOpenTNC: true })), + closeTNC: () => set(() => ({ isOpenTNC: false })), + + isValidCaptcha: false, + updateValidCaptcha: (value) => set(() => ({ isValidCaptcha: value })), + + resetForm: () => + set({ + form: { + name: '', + industryId: '', + street: '', + state: '', + city: '', + district: '', + subDistrict: '', + zip: '', + mobile: '', + bankName: '', + accountName: '', + accountNumber: '', + website: '', + estimasi: '', + tempoDuration: '', + bersedia: '', + portal: '', + categoryProduk: '', + }, + }), +})); + +type StateKontakPerson = { + formKontakPerson: TempoPropsKontakPerson; + errorsKontakPerson: { + [key in keyof TempoPropsKontakPerson]?: string; + }; +}; +type ActionKontakPerson = { + updateFormKontakPerson: (name: string, value: string) => void; + + validateKontakPerson: () => void; +}; +export const usePengajuanTempoStoreKontakPerson = create< + StateKontakPerson & ActionKontakPerson +>((set, get) => ({ + formKontakPerson: { + direkturTittle: '', + direkturName: '', + direkturMobile: '', + direkturEmail: '', + purchasingTittle: '', + purchasingName: '', + purchasingEmail: '', + financeMobile: '', + financeTittle: '', + financeName: '', + financeEmail: '', + purchasingMobile: '', + }, + updateFormKontakPerson: (name, value) => + set((state) => ({ + formKontakPerson: { ...state.formKontakPerson, [name]: value }, + })), + + errorsKontakPerson: {}, + validateKontakPerson: () => { + try { + TempoSchemaKontakPerson.parse(get().formKontakPerson); + set({ errorsKontakPerson: {} }); + } catch (error) { + if (error instanceof ZodError) { + const errorsKontakPerson: StateKontakPerson['errorsKontakPerson'] = {}; + error.errors.forEach( + (e) => + (errorsKontakPerson[e.path[0] as keyof TempoPropsKontakPerson] = + e.message) + ); + set({ errorsKontakPerson }); + } + } + }, +})); + +type StatePengiriman = { + formPengiriman: TempoPropsPengiriman; + errorsPengiriman: { + [key in keyof TempoPropsPengiriman]?: string; + }; +}; +type ActionPengiriman = { + updateFormPengiriman: (name: string, value: string) => void; + + validatePengiriman: () => void; +}; +export const usePengajuanTempoStorePengiriman = create< + StatePengiriman & ActionPengiriman +>((set, get) => ({ + formPengiriman: { + PICTittle: '', + PICName: '', + streetPengiriman: '', + statePengiriman: '', + cityPengiriman: '', + districtPengiriman: '', + subDistrictPengiriman: '', + zipPengiriman: '', + invoicePicTittle: '', + invoicePic: '', + isSameAddrees: '', + isSameAddreesStreet: '', + streetInvoice: '', + stateInvoice: '', + cityInvoice: '', + districtInvoice: '', + subDistrictInvoice: '', + zipInvoice: '', + tukarInvoiceInput: '', + tukarInvoiceInputPembayaran: '', + dokumenPengiriman: '', + dokumenPengirimanInput: '', + dokumenKirimInput: '', + dokumenPengirimanInvoice: '', + }, + updateFormPengiriman: (name, value) => + set((state) => ({ + formPengiriman: { ...state.formPengiriman, [name]: value }, + })), + + errorsPengiriman: {}, + validatePengiriman: () => { + try { + TempoSchemaPengiriman.parse(get().formPengiriman); + set({ errorsPengiriman: {} }); + } catch (error) { + if (error instanceof ZodError) { + const errorsPengiriman: StatePengiriman['errorsPengiriman'] = {}; + error.errors.forEach( + (e) => + (errorsPengiriman[e.path[0] as keyof TempoPropsPengiriman] = + e.message) + ); + set({ errorsPengiriman }); + } + } + }, +})); +type StateDokumen = { + formDokumen: TempoPropsDokumen; + errorsDokumen: { + [key in keyof TempoPropsDokumen]?: string; + }; +}; +type ActionDokumen = { + updateFormDokumen: ( + name: string, + fileName: string, + fileFormat: string, + value: string + ) => void; + + validateDokumen: () => void; + getJumlahDokumenDiisi: () => void; +}; +export const usePengajuanTempoStoreDokumen = create< + StateDokumen & ActionDokumen +>((set, get) => ({ + formDokumen: { + dokumenNib: { name: '', format: '', base64: '' }, + dokumenNpwp: { name: '', format: '', base64: '' }, + dokumenSppkp: { name: '', format: '', base64: '' }, + dokumenSiup: { name: '', format: '', base64: '' }, + dokumenTdp: { name: '', format: '', base64: '' }, + dokumenSkdp: { name: '', format: '', base64: '' }, + dokumenSkt: { name: '', format: '', base64: '' }, + dokumenAktaPerubahan: { name: '', format: '', base64: '' }, + dokumenKtpDirut: { name: '', format: '', base64: '' }, + dokumenAktaPendirian: { name: '', format: '', base64: '' }, + dokumenLaporanKeuangan: { name: '', format: '', base64: '' }, + dokumenFotoKantor: { name: '', format: '', base64: '' }, + dokumenTempatBekerja: { name: '', format: '', base64: '' }, + }, + + // Memperbarui dokumen dengan name, format, dan base64 + updateFormDokumen: (name, fileName, fileFormat, value) => + set((state) => ({ + formDokumen: { + ...state.formDokumen, + [name]: { + name: fileName, + format: fileFormat, + base64: value, + }, + }, + })), + + errorsDokumen: {}, + validateDokumen: () => { + try { + TempoSchemaDokumen.parse(get().formDokumen); + set({ errorsDokumen: {} }); + } catch (error) { + if (error instanceof ZodError) { + const errorsDokumen: StateDokumen['errorsDokumen'] = {}; + error.errors.forEach( + (e) => + (errorsDokumen[e.path[0] as keyof TempoPropsDokumen] = e.message) + ); + set({ errorsDokumen }); + } + } + }, + + getJumlahDokumenDiisi: () => { + const formDokumen = get().formDokumen; + // Menghitung jumlah field yang base64 tidak kosong + const jumlahTerisi = Object.values(formDokumen).filter( + (dokumen) => dokumen.base64 !== '' + ).length; + return jumlahTerisi; + }, +})); + +type StateSupplier = { + hasSavedata: boolean; + formSupplier: []; + errorsSupplier: { + [key in keyof TempoPropsSupplier]?: string; + }; +}; +type ActionSupplier = { + updateFormSupplier: (data: []) => void; + updateHasSave: (data: boolean) => void; + validateSupplier: () => void; +}; +export const usePengajuanTempoStoreSupplier = create< + StateSupplier & ActionSupplier +>((set, get) => ({ + formSupplier: [], + hasSavedata: true, + updateFormSupplier: (data) => { + set(() => ({ + formSupplier: data, + })); + }, + updateHasSave: (data) => { + set(() => ({ + hasSavedata: data, + })); + }, + errorsSupplier: {}, + validateSupplier: () => {}, +})); diff --git a/src-migrate/types/auth.ts b/src-migrate/types/auth.ts index 8feac2e1..1b400e95 100644 --- a/src-migrate/types/auth.ts +++ b/src-migrate/types/auth.ts @@ -20,7 +20,8 @@ export type AuthProps = { onlyReadyStock: boolean; soApproval: boolean; }; - partner_tempo: boolean; + partner_tempo: string; + tempo_progres: string; }; export type AuthApiProps = OdooApiRes<AuthProps>; diff --git a/src-migrate/types/tempo.ts b/src-migrate/types/tempo.ts new file mode 100644 index 00000000..d043e2d6 --- /dev/null +++ b/src-migrate/types/tempo.ts @@ -0,0 +1,117 @@ +import { + TempoSchema, + TempoSchemaKontakPerson, + TempoSchemaPengiriman, + TempoSchemaSupplier, + TempoSchemaDokumen, +} from '~/validations/tempo'; +import { OdooApiRes } from './odoo'; +import { z } from 'zod'; + +export type tempoProps = { + name: string; + industry_id: string; + street: string; + state: string; + city: string; + zip: string; + mobile: string; + bankName: string; + accountName: string; + accountNumber: string; + estimasi: string; + tempoDuration: string; + bersedia: string; +}; + +export type tempoPropsKontakPerson = { + direkturName: string; + direkturMobile: string; + direkturEmail: string; + purchasingName: string; + purchasingEmail: string; + financeMobile: string; + financeEmail: string; + financeName: string; + purchasingMobile: string; +}; +export type tempoPropsPengiriman = { + PICName: string; + streetPengiriman: string; + statePengiriman: string; + cityPengiriman: string; + streetInvoice: string; + zip: string; + invoicePic: string; + isSameAddrees: string; + stateInvoice: string; + cityInvoice: string; + tukarInvoiceInput: string; + tukarInvoiceInputPembayaran: string; + dokumenPengiriman: string; + dokumenPengirimanInput: string; + dokumenPengirimanInvoice: string; + dokumenPengirimanInvoiceInput: string; +}; +export type tempoPropsSupplier = { + supplier: string; + pic: string; + telepon: string; + durasiTempo: string; + creditLimit: string; +}; +export type tempoPropsDokumen = { + dokumenNib: { name: string; format: string; base64: string }; + dokumenNpwp: { name: string; format: string; base64: string }; + dokumenSppkp: { name: string; format: string; base64: string }; + dokumenAktaPerubahan: { name: string; format: string; base64: string }; + dokumenKtpDirut: { name: string; format: string; base64: string }; + dokumenAktaPendirian: { name: string; format: string; base64: string }; + dokumenLaporanKeuangan: { name: string; format: string; base64: string }; + dokumenFotoKantor: { name: string; format: string; base64: string }; + dokumenTempatBekerja: { name: string; format: string; base64: string }; +}; + +export type TempoApiProps = OdooApiRes<TempoProps>; + +export type TempoProps = z.infer<typeof TempoSchema>; +export type TempoPropsKontakPerson = z.infer<typeof TempoSchemaKontakPerson>; +export type TempoPropsPengiriman = z.infer<typeof TempoSchemaPengiriman>; +export type TempoPropsSupplier = z.infer<typeof TempoSchemaSupplier>; +export type TempoPropsDokumen = z.infer<typeof TempoSchemaDokumen>; + +export type TempoResApiProps = { + Tempo: boolean; + reason: 'EMAIL_USED' | 'NOT_ACTIVE' | null; +}; + +type ActivationResProps = { + activation: boolean; + user: TempoProps | null; +}; + +export type ActivationTokenProps = { + token: string; +}; + +export type ActivationTokenResApiProps = ActivationResProps & { + reason: 'INVALID_TOKEN' | null; +}; + +export type ActivationOtpProps = { + email: string; + otp: string; +}; + +export type ActivationOtpResApiProps = ActivationResProps & { + reason: 'INVALID_OTP' | null; +}; + +export type ActivationReqProps = { + email: string; +}; + +export type ActivationReqResApiProps = { + activation_request: boolean; + reason: 'NOT_FOUND' | 'ACTIVE' | null; +}; diff --git a/src-migrate/validations/tempo.ts b/src-migrate/validations/tempo.ts new file mode 100644 index 00000000..f019275c --- /dev/null +++ b/src-migrate/validations/tempo.ts @@ -0,0 +1,181 @@ +import { z } from 'zod'; + +export const TempoSchema = z.object({ + name: z.string().min(1, { message: 'Nama harus diisi' }), + street: z.string().min(1, { message: 'Alamat harus diisi' }), + industryId: z.string().min(1, { message: 'Jenis usaha harus dipilih' }), + zip: z.string().min(1, { message: 'Kode pos harus diisi' }), + state: z.string().min(1, { message: 'Provinsi harus dipilih' }), + city: z.string().min(1, { message: 'Kota harus dipilih' }), + district: z.string().min(1, { message: 'Kecamatan harus dipilih' }), + subDistrict: z.string().min(1, { message: 'Kelurahan harus dipilih' }), + mobile: z + .string() + .min(1, { message: 'Nomor telepon harus diisi' }) + .refine((val) => /^\d{10,12}$/.test(val), { + message: 'Format nomor telepon tidak valid, contoh: 081234567890', + }), + bankName: z.string().min(1, { message: 'Nama bank harus diisi' }), + accountName: z.string().min(1, { message: 'Nama rekening harus diisi' }), + accountNumber: z + .string() + .min(1, { message: 'Nomor rekening harus diisi' }) + .refine((val) => /^\d+$/.test(val), { + message: 'Nomor rekening hanya boleh mengandung angka', + }), + estimasi: z.string().optional(), + website: z.string().optional(), + tempoDuration: z.string().min(1, { message: 'Durasi tempo harus dipilih' }), + bersedia: z.string().min(1, { message: 'Harus dipilih' }), + portal: z.string().min(1, { message: 'Harus dipilih' }), + categoryProduk: z + .string() + .min(1, { message: 'Category produk harus dipilih' }), +}); + +export const TempoSchemaKontakPerson = z.object({ + direkturName: z.string().min(1, { message: 'Nama harus diisi' }), + direkturTittle: z.string().min(1, { message: 'Tittle harus dipilih' }), + financeName: z.string().min(1, { message: 'Nama harus diisi' }), + direkturMobile: z.string().optional(), + financeMobile: z + .string() + .min(1, { message: 'Nomor telepon harus diisi' }) + .refine((val) => /^\d{10,12}$/.test(val), { + message: 'Format nomor telepon tidak valid, contoh: 081234567890', + }), + purchasingTittle: z.string().min(1, { message: 'Tittle harus dipilih' }), + financeTittle: z.string().min(1, { message: 'Tittle harus dipilih' }), + purchasingMobile: z + .string() + .min(1, { message: 'Nomor telepon harus diisi' }) + .refine((val) => /^\d{10,12}$/.test(val), { + message: 'Format nomor telepon tidak valid, contoh: 081234567890', + }), + direkturEmail: z + .string() + .min(1, { message: 'Email harus diisi' }) + .email({ message: 'Email harus menggunakan format example@mail.com' }), + purchasingEmail: z + .string() + .min(1, { message: 'Email harus diisi' }) + .email({ message: 'Email harus menggunakan format example@mail.com' }), + financeEmail: z + .string() + .min(1, { message: 'Email harus diisi' }) + .email({ message: 'Email harus menggunakan format example@mail.com' }), + purchasingName: z.string().min(1, { message: 'Nama harus diisi' }), +}); +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() + .min(1, { message: 'Kelurahan harus dipilih' }), + zipPengiriman: z.string().min(1, { message: 'Kode pos harus diisi' }), + 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() + .min(1, { message: 'Kelurahan invoice harus dipilih' }), + zipInvoice: z.string().min(1, { message: 'Kode pos harus diisi' }), + isSameAddrees: z.string(), + isSameAddreesStreet: z.string(), + tukarInvoiceInput: z.string().optional(), + tukarInvoiceInputPembayaran: z.string().optional(), + dokumenPengiriman: z.string().optional(), + dokumenPengirimanInput: z.string().optional(), + dokumenKirimInput: z.string().optional(), + dokumenPengirimanInvoiceInput: 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', + }), + durasiTempo: z.string().min(1, { message: 'Durasi tempo harus diisi' }), + creditLimit: z.string().min(1, { message: 'Limit Kredit harus diisi' }), +}); +export const TempoSchemaDokumen = z.object({ + dokumenNib: z.object({ + name: z.string().min(1, { message: 'Nama file harus diisi' }), + format: z.string().optional(), + base64: z.string().optional(), + }), + dokumenNpwp: z.object({ + name: z.string().min(1, { message: 'Nama file harus diisi' }), + format: z.string().optional(), + base64: z.string().optional(), + }), + dokumenSppkp: z.object({ + name: z.string().min(1, { message: 'Nama file harus diisi' }), + format: z.string().optional(), + base64: z.string().optional(), + }), + dokumenSiup: z.object({ + name: z.string().optional(), + format: z.string().optional(), + base64: z.string().optional(), + }), + dokumenTdp: z.object({ + name: z.string().optional(), + format: z.string().optional(), + base64: z.string().optional(), + }), + dokumenSkdp: z.object({ + name: z.string().optional(), + format: z.string().optional(), + base64: z.string().optional(), + }), + dokumenSkt: z.object({ + name: z.string().optional(), + format: z.string().optional(), + base64: z.string().optional(), + }), + dokumenAktaPerubahan: z.object({ + name: z.string().optional(), + format: z.string().optional(), + base64: z.string().optional(), + }), + dokumenKtpDirut: z.object({ + name: z.string().optional(), + format: z.string().optional(), + base64: z.string().optional(), + }), + dokumenAktaPendirian: z.object({ + name: z.string().optional(), + format: z.string().optional(), + base64: z.string().optional(), + }), + dokumenLaporanKeuangan: z.object({ + name: z.string().optional(), + format: z.string().optional(), + base64: z.string().optional(), + }), + dokumenFotoKantor: z.object({ + name: z.string().min(1, { message: 'Nama file harus diisi' }), + format: z.string().optional(), + base64: z.string().optional(), + }), + dokumenTempatBekerja: z.object({ + name: z.string().min(1, { message: 'Nama file harus diisi' }), + format: z.string().optional(), + base64: z.string().optional(), + }), +}); |
