Feat: Add & integrate add, edit, detail page
This commit is contained in:
@@ -32,25 +32,30 @@ const {
|
||||
|
||||
const doctors = ref<Array<Item>>([])
|
||||
|
||||
async function fetchDpjp() {
|
||||
async function fetchDpjp(specialistId: string, subspecialistId: string) {
|
||||
doctors.value = await getDoctorLabelList({
|
||||
serviceType: 1,
|
||||
serviceDate: new Date().toISOString().substring(0, 10),
|
||||
specialistCode: 0,
|
||||
includes: 'employee-person',
|
||||
// "unit-id": parseInt(unitId),
|
||||
"specialist-id": parseInt(specialistId),
|
||||
"subspecialist-id": parseInt(subspecialistId),
|
||||
})
|
||||
}
|
||||
|
||||
const selectedDpjpId = inject<Ref<string | null>>("selectedDpjpId")!
|
||||
function handleDpjpChange(selected: string) {
|
||||
console.log(`change dphp`)
|
||||
selectedDpjpId.value = selected ?? null
|
||||
const dpjp = doctors.value.find(s => s.value === selectedDpjpId.value)
|
||||
console.log(dpjp)
|
||||
}
|
||||
// const selectedUnitId = inject<Ref<string | null>>("selectedUnitId")!
|
||||
const selectedSpecialistId = inject<Ref<string | null>>("selectedSpecialistId")!
|
||||
const selectedSubSpecialistId = inject<Ref<string | null>>("selectedSubSpecialistId")!
|
||||
|
||||
onMounted(() => {
|
||||
fetchDpjp()
|
||||
// function handleDpjpChange(selected: string) {
|
||||
// selectedDpjpId.value = selected ?? null
|
||||
// }
|
||||
|
||||
watch([ selectedSpecialistId, selectedSubSpecialistId], () => {
|
||||
if ( selectedSpecialistId.value && selectedSubSpecialistId.value) {
|
||||
fetchDpjp( selectedSpecialistId.value, selectedSubSpecialistId.value)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -82,7 +87,7 @@ onMounted(() => {
|
||||
:placeholder="placeholder"
|
||||
search-placeholder="Cari..."
|
||||
empty-message="Data tidak ditemukan"
|
||||
@update:model-value="handleDpjpChange"
|
||||
:is-disabled="selectedSubSpecialistId === null"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
|
||||
+17
-53
@@ -10,8 +10,7 @@ import { getValueLabelList as getSubspecialistLabelList } from '~/services/subsp
|
||||
import * as DE from '~/components/pub/my-ui/doc-entry'
|
||||
|
||||
const props = defineProps<{
|
||||
specialistFieldName?: string
|
||||
subSpecialistFieldName?: string
|
||||
fieldName?: string
|
||||
label?: string
|
||||
placeholder?: string
|
||||
errors?: FormErrors
|
||||
@@ -23,8 +22,7 @@ const props = defineProps<{
|
||||
}>()
|
||||
|
||||
const {
|
||||
specialistFieldName = 'job',
|
||||
subSpecialistFieldName = 'job',
|
||||
fieldName = 'job',
|
||||
label = 'Pekerjaan',
|
||||
placeholder = 'Pilih pekerjaan',
|
||||
errors,
|
||||
@@ -34,96 +32,62 @@ const {
|
||||
} = props
|
||||
|
||||
const specialists = ref<Array<Item>>([])
|
||||
const subspecialists = ref<Array<Item>>([])
|
||||
|
||||
async function fetchSpecialists() {
|
||||
async function fetchSpecialists(unitId: string) {
|
||||
specialists.value = await getSpecialistLabelList({
|
||||
serviceType: 1,
|
||||
serviceDate: new Date().toISOString().substring(0, 10),
|
||||
specialistCode: 0,
|
||||
})
|
||||
subspecialists.value = await getSubspecialistLabelList({
|
||||
serviceType: 1,
|
||||
serviceDate: new Date().toISOString().substring(0, 10),
|
||||
specialistCode: 0,
|
||||
"unit-id": parseInt(unitId),
|
||||
})
|
||||
}
|
||||
|
||||
const selectedUnitId = inject<Ref<string | null>>("selectedUnitId")!
|
||||
const selectedSpecialistId = inject<Ref<string | null>>("selectedSpecialistId")!
|
||||
|
||||
function handleSpecialistChange(selected: string) {
|
||||
selectedSpecialistId.value = selected ?? null
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
fetchSpecialists()
|
||||
watch([selectedUnitId], () => {
|
||||
if (selectedUnitId.value) {
|
||||
fetchSpecialists(selectedUnitId.value)
|
||||
}
|
||||
})
|
||||
console.log(selectedUnitId.value)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DE.Block :col-count="2" :class="cn('select-field-group', fieldGroupClass, containerClass)">
|
||||
<DE.Block :class="cn('select-field-group', fieldGroupClass, containerClass)">
|
||||
<div>
|
||||
<DE.Label
|
||||
:label-for="specialistFieldName"
|
||||
:label-for="fieldName"
|
||||
:class="cn('select-field-label', labelClass)"
|
||||
:is-required="isRequired"
|
||||
>
|
||||
Spesialis
|
||||
</DE.Label>
|
||||
<DE.Field
|
||||
:id="specialistFieldName"
|
||||
:id="fieldName"
|
||||
:errors="errors"
|
||||
:class="cn('select-field-wrapper')"
|
||||
>
|
||||
<FormField
|
||||
v-slot="{ componentField }"
|
||||
:name="specialistFieldName"
|
||||
:name="fieldName"
|
||||
>
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Combobox
|
||||
class="focus:ring-0 focus:ring-offset-0"
|
||||
:id="specialistFieldName"
|
||||
:id="fieldName"
|
||||
v-bind="componentField"
|
||||
:items="specialists"
|
||||
:placeholder="placeholder"
|
||||
search-placeholder="Cari..."
|
||||
empty-message="Data tidak ditemukan"
|
||||
@update:model-value="handleSpecialistChange"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</DE.Field>
|
||||
</div>
|
||||
<div>
|
||||
<DE.Label
|
||||
:label-for="subSpecialistFieldName"
|
||||
:class="cn('select-field-label', labelClass)"
|
||||
:is-required="isRequired"
|
||||
>
|
||||
Sub Spesialis
|
||||
</DE.Label>
|
||||
<DE.Field
|
||||
:id="subSpecialistFieldName"
|
||||
:errors="errors"
|
||||
:class="cn('select-field-wrapper')"
|
||||
>
|
||||
<FormField
|
||||
v-slot="{ componentField }"
|
||||
:name="subSpecialistFieldName"
|
||||
>
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Combobox
|
||||
class="focus:ring-0 focus:ring-offset-0"
|
||||
:id="subSpecialistFieldName"
|
||||
v-bind="componentField"
|
||||
:items="subspecialists"
|
||||
:placeholder="placeholder"
|
||||
search-placeholder="Cari..."
|
||||
empty-message="Data tidak ditemukan"
|
||||
:is-disabled="!selectedSpecialistId"
|
||||
:is-disabled="selectedUnitId === null"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
@@ -0,0 +1,97 @@
|
||||
<script setup lang="ts">
|
||||
import type { FormErrors } from '~/types/error'
|
||||
import Combobox from '~/components/pub/my-ui/combobox/combobox.vue'
|
||||
import { cn, mapToComboboxOptList } from '~/lib/utils'
|
||||
import { occupationCodes } from '~/lib/constants'
|
||||
import type { Item } from '~/components/pub/my-ui/combobox'
|
||||
import { getValueLabelList as getSubspecialistLabelList } from '~/services/subspecialist.service'
|
||||
|
||||
import * as DE from '~/components/pub/my-ui/doc-entry'
|
||||
|
||||
const props = defineProps<{
|
||||
fieldName?: string
|
||||
label?: string
|
||||
placeholder?: string
|
||||
errors?: FormErrors
|
||||
class?: string
|
||||
selectClass?: string
|
||||
fieldGroupClass?: string
|
||||
labelClass?: string
|
||||
isRequired?: boolean
|
||||
}>()
|
||||
|
||||
const {
|
||||
fieldName = 'job',
|
||||
label = 'Pekerjaan',
|
||||
placeholder = 'Pilih pekerjaan',
|
||||
errors,
|
||||
class: containerClass,
|
||||
fieldGroupClass,
|
||||
labelClass,
|
||||
} = props
|
||||
|
||||
const subspecialists = ref<Array<Item>>([])
|
||||
|
||||
async function fetchSubSpecialists(specialistId: string) {
|
||||
subspecialists.value = await getSubspecialistLabelList({
|
||||
serviceType: 1,
|
||||
serviceDate: new Date().toISOString().substring(0, 10),
|
||||
specialistCode: 0,
|
||||
"specialist-id": parseInt(specialistId),
|
||||
})
|
||||
}
|
||||
|
||||
const selectedSpecialistId = inject<Ref<string | null>>("selectedSpecialistId")!
|
||||
const selectedSubSpecialistId = inject<Ref<string | null>>("selectedSubSpecialistId")!
|
||||
|
||||
function handleSubSpecialistChange(selected: string) {
|
||||
selectedSubSpecialistId.value = selected ?? null
|
||||
}
|
||||
|
||||
watch([selectedSpecialistId], () => {
|
||||
if (selectedSpecialistId.value) {
|
||||
fetchSubSpecialists(selectedSpecialistId.value)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DE.Block :class="cn('select-field-group', fieldGroupClass, containerClass)">
|
||||
<div>
|
||||
<DE.Label
|
||||
:label-for="fieldName"
|
||||
:class="cn('select-field-label', labelClass)"
|
||||
:is-required="isRequired"
|
||||
>
|
||||
Sub Spesialis
|
||||
</DE.Label>
|
||||
<DE.Field
|
||||
:id="fieldName"
|
||||
:errors="errors"
|
||||
:class="cn('select-field-wrapper')"
|
||||
>
|
||||
<FormField
|
||||
v-slot="{ componentField }"
|
||||
:name="fieldName"
|
||||
>
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Combobox
|
||||
class="focus:ring-0 focus:ring-offset-0"
|
||||
:id="fieldName"
|
||||
v-bind="componentField"
|
||||
:items="subspecialists"
|
||||
:placeholder="placeholder"
|
||||
search-placeholder="Cari..."
|
||||
empty-message="Data tidak ditemukan"
|
||||
@update:model-value="handleSubSpecialistChange"
|
||||
:is-disabled="selectedSpecialistId === null"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</DE.Field>
|
||||
</div>
|
||||
</DE.Block>
|
||||
</template>
|
||||
@@ -0,0 +1,85 @@
|
||||
<script setup lang="ts">
|
||||
import type { FormErrors } from '~/types/error'
|
||||
import Combobox from '~/components/pub/my-ui/combobox/combobox.vue'
|
||||
import { cn, mapToComboboxOptList } from '~/lib/utils'
|
||||
import { occupationCodes } from '~/lib/constants'
|
||||
import { getValueLabelList as getUnitLabelList } from '~/services/unit.service'
|
||||
|
||||
import * as DE from '~/components/pub/my-ui/doc-entry'
|
||||
import type { Item } from '~/components/pub/my-ui/combobox'
|
||||
|
||||
const props = defineProps<{
|
||||
fieldName?: string
|
||||
label?: string
|
||||
placeholder?: string
|
||||
errors?: FormErrors
|
||||
class?: string
|
||||
selectClass?: string
|
||||
fieldGroupClass?: string
|
||||
labelClass?: string
|
||||
isRequired?: boolean
|
||||
}>()
|
||||
|
||||
const {
|
||||
fieldName = 'job',
|
||||
label = 'Pekerjaan',
|
||||
placeholder = 'Pilih pekerjaan',
|
||||
errors,
|
||||
class: containerClass,
|
||||
fieldGroupClass,
|
||||
labelClass,
|
||||
} = props
|
||||
|
||||
const units = ref<Array<Item>>([])
|
||||
|
||||
async function fetchData() {
|
||||
units.value = await getUnitLabelList()
|
||||
}
|
||||
|
||||
const selectedUnitId = inject<Ref<string | null>>("selectedUnitId")!
|
||||
function handleDataChange(selected: string) {
|
||||
selectedUnitId.value = selected ?? null
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
fetchData()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DE.Cell :class="cn('select-field-group', fieldGroupClass, containerClass)">
|
||||
<DE.Label
|
||||
:label-for="fieldName"
|
||||
:class="cn('select-field-label', labelClass)"
|
||||
:is-required="isRequired"
|
||||
>
|
||||
{{ label }}
|
||||
</DE.Label>
|
||||
<DE.Field
|
||||
:id="fieldName"
|
||||
:errors="errors"
|
||||
:class="cn('select-field-wrapper')"
|
||||
>
|
||||
<FormField
|
||||
v-slot="{ componentField }"
|
||||
:name="fieldName"
|
||||
>
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Combobox
|
||||
class="focus:ring-0 focus:ring-offset-0"
|
||||
:id="fieldName"
|
||||
v-bind="componentField"
|
||||
:items="units"
|
||||
:placeholder="placeholder"
|
||||
search-placeholder="Cari..."
|
||||
empty-message="Data tidak ditemukan"
|
||||
@update:model-value="handleDataChange"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</DE.Field>
|
||||
</DE.Cell>
|
||||
</template>
|
||||
@@ -4,15 +4,22 @@ 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 SelectSpeciality from './_common/select-speciality.vue'
|
||||
import SelectSpeciality from './_common/select-specialist.vue'
|
||||
import SelectDpjp from './_common/select-dpjp.vue'
|
||||
|
||||
import * as DE from '~/components/pub/my-ui/doc-entry'
|
||||
import SelectUnit from './_common/select-unit.vue'
|
||||
import SelectSubspecialist from './_common/select-subspecialist.vue'
|
||||
import SelectSpecialist from './_common/select-specialist.vue'
|
||||
|
||||
const props = defineProps<{
|
||||
schema: any
|
||||
initialValues?: any
|
||||
errors?: FormErrors
|
||||
|
||||
selectedUnitId?: number | null
|
||||
selectedSpecialistId?: number | null
|
||||
selectedSubSpecialistId?: number | null
|
||||
}>()
|
||||
|
||||
const formSchema = toTypedSchema(props.schema)
|
||||
@@ -50,21 +57,38 @@ defineExpose({
|
||||
:errors="errors"
|
||||
is-required
|
||||
/>
|
||||
<SelectSpeciality
|
||||
specialist-field-name="spesialist_id"
|
||||
sub-specialist-field-name="subspesialist_id"
|
||||
label="Spesialis/Sub Spesialis"
|
||||
placeholder="Pilih Spesialis/Sub Spesialis"
|
||||
:errors="errors"
|
||||
is-required
|
||||
/>
|
||||
<SelectDpjp
|
||||
field-name="doctor_id"
|
||||
label="DPJP"
|
||||
placeholder="Pilih DPJP"
|
||||
:errors="errors"
|
||||
is-required
|
||||
/>
|
||||
<DE.Cell :col-span="2">
|
||||
<DE.Block :col-count="4" :cell-flex="false">
|
||||
<SelectUnit
|
||||
field-name="unit_id"
|
||||
label="Unit"
|
||||
placeholder="Pilih Unit"
|
||||
:errors="errors"
|
||||
is-required
|
||||
/>
|
||||
<SelectSpecialist
|
||||
field-name="specialist_id"
|
||||
label="Spesialis/Sub Spesialis"
|
||||
placeholder="Pilih Spesialis/Sub Spesialis"
|
||||
:errors="errors"
|
||||
is-required
|
||||
/>
|
||||
<SelectSubspecialist
|
||||
field-name="subspecialist_id"
|
||||
label="Spesialis/Sub Spesialis"
|
||||
placeholder="Pilih Spesialis/Sub Spesialis"
|
||||
:errors="errors"
|
||||
is-required
|
||||
/>
|
||||
<SelectDpjp
|
||||
field-name="doctor_id"
|
||||
label="DPJP"
|
||||
placeholder="Pilih DPJP"
|
||||
:errors="errors"
|
||||
is-required
|
||||
/>
|
||||
</DE.Block>
|
||||
</DE.Cell>
|
||||
</DE.Block>
|
||||
</Form>
|
||||
</template>
|
||||
|
||||
@@ -1,23 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
import type { Patient } from '~/models/patient'
|
||||
import DetailRow from '~/components/pub/my-ui/form/view/detail-row.vue'
|
||||
import DetailSection from '~/components/pub/my-ui/form/view/detail-section.vue'
|
||||
import { formatAddress } from '~/models/person-address'
|
||||
|
||||
import {
|
||||
addressLocationTypeCode,
|
||||
educationCodes,
|
||||
genderCodes,
|
||||
occupationCodes,
|
||||
personContactTypes,
|
||||
relationshipCodes,
|
||||
religionCodes,
|
||||
} from '~/lib/constants'
|
||||
import { cn, mapToComboboxOptList } from '~/lib/utils'
|
||||
import { cn, } from '~/lib/utils'
|
||||
import type { ControlLetter } from '~/models/control-letter'
|
||||
|
||||
// #region Props & Emits
|
||||
const props = defineProps<{
|
||||
patient: Patient
|
||||
instance: ControlLetter | null
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
@@ -27,39 +15,9 @@ const emit = defineEmits<{
|
||||
// #endregion
|
||||
|
||||
// #region State & Computed
|
||||
const genderOptions = mapToComboboxOptList(genderCodes)
|
||||
const religionOptions = mapToComboboxOptList(religionCodes)
|
||||
const educationOptions = mapToComboboxOptList(educationCodes)
|
||||
const occupationOptions = mapToComboboxOptList(occupationCodes)
|
||||
const relationshipOptions = mapToComboboxOptList(relationshipCodes)
|
||||
const personContactTypeOptions = mapToComboboxOptList(personContactTypes)
|
||||
// #endregion
|
||||
|
||||
// Computed addresses from nested data
|
||||
const domicileAddress = computed(() => {
|
||||
const addresses = props.patient.person.addresses
|
||||
const resident = addresses?.find((addr) => addr.locationType_code === 'domicile')
|
||||
return formatAddress(resident)
|
||||
})
|
||||
|
||||
const identityAddress = computed(() => {
|
||||
const addresses = props.patient.person.addresses
|
||||
const primary = addresses?.find((addr) => addr.locationType_code === 'identity')
|
||||
return formatAddress(primary)
|
||||
})
|
||||
|
||||
const patientAge = computed(() => {
|
||||
if (!props.patient.person.birthDate) {
|
||||
return '-'
|
||||
}
|
||||
const birthDate = new Date(props.patient.person.birthDate)
|
||||
const today = new Date()
|
||||
let age = today.getFullYear() - birthDate.getFullYear()
|
||||
const monthDiff = today.getMonth() - birthDate.getMonth()
|
||||
if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) {
|
||||
age--
|
||||
}
|
||||
return age
|
||||
})
|
||||
// #endregion
|
||||
|
||||
// #region Lifecycle Hooks
|
||||
@@ -81,10 +39,12 @@ function onClick(type: string) {
|
||||
|
||||
<template>
|
||||
<div :class="cn('min-h-[50vh] space-y-2',)">
|
||||
<DetailRow label="Tgl Rencana Kontrol">{{ patient.number || '-' }}</DetailRow>
|
||||
<DetailRow label="Spesialis/Sub Spesialis">{{ patient.number || '-' }}</DetailRow>
|
||||
<DetailRow label="DPJP">{{ patient.number || '-' }}</DetailRow>
|
||||
<DetailRow label="Status SEP">{{ patient.number || '-' }}</DetailRow>
|
||||
<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" />
|
||||
|
||||
@@ -23,8 +23,10 @@ const controlLetterForm = ref<ExposedForm<any> | null>(null)
|
||||
// #region State & Computed
|
||||
const router = useRouter()
|
||||
const isConfirmationOpen = ref(false)
|
||||
|
||||
const selectedUnitId = ref<number|null>(null)
|
||||
const selectedSpecialistId = ref<number|null>(null)
|
||||
const selectedDpjpId = ref<number|null>(null)
|
||||
const selectedSubSpecialistId = ref<number|null>(null)
|
||||
// #endregion
|
||||
|
||||
// #region Lifecycle Hooks
|
||||
@@ -95,8 +97,9 @@ function handleCancelAdd() {
|
||||
isConfirmationOpen.value = false
|
||||
}
|
||||
|
||||
provide("selectedUnitId", selectedUnitId);
|
||||
provide("selectedSpecialistId", selectedSpecialistId);
|
||||
provide("selectedDpjpId", selectedDpjpId);
|
||||
provide("selectedSubSpecialistId", selectedSubSpecialistId);
|
||||
// #endregion
|
||||
|
||||
// #region Watchers
|
||||
@@ -107,7 +110,11 @@ provide("selectedDpjpId", selectedDpjpId);
|
||||
<div class="mb-5 border-b border-b-slate-300 pb-3 text-lg font-semibold xl:text-xl">Tambah Surat Kontrol</div>
|
||||
<AppOutpatientEncounterEntryForm
|
||||
ref="controlLetterForm"
|
||||
:schema="ControlLetterSchema" />
|
||||
:schema="ControlLetterSchema"
|
||||
:selected-unit-id="selectedUnitId"
|
||||
:selected-specialist-id="selectedSpecialistId"
|
||||
:selected-sub-specialist-id="selectedSubSpecialistId"
|
||||
/>
|
||||
|
||||
<div class="my-2 flex justify-end py-2">
|
||||
<Action :enable-draft="false" @click="handleActionClick" />
|
||||
|
||||
@@ -8,24 +8,22 @@ import { getDetail } from '~/services/control-letter.service'
|
||||
|
||||
// Components
|
||||
import Header from '~/components/pub/my-ui/nav-header/prep.vue'
|
||||
import type { ControlLetter } from '~/models/control-letter'
|
||||
|
||||
// #region Props & Emits
|
||||
const props = defineProps<{
|
||||
patientId: number
|
||||
}>()
|
||||
|
||||
// #endregion
|
||||
|
||||
// #region State & Computed
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const patient = ref(
|
||||
withBase<Patient>({
|
||||
person: {} as Person,
|
||||
personAddresses: [],
|
||||
personContacts: [],
|
||||
personRelatives: [],
|
||||
}),
|
||||
)
|
||||
const encounterId = typeof route.params.id == 'string' ? parseInt(route.params.id) : 0
|
||||
const controlLetterId = typeof route.params.control_letter_id == 'string' ? parseInt(route.params.control_letter_id) : 0
|
||||
|
||||
const controlLetter = ref<ControlLetter | null>(null)
|
||||
|
||||
const headerPrep: HeaderPrep = {
|
||||
title: 'Detail Surat Kontrol',
|
||||
@@ -36,10 +34,9 @@ const headerPrep: HeaderPrep = {
|
||||
|
||||
// #region Lifecycle Hooks
|
||||
onMounted(async () => {
|
||||
// await getPatientDetail()
|
||||
const result = await getPatientDetail(props.patientId)
|
||||
const result = await getDetail(controlLetterId)
|
||||
if (result.success) {
|
||||
patient.value = result.body.data || {}
|
||||
controlLetter.value = result.body?.data
|
||||
}
|
||||
})
|
||||
// #endregion
|
||||
@@ -56,7 +53,10 @@ function handleAction(type: string) {
|
||||
switch (type) {
|
||||
case 'edit':
|
||||
// TODO: Handle edit action
|
||||
console.log('outpatient-encounter-id-edit')
|
||||
navigateTo({
|
||||
name: 'rehab-encounter-id-control-letter-control_letter_id-edit',
|
||||
params: { id: encounterId, "control_letter_id": controlLetterId },
|
||||
})
|
||||
break
|
||||
|
||||
case 'cancel':
|
||||
@@ -73,5 +73,5 @@ function handleAction(type: string) {
|
||||
<template>
|
||||
<Header :prep="headerPrep" :ref-search-nav="headerPrep.refSearchNav" />
|
||||
|
||||
<AppOutpatientEncounterPreview :patient="patient" @click="handleAction" />
|
||||
<AppOutpatientEncounterPreview :instance="controlLetter" @click="handleAction" />
|
||||
</template>
|
||||
|
||||
@@ -22,45 +22,51 @@ import {
|
||||
isRecordConfirmationOpen,
|
||||
onResetState,
|
||||
handleActionSave,
|
||||
handleCancelForm,
|
||||
} from '~/handlers/patient.handler'
|
||||
handleActionEdit,
|
||||
} from '~/handlers/control-letter.handler'
|
||||
|
||||
import { toast } from '~/components/pub/ui/toast'
|
||||
import { getPatientDetail } from '~/services/patient.service'
|
||||
import { withBase } from '~/models/_base'
|
||||
import type { Person } from '~/models/person'
|
||||
import Confirmation from '~/components/pub/my-ui/confirmation/confirmation.vue'
|
||||
import type { ControlLetter } from '~/models/control-letter'
|
||||
import { ControlLetterSchema } from '~/schemas/control-letter.schema'
|
||||
import { formatDateYyyyMmDd } from '~/lib/date'
|
||||
|
||||
// #region Props & Emits
|
||||
const props = defineProps<{
|
||||
callbackUrl?: string
|
||||
patientId: number
|
||||
}>()
|
||||
|
||||
// form related state
|
||||
const personPatientForm = ref<ExposedForm<any> | null>(null)
|
||||
|
||||
const controlLetterForm = ref<ExposedForm<any> | null>(null)
|
||||
// #endregion
|
||||
|
||||
// #region State & Computed
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const encounterId = typeof route.params.id == 'string' ? parseInt(route.params.id) : 0
|
||||
const controlLetterId = typeof route.params.control_letter_id == 'string' ? parseInt(route.params.control_letter_id) : 0
|
||||
|
||||
const isConfirmationOpen = ref(false)
|
||||
const patient = ref(
|
||||
withBase<Patient>({
|
||||
person: {} as Person,
|
||||
personAddresses: [],
|
||||
personContacts: [],
|
||||
personRelatives: [],
|
||||
}),
|
||||
)
|
||||
const controlLetter = ref({})
|
||||
|
||||
const selectedUnitId = ref<number|null>(null)
|
||||
const selectedSpecialistId = ref<number|null>(null)
|
||||
const selectedSubSpecialistId = ref<number|null>(null)
|
||||
// #endregion
|
||||
|
||||
// #region Lifecycle Hooks
|
||||
onMounted(async () => {
|
||||
// await getPatientDetail()
|
||||
const result = await getPatientDetail(props.patientId)
|
||||
const result = await getDetail(controlLetterId)
|
||||
if (result.success) {
|
||||
patient.value = result.body.data || {}
|
||||
const responseData = {...result.body.data, date: formatDateYyyyMmDd(result.body.data.date)}
|
||||
selectedUnitId.value = responseData?.unit_id
|
||||
selectedSpecialistId.value = responseData?.specialist_id
|
||||
selectedSubSpecialistId.value = responseData?.subspecialist_id
|
||||
|
||||
controlLetter.value = responseData
|
||||
controlLetterForm.value?.setValues(responseData)
|
||||
}
|
||||
})
|
||||
// #endregion
|
||||
@@ -71,12 +77,30 @@ function goBack() {
|
||||
}
|
||||
|
||||
async function handleConfirmAdd() {
|
||||
// handleActionClick('submit')
|
||||
console.log(`tersubmit wak`)
|
||||
const response = await handleActionEdit(
|
||||
controlLetterId,
|
||||
await composeFormData(),
|
||||
() => { },
|
||||
() => { },
|
||||
toast,
|
||||
)
|
||||
goBack()
|
||||
}
|
||||
|
||||
function handleCancelAdd() {
|
||||
isConfirmationOpen.value = false
|
||||
async function composeFormData(): Promise<ControlLetter> {
|
||||
const [controlLetter,] = await Promise.all([
|
||||
controlLetterForm.value?.validate(),
|
||||
])
|
||||
|
||||
const results = [controlLetter]
|
||||
const allValid = results.every((r) => r?.valid)
|
||||
|
||||
// exit, if form errors happend during validation
|
||||
if (!allValid) return Promise.reject('Form validation failed')
|
||||
|
||||
const formData = controlLetter?.values
|
||||
formData.encounter_id = encounterId
|
||||
return new Promise((resolve) => resolve(formData))
|
||||
}
|
||||
// #endregion region
|
||||
|
||||
@@ -84,29 +108,6 @@ function handleCancelAdd() {
|
||||
async function handleActionClick(eventType: string) {
|
||||
if (eventType === 'submit') {
|
||||
isConfirmationOpen.value = true
|
||||
// const patient: Patient = await composeFormData()
|
||||
// let createdPatientId = 0
|
||||
|
||||
// const response = await handleActionSave(
|
||||
// patient,
|
||||
// () => {},
|
||||
// () => {},
|
||||
// toast,
|
||||
// )
|
||||
|
||||
// const data = (response?.body?.data ?? null) as PatientBase | null
|
||||
// if (!data) return
|
||||
// createdPatientId = data.id
|
||||
|
||||
// // If has callback provided redirect to callback with patientData
|
||||
// if (props.callbackUrl) {
|
||||
// await navigateTo(props.callbackUrl + '?patient-id=' + patient.id)
|
||||
// return
|
||||
// }
|
||||
|
||||
// // Navigate to patient list or show success message
|
||||
// await navigateTo('/outpatient/encounter')
|
||||
// return
|
||||
}
|
||||
|
||||
if (eventType === 'cancel') {
|
||||
@@ -116,9 +117,16 @@ async function handleActionClick(eventType: string) {
|
||||
}
|
||||
|
||||
goBack()
|
||||
// handleCancelForm()
|
||||
}
|
||||
}
|
||||
|
||||
function handleCancelAdd() {
|
||||
isConfirmationOpen.value = false
|
||||
}
|
||||
|
||||
provide("selectedUnitId", selectedUnitId);
|
||||
provide("selectedSpecialistId", selectedSpecialistId);
|
||||
provide("selectedSubSpecialistId", selectedSubSpecialistId);
|
||||
// #endregion
|
||||
|
||||
// #region Watchers
|
||||
@@ -128,8 +136,11 @@ async function handleActionClick(eventType: string) {
|
||||
<template>
|
||||
<div class="mb-5 border-b border-b-slate-300 pb-3 text-lg font-semibold xl:text-xl">Update Surat Kontrol</div>
|
||||
<AppOutpatientEncounterEntryForm
|
||||
ref="personPatientForm"
|
||||
:schema="PatientSchema"
|
||||
ref="controlLetterForm"
|
||||
:schema="ControlLetterSchema"
|
||||
:selected-unit-id="selectedUnitId"
|
||||
:selected-specialist-id="selectedSpecialistId"
|
||||
:selected-sub-specialist-id="selectedSubSpecialistId"
|
||||
/>
|
||||
|
||||
<div class="my-2 flex justify-end py-2">
|
||||
|
||||
@@ -107,8 +107,8 @@ watch([recId, recAction], () => {
|
||||
switch (recAction.value) {
|
||||
case ActionEvents.showDetail:
|
||||
navigateTo({
|
||||
name: 'outpatient-encounter-id',
|
||||
params: { id: recId.value },
|
||||
name: 'rehab-encounter-id-control-letter-control_letter_id',
|
||||
params: { id: encounterId, "control_letter_id": recId.value },
|
||||
})
|
||||
break
|
||||
|
||||
@@ -116,8 +116,8 @@ watch([recId, recAction], () => {
|
||||
// TODO: Handle edit action
|
||||
// isFormEntryDialogOpen.value = true
|
||||
navigateTo({
|
||||
name: 'outpatient-encounter-id-edit',
|
||||
params: { id: recId.value },
|
||||
name: 'rehab-encounter-id-control-letter-control_letter_id-edit',
|
||||
params: { id: encounterId, "control_letter_id": recId.value },
|
||||
})
|
||||
break
|
||||
|
||||
|
||||
@@ -41,4 +41,12 @@ export function getAge(dateString: string, comparedDate?: string): { idFormat: s
|
||||
idFormat,
|
||||
extFormat
|
||||
};
|
||||
}
|
||||
|
||||
export function formatDateYyyyMmDd(isoDateString: string): string {
|
||||
const date = new Date(isoDateString);
|
||||
const year = date.getFullYear();
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(date.getDate()).padStart(2, '0');
|
||||
return `${year}-${month}-${day}`;
|
||||
}
|
||||
@@ -1,18 +1,37 @@
|
||||
import { type Base, genBase } from "./_base"
|
||||
import { genDoctor, type Doctor } from "./doctor"
|
||||
import { genEncounter, type Encounter } from "./encounter"
|
||||
import { genSpecialist, type Specialist } from "./specialist"
|
||||
import { genSubspecialist, type Subspecialist } from "./subspecialist"
|
||||
import { genUnit, type Unit } from "./unit"
|
||||
|
||||
export interface ControlLetter extends Base {
|
||||
sep_status: string
|
||||
control_plan_date: string
|
||||
specialist_sub_specialist_id: string
|
||||
dpjp_id: string
|
||||
encounter_id: number
|
||||
encounter: Encounter
|
||||
unit_id: number
|
||||
unit: Unit
|
||||
specialist_id: number
|
||||
specialist: Specialist
|
||||
subspecialist_id: number
|
||||
subspecialist: Subspecialist
|
||||
doctor_id: number
|
||||
doctor: Doctor
|
||||
date: ''
|
||||
}
|
||||
|
||||
export function genControlLetter(): ControlLetter {
|
||||
return {
|
||||
...genBase(),
|
||||
sep_status: '',
|
||||
control_plan_date: '',
|
||||
specialist_sub_specialist_id: '',
|
||||
dpjp_id: '',
|
||||
encounter_id: 0,
|
||||
encounter: genEncounter(),
|
||||
unit_id: 0,
|
||||
unit: genUnit(),
|
||||
specialist_id: 0,
|
||||
specialist: genSpecialist(),
|
||||
subspecialist_id: 0,
|
||||
subspecialist: genSubspecialist(),
|
||||
doctor_id: 0,
|
||||
doctor: genDoctor(),
|
||||
date: ''
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
<script setup lang="ts">
|
||||
import type { PagePermission } from '~/models/role'
|
||||
import Error from '~/components/pub/my-ui/error/error.vue'
|
||||
import { PAGE_PERMISSIONS } from '~/lib/page-permission'
|
||||
|
||||
definePageMeta({
|
||||
middleware: ['rbac'],
|
||||
roles: ['doctor', 'nurse', 'admisi', 'pharmacy', 'billing', 'management'],
|
||||
title: 'Update Surat Kontrol',
|
||||
contentFrame: 'cf-full-width',
|
||||
})
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
useHead({
|
||||
title: () => route.meta.title as string,
|
||||
})
|
||||
|
||||
const roleAccess: PagePermission = PAGE_PERMISSIONS['/patient']
|
||||
|
||||
const { checkRole, hasReadAccess } = useRBAC()
|
||||
|
||||
// Check if user has access to this page
|
||||
const hasAccess = checkRole(roleAccess)
|
||||
// if (!hasAccess) {
|
||||
// navigateTo('/403')
|
||||
// }
|
||||
|
||||
// Define permission-based computed properties
|
||||
// const canRead = hasReadAccess(roleAccess)
|
||||
const canRead = true
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div v-if="canRead">
|
||||
<ContentOutpatientEncounterEdit />
|
||||
</div>
|
||||
<Error v-else :status-code="403" />
|
||||
</div>
|
||||
</template>
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
<script setup lang="ts">
|
||||
import type { PagePermission } from '~/models/role'
|
||||
import Error from '~/components/pub/my-ui/error/error.vue'
|
||||
import { PAGE_PERMISSIONS } from '~/lib/page-permission'
|
||||
|
||||
definePageMeta({
|
||||
middleware: ['rbac'],
|
||||
roles: ['doctor', 'nurse', 'admisi', 'pharmacy', 'billing', 'management'],
|
||||
title: 'Detail Surat Kontrol',
|
||||
contentFrame: 'cf-container-md',
|
||||
})
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
useHead({
|
||||
title: () => route.meta.title as string,
|
||||
})
|
||||
|
||||
const roleAccess: PagePermission = PAGE_PERMISSIONS['/patient']
|
||||
|
||||
const { checkRole, hasReadAccess } = useRBAC()
|
||||
|
||||
// Check if user has access to this page
|
||||
const hasAccess = checkRole(roleAccess)
|
||||
// if (!hasAccess) {
|
||||
// navigateTo('/403')
|
||||
// }
|
||||
|
||||
// Define permission-based computed properties
|
||||
// const canRead = hasReadAccess(roleAccess)
|
||||
const canRead = true
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div v-if="canRead">
|
||||
<ContentOutpatientEncounterDetail :patient-id="Number(route.params.id)" />
|
||||
</div>
|
||||
<Error v-else :status-code="403" />
|
||||
</div>
|
||||
</template>
|
||||
@@ -4,17 +4,19 @@ const ControlLetterSchema = z.object({
|
||||
sepStatus: z.string({
|
||||
required_error: 'Mohon isi status SEP',
|
||||
}).default('SEP Internal'),
|
||||
spesialist_id: z.number({
|
||||
required_error: 'Mohon isi Spesialis/Sub Spesialis',
|
||||
unit_id: z.number({
|
||||
required_error: 'Mohon isi Unit',
|
||||
}),
|
||||
subspesialist_id: z.number({
|
||||
required_error: 'Mohon isi Spesialis/Sub Spesialis',
|
||||
specialist_id: z.number({
|
||||
required_error: 'Mohon isi Spesialis',
|
||||
}),
|
||||
subspecialist_id: z.number({
|
||||
required_error: 'Mohon isi Sub Spesialis',
|
||||
}),
|
||||
doctor_id: z.number({
|
||||
required_error: 'Mohon isi DPJP',
|
||||
}),
|
||||
encounter_id: z.number().optional(),
|
||||
unit_id: z.number().optional(),
|
||||
date: z.string({
|
||||
required_error: 'Mohon lengkapi Tanggal Kontrol',
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user