134 lines
4.0 KiB
TypeScript
134 lines
4.0 KiB
TypeScript
import { z } from 'zod'
|
|
|
|
const ERROR_MESSAGES = {
|
|
required: {
|
|
doctorId: 'Dokter wajib diisi',
|
|
registerDate: 'Tanggal Daftar wajib diisi',
|
|
paymentType: 'Jenis Pembayaran wajib diisi',
|
|
subSpecialistId: 'Subspesialis wajib diisi',
|
|
patientCategory: 'Kelompok Peserta wajib diisi',
|
|
cardNumber: 'No. Kartu BPJS wajib diisi',
|
|
sepType: 'Jenis SEP wajib diisi',
|
|
sepNumber: 'No. SEP wajib diisi',
|
|
},
|
|
}
|
|
|
|
const ACCEPTED_UPLOAD_TYPES = ['image/jpeg', 'image/png', 'application/pdf']
|
|
|
|
const IntegrationEncounterSchema = z
|
|
.object({
|
|
// Patient data (readonly, populated from selected patient)
|
|
patientName: z.string().optional(),
|
|
nationalIdentity: z.string().optional(),
|
|
medicalRecordNumber: z.string().optional(),
|
|
|
|
// Visit data
|
|
doctorId: z
|
|
.string({ required_error: ERROR_MESSAGES.required.doctorId })
|
|
.min(1, ERROR_MESSAGES.required.doctorId),
|
|
subSpecialistId: z
|
|
.string({ required_error: ERROR_MESSAGES.required.subSpecialistId })
|
|
.min(1, ERROR_MESSAGES.required.subSpecialistId)
|
|
.optional(),
|
|
registerDate: z
|
|
.string({ required_error: ERROR_MESSAGES.required.registerDate })
|
|
.min(1, ERROR_MESSAGES.required.registerDate),
|
|
paymentType: z
|
|
.string({ required_error: ERROR_MESSAGES.required.paymentType })
|
|
.min(1, ERROR_MESSAGES.required.paymentType),
|
|
|
|
// BPJS related fields
|
|
patientCategory: z
|
|
.string()
|
|
.min(1, ERROR_MESSAGES.required.patientCategory)
|
|
.optional(),
|
|
cardNumber: z
|
|
.string()
|
|
.min(1, ERROR_MESSAGES.required.cardNumber)
|
|
.optional(),
|
|
sepType: z
|
|
.string()
|
|
.min(1, ERROR_MESSAGES.required.sepType)
|
|
.optional(),
|
|
sepNumber: z
|
|
.string()
|
|
.min(1, ERROR_MESSAGES.required.sepNumber)
|
|
.optional(),
|
|
|
|
// File uploads
|
|
sepFile: z
|
|
.any()
|
|
.optional()
|
|
.refine((f) => !f || f instanceof File, { message: 'Harus berupa file yang valid' })
|
|
.refine((f) => !f || ACCEPTED_UPLOAD_TYPES.includes(f.type), {
|
|
message: 'Format file harus JPG, PNG, atau PDF',
|
|
})
|
|
.refine((f) => !f || f.size <= 1 * 1024 * 1024, { message: 'Maksimal 1MB' }),
|
|
sippFile: z
|
|
.any()
|
|
.optional()
|
|
.refine((f) => !f || f instanceof File, { message: 'Harus berupa file yang valid' })
|
|
.refine((f) => !f || ACCEPTED_UPLOAD_TYPES.includes(f.type), {
|
|
message: 'Format file harus JPG, PNG, atau PDF',
|
|
})
|
|
.refine((f) => !f || f.size <= 1 * 1024 * 1024, { message: 'Maksimal 1MB' }),
|
|
})
|
|
.refine(
|
|
(data) => {
|
|
// If payment type is jkn, then patient category is required
|
|
if (data.paymentType === 'jkn') {
|
|
return data.patientCategory && data.patientCategory.trim() !== ''
|
|
}
|
|
return true
|
|
},
|
|
{
|
|
message: ERROR_MESSAGES.required.patientCategory,
|
|
path: ['patientCategory'],
|
|
},
|
|
)
|
|
.refine(
|
|
(data) => {
|
|
// If payment type is jkn, then card number is required
|
|
if (data.paymentType === 'jkn') {
|
|
return data.cardNumber && data.cardNumber.trim() !== ''
|
|
}
|
|
return true
|
|
},
|
|
{
|
|
message: ERROR_MESSAGES.required.cardNumber,
|
|
path: ['cardNumber'],
|
|
},
|
|
)
|
|
.refine(
|
|
(data) => {
|
|
// If payment type is jkn, then SEP type is required
|
|
if (data.paymentType === 'jkn') {
|
|
return data.sepType && data.sepType.trim() !== ''
|
|
}
|
|
return true
|
|
},
|
|
{
|
|
message: ERROR_MESSAGES.required.sepType,
|
|
path: ['sepType'],
|
|
},
|
|
)
|
|
.refine(
|
|
(data) => {
|
|
// If payment type is jkn and SEP type is selected, then SEP number is required
|
|
if (data.paymentType === 'jkn' && data.sepType && data.sepType.trim() !== '') {
|
|
return data.sepNumber && data.sepNumber.trim() !== ''
|
|
}
|
|
return true
|
|
},
|
|
{
|
|
message: ERROR_MESSAGES.required.sepNumber,
|
|
path: ['sepNumber'],
|
|
},
|
|
)
|
|
|
|
type IntegrationEncounterFormData = z.infer<typeof IntegrationEncounterSchema>
|
|
|
|
export { IntegrationEncounterSchema }
|
|
export type { IntegrationEncounterFormData }
|
|
|