fix edit form state

fix: id list for contacts and address list

fix warning

fix duplicate contacts responsible: true

fix edit family

fix nik required
This commit is contained in:
Khafid Prayoga
2025-12-10 12:12:35 +07:00
parent 9918501f29
commit 3cac23ce8a
9 changed files with 54 additions and 45 deletions
+3 -2
View File
@@ -30,7 +30,7 @@ import {
} from './fields'
interface FormData extends PatientFormData {
_calculatedAge: string
_calculatedAge: string | Date
}
// Type untuk initial values (sebelum transform schema)
@@ -66,7 +66,7 @@ interface Props {
const props = defineProps<Props>()
const formSchema = toTypedSchema(PatientSchema)
const { values, resetForm, setValues, setFieldValue, validate } = useForm<FormData>({
const { values, resetForm, setValues, setFieldValue, validate, setFieldError } = useForm<FormData>({
name: 'patientForm',
validationSchema: formSchema,
initialValues: (props.initialValues ?? {}) as any,
@@ -106,6 +106,7 @@ watch(
placeholder="Masukkan NIK"
numeric-only
:is-disabled="isReadonly"
:max-length="16"
/>
<InputBase
field-name="drivingLicenseNumber"
+18 -30
View File
@@ -114,7 +114,9 @@ const patientFormInitialValues = computed(() => {
// Computed: unwrap alamat domisili (alamat sekarang)
const addressFormInitialValues = computed(() => {
const addresses = patientDetail.value.person?.addresses || patientDetail.value.personAddresses || []
if (!patientDetail.value.person?.addresses) return {}
const addresses = patientDetail.value.person?.addresses
const domicileAddress = addresses.find((a: PersonAddress) => a.locationType_code === 'domicile')
if (!domicileAddress) return undefined
@@ -125,6 +127,7 @@ const addressFormInitialValues = computed(() => {
const province = regency?.province
return {
id: domicileAddress.id || 0,
locationType_code: 'domicile',
province_code: province?.code || '',
regency_code: regency?.code || '',
@@ -139,30 +142,11 @@ const addressFormInitialValues = computed(() => {
// Computed: unwrap alamat KTP (identity)
const addressRelativeFormInitialValues = computed(() => {
const addresses = patientDetail.value.person?.addresses || patientDetail.value.personAddresses || []
const domicileAddress = addresses.find((a: PersonAddress) => a.locationType_code === 'domicile')
const identityAddress = addresses.find((a: PersonAddress) => a.locationType_code === 'identity')
if (!patientDetail.value.person?.addresses) return {}
// Jika tidak ada alamat KTP terpisah, berarti sama dengan domisili
if (!identityAddress) {
return {
isSameAddress: '1',
locationType_code: 'identity',
}
}
// Cek apakah alamat sama dengan domisili
const isSame =
domicileAddress &&
identityAddress.village_code === domicileAddress.village_code &&
identityAddress.address === domicileAddress.address
if (isSame) {
return {
isSameAddress: '1',
locationType_code: 'identity',
}
}
const addresses = patientDetail.value.person?.addresses
const domicileAddress = addresses.find((a: PersonAddress) => a.locationType_code === 'domicile')!
const identityAddress = addresses.find((a: PersonAddress) => a.locationType_code === 'identity')!
// extract kode wilayah dari preload data
const village = identityAddress.postalRegion?.village
@@ -170,8 +154,11 @@ const addressRelativeFormInitialValues = computed(() => {
const regency = district?.regency
const province = regency?.province
const isSame = domicileAddress.village_code === identityAddress.village_code ? '1' : '0'
return {
isSameAddress: '0',
isSameAddress: isSame,
id: identityAddress.id || 0,
locationType_code: 'identity',
province_code: province?.code || '',
regency_code: regency?.code || '',
@@ -201,6 +188,7 @@ const familyFormInitialValues = computed(() => {
return {
shareFamilyData: '1',
families: parents.map((parent: PersonRelative) => ({
id: parent.id || 0,
relation: parent.relationship_code || '',
name: parent.name || '',
education: parent.education_code || '',
@@ -216,6 +204,7 @@ const contactFormInitialValues = computed(() => {
return {
contacts: contacts.map((contact: PersonContact) => ({
id: contact.id || 0,
contactType: reverseContactTypeMapping[contact.type_code] || contact.type_code || '',
contactNumber: contact.value || '',
})),
@@ -231,6 +220,7 @@ const responsibleFormInitialValues = computed(() => {
return {
contacts: responsibles.map((r: PersonRelative) => ({
id: r.id || 0,
relation: r.relationship_code || '',
name: r.name || '',
address: r.address || '',
@@ -272,6 +262,7 @@ async function composeFormData(): Promise<PatientEntity> {
...patient?.values,
// casting comp. val to backend well known reflect value
ethnic: patient?.values.nationality === 'WNI' ? patient?.values.ethnic : null,
birthDate: parseISO(patient?.values.birthDate || ''),
isNewBorn: patient?.values.isNewBorn === 'yes',
communicationBarrier: patient?.values.communicationBarrier === 'yes',
@@ -327,8 +318,7 @@ async function handleActionClick(eventType: string) {
let createdPatientId = 0
let response: any
// If edit mode, update patient
// return
if (props.mode === 'edit' && props.patientId) {
response = await handleActionEdit(
patientDetail.value.id,
@@ -337,9 +327,7 @@ async function handleActionClick(eventType: string) {
() => {},
toast,
)
}
// If create mode, create patient
else {
} else {
response = await handleActionSave(
patient,
() => {},
+8 -4
View File
@@ -15,7 +15,7 @@ import { contactTypeMapping } from '~/lib/constants'
export interface PatientBase extends Base {
person_id?: number | null
newBornStatus?: boolean
newBornStatus?: boolean | string
registeredAt?: Date | string | null
status_code?: string | null
number?: string | null
@@ -40,6 +40,7 @@ export interface genPatientProps {
export function genPatientEntity(props: genPatientProps, patientData: PatientEntity | null): PatientEntity {
const { patient, residentAddress, cardAddress, familyData, contacts, responsible } = props
// const val = toRaw(patientData)
const addresses: PersonAddress[] = [{ ...genBase(), person_id: patientData?.person?.id || 0, ...residentAddress }]
const familiesContact: PersonRelative[] = []
const personContacts: PersonContact[] = []
@@ -49,6 +50,7 @@ export function genPatientEntity(props: genPatientProps, patientData: PatientEnt
addresses.push({
...genBase(),
...residentAddress,
id: cardAddress.id || 0,
person_id: 0,
locationType_code: cardAddress.locationType_code || 'identity',
})
@@ -57,6 +59,7 @@ export function genPatientEntity(props: genPatientProps, patientData: PatientEnt
// Pastikan semua field yang diperlukan ada
const relativeAddress = {
...genBase(),
id: cardAddress.id || 0,
person_id: patientData?.person?.id || 0,
locationType_code: cardAddress.locationType_code || 'identity',
address: cardAddress.address || '',
@@ -75,7 +78,7 @@ export function genPatientEntity(props: genPatientProps, patientData: PatientEnt
if (familyData.shareFamilyData === '1') {
for (const family of familyData.families) {
familiesContact.push({
id: 0,
id: family.id || 0,
relationship_code: family.relation,
name: family.name,
education_code: family.education,
@@ -94,6 +97,7 @@ export function genPatientEntity(props: genPatientProps, patientData: PatientEnt
personContacts.push({
...genBase(),
id: contact.id || 0,
person_id: patientData?.person?.id || 0,
type_code: mappedContactType || '',
value: contact.contactNumber,
@@ -105,7 +109,7 @@ export function genPatientEntity(props: genPatientProps, patientData: PatientEnt
if (responsible) {
for (const contact of responsible.contacts) {
familiesContact.push({
id: 0,
id: contact.id || 0,
relationship_code: contact.relation,
name: contact.name,
address: contact.address,
@@ -164,7 +168,7 @@ export function genPatientEntity(props: genPatientProps, patientData: PatientEnt
export interface Patient extends Base {
person_id?: number | null
person: Person
newBornStatus?: boolean
newBornStatus?: boolean | string
registeredAt?: Date | string | null
status_code?: string | null
number?: string | null
+1 -1
View File
@@ -26,7 +26,7 @@ export interface Person extends Base {
ethnic_code?: string | null
language_code?: string | null
nationality?: string | null
communicationIssueStatus?: boolean
communicationIssueStatus?: boolean | string
disability?: string | null
residentIdentityFileUrl?: string | null
passportFileUrl?: string | null
+16 -8
View File
@@ -6,11 +6,6 @@ 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'),
residentIdentityFile: z
.any()
.optional()
@@ -58,8 +53,8 @@ const PatientSchema = z
nationality: z.string({
required_error: 'Pilih Kebangsaan',
}),
isNewBorn: z.string({
required_error: 'Mohon lengkapi status pasien',
isNewBorn: z.union([z.boolean(), z.string()], {
required_error: 'Mohon lengkapi Status Disabilitas',
}),
language: z.string({
required_error: 'Mohon pilih Preferensi Bahasa',
@@ -84,7 +79,7 @@ const PatientSchema = z
// Informasi Kontak
passportNumber: z.string().optional(),
communicationBarrier: z.string({
communicationBarrier: z.union([z.boolean(), z.string()], {
required_error: 'Mohon lengkapi Status Hambatan Berkomunikasi',
}),
@@ -103,6 +98,19 @@ const PatientSchema = z
path: ['disabilityType'],
},
)
.refine(
(data) => {
if (data.nationality === 'WNI') {
const nik = data.identityNumber?.trim()
return !!nik && nik.length === 16 && /^\d+$/.test(nik)
}
return true
},
{
message: 'NIK harus berupa angka 16 digit',
path: ['identityNumber'],
},
)
// .transform((data) => {
// return {
// ...data,
+2
View File
@@ -1,6 +1,8 @@
import { z } from 'zod'
const PersonAddressSchema = z.object({
id: z.number().optional(),
locationType_code: z.string({
required_error: 'Mohon pilih jenis alamat',
}),
+2
View File
@@ -1,6 +1,8 @@
import { z } from 'zod'
const PersonContactBaseSchema = z.object({
id: z.number().optional(),
contactType: z.string({ required_error: 'Mohon pilih tipe kontak' }).min(1, 'Mohon pilih tipe kontak'),
contactNumber: z.string({ required_error: 'Nomor kontak harus diisi' }).min(8, 'Nomor minimal 8 digit'),
})
+2
View File
@@ -1,6 +1,7 @@
import { z } from 'zod'
const PersonFamilySchema = z.object({
id: z.number().optional(),
relation: z.enum(['mother', 'father', 'guardian', 'emergency_contact']),
name: z
.string({
@@ -29,6 +30,7 @@ const PersonFamiliesSchema = z.discriminatedUnion('shareFamilyData', [
interface PersonFamiliesFormData {
shareFamilyData: '0' | '1'
families: {
id?: number
relation: 'mother' | 'father' | 'guardian' | 'emergency_contact'
name: string
education: string
+2
View File
@@ -1,6 +1,8 @@
import { z } from 'zod'
const ResponsibleContactPersonSchema = z.object({
id: z.number().optional(),
relation: z.string({ required_error: 'Pilih jenis Penanggung Jawab' }).min(1, 'Pilih jenis Penanggung Jawab'),
name: z.string({ required_error: 'Mohon lengkapi Nama' }).min(3, 'Mohon lengkapi Nama'),
address: z.string({ required_error: 'Mohon lengkapi Alamat' }).min(3, 'Mohon lengkapi Alamat'),