Merge branch 'dev' into feat/encounter-status-107

This commit is contained in:
Andrian Roshandy
2025-10-21 00:15:01 +07:00
324 changed files with 11741 additions and 3976 deletions

No files matched your search

+13
View File
@@ -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 }
+22
View File
@@ -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 }
+22
View File
@@ -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 }
+81 -17
View File
@@ -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>
+49 -16
View File
@@ -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>
+4 -2
View File
@@ -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')
+22
View File
@@ -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 }