Merge branch 'dev' into feat/encounter-status-107
This commit is contained in:
No files matched your search
@@ -0,0 +1,13 @@
|
||||
import { z } from 'zod'
|
||||
import type { CreateDto } from '~/models/consultation'
|
||||
|
||||
const ConsultationSchema = z.object({
|
||||
date: z.string({ required_error: 'Tanggal harus diisi' }),
|
||||
dstUnit_id: z.number({ required_error: 'Unit harus diisi' }),
|
||||
problem: z.string({ required_error: 'Uraian harus diisi' }).min(20, 'Uraian minimum 20 karakter'),
|
||||
})
|
||||
|
||||
type ConsultationFormData = z.infer<typeof ConsultationSchema> & (CreateDto)
|
||||
|
||||
export { ConsultationSchema }
|
||||
export type { ConsultationFormData }
|
||||
@@ -0,0 +1,22 @@
|
||||
import { z } from 'zod'
|
||||
import type { DiagnoseSrc } from '~/models/diagnose-src'
|
||||
|
||||
const DiagnoseSrcSchema = z.object({
|
||||
code: z
|
||||
.string({ required_error: 'Kode harus diisi' })
|
||||
.min(1, 'Kode minimum 1 karakter')
|
||||
.max(10, 'Kode maksimum 10 karakter'),
|
||||
name: z
|
||||
.string({ required_error: 'Nama harus diisi' })
|
||||
.min(1, 'Nama minimum 1 karakter')
|
||||
.max(2048, 'Nama maksimum 2048 karakter'),
|
||||
indName: z
|
||||
.string({ required_error: 'Nama (ID) harus diisi' })
|
||||
.min(1, 'Nama (ID) minimum 1 karakter')
|
||||
.max(2048, 'Nama (ID) maksimum 2048 karakter'),
|
||||
})
|
||||
|
||||
type DiagnoseSrcFormData = z.infer<typeof DiagnoseSrcSchema> & Partial<DiagnoseSrc>
|
||||
|
||||
export { DiagnoseSrcSchema }
|
||||
export type { DiagnoseSrcFormData }
|
||||
@@ -0,0 +1,22 @@
|
||||
import { z } from 'zod'
|
||||
import type { MedicalActionSrc } from '~/models/medical-action-src'
|
||||
|
||||
const MedicalActionSrcSchema = z.object({
|
||||
code: z
|
||||
.string({ required_error: 'Kode harus diisi' })
|
||||
.min(1, 'Kode minimum 1 karakter')
|
||||
.max(10, 'Kode maksimum 10 karakter'),
|
||||
name: z
|
||||
.string({ required_error: 'Nama harus diisi' })
|
||||
.min(1, 'Nama minimum 1 karakter')
|
||||
.max(2048, 'Nama maksimum 2048 karakter'),
|
||||
type_code: z
|
||||
.string({ required_error: 'Nama (ID) harus diisi' })
|
||||
.min(1, 'Nama (ID) minimum 1 karakter')
|
||||
.max(2048, 'Nama (ID) maksimum 2048 karakter'),
|
||||
})
|
||||
|
||||
type MedicalActionSrcFormData = z.infer<typeof MedicalActionSrcSchema> & Partial<MedicalActionSrc>
|
||||
|
||||
export { MedicalActionSrcSchema }
|
||||
export type { MedicalActionSrcFormData }
|
||||
@@ -6,22 +6,46 @@ const CommunicationBarrierSchema = z
|
||||
})
|
||||
.transform((val) => val === 'YA')
|
||||
|
||||
const IsNewBornSchema = z
|
||||
.enum(['YA', 'TIDAK'], {
|
||||
required_error: 'Mohon lengkapi status pasien',
|
||||
})
|
||||
.transform((val) => val === 'YA')
|
||||
|
||||
const ACCEPTED_UPLOAD_TYPES = ['image/jpeg', 'image/png', 'application/pdf']
|
||||
|
||||
const PatientSchema = z
|
||||
.object({
|
||||
// Data Diri Pasien
|
||||
identityNumber: z
|
||||
.string({
|
||||
required_error: 'Mohon lengkapi NIK',
|
||||
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'),
|
||||
residentIdentityFile: 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',
|
||||
})
|
||||
.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' }),
|
||||
.refine((f) => !f || f.size <= 1 * 1024 * 1024, { message: 'Maksimal 1MB' }),
|
||||
|
||||
familyIdentityFile: 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(f => ['image/jpeg', 'image/png'].includes(f.type), 'Hanya JPG/PNG')
|
||||
|
||||
// Informasi Dasar
|
||||
alias: z.string({
|
||||
required_error: 'Mohon pilih sapaan',
|
||||
}),
|
||||
// alias: z.string({
|
||||
// required_error: 'Mohon pilih sapaan',
|
||||
// }),
|
||||
fullName: z.string({
|
||||
required_error: 'Mohon lengkapi Nama',
|
||||
}),
|
||||
@@ -71,6 +95,7 @@ const PatientSchema = z
|
||||
nationality: z.string({
|
||||
required_error: 'Pilih Kebangsaan',
|
||||
}),
|
||||
isNewBorn: IsNewBornSchema,
|
||||
language: z.string({
|
||||
required_error: 'Mohon pilih Preferensi Bahasa',
|
||||
}),
|
||||
@@ -99,13 +124,52 @@ const PatientSchema = z
|
||||
note: z.string().optional(),
|
||||
drivingLicenseNumber: z.string().optional(),
|
||||
})
|
||||
.refine((data) => (data.disability === 'TIDAK' ? !data.disabilityType : true), {
|
||||
message: "DisabilityType hanya boleh diisi jika disability = 'YA'",
|
||||
path: ['disabilityType'],
|
||||
})
|
||||
.refine((data) => (data.disability === 'YA' ? !!data.disabilityType?.trim() : true), {
|
||||
message: 'Mohon pilih Jenis Disabilitas',
|
||||
path: ['disabilityType'],
|
||||
.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>
|
||||
|
||||
@@ -1,25 +1,58 @@
|
||||
import { z } from 'zod'
|
||||
import { PersonAddressSchema } from './person-address.schema'
|
||||
|
||||
// Schema untuk alamat opsional ketika isSameAddress = '1'
|
||||
const OptionalAddressSchema = PersonAddressSchema.partial()
|
||||
const PersonAddressRelativeSchema = z
|
||||
.object({
|
||||
isSameAddress: z
|
||||
.union([z.literal('1'), z.literal('0'), z.boolean()])
|
||||
.default('1')
|
||||
.transform((val) => {
|
||||
if (typeof val === 'boolean') return val ? '1' : '0'
|
||||
return val
|
||||
}),
|
||||
})
|
||||
.merge(PersonAddressSchema.partial())
|
||||
.superRefine((data, ctx) => {
|
||||
const isSameAddress = data.isSameAddress
|
||||
|
||||
// Schema untuk alamat required ketika isSameAddress = '0'
|
||||
const RequiredAddressSchema = PersonAddressSchema
|
||||
// Jika alamat tidak sama ('0'), maka semua field address wajib diisi
|
||||
if (isSameAddress === '0') {
|
||||
const requiredFields = [
|
||||
'province_code',
|
||||
'regency_code',
|
||||
'district_code',
|
||||
'village_code',
|
||||
'postalRegion_code',
|
||||
'address',
|
||||
]
|
||||
|
||||
const PersonAddressRelativeSchema = z.discriminatedUnion('isSameAddress', [
|
||||
z
|
||||
.object({
|
||||
isSameAddress: z.literal('1').default('1'),
|
||||
})
|
||||
.merge(OptionalAddressSchema),
|
||||
requiredFields.forEach((field) => {
|
||||
if (!data[field as keyof typeof data]) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: getRequiredMessage(field),
|
||||
path: [field],
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
.transform((data) => ({
|
||||
...data,
|
||||
isSameAddress: data.isSameAddress === '1',
|
||||
}))
|
||||
|
||||
z
|
||||
.object({
|
||||
isSameAddress: z.literal('0'),
|
||||
})
|
||||
.merge(RequiredAddressSchema),
|
||||
])
|
||||
function getRequiredMessage(field: string): string {
|
||||
const messages: Record<string, string> = {
|
||||
province_code: 'Mohon pilih provinsi',
|
||||
regency_code: 'Mohon pilih kabupaten/kota',
|
||||
district_code: 'Mohon pilih kecamatan',
|
||||
village_code: 'Mohon pilih kelurahan',
|
||||
postalRegion_code: 'Mohon lengkapi kode pos',
|
||||
address: 'Mohon lengkapi alamat',
|
||||
}
|
||||
return messages[field] || `${field} wajib diisi`
|
||||
}
|
||||
|
||||
type PersonAddressRelativeFormData = z.infer<typeof PersonAddressRelativeSchema>
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { z } from 'zod'
|
||||
|
||||
const PersonAddressSchema = z.object({
|
||||
locationType_code: z.string({
|
||||
required_error: 'Mohon pilih jenis alamat',
|
||||
}),
|
||||
address: z.string({
|
||||
required_error: 'Mohon lengkapi alamat',
|
||||
}),
|
||||
@@ -16,8 +19,7 @@ const PersonAddressSchema = z.object({
|
||||
village_code: z.string({
|
||||
required_error: 'Mohon pilih kelurahan',
|
||||
}),
|
||||
// diganti postalCode, zipCode hanya beberapa negara, kurang universal
|
||||
postalCode: z.string({
|
||||
postalRegion_code: z.string({
|
||||
required_error: 'Mohon lengkapi kode pos',
|
||||
}),
|
||||
// .min(5, 'Kode pos harus berupa angka 5 digit')
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import { z } from 'zod'
|
||||
import type { ProcedureSrc } from '~/models/procedure-src'
|
||||
|
||||
const ProcedureSrcSchema = z.object({
|
||||
code: z
|
||||
.string({ required_error: 'Kode harus diisi' })
|
||||
.min(1, 'Kode minimum 1 karakter')
|
||||
.max(10, 'Kode maksimum 10 karakter'),
|
||||
name: z
|
||||
.string({ required_error: 'Nama harus diisi' })
|
||||
.min(1, 'Nama minimum 1 karakter')
|
||||
.max(2048, 'Nama maksimum 2048 karakter'),
|
||||
indName: z
|
||||
.string({ required_error: 'Nama (ID) harus diisi' })
|
||||
.min(1, 'Nama (ID) minimum 1 karakter')
|
||||
.max(2048, 'Nama (ID) maksimum 2048 karakter'),
|
||||
})
|
||||
|
||||
type ProcedureSrcFormData = z.infer<typeof ProcedureSrcSchema> & Partial<ProcedureSrc>
|
||||
|
||||
export { ProcedureSrcSchema }
|
||||
export type { ProcedureSrcFormData }
|
||||
Reference in New Issue
Block a user