Files
simrsx-fe/app/components/app/patient/view-patient.vue

127 lines
3.1 KiB
Vue

<script setup lang="ts">
import { ref, provide, watch } from 'vue'
// Components
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
DialogTrigger,
DialogFooter,
} from '~/components/pub/ui/dialog'
import { Button } from '~/components/pub/ui/button'
import { Input } from '~/components/pub/ui/input'
import ListPatient from './list-patient.vue'
// Types
import type { PatientData } from './list-cfg.patient'
import type { PaginationMeta } from '~/components/pub/my-ui/pagination/pagination.type'
// Helpers
import { refDebounced } from '@vueuse/core'
const props = defineProps<{
open: boolean
patients: Array<PatientData>
selected: string
paginationMeta: PaginationMeta
}>()
const emit = defineEmits<{
(e: 'update:open', value: boolean): void
(e: 'update:selected', value: string): void
(e: 'fetch', value: any): void
(e: 'save'): void
}>()
const search = ref('')
const debouncedSearch = refDebounced(search, 500) // 500ms debounce
// Provide for radio selection - use selected prop directly
const recSelectId = ref<number>(Number(props.selected) || 0)
const recSelectMenu = ref<string>('patient')
provide('rec_select_id', recSelectId)
provide('rec_select_menu', recSelectMenu)
function saveSelection() {
// Validate that a patient is selected
if (!props.selected || props.selected === '') {
console.warn('No patient selected')
return
}
emit('save')
emit('update:open', false)
}
function handlePageChange(page: number) {
emit('fetch', { 'page-number': page })
}
// Watch for changes in recSelectId and emit update:selected
watch(recSelectId, (newValue) => {
if (newValue > 0) {
emit('update:selected', String(newValue))
}
})
// Watch for changes in selected prop
watch(() => props.selected, (newValue) => {
recSelectId.value = Number(newValue) || 0
})
watch(debouncedSearch, (newValue) => {
// Only search if 3+ characters or empty (to clear search)
if (newValue.length === 0 || newValue.length >= 3) {
emit('fetch', { search: newValue })
}
})
</script>
<template>
<Dialog
:open="props.open"
@update:open="emit('update:open', $event)"
>
<DialogTrigger as-child></DialogTrigger>
<DialogContent class="max-w-3xl">
<DialogHeader>
<DialogTitle>Cari Pasien</DialogTitle>
</DialogHeader>
<!-- Input Search -->
<div class="max-w-[50%]">
<Input
v-model="search"
placeholder="Cari berdasarkan No. KTP / No. RM / Nomor Kartu"
/>
</div>
<div class="overflow-x-auto rounded-lg border">
<ListPatient
:data="patients"
:selected="props.selected"
:pagination-meta="paginationMeta"
@page-change="handlePageChange"
/>
</div>
<!-- Footer -->
<DialogFooter>
<Button
variant="default"
class="h-[40px] min-w-[120px] text-white"
@click="saveSelection"
>
<Icon
name="i-lucide-save"
class="h-5 w-5"
/>
Simpan
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</template>