Files
hasyim_kai 1dd8e8e7b3 Squashed commit of the following:
commit 72ce2260c50597f782f07d29db3985607ecc2f34
Author: hasyim_kai <muhammad.hasyim.c.a@gmail.com>
Date:   Mon Nov 17 15:19:36 2025 +0700

    Feat: add doc preview in Therpay protocol List

commit 7032cd2409a660d40899ffd421137e4158cfde4a
Author: hasyim_kai <muhammad.hasyim.c.a@gmail.com>
Date:   Wed Nov 12 15:34:30 2025 +0700

    Fix: prepare API integration protokol terapi verification

commit dbf6f78d00afc818baf2b34d128ee2153814cc88
Author: hasyim_kai <muhammad.hasyim.c.a@gmail.com>
Date:   Wed Nov 12 14:09:28 2025 +0700

    Feat: add basic CRUD therapy protocol

commit 46a44e90fe4d4097b5460d2d4e5689b2a5389467
Author: hasyim_kai <muhammad.hasyim.c.a@gmail.com>
Date:   Tue Nov 11 15:57:54 2025 +0700

    Fix: Prepare protokol terapi API Integration

commit 4674090566727cebd947e50e2c06c44e8c7afa7e
Author: hasyim_kai <muhammad.hasyim.c.a@gmail.com>
Date:   Mon Nov 10 15:33:22 2025 +0700

    Fix: hotfix style add protokol terapi

commit 919c91abd8ef8b4cd193012eed7f5e8cf635cda2
Author: hasyim_kai <muhammad.hasyim.c.a@gmail.com>
Date:   Mon Nov 10 15:17:14 2025 +0700

    Fix: Typo drpodown-action-p in protokol-terapi

commit e21d30eacf1a08118e289d4bb64889e708d5023a
Author: hasyim_kai <muhammad.hasyim.c.a@gmail.com>
Date:   Mon Nov 10 15:14:33 2025 +0700

    Fix: add diagnose & procedure dialog picker in add protokol terapi

commit 9a3d73b72b0dceea778d83e7630c5ead110a6a4c
Author: hasyim_kai <muhammad.hasyim.c.a@gmail.com>
Date:   Tue Nov 4 10:21:24 2025 +0700

    Fix: Add Schema therapy protocol rehab medik

commit 4d8d2d633bbbd78038b1cc607558c1ceb31c5986
Author: hasyim_kai <muhammad.hasyim.c.a@gmail.com>
Date:   Tue Nov 4 09:30:55 2025 +0700

    Fix: refactor Actions Btn ba-dr-su

commit 5f290a6e4bd1559c0e5864a508c5ab650cfae6e8
Author: hasyim_kai <muhammad.hasyim.c.a@gmail.com>
Date:   Mon Nov 3 17:08:20 2025 +0700

    Feat: UI protokol terapi in Rehab medik

commit 63010f69ff30532bb8ac91443112f31d4942b221
Author: Khafid Prayoga <khafidp@pm.me>
Date:   Tue Oct 21 09:54:13 2025 +0700

    wip: list protokol terapi

commit 44eedc298680a5255fee0ee8feee3e24beda93dd
Author: Khafid Prayoga <khafidp@pm.me>
Date:   Mon Oct 20 12:54:01 2025 +0700

    feat(therapy-protocol): init form entry

    feat(therapy-protocol): init page routes

    wip: init entry form

    wip: form entry protokol terapi

    todo: table procedure, and diagnose  picker

    wip: schema form new entry

    todo: picker/modal yang relateds ke form entry
2025-11-25 09:23:57 +07:00

262 lines
7.6 KiB
Vue

