formanitor 0.0.38 → 0.0.40
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 +1545 -185
- 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 +1545 -185
- 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
|
}
|
|
@@ -6420,7 +6669,11 @@ var OphthalmologyWidget = ({ fieldId }) => {
|
|
|
6420
6669
|
] })
|
|
6421
6670
|
] }),
|
|
6422
6671
|
/* @__PURE__ */ jsxRuntime.jsx("tbody", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
6423
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: refractionLabelCellClass
|
|
6672
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: `${refractionLabelCellClass} whitespace-normal`, children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "block leading-tight", children: [
|
|
6673
|
+
"Current",
|
|
6674
|
+
/* @__PURE__ */ jsxRuntime.jsx("br", {}),
|
|
6675
|
+
"Glass"
|
|
6676
|
+
] }) }),
|
|
6424
6677
|
/* @__PURE__ */ jsxRuntime.jsx("td", { className: refractionDataCellClass, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6425
6678
|
Input,
|
|
6426
6679
|
{
|
|
@@ -6675,12 +6928,12 @@ var OphthalmologyWidget = ({ fieldId }) => {
|
|
|
6675
6928
|
/* @__PURE__ */ jsxRuntime.jsx("th", { className: refractionHeaderCellClass, children: "Sph" }),
|
|
6676
6929
|
/* @__PURE__ */ jsxRuntime.jsx("th", { className: refractionHeaderCellClass, children: "Cyl" }),
|
|
6677
6930
|
/* @__PURE__ */ jsxRuntime.jsx("th", { className: refractionHeaderCellClass, children: "Axis" }),
|
|
6678
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: refractionHeaderCellClass, children: "
|
|
6931
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: refractionHeaderCellClass, children: "BCVA" }),
|
|
6679
6932
|
/* @__PURE__ */ jsxRuntime.jsx("th", { className: refractionHeaderCellClass, children: "P/D" }),
|
|
6680
6933
|
/* @__PURE__ */ jsxRuntime.jsx("th", { className: refractionHeaderCellClass, children: "Sph" }),
|
|
6681
6934
|
/* @__PURE__ */ jsxRuntime.jsx("th", { className: refractionHeaderCellClass, children: "Cyl" }),
|
|
6682
6935
|
/* @__PURE__ */ jsxRuntime.jsx("th", { className: refractionHeaderCellClass, children: "Axis" }),
|
|
6683
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: refractionHeaderCellClass, children: "
|
|
6936
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: refractionHeaderCellClass, children: "BCVA" }),
|
|
6684
6937
|
/* @__PURE__ */ jsxRuntime.jsx("th", { className: refractionHeaderCellClass, children: "P/D" })
|
|
6685
6938
|
] })
|
|
6686
6939
|
] }),
|
|
@@ -8069,6 +8322,21 @@ function parallelChipArraysEqual(a, b) {
|
|
|
8069
8322
|
function isSuggestionField(type) {
|
|
8070
8323
|
return type === "suggestion_textarea" || type === "complaint_chips";
|
|
8071
8324
|
}
|
|
8325
|
+
function EmbeddedSchemaField({ fieldId }) {
|
|
8326
|
+
const store = useFormStore();
|
|
8327
|
+
const fieldDef = store.getFieldDef(fieldId);
|
|
8328
|
+
if (!fieldDef) return null;
|
|
8329
|
+
switch (fieldDef.type) {
|
|
8330
|
+
case "text":
|
|
8331
|
+
case "number":
|
|
8332
|
+
case "textarea":
|
|
8333
|
+
return /* @__PURE__ */ jsxRuntime.jsx(TextWidget, { fieldId });
|
|
8334
|
+
case "select":
|
|
8335
|
+
return /* @__PURE__ */ jsxRuntime.jsx(SelectWidget, { fieldId });
|
|
8336
|
+
default:
|
|
8337
|
+
return null;
|
|
8338
|
+
}
|
|
8339
|
+
}
|
|
8072
8340
|
var SuggestionTextareaWidget = ({ fieldId }) => {
|
|
8073
8341
|
const { fieldDef, value, setValue, setTouched, error, disabled, touched } = useField(fieldId);
|
|
8074
8342
|
const { state } = useForm();
|
|
@@ -8080,6 +8348,10 @@ var SuggestionTextareaWidget = ({ fieldId }) => {
|
|
|
8080
8348
|
const def = fieldDef && isSuggestionField(fieldDef.type) ? fieldDef : void 0;
|
|
8081
8349
|
const textValue = value == null || typeof value === "string" ? value || "" : String(value);
|
|
8082
8350
|
const parallelChipFieldId = def?.meta && typeof def.meta.parallelChipFieldId === "string" ? def.meta.parallelChipFieldId.trim() : void 0;
|
|
8351
|
+
const embeddedFieldIds = React15.useMemo(() => {
|
|
8352
|
+
const raw = def?.meta && Array.isArray(def.meta.embeddedFieldIds) ? def.meta.embeddedFieldIds : [];
|
|
8353
|
+
return raw.filter((id) => typeof id === "string" && id.trim().length > 0).map((id) => id.trim()).filter((id) => store.getFieldDef(id));
|
|
8354
|
+
}, [def?.meta, store]);
|
|
8083
8355
|
React15.useEffect(() => {
|
|
8084
8356
|
if (!def) {
|
|
8085
8357
|
setOptions([]);
|
|
@@ -8124,19 +8396,26 @@ var SuggestionTextareaWidget = ({ fieldId }) => {
|
|
|
8124
8396
|
setValue(toggleSuggestionTokenInText(textValue, String(optValue), appendSeparator));
|
|
8125
8397
|
};
|
|
8126
8398
|
const hasSuggestions = options.length > 0;
|
|
8399
|
+
const hasEmbedded = embeddedFieldIds.length > 0;
|
|
8400
|
+
const hasShell = hasSuggestions || hasEmbedded;
|
|
8127
8401
|
const isHighlightLabel = def.theme === "highlight-label";
|
|
8128
8402
|
const suggestionShellClass = cn(
|
|
8129
8403
|
"flex min-w-0 flex-col overflow-hidden",
|
|
8130
|
-
|
|
8404
|
+
hasShell && (isHighlightLabel ? "-mt-1 rounded-b-md border-[#D0D0D0] bg-white" : "rounded-md border border-input bg-background")
|
|
8131
8405
|
);
|
|
8132
8406
|
const chipsRowClass = cn(
|
|
8133
8407
|
"flex flex-wrap gap-2 px-3 pb-2 pt-3",
|
|
8134
8408
|
hasSuggestions && (isHighlightLabel ? "" : "border-b border-input/70"),
|
|
8135
8409
|
disabled && "pointer-events-none opacity-50"
|
|
8136
8410
|
);
|
|
8411
|
+
const embeddedRowClass = cn(
|
|
8412
|
+
"grid gap-3 px-3 sm:grid-cols-3",
|
|
8413
|
+
hasEmbedded && (hasSuggestions ? cn("py-2", isHighlightLabel && "border-t border-input/70") : "border-b border-input/70 py-3"),
|
|
8414
|
+
disabled && "pointer-events-none opacity-50"
|
|
8415
|
+
);
|
|
8137
8416
|
const textareaShellClass = cn(
|
|
8138
8417
|
inputClass,
|
|
8139
|
-
|
|
8418
|
+
hasShell && cn(
|
|
8140
8419
|
"mt-0 rounded-t-none rounded-b-md border-0 shadow-none focus-visible:ring-offset-0",
|
|
8141
8420
|
isHighlightLabel ? "border-t-0" : "min-h-[80px]"
|
|
8142
8421
|
)
|
|
@@ -8163,8 +8442,9 @@ var SuggestionTextareaWidget = ({ fieldId }) => {
|
|
|
8163
8442
|
/* @__PURE__ */ jsxRuntime.jsx(VoiceMicButton, { fieldId, onTranscriptReady: setValue })
|
|
8164
8443
|
] }) : labelEl,
|
|
8165
8444
|
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 }),
|
|
8445
|
+
hasShell ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: suggestionShellClass, children: [
|
|
8446
|
+
hasSuggestions && /* @__PURE__ */ jsxRuntime.jsx("div", { className: chipsRowClass, role: "group", "aria-label": suggestionsAria, children: suggestionButtons }),
|
|
8447
|
+
hasEmbedded && /* @__PURE__ */ jsxRuntime.jsx("div", { className: embeddedRowClass, children: embeddedFieldIds.map((id) => /* @__PURE__ */ jsxRuntime.jsx(EmbeddedSchemaField, { fieldId: id }, id)) }),
|
|
8168
8448
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8169
8449
|
Textarea,
|
|
8170
8450
|
{
|
|
@@ -8944,178 +9224,1176 @@ var SurgicalRiskFlagsWidget = ({ fieldId }) => {
|
|
|
8944
9224
|
}
|
|
8945
9225
|
);
|
|
8946
9226
|
};
|
|
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",
|
|
9227
|
+
var SliderWidget = ({ fieldId }) => {
|
|
9228
|
+
const { fieldDef, value, setValue, setTouched, error, disabled, touched } = useField(fieldId);
|
|
9229
|
+
const { state } = useForm();
|
|
9230
|
+
const showError = !!error && (touched || state.submitAttempted);
|
|
9231
|
+
if (!fieldDef || fieldDef.type !== "slider") return null;
|
|
9232
|
+
const def = fieldDef;
|
|
9233
|
+
const min = def.min ?? 0;
|
|
9234
|
+
const max = def.max ?? 10;
|
|
9235
|
+
const step = def.step ?? 1;
|
|
9236
|
+
const raw = value == null || value === "" ? min : Number(value);
|
|
9237
|
+
const num = Number.isFinite(raw) ? Math.min(max, Math.max(min, raw)) : min;
|
|
9238
|
+
const theme = getThemeConfig("textarea", def.theme);
|
|
9239
|
+
const wrapperClass = theme?.wrapperClassName ?? "space-y-2";
|
|
9240
|
+
const labelClass = theme?.labelClassName;
|
|
9241
|
+
const labelContent = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
9242
|
+
def.label,
|
|
9243
|
+
" ",
|
|
9244
|
+
def.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-red-500", children: "*" }),
|
|
9245
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ml-2 text-muted-foreground font-normal tabular-nums", children: [
|
|
9246
|
+
num,
|
|
9247
|
+
"/",
|
|
9248
|
+
max
|
|
9249
|
+
] })
|
|
9250
|
+
] });
|
|
9251
|
+
const labelEl = theme ? /* @__PURE__ */ jsxRuntime.jsx(Label, { className: labelClass, children: labelContent }) : /* @__PURE__ */ jsxRuntime.jsx(Label, { children: labelContent });
|
|
9252
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: wrapperClass, children: [
|
|
9253
|
+
labelEl,
|
|
9254
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9255
|
+
Slider,
|
|
9076
9256
|
{
|
|
9077
|
-
|
|
9078
|
-
|
|
9079
|
-
|
|
9080
|
-
|
|
9081
|
-
|
|
9082
|
-
|
|
9083
|
-
|
|
9257
|
+
className: cn("py-1", showError && "opacity-90 ring-1 ring-red-500 rounded"),
|
|
9258
|
+
disabled,
|
|
9259
|
+
min,
|
|
9260
|
+
max,
|
|
9261
|
+
step,
|
|
9262
|
+
value: [num],
|
|
9263
|
+
onValueChange: (v) => {
|
|
9264
|
+
const n = v[0] ?? min;
|
|
9265
|
+
setValue(n);
|
|
9266
|
+
setTouched();
|
|
9267
|
+
}
|
|
9084
9268
|
}
|
|
9085
9269
|
),
|
|
9086
|
-
|
|
9270
|
+
showError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-red-500", children: error })
|
|
9087
9271
|
] });
|
|
9088
9272
|
};
|
|
9089
|
-
var
|
|
9090
|
-
|
|
9091
|
-
label,
|
|
9092
|
-
|
|
9093
|
-
|
|
9094
|
-
|
|
9095
|
-
|
|
9096
|
-
|
|
9097
|
-
|
|
9098
|
-
}
|
|
9099
|
-
|
|
9100
|
-
|
|
9101
|
-
|
|
9273
|
+
var CHIEF_CHIPS_FIELD = "chief_complaints_chips";
|
|
9274
|
+
var SWELLING_OPTS = [
|
|
9275
|
+
{ value: "reducible_hernia", label: "Reducible (hernia)" },
|
|
9276
|
+
{ value: "cough_impulse", label: "Cough impulse" },
|
|
9277
|
+
{ value: "skin_changes", label: "Skin changes" }
|
|
9278
|
+
];
|
|
9279
|
+
var GI_OPTS = [
|
|
9280
|
+
{ value: "bleeding_pr", label: "Bleeding PR" },
|
|
9281
|
+
{ value: "vomiting", label: "Vomiting" },
|
|
9282
|
+
{ value: "haematemesis", label: "Haematemesis" }
|
|
9283
|
+
];
|
|
9284
|
+
var BREAST_OPTS = [
|
|
9285
|
+
{ value: "pain", label: "Pain" },
|
|
9286
|
+
{ value: "fh_ca_breast", label: "Family history of Ca breast" }
|
|
9287
|
+
];
|
|
9288
|
+
var ANO_OPTS = [
|
|
9289
|
+
{ value: "pain_defecation", label: "Pain during defecation" },
|
|
9290
|
+
{ value: "bleeding", label: "Bleeding" },
|
|
9291
|
+
{ value: "constipation", label: "Constipation" },
|
|
9292
|
+
{ value: "discharge", label: "Discharge" }
|
|
9293
|
+
];
|
|
9294
|
+
var THYROID_OPTS = [
|
|
9295
|
+
{ value: "dysphagia", label: "Dysphagia" },
|
|
9296
|
+
{ value: "voice_change", label: "Voice change" },
|
|
9297
|
+
{ value: "thyrotoxicosis", label: "Thyrotoxicosis symptoms" }
|
|
9298
|
+
];
|
|
9299
|
+
var SOCRATES_KEYS = [
|
|
9300
|
+
"site",
|
|
9301
|
+
"onset",
|
|
9302
|
+
"character",
|
|
9303
|
+
"radiation",
|
|
9304
|
+
"associated",
|
|
9305
|
+
"timing",
|
|
9306
|
+
"exacerbating"
|
|
9307
|
+
];
|
|
9308
|
+
function Panel({ title, children }) {
|
|
9309
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "overflow-hidden rounded-md border border-[#D0D0D0] bg-white", children: [
|
|
9310
|
+
/* @__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 }),
|
|
9311
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-3", children })
|
|
9102
9312
|
] });
|
|
9103
|
-
}
|
|
9104
|
-
|
|
9105
|
-
const
|
|
9106
|
-
|
|
9107
|
-
|
|
9108
|
-
|
|
9109
|
-
|
|
9110
|
-
|
|
9111
|
-
|
|
9112
|
-
|
|
9113
|
-
|
|
9114
|
-
|
|
9115
|
-
|
|
9116
|
-
|
|
9117
|
-
|
|
9118
|
-
|
|
9313
|
+
}
|
|
9314
|
+
function chipList(state) {
|
|
9315
|
+
const raw = state.values[CHIEF_CHIPS_FIELD];
|
|
9316
|
+
return Array.isArray(raw) ? raw.filter((x) => typeof x === "string") : [];
|
|
9317
|
+
}
|
|
9318
|
+
var GsSmartHistoryWidget = ({ fieldId }) => {
|
|
9319
|
+
const { fieldDef, value, setValue, setTouched, error, touched, disabled } = useField(fieldId);
|
|
9320
|
+
const { state } = useForm();
|
|
9321
|
+
const showError = !!error && (touched || state.submitAttempted);
|
|
9322
|
+
const safe = React15.useMemo(() => normalizeGeneralSurgerySmartHistory(value), [value]);
|
|
9323
|
+
const chips = React15.useMemo(() => chipList(state), [state]);
|
|
9324
|
+
const showPain = chips.includes("pain");
|
|
9325
|
+
const showSwelling = chips.includes("swelling_lump");
|
|
9326
|
+
const showGI = chips.includes("bleeding") || chips.includes("obstruction");
|
|
9327
|
+
const showBreast = chips.includes("breast");
|
|
9328
|
+
const showAno = chips.includes("anorectal");
|
|
9329
|
+
const showThyroid = chips.includes("thyroid");
|
|
9330
|
+
const update = (next) => {
|
|
9331
|
+
setValue(next);
|
|
9332
|
+
setTouched();
|
|
9333
|
+
};
|
|
9334
|
+
const setPain = (key, v) => {
|
|
9335
|
+
if (key === "severity") {
|
|
9336
|
+
const n = typeof v === "number" ? v : Number(v);
|
|
9337
|
+
const sev = Number.isFinite(n) ? Math.min(10, Math.max(0, Math.round(n))) : 0;
|
|
9338
|
+
update({ ...safe, pain: { ...safe.pain, severity: sev } });
|
|
9339
|
+
return;
|
|
9340
|
+
}
|
|
9341
|
+
update({ ...safe, pain: { ...safe.pain, [key]: String(v) } });
|
|
9342
|
+
};
|
|
9343
|
+
const toggleArr = (section, val) => {
|
|
9344
|
+
if (section === "swelling") {
|
|
9345
|
+
const a = safe.swelling.checks;
|
|
9346
|
+
const next = a.includes(val) ? a.filter((x) => x !== val) : [...a, val];
|
|
9347
|
+
update({ ...safe, swelling: { ...safe.swelling, checks: next } });
|
|
9348
|
+
} else if (section === "gi") {
|
|
9349
|
+
const a = safe.gi.checks;
|
|
9350
|
+
const next = a.includes(val) ? a.filter((x) => x !== val) : [...a, val];
|
|
9351
|
+
update({ ...safe, gi: { ...safe.gi, checks: next } });
|
|
9352
|
+
} else if (section === "breast") {
|
|
9353
|
+
const a = safe.breast.checks;
|
|
9354
|
+
const next = a.includes(val) ? a.filter((x) => x !== val) : [...a, val];
|
|
9355
|
+
update({ ...safe, breast: { ...safe.breast, checks: next } });
|
|
9356
|
+
} else if (section === "ano") {
|
|
9357
|
+
const a = safe.ano.checks;
|
|
9358
|
+
const next = a.includes(val) ? a.filter((x) => x !== val) : [...a, val];
|
|
9359
|
+
update({ ...safe, ano: { ...safe.ano, checks: next } });
|
|
9360
|
+
} else {
|
|
9361
|
+
const a = safe.thyroid.checks;
|
|
9362
|
+
const next = a.includes(val) ? a.filter((x) => x !== val) : [...a, val];
|
|
9363
|
+
update({ ...safe, thyroid: { ...safe.thyroid, checks: next } });
|
|
9364
|
+
}
|
|
9365
|
+
};
|
|
9366
|
+
if (!fieldDef) return null;
|
|
9367
|
+
const theme = getThemeConfig("textarea", fieldDef.theme);
|
|
9368
|
+
const wrapperClass = theme?.wrapperClassName ?? "rounded-md overflow-hidden flex flex-col border border-[#D0D0D0]";
|
|
9369
|
+
const labelClass = theme?.labelClassName;
|
|
9370
|
+
const labelContent = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
9371
|
+
fieldDef.label,
|
|
9372
|
+
fieldDef.required ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-1 text-red-500", children: "*" }) : null
|
|
9373
|
+
] });
|
|
9374
|
+
const labelEl = theme ? /* @__PURE__ */ jsxRuntime.jsx(Label, { className: labelClass, children: labelContent }) : /* @__PURE__ */ jsxRuntime.jsx(Label, { className: "text-sm font-medium", children: labelContent });
|
|
9375
|
+
const bodyClass = cn(
|
|
9376
|
+
"-mt-1 flex min-w-0 flex-col gap-3 border-t border-[#D0D0D0] bg-white px-3 py-3",
|
|
9377
|
+
disabled && "pointer-events-none opacity-60"
|
|
9378
|
+
);
|
|
9379
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("w-full min-w-0", wrapperClass), children: [
|
|
9380
|
+
labelEl,
|
|
9381
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: bodyClass, children: [
|
|
9382
|
+
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: [
|
|
9383
|
+
SOCRATES_KEYS.map((k) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
|
|
9384
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-medium uppercase tracking-wide text-muted-foreground", children: k }),
|
|
9385
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9386
|
+
Input,
|
|
9387
|
+
{
|
|
9388
|
+
className: "h-8 text-xs",
|
|
9389
|
+
value: safe.pain[k],
|
|
9390
|
+
onChange: (e) => setPain(k, e.target.value),
|
|
9391
|
+
disabled
|
|
9392
|
+
}
|
|
9393
|
+
)
|
|
9394
|
+
] }, k)),
|
|
9395
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
|
|
9396
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-medium uppercase tracking-wide text-muted-foreground", children: "Severity 0\u201310" }),
|
|
9397
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9398
|
+
Input,
|
|
9399
|
+
{
|
|
9400
|
+
type: "number",
|
|
9401
|
+
min: 0,
|
|
9402
|
+
max: 10,
|
|
9403
|
+
className: "h-8 text-xs",
|
|
9404
|
+
value: safe.pain.severity,
|
|
9405
|
+
onChange: (e) => setPain("severity", e.target.value),
|
|
9406
|
+
disabled
|
|
9407
|
+
}
|
|
9408
|
+
)
|
|
9409
|
+
] })
|
|
9410
|
+
] }) }) : null,
|
|
9411
|
+
showSwelling ? /* @__PURE__ */ jsxRuntime.jsxs(Panel, { title: "Swelling history", children: [
|
|
9412
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-3 text-xs md:grid-cols-3", children: [
|
|
9413
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex flex-col gap-1", children: [
|
|
9414
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: "Duration" }),
|
|
9415
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9416
|
+
Input,
|
|
9417
|
+
{
|
|
9418
|
+
className: "h-8 text-xs",
|
|
9419
|
+
value: safe.swelling.duration,
|
|
9420
|
+
onChange: (e) => update({ ...safe, swelling: { ...safe.swelling, duration: e.target.value } }),
|
|
9421
|
+
disabled
|
|
9422
|
+
}
|
|
9423
|
+
)
|
|
9424
|
+
] }),
|
|
9425
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex flex-col gap-1", children: [
|
|
9426
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: "Size progression" }),
|
|
9427
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9428
|
+
Input,
|
|
9429
|
+
{
|
|
9430
|
+
className: "h-8 text-xs",
|
|
9431
|
+
value: safe.swelling.sizeProgression,
|
|
9432
|
+
onChange: (e) => update({ ...safe, swelling: { ...safe.swelling, sizeProgression: e.target.value } }),
|
|
9433
|
+
disabled
|
|
9434
|
+
}
|
|
9435
|
+
)
|
|
9436
|
+
] }),
|
|
9437
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex flex-col gap-1", children: [
|
|
9438
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: "Painful / painless" }),
|
|
9439
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9440
|
+
Input,
|
|
9441
|
+
{
|
|
9442
|
+
className: "h-8 text-xs",
|
|
9443
|
+
value: safe.swelling.painfulPainless,
|
|
9444
|
+
onChange: (e) => update({ ...safe, swelling: { ...safe.swelling, painfulPainless: e.target.value } }),
|
|
9445
|
+
disabled
|
|
9446
|
+
}
|
|
9447
|
+
)
|
|
9448
|
+
] })
|
|
9449
|
+
] }),
|
|
9450
|
+
/* @__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: [
|
|
9451
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9452
|
+
Checkbox,
|
|
9453
|
+
{
|
|
9454
|
+
checked: safe.swelling.checks.includes(o.value),
|
|
9455
|
+
onCheckedChange: () => toggleArr("swelling", o.value),
|
|
9456
|
+
disabled
|
|
9457
|
+
}
|
|
9458
|
+
),
|
|
9459
|
+
o.label
|
|
9460
|
+
] }, o.value)) })
|
|
9461
|
+
] }) : null,
|
|
9462
|
+
showGI ? /* @__PURE__ */ jsxRuntime.jsxs(Panel, { title: "GI history", children: [
|
|
9463
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-2 text-xs md:grid-cols-3", children: [
|
|
9464
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex flex-col gap-1", children: [
|
|
9465
|
+
"Appetite",
|
|
9466
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9467
|
+
Input,
|
|
9468
|
+
{
|
|
9469
|
+
className: "h-8 text-xs",
|
|
9470
|
+
value: safe.gi.appetite,
|
|
9471
|
+
onChange: (e) => update({ ...safe, gi: { ...safe.gi, appetite: e.target.value } }),
|
|
9472
|
+
disabled
|
|
9473
|
+
}
|
|
9474
|
+
)
|
|
9475
|
+
] }),
|
|
9476
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex flex-col gap-1", children: [
|
|
9477
|
+
"Weight loss",
|
|
9478
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9479
|
+
Input,
|
|
9480
|
+
{
|
|
9481
|
+
className: "h-8 text-xs",
|
|
9482
|
+
value: safe.gi.weightLoss,
|
|
9483
|
+
onChange: (e) => update({ ...safe, gi: { ...safe.gi, weightLoss: e.target.value } }),
|
|
9484
|
+
disabled
|
|
9485
|
+
}
|
|
9486
|
+
)
|
|
9487
|
+
] }),
|
|
9488
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex flex-col gap-1", children: [
|
|
9489
|
+
"Bowel habits",
|
|
9490
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9491
|
+
Input,
|
|
9492
|
+
{
|
|
9493
|
+
className: "h-8 text-xs",
|
|
9494
|
+
value: safe.gi.bowelHabits,
|
|
9495
|
+
onChange: (e) => update({ ...safe, gi: { ...safe.gi, bowelHabits: e.target.value } }),
|
|
9496
|
+
disabled
|
|
9497
|
+
}
|
|
9498
|
+
)
|
|
9499
|
+
] })
|
|
9500
|
+
] }),
|
|
9501
|
+
/* @__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: [
|
|
9502
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9503
|
+
Checkbox,
|
|
9504
|
+
{
|
|
9505
|
+
checked: safe.gi.checks.includes(o.value),
|
|
9506
|
+
onCheckedChange: () => toggleArr("gi", o.value),
|
|
9507
|
+
disabled
|
|
9508
|
+
}
|
|
9509
|
+
),
|
|
9510
|
+
o.label
|
|
9511
|
+
] }, o.value)) })
|
|
9512
|
+
] }) : null,
|
|
9513
|
+
showBreast ? /* @__PURE__ */ jsxRuntime.jsxs(Panel, { title: "Breast history", children: [
|
|
9514
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-2 text-xs md:grid-cols-2", children: [
|
|
9515
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex flex-col gap-1", children: [
|
|
9516
|
+
"Lump duration",
|
|
9517
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9518
|
+
Input,
|
|
9519
|
+
{
|
|
9520
|
+
className: "h-8 text-xs",
|
|
9521
|
+
value: safe.breast.lumpDuration,
|
|
9522
|
+
onChange: (e) => update({ ...safe, breast: { ...safe.breast, lumpDuration: e.target.value } }),
|
|
9523
|
+
disabled
|
|
9524
|
+
}
|
|
9525
|
+
)
|
|
9526
|
+
] }),
|
|
9527
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex flex-col gap-1", children: [
|
|
9528
|
+
"Nipple discharge",
|
|
9529
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9530
|
+
Input,
|
|
9531
|
+
{
|
|
9532
|
+
className: "h-8 text-xs",
|
|
9533
|
+
value: safe.breast.nippleDischarge,
|
|
9534
|
+
onChange: (e) => update({ ...safe, breast: { ...safe.breast, nippleDischarge: e.target.value } }),
|
|
9535
|
+
disabled
|
|
9536
|
+
}
|
|
9537
|
+
)
|
|
9538
|
+
] })
|
|
9539
|
+
] }),
|
|
9540
|
+
/* @__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: [
|
|
9541
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9542
|
+
Checkbox,
|
|
9543
|
+
{
|
|
9544
|
+
checked: safe.breast.checks.includes(o.value),
|
|
9545
|
+
onCheckedChange: () => toggleArr("breast", o.value),
|
|
9546
|
+
disabled
|
|
9547
|
+
}
|
|
9548
|
+
),
|
|
9549
|
+
o.label
|
|
9550
|
+
] }, o.value)) })
|
|
9551
|
+
] }) : null,
|
|
9552
|
+
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: [
|
|
9553
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9554
|
+
Checkbox,
|
|
9555
|
+
{
|
|
9556
|
+
checked: safe.ano.checks.includes(o.value),
|
|
9557
|
+
onCheckedChange: () => toggleArr("ano", o.value),
|
|
9558
|
+
disabled
|
|
9559
|
+
}
|
|
9560
|
+
),
|
|
9561
|
+
o.label
|
|
9562
|
+
] }, o.value)) }) }) : null,
|
|
9563
|
+
showThyroid ? /* @__PURE__ */ jsxRuntime.jsxs(Panel, { title: "Thyroid history", children: [
|
|
9564
|
+
/* @__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: [
|
|
9565
|
+
"Swelling duration",
|
|
9566
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9567
|
+
Input,
|
|
9568
|
+
{
|
|
9569
|
+
className: "h-8 text-xs",
|
|
9570
|
+
value: safe.thyroid.swellingDuration,
|
|
9571
|
+
onChange: (e) => update({ ...safe, thyroid: { ...safe.thyroid, swellingDuration: e.target.value } }),
|
|
9572
|
+
disabled
|
|
9573
|
+
}
|
|
9574
|
+
)
|
|
9575
|
+
] }) }),
|
|
9576
|
+
/* @__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: [
|
|
9577
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9578
|
+
Checkbox,
|
|
9579
|
+
{
|
|
9580
|
+
checked: safe.thyroid.checks.includes(o.value),
|
|
9581
|
+
onCheckedChange: () => toggleArr("thyroid", o.value),
|
|
9582
|
+
disabled
|
|
9583
|
+
}
|
|
9584
|
+
),
|
|
9585
|
+
o.label
|
|
9586
|
+
] }, o.value)) })
|
|
9587
|
+
] }) : null,
|
|
9588
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
|
|
9589
|
+
/* @__PURE__ */ jsxRuntime.jsx(Label, { className: "text-xs font-medium text-slate-700", children: "Systemic surgical screening" }),
|
|
9590
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9591
|
+
Textarea,
|
|
9592
|
+
{
|
|
9593
|
+
className: "min-h-[72px] rounded-md border border-input bg-white text-sm",
|
|
9594
|
+
placeholder: "Fever, weight loss, appetite loss, fatigue, malignancy red flags\u2026",
|
|
9595
|
+
value: safe.systemic,
|
|
9596
|
+
onChange: (e) => update({ ...safe, systemic: e.target.value }),
|
|
9597
|
+
disabled
|
|
9598
|
+
}
|
|
9599
|
+
)
|
|
9600
|
+
] })
|
|
9601
|
+
] }),
|
|
9602
|
+
showError ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "px-3 pb-2 text-xs text-red-500", children: error }) : null
|
|
9603
|
+
] });
|
|
9604
|
+
};
|
|
9605
|
+
var GS_CLINICAL_EXAMINATION_FIELD = "clinical_examination";
|
|
9606
|
+
var GENERAL = [
|
|
9607
|
+
{ value: "pallor", label: "Pallor" },
|
|
9608
|
+
{ value: "icterus", label: "Icterus" },
|
|
9609
|
+
{ value: "cyanosis", label: "Cyanosis" },
|
|
9610
|
+
{ value: "clubbing", label: "Clubbing" },
|
|
9611
|
+
{ value: "lymphadenopathy", label: "Lymphadenopathy" },
|
|
9612
|
+
{ value: "oedema", label: "Oedema" }
|
|
9613
|
+
];
|
|
9614
|
+
var REGIONS = [
|
|
9615
|
+
{ key: "abdomen", label: "Abdomen" },
|
|
9616
|
+
{ key: "hernia", label: "Hernia" },
|
|
9617
|
+
{ key: "breast", label: "Breast" },
|
|
9618
|
+
{ key: "thyroid", label: "Thyroid" },
|
|
9619
|
+
{ key: "anorectal", label: "Anorectal" },
|
|
9620
|
+
{ key: "limb", label: "Limb / varicose" }
|
|
9621
|
+
];
|
|
9622
|
+
var ABD_INSP = [
|
|
9623
|
+
{ value: "distension", label: "Distension" },
|
|
9624
|
+
{ value: "scars", label: "Scars" },
|
|
9625
|
+
{ value: "visible_peristalsis", label: "Visible peristalsis" }
|
|
9626
|
+
];
|
|
9627
|
+
var ABD_PALP = [
|
|
9628
|
+
{ value: "tenderness", label: "Tenderness" },
|
|
9629
|
+
{ value: "guarding", label: "Guarding" },
|
|
9630
|
+
{ value: "rigidity", label: "Rigidity" },
|
|
9631
|
+
{ value: "mass", label: "Palpable mass" }
|
|
9632
|
+
];
|
|
9633
|
+
var ABD_PERC = [
|
|
9634
|
+
{ value: "tympany", label: "Tympany" },
|
|
9635
|
+
{ value: "shifting_dullness", label: "Shifting dullness" }
|
|
9636
|
+
];
|
|
9637
|
+
function SubGroup({ title, children }) {
|
|
9638
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
9639
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[11px] font-semibold uppercase tracking-wide text-muted-foreground", children: title }),
|
|
9640
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children })
|
|
9641
|
+
] });
|
|
9642
|
+
}
|
|
9643
|
+
function RegionCard({ title, children }) {
|
|
9644
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "overflow-hidden rounded-md border border-[#D0D0D0] bg-white", children: [
|
|
9645
|
+
/* @__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 }),
|
|
9646
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-3", children })
|
|
9647
|
+
] });
|
|
9648
|
+
}
|
|
9649
|
+
var GsExaminationWidget = ({ fieldId }) => {
|
|
9650
|
+
const { fieldDef, value, setValue, setTouched, error, touched, disabled } = useField(fieldId);
|
|
9651
|
+
const clinicalField = useField(GS_CLINICAL_EXAMINATION_FIELD);
|
|
9652
|
+
const { state } = useForm();
|
|
9653
|
+
const showError = !!error && (touched || state.submitAttempted);
|
|
9654
|
+
const safe = React15.useMemo(() => normalizeGeneralSurgeryExamination(value), [value]);
|
|
9655
|
+
const update = (next) => {
|
|
9656
|
+
setValue(next);
|
|
9657
|
+
setTouched();
|
|
9658
|
+
};
|
|
9659
|
+
const toggleIn = (arr, val) => arr.includes(val) ? arr.filter((x) => x !== val) : [...arr, val];
|
|
9660
|
+
const toggleGeneral = (val) => {
|
|
9661
|
+
update({ ...safe, general: toggleIn(safe.general, val) });
|
|
9662
|
+
};
|
|
9663
|
+
const toggleRegion = (key) => {
|
|
9664
|
+
update({ ...safe, regions: toggleIn(safe.regions, key) });
|
|
9665
|
+
};
|
|
9666
|
+
const toggleAbd = (key, val) => {
|
|
9667
|
+
update({
|
|
9668
|
+
...safe,
|
|
9669
|
+
abdomen: { ...safe.abdomen, [key]: toggleIn(safe.abdomen[key], val) }
|
|
9670
|
+
});
|
|
9671
|
+
};
|
|
9672
|
+
if (!fieldDef) return null;
|
|
9673
|
+
const has = (r) => safe.regions.includes(r);
|
|
9674
|
+
const theme = getThemeConfig("textarea", fieldDef.theme);
|
|
9675
|
+
const wrapperClass = theme?.wrapperClassName ?? "rounded-md overflow-hidden flex flex-col border border-[#D0D0D0]";
|
|
9676
|
+
const labelClass = theme?.labelClassName;
|
|
9677
|
+
const labelContent = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
9678
|
+
fieldDef.label,
|
|
9679
|
+
fieldDef.required ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-1 text-red-500", children: "*" }) : null
|
|
9680
|
+
] });
|
|
9681
|
+
const labelEl = theme ? /* @__PURE__ */ jsxRuntime.jsx(Label, { className: labelClass, children: labelContent }) : /* @__PURE__ */ jsxRuntime.jsx(Label, { className: "text-sm font-medium", children: labelContent });
|
|
9682
|
+
const bodyClass = cn(
|
|
9683
|
+
"-mt-1 flex min-w-0 flex-col gap-3 border-t border-[#D0D0D0] bg-white px-3 py-3",
|
|
9684
|
+
disabled && "pointer-events-none opacity-60"
|
|
9685
|
+
);
|
|
9686
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("w-full min-w-0", wrapperClass), children: [
|
|
9687
|
+
labelEl,
|
|
9688
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: bodyClass, children: [
|
|
9689
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "overflow-hidden rounded-md border border-[#D0D0D0] bg-white", children: [
|
|
9690
|
+
/* @__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" }),
|
|
9691
|
+
/* @__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: [
|
|
9692
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9693
|
+
Checkbox,
|
|
9694
|
+
{
|
|
9695
|
+
checked: safe.general.includes(g.value),
|
|
9696
|
+
onCheckedChange: () => toggleGeneral(g.value),
|
|
9697
|
+
disabled
|
|
9698
|
+
}
|
|
9699
|
+
),
|
|
9700
|
+
g.label
|
|
9701
|
+
] }, g.value)) }) })
|
|
9702
|
+
] }),
|
|
9703
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
9704
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-2 text-xs font-semibold text-slate-700", children: "Regional examination \u2014 select region(s)" }),
|
|
9705
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-2", children: REGIONS.map((r) => {
|
|
9706
|
+
const on = safe.regions.includes(r.key);
|
|
9707
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
9708
|
+
Button,
|
|
9709
|
+
{
|
|
9710
|
+
type: "button",
|
|
9711
|
+
size: "sm",
|
|
9712
|
+
variant: on ? "default" : "outline",
|
|
9713
|
+
className: "h-7 rounded-full px-3 text-xs",
|
|
9714
|
+
onClick: () => toggleRegion(r.key),
|
|
9715
|
+
disabled,
|
|
9716
|
+
children: r.label
|
|
9717
|
+
},
|
|
9718
|
+
r.key
|
|
9719
|
+
);
|
|
9720
|
+
}) })
|
|
9721
|
+
] }),
|
|
9722
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
|
|
9723
|
+
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: [
|
|
9724
|
+
/* @__PURE__ */ jsxRuntime.jsx(SubGroup, { title: "Inspection", children: ABD_INSP.map((o) => /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2 text-xs", children: [
|
|
9725
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9726
|
+
Checkbox,
|
|
9727
|
+
{
|
|
9728
|
+
checked: safe.abdomen.inspection.includes(o.value),
|
|
9729
|
+
onCheckedChange: () => toggleAbd("inspection", o.value),
|
|
9730
|
+
disabled
|
|
9731
|
+
}
|
|
9732
|
+
),
|
|
9733
|
+
o.label
|
|
9734
|
+
] }, o.value)) }),
|
|
9735
|
+
/* @__PURE__ */ jsxRuntime.jsxs(SubGroup, { title: "Palpation", children: [
|
|
9736
|
+
ABD_PALP.map((o) => /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2 text-xs", children: [
|
|
9737
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9738
|
+
Checkbox,
|
|
9739
|
+
{
|
|
9740
|
+
checked: safe.abdomen.palpation.includes(o.value),
|
|
9741
|
+
onCheckedChange: () => toggleAbd("palpation", o.value),
|
|
9742
|
+
disabled
|
|
9743
|
+
}
|
|
9744
|
+
),
|
|
9745
|
+
o.label
|
|
9746
|
+
] }, o.value)),
|
|
9747
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "mt-2 block text-xs", children: [
|
|
9748
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "mb-1 block font-medium", children: "Mass size / mobility" }),
|
|
9749
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9750
|
+
Input,
|
|
9751
|
+
{
|
|
9752
|
+
className: "h-8 text-xs",
|
|
9753
|
+
value: safe.abdomen.massNotes,
|
|
9754
|
+
onChange: (e) => update({ ...safe, abdomen: { ...safe.abdomen, massNotes: e.target.value } }),
|
|
9755
|
+
disabled
|
|
9756
|
+
}
|
|
9757
|
+
)
|
|
9758
|
+
] })
|
|
9759
|
+
] }),
|
|
9760
|
+
/* @__PURE__ */ jsxRuntime.jsx(SubGroup, { title: "Percussion", children: ABD_PERC.map((o) => /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2 text-xs", children: [
|
|
9761
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9762
|
+
Checkbox,
|
|
9763
|
+
{
|
|
9764
|
+
checked: safe.abdomen.percussion.includes(o.value),
|
|
9765
|
+
onCheckedChange: () => toggleAbd("percussion", o.value),
|
|
9766
|
+
disabled
|
|
9767
|
+
}
|
|
9768
|
+
),
|
|
9769
|
+
o.label
|
|
9770
|
+
] }, o.value)) }),
|
|
9771
|
+
/* @__PURE__ */ jsxRuntime.jsxs(SubGroup, { title: "Auscultation", children: [
|
|
9772
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "mb-1 block text-xs font-medium", children: "Bowel sounds" }),
|
|
9773
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
9774
|
+
Select,
|
|
9775
|
+
{
|
|
9776
|
+
value: safe.abdomen.bowelSounds,
|
|
9777
|
+
onValueChange: (val) => update({
|
|
9778
|
+
...safe,
|
|
9779
|
+
abdomen: {
|
|
9780
|
+
...safe.abdomen,
|
|
9781
|
+
bowelSounds: val
|
|
9782
|
+
}
|
|
9783
|
+
}),
|
|
9784
|
+
disabled,
|
|
9785
|
+
children: [
|
|
9786
|
+
/* @__PURE__ */ jsxRuntime.jsx(SelectTrigger, { className: "h-8 text-xs", children: /* @__PURE__ */ jsxRuntime.jsx(SelectValue, { placeholder: "Select\u2026" }) }),
|
|
9787
|
+
/* @__PURE__ */ jsxRuntime.jsxs(SelectContent, { children: [
|
|
9788
|
+
/* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: "none", children: "\u2014" }),
|
|
9789
|
+
/* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: "normal", children: "Normal" }),
|
|
9790
|
+
/* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: "up", children: "\u2191" }),
|
|
9791
|
+
/* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: "down", children: "\u2193" }),
|
|
9792
|
+
/* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: "absent", children: "Absent" })
|
|
9793
|
+
] })
|
|
9794
|
+
]
|
|
9795
|
+
}
|
|
9796
|
+
)
|
|
9797
|
+
] })
|
|
9798
|
+
] }) }) : null,
|
|
9799
|
+
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: [
|
|
9800
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "block", children: [
|
|
9801
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "mb-1 block font-medium", children: "Site" }),
|
|
9802
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9803
|
+
Input,
|
|
9804
|
+
{
|
|
9805
|
+
className: "h-8 text-xs",
|
|
9806
|
+
value: safe.hernia.site,
|
|
9807
|
+
onChange: (e) => update({ ...safe, hernia: { ...safe.hernia, site: e.target.value } }),
|
|
9808
|
+
disabled
|
|
9809
|
+
}
|
|
9810
|
+
)
|
|
9811
|
+
] }),
|
|
9812
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
|
|
9813
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9814
|
+
Checkbox,
|
|
9815
|
+
{
|
|
9816
|
+
checked: safe.hernia.reducible,
|
|
9817
|
+
onCheckedChange: (c) => update({ ...safe, hernia: { ...safe.hernia, reducible: c === true } }),
|
|
9818
|
+
disabled
|
|
9819
|
+
}
|
|
9820
|
+
),
|
|
9821
|
+
"Reducible"
|
|
9822
|
+
] }),
|
|
9823
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
|
|
9824
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9825
|
+
Checkbox,
|
|
9826
|
+
{
|
|
9827
|
+
checked: safe.hernia.coughImpulse,
|
|
9828
|
+
onCheckedChange: (c) => update({ ...safe, hernia: { ...safe.hernia, coughImpulse: c === true } }),
|
|
9829
|
+
disabled
|
|
9830
|
+
}
|
|
9831
|
+
),
|
|
9832
|
+
"Cough impulse"
|
|
9833
|
+
] }),
|
|
9834
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
|
|
9835
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9836
|
+
Checkbox,
|
|
9837
|
+
{
|
|
9838
|
+
checked: safe.hernia.tenderness,
|
|
9839
|
+
onCheckedChange: (c) => update({ ...safe, hernia: { ...safe.hernia, tenderness: c === true } }),
|
|
9840
|
+
disabled
|
|
9841
|
+
}
|
|
9842
|
+
),
|
|
9843
|
+
"Tenderness"
|
|
9844
|
+
] })
|
|
9845
|
+
] }) }) : null,
|
|
9846
|
+
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: [
|
|
9847
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "block", children: [
|
|
9848
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "mb-1 block font-medium", children: "Lump size (cm)" }),
|
|
9849
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9850
|
+
Input,
|
|
9851
|
+
{
|
|
9852
|
+
className: "h-8 text-xs",
|
|
9853
|
+
value: safe.breast.lumpSizeCm,
|
|
9854
|
+
onChange: (e) => update({ ...safe, breast: { ...safe.breast, lumpSizeCm: e.target.value } }),
|
|
9855
|
+
disabled
|
|
9856
|
+
}
|
|
9857
|
+
)
|
|
9858
|
+
] }),
|
|
9859
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
|
|
9860
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9861
|
+
Checkbox,
|
|
9862
|
+
{
|
|
9863
|
+
checked: safe.breast.mobile,
|
|
9864
|
+
onCheckedChange: (c) => update({ ...safe, breast: { ...safe.breast, mobile: c === true } }),
|
|
9865
|
+
disabled
|
|
9866
|
+
}
|
|
9867
|
+
),
|
|
9868
|
+
"Mobile"
|
|
9869
|
+
] }),
|
|
9870
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
|
|
9871
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9872
|
+
Checkbox,
|
|
9873
|
+
{
|
|
9874
|
+
checked: safe.breast.skinInvolvement,
|
|
9875
|
+
onCheckedChange: (c) => update({ ...safe, breast: { ...safe.breast, skinInvolvement: c === true } }),
|
|
9876
|
+
disabled
|
|
9877
|
+
}
|
|
9878
|
+
),
|
|
9879
|
+
"Skin involvement"
|
|
9880
|
+
] }),
|
|
9881
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
|
|
9882
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9883
|
+
Checkbox,
|
|
9884
|
+
{
|
|
9885
|
+
checked: safe.breast.axillaryNodes,
|
|
9886
|
+
onCheckedChange: (c) => update({ ...safe, breast: { ...safe.breast, axillaryNodes: c === true } }),
|
|
9887
|
+
disabled
|
|
9888
|
+
}
|
|
9889
|
+
),
|
|
9890
|
+
"Axillary nodes"
|
|
9891
|
+
] })
|
|
9892
|
+
] }) }) : null,
|
|
9893
|
+
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: [
|
|
9894
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "block", children: [
|
|
9895
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "mb-1 block font-medium", children: "Size" }),
|
|
9896
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9897
|
+
Input,
|
|
9898
|
+
{
|
|
9899
|
+
className: "h-8 text-xs",
|
|
9900
|
+
value: safe.thyroid.size,
|
|
9901
|
+
onChange: (e) => update({ ...safe, thyroid: { ...safe.thyroid, size: e.target.value } }),
|
|
9902
|
+
disabled
|
|
9903
|
+
}
|
|
9904
|
+
)
|
|
9905
|
+
] }),
|
|
9906
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
|
|
9907
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9908
|
+
Checkbox,
|
|
9909
|
+
{
|
|
9910
|
+
checked: safe.thyroid.mobileDeglutition,
|
|
9911
|
+
onCheckedChange: (c) => update({ ...safe, thyroid: { ...safe.thyroid, mobileDeglutition: c === true } }),
|
|
9912
|
+
disabled
|
|
9913
|
+
}
|
|
9914
|
+
),
|
|
9915
|
+
"Mobile with deglutition"
|
|
9916
|
+
] }),
|
|
9917
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
|
|
9918
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9919
|
+
Checkbox,
|
|
9920
|
+
{
|
|
9921
|
+
checked: safe.thyroid.nodules,
|
|
9922
|
+
onCheckedChange: (c) => update({ ...safe, thyroid: { ...safe.thyroid, nodules: c === true } }),
|
|
9923
|
+
disabled
|
|
9924
|
+
}
|
|
9925
|
+
),
|
|
9926
|
+
"Nodules"
|
|
9927
|
+
] }),
|
|
9928
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
|
|
9929
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9930
|
+
Checkbox,
|
|
9931
|
+
{
|
|
9932
|
+
checked: safe.thyroid.cervicalNodes,
|
|
9933
|
+
onCheckedChange: (c) => update({ ...safe, thyroid: { ...safe.thyroid, cervicalNodes: c === true } }),
|
|
9934
|
+
disabled
|
|
9935
|
+
}
|
|
9936
|
+
),
|
|
9937
|
+
"Cervical lymph nodes"
|
|
9938
|
+
] })
|
|
9939
|
+
] }) }) : null,
|
|
9940
|
+
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: [
|
|
9941
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "block md:col-span-3", children: [
|
|
9942
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "mb-1 block font-medium", children: "Inspection findings" }),
|
|
9943
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9944
|
+
Input,
|
|
9945
|
+
{
|
|
9946
|
+
className: "h-8 text-xs",
|
|
9947
|
+
value: safe.anorectal.inspection,
|
|
9948
|
+
onChange: (e) => update({ ...safe, anorectal: { ...safe.anorectal, inspection: e.target.value } }),
|
|
9949
|
+
disabled
|
|
9950
|
+
}
|
|
9951
|
+
)
|
|
9952
|
+
] }),
|
|
9953
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
|
|
9954
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9955
|
+
Checkbox,
|
|
9956
|
+
{
|
|
9957
|
+
checked: safe.anorectal.dreDone,
|
|
9958
|
+
onCheckedChange: (c) => update({ ...safe, anorectal: { ...safe.anorectal, dreDone: c === true } }),
|
|
9959
|
+
disabled
|
|
9960
|
+
}
|
|
9961
|
+
),
|
|
9962
|
+
"DRE done"
|
|
9963
|
+
] }),
|
|
9964
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
|
|
9965
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9966
|
+
Checkbox,
|
|
9967
|
+
{
|
|
9968
|
+
checked: safe.anorectal.proctoscopyDone,
|
|
9969
|
+
onCheckedChange: (c) => update({ ...safe, anorectal: { ...safe.anorectal, proctoscopyDone: c === true } }),
|
|
9970
|
+
disabled
|
|
9971
|
+
}
|
|
9972
|
+
),
|
|
9973
|
+
"Proctoscopy done"
|
|
9974
|
+
] }),
|
|
9975
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "md:col-span-3", children: [
|
|
9976
|
+
/* @__PURE__ */ jsxRuntime.jsx(Label, { className: "text-xs font-semibold", children: "DRE / proctoscopy notes" }),
|
|
9977
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9978
|
+
Textarea,
|
|
9979
|
+
{
|
|
9980
|
+
className: "mt-1 min-h-[64px] text-sm",
|
|
9981
|
+
placeholder: "Sphincter tone, masses, prostate, bleeding\u2026",
|
|
9982
|
+
value: safe.anorectal.notes,
|
|
9983
|
+
onChange: (e) => update({ ...safe, anorectal: { ...safe.anorectal, notes: e.target.value } }),
|
|
9984
|
+
disabled
|
|
9985
|
+
}
|
|
9986
|
+
)
|
|
9987
|
+
] })
|
|
9988
|
+
] }) }) : null,
|
|
9989
|
+
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: [
|
|
9990
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
|
|
9991
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9992
|
+
Checkbox,
|
|
9993
|
+
{
|
|
9994
|
+
checked: safe.limb.dilatedVeins,
|
|
9995
|
+
onCheckedChange: (c) => update({ ...safe, limb: { ...safe.limb, dilatedVeins: c === true } }),
|
|
9996
|
+
disabled
|
|
9997
|
+
}
|
|
9998
|
+
),
|
|
9999
|
+
"Dilated veins"
|
|
10000
|
+
] }),
|
|
10001
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
|
|
10002
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
10003
|
+
Checkbox,
|
|
10004
|
+
{
|
|
10005
|
+
checked: safe.limb.ulcer,
|
|
10006
|
+
onCheckedChange: (c) => update({ ...safe, limb: { ...safe.limb, ulcer: c === true } }),
|
|
10007
|
+
disabled
|
|
10008
|
+
}
|
|
10009
|
+
),
|
|
10010
|
+
"Ulcer"
|
|
10011
|
+
] }),
|
|
10012
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
|
|
10013
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
10014
|
+
Checkbox,
|
|
10015
|
+
{
|
|
10016
|
+
checked: safe.limb.oedema,
|
|
10017
|
+
onCheckedChange: (c) => update({ ...safe, limb: { ...safe.limb, oedema: c === true } }),
|
|
10018
|
+
disabled
|
|
10019
|
+
}
|
|
10020
|
+
),
|
|
10021
|
+
"Oedema"
|
|
10022
|
+
] })
|
|
10023
|
+
] }) }) : null
|
|
10024
|
+
] }),
|
|
10025
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
|
|
10026
|
+
/* @__PURE__ */ jsxRuntime.jsx(Label, { className: "text-xs font-semibold text-slate-700", children: clinicalField.fieldDef?.label ?? "Clinical examination" }),
|
|
10027
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
10028
|
+
Textarea,
|
|
10029
|
+
{
|
|
10030
|
+
className: "min-h-[88px] rounded-md border border-input bg-white text-sm",
|
|
10031
|
+
value: typeof clinicalField.value === "string" ? clinicalField.value : clinicalField.value == null ? "" : String(clinicalField.value),
|
|
10032
|
+
onChange: (e) => {
|
|
10033
|
+
clinicalField.setValue(e.target.value);
|
|
10034
|
+
clinicalField.setTouched();
|
|
10035
|
+
},
|
|
10036
|
+
disabled: disabled || clinicalField.disabled
|
|
10037
|
+
}
|
|
10038
|
+
)
|
|
10039
|
+
] })
|
|
10040
|
+
] }),
|
|
10041
|
+
showError ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "px-3 pb-2 text-xs text-red-500", children: error }) : null
|
|
10042
|
+
] });
|
|
10043
|
+
};
|
|
10044
|
+
var CHIEF_CHIPS_FIELD2 = "chief_complaints_chips";
|
|
10045
|
+
var GS_EXAMINATION_FIELD = "gs_examination";
|
|
10046
|
+
function chipList2(state) {
|
|
10047
|
+
const raw = state.values[CHIEF_CHIPS_FIELD2];
|
|
10048
|
+
return Array.isArray(raw) ? raw.filter((x) => typeof x === "string") : [];
|
|
10049
|
+
}
|
|
10050
|
+
function regionList(state) {
|
|
10051
|
+
const raw = state.values[GS_EXAMINATION_FIELD];
|
|
10052
|
+
const ex = normalizeGeneralSurgeryExamination(raw);
|
|
10053
|
+
return ex.regions;
|
|
10054
|
+
}
|
|
10055
|
+
var GsGradingWidget = ({ fieldId }) => {
|
|
10056
|
+
const { fieldDef, value, setValue, setTouched, error, touched, disabled } = useField(fieldId);
|
|
10057
|
+
const { state } = useForm();
|
|
10058
|
+
const showError = !!error && (touched || state.submitAttempted);
|
|
10059
|
+
const safe = React15.useMemo(() => normalizeGeneralSurgeryGrading(value), [value]);
|
|
10060
|
+
const chips = React15.useMemo(() => chipList2(state), [state]);
|
|
10061
|
+
const regions = React15.useMemo(() => regionList(state), [state]);
|
|
10062
|
+
const visibleRows = React15.useMemo(() => {
|
|
10063
|
+
return ALL_GS_CONDITIONS.filter(
|
|
10064
|
+
(c) => gsGradingRowVisible(c, chips, regions, safe[c] ?? 0)
|
|
10065
|
+
);
|
|
10066
|
+
}, [chips, regions, safe]);
|
|
10067
|
+
const update = (next) => {
|
|
10068
|
+
setValue(next);
|
|
10069
|
+
setTouched();
|
|
10070
|
+
};
|
|
10071
|
+
const setGrade = (cond, gradeStr) => {
|
|
10072
|
+
const n = Math.min(5, Math.max(0, Math.round(Number(gradeStr)) || 0));
|
|
10073
|
+
update({ ...safe, [cond]: n });
|
|
10074
|
+
};
|
|
10075
|
+
if (!fieldDef) return null;
|
|
10076
|
+
const theme = getThemeConfig("textarea", fieldDef.theme);
|
|
10077
|
+
const wrapperClass = theme?.wrapperClassName ?? "rounded-md overflow-hidden flex flex-col border border-[#D0D0D0]";
|
|
10078
|
+
const labelClass = theme?.labelClassName;
|
|
10079
|
+
const labelContent = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
10080
|
+
fieldDef.label,
|
|
10081
|
+
fieldDef.required ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-1 text-red-500", children: "*" }) : null
|
|
10082
|
+
] });
|
|
10083
|
+
const labelEl = theme ? /* @__PURE__ */ jsxRuntime.jsx(Label, { className: labelClass, children: labelContent }) : /* @__PURE__ */ jsxRuntime.jsx(Label, { className: "text-sm font-medium", children: labelContent });
|
|
10084
|
+
const bodyClass = cn(
|
|
10085
|
+
"-mt-1 flex min-w-0 flex-col gap-3 border-t border-[#D0D0D0] bg-white px-3 py-3",
|
|
10086
|
+
disabled && "pointer-events-none opacity-60"
|
|
10087
|
+
);
|
|
10088
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("w-full min-w-0", wrapperClass), children: [
|
|
10089
|
+
labelEl,
|
|
10090
|
+
/* @__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: [
|
|
10091
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "border-b border-[#D0D0D0] bg-[#FEE8EC]/50", children: [
|
|
10092
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-3 py-2 text-left font-semibold text-slate-700", children: "Condition" }),
|
|
10093
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "w-24 px-2 py-2 font-semibold text-slate-700", children: "Grade" }),
|
|
10094
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-3 py-2 text-left font-semibold text-slate-700", children: "Description" })
|
|
10095
|
+
] }) }),
|
|
10096
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "bg-white", children: visibleRows.map((c) => {
|
|
10097
|
+
const g = safe[c] ?? 0;
|
|
10098
|
+
const desc = GS_GRADE_DESCRIPTIONS[c][g] ?? "\u2014";
|
|
10099
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "border-b border-[#D0D0D0]/80 last:border-0", children: [
|
|
10100
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-3 py-2 font-medium", children: GS_CONDITION_LABELS[c] }),
|
|
10101
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-2 py-1.5 align-middle", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
10102
|
+
Select,
|
|
10103
|
+
{
|
|
10104
|
+
value: String(g),
|
|
10105
|
+
onValueChange: (v) => setGrade(c, v),
|
|
10106
|
+
disabled,
|
|
10107
|
+
children: [
|
|
10108
|
+
/* @__PURE__ */ jsxRuntime.jsx(SelectTrigger, { className: "h-8 text-xs", children: /* @__PURE__ */ jsxRuntime.jsx(SelectValue, {}) }),
|
|
10109
|
+
/* @__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)) })
|
|
10110
|
+
]
|
|
10111
|
+
}
|
|
10112
|
+
) }),
|
|
10113
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-3 py-2 text-muted-foreground", children: desc })
|
|
10114
|
+
] }, c);
|
|
10115
|
+
}) })
|
|
10116
|
+
] }) }) }),
|
|
10117
|
+
showError ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "px-3 pb-2 text-xs text-red-500", children: error }) : null
|
|
10118
|
+
] });
|
|
10119
|
+
};
|
|
10120
|
+
function isFlagSelected(selected, optValue) {
|
|
10121
|
+
return selected.some((v) => v === optValue || String(v) === String(optValue));
|
|
10122
|
+
}
|
|
10123
|
+
var PainScaleFlagsWidget = ({ fieldId }) => {
|
|
10124
|
+
const { fieldDef, value, setValue, setTouched, error, touched, disabled } = useField(fieldId);
|
|
10125
|
+
const { state } = useForm();
|
|
10126
|
+
const showError = !!error && (touched || state.submitAttempted);
|
|
10127
|
+
if (!fieldDef || fieldDef.type !== "pain_scale_flags") return null;
|
|
10128
|
+
const def = fieldDef;
|
|
10129
|
+
const min = def.min ?? 0;
|
|
10130
|
+
const max = def.max ?? 10;
|
|
10131
|
+
const step = def.step ?? 1;
|
|
10132
|
+
const flagOptions = def.options ?? [];
|
|
10133
|
+
const safe = React15.useMemo(
|
|
10134
|
+
() => normalizePainScaleFlags(value, { min, max }),
|
|
10135
|
+
[value, min, max]
|
|
10136
|
+
);
|
|
10137
|
+
const theme = getThemeConfig("textarea", def.theme);
|
|
10138
|
+
const wrapperClass = theme?.wrapperClassName ?? "space-y-2";
|
|
10139
|
+
const labelClass = theme?.labelClassName;
|
|
10140
|
+
const update = (next) => {
|
|
10141
|
+
setValue(normalizePainScaleFlags(next, { min, max }));
|
|
10142
|
+
setTouched();
|
|
10143
|
+
};
|
|
10144
|
+
const toggleFlag = (optValue) => {
|
|
10145
|
+
const sel = safe.flags;
|
|
10146
|
+
const isSelected = isFlagSelected(sel, optValue);
|
|
10147
|
+
const nextFlags = isSelected ? sel.filter((v) => v !== optValue && String(v) !== String(optValue)) : [...sel, String(optValue)];
|
|
10148
|
+
update({ pain: safe.pain, flags: nextFlags });
|
|
10149
|
+
};
|
|
10150
|
+
const labelContent = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
10151
|
+
def.label,
|
|
10152
|
+
" ",
|
|
10153
|
+
def.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-red-500", children: "*" })
|
|
10154
|
+
] });
|
|
10155
|
+
const labelEl = theme ? /* @__PURE__ */ jsxRuntime.jsx(Label, { className: labelClass, children: labelContent }) : /* @__PURE__ */ jsxRuntime.jsx(Label, { children: labelContent });
|
|
10156
|
+
const bodyClass = cn(
|
|
10157
|
+
"-mt-1 flex min-w-0 flex-col border-t border-[#D0D0D0] bg-white px-3 py-3",
|
|
10158
|
+
disabled && "pointer-events-none opacity-60"
|
|
10159
|
+
);
|
|
10160
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(wrapperClass, "h-full min-h-0 flex flex-col"), children: [
|
|
10161
|
+
labelEl,
|
|
10162
|
+
def.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: def.description }),
|
|
10163
|
+
/* @__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: [
|
|
10164
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
10165
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Label, { className: "text-sm font-medium text-slate-700", children: [
|
|
10166
|
+
"Pain score (VAS)",
|
|
10167
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ml-2 font-normal tabular-nums text-muted-foreground", children: [
|
|
10168
|
+
safe.pain,
|
|
10169
|
+
"/",
|
|
10170
|
+
max
|
|
10171
|
+
] })
|
|
10172
|
+
] }),
|
|
10173
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
10174
|
+
Slider,
|
|
10175
|
+
{
|
|
10176
|
+
className: cn("py-1", showError && "rounded opacity-90 ring-1 ring-red-500"),
|
|
10177
|
+
disabled,
|
|
10178
|
+
min,
|
|
10179
|
+
max,
|
|
10180
|
+
step,
|
|
10181
|
+
value: [safe.pain],
|
|
10182
|
+
onValueChange: (v) => {
|
|
10183
|
+
const n = v[0] ?? min;
|
|
10184
|
+
update({ pain: n, flags: safe.flags });
|
|
10185
|
+
}
|
|
10186
|
+
}
|
|
10187
|
+
)
|
|
10188
|
+
] }),
|
|
10189
|
+
flagOptions.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 space-y-1.5", children: [
|
|
10190
|
+
/* @__PURE__ */ jsxRuntime.jsx(Label, { className: "text-sm font-medium text-slate-700", children: "Triage flags" }),
|
|
10191
|
+
/* @__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: [
|
|
10192
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
10193
|
+
Checkbox,
|
|
10194
|
+
{
|
|
10195
|
+
id: `${fieldId}-flag-${String(opt.value)}`,
|
|
10196
|
+
checked: isFlagSelected(safe.flags, opt.value),
|
|
10197
|
+
onCheckedChange: () => toggleFlag(opt.value),
|
|
10198
|
+
disabled
|
|
10199
|
+
}
|
|
10200
|
+
),
|
|
10201
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
10202
|
+
Label,
|
|
10203
|
+
{
|
|
10204
|
+
htmlFor: `${fieldId}-flag-${String(opt.value)}`,
|
|
10205
|
+
className: "cursor-pointer text-sm font-normal leading-none",
|
|
10206
|
+
children: opt.label
|
|
10207
|
+
}
|
|
10208
|
+
)
|
|
10209
|
+
] }, String(opt.value))) })
|
|
10210
|
+
] }) : null
|
|
10211
|
+
] }) }),
|
|
10212
|
+
showError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-red-500", children: error })
|
|
10213
|
+
] });
|
|
10214
|
+
};
|
|
10215
|
+
var FieldRenderer = ({ fieldId }) => {
|
|
10216
|
+
const { fieldDef, visible } = useField(fieldId);
|
|
10217
|
+
if (!visible || !fieldDef) {
|
|
10218
|
+
return null;
|
|
10219
|
+
}
|
|
10220
|
+
return renderWidget(fieldId, fieldDef);
|
|
10221
|
+
};
|
|
10222
|
+
function renderWidget(fieldId, fieldDef) {
|
|
10223
|
+
switch (fieldDef.type) {
|
|
10224
|
+
case "text":
|
|
10225
|
+
case "number":
|
|
10226
|
+
return /* @__PURE__ */ jsxRuntime.jsx(TextWidget, { fieldId });
|
|
10227
|
+
case "slider":
|
|
10228
|
+
return /* @__PURE__ */ jsxRuntime.jsx(SliderWidget, { fieldId });
|
|
10229
|
+
case "textarea":
|
|
10230
|
+
if (fieldMetaRequestsMarMedicationOrdersButton(fieldDef.meta)) {
|
|
10231
|
+
return /* @__PURE__ */ jsxRuntime.jsx(MarMedicationOrdersWidget, { fieldId });
|
|
10232
|
+
}
|
|
10233
|
+
return /* @__PURE__ */ jsxRuntime.jsx(TextWidget, { fieldId });
|
|
10234
|
+
case "richtext":
|
|
10235
|
+
return /* @__PURE__ */ jsxRuntime.jsx(RichTextWidget, { fieldId });
|
|
10236
|
+
case "date":
|
|
10237
|
+
return /* @__PURE__ */ jsxRuntime.jsx(DateWidget, { fieldId });
|
|
10238
|
+
case "datetime":
|
|
10239
|
+
return /* @__PURE__ */ jsxRuntime.jsx(DateTimeWidget, { fieldId });
|
|
10240
|
+
case "select":
|
|
10241
|
+
return /* @__PURE__ */ jsxRuntime.jsx(SelectWidget, { fieldId });
|
|
10242
|
+
case "radio":
|
|
10243
|
+
return /* @__PURE__ */ jsxRuntime.jsx(RadioWidget, { fieldId });
|
|
10244
|
+
case "checkbox":
|
|
10245
|
+
return /* @__PURE__ */ jsxRuntime.jsx(CheckboxWidget, { fieldId });
|
|
10246
|
+
case "multiselect":
|
|
10247
|
+
return /* @__PURE__ */ jsxRuntime.jsx(MultiSelectWidget, { fieldId });
|
|
10248
|
+
case "repeatable":
|
|
10249
|
+
return /* @__PURE__ */ jsxRuntime.jsx(RepeatableWidget, { fieldId });
|
|
10250
|
+
case "image_upload":
|
|
10251
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ImageUploadWidget, { fieldId });
|
|
10252
|
+
case "media_upload":
|
|
10253
|
+
return /* @__PURE__ */ jsxRuntime.jsx(MediaUploadWidget, { fieldId });
|
|
10254
|
+
case "signature":
|
|
10255
|
+
return /* @__PURE__ */ jsxRuntime.jsx(SignatureUploadWidget, { fieldId });
|
|
10256
|
+
case "editable_table":
|
|
10257
|
+
return /* @__PURE__ */ jsxRuntime.jsx(EditableTableWidget, { fieldId });
|
|
10258
|
+
case "medications":
|
|
10259
|
+
return /* @__PURE__ */ jsxRuntime.jsx(AddMedicationWidget, { fieldId });
|
|
10260
|
+
case "discharge_medication_orders":
|
|
10261
|
+
return /* @__PURE__ */ jsxRuntime.jsx(DischargeMedicationOrdersWidget, { fieldId });
|
|
10262
|
+
case "investigations":
|
|
10263
|
+
return /* @__PURE__ */ jsxRuntime.jsx(AddInvestigationWidget, { fieldId });
|
|
10264
|
+
case "procedures":
|
|
10265
|
+
return /* @__PURE__ */ jsxRuntime.jsx(AddProcedureWidget, { fieldId });
|
|
10266
|
+
case "differential_diagnosis":
|
|
10267
|
+
return /* @__PURE__ */ jsxRuntime.jsx(DifferentialDiagnosisWidget, { fieldId });
|
|
10268
|
+
case "vitals":
|
|
10269
|
+
return /* @__PURE__ */ jsxRuntime.jsx(VitalsWidget, { fieldId });
|
|
10270
|
+
case "hidden_vitals":
|
|
10271
|
+
return /* @__PURE__ */ jsxRuntime.jsx(HiddenVitalsWidget, { fieldId });
|
|
10272
|
+
case "referral":
|
|
10273
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ReferralWidget, { fieldId });
|
|
10274
|
+
case "followup":
|
|
10275
|
+
return /* @__PURE__ */ jsxRuntime.jsx(FollowupWidget, { fieldId });
|
|
10276
|
+
case "smart_textarea":
|
|
10277
|
+
return /* @__PURE__ */ jsxRuntime.jsx(SmartTextareaWidget, { fieldId });
|
|
10278
|
+
case "diagnosis_textarea":
|
|
10279
|
+
return /* @__PURE__ */ jsxRuntime.jsx(DiagnosisTextareaWidget, { fieldId });
|
|
10280
|
+
case "obstetric_history":
|
|
10281
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ObstetricHistoryWidget, { fieldId });
|
|
10282
|
+
case "eye_prescription":
|
|
10283
|
+
return /* @__PURE__ */ jsxRuntime.jsx(OphthalmologyWidget, { fieldId });
|
|
10284
|
+
case "ophthal_diagnosis":
|
|
10285
|
+
return /* @__PURE__ */ jsxRuntime.jsx(OphthalDiagnosisWidget, { fieldId });
|
|
10286
|
+
case "orthopedic_exam":
|
|
10287
|
+
return /* @__PURE__ */ jsxRuntime.jsx(OrthopedicExamWidget, { fieldId });
|
|
10288
|
+
case "general_surgery_smart_history":
|
|
10289
|
+
return /* @__PURE__ */ jsxRuntime.jsx(GsSmartHistoryWidget, { fieldId });
|
|
10290
|
+
case "general_surgery_examination":
|
|
10291
|
+
return /* @__PURE__ */ jsxRuntime.jsx(GsExaminationWidget, { fieldId });
|
|
10292
|
+
case "general_surgery_grading":
|
|
10293
|
+
return /* @__PURE__ */ jsxRuntime.jsx(GsGradingWidget, { fieldId });
|
|
10294
|
+
case "pain_scale_flags":
|
|
10295
|
+
return /* @__PURE__ */ jsxRuntime.jsx(PainScaleFlagsWidget, { fieldId });
|
|
10296
|
+
case "toggle": {
|
|
10297
|
+
const { value, setValue, setTouched, disabled } = useField(fieldId);
|
|
10298
|
+
const store = useFormStore();
|
|
10299
|
+
const excludes = fieldDef.excludes ?? [];
|
|
10300
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
10301
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
10302
|
+
Switch,
|
|
10303
|
+
{
|
|
10304
|
+
checked: value === true,
|
|
10305
|
+
disabled,
|
|
10306
|
+
onCheckedChange: (checked) => {
|
|
10307
|
+
setValue(checked);
|
|
10308
|
+
setTouched();
|
|
10309
|
+
if (checked) excludes.forEach((id) => store.setValue(id, false));
|
|
10310
|
+
}
|
|
10311
|
+
}
|
|
10312
|
+
),
|
|
10313
|
+
/* @__PURE__ */ jsxRuntime.jsx(Label, { className: "text-sm font-medium leading-none cursor-pointer select-none", children: fieldDef.label })
|
|
10314
|
+
] });
|
|
10315
|
+
}
|
|
10316
|
+
case "suggestion_textarea":
|
|
10317
|
+
case "complaint_chips":
|
|
10318
|
+
return /* @__PURE__ */ jsxRuntime.jsx(SuggestionTextareaWidget, { fieldId });
|
|
10319
|
+
case "lens_assessment":
|
|
10320
|
+
return /* @__PURE__ */ jsxRuntime.jsx(LensAssessmentWidget, { fieldId });
|
|
10321
|
+
case "functional_impairment_score":
|
|
10322
|
+
return /* @__PURE__ */ jsxRuntime.jsx(FunctionalImpairmentScoreWidget, { fieldId });
|
|
10323
|
+
case "biometry_iol_workup":
|
|
10324
|
+
return /* @__PURE__ */ jsxRuntime.jsx(BiometryIolWorkupWidget, { fieldId });
|
|
10325
|
+
case "surgical_risk_flags":
|
|
10326
|
+
return /* @__PURE__ */ jsxRuntime.jsx(SurgicalRiskFlagsWidget, { fieldId });
|
|
10327
|
+
case "static_text": {
|
|
10328
|
+
const def = fieldDef;
|
|
10329
|
+
const size = def.size ?? "regular";
|
|
10330
|
+
const labelClass = size === "large" ? "text-base" : "text-sm";
|
|
10331
|
+
const descClass = size === "large" ? "text-sm" : "text-xs";
|
|
10332
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${labelClass} text-muted-foreground`, children: [
|
|
10333
|
+
def.label,
|
|
10334
|
+
def.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `mt-1 ${descClass} opacity-90`, children: def.description })
|
|
10335
|
+
] });
|
|
10336
|
+
}
|
|
10337
|
+
default:
|
|
10338
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-red-500", children: [
|
|
10339
|
+
"Unknown field type: ",
|
|
10340
|
+
fieldDef.type
|
|
10341
|
+
] });
|
|
10342
|
+
}
|
|
10343
|
+
}
|
|
10344
|
+
var Section = ({ title, children }) => {
|
|
10345
|
+
const [expanded, setExpanded] = React15.useState(true);
|
|
10346
|
+
const handleToggle = () => setExpanded((prev) => !prev);
|
|
10347
|
+
const contentClassName = cn(
|
|
10348
|
+
"overflow-hidden transition-[height] duration-200 ease-in-out",
|
|
10349
|
+
!expanded && "hidden"
|
|
10350
|
+
);
|
|
10351
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-6 border rounded-lg bg-white shadow-sm overflow-hidden", children: [
|
|
10352
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
10353
|
+
"button",
|
|
10354
|
+
{
|
|
10355
|
+
type: "button",
|
|
10356
|
+
onClick: handleToggle,
|
|
10357
|
+
className: "w-full flex items-center justify-between gap-2 p-4 text-left border-b hover:bg-gray-50/80 transition-colors",
|
|
10358
|
+
children: [
|
|
10359
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-medium", children: title }),
|
|
10360
|
+
/* @__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" }) })
|
|
10361
|
+
]
|
|
10362
|
+
}
|
|
10363
|
+
),
|
|
10364
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: contentClassName, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4 pt-4 space-y-4 border-t-0", children }) })
|
|
10365
|
+
] });
|
|
10366
|
+
};
|
|
10367
|
+
var ColumnLayout = ({
|
|
10368
|
+
columns,
|
|
10369
|
+
label,
|
|
10370
|
+
children
|
|
10371
|
+
}) => {
|
|
10372
|
+
const gridCols = Math.max(1, Math.min(columns, 12));
|
|
10373
|
+
const gridClass = `grid gap-4 w-full`;
|
|
10374
|
+
const style = {
|
|
10375
|
+
gridTemplateColumns: `repeat(${gridCols}, minmax(0, 1fr))`
|
|
10376
|
+
};
|
|
10377
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-6", children: [
|
|
10378
|
+
label != null && label !== "" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-2 text-sm font-medium text-gray-700", children: label }),
|
|
10379
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: gridClass, style, children })
|
|
10380
|
+
] });
|
|
10381
|
+
};
|
|
10382
|
+
var DynamicForm = () => {
|
|
10383
|
+
const store = useFormStore();
|
|
10384
|
+
const schema = store.getSchema();
|
|
10385
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
|
|
10386
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-4", children: /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-2xl font-bold", children: schema.title }) }),
|
|
10387
|
+
schema.layout.map((node) => {
|
|
10388
|
+
if (node.type === "section") {
|
|
10389
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Section, { title: node.title, children: node.children.map(
|
|
10390
|
+
(child, index) => typeof child === "string" ? /* @__PURE__ */ jsxRuntime.jsx(FieldRenderer, { fieldId: child }, child) : child.type === "column_layout" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
10391
|
+
ColumnLayout,
|
|
10392
|
+
{
|
|
10393
|
+
columns: child.columns,
|
|
10394
|
+
label: child.label,
|
|
10395
|
+
children: child.children.map((fieldId) => /* @__PURE__ */ jsxRuntime.jsx(FieldRenderer, { fieldId }, fieldId))
|
|
10396
|
+
},
|
|
9119
10397
|
child.id
|
|
9120
10398
|
) : /* @__PURE__ */ jsxRuntime.jsx(React15__namespace.default.Fragment, {}, child.id ?? index)
|
|
9121
10399
|
) }, node.id);
|
|
@@ -9250,14 +10528,24 @@ var SmartForm = ({
|
|
|
9250
10528
|
if (position !== "left") return null;
|
|
9251
10529
|
return /* @__PURE__ */ jsxRuntime.jsx(FieldRenderer, { fieldId }, fieldId);
|
|
9252
10530
|
}) }),
|
|
9253
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-2 grid grid-cols-2 gap-
|
|
10531
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-2 grid grid-cols-2 gap-2", children: fieldIds.map((fieldId) => {
|
|
9254
10532
|
const fieldDef = store.getFieldDef(fieldId);
|
|
9255
10533
|
if (!fieldDef) return null;
|
|
9256
10534
|
const position = fieldDef.position ?? "center";
|
|
9257
10535
|
if (position !== "center") return null;
|
|
9258
10536
|
const colSpanRaw = fieldDef.colSpan ?? 1;
|
|
9259
10537
|
const colSpan = colSpanRaw === 2 ? 2 : 1;
|
|
9260
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
10538
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
10539
|
+
"div",
|
|
10540
|
+
{
|
|
10541
|
+
className: cn(
|
|
10542
|
+
"min-h-0 flex flex-col",
|
|
10543
|
+
colSpan === 2 ? "col-span-2" : "col-span-1 h-full"
|
|
10544
|
+
),
|
|
10545
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(FieldRenderer, { fieldId })
|
|
10546
|
+
},
|
|
10547
|
+
fieldId
|
|
10548
|
+
);
|
|
9261
10549
|
}) }),
|
|
9262
10550
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-1 flex flex-col gap-2", children: fieldIds.map((fieldId) => {
|
|
9263
10551
|
const fieldDef = store.getFieldDef(fieldId);
|
|
@@ -9705,11 +10993,17 @@ var ReadOnlyDischargeMedicationOrders = ({ fieldDef, value }) => {
|
|
|
9705
10993
|
}) })
|
|
9706
10994
|
] });
|
|
9707
10995
|
};
|
|
9708
|
-
var ReadOnlyFieldRenderer = ({
|
|
10996
|
+
var ReadOnlyFieldRenderer = ({
|
|
10997
|
+
fieldDef,
|
|
10998
|
+
value,
|
|
10999
|
+
allValues,
|
|
11000
|
+
resolveFieldDef
|
|
11001
|
+
}) => {
|
|
9709
11002
|
if (!fieldDef) return null;
|
|
9710
11003
|
switch (fieldDef.type) {
|
|
9711
11004
|
case "text":
|
|
9712
11005
|
case "number":
|
|
11006
|
+
case "slider":
|
|
9713
11007
|
case "textarea":
|
|
9714
11008
|
case "richtext":
|
|
9715
11009
|
return /* @__PURE__ */ jsxRuntime.jsx(ReadOnlyText, { fieldDef, value });
|
|
@@ -9747,8 +11041,30 @@ var ReadOnlyFieldRenderer = ({ fieldDef, value }) => {
|
|
|
9747
11041
|
] });
|
|
9748
11042
|
}
|
|
9749
11043
|
case "suggestion_textarea":
|
|
9750
|
-
case "complaint_chips":
|
|
9751
|
-
|
|
11044
|
+
case "complaint_chips": {
|
|
11045
|
+
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()) : [];
|
|
11046
|
+
const showEmbedded = embeddedIds.length > 0 && resolveFieldDef && allValues && typeof allValues === "object";
|
|
11047
|
+
if (!showEmbedded) {
|
|
11048
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ReadOnlyText, { fieldDef, value });
|
|
11049
|
+
}
|
|
11050
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
|
|
11051
|
+
/* @__PURE__ */ jsxRuntime.jsx(ReadOnlyText, { fieldDef, value }),
|
|
11052
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid gap-3 border-t border-muted-foreground/20 pt-3 sm:grid-cols-3", children: embeddedIds.map((id) => {
|
|
11053
|
+
const fd = resolveFieldDef(id);
|
|
11054
|
+
if (!fd) return null;
|
|
11055
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
11056
|
+
ReadOnlyFieldRenderer,
|
|
11057
|
+
{
|
|
11058
|
+
fieldDef: fd,
|
|
11059
|
+
value: allValues[id],
|
|
11060
|
+
allValues,
|
|
11061
|
+
resolveFieldDef
|
|
11062
|
+
},
|
|
11063
|
+
id
|
|
11064
|
+
);
|
|
11065
|
+
}) })
|
|
11066
|
+
] });
|
|
11067
|
+
}
|
|
9752
11068
|
case "lens_assessment": {
|
|
9753
11069
|
const v = value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
9754
11070
|
const notes = typeof v?.notes === "string" ? v.notes : "";
|
|
@@ -9824,6 +11140,44 @@ var ReadOnlyFieldRenderer = ({ fieldDef, value }) => {
|
|
|
9824
11140
|
const lines = [`Right eye (OD): ${od}`, `Left eye (OS): ${os}`].join("\n");
|
|
9825
11141
|
return /* @__PURE__ */ jsxRuntime.jsx(ReadOnlyText, { fieldDef, value: lines });
|
|
9826
11142
|
}
|
|
11143
|
+
case "pain_scale_flags": {
|
|
11144
|
+
const def = fieldDef;
|
|
11145
|
+
const min = def.min ?? 0;
|
|
11146
|
+
const max = def.max ?? 10;
|
|
11147
|
+
const safe = normalizePainScaleFlags(value, { min, max });
|
|
11148
|
+
const opts = def.options ?? [];
|
|
11149
|
+
const flagLabels = safe.flags.map((fv) => {
|
|
11150
|
+
const o = opts.find((x) => x.value === fv || String(x.value) === String(fv));
|
|
11151
|
+
return o?.label ?? fv;
|
|
11152
|
+
});
|
|
11153
|
+
const lines = [
|
|
11154
|
+
`Pain score (VAS): ${safe.pain}/${max}`,
|
|
11155
|
+
flagLabels.length > 0 ? `Triage flags: ${flagLabels.join(", ")}` : "Triage flags: \u2014"
|
|
11156
|
+
].join("\n");
|
|
11157
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ReadOnlyText, { fieldDef, value: lines });
|
|
11158
|
+
}
|
|
11159
|
+
case "general_surgery_smart_history":
|
|
11160
|
+
case "general_surgery_grading":
|
|
11161
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
11162
|
+
ReadOnlyText,
|
|
11163
|
+
{
|
|
11164
|
+
fieldDef,
|
|
11165
|
+
value: value && typeof value === "object" ? JSON.stringify(value, null, 2) : value == null || value === "" ? "\u2014" : String(value)
|
|
11166
|
+
}
|
|
11167
|
+
);
|
|
11168
|
+
case "general_surgery_examination": {
|
|
11169
|
+
const structuredDisplay = value && typeof value === "object" ? JSON.stringify(value, null, 2) : value == null || value === "" ? "\u2014" : String(value);
|
|
11170
|
+
const clinicalDef = resolveFieldDef?.("clinical_examination");
|
|
11171
|
+
const clinicalRaw = allValues?.["clinical_examination"];
|
|
11172
|
+
const clinicalStr = typeof clinicalRaw === "string" ? clinicalRaw : clinicalRaw != null && clinicalRaw !== "" ? String(clinicalRaw) : "";
|
|
11173
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
|
|
11174
|
+
/* @__PURE__ */ jsxRuntime.jsx(ReadOnlyText, { fieldDef, value: structuredDisplay }),
|
|
11175
|
+
clinicalDef ? /* @__PURE__ */ jsxRuntime.jsx(ReadOnlyText, { fieldDef: clinicalDef, value: clinicalStr }) : clinicalStr ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
11176
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-gray-700", children: "Clinical examination" }),
|
|
11177
|
+
/* @__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 })
|
|
11178
|
+
] }) : null
|
|
11179
|
+
] });
|
|
11180
|
+
}
|
|
9827
11181
|
case "static_text": {
|
|
9828
11182
|
const def = fieldDef;
|
|
9829
11183
|
const size = def.size ?? "regular";
|
|
@@ -9870,7 +11224,9 @@ var ReadOnlyForm = ({ schema, submission }) => {
|
|
|
9870
11224
|
ReadOnlyFieldRenderer,
|
|
9871
11225
|
{
|
|
9872
11226
|
fieldDef,
|
|
9873
|
-
value: formData[child]
|
|
11227
|
+
value: formData[child],
|
|
11228
|
+
allValues: formData,
|
|
11229
|
+
resolveFieldDef: (id) => fieldMap.get(id)
|
|
9874
11230
|
},
|
|
9875
11231
|
child
|
|
9876
11232
|
) : null;
|
|
@@ -9889,7 +11245,9 @@ var ReadOnlyForm = ({ schema, submission }) => {
|
|
|
9889
11245
|
ReadOnlyFieldRenderer,
|
|
9890
11246
|
{
|
|
9891
11247
|
fieldDef,
|
|
9892
|
-
value: formData[fieldId]
|
|
11248
|
+
value: formData[fieldId],
|
|
11249
|
+
allValues: formData,
|
|
11250
|
+
resolveFieldDef: (id) => fieldMap.get(id)
|
|
9893
11251
|
},
|
|
9894
11252
|
fieldId
|
|
9895
11253
|
))
|
|
@@ -9920,7 +11278,9 @@ var ReadOnlyForm = ({ schema, submission }) => {
|
|
|
9920
11278
|
ReadOnlyFieldRenderer,
|
|
9921
11279
|
{
|
|
9922
11280
|
fieldDef,
|
|
9923
|
-
value: formData[fieldId]
|
|
11281
|
+
value: formData[fieldId],
|
|
11282
|
+
allValues: formData,
|
|
11283
|
+
resolveFieldDef: (id) => fieldMap.get(id)
|
|
9924
11284
|
},
|
|
9925
11285
|
fieldId
|
|
9926
11286
|
))
|