diff --git a/app/components/app/subspecialist-position/entry-form.vue b/app/components/app/subspecialist-position/entry-form.vue index da4782c0..c897b2f5 100644 --- a/app/components/app/subspecialist-position/entry-form.vue +++ b/app/components/app/subspecialist-position/entry-form.vue @@ -7,18 +7,18 @@ import Label from '~/components/pub/my-ui/doc-entry/label.vue' import Combobox from '~/components/pub/my-ui/combobox/combobox.vue' // Types -import type { DivisionPositionFormData } from '~/schemas/division-position.schema' +import type { SubSpecialistPositionFormData } from '~/schemas/subspecialist-position.schema' // Helpers import type z from 'zod' import { toTypedSchema } from '@vee-validate/zod' import { useForm } from 'vee-validate' import { genBase } from '~/models/_base' -import { genDivisionPosition } from '~/models/division-position' +import { genSubSpecialistPosition } from '~/models/subspecialist-position' interface Props { schema: z.ZodSchema - divisionId: number + subSpecialists: any[] employees: any[] values: any isLoading?: boolean @@ -26,21 +26,21 @@ interface Props { } const props = defineProps() - const isLoading = props.isLoading !== undefined ? props.isLoading : false const isReadonly = props.isReadonly !== undefined ? props.isReadonly : false const emit = defineEmits<{ - submit: [values: DivisionPositionFormData, resetForm: () => void] + submit: [values: SubSpecialistPositionFormData, resetForm: () => void] cancel: [resetForm: () => void] }>() const { defineField, errors, meta } = useForm({ validationSchema: toTypedSchema(props.schema), - initialValues: genDivisionPosition() as Partial, + initialValues: genSubSpecialistPosition() as Partial, }) const [code, codeAttrs] = defineField('code') const [name, nameAttrs] = defineField('name') +const [subSpecialist, subSpecialistAttrs] = defineField('subspecialist_id') const [employee, employeeAttrs] = defineField('employee_id') const [headStatus, headStatusAttrs] = defineField('headStatus') @@ -62,6 +62,8 @@ const headStatusStr = computed({ if (props.values) { if (props.values.code !== undefined) code.value = props.values.code if (props.values.name !== undefined) name.value = props.values.name + if (props.values.subspecialist_id !== undefined) + subSpecialist.value = props.values.subspecialist_id ? Number(props.values.subspecialist_id) : null if (props.values.employee_id !== undefined) employee.value = props.values.employee_id ? Number(props.values.employee_id) : null if (props.values.headStatus !== undefined) headStatus.value = !!props.values.headStatus @@ -70,20 +72,18 @@ if (props.values) { const resetForm = () => { code.value = '' name.value = '' + subSpecialist.value = null employee.value = null headStatus.value = false } // Form submission handler function onSubmitForm() { - const formData: DivisionPositionFormData = { + const formData: SubSpecialistPositionFormData = { ...genBase(), name: name.value || '', code: code.value || '', - - // readonly based on detail division - division_id: props.divisionId, - + subspecialist_id: subSpecialist.value || null, employee_id: employee.value || null, headStatus: headStatus.value !== undefined ? headStatus.value : undefined, } @@ -98,7 +98,7 @@ function onCancelForm() { diff --git a/app/components/content/subspecialist-position/list.vue b/app/components/content/subspecialist-position/list.vue index 6ff2c2be..4c833ce2 100644 --- a/app/components/content/subspecialist-position/list.vue +++ b/app/components/content/subspecialist-position/list.vue @@ -3,16 +3,20 @@ import Dialog from '~/components/pub/my-ui/modal/dialog.vue' import Header from '~/components/pub/my-ui/nav-header/prep.vue' import RecordConfirmation from '~/components/pub/my-ui/confirmation/record-confirmation.vue' -import AppSubSpecialistList from '~/components/app/subspecialist/list.vue' -import AppSubSpecialistEntryForm from '~/components/app/subspecialist/entry-form.vue' +import AppSubSpecialistPositionList from '~/components/app/subspecialist-position/list.vue' +import AppSubSpecialistPositionEntryForm from '~/components/app/subspecialist-position/entry-form.vue' // Helpers import { usePaginatedList } from '~/composables/usePaginatedList' import { toast } from '~/components/pub/ui/toast' +import { config } from '~/components/app/subspecialist-position/list.cfg' // Types import { ActionEvents, type HeaderPrep } from '~/components/pub/my-ui/data/types' -import { SubspecialistSchema, type SubspecialistFormData } from '~/schemas/subspecialist.schema' +import { + type SubSpecialistPositionFormData, + SubSpecialistPositionSchema, +} from '~/schemas/subspecialist-position.schema' // Handlers import { @@ -28,13 +32,15 @@ import { handleActionEdit, handleActionRemove, handleCancelForm, -} from '~/handlers/subspecialist.handler' +} from '~/handlers/subspecialist-position.handler' // Services -import { getList, getDetail } from '~/services/subspecialist.service' -import { getValueLabelList as getSpecialistsList } from '~/services/specialist.service' +import { getList, getDetail } from '~/services/subspecialist-position.service' +import { getValueLabelList as getValueLabelSubSpecialistList } from '~/services/subspecialist.service' +import { getValueLabelList as getEmployeeLabelList } from '~/services/employee.service' -const specialists = ref<{ value: string | number; label: string }[]>([]) +const subSpecialists = ref<{ value: string | number; label: string }[]>([]) +const employees = ref<{ value: string | number; label: string }[]>([]) const title = ref('') const { @@ -52,11 +58,11 @@ const { sort: 'createdAt:asc', 'page-number': params['page-number'] || 0, 'page-size': params['page-size'] || 10, - includes: 'specialist', + includes: 'subspecialist,Employee.Person', }) return { success: result.success || false, body: result.body || {} } }, - entityName: 'subspecialist', + entityName: 'subspecialist-position', }) const headerPrep: HeaderPrep = { @@ -92,6 +98,7 @@ provide('table_data_loader', isLoading) const getCurrentSubSpecialistDetail = async (id: number | string) => { const result = await getDetail(id) + console.log(result) if (result.success) { const currentValue = result.body?.data || {} recItem.value = currentValue @@ -104,12 +111,12 @@ watch([recId, recAction], () => { switch (recAction.value) { case ActionEvents.showDetail: getCurrentSubSpecialistDetail(recId.value) - title.value = 'Detail Sub Spesialis' + title.value = 'Detail Sub Spesialis Posisi' isReadonly.value = true break case ActionEvents.showEdit: getCurrentSubSpecialistDetail(recId.value) - title.value = 'Edit Sub Spesialis' + title.value = 'Edit Sub Spesialis Posisi' isReadonly.value = false break case ActionEvents.showConfirmDelete: @@ -119,8 +126,18 @@ watch([recId, recAction], () => { }) onMounted(async () => { - specialists.value = await getSpecialistsList() - await getSubSpecialistList() + try { + subSpecialists.value = await getValueLabelSubSpecialistList({ sort: 'createdAt:asc', 'page-size': 100 }) + employees.value = await getEmployeeLabelList({ sort: 'createdAt:asc', 'page-size': 100, includes: 'person' }) + } catch (err) { + console.log(err) + // show toast + toast({ + title: 'Terjadi Kesalahan', + description: 'Terjadi kesalahan saat memuat data', + variant: 'destructive', + }) + } }) @@ -132,7 +149,7 @@ onMounted(async () => { @search="handleSearch" /> - { } " > - { @cancel="" > diff --git a/app/handlers/subspecialist-position.handler.ts b/app/handlers/subspecialist-position.handler.ts new file mode 100644 index 00000000..42473f86 --- /dev/null +++ b/app/handlers/subspecialist-position.handler.ts @@ -0,0 +1,24 @@ +// Handlers +import { genCrudHandler } from '~/handlers/_handler' + +// Services +import { create, update, remove } from '~/services/subspecialist-position.service' + +export const { + recId, + recAction, + recItem, + isReadonly, + isProcessing, + isFormEntryDialogOpen, + isRecordConfirmationOpen, + onResetState, + handleActionSave, + handleActionEdit, + handleActionRemove, + handleCancelForm, +} = genCrudHandler({ + create, + update, + remove, +}) diff --git a/app/models/subspecialist-position.ts b/app/models/subspecialist-position.ts index 660bd71b..28ea2287 100644 --- a/app/models/subspecialist-position.ts +++ b/app/models/subspecialist-position.ts @@ -1,5 +1,6 @@ import { type Base, genBase } from './_base' import type { Employee } from './employee' +import type { Subspecialist } from './subspecialist' export interface SubSpecialistPosition extends Base { subspecialist_id: number @@ -8,6 +9,7 @@ export interface SubSpecialistPosition extends Base { headStatus?: boolean employee_id?: number + subspecialist?: Subspecialist | null employee?: Employee | null } diff --git a/app/schemas/subspecialist-position.schema.ts b/app/schemas/subspecialist-position.schema.ts new file mode 100644 index 00000000..7f458e7b --- /dev/null +++ b/app/schemas/subspecialist-position.schema.ts @@ -0,0 +1,24 @@ +import { z } from 'zod' +import type { SubSpecialistPosition } from '~/models/subspecialist-position' + +const SubSpecialistPositionSchema = 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'), + headStatus: z.boolean().optional().nullable(), + subspecialist_id: z + .union([ + z.string({ required_error: 'Spesialis harus diisi' }), + z.number({ required_error: 'Spesialis harus diisi' }), + ]) + .optional() + .nullable(), + employee_id: z + .union([z.string({ required_error: 'Karyawan harus diisi' }), z.number({ required_error: 'Karyawan harus diisi' })]) + .optional() + .nullable(), +}) + +type SubSpecialistPositionFormData = z.infer & Partial + +export { SubSpecialistPositionSchema } +export type { SubSpecialistPositionFormData } diff --git a/app/services/subspecialist-position.service.ts b/app/services/subspecialist-position.service.ts new file mode 100644 index 00000000..9653100b --- /dev/null +++ b/app/services/subspecialist-position.service.ts @@ -0,0 +1,25 @@ +// Base +import * as base from './_crud-base' + +const path = '/api/v1/subspecialist-position' +const name = 'subspecialist-position' + +export function create(data: any) { + return base.create(path, data, name) +} + +export function getList(params: any = null) { + return base.getList(path, params, name) +} + +export function getDetail(id: number | string) { + return base.getDetail(path, id, name) +} + +export function update(id: number | string, data: any) { + return base.update(path, id, data, name) +} + +export function remove(id: number | string) { + return base.remove(path, id, name) +}