<script setup lang="ts">
import type { HeaderPrep, RefSearchNav } from '~/components/pub/my-ui/data/types'
import type { Summary } from '~/components/pub/my-ui/summary-card/type'
// #region Imports
import { Calendar, Hospital, UserCheck, UsersRound } from 'lucide-vue-next'
import RecordConfirmation from '~/components/pub/my-ui/confirmation/record-confirmation.vue'
import { ActionEvents } from '~/components/pub/my-ui/data/types'
import Header from '~/components/pub/my-ui/nav-header/prep.vue'
import SummaryCard from '~/components/pub/my-ui/summary-card/summary-card.vue'
import { usePaginatedList } from '~/composables/usePaginatedList'
import { getList, remove } from '~/services/therapy-protocol.service'
import DetailRow from '~/components/pub/my-ui/form/view/detail-row.vue'
import Dialog from '~/components/pub/my-ui/modal/dialog.vue'
import Action from '~/components/pub/my-ui/nav-footer/ba-dr-su.vue'
import type { Encounter } from '~/models/encounter'
import { cn } from '~/lib/utils'
import { CalendarDate, DateFormatter, getLocalTimeZone } from '@internationalized/date'
import type { DateRange } from 'radix-vue'
import type { ExposedForm } from '~/types/form'
import { VerificationSchema } from '~/schemas/verification.schema'
import { handleActionSave } from '~/handlers/therapy-protocol.handler'
import { toast } from '~/components/pub/ui/toast'
import DocPreviewDialog from '~/components/pub/my-ui/modal/doc-preview-dialog.vue'
// #endregion
// Props
interface Props {
encounter: Encounter
}
const props = defineProps<Props>()
const route = useRoute()
const encounterId = typeof route.params.id == 'string' ? parseInt(route.params.id) : 0
// #endregion
// #region State
const isVerifyDialogOpen = ref(false)
const isHistoryDialogOpen = ref(false)
const isPatientInTherapy = ref(false)
const { data, isLoading, paginationMeta, searchInput, handlePageChange, handleSearch, fetchData } = usePaginatedList({
fetchFn: (params) => getList({ ...params }),
entityName: 'therapy-protocol',
})
const df = new DateFormatter('en-US', {
dateStyle: 'medium',
})
const dateValue = ref({
start: new CalendarDate(2022, 1, 20),
end: new CalendarDate(2022, 1, 20).add({ days: 20 }),
}) as Ref<DateRange>
const isRecordConfirmationOpen = ref(false)
const isDocPreviewDialogOpen = ref(false)
const summaryLoading = ref(false)
const inputForm = ref<ExposedForm<any> | null>(null)
const recId = ref<number>(0)
const recAction = ref<string>('')
const recItem = ref<any>(null)
const timestamp = ref<number>(0)
const isCaptchaValid = ref(false)
provide('isCaptchaValid', isCaptchaValid)
const headerPrep: HeaderPrep = {
title: "Protokol Terapi",
icon: 'i-lucide-newspaper',
addNav: {
label: "Protokol Terapi",
onClick: () => navigateTo({
name: 'rehab-encounter-id-therapy-protocol-add',
}),
},
}
// #endregion
// #region Lifecycle Hooks
onMounted(() => {
getPatientSummary()
const isInTherapy = false // TODO: determine if patient is in therapy
handleIsPatientInTherapy(isInTherapy)
})
// #endregion
// #region Functions
function handleIsPatientInTherapy(value: boolean) {
if (value) {
isPatientInTherapy.value = true
} else {
isPatientInTherapy.value = false
}
}
async function handleOpenHistory() {
isHistoryDialogOpen.value = true
console.log(`jalan history`)
}
async function getPatientSummary() {
try {
summaryLoading.value = true
await new Promise((resolve) => setTimeout(resolve, 500))
} catch (error) {
console.error('Error fetching patient summary:', error)
} finally {
summaryLoading.value = false
}
}
async function handleVerify() {
isVerifyDialogOpen.value = true
}
async function handleConfirmVerify() {
const inputData: any = await composeFormData()
const response = await handleActionSave(
inputData,
() => { },
() => { },
toast,
)
const data = (response?.body?.data ?? null)
if (!data) return
isVerifyDialogOpen.value = false
}
async function composeFormData(): Promise<any> {
const [input,] = await Promise.all([
inputForm.value?.validate(),
])
const results = [input]
const allValid = results.every((r) => r?.valid)
// exit, if form errors happend during validation
if (!allValid) return Promise.reject('Form validation failed')
const formData = input?.values
// formData.encounter_id = encounterId
return new Promise((resolve) => resolve(formData))
}
// #endregion region
// #region Utilities & event handlers
async function handleActionClick(eventType: string) {
if (eventType === 'submit') {
handleConfirmVerify()
}
if (eventType === 'back') {
isVerifyDialogOpen.value = false
}
}
// #endregion
// #region Provide
provide('rec_id', recId)
provide('rec_action', recAction)
provide('rec_item', recItem)
provide('timestamp', timestamp)
provide('table_data_loader', isLoading)
// #endregion
// #region Watchers
watch([recId, recAction, timestamp], () => {
switch (recAction.value) {
case ActionEvents.showDetail:
navigateTo({
name: 'therapy-protocol-id-detail',
params: { id: recId.value },
})
break
case ActionEvents.showEdit:
navigateTo({
name: 'rehab-encounter-id-therapy-protocol-therapy_protocol_id-edit',
params: { therapy_protocol_id: recId.value },
})
break
case ActionEvents.showConfirmVerify:
// Trigger confirmation modal open
handleVerify()
break
case ActionEvents.showPrint:
isDocPreviewDialogOpen.value = true
break
}
})
// #endregion
</script>
<template>
<Header :prep="{ ...headerPrep }" />
<section class="mb-5 flex justify-between items-center">
<!-- DATE RANGE -->
<Popover>
<PopoverTrigger as-child>
<Button variant="outline" :class="cn('w-[280px] justify-start text-left font-normal',
!dateValue && 'text-muted-foreground')">
<CalendarIcon class="mr-2 h-4 w-4" />
<template v-if="dateValue.start">
<template v-if="dateValue.end">
{{ df.format(dateValue.start.toDate(getLocalTimeZone())) }} -
{{ df.format(dateValue.end.toDate(getLocalTimeZone())) }}
</template>
<template v-else>
{{ df.format(dateValue.start.toDate(getLocalTimeZone())) }}
</template>
</template>
<template v-else> Pick a date </template>
</Button>
</PopoverTrigger>
<PopoverContent class="w-auto p-0">
<RangeCalendar v-model="dateValue" initial-focus :number-of-months="2"
@update:start-value="(startDate) => (dateValue.start = startDate)" />
</PopoverContent>
</Popover>
<!-- HISTORY -->
<Button variant="outline" :class="cn('',)" @click="handleOpenHistory">
<Icon name="i-lucide-history" class="h-4 w-4" />
History
</Button>
</section>
<AppTherapyProtocolCommonBannerPatientInTherapy
v-if="isPatientInTherapy"
class="mb-5" />
<AppTherapyProtocolList
:data="data"
:pagination-meta="paginationMeta"
@page-change="handlePageChange"/>
<Dialog v-model:open="isVerifyDialogOpen" title="Verifikasi">
<AppTherapyProtocolVerifyDialog
ref="inputForm"
:schema="VerificationSchema"
/>
<div class="flex justify-end">
<Action v-show="isCaptchaValid" :enable-draft="false" @click="handleActionClick" />
</div>
</Dialog>
<Dialog v-model:open="isHistoryDialogOpen" title="History" size="full">
<ContentTherapyProtocolHistoryList />
</Dialog>
<Dialog v-model:open="isDocPreviewDialogOpen" title="Preview Dokumen" size="2xl">
<!-- <DocPreviewDialog :link="recItem.url" /> -->
<DocPreviewDialog :link="`https://www.antennahouse.com/hubfs/xsl-fo-sample/pdf/basic-link-1.pdf`" />
</Dialog>
</template>