From a48f375018b0a48615b4aa321b434c660ac07291 Mon Sep 17 00:00:00 2001 From: riefive Date: Wed, 1 Oct 2025 12:38:04 +0700 Subject: [PATCH 01/19] feat(installation): integrate api installation --- .../app/installation/entry-form-prev.vue | 125 +++++++++ .../app/installation/entry-form.vue | 185 ++++++-------- app/components/app/installation/list-cfg.ts | 27 +- app/components/app/installation/list.vue | 11 +- .../content/installation/list-prev.vue | 206 +++++++++++++++ app/components/content/installation/list.vue | 237 ++++++++---------- app/models/installation.ts | 2 +- app/schemas/installation.schema.ts | 9 + 8 files changed, 534 insertions(+), 268 deletions(-) create mode 100644 app/components/app/installation/entry-form-prev.vue create mode 100644 app/components/content/installation/list-prev.vue create mode 100644 app/schemas/installation.schema.ts diff --git a/app/components/app/installation/entry-form-prev.vue b/app/components/app/installation/entry-form-prev.vue new file mode 100644 index 00000000..8272fc27 --- /dev/null +++ b/app/components/app/installation/entry-form-prev.vue @@ -0,0 +1,125 @@ + + + diff --git a/app/components/app/installation/entry-form.vue b/app/components/app/installation/entry-form.vue index 8272fc27..c32b9ad9 100644 --- a/app/components/app/installation/entry-form.vue +++ b/app/components/app/installation/entry-form.vue @@ -1,125 +1,102 @@ diff --git a/app/components/app/installation/list-cfg.ts b/app/components/app/installation/list-cfg.ts index 6b8dc5ea..c0bff58e 100644 --- a/app/components/app/installation/list-cfg.ts +++ b/app/components/app/installation/list-cfg.ts @@ -12,13 +12,11 @@ type SmallDetailDto = any const action = defineAsyncComponent(() => import('~/components/pub/custom-ui/data/dropdown-action-ud.vue')) -export const cols: Col[] = [{ width: 100 }, {}, {}, {}, { width: 50 }] +export const cols: Col[] = [{}, {}, {}, { width: 50 }] -export const header: Th[][] = [ - [{ label: 'Id' }, { label: 'Nama' }, { label: 'Kode' }, { label: 'Encounter Class' }, { label: '' }], -] +export const header: Th[][] = [[{ label: 'Kode' }, { label: 'Nama' }, { label: 'Encounter Class' }, { label: '' }]] -export const keys = ['id', 'name', 'cellphone', 'religion_code', 'action'] +export const keys = ['code', 'name', 'encounterClass_code', 'action'] export const delKeyNames: KeyLabel[] = [ { key: 'code', label: 'Kode' }, @@ -28,22 +26,7 @@ export const delKeyNames: KeyLabel[] = [ export const funcParsed: RecStrFuncUnknown = { name: (rec: unknown): unknown => { const recX = rec as SmallDetailDto - return `${recX.firstName} ${recX.lastName || ''}`.trim() - }, - identity_number: (rec: unknown): unknown => { - const recX = rec as SmallDetailDto - if (recX.identity_number?.substring(0, 5) === 'BLANK') { - return '(TANPA NIK)' - } - return recX.identity_number - }, - inPatient_itemPrice: (rec: unknown): unknown => { - const recX = rec as SmallDetailDto - return Number(recX.inPatient_itemPrice.price).toLocaleString('id-ID') - }, - outPatient_itemPrice: (rec: unknown): unknown => { - const recX = rec as SmallDetailDto - return Number(recX.outPatient_itemPrice.price).toLocaleString('id-ID') + return `${recX.name}`.trim() }, } @@ -65,4 +48,4 @@ export const funcHtml: RecStrFuncUnknown = { patient_address(_rec) { return '-' }, -} +} \ No newline at end of file diff --git a/app/components/app/installation/list.vue b/app/components/app/installation/list.vue index e9489ef1..cde2a4ce 100644 --- a/app/components/app/installation/list.vue +++ b/app/components/app/installation/list.vue @@ -22,10 +22,15 @@ function handlePageChange(page: number) { diff --git a/app/components/content/installation/list-prev.vue b/app/components/content/installation/list-prev.vue new file mode 100644 index 00000000..59a96c00 --- /dev/null +++ b/app/components/content/installation/list-prev.vue @@ -0,0 +1,206 @@ + + + + + diff --git a/app/components/content/installation/list.vue b/app/components/content/installation/list.vue index baeab8c9..d70db2f4 100644 --- a/app/components/content/installation/list.vue +++ b/app/components/content/installation/list.vue @@ -1,31 +1,39 @@ - - diff --git a/app/models/installation.ts b/app/models/installation.ts index c662714e..3b027962 100644 --- a/app/models/installation.ts +++ b/app/models/installation.ts @@ -1,5 +1,5 @@ export interface Installation { code: string name: string - encounterClass_code: string + encounterClass_code?: string | null } diff --git a/app/schemas/installation.schema.ts b/app/schemas/installation.schema.ts new file mode 100644 index 00000000..75e18074 --- /dev/null +++ b/app/schemas/installation.schema.ts @@ -0,0 +1,9 @@ +import { z } from 'zod' + +export const InstallationSchema = z.object({ + code: z.string().min(1, 'Kode wajib diisi'), + name: z.string().min(1, 'Nama wajib diisi'), + encounterClass_code: z.string().min(1, 'Encounter Class wajib diisi').optional(), +}) + +export type InstallationFormData = z.infer From c96d7383793c1de8775badf861df39758d878cef Mon Sep 17 00:00:00 2001 From: riefive Date: Wed, 1 Oct 2025 13:01:24 +0700 Subject: [PATCH 02/19] chore: add shared handlers --- app/components/content/equipment/list.vue | 11 +-- app/components/content/installation/list.vue | 7 +- app/components/content/tools/list.vue | 12 +-- app/handlers/_shared.handler.ts | 26 ++++++ .../(features)/org-src/installation/index.vue | 4 +- app/services/encounter.service.ts | 79 +++++++++++++++++++ 6 files changed, 110 insertions(+), 29 deletions(-) create mode 100644 app/handlers/_shared.handler.ts create mode 100644 app/services/encounter.service.ts diff --git a/app/components/content/equipment/list.vue b/app/components/content/equipment/list.vue index b1b348d1..61757da7 100644 --- a/app/components/content/equipment/list.vue +++ b/app/components/content/equipment/list.vue @@ -29,12 +29,11 @@ import { handleActionRemove, handleCancelForm, } from '~/handlers/material.handler' +import { uoms, getUomList } from "~/handlers/_shared.handler" // Services import { getMaterials, getMaterialDetail } from '~/services/material.service' -import { getUoms } from '~/services/uom.service' -const uoms = ref<{ value: string; label: string }[]>([]) const title = ref('') const { @@ -93,14 +92,6 @@ const getCurrentMaterialDetail = async (id: number | string) => { } } -const getUomList = async () => { - const result = await getUoms() - if (result.success) { - const currentUoms = result.body?.data || [] - uoms.value = currentUoms.map((uom: Uom) => ({ value: uom.code || uom.erp_id, label: uom.name })) - } -} - // Watch for row actions when recId or recAction changes watch([recId, recAction], () => { switch (recAction.value) { diff --git a/app/components/content/installation/list.vue b/app/components/content/installation/list.vue index d70db2f4..ef580cf8 100644 --- a/app/components/content/installation/list.vue +++ b/app/components/content/installation/list.vue @@ -124,12 +124,7 @@ onMounted(async () => { /> - + ([]) const title = ref('') const { @@ -96,14 +94,6 @@ const getCurrentToolsDetail = async (id: number | string) => { } } -const getUomList = async () => { - const result = await getUoms() - if (result.success) { - const currentUoms = result.body?.data || [] - uoms.value = currentUoms.map((uom: Uom) => ({ value: uom.code || uom.erp_id, label: uom.name })) - } -} - // Watch for row actions watch([recId, recAction], () => { switch (recAction.value) { diff --git a/app/handlers/_shared.handler.ts b/app/handlers/_shared.handler.ts new file mode 100644 index 00000000..0e421d0f --- /dev/null +++ b/app/handlers/_shared.handler.ts @@ -0,0 +1,26 @@ +// types +import type { Uom } from '~/models/uom' + +// services +import { getUoms } from '~/services/uom.service' +import { getEncounters } from '~/services/encounter.service' + +// variables +export const uoms = ref<{ value: string; label: string }[]>([]) +export const encounterClasses = ref<{ value: string; label: string }[]>([]) + +export const getUomList = async () => { + const result = await getUoms() + if (result.success) { + const currentUoms = result.body?.data || [] + uoms.value = currentUoms.map((uom: Uom) => ({ value: uom.code || uom.erp_id, label: uom.name })) + } +} + +export const getEncounterClassList = async () => { + const result = await getEncounters() + if (result.success) { + const currentValues = result.body?.data || [] + encounterClasses.value = currentValues.map((item: any) => ({ value: item.code || item.id, label: item.name })) + } +} diff --git a/app/pages/(features)/org-src/installation/index.vue b/app/pages/(features)/org-src/installation/index.vue index d8b934da..7b39e66b 100644 --- a/app/pages/(features)/org-src/installation/index.vue +++ b/app/pages/(features)/org-src/installation/index.vue @@ -6,8 +6,8 @@ import Error from '~/components/pub/base/error/error.vue' definePageMeta({ // middleware: ['rbac'], roles: ['doctor', 'nurse', 'admisi', 'pharmacy', 'billing', 'management'], - title: 'List Installation', - contentFrame: 'cf-full-width', + title: 'Daftar Instalasi', + contentFrame: 'cf-container-lg', }) const route = useRoute() diff --git a/app/services/encounter.service.ts b/app/services/encounter.service.ts new file mode 100644 index 00000000..51f0b060 --- /dev/null +++ b/app/services/encounter.service.ts @@ -0,0 +1,79 @@ +import { xfetch } from '~/composables/useXfetch' + +const mainUrl = '/api/v1/encounter' + +export async function getEncounters(params: any = null) { + try { + let url = mainUrl + if (params && typeof params === 'object' && Object.keys(params).length > 0) { + const searchParams = new URLSearchParams() + for (const key in params) { + if (params[key] !== null && params[key] !== undefined && params[key] !== '') { + searchParams.append(key, params[key]) + } + } + const queryString = searchParams.toString() + if (queryString) url += `?${queryString}` + } + const resp = await xfetch(url, 'GET') + const result: any = {} + result.success = resp.success + result.body = (resp.body as Record) || {} + return result + } catch (error) { + console.error('Error fetching encounters:', error) + throw new Error('Failed to fetch encounters') + } +} + +export async function getEncounterDetail(id: string | number) { + try { + const resp = await xfetch(`${mainUrl}/${id}`, 'GET') + const result: any = {} + result.success = resp.success + result.body = (resp.body as Record) || {} + return result + } catch (error) { + console.error('Error fetching encounter detail:', error) + throw new Error('Failed to fetch encounter detail') + } +} + +export async function postEncounter(data: any) { + try { + const resp = await xfetch(mainUrl, 'POST', data) + const result: any = {} + result.success = resp.success + result.body = (resp.body as Record) || {} + return result + } catch (error) { + console.error('Error creating encounter:', error) + throw new Error('Failed to create encounter') + } +} + +export async function patchEncounter(id: string | number, data: any) { + try { + const resp = await xfetch(`${mainUrl}/${id}`, 'PATCH', data) + const result: any = {} + result.success = resp.success + result.body = (resp.body as Record) || {} + return result + } catch (error) { + console.error('Error updating encounter:', error) + throw new Error('Failed to update encounter') + } +} + +export async function removeEncounter(id: string | number) { + try { + const resp = await xfetch(`${mainUrl}/${id}`, 'DELETE') + const result: any = {} + result.success = resp.success + result.body = (resp.body as Record) || {} + return result + } catch (error) { + console.error('Error deleting encounter:', error) + throw new Error('Failed to delete encounter') + } +} From 6a7a9cda80943cc8e8d4159b65f36d38e1193838 Mon Sep 17 00:00:00 2001 From: riefive Date: Wed, 1 Oct 2025 13:05:36 +0700 Subject: [PATCH 03/19] feat(installation): add encounter list --- .../app/installation/entry-form.vue | 1 + app/components/content/installation/list.vue | 10 ++++- app/components/content/medicine/list.vue | 44 ++++--------------- app/handlers/_shared.handler.ts | 28 ++++++++++++ 4 files changed, 46 insertions(+), 37 deletions(-) diff --git a/app/components/app/installation/entry-form.vue b/app/components/app/installation/entry-form.vue index c32b9ad9..ac0d068b 100644 --- a/app/components/app/installation/entry-form.vue +++ b/app/components/app/installation/entry-form.vue @@ -15,6 +15,7 @@ import { useForm } from 'vee-validate' interface Props { schema: z.ZodSchema + encounterClasses: any[] values: any isLoading?: boolean isReadonly?: boolean diff --git a/app/components/content/installation/list.vue b/app/components/content/installation/list.vue index ef580cf8..7c3986e0 100644 --- a/app/components/content/installation/list.vue +++ b/app/components/content/installation/list.vue @@ -28,6 +28,7 @@ import { handleActionRemove, handleCancelForm, } from '~/handlers/installation.handler' +import { encounterClasses, getEncounterClassList } from '~/handlers/_shared.handler' // Services import { getInstallations, getInstallationDetail } from '~/services/installation.service' @@ -110,6 +111,7 @@ watch([recId, recAction], () => { }) onMounted(async () => { + await getEncounterClassList(); await getInstallationList() }) @@ -124,9 +126,15 @@ onMounted(async () => { /> - + ([]) -const medicineMethods = ref<{ value: string; label: string }[]>([]) -const uoms = ref<{ value: string; label: string }[]>([]) const title = ref('') const { @@ -99,36 +101,6 @@ const getCurrentMedicineDetail = async (id: number | string) => { } } -const getMedicineGroupList = async () => { - const result = await getMedicineGroups() - if (result.success) { - const currentMedicineGroups = result.body?.data || [] - medicineGroups.value = currentMedicineGroups.map((medicineGroup: MedicineGroup) => ({ - value: medicineGroup.code, - label: medicineGroup.name, - })) - } -} - -const getMedicineMethodList = async () => { - const result = await getMedicineMethods() - if (result.success) { - const currentMedicineMethods = result.body?.data || [] - medicineMethods.value = currentMedicineMethods.map((medicineMethod: MedicineMethod) => ({ - value: medicineMethod.code, - label: medicineMethod.name, - })) - } -} - -const getUomList = async () => { - const result = await getUoms() - if (result.success) { - const currentUoms = result.body?.data || [] - uoms.value = currentUoms.map((uom: Uom) => ({ value: uom.code || uom.erp_id, label: uom.name })) - } -} - watch([recId, recAction], () => { switch (recAction.value) { case ActionEvents.showDetail: diff --git a/app/handlers/_shared.handler.ts b/app/handlers/_shared.handler.ts index 0e421d0f..05599509 100644 --- a/app/handlers/_shared.handler.ts +++ b/app/handlers/_shared.handler.ts @@ -1,14 +1,42 @@ // types +import type { MedicineGroup } from '~/models/medicine-group' +import type { MedicineMethod } from '~/models/medicine-method' import type { Uom } from '~/models/uom' // services +import { getMedicineGroups } from '~/services/medicine-group.service' +import { getMedicineMethods } from '~/services/medicine-method.service' import { getUoms } from '~/services/uom.service' import { getEncounters } from '~/services/encounter.service' // variables +export const medicineGroups = ref<{ value: string; label: string }[]>([]) +export const medicineMethods = ref<{ value: string; label: string }[]>([]) export const uoms = ref<{ value: string; label: string }[]>([]) export const encounterClasses = ref<{ value: string; label: string }[]>([]) +export const getMedicineGroupList = async () => { + const result = await getMedicineGroups() + if (result.success) { + const currentMedicineGroups = result.body?.data || [] + medicineGroups.value = currentMedicineGroups.map((medicineGroup: MedicineGroup) => ({ + value: medicineGroup.code, + label: medicineGroup.name, + })) + } +} + +export const getMedicineMethodList = async () => { + const result = await getMedicineMethods() + if (result.success) { + const currentMedicineMethods = result.body?.data || [] + medicineMethods.value = currentMedicineMethods.map((medicineMethod: MedicineMethod) => ({ + value: medicineMethod.code, + label: medicineMethod.name, + })) + } +} + export const getUomList = async () => { const result = await getUoms() if (result.success) { From cc41118570c5602f79385b5f07d0e9d51ff60cb5 Mon Sep 17 00:00:00 2001 From: riefive Date: Wed, 1 Oct 2025 14:36:48 +0700 Subject: [PATCH 04/19] fix: resolve list organization source --- .../app/installation/entry-form.vue | 16 +++++ app/components/app/specialist/entry-form.vue | 21 ++----- .../app/subspecialist/entry-form.vue | 23 +++----- app/components/app/unit/entry-form.vue | 23 +++++++- app/components/content/specialist/list.vue | 12 +--- app/components/content/subspecialist/list.vue | 15 +---- app/components/content/unit/list.vue | 3 + app/handlers/_shared.handler.ts | 59 +++++++++++++++---- app/models/installation.ts | 1 + app/models/unit.ts | 2 +- app/schemas/unit.schema.ts | 1 + 11 files changed, 106 insertions(+), 70 deletions(-) diff --git a/app/components/app/installation/entry-form.vue b/app/components/app/installation/entry-form.vue index ac0d068b..fe853bb0 100644 --- a/app/components/app/installation/entry-form.vue +++ b/app/components/app/installation/entry-form.vue @@ -4,6 +4,7 @@ import Block from '~/components/pub/custom-ui/doc-entry/block.vue' import Cell from '~/components/pub/custom-ui/doc-entry/cell.vue' import Field from '~/components/pub/custom-ui/doc-entry/field.vue' import Label from '~/components/pub/custom-ui/doc-entry/label.vue' +import Combobox from '~/components/pub/custom-ui/form/combobox.vue' // Types import type { InstallationFormData } from '~/schemas/installation.schema.ts' @@ -86,6 +87,21 @@ function onCancelForm() { + + + + + +
diff --git a/app/components/app/specialist/entry-form.vue b/app/components/app/specialist/entry-form.vue index 7254ec98..6f02c425 100644 --- a/app/components/app/specialist/entry-form.vue +++ b/app/components/app/specialist/entry-form.vue @@ -4,7 +4,7 @@ import Block from '~/components/pub/custom-ui/doc-entry/block.vue' import Cell from '~/components/pub/custom-ui/doc-entry/cell.vue' import Field from '~/components/pub/custom-ui/doc-entry/field.vue' import Label from '~/components/pub/custom-ui/doc-entry/label.vue' -// import Combobox from '~/components/pub/custom-ui/form/combobox.vue' +import Combobox from '~/components/pub/custom-ui/form/combobox.vue' // Types import type { SpecialistFormData } from '~/schemas/specialist.schema.ts' @@ -90,24 +90,15 @@ function onCancelForm() { - - diff --git a/app/components/app/unit/entry-form.vue b/app/components/app/unit/entry-form.vue index 7bad3552..5f9e86ff 100644 --- a/app/components/app/unit/entry-form.vue +++ b/app/components/app/unit/entry-form.vue @@ -4,6 +4,7 @@ import Block from '~/components/pub/custom-ui/doc-entry/block.vue' import Cell from '~/components/pub/custom-ui/doc-entry/cell.vue' import Field from '~/components/pub/custom-ui/doc-entry/field.vue' import Label from '~/components/pub/custom-ui/doc-entry/label.vue' +import Combobox from '~/components/pub/custom-ui/form/combobox.vue' // Types import type { UnitFormData } from '~/schemas/unit.schema.ts' @@ -15,6 +16,7 @@ import { useForm } from 'vee-validate' interface Props { schema: z.ZodSchema + installations: any[] values: any isLoading?: boolean isReadonly?: boolean @@ -33,13 +35,13 @@ const { defineField, errors, meta } = useForm({ initialValues: { code: '', name: '', - installation: '', + installation_id: 0, } as Partial, }) const [code, codeAttrs] = defineField('code') const [name, nameAttrs] = defineField('name') -const [installation, installationAttrs] = defineField('installation') +const [installation, installationAttrs] = defineField('installation_id') // Fill fields from props.values if provided if (props.values) { @@ -59,7 +61,7 @@ function onSubmitForm(values: any) { const formData: UnitFormData = { name: name.value || '', code: code.value || '', - installation: installation.value || '', + installation_id: installation.value || '', } emit('submit', formData, resetForm) } @@ -85,6 +87,21 @@ function onCancelForm() { + + + + + +
diff --git a/app/components/content/specialist/list.vue b/app/components/content/specialist/list.vue index d1c3bb21..b6d7048a 100644 --- a/app/components/content/specialist/list.vue +++ b/app/components/content/specialist/list.vue @@ -13,7 +13,6 @@ import { toast } from '~/components/pub/ui/toast' // Types import { ActionEvents, type HeaderPrep } from '~/components/pub/custom-ui/data/types' import { SpecialistSchema, type SpecialistFormData } from '~/schemas/specialist.schema' -import type { Unit } from '~/models/unit' // Handlers import { @@ -29,12 +28,11 @@ import { handleActionRemove, handleCancelForm, } from '~/handlers/specialist.handler' +import { units, getUnitList } from '~/handlers/_shared.handler' // Services import { getSpecialists, getSpecialistDetail } from '~/services/specialist.service' -import { getUnits } from '~/services/unit.service' -const units = ref<{ value: string; label: string }[]>([]) const title = ref('') const { @@ -93,14 +91,6 @@ const getCurrentSpecialistDetail = async (id: number | string) => { } } -const getUnitList = async () => { - const result = await getUnits() - if (result.success) { - const currentUnits = result.body?.data || [] - units.value = currentUnits.map((item: Unit) => ({ value: item.id ? Number(item.id) : item.code, label: item.name })) - } -} - // Watch for row actions when recId or recAction changes watch([recId, recAction], () => { switch (recAction.value) { diff --git a/app/components/content/subspecialist/list.vue b/app/components/content/subspecialist/list.vue index ad38241f..ec8520fd 100644 --- a/app/components/content/subspecialist/list.vue +++ b/app/components/content/subspecialist/list.vue @@ -13,7 +13,6 @@ import { toast } from '~/components/pub/ui/toast' // Types import { ActionEvents, type HeaderPrep } from '~/components/pub/custom-ui/data/types' import { SubspecialistSchema, type SubspecialistFormData } from '~/schemas/subspecialist.schema' -import type { Specialist } from '~/models/specialist' // Handlers import { @@ -29,12 +28,11 @@ import { handleActionRemove, handleCancelForm, } from '~/handlers/subspecialist.handler' +import { specialists, getSpecialistsList } from '~/handlers/_shared.handler' // Services import { getSubspecialists, getSubspecialistDetail } from '~/services/subspecialist.service' -import { getSpecialists } from '~/services/specialist.service' -const specialists = ref<{ value: string; label: string }[]>([]) const title = ref('') const { @@ -93,17 +91,6 @@ const getCurrentSubSpecialistDetail = async (id: number | string) => { } } -const getSpecialistsList = async () => { - const result = await getSpecialists() - if (result.success) { - const currentSpecialists = result.body?.data || [] - specialists.value = currentSpecialists.map((item: Specialist) => ({ - value: item.id ? Number(item.id) : item.code, - label: item.name, - })) - } -} - // Watch for row actions when recId or recAction changes watch([recId, recAction], () => { switch (recAction.value) { diff --git a/app/components/content/unit/list.vue b/app/components/content/unit/list.vue index 3dcd184d..0ecde4c5 100644 --- a/app/components/content/unit/list.vue +++ b/app/components/content/unit/list.vue @@ -28,6 +28,7 @@ import { handleActionRemove, handleCancelForm, } from '~/handlers/unit.handler' +import { installations, getInstallationList } from '~/handlers/_shared.handler' // Services import { getUnits, getUnitDetail } from '~/services/unit.service' @@ -110,6 +111,7 @@ watch([recId, recAction], () => { }) onMounted(async () => { + await getInstallationList() await getUnitList() }) @@ -127,6 +129,7 @@ onMounted(async () => { ([]) export const medicineMethods = ref<{ value: string; label: string }[]>([]) -export const uoms = ref<{ value: string; label: string }[]>([]) export const encounterClasses = ref<{ value: string; label: string }[]>([]) +export const installations = ref<{ value: string; label: string }[]>([]) +export const specialists = ref<{ value: string; label: string }[]>([]) +export const uoms = ref<{ value: string; label: string }[]>([]) +export const units = ref<{ value: string; label: string }[]>([]) export const getMedicineGroupList = async () => { const result = await getMedicineGroups() @@ -37,14 +46,6 @@ export const getMedicineMethodList = async () => { } } -export const getUomList = async () => { - const result = await getUoms() - if (result.success) { - const currentUoms = result.body?.data || [] - uoms.value = currentUoms.map((uom: Uom) => ({ value: uom.code || uom.erp_id, label: uom.name })) - } -} - export const getEncounterClassList = async () => { const result = await getEncounters() if (result.success) { @@ -52,3 +53,41 @@ export const getEncounterClassList = async () => { encounterClasses.value = currentValues.map((item: any) => ({ value: item.code || item.id, label: item.name })) } } + +export const getInstallationList = async () => { + const result = await getInstallations() + if (result.success) { + const currentInstallations = result.body?.data || [] + installations.value = currentInstallations.map((item: Installation) => ({ + value: item.id ? Number(item.id) : item.code, + label: item.name, + })) + } +} + +export const getSpecialistsList = async () => { + const result = await getSpecialists() + if (result.success) { + const currentSpecialists = result.body?.data || [] + specialists.value = currentSpecialists.map((item: Specialist) => ({ + value: item.id ? Number(item.id) : item.code, + label: item.name, + })) + } +} + +export const getUnitList = async () => { + const result = await getUnits() + if (result.success) { + const currentUnits = result.body?.data || [] + units.value = currentUnits.map((item: Unit) => ({ value: item.id ? Number(item.id) : item.code, label: item.name })) + } +} + +export const getUomList = async () => { + const result = await getUoms() + if (result.success) { + const currentUoms = result.body?.data || [] + uoms.value = currentUoms.map((uom: Uom) => ({ value: uom.code || uom.erp_id, label: uom.name })) + } +} diff --git a/app/models/installation.ts b/app/models/installation.ts index 3b027962..bb6e3786 100644 --- a/app/models/installation.ts +++ b/app/models/installation.ts @@ -1,4 +1,5 @@ export interface Installation { + id?: number | null code: string name: string encounterClass_code?: string | null diff --git a/app/models/unit.ts b/app/models/unit.ts index 27348354..dca2a771 100644 --- a/app/models/unit.ts +++ b/app/models/unit.ts @@ -2,5 +2,5 @@ export interface Unit { id?: number code: string name: string - installation?: string | number + installation_id?: string | number } diff --git a/app/schemas/unit.schema.ts b/app/schemas/unit.schema.ts index 30a5a075..ec6c80d4 100644 --- a/app/schemas/unit.schema.ts +++ b/app/schemas/unit.schema.ts @@ -4,6 +4,7 @@ import type { Unit } from '~/models/unit' const UnitSchema = z.object({ code: z.string({ required_error: 'Kode harus diisi' }).min(1, 'Kode minimum 1 karakter'), name: z.string({ required_error: 'Nama harus diisi' }).min(1, 'Nama minimum 1 karakter'), + installation_id: z.number().min(1, 'Instalasi harus diisi').nullable(), }) type UnitFormData = z.infer & Unit From 54a5aaa78ff653c1ba0ba73fa76cf6dcf88004c9 Mon Sep 17 00:00:00 2001 From: riefive Date: Wed, 1 Oct 2025 14:56:11 +0700 Subject: [PATCH 05/19] fix: search on list file --- app/components/content/division/list.vue | 4 ++-- app/components/content/equipment/list.vue | 4 ++-- app/components/content/installation/list.vue | 6 +++--- app/components/content/medicine-group/list.vue | 4 ++-- app/components/content/medicine-method/list.vue | 4 ++-- app/components/content/medicine/list.vue | 4 ++-- app/components/content/specialist/list.vue | 5 +++-- app/components/content/subspecialist/list.vue | 4 ++-- app/components/content/tools/list.vue | 4 ++-- app/components/content/unit/list.vue | 4 ++-- app/components/content/uom/list.vue | 4 ++-- app/composables/usePaginatedList.ts | 2 +- 12 files changed, 25 insertions(+), 24 deletions(-) diff --git a/app/components/content/division/list.vue b/app/components/content/division/list.vue index 0acae66d..8d55db24 100644 --- a/app/components/content/division/list.vue +++ b/app/components/content/division/list.vue @@ -43,8 +43,8 @@ const { handleSearch, fetchData: getDivisionList, } = usePaginatedList({ - fetchFn: async ({ page, search }) => { - const result = await getDivisions({ search, page }) + fetchFn: async (params: any) => { + const result = await getDivisions({ search: params.search, page: params['page-number'] || 0 }) return { success: result.success || false, body: result.body || {} } }, entityName: 'division', diff --git a/app/components/content/equipment/list.vue b/app/components/content/equipment/list.vue index 61757da7..e51a7f9a 100644 --- a/app/components/content/equipment/list.vue +++ b/app/components/content/equipment/list.vue @@ -45,8 +45,8 @@ const { handleSearch, fetchData: getEquipmentList, } = usePaginatedList({ - fetchFn: async ({ page }) => { - const result = await getMaterials({ search: searchInput.value, page }) + fetchFn: async (params: any) => { + const result = await getMaterials({ search: params.search, page: params['page-number'] || 0 }) return { success: result.success || false, body: result.body || {} } }, entityName: 'equipment', diff --git a/app/components/content/installation/list.vue b/app/components/content/installation/list.vue index 7c3986e0..cee19a42 100644 --- a/app/components/content/installation/list.vue +++ b/app/components/content/installation/list.vue @@ -44,8 +44,8 @@ const { handleSearch, fetchData: getInstallationList, } = usePaginatedList({ - fetchFn: async ({ page, search }) => { - const result = await getInstallations({ search, page }) + fetchFn: async (params: any) => { + const result = await getInstallations({ search: params.search, page: params['page-number'] || 0 }) return { success: result.success || false, body: result.body || {} } }, entityName: 'installation', @@ -111,7 +111,7 @@ watch([recId, recAction], () => { }) onMounted(async () => { - await getEncounterClassList(); + await getEncounterClassList() await getInstallationList() }) diff --git a/app/components/content/medicine-group/list.vue b/app/components/content/medicine-group/list.vue index d56c4c49..d0d2c6d5 100644 --- a/app/components/content/medicine-group/list.vue +++ b/app/components/content/medicine-group/list.vue @@ -43,8 +43,8 @@ const { handleSearch, fetchData: getMedicineGroupList, } = usePaginatedList({ - fetchFn: async ({ page, search }) => { - const result = await getMedicineGroups({ search, page }) + fetchFn: async (params: any) => { + const result = await getMedicineGroups({ search: params.search, page: params['page-number'] || 0 }) return { success: result.success || false, body: result.body || {} } }, entityName: 'medicine-group', diff --git a/app/components/content/medicine-method/list.vue b/app/components/content/medicine-method/list.vue index 1de41ddc..8ff1bcf3 100644 --- a/app/components/content/medicine-method/list.vue +++ b/app/components/content/medicine-method/list.vue @@ -43,8 +43,8 @@ const { handleSearch, fetchData: getMedicineMethodList, } = usePaginatedList({ - fetchFn: async ({ page, search }) => { - const result = await getMedicineMethods({ search, page }) + fetchFn: async (params: any) => { + const result = await getMedicineMethods({ search: params.search, page: params['page-number'] || 0 }) return { success: result.success || false, body: result.body || {} } }, entityName: 'medicine-method', diff --git a/app/components/content/medicine/list.vue b/app/components/content/medicine/list.vue index 8df71a01..a690f781 100644 --- a/app/components/content/medicine/list.vue +++ b/app/components/content/medicine/list.vue @@ -54,8 +54,8 @@ const { handleSearch, fetchData: getMedicineList, } = usePaginatedList({ - fetchFn: async ({ page, search }) => { - const result = await getMedicines({ search, page }) + fetchFn: async (params: any) => { + const result = await getMedicines({ search: params.search, page: params['page-number'] || 0 }) return { success: result.success || false, body: result.body || {} } }, entityName: 'medicine', diff --git a/app/components/content/specialist/list.vue b/app/components/content/specialist/list.vue index b6d7048a..628f83ac 100644 --- a/app/components/content/specialist/list.vue +++ b/app/components/content/specialist/list.vue @@ -32,6 +32,7 @@ import { units, getUnitList } from '~/handlers/_shared.handler' // Services import { getSpecialists, getSpecialistDetail } from '~/services/specialist.service' +import { get } from "@vueuse/core" const title = ref('') @@ -44,8 +45,8 @@ const { handleSearch, fetchData: getSpecialistList, } = usePaginatedList({ - fetchFn: async ({ page, search }) => { - const result = await getSpecialists({ search, page }) + fetchFn: async (params: any) => { + const result = await getSpecialists({ search: params.search, page: params['page-number'] || 0 }) return { success: result.success || false, body: result.body || {} } }, entityName: 'specialist', diff --git a/app/components/content/subspecialist/list.vue b/app/components/content/subspecialist/list.vue index ec8520fd..78466bef 100644 --- a/app/components/content/subspecialist/list.vue +++ b/app/components/content/subspecialist/list.vue @@ -44,8 +44,8 @@ const { handleSearch, fetchData: getSubSpecialistList, } = usePaginatedList({ - fetchFn: async ({ page, search }) => { - const result = await getSubspecialists({ search, page }) + fetchFn: async (params: any) => { + const result = await getSubspecialists({ search: params.search, page: params['page-number'] || 0 }) return { success: result.success || false, body: result.body || {} } }, entityName: 'subspecialist', diff --git a/app/components/content/tools/list.vue b/app/components/content/tools/list.vue index 59091ab1..5de63c0a 100644 --- a/app/components/content/tools/list.vue +++ b/app/components/content/tools/list.vue @@ -44,8 +44,8 @@ const { handleSearch, fetchData: getToolsList, } = usePaginatedList({ - fetchFn: async ({ page }) => { - const result = await getDevices({ search: searchInput.value, page }) + fetchFn: async (params: any) => { + const result = await getDevices({ search: params.search, page: params['page-number'] || 0 }) return { success: result.success || false, body: result.body || {} } }, entityName: 'device', diff --git a/app/components/content/unit/list.vue b/app/components/content/unit/list.vue index 0ecde4c5..3d474cb7 100644 --- a/app/components/content/unit/list.vue +++ b/app/components/content/unit/list.vue @@ -44,8 +44,8 @@ const { handleSearch, fetchData: getUnitList, } = usePaginatedList({ - fetchFn: async ({ page, search }) => { - const result = await getUnits({ search, page }) + fetchFn: async (params: any) => { + const result = await getUnits({ search: params.search, page: params['page-number'] || 0 }) return { success: result.success || false, body: result.body || {} } }, entityName: 'unit', diff --git a/app/components/content/uom/list.vue b/app/components/content/uom/list.vue index 6e6bda1b..383dbc3d 100644 --- a/app/components/content/uom/list.vue +++ b/app/components/content/uom/list.vue @@ -42,8 +42,8 @@ const { handleSearch, fetchData: getUomList, } = usePaginatedList({ - fetchFn: async ({ page, search }) => { - const result = await getUoms({ search, page }) + fetchFn: async (params: any) => { + const result = await getUoms({ search: params.search, page: params['page-number'] || 0 }) return { success: result.success || false, body: result.body || {} } }, entityName: 'uom', diff --git a/app/composables/usePaginatedList.ts b/app/composables/usePaginatedList.ts index d0edafb2..379d2eb6 100644 --- a/app/composables/usePaginatedList.ts +++ b/app/composables/usePaginatedList.ts @@ -97,7 +97,6 @@ export function usePaginatedList(options: UsePaginatedListOptions) { paginationMeta.hasPrev = paginationMeta.page > 1 } } catch (error) { - console.error(`Error fetching ${entityName} list:`, error) data.value = [] paginationMeta.recordCount = 0 paginationMeta.totalPage = 0 @@ -126,6 +125,7 @@ export function usePaginatedList(options: UsePaginatedListOptions) { watch( params, (newParams) => { + console.log('watch ~ newParams', newParams) // Sync search input with URL params (for back/forward navigation) if (newParams.search !== searchInput.value) { searchInput.value = newParams.search || '' From db48233f6c9d7c4652e4892af72529a9551040f3 Mon Sep 17 00:00:00 2001 From: riefive Date: Wed, 1 Oct 2025 15:17:31 +0700 Subject: [PATCH 06/19] fix: includes for medicine list --- app/components/app/medicine/list-cfg.ts | 6 +++--- app/components/content/medicine/list.vue | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/components/app/medicine/list-cfg.ts b/app/components/app/medicine/list-cfg.ts index 3440e5f9..2c96958e 100644 --- a/app/components/app/medicine/list-cfg.ts +++ b/app/components/app/medicine/list-cfg.ts @@ -35,13 +35,13 @@ export const delKeyNames: KeyLabel[] = [ export const funcParsed: RecStrFuncUnknown = { group: (rec: unknown): unknown => { - return (rec as SmallDetailDto).medicineGroup_code || '-' + return (rec as SmallDetailDto).medicineGroup?.name || '-' }, method: (rec: unknown): unknown => { - return (rec as SmallDetailDto).medicineMethod_code || '-' + return (rec as SmallDetailDto).medicineMethod?.name || '-' }, unit: (rec: unknown): unknown => { - return (rec as SmallDetailDto).uom_code || '-' + return (rec as SmallDetailDto).uom?.name || '-' }, } diff --git a/app/components/content/medicine/list.vue b/app/components/content/medicine/list.vue index a690f781..e77ce620 100644 --- a/app/components/content/medicine/list.vue +++ b/app/components/content/medicine/list.vue @@ -55,7 +55,7 @@ const { fetchData: getMedicineList, } = usePaginatedList({ fetchFn: async (params: any) => { - const result = await getMedicines({ search: params.search, page: params['page-number'] || 0 }) + const result = await getMedicines({ search: params.search, page: params['page-number'] || 0, includes: 'medicineGroup,medicineMethod,uom' }) return { success: result.success || false, body: result.body || {} } }, entityName: 'medicine', From 546423bdfb665a0b78ce9a15115fc309aecce274 Mon Sep 17 00:00:00 2001 From: riefive Date: Wed, 1 Oct 2025 15:24:54 +0700 Subject: [PATCH 07/19] fix: includes for unit --- app/components/app/unit/list-cfg.ts | 5 +++-- app/components/content/unit/list.vue | 2 +- app/handlers/_shared.handler.ts | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/app/components/app/unit/list-cfg.ts b/app/components/app/unit/list-cfg.ts index a6f5ffc7..1e3a46be 100644 --- a/app/components/app/unit/list-cfg.ts +++ b/app/components/app/unit/list-cfg.ts @@ -28,8 +28,9 @@ export const funcParsed: RecStrFuncUnknown = { const recX = rec as SmallDetailDto return `${recX.name}`.trim() }, - installation: (_rec: unknown): unknown => { - return '-' + installation: (rec: unknown): unknown => { + const recX = rec as SmallDetailDto + return recX.installation?.name || '-' }, } diff --git a/app/components/content/unit/list.vue b/app/components/content/unit/list.vue index 3d474cb7..69acc005 100644 --- a/app/components/content/unit/list.vue +++ b/app/components/content/unit/list.vue @@ -45,7 +45,7 @@ const { fetchData: getUnitList, } = usePaginatedList({ fetchFn: async (params: any) => { - const result = await getUnits({ search: params.search, page: params['page-number'] || 0 }) + const result = await getUnits({ search: params.search, page: params['page-number'] || 0, includes: 'installation' }) return { success: result.success || false, body: result.body || {} } }, entityName: 'unit', diff --git a/app/handlers/_shared.handler.ts b/app/handlers/_shared.handler.ts index 4d2179ed..e959e68d 100644 --- a/app/handlers/_shared.handler.ts +++ b/app/handlers/_shared.handler.ts @@ -50,7 +50,7 @@ export const getEncounterClassList = async () => { const result = await getEncounters() if (result.success) { const currentValues = result.body?.data || [] - encounterClasses.value = currentValues.map((item: any) => ({ value: item.code || item.id, label: item.name })) + encounterClasses.value = currentValues.map((item: any) => ({ value: item.class_code || item.id, label: item.class_code })) } } From 9603915fd7cd57bfc23baf5af1127621b8b98d18 Mon Sep 17 00:00:00 2001 From: riefive Date: Thu, 2 Oct 2025 11:00:05 +0700 Subject: [PATCH 08/19] remove previous list + form from any features --- .../app/installation/entry-form-prev.vue | 125 --------- .../app/specialist/entry-form-prev.vue | 181 ------------- .../app/subspecialist/entry-form-prev.vue | 213 ---------------- app/components/app/unit/entry-form-prev.vue | 125 --------- app/components/content/installation/entry.ts | 37 --- .../content/installation/list-prev.vue | 206 --------------- app/components/content/specialist/entry.ts | 95 ------- .../content/specialist/list-prev.vue | 240 ------------------ app/components/content/subspecialist/entry.ts | 98 ------- .../content/subspecialist/list-prev.vue | 239 ----------------- app/components/content/unit/entry.ts | 63 ----- app/components/content/unit/list-prev.vue | 207 --------------- 12 files changed, 1829 deletions(-) delete mode 100644 app/components/app/installation/entry-form-prev.vue delete mode 100644 app/components/app/specialist/entry-form-prev.vue delete mode 100644 app/components/app/subspecialist/entry-form-prev.vue delete mode 100644 app/components/app/unit/entry-form-prev.vue delete mode 100644 app/components/content/installation/entry.ts delete mode 100644 app/components/content/installation/list-prev.vue delete mode 100644 app/components/content/specialist/entry.ts delete mode 100644 app/components/content/specialist/list-prev.vue delete mode 100644 app/components/content/subspecialist/entry.ts delete mode 100644 app/components/content/subspecialist/list-prev.vue delete mode 100644 app/components/content/unit/entry.ts delete mode 100644 app/components/content/unit/list-prev.vue diff --git a/app/components/app/installation/entry-form-prev.vue b/app/components/app/installation/entry-form-prev.vue deleted file mode 100644 index 8272fc27..00000000 --- a/app/components/app/installation/entry-form-prev.vue +++ /dev/null @@ -1,125 +0,0 @@ - - - diff --git a/app/components/app/specialist/entry-form-prev.vue b/app/components/app/specialist/entry-form-prev.vue deleted file mode 100644 index 2dbfffc1..00000000 --- a/app/components/app/specialist/entry-form-prev.vue +++ /dev/null @@ -1,181 +0,0 @@ - - - diff --git a/app/components/app/subspecialist/entry-form-prev.vue b/app/components/app/subspecialist/entry-form-prev.vue deleted file mode 100644 index 9d31fd3f..00000000 --- a/app/components/app/subspecialist/entry-form-prev.vue +++ /dev/null @@ -1,213 +0,0 @@ - - - diff --git a/app/components/app/unit/entry-form-prev.vue b/app/components/app/unit/entry-form-prev.vue deleted file mode 100644 index 463a6683..00000000 --- a/app/components/app/unit/entry-form-prev.vue +++ /dev/null @@ -1,125 +0,0 @@ - - - diff --git a/app/components/content/installation/entry.ts b/app/components/content/installation/entry.ts deleted file mode 100644 index c003a029..00000000 --- a/app/components/content/installation/entry.ts +++ /dev/null @@ -1,37 +0,0 @@ -import * as z from 'zod' - -export const installationConf = { - msg: { - placeholder: '---pilih encounter class (fhir7)', - }, - items: [ - { value: '1', label: 'Ambulatory', code: 'AMB' }, - { value: '2', label: 'Inpatient', code: 'IMP' }, - { value: '3', label: 'Emergency', code: 'EMER' }, - { value: '4', label: 'Observation', code: 'OBSENC' }, - { value: '5', label: 'Pre-admission', code: 'PRENC' }, - { value: '6', label: 'Short Stay', code: 'SS' }, - { value: '7', label: 'Virtual', code: 'VR' }, - { value: '8', label: 'Home Health', code: 'HH' }, - ], -} - -export const schemaConf = z.object({ - name: z - .string({ - required_error: 'Nama instalasi harus diisi', - }) - .min(3, 'Nama instalasi minimal 3 karakter'), - - code: z - .string({ - required_error: 'Kode instalasi harus diisi', - }) - .min(3, 'Kode instalasi minimal 3 karakter'), - - encounterClassCode: z - .string({ - required_error: 'Kelompok encounter class harus dipilih', - }) - .min(1, 'Kelompok encounter class harus dipilih'), -}) diff --git a/app/components/content/installation/list-prev.vue b/app/components/content/installation/list-prev.vue deleted file mode 100644 index 59a96c00..00000000 --- a/app/components/content/installation/list-prev.vue +++ /dev/null @@ -1,206 +0,0 @@ - - - - - diff --git a/app/components/content/specialist/entry.ts b/app/components/content/specialist/entry.ts deleted file mode 100644 index c89302c2..00000000 --- a/app/components/content/specialist/entry.ts +++ /dev/null @@ -1,95 +0,0 @@ -import * as z from 'zod' - -export const schemaConf = z.object({ - name: z - .string({ - required_error: 'Nama spesialisasi harus diisi', - }) - .min(3, 'Nama spesialisasi minimal 3 karakter'), - - code: z - .string({ - required_error: 'Kode spesialisasi harus diisi', - }) - .min(3, 'Kode spesialisasi minimal 3 karakter'), - - installationId: z - .string({ - required_error: 'Instalasi harus dipilih', - }) - .min(1, 'Instalasi harus dipilih'), - - unitId: z - .string({ - required_error: 'Unit harus dipilih', - }) - .min(1, 'Unit harus dipilih'), -}) - -// Unit mapping berdasarkan installation -export const installationUnitMapping: Record = { - '1': ['1', '3', '5'], - '2': ['2', '4', '6'], - '3': ['7', '8', '9', '10', '11'], -} - -export const unitConf = { - msg: { - placeholder: '---pilih unit', - search: 'kode, nama unit', - empty: 'unit tidak ditemukan', - }, - items: [ - { value: '1', label: 'Instalasi Medis', code: 'MED' }, - { value: '2', label: 'Instalasi Keperawatan', code: 'NUR' }, - { value: '3', label: 'Instalasi Administrasi', code: 'ADM' }, - { value: '4', label: 'Instalasi Penunjang Non-Medis', code: 'SUP' }, - { value: '5', label: 'Instalasi Pendidikan & Pelatihan', code: 'EDU' }, - { value: '6', label: 'Instalasi Farmasi', code: 'PHA' }, - { value: '7', label: 'Instalasi Radiologi', code: 'RAD' }, - { value: '8', label: 'Instalasi Laboratorium', code: 'LAB' }, - { value: '9', label: 'Instalasi Keuangan', code: 'FIN' }, - { value: '10', label: 'Instalasi SDM', code: 'HR' }, - { value: '11', label: 'Instalasi Teknologi Informasi', code: 'ITS' }, - { value: '12', label: 'Instalasi Pemeliharaan & Sarana', code: 'MNT' }, - { value: '13', label: 'Instalasi Gizi / Catering', code: 'CAT' }, - { value: '14', label: 'Instalasi Keamanan', code: 'SEC' }, - { value: '15', label: 'Instalasi Gawat Darurat', code: 'EMR' }, - { value: '16', label: 'Instalasi Bedah Sentral', code: 'SUR' }, - { value: '17', label: 'Instalasi Rawat Jalan', code: 'OUT' }, - { value: '18', label: 'Instalasi Rawat Inap', code: 'INP' }, - { value: '19', label: 'Instalasi Rehabilitasi Medik', code: 'REB' }, - { value: '20', label: 'Instalasi Penelitian & Pengembangan', code: 'RSH' }, - ], -} - -export const installationConf = { - msg: { - placeholder: '---pilih instalasi', - search: 'kode, nama instalasi', - empty: 'instalasi tidak ditemukan', - }, - items: [ - { value: '1', label: 'Ambulatory', code: 'AMB' }, - { value: '2', label: 'Inpatient', code: 'IMP' }, - { value: '3', label: 'Emergency', code: 'EMER' }, - ], -} - -// Helper function untuk filter unit berdasarkan installation -export function getFilteredUnits(installationId: string) { - if (!installationId || !installationUnitMapping[installationId]) { - return [] - } - - const allowedUnitIds = installationUnitMapping[installationId] - return unitConf.items.filter((unit) => allowedUnitIds.includes(unit.value)) -} - -// Helper function untuk membuat unit config yang ter-filter -export function createFilteredUnitConf(installationId: string) { - return { - ...unitConf, - items: getFilteredUnits(installationId), - } -} diff --git a/app/components/content/specialist/list-prev.vue b/app/components/content/specialist/list-prev.vue deleted file mode 100644 index ee6d7f8b..00000000 --- a/app/components/content/specialist/list-prev.vue +++ /dev/null @@ -1,240 +0,0 @@ - - - - - diff --git a/app/components/content/subspecialist/entry.ts b/app/components/content/subspecialist/entry.ts deleted file mode 100644 index 5a93847d..00000000 --- a/app/components/content/subspecialist/entry.ts +++ /dev/null @@ -1,98 +0,0 @@ -import * as z from 'zod' - -export const schemaConf = z.object({ - name: z - .string({ - required_error: 'Nama spesialisasi harus diisi', - }) - .min(3, 'Nama spesialisasi minimal 3 karakter'), - - code: z - .string({ - required_error: 'Kode spesialisasi harus diisi', - }) - .min(3, 'Kode spesialisasi minimal 3 karakter'), - - installationId: z - .string({ - required_error: 'Instalasi harus dipilih', - }) - .min(1, 'Instalasi harus dipilih'), - - unitId: z - .string({ - required_error: 'Unit harus dipilih', - }) - .min(1, 'Unit harus dipilih'), - specialistId: z - .string({ - required_error: 'Specialist harus dipilih', - }) - .min(1, 'Specialist harus dipilih'), -}) - -// Unit mapping berdasarkan installation -export const installationUnitMapping: Record = { - '1': ['1', '3'], - '2': ['2', '3'], - '3': ['1', '2', '3'], -} - -export const unitConf = { - msg: { - placeholder: '---pilih unit', - search: 'kode, nama unit', - empty: 'unit tidak ditemukan', - }, - items: [ - { value: '1', label: 'Instalasi Medis', code: 'MED' }, - { value: '2', label: 'Instalasi Keperawatan', code: 'NUR' }, - { value: '3', label: 'Instalasi Administrasi', code: 'ADM' }, - ], -} - -export const specialistConf = { - msg: { - placeholder: '---pilih specialist', - search: 'kode, nama specialist', - empty: 'specialist tidak ditemukan', - }, - items: [ - { value: '1', label: 'Spesialis Jantung', code: 'CARD' }, - { value: '2', label: 'Spesialis Mata', code: 'OPHT' }, - { value: '3', label: 'Spesialis Bedah', code: 'SURG' }, - { value: '4', label: 'Spesialis Anak', code: 'PEDI' }, - { value: '5', label: 'Spesialis Kandungan', code: 'OBGY' }, - ], -} - -export const installationConf = { - msg: { - placeholder: '---pilih instalasi', - search: 'kode, nama instalasi', - empty: 'instalasi tidak ditemukan', - }, - items: [ - { value: '1', label: 'Ambulatory', code: 'AMB' }, - { value: '2', label: 'Inpatient', code: 'IMP' }, - { value: '3', label: 'Emergency', code: 'EMER' }, - ], -} - -// Helper function untuk filter unit berdasarkan installation -export function getFilteredUnits(installationId: string) { - if (!installationId || !installationUnitMapping[installationId]) { - return [] - } - - const allowedUnitIds = installationUnitMapping[installationId] - return unitConf.items.filter((unit) => allowedUnitIds.includes(unit.value)) -} - -// Helper function untuk membuat unit config yang ter-filter -export function createFilteredUnitConf(installationId: string) { - return { - ...unitConf, - items: getFilteredUnits(installationId), - } -} diff --git a/app/components/content/subspecialist/list-prev.vue b/app/components/content/subspecialist/list-prev.vue deleted file mode 100644 index a5496df6..00000000 --- a/app/components/content/subspecialist/list-prev.vue +++ /dev/null @@ -1,239 +0,0 @@ - - - diff --git a/app/components/content/unit/entry.ts b/app/components/content/unit/entry.ts deleted file mode 100644 index bf85a0ed..00000000 --- a/app/components/content/unit/entry.ts +++ /dev/null @@ -1,63 +0,0 @@ -import * as z from 'zod' - -export const unitConf = { - msg: { - placeholder: '--- pilih instalasi', - search: 'kode, nama instalasi', - empty: 'instalasi tidak ditemukan', - }, - items: [ - { value: '1', label: 'Instalasi Medis', code: 'MED' }, - { value: '2', label: 'Instalasi Keperawatan', code: 'NUR' }, - { value: '3', label: 'Instalasi Administrasi', code: 'ADM' }, - { value: '4', label: 'Instalasi Penunjang Non-Medis', code: 'SUP' }, - { value: '5', label: 'Instalasi Pendidikan & Pelatihan', code: 'EDU' }, - { value: '6', label: 'Instalasi Farmasi', code: 'PHA' }, - { value: '7', label: 'Instalasi Radiologi', code: 'RAD' }, - { value: '8', label: 'Instalasi Laboratorium', code: 'LAB' }, - { value: '9', label: 'Instalasi Keuangan', code: 'FIN' }, - { value: '10', label: 'Instalasi SDM', code: 'HR' }, - { value: '11', label: 'Instalasi Teknologi Informasi', code: 'ITS' }, - { value: '12', label: 'Instalasi Pemeliharaan & Sarana', code: 'MNT' }, - { value: '13', label: 'Instalasi Gizi / Catering', code: 'CAT' }, - { value: '14', label: 'Instalasi Keamanan', code: 'SEC' }, - { value: '15', label: 'Instalasi Gawat Darurat', code: 'EMR' }, - { value: '16', label: 'Instalasi Bedah Sentral', code: 'SUR' }, - { value: '17', label: 'Instalasi Rawat Jalan', code: 'OUT' }, - { value: '18', label: 'Instalasi Rawat Inap', code: 'INP' }, - { value: '19', label: 'Instalasi Rehabilitasi Medik', code: 'REB' }, - { value: '20', label: 'Instalasi Penelitian & Pengembangan', code: 'RSH' }, - ], -} - -export const schemaConf = z.object({ - name: z - .string({ - required_error: 'Nama unit harus diisi', - }) - .min(1, 'Nama unit harus diisi'), - - code: z - .string({ - required_error: 'Kode unit harus diisi', - }) - .min(1, 'Kode unit harus diisi'), - parentId: z.preprocess( - (input: unknown) => { - if (typeof input === 'string') { - // Handle empty string case - if (input.trim() === '') { - return 0 - } - return Number(input) - } - - return input - }, - z - .number({ - required_error: 'Instalasi induk harus dipilih', - }) - .refine((num) => num > 0, 'Instalasi induk harus dipilih'), - ), -}) diff --git a/app/components/content/unit/list-prev.vue b/app/components/content/unit/list-prev.vue deleted file mode 100644 index 9cee37a1..00000000 --- a/app/components/content/unit/list-prev.vue +++ /dev/null @@ -1,207 +0,0 @@ - - - - - From fc3bda14f43bd012215a69916c77f2704cd4d237 Mon Sep 17 00:00:00 2001 From: riefive Date: Thu, 2 Oct 2025 11:16:23 +0700 Subject: [PATCH 09/19] fix: change get encounter class to constants --- app/components/content/installation/list.vue | 4 ++-- app/handlers/_shared.handler.ts | 17 +++++++++++++++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/app/components/content/installation/list.vue b/app/components/content/installation/list.vue index cee19a42..5be09e61 100644 --- a/app/components/content/installation/list.vue +++ b/app/components/content/installation/list.vue @@ -28,7 +28,7 @@ import { handleActionRemove, handleCancelForm, } from '~/handlers/installation.handler' -import { encounterClasses, getEncounterClassList } from '~/handlers/_shared.handler' +import { encounterClasses, getEncounterClassConstants } from '~/handlers/_shared.handler' // Services import { getInstallations, getInstallationDetail } from '~/services/installation.service' @@ -111,7 +111,7 @@ watch([recId, recAction], () => { }) onMounted(async () => { - await getEncounterClassList() + await getEncounterClassConstants() await getInstallationList() }) diff --git a/app/handlers/_shared.handler.ts b/app/handlers/_shared.handler.ts index e959e68d..af88190a 100644 --- a/app/handlers/_shared.handler.ts +++ b/app/handlers/_shared.handler.ts @@ -1,11 +1,14 @@ // types import type { MedicineGroup } from '~/models/medicine-group' import type { MedicineMethod } from '~/models/medicine-method' -import type { Installation } from "~/models/installation" +import type { Installation } from '~/models/installation' import type { Specialist } from '~/models/specialist' import type { Uom } from '~/models/uom' import type { Unit } from '~/models/unit' +// constants +import { encounterClassCodes } from '~/lib/constants' + // services import { getMedicineGroups } from '~/services/medicine-group.service' import { getMedicineMethods } from '~/services/medicine-method.service' @@ -50,10 +53,20 @@ export const getEncounterClassList = async () => { const result = await getEncounters() if (result.success) { const currentValues = result.body?.data || [] - encounterClasses.value = currentValues.map((item: any) => ({ value: item.class_code || item.id, label: item.class_code })) + encounterClasses.value = currentValues.map((item: any) => ({ + value: item.class_code || item.id, + label: item.class_code, + })) } } +export function getEncounterClassConstants() { + const allowed = ['ambulatory', 'emergency', 'inpatient'] + encounterClasses.value = Object.entries(encounterClassCodes) + .filter(([key]) => allowed.includes(key)) + .map(([key, value]) => ({ value: key, label: value })) +} + export const getInstallationList = async () => { const result = await getInstallations() if (result.success) { From 693d8225bf34a2f2a1ef458940de6c2623708c2d Mon Sep 17 00:00:00 2001 From: riefive Date: Thu, 2 Oct 2025 14:12:10 +0700 Subject: [PATCH 10/19] fix: list integration --- app/components/app/division/entry-form.vue | 17 ++++++++++ app/components/app/division/list-cfg.ts | 12 +++---- app/components/content/division/list.vue | 3 ++ app/components/content/equipment/list.vue | 4 +-- app/components/content/installation/list.vue | 2 +- app/components/content/medicine/list.vue | 8 +++-- app/components/content/specialist/list.vue | 2 +- app/components/content/subspecialist/list.vue | 2 +- app/components/content/tools/list.vue | 2 +- app/components/content/unit/list.vue | 2 +- app/handlers/_handler.ts | 5 +-- app/handlers/_shared.handler.ts | 20 +++++++++++ app/handlers/division.handler.ts | 34 +++++++++++++++++-- 13 files changed, 91 insertions(+), 22 deletions(-) diff --git a/app/components/app/division/entry-form.vue b/app/components/app/division/entry-form.vue index 5f4b3299..d6f7556f 100644 --- a/app/components/app/division/entry-form.vue +++ b/app/components/app/division/entry-form.vue @@ -4,6 +4,7 @@ import Block from '~/components/pub/custom-ui/doc-entry/block.vue' import Cell from '~/components/pub/custom-ui/doc-entry/cell.vue' import Field from '~/components/pub/custom-ui/doc-entry/field.vue' import Label from '~/components/pub/custom-ui/doc-entry/label.vue' +import Combobox from '~/components/pub/custom-ui/form/combobox.vue' // Types import type { DivisionFormData } from '~/schemas/division.schema.ts' @@ -15,6 +16,7 @@ import { useForm } from 'vee-validate' interface Props { schema: z.ZodSchema + divisions: any[] values: any isLoading?: boolean isReadonly?: boolean @@ -85,6 +87,21 @@ function onCancelForm() { + + + + + +
diff --git a/app/components/app/division/list-cfg.ts b/app/components/app/division/list-cfg.ts index 3674b5c2..0fe14dd1 100644 --- a/app/components/app/division/list-cfg.ts +++ b/app/components/app/division/list-cfg.ts @@ -12,11 +12,11 @@ type SmallDetailDto = any const action = defineAsyncComponent(() => import('~/components/pub/custom-ui/data/dropdown-action-ud.vue')) -export const cols: Col[] = [{ width: 100 }, {}, {}, { width: 50 }] +export const cols: Col[] = [{}, {}, {}, { width: 50 }] export const header: Th[][] = [[{ label: 'Kode' }, { label: 'Nama' }, { label: 'Divisi Induk' }, { label: '' }]] -export const keys = ['code', 'name', 'ancestor', 'action'] +export const keys = ['code', 'name', 'parent', 'action'] export const delKeyNames: KeyLabel[] = [ { key: 'code', label: 'Kode' }, @@ -24,13 +24,9 @@ export const delKeyNames: KeyLabel[] = [ ] export const funcParsed: RecStrFuncUnknown = { - ancestor: (rec: unknown): unknown => { + parent: (rec: unknown): unknown => { const recX = rec as SmallDetailDto - if (recX.meta === null) { - return '-' - } - - return recX.meta.name + return recX.parent?.name || '-' }, } diff --git a/app/components/content/division/list.vue b/app/components/content/division/list.vue index 8d55db24..9da83819 100644 --- a/app/components/content/division/list.vue +++ b/app/components/content/division/list.vue @@ -28,6 +28,7 @@ import { handleActionRemove, handleCancelForm, } from '~/handlers/division.handler' +import { divisions, getDivisionParentList } from '~/handlers/_shared.handler' // Services import { getDivisions, getDivisionDetail } from '~/services/division.service' @@ -111,6 +112,7 @@ watch([recId, recAction], () => { onMounted(async () => { await getDivisionList() + await getDivisionParentList(false, data.value || []) }) @@ -127,6 +129,7 @@ onMounted(async () => { { }) onMounted(async () => { - await getUomList() await getEquipmentList() + await getUomList() }) diff --git a/app/components/content/installation/list.vue b/app/components/content/installation/list.vue index 5be09e61..f8494ba8 100644 --- a/app/components/content/installation/list.vue +++ b/app/components/content/installation/list.vue @@ -111,8 +111,8 @@ watch([recId, recAction], () => { }) onMounted(async () => { - await getEncounterClassConstants() await getInstallationList() + await getEncounterClassConstants() }) diff --git a/app/components/content/medicine/list.vue b/app/components/content/medicine/list.vue index e77ce620..2f2accb9 100644 --- a/app/components/content/medicine/list.vue +++ b/app/components/content/medicine/list.vue @@ -55,7 +55,11 @@ const { fetchData: getMedicineList, } = usePaginatedList({ fetchFn: async (params: any) => { - const result = await getMedicines({ search: params.search, page: params['page-number'] || 0, includes: 'medicineGroup,medicineMethod,uom' }) + const result = await getMedicines({ + search: params.search, + page: params['page-number'] || 0, + includes: 'medicineGroup,medicineMethod,uom', + }) return { success: result.success || false, body: result.body || {} } }, entityName: 'medicine', @@ -120,10 +124,10 @@ watch([recId, recAction], () => { }) onMounted(async () => { + await getMedicineList() await getMedicineGroupList() await getMedicineMethodList() await getUomList() - await getMedicineList() }) diff --git a/app/components/content/specialist/list.vue b/app/components/content/specialist/list.vue index 628f83ac..c157642b 100644 --- a/app/components/content/specialist/list.vue +++ b/app/components/content/specialist/list.vue @@ -112,8 +112,8 @@ watch([recId, recAction], () => { }) onMounted(async () => { - await getUnitList() await getSpecialistList() + await getUnitList() }) diff --git a/app/components/content/subspecialist/list.vue b/app/components/content/subspecialist/list.vue index 78466bef..5571f632 100644 --- a/app/components/content/subspecialist/list.vue +++ b/app/components/content/subspecialist/list.vue @@ -111,8 +111,8 @@ watch([recId, recAction], () => { }) onMounted(async () => { - await getSpecialistsList() await getSubSpecialistList() + await getSpecialistsList() }) diff --git a/app/components/content/tools/list.vue b/app/components/content/tools/list.vue index 5de63c0a..28cccb8f 100644 --- a/app/components/content/tools/list.vue +++ b/app/components/content/tools/list.vue @@ -116,8 +116,8 @@ watch([recId, recAction], () => { }) onMounted(async () => { - await getUomList() await getToolsList() + await getUomList() }) diff --git a/app/components/content/unit/list.vue b/app/components/content/unit/list.vue index 69acc005..1e8edd99 100644 --- a/app/components/content/unit/list.vue +++ b/app/components/content/unit/list.vue @@ -111,8 +111,8 @@ watch([recId, recAction], () => { }) onMounted(async () => { - await getInstallationList() await getUnitList() + await getInstallationList() }) diff --git a/app/handlers/_handler.ts b/app/handlers/_handler.ts index 4148c726..c81e87ed 100644 --- a/app/handlers/_handler.ts +++ b/app/handlers/_handler.ts @@ -33,7 +33,7 @@ export function createCrudHandler(crud: { if (refresh) refresh() }, onFinally: (isSuccess: boolean) => { - if (isSuccess) setTimeout(reset, 500) + setTimeout(reset, 300) isProcessing.value = false }, }) @@ -58,7 +58,7 @@ export function createCrudHandler(crud: { if (refresh) refresh() }, onFinally: (isSuccess: boolean) => { - if (isSuccess) setTimeout(reset, 500) + setTimeout(reset, 300) isProcessing.value = false }, }) @@ -77,6 +77,7 @@ export function createCrudHandler(crud: { if (refresh) refresh() }, onFinally: () => { + setTimeout(refresh, 300) isProcessing.value = false }, }) diff --git a/app/handlers/_shared.handler.ts b/app/handlers/_shared.handler.ts index af88190a..53417888 100644 --- a/app/handlers/_shared.handler.ts +++ b/app/handlers/_shared.handler.ts @@ -1,6 +1,7 @@ // types import type { MedicineGroup } from '~/models/medicine-group' import type { MedicineMethod } from '~/models/medicine-method' +import type { Division } from '~/models/division' import type { Installation } from '~/models/installation' import type { Specialist } from '~/models/specialist' import type { Uom } from '~/models/uom' @@ -13,6 +14,7 @@ import { encounterClassCodes } from '~/lib/constants' import { getMedicineGroups } from '~/services/medicine-group.service' import { getMedicineMethods } from '~/services/medicine-method.service' import { getEncounters } from '~/services/encounter.service' +import { getDivisions } from '~/services/division.service' import { getInstallations } from '~/services/installation.service' import { getSpecialists } from '~/services/specialist.service' import { getUoms } from '~/services/uom.service' @@ -22,6 +24,7 @@ import { getUnits } from '~/services/unit.service' export const medicineGroups = ref<{ value: string; label: string }[]>([]) export const medicineMethods = ref<{ value: string; label: string }[]>([]) export const encounterClasses = ref<{ value: string; label: string }[]>([]) +export const divisions = ref<{ value: string; label: string }[]>([]) export const installations = ref<{ value: string; label: string }[]>([]) export const specialists = ref<{ value: string; label: string }[]>([]) export const uoms = ref<{ value: string; label: string }[]>([]) @@ -49,6 +52,23 @@ export const getMedicineMethodList = async () => { } } +export const getDivisionParentList = async (isFetch = true, externalDivisions: any[] = []) => { + if (isFetch) { + const result = await getDivisions() + if (result.success) { + const currentDivisions = result.body?.data || [] + divisions.value = currentDivisions.map((division: Division) => ({ + value: division.code, + label: division.name, + })) + } + } + divisions.value = externalDivisions.map((division: Division) => ({ + value: division.code, + label: division.name, + })) +} + export const getEncounterClassList = async () => { const result = await getEncounters() if (result.success) { diff --git a/app/handlers/division.handler.ts b/app/handlers/division.handler.ts index e830260f..8b14ca86 100644 --- a/app/handlers/division.handler.ts +++ b/app/handlers/division.handler.ts @@ -1,5 +1,33 @@ import { createCrudHandler } from '~/handlers/_handler' import { postDivision, patchDivision, removeDivision } from '~/services/division.service' +import { + postDivisionPosition, + patchDivisionPosition, + removeDivisionPosition, +} from '~/services/division-position.service' + +function selectPost(payload: any) { + if (payload.division_id && Number(payload.division_id) > 0) { + return postDivisionPosition + } + delete payload.division_id; + return postDivision +} + +function selectPatch(id: number | string, payload: any) { + if (payload.division_id && Number(payload.division_id) > 0) { + return patchDivisionPosition + } + delete payload.division_id; + return patchDivision +} + +function selectRemove(payload: any) { + if (payload.division_id && Number(payload.division_id) > 0) { + return removeDivisionPosition + } + return removeDivision +} export const { recId, @@ -15,7 +43,7 @@ export const { handleActionRemove, handleCancelForm, } = createCrudHandler({ - post: postDivision, - patch: patchDivision, - remove: removeDivision, + post: (payload: any) => selectPost(payload)(payload), + patch: (id: number | string, payload: any) => selectPatch(id, payload)(id, payload), + remove: (payload: any) => selectRemove(payload)(payload), }) From d544d031c3829195fda94eaaa60a6598a729adce Mon Sep 17 00:00:00 2001 From: riefive Date: Thu, 2 Oct 2025 14:34:19 +0700 Subject: [PATCH 11/19] fix: list with params error --- app/components/content/division/list.vue | 6 +++++- app/components/content/equipment/list.vue | 1 + app/components/content/installation/list.vue | 6 +++++- app/components/content/specialist/list.vue | 7 ++++++- app/composables/usePaginatedList.ts | 3 +++ app/services/division-position.service.ts | 2 +- app/services/division.service.ts | 2 +- app/services/installation.service.ts | 2 +- app/services/medicine-group.service.ts | 2 +- app/services/medicine-method.service.ts | 2 +- app/services/specialist.service.ts | 2 +- app/services/subspecialist.service.ts | 2 +- app/services/unit.service.ts | 2 +- app/services/uom.service.ts | 2 +- 14 files changed, 29 insertions(+), 12 deletions(-) diff --git a/app/components/content/division/list.vue b/app/components/content/division/list.vue index 9da83819..0529e77a 100644 --- a/app/components/content/division/list.vue +++ b/app/components/content/division/list.vue @@ -45,7 +45,11 @@ const { fetchData: getDivisionList, } = usePaginatedList({ fetchFn: async (params: any) => { - const result = await getDivisions({ search: params.search, page: params['page-number'] || 0 }) + // TODO: use pagination params + const result = await getDivisions({ + search: params.search, + // page: params['page-number'] || 0, + }) return { success: result.success || false, body: result.body || {} } }, entityName: 'division', diff --git a/app/components/content/equipment/list.vue b/app/components/content/equipment/list.vue index 5587858f..501b64b5 100644 --- a/app/components/content/equipment/list.vue +++ b/app/components/content/equipment/list.vue @@ -46,6 +46,7 @@ const { fetchData: getEquipmentList, } = usePaginatedList({ fetchFn: async (params: any) => { + // TODO: use pagination params const result = await getMaterials({ search: params.search, page: params['page-number'] || 0 }) return { success: result.success || false, body: result.body || {} } }, diff --git a/app/components/content/installation/list.vue b/app/components/content/installation/list.vue index f8494ba8..6adba2e2 100644 --- a/app/components/content/installation/list.vue +++ b/app/components/content/installation/list.vue @@ -45,7 +45,11 @@ const { fetchData: getInstallationList, } = usePaginatedList({ fetchFn: async (params: any) => { - const result = await getInstallations({ search: params.search, page: params['page-number'] || 0 }) + // TODO: use pagination params + const result = await getInstallations({ + search: params.search, + // page: params['page-number'] || 0, + }) return { success: result.success || false, body: result.body || {} } }, entityName: 'installation', diff --git a/app/components/content/specialist/list.vue b/app/components/content/specialist/list.vue index c157642b..27b25e6b 100644 --- a/app/components/content/specialist/list.vue +++ b/app/components/content/specialist/list.vue @@ -46,7 +46,12 @@ const { fetchData: getSpecialistList, } = usePaginatedList({ fetchFn: async (params: any) => { - const result = await getSpecialists({ search: params.search, page: params['page-number'] || 0 }) + // TODO: use pagination params + const result = await getSpecialists({ + search: params.search, + // page: params['page-number'] || 0, + includes: 'unit', + }) return { success: result.success || false, body: result.body || {} } }, entityName: 'specialist', diff --git a/app/composables/usePaginatedList.ts b/app/composables/usePaginatedList.ts index 379d2eb6..1940589b 100644 --- a/app/composables/usePaginatedList.ts +++ b/app/composables/usePaginatedList.ts @@ -2,6 +2,7 @@ import type { DataTableLoader } from '~/components/pub/base/data-table/type' import type { PaginationMeta } from '~/components/pub/custom-ui/pagination/pagination.type' import { refDebounced, useUrlSearchParams } from '@vueuse/core' import * as z from 'zod' +import { is } from "date-fns/locale" // Default query schema yang bisa digunakan semua list export const defaultQuerySchema = z.object({ @@ -75,6 +76,8 @@ export function usePaginatedList(options: UsePaginatedListOptions) { // Functions async function fetchData() { + if (isLoading.isTableLoading) return + isLoading.isTableLoading = true try { diff --git a/app/services/division-position.service.ts b/app/services/division-position.service.ts index 07cfbd15..1c1855af 100644 --- a/app/services/division-position.service.ts +++ b/app/services/division-position.service.ts @@ -15,7 +15,7 @@ export async function getDivisionPositions(params: any = null) { const queryString = searchParams.toString() if (queryString) url += `?${queryString}` } - const resp = await xfetch(mainUrl, 'GET') + const resp = await xfetch(url, 'GET') const result: any = {} result.success = resp.success result.body = (resp.body as Record) || {} diff --git a/app/services/division.service.ts b/app/services/division.service.ts index 38cd6118..e58af288 100644 --- a/app/services/division.service.ts +++ b/app/services/division.service.ts @@ -15,7 +15,7 @@ export async function getDivisions(params: any = null) { const queryString = searchParams.toString() if (queryString) url += `?${queryString}` } - const resp = await xfetch(mainUrl, 'GET') + const resp = await xfetch(url, 'GET') const result: any = {} result.success = resp.success result.body = (resp.body as Record) || {} diff --git a/app/services/installation.service.ts b/app/services/installation.service.ts index 8fd9e858..aaa38c03 100644 --- a/app/services/installation.service.ts +++ b/app/services/installation.service.ts @@ -15,7 +15,7 @@ export async function getInstallations(params: any = null) { const queryString = searchParams.toString() if (queryString) url += `?${queryString}` } - const resp = await xfetch(mainUrl, 'GET') + const resp = await xfetch(url, 'GET') const result: any = {} result.success = resp.success result.body = (resp.body as Record) || {} diff --git a/app/services/medicine-group.service.ts b/app/services/medicine-group.service.ts index e1f06863..cd2be9f0 100644 --- a/app/services/medicine-group.service.ts +++ b/app/services/medicine-group.service.ts @@ -15,7 +15,7 @@ export async function getMedicineGroups(params: any = null) { const queryString = searchParams.toString() if (queryString) url += `?${queryString}` } - const resp = await xfetch(mainUrl, 'GET') + const resp = await xfetch(url, 'GET') const result: any = {} result.success = resp.success result.body = (resp.body as Record) || {} diff --git a/app/services/medicine-method.service.ts b/app/services/medicine-method.service.ts index 3050671c..44f17f34 100644 --- a/app/services/medicine-method.service.ts +++ b/app/services/medicine-method.service.ts @@ -23,7 +23,7 @@ export async function getMedicineMethods(params: any = null) { const queryString = searchParams.toString() if (queryString) url += `?${queryString}` } - const resp = await xfetch(mainUrl, 'GET') + const resp = await xfetch(url, 'GET') const result: any = {} result.success = resp.success result.body = (resp.body as Record) || {} diff --git a/app/services/specialist.service.ts b/app/services/specialist.service.ts index bd359918..4e1c2634 100644 --- a/app/services/specialist.service.ts +++ b/app/services/specialist.service.ts @@ -15,7 +15,7 @@ export async function getSpecialists(params: any = null) { const queryString = searchParams.toString() if (queryString) url += `?${queryString}` } - const resp = await xfetch(mainUrl, 'GET') + const resp = await xfetch(url, 'GET') const result: any = {} result.success = resp.success result.body = (resp.body as Record) || {} diff --git a/app/services/subspecialist.service.ts b/app/services/subspecialist.service.ts index c218b748..a5356353 100644 --- a/app/services/subspecialist.service.ts +++ b/app/services/subspecialist.service.ts @@ -15,7 +15,7 @@ export async function getSubspecialists(params: any = null) { const queryString = searchParams.toString() if (queryString) url += `?${queryString}` } - const resp = await xfetch(mainUrl, 'GET') + const resp = await xfetch(url, 'GET') const result: any = {} result.success = resp.success result.body = (resp.body as Record) || {} diff --git a/app/services/unit.service.ts b/app/services/unit.service.ts index 82d565db..052fb707 100644 --- a/app/services/unit.service.ts +++ b/app/services/unit.service.ts @@ -15,7 +15,7 @@ export async function getUnits(params: any = null) { const queryString = searchParams.toString() if (queryString) url += `?${queryString}` } - const resp = await xfetch(mainUrl, 'GET') + const resp = await xfetch(url, 'GET') const result: any = {} result.success = resp.success result.body = (resp.body as Record) || {} diff --git a/app/services/uom.service.ts b/app/services/uom.service.ts index f7b2eec1..e01b59b3 100644 --- a/app/services/uom.service.ts +++ b/app/services/uom.service.ts @@ -15,7 +15,7 @@ export async function getUoms(params: any = null) { const queryString = searchParams.toString() if (queryString) url += `?${queryString}` } - const resp = await xfetch(mainUrl, 'GET') + const resp = await xfetch(url, 'GET') const result: any = {} result.success = resp.success result.body = (resp.body as Record) || {} From 0e115eed5ecc49c55af8820d0080dd5d1d5f5c04 Mon Sep 17 00:00:00 2001 From: riefive Date: Thu, 2 Oct 2025 14:37:17 +0700 Subject: [PATCH 12/19] fix: list unit --- app/components/app/unit/list-cfg.ts | 2 +- app/components/content/specialist/list.vue | 2 +- app/components/content/subspecialist/list.vue | 7 ++++++- app/components/content/unit/list.vue | 7 ++++++- 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/app/components/app/unit/list-cfg.ts b/app/components/app/unit/list-cfg.ts index 1e3a46be..b491d4f2 100644 --- a/app/components/app/unit/list-cfg.ts +++ b/app/components/app/unit/list-cfg.ts @@ -30,7 +30,7 @@ export const funcParsed: RecStrFuncUnknown = { }, installation: (rec: unknown): unknown => { const recX = rec as SmallDetailDto - return recX.installation?.name || '-' + return recX.installation?.name || recX.Installation?.name || '-' }, } diff --git a/app/components/content/specialist/list.vue b/app/components/content/specialist/list.vue index 27b25e6b..6e68b1b3 100644 --- a/app/components/content/specialist/list.vue +++ b/app/components/content/specialist/list.vue @@ -49,7 +49,7 @@ const { // TODO: use pagination params const result = await getSpecialists({ search: params.search, - // page: params['page-number'] || 0, + page: params['page-number'] || 0, includes: 'unit', }) return { success: result.success || false, body: result.body || {} } diff --git a/app/components/content/subspecialist/list.vue b/app/components/content/subspecialist/list.vue index 5571f632..5a9d2748 100644 --- a/app/components/content/subspecialist/list.vue +++ b/app/components/content/subspecialist/list.vue @@ -45,7 +45,12 @@ const { fetchData: getSubSpecialistList, } = usePaginatedList({ fetchFn: async (params: any) => { - const result = await getSubspecialists({ search: params.search, page: params['page-number'] || 0 }) + // TODO: use pagination params + const result = await getSubspecialists({ + search: params.search, + page: params['page-number'] || 0, + includes: 'specialist', + }) return { success: result.success || false, body: result.body || {} } }, entityName: 'subspecialist', diff --git a/app/components/content/unit/list.vue b/app/components/content/unit/list.vue index 1e8edd99..d7c1a34f 100644 --- a/app/components/content/unit/list.vue +++ b/app/components/content/unit/list.vue @@ -45,7 +45,12 @@ const { fetchData: getUnitList, } = usePaginatedList({ fetchFn: async (params: any) => { - const result = await getUnits({ search: params.search, page: params['page-number'] || 0, includes: 'installation' }) + // TODO: use pagination params + const result = await getUnits({ + search: params.search, + page: params['page-number'] || 0, + includes: 'installation', + }) return { success: result.success || false, body: result.body || {} } }, entityName: 'unit', From 378e6773b8009b3a203ad2c2618353d9004a58d1 Mon Sep 17 00:00:00 2001 From: riefive Date: Thu, 2 Oct 2025 14:49:55 +0700 Subject: [PATCH 13/19] fix: handler reset state --- app/components/content/division/list.vue | 2 +- app/handlers/_handler.ts | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/app/components/content/division/list.vue b/app/components/content/division/list.vue index 0529e77a..482fd84b 100644 --- a/app/components/content/division/list.vue +++ b/app/components/content/division/list.vue @@ -129,7 +129,7 @@ onMounted(async () => { class="mb-4 xl:mb-5" /> - + {{ recId }} - {{ recAction }} (crud: { if (refresh) refresh() }, onFinally: (isSuccess: boolean) => { - setTimeout(reset, 300) + if (isSuccess) setTimeout(reset, 300) + onResetState() isProcessing.value = false }, }) @@ -58,7 +59,8 @@ export function createCrudHandler(crud: { if (refresh) refresh() }, onFinally: (isSuccess: boolean) => { - setTimeout(reset, 300) + if (isSuccess) setTimeout(reset, 300) + onResetState() isProcessing.value = false }, }) @@ -78,6 +80,7 @@ export function createCrudHandler(crud: { }, onFinally: () => { setTimeout(refresh, 300) + onResetState() isProcessing.value = false }, }) @@ -86,6 +89,7 @@ export function createCrudHandler(crud: { function handleCancelForm(reset: () => void) { isFormEntryDialogOpen.value = false isReadonly.value = false + onResetState() setTimeout(reset, 300) } From 757b8c044430082bdadc2ebc9a76c6a80fa1cbd3 Mon Sep 17 00:00:00 2001 From: riefive Date: Thu, 2 Oct 2025 15:31:27 +0700 Subject: [PATCH 14/19] test: call division position --- app/components/app/division/entry-form.vue | 4 ++-- app/components/content/division/list.vue | 13 ++++++++++--- app/handlers/_shared.handler.ts | 10 +++++----- app/models/division.ts | 1 + app/schemas/division.schema.ts | 1 + 5 files changed, 19 insertions(+), 10 deletions(-) diff --git a/app/components/app/division/entry-form.vue b/app/components/app/division/entry-form.vue index d6f7556f..118d1b6c 100644 --- a/app/components/app/division/entry-form.vue +++ b/app/components/app/division/entry-form.vue @@ -35,7 +35,7 @@ const { defineField, errors, meta } = useForm({ initialValues: { code: '', name: '', - division_id: '', + division_id: 0, } as Partial, }) @@ -57,7 +57,7 @@ const resetForm = () => { } // Form submission handler -function onSubmitForm(values: any) { +function onSubmitForm() { const formData: DivisionFormData = { name: name.value || '', code: code.value || '', diff --git a/app/components/content/division/list.vue b/app/components/content/division/list.vue index 482fd84b..d759192e 100644 --- a/app/components/content/division/list.vue +++ b/app/components/content/division/list.vue @@ -32,6 +32,7 @@ import { divisions, getDivisionParentList } from '~/handlers/_shared.handler' // Services import { getDivisions, getDivisionDetail } from '~/services/division.service' +import { getDivisionPositions } from '~/services/division-position.service' const title = ref('') @@ -114,10 +115,15 @@ watch([recId, recAction], () => { } }) -onMounted(async () => { - await getDivisionList() +watch(() => data.value, async () => { + if (!data.value) return await getDivisionParentList(false, data.value || []) }) + +onMounted(async () => { + await getDivisionPositions() + await getDivisionList() +})