Merge pull request #224 from dikstub-rssa/feat/adj-enc-list-199
Feat: Adjust Encounter
This commit is contained in:
+3
-3
@@ -43,7 +43,7 @@ const emit = defineEmits<{
|
|||||||
}>()
|
}>()
|
||||||
|
|
||||||
// Validation schema
|
// Validation schema
|
||||||
const { handleSubmit, errors, defineField, meta } = useForm<IntegrationEncounterFormData>({
|
const { handleSubmit, errors, defineField, meta } = useForm<any>({
|
||||||
validationSchema: toTypedSchema(IntegrationEncounterSchema),
|
validationSchema: toTypedSchema(IntegrationEncounterSchema),
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -141,7 +141,7 @@ function onAddSep() {
|
|||||||
registerDate: registerDate.value,
|
registerDate: registerDate.value,
|
||||||
cardNumber: cardNumber.value,
|
cardNumber: cardNumber.value,
|
||||||
paymentType: paymentType.value,
|
paymentType: paymentType.value,
|
||||||
sepType: sepType.value
|
sepType: sepType.value,
|
||||||
}
|
}
|
||||||
emit('event', 'add-sep', formValues)
|
emit('event', 'add-sep', formValues)
|
||||||
}
|
}
|
||||||
@@ -454,7 +454,7 @@ defineExpose({
|
|||||||
name="i-lucide-loader-2"
|
name="i-lucide-loader-2"
|
||||||
class="h-4 w-4 animate-spin"
|
class="h-4 w-4 animate-spin"
|
||||||
/>
|
/>
|
||||||
<Icon
|
<Icon
|
||||||
v-else
|
v-else
|
||||||
name="i-lucide-plus"
|
name="i-lucide-plus"
|
||||||
class="h-4 w-4"
|
class="h-4 w-4"
|
||||||
@@ -187,6 +187,7 @@ function onAddSep() {
|
|||||||
registerDate: registerDate.value,
|
registerDate: registerDate.value,
|
||||||
cardNumber: cardNumber.value,
|
cardNumber: cardNumber.value,
|
||||||
paymentMethodCode: paymentMethodCode.value,
|
paymentMethodCode: paymentMethodCode.value,
|
||||||
|
unitCode: props.selectedDoctor?.unit?.code || '',
|
||||||
sepFile: sepFile.value,
|
sepFile: sepFile.value,
|
||||||
sippFile: sippFile.value,
|
sippFile: sippFile.value,
|
||||||
sepType: sepType.value,
|
sepType: sepType.value,
|
||||||
|
|||||||
@@ -0,0 +1,114 @@
|
|||||||
|
<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'
|
||||||
|
|
||||||
|
interface InstallationFormData {
|
||||||
|
name: string
|
||||||
|
code: string
|
||||||
|
encounterClassCode: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
installation: {
|
||||||
|
msg: {
|
||||||
|
placeholder: string
|
||||||
|
}
|
||||||
|
items: {
|
||||||
|
value: string
|
||||||
|
label: string
|
||||||
|
code: string
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
schema: any
|
||||||
|
initialValues?: Partial<InstallationFormData>
|
||||||
|
errors?: FormErrors
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
submit: [values: InstallationFormData, resetForm: () => void]
|
||||||
|
cancel: [resetForm: () => void]
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const formSchema = toTypedSchema(props.schema)
|
||||||
|
|
||||||
|
// Form submission handler
|
||||||
|
function onSubmitForm(values: any, { resetForm }: { resetForm: () => void }) {
|
||||||
|
const formData: InstallationFormData = {
|
||||||
|
name: values.name || '',
|
||||||
|
code: values.code || '',
|
||||||
|
encounterClassCode: values.encounterClassCode || '',
|
||||||
|
}
|
||||||
|
emit('submit', formData, resetForm)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Form cancel handler
|
||||||
|
function onCancelForm({ resetForm }: { resetForm: () => void }) {
|
||||||
|
emit('cancel', resetForm)
|
||||||
|
}
|
||||||
|
|
||||||
|
const items = ref([
|
||||||
|
{ label: 'Rujukan Internal', value: 'ri' },
|
||||||
|
{ label: 'SEP Rujukan', value: 'sr' },
|
||||||
|
])
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Form
|
||||||
|
v-slot="{ handleSubmit, resetForm }"
|
||||||
|
as=""
|
||||||
|
keep-values
|
||||||
|
:validation-schema="formSchema"
|
||||||
|
: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-3 text-lg xl:text-xl">
|
||||||
|
<div class="flex flex-col justify-between">
|
||||||
|
<FieldGroup>
|
||||||
|
<Label label-for="parentId">Cara Bayar</Label>
|
||||||
|
<Field id="encounterClassCode" :errors="errors">
|
||||||
|
<FormField v-slot="{ componentField }" name="encounterClassCode">
|
||||||
|
<FormItem>
|
||||||
|
<FormControl>
|
||||||
|
<Select v-bind="componentField" :items="items" />
|
||||||
|
</FormControl>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
</FormField>
|
||||||
|
</Field>
|
||||||
|
</FieldGroup>
|
||||||
|
<FieldGroup>
|
||||||
|
<Label label-for="parentId">Poliklinik</Label>
|
||||||
|
<Field id="encounterClassCode" :errors="errors">
|
||||||
|
<FormField v-slot="{ componentField }" name="encounterClassCode">
|
||||||
|
<FormItem>
|
||||||
|
<FormControl>
|
||||||
|
<Select v-bind="componentField" :items="items" />
|
||||||
|
</FormControl>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
</FormField>
|
||||||
|
</Field>
|
||||||
|
</FieldGroup>
|
||||||
|
<FieldGroup>
|
||||||
|
<Label label-for="parentId">Kunjungan</Label>
|
||||||
|
<Field id="encounterClassCode" :errors="errors">
|
||||||
|
<FormField v-slot="{ componentField }" name="encounterClassCode">
|
||||||
|
<FormItem>
|
||||||
|
<FormControl>
|
||||||
|
<Select v-bind="componentField" :items="items" />
|
||||||
|
</FormControl>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
</FormField>
|
||||||
|
</Field>
|
||||||
|
</FieldGroup>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</Form>
|
||||||
|
</template>
|
||||||
@@ -1,114 +1,109 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { FormErrors } from '~/types/error'
|
// Components
|
||||||
import { toTypedSchema } from '@vee-validate/zod'
|
import * as DE from '~/components/pub/my-ui/doc-entry'
|
||||||
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'
|
|
||||||
|
|
||||||
interface InstallationFormData {
|
|
||||||
name: string
|
|
||||||
code: string
|
|
||||||
encounterClassCode: string
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Props
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
installation: {
|
payments: any[]
|
||||||
msg: {
|
units: any[]
|
||||||
placeholder: string
|
visits: any[]
|
||||||
}
|
|
||||||
items: {
|
|
||||||
value: string
|
|
||||||
label: string
|
|
||||||
code: string
|
|
||||||
}[]
|
|
||||||
}
|
|
||||||
schema: any
|
|
||||||
initialValues?: Partial<InstallationFormData>
|
|
||||||
errors?: FormErrors
|
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
submit: [values: InstallationFormData, resetForm: () => void]
|
(e: 'search', values: any): void
|
||||||
cancel: [resetForm: () => void]
|
(e: 'reset'): void
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const formSchema = toTypedSchema(props.schema)
|
const paymentItem = ref<any>(null)
|
||||||
|
const unitItem = ref<any>(null)
|
||||||
|
const visitItem = ref<any>(null)
|
||||||
|
|
||||||
// Form submission handler
|
function handleReset() {
|
||||||
function onSubmitForm(values: any, { resetForm }: { resetForm: () => void }) {
|
paymentItem.value = null
|
||||||
const formData: InstallationFormData = {
|
unitItem.value = null
|
||||||
name: values.name || '',
|
visitItem.value = null
|
||||||
code: values.code || '',
|
emit('reset')
|
||||||
encounterClassCode: values.encounterClassCode || '',
|
|
||||||
}
|
|
||||||
emit('submit', formData, resetForm)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Form cancel handler
|
function handleSearch() {
|
||||||
function onCancelForm({ resetForm }: { resetForm: () => void }) {
|
emit('search', {
|
||||||
emit('cancel', resetForm)
|
'paymentMethod-code': paymentItem.value,
|
||||||
|
'unit-code': unitItem.value,
|
||||||
|
visit: visitItem.value,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const items = ref([
|
|
||||||
{ label: 'Rujukan Internal', value: 'ri' },
|
|
||||||
{ label: 'SEP Rujukan', value: 'sr' },
|
|
||||||
])
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Form
|
<div class="mx-auto w-full">
|
||||||
v-slot="{ handleSubmit, resetForm }"
|
<DE.Block
|
||||||
as=""
|
labelSize="thin"
|
||||||
keep-values
|
class="!pt-0"
|
||||||
:validation-schema="formSchema"
|
:colCount="1"
|
||||||
:initial-values="initialValues"
|
:cellFlex="false"
|
||||||
>
|
>
|
||||||
<form id="entry-form" @submit="handleSubmit($event, (values) => onSubmitForm(values, { resetForm }))">
|
<DE.Cell>
|
||||||
<div class="mb-5 border-b border-b-slate-300 pb-3 text-lg xl:text-xl">
|
<DE.Label height="compact">Cara Bayar</DE.Label>
|
||||||
<div class="flex flex-col justify-between">
|
<DE.Field>
|
||||||
<FieldGroup>
|
<Select
|
||||||
<Label label-for="parentId">Cara Bayar</Label>
|
id="paymentMethodCode"
|
||||||
<Field id="encounterClassCode" :errors="errors">
|
v-model="paymentItem"
|
||||||
<FormField v-slot="{ componentField }" name="encounterClassCode">
|
:items="payments || []"
|
||||||
<FormItem>
|
placeholder="Pilih Jenis Pembayaran"
|
||||||
<FormControl>
|
/>
|
||||||
<Select v-bind="componentField" :items="items" />
|
</DE.Field>
|
||||||
</FormControl>
|
</DE.Cell>
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
<DE.Cell>
|
||||||
</FormField>
|
<DE.Label height="compact">Poliklinik</DE.Label>
|
||||||
</Field>
|
<DE.Field>
|
||||||
</FieldGroup>
|
<Select
|
||||||
<FieldGroup>
|
id="unit"
|
||||||
<Label label-for="parentId">Poliklinik</Label>
|
v-model="unitItem"
|
||||||
<Field id="encounterClassCode" :errors="errors">
|
:items="units || []"
|
||||||
<FormField v-slot="{ componentField }" name="encounterClassCode">
|
placeholder="Pilih Poliklinik"
|
||||||
<FormItem>
|
/>
|
||||||
<FormControl>
|
</DE.Field>
|
||||||
<Select v-bind="componentField" :items="items" />
|
</DE.Cell>
|
||||||
</FormControl>
|
|
||||||
<FormMessage />
|
<DE.Cell>
|
||||||
</FormItem>
|
<DE.Label height="compact">Kunjungan</DE.Label>
|
||||||
</FormField>
|
<DE.Field>
|
||||||
</Field>
|
<Select
|
||||||
</FieldGroup>
|
id="visit"
|
||||||
<FieldGroup>
|
v-model="visitItem"
|
||||||
<Label label-for="parentId">Kunjungan</Label>
|
:items="visits || []"
|
||||||
<Field id="encounterClassCode" :errors="errors">
|
placeholder="Pilih Kunjungan"
|
||||||
<FormField v-slot="{ componentField }" name="encounterClassCode">
|
/>
|
||||||
<FormItem>
|
</DE.Field>
|
||||||
<FormControl>
|
</DE.Cell>
|
||||||
<Select v-bind="componentField" :items="items" />
|
</DE.Block>
|
||||||
</FormControl>
|
|
||||||
<FormMessage />
|
<div class="flex w-full justify-end gap-2">
|
||||||
</FormItem>
|
<Button
|
||||||
</FormField>
|
variant="outline"
|
||||||
</Field>
|
type="button"
|
||||||
</FieldGroup>
|
class="h-[40px] rounded-md border-orange-400 text-orange-400 hover:bg-green-50"
|
||||||
</div>
|
@click="handleReset"
|
||||||
</div>
|
>
|
||||||
</form>
|
<Icon
|
||||||
</Form>
|
name="i-lucide-rotate-ccw"
|
||||||
|
class="h-5 w-5"
|
||||||
|
/>
|
||||||
|
Reset
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="default"
|
||||||
|
type="button"
|
||||||
|
class="h-[40px]"
|
||||||
|
@click="handleSearch"
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
name="i-lucide-check"
|
||||||
|
class="h-5 w-5"
|
||||||
|
/>
|
||||||
|
Terapkan
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -20,11 +20,13 @@ const props = defineProps<{
|
|||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
apply: [filters: { personName: string; startDate: string; endDate: string }]
|
apply: [filters: { personName: string; startDate: string; endDate: string }]
|
||||||
|
click: []
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const searchQuery = ref('')
|
const searchQuery = ref('')
|
||||||
const isRoleRegistration = props.activePositon === 'registration'
|
const isRoleRegistration = props.activePositon === 'registration'
|
||||||
const isRoleMedical = props.activePositon === 'medical'
|
const isRoleMedical = props.activePositon === 'medical'
|
||||||
|
const debouncedSearchQuery = refDebounced(searchQuery, 500)
|
||||||
|
|
||||||
const df = new DateFormatter('en-US', {
|
const df = new DateFormatter('en-US', {
|
||||||
dateStyle: 'medium',
|
dateStyle: 'medium',
|
||||||
@@ -43,14 +45,18 @@ const oneMonthAgoCalendar = new CalendarDate(
|
|||||||
oneMonthAgo.getDate(),
|
oneMonthAgo.getDate(),
|
||||||
)
|
)
|
||||||
|
|
||||||
const value = ref({
|
const dateRange = ref({
|
||||||
start: oneMonthAgoCalendar,
|
start: oneMonthAgoCalendar,
|
||||||
end: todayCalendar,
|
end: todayCalendar,
|
||||||
}) as Ref<DateRange>
|
}) as Ref<DateRange>
|
||||||
|
|
||||||
function onFilterClick() {
|
function onFilterClick() {
|
||||||
const startDate = value.value.start ? value.value.start.toString() : ''
|
emit('click')
|
||||||
const endDate = value.value.end ? value.value.end.toString() : startDate
|
}
|
||||||
|
|
||||||
|
function onFilterApply() {
|
||||||
|
const startDate = dateRange.value.start ? dateRange.value.start.toString() : ''
|
||||||
|
const endDate = dateRange.value.end ? dateRange.value.end.toString() : startDate
|
||||||
|
|
||||||
emit('apply', {
|
emit('apply', {
|
||||||
personName: searchQuery.value,
|
personName: searchQuery.value,
|
||||||
@@ -58,6 +64,18 @@ function onFilterClick() {
|
|||||||
endDate,
|
endDate,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
watch(debouncedSearchQuery, () => {
|
||||||
|
onFilterApply()
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(
|
||||||
|
dateRange,
|
||||||
|
() => {
|
||||||
|
onFilterApply()
|
||||||
|
},
|
||||||
|
{ deep: true },
|
||||||
|
)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -76,18 +94,18 @@ function onFilterClick() {
|
|||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
:class="
|
:class="
|
||||||
cn('min-w-[240px] max-w-[320px] justify-start text-left font-normal', !value && 'text-muted-foreground')
|
cn('min-w-[240px] max-w-[320px] justify-start text-left font-normal', !dateRange && 'text-muted-foreground')
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<CalendarIcon class="mr-2 h-4 w-4" />
|
<CalendarIcon class="mr-2 h-4 w-4" />
|
||||||
<template v-if="value.start">
|
<template v-if="dateRange.start">
|
||||||
<template v-if="value.end">
|
<template v-if="dateRange.end">
|
||||||
{{ df.format(value.start.toDate(getLocalTimeZone())) }} -
|
{{ df.format(dateRange.start.toDate(getLocalTimeZone())) }} -
|
||||||
{{ df.format(value.end.toDate(getLocalTimeZone())) }}
|
{{ df.format(dateRange.end.toDate(getLocalTimeZone())) }}
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-else>
|
<template v-else>
|
||||||
{{ df.format(value.start.toDate(getLocalTimeZone())) }}
|
{{ df.format(dateRange.start.toDate(getLocalTimeZone())) }}
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>Pick a date</template>
|
<template v-else>Pick a date</template>
|
||||||
@@ -95,10 +113,10 @@ function onFilterClick() {
|
|||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
<PopoverContent class="w-auto p-0">
|
<PopoverContent class="w-auto p-0">
|
||||||
<RangeCalendar
|
<RangeCalendar
|
||||||
v-model="value"
|
v-model="dateRange"
|
||||||
initial-focus
|
initial-focus
|
||||||
:number-of-months="2"
|
:number-of-months="2"
|
||||||
@update:start-value="(startDate) => (value.start = startDate)"
|
@update:start-value="(startDate) => (dateRange.start = startDate)"
|
||||||
/>
|
/>
|
||||||
</PopoverContent>
|
</PopoverContent>
|
||||||
</Popover>
|
</Popover>
|
||||||
@@ -112,7 +130,7 @@ function onFilterClick() {
|
|||||||
Filter
|
Filter
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<DropdownMenu v-show="props.enableExport && (isRoleRegistration || isRoleMedical)">
|
<DropdownMenu v-if="props.enableExport && (isRoleRegistration || isRoleMedical)">
|
||||||
<DropdownMenuTrigger as-child>
|
<DropdownMenuTrigger as-child>
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
|
|||||||
@@ -1,25 +1,19 @@
|
|||||||
import type { Config, RecComponent } from '~/components/pub/my-ui/data-table'
|
import type { Config, RecComponent } from '~/components/pub/my-ui/data-table'
|
||||||
import { defineAsyncComponent } from 'vue'
|
import { defineAsyncComponent } from 'vue'
|
||||||
import type { Encounter } from '~/models/encounter'
|
import type { Encounter } from '~/models/encounter'
|
||||||
import { educationCodes, genderCodes } from '~/lib/constants'
|
import { formatAddress } from '~/models/person-address'
|
||||||
|
import { educationCodes, encounterClassCodes, genderCodes } from '~/lib/constants'
|
||||||
import { getAge } from '~/lib/date'
|
import { getAge } from '~/lib/date'
|
||||||
|
|
||||||
type SmallDetailDto = Encounter
|
type SmallDetailDto = Encounter
|
||||||
|
|
||||||
const action = defineAsyncComponent(() => import('./dropdown-action.vue'))
|
const action = defineAsyncComponent(() => import('./dropdown-action.vue'))
|
||||||
const statusBadge = defineAsyncComponent(() => import('./status-badge.vue'))
|
const statusBadge = defineAsyncComponent(() => import('./status-badge.vue'))
|
||||||
|
const vclaimSepInfo = defineAsyncComponent(() => import('./vclaim-sep-info.vue'))
|
||||||
|
const vclaimSepNone = defineAsyncComponent(() => import('./vclaim-sep-none.vue'))
|
||||||
|
|
||||||
export const config: Config = {
|
export const defaultConfig: Config = {
|
||||||
cols: [
|
cols: [{}, {}, {}, { width: 160 }, {}, { width: 70 }, {}, { width: 50 }],
|
||||||
{},
|
|
||||||
{},
|
|
||||||
{},
|
|
||||||
{ width: 160 },
|
|
||||||
{},
|
|
||||||
{ width: 70 },
|
|
||||||
{ },
|
|
||||||
{ width: 50 },
|
|
||||||
],
|
|
||||||
|
|
||||||
headers: [
|
headers: [
|
||||||
[
|
[
|
||||||
@@ -94,11 +88,146 @@ export const config: Config = {
|
|||||||
birth_date: (rec: unknown): unknown => {
|
birth_date: (rec: unknown): unknown => {
|
||||||
const recX = rec as Encounter
|
const recX = rec as Encounter
|
||||||
if (recX.patient?.person?.birthDate) {
|
if (recX.patient?.person?.birthDate) {
|
||||||
return '' +
|
return (
|
||||||
'<div>' + (recX.patient.person.birthDate as string).substring(0, 10) + ' / </div>' +
|
'' +
|
||||||
|
'<div>' +
|
||||||
|
(recX.patient.person.birthDate as string).substring(0, 10) +
|
||||||
|
' / </div>' +
|
||||||
getAge(recX.patient.person.birthDate as string).extFormat
|
getAge(recX.patient.person.birthDate as string).extFormat
|
||||||
|
)
|
||||||
}
|
}
|
||||||
return '-'
|
return '-'
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const ambulatoryConfig: Config = {
|
||||||
|
cols: [{}, {}, {}, { width: 160 }, {}, { width: 70 }, {}, {}, {}, {}, {}, {}, { width: 50 }],
|
||||||
|
|
||||||
|
headers: [
|
||||||
|
[
|
||||||
|
{ label: 'TANGGAL' },
|
||||||
|
{ label: 'NO. RM' },
|
||||||
|
{ label: 'NO. BILL' },
|
||||||
|
{ label: 'NAMA PASIEN' },
|
||||||
|
{ label: 'L/P' },
|
||||||
|
{ label: 'ALAMAT' },
|
||||||
|
{ label: 'KLINIK' },
|
||||||
|
{ label: 'CARA BAYAR' },
|
||||||
|
{ label: 'RUJUKAN' },
|
||||||
|
{ label: 'KET. RUJUKAN' },
|
||||||
|
{ label: 'ASAL' },
|
||||||
|
{ label: 'SEP' },
|
||||||
|
{ label: 'STATUS', classVal: '!text-center' },
|
||||||
|
{ label: '' },
|
||||||
|
],
|
||||||
|
],
|
||||||
|
|
||||||
|
keys: [
|
||||||
|
'registeredAt',
|
||||||
|
'patientNumber',
|
||||||
|
'trxNumber',
|
||||||
|
'patient.person.name',
|
||||||
|
'gender',
|
||||||
|
'address',
|
||||||
|
'clinic',
|
||||||
|
'paymentMethod_code',
|
||||||
|
'referral',
|
||||||
|
'note',
|
||||||
|
'class_code',
|
||||||
|
'sep',
|
||||||
|
'status',
|
||||||
|
'action',
|
||||||
|
],
|
||||||
|
|
||||||
|
delKeyNames: [
|
||||||
|
{ key: 'code', label: 'Kode' },
|
||||||
|
{ key: 'name', label: 'Nama' },
|
||||||
|
],
|
||||||
|
|
||||||
|
parses: {
|
||||||
|
registeredAt: (rec: unknown): unknown => {
|
||||||
|
const recX = rec as Encounter
|
||||||
|
const currentDate = recX.registeredAt ? (recX.registeredAt as string) : (recX as any).createdAt
|
||||||
|
return currentDate ? currentDate.substring(0, 10) : '-'
|
||||||
|
},
|
||||||
|
patientNumber: (rec: unknown): unknown => {
|
||||||
|
const recX = rec as any
|
||||||
|
return recX.patient?.number || '-'
|
||||||
|
},
|
||||||
|
trxNumber: (rec: unknown): unknown => {
|
||||||
|
const recX = rec as any
|
||||||
|
return recX.trx_number || '-'
|
||||||
|
},
|
||||||
|
gender: (rec: unknown): unknown => {
|
||||||
|
const recX = rec as Encounter
|
||||||
|
if (recX.patient?.person?.gender_code) {
|
||||||
|
return genderCodes[recX.patient.person.gender_code]
|
||||||
|
}
|
||||||
|
return '-'
|
||||||
|
},
|
||||||
|
address: (rec: unknown): unknown => {
|
||||||
|
const recX = rec as Encounter
|
||||||
|
const addresses = recX.patient?.person?.addresses || []
|
||||||
|
const resident = addresses?.find((addr) => addr.locationType_code === 'domicile')
|
||||||
|
const text = resident ? formatAddress(resident) : '-'
|
||||||
|
return text.length > 20 ? text.substring(0, 17) + '...' : text
|
||||||
|
},
|
||||||
|
clinic: (rec: unknown): unknown => {
|
||||||
|
const recX = rec as Encounter
|
||||||
|
return recX.unit?.name || recX.refSource_name || '-'
|
||||||
|
},
|
||||||
|
paymentMethod_code: (rec: unknown): unknown => {
|
||||||
|
const recX = rec as Encounter
|
||||||
|
return (recX.paymentMethod_code || '-').toUpperCase()
|
||||||
|
},
|
||||||
|
referral: (rec: unknown): unknown => {
|
||||||
|
const recX = rec as any
|
||||||
|
return recX?.vclaimReference?.poliRujukan || '-'
|
||||||
|
},
|
||||||
|
note: (rec: unknown): unknown => {
|
||||||
|
const recX = rec as any
|
||||||
|
return recX?.vclaimReference?.ppkDirujuk || '-'
|
||||||
|
},
|
||||||
|
class_code: (rec: unknown): unknown => {
|
||||||
|
const recX = rec as Encounter
|
||||||
|
return recX.class_code ? encounterClassCodes[recX.class_code] : '-'
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
components: {
|
||||||
|
sep(rec: any) {
|
||||||
|
if (rec?.paymentMethod_code !== 'jkn') {
|
||||||
|
return {
|
||||||
|
rec: rec as object,
|
||||||
|
component: vclaimSepNone,
|
||||||
|
} as RecComponent
|
||||||
|
}
|
||||||
|
const res: RecComponent = {
|
||||||
|
rec: rec as object,
|
||||||
|
component: vclaimSepInfo,
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
},
|
||||||
|
status(rec, idx) {
|
||||||
|
const recX = rec as Encounter
|
||||||
|
if (!recX.status_code) {
|
||||||
|
recX.status_code = 'new'
|
||||||
|
}
|
||||||
|
const res: RecComponent = {
|
||||||
|
idx,
|
||||||
|
rec: recX,
|
||||||
|
component: statusBadge,
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
},
|
||||||
|
action(rec, idx) {
|
||||||
|
const res: RecComponent = {
|
||||||
|
idx,
|
||||||
|
rec: rec as object,
|
||||||
|
component: action,
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import DataTable from '~/components/pub/my-ui/data-table/data-table.vue'
|
import DataTable from '~/components/pub/my-ui/data-table/data-table.vue'
|
||||||
import { config } from './list.cfg'
|
import { defaultConfig, ambulatoryConfig } from './list.cfg'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
data: any[],
|
data: any[]
|
||||||
|
classCode: string | undefined
|
||||||
}>()
|
}>()
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<DataTable
|
<DataTable
|
||||||
v-bind="config"
|
v-bind="props.classCode === 'ambulatory' ? ambulatoryConfig : defaultConfig"
|
||||||
:rows="props.data"
|
:rows="props.data"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
const props = defineProps<{
|
||||||
|
rec: any
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const recSepId = inject<Ref<number>>('rec_sep_id')!
|
||||||
|
const recSepMenu = inject<Ref<string>>('rec_sep_menu')!
|
||||||
|
const recSepSubMenu = inject<Ref<string>>('rec_sep_sub_menu')!
|
||||||
|
const sepFileReview = ref<any>({})
|
||||||
|
const sippFileReview = ref<any>({})
|
||||||
|
|
||||||
|
const getEncounterDocument = () => {
|
||||||
|
const encounter = props.rec
|
||||||
|
sippFileReview.value = {}
|
||||||
|
sepFileReview.value = {}
|
||||||
|
if (encounter.encounterDocuments && Array.isArray(encounter.encounterDocuments)) {
|
||||||
|
for (const doc of encounter.encounterDocuments) {
|
||||||
|
if (doc.type_code === 'vclaim-sep') {
|
||||||
|
sepFileReview.value = { id: doc.id, fileName: doc.fileName, filePath: doc.filePath, type: doc.type_code }
|
||||||
|
} else if (doc.type_code === 'vclaim-sipp') {
|
||||||
|
sippFileReview.value = { id: doc.id, fileName: doc.fileName, filePath: doc.filePath, type: doc.type_code }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleSepView(menu: string, subMenu: string) {
|
||||||
|
recSepId.value = props.rec.id || 0
|
||||||
|
recSepMenu.value = menu
|
||||||
|
recSepSubMenu.value = subMenu
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getEncounterDocument()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="flex flex-col gap-2">
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
type="button"
|
||||||
|
class="h-[40px] rounded-md border-orange-400 text-orange-400 hover:bg-green-50"
|
||||||
|
@click="handleSepView('sipp', sippFileReview.id ? 'view' : 'edit')"
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
v-if="sippFileReview.id"
|
||||||
|
name="i-lucide-eye"
|
||||||
|
class="h-5 w-5"
|
||||||
|
/>
|
||||||
|
<Icon
|
||||||
|
v-else
|
||||||
|
name="i-lucide-upload"
|
||||||
|
class="h-5 w-5"
|
||||||
|
/>
|
||||||
|
{{ sippFileReview.id ? 'Lihat SIPP' : 'Upload File SIPP' }}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
type="button"
|
||||||
|
class="h-[40px] rounded-md border-orange-400 text-orange-400 hover:bg-green-50"
|
||||||
|
@click="handleSepView('sep', sepFileReview.id ? 'view' : 'edit')"
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
v-if="sepFileReview.id"
|
||||||
|
name="i-lucide-eye"
|
||||||
|
class="h-5 w-5"
|
||||||
|
/>
|
||||||
|
<Icon
|
||||||
|
v-else
|
||||||
|
name="i-lucide-upload"
|
||||||
|
class="h-5 w-5"
|
||||||
|
/>
|
||||||
|
{{ sepFileReview.id ? 'Lihat SEP' : 'Upload File SEP' }}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
const props = defineProps<{
|
||||||
|
rec: any
|
||||||
|
}>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="flex flex-col gap-2">
|
||||||
|
<span>Tidak ada</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -7,8 +7,12 @@ import { ActionEvents } from '~/components/pub/my-ui/data/types'
|
|||||||
import Dialog from '~/components/pub/my-ui/modal/dialog.vue'
|
import Dialog from '~/components/pub/my-ui/modal/dialog.vue'
|
||||||
import * as CH from '~/components/pub/my-ui/content-header'
|
import * as CH from '~/components/pub/my-ui/content-header'
|
||||||
import RecordConfirmation from '~/components/pub/my-ui/confirmation/record-confirmation.vue'
|
import RecordConfirmation from '~/components/pub/my-ui/confirmation/record-confirmation.vue'
|
||||||
|
import FileUpload from '~/components/pub/my-ui/form/file-field.vue'
|
||||||
import { useSidebar } from '~/components/pub/ui/sidebar/utils'
|
import { useSidebar } from '~/components/pub/ui/sidebar/utils'
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
import { paymentTypes, sepRefTypeCodes } from '~/lib/constants.vclaim'
|
||||||
|
|
||||||
// App libs
|
// App libs
|
||||||
import { getServicePosition } from '~/lib/roles' // previously getPositionAs
|
import { getServicePosition } from '~/lib/roles' // previously getPositionAs
|
||||||
|
|
||||||
@@ -18,6 +22,10 @@ import {
|
|||||||
remove as removeEncounter,
|
remove as removeEncounter,
|
||||||
cancel as cancelEncounter,
|
cancel as cancelEncounter,
|
||||||
} from '~/services/encounter.service'
|
} from '~/services/encounter.service'
|
||||||
|
import { getValueLabelList as getUnits } from '~/services/unit.service'
|
||||||
|
|
||||||
|
// Handlers
|
||||||
|
import { uploadAttachmentCustom } from '~/handlers/supporting-document.handler'
|
||||||
|
|
||||||
// Apps
|
// Apps
|
||||||
import Content from '~/components/app/encounter/list.vue'
|
import Content from '~/components/app/encounter/list.vue'
|
||||||
@@ -53,9 +61,16 @@ const isLoading = reactive<DataTableLoader>({
|
|||||||
const recId = ref<number>(0)
|
const recId = ref<number>(0)
|
||||||
const recAction = ref<string>('')
|
const recAction = ref<string>('')
|
||||||
const recItem = ref<any>(null)
|
const recItem = ref<any>(null)
|
||||||
|
const recSepId = ref<number>(0)
|
||||||
|
const recSepMenu = ref<string>('')
|
||||||
|
const recSepSubMenu = ref<string>('')
|
||||||
const isFilterFormDialogOpen = ref(false)
|
const isFilterFormDialogOpen = ref(false)
|
||||||
const isRecordConfirmationOpen = ref(false)
|
const isRecordConfirmationOpen = ref(false)
|
||||||
const isRecordCancelOpen = ref(false)
|
const isRecordCancelOpen = ref(false)
|
||||||
|
const uploadFile = ref<any>(null)
|
||||||
|
const payments = ref<any>([])
|
||||||
|
const units = ref<any>([])
|
||||||
|
const sepsList = ref<any>([])
|
||||||
|
|
||||||
// Headers
|
// Headers
|
||||||
const hreaderPrep: CH.Config = {
|
const hreaderPrep: CH.Config = {
|
||||||
@@ -72,36 +87,14 @@ if (!props.canCreate) {
|
|||||||
delete hreaderPrep.addNav
|
delete hreaderPrep.addNav
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filters
|
|
||||||
const filter = ref<{
|
|
||||||
installation: {
|
|
||||||
msg: {
|
|
||||||
placeholder: string
|
|
||||||
}
|
|
||||||
items: {
|
|
||||||
value: string
|
|
||||||
label: string
|
|
||||||
code: string
|
|
||||||
}[]
|
|
||||||
}
|
|
||||||
schema: any
|
|
||||||
initialValues?: Partial<any>
|
|
||||||
errors?: any
|
|
||||||
}>({
|
|
||||||
installation: {
|
|
||||||
msg: {
|
|
||||||
placeholder: 'Pilih',
|
|
||||||
},
|
|
||||||
items: [],
|
|
||||||
},
|
|
||||||
schema: {},
|
|
||||||
})
|
|
||||||
|
|
||||||
// Recrod reactivities
|
// Recrod reactivities
|
||||||
provide('activeServicePosition', activeServicePosition)
|
provide('activeServicePosition', activeServicePosition)
|
||||||
provide('rec_id', recId)
|
provide('rec_id', recId)
|
||||||
provide('rec_action', recAction)
|
provide('rec_action', recAction)
|
||||||
provide('rec_item', recItem)
|
provide('rec_item', recItem)
|
||||||
|
provide('rec_sep_id', recSepId)
|
||||||
|
provide('rec_sep_menu', recSepMenu)
|
||||||
|
provide('rec_sep_sub_menu', recSepSubMenu)
|
||||||
provide('table_data_loader', isLoading)
|
provide('table_data_loader', isLoading)
|
||||||
|
|
||||||
watch(getActiveRole, (role?: string) => {
|
watch(getActiveRole, (role?: string) => {
|
||||||
@@ -129,15 +122,50 @@ watch(
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
onMounted(() => {
|
watch([recSepId, recSepMenu, recSepSubMenu], (value) => {
|
||||||
|
const id = value[0]
|
||||||
|
const menu = value[1]
|
||||||
|
const subMenu = value[2]
|
||||||
|
if (!id) return
|
||||||
|
if (subMenu === 'view') {
|
||||||
|
handleViewFile(id, menu, subMenu)
|
||||||
|
}
|
||||||
|
if (subMenu === 'edit') {
|
||||||
|
handleUploadFile(id, menu)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
getPatientList()
|
getPatientList()
|
||||||
|
units.value = await getUnits({}, true)
|
||||||
|
payments.value = Object.keys(paymentTypes).map((item) => ({
|
||||||
|
value: item.toString(),
|
||||||
|
label: paymentTypes[item],
|
||||||
|
})) as any
|
||||||
|
sepsList.value = Object.keys(sepRefTypeCodes).map((item) => ({
|
||||||
|
value: item.toString(),
|
||||||
|
label: sepRefTypeCodes[item],
|
||||||
|
})) as any
|
||||||
})
|
})
|
||||||
|
|
||||||
/////// Functions
|
/////// Functions
|
||||||
async function getPatientList() {
|
async function getPatientList() {
|
||||||
isLoading.isTableLoading = true
|
isLoading.isTableLoading = true
|
||||||
const includesParams =
|
const includesParamsArrays = [
|
||||||
'patient,patient-person,patient-person-addresses,unit,Appointment_Doctor,Appointment_Doctor-employee,Appointment_Doctor-employee-person,Responsible_Doctor,Responsible_Doctor-employee,Responsible_Doctor-employee-person'
|
'patient',
|
||||||
|
'patient-person',
|
||||||
|
'patient-person-addresses',
|
||||||
|
'Appointment_Doctor',
|
||||||
|
'Appointment_Doctor-employee',
|
||||||
|
'Appointment_Doctor-employee-person',
|
||||||
|
'Responsible_Doctor',
|
||||||
|
'Responsible_Doctor-employee',
|
||||||
|
'Responsible_Doctor-employee-person',
|
||||||
|
'EncounterDocuments',
|
||||||
|
'unit',
|
||||||
|
'vclaimReference', // vclaimReference | vclaimSep
|
||||||
|
]
|
||||||
|
const includesParams = includesParamsArrays.join(',')
|
||||||
data.value = []
|
data.value = []
|
||||||
try {
|
try {
|
||||||
const params: any = { includes: includesParams, ...filterParams.value }
|
const params: any = { includes: includesParams, ...filterParams.value }
|
||||||
@@ -159,15 +187,92 @@ async function getPatientList() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleUploadFile(id: number, menu: string) {
|
||||||
|
uploadFile.value = null
|
||||||
|
const fileInput: HTMLInputElement | undefined | null = document
|
||||||
|
.getElementById('uploadFile')
|
||||||
|
?.querySelector("input[type='file']")
|
||||||
|
if (fileInput) {
|
||||||
|
fileInput.value = ''
|
||||||
|
fileInput.click()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleUploadFileSubmit() {
|
||||||
|
const files = uploadFile.value
|
||||||
|
if (!uploadFile.value || files.length === 0) {
|
||||||
|
recSepId.value = 0
|
||||||
|
recSepMenu.value = ''
|
||||||
|
recSepSubMenu.value = ''
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const result = await uploadAttachmentCustom({
|
||||||
|
file: uploadFile.value,
|
||||||
|
refId: recSepId.value,
|
||||||
|
entityTypeCode: 'encounter',
|
||||||
|
type: recSepMenu.value === 'sep' ? 'vclaim-sep' : 'vclaim-sipp',
|
||||||
|
})
|
||||||
|
if (result.success) {
|
||||||
|
toast({
|
||||||
|
title: 'Berhasil',
|
||||||
|
description: 'File berhasil diunggah',
|
||||||
|
variant: 'default',
|
||||||
|
})
|
||||||
|
await getPatientList()
|
||||||
|
} else {
|
||||||
|
toast({
|
||||||
|
title: 'Gagal',
|
||||||
|
description: 'File gagal diunggah',
|
||||||
|
variant: 'destructive',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
recSepId.value = 0
|
||||||
|
recSepMenu.value = ''
|
||||||
|
recSepSubMenu.value = ''
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleViewFile(id: number, menu: string, subMenu: string) {
|
||||||
|
const currentData: any = data.value.find((item: any) => Number(item.id) === Number(id))
|
||||||
|
if (!currentData) return
|
||||||
|
let fileReviewSep: any = null
|
||||||
|
let fileReviewSipp: any = null
|
||||||
|
for (const doc of currentData.encounterDocuments) {
|
||||||
|
if (doc.type_code === 'vclaim-sep') {
|
||||||
|
fileReviewSep = { id: doc.id, fileName: doc.fileName, filePath: doc.filePath, type: doc.type_code }
|
||||||
|
} else if (doc.type_code === 'vclaim-sipp') {
|
||||||
|
fileReviewSipp = { id: doc.id, fileName: doc.fileName, filePath: doc.filePath, type: doc.type_code }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fileReviewSep && menu === 'sep' && subMenu === 'view') {
|
||||||
|
window.open(fileReviewSep.filePath, '_blank')
|
||||||
|
}
|
||||||
|
if (fileReviewSipp && menu === 'sipp' && subMenu === 'view') {
|
||||||
|
window.open(fileReviewSipp.filePath, '_blank')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function handleFilterApply(filters: { personName: string; startDate: string; endDate: string }) {
|
function handleFilterApply(filters: { personName: string; startDate: string; endDate: string }) {
|
||||||
filterParams.value = {
|
filterParams.value = {
|
||||||
'person-name': filters.personName,
|
// 'person-name': filters.personName,
|
||||||
|
'patient-identifier': filters.personName,
|
||||||
'start-date': filters.startDate,
|
'start-date': filters.startDate,
|
||||||
'end-date': filters.endDate,
|
'end-date': filters.endDate,
|
||||||
}
|
}
|
||||||
getPatientList()
|
getPatientList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleFilterReset() {
|
||||||
|
isFilterFormDialogOpen.value = false
|
||||||
|
filterParams.value = {}
|
||||||
|
getPatientList()
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleFilterSearch(filters: any) {
|
||||||
|
isFilterFormDialogOpen.value = false
|
||||||
|
filterParams.value = { ...filterParams.value, ...filters }
|
||||||
|
getPatientList()
|
||||||
|
}
|
||||||
|
|
||||||
// Handle confirmation result
|
// Handle confirmation result
|
||||||
async function handleConfirmCancel(record: any, action: string) {
|
async function handleConfirmCancel(record: any, action: string) {
|
||||||
if (action === 'deactivate' && record?.id) {
|
if (action === 'deactivate' && record?.id) {
|
||||||
@@ -263,23 +368,34 @@ function handleRemoveConfirmation() {
|
|||||||
<CH.ContentHeader v-bind="hreaderPrep">
|
<CH.ContentHeader v-bind="hreaderPrep">
|
||||||
<FilterNav
|
<FilterNav
|
||||||
:active-positon="activeServicePosition"
|
:active-positon="activeServicePosition"
|
||||||
|
:enable-export="false"
|
||||||
@apply="handleFilterApply"
|
@apply="handleFilterApply"
|
||||||
|
@click="() => (isFilterFormDialogOpen = true)"
|
||||||
@onExportPdf="() => {}"
|
@onExportPdf="() => {}"
|
||||||
@onExportExcel="() => {}"
|
@onExportExcel="() => {}"
|
||||||
@nExportCsv="() => {}"
|
@nExportCsv="() => {}"
|
||||||
/>
|
/>
|
||||||
</CH.ContentHeader>
|
</CH.ContentHeader>
|
||||||
|
|
||||||
<Content :data="data" />
|
<Content
|
||||||
|
:data="data"
|
||||||
|
:class-code="classCode"
|
||||||
|
/>
|
||||||
|
|
||||||
<!-- Filter -->
|
<!-- Filter -->
|
||||||
<Dialog
|
<Dialog
|
||||||
v-model:open="isFilterFormDialogOpen"
|
v-model:open="isFilterFormDialogOpen"
|
||||||
title="Filter"
|
title="Filter Data"
|
||||||
size="lg"
|
size="lg"
|
||||||
prevent-outside
|
prevent-outside
|
||||||
>
|
>
|
||||||
<FilterForm v-bind="filter" />
|
<FilterForm
|
||||||
|
:payments="payments"
|
||||||
|
:units="units"
|
||||||
|
:visits="sepsList"
|
||||||
|
@search="handleFilterSearch"
|
||||||
|
@reset="handleFilterReset"
|
||||||
|
/>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
|
||||||
<!-- Batal -->
|
<!-- Batal -->
|
||||||
@@ -340,4 +456,15 @@ function handleRemoveConfirmation() {
|
|||||||
>
|
>
|
||||||
Hak akses tidak memenuhi kriteria untuk proses ini.
|
Hak akses tidak memenuhi kriteria untuk proses ini.
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
|
||||||
|
<FileUpload
|
||||||
|
class="hidden"
|
||||||
|
field-name="uploadFile"
|
||||||
|
label="Dokumen"
|
||||||
|
placeholder="Pilih file"
|
||||||
|
:accept="['pdf', 'jpg', 'png']"
|
||||||
|
:max-size-mb="1"
|
||||||
|
v-model="uploadFile"
|
||||||
|
@file-selected="handleUploadFileSubmit"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ async function onFileChange(event: Event, handleChange: (value: any) => void) {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<DE.Cell>
|
<DE.Cell :class="class">
|
||||||
<DE.Label
|
<DE.Label
|
||||||
v-if="label !== ''"
|
v-if="label !== ''"
|
||||||
:label-for="fieldName"
|
:label-for="fieldName"
|
||||||
@@ -88,12 +88,13 @@ async function onFileChange(event: Event, handleChange: (value: any) => void) {
|
|||||||
<FormItem>
|
<FormItem>
|
||||||
<FormControl class="flex flex-col">
|
<FormControl class="flex flex-col">
|
||||||
<Input
|
<Input
|
||||||
@change="onFileChange($event, handleChange)"
|
:id="fieldName"
|
||||||
type="file"
|
type="file"
|
||||||
:disabled="isDisabled"
|
:disabled="isDisabled"
|
||||||
v-bind="{ onBlur: componentField.onBlur }"
|
v-bind="{ onBlur: componentField.onBlur }"
|
||||||
:placeholder="placeholder"
|
:placeholder="placeholder"
|
||||||
:class="cn('focus:border-primary focus:ring-2 focus:ring-primary focus:ring-offset-0')"
|
:class="cn('focus:border-primary focus:ring-2 focus:ring-primary focus:ring-offset-0')"
|
||||||
|
@change="onFileChange($event, handleChange)"
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
|
|||||||
@@ -539,7 +539,7 @@ export function useEncounterEntry(props: {
|
|||||||
class_code: props.classCode || '',
|
class_code: props.classCode || '',
|
||||||
subClass_code: props.subClassCode || '',
|
subClass_code: props.subClassCode || '',
|
||||||
infra_id: formValues.infra_id ?? null,
|
infra_id: formValues.infra_id ?? null,
|
||||||
unit_code: userStore?.user?.unit_code ?? null,
|
unit_code: formValues.unitCode ?? userStore?.user?.unit_code ?? null,
|
||||||
refSource_name: formValues.refSource_name ?? 'RSSA',
|
refSource_name: formValues.refSource_name ?? 'RSSA',
|
||||||
refTypeCode: formValues.paymentType === 'jkn' ? 'bpjs' : '',
|
refTypeCode: formValues.paymentType === 'jkn' ? 'bpjs' : '',
|
||||||
vclaimReference: vclaimReference.value ?? null,
|
vclaimReference: vclaimReference.value ?? null,
|
||||||
@@ -547,7 +547,7 @@ export function useEncounterEntry(props: {
|
|||||||
registeredAt: formatDate(registeredAtValue),
|
registeredAt: formatDate(registeredAtValue),
|
||||||
visitDate: formatDate(visitDateValue),
|
visitDate: formatDate(visitDateValue),
|
||||||
}
|
}
|
||||||
|
|
||||||
if (props.classCode !== 'inpatient') {
|
if (props.classCode !== 'inpatient') {
|
||||||
delete payload.infra_id
|
delete payload.infra_id
|
||||||
}
|
}
|
||||||
@@ -599,7 +599,7 @@ export function useEncounterEntry(props: {
|
|||||||
if (encounterId) {
|
if (encounterId) {
|
||||||
if (sepFile.value) {
|
if (sepFile.value) {
|
||||||
await uploadAttachmentCustom({
|
await uploadAttachmentCustom({
|
||||||
id: isEditMode.value && formValues.sepFileReview ? formValues.sepFileReview.id : null,
|
// id: isEditMode.value && formValues.sepFileReview ? formValues.sepFileReview.id : null,
|
||||||
file: sepFile.value,
|
file: sepFile.value,
|
||||||
refId: encounterId,
|
refId: encounterId,
|
||||||
entityTypeCode: 'encounter',
|
entityTypeCode: 'encounter',
|
||||||
@@ -608,7 +608,7 @@ export function useEncounterEntry(props: {
|
|||||||
}
|
}
|
||||||
if (sippFile.value) {
|
if (sippFile.value) {
|
||||||
await uploadAttachmentCustom({
|
await uploadAttachmentCustom({
|
||||||
id: isEditMode.value && formValues.sippFileReview ? formValues.sippFileReview.id : null,
|
// id: isEditMode.value && formValues.sippFileReview ? formValues.sippFileReview.id : null,
|
||||||
file: sippFile.value,
|
file: sippFile.value,
|
||||||
refId: encounterId,
|
refId: encounterId,
|
||||||
entityTypeCode: 'encounter',
|
entityTypeCode: 'encounter',
|
||||||
|
|||||||
@@ -27,6 +27,9 @@ export async function uploadAttachmentCustom(payload: any) {
|
|||||||
const { user } = useUserStore()
|
const { user } = useUserStore()
|
||||||
|
|
||||||
const formData = new FormData()
|
const formData = new FormData()
|
||||||
|
if (!payload.id && payload.name) {
|
||||||
|
formData.append('name', payload.name)
|
||||||
|
}
|
||||||
formData.append('content', payload.file)
|
formData.append('content', payload.file)
|
||||||
formData.append('entityType_code', payload.entityTypeCode)
|
formData.append('entityType_code', payload.entityTypeCode)
|
||||||
formData.append('type_code', payload.type)
|
formData.append('type_code', payload.type)
|
||||||
@@ -34,5 +37,5 @@ export async function uploadAttachmentCustom(payload: any) {
|
|||||||
formData.append('upload_employee_id', user.employee_id)
|
formData.append('upload_employee_id', user.employee_id)
|
||||||
|
|
||||||
const response = payload.id ? await update(payload.id, formData) : await create(formData)
|
const response = payload.id ? await update(payload.id, formData) : await create(formData)
|
||||||
return response?.body?.data
|
return response
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ export default defineEventHandler(async (event) => {
|
|||||||
let body: any
|
let body: any
|
||||||
if (['POST', 'PATCH', 'PUT', 'DELETE'].includes(method)) {
|
if (['POST', 'PATCH', 'PUT', 'DELETE'].includes(method)) {
|
||||||
if (headers['content-type']?.includes('multipart/form-data')) {
|
if (headers['content-type']?.includes('multipart/form-data')) {
|
||||||
body = await readBody(event)
|
body = await readRawBody(event, false) // false to get Buffer
|
||||||
} else {
|
} else {
|
||||||
body = await readBody(event)
|
body = await readBody(event)
|
||||||
forwardHeaders.set('Content-Type', 'application/json')
|
forwardHeaders.set('Content-Type', 'application/json')
|
||||||
|
|||||||
Reference in New Issue
Block a user