formanitor 0.0.38 → 0.0.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1521 -165
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +38 -2
- package/dist/index.d.ts +38 -2
- package/dist/index.mjs +1521 -165
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -97,6 +97,15 @@ function validateField(value, field) {
|
|
|
97
97
|
return `Must be at most ${rules.max}`;
|
|
98
98
|
}
|
|
99
99
|
}
|
|
100
|
+
if (field.type === "slider") {
|
|
101
|
+
const num = Number(value);
|
|
102
|
+
if (isNaN(num)) return "Must be a valid number";
|
|
103
|
+
const s = field;
|
|
104
|
+
const min = s.min ?? 0;
|
|
105
|
+
const max = s.max ?? 10;
|
|
106
|
+
if (num < min) return `Must be at least ${min}`;
|
|
107
|
+
if (num > max) return `Must be at most ${max}`;
|
|
108
|
+
}
|
|
100
109
|
if (typeof value === "string") {
|
|
101
110
|
if (rules.minLength !== void 0 && value.length < rules.minLength) {
|
|
102
111
|
return `Must be at least ${rules.minLength} characters`;
|
|
@@ -235,6 +244,227 @@ function applyPrefill(currentValues, fields, prefilledData = {}) {
|
|
|
235
244
|
return newValues;
|
|
236
245
|
}
|
|
237
246
|
|
|
247
|
+
// src/core/generalSurgeryPathway.ts
|
|
248
|
+
var defaultGeneralSurgerySmartHistory = () => ({
|
|
249
|
+
pain: {
|
|
250
|
+
site: "",
|
|
251
|
+
onset: "",
|
|
252
|
+
character: "",
|
|
253
|
+
radiation: "",
|
|
254
|
+
associated: "",
|
|
255
|
+
timing: "",
|
|
256
|
+
exacerbating: "",
|
|
257
|
+
severity: 0
|
|
258
|
+
},
|
|
259
|
+
swelling: { duration: "", sizeProgression: "", painfulPainless: "", checks: [] },
|
|
260
|
+
gi: { appetite: "", weightLoss: "", bowelHabits: "", checks: [] },
|
|
261
|
+
breast: { lumpDuration: "", nippleDischarge: "", checks: [] },
|
|
262
|
+
ano: { checks: [] },
|
|
263
|
+
thyroid: { swellingDuration: "", checks: [] },
|
|
264
|
+
systemic: ""
|
|
265
|
+
});
|
|
266
|
+
var defaultGeneralSurgeryExamination = () => ({
|
|
267
|
+
general: [],
|
|
268
|
+
regions: [],
|
|
269
|
+
abdomen: {
|
|
270
|
+
inspection: [],
|
|
271
|
+
palpation: [],
|
|
272
|
+
percussion: [],
|
|
273
|
+
massNotes: "",
|
|
274
|
+
bowelSounds: "none"
|
|
275
|
+
},
|
|
276
|
+
hernia: { site: "", reducible: false, coughImpulse: false, tenderness: false },
|
|
277
|
+
breast: { lumpSizeCm: "", mobile: false, skinInvolvement: false, axillaryNodes: false },
|
|
278
|
+
thyroid: { size: "", mobileDeglutition: false, nodules: false, cervicalNodes: false },
|
|
279
|
+
anorectal: { inspection: "", dreDone: false, proctoscopyDone: false, notes: "" },
|
|
280
|
+
limb: { dilatedVeins: false, ulcer: false, oedema: false }
|
|
281
|
+
});
|
|
282
|
+
var ALL_GS_CONDITIONS = [
|
|
283
|
+
"hernia",
|
|
284
|
+
"appendicitis",
|
|
285
|
+
"gallbladder",
|
|
286
|
+
"breast",
|
|
287
|
+
"thyroid",
|
|
288
|
+
"piles",
|
|
289
|
+
"varicose",
|
|
290
|
+
"ulcer"
|
|
291
|
+
];
|
|
292
|
+
var defaultGeneralSurgeryGrading = () => ({
|
|
293
|
+
hernia: 0,
|
|
294
|
+
appendicitis: 0,
|
|
295
|
+
gallbladder: 0,
|
|
296
|
+
breast: 0,
|
|
297
|
+
thyroid: 0,
|
|
298
|
+
piles: 0,
|
|
299
|
+
varicose: 0,
|
|
300
|
+
ulcer: 0
|
|
301
|
+
});
|
|
302
|
+
var GS_CONDITION_TRIGGERS = {
|
|
303
|
+
hernia: { regions: ["hernia", "abdomen"], chips: ["swelling_lump", "obstruction"] },
|
|
304
|
+
appendicitis: { regions: ["abdomen"], chips: ["pain", "obstruction"] },
|
|
305
|
+
gallbladder: { regions: ["abdomen"], chips: ["pain"] },
|
|
306
|
+
breast: { regions: ["breast"], chips: ["breast", "swelling_lump"] },
|
|
307
|
+
thyroid: { regions: ["thyroid"], chips: ["thyroid", "swelling_lump"] },
|
|
308
|
+
piles: { regions: ["anorectal"], chips: ["anorectal", "bleeding"] },
|
|
309
|
+
varicose: { regions: ["limb"], chips: ["swelling_lump"] },
|
|
310
|
+
ulcer: { regions: ["limb", "anorectal"], chips: ["ulcer_wound", "discharge"] }
|
|
311
|
+
};
|
|
312
|
+
var GS_CONDITION_LABELS = {
|
|
313
|
+
hernia: "Hernia",
|
|
314
|
+
appendicitis: "Appendicitis",
|
|
315
|
+
gallbladder: "Gallbladder disease",
|
|
316
|
+
breast: "Breast lump (BIRADS)",
|
|
317
|
+
thyroid: "Thyroid nodule (TIRADS)",
|
|
318
|
+
piles: "Haemorrhoids",
|
|
319
|
+
varicose: "Varicose veins (CEAP)",
|
|
320
|
+
ulcer: "Ulcer / wound"
|
|
321
|
+
};
|
|
322
|
+
var GS_GRADE_DESCRIPTIONS = {
|
|
323
|
+
hernia: ["\u2014", "Small reducible", "Large reducible", "Irreducible", "Obstructed", "Strangulated"],
|
|
324
|
+
appendicitis: ["\u2014", "Mild (clinical)", "Confirmed (USG/CT)", "Complicated (mass)", "Abscess", "Perforation"],
|
|
325
|
+
gallbladder: ["\u2014", "Asymptomatic stones", "Symptomatic", "Acute cholecystitis", "Complicated (CBD stone)", "Perforation/empyema"],
|
|
326
|
+
breast: ["\u2014", "BIRADS 1 \u2014 Negative", "BIRADS 2 \u2014 Benign", "BIRADS 3 \u2014 Probably benign", "BIRADS 4 \u2014 Suspicious", "BIRADS 5 \u2014 Malignant"],
|
|
327
|
+
thyroid: ["\u2014", "TIRADS 1 \u2014 Normal", "TIRADS 2 \u2014 Benign", "TIRADS 3 \u2014 Indeterminate", "TIRADS 4 \u2014 Suspicious", "TIRADS 5 \u2014 Highly suspicious"],
|
|
328
|
+
piles: ["\u2014", "Grade 1", "Grade 2", "Grade 3", "Grade 4", "Grade 5"],
|
|
329
|
+
varicose: ["\u2014", "C1 telangiectasia", "C2 varicose", "C3 oedema", "C4 skin changes", "C5-C6 ulcer"],
|
|
330
|
+
ulcer: ["\u2014", "Superficial", "Deep", "Infected", "Necrotic", "Gangrene"]
|
|
331
|
+
};
|
|
332
|
+
function normalizeGeneralSurgerySmartHistory(raw) {
|
|
333
|
+
const d = defaultGeneralSurgerySmartHistory();
|
|
334
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return d;
|
|
335
|
+
const v = raw;
|
|
336
|
+
const painIn = v.pain && typeof v.pain === "object" ? v.pain : {};
|
|
337
|
+
const sev = Number(painIn.severity);
|
|
338
|
+
const pain = {
|
|
339
|
+
...d.pain,
|
|
340
|
+
...painIn,
|
|
341
|
+
severity: Number.isFinite(sev) ? Math.min(10, Math.max(0, Math.round(sev))) : d.pain.severity
|
|
342
|
+
};
|
|
343
|
+
const str2 = (x) => typeof x === "string" ? x : "";
|
|
344
|
+
const strArr = (x) => Array.isArray(x) ? x.filter((i) => typeof i === "string") : [];
|
|
345
|
+
const swell = v.swelling && typeof v.swelling === "object" ? v.swelling : {};
|
|
346
|
+
const gi = v.gi && typeof v.gi === "object" ? v.gi : {};
|
|
347
|
+
const breast = v.breast && typeof v.breast === "object" ? v.breast : {};
|
|
348
|
+
const ano = v.ano && typeof v.ano === "object" ? v.ano : {};
|
|
349
|
+
const thy = v.thyroid && typeof v.thyroid === "object" ? v.thyroid : {};
|
|
350
|
+
return {
|
|
351
|
+
pain,
|
|
352
|
+
swelling: {
|
|
353
|
+
duration: str2(swell.duration),
|
|
354
|
+
sizeProgression: str2(swell.sizeProgression),
|
|
355
|
+
painfulPainless: str2(swell.painfulPainless),
|
|
356
|
+
checks: strArr(swell.checks)
|
|
357
|
+
},
|
|
358
|
+
gi: {
|
|
359
|
+
appetite: str2(gi.appetite),
|
|
360
|
+
weightLoss: str2(gi.weightLoss),
|
|
361
|
+
bowelHabits: str2(gi.bowelHabits),
|
|
362
|
+
checks: strArr(gi.checks)
|
|
363
|
+
},
|
|
364
|
+
breast: {
|
|
365
|
+
lumpDuration: str2(breast.lumpDuration),
|
|
366
|
+
nippleDischarge: str2(breast.nippleDischarge),
|
|
367
|
+
checks: strArr(breast.checks)
|
|
368
|
+
},
|
|
369
|
+
ano: { checks: strArr(ano.checks) },
|
|
370
|
+
thyroid: {
|
|
371
|
+
swellingDuration: str2(thy.swellingDuration),
|
|
372
|
+
checks: strArr(thy.checks)
|
|
373
|
+
},
|
|
374
|
+
systemic: typeof v.systemic === "string" ? v.systemic : d.systemic
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
function normalizeGeneralSurgeryExamination(raw) {
|
|
378
|
+
const d = defaultGeneralSurgeryExamination();
|
|
379
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return d;
|
|
380
|
+
const v = raw;
|
|
381
|
+
const strArr = (x) => Array.isArray(x) ? x.filter((i) => typeof i === "string") : [];
|
|
382
|
+
const ab = v.abdomen && typeof v.abdomen === "object" ? v.abdomen : {};
|
|
383
|
+
const bowel = ab.bowelSounds;
|
|
384
|
+
const bowels = bowel === "normal" || bowel === "up" || bowel === "down" || bowel === "absent" ? bowel : "none";
|
|
385
|
+
const hb = v.hernia && typeof v.hernia === "object" ? v.hernia : {};
|
|
386
|
+
const br = v.breast && typeof v.breast === "object" ? v.breast : {};
|
|
387
|
+
const th = v.thyroid && typeof v.thyroid === "object" ? v.thyroid : {};
|
|
388
|
+
const ar = v.anorectal && typeof v.anorectal === "object" ? v.anorectal : {};
|
|
389
|
+
const lm = v.limb && typeof v.limb === "object" ? v.limb : {};
|
|
390
|
+
const bool = (x) => x === true;
|
|
391
|
+
return {
|
|
392
|
+
general: strArr(v.general),
|
|
393
|
+
regions: strArr(v.regions),
|
|
394
|
+
abdomen: {
|
|
395
|
+
inspection: strArr(ab.inspection),
|
|
396
|
+
palpation: strArr(ab.palpation),
|
|
397
|
+
percussion: strArr(ab.percussion),
|
|
398
|
+
massNotes: typeof ab.massNotes === "string" ? ab.massNotes : d.abdomen.massNotes,
|
|
399
|
+
bowelSounds: bowels
|
|
400
|
+
},
|
|
401
|
+
hernia: {
|
|
402
|
+
site: typeof hb.site === "string" ? hb.site : "",
|
|
403
|
+
reducible: bool(hb.reducible),
|
|
404
|
+
coughImpulse: bool(hb.coughImpulse),
|
|
405
|
+
tenderness: bool(hb.tenderness)
|
|
406
|
+
},
|
|
407
|
+
breast: {
|
|
408
|
+
lumpSizeCm: typeof br.lumpSizeCm === "string" ? br.lumpSizeCm : "",
|
|
409
|
+
mobile: bool(br.mobile),
|
|
410
|
+
skinInvolvement: bool(br.skinInvolvement),
|
|
411
|
+
axillaryNodes: bool(br.axillaryNodes)
|
|
412
|
+
},
|
|
413
|
+
thyroid: {
|
|
414
|
+
size: typeof th.size === "string" ? th.size : "",
|
|
415
|
+
mobileDeglutition: bool(th.mobileDeglutition),
|
|
416
|
+
nodules: bool(th.nodules),
|
|
417
|
+
cervicalNodes: bool(th.cervicalNodes)
|
|
418
|
+
},
|
|
419
|
+
anorectal: {
|
|
420
|
+
inspection: typeof ar.inspection === "string" ? ar.inspection : "",
|
|
421
|
+
dreDone: bool(ar.dreDone),
|
|
422
|
+
proctoscopyDone: bool(ar.proctoscopyDone),
|
|
423
|
+
notes: typeof ar.notes === "string" ? ar.notes : ""
|
|
424
|
+
},
|
|
425
|
+
limb: {
|
|
426
|
+
dilatedVeins: bool(lm.dilatedVeins),
|
|
427
|
+
ulcer: bool(lm.ulcer),
|
|
428
|
+
oedema: bool(lm.oedema)
|
|
429
|
+
}
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
function normalizeGeneralSurgeryGrading(raw) {
|
|
433
|
+
const d = defaultGeneralSurgeryGrading();
|
|
434
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return d;
|
|
435
|
+
const v = raw;
|
|
436
|
+
const out = { ...d };
|
|
437
|
+
for (const k of ALL_GS_CONDITIONS) {
|
|
438
|
+
const n = Number(v[k]);
|
|
439
|
+
if (Number.isFinite(n) && n >= 0 && n <= 5) out[k] = Math.round(n);
|
|
440
|
+
}
|
|
441
|
+
return out;
|
|
442
|
+
}
|
|
443
|
+
function gsGradingRowVisible(cond, chips, regions, grade) {
|
|
444
|
+
if (grade > 0) return true;
|
|
445
|
+
const t = GS_CONDITION_TRIGGERS[cond];
|
|
446
|
+
if (t.chips.some((c) => chips.includes(c))) return true;
|
|
447
|
+
if (t.regions.some((r) => regions.includes(r))) return true;
|
|
448
|
+
return false;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
// src/core/painScaleFlags.ts
|
|
452
|
+
function normalizePainScaleFlags(raw, bounds) {
|
|
453
|
+
const min = bounds?.min ?? 0;
|
|
454
|
+
const max = bounds?.max ?? 10;
|
|
455
|
+
let pain = min;
|
|
456
|
+
let flags = [];
|
|
457
|
+
if (raw && typeof raw === "object" && !Array.isArray(raw)) {
|
|
458
|
+
const o = raw;
|
|
459
|
+
const p = Number(o.pain);
|
|
460
|
+
if (Number.isFinite(p)) pain = Math.min(max, Math.max(min, p));
|
|
461
|
+
if (Array.isArray(o.flags)) {
|
|
462
|
+
flags = o.flags.filter((x) => typeof x === "string");
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
return { pain, flags };
|
|
466
|
+
}
|
|
467
|
+
|
|
238
468
|
// src/core/store.ts
|
|
239
469
|
var FormStore = class {
|
|
240
470
|
state;
|
|
@@ -321,7 +551,22 @@ var FormStore = class {
|
|
|
321
551
|
else if (field.type === "surgical_risk_flags")
|
|
322
552
|
values[field.id] = { OD: [], OS: [] };
|
|
323
553
|
else if (field.type === "toggle") values[field.id] = false;
|
|
324
|
-
else
|
|
554
|
+
else if (field.type === "slider") {
|
|
555
|
+
const s = field;
|
|
556
|
+
values[field.id] = s.defaultValue ?? s.min ?? 0;
|
|
557
|
+
} else if (field.type === "general_surgery_smart_history") {
|
|
558
|
+
values[field.id] = field.defaultValue ?? defaultGeneralSurgerySmartHistory();
|
|
559
|
+
} else if (field.type === "general_surgery_examination") {
|
|
560
|
+
values[field.id] = field.defaultValue ?? defaultGeneralSurgeryExamination();
|
|
561
|
+
} else if (field.type === "general_surgery_grading") {
|
|
562
|
+
values[field.id] = field.defaultValue ?? defaultGeneralSurgeryGrading();
|
|
563
|
+
} else if (field.type === "pain_scale_flags") {
|
|
564
|
+
const f = field;
|
|
565
|
+
values[field.id] = normalizePainScaleFlags(
|
|
566
|
+
f.defaultValue ?? { pain: f.min ?? 0, flags: [] },
|
|
567
|
+
{ min: f.min, max: f.max }
|
|
568
|
+
);
|
|
569
|
+
} else values[field.id] = null;
|
|
325
570
|
}
|
|
326
571
|
});
|
|
327
572
|
this.state.values = values;
|
|
@@ -1041,7 +1286,8 @@ var TextWidget = ({ fieldId }) => {
|
|
|
1041
1286
|
fieldDef.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-red-500", children: "*" })
|
|
1042
1287
|
] });
|
|
1043
1288
|
const labelEl = theme ? /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: fieldId, className: labelClass, children: labelContent }) : /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: fieldId, children: labelContent });
|
|
1044
|
-
|
|
1289
|
+
const placeholder = typeof fieldDef.placeholder === "string" && fieldDef.placeholder.trim() ? fieldDef.placeholder : void 0;
|
|
1290
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(wrapperClass, isTextarea && "flex h-full min-h-0 flex-col"), children: [
|
|
1045
1291
|
hasVoice ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
1046
1292
|
labelEl,
|
|
1047
1293
|
/* @__PURE__ */ jsxRuntime.jsx(VoiceMicButton, { fieldId, onTranscriptReady: setValue })
|
|
@@ -1055,7 +1301,8 @@ var TextWidget = ({ fieldId }) => {
|
|
|
1055
1301
|
onBlur: setTouched,
|
|
1056
1302
|
disabled,
|
|
1057
1303
|
type: fieldDef.type === "number" ? "number" : "text",
|
|
1058
|
-
className: inputClass,
|
|
1304
|
+
className: cn(inputClass, isTextarea && height == null && "min-h-[80px] flex-1"),
|
|
1305
|
+
placeholder,
|
|
1059
1306
|
...isTextarea && { height }
|
|
1060
1307
|
}
|
|
1061
1308
|
),
|
|
@@ -1531,6 +1778,8 @@ var SelectWidget = ({ fieldId }) => {
|
|
|
1531
1778
|
}
|
|
1532
1779
|
}, [fieldDef]);
|
|
1533
1780
|
if (!fieldDef) return null;
|
|
1781
|
+
const schemaPlaceholder = typeof fieldDef.placeholder === "string" && fieldDef.placeholder.trim() ? fieldDef.placeholder : void 0;
|
|
1782
|
+
const selectPlaceholder = loading ? "Loading..." : schemaPlaceholder ?? "Select...";
|
|
1534
1783
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
1535
1784
|
/* @__PURE__ */ jsxRuntime.jsxs(Label, { htmlFor: fieldId, children: [
|
|
1536
1785
|
fieldDef.label,
|
|
@@ -1548,7 +1797,7 @@ var SelectWidget = ({ fieldId }) => {
|
|
|
1548
1797
|
setTouched();
|
|
1549
1798
|
},
|
|
1550
1799
|
children: [
|
|
1551
|
-
/* @__PURE__ */ jsxRuntime.jsx(SelectTrigger, { id: fieldId, className: showError ? "border-red-500" : "", children: /* @__PURE__ */ jsxRuntime.jsx(SelectValue, { placeholder:
|
|
1800
|
+
/* @__PURE__ */ jsxRuntime.jsx(SelectTrigger, { id: fieldId, className: showError ? "border-red-500" : "", children: /* @__PURE__ */ jsxRuntime.jsx(SelectValue, { placeholder: selectPlaceholder }) }),
|
|
1552
1801
|
/* @__PURE__ */ jsxRuntime.jsx(SelectContent, { children: options.map((opt) => /* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: String(opt.value), children: opt.label }, String(opt.value))) })
|
|
1553
1802
|
]
|
|
1554
1803
|
}
|
|
@@ -8069,6 +8318,21 @@ function parallelChipArraysEqual(a, b) {
|
|
|
8069
8318
|
function isSuggestionField(type) {
|
|
8070
8319
|
return type === "suggestion_textarea" || type === "complaint_chips";
|
|
8071
8320
|
}
|
|
8321
|
+
function EmbeddedSchemaField({ fieldId }) {
|
|
8322
|
+
const store = useFormStore();
|
|
8323
|
+
const fieldDef = store.getFieldDef(fieldId);
|
|
8324
|
+
if (!fieldDef) return null;
|
|
8325
|
+
switch (fieldDef.type) {
|
|
8326
|
+
case "text":
|
|
8327
|
+
case "number":
|
|
8328
|
+
case "textarea":
|
|
8329
|
+
return /* @__PURE__ */ jsxRuntime.jsx(TextWidget, { fieldId });
|
|
8330
|
+
case "select":
|
|
8331
|
+
return /* @__PURE__ */ jsxRuntime.jsx(SelectWidget, { fieldId });
|
|
8332
|
+
default:
|
|
8333
|
+
return null;
|
|
8334
|
+
}
|
|
8335
|
+
}
|
|
8072
8336
|
var SuggestionTextareaWidget = ({ fieldId }) => {
|
|
8073
8337
|
const { fieldDef, value, setValue, setTouched, error, disabled, touched } = useField(fieldId);
|
|
8074
8338
|
const { state } = useForm();
|
|
@@ -8080,6 +8344,10 @@ var SuggestionTextareaWidget = ({ fieldId }) => {
|
|
|
8080
8344
|
const def = fieldDef && isSuggestionField(fieldDef.type) ? fieldDef : void 0;
|
|
8081
8345
|
const textValue = value == null || typeof value === "string" ? value || "" : String(value);
|
|
8082
8346
|
const parallelChipFieldId = def?.meta && typeof def.meta.parallelChipFieldId === "string" ? def.meta.parallelChipFieldId.trim() : void 0;
|
|
8347
|
+
const embeddedFieldIds = React15.useMemo(() => {
|
|
8348
|
+
const raw = def?.meta && Array.isArray(def.meta.embeddedFieldIds) ? def.meta.embeddedFieldIds : [];
|
|
8349
|
+
return raw.filter((id) => typeof id === "string" && id.trim().length > 0).map((id) => id.trim()).filter((id) => store.getFieldDef(id));
|
|
8350
|
+
}, [def?.meta, store]);
|
|
8083
8351
|
React15.useEffect(() => {
|
|
8084
8352
|
if (!def) {
|
|
8085
8353
|
setOptions([]);
|
|
@@ -8124,19 +8392,26 @@ var SuggestionTextareaWidget = ({ fieldId }) => {
|
|
|
8124
8392
|
setValue(toggleSuggestionTokenInText(textValue, String(optValue), appendSeparator));
|
|
8125
8393
|
};
|
|
8126
8394
|
const hasSuggestions = options.length > 0;
|
|
8395
|
+
const hasEmbedded = embeddedFieldIds.length > 0;
|
|
8396
|
+
const hasShell = hasSuggestions || hasEmbedded;
|
|
8127
8397
|
const isHighlightLabel = def.theme === "highlight-label";
|
|
8128
8398
|
const suggestionShellClass = cn(
|
|
8129
8399
|
"flex min-w-0 flex-col overflow-hidden",
|
|
8130
|
-
|
|
8400
|
+
hasShell && (isHighlightLabel ? "-mt-1 rounded-b-md border-[#D0D0D0] bg-white" : "rounded-md border border-input bg-background")
|
|
8131
8401
|
);
|
|
8132
8402
|
const chipsRowClass = cn(
|
|
8133
8403
|
"flex flex-wrap gap-2 px-3 pb-2 pt-3",
|
|
8134
8404
|
hasSuggestions && (isHighlightLabel ? "" : "border-b border-input/70"),
|
|
8135
8405
|
disabled && "pointer-events-none opacity-50"
|
|
8136
8406
|
);
|
|
8407
|
+
const embeddedRowClass = cn(
|
|
8408
|
+
"grid gap-3 px-3 sm:grid-cols-3",
|
|
8409
|
+
hasEmbedded && (hasSuggestions ? cn("py-2", isHighlightLabel && "border-t border-input/70") : "border-b border-input/70 py-3"),
|
|
8410
|
+
disabled && "pointer-events-none opacity-50"
|
|
8411
|
+
);
|
|
8137
8412
|
const textareaShellClass = cn(
|
|
8138
8413
|
inputClass,
|
|
8139
|
-
|
|
8414
|
+
hasShell && cn(
|
|
8140
8415
|
"mt-0 rounded-t-none rounded-b-md border-0 shadow-none focus-visible:ring-offset-0",
|
|
8141
8416
|
isHighlightLabel ? "border-t-0" : "min-h-[80px]"
|
|
8142
8417
|
)
|
|
@@ -8163,8 +8438,9 @@ var SuggestionTextareaWidget = ({ fieldId }) => {
|
|
|
8163
8438
|
/* @__PURE__ */ jsxRuntime.jsx(VoiceMicButton, { fieldId, onTranscriptReady: setValue })
|
|
8164
8439
|
] }) : labelEl,
|
|
8165
8440
|
def.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: def.description }),
|
|
8166
|
-
|
|
8167
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: chipsRowClass, role: "group", "aria-label": suggestionsAria, children: suggestionButtons }),
|
|
8441
|
+
hasShell ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: suggestionShellClass, children: [
|
|
8442
|
+
hasSuggestions && /* @__PURE__ */ jsxRuntime.jsx("div", { className: chipsRowClass, role: "group", "aria-label": suggestionsAria, children: suggestionButtons }),
|
|
8443
|
+
hasEmbedded && /* @__PURE__ */ jsxRuntime.jsx("div", { className: embeddedRowClass, children: embeddedFieldIds.map((id) => /* @__PURE__ */ jsxRuntime.jsx(EmbeddedSchemaField, { fieldId: id }, id)) }),
|
|
8168
8444
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8169
8445
|
Textarea,
|
|
8170
8446
|
{
|
|
@@ -8944,161 +9220,1159 @@ var SurgicalRiskFlagsWidget = ({ fieldId }) => {
|
|
|
8944
9220
|
}
|
|
8945
9221
|
);
|
|
8946
9222
|
};
|
|
8947
|
-
var
|
|
8948
|
-
const { fieldDef,
|
|
8949
|
-
|
|
8950
|
-
|
|
8951
|
-
|
|
8952
|
-
|
|
8953
|
-
|
|
8954
|
-
|
|
8955
|
-
|
|
8956
|
-
|
|
8957
|
-
|
|
8958
|
-
|
|
8959
|
-
|
|
8960
|
-
|
|
8961
|
-
|
|
8962
|
-
|
|
8963
|
-
|
|
8964
|
-
|
|
8965
|
-
|
|
8966
|
-
|
|
8967
|
-
|
|
8968
|
-
|
|
8969
|
-
|
|
8970
|
-
|
|
8971
|
-
|
|
8972
|
-
|
|
8973
|
-
|
|
8974
|
-
|
|
8975
|
-
|
|
8976
|
-
case "multiselect":
|
|
8977
|
-
return /* @__PURE__ */ jsxRuntime.jsx(MultiSelectWidget, { fieldId });
|
|
8978
|
-
case "repeatable":
|
|
8979
|
-
return /* @__PURE__ */ jsxRuntime.jsx(RepeatableWidget, { fieldId });
|
|
8980
|
-
case "image_upload":
|
|
8981
|
-
return /* @__PURE__ */ jsxRuntime.jsx(ImageUploadWidget, { fieldId });
|
|
8982
|
-
case "media_upload":
|
|
8983
|
-
return /* @__PURE__ */ jsxRuntime.jsx(MediaUploadWidget, { fieldId });
|
|
8984
|
-
case "signature":
|
|
8985
|
-
return /* @__PURE__ */ jsxRuntime.jsx(SignatureUploadWidget, { fieldId });
|
|
8986
|
-
case "editable_table":
|
|
8987
|
-
return /* @__PURE__ */ jsxRuntime.jsx(EditableTableWidget, { fieldId });
|
|
8988
|
-
case "medications":
|
|
8989
|
-
return /* @__PURE__ */ jsxRuntime.jsx(AddMedicationWidget, { fieldId });
|
|
8990
|
-
case "discharge_medication_orders":
|
|
8991
|
-
return /* @__PURE__ */ jsxRuntime.jsx(DischargeMedicationOrdersWidget, { fieldId });
|
|
8992
|
-
case "investigations":
|
|
8993
|
-
return /* @__PURE__ */ jsxRuntime.jsx(AddInvestigationWidget, { fieldId });
|
|
8994
|
-
case "procedures":
|
|
8995
|
-
return /* @__PURE__ */ jsxRuntime.jsx(AddProcedureWidget, { fieldId });
|
|
8996
|
-
case "differential_diagnosis":
|
|
8997
|
-
return /* @__PURE__ */ jsxRuntime.jsx(DifferentialDiagnosisWidget, { fieldId });
|
|
8998
|
-
case "vitals":
|
|
8999
|
-
return /* @__PURE__ */ jsxRuntime.jsx(VitalsWidget, { fieldId });
|
|
9000
|
-
case "hidden_vitals":
|
|
9001
|
-
return /* @__PURE__ */ jsxRuntime.jsx(HiddenVitalsWidget, { fieldId });
|
|
9002
|
-
case "referral":
|
|
9003
|
-
return /* @__PURE__ */ jsxRuntime.jsx(ReferralWidget, { fieldId });
|
|
9004
|
-
case "followup":
|
|
9005
|
-
return /* @__PURE__ */ jsxRuntime.jsx(FollowupWidget, { fieldId });
|
|
9006
|
-
case "smart_textarea":
|
|
9007
|
-
return /* @__PURE__ */ jsxRuntime.jsx(SmartTextareaWidget, { fieldId });
|
|
9008
|
-
case "diagnosis_textarea":
|
|
9009
|
-
return /* @__PURE__ */ jsxRuntime.jsx(DiagnosisTextareaWidget, { fieldId });
|
|
9010
|
-
case "obstetric_history":
|
|
9011
|
-
return /* @__PURE__ */ jsxRuntime.jsx(ObstetricHistoryWidget, { fieldId });
|
|
9012
|
-
case "eye_prescription":
|
|
9013
|
-
return /* @__PURE__ */ jsxRuntime.jsx(OphthalmologyWidget, { fieldId });
|
|
9014
|
-
case "ophthal_diagnosis":
|
|
9015
|
-
return /* @__PURE__ */ jsxRuntime.jsx(OphthalDiagnosisWidget, { fieldId });
|
|
9016
|
-
case "orthopedic_exam":
|
|
9017
|
-
return /* @__PURE__ */ jsxRuntime.jsx(OrthopedicExamWidget, { fieldId });
|
|
9018
|
-
case "toggle": {
|
|
9019
|
-
const { value, setValue, setTouched, disabled } = useField(fieldId);
|
|
9020
|
-
const store = useFormStore();
|
|
9021
|
-
const excludes = fieldDef.excludes ?? [];
|
|
9022
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
9023
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9024
|
-
Switch,
|
|
9025
|
-
{
|
|
9026
|
-
checked: value === true,
|
|
9027
|
-
disabled,
|
|
9028
|
-
onCheckedChange: (checked) => {
|
|
9029
|
-
setValue(checked);
|
|
9030
|
-
setTouched();
|
|
9031
|
-
if (checked) excludes.forEach((id) => store.setValue(id, false));
|
|
9032
|
-
}
|
|
9033
|
-
}
|
|
9034
|
-
),
|
|
9035
|
-
/* @__PURE__ */ jsxRuntime.jsx(Label, { className: "text-sm font-medium leading-none cursor-pointer select-none", children: fieldDef.label })
|
|
9036
|
-
] });
|
|
9037
|
-
}
|
|
9038
|
-
case "suggestion_textarea":
|
|
9039
|
-
case "complaint_chips":
|
|
9040
|
-
return /* @__PURE__ */ jsxRuntime.jsx(SuggestionTextareaWidget, { fieldId });
|
|
9041
|
-
case "lens_assessment":
|
|
9042
|
-
return /* @__PURE__ */ jsxRuntime.jsx(LensAssessmentWidget, { fieldId });
|
|
9043
|
-
case "functional_impairment_score":
|
|
9044
|
-
return /* @__PURE__ */ jsxRuntime.jsx(FunctionalImpairmentScoreWidget, { fieldId });
|
|
9045
|
-
case "biometry_iol_workup":
|
|
9046
|
-
return /* @__PURE__ */ jsxRuntime.jsx(BiometryIolWorkupWidget, { fieldId });
|
|
9047
|
-
case "surgical_risk_flags":
|
|
9048
|
-
return /* @__PURE__ */ jsxRuntime.jsx(SurgicalRiskFlagsWidget, { fieldId });
|
|
9049
|
-
case "static_text": {
|
|
9050
|
-
const def = fieldDef;
|
|
9051
|
-
const size = def.size ?? "regular";
|
|
9052
|
-
const labelClass = size === "large" ? "text-base" : "text-sm";
|
|
9053
|
-
const descClass = size === "large" ? "text-sm" : "text-xs";
|
|
9054
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${labelClass} text-muted-foreground`, children: [
|
|
9055
|
-
def.label,
|
|
9056
|
-
def.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `mt-1 ${descClass} opacity-90`, children: def.description })
|
|
9057
|
-
] });
|
|
9058
|
-
}
|
|
9059
|
-
default:
|
|
9060
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-red-500", children: [
|
|
9061
|
-
"Unknown field type: ",
|
|
9062
|
-
fieldDef.type
|
|
9063
|
-
] });
|
|
9064
|
-
}
|
|
9065
|
-
}
|
|
9066
|
-
var Section = ({ title, children }) => {
|
|
9067
|
-
const [expanded, setExpanded] = React15.useState(true);
|
|
9068
|
-
const handleToggle = () => setExpanded((prev) => !prev);
|
|
9069
|
-
const contentClassName = cn(
|
|
9070
|
-
"overflow-hidden transition-[height] duration-200 ease-in-out",
|
|
9071
|
-
!expanded && "hidden"
|
|
9072
|
-
);
|
|
9073
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-6 border rounded-lg bg-white shadow-sm overflow-hidden", children: [
|
|
9074
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
9075
|
-
"button",
|
|
9223
|
+
var SliderWidget = ({ fieldId }) => {
|
|
9224
|
+
const { fieldDef, value, setValue, setTouched, error, disabled, touched } = useField(fieldId);
|
|
9225
|
+
const { state } = useForm();
|
|
9226
|
+
const showError = !!error && (touched || state.submitAttempted);
|
|
9227
|
+
if (!fieldDef || fieldDef.type !== "slider") return null;
|
|
9228
|
+
const def = fieldDef;
|
|
9229
|
+
const min = def.min ?? 0;
|
|
9230
|
+
const max = def.max ?? 10;
|
|
9231
|
+
const step = def.step ?? 1;
|
|
9232
|
+
const raw = value == null || value === "" ? min : Number(value);
|
|
9233
|
+
const num = Number.isFinite(raw) ? Math.min(max, Math.max(min, raw)) : min;
|
|
9234
|
+
const theme = getThemeConfig("textarea", def.theme);
|
|
9235
|
+
const wrapperClass = theme?.wrapperClassName ?? "space-y-2";
|
|
9236
|
+
const labelClass = theme?.labelClassName;
|
|
9237
|
+
const labelContent = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
9238
|
+
def.label,
|
|
9239
|
+
" ",
|
|
9240
|
+
def.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-red-500", children: "*" }),
|
|
9241
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ml-2 text-muted-foreground font-normal tabular-nums", children: [
|
|
9242
|
+
num,
|
|
9243
|
+
"/",
|
|
9244
|
+
max
|
|
9245
|
+
] })
|
|
9246
|
+
] });
|
|
9247
|
+
const labelEl = theme ? /* @__PURE__ */ jsxRuntime.jsx(Label, { className: labelClass, children: labelContent }) : /* @__PURE__ */ jsxRuntime.jsx(Label, { children: labelContent });
|
|
9248
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: wrapperClass, children: [
|
|
9249
|
+
labelEl,
|
|
9250
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9251
|
+
Slider,
|
|
9076
9252
|
{
|
|
9077
|
-
|
|
9078
|
-
|
|
9079
|
-
|
|
9080
|
-
|
|
9081
|
-
|
|
9082
|
-
|
|
9083
|
-
|
|
9253
|
+
className: cn("py-1", showError && "opacity-90 ring-1 ring-red-500 rounded"),
|
|
9254
|
+
disabled,
|
|
9255
|
+
min,
|
|
9256
|
+
max,
|
|
9257
|
+
step,
|
|
9258
|
+
value: [num],
|
|
9259
|
+
onValueChange: (v) => {
|
|
9260
|
+
const n = v[0] ?? min;
|
|
9261
|
+
setValue(n);
|
|
9262
|
+
setTouched();
|
|
9263
|
+
}
|
|
9084
9264
|
}
|
|
9085
9265
|
),
|
|
9086
|
-
|
|
9266
|
+
showError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-red-500", children: error })
|
|
9087
9267
|
] });
|
|
9088
9268
|
};
|
|
9089
|
-
var
|
|
9090
|
-
|
|
9091
|
-
label,
|
|
9092
|
-
|
|
9093
|
-
|
|
9094
|
-
|
|
9095
|
-
|
|
9096
|
-
|
|
9097
|
-
|
|
9269
|
+
var CHIEF_CHIPS_FIELD = "chief_complaints_chips";
|
|
9270
|
+
var SWELLING_OPTS = [
|
|
9271
|
+
{ value: "reducible_hernia", label: "Reducible (hernia)" },
|
|
9272
|
+
{ value: "cough_impulse", label: "Cough impulse" },
|
|
9273
|
+
{ value: "skin_changes", label: "Skin changes" }
|
|
9274
|
+
];
|
|
9275
|
+
var GI_OPTS = [
|
|
9276
|
+
{ value: "bleeding_pr", label: "Bleeding PR" },
|
|
9277
|
+
{ value: "vomiting", label: "Vomiting" },
|
|
9278
|
+
{ value: "haematemesis", label: "Haematemesis" }
|
|
9279
|
+
];
|
|
9280
|
+
var BREAST_OPTS = [
|
|
9281
|
+
{ value: "pain", label: "Pain" },
|
|
9282
|
+
{ value: "fh_ca_breast", label: "Family history of Ca breast" }
|
|
9283
|
+
];
|
|
9284
|
+
var ANO_OPTS = [
|
|
9285
|
+
{ value: "pain_defecation", label: "Pain during defecation" },
|
|
9286
|
+
{ value: "bleeding", label: "Bleeding" },
|
|
9287
|
+
{ value: "constipation", label: "Constipation" },
|
|
9288
|
+
{ value: "discharge", label: "Discharge" }
|
|
9289
|
+
];
|
|
9290
|
+
var THYROID_OPTS = [
|
|
9291
|
+
{ value: "dysphagia", label: "Dysphagia" },
|
|
9292
|
+
{ value: "voice_change", label: "Voice change" },
|
|
9293
|
+
{ value: "thyrotoxicosis", label: "Thyrotoxicosis symptoms" }
|
|
9294
|
+
];
|
|
9295
|
+
var SOCRATES_KEYS = [
|
|
9296
|
+
"site",
|
|
9297
|
+
"onset",
|
|
9298
|
+
"character",
|
|
9299
|
+
"radiation",
|
|
9300
|
+
"associated",
|
|
9301
|
+
"timing",
|
|
9302
|
+
"exacerbating"
|
|
9303
|
+
];
|
|
9304
|
+
function Panel({ title, children }) {
|
|
9305
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "overflow-hidden rounded-md border border-[#D0D0D0] bg-white", children: [
|
|
9306
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-b border-[#D0D0D0] bg-[#FEE8EC]/50 px-3 py-1.5 text-xs font-semibold text-slate-700", children: title }),
|
|
9307
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-3", children })
|
|
9308
|
+
] });
|
|
9309
|
+
}
|
|
9310
|
+
function chipList(state) {
|
|
9311
|
+
const raw = state.values[CHIEF_CHIPS_FIELD];
|
|
9312
|
+
return Array.isArray(raw) ? raw.filter((x) => typeof x === "string") : [];
|
|
9313
|
+
}
|
|
9314
|
+
var GsSmartHistoryWidget = ({ fieldId }) => {
|
|
9315
|
+
const { fieldDef, value, setValue, setTouched, error, touched, disabled } = useField(fieldId);
|
|
9316
|
+
const { state } = useForm();
|
|
9317
|
+
const showError = !!error && (touched || state.submitAttempted);
|
|
9318
|
+
const safe = React15.useMemo(() => normalizeGeneralSurgerySmartHistory(value), [value]);
|
|
9319
|
+
const chips = React15.useMemo(() => chipList(state), [state]);
|
|
9320
|
+
const showPain = chips.includes("pain");
|
|
9321
|
+
const showSwelling = chips.includes("swelling_lump");
|
|
9322
|
+
const showGI = chips.includes("bleeding") || chips.includes("obstruction");
|
|
9323
|
+
const showBreast = chips.includes("breast");
|
|
9324
|
+
const showAno = chips.includes("anorectal");
|
|
9325
|
+
const showThyroid = chips.includes("thyroid");
|
|
9326
|
+
const update = (next) => {
|
|
9327
|
+
setValue(next);
|
|
9328
|
+
setTouched();
|
|
9098
9329
|
};
|
|
9099
|
-
|
|
9100
|
-
|
|
9101
|
-
|
|
9330
|
+
const setPain = (key, v) => {
|
|
9331
|
+
if (key === "severity") {
|
|
9332
|
+
const n = typeof v === "number" ? v : Number(v);
|
|
9333
|
+
const sev = Number.isFinite(n) ? Math.min(10, Math.max(0, Math.round(n))) : 0;
|
|
9334
|
+
update({ ...safe, pain: { ...safe.pain, severity: sev } });
|
|
9335
|
+
return;
|
|
9336
|
+
}
|
|
9337
|
+
update({ ...safe, pain: { ...safe.pain, [key]: String(v) } });
|
|
9338
|
+
};
|
|
9339
|
+
const toggleArr = (section, val) => {
|
|
9340
|
+
if (section === "swelling") {
|
|
9341
|
+
const a = safe.swelling.checks;
|
|
9342
|
+
const next = a.includes(val) ? a.filter((x) => x !== val) : [...a, val];
|
|
9343
|
+
update({ ...safe, swelling: { ...safe.swelling, checks: next } });
|
|
9344
|
+
} else if (section === "gi") {
|
|
9345
|
+
const a = safe.gi.checks;
|
|
9346
|
+
const next = a.includes(val) ? a.filter((x) => x !== val) : [...a, val];
|
|
9347
|
+
update({ ...safe, gi: { ...safe.gi, checks: next } });
|
|
9348
|
+
} else if (section === "breast") {
|
|
9349
|
+
const a = safe.breast.checks;
|
|
9350
|
+
const next = a.includes(val) ? a.filter((x) => x !== val) : [...a, val];
|
|
9351
|
+
update({ ...safe, breast: { ...safe.breast, checks: next } });
|
|
9352
|
+
} else if (section === "ano") {
|
|
9353
|
+
const a = safe.ano.checks;
|
|
9354
|
+
const next = a.includes(val) ? a.filter((x) => x !== val) : [...a, val];
|
|
9355
|
+
update({ ...safe, ano: { ...safe.ano, checks: next } });
|
|
9356
|
+
} else {
|
|
9357
|
+
const a = safe.thyroid.checks;
|
|
9358
|
+
const next = a.includes(val) ? a.filter((x) => x !== val) : [...a, val];
|
|
9359
|
+
update({ ...safe, thyroid: { ...safe.thyroid, checks: next } });
|
|
9360
|
+
}
|
|
9361
|
+
};
|
|
9362
|
+
if (!fieldDef) return null;
|
|
9363
|
+
const theme = getThemeConfig("textarea", fieldDef.theme);
|
|
9364
|
+
const wrapperClass = theme?.wrapperClassName ?? "rounded-md overflow-hidden flex flex-col border border-[#D0D0D0]";
|
|
9365
|
+
const labelClass = theme?.labelClassName;
|
|
9366
|
+
const labelContent = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
9367
|
+
fieldDef.label,
|
|
9368
|
+
fieldDef.required ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-1 text-red-500", children: "*" }) : null
|
|
9369
|
+
] });
|
|
9370
|
+
const labelEl = theme ? /* @__PURE__ */ jsxRuntime.jsx(Label, { className: labelClass, children: labelContent }) : /* @__PURE__ */ jsxRuntime.jsx(Label, { className: "text-sm font-medium", children: labelContent });
|
|
9371
|
+
const bodyClass = cn(
|
|
9372
|
+
"-mt-1 flex min-w-0 flex-col gap-3 border-t border-[#D0D0D0] bg-white px-3 py-3",
|
|
9373
|
+
disabled && "pointer-events-none opacity-60"
|
|
9374
|
+
);
|
|
9375
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("w-full min-w-0", wrapperClass), children: [
|
|
9376
|
+
labelEl,
|
|
9377
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: bodyClass, children: [
|
|
9378
|
+
showPain ? /* @__PURE__ */ jsxRuntime.jsx(Panel, { title: "SOCRATES \u2014 pain", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-2 md:grid-cols-4", children: [
|
|
9379
|
+
SOCRATES_KEYS.map((k) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
|
|
9380
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-medium uppercase tracking-wide text-muted-foreground", children: k }),
|
|
9381
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9382
|
+
Input,
|
|
9383
|
+
{
|
|
9384
|
+
className: "h-8 text-xs",
|
|
9385
|
+
value: safe.pain[k],
|
|
9386
|
+
onChange: (e) => setPain(k, e.target.value),
|
|
9387
|
+
disabled
|
|
9388
|
+
}
|
|
9389
|
+
)
|
|
9390
|
+
] }, k)),
|
|
9391
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
|
|
9392
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-medium uppercase tracking-wide text-muted-foreground", children: "Severity 0\u201310" }),
|
|
9393
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9394
|
+
Input,
|
|
9395
|
+
{
|
|
9396
|
+
type: "number",
|
|
9397
|
+
min: 0,
|
|
9398
|
+
max: 10,
|
|
9399
|
+
className: "h-8 text-xs",
|
|
9400
|
+
value: safe.pain.severity,
|
|
9401
|
+
onChange: (e) => setPain("severity", e.target.value),
|
|
9402
|
+
disabled
|
|
9403
|
+
}
|
|
9404
|
+
)
|
|
9405
|
+
] })
|
|
9406
|
+
] }) }) : null,
|
|
9407
|
+
showSwelling ? /* @__PURE__ */ jsxRuntime.jsxs(Panel, { title: "Swelling history", children: [
|
|
9408
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-3 text-xs md:grid-cols-3", children: [
|
|
9409
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex flex-col gap-1", children: [
|
|
9410
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: "Duration" }),
|
|
9411
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9412
|
+
Input,
|
|
9413
|
+
{
|
|
9414
|
+
className: "h-8 text-xs",
|
|
9415
|
+
value: safe.swelling.duration,
|
|
9416
|
+
onChange: (e) => update({ ...safe, swelling: { ...safe.swelling, duration: e.target.value } }),
|
|
9417
|
+
disabled
|
|
9418
|
+
}
|
|
9419
|
+
)
|
|
9420
|
+
] }),
|
|
9421
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex flex-col gap-1", children: [
|
|
9422
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: "Size progression" }),
|
|
9423
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9424
|
+
Input,
|
|
9425
|
+
{
|
|
9426
|
+
className: "h-8 text-xs",
|
|
9427
|
+
value: safe.swelling.sizeProgression,
|
|
9428
|
+
onChange: (e) => update({ ...safe, swelling: { ...safe.swelling, sizeProgression: e.target.value } }),
|
|
9429
|
+
disabled
|
|
9430
|
+
}
|
|
9431
|
+
)
|
|
9432
|
+
] }),
|
|
9433
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex flex-col gap-1", children: [
|
|
9434
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: "Painful / painless" }),
|
|
9435
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9436
|
+
Input,
|
|
9437
|
+
{
|
|
9438
|
+
className: "h-8 text-xs",
|
|
9439
|
+
value: safe.swelling.painfulPainless,
|
|
9440
|
+
onChange: (e) => update({ ...safe, swelling: { ...safe.swelling, painfulPainless: e.target.value } }),
|
|
9441
|
+
disabled
|
|
9442
|
+
}
|
|
9443
|
+
)
|
|
9444
|
+
] })
|
|
9445
|
+
] }),
|
|
9446
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-3 flex flex-wrap gap-x-4 gap-y-2", children: SWELLING_OPTS.map((o) => /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2 text-xs", children: [
|
|
9447
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9448
|
+
Checkbox,
|
|
9449
|
+
{
|
|
9450
|
+
checked: safe.swelling.checks.includes(o.value),
|
|
9451
|
+
onCheckedChange: () => toggleArr("swelling", o.value),
|
|
9452
|
+
disabled
|
|
9453
|
+
}
|
|
9454
|
+
),
|
|
9455
|
+
o.label
|
|
9456
|
+
] }, o.value)) })
|
|
9457
|
+
] }) : null,
|
|
9458
|
+
showGI ? /* @__PURE__ */ jsxRuntime.jsxs(Panel, { title: "GI history", children: [
|
|
9459
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-2 text-xs md:grid-cols-3", children: [
|
|
9460
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex flex-col gap-1", children: [
|
|
9461
|
+
"Appetite",
|
|
9462
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9463
|
+
Input,
|
|
9464
|
+
{
|
|
9465
|
+
className: "h-8 text-xs",
|
|
9466
|
+
value: safe.gi.appetite,
|
|
9467
|
+
onChange: (e) => update({ ...safe, gi: { ...safe.gi, appetite: e.target.value } }),
|
|
9468
|
+
disabled
|
|
9469
|
+
}
|
|
9470
|
+
)
|
|
9471
|
+
] }),
|
|
9472
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex flex-col gap-1", children: [
|
|
9473
|
+
"Weight loss",
|
|
9474
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9475
|
+
Input,
|
|
9476
|
+
{
|
|
9477
|
+
className: "h-8 text-xs",
|
|
9478
|
+
value: safe.gi.weightLoss,
|
|
9479
|
+
onChange: (e) => update({ ...safe, gi: { ...safe.gi, weightLoss: e.target.value } }),
|
|
9480
|
+
disabled
|
|
9481
|
+
}
|
|
9482
|
+
)
|
|
9483
|
+
] }),
|
|
9484
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex flex-col gap-1", children: [
|
|
9485
|
+
"Bowel habits",
|
|
9486
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9487
|
+
Input,
|
|
9488
|
+
{
|
|
9489
|
+
className: "h-8 text-xs",
|
|
9490
|
+
value: safe.gi.bowelHabits,
|
|
9491
|
+
onChange: (e) => update({ ...safe, gi: { ...safe.gi, bowelHabits: e.target.value } }),
|
|
9492
|
+
disabled
|
|
9493
|
+
}
|
|
9494
|
+
)
|
|
9495
|
+
] })
|
|
9496
|
+
] }),
|
|
9497
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-3 flex flex-wrap gap-x-4 gap-y-2", children: GI_OPTS.map((o) => /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2 text-xs", children: [
|
|
9498
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9499
|
+
Checkbox,
|
|
9500
|
+
{
|
|
9501
|
+
checked: safe.gi.checks.includes(o.value),
|
|
9502
|
+
onCheckedChange: () => toggleArr("gi", o.value),
|
|
9503
|
+
disabled
|
|
9504
|
+
}
|
|
9505
|
+
),
|
|
9506
|
+
o.label
|
|
9507
|
+
] }, o.value)) })
|
|
9508
|
+
] }) : null,
|
|
9509
|
+
showBreast ? /* @__PURE__ */ jsxRuntime.jsxs(Panel, { title: "Breast history", children: [
|
|
9510
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-2 text-xs md:grid-cols-2", children: [
|
|
9511
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex flex-col gap-1", children: [
|
|
9512
|
+
"Lump duration",
|
|
9513
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9514
|
+
Input,
|
|
9515
|
+
{
|
|
9516
|
+
className: "h-8 text-xs",
|
|
9517
|
+
value: safe.breast.lumpDuration,
|
|
9518
|
+
onChange: (e) => update({ ...safe, breast: { ...safe.breast, lumpDuration: e.target.value } }),
|
|
9519
|
+
disabled
|
|
9520
|
+
}
|
|
9521
|
+
)
|
|
9522
|
+
] }),
|
|
9523
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex flex-col gap-1", children: [
|
|
9524
|
+
"Nipple discharge",
|
|
9525
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9526
|
+
Input,
|
|
9527
|
+
{
|
|
9528
|
+
className: "h-8 text-xs",
|
|
9529
|
+
value: safe.breast.nippleDischarge,
|
|
9530
|
+
onChange: (e) => update({ ...safe, breast: { ...safe.breast, nippleDischarge: e.target.value } }),
|
|
9531
|
+
disabled
|
|
9532
|
+
}
|
|
9533
|
+
)
|
|
9534
|
+
] })
|
|
9535
|
+
] }),
|
|
9536
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-3 flex flex-wrap gap-x-4 gap-y-2", children: BREAST_OPTS.map((o) => /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2 text-xs", children: [
|
|
9537
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9538
|
+
Checkbox,
|
|
9539
|
+
{
|
|
9540
|
+
checked: safe.breast.checks.includes(o.value),
|
|
9541
|
+
onCheckedChange: () => toggleArr("breast", o.value),
|
|
9542
|
+
disabled
|
|
9543
|
+
}
|
|
9544
|
+
),
|
|
9545
|
+
o.label
|
|
9546
|
+
] }, o.value)) })
|
|
9547
|
+
] }) : null,
|
|
9548
|
+
showAno ? /* @__PURE__ */ jsxRuntime.jsx(Panel, { title: "Anorectal history", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-2 text-xs md:grid-cols-2", children: ANO_OPTS.map((o) => /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
|
|
9549
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9550
|
+
Checkbox,
|
|
9551
|
+
{
|
|
9552
|
+
checked: safe.ano.checks.includes(o.value),
|
|
9553
|
+
onCheckedChange: () => toggleArr("ano", o.value),
|
|
9554
|
+
disabled
|
|
9555
|
+
}
|
|
9556
|
+
),
|
|
9557
|
+
o.label
|
|
9558
|
+
] }, o.value)) }) }) : null,
|
|
9559
|
+
showThyroid ? /* @__PURE__ */ jsxRuntime.jsxs(Panel, { title: "Thyroid history", children: [
|
|
9560
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-2 text-xs md:grid-cols-2", children: /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex flex-col gap-1 md:col-span-2", children: [
|
|
9561
|
+
"Swelling duration",
|
|
9562
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9563
|
+
Input,
|
|
9564
|
+
{
|
|
9565
|
+
className: "h-8 text-xs",
|
|
9566
|
+
value: safe.thyroid.swellingDuration,
|
|
9567
|
+
onChange: (e) => update({ ...safe, thyroid: { ...safe.thyroid, swellingDuration: e.target.value } }),
|
|
9568
|
+
disabled
|
|
9569
|
+
}
|
|
9570
|
+
)
|
|
9571
|
+
] }) }),
|
|
9572
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-3 flex flex-wrap gap-x-4 gap-y-2", children: THYROID_OPTS.map((o) => /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2 text-xs", children: [
|
|
9573
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9574
|
+
Checkbox,
|
|
9575
|
+
{
|
|
9576
|
+
checked: safe.thyroid.checks.includes(o.value),
|
|
9577
|
+
onCheckedChange: () => toggleArr("thyroid", o.value),
|
|
9578
|
+
disabled
|
|
9579
|
+
}
|
|
9580
|
+
),
|
|
9581
|
+
o.label
|
|
9582
|
+
] }, o.value)) })
|
|
9583
|
+
] }) : null,
|
|
9584
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
|
|
9585
|
+
/* @__PURE__ */ jsxRuntime.jsx(Label, { className: "text-xs font-medium text-slate-700", children: "Systemic surgical screening" }),
|
|
9586
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9587
|
+
Textarea,
|
|
9588
|
+
{
|
|
9589
|
+
className: "min-h-[72px] rounded-md border border-input bg-white text-sm",
|
|
9590
|
+
placeholder: "Fever, weight loss, appetite loss, fatigue, malignancy red flags\u2026",
|
|
9591
|
+
value: safe.systemic,
|
|
9592
|
+
onChange: (e) => update({ ...safe, systemic: e.target.value }),
|
|
9593
|
+
disabled
|
|
9594
|
+
}
|
|
9595
|
+
)
|
|
9596
|
+
] })
|
|
9597
|
+
] }),
|
|
9598
|
+
showError ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "px-3 pb-2 text-xs text-red-500", children: error }) : null
|
|
9599
|
+
] });
|
|
9600
|
+
};
|
|
9601
|
+
var GS_CLINICAL_EXAMINATION_FIELD = "clinical_examination";
|
|
9602
|
+
var GENERAL = [
|
|
9603
|
+
{ value: "pallor", label: "Pallor" },
|
|
9604
|
+
{ value: "icterus", label: "Icterus" },
|
|
9605
|
+
{ value: "cyanosis", label: "Cyanosis" },
|
|
9606
|
+
{ value: "clubbing", label: "Clubbing" },
|
|
9607
|
+
{ value: "lymphadenopathy", label: "Lymphadenopathy" },
|
|
9608
|
+
{ value: "oedema", label: "Oedema" }
|
|
9609
|
+
];
|
|
9610
|
+
var REGIONS = [
|
|
9611
|
+
{ key: "abdomen", label: "Abdomen" },
|
|
9612
|
+
{ key: "hernia", label: "Hernia" },
|
|
9613
|
+
{ key: "breast", label: "Breast" },
|
|
9614
|
+
{ key: "thyroid", label: "Thyroid" },
|
|
9615
|
+
{ key: "anorectal", label: "Anorectal" },
|
|
9616
|
+
{ key: "limb", label: "Limb / varicose" }
|
|
9617
|
+
];
|
|
9618
|
+
var ABD_INSP = [
|
|
9619
|
+
{ value: "distension", label: "Distension" },
|
|
9620
|
+
{ value: "scars", label: "Scars" },
|
|
9621
|
+
{ value: "visible_peristalsis", label: "Visible peristalsis" }
|
|
9622
|
+
];
|
|
9623
|
+
var ABD_PALP = [
|
|
9624
|
+
{ value: "tenderness", label: "Tenderness" },
|
|
9625
|
+
{ value: "guarding", label: "Guarding" },
|
|
9626
|
+
{ value: "rigidity", label: "Rigidity" },
|
|
9627
|
+
{ value: "mass", label: "Palpable mass" }
|
|
9628
|
+
];
|
|
9629
|
+
var ABD_PERC = [
|
|
9630
|
+
{ value: "tympany", label: "Tympany" },
|
|
9631
|
+
{ value: "shifting_dullness", label: "Shifting dullness" }
|
|
9632
|
+
];
|
|
9633
|
+
function SubGroup({ title, children }) {
|
|
9634
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
9635
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[11px] font-semibold uppercase tracking-wide text-muted-foreground", children: title }),
|
|
9636
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children })
|
|
9637
|
+
] });
|
|
9638
|
+
}
|
|
9639
|
+
function RegionCard({ title, children }) {
|
|
9640
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "overflow-hidden rounded-md border border-[#D0D0D0] bg-white", children: [
|
|
9641
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-b border-[#D0D0D0] bg-[#FEE8EC]/50 px-3 py-1.5 text-xs font-semibold text-slate-700", children: title }),
|
|
9642
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-3", children })
|
|
9643
|
+
] });
|
|
9644
|
+
}
|
|
9645
|
+
var GsExaminationWidget = ({ fieldId }) => {
|
|
9646
|
+
const { fieldDef, value, setValue, setTouched, error, touched, disabled } = useField(fieldId);
|
|
9647
|
+
const clinicalField = useField(GS_CLINICAL_EXAMINATION_FIELD);
|
|
9648
|
+
const { state } = useForm();
|
|
9649
|
+
const showError = !!error && (touched || state.submitAttempted);
|
|
9650
|
+
const safe = React15.useMemo(() => normalizeGeneralSurgeryExamination(value), [value]);
|
|
9651
|
+
const update = (next) => {
|
|
9652
|
+
setValue(next);
|
|
9653
|
+
setTouched();
|
|
9654
|
+
};
|
|
9655
|
+
const toggleIn = (arr, val) => arr.includes(val) ? arr.filter((x) => x !== val) : [...arr, val];
|
|
9656
|
+
const toggleGeneral = (val) => {
|
|
9657
|
+
update({ ...safe, general: toggleIn(safe.general, val) });
|
|
9658
|
+
};
|
|
9659
|
+
const toggleRegion = (key) => {
|
|
9660
|
+
update({ ...safe, regions: toggleIn(safe.regions, key) });
|
|
9661
|
+
};
|
|
9662
|
+
const toggleAbd = (key, val) => {
|
|
9663
|
+
update({
|
|
9664
|
+
...safe,
|
|
9665
|
+
abdomen: { ...safe.abdomen, [key]: toggleIn(safe.abdomen[key], val) }
|
|
9666
|
+
});
|
|
9667
|
+
};
|
|
9668
|
+
if (!fieldDef) return null;
|
|
9669
|
+
const has = (r) => safe.regions.includes(r);
|
|
9670
|
+
const theme = getThemeConfig("textarea", fieldDef.theme);
|
|
9671
|
+
const wrapperClass = theme?.wrapperClassName ?? "rounded-md overflow-hidden flex flex-col border border-[#D0D0D0]";
|
|
9672
|
+
const labelClass = theme?.labelClassName;
|
|
9673
|
+
const labelContent = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
9674
|
+
fieldDef.label,
|
|
9675
|
+
fieldDef.required ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-1 text-red-500", children: "*" }) : null
|
|
9676
|
+
] });
|
|
9677
|
+
const labelEl = theme ? /* @__PURE__ */ jsxRuntime.jsx(Label, { className: labelClass, children: labelContent }) : /* @__PURE__ */ jsxRuntime.jsx(Label, { className: "text-sm font-medium", children: labelContent });
|
|
9678
|
+
const bodyClass = cn(
|
|
9679
|
+
"-mt-1 flex min-w-0 flex-col gap-3 border-t border-[#D0D0D0] bg-white px-3 py-3",
|
|
9680
|
+
disabled && "pointer-events-none opacity-60"
|
|
9681
|
+
);
|
|
9682
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("w-full min-w-0", wrapperClass), children: [
|
|
9683
|
+
labelEl,
|
|
9684
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: bodyClass, children: [
|
|
9685
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "overflow-hidden rounded-md border border-[#D0D0D0] bg-white", children: [
|
|
9686
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-b border-[#D0D0D0] bg-[#FEE8EC]/50 px-3 py-1.5 text-xs font-semibold text-slate-700", children: "General examination" }),
|
|
9687
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-3", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 gap-2 text-xs md:grid-cols-3 lg:grid-cols-6", children: GENERAL.map((g) => /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
|
|
9688
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9689
|
+
Checkbox,
|
|
9690
|
+
{
|
|
9691
|
+
checked: safe.general.includes(g.value),
|
|
9692
|
+
onCheckedChange: () => toggleGeneral(g.value),
|
|
9693
|
+
disabled
|
|
9694
|
+
}
|
|
9695
|
+
),
|
|
9696
|
+
g.label
|
|
9697
|
+
] }, g.value)) }) })
|
|
9698
|
+
] }),
|
|
9699
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
9700
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-2 text-xs font-semibold text-slate-700", children: "Regional examination \u2014 select region(s)" }),
|
|
9701
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-2", children: REGIONS.map((r) => {
|
|
9702
|
+
const on = safe.regions.includes(r.key);
|
|
9703
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
9704
|
+
Button,
|
|
9705
|
+
{
|
|
9706
|
+
type: "button",
|
|
9707
|
+
size: "sm",
|
|
9708
|
+
variant: on ? "default" : "outline",
|
|
9709
|
+
className: "h-7 rounded-full px-3 text-xs",
|
|
9710
|
+
onClick: () => toggleRegion(r.key),
|
|
9711
|
+
disabled,
|
|
9712
|
+
children: r.label
|
|
9713
|
+
},
|
|
9714
|
+
r.key
|
|
9715
|
+
);
|
|
9716
|
+
}) })
|
|
9717
|
+
] }),
|
|
9718
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
|
|
9719
|
+
has("abdomen") ? /* @__PURE__ */ jsxRuntime.jsx(RegionCard, { title: "Abdomen \u2014 inspection \xB7 palpation \xB7 percussion \xB7 auscultation", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-4", children: [
|
|
9720
|
+
/* @__PURE__ */ jsxRuntime.jsx(SubGroup, { title: "Inspection", children: ABD_INSP.map((o) => /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2 text-xs", children: [
|
|
9721
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9722
|
+
Checkbox,
|
|
9723
|
+
{
|
|
9724
|
+
checked: safe.abdomen.inspection.includes(o.value),
|
|
9725
|
+
onCheckedChange: () => toggleAbd("inspection", o.value),
|
|
9726
|
+
disabled
|
|
9727
|
+
}
|
|
9728
|
+
),
|
|
9729
|
+
o.label
|
|
9730
|
+
] }, o.value)) }),
|
|
9731
|
+
/* @__PURE__ */ jsxRuntime.jsxs(SubGroup, { title: "Palpation", children: [
|
|
9732
|
+
ABD_PALP.map((o) => /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2 text-xs", children: [
|
|
9733
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9734
|
+
Checkbox,
|
|
9735
|
+
{
|
|
9736
|
+
checked: safe.abdomen.palpation.includes(o.value),
|
|
9737
|
+
onCheckedChange: () => toggleAbd("palpation", o.value),
|
|
9738
|
+
disabled
|
|
9739
|
+
}
|
|
9740
|
+
),
|
|
9741
|
+
o.label
|
|
9742
|
+
] }, o.value)),
|
|
9743
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "mt-2 block text-xs", children: [
|
|
9744
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "mb-1 block font-medium", children: "Mass size / mobility" }),
|
|
9745
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9746
|
+
Input,
|
|
9747
|
+
{
|
|
9748
|
+
className: "h-8 text-xs",
|
|
9749
|
+
value: safe.abdomen.massNotes,
|
|
9750
|
+
onChange: (e) => update({ ...safe, abdomen: { ...safe.abdomen, massNotes: e.target.value } }),
|
|
9751
|
+
disabled
|
|
9752
|
+
}
|
|
9753
|
+
)
|
|
9754
|
+
] })
|
|
9755
|
+
] }),
|
|
9756
|
+
/* @__PURE__ */ jsxRuntime.jsx(SubGroup, { title: "Percussion", children: ABD_PERC.map((o) => /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2 text-xs", children: [
|
|
9757
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9758
|
+
Checkbox,
|
|
9759
|
+
{
|
|
9760
|
+
checked: safe.abdomen.percussion.includes(o.value),
|
|
9761
|
+
onCheckedChange: () => toggleAbd("percussion", o.value),
|
|
9762
|
+
disabled
|
|
9763
|
+
}
|
|
9764
|
+
),
|
|
9765
|
+
o.label
|
|
9766
|
+
] }, o.value)) }),
|
|
9767
|
+
/* @__PURE__ */ jsxRuntime.jsxs(SubGroup, { title: "Auscultation", children: [
|
|
9768
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "mb-1 block text-xs font-medium", children: "Bowel sounds" }),
|
|
9769
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
9770
|
+
Select,
|
|
9771
|
+
{
|
|
9772
|
+
value: safe.abdomen.bowelSounds,
|
|
9773
|
+
onValueChange: (val) => update({
|
|
9774
|
+
...safe,
|
|
9775
|
+
abdomen: {
|
|
9776
|
+
...safe.abdomen,
|
|
9777
|
+
bowelSounds: val
|
|
9778
|
+
}
|
|
9779
|
+
}),
|
|
9780
|
+
disabled,
|
|
9781
|
+
children: [
|
|
9782
|
+
/* @__PURE__ */ jsxRuntime.jsx(SelectTrigger, { className: "h-8 text-xs", children: /* @__PURE__ */ jsxRuntime.jsx(SelectValue, { placeholder: "Select\u2026" }) }),
|
|
9783
|
+
/* @__PURE__ */ jsxRuntime.jsxs(SelectContent, { children: [
|
|
9784
|
+
/* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: "none", children: "\u2014" }),
|
|
9785
|
+
/* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: "normal", children: "Normal" }),
|
|
9786
|
+
/* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: "up", children: "\u2191" }),
|
|
9787
|
+
/* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: "down", children: "\u2193" }),
|
|
9788
|
+
/* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: "absent", children: "Absent" })
|
|
9789
|
+
] })
|
|
9790
|
+
]
|
|
9791
|
+
}
|
|
9792
|
+
)
|
|
9793
|
+
] })
|
|
9794
|
+
] }) }) : null,
|
|
9795
|
+
has("hernia") ? /* @__PURE__ */ jsxRuntime.jsx(RegionCard, { title: "Hernia exam", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-3 text-xs md:grid-cols-4", children: [
|
|
9796
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "block", children: [
|
|
9797
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "mb-1 block font-medium", children: "Site" }),
|
|
9798
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9799
|
+
Input,
|
|
9800
|
+
{
|
|
9801
|
+
className: "h-8 text-xs",
|
|
9802
|
+
value: safe.hernia.site,
|
|
9803
|
+
onChange: (e) => update({ ...safe, hernia: { ...safe.hernia, site: e.target.value } }),
|
|
9804
|
+
disabled
|
|
9805
|
+
}
|
|
9806
|
+
)
|
|
9807
|
+
] }),
|
|
9808
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
|
|
9809
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9810
|
+
Checkbox,
|
|
9811
|
+
{
|
|
9812
|
+
checked: safe.hernia.reducible,
|
|
9813
|
+
onCheckedChange: (c) => update({ ...safe, hernia: { ...safe.hernia, reducible: c === true } }),
|
|
9814
|
+
disabled
|
|
9815
|
+
}
|
|
9816
|
+
),
|
|
9817
|
+
"Reducible"
|
|
9818
|
+
] }),
|
|
9819
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
|
|
9820
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9821
|
+
Checkbox,
|
|
9822
|
+
{
|
|
9823
|
+
checked: safe.hernia.coughImpulse,
|
|
9824
|
+
onCheckedChange: (c) => update({ ...safe, hernia: { ...safe.hernia, coughImpulse: c === true } }),
|
|
9825
|
+
disabled
|
|
9826
|
+
}
|
|
9827
|
+
),
|
|
9828
|
+
"Cough impulse"
|
|
9829
|
+
] }),
|
|
9830
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
|
|
9831
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9832
|
+
Checkbox,
|
|
9833
|
+
{
|
|
9834
|
+
checked: safe.hernia.tenderness,
|
|
9835
|
+
onCheckedChange: (c) => update({ ...safe, hernia: { ...safe.hernia, tenderness: c === true } }),
|
|
9836
|
+
disabled
|
|
9837
|
+
}
|
|
9838
|
+
),
|
|
9839
|
+
"Tenderness"
|
|
9840
|
+
] })
|
|
9841
|
+
] }) }) : null,
|
|
9842
|
+
has("breast") ? /* @__PURE__ */ jsxRuntime.jsx(RegionCard, { title: "Breast exam", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-3 text-xs md:grid-cols-4", children: [
|
|
9843
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "block", children: [
|
|
9844
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "mb-1 block font-medium", children: "Lump size (cm)" }),
|
|
9845
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9846
|
+
Input,
|
|
9847
|
+
{
|
|
9848
|
+
className: "h-8 text-xs",
|
|
9849
|
+
value: safe.breast.lumpSizeCm,
|
|
9850
|
+
onChange: (e) => update({ ...safe, breast: { ...safe.breast, lumpSizeCm: e.target.value } }),
|
|
9851
|
+
disabled
|
|
9852
|
+
}
|
|
9853
|
+
)
|
|
9854
|
+
] }),
|
|
9855
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
|
|
9856
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9857
|
+
Checkbox,
|
|
9858
|
+
{
|
|
9859
|
+
checked: safe.breast.mobile,
|
|
9860
|
+
onCheckedChange: (c) => update({ ...safe, breast: { ...safe.breast, mobile: c === true } }),
|
|
9861
|
+
disabled
|
|
9862
|
+
}
|
|
9863
|
+
),
|
|
9864
|
+
"Mobile"
|
|
9865
|
+
] }),
|
|
9866
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
|
|
9867
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9868
|
+
Checkbox,
|
|
9869
|
+
{
|
|
9870
|
+
checked: safe.breast.skinInvolvement,
|
|
9871
|
+
onCheckedChange: (c) => update({ ...safe, breast: { ...safe.breast, skinInvolvement: c === true } }),
|
|
9872
|
+
disabled
|
|
9873
|
+
}
|
|
9874
|
+
),
|
|
9875
|
+
"Skin involvement"
|
|
9876
|
+
] }),
|
|
9877
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
|
|
9878
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9879
|
+
Checkbox,
|
|
9880
|
+
{
|
|
9881
|
+
checked: safe.breast.axillaryNodes,
|
|
9882
|
+
onCheckedChange: (c) => update({ ...safe, breast: { ...safe.breast, axillaryNodes: c === true } }),
|
|
9883
|
+
disabled
|
|
9884
|
+
}
|
|
9885
|
+
),
|
|
9886
|
+
"Axillary nodes"
|
|
9887
|
+
] })
|
|
9888
|
+
] }) }) : null,
|
|
9889
|
+
has("thyroid") ? /* @__PURE__ */ jsxRuntime.jsx(RegionCard, { title: "Thyroid exam", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-3 text-xs md:grid-cols-4", children: [
|
|
9890
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "block", children: [
|
|
9891
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "mb-1 block font-medium", children: "Size" }),
|
|
9892
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9893
|
+
Input,
|
|
9894
|
+
{
|
|
9895
|
+
className: "h-8 text-xs",
|
|
9896
|
+
value: safe.thyroid.size,
|
|
9897
|
+
onChange: (e) => update({ ...safe, thyroid: { ...safe.thyroid, size: e.target.value } }),
|
|
9898
|
+
disabled
|
|
9899
|
+
}
|
|
9900
|
+
)
|
|
9901
|
+
] }),
|
|
9902
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
|
|
9903
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9904
|
+
Checkbox,
|
|
9905
|
+
{
|
|
9906
|
+
checked: safe.thyroid.mobileDeglutition,
|
|
9907
|
+
onCheckedChange: (c) => update({ ...safe, thyroid: { ...safe.thyroid, mobileDeglutition: c === true } }),
|
|
9908
|
+
disabled
|
|
9909
|
+
}
|
|
9910
|
+
),
|
|
9911
|
+
"Mobile with deglutition"
|
|
9912
|
+
] }),
|
|
9913
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
|
|
9914
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9915
|
+
Checkbox,
|
|
9916
|
+
{
|
|
9917
|
+
checked: safe.thyroid.nodules,
|
|
9918
|
+
onCheckedChange: (c) => update({ ...safe, thyroid: { ...safe.thyroid, nodules: c === true } }),
|
|
9919
|
+
disabled
|
|
9920
|
+
}
|
|
9921
|
+
),
|
|
9922
|
+
"Nodules"
|
|
9923
|
+
] }),
|
|
9924
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
|
|
9925
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9926
|
+
Checkbox,
|
|
9927
|
+
{
|
|
9928
|
+
checked: safe.thyroid.cervicalNodes,
|
|
9929
|
+
onCheckedChange: (c) => update({ ...safe, thyroid: { ...safe.thyroid, cervicalNodes: c === true } }),
|
|
9930
|
+
disabled
|
|
9931
|
+
}
|
|
9932
|
+
),
|
|
9933
|
+
"Cervical lymph nodes"
|
|
9934
|
+
] })
|
|
9935
|
+
] }) }) : null,
|
|
9936
|
+
has("anorectal") ? /* @__PURE__ */ jsxRuntime.jsx(RegionCard, { title: "Anorectal exam", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-3 text-xs md:grid-cols-3", children: [
|
|
9937
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "block md:col-span-3", children: [
|
|
9938
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "mb-1 block font-medium", children: "Inspection findings" }),
|
|
9939
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9940
|
+
Input,
|
|
9941
|
+
{
|
|
9942
|
+
className: "h-8 text-xs",
|
|
9943
|
+
value: safe.anorectal.inspection,
|
|
9944
|
+
onChange: (e) => update({ ...safe, anorectal: { ...safe.anorectal, inspection: e.target.value } }),
|
|
9945
|
+
disabled
|
|
9946
|
+
}
|
|
9947
|
+
)
|
|
9948
|
+
] }),
|
|
9949
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
|
|
9950
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9951
|
+
Checkbox,
|
|
9952
|
+
{
|
|
9953
|
+
checked: safe.anorectal.dreDone,
|
|
9954
|
+
onCheckedChange: (c) => update({ ...safe, anorectal: { ...safe.anorectal, dreDone: c === true } }),
|
|
9955
|
+
disabled
|
|
9956
|
+
}
|
|
9957
|
+
),
|
|
9958
|
+
"DRE done"
|
|
9959
|
+
] }),
|
|
9960
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
|
|
9961
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9962
|
+
Checkbox,
|
|
9963
|
+
{
|
|
9964
|
+
checked: safe.anorectal.proctoscopyDone,
|
|
9965
|
+
onCheckedChange: (c) => update({ ...safe, anorectal: { ...safe.anorectal, proctoscopyDone: c === true } }),
|
|
9966
|
+
disabled
|
|
9967
|
+
}
|
|
9968
|
+
),
|
|
9969
|
+
"Proctoscopy done"
|
|
9970
|
+
] }),
|
|
9971
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "md:col-span-3", children: [
|
|
9972
|
+
/* @__PURE__ */ jsxRuntime.jsx(Label, { className: "text-xs font-semibold", children: "DRE / proctoscopy notes" }),
|
|
9973
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9974
|
+
Textarea,
|
|
9975
|
+
{
|
|
9976
|
+
className: "mt-1 min-h-[64px] text-sm",
|
|
9977
|
+
placeholder: "Sphincter tone, masses, prostate, bleeding\u2026",
|
|
9978
|
+
value: safe.anorectal.notes,
|
|
9979
|
+
onChange: (e) => update({ ...safe, anorectal: { ...safe.anorectal, notes: e.target.value } }),
|
|
9980
|
+
disabled
|
|
9981
|
+
}
|
|
9982
|
+
)
|
|
9983
|
+
] })
|
|
9984
|
+
] }) }) : null,
|
|
9985
|
+
has("limb") ? /* @__PURE__ */ jsxRuntime.jsx(RegionCard, { title: "Limb / varicose veins", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-x-4 gap-y-2 text-xs", children: [
|
|
9986
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
|
|
9987
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9988
|
+
Checkbox,
|
|
9989
|
+
{
|
|
9990
|
+
checked: safe.limb.dilatedVeins,
|
|
9991
|
+
onCheckedChange: (c) => update({ ...safe, limb: { ...safe.limb, dilatedVeins: c === true } }),
|
|
9992
|
+
disabled
|
|
9993
|
+
}
|
|
9994
|
+
),
|
|
9995
|
+
"Dilated veins"
|
|
9996
|
+
] }),
|
|
9997
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
|
|
9998
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9999
|
+
Checkbox,
|
|
10000
|
+
{
|
|
10001
|
+
checked: safe.limb.ulcer,
|
|
10002
|
+
onCheckedChange: (c) => update({ ...safe, limb: { ...safe.limb, ulcer: c === true } }),
|
|
10003
|
+
disabled
|
|
10004
|
+
}
|
|
10005
|
+
),
|
|
10006
|
+
"Ulcer"
|
|
10007
|
+
] }),
|
|
10008
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
|
|
10009
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
10010
|
+
Checkbox,
|
|
10011
|
+
{
|
|
10012
|
+
checked: safe.limb.oedema,
|
|
10013
|
+
onCheckedChange: (c) => update({ ...safe, limb: { ...safe.limb, oedema: c === true } }),
|
|
10014
|
+
disabled
|
|
10015
|
+
}
|
|
10016
|
+
),
|
|
10017
|
+
"Oedema"
|
|
10018
|
+
] })
|
|
10019
|
+
] }) }) : null
|
|
10020
|
+
] }),
|
|
10021
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
|
|
10022
|
+
/* @__PURE__ */ jsxRuntime.jsx(Label, { className: "text-xs font-semibold text-slate-700", children: clinicalField.fieldDef?.label ?? "Clinical examination" }),
|
|
10023
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
10024
|
+
Textarea,
|
|
10025
|
+
{
|
|
10026
|
+
className: "min-h-[88px] rounded-md border border-input bg-white text-sm",
|
|
10027
|
+
value: typeof clinicalField.value === "string" ? clinicalField.value : clinicalField.value == null ? "" : String(clinicalField.value),
|
|
10028
|
+
onChange: (e) => {
|
|
10029
|
+
clinicalField.setValue(e.target.value);
|
|
10030
|
+
clinicalField.setTouched();
|
|
10031
|
+
},
|
|
10032
|
+
disabled: disabled || clinicalField.disabled
|
|
10033
|
+
}
|
|
10034
|
+
)
|
|
10035
|
+
] })
|
|
10036
|
+
] }),
|
|
10037
|
+
showError ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "px-3 pb-2 text-xs text-red-500", children: error }) : null
|
|
10038
|
+
] });
|
|
10039
|
+
};
|
|
10040
|
+
var CHIEF_CHIPS_FIELD2 = "chief_complaints_chips";
|
|
10041
|
+
var GS_EXAMINATION_FIELD = "gs_examination";
|
|
10042
|
+
function chipList2(state) {
|
|
10043
|
+
const raw = state.values[CHIEF_CHIPS_FIELD2];
|
|
10044
|
+
return Array.isArray(raw) ? raw.filter((x) => typeof x === "string") : [];
|
|
10045
|
+
}
|
|
10046
|
+
function regionList(state) {
|
|
10047
|
+
const raw = state.values[GS_EXAMINATION_FIELD];
|
|
10048
|
+
const ex = normalizeGeneralSurgeryExamination(raw);
|
|
10049
|
+
return ex.regions;
|
|
10050
|
+
}
|
|
10051
|
+
var GsGradingWidget = ({ fieldId }) => {
|
|
10052
|
+
const { fieldDef, value, setValue, setTouched, error, touched, disabled } = useField(fieldId);
|
|
10053
|
+
const { state } = useForm();
|
|
10054
|
+
const showError = !!error && (touched || state.submitAttempted);
|
|
10055
|
+
const safe = React15.useMemo(() => normalizeGeneralSurgeryGrading(value), [value]);
|
|
10056
|
+
const chips = React15.useMemo(() => chipList2(state), [state]);
|
|
10057
|
+
const regions = React15.useMemo(() => regionList(state), [state]);
|
|
10058
|
+
const visibleRows = React15.useMemo(() => {
|
|
10059
|
+
return ALL_GS_CONDITIONS.filter(
|
|
10060
|
+
(c) => gsGradingRowVisible(c, chips, regions, safe[c] ?? 0)
|
|
10061
|
+
);
|
|
10062
|
+
}, [chips, regions, safe]);
|
|
10063
|
+
const update = (next) => {
|
|
10064
|
+
setValue(next);
|
|
10065
|
+
setTouched();
|
|
10066
|
+
};
|
|
10067
|
+
const setGrade = (cond, gradeStr) => {
|
|
10068
|
+
const n = Math.min(5, Math.max(0, Math.round(Number(gradeStr)) || 0));
|
|
10069
|
+
update({ ...safe, [cond]: n });
|
|
10070
|
+
};
|
|
10071
|
+
if (!fieldDef) return null;
|
|
10072
|
+
const theme = getThemeConfig("textarea", fieldDef.theme);
|
|
10073
|
+
const wrapperClass = theme?.wrapperClassName ?? "rounded-md overflow-hidden flex flex-col border border-[#D0D0D0]";
|
|
10074
|
+
const labelClass = theme?.labelClassName;
|
|
10075
|
+
const labelContent = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
10076
|
+
fieldDef.label,
|
|
10077
|
+
fieldDef.required ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-1 text-red-500", children: "*" }) : null
|
|
10078
|
+
] });
|
|
10079
|
+
const labelEl = theme ? /* @__PURE__ */ jsxRuntime.jsx(Label, { className: labelClass, children: labelContent }) : /* @__PURE__ */ jsxRuntime.jsx(Label, { className: "text-sm font-medium", children: labelContent });
|
|
10080
|
+
const bodyClass = cn(
|
|
10081
|
+
"-mt-1 flex min-w-0 flex-col gap-3 border-t border-[#D0D0D0] bg-white px-3 py-3",
|
|
10082
|
+
disabled && "pointer-events-none opacity-60"
|
|
10083
|
+
);
|
|
10084
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("w-full min-w-0", wrapperClass), children: [
|
|
10085
|
+
labelEl,
|
|
10086
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: bodyClass, children: visibleRows.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-md border border-dashed border-[#D0D0D0] bg-white p-6 text-center text-xs text-muted-foreground", children: "No conditions to grade yet. Select a chief complaint category or pick an examination region." }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto rounded-md border border-[#D0D0D0]", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full min-w-[520px] border-collapse text-xs", children: [
|
|
10087
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "border-b border-[#D0D0D0] bg-[#FEE8EC]/50", children: [
|
|
10088
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-3 py-2 text-left font-semibold text-slate-700", children: "Condition" }),
|
|
10089
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "w-24 px-2 py-2 font-semibold text-slate-700", children: "Grade" }),
|
|
10090
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-3 py-2 text-left font-semibold text-slate-700", children: "Description" })
|
|
10091
|
+
] }) }),
|
|
10092
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "bg-white", children: visibleRows.map((c) => {
|
|
10093
|
+
const g = safe[c] ?? 0;
|
|
10094
|
+
const desc = GS_GRADE_DESCRIPTIONS[c][g] ?? "\u2014";
|
|
10095
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "border-b border-[#D0D0D0]/80 last:border-0", children: [
|
|
10096
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-3 py-2 font-medium", children: GS_CONDITION_LABELS[c] }),
|
|
10097
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-2 py-1.5 align-middle", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
10098
|
+
Select,
|
|
10099
|
+
{
|
|
10100
|
+
value: String(g),
|
|
10101
|
+
onValueChange: (v) => setGrade(c, v),
|
|
10102
|
+
disabled,
|
|
10103
|
+
children: [
|
|
10104
|
+
/* @__PURE__ */ jsxRuntime.jsx(SelectTrigger, { className: "h-8 text-xs", children: /* @__PURE__ */ jsxRuntime.jsx(SelectValue, {}) }),
|
|
10105
|
+
/* @__PURE__ */ jsxRuntime.jsx(SelectContent, { children: [0, 1, 2, 3, 4, 5].map((n) => /* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: String(n), children: n === 0 ? "\u2014" : String(n) }, n)) })
|
|
10106
|
+
]
|
|
10107
|
+
}
|
|
10108
|
+
) }),
|
|
10109
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-3 py-2 text-muted-foreground", children: desc })
|
|
10110
|
+
] }, c);
|
|
10111
|
+
}) })
|
|
10112
|
+
] }) }) }),
|
|
10113
|
+
showError ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "px-3 pb-2 text-xs text-red-500", children: error }) : null
|
|
10114
|
+
] });
|
|
10115
|
+
};
|
|
10116
|
+
function isFlagSelected(selected, optValue) {
|
|
10117
|
+
return selected.some((v) => v === optValue || String(v) === String(optValue));
|
|
10118
|
+
}
|
|
10119
|
+
var PainScaleFlagsWidget = ({ fieldId }) => {
|
|
10120
|
+
const { fieldDef, value, setValue, setTouched, error, touched, disabled } = useField(fieldId);
|
|
10121
|
+
const { state } = useForm();
|
|
10122
|
+
const showError = !!error && (touched || state.submitAttempted);
|
|
10123
|
+
if (!fieldDef || fieldDef.type !== "pain_scale_flags") return null;
|
|
10124
|
+
const def = fieldDef;
|
|
10125
|
+
const min = def.min ?? 0;
|
|
10126
|
+
const max = def.max ?? 10;
|
|
10127
|
+
const step = def.step ?? 1;
|
|
10128
|
+
const flagOptions = def.options ?? [];
|
|
10129
|
+
const safe = React15.useMemo(
|
|
10130
|
+
() => normalizePainScaleFlags(value, { min, max }),
|
|
10131
|
+
[value, min, max]
|
|
10132
|
+
);
|
|
10133
|
+
const theme = getThemeConfig("textarea", def.theme);
|
|
10134
|
+
const wrapperClass = theme?.wrapperClassName ?? "space-y-2";
|
|
10135
|
+
const labelClass = theme?.labelClassName;
|
|
10136
|
+
const update = (next) => {
|
|
10137
|
+
setValue(normalizePainScaleFlags(next, { min, max }));
|
|
10138
|
+
setTouched();
|
|
10139
|
+
};
|
|
10140
|
+
const toggleFlag = (optValue) => {
|
|
10141
|
+
const sel = safe.flags;
|
|
10142
|
+
const isSelected = isFlagSelected(sel, optValue);
|
|
10143
|
+
const nextFlags = isSelected ? sel.filter((v) => v !== optValue && String(v) !== String(optValue)) : [...sel, String(optValue)];
|
|
10144
|
+
update({ pain: safe.pain, flags: nextFlags });
|
|
10145
|
+
};
|
|
10146
|
+
const labelContent = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
10147
|
+
def.label,
|
|
10148
|
+
" ",
|
|
10149
|
+
def.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-red-500", children: "*" })
|
|
10150
|
+
] });
|
|
10151
|
+
const labelEl = theme ? /* @__PURE__ */ jsxRuntime.jsx(Label, { className: labelClass, children: labelContent }) : /* @__PURE__ */ jsxRuntime.jsx(Label, { children: labelContent });
|
|
10152
|
+
const bodyClass = cn(
|
|
10153
|
+
"-mt-1 flex min-w-0 flex-col border-t border-[#D0D0D0] bg-white px-3 py-3",
|
|
10154
|
+
disabled && "pointer-events-none opacity-60"
|
|
10155
|
+
);
|
|
10156
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(wrapperClass, "h-full min-h-0 flex flex-col"), children: [
|
|
10157
|
+
labelEl,
|
|
10158
|
+
def.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: def.description }),
|
|
10159
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(bodyClass, "min-h-0 flex-1"), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 space-y-3", children: [
|
|
10160
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
10161
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Label, { className: "text-sm font-medium text-slate-700", children: [
|
|
10162
|
+
"Pain score (VAS)",
|
|
10163
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ml-2 font-normal tabular-nums text-muted-foreground", children: [
|
|
10164
|
+
safe.pain,
|
|
10165
|
+
"/",
|
|
10166
|
+
max
|
|
10167
|
+
] })
|
|
10168
|
+
] }),
|
|
10169
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
10170
|
+
Slider,
|
|
10171
|
+
{
|
|
10172
|
+
className: cn("py-1", showError && "rounded opacity-90 ring-1 ring-red-500"),
|
|
10173
|
+
disabled,
|
|
10174
|
+
min,
|
|
10175
|
+
max,
|
|
10176
|
+
step,
|
|
10177
|
+
value: [safe.pain],
|
|
10178
|
+
onValueChange: (v) => {
|
|
10179
|
+
const n = v[0] ?? min;
|
|
10180
|
+
update({ pain: n, flags: safe.flags });
|
|
10181
|
+
}
|
|
10182
|
+
}
|
|
10183
|
+
)
|
|
10184
|
+
] }),
|
|
10185
|
+
flagOptions.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 space-y-1.5", children: [
|
|
10186
|
+
/* @__PURE__ */ jsxRuntime.jsx(Label, { className: "text-sm font-medium text-slate-700", children: "Triage flags" }),
|
|
10187
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-x-4 gap-y-2", children: flagOptions.map((opt) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
10188
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
10189
|
+
Checkbox,
|
|
10190
|
+
{
|
|
10191
|
+
id: `${fieldId}-flag-${String(opt.value)}`,
|
|
10192
|
+
checked: isFlagSelected(safe.flags, opt.value),
|
|
10193
|
+
onCheckedChange: () => toggleFlag(opt.value),
|
|
10194
|
+
disabled
|
|
10195
|
+
}
|
|
10196
|
+
),
|
|
10197
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
10198
|
+
Label,
|
|
10199
|
+
{
|
|
10200
|
+
htmlFor: `${fieldId}-flag-${String(opt.value)}`,
|
|
10201
|
+
className: "cursor-pointer text-sm font-normal leading-none",
|
|
10202
|
+
children: opt.label
|
|
10203
|
+
}
|
|
10204
|
+
)
|
|
10205
|
+
] }, String(opt.value))) })
|
|
10206
|
+
] }) : null
|
|
10207
|
+
] }) }),
|
|
10208
|
+
showError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-red-500", children: error })
|
|
10209
|
+
] });
|
|
10210
|
+
};
|
|
10211
|
+
var FieldRenderer = ({ fieldId }) => {
|
|
10212
|
+
const { fieldDef, visible } = useField(fieldId);
|
|
10213
|
+
if (!visible || !fieldDef) {
|
|
10214
|
+
return null;
|
|
10215
|
+
}
|
|
10216
|
+
return renderWidget(fieldId, fieldDef);
|
|
10217
|
+
};
|
|
10218
|
+
function renderWidget(fieldId, fieldDef) {
|
|
10219
|
+
switch (fieldDef.type) {
|
|
10220
|
+
case "text":
|
|
10221
|
+
case "number":
|
|
10222
|
+
return /* @__PURE__ */ jsxRuntime.jsx(TextWidget, { fieldId });
|
|
10223
|
+
case "slider":
|
|
10224
|
+
return /* @__PURE__ */ jsxRuntime.jsx(SliderWidget, { fieldId });
|
|
10225
|
+
case "textarea":
|
|
10226
|
+
if (fieldMetaRequestsMarMedicationOrdersButton(fieldDef.meta)) {
|
|
10227
|
+
return /* @__PURE__ */ jsxRuntime.jsx(MarMedicationOrdersWidget, { fieldId });
|
|
10228
|
+
}
|
|
10229
|
+
return /* @__PURE__ */ jsxRuntime.jsx(TextWidget, { fieldId });
|
|
10230
|
+
case "richtext":
|
|
10231
|
+
return /* @__PURE__ */ jsxRuntime.jsx(RichTextWidget, { fieldId });
|
|
10232
|
+
case "date":
|
|
10233
|
+
return /* @__PURE__ */ jsxRuntime.jsx(DateWidget, { fieldId });
|
|
10234
|
+
case "datetime":
|
|
10235
|
+
return /* @__PURE__ */ jsxRuntime.jsx(DateTimeWidget, { fieldId });
|
|
10236
|
+
case "select":
|
|
10237
|
+
return /* @__PURE__ */ jsxRuntime.jsx(SelectWidget, { fieldId });
|
|
10238
|
+
case "radio":
|
|
10239
|
+
return /* @__PURE__ */ jsxRuntime.jsx(RadioWidget, { fieldId });
|
|
10240
|
+
case "checkbox":
|
|
10241
|
+
return /* @__PURE__ */ jsxRuntime.jsx(CheckboxWidget, { fieldId });
|
|
10242
|
+
case "multiselect":
|
|
10243
|
+
return /* @__PURE__ */ jsxRuntime.jsx(MultiSelectWidget, { fieldId });
|
|
10244
|
+
case "repeatable":
|
|
10245
|
+
return /* @__PURE__ */ jsxRuntime.jsx(RepeatableWidget, { fieldId });
|
|
10246
|
+
case "image_upload":
|
|
10247
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ImageUploadWidget, { fieldId });
|
|
10248
|
+
case "media_upload":
|
|
10249
|
+
return /* @__PURE__ */ jsxRuntime.jsx(MediaUploadWidget, { fieldId });
|
|
10250
|
+
case "signature":
|
|
10251
|
+
return /* @__PURE__ */ jsxRuntime.jsx(SignatureUploadWidget, { fieldId });
|
|
10252
|
+
case "editable_table":
|
|
10253
|
+
return /* @__PURE__ */ jsxRuntime.jsx(EditableTableWidget, { fieldId });
|
|
10254
|
+
case "medications":
|
|
10255
|
+
return /* @__PURE__ */ jsxRuntime.jsx(AddMedicationWidget, { fieldId });
|
|
10256
|
+
case "discharge_medication_orders":
|
|
10257
|
+
return /* @__PURE__ */ jsxRuntime.jsx(DischargeMedicationOrdersWidget, { fieldId });
|
|
10258
|
+
case "investigations":
|
|
10259
|
+
return /* @__PURE__ */ jsxRuntime.jsx(AddInvestigationWidget, { fieldId });
|
|
10260
|
+
case "procedures":
|
|
10261
|
+
return /* @__PURE__ */ jsxRuntime.jsx(AddProcedureWidget, { fieldId });
|
|
10262
|
+
case "differential_diagnosis":
|
|
10263
|
+
return /* @__PURE__ */ jsxRuntime.jsx(DifferentialDiagnosisWidget, { fieldId });
|
|
10264
|
+
case "vitals":
|
|
10265
|
+
return /* @__PURE__ */ jsxRuntime.jsx(VitalsWidget, { fieldId });
|
|
10266
|
+
case "hidden_vitals":
|
|
10267
|
+
return /* @__PURE__ */ jsxRuntime.jsx(HiddenVitalsWidget, { fieldId });
|
|
10268
|
+
case "referral":
|
|
10269
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ReferralWidget, { fieldId });
|
|
10270
|
+
case "followup":
|
|
10271
|
+
return /* @__PURE__ */ jsxRuntime.jsx(FollowupWidget, { fieldId });
|
|
10272
|
+
case "smart_textarea":
|
|
10273
|
+
return /* @__PURE__ */ jsxRuntime.jsx(SmartTextareaWidget, { fieldId });
|
|
10274
|
+
case "diagnosis_textarea":
|
|
10275
|
+
return /* @__PURE__ */ jsxRuntime.jsx(DiagnosisTextareaWidget, { fieldId });
|
|
10276
|
+
case "obstetric_history":
|
|
10277
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ObstetricHistoryWidget, { fieldId });
|
|
10278
|
+
case "eye_prescription":
|
|
10279
|
+
return /* @__PURE__ */ jsxRuntime.jsx(OphthalmologyWidget, { fieldId });
|
|
10280
|
+
case "ophthal_diagnosis":
|
|
10281
|
+
return /* @__PURE__ */ jsxRuntime.jsx(OphthalDiagnosisWidget, { fieldId });
|
|
10282
|
+
case "orthopedic_exam":
|
|
10283
|
+
return /* @__PURE__ */ jsxRuntime.jsx(OrthopedicExamWidget, { fieldId });
|
|
10284
|
+
case "general_surgery_smart_history":
|
|
10285
|
+
return /* @__PURE__ */ jsxRuntime.jsx(GsSmartHistoryWidget, { fieldId });
|
|
10286
|
+
case "general_surgery_examination":
|
|
10287
|
+
return /* @__PURE__ */ jsxRuntime.jsx(GsExaminationWidget, { fieldId });
|
|
10288
|
+
case "general_surgery_grading":
|
|
10289
|
+
return /* @__PURE__ */ jsxRuntime.jsx(GsGradingWidget, { fieldId });
|
|
10290
|
+
case "pain_scale_flags":
|
|
10291
|
+
return /* @__PURE__ */ jsxRuntime.jsx(PainScaleFlagsWidget, { fieldId });
|
|
10292
|
+
case "toggle": {
|
|
10293
|
+
const { value, setValue, setTouched, disabled } = useField(fieldId);
|
|
10294
|
+
const store = useFormStore();
|
|
10295
|
+
const excludes = fieldDef.excludes ?? [];
|
|
10296
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
10297
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
10298
|
+
Switch,
|
|
10299
|
+
{
|
|
10300
|
+
checked: value === true,
|
|
10301
|
+
disabled,
|
|
10302
|
+
onCheckedChange: (checked) => {
|
|
10303
|
+
setValue(checked);
|
|
10304
|
+
setTouched();
|
|
10305
|
+
if (checked) excludes.forEach((id) => store.setValue(id, false));
|
|
10306
|
+
}
|
|
10307
|
+
}
|
|
10308
|
+
),
|
|
10309
|
+
/* @__PURE__ */ jsxRuntime.jsx(Label, { className: "text-sm font-medium leading-none cursor-pointer select-none", children: fieldDef.label })
|
|
10310
|
+
] });
|
|
10311
|
+
}
|
|
10312
|
+
case "suggestion_textarea":
|
|
10313
|
+
case "complaint_chips":
|
|
10314
|
+
return /* @__PURE__ */ jsxRuntime.jsx(SuggestionTextareaWidget, { fieldId });
|
|
10315
|
+
case "lens_assessment":
|
|
10316
|
+
return /* @__PURE__ */ jsxRuntime.jsx(LensAssessmentWidget, { fieldId });
|
|
10317
|
+
case "functional_impairment_score":
|
|
10318
|
+
return /* @__PURE__ */ jsxRuntime.jsx(FunctionalImpairmentScoreWidget, { fieldId });
|
|
10319
|
+
case "biometry_iol_workup":
|
|
10320
|
+
return /* @__PURE__ */ jsxRuntime.jsx(BiometryIolWorkupWidget, { fieldId });
|
|
10321
|
+
case "surgical_risk_flags":
|
|
10322
|
+
return /* @__PURE__ */ jsxRuntime.jsx(SurgicalRiskFlagsWidget, { fieldId });
|
|
10323
|
+
case "static_text": {
|
|
10324
|
+
const def = fieldDef;
|
|
10325
|
+
const size = def.size ?? "regular";
|
|
10326
|
+
const labelClass = size === "large" ? "text-base" : "text-sm";
|
|
10327
|
+
const descClass = size === "large" ? "text-sm" : "text-xs";
|
|
10328
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${labelClass} text-muted-foreground`, children: [
|
|
10329
|
+
def.label,
|
|
10330
|
+
def.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `mt-1 ${descClass} opacity-90`, children: def.description })
|
|
10331
|
+
] });
|
|
10332
|
+
}
|
|
10333
|
+
default:
|
|
10334
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-red-500", children: [
|
|
10335
|
+
"Unknown field type: ",
|
|
10336
|
+
fieldDef.type
|
|
10337
|
+
] });
|
|
10338
|
+
}
|
|
10339
|
+
}
|
|
10340
|
+
var Section = ({ title, children }) => {
|
|
10341
|
+
const [expanded, setExpanded] = React15.useState(true);
|
|
10342
|
+
const handleToggle = () => setExpanded((prev) => !prev);
|
|
10343
|
+
const contentClassName = cn(
|
|
10344
|
+
"overflow-hidden transition-[height] duration-200 ease-in-out",
|
|
10345
|
+
!expanded && "hidden"
|
|
10346
|
+
);
|
|
10347
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-6 border rounded-lg bg-white shadow-sm overflow-hidden", children: [
|
|
10348
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
10349
|
+
"button",
|
|
10350
|
+
{
|
|
10351
|
+
type: "button",
|
|
10352
|
+
onClick: handleToggle,
|
|
10353
|
+
className: "w-full flex items-center justify-between gap-2 p-4 text-left border-b hover:bg-gray-50/80 transition-colors",
|
|
10354
|
+
children: [
|
|
10355
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-medium", children: title }),
|
|
10356
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0 text-muted-foreground", "aria-hidden": true, children: expanded ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "h-5 w-5" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { className: "h-5 w-5" }) })
|
|
10357
|
+
]
|
|
10358
|
+
}
|
|
10359
|
+
),
|
|
10360
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: contentClassName, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4 pt-4 space-y-4 border-t-0", children }) })
|
|
10361
|
+
] });
|
|
10362
|
+
};
|
|
10363
|
+
var ColumnLayout = ({
|
|
10364
|
+
columns,
|
|
10365
|
+
label,
|
|
10366
|
+
children
|
|
10367
|
+
}) => {
|
|
10368
|
+
const gridCols = Math.max(1, Math.min(columns, 12));
|
|
10369
|
+
const gridClass = `grid gap-4 w-full`;
|
|
10370
|
+
const style = {
|
|
10371
|
+
gridTemplateColumns: `repeat(${gridCols}, minmax(0, 1fr))`
|
|
10372
|
+
};
|
|
10373
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-6", children: [
|
|
10374
|
+
label != null && label !== "" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-2 text-sm font-medium text-gray-700", children: label }),
|
|
10375
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: gridClass, style, children })
|
|
9102
10376
|
] });
|
|
9103
10377
|
};
|
|
9104
10378
|
var DynamicForm = () => {
|
|
@@ -9250,14 +10524,24 @@ var SmartForm = ({
|
|
|
9250
10524
|
if (position !== "left") return null;
|
|
9251
10525
|
return /* @__PURE__ */ jsxRuntime.jsx(FieldRenderer, { fieldId }, fieldId);
|
|
9252
10526
|
}) }),
|
|
9253
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-2 grid grid-cols-2 gap-
|
|
10527
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-2 grid grid-cols-2 gap-2", children: fieldIds.map((fieldId) => {
|
|
9254
10528
|
const fieldDef = store.getFieldDef(fieldId);
|
|
9255
10529
|
if (!fieldDef) return null;
|
|
9256
10530
|
const position = fieldDef.position ?? "center";
|
|
9257
10531
|
if (position !== "center") return null;
|
|
9258
10532
|
const colSpanRaw = fieldDef.colSpan ?? 1;
|
|
9259
10533
|
const colSpan = colSpanRaw === 2 ? 2 : 1;
|
|
9260
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
10534
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
10535
|
+
"div",
|
|
10536
|
+
{
|
|
10537
|
+
className: cn(
|
|
10538
|
+
"min-h-0 flex flex-col",
|
|
10539
|
+
colSpan === 2 ? "col-span-2" : "col-span-1 h-full"
|
|
10540
|
+
),
|
|
10541
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(FieldRenderer, { fieldId })
|
|
10542
|
+
},
|
|
10543
|
+
fieldId
|
|
10544
|
+
);
|
|
9261
10545
|
}) }),
|
|
9262
10546
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-1 flex flex-col gap-2", children: fieldIds.map((fieldId) => {
|
|
9263
10547
|
const fieldDef = store.getFieldDef(fieldId);
|
|
@@ -9705,11 +10989,17 @@ var ReadOnlyDischargeMedicationOrders = ({ fieldDef, value }) => {
|
|
|
9705
10989
|
}) })
|
|
9706
10990
|
] });
|
|
9707
10991
|
};
|
|
9708
|
-
var ReadOnlyFieldRenderer = ({
|
|
10992
|
+
var ReadOnlyFieldRenderer = ({
|
|
10993
|
+
fieldDef,
|
|
10994
|
+
value,
|
|
10995
|
+
allValues,
|
|
10996
|
+
resolveFieldDef
|
|
10997
|
+
}) => {
|
|
9709
10998
|
if (!fieldDef) return null;
|
|
9710
10999
|
switch (fieldDef.type) {
|
|
9711
11000
|
case "text":
|
|
9712
11001
|
case "number":
|
|
11002
|
+
case "slider":
|
|
9713
11003
|
case "textarea":
|
|
9714
11004
|
case "richtext":
|
|
9715
11005
|
return /* @__PURE__ */ jsxRuntime.jsx(ReadOnlyText, { fieldDef, value });
|
|
@@ -9747,8 +11037,30 @@ var ReadOnlyFieldRenderer = ({ fieldDef, value }) => {
|
|
|
9747
11037
|
] });
|
|
9748
11038
|
}
|
|
9749
11039
|
case "suggestion_textarea":
|
|
9750
|
-
case "complaint_chips":
|
|
9751
|
-
|
|
11040
|
+
case "complaint_chips": {
|
|
11041
|
+
const embeddedIds = fieldDef.meta && Array.isArray(fieldDef.meta.embeddedFieldIds) ? fieldDef.meta.embeddedFieldIds.filter((id) => typeof id === "string" && id.trim().length > 0).map((id) => id.trim()) : [];
|
|
11042
|
+
const showEmbedded = embeddedIds.length > 0 && resolveFieldDef && allValues && typeof allValues === "object";
|
|
11043
|
+
if (!showEmbedded) {
|
|
11044
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ReadOnlyText, { fieldDef, value });
|
|
11045
|
+
}
|
|
11046
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
|
|
11047
|
+
/* @__PURE__ */ jsxRuntime.jsx(ReadOnlyText, { fieldDef, value }),
|
|
11048
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid gap-3 border-t border-muted-foreground/20 pt-3 sm:grid-cols-3", children: embeddedIds.map((id) => {
|
|
11049
|
+
const fd = resolveFieldDef(id);
|
|
11050
|
+
if (!fd) return null;
|
|
11051
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
11052
|
+
ReadOnlyFieldRenderer,
|
|
11053
|
+
{
|
|
11054
|
+
fieldDef: fd,
|
|
11055
|
+
value: allValues[id],
|
|
11056
|
+
allValues,
|
|
11057
|
+
resolveFieldDef
|
|
11058
|
+
},
|
|
11059
|
+
id
|
|
11060
|
+
);
|
|
11061
|
+
}) })
|
|
11062
|
+
] });
|
|
11063
|
+
}
|
|
9752
11064
|
case "lens_assessment": {
|
|
9753
11065
|
const v = value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
9754
11066
|
const notes = typeof v?.notes === "string" ? v.notes : "";
|
|
@@ -9824,6 +11136,44 @@ var ReadOnlyFieldRenderer = ({ fieldDef, value }) => {
|
|
|
9824
11136
|
const lines = [`Right eye (OD): ${od}`, `Left eye (OS): ${os}`].join("\n");
|
|
9825
11137
|
return /* @__PURE__ */ jsxRuntime.jsx(ReadOnlyText, { fieldDef, value: lines });
|
|
9826
11138
|
}
|
|
11139
|
+
case "pain_scale_flags": {
|
|
11140
|
+
const def = fieldDef;
|
|
11141
|
+
const min = def.min ?? 0;
|
|
11142
|
+
const max = def.max ?? 10;
|
|
11143
|
+
const safe = normalizePainScaleFlags(value, { min, max });
|
|
11144
|
+
const opts = def.options ?? [];
|
|
11145
|
+
const flagLabels = safe.flags.map((fv) => {
|
|
11146
|
+
const o = opts.find((x) => x.value === fv || String(x.value) === String(fv));
|
|
11147
|
+
return o?.label ?? fv;
|
|
11148
|
+
});
|
|
11149
|
+
const lines = [
|
|
11150
|
+
`Pain score (VAS): ${safe.pain}/${max}`,
|
|
11151
|
+
flagLabels.length > 0 ? `Triage flags: ${flagLabels.join(", ")}` : "Triage flags: \u2014"
|
|
11152
|
+
].join("\n");
|
|
11153
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ReadOnlyText, { fieldDef, value: lines });
|
|
11154
|
+
}
|
|
11155
|
+
case "general_surgery_smart_history":
|
|
11156
|
+
case "general_surgery_grading":
|
|
11157
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
11158
|
+
ReadOnlyText,
|
|
11159
|
+
{
|
|
11160
|
+
fieldDef,
|
|
11161
|
+
value: value && typeof value === "object" ? JSON.stringify(value, null, 2) : value == null || value === "" ? "\u2014" : String(value)
|
|
11162
|
+
}
|
|
11163
|
+
);
|
|
11164
|
+
case "general_surgery_examination": {
|
|
11165
|
+
const structuredDisplay = value && typeof value === "object" ? JSON.stringify(value, null, 2) : value == null || value === "" ? "\u2014" : String(value);
|
|
11166
|
+
const clinicalDef = resolveFieldDef?.("clinical_examination");
|
|
11167
|
+
const clinicalRaw = allValues?.["clinical_examination"];
|
|
11168
|
+
const clinicalStr = typeof clinicalRaw === "string" ? clinicalRaw : clinicalRaw != null && clinicalRaw !== "" ? String(clinicalRaw) : "";
|
|
11169
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
|
|
11170
|
+
/* @__PURE__ */ jsxRuntime.jsx(ReadOnlyText, { fieldDef, value: structuredDisplay }),
|
|
11171
|
+
clinicalDef ? /* @__PURE__ */ jsxRuntime.jsx(ReadOnlyText, { fieldDef: clinicalDef, value: clinicalStr }) : clinicalStr ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
11172
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-gray-700", children: "Clinical examination" }),
|
|
11173
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-gray-900 border border-gray-200 rounded-md p-3 bg-gray-50 min-h-[2.5rem] whitespace-pre-wrap", children: clinicalStr })
|
|
11174
|
+
] }) : null
|
|
11175
|
+
] });
|
|
11176
|
+
}
|
|
9827
11177
|
case "static_text": {
|
|
9828
11178
|
const def = fieldDef;
|
|
9829
11179
|
const size = def.size ?? "regular";
|
|
@@ -9870,7 +11220,9 @@ var ReadOnlyForm = ({ schema, submission }) => {
|
|
|
9870
11220
|
ReadOnlyFieldRenderer,
|
|
9871
11221
|
{
|
|
9872
11222
|
fieldDef,
|
|
9873
|
-
value: formData[child]
|
|
11223
|
+
value: formData[child],
|
|
11224
|
+
allValues: formData,
|
|
11225
|
+
resolveFieldDef: (id) => fieldMap.get(id)
|
|
9874
11226
|
},
|
|
9875
11227
|
child
|
|
9876
11228
|
) : null;
|
|
@@ -9889,7 +11241,9 @@ var ReadOnlyForm = ({ schema, submission }) => {
|
|
|
9889
11241
|
ReadOnlyFieldRenderer,
|
|
9890
11242
|
{
|
|
9891
11243
|
fieldDef,
|
|
9892
|
-
value: formData[fieldId]
|
|
11244
|
+
value: formData[fieldId],
|
|
11245
|
+
allValues: formData,
|
|
11246
|
+
resolveFieldDef: (id) => fieldMap.get(id)
|
|
9893
11247
|
},
|
|
9894
11248
|
fieldId
|
|
9895
11249
|
))
|
|
@@ -9920,7 +11274,9 @@ var ReadOnlyForm = ({ schema, submission }) => {
|
|
|
9920
11274
|
ReadOnlyFieldRenderer,
|
|
9921
11275
|
{
|
|
9922
11276
|
fieldDef,
|
|
9923
|
-
value: formData[fieldId]
|
|
11277
|
+
value: formData[fieldId],
|
|
11278
|
+
allValues: formData,
|
|
11279
|
+
resolveFieldDef: (id) => fieldMap.get(id)
|
|
9924
11280
|
},
|
|
9925
11281
|
fieldId
|
|
9926
11282
|
))
|