done: edit, detail report
fix: parsing err datetime on edit mode todo: koordinasi dengan tim be terkait datetime iso impl edit form feat(treatment-report): add detail view and preview components - Implement treatment report detail page with RBAC checks - Create preview component with accordion layout - Extract mock data to shared sample file - Enhance procedure picker with preview mode - Update schema to make procedure id required - Improve detail row styling and layout feat(treatment-report): update page titles and enhance preview component - Update page titles for treatment report pages to be more descriptive - Implement date formatting in treatment report preview - Add router navigation for edit functionality - Enhance preview component with detailed operation data sections - Add support for tissue notes display in preview
This commit is contained in:
+116
-58
@@ -1,10 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
import { cn } from '~/lib/utils'
|
||||
|
||||
// types
|
||||
import { type ProcedureSrc } from '~/models/procedure-src'
|
||||
|
||||
// componenets
|
||||
// Components
|
||||
import { FieldArray } from 'vee-validate'
|
||||
import { ButtonAction } from '~/components/pub/my-ui/form'
|
||||
import TableHeader from '~/components/pub/ui/table/TableHeader.vue'
|
||||
@@ -14,69 +12,129 @@ interface Props {
|
||||
fieldName: string
|
||||
title: string
|
||||
subTitle?: string
|
||||
isReadonly?: boolean
|
||||
}
|
||||
const props = defineProps<Props>()
|
||||
|
||||
const { isReadonly = false } = props
|
||||
// State UI (Loading / Disabled)
|
||||
isReadonly?: boolean
|
||||
|
||||
// Data Architecture Switch
|
||||
// 'form' = Pakai Vee-Validate (Parent wajib useForm)
|
||||
// 'preview' = Pakai Props sampleItems (Parent bebas)
|
||||
mode?: 'form' | 'preview'
|
||||
|
||||
// Data Source untuk mode 'preview' (atau initial data)
|
||||
sampleItems?: ProcedureSrc[]
|
||||
}
|
||||
|
||||
// Set default mode ke 'form' agar backward compatible
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
mode: 'form',
|
||||
isReadonly: false,
|
||||
sampleItems: () => [],
|
||||
})
|
||||
|
||||
const isProcedurePickerDialogOpen = ref<boolean>(false)
|
||||
provide(`isProcedurePickerDialogOpen`, isProcedurePickerDialogOpen)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="">
|
||||
<div class="mb-2 flex items-center justify-between">
|
||||
<p class="mb-2 font-medium">{{ title }}</p>
|
||||
<ButtonAction
|
||||
preset="add"
|
||||
title="Tambah Item"
|
||||
icon="i-lucide-search"
|
||||
:disabled="isReadonly"
|
||||
:label="subTitle || 'Pilih Diagnosis'"
|
||||
:full-width-mobile="true"
|
||||
@click="isProcedurePickerDialogOpen = true"
|
||||
/>
|
||||
</div>
|
||||
<div class="mb-2 flex items-center justify-between">
|
||||
<p class="mb-2 font-medium">{{ title }}</p>
|
||||
|
||||
<FieldArray
|
||||
v-slot="{ fields, push, remove }"
|
||||
:name="props.fieldName"
|
||||
>
|
||||
<ProcedureListDialog :process-fn="push" />
|
||||
<ButtonAction
|
||||
v-if="mode === 'form' && !isReadonly"
|
||||
preset="add"
|
||||
title="Tambah Item"
|
||||
icon="i-lucide-search"
|
||||
:label="subTitle || 'Pilih Diagnosis'"
|
||||
:full-width-mobile="true"
|
||||
@click="isProcedurePickerDialogOpen = true"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="overflow-hidden rounded-lg border border-gray-200">
|
||||
<Table>
|
||||
<TableHeader class="bg-gray-100">
|
||||
<TableRow>
|
||||
<TableHead class="w-1/2">Prosedur</TableHead>
|
||||
<TableHead class="w-1/2">ICD-X</TableHead>
|
||||
<TableHead class="w-1/2">Action</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
<TableRow
|
||||
v-for="(field, idx) in fields"
|
||||
:key="idx"
|
||||
<FieldArray
|
||||
v-if="mode === 'form'"
|
||||
v-slot="{ fields, push, remove }"
|
||||
:name="props.fieldName"
|
||||
>
|
||||
<ProcedureListDialog :process-fn="push" />
|
||||
|
||||
<div class="overflow-hidden rounded-lg border border-gray-200">
|
||||
<Table>
|
||||
<TableHeader class="bg-gray-100">
|
||||
<TableRow>
|
||||
<TableHead class="w-1/2">Prosedur</TableHead>
|
||||
<TableHead class="w-1/2">ICD-X</TableHead>
|
||||
<TableHead class="w-[50px]">Action</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
<TableRow v-if="fields.length === 0">
|
||||
<TableCell
|
||||
colspan="3"
|
||||
class="py-4 text-center text-muted-foreground"
|
||||
>
|
||||
<TableCell :class="cn(isReadonly && 'text-muted-foreground')">
|
||||
{{ (field.value as ProcedureSrc)?.name }}
|
||||
</TableCell>
|
||||
<TableCell :class="cn(isReadonly && 'text-muted-foreground')">
|
||||
{{ (field.value as ProcedureSrc)?.code }}
|
||||
</TableCell>
|
||||
<TableCell class="">
|
||||
<ButtonAction
|
||||
:disabled="isReadonly"
|
||||
preset="delete"
|
||||
:title="`Hapus prosedur '${(field.value as ProcedureSrc)?.name}'`"
|
||||
icon-only
|
||||
@click="remove(idx)"
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
</FieldArray>
|
||||
Belum ada data dipilih.
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
|
||||
<TableRow
|
||||
v-for="(field, idx) in fields"
|
||||
:key="field.key"
|
||||
>
|
||||
<TableCell :class="cn(isReadonly && 'opacity-50')">
|
||||
{{ (field.value as ProcedureSrc)?.name }}
|
||||
</TableCell>
|
||||
<TableCell :class="cn(isReadonly && 'opacity-50')">
|
||||
{{ (field.value as ProcedureSrc)?.code }}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<ButtonAction
|
||||
v-if="!isReadonly"
|
||||
preset="delete"
|
||||
icon-only
|
||||
:title="`Hapus ${(field.value as ProcedureSrc)?.name}`"
|
||||
@click="remove(idx)"
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
</FieldArray>
|
||||
|
||||
<div
|
||||
v-else
|
||||
class="overflow-hidden rounded-lg border border-gray-200"
|
||||
>
|
||||
<Table>
|
||||
<TableHeader class="bg-gray-100">
|
||||
<TableRow>
|
||||
<TableHead class="w-1/2">Prosedur</TableHead>
|
||||
<TableHead class="w-1/2">ICD-X</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
<TableRow v-if="sampleItems.length === 0">
|
||||
<TableCell
|
||||
colspan="2"
|
||||
class="py-4 text-center text-muted-foreground"
|
||||
>
|
||||
Tidak ada data.
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
|
||||
<TableRow
|
||||
v-for="item in sampleItems"
|
||||
:key="item.code || item.id"
|
||||
>
|
||||
<TableCell class="text-muted-foreground">
|
||||
{{ item.name }}
|
||||
</TableCell>
|
||||
<TableCell class="text-muted-foreground">
|
||||
{{ item.code }}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -0,0 +1,151 @@
|
||||
<script setup lang="ts">
|
||||
import { format } from 'date-fns'
|
||||
import { id } from 'date-fns/locale'
|
||||
|
||||
// type
|
||||
import { type ProcedureSrc } from '~/models/procedure-src'
|
||||
import { type TreatmentReportFormData } from '~/schemas/treatment-report.schema'
|
||||
|
||||
// componenets
|
||||
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '~/components/pub/ui/accordion'
|
||||
import * as DE from '~/components/pub/my-ui/doc-entry'
|
||||
import DetailRow from '~/components/pub/my-ui/form/view/detail-row.vue'
|
||||
import ArrangementProcedurePicker from '~/components/app/therapy-protocol/picker-dialog/arrangement-procedure/procedure-picker.vue'
|
||||
|
||||
// #region Props & Emits
|
||||
const props = defineProps<{
|
||||
data: TreatmentReportFormData
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'back'): void
|
||||
(e: 'edit'): void
|
||||
}>()
|
||||
|
||||
// #endregion
|
||||
|
||||
// #region State & Computed
|
||||
const { operatorTeam, procedures, operationExecution, bloodInput, implant, specimen, tissueNotes = [] } = props.data
|
||||
|
||||
const procedureSampleData = procedures as unknown as ProcedureSrc[]
|
||||
// #region Lifecycle Hooks
|
||||
// #endregion
|
||||
|
||||
// #region Functions
|
||||
|
||||
// #endregion region
|
||||
// #region Utilities & event handlers
|
||||
function onNavigate(type: string) {
|
||||
if (type == 'back') emit('back')
|
||||
if (type == 'edit') emit('edit')
|
||||
}
|
||||
// #endregion
|
||||
|
||||
// #region Watchers
|
||||
// #endregion
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DetailRow label="Tanggal Laporan">
|
||||
{{ format(new Date(), 'd MMMM yyyy, HH:mm', { locale: id }) }}
|
||||
</DetailRow>
|
||||
|
||||
<Accordion
|
||||
type="multiple"
|
||||
class="w-full"
|
||||
collapsible
|
||||
:default-value="['section-1', 'section-2', 'section-3']"
|
||||
>
|
||||
<AccordionItem value="section-1">
|
||||
<AccordionTrigger>Tim Pelaksanaan Tindakan</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
<DE.Block>
|
||||
<DetailRow label="DPJP">dr. Marcell Galliard Sp.Gr</DetailRow>
|
||||
<DetailRow label="Operator">Sumitro</DetailRow>
|
||||
<DetailRow label="Asisten Operator">Alexis Lewis Carol</DetailRow>
|
||||
<DetailRow label="Instrumentir">Mikel Arteta</DetailRow>
|
||||
<DetailRow label="Tanggal Pembedahan">
|
||||
{{ format(new Date(), 'd MMMM yyyy', { locale: id }) }}
|
||||
</DetailRow>
|
||||
<DetailRow label="Diagnosa Tindakan">{{ operatorTeam?.actionDiagnosis || '-' }}</DetailRow>
|
||||
<DetailRow label="Perawat Pasca Bedah">Cak Armuji</DetailRow>
|
||||
</DE.Block>
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
|
||||
<AccordionItem value="section-2">
|
||||
<AccordionTrigger>Tindakan Operatif / Non Operatif Lain</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
<ArrangementProcedurePicker
|
||||
field-name="procedures"
|
||||
title="List Prosedur"
|
||||
sub-title="Pilih Prosedur"
|
||||
:mode="'preview'"
|
||||
:sample-items="procedureSampleData"
|
||||
/>
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
|
||||
<AccordionItem value="section-3">
|
||||
<AccordionTrigger>Data Pelaksanaan Tindakan</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
<DE.Block>
|
||||
<DetailRow label="Jenis Operasi">dr. Marcell Galliard Sp.Gr</DetailRow>
|
||||
<DetailRow label="Kode Billing">GCASH1128190</DetailRow>
|
||||
<DetailRow label="Sistem Operasi">Alexis Lewis Carol</DetailRow>
|
||||
<DetailRow label="Operasi Mulai">
|
||||
{{ format(new Date(), 'd MMMM yyyy, HH:mm', { locale: id }) }}
|
||||
</DetailRow>
|
||||
<DetailRow label="Operasi Selesai">
|
||||
{{ format(new Date(), 'd MMMM yyyy, HH:mm', { locale: id }) }}
|
||||
</DetailRow>
|
||||
<DetailRow label="Lama Operasi">5 menit</DetailRow>
|
||||
<DetailRow label="Pembiusan Mulai">
|
||||
{{ format(new Date(), 'd MMMM yyyy, HH:mm', { locale: id }) }}
|
||||
</DetailRow>
|
||||
<DetailRow label="Pembiusan Selesai">
|
||||
{{ format(new Date(), 'd MMMM yyyy, HH:mm', { locale: id }) }}
|
||||
</DetailRow>
|
||||
<DetailRow label="Lama Pembiusan">5 menit</DetailRow>
|
||||
|
||||
<DetailRow label="PRC">300 CC</DetailRow>
|
||||
<DetailRow label="FPP">-</DetailRow>
|
||||
<DetailRow label="WB">-</DetailRow>
|
||||
<DetailRow label="TC">-</DetailRow>
|
||||
<DetailRow label="Merk">-</DetailRow>
|
||||
<DetailRow label="Nama Implant">-</DetailRow>
|
||||
<DetailRow label="Sticker / Nomor Register Implant">-</DetailRow>
|
||||
<DetailRow label="Nama Pendamping Implant">-</DetailRow>
|
||||
</DE.Block>
|
||||
<DE.Block>
|
||||
<DetailRow label="Jenis Pembedahan">Bersih</DetailRow>
|
||||
<DetailRow label="Operasi ke">1 (Satu)</DetailRow>
|
||||
<DetailRow label="Keterangan Lahir">Lahir Hidup</DetailRow>
|
||||
<DetailRow label="Ket. Tempat Lahir">RSSA</DetailRow>
|
||||
<DetailRow label="Berat Badan">18 gram</DetailRow>
|
||||
<DetailRow label="Ket. Saat Lahir">Normal dan sehat</DetailRow>
|
||||
<DetailRow label="Uraian Operasi">-</DetailRow>
|
||||
<DetailRow label="Jumlah Pendarahan">300 CC</DetailRow>
|
||||
<DetailRow label="Specimen / Jaringan dikirim ke">PA</DetailRow>
|
||||
</DE.Block>
|
||||
<DE.Block>
|
||||
<DetailRow label="Keterangan Jaringan">
|
||||
<ul
|
||||
class="list-disc space-y-1 pl-5 text-sm"
|
||||
v-if="tissueNotes.length > 0"
|
||||
v-for="item in tissueNotes"
|
||||
>
|
||||
<li>{{ item.note }}</li>
|
||||
</ul>
|
||||
<span v-else>-</span>
|
||||
</DetailRow>
|
||||
</DE.Block>
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
</Accordion>
|
||||
<div class="my-2 flex justify-end py-2">
|
||||
<PubMyUiNavFooterBaEd @click="onNavigate" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
|
||||
@@ -9,7 +9,7 @@ import AppTreatmentReportEntry from '~/components/app/treatment-report/entry-for
|
||||
import ArrangementProcedurePicker from '~/components/app/therapy-protocol/picker-dialog/arrangement-procedure/procedure-picker.vue'
|
||||
|
||||
const doctors = ref<Doctor[]>([])
|
||||
|
||||
const isLoading = ref<boolean>(false)
|
||||
// TODO: dummy data
|
||||
;(() => {
|
||||
doctors.value = [genDoctor()]
|
||||
@@ -18,7 +18,7 @@ const doctors = ref<Doctor[]>([])
|
||||
|
||||
<template>
|
||||
<AppTreatmentReportEntry
|
||||
:isLoading="false"
|
||||
:isLoading="isLoading"
|
||||
@submit="(val) => console.log(val)"
|
||||
@error="
|
||||
(err: Error) => {
|
||||
@@ -30,58 +30,6 @@ const doctors = ref<Doctor[]>([])
|
||||
}
|
||||
"
|
||||
:doctors="doctors"
|
||||
:initialValues="
|
||||
{
|
||||
operatorTeam: {
|
||||
dpjpId: -1,
|
||||
operatorName: 'Julian',
|
||||
assistantOperatorName: 'Amar',
|
||||
instrumentNurseName: 'Anang',
|
||||
surgeryDate: '2025-11-13T14:29',
|
||||
actionDiagnosis: 'Omon Omon Saja',
|
||||
},
|
||||
procedures: [
|
||||
{
|
||||
id: -1,
|
||||
name: 'Ndase mumet',
|
||||
code: 'CX1',
|
||||
},
|
||||
],
|
||||
operationExecution: {
|
||||
surgeryType: 'khusus',
|
||||
billingCode: 'local',
|
||||
operationSystem: 'cito',
|
||||
surgeryCleanType: 'kotor',
|
||||
surgeryNumber: 'retry',
|
||||
birthPlaceNote: 'out3',
|
||||
personWeight: 100,
|
||||
operationDescription: 'asdsadsa1',
|
||||
birthRemark: 'lahir_hidup',
|
||||
},
|
||||
bloodInput: {
|
||||
type: 'tc',
|
||||
amount: {
|
||||
prc: null,
|
||||
wb: null,
|
||||
ffp: null,
|
||||
tc: 3243324,
|
||||
},
|
||||
},
|
||||
implant: {
|
||||
brand: 'Samsung',
|
||||
name: 'S.komedi',
|
||||
companionName: 'When ya',
|
||||
},
|
||||
specimen: {
|
||||
destination: 'pa',
|
||||
},
|
||||
tissueNotes: [
|
||||
{
|
||||
note: 'Anjai',
|
||||
},
|
||||
],
|
||||
} as unknown as TreatmentReportFormData
|
||||
"
|
||||
>
|
||||
<template #procedures>
|
||||
<ArrangementProcedurePicker
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
<script setup lang="ts">
|
||||
import mockData from './sample'
|
||||
|
||||
// types
|
||||
import { type TreatmentReportFormData } from '~/schemas/treatment-report.schema'
|
||||
|
||||
// Components
|
||||
import Header from '~/components/pub/my-ui/nav-header/prep.vue'
|
||||
import type { HeaderPrep } from '~/components/pub/my-ui/data/types'
|
||||
|
||||
// #region Props & Emits
|
||||
const router = useRouter()
|
||||
const props = defineProps<{
|
||||
id: string | number
|
||||
}>()
|
||||
|
||||
// #endregion
|
||||
|
||||
// #region State & Computed
|
||||
const reportData = ref<TreatmentReportFormData | null>(null)
|
||||
|
||||
const headerPrep: HeaderPrep = {
|
||||
title: 'Detail Laporan Tindakan',
|
||||
icon: 'i-lucide-stethoscope',
|
||||
}
|
||||
|
||||
// #endregion
|
||||
|
||||
// #region Lifecycle Hooks
|
||||
onMounted(async () => {
|
||||
reportData.value = mockData as unknown as TreatmentReportFormData
|
||||
})
|
||||
// #endregion
|
||||
|
||||
// #region Functions
|
||||
// #endregion region
|
||||
|
||||
// #region Utilities & event handlers
|
||||
function onEdit() {
|
||||
router.push({
|
||||
name: 'treatment-report-id-edit',
|
||||
params: { id: 100 },
|
||||
})
|
||||
}
|
||||
function onBack() {}
|
||||
// #endregion
|
||||
|
||||
// #region Watchers
|
||||
// #endregion
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Header
|
||||
:prep="headerPrep"
|
||||
:ref-search-nav="headerPrep.refSearchNav"
|
||||
/>
|
||||
|
||||
<AppTreatmentReportPreview
|
||||
v-if="reportData"
|
||||
:data="reportData"
|
||||
@back="onBack"
|
||||
@edit="onEdit"
|
||||
/>
|
||||
</template>
|
||||
@@ -0,0 +1,60 @@
|
||||
<script setup lang="ts">
|
||||
import mockData from './sample'
|
||||
|
||||
// type
|
||||
import { genDoctor, type Doctor } from '~/models/doctor'
|
||||
import type { TreatmentReportFormData } from '~/schemas/treatment-report.schema'
|
||||
|
||||
// components
|
||||
import { toast } from '~/components/pub/ui/toast'
|
||||
import AppTreatmentReportEntry from '~/components/app/treatment-report/entry-form.vue'
|
||||
import ArrangementProcedurePicker from '~/components/app/therapy-protocol/picker-dialog/arrangement-procedure/procedure-picker.vue'
|
||||
|
||||
interface Props {
|
||||
id: string | number
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
const detail = ref<TreatmentReportFormData | null>(null)
|
||||
|
||||
const doctors = ref<Doctor[]>([])
|
||||
|
||||
// TODO: dummy data
|
||||
;(() => {
|
||||
doctors.value = [genDoctor()]
|
||||
})()
|
||||
|
||||
onMounted(() => {
|
||||
// TODO: get data report by props.id
|
||||
|
||||
// mock
|
||||
detail.value = mockData as unknown as TreatmentReportFormData
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AppTreatmentReportEntry
|
||||
v-if="detail"
|
||||
:isLoading="false"
|
||||
@submit="(val) => console.log(val)"
|
||||
@error="
|
||||
(err: Error) => {
|
||||
toast({
|
||||
title: 'Terjadi Kesalahan',
|
||||
description: err.message,
|
||||
variant: 'destructive',
|
||||
})
|
||||
}
|
||||
"
|
||||
:doctors="doctors"
|
||||
:initialValues="detail as unknown as TreatmentReportFormData"
|
||||
>
|
||||
<template #procedures>
|
||||
<ArrangementProcedurePicker
|
||||
field-name="procedures"
|
||||
title="Tindakan Operatif/Non-Operatif Lain"
|
||||
sub-title="Pilih Prosedur"
|
||||
/>
|
||||
</template>
|
||||
</AppTreatmentReportEntry>
|
||||
</template>
|
||||
@@ -0,0 +1,68 @@
|
||||
export default {
|
||||
operatorTeam: {
|
||||
dpjpId: -1,
|
||||
operatorName: 'Julian Alvarez',
|
||||
assistantOperatorName: 'Arda Guller',
|
||||
instrumentNurseName: 'Kenan Yildiz',
|
||||
surgeryDate: '2025-11-13T14:29:00',
|
||||
actionDiagnosis: 'Sprei gratisnya mana',
|
||||
},
|
||||
procedures: [
|
||||
{
|
||||
id: -1,
|
||||
name: 'Ndase mumet',
|
||||
code: 'CX1',
|
||||
},
|
||||
],
|
||||
operationExecution: {
|
||||
surgeryType: 'khusus',
|
||||
billingCode: 'local',
|
||||
operationSystem: 'cito',
|
||||
surgeryCleanType: 'kotor',
|
||||
surgeryNumber: 'retry',
|
||||
birthPlaceNote: 'out3',
|
||||
personWeight: 100,
|
||||
operationDescription: 'asdsadsa1',
|
||||
birthRemark: 'lahir_hidup',
|
||||
|
||||
operationStartAt: '2025-11-13T14:29:00',
|
||||
operationEndAt: '2025-11-13T17:29:00',
|
||||
|
||||
anesthesiaStartAt: '2025-11-13T11:29:00',
|
||||
anesthesiaEndAt: '2025-11-13T18:29:00',
|
||||
},
|
||||
bloodInput: {
|
||||
type: 'tc',
|
||||
amount: {
|
||||
prc: null,
|
||||
wb: null,
|
||||
ffp: null,
|
||||
tc: 3243324,
|
||||
},
|
||||
},
|
||||
implant: {
|
||||
brand: 'Samsung',
|
||||
name: 'S.Komedi',
|
||||
companionName: 'When ya',
|
||||
},
|
||||
specimen: {
|
||||
destination: 'pa',
|
||||
},
|
||||
tissueNotes: [
|
||||
{
|
||||
note: 'Anjai',
|
||||
},
|
||||
{
|
||||
note: 'Ciee Kaget',
|
||||
},
|
||||
{
|
||||
note: 'Baper',
|
||||
},
|
||||
{
|
||||
note: 'Saltink weeh',
|
||||
},
|
||||
{
|
||||
note: 'Kaburrr',
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -5,15 +5,17 @@ defineProps<{
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-col gap-1 lg:grid lg:grid-cols-[180px_minmax(0,1fr)] lg:gap-x-3">
|
||||
<div class="grid grid-cols-[150px_10px_1fr] gap-y-1 lg:grid-cols-[180px_12px_1fr]">
|
||||
<!-- Label -->
|
||||
<span class="text-md font-normal text-muted-foreground">
|
||||
<span class="text-md font-normal tracking-wide text-muted-foreground">
|
||||
{{ label }}
|
||||
</span>
|
||||
|
||||
<!-- Colon -->
|
||||
<span class="text-md tracking-wide text-muted-foreground">:</span>
|
||||
|
||||
<!-- Value -->
|
||||
<span class="truncate lg:whitespace-normal">
|
||||
<span class="me-3 hidden lg:inline-block">:</span>
|
||||
<span class="text-md font-sans tracking-wide">
|
||||
<slot />
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
<script setup lang="ts">
|
||||
// import type { PagePermission } from '~/models/role'
|
||||
import Error from '~/components/pub/my-ui/error/error.vue'
|
||||
// import { PAGE_PERMISSIONS } from '~/lib/page-permission'
|
||||
|
||||
definePageMeta({
|
||||
// middleware: ['rbac'],
|
||||
roles: ['doctor', 'nurse', 'admisi', 'pharmacy', 'billing', 'management'],
|
||||
title: 'Edit Laporan Tindakan',
|
||||
contentFrame: 'cf-full-width',
|
||||
})
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
useHead({
|
||||
title: () => route.meta.title as string,
|
||||
})
|
||||
|
||||
// const roleAccess: PagePermission = PAGE_PERMISSIONS['/patient']
|
||||
|
||||
// const { checkRole, hasReadAccess } = useRBAC()
|
||||
|
||||
// // Check if user has access to this page
|
||||
// const hasAccess = checkRole(roleAccess)
|
||||
// if (!hasAccess) {
|
||||
// navigateTo('/403')
|
||||
// }
|
||||
|
||||
// Define permission-based computed properties
|
||||
// const canRead = hasReadAccess(roleAccess)
|
||||
const canRead = true
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<ContentTreatmentReportEdit
|
||||
v-if="canRead"
|
||||
:id="route.params.id as string"
|
||||
/>
|
||||
|
||||
<Error
|
||||
v-else
|
||||
:status-code="403"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,44 @@
|
||||
<script setup lang="ts">
|
||||
import type { PagePermission } from '~/models/role'
|
||||
import Error from '~/components/pub/my-ui/error/error.vue'
|
||||
import { PAGE_PERMISSIONS } from '~/lib/page-permission'
|
||||
|
||||
definePageMeta({
|
||||
middleware: ['rbac'],
|
||||
roles: ['doctor', 'nurse', 'admisi', 'pharmacy', 'billing', 'management'],
|
||||
title: 'Detail Laporan Tindakan',
|
||||
contentFrame: 'cf-container-xl',
|
||||
})
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
useHead({
|
||||
title: () => route.meta.title as string,
|
||||
})
|
||||
|
||||
const roleAccess: PagePermission = PAGE_PERMISSIONS['/patient']
|
||||
|
||||
const { checkRole, hasReadAccess } = useRBAC()
|
||||
|
||||
// Check if user has access to this page
|
||||
const hasAccess = checkRole(roleAccess)
|
||||
if (!hasAccess) {
|
||||
navigateTo('/403')
|
||||
}
|
||||
|
||||
// Define permission-based computed properties
|
||||
const canRead = hasReadAccess(roleAccess)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<ContentTreatmentReportDetail
|
||||
v-if="canRead"
|
||||
:id="route.params.id as string"
|
||||
/>
|
||||
<Error
|
||||
v-else
|
||||
:status-code="403"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
@@ -6,7 +6,7 @@ import { PAGE_PERMISSIONS } from '~/lib/page-permission'
|
||||
definePageMeta({
|
||||
middleware: ['rbac'],
|
||||
roles: ['doctor', 'nurse', 'admisi', 'pharmacy', 'billing', 'management'],
|
||||
title: 'Tambah Laporan',
|
||||
title: 'Tambah Laporan Tindakan',
|
||||
contentFrame: 'cf-container-2xl',
|
||||
})
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ const isoDateTime = z
|
||||
const date = new Date(val)
|
||||
return !isNaN(date.getTime())
|
||||
}, 'Format tanggal / waktu tidak valid')
|
||||
.transform((val) => new Date(val).toISOString())
|
||||
|
||||
const positiveInt = z.coerce.number().int().nonnegative()
|
||||
|
||||
@@ -34,7 +33,7 @@ const OperatorTeamSchema = z.object({
|
||||
})
|
||||
|
||||
const ProcedureSchema = z.object({
|
||||
id: z.number().int().optional(),
|
||||
id: z.number().int(),
|
||||
name: z.string().min(1),
|
||||
code: z.string().min(1),
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user