feat/consulation-82: done

This commit is contained in:
2025-10-20 09:34:42 +07:00
parent e1358c0d9e
commit f3b45f2cb1
8 changed files with 79 additions and 66 deletions
+10 -10
View File
@@ -10,10 +10,12 @@ import type z from 'zod'
import { toTypedSchema } from '@vee-validate/zod' import { toTypedSchema } from '@vee-validate/zod'
import { useForm } from 'vee-validate' import { useForm } from 'vee-validate'
import Textarea from '~/components/pub/ui/textarea/Textarea.vue' import Textarea from '~/components/pub/ui/textarea/Textarea.vue'
import type { CreateDto } from '~/models/consultation'
interface Props { interface Props {
schema: z.ZodSchema<any> schema: z.ZodSchema<any>
values: any values: CreateDto
encounter_id: number
units: { value: string; label: string }[] units: { value: string; label: string }[]
isLoading?: boolean isLoading?: boolean
isReadonly?: boolean isReadonly?: boolean
@@ -31,11 +33,9 @@ const today = new Date()
const { defineField, errors, meta } = useForm({ const { defineField, errors, meta } = useForm({
validationSchema: toTypedSchema(props.schema), validationSchema: toTypedSchema(props.schema),
initialValues: { initialValues: {
id: 0,
encounter_id: 0,
date: props.values.date || today.toISOString().slice(0, 10), date: props.values.date || today.toISOString().slice(0, 10),
problem: '', problem: '',
unit_id: 0, dstUnit_id: 0,
} as Partial<ConsultationFormData>, } as Partial<ConsultationFormData>,
}) })
@@ -45,8 +45,9 @@ const [problem, problemAttrs] = defineField('problem')
// Fill fields from props.values if provided // Fill fields from props.values if provided
if (props.values) { if (props.values) {
if (props.values.unit_id !== undefined) unit_id.value = props.values.unit_id if (props.values.date !== undefined) date.value = props.values.date.substring(0, 10)
if (props.values.code !== undefined) problem.value = props.values.problem if (props.values.dstUnit_id !== undefined) unit_id.value = props.values.dstUnit_id
if (props.values.problem !== undefined) problem.value = props.values.problem
} }
const resetForm = () => { const resetForm = () => {
@@ -58,11 +59,10 @@ const resetForm = () => {
// Form submission handler // Form submission handler
function onSubmitForm(values: any) { function onSubmitForm(values: any) {
const formData: ConsultationFormData = { const formData: ConsultationFormData = {
id: 0, encounter_id: props.encounter_id,
encounter_id: 0, date: date.value ? `${date.value}T00:00:00Z` : '',
date: date.value || '',
problem: problem.value || '', problem: problem.value || '',
unit_id: unit_id.value || 0, dstUnit_id: unit_id.value || 0,
} }
emit('submit', formData, resetForm) emit('submit', formData, resetForm)
} }
@@ -0,0 +1,54 @@
import type { Config, RecComponent, RecStrFuncComponent, RecStrFuncUnknown } from '~/components/pub/my-ui/data-table'
import { defineAsyncComponent } from 'vue'
import type { Consultation } from '~/models/consultation'
type SmallDetailDto = any
const action = defineAsyncComponent(() => import('~/components/pub/my-ui/data/dropdown-action-ud.vue'))
export const config: Config = {
cols: [{ width: 100 }, {}, {}, {}, { width: 50 }],
headers: [[
{ label: 'Tanggal' },
{ label: 'Tujuan' },
{ label: 'Dokter' },
{ label: 'Pertanyaan' },
{ label: 'Jawaban' },
{ label: '' },
]],
keys: ['date', 'dstUnit.name', 'dstDoctor.name', 'problem', 'solution', 'action'],
delKeyNames: [
{ key: 'data', label: 'Tanggal' },
{ key: 'dstDoctor.name', label: 'Dokter' },
],
parses: {
action(rec, idx) {
const res: RecComponent = {
idx,
rec: rec as object,
component: action,
props: {
size: 'sm',
},
}
return res
},
date(rec) {
const recX = rec as Consultation
return recX.date?.substring(0, 10) || '-'
}
},
components: {
action(rec, idx) {
const res: RecComponent = {
idx,
rec: rec as object,
component: action,
props: {
size: 'sm',
},
}
return res
},
} as RecStrFuncComponent,
htmls: {} as RecStrFuncUnknown,
}
-40
View File
@@ -1,40 +0,0 @@
import type {
Col,
KeyLabel,
RecComponent,
RecStrFuncComponent,
RecStrFuncUnknown,
Th,
} from '~/components/pub/my-ui/data/types'
import { defineAsyncComponent } from 'vue'
type SmallDetailDto = any
const action = defineAsyncComponent(() => import('~/components/pub/my-ui/data/dropdown-action-ud.vue'))
export const cols: Col[] = [{ width: 100 }, {}, {}, {}, { width: 50 }]
export const header: Th[][] = [[{ label: 'Tanggal' }, { label: 'Dokter' }, { label: 'Tujuan' }, { label: 'Pertanyaan' }, { label: 'Jawaban' }, { label: '' }]]
export const keys = ['date', 'dstDoctor.name', 'dstUnit.name', 'case', 'solution', 'action']
export const delKeyNames: KeyLabel[] = [
{ key: 'data', label: 'Tanggal' },
{ key: 'dstDoctor.name', label: 'Dokter' },
]
export const funcComponent: RecStrFuncComponent = {
action(rec, idx) {
const res: RecComponent = {
idx,
rec: rec as object,
component: action,
props: {
size: 'sm',
},
}
return res
},
}
export const funcHtml: RecStrFuncUnknown = {}
+4 -9
View File
@@ -1,14 +1,13 @@
<script setup lang="ts"> <script setup lang="ts">
import type { PaginationMeta } from '~/components/pub/my-ui/pagination/pagination.type' import type { PaginationMeta } from '~/components/pub/my-ui/pagination/pagination.type'
import PaginationView from '~/components/pub/my-ui/pagination/pagination-view.vue' import PaginationView from '~/components/pub/my-ui/pagination/pagination-view.vue'
import { cols, funcComponent, funcHtml, header, keys } from './list' import { config } from './list.cfg'
interface Props { interface Props {
data: any[] data: any[]
paginationMeta: PaginationMeta paginationMeta: PaginationMeta
} }
const props = defineProps<Props>()
defineProps<Props>()
const emit = defineEmits<{ const emit = defineEmits<{
pageChange: [page: number] pageChange: [page: number]
@@ -21,13 +20,9 @@ function handlePageChange(page: number) {
<template> <template>
<div class="space-y-4"> <div class="space-y-4">
<PubBaseDataTable <PubMyUiDataTable
v-bind="config"
:rows="data" :rows="data"
:cols="cols"
:header="header"
:keys="keys"
:func-html="funcHtml"
:func-component="funcComponent"
:skeleton-size="paginationMeta?.pageSize" :skeleton-size="paginationMeta?.pageSize"
/> />
<!-- FIXME: pindahkan ke content/division/list.vue --> <!-- FIXME: pindahkan ke content/division/list.vue -->
+6 -2
View File
@@ -41,7 +41,6 @@ interface Props {
encounter: Encounter encounter: Encounter
} }
const props = defineProps<Props>() const props = defineProps<Props>()
console.log(props.encounter);
let units = ref<{ value: string; label: string }[]>([]) let units = ref<{ value: string; label: string }[]>([])
const title = ref('') const title = ref('')
@@ -56,7 +55,10 @@ const {
fetchData: getMyList, fetchData: getMyList,
} = usePaginatedList({ } = usePaginatedList({
fetchFn: async ({ page, search }) => { fetchFn: async ({ page, search }) => {
const result = await getList({ search, page }) const result = await getList({ 'encounter-id': props.encounter.id, includes: 'encounter,dstUnit', search, page })
if (result.success) {
data.value = result.body.data;
}
return { success: result.success || false, body: result.body || {} } return { success: result.success || false, body: result.body || {} }
}, },
entityName: 'consultation', entityName: 'consultation',
@@ -148,6 +150,7 @@ onMounted(async () => {
<Entry <Entry
:schema="ConsultationSchema" :schema="ConsultationSchema"
:values="recItem" :values="recItem"
:encounter_id="props.encounter.id"
:units="units" :units="units"
:is-loading="isProcessing" :is-loading="isProcessing"
:is-readonly="isReadonly" :is-readonly="isReadonly"
@@ -165,6 +168,7 @@ onMounted(async () => {
</Dialog> </Dialog>
<!-- Record Confirmation Modal --> <!-- Record Confirmation Modal -->
{{ isRecordConfirmationOpen }}
<RecordConfirmation <RecordConfirmation
v-model:open="isRecordConfirmationOpen" v-model:open="isRecordConfirmationOpen"
action="delete" action="delete"
+1 -1
View File
@@ -56,7 +56,7 @@ const tabs: TabItem[] = [
{ value: 'mcu-lab-pa', label: 'Order Lab PA' }, { value: 'mcu-lab-pa', label: 'Order Lab PA' },
{ value: 'medical-action', label: 'Order Ruang Tindakan' }, { value: 'medical-action', label: 'Order Ruang Tindakan' },
{ value: 'mcu-result', label: 'Hasil Penunjang' }, { value: 'mcu-result', label: 'Hasil Penunjang' },
{ value: 'consultation', label: 'Konsultasi', component: Consultation, props: { encounter } }, { value: 'consultation', label: 'Konsultasi', component: Consultation, props: { encounter: data } },
{ value: 'resume', label: 'Resume' }, { value: 'resume', label: 'Resume' },
{ value: 'control', label: 'Surat Kontrol' }, { value: 'control', label: 'Surat Kontrol' },
{ value: 'screening', label: 'Skrinning MPP' }, { value: 'screening', label: 'Skrinning MPP' },
+1 -1
View File
@@ -13,7 +13,7 @@ export interface CreateDto {
encounter_id: number encounter_id: number
date: string date: string
problem: string problem: string
unit_id: number dstUnit_id: number
} }
export interface UpdateDto { export interface UpdateDto {
+3 -3
View File
@@ -1,13 +1,13 @@
import { z } from 'zod' import { z } from 'zod'
import type { Consultation } from '~/models/consultation' import type { CreateDto } from '~/models/consultation'
const ConsultationSchema = z.object({ const ConsultationSchema = z.object({
date: z.string({ required_error: 'Tanggal harus diisi' }), date: z.string({ required_error: 'Tanggal harus diisi' }),
unit_id: z.number({ required_error: 'Unit harus diisi' }), dstUnit_id: z.number({ required_error: 'Unit harus diisi' }),
problem: z.string({ required_error: 'Uraian harus diisi' }).min(20, 'Uraian minimum 20 karakter'), problem: z.string({ required_error: 'Uraian harus diisi' }).min(20, 'Uraian minimum 20 karakter'),
}) })
type ConsultationFormData = z.infer<typeof ConsultationSchema> & (Consultation) type ConsultationFormData = z.infer<typeof ConsultationSchema> & (CreateDto)
export { ConsultationSchema } export { ConsultationSchema }
export type { ConsultationFormData } export type { ConsultationFormData }