fix: move patient view dialog under patient
This commit is contained in:
@@ -1,41 +0,0 @@
|
||||
import type { Config } from '~/components/pub/my-ui/data-table'
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
|
||||
const SelectedRadio = defineAsyncComponent(() => import('./select-radio.vue'))
|
||||
|
||||
export interface PatientData {
|
||||
id: string
|
||||
identity: string
|
||||
number: string
|
||||
bpjs: string
|
||||
name: string
|
||||
}
|
||||
|
||||
export const config: Config = {
|
||||
cols: [{ width: 50 }, { width: 100 }, { width: 100 }, { width: 100 }, { width: 100 }],
|
||||
|
||||
headers: [
|
||||
[{ label: '' }, { label: 'NO. KTP' }, { label: 'NO. RM' }, { label: 'NO. KARTU BPJS' }, { label: 'NAMA PASIEN' }],
|
||||
],
|
||||
|
||||
keys: ['check', 'identity', 'number', 'bpjs', 'name'],
|
||||
|
||||
delKeyNames: [
|
||||
{ key: 'code', label: 'Kode' },
|
||||
{ key: 'name', label: 'Nama' },
|
||||
],
|
||||
|
||||
parses: {},
|
||||
|
||||
components: {
|
||||
check(rec, idx) {
|
||||
return {
|
||||
idx,
|
||||
rec: { ...rec as object, menu: 'patient' },
|
||||
component: SelectedRadio,
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
htmls: {},
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
// Components
|
||||
import PaginationView from '~/components/pub/my-ui/pagination/pagination-view.vue'
|
||||
|
||||
// Types
|
||||
import type { PatientData } from './list-cfg.patient'
|
||||
import type { PaginationMeta } from '~/components/pub/my-ui/pagination/pagination.type'
|
||||
|
||||
// Configs
|
||||
import { config } from './list-cfg.patient'
|
||||
|
||||
const props = defineProps<{
|
||||
data: PatientData[]
|
||||
selected?: string
|
||||
paginationMeta?: PaginationMeta
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
pageChange: [page: number]
|
||||
}>()
|
||||
|
||||
function handlePageChange(page: number) {
|
||||
emit('pageChange', page)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PubMyUiDataTable
|
||||
v-bind="config"
|
||||
:rows="props.data"
|
||||
:selected="props.selected"
|
||||
/>
|
||||
<PaginationView
|
||||
v-if="paginationMeta"
|
||||
:pagination-meta="paginationMeta"
|
||||
@page-change="handlePageChange"
|
||||
/>
|
||||
</template>
|
||||
@@ -1,38 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, inject, type Ref } from 'vue'
|
||||
// Components
|
||||
import { RadioGroup, RadioGroupItem } from '~/components/pub/ui/radio-group'
|
||||
|
||||
const props = defineProps<{
|
||||
rec: { id: string; name: string; menu: string }
|
||||
selected?: string
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
// No emits needed - using provide/inject
|
||||
}>()
|
||||
|
||||
const record = props.rec || {}
|
||||
const recId = inject('rec_select_id') as Ref<number>
|
||||
const recMenu = inject('rec_select_menu') as Ref<string>
|
||||
const selected = computed(() => recId.value === Number(record.id) ? record.id : '')
|
||||
|
||||
function handleSelection(value: string) {
|
||||
if (value === record.id) {
|
||||
recId.value = Number(record.id) || 0
|
||||
recMenu.value = record.menu || ''
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<RadioGroup
|
||||
:model-value="selected"
|
||||
@update:model-value="handleSelection"
|
||||
>
|
||||
<RadioGroupItem
|
||||
:id="record.id"
|
||||
:value="record.id"
|
||||
/>
|
||||
</RadioGroup>
|
||||
</template>
|
||||
@@ -1,140 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } 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 { RadioGroup, RadioGroupItem } from '~/components/pub/ui/radio-group'
|
||||
import PaginationView from '~/components/pub/my-ui/pagination/pagination-view.vue'
|
||||
|
||||
// Types
|
||||
import type { PaginationMeta } from '~/components/pub/my-ui/pagination/pagination.type'
|
||||
|
||||
// Helpers
|
||||
import { refDebounced } from '@vueuse/core'
|
||||
|
||||
const props = defineProps<{
|
||||
open: boolean
|
||||
patients: Array<{ id: string; identity: string; number: string; bpjs: string; name: string }>
|
||||
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
|
||||
|
||||
const filteredPatients = computed(() => {
|
||||
const patients = props.patients || []
|
||||
return patients
|
||||
})
|
||||
|
||||
function saveSelection() {
|
||||
emit('save')
|
||||
emit('update:open', false)
|
||||
}
|
||||
|
||||
function handlePageChange(page: number) {
|
||||
emit('fetch', { 'page-number': page })
|
||||
}
|
||||
|
||||
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="mb-2 max-w-[50%]">
|
||||
<Input
|
||||
v-model="search"
|
||||
placeholder="Cari berdasarkan No. KTP / No. RM / Nomor Kartu"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Table -->
|
||||
<div class="overflow-x-auto rounded-lg border">
|
||||
<table class="w-full text-sm">
|
||||
<thead class="bg-gray-100">
|
||||
<tr class="text-left">
|
||||
<th class="p-2"></th>
|
||||
<th class="p-2">NO. KTP</th>
|
||||
<th class="p-2">NO. RM</th>
|
||||
<th class="p-2">NO. KARTU BPJS</th>
|
||||
<th class="p-2">NAMA PASIEN</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="font-normal">
|
||||
<tr
|
||||
v-for="p in filteredPatients"
|
||||
:key="p.identity"
|
||||
class="border-t hover:bg-gray-50"
|
||||
>
|
||||
<td class="p-2">
|
||||
<RadioGroup
|
||||
:model-value="props.selected"
|
||||
@update:model-value="emit('update:selected', $event)"
|
||||
>
|
||||
<RadioGroupItem
|
||||
:id="p.id"
|
||||
:value="p.id"
|
||||
/>
|
||||
</RadioGroup>
|
||||
</td>
|
||||
<td class="p-2">{{ p.identity }}</td>
|
||||
<td class="p-2">{{ p.number }}</td>
|
||||
<td class="p-2">{{ p.bpjs }}</td>
|
||||
<td class="p-2">{{ p.name }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<PaginationView
|
||||
: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>
|
||||
@@ -1,127 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, provide, watch, computed } 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>
|
||||
Reference in New Issue
Block a user