feat/role-check: updat flow for input encounter

This commit is contained in:
2025-12-15 12:10:04 +07:00
parent 49ffad1dde
commit bd48cc5907
13 changed files with 1163 additions and 499 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
# Build Stage
FROM node:20-alpine AS build-stage
FROM node:24-alpine AS build-stage
# Set the working directory inside the container
WORKDIR /app
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,476 @@
<script setup lang="ts">
import type { FormErrors } from '~/types/error'
import { Form } from '~/components/pub/ui/form'
import { toTypedSchema } from '@vee-validate/zod'
import Block from '~/components/pub/my-ui/form/block.vue'
import Combobox from '~/components/pub/my-ui/combobox/combobox.vue'
import FieldGroup from '~/components/pub/my-ui/form/field-group.vue'
import Field from '~/components/pub/my-ui/form/field.vue'
import Label from '~/components/pub/my-ui/form/label.vue'
import { educationCodes, genderCodes, occupationCodes, religionCodes } from '~/lib/constants'
import { mapToComboboxOptList } from '~/lib/utils'
interface DivisionFormData {
name: string
code: string
parentId: string
}
const props = defineProps<{
division: {
msg: {
placeholder: string
search: string
empty: string
}
}
items: {
value: string
label: string
code: string
}[]
schema: any
initialValues?: Partial<DivisionFormData>
errors?: FormErrors
}>()
const emit = defineEmits<{
submit: [values: DivisionFormData, resetForm: () => void]
cancel: [resetForm: () => void]
}>()
const educationOpts = mapToComboboxOptList(educationCodes)
const occupationOpts = mapToComboboxOptList(occupationCodes)
const religionOpts = mapToComboboxOptList(religionCodes)
const genderOpts = mapToComboboxOptList(genderCodes)
const formSchema = toTypedSchema(props.schema)
// Form submission handler
function onSubmitForm(values: any, { resetForm }: { resetForm: () => void }) {
const formData: DivisionFormData = {
name: values.name || '',
code: values.code || '',
parentId: values.parentId || '',
}
emit('submit', formData, resetForm)
}
</script>
<template>
<Form
v-slot="{ handleSubmit, resetForm }"
as=""
keep-values
:validation-schema="formSchema"
:initial-values="initialValues"
>
<form
id="entry-form"
@submit="handleSubmit($event, (values) => onSubmitForm(values, { resetForm }))"
>
<div class="mb-5 border-b border-b-slate-300 pb-3 text-lg xl:text-xl">
<div class="flex flex-col justify-between">
<Block>
<FieldGroup>
<Label label-for="residentIdentityNumber">KTP</Label>
<Field
id="residentIdentityNumber"
:errors="errors"
>
<FormField
v-slot="{ componentField }"
name="residentIdentityNumber"
>
<FormItem>
<FormControl>
<Input
id="residentIdentityNumber"
type="text"
maxlength="16"
placeholder="Nomor KTP"
autocomplete="off"
v-bind="componentField"
/>
</FormControl>
<FormMessage />
</FormItem>
</FormField>
</Field>
</FieldGroup>
<!-- FrontTitle -->
<FieldGroup :column="3">
<Label label-for="frontTitle">Gelar Depan</Label>
<Field
id="frontTitle"
:errors="errors"
>
<FormField
v-slot="{ componentField }"
name="frontTitle"
>
<FormItem>
<FormControl>
<Input
id="frontTitle"
type="text"
placeholder="Dr., Ir., dll"
autocomplete="off"
v-bind="componentField"
/>
</FormControl>
<FormMessage />
</FormItem>
</FormField>
</Field>
</FieldGroup>
<FieldGroup :column="3">
<Label
label-for="name"
position="dynamic"
>
Nama
</Label>
<Field
id="name"
:errors="errors"
>
<FormField
v-slot="{ componentField }"
name="name"
>
<FormItem>
<FormControl>
<Input
id="name"
type="text"
placeholder="Nama lengkap"
autocomplete="off"
v-bind="componentField"
/>
</FormControl>
<FormMessage />
</FormItem>
</FormField>
</Field>
</FieldGroup>
<!-- EndTitle -->
<FieldGroup :column="3">
<Label
label-for="endTitle"
position="dynamic"
>
Gelar Belakang
</Label>
<Field
id="endTitle"
:errors="errors"
>
<FormField
v-slot="{ componentField }"
name="endTitle"
>
<FormItem>
<FormControl>
<Input
id="endTitle"
type="text"
placeholder="S.Kom, M.Kes, dll"
autocomplete="off"
v-bind="componentField"
/>
</FormControl>
<FormMessage />
</FormItem>
</FormField>
</Field>
</FieldGroup>
<!-- BirthDate -->
<FieldGroup :column="2">
<Label label-for="birthDate">Tanggal Lahir</Label>
<Field
id="birthDate"
:errors="errors"
>
<FormField
v-slot="{ componentField }"
name="birthDate"
>
<FormItem>
<FormControl>
<Input
id="birthDate"
type="date"
v-bind="componentField"
/>
</FormControl>
<FormMessage />
</FormItem>
</FormField>
</Field>
</FieldGroup>
<!-- BirthRegency_Code -->
<FieldGroup :column="2">
<Label label-for="birthRegencyCode">Tempat Lahir</Label>
<Field
id="birthRegencyCode"
:errors="errors"
>
<FormField
v-slot="{ componentField }"
name="birthRegencyCode"
>
<FormItem>
<FormControl>
<Combobox
id="parentId"
v-bind="componentField"
:items="educationOpts"
/>
</FormControl>
<FormMessage />
</FormItem>
</FormField>
</Field>
</FieldGroup>
<!-- Gender_Code -->
<FieldGroup>
<Label label-for="genderCode">Jenis Kelamin</Label>
<Field
id="genderCode"
:errors="errors"
>
<FormField
v-slot="{ componentField }"
name="genderCode"
>
<FormItem>
<FormControl>
<Combobox
id="genderCode"
v-bind="componentField"
:items="genderOpts"
/>
</FormControl>
<FormMessage />
</FormItem>
</FormField>
</Field>
</FieldGroup>
<!-- PassportNumber -->
<FieldGroup :column="2">
<Label label-for="passportNumber">Paspor</Label>
<Field
id="passportNumber"
:errors="errors"
>
<FormField
v-slot="{ componentField }"
name="passportNumber"
>
<FormItem>
<FormControl>
<Input
id="passportNumber"
type="text"
placeholder="Nomor Paspor"
autocomplete="off"
v-bind="componentField"
/>
</FormControl>
<FormMessage />
</FormItem>
</FormField>
</Field>
</FieldGroup>
<!-- DrivingLicenseNumber -->
<FieldGroup :column="2">
<Label label-for="drivingLicenseNumber">SIM</Label>
<Field
id="drivingLicenseNumber"
:errors="errors"
>
<FormField
v-slot="{ componentField }"
name="drivingLicenseNumber"
>
<FormItem>
<FormControl>
<Input
id="drivingLicenseNumber"
type="text"
placeholder="Nomor SIM"
autocomplete="off"
v-bind="componentField"
/>
</FormControl>
<FormMessage />
</FormItem>
</FormField>
</Field>
</FieldGroup>
<!-- Religion_Code -->
<FieldGroup :column="2">
<Label label-for="religionCode">Agama</Label>
<Field
id="religionCode"
:errors="errors"
>
<FormField
v-slot="{ componentField }"
name="religionCode"
>
<FormItem>
<FormControl>
<Combobox
id="religionCode"
v-bind="componentField"
:items="religionOpts"
/>
</FormControl>
<FormMessage />
</FormItem>
</FormField>
</Field>
</FieldGroup>
<FieldGroup :column="2">
<Label label-for="ethnicCode">Suku</Label>
<Field
id="ethnicCode"
:errors="errors"
>
<FormField
v-slot="{ componentField }"
name="ethnicCode"
>
<FormItem>
<FormControl>
<Combobox
id="ethnicCode"
v-bind="componentField"
:items="occupationOpts"
/>
</FormControl>
<FormMessage />
</FormItem>
</FormField>
</Field>
</FieldGroup>
<!-- Language_Code -->
<FieldGroup :column="2">
<Label label-for="languageCode">Bahasa</Label>
<Field
id="languageCode"
:errors="errors"
>
<FormField
v-slot="{ componentField }"
name="languageCode"
>
<FormItem>
<FormControl>
<Combobox
id="parentId"
v-bind="componentField"
:items="educationOpts"
/>
</FormControl>
<FormMessage />
</FormItem>
</FormField>
</Field>
</FieldGroup>
<!-- Education_Code -->
<FieldGroup :column="2">
<Label label-for="educationCode">Pendidikan</Label>
<Field
id="educationCode"
:errors="errors"
>
<FormField
v-slot="{ componentField }"
name="educationCode"
>
<FormItem>
<FormControl>
<Combobox
id="educationCode"
v-bind="componentField"
:items="educationOpts"
/>
</FormControl>
<FormMessage />
</FormItem>
</FormField>
</Field>
</FieldGroup>
<!-- Occupation_Code -->
<FieldGroup :column="2">
<Label label-for="occupationCode">Pekerjaan</Label>
<Field
id="occupationCode"
:errors="errors"
>
<FormField
v-slot="{ componentField }"
name="occupationCode"
>
<FormItem>
<FormControl>
<Combobox
id="occupationCode"
v-bind="componentField"
:items="occupationOpts"
/>
</FormControl>
<FormMessage />
</FormItem>
</FormField>
</Field>
</FieldGroup>
<!-- Occupation_Name -->
<FieldGroup :column="2">
<Label label-for="occupationName">Detail Pekerjaan</Label>
<Field
id="occupationName"
:errors="errors"
>
<FormField
v-slot="{ componentField }"
name="occupationName"
>
<FormItem>
<FormControl>
<Input
id="occupationName"
type="text"
placeholder="Contoh: Guru SMP, Petani"
autocomplete="off"
v-bind="componentField"
/>
</FormControl>
<FormMessage />
</FormItem>
</FormField>
</Field>
</FieldGroup>
</Block>
</div>
</div>
</form>
</Form>
</template>
+8 -5
View File
@@ -15,13 +15,14 @@ import { useIntegrationSepEntry } from '~/handlers/integration-sep-entry.handler
// Props
const props = defineProps<{
id: number
classCode?: 'ambulatory' | 'emergency' | 'inpatient' | 'outpatient'
subclassCode?: 'reg' | 'rehab' | 'chemo' | 'emg' | 'eon' | 'op' | 'icu' | 'hcu' | 'vk'
classCode?: 'ambulatory' | 'emergency' | 'inpatient'
subclassCode?: 'regular' | 'rehab' | 'chemo' | 'emg' | 'eon' | 'op' | 'icu' | 'hcu' | 'vk'
formType: string
}>()
const route = useRoute()
const formRef = ref<InstanceType<typeof AppEncounterEntryForm> | null>(null)
// const patientMode = ref<'new' | 'exists'>('exists')
const {
paymentsList,
@@ -56,7 +57,6 @@ const {
getDoctorInfo,
getValidateMember,
getValidateSepNumber,
handleFetchDoctors,
} = useEncounterEntry(props)
const { recSepId, openHistory, histories, getMonitoringHistoryMappers } = useIntegrationSepEntry()
@@ -82,11 +82,13 @@ function handleFetch(value?: any) {
async function handleEvent(menu: string, value?: any) {
if (menu === 'search') {
// patientMode.value = 'exists'
getPatientsList({ 'page-size': 10, includes: 'person' }).then(() => {
openPatient.value = true
})
} else if (menu === 'add') {
navigateTo('/client/patient/add')
// navigateTo('/client/patient/add')
// patientMode.value = 'new'
} else if (menu === 'add-sep') {
if (isSepValid.value) {
return
@@ -167,6 +169,7 @@ onMounted(async () => {
Kunjungan
</div>
<!-- :patientMode="patientMode" -->
<AppEncounterEntryForm
ref="formRef"
:mode="props.formType"
@@ -226,10 +229,10 @@ onMounted(async () => {
/>
Batal
</Button>
<!-- :disabled="isSaveDisabled" -->
<Button
type="button"
class="h-[40px] min-w-[120px] text-white"
:disabled="isSaveDisabled"
@click="handleSaveClick"
>
<Icon
+7 -4
View File
@@ -35,7 +35,7 @@ import FilterForm from '~/components/app/encounter/filter-form.vue'
// Props
const props = defineProps<{
classCode?: 'ambulatory' | 'emergency' | 'inpatient'
subclassCode?: 'reg' | 'rehab' | 'chemo' | 'emg' | 'eon' | 'op' | 'icu' | 'hcu' | 'vk'
subclassCode?: 'regular' | 'rehab' | 'chemo' | 'emg' | 'eon' | 'op' | 'icu' | 'hcu' | 'vk' | undefined
canCreate?: boolean
canUpdate?: boolean
canDelete?: boolean
@@ -162,7 +162,6 @@ async function getPatientList() {
'Responsible_Doctor-employee',
'Responsible_Doctor-employee-person',
'EncounterDocuments',
'unit',
'vclaimReference', // vclaimReference | vclaimSep
]
const includesParams = includesParamsArrays.join(',')
@@ -172,8 +171,11 @@ async function getPatientList() {
if (props.classCode) {
params['class-code'] = props.classCode
}
if (props.subclassCode) {
params['subclass-code'] = props.subclassCode
if (props.subclassCode == 'regular') {
params['specialist-code'] = 'rehab'
params['specialist-code-opt'] = 'ne'
} else {
params['specialist-code'] = 'rehab'
}
const result = await getEncounterList(params)
if (result.success) {
@@ -365,6 +367,7 @@ function handleRemoveConfirmation() {
</script>
<template>
{{ subclassCode }}
<CH.ContentHeader v-bind="hreaderPrep">
<FilterNav
:active-positon="activeServicePosition"
+46 -32
View File
@@ -24,6 +24,7 @@ import {
import { getDetail as getDoctorDetail, getValueLabelList as getDoctorValueLabelList } from '~/services/doctor.service'
import {
create as createEncounter,
createWithPatient,
getDetail as getEncounterDetail,
update as updateEncounter,
} from '~/services/encounter.service'
@@ -510,15 +511,18 @@ export function useEncounterEntry(props: {
}
async function handleSaveEncounter(formValues: any) {
console.log(formValues)
return
if (!selectedPatient.value || !selectedPatientObject.value) {
toast({
title: 'Gagal',
description: 'Pasien harus dipilih terlebih dahulu',
variant: 'destructive',
})
return
let enccounterRef = formValues
if (!formValues.encounter) {
if (!selectedPatient.value || !selectedPatientObject.value) {
toast({
title: 'Gagal',
description: 'Pasien harus dipilih terlebih dahulu',
variant: 'destructive',
})
return
}
} else {
enccounterRef = {...formValues.encounter}
}
try {
@@ -532,24 +536,24 @@ export function useEncounterEntry(props: {
return date.toISOString()
}
const { specialist_id, subspecialist_id } = getSpecialistIdsFromCode(formValues.subSpecialistId || '')
const { specialist_id, subspecialist_id } = getSpecialistIdsFromCode(enccounterRef.subSpecialistId || '')
const patientId = formValues.patient_id || selectedPatientObject.value?.id || Number(selectedPatient.value)
const patientId = enccounterRef.patient_id || selectedPatientObject.value?.id || Number(selectedPatient.value)
const registeredAtValue = formValues.registeredAt || formValues.registerDate || ''
const visitDateValue = formValues.visitDate || formValues.registeredAt || formValues.registerDate || ''
const memberNumber = formValues.member_number ?? formValues.cardNumber ?? formValues.memberNumber ?? null
const refNumber = formValues.ref_number ?? formValues.sepNumber ?? formValues.refNumber ?? null
sepFile.value = formValues.sepFile || null
sippFile.value = formValues.sippFile || null
const registeredAtValue = enccounterRef.registeredAt || enccounterRef.registerDate || ''
const visitDateValue = enccounterRef.visitDate || enccounterRef.registeredAt || enccounterRef.registerDate || ''
const memberNumber = enccounterRef.member_number ?? enccounterRef.cardNumber ?? enccounterRef.memberNumber ?? null
const refNumber = enccounterRef.ref_number ?? enccounterRef.sepNumber ?? enccounterRef.refNumber ?? null
sepFile.value = enccounterRef.sepFile || null
sippFile.value = enccounterRef.sippFile || null
let paymentMethodCode = formValues.paymentMethod_code ?? null
let paymentMethodCode = enccounterRef.paymentMethod_code ?? null
if (!isUsePaymentNew && !paymentMethodCode) {
if (formValues.paymentType === 'jkn' || formValues.paymentType === 'jkmm') {
if (enccounterRef.paymentType === 'jkn' || enccounterRef.paymentType === 'jkmm') {
paymentMethodCode = 'insurance'
} else if (formValues.paymentType === 'spm') {
} else if (enccounterRef.paymentType === 'spm') {
paymentMethodCode = 'cash'
} else if (formValues.paymentType === 'pks') {
} else if (enccounterRef.paymentType === 'pks') {
paymentMethodCode = 'membership'
} else {
paymentMethodCode = 'cash'
@@ -558,16 +562,16 @@ export function useEncounterEntry(props: {
const payload: any = {
patient_id: patientId,
appointment_doctor_code: formValues.doctor_code || null,
appointment_doctor_code: enccounterRef.doctor_code || null,
class_code: props.classCode || '',
subClass_code: props.subclassCode || '',
specialist_code: selectedDoctor.value?.specialist_code || '',
infra_id: formValues.infra_id ?? null,
unit_code: formValues.unitCode ?? userStore?.user?.unit_code ?? null,
refSource_name: formValues.refSource_name ?? 'RSSA',
refTypeCode: formValues.paymentType === 'jkn' ? 'bpjs' : '',
infra_id: enccounterRef.infra_id ?? null,
unit_code: enccounterRef.unitCode ?? userStore?.user?.unit_code ?? null,
refSource_name: enccounterRef.refSource_name ?? 'RSSA',
refTypeCode: enccounterRef.paymentType === 'jkn' ? 'bpjs' : '',
vclaimReference: vclaimReference.value ?? null,
paymentType: formValues.paymentType,
paymentType: enccounterRef.paymentType,
registeredAt: formatDate(registeredAtValue),
visitDate: formatDate(visitDateValue),
}
@@ -594,10 +598,10 @@ export function useEncounterEntry(props: {
}
if (paymentMethodCode === 'insurance') {
payload.insuranceCompany_id = formValues.insuranceCompany_id ?? null
payload.insuranceCompany_id = enccounterRef.insuranceCompany_id ?? null
if (memberNumber) payload.member_number = memberNumber
if (formValues.refTypeCode) payload.refTypeCode = formValues.refTypeCode
if (formValues.vclaimReference) payload.vclaimReference = formValues.vclaimReference
if (enccounterRef.refTypeCode) payload.refTypeCode = enccounterRef.refTypeCode
if (enccounterRef.vclaimReference) payload.vclaimReference = enccounterRef.vclaimReference
} else {
if (paymentMethodCode === 'membership' && memberNumber) {
payload.member_number = memberNumber
@@ -613,8 +617,18 @@ export function useEncounterEntry(props: {
if (isEditMode.value) {
result = await updateEncounter(props.id, payload)
} else {
console.log('💾 [ADD MODE] Sending POST request:', { payload })
result = await createEncounter(payload)
// console.log('💾 [ADD MODE] Sending POST request:', { payload })
if (!formValues.encounter) {
result = await createEncounter(payload)
} else {
if (formValues.patient?.person?.birthDate) {
formValues.patient.person.birthDate += 'T00:00:00.000Z'
}
result = await createWithPatient({
encounter: payload,
patient: formValues.patient,
})
}
}
if (result.success) {
+15
View File
@@ -5,6 +5,10 @@ import type { EncounterDocument } from "./encounter-document"
import type { InternalReference } from "./internal-reference"
import type { Nurse } from "./nurse"
import { type Patient, genPatient } from "./patient"
import type { Person } from "./person"
import type { PersonAddress } from "./person-address"
import type { PersonContact } from "./person-contact"
import type { PersonRelative } from "./person-relative"
import type { Specialist } from "./specialist"
import type { Subspecialist } from "./subspecialist"
import { genUnit, type Unit } from "./unit"
@@ -45,6 +49,16 @@ export interface Encounter {
encounterDocuments: EncounterDocument[]
}
export interface CreateDtoWithPatient {
encounter: Encounter
patient: {
person: Person
personAddresses: PersonAddress[]
personContacts: PersonContact[]
personRelatives: PersonRelative[]
}
}
export function genEncounter(): Encounter {
return {
id: 0,
@@ -62,6 +76,7 @@ export function genEncounter(): Encounter {
medicalDischargeEducation: '',
status_code: '',
encounterDocuments: [],
}
}
@@ -32,29 +32,26 @@ const hasAccess = getPageAccess(roleAccess, 'create')
// TODO: Make a function for this
const { user } = useUserStore()
const servicePosition = user.user_contractPosition_code == 'emp' ? getServicePosition('emp|'+user.employee_position_code) : null
const servicePosition = user.user_contractPosition_code == 'emp' ? getServicePosition(user.activeRole) : null
const subClassCode = servicePosition == 'med' ?
// medic
(user.unit_code == 'rehab' ? 'rehab' : 'reg') :
(user.specialist_code == 'rehab' ? 'rehab' : 'regular') :
// non medic
(
user.employee_position_code == 'reg' ?
(user.installation_code == 'rehab' ? 'rehab' : 'reg') :
servicePosition == 'reg' ?
(user.installation_code == 'rehab' ? 'rehab' : 'regular') :
undefined
)
</script>
<template>
<div v-if="hasAccess">
<Content
:id="0"
class-code="ambulatory"
:subclass-code="subClassCode"
form-type="add"
/>
</div>
<Error
v-else
<Content v-if="hasAccess"
:id="0"
class-code="ambulatory"
:subclass-code="subClassCode"
form-type="add"
/>
<Error v-else
:status-code="403"
/>
</template>
@@ -39,24 +39,23 @@ const canRemove = getPageAccess(roleAccess, 'delete')
// User info
const { user } = useUserStore()
// TODO: Make a function for this
const servicePosition = user.user_contractPosition_code == 'emp' ? getServicePosition('emp|'+user.employee_position_code) : null
const servicePosition = user.user_contractPosition_code == 'emp' ? getServicePosition(user.activeRole) : null
const subClassCode = servicePosition == 'med' ?
// medic
(user.unit_code == 'rehab' ? 'rehab' : 'reg') :
(user.specialist_code == 'rehab' ? 'rehab' : 'regular') :
// non medic
(
user.employee_position_code == 'reg' ?
(user.installation_code == 'rehab' ? 'rehab' : 'reg') :
servicePosition == 'reg' ?
(user.installation_code == 'rehab' ? 'rehab' : 'regular') :
undefined
)
</script>
<template>
<div>
{{ user.employee_position_code }}---<br />
{{ servicePosition }}---<br />
{{ subClassCode }}---
<div v-if="hasAccess">
{{ servicePosition }}--
{{ subClassCode }}--
<Content
class-code="ambulatory"
:subclass-code="subClassCode"
+19 -2
View File
@@ -1,5 +1,9 @@
import { isValid } from "date-fns"
import { z } from 'zod'
import { PatientSchema } from "./patient.schema"
import { PersonAddressSchema } from "./person-address.schema"
import { PersonContactBaseSchema } from "./person-contact.schema"
import { PersonAddressRelativeSchema } from "./person-address-relative.schema"
const ERROR_MESSAGES = {
required: {
@@ -132,8 +136,21 @@ const IntegrationEncounterSchema = z
},
)
const IntegrationEncounterWPSchema = z
.object({
encounter: IntegrationEncounterSchema,
patient: z.object({
person: PatientSchema,
personAddresses: z.array(PersonAddressSchema),
personContacts: z.array(PersonContactBaseSchema),
personRelatives: z.array(PersonAddressRelativeSchema),
}),
})
type IntegrationEncounterFormData = z.infer<typeof IntegrationEncounterSchema>
type IntegrationEncounterWPFormData = z.infer<typeof IntegrationEncounterWPSchema>
export { IntegrationEncounterSchema }
export type { IntegrationEncounterFormData }
export { IntegrationEncounterSchema, IntegrationEncounterWPSchema }
export type { IntegrationEncounterFormData, IntegrationEncounterWPFormData }
+2 -1
View File
@@ -102,7 +102,8 @@ const PatientSchema = z
(data) => {
if (data.nationality === 'WNI') {
const nik = data.identityNumber?.trim()
return !!nik && nik.length === 16 && /^\d+$/.test(nik)
if (!nik) return true
return nik && nik.length === 16 && /^\d+$/.test(nik)
}
return true
},
+13
View File
@@ -65,3 +65,16 @@ export async function checkIn(id: number, data: CheckInFormData) {
throw new Error(`Failed to put ${name}`)
}
}
export async function createWithPatient(data: any) {
try {
const resp = await xfetch(path + '/create-with-patient', 'POST', data)
const result: any = {}
result.success = resp.success
result.body = (resp.body as Record<string, any>) || {}
return result
} catch (error) {
console.error(`Error putting ${name}:`, error)
throw new Error(`Failed to put ${name}`)
}
}