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.mjs
CHANGED
|
@@ -62,6 +62,15 @@ function validateField(value, field) {
|
|
|
62
62
|
return `Must be at most ${rules.max}`;
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
|
+
if (field.type === "slider") {
|
|
66
|
+
const num = Number(value);
|
|
67
|
+
if (isNaN(num)) return "Must be a valid number";
|
|
68
|
+
const s = field;
|
|
69
|
+
const min = s.min ?? 0;
|
|
70
|
+
const max = s.max ?? 10;
|
|
71
|
+
if (num < min) return `Must be at least ${min}`;
|
|
72
|
+
if (num > max) return `Must be at most ${max}`;
|
|
73
|
+
}
|
|
65
74
|
if (typeof value === "string") {
|
|
66
75
|
if (rules.minLength !== void 0 && value.length < rules.minLength) {
|
|
67
76
|
return `Must be at least ${rules.minLength} characters`;
|
|
@@ -200,6 +209,227 @@ function applyPrefill(currentValues, fields, prefilledData = {}) {
|
|
|
200
209
|
return newValues;
|
|
201
210
|
}
|
|
202
211
|
|
|
212
|
+
// src/core/generalSurgeryPathway.ts
|
|
213
|
+
var defaultGeneralSurgerySmartHistory = () => ({
|
|
214
|
+
pain: {
|
|
215
|
+
site: "",
|
|
216
|
+
onset: "",
|
|
217
|
+
character: "",
|
|
218
|
+
radiation: "",
|
|
219
|
+
associated: "",
|
|
220
|
+
timing: "",
|
|
221
|
+
exacerbating: "",
|
|
222
|
+
severity: 0
|
|
223
|
+
},
|
|
224
|
+
swelling: { duration: "", sizeProgression: "", painfulPainless: "", checks: [] },
|
|
225
|
+
gi: { appetite: "", weightLoss: "", bowelHabits: "", checks: [] },
|
|
226
|
+
breast: { lumpDuration: "", nippleDischarge: "", checks: [] },
|
|
227
|
+
ano: { checks: [] },
|
|
228
|
+
thyroid: { swellingDuration: "", checks: [] },
|
|
229
|
+
systemic: ""
|
|
230
|
+
});
|
|
231
|
+
var defaultGeneralSurgeryExamination = () => ({
|
|
232
|
+
general: [],
|
|
233
|
+
regions: [],
|
|
234
|
+
abdomen: {
|
|
235
|
+
inspection: [],
|
|
236
|
+
palpation: [],
|
|
237
|
+
percussion: [],
|
|
238
|
+
massNotes: "",
|
|
239
|
+
bowelSounds: "none"
|
|
240
|
+
},
|
|
241
|
+
hernia: { site: "", reducible: false, coughImpulse: false, tenderness: false },
|
|
242
|
+
breast: { lumpSizeCm: "", mobile: false, skinInvolvement: false, axillaryNodes: false },
|
|
243
|
+
thyroid: { size: "", mobileDeglutition: false, nodules: false, cervicalNodes: false },
|
|
244
|
+
anorectal: { inspection: "", dreDone: false, proctoscopyDone: false, notes: "" },
|
|
245
|
+
limb: { dilatedVeins: false, ulcer: false, oedema: false }
|
|
246
|
+
});
|
|
247
|
+
var ALL_GS_CONDITIONS = [
|
|
248
|
+
"hernia",
|
|
249
|
+
"appendicitis",
|
|
250
|
+
"gallbladder",
|
|
251
|
+
"breast",
|
|
252
|
+
"thyroid",
|
|
253
|
+
"piles",
|
|
254
|
+
"varicose",
|
|
255
|
+
"ulcer"
|
|
256
|
+
];
|
|
257
|
+
var defaultGeneralSurgeryGrading = () => ({
|
|
258
|
+
hernia: 0,
|
|
259
|
+
appendicitis: 0,
|
|
260
|
+
gallbladder: 0,
|
|
261
|
+
breast: 0,
|
|
262
|
+
thyroid: 0,
|
|
263
|
+
piles: 0,
|
|
264
|
+
varicose: 0,
|
|
265
|
+
ulcer: 0
|
|
266
|
+
});
|
|
267
|
+
var GS_CONDITION_TRIGGERS = {
|
|
268
|
+
hernia: { regions: ["hernia", "abdomen"], chips: ["swelling_lump", "obstruction"] },
|
|
269
|
+
appendicitis: { regions: ["abdomen"], chips: ["pain", "obstruction"] },
|
|
270
|
+
gallbladder: { regions: ["abdomen"], chips: ["pain"] },
|
|
271
|
+
breast: { regions: ["breast"], chips: ["breast", "swelling_lump"] },
|
|
272
|
+
thyroid: { regions: ["thyroid"], chips: ["thyroid", "swelling_lump"] },
|
|
273
|
+
piles: { regions: ["anorectal"], chips: ["anorectal", "bleeding"] },
|
|
274
|
+
varicose: { regions: ["limb"], chips: ["swelling_lump"] },
|
|
275
|
+
ulcer: { regions: ["limb", "anorectal"], chips: ["ulcer_wound", "discharge"] }
|
|
276
|
+
};
|
|
277
|
+
var GS_CONDITION_LABELS = {
|
|
278
|
+
hernia: "Hernia",
|
|
279
|
+
appendicitis: "Appendicitis",
|
|
280
|
+
gallbladder: "Gallbladder disease",
|
|
281
|
+
breast: "Breast lump (BIRADS)",
|
|
282
|
+
thyroid: "Thyroid nodule (TIRADS)",
|
|
283
|
+
piles: "Haemorrhoids",
|
|
284
|
+
varicose: "Varicose veins (CEAP)",
|
|
285
|
+
ulcer: "Ulcer / wound"
|
|
286
|
+
};
|
|
287
|
+
var GS_GRADE_DESCRIPTIONS = {
|
|
288
|
+
hernia: ["\u2014", "Small reducible", "Large reducible", "Irreducible", "Obstructed", "Strangulated"],
|
|
289
|
+
appendicitis: ["\u2014", "Mild (clinical)", "Confirmed (USG/CT)", "Complicated (mass)", "Abscess", "Perforation"],
|
|
290
|
+
gallbladder: ["\u2014", "Asymptomatic stones", "Symptomatic", "Acute cholecystitis", "Complicated (CBD stone)", "Perforation/empyema"],
|
|
291
|
+
breast: ["\u2014", "BIRADS 1 \u2014 Negative", "BIRADS 2 \u2014 Benign", "BIRADS 3 \u2014 Probably benign", "BIRADS 4 \u2014 Suspicious", "BIRADS 5 \u2014 Malignant"],
|
|
292
|
+
thyroid: ["\u2014", "TIRADS 1 \u2014 Normal", "TIRADS 2 \u2014 Benign", "TIRADS 3 \u2014 Indeterminate", "TIRADS 4 \u2014 Suspicious", "TIRADS 5 \u2014 Highly suspicious"],
|
|
293
|
+
piles: ["\u2014", "Grade 1", "Grade 2", "Grade 3", "Grade 4", "Grade 5"],
|
|
294
|
+
varicose: ["\u2014", "C1 telangiectasia", "C2 varicose", "C3 oedema", "C4 skin changes", "C5-C6 ulcer"],
|
|
295
|
+
ulcer: ["\u2014", "Superficial", "Deep", "Infected", "Necrotic", "Gangrene"]
|
|
296
|
+
};
|
|
297
|
+
function normalizeGeneralSurgerySmartHistory(raw) {
|
|
298
|
+
const d = defaultGeneralSurgerySmartHistory();
|
|
299
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return d;
|
|
300
|
+
const v = raw;
|
|
301
|
+
const painIn = v.pain && typeof v.pain === "object" ? v.pain : {};
|
|
302
|
+
const sev = Number(painIn.severity);
|
|
303
|
+
const pain = {
|
|
304
|
+
...d.pain,
|
|
305
|
+
...painIn,
|
|
306
|
+
severity: Number.isFinite(sev) ? Math.min(10, Math.max(0, Math.round(sev))) : d.pain.severity
|
|
307
|
+
};
|
|
308
|
+
const str2 = (x) => typeof x === "string" ? x : "";
|
|
309
|
+
const strArr = (x) => Array.isArray(x) ? x.filter((i) => typeof i === "string") : [];
|
|
310
|
+
const swell = v.swelling && typeof v.swelling === "object" ? v.swelling : {};
|
|
311
|
+
const gi = v.gi && typeof v.gi === "object" ? v.gi : {};
|
|
312
|
+
const breast = v.breast && typeof v.breast === "object" ? v.breast : {};
|
|
313
|
+
const ano = v.ano && typeof v.ano === "object" ? v.ano : {};
|
|
314
|
+
const thy = v.thyroid && typeof v.thyroid === "object" ? v.thyroid : {};
|
|
315
|
+
return {
|
|
316
|
+
pain,
|
|
317
|
+
swelling: {
|
|
318
|
+
duration: str2(swell.duration),
|
|
319
|
+
sizeProgression: str2(swell.sizeProgression),
|
|
320
|
+
painfulPainless: str2(swell.painfulPainless),
|
|
321
|
+
checks: strArr(swell.checks)
|
|
322
|
+
},
|
|
323
|
+
gi: {
|
|
324
|
+
appetite: str2(gi.appetite),
|
|
325
|
+
weightLoss: str2(gi.weightLoss),
|
|
326
|
+
bowelHabits: str2(gi.bowelHabits),
|
|
327
|
+
checks: strArr(gi.checks)
|
|
328
|
+
},
|
|
329
|
+
breast: {
|
|
330
|
+
lumpDuration: str2(breast.lumpDuration),
|
|
331
|
+
nippleDischarge: str2(breast.nippleDischarge),
|
|
332
|
+
checks: strArr(breast.checks)
|
|
333
|
+
},
|
|
334
|
+
ano: { checks: strArr(ano.checks) },
|
|
335
|
+
thyroid: {
|
|
336
|
+
swellingDuration: str2(thy.swellingDuration),
|
|
337
|
+
checks: strArr(thy.checks)
|
|
338
|
+
},
|
|
339
|
+
systemic: typeof v.systemic === "string" ? v.systemic : d.systemic
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
function normalizeGeneralSurgeryExamination(raw) {
|
|
343
|
+
const d = defaultGeneralSurgeryExamination();
|
|
344
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return d;
|
|
345
|
+
const v = raw;
|
|
346
|
+
const strArr = (x) => Array.isArray(x) ? x.filter((i) => typeof i === "string") : [];
|
|
347
|
+
const ab = v.abdomen && typeof v.abdomen === "object" ? v.abdomen : {};
|
|
348
|
+
const bowel = ab.bowelSounds;
|
|
349
|
+
const bowels = bowel === "normal" || bowel === "up" || bowel === "down" || bowel === "absent" ? bowel : "none";
|
|
350
|
+
const hb = v.hernia && typeof v.hernia === "object" ? v.hernia : {};
|
|
351
|
+
const br = v.breast && typeof v.breast === "object" ? v.breast : {};
|
|
352
|
+
const th = v.thyroid && typeof v.thyroid === "object" ? v.thyroid : {};
|
|
353
|
+
const ar = v.anorectal && typeof v.anorectal === "object" ? v.anorectal : {};
|
|
354
|
+
const lm = v.limb && typeof v.limb === "object" ? v.limb : {};
|
|
355
|
+
const bool = (x) => x === true;
|
|
356
|
+
return {
|
|
357
|
+
general: strArr(v.general),
|
|
358
|
+
regions: strArr(v.regions),
|
|
359
|
+
abdomen: {
|
|
360
|
+
inspection: strArr(ab.inspection),
|
|
361
|
+
palpation: strArr(ab.palpation),
|
|
362
|
+
percussion: strArr(ab.percussion),
|
|
363
|
+
massNotes: typeof ab.massNotes === "string" ? ab.massNotes : d.abdomen.massNotes,
|
|
364
|
+
bowelSounds: bowels
|
|
365
|
+
},
|
|
366
|
+
hernia: {
|
|
367
|
+
site: typeof hb.site === "string" ? hb.site : "",
|
|
368
|
+
reducible: bool(hb.reducible),
|
|
369
|
+
coughImpulse: bool(hb.coughImpulse),
|
|
370
|
+
tenderness: bool(hb.tenderness)
|
|
371
|
+
},
|
|
372
|
+
breast: {
|
|
373
|
+
lumpSizeCm: typeof br.lumpSizeCm === "string" ? br.lumpSizeCm : "",
|
|
374
|
+
mobile: bool(br.mobile),
|
|
375
|
+
skinInvolvement: bool(br.skinInvolvement),
|
|
376
|
+
axillaryNodes: bool(br.axillaryNodes)
|
|
377
|
+
},
|
|
378
|
+
thyroid: {
|
|
379
|
+
size: typeof th.size === "string" ? th.size : "",
|
|
380
|
+
mobileDeglutition: bool(th.mobileDeglutition),
|
|
381
|
+
nodules: bool(th.nodules),
|
|
382
|
+
cervicalNodes: bool(th.cervicalNodes)
|
|
383
|
+
},
|
|
384
|
+
anorectal: {
|
|
385
|
+
inspection: typeof ar.inspection === "string" ? ar.inspection : "",
|
|
386
|
+
dreDone: bool(ar.dreDone),
|
|
387
|
+
proctoscopyDone: bool(ar.proctoscopyDone),
|
|
388
|
+
notes: typeof ar.notes === "string" ? ar.notes : ""
|
|
389
|
+
},
|
|
390
|
+
limb: {
|
|
391
|
+
dilatedVeins: bool(lm.dilatedVeins),
|
|
392
|
+
ulcer: bool(lm.ulcer),
|
|
393
|
+
oedema: bool(lm.oedema)
|
|
394
|
+
}
|
|
395
|
+
};
|
|
396
|
+
}
|
|
397
|
+
function normalizeGeneralSurgeryGrading(raw) {
|
|
398
|
+
const d = defaultGeneralSurgeryGrading();
|
|
399
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return d;
|
|
400
|
+
const v = raw;
|
|
401
|
+
const out = { ...d };
|
|
402
|
+
for (const k of ALL_GS_CONDITIONS) {
|
|
403
|
+
const n = Number(v[k]);
|
|
404
|
+
if (Number.isFinite(n) && n >= 0 && n <= 5) out[k] = Math.round(n);
|
|
405
|
+
}
|
|
406
|
+
return out;
|
|
407
|
+
}
|
|
408
|
+
function gsGradingRowVisible(cond, chips, regions, grade) {
|
|
409
|
+
if (grade > 0) return true;
|
|
410
|
+
const t = GS_CONDITION_TRIGGERS[cond];
|
|
411
|
+
if (t.chips.some((c) => chips.includes(c))) return true;
|
|
412
|
+
if (t.regions.some((r) => regions.includes(r))) return true;
|
|
413
|
+
return false;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
// src/core/painScaleFlags.ts
|
|
417
|
+
function normalizePainScaleFlags(raw, bounds) {
|
|
418
|
+
const min = bounds?.min ?? 0;
|
|
419
|
+
const max = bounds?.max ?? 10;
|
|
420
|
+
let pain = min;
|
|
421
|
+
let flags = [];
|
|
422
|
+
if (raw && typeof raw === "object" && !Array.isArray(raw)) {
|
|
423
|
+
const o = raw;
|
|
424
|
+
const p = Number(o.pain);
|
|
425
|
+
if (Number.isFinite(p)) pain = Math.min(max, Math.max(min, p));
|
|
426
|
+
if (Array.isArray(o.flags)) {
|
|
427
|
+
flags = o.flags.filter((x) => typeof x === "string");
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
return { pain, flags };
|
|
431
|
+
}
|
|
432
|
+
|
|
203
433
|
// src/core/store.ts
|
|
204
434
|
var FormStore = class {
|
|
205
435
|
state;
|
|
@@ -286,7 +516,22 @@ var FormStore = class {
|
|
|
286
516
|
else if (field.type === "surgical_risk_flags")
|
|
287
517
|
values[field.id] = { OD: [], OS: [] };
|
|
288
518
|
else if (field.type === "toggle") values[field.id] = false;
|
|
289
|
-
else
|
|
519
|
+
else if (field.type === "slider") {
|
|
520
|
+
const s = field;
|
|
521
|
+
values[field.id] = s.defaultValue ?? s.min ?? 0;
|
|
522
|
+
} else if (field.type === "general_surgery_smart_history") {
|
|
523
|
+
values[field.id] = field.defaultValue ?? defaultGeneralSurgerySmartHistory();
|
|
524
|
+
} else if (field.type === "general_surgery_examination") {
|
|
525
|
+
values[field.id] = field.defaultValue ?? defaultGeneralSurgeryExamination();
|
|
526
|
+
} else if (field.type === "general_surgery_grading") {
|
|
527
|
+
values[field.id] = field.defaultValue ?? defaultGeneralSurgeryGrading();
|
|
528
|
+
} else if (field.type === "pain_scale_flags") {
|
|
529
|
+
const f = field;
|
|
530
|
+
values[field.id] = normalizePainScaleFlags(
|
|
531
|
+
f.defaultValue ?? { pain: f.min ?? 0, flags: [] },
|
|
532
|
+
{ min: f.min, max: f.max }
|
|
533
|
+
);
|
|
534
|
+
} else values[field.id] = null;
|
|
290
535
|
}
|
|
291
536
|
});
|
|
292
537
|
this.state.values = values;
|
|
@@ -1006,7 +1251,8 @@ var TextWidget = ({ fieldId }) => {
|
|
|
1006
1251
|
fieldDef.required && /* @__PURE__ */ jsx("span", { className: "text-red-500", children: "*" })
|
|
1007
1252
|
] });
|
|
1008
1253
|
const labelEl = theme ? /* @__PURE__ */ jsx(Label, { htmlFor: fieldId, className: labelClass, children: labelContent }) : /* @__PURE__ */ jsx(Label, { htmlFor: fieldId, children: labelContent });
|
|
1009
|
-
|
|
1254
|
+
const placeholder = typeof fieldDef.placeholder === "string" && fieldDef.placeholder.trim() ? fieldDef.placeholder : void 0;
|
|
1255
|
+
return /* @__PURE__ */ jsxs("div", { className: cn(wrapperClass, isTextarea && "flex h-full min-h-0 flex-col"), children: [
|
|
1010
1256
|
hasVoice ? /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
1011
1257
|
labelEl,
|
|
1012
1258
|
/* @__PURE__ */ jsx(VoiceMicButton, { fieldId, onTranscriptReady: setValue })
|
|
@@ -1020,7 +1266,8 @@ var TextWidget = ({ fieldId }) => {
|
|
|
1020
1266
|
onBlur: setTouched,
|
|
1021
1267
|
disabled,
|
|
1022
1268
|
type: fieldDef.type === "number" ? "number" : "text",
|
|
1023
|
-
className: inputClass,
|
|
1269
|
+
className: cn(inputClass, isTextarea && height == null && "min-h-[80px] flex-1"),
|
|
1270
|
+
placeholder,
|
|
1024
1271
|
...isTextarea && { height }
|
|
1025
1272
|
}
|
|
1026
1273
|
),
|
|
@@ -1496,6 +1743,8 @@ var SelectWidget = ({ fieldId }) => {
|
|
|
1496
1743
|
}
|
|
1497
1744
|
}, [fieldDef]);
|
|
1498
1745
|
if (!fieldDef) return null;
|
|
1746
|
+
const schemaPlaceholder = typeof fieldDef.placeholder === "string" && fieldDef.placeholder.trim() ? fieldDef.placeholder : void 0;
|
|
1747
|
+
const selectPlaceholder = loading ? "Loading..." : schemaPlaceholder ?? "Select...";
|
|
1499
1748
|
return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
1500
1749
|
/* @__PURE__ */ jsxs(Label, { htmlFor: fieldId, children: [
|
|
1501
1750
|
fieldDef.label,
|
|
@@ -1513,7 +1762,7 @@ var SelectWidget = ({ fieldId }) => {
|
|
|
1513
1762
|
setTouched();
|
|
1514
1763
|
},
|
|
1515
1764
|
children: [
|
|
1516
|
-
/* @__PURE__ */ jsx(SelectTrigger, { id: fieldId, className: showError ? "border-red-500" : "", children: /* @__PURE__ */ jsx(SelectValue, { placeholder:
|
|
1765
|
+
/* @__PURE__ */ jsx(SelectTrigger, { id: fieldId, className: showError ? "border-red-500" : "", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: selectPlaceholder }) }),
|
|
1517
1766
|
/* @__PURE__ */ jsx(SelectContent, { children: options.map((opt) => /* @__PURE__ */ jsx(SelectItem, { value: String(opt.value), children: opt.label }, String(opt.value))) })
|
|
1518
1767
|
]
|
|
1519
1768
|
}
|
|
@@ -6385,7 +6634,11 @@ var OphthalmologyWidget = ({ fieldId }) => {
|
|
|
6385
6634
|
] })
|
|
6386
6635
|
] }),
|
|
6387
6636
|
/* @__PURE__ */ jsx("tbody", { children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
6388
|
-
/* @__PURE__ */ jsx("td", { className: refractionLabelCellClass
|
|
6637
|
+
/* @__PURE__ */ jsx("td", { className: `${refractionLabelCellClass} whitespace-normal`, children: /* @__PURE__ */ jsxs("span", { className: "block leading-tight", children: [
|
|
6638
|
+
"Current",
|
|
6639
|
+
/* @__PURE__ */ jsx("br", {}),
|
|
6640
|
+
"Glass"
|
|
6641
|
+
] }) }),
|
|
6389
6642
|
/* @__PURE__ */ jsx("td", { className: refractionDataCellClass, children: /* @__PURE__ */ jsx(
|
|
6390
6643
|
Input,
|
|
6391
6644
|
{
|
|
@@ -6640,12 +6893,12 @@ var OphthalmologyWidget = ({ fieldId }) => {
|
|
|
6640
6893
|
/* @__PURE__ */ jsx("th", { className: refractionHeaderCellClass, children: "Sph" }),
|
|
6641
6894
|
/* @__PURE__ */ jsx("th", { className: refractionHeaderCellClass, children: "Cyl" }),
|
|
6642
6895
|
/* @__PURE__ */ jsx("th", { className: refractionHeaderCellClass, children: "Axis" }),
|
|
6643
|
-
/* @__PURE__ */ jsx("th", { className: refractionHeaderCellClass, children: "
|
|
6896
|
+
/* @__PURE__ */ jsx("th", { className: refractionHeaderCellClass, children: "BCVA" }),
|
|
6644
6897
|
/* @__PURE__ */ jsx("th", { className: refractionHeaderCellClass, children: "P/D" }),
|
|
6645
6898
|
/* @__PURE__ */ jsx("th", { className: refractionHeaderCellClass, children: "Sph" }),
|
|
6646
6899
|
/* @__PURE__ */ jsx("th", { className: refractionHeaderCellClass, children: "Cyl" }),
|
|
6647
6900
|
/* @__PURE__ */ jsx("th", { className: refractionHeaderCellClass, children: "Axis" }),
|
|
6648
|
-
/* @__PURE__ */ jsx("th", { className: refractionHeaderCellClass, children: "
|
|
6901
|
+
/* @__PURE__ */ jsx("th", { className: refractionHeaderCellClass, children: "BCVA" }),
|
|
6649
6902
|
/* @__PURE__ */ jsx("th", { className: refractionHeaderCellClass, children: "P/D" })
|
|
6650
6903
|
] })
|
|
6651
6904
|
] }),
|
|
@@ -8034,6 +8287,21 @@ function parallelChipArraysEqual(a, b) {
|
|
|
8034
8287
|
function isSuggestionField(type) {
|
|
8035
8288
|
return type === "suggestion_textarea" || type === "complaint_chips";
|
|
8036
8289
|
}
|
|
8290
|
+
function EmbeddedSchemaField({ fieldId }) {
|
|
8291
|
+
const store = useFormStore();
|
|
8292
|
+
const fieldDef = store.getFieldDef(fieldId);
|
|
8293
|
+
if (!fieldDef) return null;
|
|
8294
|
+
switch (fieldDef.type) {
|
|
8295
|
+
case "text":
|
|
8296
|
+
case "number":
|
|
8297
|
+
case "textarea":
|
|
8298
|
+
return /* @__PURE__ */ jsx(TextWidget, { fieldId });
|
|
8299
|
+
case "select":
|
|
8300
|
+
return /* @__PURE__ */ jsx(SelectWidget, { fieldId });
|
|
8301
|
+
default:
|
|
8302
|
+
return null;
|
|
8303
|
+
}
|
|
8304
|
+
}
|
|
8037
8305
|
var SuggestionTextareaWidget = ({ fieldId }) => {
|
|
8038
8306
|
const { fieldDef, value, setValue, setTouched, error, disabled, touched } = useField(fieldId);
|
|
8039
8307
|
const { state } = useForm();
|
|
@@ -8045,6 +8313,10 @@ var SuggestionTextareaWidget = ({ fieldId }) => {
|
|
|
8045
8313
|
const def = fieldDef && isSuggestionField(fieldDef.type) ? fieldDef : void 0;
|
|
8046
8314
|
const textValue = value == null || typeof value === "string" ? value || "" : String(value);
|
|
8047
8315
|
const parallelChipFieldId = def?.meta && typeof def.meta.parallelChipFieldId === "string" ? def.meta.parallelChipFieldId.trim() : void 0;
|
|
8316
|
+
const embeddedFieldIds = useMemo(() => {
|
|
8317
|
+
const raw = def?.meta && Array.isArray(def.meta.embeddedFieldIds) ? def.meta.embeddedFieldIds : [];
|
|
8318
|
+
return raw.filter((id) => typeof id === "string" && id.trim().length > 0).map((id) => id.trim()).filter((id) => store.getFieldDef(id));
|
|
8319
|
+
}, [def?.meta, store]);
|
|
8048
8320
|
useEffect(() => {
|
|
8049
8321
|
if (!def) {
|
|
8050
8322
|
setOptions([]);
|
|
@@ -8089,19 +8361,26 @@ var SuggestionTextareaWidget = ({ fieldId }) => {
|
|
|
8089
8361
|
setValue(toggleSuggestionTokenInText(textValue, String(optValue), appendSeparator));
|
|
8090
8362
|
};
|
|
8091
8363
|
const hasSuggestions = options.length > 0;
|
|
8364
|
+
const hasEmbedded = embeddedFieldIds.length > 0;
|
|
8365
|
+
const hasShell = hasSuggestions || hasEmbedded;
|
|
8092
8366
|
const isHighlightLabel = def.theme === "highlight-label";
|
|
8093
8367
|
const suggestionShellClass = cn(
|
|
8094
8368
|
"flex min-w-0 flex-col overflow-hidden",
|
|
8095
|
-
|
|
8369
|
+
hasShell && (isHighlightLabel ? "-mt-1 rounded-b-md border-[#D0D0D0] bg-white" : "rounded-md border border-input bg-background")
|
|
8096
8370
|
);
|
|
8097
8371
|
const chipsRowClass = cn(
|
|
8098
8372
|
"flex flex-wrap gap-2 px-3 pb-2 pt-3",
|
|
8099
8373
|
hasSuggestions && (isHighlightLabel ? "" : "border-b border-input/70"),
|
|
8100
8374
|
disabled && "pointer-events-none opacity-50"
|
|
8101
8375
|
);
|
|
8376
|
+
const embeddedRowClass = cn(
|
|
8377
|
+
"grid gap-3 px-3 sm:grid-cols-3",
|
|
8378
|
+
hasEmbedded && (hasSuggestions ? cn("py-2", isHighlightLabel && "border-t border-input/70") : "border-b border-input/70 py-3"),
|
|
8379
|
+
disabled && "pointer-events-none opacity-50"
|
|
8380
|
+
);
|
|
8102
8381
|
const textareaShellClass = cn(
|
|
8103
8382
|
inputClass,
|
|
8104
|
-
|
|
8383
|
+
hasShell && cn(
|
|
8105
8384
|
"mt-0 rounded-t-none rounded-b-md border-0 shadow-none focus-visible:ring-offset-0",
|
|
8106
8385
|
isHighlightLabel ? "border-t-0" : "min-h-[80px]"
|
|
8107
8386
|
)
|
|
@@ -8128,8 +8407,9 @@ var SuggestionTextareaWidget = ({ fieldId }) => {
|
|
|
8128
8407
|
/* @__PURE__ */ jsx(VoiceMicButton, { fieldId, onTranscriptReady: setValue })
|
|
8129
8408
|
] }) : labelEl,
|
|
8130
8409
|
def.description && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: def.description }),
|
|
8131
|
-
|
|
8132
|
-
/* @__PURE__ */ jsx("div", { className: chipsRowClass, role: "group", "aria-label": suggestionsAria, children: suggestionButtons }),
|
|
8410
|
+
hasShell ? /* @__PURE__ */ jsxs("div", { className: suggestionShellClass, children: [
|
|
8411
|
+
hasSuggestions && /* @__PURE__ */ jsx("div", { className: chipsRowClass, role: "group", "aria-label": suggestionsAria, children: suggestionButtons }),
|
|
8412
|
+
hasEmbedded && /* @__PURE__ */ jsx("div", { className: embeddedRowClass, children: embeddedFieldIds.map((id) => /* @__PURE__ */ jsx(EmbeddedSchemaField, { fieldId: id }, id)) }),
|
|
8133
8413
|
/* @__PURE__ */ jsx(
|
|
8134
8414
|
Textarea,
|
|
8135
8415
|
{
|
|
@@ -8909,178 +9189,1176 @@ var SurgicalRiskFlagsWidget = ({ fieldId }) => {
|
|
|
8909
9189
|
}
|
|
8910
9190
|
);
|
|
8911
9191
|
};
|
|
8912
|
-
var
|
|
8913
|
-
const { fieldDef,
|
|
8914
|
-
|
|
8915
|
-
|
|
8916
|
-
|
|
8917
|
-
|
|
8918
|
-
|
|
8919
|
-
|
|
8920
|
-
|
|
8921
|
-
|
|
8922
|
-
|
|
8923
|
-
|
|
8924
|
-
|
|
8925
|
-
|
|
8926
|
-
|
|
8927
|
-
|
|
8928
|
-
|
|
8929
|
-
|
|
8930
|
-
|
|
8931
|
-
|
|
8932
|
-
|
|
8933
|
-
|
|
8934
|
-
|
|
8935
|
-
|
|
8936
|
-
|
|
8937
|
-
|
|
8938
|
-
|
|
8939
|
-
|
|
8940
|
-
|
|
8941
|
-
case "multiselect":
|
|
8942
|
-
return /* @__PURE__ */ jsx(MultiSelectWidget, { fieldId });
|
|
8943
|
-
case "repeatable":
|
|
8944
|
-
return /* @__PURE__ */ jsx(RepeatableWidget, { fieldId });
|
|
8945
|
-
case "image_upload":
|
|
8946
|
-
return /* @__PURE__ */ jsx(ImageUploadWidget, { fieldId });
|
|
8947
|
-
case "media_upload":
|
|
8948
|
-
return /* @__PURE__ */ jsx(MediaUploadWidget, { fieldId });
|
|
8949
|
-
case "signature":
|
|
8950
|
-
return /* @__PURE__ */ jsx(SignatureUploadWidget, { fieldId });
|
|
8951
|
-
case "editable_table":
|
|
8952
|
-
return /* @__PURE__ */ jsx(EditableTableWidget, { fieldId });
|
|
8953
|
-
case "medications":
|
|
8954
|
-
return /* @__PURE__ */ jsx(AddMedicationWidget, { fieldId });
|
|
8955
|
-
case "discharge_medication_orders":
|
|
8956
|
-
return /* @__PURE__ */ jsx(DischargeMedicationOrdersWidget, { fieldId });
|
|
8957
|
-
case "investigations":
|
|
8958
|
-
return /* @__PURE__ */ jsx(AddInvestigationWidget, { fieldId });
|
|
8959
|
-
case "procedures":
|
|
8960
|
-
return /* @__PURE__ */ jsx(AddProcedureWidget, { fieldId });
|
|
8961
|
-
case "differential_diagnosis":
|
|
8962
|
-
return /* @__PURE__ */ jsx(DifferentialDiagnosisWidget, { fieldId });
|
|
8963
|
-
case "vitals":
|
|
8964
|
-
return /* @__PURE__ */ jsx(VitalsWidget, { fieldId });
|
|
8965
|
-
case "hidden_vitals":
|
|
8966
|
-
return /* @__PURE__ */ jsx(HiddenVitalsWidget, { fieldId });
|
|
8967
|
-
case "referral":
|
|
8968
|
-
return /* @__PURE__ */ jsx(ReferralWidget, { fieldId });
|
|
8969
|
-
case "followup":
|
|
8970
|
-
return /* @__PURE__ */ jsx(FollowupWidget, { fieldId });
|
|
8971
|
-
case "smart_textarea":
|
|
8972
|
-
return /* @__PURE__ */ jsx(SmartTextareaWidget, { fieldId });
|
|
8973
|
-
case "diagnosis_textarea":
|
|
8974
|
-
return /* @__PURE__ */ jsx(DiagnosisTextareaWidget, { fieldId });
|
|
8975
|
-
case "obstetric_history":
|
|
8976
|
-
return /* @__PURE__ */ jsx(ObstetricHistoryWidget, { fieldId });
|
|
8977
|
-
case "eye_prescription":
|
|
8978
|
-
return /* @__PURE__ */ jsx(OphthalmologyWidget, { fieldId });
|
|
8979
|
-
case "ophthal_diagnosis":
|
|
8980
|
-
return /* @__PURE__ */ jsx(OphthalDiagnosisWidget, { fieldId });
|
|
8981
|
-
case "orthopedic_exam":
|
|
8982
|
-
return /* @__PURE__ */ jsx(OrthopedicExamWidget, { fieldId });
|
|
8983
|
-
case "toggle": {
|
|
8984
|
-
const { value, setValue, setTouched, disabled } = useField(fieldId);
|
|
8985
|
-
const store = useFormStore();
|
|
8986
|
-
const excludes = fieldDef.excludes ?? [];
|
|
8987
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
8988
|
-
/* @__PURE__ */ jsx(
|
|
8989
|
-
Switch,
|
|
8990
|
-
{
|
|
8991
|
-
checked: value === true,
|
|
8992
|
-
disabled,
|
|
8993
|
-
onCheckedChange: (checked) => {
|
|
8994
|
-
setValue(checked);
|
|
8995
|
-
setTouched();
|
|
8996
|
-
if (checked) excludes.forEach((id) => store.setValue(id, false));
|
|
8997
|
-
}
|
|
8998
|
-
}
|
|
8999
|
-
),
|
|
9000
|
-
/* @__PURE__ */ jsx(Label, { className: "text-sm font-medium leading-none cursor-pointer select-none", children: fieldDef.label })
|
|
9001
|
-
] });
|
|
9002
|
-
}
|
|
9003
|
-
case "suggestion_textarea":
|
|
9004
|
-
case "complaint_chips":
|
|
9005
|
-
return /* @__PURE__ */ jsx(SuggestionTextareaWidget, { fieldId });
|
|
9006
|
-
case "lens_assessment":
|
|
9007
|
-
return /* @__PURE__ */ jsx(LensAssessmentWidget, { fieldId });
|
|
9008
|
-
case "functional_impairment_score":
|
|
9009
|
-
return /* @__PURE__ */ jsx(FunctionalImpairmentScoreWidget, { fieldId });
|
|
9010
|
-
case "biometry_iol_workup":
|
|
9011
|
-
return /* @__PURE__ */ jsx(BiometryIolWorkupWidget, { fieldId });
|
|
9012
|
-
case "surgical_risk_flags":
|
|
9013
|
-
return /* @__PURE__ */ jsx(SurgicalRiskFlagsWidget, { fieldId });
|
|
9014
|
-
case "static_text": {
|
|
9015
|
-
const def = fieldDef;
|
|
9016
|
-
const size = def.size ?? "regular";
|
|
9017
|
-
const labelClass = size === "large" ? "text-base" : "text-sm";
|
|
9018
|
-
const descClass = size === "large" ? "text-sm" : "text-xs";
|
|
9019
|
-
return /* @__PURE__ */ jsxs("div", { className: `${labelClass} text-muted-foreground`, children: [
|
|
9020
|
-
def.label,
|
|
9021
|
-
def.description && /* @__PURE__ */ jsx("p", { className: `mt-1 ${descClass} opacity-90`, children: def.description })
|
|
9022
|
-
] });
|
|
9023
|
-
}
|
|
9024
|
-
default:
|
|
9025
|
-
return /* @__PURE__ */ jsxs("div", { className: "text-red-500", children: [
|
|
9026
|
-
"Unknown field type: ",
|
|
9027
|
-
fieldDef.type
|
|
9028
|
-
] });
|
|
9029
|
-
}
|
|
9030
|
-
}
|
|
9031
|
-
var Section = ({ title, children }) => {
|
|
9032
|
-
const [expanded, setExpanded] = useState(true);
|
|
9033
|
-
const handleToggle = () => setExpanded((prev) => !prev);
|
|
9034
|
-
const contentClassName = cn(
|
|
9035
|
-
"overflow-hidden transition-[height] duration-200 ease-in-out",
|
|
9036
|
-
!expanded && "hidden"
|
|
9037
|
-
);
|
|
9038
|
-
return /* @__PURE__ */ jsxs("div", { className: "mb-6 border rounded-lg bg-white shadow-sm overflow-hidden", children: [
|
|
9039
|
-
/* @__PURE__ */ jsxs(
|
|
9040
|
-
"button",
|
|
9192
|
+
var SliderWidget = ({ fieldId }) => {
|
|
9193
|
+
const { fieldDef, value, setValue, setTouched, error, disabled, touched } = useField(fieldId);
|
|
9194
|
+
const { state } = useForm();
|
|
9195
|
+
const showError = !!error && (touched || state.submitAttempted);
|
|
9196
|
+
if (!fieldDef || fieldDef.type !== "slider") return null;
|
|
9197
|
+
const def = fieldDef;
|
|
9198
|
+
const min = def.min ?? 0;
|
|
9199
|
+
const max = def.max ?? 10;
|
|
9200
|
+
const step = def.step ?? 1;
|
|
9201
|
+
const raw = value == null || value === "" ? min : Number(value);
|
|
9202
|
+
const num = Number.isFinite(raw) ? Math.min(max, Math.max(min, raw)) : min;
|
|
9203
|
+
const theme = getThemeConfig("textarea", def.theme);
|
|
9204
|
+
const wrapperClass = theme?.wrapperClassName ?? "space-y-2";
|
|
9205
|
+
const labelClass = theme?.labelClassName;
|
|
9206
|
+
const labelContent = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
9207
|
+
def.label,
|
|
9208
|
+
" ",
|
|
9209
|
+
def.required && /* @__PURE__ */ jsx("span", { className: "text-red-500", children: "*" }),
|
|
9210
|
+
/* @__PURE__ */ jsxs("span", { className: "ml-2 text-muted-foreground font-normal tabular-nums", children: [
|
|
9211
|
+
num,
|
|
9212
|
+
"/",
|
|
9213
|
+
max
|
|
9214
|
+
] })
|
|
9215
|
+
] });
|
|
9216
|
+
const labelEl = theme ? /* @__PURE__ */ jsx(Label, { className: labelClass, children: labelContent }) : /* @__PURE__ */ jsx(Label, { children: labelContent });
|
|
9217
|
+
return /* @__PURE__ */ jsxs("div", { className: wrapperClass, children: [
|
|
9218
|
+
labelEl,
|
|
9219
|
+
/* @__PURE__ */ jsx(
|
|
9220
|
+
Slider,
|
|
9041
9221
|
{
|
|
9042
|
-
|
|
9043
|
-
|
|
9044
|
-
|
|
9045
|
-
|
|
9046
|
-
|
|
9047
|
-
|
|
9048
|
-
|
|
9222
|
+
className: cn("py-1", showError && "opacity-90 ring-1 ring-red-500 rounded"),
|
|
9223
|
+
disabled,
|
|
9224
|
+
min,
|
|
9225
|
+
max,
|
|
9226
|
+
step,
|
|
9227
|
+
value: [num],
|
|
9228
|
+
onValueChange: (v) => {
|
|
9229
|
+
const n = v[0] ?? min;
|
|
9230
|
+
setValue(n);
|
|
9231
|
+
setTouched();
|
|
9232
|
+
}
|
|
9049
9233
|
}
|
|
9050
9234
|
),
|
|
9051
|
-
|
|
9235
|
+
showError && /* @__PURE__ */ jsx("p", { className: "text-xs text-red-500", children: error })
|
|
9052
9236
|
] });
|
|
9053
9237
|
};
|
|
9054
|
-
var
|
|
9055
|
-
|
|
9056
|
-
label,
|
|
9057
|
-
|
|
9058
|
-
|
|
9059
|
-
|
|
9060
|
-
|
|
9061
|
-
|
|
9062
|
-
|
|
9063
|
-
}
|
|
9064
|
-
|
|
9065
|
-
|
|
9066
|
-
|
|
9238
|
+
var CHIEF_CHIPS_FIELD = "chief_complaints_chips";
|
|
9239
|
+
var SWELLING_OPTS = [
|
|
9240
|
+
{ value: "reducible_hernia", label: "Reducible (hernia)" },
|
|
9241
|
+
{ value: "cough_impulse", label: "Cough impulse" },
|
|
9242
|
+
{ value: "skin_changes", label: "Skin changes" }
|
|
9243
|
+
];
|
|
9244
|
+
var GI_OPTS = [
|
|
9245
|
+
{ value: "bleeding_pr", label: "Bleeding PR" },
|
|
9246
|
+
{ value: "vomiting", label: "Vomiting" },
|
|
9247
|
+
{ value: "haematemesis", label: "Haematemesis" }
|
|
9248
|
+
];
|
|
9249
|
+
var BREAST_OPTS = [
|
|
9250
|
+
{ value: "pain", label: "Pain" },
|
|
9251
|
+
{ value: "fh_ca_breast", label: "Family history of Ca breast" }
|
|
9252
|
+
];
|
|
9253
|
+
var ANO_OPTS = [
|
|
9254
|
+
{ value: "pain_defecation", label: "Pain during defecation" },
|
|
9255
|
+
{ value: "bleeding", label: "Bleeding" },
|
|
9256
|
+
{ value: "constipation", label: "Constipation" },
|
|
9257
|
+
{ value: "discharge", label: "Discharge" }
|
|
9258
|
+
];
|
|
9259
|
+
var THYROID_OPTS = [
|
|
9260
|
+
{ value: "dysphagia", label: "Dysphagia" },
|
|
9261
|
+
{ value: "voice_change", label: "Voice change" },
|
|
9262
|
+
{ value: "thyrotoxicosis", label: "Thyrotoxicosis symptoms" }
|
|
9263
|
+
];
|
|
9264
|
+
var SOCRATES_KEYS = [
|
|
9265
|
+
"site",
|
|
9266
|
+
"onset",
|
|
9267
|
+
"character",
|
|
9268
|
+
"radiation",
|
|
9269
|
+
"associated",
|
|
9270
|
+
"timing",
|
|
9271
|
+
"exacerbating"
|
|
9272
|
+
];
|
|
9273
|
+
function Panel({ title, children }) {
|
|
9274
|
+
return /* @__PURE__ */ jsxs("div", { className: "overflow-hidden rounded-md border border-[#D0D0D0] bg-white", children: [
|
|
9275
|
+
/* @__PURE__ */ jsx("div", { className: "border-b border-[#D0D0D0] bg-[#FEE8EC]/50 px-3 py-1.5 text-xs font-semibold text-slate-700", children: title }),
|
|
9276
|
+
/* @__PURE__ */ jsx("div", { className: "p-3", children })
|
|
9067
9277
|
] });
|
|
9068
|
-
}
|
|
9069
|
-
|
|
9070
|
-
const
|
|
9071
|
-
|
|
9072
|
-
|
|
9073
|
-
|
|
9074
|
-
|
|
9075
|
-
|
|
9076
|
-
|
|
9077
|
-
|
|
9078
|
-
|
|
9079
|
-
|
|
9080
|
-
|
|
9081
|
-
|
|
9082
|
-
|
|
9083
|
-
|
|
9278
|
+
}
|
|
9279
|
+
function chipList(state) {
|
|
9280
|
+
const raw = state.values[CHIEF_CHIPS_FIELD];
|
|
9281
|
+
return Array.isArray(raw) ? raw.filter((x) => typeof x === "string") : [];
|
|
9282
|
+
}
|
|
9283
|
+
var GsSmartHistoryWidget = ({ fieldId }) => {
|
|
9284
|
+
const { fieldDef, value, setValue, setTouched, error, touched, disabled } = useField(fieldId);
|
|
9285
|
+
const { state } = useForm();
|
|
9286
|
+
const showError = !!error && (touched || state.submitAttempted);
|
|
9287
|
+
const safe = useMemo(() => normalizeGeneralSurgerySmartHistory(value), [value]);
|
|
9288
|
+
const chips = useMemo(() => chipList(state), [state]);
|
|
9289
|
+
const showPain = chips.includes("pain");
|
|
9290
|
+
const showSwelling = chips.includes("swelling_lump");
|
|
9291
|
+
const showGI = chips.includes("bleeding") || chips.includes("obstruction");
|
|
9292
|
+
const showBreast = chips.includes("breast");
|
|
9293
|
+
const showAno = chips.includes("anorectal");
|
|
9294
|
+
const showThyroid = chips.includes("thyroid");
|
|
9295
|
+
const update = (next) => {
|
|
9296
|
+
setValue(next);
|
|
9297
|
+
setTouched();
|
|
9298
|
+
};
|
|
9299
|
+
const setPain = (key, v) => {
|
|
9300
|
+
if (key === "severity") {
|
|
9301
|
+
const n = typeof v === "number" ? v : Number(v);
|
|
9302
|
+
const sev = Number.isFinite(n) ? Math.min(10, Math.max(0, Math.round(n))) : 0;
|
|
9303
|
+
update({ ...safe, pain: { ...safe.pain, severity: sev } });
|
|
9304
|
+
return;
|
|
9305
|
+
}
|
|
9306
|
+
update({ ...safe, pain: { ...safe.pain, [key]: String(v) } });
|
|
9307
|
+
};
|
|
9308
|
+
const toggleArr = (section, val) => {
|
|
9309
|
+
if (section === "swelling") {
|
|
9310
|
+
const a = safe.swelling.checks;
|
|
9311
|
+
const next = a.includes(val) ? a.filter((x) => x !== val) : [...a, val];
|
|
9312
|
+
update({ ...safe, swelling: { ...safe.swelling, checks: next } });
|
|
9313
|
+
} else if (section === "gi") {
|
|
9314
|
+
const a = safe.gi.checks;
|
|
9315
|
+
const next = a.includes(val) ? a.filter((x) => x !== val) : [...a, val];
|
|
9316
|
+
update({ ...safe, gi: { ...safe.gi, checks: next } });
|
|
9317
|
+
} else if (section === "breast") {
|
|
9318
|
+
const a = safe.breast.checks;
|
|
9319
|
+
const next = a.includes(val) ? a.filter((x) => x !== val) : [...a, val];
|
|
9320
|
+
update({ ...safe, breast: { ...safe.breast, checks: next } });
|
|
9321
|
+
} else if (section === "ano") {
|
|
9322
|
+
const a = safe.ano.checks;
|
|
9323
|
+
const next = a.includes(val) ? a.filter((x) => x !== val) : [...a, val];
|
|
9324
|
+
update({ ...safe, ano: { ...safe.ano, checks: next } });
|
|
9325
|
+
} else {
|
|
9326
|
+
const a = safe.thyroid.checks;
|
|
9327
|
+
const next = a.includes(val) ? a.filter((x) => x !== val) : [...a, val];
|
|
9328
|
+
update({ ...safe, thyroid: { ...safe.thyroid, checks: next } });
|
|
9329
|
+
}
|
|
9330
|
+
};
|
|
9331
|
+
if (!fieldDef) return null;
|
|
9332
|
+
const theme = getThemeConfig("textarea", fieldDef.theme);
|
|
9333
|
+
const wrapperClass = theme?.wrapperClassName ?? "rounded-md overflow-hidden flex flex-col border border-[#D0D0D0]";
|
|
9334
|
+
const labelClass = theme?.labelClassName;
|
|
9335
|
+
const labelContent = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
9336
|
+
fieldDef.label,
|
|
9337
|
+
fieldDef.required ? /* @__PURE__ */ jsx("span", { className: "ml-1 text-red-500", children: "*" }) : null
|
|
9338
|
+
] });
|
|
9339
|
+
const labelEl = theme ? /* @__PURE__ */ jsx(Label, { className: labelClass, children: labelContent }) : /* @__PURE__ */ jsx(Label, { className: "text-sm font-medium", children: labelContent });
|
|
9340
|
+
const bodyClass = cn(
|
|
9341
|
+
"-mt-1 flex min-w-0 flex-col gap-3 border-t border-[#D0D0D0] bg-white px-3 py-3",
|
|
9342
|
+
disabled && "pointer-events-none opacity-60"
|
|
9343
|
+
);
|
|
9344
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("w-full min-w-0", wrapperClass), children: [
|
|
9345
|
+
labelEl,
|
|
9346
|
+
/* @__PURE__ */ jsxs("div", { className: bodyClass, children: [
|
|
9347
|
+
showPain ? /* @__PURE__ */ jsx(Panel, { title: "SOCRATES \u2014 pain", children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2 md:grid-cols-4", children: [
|
|
9348
|
+
SOCRATES_KEYS.map((k) => /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
9349
|
+
/* @__PURE__ */ jsx("span", { className: "text-[10px] font-medium uppercase tracking-wide text-muted-foreground", children: k }),
|
|
9350
|
+
/* @__PURE__ */ jsx(
|
|
9351
|
+
Input,
|
|
9352
|
+
{
|
|
9353
|
+
className: "h-8 text-xs",
|
|
9354
|
+
value: safe.pain[k],
|
|
9355
|
+
onChange: (e) => setPain(k, e.target.value),
|
|
9356
|
+
disabled
|
|
9357
|
+
}
|
|
9358
|
+
)
|
|
9359
|
+
] }, k)),
|
|
9360
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
9361
|
+
/* @__PURE__ */ jsx("span", { className: "text-[10px] font-medium uppercase tracking-wide text-muted-foreground", children: "Severity 0\u201310" }),
|
|
9362
|
+
/* @__PURE__ */ jsx(
|
|
9363
|
+
Input,
|
|
9364
|
+
{
|
|
9365
|
+
type: "number",
|
|
9366
|
+
min: 0,
|
|
9367
|
+
max: 10,
|
|
9368
|
+
className: "h-8 text-xs",
|
|
9369
|
+
value: safe.pain.severity,
|
|
9370
|
+
onChange: (e) => setPain("severity", e.target.value),
|
|
9371
|
+
disabled
|
|
9372
|
+
}
|
|
9373
|
+
)
|
|
9374
|
+
] })
|
|
9375
|
+
] }) }) : null,
|
|
9376
|
+
showSwelling ? /* @__PURE__ */ jsxs(Panel, { title: "Swelling history", children: [
|
|
9377
|
+
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-3 text-xs md:grid-cols-3", children: [
|
|
9378
|
+
/* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
|
|
9379
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium", children: "Duration" }),
|
|
9380
|
+
/* @__PURE__ */ jsx(
|
|
9381
|
+
Input,
|
|
9382
|
+
{
|
|
9383
|
+
className: "h-8 text-xs",
|
|
9384
|
+
value: safe.swelling.duration,
|
|
9385
|
+
onChange: (e) => update({ ...safe, swelling: { ...safe.swelling, duration: e.target.value } }),
|
|
9386
|
+
disabled
|
|
9387
|
+
}
|
|
9388
|
+
)
|
|
9389
|
+
] }),
|
|
9390
|
+
/* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
|
|
9391
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium", children: "Size progression" }),
|
|
9392
|
+
/* @__PURE__ */ jsx(
|
|
9393
|
+
Input,
|
|
9394
|
+
{
|
|
9395
|
+
className: "h-8 text-xs",
|
|
9396
|
+
value: safe.swelling.sizeProgression,
|
|
9397
|
+
onChange: (e) => update({ ...safe, swelling: { ...safe.swelling, sizeProgression: e.target.value } }),
|
|
9398
|
+
disabled
|
|
9399
|
+
}
|
|
9400
|
+
)
|
|
9401
|
+
] }),
|
|
9402
|
+
/* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
|
|
9403
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium", children: "Painful / painless" }),
|
|
9404
|
+
/* @__PURE__ */ jsx(
|
|
9405
|
+
Input,
|
|
9406
|
+
{
|
|
9407
|
+
className: "h-8 text-xs",
|
|
9408
|
+
value: safe.swelling.painfulPainless,
|
|
9409
|
+
onChange: (e) => update({ ...safe, swelling: { ...safe.swelling, painfulPainless: e.target.value } }),
|
|
9410
|
+
disabled
|
|
9411
|
+
}
|
|
9412
|
+
)
|
|
9413
|
+
] })
|
|
9414
|
+
] }),
|
|
9415
|
+
/* @__PURE__ */ jsx("div", { className: "mt-3 flex flex-wrap gap-x-4 gap-y-2", children: SWELLING_OPTS.map((o) => /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 text-xs", children: [
|
|
9416
|
+
/* @__PURE__ */ jsx(
|
|
9417
|
+
Checkbox,
|
|
9418
|
+
{
|
|
9419
|
+
checked: safe.swelling.checks.includes(o.value),
|
|
9420
|
+
onCheckedChange: () => toggleArr("swelling", o.value),
|
|
9421
|
+
disabled
|
|
9422
|
+
}
|
|
9423
|
+
),
|
|
9424
|
+
o.label
|
|
9425
|
+
] }, o.value)) })
|
|
9426
|
+
] }) : null,
|
|
9427
|
+
showGI ? /* @__PURE__ */ jsxs(Panel, { title: "GI history", children: [
|
|
9428
|
+
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-2 text-xs md:grid-cols-3", children: [
|
|
9429
|
+
/* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
|
|
9430
|
+
"Appetite",
|
|
9431
|
+
/* @__PURE__ */ jsx(
|
|
9432
|
+
Input,
|
|
9433
|
+
{
|
|
9434
|
+
className: "h-8 text-xs",
|
|
9435
|
+
value: safe.gi.appetite,
|
|
9436
|
+
onChange: (e) => update({ ...safe, gi: { ...safe.gi, appetite: e.target.value } }),
|
|
9437
|
+
disabled
|
|
9438
|
+
}
|
|
9439
|
+
)
|
|
9440
|
+
] }),
|
|
9441
|
+
/* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
|
|
9442
|
+
"Weight loss",
|
|
9443
|
+
/* @__PURE__ */ jsx(
|
|
9444
|
+
Input,
|
|
9445
|
+
{
|
|
9446
|
+
className: "h-8 text-xs",
|
|
9447
|
+
value: safe.gi.weightLoss,
|
|
9448
|
+
onChange: (e) => update({ ...safe, gi: { ...safe.gi, weightLoss: e.target.value } }),
|
|
9449
|
+
disabled
|
|
9450
|
+
}
|
|
9451
|
+
)
|
|
9452
|
+
] }),
|
|
9453
|
+
/* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
|
|
9454
|
+
"Bowel habits",
|
|
9455
|
+
/* @__PURE__ */ jsx(
|
|
9456
|
+
Input,
|
|
9457
|
+
{
|
|
9458
|
+
className: "h-8 text-xs",
|
|
9459
|
+
value: safe.gi.bowelHabits,
|
|
9460
|
+
onChange: (e) => update({ ...safe, gi: { ...safe.gi, bowelHabits: e.target.value } }),
|
|
9461
|
+
disabled
|
|
9462
|
+
}
|
|
9463
|
+
)
|
|
9464
|
+
] })
|
|
9465
|
+
] }),
|
|
9466
|
+
/* @__PURE__ */ jsx("div", { className: "mt-3 flex flex-wrap gap-x-4 gap-y-2", children: GI_OPTS.map((o) => /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 text-xs", children: [
|
|
9467
|
+
/* @__PURE__ */ jsx(
|
|
9468
|
+
Checkbox,
|
|
9469
|
+
{
|
|
9470
|
+
checked: safe.gi.checks.includes(o.value),
|
|
9471
|
+
onCheckedChange: () => toggleArr("gi", o.value),
|
|
9472
|
+
disabled
|
|
9473
|
+
}
|
|
9474
|
+
),
|
|
9475
|
+
o.label
|
|
9476
|
+
] }, o.value)) })
|
|
9477
|
+
] }) : null,
|
|
9478
|
+
showBreast ? /* @__PURE__ */ jsxs(Panel, { title: "Breast history", children: [
|
|
9479
|
+
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-2 text-xs md:grid-cols-2", children: [
|
|
9480
|
+
/* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
|
|
9481
|
+
"Lump duration",
|
|
9482
|
+
/* @__PURE__ */ jsx(
|
|
9483
|
+
Input,
|
|
9484
|
+
{
|
|
9485
|
+
className: "h-8 text-xs",
|
|
9486
|
+
value: safe.breast.lumpDuration,
|
|
9487
|
+
onChange: (e) => update({ ...safe, breast: { ...safe.breast, lumpDuration: e.target.value } }),
|
|
9488
|
+
disabled
|
|
9489
|
+
}
|
|
9490
|
+
)
|
|
9491
|
+
] }),
|
|
9492
|
+
/* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
|
|
9493
|
+
"Nipple discharge",
|
|
9494
|
+
/* @__PURE__ */ jsx(
|
|
9495
|
+
Input,
|
|
9496
|
+
{
|
|
9497
|
+
className: "h-8 text-xs",
|
|
9498
|
+
value: safe.breast.nippleDischarge,
|
|
9499
|
+
onChange: (e) => update({ ...safe, breast: { ...safe.breast, nippleDischarge: e.target.value } }),
|
|
9500
|
+
disabled
|
|
9501
|
+
}
|
|
9502
|
+
)
|
|
9503
|
+
] })
|
|
9504
|
+
] }),
|
|
9505
|
+
/* @__PURE__ */ jsx("div", { className: "mt-3 flex flex-wrap gap-x-4 gap-y-2", children: BREAST_OPTS.map((o) => /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 text-xs", children: [
|
|
9506
|
+
/* @__PURE__ */ jsx(
|
|
9507
|
+
Checkbox,
|
|
9508
|
+
{
|
|
9509
|
+
checked: safe.breast.checks.includes(o.value),
|
|
9510
|
+
onCheckedChange: () => toggleArr("breast", o.value),
|
|
9511
|
+
disabled
|
|
9512
|
+
}
|
|
9513
|
+
),
|
|
9514
|
+
o.label
|
|
9515
|
+
] }, o.value)) })
|
|
9516
|
+
] }) : null,
|
|
9517
|
+
showAno ? /* @__PURE__ */ jsx(Panel, { title: "Anorectal history", children: /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 gap-2 text-xs md:grid-cols-2", children: ANO_OPTS.map((o) => /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
|
|
9518
|
+
/* @__PURE__ */ jsx(
|
|
9519
|
+
Checkbox,
|
|
9520
|
+
{
|
|
9521
|
+
checked: safe.ano.checks.includes(o.value),
|
|
9522
|
+
onCheckedChange: () => toggleArr("ano", o.value),
|
|
9523
|
+
disabled
|
|
9524
|
+
}
|
|
9525
|
+
),
|
|
9526
|
+
o.label
|
|
9527
|
+
] }, o.value)) }) }) : null,
|
|
9528
|
+
showThyroid ? /* @__PURE__ */ jsxs(Panel, { title: "Thyroid history", children: [
|
|
9529
|
+
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 gap-2 text-xs md:grid-cols-2", children: /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1 md:col-span-2", children: [
|
|
9530
|
+
"Swelling duration",
|
|
9531
|
+
/* @__PURE__ */ jsx(
|
|
9532
|
+
Input,
|
|
9533
|
+
{
|
|
9534
|
+
className: "h-8 text-xs",
|
|
9535
|
+
value: safe.thyroid.swellingDuration,
|
|
9536
|
+
onChange: (e) => update({ ...safe, thyroid: { ...safe.thyroid, swellingDuration: e.target.value } }),
|
|
9537
|
+
disabled
|
|
9538
|
+
}
|
|
9539
|
+
)
|
|
9540
|
+
] }) }),
|
|
9541
|
+
/* @__PURE__ */ jsx("div", { className: "mt-3 flex flex-wrap gap-x-4 gap-y-2", children: THYROID_OPTS.map((o) => /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 text-xs", children: [
|
|
9542
|
+
/* @__PURE__ */ jsx(
|
|
9543
|
+
Checkbox,
|
|
9544
|
+
{
|
|
9545
|
+
checked: safe.thyroid.checks.includes(o.value),
|
|
9546
|
+
onCheckedChange: () => toggleArr("thyroid", o.value),
|
|
9547
|
+
disabled
|
|
9548
|
+
}
|
|
9549
|
+
),
|
|
9550
|
+
o.label
|
|
9551
|
+
] }, o.value)) })
|
|
9552
|
+
] }) : null,
|
|
9553
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
9554
|
+
/* @__PURE__ */ jsx(Label, { className: "text-xs font-medium text-slate-700", children: "Systemic surgical screening" }),
|
|
9555
|
+
/* @__PURE__ */ jsx(
|
|
9556
|
+
Textarea,
|
|
9557
|
+
{
|
|
9558
|
+
className: "min-h-[72px] rounded-md border border-input bg-white text-sm",
|
|
9559
|
+
placeholder: "Fever, weight loss, appetite loss, fatigue, malignancy red flags\u2026",
|
|
9560
|
+
value: safe.systemic,
|
|
9561
|
+
onChange: (e) => update({ ...safe, systemic: e.target.value }),
|
|
9562
|
+
disabled
|
|
9563
|
+
}
|
|
9564
|
+
)
|
|
9565
|
+
] })
|
|
9566
|
+
] }),
|
|
9567
|
+
showError ? /* @__PURE__ */ jsx("p", { className: "px-3 pb-2 text-xs text-red-500", children: error }) : null
|
|
9568
|
+
] });
|
|
9569
|
+
};
|
|
9570
|
+
var GS_CLINICAL_EXAMINATION_FIELD = "clinical_examination";
|
|
9571
|
+
var GENERAL = [
|
|
9572
|
+
{ value: "pallor", label: "Pallor" },
|
|
9573
|
+
{ value: "icterus", label: "Icterus" },
|
|
9574
|
+
{ value: "cyanosis", label: "Cyanosis" },
|
|
9575
|
+
{ value: "clubbing", label: "Clubbing" },
|
|
9576
|
+
{ value: "lymphadenopathy", label: "Lymphadenopathy" },
|
|
9577
|
+
{ value: "oedema", label: "Oedema" }
|
|
9578
|
+
];
|
|
9579
|
+
var REGIONS = [
|
|
9580
|
+
{ key: "abdomen", label: "Abdomen" },
|
|
9581
|
+
{ key: "hernia", label: "Hernia" },
|
|
9582
|
+
{ key: "breast", label: "Breast" },
|
|
9583
|
+
{ key: "thyroid", label: "Thyroid" },
|
|
9584
|
+
{ key: "anorectal", label: "Anorectal" },
|
|
9585
|
+
{ key: "limb", label: "Limb / varicose" }
|
|
9586
|
+
];
|
|
9587
|
+
var ABD_INSP = [
|
|
9588
|
+
{ value: "distension", label: "Distension" },
|
|
9589
|
+
{ value: "scars", label: "Scars" },
|
|
9590
|
+
{ value: "visible_peristalsis", label: "Visible peristalsis" }
|
|
9591
|
+
];
|
|
9592
|
+
var ABD_PALP = [
|
|
9593
|
+
{ value: "tenderness", label: "Tenderness" },
|
|
9594
|
+
{ value: "guarding", label: "Guarding" },
|
|
9595
|
+
{ value: "rigidity", label: "Rigidity" },
|
|
9596
|
+
{ value: "mass", label: "Palpable mass" }
|
|
9597
|
+
];
|
|
9598
|
+
var ABD_PERC = [
|
|
9599
|
+
{ value: "tympany", label: "Tympany" },
|
|
9600
|
+
{ value: "shifting_dullness", label: "Shifting dullness" }
|
|
9601
|
+
];
|
|
9602
|
+
function SubGroup({ title, children }) {
|
|
9603
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
9604
|
+
/* @__PURE__ */ jsx("p", { className: "text-[11px] font-semibold uppercase tracking-wide text-muted-foreground", children: title }),
|
|
9605
|
+
/* @__PURE__ */ jsx("div", { className: "space-y-2", children })
|
|
9606
|
+
] });
|
|
9607
|
+
}
|
|
9608
|
+
function RegionCard({ title, children }) {
|
|
9609
|
+
return /* @__PURE__ */ jsxs("div", { className: "overflow-hidden rounded-md border border-[#D0D0D0] bg-white", children: [
|
|
9610
|
+
/* @__PURE__ */ jsx("div", { className: "border-b border-[#D0D0D0] bg-[#FEE8EC]/50 px-3 py-1.5 text-xs font-semibold text-slate-700", children: title }),
|
|
9611
|
+
/* @__PURE__ */ jsx("div", { className: "p-3", children })
|
|
9612
|
+
] });
|
|
9613
|
+
}
|
|
9614
|
+
var GsExaminationWidget = ({ fieldId }) => {
|
|
9615
|
+
const { fieldDef, value, setValue, setTouched, error, touched, disabled } = useField(fieldId);
|
|
9616
|
+
const clinicalField = useField(GS_CLINICAL_EXAMINATION_FIELD);
|
|
9617
|
+
const { state } = useForm();
|
|
9618
|
+
const showError = !!error && (touched || state.submitAttempted);
|
|
9619
|
+
const safe = useMemo(() => normalizeGeneralSurgeryExamination(value), [value]);
|
|
9620
|
+
const update = (next) => {
|
|
9621
|
+
setValue(next);
|
|
9622
|
+
setTouched();
|
|
9623
|
+
};
|
|
9624
|
+
const toggleIn = (arr, val) => arr.includes(val) ? arr.filter((x) => x !== val) : [...arr, val];
|
|
9625
|
+
const toggleGeneral = (val) => {
|
|
9626
|
+
update({ ...safe, general: toggleIn(safe.general, val) });
|
|
9627
|
+
};
|
|
9628
|
+
const toggleRegion = (key) => {
|
|
9629
|
+
update({ ...safe, regions: toggleIn(safe.regions, key) });
|
|
9630
|
+
};
|
|
9631
|
+
const toggleAbd = (key, val) => {
|
|
9632
|
+
update({
|
|
9633
|
+
...safe,
|
|
9634
|
+
abdomen: { ...safe.abdomen, [key]: toggleIn(safe.abdomen[key], val) }
|
|
9635
|
+
});
|
|
9636
|
+
};
|
|
9637
|
+
if (!fieldDef) return null;
|
|
9638
|
+
const has = (r) => safe.regions.includes(r);
|
|
9639
|
+
const theme = getThemeConfig("textarea", fieldDef.theme);
|
|
9640
|
+
const wrapperClass = theme?.wrapperClassName ?? "rounded-md overflow-hidden flex flex-col border border-[#D0D0D0]";
|
|
9641
|
+
const labelClass = theme?.labelClassName;
|
|
9642
|
+
const labelContent = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
9643
|
+
fieldDef.label,
|
|
9644
|
+
fieldDef.required ? /* @__PURE__ */ jsx("span", { className: "ml-1 text-red-500", children: "*" }) : null
|
|
9645
|
+
] });
|
|
9646
|
+
const labelEl = theme ? /* @__PURE__ */ jsx(Label, { className: labelClass, children: labelContent }) : /* @__PURE__ */ jsx(Label, { className: "text-sm font-medium", children: labelContent });
|
|
9647
|
+
const bodyClass = cn(
|
|
9648
|
+
"-mt-1 flex min-w-0 flex-col gap-3 border-t border-[#D0D0D0] bg-white px-3 py-3",
|
|
9649
|
+
disabled && "pointer-events-none opacity-60"
|
|
9650
|
+
);
|
|
9651
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("w-full min-w-0", wrapperClass), children: [
|
|
9652
|
+
labelEl,
|
|
9653
|
+
/* @__PURE__ */ jsxs("div", { className: bodyClass, children: [
|
|
9654
|
+
/* @__PURE__ */ jsxs("div", { className: "overflow-hidden rounded-md border border-[#D0D0D0] bg-white", children: [
|
|
9655
|
+
/* @__PURE__ */ 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" }),
|
|
9656
|
+
/* @__PURE__ */ jsx("div", { className: "p-3", children: /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 gap-2 text-xs md:grid-cols-3 lg:grid-cols-6", children: GENERAL.map((g) => /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
|
|
9657
|
+
/* @__PURE__ */ jsx(
|
|
9658
|
+
Checkbox,
|
|
9659
|
+
{
|
|
9660
|
+
checked: safe.general.includes(g.value),
|
|
9661
|
+
onCheckedChange: () => toggleGeneral(g.value),
|
|
9662
|
+
disabled
|
|
9663
|
+
}
|
|
9664
|
+
),
|
|
9665
|
+
g.label
|
|
9666
|
+
] }, g.value)) }) })
|
|
9667
|
+
] }),
|
|
9668
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
9669
|
+
/* @__PURE__ */ jsx("p", { className: "mb-2 text-xs font-semibold text-slate-700", children: "Regional examination \u2014 select region(s)" }),
|
|
9670
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2", children: REGIONS.map((r) => {
|
|
9671
|
+
const on = safe.regions.includes(r.key);
|
|
9672
|
+
return /* @__PURE__ */ jsx(
|
|
9673
|
+
Button,
|
|
9674
|
+
{
|
|
9675
|
+
type: "button",
|
|
9676
|
+
size: "sm",
|
|
9677
|
+
variant: on ? "default" : "outline",
|
|
9678
|
+
className: "h-7 rounded-full px-3 text-xs",
|
|
9679
|
+
onClick: () => toggleRegion(r.key),
|
|
9680
|
+
disabled,
|
|
9681
|
+
children: r.label
|
|
9682
|
+
},
|
|
9683
|
+
r.key
|
|
9684
|
+
);
|
|
9685
|
+
}) })
|
|
9686
|
+
] }),
|
|
9687
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
9688
|
+
has("abdomen") ? /* @__PURE__ */ jsx(RegionCard, { title: "Abdomen \u2014 inspection \xB7 palpation \xB7 percussion \xB7 auscultation", children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-4", children: [
|
|
9689
|
+
/* @__PURE__ */ jsx(SubGroup, { title: "Inspection", children: ABD_INSP.map((o) => /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 text-xs", children: [
|
|
9690
|
+
/* @__PURE__ */ jsx(
|
|
9691
|
+
Checkbox,
|
|
9692
|
+
{
|
|
9693
|
+
checked: safe.abdomen.inspection.includes(o.value),
|
|
9694
|
+
onCheckedChange: () => toggleAbd("inspection", o.value),
|
|
9695
|
+
disabled
|
|
9696
|
+
}
|
|
9697
|
+
),
|
|
9698
|
+
o.label
|
|
9699
|
+
] }, o.value)) }),
|
|
9700
|
+
/* @__PURE__ */ jsxs(SubGroup, { title: "Palpation", children: [
|
|
9701
|
+
ABD_PALP.map((o) => /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 text-xs", children: [
|
|
9702
|
+
/* @__PURE__ */ jsx(
|
|
9703
|
+
Checkbox,
|
|
9704
|
+
{
|
|
9705
|
+
checked: safe.abdomen.palpation.includes(o.value),
|
|
9706
|
+
onCheckedChange: () => toggleAbd("palpation", o.value),
|
|
9707
|
+
disabled
|
|
9708
|
+
}
|
|
9709
|
+
),
|
|
9710
|
+
o.label
|
|
9711
|
+
] }, o.value)),
|
|
9712
|
+
/* @__PURE__ */ jsxs("label", { className: "mt-2 block text-xs", children: [
|
|
9713
|
+
/* @__PURE__ */ jsx("span", { className: "mb-1 block font-medium", children: "Mass size / mobility" }),
|
|
9714
|
+
/* @__PURE__ */ jsx(
|
|
9715
|
+
Input,
|
|
9716
|
+
{
|
|
9717
|
+
className: "h-8 text-xs",
|
|
9718
|
+
value: safe.abdomen.massNotes,
|
|
9719
|
+
onChange: (e) => update({ ...safe, abdomen: { ...safe.abdomen, massNotes: e.target.value } }),
|
|
9720
|
+
disabled
|
|
9721
|
+
}
|
|
9722
|
+
)
|
|
9723
|
+
] })
|
|
9724
|
+
] }),
|
|
9725
|
+
/* @__PURE__ */ jsx(SubGroup, { title: "Percussion", children: ABD_PERC.map((o) => /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 text-xs", children: [
|
|
9726
|
+
/* @__PURE__ */ jsx(
|
|
9727
|
+
Checkbox,
|
|
9728
|
+
{
|
|
9729
|
+
checked: safe.abdomen.percussion.includes(o.value),
|
|
9730
|
+
onCheckedChange: () => toggleAbd("percussion", o.value),
|
|
9731
|
+
disabled
|
|
9732
|
+
}
|
|
9733
|
+
),
|
|
9734
|
+
o.label
|
|
9735
|
+
] }, o.value)) }),
|
|
9736
|
+
/* @__PURE__ */ jsxs(SubGroup, { title: "Auscultation", children: [
|
|
9737
|
+
/* @__PURE__ */ jsx("span", { className: "mb-1 block text-xs font-medium", children: "Bowel sounds" }),
|
|
9738
|
+
/* @__PURE__ */ jsxs(
|
|
9739
|
+
Select,
|
|
9740
|
+
{
|
|
9741
|
+
value: safe.abdomen.bowelSounds,
|
|
9742
|
+
onValueChange: (val) => update({
|
|
9743
|
+
...safe,
|
|
9744
|
+
abdomen: {
|
|
9745
|
+
...safe.abdomen,
|
|
9746
|
+
bowelSounds: val
|
|
9747
|
+
}
|
|
9748
|
+
}),
|
|
9749
|
+
disabled,
|
|
9750
|
+
children: [
|
|
9751
|
+
/* @__PURE__ */ jsx(SelectTrigger, { className: "h-8 text-xs", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Select\u2026" }) }),
|
|
9752
|
+
/* @__PURE__ */ jsxs(SelectContent, { children: [
|
|
9753
|
+
/* @__PURE__ */ jsx(SelectItem, { value: "none", children: "\u2014" }),
|
|
9754
|
+
/* @__PURE__ */ jsx(SelectItem, { value: "normal", children: "Normal" }),
|
|
9755
|
+
/* @__PURE__ */ jsx(SelectItem, { value: "up", children: "\u2191" }),
|
|
9756
|
+
/* @__PURE__ */ jsx(SelectItem, { value: "down", children: "\u2193" }),
|
|
9757
|
+
/* @__PURE__ */ jsx(SelectItem, { value: "absent", children: "Absent" })
|
|
9758
|
+
] })
|
|
9759
|
+
]
|
|
9760
|
+
}
|
|
9761
|
+
)
|
|
9762
|
+
] })
|
|
9763
|
+
] }) }) : null,
|
|
9764
|
+
has("hernia") ? /* @__PURE__ */ jsx(RegionCard, { title: "Hernia exam", children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-3 text-xs md:grid-cols-4", children: [
|
|
9765
|
+
/* @__PURE__ */ jsxs("label", { className: "block", children: [
|
|
9766
|
+
/* @__PURE__ */ jsx("span", { className: "mb-1 block font-medium", children: "Site" }),
|
|
9767
|
+
/* @__PURE__ */ jsx(
|
|
9768
|
+
Input,
|
|
9769
|
+
{
|
|
9770
|
+
className: "h-8 text-xs",
|
|
9771
|
+
value: safe.hernia.site,
|
|
9772
|
+
onChange: (e) => update({ ...safe, hernia: { ...safe.hernia, site: e.target.value } }),
|
|
9773
|
+
disabled
|
|
9774
|
+
}
|
|
9775
|
+
)
|
|
9776
|
+
] }),
|
|
9777
|
+
/* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
|
|
9778
|
+
/* @__PURE__ */ jsx(
|
|
9779
|
+
Checkbox,
|
|
9780
|
+
{
|
|
9781
|
+
checked: safe.hernia.reducible,
|
|
9782
|
+
onCheckedChange: (c) => update({ ...safe, hernia: { ...safe.hernia, reducible: c === true } }),
|
|
9783
|
+
disabled
|
|
9784
|
+
}
|
|
9785
|
+
),
|
|
9786
|
+
"Reducible"
|
|
9787
|
+
] }),
|
|
9788
|
+
/* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
|
|
9789
|
+
/* @__PURE__ */ jsx(
|
|
9790
|
+
Checkbox,
|
|
9791
|
+
{
|
|
9792
|
+
checked: safe.hernia.coughImpulse,
|
|
9793
|
+
onCheckedChange: (c) => update({ ...safe, hernia: { ...safe.hernia, coughImpulse: c === true } }),
|
|
9794
|
+
disabled
|
|
9795
|
+
}
|
|
9796
|
+
),
|
|
9797
|
+
"Cough impulse"
|
|
9798
|
+
] }),
|
|
9799
|
+
/* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
|
|
9800
|
+
/* @__PURE__ */ jsx(
|
|
9801
|
+
Checkbox,
|
|
9802
|
+
{
|
|
9803
|
+
checked: safe.hernia.tenderness,
|
|
9804
|
+
onCheckedChange: (c) => update({ ...safe, hernia: { ...safe.hernia, tenderness: c === true } }),
|
|
9805
|
+
disabled
|
|
9806
|
+
}
|
|
9807
|
+
),
|
|
9808
|
+
"Tenderness"
|
|
9809
|
+
] })
|
|
9810
|
+
] }) }) : null,
|
|
9811
|
+
has("breast") ? /* @__PURE__ */ jsx(RegionCard, { title: "Breast exam", children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-3 text-xs md:grid-cols-4", children: [
|
|
9812
|
+
/* @__PURE__ */ jsxs("label", { className: "block", children: [
|
|
9813
|
+
/* @__PURE__ */ jsx("span", { className: "mb-1 block font-medium", children: "Lump size (cm)" }),
|
|
9814
|
+
/* @__PURE__ */ jsx(
|
|
9815
|
+
Input,
|
|
9816
|
+
{
|
|
9817
|
+
className: "h-8 text-xs",
|
|
9818
|
+
value: safe.breast.lumpSizeCm,
|
|
9819
|
+
onChange: (e) => update({ ...safe, breast: { ...safe.breast, lumpSizeCm: e.target.value } }),
|
|
9820
|
+
disabled
|
|
9821
|
+
}
|
|
9822
|
+
)
|
|
9823
|
+
] }),
|
|
9824
|
+
/* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
|
|
9825
|
+
/* @__PURE__ */ jsx(
|
|
9826
|
+
Checkbox,
|
|
9827
|
+
{
|
|
9828
|
+
checked: safe.breast.mobile,
|
|
9829
|
+
onCheckedChange: (c) => update({ ...safe, breast: { ...safe.breast, mobile: c === true } }),
|
|
9830
|
+
disabled
|
|
9831
|
+
}
|
|
9832
|
+
),
|
|
9833
|
+
"Mobile"
|
|
9834
|
+
] }),
|
|
9835
|
+
/* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
|
|
9836
|
+
/* @__PURE__ */ jsx(
|
|
9837
|
+
Checkbox,
|
|
9838
|
+
{
|
|
9839
|
+
checked: safe.breast.skinInvolvement,
|
|
9840
|
+
onCheckedChange: (c) => update({ ...safe, breast: { ...safe.breast, skinInvolvement: c === true } }),
|
|
9841
|
+
disabled
|
|
9842
|
+
}
|
|
9843
|
+
),
|
|
9844
|
+
"Skin involvement"
|
|
9845
|
+
] }),
|
|
9846
|
+
/* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
|
|
9847
|
+
/* @__PURE__ */ jsx(
|
|
9848
|
+
Checkbox,
|
|
9849
|
+
{
|
|
9850
|
+
checked: safe.breast.axillaryNodes,
|
|
9851
|
+
onCheckedChange: (c) => update({ ...safe, breast: { ...safe.breast, axillaryNodes: c === true } }),
|
|
9852
|
+
disabled
|
|
9853
|
+
}
|
|
9854
|
+
),
|
|
9855
|
+
"Axillary nodes"
|
|
9856
|
+
] })
|
|
9857
|
+
] }) }) : null,
|
|
9858
|
+
has("thyroid") ? /* @__PURE__ */ jsx(RegionCard, { title: "Thyroid exam", children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-3 text-xs md:grid-cols-4", children: [
|
|
9859
|
+
/* @__PURE__ */ jsxs("label", { className: "block", children: [
|
|
9860
|
+
/* @__PURE__ */ jsx("span", { className: "mb-1 block font-medium", children: "Size" }),
|
|
9861
|
+
/* @__PURE__ */ jsx(
|
|
9862
|
+
Input,
|
|
9863
|
+
{
|
|
9864
|
+
className: "h-8 text-xs",
|
|
9865
|
+
value: safe.thyroid.size,
|
|
9866
|
+
onChange: (e) => update({ ...safe, thyroid: { ...safe.thyroid, size: e.target.value } }),
|
|
9867
|
+
disabled
|
|
9868
|
+
}
|
|
9869
|
+
)
|
|
9870
|
+
] }),
|
|
9871
|
+
/* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
|
|
9872
|
+
/* @__PURE__ */ jsx(
|
|
9873
|
+
Checkbox,
|
|
9874
|
+
{
|
|
9875
|
+
checked: safe.thyroid.mobileDeglutition,
|
|
9876
|
+
onCheckedChange: (c) => update({ ...safe, thyroid: { ...safe.thyroid, mobileDeglutition: c === true } }),
|
|
9877
|
+
disabled
|
|
9878
|
+
}
|
|
9879
|
+
),
|
|
9880
|
+
"Mobile with deglutition"
|
|
9881
|
+
] }),
|
|
9882
|
+
/* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
|
|
9883
|
+
/* @__PURE__ */ jsx(
|
|
9884
|
+
Checkbox,
|
|
9885
|
+
{
|
|
9886
|
+
checked: safe.thyroid.nodules,
|
|
9887
|
+
onCheckedChange: (c) => update({ ...safe, thyroid: { ...safe.thyroid, nodules: c === true } }),
|
|
9888
|
+
disabled
|
|
9889
|
+
}
|
|
9890
|
+
),
|
|
9891
|
+
"Nodules"
|
|
9892
|
+
] }),
|
|
9893
|
+
/* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
|
|
9894
|
+
/* @__PURE__ */ jsx(
|
|
9895
|
+
Checkbox,
|
|
9896
|
+
{
|
|
9897
|
+
checked: safe.thyroid.cervicalNodes,
|
|
9898
|
+
onCheckedChange: (c) => update({ ...safe, thyroid: { ...safe.thyroid, cervicalNodes: c === true } }),
|
|
9899
|
+
disabled
|
|
9900
|
+
}
|
|
9901
|
+
),
|
|
9902
|
+
"Cervical lymph nodes"
|
|
9903
|
+
] })
|
|
9904
|
+
] }) }) : null,
|
|
9905
|
+
has("anorectal") ? /* @__PURE__ */ jsx(RegionCard, { title: "Anorectal exam", children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-3 text-xs md:grid-cols-3", children: [
|
|
9906
|
+
/* @__PURE__ */ jsxs("label", { className: "block md:col-span-3", children: [
|
|
9907
|
+
/* @__PURE__ */ jsx("span", { className: "mb-1 block font-medium", children: "Inspection findings" }),
|
|
9908
|
+
/* @__PURE__ */ jsx(
|
|
9909
|
+
Input,
|
|
9910
|
+
{
|
|
9911
|
+
className: "h-8 text-xs",
|
|
9912
|
+
value: safe.anorectal.inspection,
|
|
9913
|
+
onChange: (e) => update({ ...safe, anorectal: { ...safe.anorectal, inspection: e.target.value } }),
|
|
9914
|
+
disabled
|
|
9915
|
+
}
|
|
9916
|
+
)
|
|
9917
|
+
] }),
|
|
9918
|
+
/* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
|
|
9919
|
+
/* @__PURE__ */ jsx(
|
|
9920
|
+
Checkbox,
|
|
9921
|
+
{
|
|
9922
|
+
checked: safe.anorectal.dreDone,
|
|
9923
|
+
onCheckedChange: (c) => update({ ...safe, anorectal: { ...safe.anorectal, dreDone: c === true } }),
|
|
9924
|
+
disabled
|
|
9925
|
+
}
|
|
9926
|
+
),
|
|
9927
|
+
"DRE done"
|
|
9928
|
+
] }),
|
|
9929
|
+
/* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
|
|
9930
|
+
/* @__PURE__ */ jsx(
|
|
9931
|
+
Checkbox,
|
|
9932
|
+
{
|
|
9933
|
+
checked: safe.anorectal.proctoscopyDone,
|
|
9934
|
+
onCheckedChange: (c) => update({ ...safe, anorectal: { ...safe.anorectal, proctoscopyDone: c === true } }),
|
|
9935
|
+
disabled
|
|
9936
|
+
}
|
|
9937
|
+
),
|
|
9938
|
+
"Proctoscopy done"
|
|
9939
|
+
] }),
|
|
9940
|
+
/* @__PURE__ */ jsxs("div", { className: "md:col-span-3", children: [
|
|
9941
|
+
/* @__PURE__ */ jsx(Label, { className: "text-xs font-semibold", children: "DRE / proctoscopy notes" }),
|
|
9942
|
+
/* @__PURE__ */ jsx(
|
|
9943
|
+
Textarea,
|
|
9944
|
+
{
|
|
9945
|
+
className: "mt-1 min-h-[64px] text-sm",
|
|
9946
|
+
placeholder: "Sphincter tone, masses, prostate, bleeding\u2026",
|
|
9947
|
+
value: safe.anorectal.notes,
|
|
9948
|
+
onChange: (e) => update({ ...safe, anorectal: { ...safe.anorectal, notes: e.target.value } }),
|
|
9949
|
+
disabled
|
|
9950
|
+
}
|
|
9951
|
+
)
|
|
9952
|
+
] })
|
|
9953
|
+
] }) }) : null,
|
|
9954
|
+
has("limb") ? /* @__PURE__ */ jsx(RegionCard, { title: "Limb / varicose veins", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-x-4 gap-y-2 text-xs", children: [
|
|
9955
|
+
/* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
|
|
9956
|
+
/* @__PURE__ */ jsx(
|
|
9957
|
+
Checkbox,
|
|
9958
|
+
{
|
|
9959
|
+
checked: safe.limb.dilatedVeins,
|
|
9960
|
+
onCheckedChange: (c) => update({ ...safe, limb: { ...safe.limb, dilatedVeins: c === true } }),
|
|
9961
|
+
disabled
|
|
9962
|
+
}
|
|
9963
|
+
),
|
|
9964
|
+
"Dilated veins"
|
|
9965
|
+
] }),
|
|
9966
|
+
/* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
|
|
9967
|
+
/* @__PURE__ */ jsx(
|
|
9968
|
+
Checkbox,
|
|
9969
|
+
{
|
|
9970
|
+
checked: safe.limb.ulcer,
|
|
9971
|
+
onCheckedChange: (c) => update({ ...safe, limb: { ...safe.limb, ulcer: c === true } }),
|
|
9972
|
+
disabled
|
|
9973
|
+
}
|
|
9974
|
+
),
|
|
9975
|
+
"Ulcer"
|
|
9976
|
+
] }),
|
|
9977
|
+
/* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
|
|
9978
|
+
/* @__PURE__ */ jsx(
|
|
9979
|
+
Checkbox,
|
|
9980
|
+
{
|
|
9981
|
+
checked: safe.limb.oedema,
|
|
9982
|
+
onCheckedChange: (c) => update({ ...safe, limb: { ...safe.limb, oedema: c === true } }),
|
|
9983
|
+
disabled
|
|
9984
|
+
}
|
|
9985
|
+
),
|
|
9986
|
+
"Oedema"
|
|
9987
|
+
] })
|
|
9988
|
+
] }) }) : null
|
|
9989
|
+
] }),
|
|
9990
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
9991
|
+
/* @__PURE__ */ jsx(Label, { className: "text-xs font-semibold text-slate-700", children: clinicalField.fieldDef?.label ?? "Clinical examination" }),
|
|
9992
|
+
/* @__PURE__ */ jsx(
|
|
9993
|
+
Textarea,
|
|
9994
|
+
{
|
|
9995
|
+
className: "min-h-[88px] rounded-md border border-input bg-white text-sm",
|
|
9996
|
+
value: typeof clinicalField.value === "string" ? clinicalField.value : clinicalField.value == null ? "" : String(clinicalField.value),
|
|
9997
|
+
onChange: (e) => {
|
|
9998
|
+
clinicalField.setValue(e.target.value);
|
|
9999
|
+
clinicalField.setTouched();
|
|
10000
|
+
},
|
|
10001
|
+
disabled: disabled || clinicalField.disabled
|
|
10002
|
+
}
|
|
10003
|
+
)
|
|
10004
|
+
] })
|
|
10005
|
+
] }),
|
|
10006
|
+
showError ? /* @__PURE__ */ jsx("p", { className: "px-3 pb-2 text-xs text-red-500", children: error }) : null
|
|
10007
|
+
] });
|
|
10008
|
+
};
|
|
10009
|
+
var CHIEF_CHIPS_FIELD2 = "chief_complaints_chips";
|
|
10010
|
+
var GS_EXAMINATION_FIELD = "gs_examination";
|
|
10011
|
+
function chipList2(state) {
|
|
10012
|
+
const raw = state.values[CHIEF_CHIPS_FIELD2];
|
|
10013
|
+
return Array.isArray(raw) ? raw.filter((x) => typeof x === "string") : [];
|
|
10014
|
+
}
|
|
10015
|
+
function regionList(state) {
|
|
10016
|
+
const raw = state.values[GS_EXAMINATION_FIELD];
|
|
10017
|
+
const ex = normalizeGeneralSurgeryExamination(raw);
|
|
10018
|
+
return ex.regions;
|
|
10019
|
+
}
|
|
10020
|
+
var GsGradingWidget = ({ fieldId }) => {
|
|
10021
|
+
const { fieldDef, value, setValue, setTouched, error, touched, disabled } = useField(fieldId);
|
|
10022
|
+
const { state } = useForm();
|
|
10023
|
+
const showError = !!error && (touched || state.submitAttempted);
|
|
10024
|
+
const safe = useMemo(() => normalizeGeneralSurgeryGrading(value), [value]);
|
|
10025
|
+
const chips = useMemo(() => chipList2(state), [state]);
|
|
10026
|
+
const regions = useMemo(() => regionList(state), [state]);
|
|
10027
|
+
const visibleRows = useMemo(() => {
|
|
10028
|
+
return ALL_GS_CONDITIONS.filter(
|
|
10029
|
+
(c) => gsGradingRowVisible(c, chips, regions, safe[c] ?? 0)
|
|
10030
|
+
);
|
|
10031
|
+
}, [chips, regions, safe]);
|
|
10032
|
+
const update = (next) => {
|
|
10033
|
+
setValue(next);
|
|
10034
|
+
setTouched();
|
|
10035
|
+
};
|
|
10036
|
+
const setGrade = (cond, gradeStr) => {
|
|
10037
|
+
const n = Math.min(5, Math.max(0, Math.round(Number(gradeStr)) || 0));
|
|
10038
|
+
update({ ...safe, [cond]: n });
|
|
10039
|
+
};
|
|
10040
|
+
if (!fieldDef) return null;
|
|
10041
|
+
const theme = getThemeConfig("textarea", fieldDef.theme);
|
|
10042
|
+
const wrapperClass = theme?.wrapperClassName ?? "rounded-md overflow-hidden flex flex-col border border-[#D0D0D0]";
|
|
10043
|
+
const labelClass = theme?.labelClassName;
|
|
10044
|
+
const labelContent = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
10045
|
+
fieldDef.label,
|
|
10046
|
+
fieldDef.required ? /* @__PURE__ */ jsx("span", { className: "ml-1 text-red-500", children: "*" }) : null
|
|
10047
|
+
] });
|
|
10048
|
+
const labelEl = theme ? /* @__PURE__ */ jsx(Label, { className: labelClass, children: labelContent }) : /* @__PURE__ */ jsx(Label, { className: "text-sm font-medium", children: labelContent });
|
|
10049
|
+
const bodyClass = cn(
|
|
10050
|
+
"-mt-1 flex min-w-0 flex-col gap-3 border-t border-[#D0D0D0] bg-white px-3 py-3",
|
|
10051
|
+
disabled && "pointer-events-none opacity-60"
|
|
10052
|
+
);
|
|
10053
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("w-full min-w-0", wrapperClass), children: [
|
|
10054
|
+
labelEl,
|
|
10055
|
+
/* @__PURE__ */ jsx("div", { className: bodyClass, children: visibleRows.length === 0 ? /* @__PURE__ */ 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__ */ jsx("div", { className: "overflow-x-auto rounded-md border border-[#D0D0D0]", children: /* @__PURE__ */ jsxs("table", { className: "w-full min-w-[520px] border-collapse text-xs", children: [
|
|
10056
|
+
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { className: "border-b border-[#D0D0D0] bg-[#FEE8EC]/50", children: [
|
|
10057
|
+
/* @__PURE__ */ jsx("th", { className: "px-3 py-2 text-left font-semibold text-slate-700", children: "Condition" }),
|
|
10058
|
+
/* @__PURE__ */ jsx("th", { className: "w-24 px-2 py-2 font-semibold text-slate-700", children: "Grade" }),
|
|
10059
|
+
/* @__PURE__ */ jsx("th", { className: "px-3 py-2 text-left font-semibold text-slate-700", children: "Description" })
|
|
10060
|
+
] }) }),
|
|
10061
|
+
/* @__PURE__ */ jsx("tbody", { className: "bg-white", children: visibleRows.map((c) => {
|
|
10062
|
+
const g = safe[c] ?? 0;
|
|
10063
|
+
const desc = GS_GRADE_DESCRIPTIONS[c][g] ?? "\u2014";
|
|
10064
|
+
return /* @__PURE__ */ jsxs("tr", { className: "border-b border-[#D0D0D0]/80 last:border-0", children: [
|
|
10065
|
+
/* @__PURE__ */ jsx("td", { className: "px-3 py-2 font-medium", children: GS_CONDITION_LABELS[c] }),
|
|
10066
|
+
/* @__PURE__ */ jsx("td", { className: "px-2 py-1.5 align-middle", children: /* @__PURE__ */ jsxs(
|
|
10067
|
+
Select,
|
|
10068
|
+
{
|
|
10069
|
+
value: String(g),
|
|
10070
|
+
onValueChange: (v) => setGrade(c, v),
|
|
10071
|
+
disabled,
|
|
10072
|
+
children: [
|
|
10073
|
+
/* @__PURE__ */ jsx(SelectTrigger, { className: "h-8 text-xs", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
|
|
10074
|
+
/* @__PURE__ */ jsx(SelectContent, { children: [0, 1, 2, 3, 4, 5].map((n) => /* @__PURE__ */ jsx(SelectItem, { value: String(n), children: n === 0 ? "\u2014" : String(n) }, n)) })
|
|
10075
|
+
]
|
|
10076
|
+
}
|
|
10077
|
+
) }),
|
|
10078
|
+
/* @__PURE__ */ jsx("td", { className: "px-3 py-2 text-muted-foreground", children: desc })
|
|
10079
|
+
] }, c);
|
|
10080
|
+
}) })
|
|
10081
|
+
] }) }) }),
|
|
10082
|
+
showError ? /* @__PURE__ */ jsx("p", { className: "px-3 pb-2 text-xs text-red-500", children: error }) : null
|
|
10083
|
+
] });
|
|
10084
|
+
};
|
|
10085
|
+
function isFlagSelected(selected, optValue) {
|
|
10086
|
+
return selected.some((v) => v === optValue || String(v) === String(optValue));
|
|
10087
|
+
}
|
|
10088
|
+
var PainScaleFlagsWidget = ({ fieldId }) => {
|
|
10089
|
+
const { fieldDef, value, setValue, setTouched, error, touched, disabled } = useField(fieldId);
|
|
10090
|
+
const { state } = useForm();
|
|
10091
|
+
const showError = !!error && (touched || state.submitAttempted);
|
|
10092
|
+
if (!fieldDef || fieldDef.type !== "pain_scale_flags") return null;
|
|
10093
|
+
const def = fieldDef;
|
|
10094
|
+
const min = def.min ?? 0;
|
|
10095
|
+
const max = def.max ?? 10;
|
|
10096
|
+
const step = def.step ?? 1;
|
|
10097
|
+
const flagOptions = def.options ?? [];
|
|
10098
|
+
const safe = useMemo(
|
|
10099
|
+
() => normalizePainScaleFlags(value, { min, max }),
|
|
10100
|
+
[value, min, max]
|
|
10101
|
+
);
|
|
10102
|
+
const theme = getThemeConfig("textarea", def.theme);
|
|
10103
|
+
const wrapperClass = theme?.wrapperClassName ?? "space-y-2";
|
|
10104
|
+
const labelClass = theme?.labelClassName;
|
|
10105
|
+
const update = (next) => {
|
|
10106
|
+
setValue(normalizePainScaleFlags(next, { min, max }));
|
|
10107
|
+
setTouched();
|
|
10108
|
+
};
|
|
10109
|
+
const toggleFlag = (optValue) => {
|
|
10110
|
+
const sel = safe.flags;
|
|
10111
|
+
const isSelected = isFlagSelected(sel, optValue);
|
|
10112
|
+
const nextFlags = isSelected ? sel.filter((v) => v !== optValue && String(v) !== String(optValue)) : [...sel, String(optValue)];
|
|
10113
|
+
update({ pain: safe.pain, flags: nextFlags });
|
|
10114
|
+
};
|
|
10115
|
+
const labelContent = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
10116
|
+
def.label,
|
|
10117
|
+
" ",
|
|
10118
|
+
def.required && /* @__PURE__ */ jsx("span", { className: "text-red-500", children: "*" })
|
|
10119
|
+
] });
|
|
10120
|
+
const labelEl = theme ? /* @__PURE__ */ jsx(Label, { className: labelClass, children: labelContent }) : /* @__PURE__ */ jsx(Label, { children: labelContent });
|
|
10121
|
+
const bodyClass = cn(
|
|
10122
|
+
"-mt-1 flex min-w-0 flex-col border-t border-[#D0D0D0] bg-white px-3 py-3",
|
|
10123
|
+
disabled && "pointer-events-none opacity-60"
|
|
10124
|
+
);
|
|
10125
|
+
return /* @__PURE__ */ jsxs("div", { className: cn(wrapperClass, "h-full min-h-0 flex flex-col"), children: [
|
|
10126
|
+
labelEl,
|
|
10127
|
+
def.description && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: def.description }),
|
|
10128
|
+
/* @__PURE__ */ jsx("div", { className: cn(bodyClass, "min-h-0 flex-1"), children: /* @__PURE__ */ jsxs("div", { className: "min-w-0 space-y-3", children: [
|
|
10129
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
10130
|
+
/* @__PURE__ */ jsxs(Label, { className: "text-sm font-medium text-slate-700", children: [
|
|
10131
|
+
"Pain score (VAS)",
|
|
10132
|
+
/* @__PURE__ */ jsxs("span", { className: "ml-2 font-normal tabular-nums text-muted-foreground", children: [
|
|
10133
|
+
safe.pain,
|
|
10134
|
+
"/",
|
|
10135
|
+
max
|
|
10136
|
+
] })
|
|
10137
|
+
] }),
|
|
10138
|
+
/* @__PURE__ */ jsx(
|
|
10139
|
+
Slider,
|
|
10140
|
+
{
|
|
10141
|
+
className: cn("py-1", showError && "rounded opacity-90 ring-1 ring-red-500"),
|
|
10142
|
+
disabled,
|
|
10143
|
+
min,
|
|
10144
|
+
max,
|
|
10145
|
+
step,
|
|
10146
|
+
value: [safe.pain],
|
|
10147
|
+
onValueChange: (v) => {
|
|
10148
|
+
const n = v[0] ?? min;
|
|
10149
|
+
update({ pain: n, flags: safe.flags });
|
|
10150
|
+
}
|
|
10151
|
+
}
|
|
10152
|
+
)
|
|
10153
|
+
] }),
|
|
10154
|
+
flagOptions.length > 0 ? /* @__PURE__ */ jsxs("div", { className: "min-w-0 space-y-1.5", children: [
|
|
10155
|
+
/* @__PURE__ */ jsx(Label, { className: "text-sm font-medium text-slate-700", children: "Triage flags" }),
|
|
10156
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-x-4 gap-y-2", children: flagOptions.map((opt) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
10157
|
+
/* @__PURE__ */ jsx(
|
|
10158
|
+
Checkbox,
|
|
10159
|
+
{
|
|
10160
|
+
id: `${fieldId}-flag-${String(opt.value)}`,
|
|
10161
|
+
checked: isFlagSelected(safe.flags, opt.value),
|
|
10162
|
+
onCheckedChange: () => toggleFlag(opt.value),
|
|
10163
|
+
disabled
|
|
10164
|
+
}
|
|
10165
|
+
),
|
|
10166
|
+
/* @__PURE__ */ jsx(
|
|
10167
|
+
Label,
|
|
10168
|
+
{
|
|
10169
|
+
htmlFor: `${fieldId}-flag-${String(opt.value)}`,
|
|
10170
|
+
className: "cursor-pointer text-sm font-normal leading-none",
|
|
10171
|
+
children: opt.label
|
|
10172
|
+
}
|
|
10173
|
+
)
|
|
10174
|
+
] }, String(opt.value))) })
|
|
10175
|
+
] }) : null
|
|
10176
|
+
] }) }),
|
|
10177
|
+
showError && /* @__PURE__ */ jsx("p", { className: "text-xs text-red-500", children: error })
|
|
10178
|
+
] });
|
|
10179
|
+
};
|
|
10180
|
+
var FieldRenderer = ({ fieldId }) => {
|
|
10181
|
+
const { fieldDef, visible } = useField(fieldId);
|
|
10182
|
+
if (!visible || !fieldDef) {
|
|
10183
|
+
return null;
|
|
10184
|
+
}
|
|
10185
|
+
return renderWidget(fieldId, fieldDef);
|
|
10186
|
+
};
|
|
10187
|
+
function renderWidget(fieldId, fieldDef) {
|
|
10188
|
+
switch (fieldDef.type) {
|
|
10189
|
+
case "text":
|
|
10190
|
+
case "number":
|
|
10191
|
+
return /* @__PURE__ */ jsx(TextWidget, { fieldId });
|
|
10192
|
+
case "slider":
|
|
10193
|
+
return /* @__PURE__ */ jsx(SliderWidget, { fieldId });
|
|
10194
|
+
case "textarea":
|
|
10195
|
+
if (fieldMetaRequestsMarMedicationOrdersButton(fieldDef.meta)) {
|
|
10196
|
+
return /* @__PURE__ */ jsx(MarMedicationOrdersWidget, { fieldId });
|
|
10197
|
+
}
|
|
10198
|
+
return /* @__PURE__ */ jsx(TextWidget, { fieldId });
|
|
10199
|
+
case "richtext":
|
|
10200
|
+
return /* @__PURE__ */ jsx(RichTextWidget, { fieldId });
|
|
10201
|
+
case "date":
|
|
10202
|
+
return /* @__PURE__ */ jsx(DateWidget, { fieldId });
|
|
10203
|
+
case "datetime":
|
|
10204
|
+
return /* @__PURE__ */ jsx(DateTimeWidget, { fieldId });
|
|
10205
|
+
case "select":
|
|
10206
|
+
return /* @__PURE__ */ jsx(SelectWidget, { fieldId });
|
|
10207
|
+
case "radio":
|
|
10208
|
+
return /* @__PURE__ */ jsx(RadioWidget, { fieldId });
|
|
10209
|
+
case "checkbox":
|
|
10210
|
+
return /* @__PURE__ */ jsx(CheckboxWidget, { fieldId });
|
|
10211
|
+
case "multiselect":
|
|
10212
|
+
return /* @__PURE__ */ jsx(MultiSelectWidget, { fieldId });
|
|
10213
|
+
case "repeatable":
|
|
10214
|
+
return /* @__PURE__ */ jsx(RepeatableWidget, { fieldId });
|
|
10215
|
+
case "image_upload":
|
|
10216
|
+
return /* @__PURE__ */ jsx(ImageUploadWidget, { fieldId });
|
|
10217
|
+
case "media_upload":
|
|
10218
|
+
return /* @__PURE__ */ jsx(MediaUploadWidget, { fieldId });
|
|
10219
|
+
case "signature":
|
|
10220
|
+
return /* @__PURE__ */ jsx(SignatureUploadWidget, { fieldId });
|
|
10221
|
+
case "editable_table":
|
|
10222
|
+
return /* @__PURE__ */ jsx(EditableTableWidget, { fieldId });
|
|
10223
|
+
case "medications":
|
|
10224
|
+
return /* @__PURE__ */ jsx(AddMedicationWidget, { fieldId });
|
|
10225
|
+
case "discharge_medication_orders":
|
|
10226
|
+
return /* @__PURE__ */ jsx(DischargeMedicationOrdersWidget, { fieldId });
|
|
10227
|
+
case "investigations":
|
|
10228
|
+
return /* @__PURE__ */ jsx(AddInvestigationWidget, { fieldId });
|
|
10229
|
+
case "procedures":
|
|
10230
|
+
return /* @__PURE__ */ jsx(AddProcedureWidget, { fieldId });
|
|
10231
|
+
case "differential_diagnosis":
|
|
10232
|
+
return /* @__PURE__ */ jsx(DifferentialDiagnosisWidget, { fieldId });
|
|
10233
|
+
case "vitals":
|
|
10234
|
+
return /* @__PURE__ */ jsx(VitalsWidget, { fieldId });
|
|
10235
|
+
case "hidden_vitals":
|
|
10236
|
+
return /* @__PURE__ */ jsx(HiddenVitalsWidget, { fieldId });
|
|
10237
|
+
case "referral":
|
|
10238
|
+
return /* @__PURE__ */ jsx(ReferralWidget, { fieldId });
|
|
10239
|
+
case "followup":
|
|
10240
|
+
return /* @__PURE__ */ jsx(FollowupWidget, { fieldId });
|
|
10241
|
+
case "smart_textarea":
|
|
10242
|
+
return /* @__PURE__ */ jsx(SmartTextareaWidget, { fieldId });
|
|
10243
|
+
case "diagnosis_textarea":
|
|
10244
|
+
return /* @__PURE__ */ jsx(DiagnosisTextareaWidget, { fieldId });
|
|
10245
|
+
case "obstetric_history":
|
|
10246
|
+
return /* @__PURE__ */ jsx(ObstetricHistoryWidget, { fieldId });
|
|
10247
|
+
case "eye_prescription":
|
|
10248
|
+
return /* @__PURE__ */ jsx(OphthalmologyWidget, { fieldId });
|
|
10249
|
+
case "ophthal_diagnosis":
|
|
10250
|
+
return /* @__PURE__ */ jsx(OphthalDiagnosisWidget, { fieldId });
|
|
10251
|
+
case "orthopedic_exam":
|
|
10252
|
+
return /* @__PURE__ */ jsx(OrthopedicExamWidget, { fieldId });
|
|
10253
|
+
case "general_surgery_smart_history":
|
|
10254
|
+
return /* @__PURE__ */ jsx(GsSmartHistoryWidget, { fieldId });
|
|
10255
|
+
case "general_surgery_examination":
|
|
10256
|
+
return /* @__PURE__ */ jsx(GsExaminationWidget, { fieldId });
|
|
10257
|
+
case "general_surgery_grading":
|
|
10258
|
+
return /* @__PURE__ */ jsx(GsGradingWidget, { fieldId });
|
|
10259
|
+
case "pain_scale_flags":
|
|
10260
|
+
return /* @__PURE__ */ jsx(PainScaleFlagsWidget, { fieldId });
|
|
10261
|
+
case "toggle": {
|
|
10262
|
+
const { value, setValue, setTouched, disabled } = useField(fieldId);
|
|
10263
|
+
const store = useFormStore();
|
|
10264
|
+
const excludes = fieldDef.excludes ?? [];
|
|
10265
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
10266
|
+
/* @__PURE__ */ jsx(
|
|
10267
|
+
Switch,
|
|
10268
|
+
{
|
|
10269
|
+
checked: value === true,
|
|
10270
|
+
disabled,
|
|
10271
|
+
onCheckedChange: (checked) => {
|
|
10272
|
+
setValue(checked);
|
|
10273
|
+
setTouched();
|
|
10274
|
+
if (checked) excludes.forEach((id) => store.setValue(id, false));
|
|
10275
|
+
}
|
|
10276
|
+
}
|
|
10277
|
+
),
|
|
10278
|
+
/* @__PURE__ */ jsx(Label, { className: "text-sm font-medium leading-none cursor-pointer select-none", children: fieldDef.label })
|
|
10279
|
+
] });
|
|
10280
|
+
}
|
|
10281
|
+
case "suggestion_textarea":
|
|
10282
|
+
case "complaint_chips":
|
|
10283
|
+
return /* @__PURE__ */ jsx(SuggestionTextareaWidget, { fieldId });
|
|
10284
|
+
case "lens_assessment":
|
|
10285
|
+
return /* @__PURE__ */ jsx(LensAssessmentWidget, { fieldId });
|
|
10286
|
+
case "functional_impairment_score":
|
|
10287
|
+
return /* @__PURE__ */ jsx(FunctionalImpairmentScoreWidget, { fieldId });
|
|
10288
|
+
case "biometry_iol_workup":
|
|
10289
|
+
return /* @__PURE__ */ jsx(BiometryIolWorkupWidget, { fieldId });
|
|
10290
|
+
case "surgical_risk_flags":
|
|
10291
|
+
return /* @__PURE__ */ jsx(SurgicalRiskFlagsWidget, { fieldId });
|
|
10292
|
+
case "static_text": {
|
|
10293
|
+
const def = fieldDef;
|
|
10294
|
+
const size = def.size ?? "regular";
|
|
10295
|
+
const labelClass = size === "large" ? "text-base" : "text-sm";
|
|
10296
|
+
const descClass = size === "large" ? "text-sm" : "text-xs";
|
|
10297
|
+
return /* @__PURE__ */ jsxs("div", { className: `${labelClass} text-muted-foreground`, children: [
|
|
10298
|
+
def.label,
|
|
10299
|
+
def.description && /* @__PURE__ */ jsx("p", { className: `mt-1 ${descClass} opacity-90`, children: def.description })
|
|
10300
|
+
] });
|
|
10301
|
+
}
|
|
10302
|
+
default:
|
|
10303
|
+
return /* @__PURE__ */ jsxs("div", { className: "text-red-500", children: [
|
|
10304
|
+
"Unknown field type: ",
|
|
10305
|
+
fieldDef.type
|
|
10306
|
+
] });
|
|
10307
|
+
}
|
|
10308
|
+
}
|
|
10309
|
+
var Section = ({ title, children }) => {
|
|
10310
|
+
const [expanded, setExpanded] = useState(true);
|
|
10311
|
+
const handleToggle = () => setExpanded((prev) => !prev);
|
|
10312
|
+
const contentClassName = cn(
|
|
10313
|
+
"overflow-hidden transition-[height] duration-200 ease-in-out",
|
|
10314
|
+
!expanded && "hidden"
|
|
10315
|
+
);
|
|
10316
|
+
return /* @__PURE__ */ jsxs("div", { className: "mb-6 border rounded-lg bg-white shadow-sm overflow-hidden", children: [
|
|
10317
|
+
/* @__PURE__ */ jsxs(
|
|
10318
|
+
"button",
|
|
10319
|
+
{
|
|
10320
|
+
type: "button",
|
|
10321
|
+
onClick: handleToggle,
|
|
10322
|
+
className: "w-full flex items-center justify-between gap-2 p-4 text-left border-b hover:bg-gray-50/80 transition-colors",
|
|
10323
|
+
children: [
|
|
10324
|
+
/* @__PURE__ */ jsx("h3", { className: "text-lg font-medium", children: title }),
|
|
10325
|
+
/* @__PURE__ */ jsx("span", { className: "flex-shrink-0 text-muted-foreground", "aria-hidden": true, children: expanded ? /* @__PURE__ */ jsx(ChevronDown, { className: "h-5 w-5" }) : /* @__PURE__ */ jsx(ChevronRight, { className: "h-5 w-5" }) })
|
|
10326
|
+
]
|
|
10327
|
+
}
|
|
10328
|
+
),
|
|
10329
|
+
/* @__PURE__ */ jsx("div", { className: contentClassName, children: /* @__PURE__ */ jsx("div", { className: "p-4 pt-4 space-y-4 border-t-0", children }) })
|
|
10330
|
+
] });
|
|
10331
|
+
};
|
|
10332
|
+
var ColumnLayout = ({
|
|
10333
|
+
columns,
|
|
10334
|
+
label,
|
|
10335
|
+
children
|
|
10336
|
+
}) => {
|
|
10337
|
+
const gridCols = Math.max(1, Math.min(columns, 12));
|
|
10338
|
+
const gridClass = `grid gap-4 w-full`;
|
|
10339
|
+
const style = {
|
|
10340
|
+
gridTemplateColumns: `repeat(${gridCols}, minmax(0, 1fr))`
|
|
10341
|
+
};
|
|
10342
|
+
return /* @__PURE__ */ jsxs("div", { className: "mb-6", children: [
|
|
10343
|
+
label != null && label !== "" && /* @__PURE__ */ jsx("div", { className: "mb-2 text-sm font-medium text-gray-700", children: label }),
|
|
10344
|
+
/* @__PURE__ */ jsx("div", { className: gridClass, style, children })
|
|
10345
|
+
] });
|
|
10346
|
+
};
|
|
10347
|
+
var DynamicForm = () => {
|
|
10348
|
+
const store = useFormStore();
|
|
10349
|
+
const schema = store.getSchema();
|
|
10350
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
|
|
10351
|
+
/* @__PURE__ */ jsx("div", { className: "mb-4", children: /* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold", children: schema.title }) }),
|
|
10352
|
+
schema.layout.map((node) => {
|
|
10353
|
+
if (node.type === "section") {
|
|
10354
|
+
return /* @__PURE__ */ jsx(Section, { title: node.title, children: node.children.map(
|
|
10355
|
+
(child, index) => typeof child === "string" ? /* @__PURE__ */ jsx(FieldRenderer, { fieldId: child }, child) : child.type === "column_layout" ? /* @__PURE__ */ jsx(
|
|
10356
|
+
ColumnLayout,
|
|
10357
|
+
{
|
|
10358
|
+
columns: child.columns,
|
|
10359
|
+
label: child.label,
|
|
10360
|
+
children: child.children.map((fieldId) => /* @__PURE__ */ jsx(FieldRenderer, { fieldId }, fieldId))
|
|
10361
|
+
},
|
|
9084
10362
|
child.id
|
|
9085
10363
|
) : /* @__PURE__ */ jsx(React15__default.Fragment, {}, child.id ?? index)
|
|
9086
10364
|
) }, node.id);
|
|
@@ -9215,14 +10493,24 @@ var SmartForm = ({
|
|
|
9215
10493
|
if (position !== "left") return null;
|
|
9216
10494
|
return /* @__PURE__ */ jsx(FieldRenderer, { fieldId }, fieldId);
|
|
9217
10495
|
}) }),
|
|
9218
|
-
/* @__PURE__ */ jsx("div", { className: "col-span-2 grid grid-cols-2 gap-
|
|
10496
|
+
/* @__PURE__ */ jsx("div", { className: "col-span-2 grid grid-cols-2 gap-2", children: fieldIds.map((fieldId) => {
|
|
9219
10497
|
const fieldDef = store.getFieldDef(fieldId);
|
|
9220
10498
|
if (!fieldDef) return null;
|
|
9221
10499
|
const position = fieldDef.position ?? "center";
|
|
9222
10500
|
if (position !== "center") return null;
|
|
9223
10501
|
const colSpanRaw = fieldDef.colSpan ?? 1;
|
|
9224
10502
|
const colSpan = colSpanRaw === 2 ? 2 : 1;
|
|
9225
|
-
return /* @__PURE__ */ jsx(
|
|
10503
|
+
return /* @__PURE__ */ jsx(
|
|
10504
|
+
"div",
|
|
10505
|
+
{
|
|
10506
|
+
className: cn(
|
|
10507
|
+
"min-h-0 flex flex-col",
|
|
10508
|
+
colSpan === 2 ? "col-span-2" : "col-span-1 h-full"
|
|
10509
|
+
),
|
|
10510
|
+
children: /* @__PURE__ */ jsx(FieldRenderer, { fieldId })
|
|
10511
|
+
},
|
|
10512
|
+
fieldId
|
|
10513
|
+
);
|
|
9226
10514
|
}) }),
|
|
9227
10515
|
/* @__PURE__ */ jsx("div", { className: "col-span-1 flex flex-col gap-2", children: fieldIds.map((fieldId) => {
|
|
9228
10516
|
const fieldDef = store.getFieldDef(fieldId);
|
|
@@ -9670,11 +10958,17 @@ var ReadOnlyDischargeMedicationOrders = ({ fieldDef, value }) => {
|
|
|
9670
10958
|
}) })
|
|
9671
10959
|
] });
|
|
9672
10960
|
};
|
|
9673
|
-
var ReadOnlyFieldRenderer = ({
|
|
10961
|
+
var ReadOnlyFieldRenderer = ({
|
|
10962
|
+
fieldDef,
|
|
10963
|
+
value,
|
|
10964
|
+
allValues,
|
|
10965
|
+
resolveFieldDef
|
|
10966
|
+
}) => {
|
|
9674
10967
|
if (!fieldDef) return null;
|
|
9675
10968
|
switch (fieldDef.type) {
|
|
9676
10969
|
case "text":
|
|
9677
10970
|
case "number":
|
|
10971
|
+
case "slider":
|
|
9678
10972
|
case "textarea":
|
|
9679
10973
|
case "richtext":
|
|
9680
10974
|
return /* @__PURE__ */ jsx(ReadOnlyText, { fieldDef, value });
|
|
@@ -9712,8 +11006,30 @@ var ReadOnlyFieldRenderer = ({ fieldDef, value }) => {
|
|
|
9712
11006
|
] });
|
|
9713
11007
|
}
|
|
9714
11008
|
case "suggestion_textarea":
|
|
9715
|
-
case "complaint_chips":
|
|
9716
|
-
|
|
11009
|
+
case "complaint_chips": {
|
|
11010
|
+
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()) : [];
|
|
11011
|
+
const showEmbedded = embeddedIds.length > 0 && resolveFieldDef && allValues && typeof allValues === "object";
|
|
11012
|
+
if (!showEmbedded) {
|
|
11013
|
+
return /* @__PURE__ */ jsx(ReadOnlyText, { fieldDef, value });
|
|
11014
|
+
}
|
|
11015
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
11016
|
+
/* @__PURE__ */ jsx(ReadOnlyText, { fieldDef, value }),
|
|
11017
|
+
/* @__PURE__ */ jsx("div", { className: "grid gap-3 border-t border-muted-foreground/20 pt-3 sm:grid-cols-3", children: embeddedIds.map((id) => {
|
|
11018
|
+
const fd = resolveFieldDef(id);
|
|
11019
|
+
if (!fd) return null;
|
|
11020
|
+
return /* @__PURE__ */ jsx(
|
|
11021
|
+
ReadOnlyFieldRenderer,
|
|
11022
|
+
{
|
|
11023
|
+
fieldDef: fd,
|
|
11024
|
+
value: allValues[id],
|
|
11025
|
+
allValues,
|
|
11026
|
+
resolveFieldDef
|
|
11027
|
+
},
|
|
11028
|
+
id
|
|
11029
|
+
);
|
|
11030
|
+
}) })
|
|
11031
|
+
] });
|
|
11032
|
+
}
|
|
9717
11033
|
case "lens_assessment": {
|
|
9718
11034
|
const v = value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
9719
11035
|
const notes = typeof v?.notes === "string" ? v.notes : "";
|
|
@@ -9789,6 +11105,44 @@ var ReadOnlyFieldRenderer = ({ fieldDef, value }) => {
|
|
|
9789
11105
|
const lines = [`Right eye (OD): ${od}`, `Left eye (OS): ${os}`].join("\n");
|
|
9790
11106
|
return /* @__PURE__ */ jsx(ReadOnlyText, { fieldDef, value: lines });
|
|
9791
11107
|
}
|
|
11108
|
+
case "pain_scale_flags": {
|
|
11109
|
+
const def = fieldDef;
|
|
11110
|
+
const min = def.min ?? 0;
|
|
11111
|
+
const max = def.max ?? 10;
|
|
11112
|
+
const safe = normalizePainScaleFlags(value, { min, max });
|
|
11113
|
+
const opts = def.options ?? [];
|
|
11114
|
+
const flagLabels = safe.flags.map((fv) => {
|
|
11115
|
+
const o = opts.find((x) => x.value === fv || String(x.value) === String(fv));
|
|
11116
|
+
return o?.label ?? fv;
|
|
11117
|
+
});
|
|
11118
|
+
const lines = [
|
|
11119
|
+
`Pain score (VAS): ${safe.pain}/${max}`,
|
|
11120
|
+
flagLabels.length > 0 ? `Triage flags: ${flagLabels.join(", ")}` : "Triage flags: \u2014"
|
|
11121
|
+
].join("\n");
|
|
11122
|
+
return /* @__PURE__ */ jsx(ReadOnlyText, { fieldDef, value: lines });
|
|
11123
|
+
}
|
|
11124
|
+
case "general_surgery_smart_history":
|
|
11125
|
+
case "general_surgery_grading":
|
|
11126
|
+
return /* @__PURE__ */ jsx(
|
|
11127
|
+
ReadOnlyText,
|
|
11128
|
+
{
|
|
11129
|
+
fieldDef,
|
|
11130
|
+
value: value && typeof value === "object" ? JSON.stringify(value, null, 2) : value == null || value === "" ? "\u2014" : String(value)
|
|
11131
|
+
}
|
|
11132
|
+
);
|
|
11133
|
+
case "general_surgery_examination": {
|
|
11134
|
+
const structuredDisplay = value && typeof value === "object" ? JSON.stringify(value, null, 2) : value == null || value === "" ? "\u2014" : String(value);
|
|
11135
|
+
const clinicalDef = resolveFieldDef?.("clinical_examination");
|
|
11136
|
+
const clinicalRaw = allValues?.["clinical_examination"];
|
|
11137
|
+
const clinicalStr = typeof clinicalRaw === "string" ? clinicalRaw : clinicalRaw != null && clinicalRaw !== "" ? String(clinicalRaw) : "";
|
|
11138
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
11139
|
+
/* @__PURE__ */ jsx(ReadOnlyText, { fieldDef, value: structuredDisplay }),
|
|
11140
|
+
clinicalDef ? /* @__PURE__ */ jsx(ReadOnlyText, { fieldDef: clinicalDef, value: clinicalStr }) : clinicalStr ? /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
11141
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-gray-700", children: "Clinical examination" }),
|
|
11142
|
+
/* @__PURE__ */ 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 })
|
|
11143
|
+
] }) : null
|
|
11144
|
+
] });
|
|
11145
|
+
}
|
|
9792
11146
|
case "static_text": {
|
|
9793
11147
|
const def = fieldDef;
|
|
9794
11148
|
const size = def.size ?? "regular";
|
|
@@ -9835,7 +11189,9 @@ var ReadOnlyForm = ({ schema, submission }) => {
|
|
|
9835
11189
|
ReadOnlyFieldRenderer,
|
|
9836
11190
|
{
|
|
9837
11191
|
fieldDef,
|
|
9838
|
-
value: formData[child]
|
|
11192
|
+
value: formData[child],
|
|
11193
|
+
allValues: formData,
|
|
11194
|
+
resolveFieldDef: (id) => fieldMap.get(id)
|
|
9839
11195
|
},
|
|
9840
11196
|
child
|
|
9841
11197
|
) : null;
|
|
@@ -9854,7 +11210,9 @@ var ReadOnlyForm = ({ schema, submission }) => {
|
|
|
9854
11210
|
ReadOnlyFieldRenderer,
|
|
9855
11211
|
{
|
|
9856
11212
|
fieldDef,
|
|
9857
|
-
value: formData[fieldId]
|
|
11213
|
+
value: formData[fieldId],
|
|
11214
|
+
allValues: formData,
|
|
11215
|
+
resolveFieldDef: (id) => fieldMap.get(id)
|
|
9858
11216
|
},
|
|
9859
11217
|
fieldId
|
|
9860
11218
|
))
|
|
@@ -9885,7 +11243,9 @@ var ReadOnlyForm = ({ schema, submission }) => {
|
|
|
9885
11243
|
ReadOnlyFieldRenderer,
|
|
9886
11244
|
{
|
|
9887
11245
|
fieldDef,
|
|
9888
|
-
value: formData[fieldId]
|
|
11246
|
+
value: formData[fieldId],
|
|
11247
|
+
allValues: formData,
|
|
11248
|
+
resolveFieldDef: (id) => fieldMap.get(id)
|
|
9889
11249
|
},
|
|
9890
11250
|
fieldId
|
|
9891
11251
|
))
|