Files
My-KOPKB/fe/src/modules/membership-application/utils/membership-application-form.utils.ts
T

205 lines
6.4 KiB
TypeScript

import dayjs from 'dayjs'
import * as select from '@zag-js/select'
import type {
MembershipApplicationDetail,
MembershipApplicationDocumentsForm,
MembershipApplicationFormState,
MembershipApplicationHeirForm,
MembershipApplicationReferenceForm,
UpdateMembershipApplicationPayload,
} from '../types/membership-application.types'
export type SelectOption = { label: string; value: string }
export const GENDER_OPTIONS: SelectOption[] = [
{ label: 'Lelaki', value: 'Lelaki' },
{ label: 'Perempuan', value: 'Perempuan' },
]
export const MARRIAGE_STATUS_OPTIONS: SelectOption[] = [
{ label: 'Belum Berkahwin', value: 'Belum Berkahwin' },
{ label: 'Berkahwin', value: 'Berkahwin' },
{ label: 'Bercerai', value: 'Bercerai' },
{ label: 'Balu', value: 'Balu' },
{ label: 'Duda', value: 'Duda' },
]
export const RELATIONSHIP_OPTIONS: SelectOption[] = [
{ label: 'Isteri', value: 'Isteri' },
{ label: 'Suami', value: 'Suami' },
{ label: 'Anak', value: 'Anak' },
{ label: 'Bapa', value: 'Bapa' },
{ label: 'Ibu', value: 'Ibu' },
{ label: 'Orang Tua', value: 'Orang Tua' },
{ label: 'Saudara', value: 'Saudara' },
{ label: 'Lain-lain', value: 'Lain-lain' },
]
export const DOCUMENT_TYPE_LABELS: Record<string, string> = {
ic_copy: 'Salinan Kad Pengenalan',
photo: 'Gambar Passport',
salary_slip: 'Slip Gaji',
employer_letter: 'Surat Pengesahan Majikan',
}
export const DOCUMENT_UPLOAD_TYPES = ['ic_copy', 'photo', 'salary_slip', 'employer_letter'] as const
export type DocumentUploadType = (typeof DOCUMENT_UPLOAD_TYPES)[number]
export function createSelectCollection(options: SelectOption[]) {
return select.collection({
items: options,
itemToValue: (item) => item.label,
})
}
export function labelToApiValue(options: SelectOption[], label: string | undefined): string {
if (!label) return ''
return options.find((option) => option.label === label)?.value ?? ''
}
export function apiValueToLabel(options: SelectOption[], value: string | undefined): string[] {
if (!value) return []
const option = options.find((item) => item.value === value)
return option ? [option.label] : [value]
}
export function createEmptyReference(): MembershipApplicationReferenceForm {
return {
ic_number: '',
user_id: '',
name: '',
}
}
export function createEmptyHeir(): MembershipApplicationHeirForm {
return {
name: '',
ic_number: '',
relationship: '',
phone_number: '',
}
}
function toDateInputValue(value: string | null | undefined): string {
if (!value) return ''
return dayjs(value).format('YYYY-MM-DD')
}
function toFormString(value: string | number | null | undefined): string {
if (value === null || value === undefined) return ''
return String(value)
}
export function createEmptyFormState(): MembershipApplicationFormState {
return {
applicant: {
name: '',
email: '',
ic_number: '',
birth_date: '',
birth_place: '',
gender: '',
marriage_status: '',
address: '',
phone_number: '',
office_number: '',
postcode: '',
employer_name: '',
employer_address: '',
current_position: '',
start_work_date: '',
stock_monthly_contribution: '',
fee_monthly_contribution: '',
},
heirs: [createEmptyHeir()],
references: {
proposer: createEmptyReference(),
supporter: createEmptyReference(),
},
documents: {
ic_copy: null,
photo: null,
salary_slip: null,
employer_letter: null,
},
}
}
export function detailToFormState(detail: MembershipApplicationDetail): MembershipApplicationFormState {
const applicant = detail.applicant
const proposer = detail.references.find((reference) => reference.reference_type === 'PROPOSER')
const supporter = detail.references.find((reference) => reference.reference_type === 'SUPPORTER')
return {
applicant: {
name: toFormString(applicant?.name),
email: toFormString(applicant?.email),
ic_number: toFormString(applicant?.ic_number),
birth_date: toDateInputValue(applicant?.birth_date),
birth_place: toFormString(applicant?.birth_place),
gender: toFormString(applicant?.gender),
marriage_status: toFormString(applicant?.marriage_status),
address: toFormString(applicant?.address),
phone_number: toFormString(applicant?.phone_number),
office_number: toFormString(applicant?.office_number),
postcode: toFormString(applicant?.postcode),
employer_name: toFormString(applicant?.employer_name),
employer_address: toFormString(applicant?.employer_address),
current_position: toFormString(applicant?.current_position),
start_work_date: toDateInputValue(applicant?.start_work_date),
stock_monthly_contribution: toFormString(applicant?.stock_monthly_contribution),
fee_monthly_contribution: toFormString(applicant?.fee_monthly_contribution),
},
heirs: detail.heirs.length
? detail.heirs.map((heir) => ({
name: toFormString(heir.name),
ic_number: toFormString(heir.ic_number),
relationship: toFormString(heir.relationship),
phone_number: toFormString(heir.phone_number),
}))
: [createEmptyHeir()],
references: {
proposer: {
ic_number: toFormString(proposer?.member?.ic_number),
user_id: toFormString(proposer?.user_id),
name: toFormString(proposer?.member?.name),
},
supporter: {
ic_number: toFormString(supporter?.member?.ic_number),
user_id: toFormString(supporter?.user_id),
name: toFormString(supporter?.member?.name),
},
},
documents: {
ic_copy: null,
photo: null,
salary_slip: null,
employer_letter: null,
},
}
}
export function buildUpdatePayload(form: MembershipApplicationFormState): UpdateMembershipApplicationPayload {
return {
applicant: {
...form.applicant,
stock_monthly_contribution: Number(form.applicant.stock_monthly_contribution || 0),
fee_monthly_contribution: Number(form.applicant.fee_monthly_contribution || 0),
},
heirs: form.heirs,
references: {
proposer_ic_number: form.references.proposer.ic_number.trim(),
supporter_ic_number: form.references.supporter.ic_number.trim(),
},
}
}
export function emptyDocumentsForm(): MembershipApplicationDocumentsForm {
return {
ic_copy: null,
photo: null,
salary_slip: null,
employer_letter: null,
}
}