From 0ae1923f275327c197549db1f64610764864dfd1 Mon Sep 17 00:00:00 2001 From: Khafid Prayoga Date: Tue, 16 Sep 2025 15:38:06 +0700 Subject: [PATCH] refactor(division): move entry logic to shared config file Extract division form configuration and tree logic from entry.vue component into a shared entry.ts file. This improves code organization and reusability while maintaining the same functionality. --- app/components/app/divison/entry-form.vue | 1 - app/components/content/division/entry.ts | 173 ++++++++++++++++------ app/components/content/division/entry.vue | 154 ------------------- app/components/content/division/list.vue | 19 ++- 4 files changed, 142 insertions(+), 205 deletions(-) delete mode 100644 app/components/content/division/entry.vue diff --git a/app/components/app/divison/entry-form.vue b/app/components/app/divison/entry-form.vue index 1780895a..7f21d90a 100644 --- a/app/components/app/divison/entry-form.vue +++ b/app/components/app/divison/entry-form.vue @@ -23,7 +23,6 @@ const props = defineProps<{ items: { value: string label: string - code: string }[] } divisionTree?: { diff --git a/app/components/content/division/entry.ts b/app/components/content/division/entry.ts index 60617c45..aef024e7 100644 --- a/app/components/content/division/entry.ts +++ b/app/components/content/division/entry.ts @@ -1,58 +1,145 @@ +import type { TreeItem } from '~/components/pub/base/select-tree/type' import * as z from 'zod' -export const division = { +export const divisionConf = { msg: { placeholder: '---pilih divisi utama', search: 'kode, nama divisi', empty: 'divisi tidak ditemukan', }, items: [ - { value: '1', label: 'Medical', code: 'MED' }, - { value: '2', label: 'Nursing', code: 'NUR' }, - { value: '3', label: 'Admin', code: 'ADM' }, - { value: '4', label: 'Support', code: 'SUP' }, - { value: '5', label: 'Education', code: 'EDU' }, - { value: '6', label: 'Pharmacy', code: 'PHA' }, - { value: '7', label: 'Radiology', code: 'RAD' }, - { value: '8', label: 'Laboratory', code: 'LAB' }, - { value: '9', label: 'Finance', code: 'FIN' }, - { value: '10', label: 'Human Resources', code: 'HR' }, - { value: '11', label: 'IT Services', code: 'ITS' }, - { value: '12', label: 'Maintenance', code: 'MNT' }, - { value: '13', label: 'Catering', code: 'CAT' }, - { value: '14', label: 'Security', code: 'SEC' }, - { value: '15', label: 'Emergency', code: 'EMR' }, - { value: '16', label: 'Surgery', code: 'SUR' }, - { value: '17', label: 'Outpatient', code: 'OUT' }, - { value: '18', label: 'Inpatient', code: 'INP' }, - { value: '19', label: 'Rehabilitation', code: 'REB' }, - { value: '20', label: 'Research', code: 'RSH' }, + { value: '1', label: 'Medical' }, + { value: '2', label: 'Nursing' }, + { value: '3', label: 'Admin' }, + { value: '4', label: 'Support' }, + { value: '5', label: 'Education' }, + { value: '6', label: 'Pharmacy' }, + { value: '7', label: 'Radiology' }, + { value: '8', label: 'Laboratory' }, + { value: '9', label: 'Finance' }, + { value: '10', label: 'Human Resources' }, + { value: '11', label: 'IT Services' }, + { value: '12', label: 'Maintenance' }, + { value: '13', label: 'Catering' }, + { value: '14', label: 'Security' }, + { value: '15', label: 'Emergency' }, + { value: '16', label: 'Surgery' }, + { value: '17', label: 'Outpatient' }, + { value: '18', label: 'Inpatient' }, + { value: '19', label: 'Rehabilitation' }, + { value: '20', label: 'Research' }, ], } export const schema = z.object({ - name: z.string({ - required_error: 'Nama wajib diisi', - }).min(1, 'Nama divisi wajib diisi'), + name: z + .string({ + required_error: 'Nama wajib diisi', + }) + .min(1, 'Nama divisi wajib diisi'), - code: z.string({ - required_error: 'Kode wajib diisi', - }).min(1, 'Kode divisi wajib diisi'), + code: z + .string({ + required_error: 'Kode wajib diisi', + }) + .min(1, 'Kode divisi wajib diisi'), - parentId: z.preprocess( - (input: unknown) => { - if (typeof input === 'string') { - // Handle empty string case - if (input.trim() === '') { - return undefined - } - return Number(input) - } - - return input - }, - z.number({ - required_error: 'Kelompok wajib dipilih', - }).min(1, 'Kelompok wajib dipilih'), - ), + parentId: z.string().optional(), }) + +// State untuk tree data divisi - dimulai dengan data level atas +const divisionTreeData = ref([ + { value: '1', label: 'Medical', hasChildren: true }, + { value: '2', label: 'Nursing', hasChildren: true }, + { value: '3', label: 'Admin', hasChildren: false }, + { value: '4', label: 'Support', hasChildren: true }, + { value: '5', label: 'Education', hasChildren: false }, + { value: '6', label: 'Pharmacy', hasChildren: true }, + { value: '7', label: 'Radiology', hasChildren: false }, + { value: '8', label: 'Laboratory', hasChildren: true }, +]) + +// Helper function untuk mencari dan menyisipkan data anak ke dalam tree +function findAndInsertChildren(nodes: TreeItem[], parentId: string, newChildren: TreeItem[]): boolean { + for (const node of nodes) { + if (node.value === parentId) { + node.children = newChildren + return true + } + if (node.children && findAndInsertChildren(node.children as TreeItem[], parentId, newChildren)) { + return true + } + } + return false +} + +// Fungsi untuk fetch data anak divisi (lazy loading) +async function handleFetchDivisionChildren(parentId: string): Promise { + console.log(`Mengambil data sub-divisi untuk parent: ${parentId}`) + + // Simulasi delay API call + await new Promise((resolve) => setTimeout(resolve, 800)) + + let childrenData: TreeItem[] = [] + + // Sample data berdasarkan parent ID + switch (parentId) { + case '1': // Medical + childrenData = [ + { value: '1-1', label: 'Cardiology', hasChildren: true }, + { value: '1-2', label: 'Neurology', hasChildren: false }, + { value: '1-3', label: 'Oncology', hasChildren: false }, + ] + break + case '2': // Nursing + childrenData = [ + { value: '2-1', label: 'ICU Nursing', hasChildren: false }, + { value: '2-2', label: 'ER Nursing', hasChildren: false }, + { value: '2-3', label: 'Ward Nursing', hasChildren: true }, + ] + break + case '4': // Support + childrenData = [ + { value: '4-1', label: 'IT Support', hasChildren: false }, + { value: '4-2', label: 'Maintenance', hasChildren: false }, + ] + break + case '6': // Pharmacy + childrenData = [ + { value: '6-1', label: 'Inpatient Pharmacy', hasChildren: false }, + { value: '6-2', label: 'Outpatient Pharmacy', hasChildren: false }, + ] + break + case '8': // Laboratory + childrenData = [ + { value: '8-1', label: 'Clinical Lab', hasChildren: false }, + { value: '8-2', label: 'Pathology Lab', hasChildren: false }, + ] + break + case '1-1': // Cardiology sub-divisions + childrenData = [ + { value: '1-1-1', label: 'Cardiac Surgery', hasChildren: false }, + { value: '1-1-2', label: 'Cardiac Cathlab', hasChildren: false }, + ] + break + case '2-3': // Ward Nursing sub-divisions + childrenData = [ + { value: '2-3-1', label: 'Pediatric Ward', hasChildren: false }, + { value: '2-3-2', label: 'Surgical Ward', hasChildren: false }, + ] + break + } + + // Insert data ke dalam tree state + findAndInsertChildren(divisionTreeData.value, parentId, childrenData) +} + +export const divisionTreeConfig = computed(() => ({ + msg: { + placeholder: '--- Pilih divisi induk', + search: 'Cari divisi...', + empty: 'Divisi tidak ditemukan', + }, + data: divisionTreeData.value, + onFetchChildren: handleFetchDivisionChildren, +})) diff --git a/app/components/content/division/entry.vue b/app/components/content/division/entry.vue deleted file mode 100644 index a6ccf816..00000000 --- a/app/components/content/division/entry.vue +++ /dev/null @@ -1,154 +0,0 @@ - - - diff --git a/app/components/content/division/list.vue b/app/components/content/division/list.vue index 511a5a1a..9c2a2ecd 100644 --- a/app/components/content/division/list.vue +++ b/app/components/content/division/list.vue @@ -1,12 +1,12 @@