diff --git a/app/models/_base.ts b/app/models/_base.ts
index 6aaa99fc..ed6f7204 100644
--- a/app/models/_base.ts
+++ b/app/models/_base.ts
@@ -1,4 +1,3 @@
-
export interface Base {
id: number
createdAt: string | null
@@ -20,7 +19,9 @@ export interface TreeItem {
export function genBase(): Base {
return {
- id: 0,
+ // -1 buat mock data
+ // backend harusnya non-negative/ > 0 (untuk auto increment constraint) jadi harusnya aman ya
+ id: -1,
createdAt: '',
updatedAt: '',
}
diff --git a/app/models/doctor.ts b/app/models/doctor.ts
index 297f9372..17c4f803 100644
--- a/app/models/doctor.ts
+++ b/app/models/doctor.ts
@@ -1,8 +1,8 @@
-import { type Base, genBase } from "./_base"
-import { type Employee, genEmployee } from "./employee"
-import type { Unit } from "./unit"
-import type { Specialist } from "./specialist"
-import type { Subspecialist } from "./subspecialist"
+import { type Base, genBase } from './_base'
+import { type Employee, genEmployee } from './employee'
+import type { Unit } from './unit'
+import type { Specialist } from './specialist'
+import type { Subspecialist } from './subspecialist'
export interface Doctor extends Base {
employee_id: number
diff --git a/app/models/person.ts b/app/models/person.ts
index 06b313b8..f2c400b6 100644
--- a/app/models/person.ts
+++ b/app/models/person.ts
@@ -1,7 +1,7 @@
-import { type Base, genBase } from "./_base"
-import type { PersonAddress } from "./person-address"
-import type { PersonContact } from "./person-contact"
-import type { PersonRelative } from "./person-relative"
+import { type Base, genBase } from './_base'
+import type { PersonAddress } from './person-address'
+import type { PersonContact } from './person-contact'
+import type { PersonRelative } from './person-relative'
import type { Ethnic } from './ethnic'
import type { Language } from './language'
import type { Regency } from './regency'
@@ -43,6 +43,15 @@ export interface Person extends Base {
export function genPerson(): Person {
return {
...genBase(),
- name: '',
+ frontTitle: '[MOCK] dr. ',
+ name: 'Agus Iwan Setiawan',
+ endTitle: 'Sp.Bo',
}
}
+
+export function parseName(person: Person): string {
+ if (!person) return ''
+ const fullName = [person.frontTitle, person.name, person.endTitle].filter(Boolean).join(' ').trim()
+
+ return fullName
+}
diff --git a/app/schemas/action-report.schema.ts b/app/schemas/action-report.schema.ts
new file mode 100644
index 00000000..cd23eb28
--- /dev/null
+++ b/app/schemas/action-report.schema.ts
@@ -0,0 +1,121 @@
+import { z } from 'zod'
+
+const isoDateTime = z
+ .string()
+ .min(1, 'Tanggal / waktu wajib diisi')
+ .refine((val) => {
+ const date = new Date(val)
+ return !isNaN(date.getTime())
+ }, 'Format tanggal / waktu tidak valid')
+
+const positiveInt = z.coerce.number().int().nonnegative()
+
+const OperatorTeamSchema = z.object({
+ dpjpId: z.coerce
+ .number({
+ invalid_type_error: 'Silahkan pilih dpjp terlebih dahulu',
+ })
+ .int(),
+ operatorName: z.string({
+ required_error: 'Masukkan nama operator',
+ }),
+ assistantOperatorName: z.string({
+ required_error: 'Masukkan nama asisten operator',
+ }),
+ instrumentNurseName: z.string({
+ required_error: 'Masukkan nama instrumentir',
+ }),
+
+ surgeryDate: isoDateTime,
+ actionDiagnosis: z.string(),
+
+ postSurgeryNurseId: z.number().int().optional().nullable(),
+})
+
+const ProcedureSchema = z.object({
+ id: z.number().int(),
+ name: z.string().min(1),
+ code: z.string().min(1),
+})
+
+const OperationExecutionSchema = z.object({
+ surgeryType: z.enum(['kecil', 'sedang', 'besar', 'khusus'], { required_error: 'Silahkan pilih jenis operasi' }),
+ billingCode: z.string({
+ required_error: 'Silahkan pilih kode billing',
+ }),
+ operationSystem: z.enum(['khusus', 'cito', 'efektif', 'urgent'], { required_error: 'Silahkan pilih sistem operasi' }),
+
+ operationStartAt: isoDateTime,
+ operationEndAt: isoDateTime,
+
+ anesthesiaStartAt: isoDateTime,
+ anesthesiaEndAt: isoDateTime,
+
+ surgeryCleanType: z.enum(['bersih', 'bersih_terkontaminasi', 'terkontaminasi', 'kotor']).optional(),
+ surgeryNumber: z.enum(['first', 'retry']).optional(),
+
+ birthPlaceNote: z.string().optional(),
+ personWeight: positiveInt.optional(),
+ birthCondition: z.string().optional(),
+
+ operationDescription: z.string({
+ required_error: 'Mohon lengkapi uraian operasi',
+ }),
+
+ bleedingAmountCc: positiveInt.optional(),
+
+ birthRemark: z.enum(['lahir_hidup', 'lahir_mati']).optional(),
+})
+
+const BloodInputSchema = z
+ .object({
+ type: z.enum(['prc', 'wb', 'ffp', 'tc']),
+ amount: z.object({
+ prc: z.coerce.number().optional(),
+ wb: z.coerce.number().optional(),
+ ffp: z.coerce.number().optional(),
+ tc: z.coerce.number().optional(),
+ }),
+ })
+ .transform((val) => ({
+ type: val.type,
+ amount: Object.fromEntries(
+ ['prc', 'wb', 'ffp', 'tc'].map((k) => [k, val.type === k ? (val.amount[k] ?? null) : null]),
+ ),
+ }))
+
+const ImplantSchema = z.object({
+ brand: z.string().optional(),
+ name: z.string().optional(),
+ stickerNumber: z.string().optional(),
+ companionName: z.string().optional(),
+})
+
+const SpecimenSchema = z.object({
+ destination: z.string({
+ required_error: 'Silahkan pilih specimen',
+ }),
+})
+
+const TissueNoteSchema = z.object({
+ note: z
+ .string()
+ .trim()
+ .transform((val) => (val === '' ? undefined : val))
+ .optional(),
+})
+
+export const ActionReportSchema = z.object({
+ operatorTeam: OperatorTeamSchema,
+ procedures: z.array(ProcedureSchema).min(1, { message: 'Silahkan pilih prosedur' }),
+
+ operationExecution: OperationExecutionSchema,
+
+ bloodInput: BloodInputSchema.optional(),
+ implant: ImplantSchema.optional(),
+ specimen: SpecimenSchema.optional(),
+
+ tissueNotes: z.array(TissueNoteSchema).optional(),
+})
+
+export type ActionReportFormData = z.infer