diff --git a/app/components/app/divison/list-cfg.ts b/app/components/app/divison/list-cfg.ts
index 45cfcd6f..509b47ee 100644
--- a/app/components/app/divison/list-cfg.ts
+++ b/app/components/app/divison/list-cfg.ts
@@ -10,29 +10,32 @@ import { defineAsyncComponent } from 'vue'
type SmallDetailDto = any
-const action = defineAsyncComponent(() => import('~/components/pub/custom-ui/data/dropdown-action-dud.vue'))
+const action = defineAsyncComponent(() => import('~/components/pub/custom-ui/data/dropdown-action-ud.vue'))
export const cols: Col[] = [
- {},
- {},
- {},
- {},
+ { width: 100 },
+ { },
+ { },
+ { },
+ { width: 50 },
]
export const header: Th[][] = [
[
{ label: 'Id' },
- { label: 'Kode' },
{ label: 'Nama' },
+ { label: 'Kode' },
{ label: 'Kelompok' },
+ { label: '' },
],
]
export const keys = [
'id',
- 'cellphone',
'firstName',
+ 'cellphone',
'birth_place',
+ 'action',
]
export const delKeyNames: KeyLabel[] = [
diff --git a/app/components/flow/division/entry.ts b/app/components/flow/division/entry.ts
new file mode 100644
index 00000000..60617c45
--- /dev/null
+++ b/app/components/flow/division/entry.ts
@@ -0,0 +1,58 @@
+import * as z from 'zod'
+
+export const division = {
+ 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' },
+ ],
+}
+
+export const schema = z.object({
+ 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'),
+
+ 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'),
+ ),
+})
diff --git a/app/components/flow/division/entry.vue b/app/components/flow/division/entry.vue
deleted file mode 100644
index cdd237ac..00000000
--- a/app/components/flow/division/entry.vue
+++ /dev/null
@@ -1,98 +0,0 @@
-
-
-
-
-
- Tambah Divisi
-
-
-
-
diff --git a/app/components/flow/division/list.vue b/app/components/flow/division/list.vue
index 28f514b6..96b3a66a 100644
--- a/app/components/flow/division/list.vue
+++ b/app/components/flow/division/list.vue
@@ -2,8 +2,11 @@
import type { DataTableLoader } from '~/components/pub/base/data-table/type'
import type { HeaderPrep } from '~/components/pub/custom-ui/data/types'
import type { PaginationMeta } from '~/components/pub/custom-ui/pagination/pagination.type'
+import { toTypedSchema } from '@vee-validate/zod'
import { refDebounced, useUrlSearchParams } from '@vueuse/core'
+import Combobox from '~/components/pub/custom-ui/form/combobox.vue'
import Header from '~/components/pub/custom-ui/nav-header/header.vue'
+import { division as divisionConf, schema as schemaConf } from './entry'
import { defaultQuery, querySchema } from './schema.query'
// #region State & Computed
@@ -11,6 +14,7 @@ const data = ref([])
const isLoading = reactive({
isTableLoading: false,
})
+const isDialogOpen = ref(false)
// URL state management
const queryParams = useUrlSearchParams('history', {
@@ -33,6 +37,11 @@ const paginationMeta = reactive({
hasPrev: false,
})
+// Table action rowId provider
+const recId = ref(0)
+const recAction = ref('')
+const recItem = ref(null)
+
// Search model with debounce
const searchInput = ref(params.value.q || '')
const debouncedSearch = refDebounced(searchInput, 500) // 500ms debounce
@@ -58,11 +67,17 @@ const headerPrep: HeaderPrep = {
addNav: {
label: 'Tambah Divisi',
icon: 'i-lucide-send',
- // todo: open modal form
- onClick: () => navigateTo('/org-src/division/add'),
+ onClick: () => {
+ isDialogOpen.value = true
+ },
},
}
+const formSchema = toTypedSchema(schemaConf)
+
+provide('rec_id', recId)
+provide('rec_action', recAction)
+provide('rec_item', recItem)
provide('table_data_loader', isLoading)
// #endregion
@@ -127,6 +142,54 @@ function handlePageChange(page: number) {
// #endregion region
// #region Utilities & event handlers
+
+function clearForm(setValues: (values: Record) => void) {
+ // Manually clear all form fields
+ setValues({
+ name: '',
+ code: '',
+ parentId: '',
+ })
+}
+
+function onCancelForm(setValues: (values: Record) => void) {
+ isDialogOpen.value = false
+ setTimeout(() => {
+ clearForm(setValues)
+ }, 500)
+}
+
+async function onSubmitForm(values: any, setValues: (values: Record) => void) {
+ let isSuccess = false
+ try {
+ // TODO: Implement form submission logic
+ console.log('Form submitted:', values)
+
+ // Simulate API call
+ // const response = await xfetch('/api/v1/division', {
+ // method: 'POST',
+ // body: JSON.stringify(values)
+ // })
+
+ // If successful, mark as success and close dialog
+ isDialogOpen.value = false
+ isSuccess = true
+
+ // TODO: Show success message
+ console.log('Division created successfully')
+ } catch (error: unknown) {
+ console.warn('Error submitting form:', error)
+ isSuccess = false
+ // Don't close dialog or reset form on error
+ // TODO: Show error message to user
+ } finally {
+ if (isSuccess) {
+ setTimeout(() => {
+ clearForm(setValues)
+ }, 500)
+ }
+ }
+}
// #endregion
// #region Watchers
@@ -161,6 +224,67 @@ watch(debouncedSearch, (newValue) => {
diff --git a/app/components/pub/custom-ui/form/combobox.vue b/app/components/pub/custom-ui/form/combobox.vue
index 74da7025..12171c85 100644
--- a/app/components/pub/custom-ui/form/combobox.vue
+++ b/app/components/pub/custom-ui/form/combobox.vue
@@ -8,6 +8,7 @@ interface Item {
}
const props = defineProps<{
+ id: string
modelValue?: string
items: Item[]
placeholder?: string
@@ -61,6 +62,7 @@ function onSelect(item: Item) {