From 0212b9c39f59557dd9471a8fe623edc71668fb6c Mon Sep 17 00:00:00 2001 From: Andsky Date: Sat, 25 Oct 2025 05:03:48 +0700 Subject: [PATCH 1/2] Feat/encounter status 107 (#129) * dev: hotfix, moved combobox and datepicker * dev: hotfix, moved combobox and datepicker * dev: hotfix, text-size standardization * dev: hotfix, text-size standardization * feat/encounter-status-107: wip * feat/encounter: wip * feat/encounter: done --------- Co-authored-by: Munawwirul Jamal --- .../app/encounter/check-in-entry.vue | 107 ++++++++++ .../app/encounter/check-in-view.vue | 56 ++++++ .../app/encounter/check-out-entry.vue | 187 ++++++++++++++++++ .../app/encounter/check-out-view.vue | 90 +++++++++ app/components/app/encounter/status.vue | 6 - app/components/content/encounter/process.vue | 6 +- app/components/content/encounter/status.vue | 125 ++++++++++++ app/lib/constants.ts | 14 +- app/models/death-cause.ts | 6 + app/models/encounter.ts | 7 +- app/models/internal-reference.ts | 12 ++ app/schemas/encounter.schema.ts | 48 +++++ app/schemas/internal-reference.schema.ts | 12 ++ app/services/doctor.service.ts | 39 ++++ app/services/employee.service.ts | 2 +- app/services/encounter.service.ts | 14 ++ 16 files changed, 718 insertions(+), 13 deletions(-) create mode 100644 app/components/app/encounter/check-in-entry.vue create mode 100644 app/components/app/encounter/check-in-view.vue create mode 100644 app/components/app/encounter/check-out-entry.vue create mode 100644 app/components/app/encounter/check-out-view.vue delete mode 100644 app/components/app/encounter/status.vue create mode 100644 app/components/content/encounter/status.vue create mode 100644 app/models/death-cause.ts create mode 100644 app/models/internal-reference.ts create mode 100644 app/schemas/encounter.schema.ts create mode 100644 app/schemas/internal-reference.schema.ts create mode 100644 app/services/doctor.service.ts diff --git a/app/components/app/encounter/check-in-entry.vue b/app/components/app/encounter/check-in-entry.vue new file mode 100644 index 00000000..ad7de5d6 --- /dev/null +++ b/app/components/app/encounter/check-in-entry.vue @@ -0,0 +1,107 @@ + + + + + \ No newline at end of file diff --git a/app/components/app/encounter/check-in-view.vue b/app/components/app/encounter/check-in-view.vue new file mode 100644 index 00000000..a3b6ab53 --- /dev/null +++ b/app/components/app/encounter/check-in-view.vue @@ -0,0 +1,56 @@ + + + + + \ No newline at end of file diff --git a/app/components/app/encounter/check-out-entry.vue b/app/components/app/encounter/check-out-entry.vue new file mode 100644 index 00000000..fb8b4333 --- /dev/null +++ b/app/components/app/encounter/check-out-entry.vue @@ -0,0 +1,187 @@ + + + + + \ No newline at end of file diff --git a/app/components/app/encounter/check-out-view.vue b/app/components/app/encounter/check-out-view.vue new file mode 100644 index 00000000..37cd2bbe --- /dev/null +++ b/app/components/app/encounter/check-out-view.vue @@ -0,0 +1,90 @@ + + + + + \ No newline at end of file diff --git a/app/components/app/encounter/status.vue b/app/components/app/encounter/status.vue deleted file mode 100644 index e45c0a78..00000000 --- a/app/components/app/encounter/status.vue +++ /dev/null @@ -1,6 +0,0 @@ - - - \ No newline at end of file diff --git a/app/components/content/encounter/process.vue b/app/components/content/encounter/process.vue index 4779f6ec..8179b1ce 100644 --- a/app/components/content/encounter/process.vue +++ b/app/components/content/encounter/process.vue @@ -6,14 +6,14 @@ import { useRoute, useRouter } from 'vue-router' import { getDetail } from '~/services/encounter.service' // Components -import type { Encounter } from '~/models/encounter' import type { TabItem } from '~/components/pub/my-ui/comp-tab/type' import CompTab from '~/components/pub/my-ui/comp-tab/comp-tab.vue' -import AssesmentFunctionList from '~/components/content/soapi/entry.vue' + +import Status from '~/components/content/encounter/status.vue' +import AssesmentFunctionList from '~/components/content/assesment-function/list.vue' import EarlyMedicalAssesmentList from '~/components/content/soapi/entry.vue' import EarlyMedicalRehabList from '~/components/content/soapi/entry.vue' import PrescriptionList from '~/components/content/prescription/list.vue' -import Status from '~/components/app/encounter/status.vue' import Consultation from '~/components/content/consultation/list.vue' const route = useRoute() diff --git a/app/components/content/encounter/status.vue b/app/components/content/encounter/status.vue new file mode 100644 index 00000000..513a7ab5 --- /dev/null +++ b/app/components/content/encounter/status.vue @@ -0,0 +1,125 @@ + + + \ No newline at end of file diff --git a/app/lib/constants.ts b/app/lib/constants.ts index 59dd9bf5..28565a50 100644 --- a/app/lib/constants.ts +++ b/app/lib/constants.ts @@ -67,8 +67,18 @@ export const timeUnitCodes: Record = { } export const dischargeMethodCodes: Record = { - home: 'Home', - 'home-request': 'Home Request', + home: "Pulang", + "home-request": "Pulang Atas Permintaan Sendiri", + "consul-back": "Konsultasi Balik / Lanjutan", + "consul-poly": "Konsultasi Poliklinik Lain", + "consul-executive": "Konsultasi Antar Dokter Eksekutif", + "consul-ch-day": "Konsultasi Hari Lain", + emergency: "Rujuk IGD", + "emergency-covid": "Rujuk IGD Covid", + inpatient: "Rujuk Rawat Inap", + external: "Rujuk Faskes Lain", + death: "Meninggal", + "death-on-arrival": "Meninggal Saat Tiba" } export const genderCodes: Record = { diff --git a/app/models/death-cause.ts b/app/models/death-cause.ts new file mode 100644 index 00000000..0f04609a --- /dev/null +++ b/app/models/death-cause.ts @@ -0,0 +1,6 @@ +export interface DeathCause { + id: bigint; + encounter_id: bigint; + value: any; // json mapped to 'any' type +} + \ No newline at end of file diff --git a/app/models/encounter.ts b/app/models/encounter.ts index 681a2ac9..fb2c0b04 100644 --- a/app/models/encounter.ts +++ b/app/models/encounter.ts @@ -1,5 +1,7 @@ +import type { DeathCause } from "./death-cause" import { type Doctor, genDoctor } from "./doctor" import { genEmployee, type Employee } from "./employee" +import type { InternalReference } from "./internal-reference" import { type Patient, genPatient } from "./patient" import type { Specialist } from "./specialist" import type { Subspecialist } from "./subspecialist" @@ -29,8 +31,11 @@ export interface Encounter { earlyEducation?: string medicalDischargeEducation: string admDischargeEducation?: string - dischargeMethod_code?: string + discharge_method_code?: string discharge_reason?: string + discharge_date?: string + internalReferences?: InternalReference[] + deathCause?: DeathCause status_code: string } diff --git a/app/models/internal-reference.ts b/app/models/internal-reference.ts new file mode 100644 index 00000000..8af315a8 --- /dev/null +++ b/app/models/internal-reference.ts @@ -0,0 +1,12 @@ +export interface InternalReference { + id: number; + encounter_id: number; + unit_id: number; // smallint mapped to number + doctor_id: number; // int mapped to number +} + +export interface CreateDto { + encounter_id: number; + unit_id: number; // smallint mapped to number + doctor_id: number; // int mapped to number +} \ No newline at end of file diff --git a/app/schemas/encounter.schema.ts b/app/schemas/encounter.schema.ts new file mode 100644 index 00000000..e3c9affc --- /dev/null +++ b/app/schemas/encounter.schema.ts @@ -0,0 +1,48 @@ +import { z } from 'zod' +import { InternalReferenceSchema } from './internal-reference.schema' + +// Check In +const CheckInSchema = z.object({ + // registeredAt: z.string({ required_error: 'Tanggal masuk harus diisi' }), + responsible_doctor_id: z.number({ required_error: 'Dokter harus diisi' }).gt(0, 'Dokter harus diisi'), + adm_employee_id: z.number({ required_error: 'PJA harus diisi' }).gt(0, 'PJA harus diisi'), +}) +type CheckInFormData = z.infer + +// Checkout +const CheckOutSchema = z.object({ + discharge_method_code: z.string({ required_error: 'Metode pulang harus diisi' }), + discharge_date: z.string({ required_error: 'Tanggal pulang harus diisi' }), +}) +type CheckOutFormData = z.infer + +// CheckoutDeath +const CheckOutDeathSchema = z.object({ + discharge_method_code: z.string({ required_error: 'Metode pulang harus diisi' }), + discharge_date: z.string({ required_error: 'Tanggal pulang harus diisi' }), + death_cause: z.array(z.string()).nonempty(), +}) +type CheckOutDeathFormData = z.infer + +// CheckoutDeath +const CheckOutInternalReferenceSchema = z.object({ + discharge_method_code: z.string({ required_error: 'Metode pulang harus diisi' }), + discharge_date: z.string({ required_error: 'Tanggal pulang harus diisi' }), + internalReferences: z.array(InternalReferenceSchema).nonempty(), +}) +type CheckOutInternalReferenceFormData = z.infer + + +// Exports +export { + CheckInSchema, + CheckOutSchema, + CheckOutDeathSchema, + CheckOutInternalReferenceSchema +} +export type { + CheckInFormData, + CheckOutFormData, + CheckOutDeathFormData, + CheckOutInternalReferenceFormData +} diff --git a/app/schemas/internal-reference.schema.ts b/app/schemas/internal-reference.schema.ts new file mode 100644 index 00000000..eae75319 --- /dev/null +++ b/app/schemas/internal-reference.schema.ts @@ -0,0 +1,12 @@ +import { z } from 'zod' +import type { InternalReference } from '~/models/internal-reference' + +const InternalReferenceSchema = z.object({ + 'unit_id': z.number({ required_error: 'Kode harus diisi' }).min(1, 'Kode minimum 1 karakter'), + 'doctor_id': z.number({ required_error: 'Kode harus diisi' }).min(1, 'Kode minimum 1 karakter'), +}) + +type InternalReferenceFormData = z.infer & Partial + +export { InternalReferenceSchema } +export type { InternalReferenceFormData } diff --git a/app/services/doctor.service.ts b/app/services/doctor.service.ts new file mode 100644 index 00000000..64ab22e9 --- /dev/null +++ b/app/services/doctor.service.ts @@ -0,0 +1,39 @@ +// Base +import * as base from './_crud-base' +import type { Doctor } from "~/models/doctor"; + +const path = '/api/v1/doctor' +const name = 'device' + +export function create(data: any) { + return base.create(path, data, name) +} + +export function getList(params: any = null) { + return base.getList(path, params, name) +} + +export function getDetail(id: number | string) { + return base.getDetail(path, id, name) +} + +export function update(id: number | string, data: any) { + return base.update(path, id, data, name) +} + +export function remove(id: number | string) { + return base.remove(path, id, name) +} + +export async function getValueLabelList(params: any = null): Promise<{ value: string; label: string }[]> { + let data: { value: string; label: string }[] = [] + const result = await getList(params) + if (result.success) { + const resultData = result.body?.data || [] + data = resultData.map((item: Doctor) => ({ + value: item.id, + label: item.employee.person.name, + })) + } + return data +} diff --git a/app/services/employee.service.ts b/app/services/employee.service.ts index d3691c83..366ef71e 100644 --- a/app/services/employee.service.ts +++ b/app/services/employee.service.ts @@ -31,7 +31,7 @@ export async function getValueLabelList(params: any = null): Promise<{ value: st const resultData = result.body?.data || [] data = resultData.map((item: any) => ({ value: item.id ? Number(item.id) : item.code, - label: item.name, + label: item.person.name, })) } return data diff --git a/app/services/encounter.service.ts b/app/services/encounter.service.ts index cd7c28ed..6e42fd41 100644 --- a/app/services/encounter.service.ts +++ b/app/services/encounter.service.ts @@ -1,4 +1,5 @@ // Base +import type { CheckInFormData } from '~/schemas/encounter.schema' import * as base from './_crud-base' // Constants @@ -46,3 +47,16 @@ export function getValueLabelListConstants() { .filter(([key]) => allowed.includes(key)) .map(([key, value]) => ({ value: key, label: value })) } + +export async function checkIn(id: number, data: CheckInFormData) { + try { + const resp = await xfetch(`${path}/${id}/check-in`, 'PATCH', data) + const result: any = {} + result.success = resp.success + result.body = (resp.body as Record) || {} + return result + } catch (error) { + console.error(`Error putting ${name}:`, error) + throw new Error(`Failed to put ${name}`) + } +} \ No newline at end of file From e93e72a78026423cd54ff6c67f5ccaf70bf3995e Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Sat, 25 Oct 2025 05:05:53 +0700 Subject: [PATCH 2/2] dev: chore, note on encounter process --- app/components/content/encounter/process.vue | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/components/content/encounter/process.vue b/app/components/content/encounter/process.vue index 8179b1ce..71c7fe3d 100644 --- a/app/components/content/encounter/process.vue +++ b/app/components/content/encounter/process.vue @@ -5,10 +5,11 @@ import { useRoute, useRouter } from 'vue-router' import { getDetail } from '~/services/encounter.service' -// Components +// import type { TabItem } from '~/components/pub/my-ui/comp-tab/type' import CompTab from '~/components/pub/my-ui/comp-tab/comp-tab.vue' +// PLASE ORDER BY TAB POSITION import Status from '~/components/content/encounter/status.vue' import AssesmentFunctionList from '~/components/content/assesment-function/list.vue' import EarlyMedicalAssesmentList from '~/components/content/soapi/entry.vue'