Feat: UI Laporan Operasi
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
<script setup lang="ts">
|
||||
import { ActionEvents, type ListItemDto } from '~/components/pub/my-ui/data/types';
|
||||
import Button from '~/components/pub/ui/button/Button.vue';
|
||||
|
||||
const props = defineProps<{
|
||||
|
||||
}>()
|
||||
const isModalOpen = inject<Ref<boolean>>('isHistoryDialogOpen')!
|
||||
|
||||
function openDialog() {
|
||||
isModalOpen.value = true
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Button type="button" variant="outline" class="text-orange-500 border border-orange-400 bg-orange-50"
|
||||
@click="openDialog">
|
||||
<Icon name="i-lucide-history" class="h-4 w-4 align-middle transition-colors" />
|
||||
History
|
||||
</Button>
|
||||
</template>
|
||||
@@ -0,0 +1,73 @@
|
||||
<script setup lang="ts">
|
||||
import type { FormErrors } from '~/types/error'
|
||||
import { toTypedSchema } from '@vee-validate/zod'
|
||||
import FieldGroup from '~/components/pub/my-ui/form/field-group.vue'
|
||||
import Field from '~/components/pub/my-ui/form/field.vue'
|
||||
import Label from '~/components/pub/my-ui/form/label.vue'
|
||||
import Select from '~/components/pub/my-ui/form/select.vue'
|
||||
import { Form } from '~/components/pub/ui/form'
|
||||
import InputBase from '~/components/pub/my-ui/form/input-base.vue'
|
||||
import { cn } from '~/lib/utils'
|
||||
|
||||
interface InstallationFormData {
|
||||
name: string
|
||||
code: string
|
||||
encounterClassCode: string
|
||||
}
|
||||
|
||||
const props = defineProps<{
|
||||
schema: any
|
||||
initialValues?: Partial<InstallationFormData>
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
submit: [values: InstallationFormData, resetForm: () => void]
|
||||
reset: [resetForm: () => void]
|
||||
}>()
|
||||
|
||||
// Form submission handler
|
||||
function onSubmitForm(values: any, { resetForm }: { resetForm: () => void }) {
|
||||
emit('submit', values, resetForm)
|
||||
}
|
||||
|
||||
// Form cancel handler
|
||||
function onResetForm({ resetForm }: { resetForm: () => void }) {
|
||||
emit('reset', resetForm)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Form
|
||||
v-slot="{ handleSubmit, resetForm }"
|
||||
as=""
|
||||
keep-values
|
||||
:initial-values="initialValues"
|
||||
>
|
||||
<form id="entry-form" @submit="handleSubmit($event, (values) => onSubmitForm(values, { resetForm }))">
|
||||
<div class="mb-5 border-b border-b-slate-300 pb-7 text-lg xl:text-xl">
|
||||
<div class="flex flex-col justify-between">
|
||||
<InputBase
|
||||
field-name="patientName"
|
||||
label="Nama Pasien"
|
||||
placeholder="Nama Pasien"
|
||||
/>
|
||||
<InputBase
|
||||
field-name="cardNumber"
|
||||
label="Nomor Kartu"
|
||||
placeholder="Nomor Kartu"
|
||||
/>
|
||||
<InputBase
|
||||
field-name="sepNumber"
|
||||
label="Nomor SEP"
|
||||
placeholder="Nomor SEP"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="my-2 flex items-center gap-3 justify-end">
|
||||
<Button @click="onResetForm" variant="secondary">Reset</Button>
|
||||
<Button @click="onSubmitForm">Terapkan</Button>
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
</template>
|
||||
@@ -0,0 +1,52 @@
|
||||
<script setup lang="ts">
|
||||
import type { FormErrors } from '~/types/error'
|
||||
import { toTypedSchema } from '@vee-validate/zod'
|
||||
import FieldGroup from '~/components/pub/my-ui/form/field-group.vue'
|
||||
import Field from '~/components/pub/my-ui/form/field.vue'
|
||||
import Label from '~/components/pub/my-ui/form/label.vue'
|
||||
import Select from '~/components/pub/my-ui/form/select.vue'
|
||||
import { Form } from '~/components/pub/ui/form'
|
||||
import InputBase from '~/components/pub/my-ui/form/input-base.vue'
|
||||
import SelectOriginPolyclinic from '~/components/app/bpjs/control-letter/_common/select-origin-polyclinic.vue'
|
||||
import SelectDestinationPolyclinic from '~/components/app/bpjs/control-letter/_common/select-destination-polyclinic.vue'
|
||||
import { cn } from '~/lib/utils'
|
||||
|
||||
const props = defineProps()
|
||||
|
||||
const items = reactive([
|
||||
{ id: 1, updatedBy: 'Kakek Sugiono', createdAt: new Date(Date.now() - 86400000 * 2) },
|
||||
{ id: 2, updatedBy: 'Kakek Sugiono', createdAt: new Date(Date.now() - 86400000) },
|
||||
{ id: 3, updatedBy: 'Kakek Sugiono', createdAt: new Date() },
|
||||
])
|
||||
const itemsCount = computed(() => items.length || 0)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ul :class="cn('pb-5 flex flex-col min-h-[30rem]', '')">
|
||||
<li v-for="(item, index) in items" :key="item.id" class="flex gap-3 items-start">
|
||||
|
||||
<div class="flex flex-col items-center">
|
||||
<div class="h-5 w-5 rounded-full border-2 border-gray-300 flex items-center justify-center">
|
||||
<div :class="cn('dark:bg-white border-gray-300 rounded-full p-1.5',
|
||||
index === 0 ? 'bg-green-500' : 'bg-transparent'
|
||||
)">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr v-if="index !== itemsCount - 1" class="h-14 w-0.5 bg-gray-300 dark:bg-gray-300" aria-hidden="true">
|
||||
</div>
|
||||
|
||||
<div class="flex justify-between items-center min-w-96">
|
||||
<div class="max-w-80">
|
||||
<time :class="cn('mt-0 text-base font-medium text-gray-800 dark:text-gray-100', '')">
|
||||
{{ item?.createdAt.toLocaleDateString('id-ID') }}
|
||||
</time>
|
||||
<h1 :class="cn('text-gray-500 dark:text-gray-400', '')">Ditambahkan Oleh : {{ item.updatedBy }}</h1>
|
||||
<NuxtLink class="mt-1 text-orange-500" :to="`surgery-report/${item.id}`">
|
||||
Lihat Detail
|
||||
</NuxtLink>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
@@ -0,0 +1,94 @@
|
||||
<script setup lang="ts">
|
||||
import type { FormErrors } from '~/types/error'
|
||||
import { Label as RadioLabel } from '~/components/pub/ui/label'
|
||||
import { RadioGroup, RadioGroupItem } from '~/components/pub/ui/radio-group'
|
||||
import { cn } from '~/lib/utils'
|
||||
|
||||
import * as DE from '~/components/pub/my-ui/doc-entry'
|
||||
|
||||
const props = defineProps<{
|
||||
fieldName?: string
|
||||
label?: string
|
||||
errors?: FormErrors
|
||||
class?: string
|
||||
radioGroupClass?: string
|
||||
radioItemClass?: string
|
||||
labelClass?: string
|
||||
isRequired?: boolean
|
||||
}>()
|
||||
|
||||
const {
|
||||
fieldName = 'isNewBorn',
|
||||
label = 'Status Pasien',
|
||||
errors,
|
||||
class: containerClass,
|
||||
radioGroupClass,
|
||||
radioItemClass,
|
||||
labelClass,
|
||||
} = props
|
||||
|
||||
const newbornOptions = [
|
||||
{ label: 'PRC', value: 'prc' },
|
||||
{ label: 'FFP', value: 'ffp' },
|
||||
{ label: 'WB', value: 'wb' },
|
||||
{ label: 'TC', value: 'tc' },
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DE.Cell :class="cn('radio-group-field', containerClass)" :col-span="2">
|
||||
<DE.Label
|
||||
:label-for="fieldName"
|
||||
:is-required="isRequired"
|
||||
>
|
||||
{{ label }}
|
||||
</DE.Label>
|
||||
<DE.Field
|
||||
:id="fieldName"
|
||||
:errors="errors"
|
||||
>
|
||||
<FormField
|
||||
v-slot="{ componentField }"
|
||||
:name="fieldName"
|
||||
>
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<RadioGroup
|
||||
v-bind="componentField"
|
||||
:class="cn('flex flex-row flex-wrap gap-4 sm:gap-6', radioGroupClass)"
|
||||
>
|
||||
<div
|
||||
v-for="(option, index) in newbornOptions"
|
||||
:key="option.value"
|
||||
:class="cn('flex min-w-fit items-center space-x-2 pt-1', radioItemClass)"
|
||||
>
|
||||
<RadioGroupItem
|
||||
:id="`${fieldName}-${index}`"
|
||||
:value="option.value"
|
||||
:class="
|
||||
cn(
|
||||
'relative h-4 w-4 rounded-full border-muted-foreground before:absolute before:inset-1 before:rounded-full before:bg-primary before:opacity-0 before:transition-opacity data-[state=checked]:border-primary data-[state=checked]:bg-white data-[state=checked]:before:opacity-100 sm:h-5 sm:w-5',
|
||||
containerClass,
|
||||
)
|
||||
"
|
||||
/>
|
||||
<RadioLabel
|
||||
:for="`${fieldName}-${index}`"
|
||||
:class="
|
||||
cn(
|
||||
'cursor-pointer select-none text-xs font-normal leading-none transition-colors hover:text-primary peer-disabled:cursor-not-allowed peer-disabled:opacity-70 sm:text-sm',
|
||||
labelClass,
|
||||
)
|
||||
"
|
||||
>
|
||||
{{ option.label }}
|
||||
</RadioLabel>
|
||||
</div>
|
||||
</RadioGroup>
|
||||
</FormControl>
|
||||
<FormMessage class="ml-0 mt-1" />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</DE.Field>
|
||||
</DE.Cell>
|
||||
</template>
|
||||
@@ -1,7 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import DetailRow from '~/components/pub/my-ui/form/view/detail-row.vue'
|
||||
import { type Variants, Badge } from '~/components/pub/ui/badge'
|
||||
import { cn, } from '~/lib/utils'
|
||||
import type { ControlLetter } from '~/models/control-letter'
|
||||
import * as DE from '~/components/pub/my-ui/doc-entry'
|
||||
|
||||
// #region Props & Emits
|
||||
const props = defineProps<{
|
||||
@@ -9,9 +11,18 @@ const props = defineProps<{
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'click', type: string): void
|
||||
(e: 'click'): void
|
||||
}>()
|
||||
|
||||
const dummy = [
|
||||
{
|
||||
id: 1,
|
||||
number: 1,
|
||||
name: 'Operasi',
|
||||
code: 'OP-001'
|
||||
}
|
||||
]
|
||||
|
||||
// #endregion
|
||||
|
||||
// #region State & Computed
|
||||
@@ -28,8 +39,8 @@ const emit = defineEmits<{
|
||||
// #endregion region
|
||||
|
||||
// #region Utilities & event handlers
|
||||
function onClick(type: string) {
|
||||
emit('click', type)
|
||||
function onClick() {
|
||||
emit('click')
|
||||
}
|
||||
// #endregion
|
||||
|
||||
@@ -38,17 +49,96 @@ function onClick(type: string) {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div :class="cn('min-h-[50vh] space-y-2',)">
|
||||
<DetailRow label="Tgl Rencana Kontrol">{{ props.instance?.date ? new Date(props.instance?.date).toLocaleDateString('id-ID') : '-' }}</DetailRow>
|
||||
<DetailRow label="Unit">{{ props.instance?.unit.name || '-' }}</DetailRow>
|
||||
<DetailRow label="Spesialis">{{ props.instance?.specialist.name || '-' }}</DetailRow>
|
||||
<DetailRow label="Sub Spesialis">{{ props.instance?.subspecialist.name || '-' }}</DetailRow>
|
||||
<DetailRow label="DPJP">{{ props.instance?.doctor.employee.person.name || '-' }}</DetailRow>
|
||||
<DetailRow label="Status SEP">{{ 'SEP INTERNAL' }}</DetailRow>
|
||||
</div>
|
||||
<div class="border-t-1 my-2 flex justify-end border-t-slate-300 py-2">
|
||||
<PubMyUiNavFooterBaEd @click="onClick" />
|
||||
</div>
|
||||
<article :class="cn('space-y-10',)">
|
||||
<div :class="cn('space-y-2',)">
|
||||
<h1>Dibuat oleh {{ `Dr. Agus` }} pada {{ `11 Agustus 2025, 20.00` }}</h1>
|
||||
<DetailRow label="Tanggal Laporan">{{ props.instance?.date ? new
|
||||
Date(props.instance?.date).toLocaleDateString('id-ID') : '-' }}</DetailRow>
|
||||
</div>
|
||||
<div :class="cn('space-y-2',)">
|
||||
<h1 class="font-semibold text-lg">Tim Pelaksanaan Operasi</h1>
|
||||
<DetailRow label="DPJP Bedah">{{ props.instance?.date ? props.instance?.date : '-' }}</DetailRow>
|
||||
<DetailRow label="Operator">{{ props.instance?.date ? props.instance?.date : '-' }}</DetailRow>
|
||||
<DetailRow label="Asisten Operator">{{ props.instance?.date ? props.instance?.date : '-' }}</DetailRow>
|
||||
<DetailRow label="Instrumentir">{{ props.instance?.date ? props.instance?.date : '-' }}</DetailRow>
|
||||
<DetailRow label="DPJP Anastesi">{{ props.instance?.date ? props.instance?.date : '-' }}</DetailRow>
|
||||
<DetailRow label="Perawat Anastesi">{{ props.instance?.date ? props.instance?.date : '-' }}</DetailRow>
|
||||
<DetailRow label="Tanggal Pembedahan">{{ props.instance?.date ? props.instance?.date : '-' }}</DetailRow>
|
||||
<DetailRow label="Diagnosa Pra Bedah">{{ props.instance?.date ? props.instance?.date : '-' }}</DetailRow>
|
||||
<DetailRow label="Perawat Pasca Bedah">{{ props.instance?.date ? props.instance?.date : '-' }}</DetailRow>
|
||||
</div>
|
||||
|
||||
<div :class="cn('space-y-2',)">
|
||||
<h1 class="font-semibold text-lg">Tindakan Operatif / Non Operatif Lain</h1>
|
||||
<div class="border border-gray-200 rounded-lg overflow-hidden">
|
||||
<Table>
|
||||
<TableHeader class="bg-gray-100">
|
||||
<TableRow>
|
||||
<TableHead class="w-14">No</TableHead>
|
||||
<TableHead class="">Prosedur</TableHead>
|
||||
<TableHead class="">Code</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
<TableRow v-for="(field, idx) in dummy" :key="idx">
|
||||
<TableCell class="">{{ idx + 1 }}</TableCell>
|
||||
<TableCell class="">{{ field.name }}</TableCell>
|
||||
<TableCell class="">{{ field.code }}</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div :class="cn('space-y-2',)">
|
||||
<h1 class="font-semibold text-lg">Data Pelaksanaan Operasi</h1>
|
||||
<DE.Block :col-count="2" :cell-flex="false">
|
||||
<div>
|
||||
<DetailRow label="Jenis Operasi">{{ props.instance?.date ? props.instance?.date : '-' }}</DetailRow>
|
||||
<DetailRow label="Kode Biling">{{ props.instance?.date ? props.instance?.date : '-' }}</DetailRow>
|
||||
<DetailRow label="Sitem Operasi">{{ props.instance?.date ? props.instance?.date : '-' }}</DetailRow>
|
||||
<DetailRow label="Operasi Mulai">{{ props.instance?.date ? props.instance?.date : '-' }}</DetailRow>
|
||||
<DetailRow label="Operasi Selesai">{{ props.instance?.date ? props.instance?.date : '-' }}</DetailRow>
|
||||
<DetailRow label="Lama Operasi"><b>{{ 1 }}</b> Jam <b>{{ 1 }}</b> Menit</DetailRow>
|
||||
<DetailRow label="Pembiusan Mulai">{{ props.instance?.date ? props.instance?.date : '-' }}</DetailRow>
|
||||
<DetailRow label="Pembiusan Selesai">{{ props.instance?.date ? props.instance?.date : '-' }}</DetailRow>
|
||||
<DetailRow label="Lama Pembiusan"><b>{{ 1 }}</b> Jam <b>{{ 1 }}</b> Menit</DetailRow>
|
||||
</div>
|
||||
<div>
|
||||
<DetailRow label="Jenis Pembedahan">{{ props.instance?.date ? props.instance?.date : '-' }}</DetailRow>
|
||||
<DetailRow label="Operasi ke">{{ props.instance?.date ? props.instance?.date : '-' }}</DetailRow>
|
||||
<DetailRow label="Keterangan Lahir">{{ props.instance?.date ? props.instance?.date : '-' }}</DetailRow>
|
||||
<DetailRow label="Ket Tempat Lahir">{{ props.instance?.date ? props.instance?.date : '-' }}</DetailRow>
|
||||
<DetailRow label="Berat Badan">{{ props.instance?.date ? props.instance?.date : '-' }}</DetailRow>
|
||||
<DetailRow label="Ket Saat Lahir">{{ props.instance?.date ? props.instance?.date : '-' }}</DetailRow>
|
||||
<DetailRow label="Uraian Operasi">{{ props.instance?.date ? props.instance?.date : '-' }}</DetailRow>
|
||||
<DetailRow label="Jumlah Pendarahan">{{ props.instance?.date ? props.instance?.date : '-' }} CC</DetailRow>
|
||||
</div>
|
||||
<div>
|
||||
<DetailRow label="PRC">{{ props.instance?.date ? props.instance?.date : '-' }} CC</DetailRow>
|
||||
<DetailRow label="FPP">{{ props.instance?.date ? props.instance?.date : '-' }}</DetailRow>
|
||||
<DetailRow label="WB">{{ props.instance?.date ? props.instance?.date : '-' }}</DetailRow>
|
||||
<DetailRow label="TC">{{ props.instance?.date ? props.instance?.date : '-' }}</DetailRow>
|
||||
<DetailRow label="Merk">{{ props.instance?.date ? props.instance?.date : '-' }}</DetailRow>
|
||||
<DetailRow label="Nama Implant">{{ props.instance?.date ? props.instance?.date : '-' }}</DetailRow>
|
||||
<DetailRow label="Stiker/Nomor Register Implant">{{ props.instance?.date ? props.instance?.date : '-' }}</DetailRow>
|
||||
<DetailRow label="Nama Pendamping Implant">{{ props.instance?.date ? props.instance?.date : '-' }}</DetailRow>
|
||||
</div>
|
||||
<div>
|
||||
<DetailRow label-class="w-96" label="Specimen/Jaringan dikirim ke">{{ props.instance?.date ? props.instance?.date : '-' }}</DetailRow>
|
||||
<DetailRow label="Keterangan Jaringan">
|
||||
<Badge :variant="`outline`">
|
||||
{{ `Example` }}
|
||||
</Badge>
|
||||
</DetailRow>
|
||||
</div>
|
||||
</DE.Block>
|
||||
</div>
|
||||
|
||||
<div class="border-t-1 my-2 flex justify-end border-t-slate-300 py-2">
|
||||
<PubMyUiNavFooterBa @click="onClick" />
|
||||
</div>
|
||||
</article>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
|
||||
@@ -4,6 +4,7 @@ import { toTypedSchema } from '@vee-validate/zod'
|
||||
import { Form } from '~/components/pub/ui/form'
|
||||
import SelectDate from './_common/select-date.vue'
|
||||
import InputBase from '~/components/pub/my-ui/form/input-base.vue'
|
||||
import { FieldArray } from 'vee-validate'
|
||||
|
||||
import * as DE from '~/components/pub/my-ui/doc-entry'
|
||||
import SelectDpjpBedah from './_common/select-dpjp-bedah.vue'
|
||||
@@ -17,16 +18,18 @@ import SelectBirthDesc from './_common/select-birth-desc.vue'
|
||||
import SelectBirthPlaceDesc from './_common/select-birth-place-desc.vue'
|
||||
import SelectSpecimenType from './_common/select-specimen-type.vue'
|
||||
import TextAreaInput from '~/components/pub/my-ui/form/text-area-input.vue'
|
||||
import RadioBloodType from './_common/radio-blood-type.vue'
|
||||
import OperativeActionPicker from './operative-action/picker-dialog.vue'
|
||||
|
||||
const props = defineProps<{
|
||||
schema: any
|
||||
initialValues?: any
|
||||
errors?: FormErrors
|
||||
operativeActionList?: any[]
|
||||
}>()
|
||||
|
||||
const formSchema = toTypedSchema(props.schema)
|
||||
const formRef = ref()
|
||||
const isOperativeActionDialogOpen = inject<Ref<boolean>>('isOperativeActionDialogOpen')!
|
||||
|
||||
defineExpose({
|
||||
validate: () => formRef.value?.validate(),
|
||||
@@ -34,10 +37,6 @@ defineExpose({
|
||||
setValues: (values: any, shouldValidate = true) => formRef.value?.setValues(values, shouldValidate),
|
||||
values: computed(() => formRef.value?.values),
|
||||
})
|
||||
|
||||
const handleToggleOperativeActionDialog = () => {
|
||||
isOperativeActionDialogOpen.value = !isOperativeActionDialogOpen.value
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -95,18 +94,20 @@ const handleToggleOperativeActionDialog = () => {
|
||||
</DE.Cell>
|
||||
<InputBase :errors="errors"
|
||||
field-name="a9"
|
||||
label="Perawat Pra Bedah" placeholder="Isi Perawat Pra Bedah"
|
||||
label="Perawat Pasca Bedah" placeholder="Isi Perawat Pasca Bedah"
|
||||
/>
|
||||
</DE.Block>
|
||||
|
||||
<!-- PICKER -->
|
||||
|
||||
<DE.Block :col-count="1" :cell-flex="false" class="w-1/2">
|
||||
<OperativeActionPicker field-name="a63" title="Prosedur" />
|
||||
</DE.Block>
|
||||
<!-- -->
|
||||
|
||||
<DE.Block :col-count="3" :cell-flex="false">
|
||||
<SelectSurgeryType :errors="errors"
|
||||
field-name="a10"
|
||||
label="Tipe Operasi" placeholder="Pilih Tipe Operasi"
|
||||
label="Jenis Operasi" placeholder="Pilih Jenis Operasi"
|
||||
is-required
|
||||
/>
|
||||
<SelectBillingCode :errors="errors"
|
||||
@@ -133,32 +134,32 @@ const handleToggleOperativeActionDialog = () => {
|
||||
/>
|
||||
<div>
|
||||
<p class="mt-1.5 mb-2">Lama Operasi</p>
|
||||
<h1 class="text-lg"><b>{{ 1 }}</b> Jam <b>{{ 1 }}</b> Menit</h1>
|
||||
<h1 class="text-base"><b>{{ 1 }}</b> Jam <b>{{ 1 }}</b> Menit</h1>
|
||||
</div>
|
||||
<SelectDate :errors="errors"
|
||||
field-name="a7"
|
||||
field-name="a44"
|
||||
label="Pembiusan Mulai"
|
||||
is-required
|
||||
is-with-time
|
||||
/>
|
||||
<SelectDate :errors="errors"
|
||||
field-name="a7"
|
||||
field-name="a45"
|
||||
label="Pembiusan Selesai"
|
||||
is-required
|
||||
is-with-time
|
||||
/>
|
||||
<div>
|
||||
<p class="mt-1.5 mb-2">Lama Pembiusan</p>
|
||||
<h1 class="text-lg"><b>{{ 1 }}</b> Jam <b>{{ 1 }}</b> Menit</h1>
|
||||
<h1 class="text-base"><b>{{ 1 }}</b> Jam <b>{{ 1 }}</b> Menit</h1>
|
||||
</div>
|
||||
<SelectDissectionType :errors="errors"
|
||||
field-name="a13"
|
||||
label="Tipe Pembedahan" placeholder="Pilih Tipe Pembedahan"
|
||||
label="Jenis Pembedahan" placeholder="Pilih Jenis Pembedahan"
|
||||
is-required
|
||||
/>
|
||||
<SelectSurgeryOrder :errors="errors"
|
||||
field-name="a14"
|
||||
label="Urutan Operasi" placeholder="Pilih Urutan Operasi"
|
||||
label="Urutan Operasi Ke" placeholder="Pilih Urutan Operasi Ke"
|
||||
is-required
|
||||
/>
|
||||
<SelectBirthDesc :errors="errors"
|
||||
@@ -171,13 +172,88 @@ const handleToggleOperativeActionDialog = () => {
|
||||
label="Ket. Tempat Lahir" placeholder="Pilih Ket. Tempat Lahir"
|
||||
is-required
|
||||
/>
|
||||
<InputBase :errors="errors"
|
||||
field-name="a6"
|
||||
label="Berat Badan" placeholder="Isi Berat Badan"
|
||||
right-label="Gram"
|
||||
numeric-only
|
||||
/>
|
||||
<InputBase :errors="errors"
|
||||
field-name="a6"
|
||||
label="Ket. Saat Lahir" placeholder="Isi Ket. Saat Lahir"
|
||||
/>
|
||||
<TextAreaInput :errors="errors"
|
||||
field-name="a8"
|
||||
label="Uraian Operasi" placeholder="Isi Uraian Operasi"
|
||||
is-required
|
||||
/>
|
||||
<InputBase :errors="errors"
|
||||
field-name="a6"
|
||||
label="Jumlah Pendarahan" placeholder="Isi Jumlah Pendarahan"
|
||||
right-label="cc"
|
||||
numeric-only
|
||||
/>
|
||||
</DE.Block>
|
||||
|
||||
|
||||
<DE.Block :col-count="1" :cell-flex="false" class="w-1/2">
|
||||
<RadioBloodType :errors="errors"
|
||||
field-name="a16"
|
||||
label="Jenis Darah Masuk" placeholder="Pilih Jenis Darah Masuk"
|
||||
/>
|
||||
<InputBase :errors="errors"
|
||||
class=""
|
||||
field-name="a6"
|
||||
label="Jumlah Darah Masuk" placeholder="Isi Jumlah Darah Masuk"
|
||||
right-label="cc"
|
||||
numeric-only
|
||||
/>
|
||||
</DE.Block>
|
||||
|
||||
<DE.Block :col-count="3" :cell-flex="false">
|
||||
<InputBase :errors="errors"
|
||||
field-name="a6"
|
||||
label="Merk" placeholder="Isi Merk"
|
||||
/>
|
||||
<InputBase :errors="errors"
|
||||
field-name="a6"
|
||||
label="Nama Implant" placeholder="Isi Nama Implant"
|
||||
/>
|
||||
<InputBase :errors="errors"
|
||||
field-name="a6"
|
||||
label="Stiker / Nomor Register Implant" placeholder="Isi Stiker / Nomor Register Implant"
|
||||
/>
|
||||
<InputBase :errors="errors"
|
||||
field-name="a6"
|
||||
label="Nama Penedamping Implant" placeholder="Isi Nama Penedamping Implant"
|
||||
/>
|
||||
<SelectSpecimenType :errors="errors"
|
||||
field-name="a17"
|
||||
label="Specimen/Jaringan Dikirim Ke" placeholder="Pilih Specimen/Jaringan Dikirim Ke"
|
||||
is-required
|
||||
/>
|
||||
</DE.Block>
|
||||
|
||||
|
||||
<DE.Block :col-count="1" :cell-flex="false" class="w-1/2">
|
||||
<FieldArray v-slot="{ fields, push, remove }" name="a32">
|
||||
<div v-for="(field, idx) in fields" :key="idx" class="flex items-end gap-3 mb-3">
|
||||
<InputBase :errors="errors"
|
||||
:field-name="`a32[${idx}]`"
|
||||
label="Keterangan Jaringan" placeholder="Isi Keterangan Jaringan"
|
||||
/>
|
||||
<Button v-if="idx !== 0" type="button" variant="destructive" size="sm" @click="remove(idx)">
|
||||
<Icon name="i-lucide-trash-2" class="h-4 w-4" />
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<Button type="button" variant="outline"
|
||||
class="mt-3 w-full rounded-md border border-primary bg-white px-4 py-2 text-primary hover:border-primary hover:bg-primary hover:text-white sm:w-auto sm:text-sm"
|
||||
@click="push(``)">
|
||||
<Icon name="i-lucide-plus" class="mr-2 h-4 w-4 align-middle transition-colors" />
|
||||
Tambah Keterangan Jaringan
|
||||
</Button>
|
||||
</FieldArray>
|
||||
</DE.Block>
|
||||
|
||||
</Form>
|
||||
</template>
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { config } from './operative-action-list.cfg'
|
||||
import type { PaginationMeta } from '~/components/pub/my-ui/pagination/pagination.type'
|
||||
import PaginationView from '~/components/pub/my-ui/pagination/pagination-view.vue'
|
||||
|
||||
interface Props {
|
||||
data: any[]
|
||||
paginationMeta: PaginationMeta
|
||||
}
|
||||
defineProps<Props>()
|
||||
const modelValue = defineModel<any[]>('modelValue', { default: [] })
|
||||
|
||||
const emit = defineEmits<{
|
||||
pageChange: [page: number]
|
||||
}>()
|
||||
|
||||
function handlePageChange(page: number) {
|
||||
emit('pageChange', page)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="space-y-4">
|
||||
<PubMyUiDataTable
|
||||
select-mode="multiple"
|
||||
v-model="modelValue"
|
||||
v-bind="config"
|
||||
:rows="data"
|
||||
:skeleton-size="paginationMeta?.pageSize"
|
||||
/>
|
||||
<PaginationView :pagination-meta="paginationMeta" @page-change="handlePageChange" />
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,56 +0,0 @@
|
||||
import type { Config } from '~/components/pub/my-ui/data-table'
|
||||
import type { Patient } from '~/models/patient'
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
import { educationCodes, genderCodes } from '~/lib/constants'
|
||||
import { calculateAge } from '~/lib/utils'
|
||||
|
||||
const action = defineAsyncComponent(() => import('~/components/pub/my-ui/data/dropdown-action-dud.vue'))
|
||||
|
||||
export const config: Config = {
|
||||
cols: [{}, {}, {}, {}, {}, {}, {}, ],
|
||||
|
||||
headers: [
|
||||
[
|
||||
{ label: 'Tgl Laporan' },
|
||||
{ label: 'DPJP Bedah' },
|
||||
{ label: 'DPJP Anastesi' },
|
||||
{ label: 'Tgl Pembedahan' },
|
||||
{ label: 'Jenis Operasi' },
|
||||
{ label: 'Kode Billing' },
|
||||
{ label: 'Sistem Operasi' },
|
||||
],
|
||||
],
|
||||
|
||||
keys: ['date', 'doctor.employee.person.name', 'doctor.employee.person.name', 'date', 'name', 'name', 'name'],
|
||||
|
||||
delKeyNames: [
|
||||
{ key: 'code', label: 'Kode' },
|
||||
{ key: 'name', label: 'Nama' },
|
||||
],
|
||||
|
||||
parses: {
|
||||
date: (rec: unknown): unknown => {
|
||||
const date = (rec as any).date
|
||||
if (typeof date == 'object' && date) {
|
||||
return (date as Date).toLocaleDateString('id-ID')
|
||||
} else if (typeof date == 'string') {
|
||||
return (date as string).substring(0, 10)
|
||||
}
|
||||
return date
|
||||
},
|
||||
},
|
||||
|
||||
components: {
|
||||
// action(rec, idx) {
|
||||
// return {
|
||||
// idx,
|
||||
// rec: rec as object,
|
||||
// component: action,
|
||||
// }
|
||||
// },
|
||||
},
|
||||
|
||||
htmls: {
|
||||
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<script setup lang="ts">
|
||||
import { ActionEvents, type LinkItem, type ListItemDto } from '~/components/pub/my-ui/data/types';
|
||||
|
||||
|
||||
const props = defineProps<{
|
||||
rec: ListItemDto
|
||||
}>()
|
||||
|
||||
const recId = inject<Ref<number>>('ap_rec_id')!
|
||||
const recAction = inject<Ref<string>>('ap_rec_action')!
|
||||
const recItem = inject<Ref<any>>('ap_rec_item')!
|
||||
const timestamp = inject<Ref<any>>('timestamp')!
|
||||
|
||||
const activeKey = ref<string | null>(null)
|
||||
|
||||
function process() {
|
||||
recId.value = props.rec.id || 0
|
||||
recAction.value = ActionEvents.showProcess
|
||||
recItem.value = props.rec
|
||||
timestamp.value = new Date().getTime()
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Button @click="process" variant="outline"
|
||||
class="text-orange-400 border-orange-400 bg-transparent">
|
||||
Pilih
|
||||
<Icon name="i-lucide-arrow-right" class="h-4 w-4 align-middle transition-colors" />
|
||||
</Button>
|
||||
</template>
|
||||
@@ -0,0 +1,44 @@
|
||||
import type { Config } from '~/components/pub/my-ui/data-table'
|
||||
import type { Patient } from '~/models/patient'
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
import { educationCodes, genderCodes } from '~/lib/constants'
|
||||
import { calculateAge } from '~/lib/utils'
|
||||
|
||||
const action = defineAsyncComponent(() => import('./dropdown-action.vue'))
|
||||
|
||||
export const config: Config = {
|
||||
cols: [{}, {}, {width: 30}, ],
|
||||
|
||||
headers: [
|
||||
[
|
||||
{ label: 'Nama Prosedur' },
|
||||
{ label: 'Code' },
|
||||
{ label: 'Action' },
|
||||
],
|
||||
],
|
||||
|
||||
keys: ['name', 'code', 'action',],
|
||||
|
||||
delKeyNames: [
|
||||
{ key: 'code', label: 'Kode' },
|
||||
{ key: 'name', label: 'Nama' },
|
||||
],
|
||||
|
||||
parses: {
|
||||
|
||||
},
|
||||
|
||||
components: {
|
||||
action(rec, idx) {
|
||||
return {
|
||||
idx,
|
||||
rec: rec as object,
|
||||
component: action,
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
htmls: {
|
||||
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
<script setup lang="ts">
|
||||
// Components
|
||||
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 type { PaginationMeta } from '~/components/pub/my-ui/pagination/pagination.type'
|
||||
import PaginationView from '~/components/pub/my-ui/pagination/pagination-view.vue'
|
||||
|
||||
// Helpers
|
||||
import { usePaginatedList } from '~/composables/usePaginatedList'
|
||||
import { toast } from '~/components/pub/ui/toast'
|
||||
import { config } from './list.cfg'
|
||||
|
||||
// Types
|
||||
import { ActionEvents, type HeaderPrep } from '~/components/pub/my-ui/data/types'
|
||||
import { ProcedureSrcSchema, type ProcedureSrcFormData } from '~/schemas/procedure-src.schema'
|
||||
|
||||
// Handlers
|
||||
import {
|
||||
isReadonly,
|
||||
isProcessing,
|
||||
isFormEntryDialogOpen,
|
||||
isRecordConfirmationOpen,
|
||||
onResetState,
|
||||
handleActionSave,
|
||||
handleActionEdit,
|
||||
handleActionRemove,
|
||||
handleCancelForm,
|
||||
} from '~/handlers/procedure-src.handler'
|
||||
|
||||
// Services
|
||||
import { getList, getDetail } from '~/services/procedure-src.service'
|
||||
|
||||
const title = ref('')
|
||||
|
||||
interface Props {
|
||||
data: any[]
|
||||
paginationMeta: PaginationMeta
|
||||
processFn: (input: unknown) => void
|
||||
}
|
||||
const props = defineProps<Props>()
|
||||
|
||||
const recId = ref<string>(``)
|
||||
const recAction = ref<string>(``)
|
||||
const recItem = ref<any>({})
|
||||
const timestamp = ref<any>({})
|
||||
provide('ap_rec_id', recId)
|
||||
provide('ap_rec_action', recAction)
|
||||
provide('ap_rec_item', recItem)
|
||||
provide('timestamp', timestamp)
|
||||
|
||||
const emit = defineEmits<{
|
||||
pageChange: [page: number]
|
||||
toggleDialog: []
|
||||
}>()
|
||||
|
||||
function handlePageChange(page: number) {
|
||||
emit('pageChange', page)
|
||||
}
|
||||
|
||||
watch([recId, recAction, ], () => {
|
||||
switch (recAction.value) {
|
||||
case ActionEvents.showProcess:
|
||||
props.processFn({
|
||||
id: recId.value,
|
||||
code: recItem.value.code,
|
||||
name: recItem.value.name,
|
||||
})
|
||||
emit('toggleDialog')
|
||||
break
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="space-y-4">
|
||||
<PubMyUiDataTable
|
||||
v-bind="config"
|
||||
:rows="data"
|
||||
:skeleton-size="paginationMeta?.pageSize"
|
||||
/>
|
||||
<PaginationView :pagination-meta="paginationMeta" @page-change="handlePageChange" />
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,116 @@
|
||||
<script setup lang="ts">
|
||||
import ProcedureListDialog from './list.vue'
|
||||
import type { FormErrors } from '~/types/error'
|
||||
import { toTypedSchema } from '@vee-validate/zod'
|
||||
import { Form } from '~/components/pub/ui/form'
|
||||
import { FieldArray } from 'vee-validate'
|
||||
import InputBase from '~/components/pub/my-ui/form/input-base.vue'
|
||||
import * as DE from '~/components/pub/my-ui/doc-entry'
|
||||
import TextAreaInput from '~/components/pub/my-ui/form/text-area-input.vue'
|
||||
import { cn } from '~/lib/utils'
|
||||
import TableHeader from '~/components/pub/ui/table/TableHeader.vue'
|
||||
import { is } from 'date-fns/locale'
|
||||
import Dialog from '~/components/pub/my-ui/modal/dialog.vue'
|
||||
import List from './list.vue'
|
||||
import Action from '~/components/pub/my-ui/nav-footer/ba-dr-su.vue'
|
||||
import Header from '~/components/pub/my-ui/nav-header/prep.vue'
|
||||
import { getList, getDetail } from '~/services/procedure-src.service'
|
||||
import { ActionEvents, type HeaderPrep, type RefSearchNav } from '~/components/pub/my-ui/data/types'
|
||||
|
||||
interface Props {
|
||||
fieldName: string
|
||||
title: string
|
||||
}
|
||||
const props = defineProps<Props>()
|
||||
const isOperativeActionDialogOpen = ref(false)
|
||||
provide("isOperativeActionDialogOpen", isOperativeActionDialogOpen);
|
||||
|
||||
const { data, isLoading, paginationMeta, searchInput, handlePageChange, handleSearch, fetchData } = usePaginatedList({
|
||||
fetchFn: (params) => getList({ ...params, includes: 'specialist,subspecialist,doctor-employee-person', }),
|
||||
entityName: 'surgery-report',
|
||||
})
|
||||
const headerPrep: HeaderPrep = {
|
||||
title: props.title,
|
||||
icon: 'i-lucide-clipboard-list',
|
||||
}
|
||||
const refSearchNav: RefSearchNav = {
|
||||
onClick: () => {
|
||||
// open filter modal
|
||||
},
|
||||
onInput: (val: string) => {
|
||||
searchInput.value = val
|
||||
},
|
||||
onClear: () => {
|
||||
searchInput.value = ''
|
||||
},
|
||||
}
|
||||
|
||||
const handleToggleOperativeActionDialog = () => {
|
||||
isOperativeActionDialogOpen.value = !isOperativeActionDialogOpen.value
|
||||
}
|
||||
|
||||
const dummy = [
|
||||
{
|
||||
id: 1,
|
||||
number: 1,
|
||||
name: 'Operasi',
|
||||
code: 'OP-001'
|
||||
}
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="">
|
||||
<div class="mb-2 flex justify-between">
|
||||
<h1 class="mb-2 font-medium">{{ title }}</h1>
|
||||
<Button @click="isOperativeActionDialogOpen = true" size="xs" variant="outline"
|
||||
class="text-orange-400 border-orange-400 bg-transparent">
|
||||
<Icon name="i-lucide-search" class="h-4 w-4 align-middle transition-colors" />
|
||||
Pilih {{ title }}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<FieldArray v-slot="{ fields, push, remove }" :name="props.fieldName">
|
||||
<Dialog
|
||||
v-model:open="isOperativeActionDialogOpen"
|
||||
title="" size="xl">
|
||||
<Header
|
||||
:prep="headerPrep"
|
||||
:ref-search-nav="refSearchNav"
|
||||
v-model:search="searchInput"
|
||||
@search="handleSearch" />
|
||||
<!-- <List :data="dummy" :process-fn="push" /> -->
|
||||
<List
|
||||
:data="dummy"
|
||||
:pagination-meta="paginationMeta"
|
||||
@page-change="handlePageChange"
|
||||
@toggle-dialog="handleToggleOperativeActionDialog"
|
||||
:process-fn="push"
|
||||
/>
|
||||
</Dialog>
|
||||
|
||||
<div class="border border-gray-200 rounded-lg overflow-hidden">
|
||||
<Table>
|
||||
<TableHeader class="bg-gray-100">
|
||||
<TableRow>
|
||||
<TableHead class="">Prosedur</TableHead>
|
||||
<TableHead class="">Code</TableHead>
|
||||
<TableHead class="w-24">Action</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
<TableRow v-for="(field, idx) in fields" :key="idx">
|
||||
<TableCell class="">{{ field.value?.name }}</TableCell>
|
||||
<TableCell class="">{{ field.value?.code }}</TableCell>
|
||||
<TableCell class="">
|
||||
<Button type="button" variant="destructive" size="sm" @click="remove(idx)">
|
||||
<Icon name="i-lucide-trash-2" class="h-4 w-4" />
|
||||
</Button>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
</FieldArray>
|
||||
</div>
|
||||
</template>
|
||||
@@ -32,14 +32,14 @@ const headerPrep: HeaderPrep = {
|
||||
// #endregion
|
||||
|
||||
// #region Lifecycle Hooks
|
||||
onMounted(async () => {
|
||||
const result = await getDetail(controlLetterId, {
|
||||
includes: "unit,specialist,subspecialist,doctor-employee-person",
|
||||
})
|
||||
if (result.success) {
|
||||
controlLetter.value = result.body?.data
|
||||
}
|
||||
})
|
||||
// onMounted(async () => {
|
||||
// const result = await getDetail(controlLetterId, {
|
||||
// includes: "unit,specialist,subspecialist,doctor-employee-person",
|
||||
// })
|
||||
// if (result.success) {
|
||||
// controlLetter.value = result.body?.data
|
||||
// }
|
||||
// })
|
||||
// #endregion
|
||||
|
||||
// #region Functions
|
||||
@@ -50,19 +50,8 @@ function goBack() {
|
||||
// #endregion region
|
||||
|
||||
// #region Utilities & event handlers
|
||||
function handleAction(type: string) {
|
||||
switch (type) {
|
||||
// case 'edit':
|
||||
// navigateTo({
|
||||
// name: 'rehab-encounter-id-surgery-report-control_letter_id-edit',
|
||||
// params: { id: encounterId, "control_letter_id": controlLetterId },
|
||||
// })
|
||||
// break
|
||||
|
||||
case 'back':
|
||||
goBack()
|
||||
break
|
||||
}
|
||||
function handleAction() {
|
||||
goBack()
|
||||
}
|
||||
// #endregion
|
||||
|
||||
@@ -72,6 +61,5 @@ function handleAction(type: string) {
|
||||
|
||||
<template>
|
||||
<Header :prep="headerPrep" :ref-search-nav="headerPrep.refSearchNav" />
|
||||
|
||||
<AppSurgeryReportDetail :instance="controlLetter" @click="handleAction" />
|
||||
<AppSurgeryReportDetail :instance="surgeryReport" @click="handleAction" />
|
||||
</template>
|
||||
|
||||
@@ -15,6 +15,7 @@ import { ResponsiblePersonSchema } from '~/schemas/person-relative.schema'
|
||||
import { uploadAttachment } from '~/services/patient.service'
|
||||
import { getDetail, update } from '~/services/surgery-report.service'
|
||||
import type { SurgeryReport } from '~/models/surgery-report'
|
||||
import ActionDialog from '~/components/pub/my-ui/nav-footer/ba-su.vue'
|
||||
|
||||
import { toast } from '~/components/pub/ui/toast'
|
||||
import { withBase } from '~/models/_base'
|
||||
@@ -48,24 +49,6 @@ const inputForm = ref<ExposedForm<any> | null>(null)
|
||||
const surgeryReport = ref({})
|
||||
const isConfirmationOpen = ref(false)
|
||||
const selectedOperativeAction = ref<any>(null)
|
||||
const isOperativeActionDialogOpen = ref(false)
|
||||
provide("isOperativeActionDialogOpen", isOperativeActionDialogOpen);
|
||||
|
||||
const headerPrep: HeaderPrep = {
|
||||
title: "Pilih Tindakan",
|
||||
icon: 'i-lucide-history',
|
||||
}
|
||||
const refSearchNav: RefSearchNav = {
|
||||
onClick: () => {
|
||||
// open filter modal
|
||||
},
|
||||
onInput: (val: string) => {
|
||||
searchInput.value = val
|
||||
},
|
||||
onClear: () => {
|
||||
searchInput.value = ''
|
||||
},
|
||||
}
|
||||
// #endregion
|
||||
|
||||
// #region Lifecycle Hooks
|
||||
@@ -131,13 +114,6 @@ async function handleActionClick(eventType: string) {
|
||||
function handleCancelAdd() {
|
||||
isConfirmationOpen.value = false
|
||||
}
|
||||
|
||||
function actionDialogHandler(type: string) {
|
||||
if (type === 'submit') {
|
||||
// icdPreview.value.procedures = selectedOperativeAction.value || []
|
||||
}
|
||||
isOperativeActionDialogOpen.value = false
|
||||
}
|
||||
// #endregion
|
||||
|
||||
// #region Watchers
|
||||
@@ -146,39 +122,17 @@ function actionDialogHandler(type: string) {
|
||||
|
||||
<template>
|
||||
<div class="mb-5 border-b border-b-slate-300 pb-3 text-lg font-semibold xl:text-xl">Update Laporan Operasi</div>
|
||||
<code>{{ selectedOperativeAction }}</code>
|
||||
<AppSurgeryReportEntry
|
||||
ref="inputForm"
|
||||
:schema="SurgeryReportSchema"
|
||||
:operative-action-list="[]"
|
||||
/>
|
||||
|
||||
<div class="my-2 flex justify-end py-2">
|
||||
<Action :enable-draft="false" @click="handleActionClick" />
|
||||
</div>
|
||||
|
||||
|
||||
<Dialog
|
||||
v-model:open="isOperativeActionDialogOpen"
|
||||
title=""
|
||||
size="xl"
|
||||
>
|
||||
<Header
|
||||
:prep="headerPrep"
|
||||
:ref-search-nav="refSearchNav"
|
||||
v-model:search="searchInput"
|
||||
@search="handleSearch" />
|
||||
|
||||
<AppSurgeryReportPicker
|
||||
v-model:model-value="selectedOperativeAction"
|
||||
:data="data"
|
||||
:pagination-meta="paginationMeta"
|
||||
@page-change="handlePageChange"
|
||||
/>
|
||||
|
||||
<div class="my-2 flex justify-end py-2">
|
||||
<ActionDialog @click="actionDialogHandler" />
|
||||
</div>
|
||||
</Dialog>
|
||||
|
||||
<Confirmation
|
||||
v-model:open="isConfirmationOpen"
|
||||
title="Simpan Data"
|
||||
|
||||
@@ -27,6 +27,7 @@ const { data, isLoading, paginationMeta, searchInput, handlePageChange, handleSe
|
||||
entityName: 'surgery-report',
|
||||
})
|
||||
|
||||
const isHistoryDialogOpen = ref(false)
|
||||
const isFilterDialogOpen = ref(false)
|
||||
const isRecordConfirmationOpen = ref(false)
|
||||
const summaryLoading = ref(false)
|
||||
@@ -58,6 +59,12 @@ const refSearchNav: RefSearchNav = {
|
||||
searchInput.value = ''
|
||||
},
|
||||
}
|
||||
headerPrep.components = [
|
||||
{
|
||||
component: defineAsyncComponent(() => import('~/components/app/surgery-report/_common/btn-history.vue')),
|
||||
props: { }
|
||||
},
|
||||
];
|
||||
// #endregion
|
||||
|
||||
// #region Lifecycle Hooks
|
||||
@@ -79,6 +86,9 @@ async function getListData() {
|
||||
}
|
||||
|
||||
// Handle confirmation result
|
||||
function handleFiltering(value: any) {
|
||||
isFilterDialogOpen.value = false
|
||||
}
|
||||
async function handleConfirmDelete(record: any, action: string) {
|
||||
if (action === 'delete' && record?.id) {
|
||||
try {
|
||||
@@ -108,6 +118,7 @@ provide('rec_id', recId)
|
||||
provide('rec_action', recAction)
|
||||
provide('rec_item', recItem)
|
||||
provide('table_data_loader', isLoading)
|
||||
provide('isHistoryDialogOpen', isHistoryDialogOpen)
|
||||
// #endregion
|
||||
|
||||
// #region Watchers
|
||||
@@ -148,10 +159,7 @@ watch([recId, recAction], () => {
|
||||
]" />
|
||||
|
||||
<div v-else>
|
||||
<Header v-model:search="searchInput"
|
||||
:prep="headerPrep"
|
||||
:ref-search-nav="refSearchNav"
|
||||
@search="handleSearch" />
|
||||
<Header :prep="headerPrep" />
|
||||
|
||||
<Filter
|
||||
:prep="headerPrep"
|
||||
@@ -162,14 +170,11 @@ watch([recId, recAction], () => {
|
||||
<AppSurgeryReportList :data="data" :pagination-meta="paginationMeta" @page-change="handlePageChange" />
|
||||
|
||||
<Dialog v-model:open="isFilterDialogOpen" title="Filter" size="lg">
|
||||
<!-- <AppEncounterFilter
|
||||
:installation="{
|
||||
msg: { placeholder: 'Pilih' },
|
||||
items: [],
|
||||
}"
|
||||
:schema="{}"
|
||||
/> -->
|
||||
aaaaaaa
|
||||
<AppSurgeryReportCommonFilter @submit="handleFiltering" />
|
||||
</Dialog>
|
||||
|
||||
<Dialog v-model:open="isHistoryDialogOpen" title="History">
|
||||
<AppSurgeryReportCommonHistoryDialog />
|
||||
</Dialog>
|
||||
|
||||
<RecordConfirmation v-model:open="isRecordConfirmationOpen" action="delete" :record="recItem"
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
<script setup lang="ts">
|
||||
defineProps<{
|
||||
import { cn } from '~/lib/utils';
|
||||
|
||||
const props = defineProps<{
|
||||
label: string
|
||||
class?: string
|
||||
labelClass?: string
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-col gap-1 lg:grid lg:grid-cols-[180px_minmax(0,1fr)] lg:gap-x-3">
|
||||
<div :class="cn(`flex flex-col gap-1 lg:grid lg:grid-cols-[180px_minmax(0,1fr)] lg:gap-x-3`, props.class)">
|
||||
<!-- Label -->
|
||||
<span class="text-md font-normal text-muted-foreground">
|
||||
<span :class="cn(`text-md font-normal text-muted-foreground`, props.labelClass)">
|
||||
{{ label }}
|
||||
</span>
|
||||
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
import { Dialog } from '~/components/pub/ui/dialog'
|
||||
import DialogContent from '~/components/pub/ui/dialog/DialogContent.vue'
|
||||
import DialogDescription from '~/components/pub/ui/dialog/DialogDescription.vue'
|
||||
import DialogContent from '~/components/pub/ui/dialog/DialogContent.vue'
|
||||
import DialogDescription from '~/components/pub/ui/dialog/DialogDescription.vue'
|
||||
|
||||
interface DialogProps {
|
||||
title: string
|
||||
|
||||
@@ -50,8 +50,11 @@ const value = ref({
|
||||
end: todayCalendar,
|
||||
}) as Ref<DateRange>
|
||||
|
||||
|
||||
function onInput(event: Event) {
|
||||
props.refSearchNav?.onInput((event.target as HTMLInputElement).value)
|
||||
}
|
||||
function onFilterClick() {
|
||||
console.log('Search:', searchQuery.value)
|
||||
console.log('Date Range:', dateRange.value)
|
||||
props.refSearchNav?.onClick()
|
||||
}
|
||||
@@ -60,9 +63,11 @@ function onFilterClick() {
|
||||
<template>
|
||||
<header>
|
||||
<div class="flex items-center gap-2 mb-4 2xl:mb-5">
|
||||
<div class="relative w-64">
|
||||
|
||||
<div v-if="refSearchNav" class="relative w-64">
|
||||
<Search class="absolute left-3 top-1/2 size-4 -translate-y-1/2 text-gray-400" />
|
||||
<Input v-model="searchQuery" type="text" placeholder="Cari Nama /No.RM" class="pl-9" />
|
||||
<Input v-model="searchQuery" @input="onInput"
|
||||
type="text" placeholder="Cari .." class="pl-9" />
|
||||
</div>
|
||||
|
||||
<Popover>
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ definePageMeta({
|
||||
middleware: ['rbac'],
|
||||
roles: ['doctor', 'nurse', 'admisi', 'pharmacy', 'billing', 'management'],
|
||||
title: 'Detail Surat Kontrol',
|
||||
contentFrame: 'cf-container-md',
|
||||
contentFrame: 'cf-full-width',
|
||||
})
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
Reference in New Issue
Block a user