205 lines
6.4 KiB
TypeScript
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,
|
|
}
|
|
}
|