Files
simrsx-fe/app/schemas/patient.schema.ts
T
Khafid Prayoga 46911514fb refactor: postal region, add new field on list
feat: implement postal region model and update address handling

- Add new PostalRegion model and service
- Replace postalCode with postalRegion in address-related components
- Update schemas and models to use locationType_code consistently
- Add usePostalRegion composable for postal code selection
- Modify patient form to handle address changes more robustly

feat(patient): add ID column and improve date formatting

- Add patient ID column to patient list
- Format dates using 'id-ID' locale in preview
- Update identity number display for foreign patients
- Include passport number for foreign nationals
2025-10-13 13:07:00 +07:00

161 lines
4.6 KiB
TypeScript

import { z } from 'zod'
const CommunicationBarrierSchema = z
.enum(['YA', 'TIDAK'], {
required_error: 'Mohon lengkapi Status Hambatan Berkomunikasi',
})
.transform((val) => val === 'YA')
const IsNewBornSchema = z
.enum(['YA', 'TIDAK'], {
required_error: 'Mohon lengkapi status pasien',
})
.transform((val) => val === 'YA')
const PatientSchema = z
.object({
// Data Diri Pasien
identityNumber: z.string().optional(),
// .string({
// required_error: 'Mohon lengkapi NIK',
// })
// .min(16, 'NIK harus berupa angka 16 digit')
// .regex(/^\d+$/, 'NIK harus berupa angka 16 digit'),
// identityCardFile: z.instanceof(File, { message: 'File KTP harus dipilih' }),
// familyCardFile: z.instanceof(File, { message: 'File KK harus dipilih' }),
// Informasi Dasar
// alias: z.string({
// required_error: 'Mohon pilih sapaan',
// }),
fullName: z.string({
required_error: 'Mohon lengkapi Nama',
}),
birthPlace: z
.string({
required_error: 'Mohon lengkapi Tempat Lahir',
})
.min(1, 'Mohon lengkapi Tempat Lahir'),
birthDate: z
.string({
required_error: 'Mohon lengkapi Tanggal Lahir',
})
.refine(
(date) => {
// Jika kosong, return false untuk required validation
if (!date || date.trim() === '') return false
// Jika ada isi, validasi format tanggal
try {
const dateObj = new Date(date)
// Cek apakah tanggal valid dan tahun >= 1900
return !isNaN(dateObj.getTime()) && dateObj.getFullYear() >= 1900
} catch {
return false
}
},
{
message: 'Mohon lengkapi Tanggal Lahir dengan format yang valid',
},
)
.transform((dateStr) => new Date(dateStr).toISOString()),
// Jenis Kelamin & Status
gender: z.string({
required_error: 'Pilih Jenis Kelamin',
}),
maritalStatus: z.enum(['TIDAK_DIKETAHUI', 'BELUM_KAWIN', 'KAWIN', 'CERAI_HIDUP', 'CERAI_MATI'], {
required_error: 'Pilih Status Perkawinan',
}),
// Informasi Lokasi & Sosial
job: z
.string({
required_error: 'Mohon lengkapi Pekerjaan',
})
.min(1),
nationality: z.string({
required_error: 'Pilih Kebangsaan',
}),
isNewBorn: IsNewBornSchema,
language: z.string({
required_error: 'Mohon pilih Preferensi Bahasa',
}),
education: z
.string({
required_error: 'Mohon lengkapi Pendidikan',
})
.min(1),
religion: z
.string({
required_error: 'Pilih Kepercayaan',
})
.min(1),
ethnicity: z.string().optional(),
// Disabilitas
disability: z.enum(['YA', 'TIDAK'], {
required_error: 'Mohon lengkapi Status Disabilitas',
}),
disabilityType: z.string().optional(),
// Informasi Kontak
passportNumber: z.string().optional(),
communicationBarrier: CommunicationBarrierSchema,
note: z.string().optional(),
drivingLicenseNumber: z.string().optional(),
})
.refine(
(data) => {
// Jika disability = 'TIDAK', maka disabilityType harus kosong atau undefined
if (data.disability === 'TIDAK') {
return !data.disabilityType || data.disabilityType.trim() === ''
}
return true
},
{
message: "Jenis Disabilitas harus kosong jika Status Disabilitas = 'TIDAK'",
path: ['disabilityType'],
},
)
.refine(
(data) => {
// Jika disability = 'YA', maka disabilityType wajib diisi
if (data.disability === 'YA') {
return !!data.disabilityType?.trim()
}
return true
},
{
message: 'Mohon pilih Jenis Disabilitas',
path: ['disabilityType'],
},
)
// .refine((data) => {
// // Jika nationality = 'WNA', maka passportNumber wajib diisi
// if (data.nationality === 'WNA') {
// return !!data.passportNumber?.trim()
// }
// return true
// }, {
// message: 'Nomor Paspor wajib diisi untuk Warga Negara Asing',
// path: ['passportNumber'],
// })
.transform((data) => {
// Transform untuk backend: hanya kirim disabilityType sesuai kondisi
return {
...data,
// Jika disability = 'YA', kirim disabilityType
// Jika disability = 'TIDAK', kirim null untuk disabilityType
disabilityType: data.disability === 'YA' ? data.disabilityType : null,
// Hapus field disability karena yang dikirim ke backend adalah disabilityType
disability: undefined,
}
})
type PatientFormData = z.infer<typeof PatientSchema>
export { PatientSchema }
export type { PatientFormData }