feat(cemo): add dialog verification and list register
This commit is contained in:
@@ -0,0 +1,164 @@
|
||||
<script setup lang="ts">
|
||||
import Dialog from '~/components/pub/my-ui/modal/dialog.vue'
|
||||
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '~/components/pub/ui/table'
|
||||
import Input from '~/components/pub/ui/input/Input.vue'
|
||||
import DatepickerSingle from '~/components/pub/my-ui/datepicker/datepicker-single.vue'
|
||||
import Button from '~/components/pub/ui/button/Button.vue'
|
||||
import { format, parseISO } from 'date-fns'
|
||||
import { id as localeID } from 'date-fns/locale'
|
||||
|
||||
interface Props {
|
||||
open?: boolean
|
||||
tanggalPemeriksaan?: string | Date
|
||||
jadwalTanggalPemeriksaan?: string | Date
|
||||
isLoading?: boolean
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
open: false,
|
||||
tanggalPemeriksaan: undefined,
|
||||
jadwalTanggalPemeriksaan: undefined,
|
||||
isLoading: false,
|
||||
})
|
||||
|
||||
const emit = defineEmits<{
|
||||
'update:open': [value: boolean]
|
||||
'update:date': [value: string | undefined]
|
||||
'update:schedule': [value: string | undefined]
|
||||
submit: [data: { tanggalPemeriksaan: string | undefined; jadwalTanggalPemeriksaan: string | undefined }]
|
||||
}>()
|
||||
|
||||
// Local state for jadwal tanggal pemeriksaan
|
||||
const jadwalTanggal = ref<string | undefined>(
|
||||
props.jadwalTanggalPemeriksaan
|
||||
? typeof props.jadwalTanggalPemeriksaan === 'string'
|
||||
? props.jadwalTanggalPemeriksaan
|
||||
: format(props.jadwalTanggalPemeriksaan, 'yyyy-MM-dd')
|
||||
: undefined,
|
||||
)
|
||||
|
||||
// Watch for external changes
|
||||
watch(
|
||||
() => props.jadwalTanggalPemeriksaan,
|
||||
(newValue) => {
|
||||
if (newValue) {
|
||||
jadwalTanggal.value =
|
||||
typeof newValue === 'string' ? newValue : format(newValue, 'yyyy-MM-dd')
|
||||
} else {
|
||||
jadwalTanggal.value = undefined
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
// Watch local changes
|
||||
watch(jadwalTanggal, (newValue) => {
|
||||
emit('update:schedule', newValue)
|
||||
})
|
||||
|
||||
// Format date for display
|
||||
const formattedTanggalPemeriksaan = computed(() => {
|
||||
if (!props.tanggalPemeriksaan) return ''
|
||||
try {
|
||||
const date =
|
||||
props.tanggalPemeriksaan instanceof Date
|
||||
? props.tanggalPemeriksaan
|
||||
: parseISO(props.tanggalPemeriksaan)
|
||||
return format(date, 'dd MMMM yyyy', { locale: localeID })
|
||||
} catch {
|
||||
return props.tanggalPemeriksaan.toString()
|
||||
}
|
||||
})
|
||||
|
||||
// Handle submit
|
||||
function handleSubmit() {
|
||||
emit('submit', {
|
||||
tanggalPemeriksaan: props.tanggalPemeriksaan
|
||||
? typeof props.tanggalPemeriksaan === 'string'
|
||||
? props.tanggalPemeriksaan
|
||||
: format(props.tanggalPemeriksaan, 'yyyy-MM-dd')
|
||||
: undefined,
|
||||
jadwalTanggalPemeriksaan: jadwalTanggal.value,
|
||||
})
|
||||
}
|
||||
|
||||
// Table data for Jadwal Ruang Tindakan
|
||||
const scheduleData = [
|
||||
{
|
||||
no: 1,
|
||||
namaJenis: 'Ruang Tindakan',
|
||||
jenisPemeriksaan: 'KEMOTERAPI',
|
||||
},
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Dialog
|
||||
:open="open"
|
||||
size="lg"
|
||||
title="Verifikasi Jadwal Pasien"
|
||||
@update:open="$emit('update:open', $event)"
|
||||
>
|
||||
<div class="space-y-6 py-4">
|
||||
<!-- Jadwal Ruang Tindakan Section -->
|
||||
<div class="space-y-3">
|
||||
<h4 class="text-base font-semibold">Jadwal Ruang Tindakan</h4>
|
||||
<div class="overflow-hidden rounded-md border">
|
||||
<Table>
|
||||
<TableHeader class="bg-gray-50">
|
||||
<TableRow>
|
||||
<TableHead class="font-semibold">NO</TableHead>
|
||||
<TableHead class="font-semibold">NAMA JENIS</TableHead>
|
||||
<TableHead class="font-semibold">JENIS PEMERIKSAAN</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
<TableRow v-for="(row, index) in scheduleData" :key="index">
|
||||
<TableCell>{{ row.no }}</TableCell>
|
||||
<TableCell>{{ row.namaJenis }}</TableCell>
|
||||
<TableCell>{{ row.jenisPemeriksaan }}</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tanggal Pemeriksaan Section -->
|
||||
<div class="space-y-2">
|
||||
<label class="text-sm font-medium">Tanggal Pemeriksaan</label>
|
||||
<Input
|
||||
:model-value="formattedTanggalPemeriksaan"
|
||||
:disabled="true"
|
||||
class="bg-gray-100 text-gray-700"
|
||||
readonly
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Jadwal Tanggal Pemeriksaan Section -->
|
||||
<div class="space-y-2">
|
||||
<label class="text-sm font-medium">
|
||||
Jadwal Tanggal Pemeriksaan
|
||||
<span class="text-red-500">*</span>
|
||||
</label>
|
||||
<DatepickerSingle
|
||||
v-model="jadwalTanggal"
|
||||
placeholder="Pilih Jadwal"
|
||||
:disabled="isLoading"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Action Button -->
|
||||
<div class="flex justify-end pt-4">
|
||||
<Button
|
||||
type="button"
|
||||
:disabled="isLoading || !jadwalTanggal"
|
||||
class="bg-gradient-to-r from-orange-500 to-orange-400 hover:from-orange-600 hover:to-orange-500 text-white shadow-md"
|
||||
@click="handleSubmit"
|
||||
>
|
||||
<Icon name="i-lucide-calendar-check" class="mr-2 h-4 w-4" />
|
||||
Simpan Jadwal
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Dialog>
|
||||
</template>
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
<script setup lang="ts">
|
||||
// Components
|
||||
import PaginationView from '~/components/pub/my-ui/pagination/pagination-view.vue'
|
||||
|
||||
// Types
|
||||
import type { PaginationMeta } from '~/components/pub/my-ui/pagination/pagination.type'
|
||||
|
||||
// Configs
|
||||
import { config } from './list-cfg.protocol'
|
||||
|
||||
const searchQuery = ref('')
|
||||
|
||||
function handleSearch(event: Event) {
|
||||
const target = event.target as HTMLInputElement
|
||||
searchQuery.value = target.value
|
||||
// TODO: Implement search logic here
|
||||
// You can emit an event to parent or filter data directly
|
||||
}
|
||||
|
||||
interface Props {
|
||||
data: any[]
|
||||
paginationMeta: PaginationMeta
|
||||
}
|
||||
|
||||
defineProps<Props>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
pageChange: [page: number]
|
||||
}>()
|
||||
|
||||
function handlePageChange(page: number) {
|
||||
emit('pageChange', page)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="space-y-4">
|
||||
<!-- Title and Search Section -->
|
||||
<div class="flex flex-col items-start">
|
||||
<div class="flex items-center justify-between w-full">
|
||||
<div>
|
||||
<h2 class="mb-1 text-xl font-semibold">Daftar Kunjungan Rawat Jalan Kemoterapi</h2>
|
||||
<p class="mb-4 text-sm text-gray-500">Manajemen pendaftaran serta monitoring terapi pasien tindakan rawat jalan.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="relative mt-10 w-72">
|
||||
<input
|
||||
v-model="searchQuery"
|
||||
type="text"
|
||||
placeholder="Cari jadwal pemeriksaan..."
|
||||
class="w-full rounded-md border px-4 py-2 focus:border-primary focus:outline-none focus:ring-2 focus:ring-primary/20"
|
||||
@input="handleSearch"
|
||||
/>
|
||||
<span class="absolute right-3 top-2.5 text-gray-400">
|
||||
<i class="ri-search-line"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<PubMyUiDataTable
|
||||
v-bind="config"
|
||||
:rows="data"
|
||||
:skeleton-size="paginationMeta?.pageSize"
|
||||
/>
|
||||
<PaginationView
|
||||
:pagination-meta="paginationMeta"
|
||||
@page-change="handlePageChange"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
Reference in New Issue
Block a user