diff --git a/app/assets/css/main.css b/app/assets/css/main.css index cab62d6e..17502027 100644 --- a/app/assets/css/main.css +++ b/app/assets/css/main.css @@ -174,7 +174,7 @@ body { } body, table, label { - @apply md:!text-xs 2xl:!text-sm; + @apply md:!text-xs 2xl:!text-sm; } /* Container */ diff --git a/app/components/app/diagnose-src/entry-form.vue b/app/components/app/diagnose-src/entry-form.vue new file mode 100644 index 00000000..3f84b2a2 --- /dev/null +++ b/app/components/app/diagnose-src/entry-form.vue @@ -0,0 +1,137 @@ + + + diff --git a/app/components/app/diagnose-src/list-cfg.ts b/app/components/app/diagnose-src/list-cfg.ts new file mode 100644 index 00000000..0a576270 --- /dev/null +++ b/app/components/app/diagnose-src/list-cfg.ts @@ -0,0 +1,33 @@ +import type { Config, RecComponent } from '~/components/pub/my-ui/data-table' +import { defineAsyncComponent } from 'vue' + +const action = defineAsyncComponent(() => import('~/components/pub/my-ui/data/dropdown-action-dud.vue')) + +export const config: Config = { + cols: [{}, {}, {}, { width: 50 }], + + headers: [[{ label: 'Kode' }, { label: 'Nama (FHIR)' }, { label: 'Nama (ID)' }, { label: '' }]], + + keys: ['code', 'name', 'indName', 'action'], + + delKeyNames: [ + { key: 'code', label: 'Kode' }, + { key: 'name', label: 'Nama (FHIR)' }, + { key: 'indName', label: 'Nama (ID)' }, + ], + + parses: {}, + + components: { + action(rec, idx) { + const res: RecComponent = { + idx, + rec: rec as object, + component: action, + } + return res + }, + }, + + htmls: {}, +} diff --git a/app/components/app/diagnose-src/list.vue b/app/components/app/diagnose-src/list.vue new file mode 100644 index 00000000..1be60a60 --- /dev/null +++ b/app/components/app/diagnose-src/list.vue @@ -0,0 +1,36 @@ + + + diff --git a/app/components/app/encounter/entry-form.vue b/app/components/app/encounter/entry-form.vue index fd6c8da9..25bdf9d8 100644 --- a/app/components/app/encounter/entry-form.vue +++ b/app/components/app/encounter/entry-form.vue @@ -108,248 +108,246 @@ function onAddSep() { :initial-values="initialValues" >
-
-
-
-

Data Pasien

-
-
- - Sudah pernah terdaftar sebagai pasien? - - - - Belum pernah terdaftar sebagai pasien? - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Data Kunjungan

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - -
- - - -
-
- -
-
-
-
- - - - - - - - -
- - - -
-
- -
-
-
-
- +
+
+ Data Pasien
+
+ + Sudah pernah terdaftar sebagai pasien? + + + + Belum pernah terdaftar sebagai pasien? + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Data Kunjungan +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + +
+ + + +
+
+ +
+
+
+
+ + + + + + + + +
+ + + +
+
+ +
+
+
+
+
diff --git a/app/components/app/medical-action-src/entry-form.vue b/app/components/app/medical-action-src/entry-form.vue new file mode 100644 index 00000000..f8bf87e4 --- /dev/null +++ b/app/components/app/medical-action-src/entry-form.vue @@ -0,0 +1,144 @@ + + + diff --git a/app/components/app/medical-action-src/list-cfg.ts b/app/components/app/medical-action-src/list-cfg.ts new file mode 100644 index 00000000..2fecde69 --- /dev/null +++ b/app/components/app/medical-action-src/list-cfg.ts @@ -0,0 +1,32 @@ +import type { Config, RecComponent } from '~/components/pub/my-ui/data-table' +import { defineAsyncComponent } from 'vue' + +const action = defineAsyncComponent(() => import('~/components/pub/my-ui/data/dropdown-action-dud.vue')) + +export const config: Config = { + cols: [{}, {}, {}, { width: 50 }], + + headers: [[{ label: 'Kode' }, { label: 'Nama' }, { label: '' }]], + + keys: ['code', 'name', 'action'], + + delKeyNames: [ + { key: 'code', label: 'Kode' }, + { key: 'name', label: 'Nama ' }, + ], + + parses: {}, + + components: { + action(rec, idx) { + const res: RecComponent = { + idx, + rec: rec as object, + component: action, + } + return res + }, + }, + + htmls: {}, +} diff --git a/app/components/app/medical-action-src/list.vue b/app/components/app/medical-action-src/list.vue new file mode 100644 index 00000000..1be60a60 --- /dev/null +++ b/app/components/app/medical-action-src/list.vue @@ -0,0 +1,36 @@ + + + diff --git a/app/components/app/patient/_common/input-name.vue b/app/components/app/patient/_common/input-name.vue new file mode 100644 index 00000000..db9005f1 --- /dev/null +++ b/app/components/app/patient/_common/input-name.vue @@ -0,0 +1,54 @@ + + + diff --git a/app/components/app/patient/_common/input-patient-name.vue b/app/components/app/patient/_common/input-patient-name.vue deleted file mode 100644 index fbc57351..00000000 --- a/app/components/app/patient/_common/input-patient-name.vue +++ /dev/null @@ -1,102 +0,0 @@ - - - diff --git a/app/components/app/patient/_common/radio-communication-barrier.vue b/app/components/app/patient/_common/radio-communication-barrier.vue index 463b3659..56918101 100644 --- a/app/components/app/patient/_common/radio-communication-barrier.vue +++ b/app/components/app/patient/_common/radio-communication-barrier.vue @@ -1,12 +1,11 @@ diff --git a/app/components/app/patient/_common/radio-disability.vue b/app/components/app/patient/_common/radio-disability.vue index 312c3730..6c1464e2 100644 --- a/app/components/app/patient/_common/radio-disability.vue +++ b/app/components/app/patient/_common/radio-disability.vue @@ -1,12 +1,11 @@ diff --git a/app/components/app/patient/_common/radio-gender.vue b/app/components/app/patient/_common/radio-gender.vue index 108b1d22..47968c8f 100644 --- a/app/components/app/patient/_common/radio-gender.vue +++ b/app/components/app/patient/_common/radio-gender.vue @@ -1,13 +1,12 @@ diff --git a/app/components/app/patient/_common/radio-nationality.vue b/app/components/app/patient/_common/radio-nationality.vue index 9c0eef1d..40525dff 100644 --- a/app/components/app/patient/_common/radio-nationality.vue +++ b/app/components/app/patient/_common/radio-nationality.vue @@ -1,12 +1,11 @@ diff --git a/app/components/app/patient/_common/radio-newborn.vue b/app/components/app/patient/_common/radio-newborn.vue new file mode 100644 index 00000000..86953443 --- /dev/null +++ b/app/components/app/patient/_common/radio-newborn.vue @@ -0,0 +1,92 @@ + + + diff --git a/app/components/app/patient/_common/select-disability.vue b/app/components/app/patient/_common/select-disability.vue index de65a07f..6058773a 100644 --- a/app/components/app/patient/_common/select-disability.vue +++ b/app/components/app/patient/_common/select-disability.vue @@ -1,11 +1,10 @@ diff --git a/app/components/app/patient/_common/select-dob.vue b/app/components/app/patient/_common/select-dob.vue index 938bd254..eee11acc 100644 --- a/app/components/app/patient/_common/select-dob.vue +++ b/app/components/app/patient/_common/select-dob.vue @@ -1,12 +1,11 @@ diff --git a/app/components/app/patient/_common/select-education.vue b/app/components/app/patient/_common/select-education.vue index 33caac16..848ed614 100644 --- a/app/components/app/patient/_common/select-education.vue +++ b/app/components/app/patient/_common/select-education.vue @@ -1,12 +1,11 @@ diff --git a/app/components/app/patient/_common/select-ethnicity.vue b/app/components/app/patient/_common/select-ethnicity.vue index e1ecd08a..43ef6cba 100644 --- a/app/components/app/patient/_common/select-ethnicity.vue +++ b/app/components/app/patient/_common/select-ethnicity.vue @@ -1,11 +1,10 @@ diff --git a/app/components/app/patient/_common/select-gender.vue b/app/components/app/patient/_common/select-gender.vue new file mode 100644 index 00000000..dfedf9ec --- /dev/null +++ b/app/components/app/patient/_common/select-gender.vue @@ -0,0 +1,76 @@ + + + diff --git a/app/components/app/patient/_common/select-job.vue b/app/components/app/patient/_common/select-job.vue index b14cbb66..814eb7ca 100644 --- a/app/components/app/patient/_common/select-job.vue +++ b/app/components/app/patient/_common/select-job.vue @@ -1,10 +1,10 @@ diff --git a/app/components/app/patient/_common/select-lang.vue b/app/components/app/patient/_common/select-lang.vue index aadf9313..ce5bbac8 100644 --- a/app/components/app/patient/_common/select-lang.vue +++ b/app/components/app/patient/_common/select-lang.vue @@ -1,11 +1,10 @@ diff --git a/app/components/app/patient/_common/select-marital-status.vue b/app/components/app/patient/_common/select-marital-status.vue index cb3b56fb..21ebf0c2 100644 --- a/app/components/app/patient/_common/select-marital-status.vue +++ b/app/components/app/patient/_common/select-marital-status.vue @@ -1,11 +1,10 @@ diff --git a/app/components/app/patient/_common/select-religion.vue b/app/components/app/patient/_common/select-religion.vue index 069e3575..6a1fec66 100644 --- a/app/components/app/patient/_common/select-religion.vue +++ b/app/components/app/patient/_common/select-religion.vue @@ -1,12 +1,11 @@ diff --git a/app/components/app/patient/entry-form.vue b/app/components/app/patient/entry-form.vue index e3587988..a83189c2 100644 --- a/app/components/app/patient/entry-form.vue +++ b/app/components/app/patient/entry-form.vue @@ -3,12 +3,14 @@ import type { FormErrors } from '~/types/error' import { toTypedSchema } from '@vee-validate/zod' import { Form } from '~/components/pub/ui/form' import InputBase from '~/components/pub/my-ui/form/input-base.vue' -import InputFile from './_common/input-file.vue' -import InputPatientName from './_common/input-patient-name.vue' +import FileUpload from '~/components/pub/my-ui/form/file-field.vue' +import InputName from './_common/input-name.vue' import RadioCommunicationBarrier from './_common/radio-communication-barrier.vue' import RadioDisability from './_common/radio-disability.vue' -import RadioGender from './_common/radio-gender.vue' +import SelectGender from './_common/select-gender.vue' import RadioNationality from './_common/radio-nationality.vue' +import RadioNewborn from './_common/radio-newborn.vue' +import SelectBirthPlace from '~/components/app/person/_common/select-birth-place.vue' import SelectDisability from './_common/select-disability.vue' import SelectDob from './_common/select-dob.vue' import SelectEducation from './_common/select-education.vue' @@ -17,6 +19,9 @@ import SelectJob from './_common/select-job.vue' import SelectLanguage from './_common/select-lang.vue' import SelectMaritalStatus from './_common/select-marital-status.vue' import SelectReligion from './_common/select-religion.vue' +import Separator from '~/components/pub/ui/separator/Separator.vue' + +import * as DE from '~/components/pub/my-ui/doc-entry' const props = defineProps<{ schema: any @@ -46,180 +51,161 @@ defineExpose({ validation-mode="onSubmit" :initial-values="initialValues ? initialValues : {}" > -
-

Data Diri Pasien

-
- -
-
- - -
-
- - -
-
+

Data Diri Pasien

+ + + + + + + + + + + + + + + + + + + + + + -
-

Dokumen Identitas

+
-
- - - - -
-
- - -
-
- -
-

Data Demografis

- -
- - - -
-
- - - -
-
- -
-

Kondisi Khusus

-
- -
- - -
- - -
-
+

Dokumen Identitas

+ + + + diff --git a/app/components/app/patient/list-cfg.ts b/app/components/app/patient/list-cfg.ts index e8d2b220..559428a7 100644 --- a/app/components/app/patient/list-cfg.ts +++ b/app/components/app/patient/list-cfg.ts @@ -1,5 +1,5 @@ import type { Config } from '~/components/pub/my-ui/data-table' -import type { PatientEntity } from '~/models/patient' +import type { Patient } from '~/models/patient' import { defineAsyncComponent } from 'vue' import { educationCodes, genderCodes } from '~/lib/constants' import { calculateAge } from '~/lib/utils' @@ -11,8 +11,9 @@ export const config: Config = { headers: [ [ + { label: 'ID' }, { label: 'Nama' }, - { label: 'NIK' }, + { label: 'NIK/No. Paspor' }, { label: 'Tgl Lahir' }, { label: 'Umur' }, { label: 'Jenis Kelamin' }, @@ -21,15 +22,7 @@ export const config: Config = { ], ], - keys: [ - 'name', - 'identity_number', - 'birth_date', - 'patient_age', - 'gender', - 'education', - 'action', - ], + keys: ['patientId', 'name', 'identity_number', 'birth_date', 'patient_age', 'gender', 'education', 'action'], delKeyNames: [ { key: 'code', label: 'Kode' }, @@ -37,33 +30,41 @@ export const config: Config = { ], parses: { + patientId: (rec: unknown): unknown => { + const patient = rec as Patient + return patient.number + }, name: (rec: unknown): unknown => { - const { person } = rec as PatientEntity + const { person } = rec as Patient return person.name.trim() }, identity_number: (rec: unknown): unknown => { - const { person } = rec as PatientEntity - if (person?.residentIdentityNumber?.substring(0, 5) === 'BLANK') { - return '(TANPA NIK)' + const { person } = rec as Patient + + if (person.nationality == 'WNA') { + return person.passportNumber } - return person.residentIdentityNumber + + return person.residentIdentityNumber || '-' }, birth_date: (rec: unknown): unknown => { - const { person } = rec as PatientEntity - if (typeof person.birthDate === 'object' && person.birthDate) { - return (person.birthDate as Date).toLocaleDateString() - } else if (typeof person.birthDate === 'string') { - return person.birthDate.substring(0, 10) + const { person } = rec as Patient + + if (typeof person.birthDate == 'object' && person.birthDate) { + return (person.birthDate as Date).toLocaleDateString('id-ID') + } else if (typeof person.birthDate == 'string') { + return (person.birthDate as string).substring(0, 10) } return person.birthDate }, patient_age: (rec: unknown): unknown => { - const { person } = rec as PatientEntity + const { person } = rec as Patient return calculateAge(person.birthDate) }, gender: (rec: unknown): unknown => { - const { person } = rec as PatientEntity - if (typeof person.gender_code === 'number' && person.gender_code >= 0) { + const { person } = rec as Patient + + if (typeof person.gender_code == 'number' && person.gender_code >= 0) { return person.gender_code } else if (typeof person.gender_code === 'string' && person.gender_code) { return genderCodes[person.gender_code] || '-' @@ -71,8 +72,8 @@ export const config: Config = { return '-' }, education: (rec: unknown): unknown => { - const { person } = rec as PatientEntity - if (typeof person.education_code === 'number' && person.education_code >= 0) { + const { person } = rec as Patient + if (typeof person.education_code == 'number' && person.education_code >= 0) { return person.education_code } else if (typeof person.education_code === 'string' && person.education_code) { return educationCodes[person.education_code] || '-' diff --git a/app/components/app/patient/list.cfg.ts b/app/components/app/patient/list.cfg.ts new file mode 100644 index 00000000..d86c8dc1 --- /dev/null +++ b/app/components/app/patient/list.cfg.ts @@ -0,0 +1,96 @@ +import type { Config } from '~/components/pub/my-ui/data-table' +import type { Patient } from '~/models/patient' +import { defineAsyncComponent } from 'vue' +import { educationCodes, genderCodes } from '~/lib/constants' +import { calculateAge } from '~/lib/utils' + +const action = defineAsyncComponent(() => import('~/components/pub/my-ui/data/dropdown-action-dud.vue')) + +export const config: Config = { + cols: [{}, {}, {}, {}, {}, {}, {}, { width: 5 }], + + headers: [ + [ + { label: 'No. RM' }, + { label: 'Nama' }, + { label: 'No. KTP/SIM/Passpor' }, + { label: 'Tgl Lahir' }, + { label: 'Umur' }, + { label: 'Kelamin' }, + { label: 'Pendidikan' }, + { label: '' }, + ], + ], + + keys: ['number', 'person.name', 'identity_number', 'birth_date', 'patient_age', 'gender', 'education', 'action'], + + delKeyNames: [ + { key: 'code', label: 'Kode' }, + { key: 'name', label: 'Nama' }, + ], + + parses: { + patientId: (rec: unknown): unknown => { + const patient = rec as Patient + return patient.number + }, + identity_number: (rec: unknown): unknown => { + const { person } = rec as Patient + + if (person.nationality == 'WNA') { + return person.passportNumber + } + + return person.residentIdentityNumber || '-' + }, + birth_date: (rec: unknown): unknown => { + const { person } = rec as Patient + + if (typeof person.birthDate == 'object' && person.birthDate) { + return (person.birthDate as Date).toLocaleDateString('id-ID') + } else if (typeof person.birthDate == 'string') { + return (person.birthDate as string).substring(0, 10) + } + return person.birthDate + }, + patient_age: (rec: unknown): unknown => { + const { person } = rec as Patient + return calculateAge(person.birthDate) + }, + gender: (rec: unknown): unknown => { + const { person } = rec as Patient + + if (typeof person.gender_code == 'number' && person.gender_code >= 0) { + return person.gender_code + } else if (typeof person.gender_code === 'string' && person.gender_code) { + return genderCodes[person.gender_code] || '-' + } + return '-' + }, + education: (rec: unknown): unknown => { + const { person } = rec as Patient + if (typeof person.education_code == 'number' && person.education_code >= 0) { + return person.education_code + } else if (typeof person.education_code === 'string' && person.education_code) { + return educationCodes[person.education_code] || '-' + } + return '-' + }, + }, + + components: { + action(rec, idx) { + return { + idx, + rec: rec as object, + component: action, + } + }, + }, + + htmls: { + patient_address(_rec) { + return '-' + }, + }, +} diff --git a/app/components/app/patient/list.vue b/app/components/app/patient/list.vue index c12f409f..8274e752 100644 --- a/app/components/app/patient/list.vue +++ b/app/components/app/patient/list.vue @@ -1,7 +1,7 @@ diff --git a/app/components/app/person-address/_common/select-postal.vue b/app/components/app/person-address/_common/select-postal.vue index 83b33786..56867c7f 100644 --- a/app/components/app/person-address/_common/select-postal.vue +++ b/app/components/app/person-address/_common/select-postal.vue @@ -6,8 +6,11 @@ import Field from '~/components/pub/my-ui/form/field.vue' import Label from '~/components/pub/my-ui/form/label.vue' import { cn } from '~/lib/utils' +import * as DE from '~/components/pub/my-ui/doc-entry' + const props = defineProps<{ fieldName: string + villageCode?: string isDisabled?: boolean placeholder?: string errors?: FormErrors @@ -17,37 +20,32 @@ const props = defineProps<{ isRequired?: boolean }>() -const { - fieldName = 'zipCode', - placeholder = 'Kode Pos', - errors, - class: containerClass, - selectClass, - fieldGroupClass, -} = props +const { fieldName = 'postalRegion', placeholder = 'Kode Pos', errors, class: containerClass, fieldGroupClass } = props -const postalCodeOptions = [ - { label: '65120', value: '65120' }, - { label: '65121', value: '65121' }, - { label: '65123', value: '65123' }, - { label: '65124', value: '65124' }, - { label: '65125', value: '65125' }, - { label: '65126', value: '65126' }, - { label: '65127', value: '65127' }, - { label: '65128', value: '65128' }, - { label: '65129', value: '65129' }, -] +const villageCodeRef = toRef(props, 'villageCode') +const { postalRegionOptions, isLoading, error } = usePostalRegion(villageCodeRef) + +const dynamicPlaceholder = computed(() => { + if (!props.villageCode) return 'Pilih kelurahan terlebih dahulu' + if (isLoading.value) return 'Memuat kode pos...' + if (error.value) return 'Gagal memuat data' + return placeholder +}) + +const isFieldDisabled = computed(() => { + return props.isDisabled || !props.villageCode || isLoading.value || !!error.value +}) diff --git a/app/components/app/person-address/_common/select-province.vue b/app/components/app/person-address/_common/select-province.vue index f8cc5464..ca6dd51a 100644 --- a/app/components/app/person-address/_common/select-province.vue +++ b/app/components/app/person-address/_common/select-province.vue @@ -6,8 +6,10 @@ import Field from '~/components/pub/my-ui/form/field.vue' import Label from '~/components/pub/my-ui/form/label.vue' import { cn } from '~/lib/utils' +import * as DE from '~/components/pub/my-ui/doc-entry' + const props = defineProps<{ - fieldName: string + fieldName?: string isDisabled?: boolean placeholder?: string errors?: FormErrors @@ -18,29 +20,38 @@ const props = defineProps<{ }>() const { - fieldName = 'provinceId', + fieldName = 'provinceCode', placeholder = 'Pilih provinsi', errors, class: containerClass, fieldGroupClass, } = props -const provinceList = [ - { label: 'Jawa Barat', value: '18' }, - { label: 'Jawa Tengah', value: '33' }, - { label: 'Jawa Timur', value: '35' }, -] +// Gunakan composable untuk mengelola data provinces +const { provinceOptions, isLoading, error } = useProvinces() + +// Computed untuk menentukan placeholder berdasarkan state +const dynamicPlaceholder = computed(() => { + if (isLoading.value) return 'Memuat data provinsi...' + if (error.value) return 'Gagal memuat data' + return placeholder +}) + +// Computed untuk menentukan apakah field disabled +const isFieldDisabled = computed(() => { + return props.isDisabled || isLoading.value || !!error.value +}) diff --git a/app/components/app/person-address/_common/select-regency.vue b/app/components/app/person-address/_common/select-regency.vue index 9b415b6e..8fbf6f23 100644 --- a/app/components/app/person-address/_common/select-regency.vue +++ b/app/components/app/person-address/_common/select-regency.vue @@ -6,8 +6,11 @@ import Field from '~/components/pub/my-ui/form/field.vue' import Label from '~/components/pub/my-ui/form/label.vue' import { cn } from '~/lib/utils' +import * as DE from '~/components/pub/my-ui/doc-entry' + const props = defineProps<{ - fieldName: string + fieldName?: string + provinceCode?: string isDisabled?: boolean placeholder?: string errors?: FormErrors @@ -17,26 +20,41 @@ const props = defineProps<{ isRequired?: boolean }>() -const { placeholder = 'Pilih kabupaten/kota', errors, class: containerClass, selectClass, fieldGroupClass } = props +const { + fieldName = 'regencyId', + placeholder = 'Pilih kabupaten/kota', + errors, + class: containerClass, + fieldGroupClass, +} = props -const regencyOptions = [ - { label: 'Kab. Sidoarjo', value: '32' }, - { label: 'Kab. Malang', value: '35' }, - { label: 'Kab. Mojokerto', value: '31' }, - { label: 'Kab. Lamongan', value: '30' }, - { label: 'Kota Malang', value: '18' }, -] +// Gunakan composable untuk mengelola data regencies +const provinceCodeRef = toRef(props, 'provinceCode') +const { regencyOptions, isLoading, error } = useRegencies({ provinceCode: provinceCodeRef, enablePagination: false }) + +// Computed untuk menentukan placeholder berdasarkan state +const dynamicPlaceholder = computed(() => { + if (!props.provinceCode) return 'Pilih provinsi dahulu' + if (isLoading.value) return 'Memuat data kabupaten/kota...' + if (error.value) return 'Gagal memuat data' + return placeholder +}) + +// Computed untuk menentukan apakah field disabled +const isFieldDisabled = computed(() => { + return props.isDisabled || !props.provinceCode || isLoading.value || !!error.value +}) diff --git a/app/components/app/person-address/_common/select-village.vue b/app/components/app/person-address/_common/select-village.vue index a3d7725c..9684954f 100644 --- a/app/components/app/person-address/_common/select-village.vue +++ b/app/components/app/person-address/_common/select-village.vue @@ -6,8 +6,11 @@ import Field from '~/components/pub/my-ui/form/field.vue' import Label from '~/components/pub/my-ui/form/label.vue' import { cn } from '~/lib/utils' +import * as DE from '~/components/pub/my-ui/doc-entry' + const props = defineProps<{ - fieldName: string + fieldName?: string + districtCode?: string isDisabled?: boolean placeholder?: string errors?: FormErrors @@ -17,25 +20,41 @@ const props = defineProps<{ isRequired?: boolean }>() -const { placeholder = 'Pilih Kelurahan', errors, class: containerClass, selectClass, fieldGroupClass } = props +const { + fieldName = 'villageId', + placeholder = 'Pilih kelurahan', + errors, + class: containerClass, + fieldGroupClass, +} = props -const villageOptions = [ - { label: 'Lowokwaru', value: '18' }, - { label: 'Dinoyo', value: '33' }, - { label: 'Blimbing', value: '35' }, - { label: 'Sawojajar', value: '36' }, -] +// Gunakan composable untuk mengelola data villages +const districtCodeRef = toRef(props, 'districtCode') +const { villageOptions, isLoading, error } = useVillages(districtCodeRef) + +// Computed untuk menentukan placeholder berdasarkan state +const dynamicPlaceholder = computed(() => { + if (!props.districtCode) return 'Pilih kecamatan dahulu' + if (isLoading.value) return 'Memuat data kelurahan...' + if (error.value) return 'Gagal memuat data' + return placeholder +}) + +// Computed untuk menentukan apakah field disabled +const isFieldDisabled = computed(() => { + return props.isDisabled || !props.districtCode || isLoading.value || !!error.value +}) diff --git a/app/components/app/person-address/entry-form-relative.vue b/app/components/app/person-address/entry-form-relative.vue index 1c8c91a7..cc294bab 100644 --- a/app/components/app/person-address/entry-form-relative.vue +++ b/app/components/app/person-address/entry-form-relative.vue @@ -6,7 +6,8 @@ import FieldGroup from '~/components/pub/my-ui/form/field-group.vue' import Field from '~/components/pub/my-ui/form/field.vue' import InputBase from '~/components/pub/my-ui/form/input-base.vue' import Label from '~/components/pub/my-ui/form/label.vue' -import RadioResidence from './_common/radio-residence.vue' +import { Label as RadioLabel } from '~/components/pub/ui/label' +import { RadioGroup, RadioGroupItem } from '~/components/pub/ui/radio-group' import SelectDistrict from './_common/select-district.vue' import SelectPostal from './_common/select-postal.vue' import SelectProvince from './_common/select-province.vue' @@ -14,6 +15,8 @@ import SelectRegency from './_common/select-regency.vue' import SelectVillage from './_common/select-village.vue' import { Form } from '~/components/pub/ui/form' +import * as DE from '~/components/pub/my-ui/doc-entry' + const props = defineProps<{ title: string conf?: { @@ -39,18 +42,27 @@ let isResetting = false // Field dependency map for placeholder const fieldStates: Record = { - regencyId: { dependsOn: 'provinceId', placeholder: 'Pilih provinsi dahulu' }, - districtId: { dependsOn: 'regencyId', placeholder: 'Pilih kabupaten/kota dahulu' }, - villageId: { dependsOn: 'districtId', placeholder: 'Pilih kecamatan dahulu' }, - zipCode: { dependsOn: 'villageId', placeholder: 'Pilih kelurahan dahulu' }, + regency_code: { dependsOn: 'province_code', placeholder: 'Pilih provinsi dahulu' }, + district_code: { dependsOn: 'regency_code', placeholder: 'Pilih kabupaten/kota dahulu' }, + village_code: { dependsOn: 'district_code', placeholder: 'Pilih kecamatan dahulu' }, + postalRegion_code: { dependsOn: 'village_code', placeholder: 'Pilih kelurahan dahulu' }, address: { placeholder: 'Masukkan alamat' }, rt: { placeholder: '001' }, rw: { placeholder: '002' }, } + +// Computed untuk konversi boolean ke string untuk radio group +const isSameAddressString = computed(() => { + const value = formRef.value?.values?.isSameAddress + if (typeof value === 'boolean') { + return value ? '1' : '0' + } + return value || '1' +}) // #region Function Helper function getFieldState(field: string) { const state = fieldStates[field] - const isSame = formRef.value?.values?.isSameAddress === '1' + const isSame = formRef.value?.values?.isSameAddress === true || formRef.value?.values?.isSameAddress === '1' // Jika alamat sama, semua field kecuali provinsi disabled if (['address', 'rt', 'rw'].includes(field) && isSame) { @@ -63,7 +75,7 @@ function getFieldState(field: string) { const isDisabledByDependency = !dependencyValue // Jika isSame, semua field location disabled - if (isSame && ['regencyId', 'districtId', 'villageId', 'zipCode'].includes(field)) { + if (isSame && ['regency_code', 'district_code', 'village_code', 'postalRegion_code'].includes(field)) { return { placeholder: '-', disabled: true } } @@ -73,7 +85,7 @@ function getFieldState(field: string) { } // Jika isSame dan field location, disabled - if (isSame && ['regencyId', 'districtId', 'villageId', 'zipCode'].includes(field)) { + if (isSame && ['regency_code', 'district_code', 'village_code', 'postalRegion_code'].includes(field)) { return { placeholder: '-', disabled: true } } @@ -84,9 +96,9 @@ function getFieldState(field: string) { // #region watch -// Watch provinceId changes +// Watch province_code changes watch( - () => formRef.value?.values?.provinceId, + () => formRef.value?.values?.province_code, (newValue, oldValue) => { if (isResetting || !formRef.value || newValue === oldValue) return @@ -95,10 +107,10 @@ watch( formRef.value.setValues( { - regencyId: undefined, - districtId: undefined, - villageId: undefined, - zipCode: undefined, + regency_code: undefined, + district_code: undefined, + village_code: undefined, + postalRegion_code: undefined, }, false, ) @@ -110,9 +122,9 @@ watch( }, ) -// Watch regencyId changes +// Watch regency_code changes watch( - () => formRef.value?.values?.regencyId, + () => formRef.value?.values?.regency_code, (newValue, oldValue) => { if (isResetting || !formRef.value || newValue === oldValue) return @@ -121,9 +133,9 @@ watch( formRef.value.setValues( { - districtId: undefined, - villageId: undefined, - zipCode: undefined, + district_code: undefined, + village_code: undefined, + postalRegion_code: undefined, }, false, ) @@ -135,9 +147,9 @@ watch( }, ) -// Watch districtId changes +// Watch district_code changes watch( - () => formRef.value?.values?.districtId, + () => formRef.value?.values?.district_code, (newValue, oldValue) => { if (isResetting || !formRef.value || newValue === oldValue) return @@ -146,8 +158,8 @@ watch( formRef.value.setValues( { - villageId: undefined, - zipCode: undefined, + village_code: undefined, + postalRegion_code: undefined, }, false, ) @@ -159,9 +171,9 @@ watch( }, ) -// Watch villageId changes +// Watch village_code changes watch( - () => formRef.value?.values?.villageId, + () => formRef.value?.values?.village_code, (newValue, oldValue) => { if (isResetting || !formRef.value || newValue === oldValue) return @@ -170,7 +182,7 @@ watch( formRef.value.setValues( { - zipCode: undefined, + postalRegion_code: undefined, }, false, ) @@ -188,19 +200,23 @@ watch( (newValue, oldValue) => { if (!formRef.value || newValue === oldValue) return - // Ketika berubah dari '1' ke '0', clear empty strings dan trigger validasi - if (oldValue === '1' && newValue === '0') { + // Konversi ke boolean untuk perbandingan yang konsisten + const newBool = newValue === true || newValue === '1' + const oldBool = oldValue === true || oldValue === '1' + + // Ketika berubah dari true ke false, clear empty strings dan trigger validasi + if (oldBool && !newBool) { nextTick(() => { // Set empty strings ke undefined untuk trigger required validation const currentValues = formRef.value.values const updatedValues = { ...currentValues } // Convert empty strings to undefined untuk field yang sekarang required - if (updatedValues.provinceId === '') updatedValues.provinceId = undefined - if (updatedValues.regencyId === '') updatedValues.regencyId = undefined - if (updatedValues.districtId === '') updatedValues.districtId = undefined - if (updatedValues.villageId === '') updatedValues.villageId = undefined - if (updatedValues.zipCode === '') updatedValues.zipCode = undefined + if (updatedValues.province_code === '') updatedValues.province_code = undefined + if (updatedValues.regency_code === '') updatedValues.regency_code = undefined + if (updatedValues.district_code === '') updatedValues.district_code = undefined + if (updatedValues.village_code === '') updatedValues.village_code = undefined + if (updatedValues.postalRegion_code === '') updatedValues.postalRegion_code = undefined if (updatedValues.address === '') updatedValues.address = undefined // Update values dan trigger validasi @@ -213,15 +229,15 @@ watch( }) } - // Ketika berubah dari '0' ke '1', clear error messages - if (oldValue === '0' && newValue === '1') { + // Ketika berubah dari false ke true, clear error messages + if (!oldBool && newBool) { nextTick(() => { // Clear error messages untuk field yang tidak lagi required - formRef.value?.setFieldError('provinceId', undefined) - formRef.value?.setFieldError('regencyId', undefined) - formRef.value?.setFieldError('districtId', undefined) - formRef.value?.setFieldError('villageId', undefined) - formRef.value?.setFieldError('zipCode', undefined) + formRef.value?.setFieldError('province_code', undefined) + formRef.value?.setFieldError('regency_code', undefined) + formRef.value?.setFieldError('district_code', undefined) + formRef.value?.setFieldError('village_code', undefined) + formRef.value?.setFieldError('postalRegion_code', undefined) formRef.value?.setFieldError('address', undefined) formRef.value?.setFieldError('rt', undefined) formRef.value?.setFieldError('rw', undefined) @@ -241,129 +257,138 @@ watch( :validation-schema="formSchema" :validate-on-mount="false" validation-mode="onSubmit" - :initial-values="initialValues ?? { isSameAddress: '1' }" + :initial-values="initialValues ?? { isSameAddress: '1', locationType_code: 'identity' }" >

{{ props.title }}

-
-
- - - - - - - - + + + + + Apakah alamat KTP sama dengan alamat sekarang? + + + + + + +
+ + + {{ option.label }} + +
+
+
+ +
+
+
+
+ + + + + +
+ + -
-
- -
- -
- -
- -
- -
-
-
+ + + diff --git a/app/components/app/person-address/entry-form.vue b/app/components/app/person-address/entry-form.vue index a26381d8..b3ef300d 100644 --- a/app/components/app/person-address/entry-form.vue +++ b/app/components/app/person-address/entry-form.vue @@ -12,6 +12,8 @@ import SelectRegency from './_common/select-regency.vue' import SelectVillage from './_common/select-village.vue' import { Form } from '~/components/pub/ui/form' +import * as DE from '~/components/pub/my-ui/doc-entry' + const props = defineProps<{ title: string conf?: { @@ -35,29 +37,34 @@ defineExpose({ // Watchers untuk cascading reset let isResetting = false -// #region Watch provinceId changes +// #region Watch provinceCode changes watch( - () => formRef.value?.values?.provinceId, + () => formRef.value?.values?.provinceCode, (newValue, oldValue) => { if (isResetting || !formRef.value || newValue === oldValue) return if (oldValue && newValue !== oldValue) { isResetting = true - formRef.value.setValues( - { - regencyId: undefined, - districtId: undefined, - villageId: undefined, - zipCode: undefined, - }, - false, - ) + // Delay reset untuk memberikan waktu composable menyelesaikan request + setTimeout(() => { + if (formRef.value) { + formRef.value.setValues( + { + regencyId: undefined, + districtId: undefined, + villageId: undefined, + zipCode: undefined, + }, + false, + ) + } - nextTick(() => { - isResetting = false - }) + nextTick(() => { + isResetting = false + }) + }, 150) // Delay 150ms, lebih dari debounce composable (100ms) } }, ) @@ -71,18 +78,23 @@ watch( if (oldValue && newValue !== oldValue) { isResetting = true - formRef.value.setValues( - { - districtId: undefined, - villageId: undefined, - zipCode: undefined, - }, - false, - ) + // Delay reset untuk memberikan waktu composable menyelesaikan request + setTimeout(() => { + if (formRef.value) { + formRef.value.setValues( + { + districtId: undefined, + villageId: undefined, + zipCode: undefined, + }, + false, + ) + } - nextTick(() => { - isResetting = false - }) + nextTick(() => { + isResetting = false + }) + }, 150) } }, ) @@ -96,17 +108,22 @@ watch( if (oldValue && newValue !== oldValue) { isResetting = true - formRef.value.setValues( - { - villageId: undefined, - zipCode: undefined, - }, - false, - ) + // Delay reset untuk memberikan waktu composable menyelesaikan request + setTimeout(() => { + if (formRef.value) { + formRef.value.setValues( + { + villageId: undefined, + zipCode: undefined, + }, + false, + ) + } - nextTick(() => { - isResetting = false - }) + nextTick(() => { + isResetting = false + }) + }, 150) } }, ) @@ -145,124 +162,84 @@ watch( :validation-schema="formSchema" :validate-on-mount="false" validation-mode="onSubmit" - :initial-values="initialValues ? initialValues : {}" + :initial-values=" + initialValues ? { locationType_code: 'domicile', ...initialValues } : { locationType_code: 'domicile' } + " >

{{ props.title }}

-
-
- - - - + + + + + + + + + + +
+ - - - -