diff --git a/app/components/app/specialist/entry-form-prev.vue b/app/components/app/specialist/entry-form-prev.vue new file mode 100644 index 00000000..2dbfffc1 --- /dev/null +++ b/app/components/app/specialist/entry-form-prev.vue @@ -0,0 +1,181 @@ + + + + + onSubmitForm(values, { resetForm }))"> + + + + Nama + + + + + + + + + + + + + + Kode + + + + + + + + + + + + + + Instalasi + + + + + onInstallationChanged(value, setFieldValue)" + /> + + + + + + + + + Unit + + + + + + + + + + + + + + + + + Batal + + + Simpan + + + + + diff --git a/app/components/app/specialist/entry-form.vue b/app/components/app/specialist/entry-form.vue index 2dbfffc1..d3391208 100644 --- a/app/components/app/specialist/entry-form.vue +++ b/app/components/app/specialist/entry-form.vue @@ -1,181 +1,119 @@ - - onSubmitForm(values, { resetForm }))"> - - - - Nama - - - - - - - - - - - - - - Kode - - - - - - - - - - - - - - Instalasi - - - - - onInstallationChanged(value, setFieldValue)" - /> - - - - - - - - - Unit - - - - - - - - - - - - - - - - - Batal - - - Simpan - - - - + + + + Kode + + + + + + Nama + + + + + + Unit + + + + + + + Kembali + + Simpan + + + diff --git a/app/components/app/specialist/list-cfg.ts b/app/components/app/specialist/list-cfg.ts index 367d4d9f..afce3e16 100644 --- a/app/components/app/specialist/list-cfg.ts +++ b/app/components/app/specialist/list-cfg.ts @@ -10,15 +10,13 @@ import { defineAsyncComponent } from 'vue' type SmallDetailDto = any -const action = defineAsyncComponent(() => import('~/components/pub/custom-ui/data/dropdown-action-ud.vue')) +const action = defineAsyncComponent(() => import('~/components/pub/custom-ui/data/dropdown-action-dud.vue')) -export const cols: Col[] = [{ width: 100 }, {}, {}, {}, { width: 50 }] +export const cols: Col[] = [{}, {}, {}, { width: 50 }] -export const header: Th[][] = [ - [{ label: 'Id' }, { label: 'Name' }, { label: 'Code' }, { label: 'Unit' }, { label: '' }], -] +export const header: Th[][] = [[{ label: 'Kode' }, { label: 'Nama' }, { label: 'Unit' }, { label: '' }]] -export const keys = ['id', 'name', 'cellphone', 'religion_code', 'action'] +export const keys = ['code', 'name', 'unit', 'action'] export const delKeyNames: KeyLabel[] = [ { key: 'code', label: 'Kode' }, @@ -28,7 +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() + return `${recX.name}`.trim() }, } @@ -38,13 +36,9 @@ export const funcComponent: RecStrFuncComponent = { idx, rec: rec as object, component: action, - props: { - size: 'sm', - }, } return res }, } -export const funcHtml: RecStrFuncUnknown = { -} +export const funcHtml: RecStrFuncUnknown = {} diff --git a/app/components/app/unit/entry-form.vue b/app/components/app/unit/entry-form.vue index 5e3566b7..7bad3552 100644 --- a/app/components/app/unit/entry-form.vue +++ b/app/components/app/unit/entry-form.vue @@ -71,7 +71,7 @@ function onCancelForm() { - + Kode diff --git a/app/components/app/unit/list-cfg.ts b/app/components/app/unit/list-cfg.ts index c341342e..a6f5ffc7 100644 --- a/app/components/app/unit/list-cfg.ts +++ b/app/components/app/unit/list-cfg.ts @@ -10,9 +10,9 @@ import { defineAsyncComponent } from 'vue' type SmallDetailDto = any -const action = defineAsyncComponent(() => import('~/components/pub/custom-ui/data/dropdown-action-ud.vue')) +const action = defineAsyncComponent(() => import('~/components/pub/custom-ui/data/dropdown-action-dud.vue')) -export const cols: Col[] = [{ width: 100 }, {}, {}, { width: 50 }] +export const cols: Col[] = [{}, {}, {}, { width: 50 }] export const header: Th[][] = [[{ label: 'Kode' }, { label: 'Nama' }, { label: 'Instalasi' }, { label: '' }]] @@ -28,6 +28,9 @@ export const funcParsed: RecStrFuncUnknown = { const recX = rec as SmallDetailDto return `${recX.name}`.trim() }, + installation: (_rec: unknown): unknown => { + return '-' + }, } export const funcComponent: RecStrFuncComponent = { diff --git a/app/components/content/division/list.vue b/app/components/content/division/list.vue index 5c6c83ce..0acae66d 100644 --- a/app/components/content/division/list.vue +++ b/app/components/content/division/list.vue @@ -3,6 +3,7 @@ import Dialog from '~/components/pub/base/modal/dialog.vue' import Header from '~/components/pub/custom-ui/nav-header/prep.vue' import RecordConfirmation from '~/components/pub/custom-ui/confirmation/record-confirmation.vue' +import AppDivisionList from '~/components/app/division/list.vue' import AppDivisionEntryForm from '~/components/app/division/entry-form.vue' // Helpers @@ -121,7 +122,7 @@ onMounted(async () => { @search="handleSearch" class="mb-4 xl:mb-5" /> - + +import type { HeaderPrep } from '~/components/pub/custom-ui/data/types' +import AppSpecialistEntryForm from '~/components/app/specialist/entry-form.vue' +import Dialog from '~/components/pub/base/modal/dialog.vue' +import RecordConfirmation from '~/components/pub/custom-ui/confirmation/record-confirmation.vue' +import { ActionEvents } from '~/components/pub/custom-ui/data/types' +import Header from '~/components/pub/custom-ui/nav-header/header.vue' +import { usePaginatedList } from '~/composables/usePaginatedList' +import { createFilteredUnitConf, installationConf, schemaConf, unitConf } from './entry' + +// #region State & Computed +// Dialog state +const isFormEntryDialogOpen = ref(false) +const isRecordConfirmationOpen = ref(false) + +// Table action rowId provider +const recId = ref(0) +const recAction = ref('') +const recItem = ref(null) + +// State untuk tracking installation yang dipilih di form +const selectedInstallationId = ref('') + +// Computed untuk filtered unit berdasarkan installation yang dipilih +const filteredUnitConf = computed(() => { + if (!selectedInstallationId.value) { + return { ...unitConf, items: [] } + } + return createFilteredUnitConf(selectedInstallationId.value) +}) + +const { + data, + isLoading, + paginationMeta, + searchInput, + handlePageChange, + handleSearch, + fetchData: getSpecialistList, +} = usePaginatedList({ + fetchFn: fetchSpecialistData, + entityName: 'specialist', +}) + +const headerPrep: HeaderPrep = { + title: 'Specialist', + icon: 'i-lucide-box', + refSearchNav: { + placeholder: 'Cari (min. 3 karakter)...', + minLength: 3, + debounceMs: 500, + showValidationFeedback: true, + onInput: (_val: string) => { + // Handle search input - this will be triggered by the header component + }, + onClick: () => { + // Handle search button click if needed + }, + onClear: () => { + // Handle search clear + }, + }, + addNav: { + label: 'Tambah Specialist', + icon: 'i-lucide-send', + onClick: () => { + isFormEntryDialogOpen.value = true + }, + }, +} + +provide('rec_id', recId) +provide('rec_action', recAction) +provide('rec_item', recItem) +provide('table_data_loader', isLoading) +// #endregion + +// #region Functions +async function fetchSpecialistData(params: any) { + const endpoint = transform('/api/v1/patient', params) + return await xfetch(endpoint) +} + +async function handleDeleteRow(record: any) { + try { + // TODO : hit backend request untuk delete + console.log('Deleting record:', record) + + // Simulate API call + // const response = await xfetch(`/api/v1/Installation/${record.id}`, { + // method: 'DELETE' + // }) + + // Refresh data setelah berhasil delete + await getSpecialistList() + + // TODO: Show success message + console.log('Record deleted successfully') + } catch (error) { + console.error('Error deleting record:', error) + // TODO: Show error message + } finally { + // Reset record state + recId.value = 0 + recAction.value = '' + recItem.value = null + } +} + +// Handle confirmation result +function handleConfirmDelete(record: any, action: string) { + console.log('Confirmed action:', action, 'for record:', record) + handleDeleteRow(record) +} + +function handleCancelConfirmation() { + // Reset record state when cancelled + recId.value = 0 + recAction.value = '' + recItem.value = null +} + +// #endregion region + +// #region Form event handlers + +function onCancelForm(resetForm: () => void) { + isFormEntryDialogOpen.value = false + // Reset installation selection ketika form dibatal + selectedInstallationId.value = '' + setTimeout(() => { + resetForm() + }, 500) +} + +function onInstallationChanged(installationId: string) { + // Update local state untuk trigger re-render filtered units + selectedInstallationId.value = installationId + + // The filteredUnitConf computed will automatically update + // based on the new selectedInstallationId value +} + +async function onSubmitForm(values: any, resetForm: () => void) { + let isSuccess = false + try { + // TODO: Implement form submission logic + console.log('Form submitted:', values) + + // Simulate API call + // const response = await xfetch('/api/v1/Installation', { + // method: 'POST', + // body: JSON.stringify(values) + // }) + + // If successful, mark as success and close dialog + isFormEntryDialogOpen.value = false + isSuccess = true + + // Reset installation selection ketika form berhasil submit + selectedInstallationId.value = '' + + // Refresh data after successful submission + await getSpecialistList() + + // TODO: Show success message + console.log('Installation 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(() => { + resetForm() + }, 500) + } + } +} +// #endregion + +// #region Watchers + +// Watch for row actions +watch(recId, () => { + switch (recAction.value) { + case ActionEvents.showEdit: + // TODO: Handle edit action + // isFormEntryDialogOpen.value = true + break + case ActionEvents.showConfirmDelete: + // Trigger confirmation modal open + isRecordConfirmationOpen.value = true + break + } +}) + +// Note: Installation change logic is now handled by the entry-form component +// through the onInstallationChanged event handler +// #endregion + + + + + + + + + + + + + + ID: {{ record?.id }} + Nama: {{ record.firstName }} + Kode: {{ record.cellphone }} + + + + + + diff --git a/app/components/content/specialist/list.vue b/app/components/content/specialist/list.vue index 7cf4e993..9f3c9ef8 100644 --- a/app/components/content/specialist/list.vue +++ b/app/components/content/specialist/list.vue @@ -1,33 +1,41 @@ - + - + , resetForm: () => void) => { + if (recId > 0) { + handleActionEdit(recId, values, getSpecialistList, resetForm, toast) + return + } + handleActionSave(values, getSpecialistList, resetForm, toast) + } + " + @cancel="handleCancelForm" /> + handleActionRemove(recId, getSpecialistList, toast)" + @cancel="" > ID: {{ record?.id }} - Nama: {{ record.firstName }} - Kode: {{ record.cellphone }} + Nama: {{ record.name }} + Kode: {{ record.code }} - - diff --git a/app/components/content/tools/list.vue b/app/components/content/tools/list.vue index f0ea8af9..27e90f56 100644 --- a/app/components/content/tools/list.vue +++ b/app/components/content/tools/list.vue @@ -3,6 +3,7 @@ import Dialog from '~/components/pub/base/modal/dialog.vue' import Header from '~/components/pub/custom-ui/nav-header/prep.vue' import RecordConfirmation from '~/components/pub/custom-ui/confirmation/record-confirmation.vue' +import AppToolsList from '~/components/app/tools/list.vue' import AppToolsEntryForm from '~/components/app/tools/entry-form.vue' // Helpers diff --git a/app/components/content/unit/list.vue b/app/components/content/unit/list.vue index b2badd43..3dcd184d 100644 --- a/app/components/content/unit/list.vue +++ b/app/components/content/unit/list.vue @@ -3,6 +3,7 @@ import Dialog from '~/components/pub/base/modal/dialog.vue' import Header from '~/components/pub/custom-ui/nav-header/prep.vue' import RecordConfirmation from '~/components/pub/custom-ui/confirmation/record-confirmation.vue' +import AppUnitList from '~/components/app/unit/list.vue' import AppUnitEntryForm from '~/components/app/unit/entry-form.vue' // Helpers @@ -121,7 +122,7 @@ onMounted(async () => { @search="handleSearch" class="mb-4 xl:mb-5" /> - + & Specialist + +export { SpecialistSchema } +export type { SpecialistFormData }
ID: {{ record?.id }}
Nama: {{ record.firstName }}
Kode: {{ record.cellphone }}
Nama: {{ record.name }}
Kode: {{ record.code }}