277 lines
6.4 KiB
Vue
277 lines
6.4 KiB
Vue
<script setup lang="ts">
|
|
// Components
|
|
import Dialog from '~/components/pub/my-ui/modal/dialog.vue'
|
|
import AppActionReportList from '~/components/app/action-report/list.vue'
|
|
import AppActionReportListHistory from '~/components/app/action-report/list-history.vue'
|
|
import RecordConfirmation from '~/components/pub/my-ui/confirmation/record-confirmation.vue'
|
|
import { ButtonAction } from '~/components/pub/my-ui/form'
|
|
|
|
// config
|
|
import { config } from '~/components/app/action-report/list.cfg'
|
|
|
|
// types
|
|
import { ActionEvents } from '~/components/pub/my-ui/data/types'
|
|
import type { Encounter } from '~/models/encounter'
|
|
|
|
// Samples
|
|
import { sampleRows, type ActionReportData } from '~/components/app/action-report/sample'
|
|
import sampleReport from './sample'
|
|
|
|
// helpers
|
|
import { toast } from '~/components/pub/ui/toast'
|
|
|
|
// Props
|
|
interface Props {
|
|
encounter: Encounter
|
|
}
|
|
const props = defineProps<Props>()
|
|
const emits = defineEmits<{
|
|
(e: 'add'): void
|
|
(e: 'edit', id: number | string): void
|
|
(e: 'view', id: number | string): void
|
|
}>()
|
|
|
|
// states
|
|
const router = useRouter()
|
|
const route = useRoute()
|
|
const { goToEntry, backToList } = useQueryCRUDMode('mode')
|
|
const title = ref('')
|
|
const search = ref('')
|
|
const dateFrom = ref('')
|
|
const dateTo = ref('')
|
|
const isDialogOpen = ref<boolean>(false)
|
|
const isLoading = ref<boolean>(false)
|
|
|
|
// #region mock
|
|
// Handlers
|
|
import {
|
|
recId,
|
|
recAction,
|
|
recItem,
|
|
isReadonly,
|
|
isProcessing,
|
|
isFormEntryDialogOpen,
|
|
isRecordConfirmationOpen,
|
|
onResetState,
|
|
handleActionSave,
|
|
handleActionEdit,
|
|
handleActionRemove,
|
|
handleCancelForm,
|
|
} from '~/handlers/consultation.handler'
|
|
// #endregion
|
|
|
|
// filter + pencarian sederhana (client-side)
|
|
const filtered = computed(() => {
|
|
const q = search.value.trim().toLowerCase()
|
|
return sampleRows.filter((r: ActionReportData) => {
|
|
if (q) {
|
|
return r.nama.toLowerCase().includes(q) || r.noRm.toLowerCase().includes(q) || r.dokter.toLowerCase().includes(q)
|
|
}
|
|
return true
|
|
})
|
|
})
|
|
|
|
const goEdit = (id: number | string) => {
|
|
router.replace({
|
|
path: route.path,
|
|
query: {
|
|
...route.query,
|
|
mode: 'entry',
|
|
'record-id': id,
|
|
},
|
|
})
|
|
}
|
|
|
|
const goView = (id: number | string) => {
|
|
router.replace({
|
|
path: route.path,
|
|
query: {
|
|
...route.query,
|
|
mode: 'view',
|
|
'record-id': id,
|
|
},
|
|
})
|
|
}
|
|
|
|
provide('rec_id', recId)
|
|
provide('rec_action', recAction)
|
|
provide('rec_item', recItem)
|
|
provide('table_data_loader', isLoading)
|
|
|
|
async function onGetDetail(id: number | string) {
|
|
isLoading.value = true
|
|
const res = sampleReport
|
|
recItem.value = res
|
|
console.log(res)
|
|
isLoading.value = false
|
|
}
|
|
|
|
// #region watcher
|
|
watch([recId, recAction], (newVal) => {
|
|
const [id, action] = newVal
|
|
|
|
// Guard: jangan proses jika id = 0 atau action kosong
|
|
if (!id || !action) return
|
|
|
|
switch (action) {
|
|
case ActionEvents.showDetail:
|
|
// onGetDetail(recId.value)
|
|
goView(id)
|
|
title.value = 'Detail Konsultasi'
|
|
break
|
|
case ActionEvents.showEdit:
|
|
goEdit(id)
|
|
title.value = 'Edit Konsultasi'
|
|
break
|
|
case ActionEvents.showConfirmDelete:
|
|
isRecordConfirmationOpen.value = true
|
|
break
|
|
}
|
|
|
|
// Reset KEDUANYA menggunakan nextTick agar tidak trigger watcher lagi
|
|
nextTick(() => {
|
|
recId.value = 0
|
|
recAction.value = ''
|
|
})
|
|
})
|
|
// #endregion
|
|
</script>
|
|
|
|
<template>
|
|
<div class="mx-auto max-w-full">
|
|
<div class="border-b p-6">
|
|
<h1 class="text-2xl font-semibold">Laporan Tindakan</h1>
|
|
<p class="mt-1 text-sm text-gray-500">Infomasi laporan tindakan pasien</p>
|
|
</div>
|
|
|
|
<div class="flex flex-wrap items-center gap-3 border-b p-4">
|
|
<div class="flex items-center gap-2">
|
|
<input
|
|
v-model="search"
|
|
placeholder="Cari Nama / No.RM"
|
|
class="w-64 rounded border px-3 py-2"
|
|
/>
|
|
</div>
|
|
|
|
<div class="flex items-center gap-2">
|
|
<input
|
|
v-model="dateFrom"
|
|
type="date"
|
|
class="rounded border px-3 py-2"
|
|
/>
|
|
<span class="text-sm text-gray-500">-</span>
|
|
<input
|
|
v-model="dateTo"
|
|
type="date"
|
|
class="rounded border px-3 py-2"
|
|
/>
|
|
<ButtonAction
|
|
preset="custom"
|
|
title="Filter List Laporan Tindakan"
|
|
label="Filter"
|
|
icon="i-lucide-filter"
|
|
@click="
|
|
() => {
|
|
isDialogOpen = true
|
|
}
|
|
"
|
|
/>
|
|
</div>
|
|
|
|
<div class="ml-auto flex items-center gap-2">
|
|
<ButtonAction
|
|
preset="custom"
|
|
title="Riwayat Laporan Tindakan"
|
|
icon="i-lucide-history"
|
|
label="Riwayat Laporan Tindakan"
|
|
@click="
|
|
() => {
|
|
isDialogOpen = true
|
|
}
|
|
"
|
|
/>
|
|
<ButtonAction
|
|
preset="add"
|
|
title="Tambah Data Laporan Tindakan"
|
|
icon="i-lucide-plus"
|
|
label="Tambah Data"
|
|
@click="
|
|
() => {
|
|
goToEntry()
|
|
}
|
|
"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="overflow-x-auto p-4">
|
|
<AppActionReportList
|
|
:data="filtered"
|
|
:pagination-meta="{
|
|
recordCount: 2,
|
|
page: 1,
|
|
pageSize: 10,
|
|
totalPage: 1,
|
|
hasPrev: false,
|
|
hasNext: false,
|
|
}"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<Dialog
|
|
v-model:open="isDialogOpen"
|
|
title="Arsip Riwayat Laporan Tindakan"
|
|
size="2xl"
|
|
prevent-outside
|
|
@update:open="
|
|
(value: any) => {
|
|
isDialogOpen = value
|
|
}
|
|
"
|
|
>
|
|
<AppActionReportListHistory
|
|
:data="filtered"
|
|
:pagination-meta="{
|
|
recordCount: 2,
|
|
page: 1,
|
|
pageSize: 10,
|
|
totalPage: 1,
|
|
hasPrev: false,
|
|
hasNext: false,
|
|
}"
|
|
/>
|
|
</Dialog>
|
|
|
|
<RecordConfirmation
|
|
v-model:open="isRecordConfirmationOpen"
|
|
action="delete"
|
|
:record="recItem"
|
|
@confirm="
|
|
() =>
|
|
handleActionRemove(
|
|
recItem.id,
|
|
() => {
|
|
router.go(0)
|
|
},
|
|
toast,
|
|
)
|
|
"
|
|
@cancel=""
|
|
>
|
|
<template #default="{ record }">
|
|
{{ console.log(JSON.stringify(record)) }}
|
|
<div class="space-y-1 text-sm">
|
|
<p
|
|
v-for="field in config.delKeyNames"
|
|
:key="field.key"
|
|
:v-if="record?.[field.key]"
|
|
>
|
|
<span class="font-semibold">{{ field.label }}:</span>
|
|
{{ record[field.key] }}
|
|
</p>
|
|
</div>
|
|
</template>
|
|
</RecordConfirmation>
|
|
</template>
|