formanitor 0.0.39 → 0.0.41

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.mjs CHANGED
@@ -30,6 +30,326 @@ function fieldMetaRequestsMarMedicationOrdersButton(meta) {
30
30
  return meta[MAR_MEDICATION_ORDERS_META_KEY] === true;
31
31
  }
32
32
 
33
+ // src/core/urologyClinicalPathwayMetadata.ts
34
+ function isUrologyTemplate(template) {
35
+ if (!template || typeof template !== "object") return false;
36
+ const t = template;
37
+ return t.meta?.specialization === "urology" || t.specialization === "urology" || t.id === "uro_prescription";
38
+ }
39
+ function shouldFoldUrologyClinicalPathway(template, payload) {
40
+ if (isUrologyTemplate(template)) return true;
41
+ return Object.keys(payload).some(
42
+ (k) => k.startsWith("uro_") || k === "chief_complaints" || k === "chief_complaints_chips"
43
+ );
44
+ }
45
+ var UROLOGY_EXTRA_METADATA_KEYS = ["symptoms", "notes", "vitals"];
46
+ function isUroPlainObject(v) {
47
+ return v !== null && typeof v === "object" && !Array.isArray(v);
48
+ }
49
+ function coerceUrologyBool(value) {
50
+ if (value === true || value === false) return value;
51
+ if (value === "true") return true;
52
+ if (value === "false") return false;
53
+ if (Array.isArray(value)) {
54
+ if (value.includes("yes") || value.includes(true)) return true;
55
+ if (value.length === 0) return false;
56
+ }
57
+ return value;
58
+ }
59
+ function urologyIpssItem(v) {
60
+ const n = Number(v);
61
+ if (!Number.isFinite(n)) return 0;
62
+ return Math.min(5, Math.max(0, Math.round(n)));
63
+ }
64
+ function urologyIpssSevenTotalFromParts(ipss) {
65
+ return ipss.incomplete + ipss.frequency + ipss.intermittency + ipss.urgency + ipss.weakStream + ipss.straining + ipss.nocturia;
66
+ }
67
+ function buildUrologySmartHistoryFromLegacyFlat(flat) {
68
+ return {
69
+ socrates_pain_flank_suprapubic: {
70
+ site: flat.uro_sh_socrates_site,
71
+ onset: flat.uro_sh_socrates_onset,
72
+ character: flat.uro_sh_socrates_character,
73
+ radiation: flat.uro_sh_socrates_radiation,
74
+ associated: flat.uro_sh_socrates_associated,
75
+ timing: flat.uro_sh_socrates_timing,
76
+ exacerbating: flat.uro_sh_socrates_exacerbating,
77
+ severity_0_to_10: flat.uro_sh_socrates_severity
78
+ },
79
+ ipss_international_symptom_score: {
80
+ incomplete_emptying: flat.uro_sh_ipss_incomplete,
81
+ frequency_lt_2h: flat.uro_sh_ipss_frequency,
82
+ intermittency: flat.uro_sh_ipss_intermittency,
83
+ urgency: flat.uro_sh_ipss_urgency,
84
+ weak_stream: flat.uro_sh_ipss_weak_stream,
85
+ straining: flat.uro_sh_ipss_straining,
86
+ nocturia: flat.uro_sh_ipss_nocturia,
87
+ qol_0_to_6: flat.uro_sh_ipss_qol,
88
+ seven_item_total_computed_max_35: flat.uro_sh_ipss_total_display
89
+ },
90
+ haematuria_profile: {
91
+ present: flat.uro_sh_haem_present,
92
+ timing: flat.uro_sh_haem_timing,
93
+ painful: flat.uro_sh_haem_painful,
94
+ clots: flat.uro_sh_haem_clots
95
+ },
96
+ sexual_and_reproductive: {
97
+ erectile_function: flat.uro_sh_sex_erectile,
98
+ libido: flat.uro_sh_sex_libido,
99
+ ejaculation: flat.uro_sh_sex_ejaculation,
100
+ infertility_months: flat.uro_sh_sex_infertility_months
101
+ },
102
+ context_prior_stones_surgery_comorbidity: flat.uro_smart_notes_free ?? ""
103
+ };
104
+ }
105
+ function buildUrologySmartHistoryFromComposite(raw, flat) {
106
+ const soc = isUroPlainObject(raw.socrates) ? raw.socrates : {};
107
+ const ipssIn = isUroPlainObject(raw.ipss) ? raw.ipss : {};
108
+ const haem = isUroPlainObject(raw.haematuria) ? raw.haematuria : {};
109
+ const sex = isUroPlainObject(raw.sexual) ? raw.sexual : {};
110
+ const str2 = (x) => typeof x === "string" ? x : "";
111
+ const sev = Number(soc.severity);
112
+ const severity0to10 = Number.isFinite(sev) ? Math.min(10, Math.max(0, Math.round(sev))) : 0;
113
+ const ipss = {
114
+ incomplete: urologyIpssItem(ipssIn.incomplete),
115
+ frequency: urologyIpssItem(ipssIn.frequency),
116
+ intermittency: urologyIpssItem(ipssIn.intermittency),
117
+ urgency: urologyIpssItem(ipssIn.urgency),
118
+ weakStream: urologyIpssItem(
119
+ ipssIn.weakStream ?? ipssIn.weak_stream
120
+ ),
121
+ straining: urologyIpssItem(ipssIn.straining),
122
+ nocturia: urologyIpssItem(ipssIn.nocturia)
123
+ };
124
+ const sevenTotal = urologyIpssSevenTotalFromParts(ipss);
125
+ const qolRaw = Number(raw.ipssQoL);
126
+ const qol = Number.isFinite(qolRaw) ? Math.min(6, Math.max(0, Math.round(qolRaw))) : 0;
127
+ const timingRaw = str2(haem.timing);
128
+ const pastNotes = str2(raw.pastNotes);
129
+ const legacyNotes = flat.uro_smart_notes_free;
130
+ const contextPrior = pastNotes !== "" ? pastNotes : typeof legacyNotes === "string" ? legacyNotes : legacyNotes ?? "";
131
+ const infertilityRaw = Number(sex.infertilityMonths);
132
+ const infertilityMonths = Number.isFinite(infertilityRaw) ? Math.max(0, Math.round(infertilityRaw)) : 0;
133
+ return {
134
+ socrates_pain_flank_suprapubic: {
135
+ site: str2(soc.site),
136
+ onset: str2(soc.onset),
137
+ character: str2(soc.character),
138
+ radiation: str2(soc.radiation),
139
+ associated: str2(soc.associated),
140
+ timing: str2(soc.timing),
141
+ exacerbating: str2(soc.exacerbating),
142
+ severity_0_to_10: severity0to10
143
+ },
144
+ ipss_international_symptom_score: {
145
+ incomplete_emptying: ipss.incomplete,
146
+ frequency_lt_2h: ipss.frequency,
147
+ intermittency: ipss.intermittency,
148
+ urgency: ipss.urgency,
149
+ weak_stream: ipss.weakStream,
150
+ straining: ipss.straining,
151
+ nocturia: ipss.nocturia,
152
+ qol_0_to_6: qol,
153
+ seven_item_total_computed_max_35: sevenTotal
154
+ },
155
+ haematuria_profile: {
156
+ present: haem.present === true,
157
+ timing: timingRaw,
158
+ painful: haem.painful === true,
159
+ clots: haem.clots === true
160
+ },
161
+ sexual_and_reproductive: {
162
+ erectile_function: str2(sex.erectile),
163
+ libido: str2(sex.libido),
164
+ ejaculation: str2(sex.ejaculation),
165
+ infertility_months: infertilityMonths
166
+ },
167
+ context_prior_stones_surgery_comorbidity: contextPrior
168
+ };
169
+ }
170
+ function buildUrologyExaminationFromLegacyFlat(flat) {
171
+ return {
172
+ general: {
173
+ pallor: flat.uro_ex_general_pallor,
174
+ oedema: flat.uro_ex_general_oedema,
175
+ icterus: flat.uro_ex_general_icterus,
176
+ lymphadenopathy: flat.uro_ex_general_lymph
177
+ },
178
+ abdomen: {
179
+ distension: flat.uro_ex_ab_distension,
180
+ surgical_scars: flat.uro_ex_ab_scars,
181
+ visible_mass: flat.uro_ex_ab_mass,
182
+ kidney_palpable: flat.uro_ex_ab_kidney_palpable,
183
+ bladder_palpable: flat.uro_ex_ab_bladder_palpable,
184
+ renal_angle_tender: flat.uro_ex_ab_renal_angle_tender,
185
+ bladder_dullness_retention: flat.uro_ex_ab_bladder_dull
186
+ },
187
+ external_genitalia_scrotum: {
188
+ meatus_abnormal_hypospadias_query: flat.uro_ex_gu_meatus,
189
+ phimosis_paraphimosis: flat.uro_ex_gu_phimosis,
190
+ penile_lesions_ulcers: flat.uro_ex_gu_lesions,
191
+ scrotal_swelling: flat.uro_ex_gu_scrotal_swelling,
192
+ transilluminant: flat.uro_ex_gu_transilluminant,
193
+ tender_testis: flat.uro_ex_gu_tender_testis,
194
+ hydrocele: flat.uro_ex_gu_hydrocele,
195
+ varicocele: flat.uro_ex_gu_varicocele,
196
+ suspicious_mass_urgent: flat.uro_ex_gu_suspicious_mass
197
+ },
198
+ dre_prostate: {
199
+ dre_performed: flat.uro_ex_dre_done,
200
+ estimated_size_grams: flat.uro_ex_dre_size_g,
201
+ consistency: flat.uro_ex_dre_consistency,
202
+ median_sulcus: flat.uro_ex_dre_median_sulcus,
203
+ tenderness_prostatitis_query: flat.uro_ex_dre_tender
204
+ },
205
+ examination_notes_free_text: flat.uro_examination_notes ?? ""
206
+ };
207
+ }
208
+ function buildUrologyExaminationFromComposite(raw) {
209
+ const regions = Array.isArray(raw.regions) ? raw.regions.filter((x) => typeof x === "string") : [];
210
+ const g = isUroPlainObject(raw.general) ? raw.general : {};
211
+ const ab = isUroPlainObject(raw.abdomen) ? raw.abdomen : {};
212
+ const gu = isUroPlainObject(raw.gu) ? raw.gu : {};
213
+ const dr = isUroPlainObject(raw.dre) ? raw.dre : {};
214
+ const dreConsistency = typeof dr.consistency === "string" ? dr.consistency : "";
215
+ const dreMedian = typeof dr.medianSulcus === "string" ? dr.medianSulcus : typeof dr.median_sulcus === "string" ? dr.median_sulcus : "";
216
+ const sizeG = Number(dr.sizeGrams);
217
+ const sizeGrams = Number.isFinite(sizeG) && sizeG >= 0 ? Math.round(sizeG) : 0;
218
+ const notesRaw = raw.examinationNotes;
219
+ const notes = typeof notesRaw === "string" ? notesRaw : "";
220
+ const bool = (x) => x === true;
221
+ return {
222
+ regions_reviewed: regions,
223
+ general: {
224
+ pallor: bool(g.pallor),
225
+ oedema: bool(g.oedema),
226
+ icterus: bool(g.icterus),
227
+ lymphadenopathy: bool(g.lymphadenopathy)
228
+ },
229
+ abdomen: {
230
+ distension: bool(ab.distension),
231
+ surgical_scars: bool(ab.scars),
232
+ visible_mass: bool(ab.mass),
233
+ kidney_palpable: bool(ab.kidneyPalpable),
234
+ bladder_palpable: bool(ab.bladderPalpable),
235
+ renal_angle_tender: bool(ab.renalAngleTender),
236
+ bladder_dullness_retention: bool(ab.bladderDull)
237
+ },
238
+ external_genitalia_scrotum: {
239
+ meatus_abnormal_hypospadias_query: bool(gu.meatusAbnormal),
240
+ phimosis_paraphimosis: bool(gu.phimosis),
241
+ penile_lesions_ulcers: bool(gu.lesions),
242
+ scrotal_swelling: bool(gu.scrotalSwelling),
243
+ transilluminant: bool(gu.transilluminant),
244
+ tender_testis: bool(gu.tenderTestis),
245
+ hydrocele: bool(gu.hydrocele),
246
+ varicocele: bool(gu.varicocele),
247
+ suspicious_mass_urgent: bool(gu.suspiciousMass)
248
+ },
249
+ dre_prostate: {
250
+ dre_performed: bool(dr.done),
251
+ estimated_size_grams: sizeGrams,
252
+ consistency: dreConsistency === "none" ? "" : dreConsistency,
253
+ median_sulcus: dreMedian === "none" ? "" : dreMedian,
254
+ tenderness_prostatitis_query: bool(dr.tenderness)
255
+ },
256
+ examination_notes_free_text: notes
257
+ };
258
+ }
259
+ function buildUrologyDecisionEngineAndRisk(flat) {
260
+ const comp = flat.uro_pathway;
261
+ if (isUroPlainObject(comp)) {
262
+ const riskIn = isUroPlainObject(comp.risk) ? comp.risk : {};
263
+ return {
264
+ decision_engine: {
265
+ stone_disease: {
266
+ stone_size_mm: comp.stoneSizeMm ?? 0,
267
+ hydronephrosis_on_imaging: coerceUrologyBool(comp.hydronephrosis)
268
+ },
269
+ prostate_bph_flow_lab: {
270
+ prostate_volume_cc: comp.prostateVolumeCc ?? 0,
271
+ psa_ng_ml: comp.psaNgMl ?? 0,
272
+ uroflow_qmax_ml_s: comp.uroflowQmaxMlSec ?? 0
273
+ }
274
+ },
275
+ risk_stratification: {
276
+ ckd: coerceUrologyBool(riskIn.ckd),
277
+ diabetes: coerceUrologyBool(riskIn.diabetes),
278
+ anticoagulants: coerceUrologyBool(riskIn.anticoagulants),
279
+ active_infection: coerceUrologyBool(riskIn.activeInfection)
280
+ }
281
+ };
282
+ }
283
+ return {
284
+ decision_engine: {
285
+ stone_disease: {
286
+ stone_size_mm: flat.uro_stone_size_mm,
287
+ hydronephrosis_on_imaging: coerceUrologyBool(flat.uro_stone_hydronephrosis)
288
+ },
289
+ prostate_bph_flow_lab: {
290
+ prostate_volume_cc: flat.uro_prostate_vol_cc,
291
+ psa_ng_ml: flat.uro_psa_ng_ml,
292
+ uroflow_qmax_ml_s: flat.uro_flow_qmax
293
+ }
294
+ },
295
+ risk_stratification: {
296
+ ckd: coerceUrologyBool(flat.uro_risk_ckd),
297
+ diabetes: coerceUrologyBool(flat.uro_risk_diabetes),
298
+ anticoagulants: coerceUrologyBool(flat.uro_risk_anticoag),
299
+ active_infection: coerceUrologyBool(flat.uro_risk_active_infection)
300
+ }
301
+ };
302
+ }
303
+ function attachUrologyClinicalPathwayMetadata(payload, template) {
304
+ if (!shouldFoldUrologyClinicalPathway(template, payload)) return;
305
+ const extra = UROLOGY_EXTRA_METADATA_KEYS;
306
+ const keys = Object.keys(payload).filter(
307
+ (k) => k.startsWith("uro_") || k === "chief_complaints" || k === "chief_complaints_chips" || extra.includes(k)
308
+ );
309
+ if (keys.length === 0) return;
310
+ const flat = {};
311
+ for (const k of keys) {
312
+ flat[k] = payload[k];
313
+ delete payload[k];
314
+ }
315
+ const triage = flat.uro_triage;
316
+ const chiefComplaints = {
317
+ narrative: flat.chief_complaints ?? "",
318
+ chips: flat.chief_complaints_chips ?? [],
319
+ duration: flat.uro_chief_duration ?? "",
320
+ onset: flat.uro_chief_onset ?? "",
321
+ progression: flat.uro_chief_progression ?? "",
322
+ active_syndrome: flat.uro_active_syndrome ?? ""
323
+ };
324
+ const compositeSh = flat.uro_smart_history;
325
+ const compositeEx = flat.uro_examination;
326
+ const smart_history = isUroPlainObject(compositeSh) ? buildUrologySmartHistoryFromComposite(compositeSh, flat) : buildUrologySmartHistoryFromLegacyFlat(flat);
327
+ const examination = isUroPlainObject(compositeEx) ? buildUrologyExaminationFromComposite(compositeEx) : buildUrologyExaminationFromLegacyFlat(flat);
328
+ const { decision_engine, risk_stratification } = buildUrologyDecisionEngineAndRisk(flat);
329
+ const structured = {
330
+ triage_vas_and_flags: triage ?? null,
331
+ chief_complaint_engine: chiefComplaints,
332
+ smart_history,
333
+ examination,
334
+ pathway_triggers_objective_scores: decision_engine,
335
+ risk_stratification,
336
+ encounter_narrative: {
337
+ symptoms: flat.symptoms ?? "",
338
+ notes: flat.notes ?? "",
339
+ vitals: flat.vitals ?? ""
340
+ }
341
+ };
342
+ const existingMetadata = payload.metadata ?? {};
343
+ const existingPathways = existingMetadata.clinical_pathways ?? {};
344
+ payload.metadata = {
345
+ ...existingMetadata,
346
+ clinical_pathways: {
347
+ ...existingPathways,
348
+ urology: structured
349
+ }
350
+ };
351
+ }
352
+
33
353
  // src/core/validate.ts
34
354
  var EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
35
355
  function validateField(value, field) {
@@ -225,8 +545,21 @@ var defaultGeneralSurgerySmartHistory = () => ({
225
545
  gi: { appetite: "", weightLoss: "", bowelHabits: "", checks: [] },
226
546
  breast: { lumpDuration: "", nippleDischarge: "", checks: [] },
227
547
  ano: { checks: [] },
228
- thyroid: { swellingDuration: "", checks: [] },
229
- systemic: ""
548
+ thyroid: { swellingDuration: "", checks: [] }
549
+ });
550
+ var defaultBreastExamSide = () => ({
551
+ size: "",
552
+ quadrant: "",
553
+ tenderness: "",
554
+ fixity: "",
555
+ skinInvolvement: "",
556
+ consistency: "",
557
+ axillaryNodes: false,
558
+ nippleAreolarComplex: false
559
+ });
560
+ var defaultBreastExaminationBlock = () => ({
561
+ left: defaultBreastExamSide(),
562
+ right: defaultBreastExamSide()
230
563
  });
231
564
  var defaultGeneralSurgeryExamination = () => ({
232
565
  general: [],
@@ -239,7 +572,7 @@ var defaultGeneralSurgeryExamination = () => ({
239
572
  bowelSounds: "none"
240
573
  },
241
574
  hernia: { site: "", reducible: false, coughImpulse: false, tenderness: false },
242
- breast: { lumpSizeCm: "", mobile: false, skinInvolvement: false, axillaryNodes: false },
575
+ breast: defaultBreastExaminationBlock(),
243
576
  thyroid: { size: "", mobileDeglutition: false, nodules: false, cervicalNodes: false },
244
577
  anorectal: { inspection: "", dreDone: false, proctoscopyDone: false, notes: "" },
245
578
  limb: { dilatedVeins: false, ulcer: false, oedema: false }
@@ -335,8 +668,32 @@ function normalizeGeneralSurgerySmartHistory(raw) {
335
668
  thyroid: {
336
669
  swellingDuration: str2(thy.swellingDuration),
337
670
  checks: strArr(thy.checks)
338
- },
339
- systemic: typeof v.systemic === "string" ? v.systemic : d.systemic
671
+ }
672
+ };
673
+ }
674
+ function normalizeBreastExamSide(partial) {
675
+ const e = defaultBreastExamSide();
676
+ const str2 = (x) => typeof x === "string" ? x : "";
677
+ const bool = (x) => x === true;
678
+ if (!partial || typeof partial !== "object") return e;
679
+ const p = partial;
680
+ return {
681
+ size: str2(p.size),
682
+ quadrant: str2(p.quadrant),
683
+ tenderness: str2(p.tenderness),
684
+ fixity: str2(p.fixity),
685
+ skinInvolvement: str2(p.skinInvolvement),
686
+ consistency: str2(p.consistency),
687
+ axillaryNodes: bool(p.axillaryNodes),
688
+ nippleAreolarComplex: bool(p.nippleAreolarComplex)
689
+ };
690
+ }
691
+ function normalizeBreastExaminationBlock(raw) {
692
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return defaultBreastExaminationBlock();
693
+ const br = raw;
694
+ return {
695
+ left: normalizeBreastExamSide(br.left),
696
+ right: normalizeBreastExamSide(br.right)
340
697
  };
341
698
  }
342
699
  function normalizeGeneralSurgeryExamination(raw) {
@@ -369,12 +726,7 @@ function normalizeGeneralSurgeryExamination(raw) {
369
726
  coughImpulse: bool(hb.coughImpulse),
370
727
  tenderness: bool(hb.tenderness)
371
728
  },
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
- },
729
+ breast: normalizeBreastExaminationBlock(br),
378
730
  thyroid: {
379
731
  size: typeof th.size === "string" ? th.size : "",
380
732
  mobileDeglutition: bool(th.mobileDeglutition),
@@ -412,6 +764,486 @@ function gsGradingRowVisible(cond, chips, regions, grade) {
412
764
  if (t.regions.some((r) => regions.includes(r))) return true;
413
765
  return false;
414
766
  }
767
+ var SWELLING_OPT_LABELS = {
768
+ reducible_hernia: "Reducible (hernia)",
769
+ cough_impulse: "Cough impulse",
770
+ skin_changes: "Skin changes"
771
+ };
772
+ var GI_OPT_LABELS = {
773
+ bleeding_pr: "Bleeding PR",
774
+ vomiting: "Vomiting",
775
+ haematemesis: "Haematemesis"
776
+ };
777
+ var BREAST_OPT_LABELS = {
778
+ pain: "Pain",
779
+ fh_ca_breast: "Family history of Ca breast"
780
+ };
781
+ var ANO_OPT_LABELS = {
782
+ pain_defecation: "Pain during defecation",
783
+ bleeding: "Bleeding",
784
+ constipation: "Constipation",
785
+ discharge: "Discharge"
786
+ };
787
+ var THYROID_OPT_LABELS = {
788
+ dysphagia: "Dysphagia",
789
+ voice_change: "Voice change",
790
+ thyrotoxicosis: "Thyrotoxicosis symptoms"
791
+ };
792
+ var SOCRATES_LABELS = {
793
+ site: "Site",
794
+ onset: "Onset",
795
+ character: "Character",
796
+ radiation: "Radiation",
797
+ associated: "Associated",
798
+ timing: "Timing",
799
+ exacerbating: "Exacerbating / relieving"
800
+ };
801
+ var GENERAL_EXAM_LABELS = {
802
+ pallor: "Pallor",
803
+ icterus: "Icterus",
804
+ cyanosis: "Cyanosis",
805
+ clubbing: "Clubbing",
806
+ lymphadenopathy: "Lymphadenopathy",
807
+ oedema: "Oedema"
808
+ };
809
+ var REGION_EXAM_LABELS = {
810
+ abdomen: "Abdomen",
811
+ hernia: "Hernia",
812
+ breast: "Breast",
813
+ thyroid: "Thyroid",
814
+ anorectal: "Anorectal",
815
+ limb: "Limb / varicose"
816
+ };
817
+ var ABD_INSP_LABELS = {
818
+ distension: "Distension",
819
+ scars: "Scars",
820
+ visible_peristalsis: "Visible peristalsis"
821
+ };
822
+ var ABD_PALP_LABELS = {
823
+ tenderness: "Tenderness",
824
+ guarding: "Guarding",
825
+ rigidity: "Rigidity",
826
+ mass: "Palpable mass"
827
+ };
828
+ var ABD_PERC_LABELS = {
829
+ tympany: "Tympany",
830
+ shifting_dullness: "Shifting dullness"
831
+ };
832
+ function trimLine(s) {
833
+ return s.replace(/\s+/g, " ").trim();
834
+ }
835
+ var SK_ORDER = ["site", "onset", "character", "radiation", "associated", "timing", "exacerbating"];
836
+ function formatGeneralSurgerySmartHistoryToNarrative(v, chips) {
837
+ const blocks = [];
838
+ const showPain = chips.includes("pain");
839
+ const showSwelling = chips.includes("swelling_lump");
840
+ const showGI = chips.includes("bleeding") || chips.includes("obstruction");
841
+ const showBreast = chips.includes("breast");
842
+ const showAno = chips.includes("anorectal");
843
+ const showThyroid = chips.includes("thyroid");
844
+ if (showPain) {
845
+ const painLines = [];
846
+ for (const key of SK_ORDER) {
847
+ const raw = v.pain[key];
848
+ if (typeof raw === "string" && raw.trim()) {
849
+ painLines.push(`${SOCRATES_LABELS[key]}: ${trimLine(raw)}`);
850
+ }
851
+ }
852
+ if (v.pain.severity > 0) {
853
+ painLines.push(`Severity (0\u201310): ${v.pain.severity}`);
854
+ }
855
+ if (painLines.length > 0) {
856
+ blocks.push(["SOCRATES \u2014 pain", ...painLines.map((l) => `\u2022 ${l}`)].join("\n"));
857
+ }
858
+ }
859
+ if (showSwelling) {
860
+ const parts = [];
861
+ if (v.swelling.duration.trim()) parts.push(`Duration: ${trimLine(v.swelling.duration)}`);
862
+ if (v.swelling.sizeProgression.trim())
863
+ parts.push(`Size progression: ${trimLine(v.swelling.sizeProgression)}`);
864
+ if (v.swelling.painfulPainless.trim())
865
+ parts.push(`Painful / painless: ${trimLine(v.swelling.painfulPainless)}`);
866
+ for (const c of v.swelling.checks) {
867
+ const lb = SWELLING_OPT_LABELS[c] ?? c;
868
+ parts.push(lb);
869
+ }
870
+ if (parts.length > 0) {
871
+ blocks.push(["Swelling history", ...parts.map((p) => `\u2022 ${p}`)].join("\n"));
872
+ }
873
+ }
874
+ if (showGI) {
875
+ const parts = [];
876
+ if (v.gi.appetite.trim()) parts.push(`Appetite: ${trimLine(v.gi.appetite)}`);
877
+ if (v.gi.weightLoss.trim()) parts.push(`Weight loss: ${trimLine(v.gi.weightLoss)}`);
878
+ if (v.gi.bowelHabits.trim()) parts.push(`Bowel habits: ${trimLine(v.gi.bowelHabits)}`);
879
+ for (const c of v.gi.checks) {
880
+ parts.push(GI_OPT_LABELS[c] ?? c);
881
+ }
882
+ if (parts.length > 0) {
883
+ blocks.push(["GI history", ...parts.map((p) => `\u2022 ${p}`)].join("\n"));
884
+ }
885
+ }
886
+ if (showBreast) {
887
+ const parts = [];
888
+ if (v.breast.lumpDuration.trim()) parts.push(`Lump duration: ${trimLine(v.breast.lumpDuration)}`);
889
+ if (v.breast.nippleDischarge.trim())
890
+ parts.push(`Nipple discharge: ${trimLine(v.breast.nippleDischarge)}`);
891
+ for (const c of v.breast.checks) {
892
+ parts.push(BREAST_OPT_LABELS[c] ?? c);
893
+ }
894
+ if (parts.length > 0) {
895
+ blocks.push(["Breast history", ...parts.map((p) => `\u2022 ${p}`)].join("\n"));
896
+ }
897
+ }
898
+ if (showAno) {
899
+ const parts = [];
900
+ for (const c of v.ano.checks) {
901
+ parts.push(ANO_OPT_LABELS[c] ?? c);
902
+ }
903
+ if (parts.length > 0) {
904
+ blocks.push(["Anorectal history", ...parts.map((p) => `\u2022 ${p}`)].join("\n"));
905
+ }
906
+ }
907
+ if (showThyroid) {
908
+ const parts = [];
909
+ if (v.thyroid.swellingDuration.trim())
910
+ parts.push(`Swelling duration: ${trimLine(v.thyroid.swellingDuration)}`);
911
+ for (const c of v.thyroid.checks) {
912
+ parts.push(THYROID_OPT_LABELS[c] ?? c);
913
+ }
914
+ if (parts.length > 0) {
915
+ blocks.push(["Thyroid history", ...parts.map((p) => `\u2022 ${p}`)].join("\n"));
916
+ }
917
+ }
918
+ return blocks.join("\n\n");
919
+ }
920
+ var BOWEL_SOUND_LABELS = {
921
+ none: "\u2014",
922
+ normal: "Normal",
923
+ up: "Increased (\u2191)",
924
+ down: "Decreased (\u2193)",
925
+ absent: "Absent"
926
+ };
927
+ function formatGeneralSurgeryExaminationToNarrative(v) {
928
+ const blocks = [];
929
+ const generalPositive = v.general.map((k) => GENERAL_EXAM_LABELS[k] ?? k).filter(Boolean);
930
+ if (generalPositive.length > 0) {
931
+ blocks.push(
932
+ ["General examination", ...generalPositive.map((g) => `\u2022 ${g}`)].join("\n")
933
+ );
934
+ }
935
+ if (v.regions.length > 0) {
936
+ const names = v.regions.map((r) => REGION_EXAM_LABELS[r] ?? r);
937
+ blocks.push(`Regional examination: ${names.join(", ")}`);
938
+ }
939
+ if (v.regions.includes("abdomen")) {
940
+ const sub = [];
941
+ const ins = v.abdomen.inspection.map((x) => ABD_INSP_LABELS[x] ?? x);
942
+ const pal = v.abdomen.palpation.map((x) => ABD_PALP_LABELS[x] ?? x);
943
+ const per = v.abdomen.percussion.map((x) => ABD_PERC_LABELS[x] ?? x);
944
+ if (ins.length) sub.push(`Inspection: ${ins.join(", ")}`);
945
+ if (pal.length) sub.push(`Palpation: ${pal.join(", ")}`);
946
+ if (v.abdomen.massNotes.trim()) sub.push(`Mass / mobility: ${trimLine(v.abdomen.massNotes)}`);
947
+ if (per.length) sub.push(`Percussion: ${per.join(", ")}`);
948
+ const bs = BOWEL_SOUND_LABELS[v.abdomen.bowelSounds];
949
+ if (v.abdomen.bowelSounds !== "none") {
950
+ sub.push(`Bowel sounds: ${bs}`);
951
+ }
952
+ if (sub.length > 0) {
953
+ blocks.push(["Abdomen", ...sub.map((s) => `\u2022 ${s}`)].join("\n"));
954
+ }
955
+ }
956
+ if (v.regions.includes("hernia")) {
957
+ const sub = [];
958
+ if (v.hernia.site.trim()) sub.push(`Site: ${trimLine(v.hernia.site)}`);
959
+ if (v.hernia.reducible) sub.push("Reducible");
960
+ if (v.hernia.coughImpulse) sub.push("Cough impulse positive");
961
+ if (v.hernia.tenderness) sub.push("Tenderness");
962
+ if (sub.length > 0) {
963
+ blocks.push(["Hernia", ...sub.map((s) => `\u2022 ${s}`)].join("\n"));
964
+ }
965
+ }
966
+ if (v.regions.includes("breast")) {
967
+ const sub = [];
968
+ const appendSide = (label, s) => {
969
+ const lines = [];
970
+ if (s.size.trim()) lines.push(`Size: ${trimLine(s.size)}`);
971
+ if (s.quadrant.trim()) lines.push(`Quadrant: ${trimLine(s.quadrant)}`);
972
+ if (s.tenderness.trim()) lines.push(`Tenderness: ${trimLine(s.tenderness)}`);
973
+ if (s.fixity.trim()) lines.push(`Fixity: ${trimLine(s.fixity)}`);
974
+ if (s.skinInvolvement.trim()) lines.push(`Skin involvement: ${trimLine(s.skinInvolvement)}`);
975
+ if (s.consistency.trim()) lines.push(`Consistency: ${trimLine(s.consistency)}`);
976
+ if (s.axillaryNodes) lines.push("Axillary nodes");
977
+ if (s.nippleAreolarComplex) lines.push("Nipple-areolar complex");
978
+ if (lines.length > 0) {
979
+ sub.push(`${label}: ${lines.join("; ")}`);
980
+ }
981
+ };
982
+ appendSide("Left breast", v.breast.left);
983
+ appendSide("Right breast", v.breast.right);
984
+ if (sub.length > 0) {
985
+ blocks.push(["Breast", ...sub.map((s) => `\u2022 ${s}`)].join("\n"));
986
+ }
987
+ }
988
+ if (v.regions.includes("thyroid")) {
989
+ const sub = [];
990
+ if (v.thyroid.size.trim()) sub.push(`Size: ${trimLine(v.thyroid.size)}`);
991
+ if (v.thyroid.mobileDeglutition) sub.push("Mobile with deglutition");
992
+ if (v.thyroid.nodules) sub.push("Nodules");
993
+ if (v.thyroid.cervicalNodes) sub.push("Cervical lymph nodes");
994
+ if (sub.length > 0) {
995
+ blocks.push(["Thyroid", ...sub.map((s) => `\u2022 ${s}`)].join("\n"));
996
+ }
997
+ }
998
+ if (v.regions.includes("anorectal")) {
999
+ const sub = [];
1000
+ if (v.anorectal.inspection.trim())
1001
+ sub.push(`Inspection: ${trimLine(v.anorectal.inspection)}`);
1002
+ if (v.anorectal.dreDone) sub.push("DRE done");
1003
+ if (v.anorectal.proctoscopyDone) sub.push("Proctoscopy done");
1004
+ if (v.anorectal.notes.trim()) sub.push(`DRE / proctoscopy notes: ${trimLine(v.anorectal.notes)}`);
1005
+ if (sub.length > 0) {
1006
+ blocks.push(["Anorectal", ...sub.map((s) => `\u2022 ${s}`)].join("\n"));
1007
+ }
1008
+ }
1009
+ if (v.regions.includes("limb")) {
1010
+ const sub = [];
1011
+ if (v.limb.dilatedVeins) sub.push("Dilated veins");
1012
+ if (v.limb.ulcer) sub.push("Ulcer");
1013
+ if (v.limb.oedema) sub.push("Oedema");
1014
+ if (sub.length > 0) {
1015
+ blocks.push(["Limb / varicose", ...sub.map((s) => `\u2022 ${s}`)].join("\n"));
1016
+ }
1017
+ }
1018
+ return blocks.join("\n\n");
1019
+ }
1020
+
1021
+ // src/core/urologyPathway.ts
1022
+ var defaultUrologySmartHistory = () => ({
1023
+ socrates: {
1024
+ site: "",
1025
+ onset: "",
1026
+ character: "",
1027
+ radiation: "",
1028
+ associated: "",
1029
+ timing: "",
1030
+ exacerbating: "",
1031
+ severity: 0
1032
+ },
1033
+ ipss: {
1034
+ incomplete: 0,
1035
+ frequency: 0,
1036
+ intermittency: 0,
1037
+ urgency: 0,
1038
+ weakStream: 0,
1039
+ straining: 0,
1040
+ nocturia: 0
1041
+ },
1042
+ ipssQoL: 0,
1043
+ haematuria: { present: false, timing: "", painful: false, clots: false },
1044
+ sexual: { erectile: "", libido: "", ejaculation: "", infertilityMonths: 0 },
1045
+ pastNotes: ""
1046
+ });
1047
+ var defaultUrologyExamination = () => ({
1048
+ regions: [],
1049
+ general: { pallor: false, oedema: false, icterus: false, lymphadenopathy: false },
1050
+ abdomen: {
1051
+ distension: false,
1052
+ scars: false,
1053
+ mass: false,
1054
+ kidneyPalpable: false,
1055
+ bladderPalpable: false,
1056
+ renalAngleTender: false,
1057
+ bladderDull: false
1058
+ },
1059
+ gu: {
1060
+ meatusAbnormal: false,
1061
+ phimosis: false,
1062
+ lesions: false,
1063
+ scrotalSwelling: false,
1064
+ transilluminant: false,
1065
+ tenderTestis: false,
1066
+ hydrocele: false,
1067
+ varicocele: false,
1068
+ suspiciousMass: false
1069
+ },
1070
+ dre: { done: false, sizeGrams: 0, consistency: "", medianSulcus: "", tenderness: false },
1071
+ examinationNotes: ""
1072
+ });
1073
+ function clampInt(n, lo, hi) {
1074
+ if (!Number.isFinite(n)) return lo;
1075
+ return Math.min(hi, Math.max(lo, Math.round(n)));
1076
+ }
1077
+ var SOCRATES_KEYS = [
1078
+ "site",
1079
+ "onset",
1080
+ "character",
1081
+ "radiation",
1082
+ "associated",
1083
+ "timing",
1084
+ "exacerbating"
1085
+ ];
1086
+ function urologyIpssSevenTotal(ipss) {
1087
+ return ipss.incomplete + ipss.frequency + ipss.intermittency + ipss.urgency + ipss.weakStream + ipss.straining + ipss.nocturia;
1088
+ }
1089
+ function urologyIpssBand(total) {
1090
+ if (total <= 7) return "Mild";
1091
+ if (total <= 19) return "Moderate";
1092
+ return "Severe";
1093
+ }
1094
+ function normalizeUrologySmartHistory(raw) {
1095
+ const d = defaultUrologySmartHistory();
1096
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return d;
1097
+ const v = raw;
1098
+ const socIn = v.socrates && typeof v.socrates === "object" ? v.socrates : {};
1099
+ const socrates = { ...d.socrates };
1100
+ for (const k of SOCRATES_KEYS) {
1101
+ const x = socIn[k];
1102
+ socrates[k] = typeof x === "string" ? x : "";
1103
+ }
1104
+ const sev = Number(socIn.severity);
1105
+ socrates.severity = clampInt(Number.isFinite(sev) ? sev : d.socrates.severity, 0, 10);
1106
+ const ipIn = v.ipss && typeof v.ipss === "object" ? v.ipss : {};
1107
+ const ipss = { ...d.ipss };
1108
+ for (const k of [
1109
+ "incomplete",
1110
+ "frequency",
1111
+ "intermittency",
1112
+ "urgency",
1113
+ "weakStream",
1114
+ "straining",
1115
+ "nocturia"
1116
+ ]) {
1117
+ const n = Number(ipIn[k]);
1118
+ ipss[k] = clampInt(Number.isFinite(n) ? n : 0, 0, 5);
1119
+ }
1120
+ const qol = Number(v.ipssQoL);
1121
+ const ipssQoL = clampInt(Number.isFinite(qol) ? qol : d.ipssQoL, 0, 6);
1122
+ const haIn = v.haematuria && typeof v.haematuria === "object" ? v.haematuria : {};
1123
+ const timingRaw = haIn.timing;
1124
+ const haematuria = {
1125
+ present: haIn.present === true,
1126
+ timing: typeof timingRaw === "string" && timingRaw !== "none" && timingRaw.length > 0 ? timingRaw : "",
1127
+ painful: haIn.painful === true,
1128
+ clots: haIn.clots === true
1129
+ };
1130
+ const sxIn = v.sexual && typeof v.sexual === "object" ? v.sexual : {};
1131
+ const str2 = (x) => typeof x === "string" && x.length > 0 && x !== "none" ? x : "";
1132
+ const inf = Number(sxIn.infertilityMonths);
1133
+ const sexual = {
1134
+ erectile: str2(sxIn.erectile),
1135
+ libido: str2(sxIn.libido),
1136
+ ejaculation: str2(sxIn.ejaculation),
1137
+ infertilityMonths: Number.isFinite(inf) && inf >= 0 ? Math.round(inf) : 0
1138
+ };
1139
+ const pastNotes = typeof v.pastNotes === "string" ? v.pastNotes : d.pastNotes;
1140
+ return { socrates, ipss, ipssQoL, haematuria, sexual, pastNotes };
1141
+ }
1142
+ function normalizeUrologyExamination(raw) {
1143
+ const d = defaultUrologyExamination();
1144
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return d;
1145
+ const v = raw;
1146
+ const strArr = (x) => Array.isArray(x) ? x.filter((i) => typeof i === "string") : [];
1147
+ const bool = (x) => x === true;
1148
+ const g = v.general && typeof v.general === "object" ? v.general : {};
1149
+ const ab = v.abdomen && typeof v.abdomen === "object" ? v.abdomen : {};
1150
+ const gu = v.gu && typeof v.gu === "object" ? v.gu : {};
1151
+ const dr = v.dre && typeof v.dre === "object" ? v.dre : {};
1152
+ const sg = Number(dr.sizeGrams);
1153
+ const consistencyRaw = dr.consistency;
1154
+ const medianRaw = dr.medianSulcus;
1155
+ const dreEmpty = (x) => !(typeof x === "string" && x.length > 0 && x !== "none");
1156
+ return {
1157
+ regions: strArr(v.regions),
1158
+ general: {
1159
+ pallor: bool(g.pallor),
1160
+ oedema: bool(g.oedema),
1161
+ icterus: bool(g.icterus),
1162
+ lymphadenopathy: bool(g.lymphadenopathy)
1163
+ },
1164
+ abdomen: {
1165
+ distension: bool(ab.distension),
1166
+ scars: bool(ab.scars),
1167
+ mass: bool(ab.mass),
1168
+ kidneyPalpable: bool(ab.kidneyPalpable),
1169
+ bladderPalpable: bool(ab.bladderPalpable),
1170
+ renalAngleTender: bool(ab.renalAngleTender),
1171
+ bladderDull: bool(ab.bladderDull)
1172
+ },
1173
+ gu: {
1174
+ meatusAbnormal: bool(gu.meatusAbnormal),
1175
+ phimosis: bool(gu.phimosis),
1176
+ lesions: bool(gu.lesions),
1177
+ scrotalSwelling: bool(gu.scrotalSwelling),
1178
+ transilluminant: bool(gu.transilluminant),
1179
+ tenderTestis: bool(gu.tenderTestis),
1180
+ hydrocele: bool(gu.hydrocele),
1181
+ varicocele: bool(gu.varicocele),
1182
+ suspiciousMass: bool(gu.suspiciousMass)
1183
+ },
1184
+ dre: {
1185
+ done: bool(dr.done),
1186
+ sizeGrams: Number.isFinite(sg) && sg >= 0 ? Math.round(sg) : 0,
1187
+ consistency: dreEmpty(consistencyRaw) ? "" : String(consistencyRaw),
1188
+ medianSulcus: dreEmpty(medianRaw) ? "" : String(medianRaw),
1189
+ tenderness: bool(dr.tenderness)
1190
+ },
1191
+ examinationNotes: typeof v.examinationNotes === "string" ? v.examinationNotes : d.examinationNotes
1192
+ };
1193
+ }
1194
+ var defaultUrologyPathway = () => ({
1195
+ stoneSizeMm: 0,
1196
+ hydronephrosis: false,
1197
+ prostateVolumeCc: 0,
1198
+ psaNgMl: 0,
1199
+ uroflowQmaxMlSec: 0,
1200
+ risk: {
1201
+ ckd: false,
1202
+ diabetes: false,
1203
+ anticoagulants: false,
1204
+ activeInfection: false
1205
+ }
1206
+ });
1207
+ function clampNonNegativeNumber(x, fallback) {
1208
+ const n = Number(x);
1209
+ if (!Number.isFinite(n) || n < 0) return fallback;
1210
+ return n;
1211
+ }
1212
+ function normalizeUrologyPathway(raw) {
1213
+ const d = defaultUrologyPathway();
1214
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return d;
1215
+ const v = raw;
1216
+ const rIn = v.risk && typeof v.risk === "object" && !Array.isArray(v.risk) ? v.risk : {};
1217
+ return {
1218
+ stoneSizeMm: clampNonNegativeNumber(v.stoneSizeMm, d.stoneSizeMm),
1219
+ hydronephrosis: v.hydronephrosis === true,
1220
+ prostateVolumeCc: clampNonNegativeNumber(v.prostateVolumeCc, d.prostateVolumeCc),
1221
+ psaNgMl: clampNonNegativeNumber(v.psaNgMl, d.psaNgMl),
1222
+ uroflowQmaxMlSec: clampNonNegativeNumber(v.uroflowQmaxMlSec, d.uroflowQmaxMlSec),
1223
+ risk: {
1224
+ ckd: rIn.ckd === true,
1225
+ diabetes: rIn.diabetes === true,
1226
+ anticoagulants: rIn.anticoagulants === true,
1227
+ activeInfection: rIn.activeInfection === true
1228
+ }
1229
+ };
1230
+ }
1231
+ function urologyStoneRecommendation(sizeMm, hydronephrosis) {
1232
+ if (sizeMm <= 0) return { plan: "Enter stone size to auto-trigger plan.", surgical: false };
1233
+ if (sizeMm < 5) return { plan: "Conservative + MET (\u03B1-blocker), hydration", surgical: false };
1234
+ if (sizeMm <= 10)
1235
+ return {
1236
+ plan: hydronephrosis ? "URS / SWL \u2014 obstruction present" : "Medical expulsive therapy / URS",
1237
+ surgical: hydronephrosis
1238
+ };
1239
+ return { plan: "URS / PCNL \u2014 surgical clearance indicated", surgical: true };
1240
+ }
1241
+ function urologyProstateProcedure(volumeCc) {
1242
+ if (volumeCc <= 0) return "Enter prostate volume.";
1243
+ if (volumeCc < 30) return "Medical (\u03B1-blocker \xB1 5-ARI)";
1244
+ if (volumeCc <= 80) return "TURP";
1245
+ return "HoLEP / Open simple prostatectomy";
1246
+ }
415
1247
 
416
1248
  // src/core/painScaleFlags.ts
417
1249
  function normalizePainScaleFlags(raw, bounds) {
@@ -531,6 +1363,12 @@ var FormStore = class {
531
1363
  f.defaultValue ?? { pain: f.min ?? 0, flags: [] },
532
1364
  { min: f.min, max: f.max }
533
1365
  );
1366
+ } else if (field.type === "urology_smart_history") {
1367
+ values[field.id] = field.defaultValue ?? defaultUrologySmartHistory();
1368
+ } else if (field.type === "urology_examination") {
1369
+ values[field.id] = field.defaultValue ?? defaultUrologyExamination();
1370
+ } else if (field.type === "urology_pathway") {
1371
+ values[field.id] = field.defaultValue ?? defaultUrologyPathway();
534
1372
  } else values[field.id] = null;
535
1373
  }
536
1374
  });
@@ -740,6 +1578,7 @@ var FormStore = class {
740
1578
  }
741
1579
  }
742
1580
  });
1581
+ attachUrologyClinicalPathwayMetadata(result, this.schema);
743
1582
  return result;
744
1583
  }
745
1584
  // --- Core Logic ---
@@ -5712,7 +6551,7 @@ function safeJsonParse(val) {
5712
6551
  return null;
5713
6552
  }
5714
6553
  }
5715
- function clampInt(val, min, max) {
6554
+ function clampInt2(val, min, max) {
5716
6555
  if (!Number.isFinite(val)) return min;
5717
6556
  return Math.max(min, Math.min(max, Math.trunc(val)));
5718
6557
  }
@@ -5722,10 +6561,10 @@ function parseLegacyString(input) {
5722
6561
  if (gpalMatch) {
5723
6562
  const [, g, p, a, l] = gpalMatch;
5724
6563
  result.gpal = {
5725
- G: clampInt(Number(g), 0, 20),
5726
- P: clampInt(Number(p), 0, 20),
5727
- A: clampInt(Number(a), 0, 20),
5728
- L: clampInt(Number(l), 0, 20)
6564
+ G: clampInt2(Number(g), 0, 20),
6565
+ P: clampInt2(Number(p), 0, 20),
6566
+ A: clampInt2(Number(a), 0, 20),
6567
+ L: clampInt2(Number(l), 0, 20)
5729
6568
  };
5730
6569
  }
5731
6570
  const lmpMatch = input.match(/LMP:\s*([^\n]+)/i);
@@ -5758,10 +6597,10 @@ function normalizeToDraft(value) {
5758
6597
  isNewEntry: false,
5759
6598
  draft: {
5760
6599
  gpal: {
5761
- G: clampInt(Number(gpal.G ?? 0), 0, 20),
5762
- P: clampInt(Number(gpal.P ?? 0), 0, 20),
5763
- A: clampInt(Number(gpal.A ?? 0), 0, 20),
5764
- L: clampInt(Number(gpal.L ?? 0), 0, 20)
6600
+ G: clampInt2(Number(gpal.G ?? 0), 0, 20),
6601
+ P: clampInt2(Number(gpal.P ?? 0), 0, 20),
6602
+ A: clampInt2(Number(gpal.A ?? 0), 0, 20),
6603
+ L: clampInt2(Number(gpal.L ?? 0), 0, 20)
5765
6604
  },
5766
6605
  lmp: typeof lmp === "string" ? lmp : "",
5767
6606
  is_pregnant,
@@ -5779,10 +6618,10 @@ function normalizeToDraft(value) {
5779
6618
  }
5780
6619
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
5781
6620
  const gpalFromFlat = {
5782
- G: clampInt(Number(parsed.G ?? parsed.g ?? 0), 0, 20),
5783
- P: clampInt(Number(parsed.P ?? parsed.p ?? 0), 0, 20),
5784
- A: clampInt(Number(parsed.A ?? parsed.a ?? 0), 0, 20),
5785
- L: clampInt(Number(parsed.L ?? parsed.l ?? 0), 0, 20)
6621
+ G: clampInt2(Number(parsed.G ?? parsed.g ?? 0), 0, 20),
6622
+ P: clampInt2(Number(parsed.P ?? parsed.p ?? 0), 0, 20),
6623
+ A: clampInt2(Number(parsed.A ?? parsed.a ?? 0), 0, 20),
6624
+ L: clampInt2(Number(parsed.L ?? parsed.l ?? 0), 0, 20)
5786
6625
  };
5787
6626
  return {
5788
6627
  isNewEntry: false,
@@ -5934,7 +6773,7 @@ var ObstetricHistoryWidget = ({ fieldId }) => {
5934
6773
  const sanitizeGpalInput = (raw) => {
5935
6774
  const digits = raw.replace(/[^\d]/g, "").slice(0, 2);
5936
6775
  if (!digits) return 0;
5937
- return clampInt(Number(digits), 0, 20);
6776
+ return clampInt2(Number(digits), 0, 20);
5938
6777
  };
5939
6778
  const handleGpalChange = (key, raw) => {
5940
6779
  const prevWasEmpty = draft.gpal[key] === 0 && activeGpalKey === key;
@@ -6634,7 +7473,11 @@ var OphthalmologyWidget = ({ fieldId }) => {
6634
7473
  ] })
6635
7474
  ] }),
6636
7475
  /* @__PURE__ */ jsx("tbody", { children: /* @__PURE__ */ jsxs("tr", { children: [
6637
- /* @__PURE__ */ jsx("td", { className: refractionLabelCellClass, children: "Current Glass" }),
7476
+ /* @__PURE__ */ jsx("td", { className: `${refractionLabelCellClass} whitespace-normal`, children: /* @__PURE__ */ jsxs("span", { className: "block leading-tight", children: [
7477
+ "Current",
7478
+ /* @__PURE__ */ jsx("br", {}),
7479
+ "Glass"
7480
+ ] }) }),
6638
7481
  /* @__PURE__ */ jsx("td", { className: refractionDataCellClass, children: /* @__PURE__ */ jsx(
6639
7482
  Input,
6640
7483
  {
@@ -6889,12 +7732,12 @@ var OphthalmologyWidget = ({ fieldId }) => {
6889
7732
  /* @__PURE__ */ jsx("th", { className: refractionHeaderCellClass, children: "Sph" }),
6890
7733
  /* @__PURE__ */ jsx("th", { className: refractionHeaderCellClass, children: "Cyl" }),
6891
7734
  /* @__PURE__ */ jsx("th", { className: refractionHeaderCellClass, children: "Axis" }),
6892
- /* @__PURE__ */ jsx("th", { className: refractionHeaderCellClass, children: "V/A" }),
7735
+ /* @__PURE__ */ jsx("th", { className: refractionHeaderCellClass, children: "BCVA" }),
6893
7736
  /* @__PURE__ */ jsx("th", { className: refractionHeaderCellClass, children: "P/D" }),
6894
7737
  /* @__PURE__ */ jsx("th", { className: refractionHeaderCellClass, children: "Sph" }),
6895
7738
  /* @__PURE__ */ jsx("th", { className: refractionHeaderCellClass, children: "Cyl" }),
6896
7739
  /* @__PURE__ */ jsx("th", { className: refractionHeaderCellClass, children: "Axis" }),
6897
- /* @__PURE__ */ jsx("th", { className: refractionHeaderCellClass, children: "V/A" }),
7740
+ /* @__PURE__ */ jsx("th", { className: refractionHeaderCellClass, children: "BCVA" }),
6898
7741
  /* @__PURE__ */ jsx("th", { className: refractionHeaderCellClass, children: "P/D" })
6899
7742
  ] })
6900
7743
  ] }),
@@ -9232,6 +10075,7 @@ var SliderWidget = ({ fieldId }) => {
9232
10075
  ] });
9233
10076
  };
9234
10077
  var CHIEF_CHIPS_FIELD = "chief_complaints_chips";
10078
+ var GS_SYMPTOMS_FIELD = "symptoms";
9235
10079
  var SWELLING_OPTS = [
9236
10080
  { value: "reducible_hernia", label: "Reducible (hernia)" },
9237
10081
  { value: "cough_impulse", label: "Cough impulse" },
@@ -9257,7 +10101,7 @@ var THYROID_OPTS = [
9257
10101
  { value: "voice_change", label: "Voice change" },
9258
10102
  { value: "thyrotoxicosis", label: "Thyrotoxicosis symptoms" }
9259
10103
  ];
9260
- var SOCRATES_KEYS = [
10104
+ var SOCRATES_KEYS2 = [
9261
10105
  "site",
9262
10106
  "onset",
9263
10107
  "character",
@@ -9272,16 +10116,26 @@ function Panel({ title, children }) {
9272
10116
  /* @__PURE__ */ jsx("div", { className: "p-3", children })
9273
10117
  ] });
9274
10118
  }
9275
- function chipList(state) {
9276
- const raw = state.values[CHIEF_CHIPS_FIELD];
10119
+ function chipListFromRaw(raw) {
9277
10120
  return Array.isArray(raw) ? raw.filter((x) => typeof x === "string") : [];
9278
10121
  }
9279
10122
  var GsSmartHistoryWidget = ({ fieldId }) => {
9280
10123
  const { fieldDef, value, setValue, setTouched, error, touched, disabled } = useField(fieldId);
10124
+ const hopcField = useField(GS_SYMPTOMS_FIELD);
9281
10125
  const { state } = useForm();
9282
10126
  const showError = !!error && (touched || state.submitAttempted);
9283
10127
  const safe = useMemo(() => normalizeGeneralSurgerySmartHistory(value), [value]);
9284
- const chips = useMemo(() => chipList(state), [state]);
10128
+ const chiefChipsRaw = state.values[CHIEF_CHIPS_FIELD];
10129
+ const chips = useMemo(() => chipListFromRaw(chiefChipsRaw), [chiefChipsRaw]);
10130
+ const [hopcNarrativeLocked, setHopcNarrativeLocked] = useState(false);
10131
+ useEffect(() => {
10132
+ if (hopcNarrativeLocked) return;
10133
+ const next = formatGeneralSurgerySmartHistoryToNarrative(
10134
+ normalizeGeneralSurgerySmartHistory(value),
10135
+ chips
10136
+ );
10137
+ hopcField.setValue(next);
10138
+ }, [value, chips, hopcNarrativeLocked]);
9285
10139
  const showPain = chips.includes("pain");
9286
10140
  const showSwelling = chips.includes("swelling_lump");
9287
10141
  const showGI = chips.includes("bleeding") || chips.includes("obstruction");
@@ -9341,7 +10195,7 @@ var GsSmartHistoryWidget = ({ fieldId }) => {
9341
10195
  labelEl,
9342
10196
  /* @__PURE__ */ jsxs("div", { className: bodyClass, children: [
9343
10197
  showPain ? /* @__PURE__ */ jsx(Panel, { title: "SOCRATES \u2014 pain", children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2 md:grid-cols-4", children: [
9344
- SOCRATES_KEYS.map((k) => /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
10198
+ SOCRATES_KEYS2.map((k) => /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
9345
10199
  /* @__PURE__ */ jsx("span", { className: "text-[10px] font-medium uppercase tracking-wide text-muted-foreground", children: k }),
9346
10200
  /* @__PURE__ */ jsx(
9347
10201
  Input,
@@ -9547,15 +10401,51 @@ var GsSmartHistoryWidget = ({ fieldId }) => {
9547
10401
  ] }, o.value)) })
9548
10402
  ] }) : null,
9549
10403
  /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
9550
- /* @__PURE__ */ jsx(Label, { className: "text-xs font-medium text-slate-700", children: "Systemic surgical screening" }),
10404
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-between gap-2", children: [
10405
+ /* @__PURE__ */ jsx(Label, { className: "text-xs font-semibold text-slate-700", children: hopcField.fieldDef?.label ?? "History of presenting complaint" }),
10406
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
10407
+ hopcNarrativeLocked ? /* @__PURE__ */ jsxs("span", { className: "rounded bg-amber-50 px-1.5 py-0.5 text-[10px] font-medium text-amber-900 ring-1 ring-amber-200/80", children: [
10408
+ "You edited this summary. Use",
10409
+ " ",
10410
+ /* @__PURE__ */ jsx("span", { className: "italic", children: "'Regenerate'" }),
10411
+ " ",
10412
+ "to update it from the form."
10413
+ ] }) : null,
10414
+ hopcNarrativeLocked ? /* @__PURE__ */ jsx(
10415
+ Button,
10416
+ {
10417
+ type: "button",
10418
+ variant: "outline",
10419
+ size: "sm",
10420
+ className: "h-7 shrink-0 px-2 text-xs",
10421
+ disabled: disabled || hopcField.disabled,
10422
+ onClick: () => {
10423
+ setHopcNarrativeLocked(false);
10424
+ hopcField.setValue(
10425
+ formatGeneralSurgerySmartHistoryToNarrative(
10426
+ normalizeGeneralSurgerySmartHistory(value),
10427
+ chips
10428
+ )
10429
+ );
10430
+ },
10431
+ children: "Regenerate"
10432
+ }
10433
+ ) : null
10434
+ ] })
10435
+ ] }),
10436
+ hopcNarrativeLocked ? /* @__PURE__ */ jsx("p", { className: "text-[10px] text-muted-foreground", children: "Edit this box anytime. Use Regenerate to replace with fresh text from the structured fields." }) : null,
9551
10437
  /* @__PURE__ */ jsx(
9552
10438
  Textarea,
9553
10439
  {
9554
- className: "min-h-[72px] rounded-md border border-input bg-white text-sm",
9555
- placeholder: "Fever, weight loss, appetite loss, fatigue, malignancy red flags\u2026",
9556
- value: safe.systemic,
9557
- onChange: (e) => update({ ...safe, systemic: e.target.value }),
9558
- disabled
10440
+ className: "min-h-[88px] rounded-md border border-input bg-white text-sm",
10441
+ placeholder: "Onset, progression, associated symptoms, relevant negatives\u2026",
10442
+ value: typeof hopcField.value === "string" ? hopcField.value : hopcField.value == null ? "" : String(hopcField.value),
10443
+ onChange: (e) => {
10444
+ setHopcNarrativeLocked(true);
10445
+ hopcField.setValue(e.target.value);
10446
+ hopcField.setTouched();
10447
+ },
10448
+ disabled: disabled || hopcField.disabled
9559
10449
  }
9560
10450
  )
9561
10451
  ] })
@@ -9607,12 +10497,72 @@ function RegionCard({ title, children }) {
9607
10497
  /* @__PURE__ */ jsx("div", { className: "p-3", children })
9608
10498
  ] });
9609
10499
  }
10500
+ var BREAST_TEXT_KEYS = [
10501
+ { key: "size", label: "Size" },
10502
+ { key: "quadrant", label: "Quadrant" },
10503
+ { key: "tenderness", label: "Tenderness" },
10504
+ { key: "fixity", label: "Fixity" },
10505
+ { key: "skinInvolvement", label: "Skin involvement" },
10506
+ { key: "consistency", label: "Consistency" }
10507
+ ];
10508
+ function BreastLumpColumn({
10509
+ title,
10510
+ data,
10511
+ onChange,
10512
+ disabled
10513
+ }) {
10514
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-2 rounded-md border border-[#D0D0D0] bg-slate-50/50 p-3", children: [
10515
+ /* @__PURE__ */ jsx("p", { className: "text-[11px] font-semibold uppercase tracking-wide text-muted-foreground", children: title }),
10516
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2", children: BREAST_TEXT_KEYS.map(({ key, label }) => /* @__PURE__ */ jsxs("label", { className: "block", children: [
10517
+ /* @__PURE__ */ jsx("span", { className: "mb-1 block font-medium", children: label }),
10518
+ /* @__PURE__ */ jsx(
10519
+ Input,
10520
+ {
10521
+ className: "h-8 text-xs",
10522
+ value: data[key],
10523
+ onChange: (e) => onChange({ [key]: e.target.value }),
10524
+ disabled
10525
+ }
10526
+ )
10527
+ ] }, key)) }),
10528
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-x-4 gap-y-2 pt-1", children: [
10529
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
10530
+ /* @__PURE__ */ jsx(
10531
+ Checkbox,
10532
+ {
10533
+ checked: data.axillaryNodes,
10534
+ onCheckedChange: (c) => onChange({ axillaryNodes: c === true }),
10535
+ disabled
10536
+ }
10537
+ ),
10538
+ "Axillary nodes"
10539
+ ] }),
10540
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
10541
+ /* @__PURE__ */ jsx(
10542
+ Checkbox,
10543
+ {
10544
+ checked: data.nippleAreolarComplex,
10545
+ onCheckedChange: (c) => onChange({ nippleAreolarComplex: c === true }),
10546
+ disabled
10547
+ }
10548
+ ),
10549
+ "Nipple-areolar complex"
10550
+ ] })
10551
+ ] })
10552
+ ] });
10553
+ }
9610
10554
  var GsExaminationWidget = ({ fieldId }) => {
9611
10555
  const { fieldDef, value, setValue, setTouched, error, touched, disabled } = useField(fieldId);
9612
10556
  const clinicalField = useField(GS_CLINICAL_EXAMINATION_FIELD);
9613
10557
  const { state } = useForm();
9614
10558
  const showError = !!error && (touched || state.submitAttempted);
9615
10559
  const safe = useMemo(() => normalizeGeneralSurgeryExamination(value), [value]);
10560
+ const [clinicalNarrativeLocked, setClinicalNarrativeLocked] = useState(false);
10561
+ useEffect(() => {
10562
+ if (clinicalNarrativeLocked) return;
10563
+ const next = formatGeneralSurgeryExaminationToNarrative(normalizeGeneralSurgeryExamination(value));
10564
+ clinicalField.setValue(next);
10565
+ }, [value, clinicalNarrativeLocked]);
9616
10566
  const update = (next) => {
9617
10567
  setValue(next);
9618
10568
  setTouched();
@@ -9804,56 +10754,35 @@ var GsExaminationWidget = ({ fieldId }) => {
9804
10754
  "Tenderness"
9805
10755
  ] })
9806
10756
  ] }) }) : null,
9807
- 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: [
10757
+ has("breast") ? /* @__PURE__ */ jsx(RegionCard, { title: "Breast exam", children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-4 text-xs md:grid-cols-2", children: [
10758
+ /* @__PURE__ */ jsx(
10759
+ BreastLumpColumn,
10760
+ {
10761
+ title: "Left breast",
10762
+ data: safe.breast.left,
10763
+ onChange: (p) => update({
10764
+ ...safe,
10765
+ breast: { ...safe.breast, left: { ...safe.breast.left, ...p } }
10766
+ }),
10767
+ disabled
10768
+ }
10769
+ ),
10770
+ /* @__PURE__ */ jsx(
10771
+ BreastLumpColumn,
10772
+ {
10773
+ title: "Right breast",
10774
+ data: safe.breast.right,
10775
+ onChange: (p) => update({
10776
+ ...safe,
10777
+ breast: { ...safe.breast, right: { ...safe.breast.right, ...p } }
10778
+ }),
10779
+ disabled
10780
+ }
10781
+ )
10782
+ ] }) }) : null,
10783
+ 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: [
9808
10784
  /* @__PURE__ */ jsxs("label", { className: "block", children: [
9809
- /* @__PURE__ */ jsx("span", { className: "mb-1 block font-medium", children: "Lump size (cm)" }),
9810
- /* @__PURE__ */ jsx(
9811
- Input,
9812
- {
9813
- className: "h-8 text-xs",
9814
- value: safe.breast.lumpSizeCm,
9815
- onChange: (e) => update({ ...safe, breast: { ...safe.breast, lumpSizeCm: e.target.value } }),
9816
- disabled
9817
- }
9818
- )
9819
- ] }),
9820
- /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
9821
- /* @__PURE__ */ jsx(
9822
- Checkbox,
9823
- {
9824
- checked: safe.breast.mobile,
9825
- onCheckedChange: (c) => update({ ...safe, breast: { ...safe.breast, mobile: c === true } }),
9826
- disabled
9827
- }
9828
- ),
9829
- "Mobile"
9830
- ] }),
9831
- /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
9832
- /* @__PURE__ */ jsx(
9833
- Checkbox,
9834
- {
9835
- checked: safe.breast.skinInvolvement,
9836
- onCheckedChange: (c) => update({ ...safe, breast: { ...safe.breast, skinInvolvement: c === true } }),
9837
- disabled
9838
- }
9839
- ),
9840
- "Skin involvement"
9841
- ] }),
9842
- /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
9843
- /* @__PURE__ */ jsx(
9844
- Checkbox,
9845
- {
9846
- checked: safe.breast.axillaryNodes,
9847
- onCheckedChange: (c) => update({ ...safe, breast: { ...safe.breast, axillaryNodes: c === true } }),
9848
- disabled
9849
- }
9850
- ),
9851
- "Axillary nodes"
9852
- ] })
9853
- ] }) }) : null,
9854
- 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: [
9855
- /* @__PURE__ */ jsxs("label", { className: "block", children: [
9856
- /* @__PURE__ */ jsx("span", { className: "mb-1 block font-medium", children: "Size" }),
10785
+ /* @__PURE__ */ jsx("span", { className: "mb-1 block font-medium", children: "Size" }),
9857
10786
  /* @__PURE__ */ jsx(
9858
10787
  Input,
9859
10788
  {
@@ -9984,13 +10913,43 @@ var GsExaminationWidget = ({ fieldId }) => {
9984
10913
  ] }) }) : null
9985
10914
  ] }),
9986
10915
  /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
9987
- /* @__PURE__ */ jsx(Label, { className: "text-xs font-semibold text-slate-700", children: clinicalField.fieldDef?.label ?? "Clinical examination" }),
10916
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-between gap-2", children: [
10917
+ /* @__PURE__ */ jsx(Label, { className: "text-xs font-semibold text-slate-700", children: clinicalField.fieldDef?.label ?? "Clinical examination" }),
10918
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
10919
+ clinicalNarrativeLocked ? /* @__PURE__ */ jsxs("span", { className: "rounded bg-amber-50 px-1.5 py-0.5 text-[10px] font-medium text-amber-900 ring-1 ring-amber-200/80", children: [
10920
+ "You edited this summary. Use",
10921
+ " ",
10922
+ /* @__PURE__ */ jsx("span", { className: "italic", children: "'Regenerate'" }),
10923
+ " ",
10924
+ "to update it from the form."
10925
+ ] }) : null,
10926
+ clinicalNarrativeLocked ? /* @__PURE__ */ jsx(
10927
+ Button,
10928
+ {
10929
+ type: "button",
10930
+ variant: "outline",
10931
+ size: "sm",
10932
+ className: "h-7 shrink-0 px-2 text-xs",
10933
+ disabled: disabled || clinicalField.disabled,
10934
+ onClick: () => {
10935
+ setClinicalNarrativeLocked(false);
10936
+ clinicalField.setValue(
10937
+ formatGeneralSurgeryExaminationToNarrative(normalizeGeneralSurgeryExamination(value))
10938
+ );
10939
+ },
10940
+ children: "Regenerate"
10941
+ }
10942
+ ) : null
10943
+ ] })
10944
+ ] }),
10945
+ clinicalNarrativeLocked ? /* @__PURE__ */ jsx("p", { className: "text-[10px] text-muted-foreground", children: "Edit this box anytime. Use Regenerate to replace with fresh text from the structured examination." }) : null,
9988
10946
  /* @__PURE__ */ jsx(
9989
10947
  Textarea,
9990
10948
  {
9991
10949
  className: "min-h-[88px] rounded-md border border-input bg-white text-sm",
9992
10950
  value: typeof clinicalField.value === "string" ? clinicalField.value : clinicalField.value == null ? "" : String(clinicalField.value),
9993
10951
  onChange: (e) => {
10952
+ setClinicalNarrativeLocked(true);
9994
10953
  clinicalField.setValue(e.target.value);
9995
10954
  clinicalField.setTouched();
9996
10955
  },
@@ -10004,7 +10963,7 @@ var GsExaminationWidget = ({ fieldId }) => {
10004
10963
  };
10005
10964
  var CHIEF_CHIPS_FIELD2 = "chief_complaints_chips";
10006
10965
  var GS_EXAMINATION_FIELD = "gs_examination";
10007
- function chipList2(state) {
10966
+ function chipList(state) {
10008
10967
  const raw = state.values[CHIEF_CHIPS_FIELD2];
10009
10968
  return Array.isArray(raw) ? raw.filter((x) => typeof x === "string") : [];
10010
10969
  }
@@ -10018,7 +10977,7 @@ var GsGradingWidget = ({ fieldId }) => {
10018
10977
  const { state } = useForm();
10019
10978
  const showError = !!error && (touched || state.submitAttempted);
10020
10979
  const safe = useMemo(() => normalizeGeneralSurgeryGrading(value), [value]);
10021
- const chips = useMemo(() => chipList2(state), [state]);
10980
+ const chips = useMemo(() => chipList(state), [state]);
10022
10981
  const regions = useMemo(() => regionList(state), [state]);
10023
10982
  const visibleRows = useMemo(() => {
10024
10983
  return ALL_GS_CONDITIONS.filter(
@@ -10173,6 +11132,813 @@ var PainScaleFlagsWidget = ({ fieldId }) => {
10173
11132
  showError && /* @__PURE__ */ jsx("p", { className: "text-xs text-red-500", children: error })
10174
11133
  ] });
10175
11134
  };
11135
+ var CHIEF_CHIPS_FIELD3 = "chief_complaints_chips";
11136
+ var ACTIVE_SYNDROME_FIELD = "uro_active_syndrome";
11137
+ function chipList2(state) {
11138
+ const raw = state.values[CHIEF_CHIPS_FIELD3];
11139
+ return Array.isArray(raw) ? raw.filter((x) => typeof x === "string") : [];
11140
+ }
11141
+ var IPSS_LABELS = {
11142
+ incomplete: "Incomplete emptying",
11143
+ frequency: "Frequency (<2h)",
11144
+ intermittency: "Intermittency",
11145
+ urgency: "Urgency",
11146
+ weakStream: "Weak stream",
11147
+ straining: "Straining",
11148
+ nocturia: "Nocturia (\xD7/night)"
11149
+ };
11150
+ var SOCRATES_KEYS3 = [
11151
+ "site",
11152
+ "onset",
11153
+ "character",
11154
+ "radiation",
11155
+ "associated",
11156
+ "timing",
11157
+ "exacerbating"
11158
+ ];
11159
+ function Panel2({
11160
+ title,
11161
+ right,
11162
+ children
11163
+ }) {
11164
+ return /* @__PURE__ */ jsxs("div", { className: "overflow-hidden rounded-md border border-[#D0D0D0] bg-white", children: [
11165
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between border-b border-[#D0D0D0] bg-[#FEE8EC]/50 px-3 py-1.5", children: [
11166
+ /* @__PURE__ */ jsx("span", { className: "text-xs font-semibold text-slate-700", children: title }),
11167
+ right
11168
+ ] }),
11169
+ /* @__PURE__ */ jsx("div", { className: "p-3", children })
11170
+ ] });
11171
+ }
11172
+ var UrologySmartHistoryWidget = ({ fieldId }) => {
11173
+ const { fieldDef, value, setValue, setTouched, error, touched, disabled } = useField(fieldId);
11174
+ const syndromeField = useField(ACTIVE_SYNDROME_FIELD);
11175
+ const { state } = useForm();
11176
+ const showError = !!error && (touched || state.submitAttempted);
11177
+ const safe = useMemo(() => normalizeUrologySmartHistory(value), [value]);
11178
+ const chips = useMemo(() => chipList2(state), [state]);
11179
+ const rawSyndrome = syndromeField.value ?? state.values[ACTIVE_SYNDROME_FIELD];
11180
+ const syndrome = typeof rawSyndrome === "string" && rawSyndrome !== "" && rawSyndrome !== "none" ? rawSyndrome : "none";
11181
+ const showPain = chips.includes("pain_abdomen_flank") || chips.includes("scrotal_swelling_pain") || syndrome === "stone" || syndrome === "scrotal";
11182
+ const showLUTS = syndrome === "luts" || syndrome === "retention" || chips.includes("frequency_urgency") || chips.includes("poor_stream") || chips.includes("acute_retention");
11183
+ const showHaem = syndrome === "haematuria" || chips.includes("haematuria");
11184
+ const showSex = syndrome === "ed_infertility" || chips.includes("erectile_dysfunction") || chips.includes("infertility_concern");
11185
+ const update = (next) => {
11186
+ setValue(next);
11187
+ setTouched();
11188
+ };
11189
+ const ipssTotal = urologyIpssSevenTotal(safe.ipss);
11190
+ const ipssBandLabel = urologyIpssBand(ipssTotal);
11191
+ const bandClass = ipssBandLabel === "Severe" ? "bg-red-500/15 text-red-700" : ipssBandLabel === "Moderate" ? "bg-amber-500/15 text-amber-800" : "bg-emerald-500/15 text-emerald-800";
11192
+ const setSocrates = (key, v) => {
11193
+ if (key === "severity") {
11194
+ const n = typeof v === "number" ? v : Number(v);
11195
+ const sev = Number.isFinite(n) ? Math.min(10, Math.max(0, Math.round(n))) : 0;
11196
+ update({ ...safe, socrates: { ...safe.socrates, severity: sev } });
11197
+ return;
11198
+ }
11199
+ update({ ...safe, socrates: { ...safe.socrates, [key]: String(v) } });
11200
+ };
11201
+ const setIpss = (key, v) => {
11202
+ update({ ...safe, ipss: { ...safe.ipss, [key]: v } });
11203
+ };
11204
+ if (!fieldDef) return null;
11205
+ const theme = getThemeConfig("textarea", fieldDef.theme);
11206
+ const wrapperClass = theme?.wrapperClassName ?? "rounded-md overflow-hidden flex flex-col border border-[#D0D0D0]";
11207
+ const labelClass = theme?.labelClassName;
11208
+ const labelContent = /* @__PURE__ */ jsxs(Fragment, { children: [
11209
+ fieldDef.label,
11210
+ fieldDef.required ? /* @__PURE__ */ jsx("span", { className: "ml-1 text-red-500", children: "*" }) : null
11211
+ ] });
11212
+ const labelEl = theme ? /* @__PURE__ */ jsx(Label, { className: labelClass, children: labelContent }) : /* @__PURE__ */ jsx(Label, { className: "text-sm font-medium", children: labelContent });
11213
+ const bodyClass = cn(
11214
+ "-mt-1 flex min-w-0 flex-col gap-3 border-t border-[#D0D0D0] bg-white px-3 py-3",
11215
+ disabled && "pointer-events-none opacity-60"
11216
+ );
11217
+ return /* @__PURE__ */ jsxs("div", { className: cn("w-full min-w-0", wrapperClass), children: [
11218
+ labelEl,
11219
+ /* @__PURE__ */ jsxs("div", { className: bodyClass, children: [
11220
+ /* @__PURE__ */ jsx("p", { className: "text-[11px] text-muted-foreground", children: "Panels follow chief complaint chips and active syndrome (Clearsight SmartHistoryUro)." }),
11221
+ showPain ? /* @__PURE__ */ jsx(Panel2, { title: "SOCRATES \u2014 Pain (flank / suprapubic / testicular)", children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2 md:grid-cols-4", children: [
11222
+ SOCRATES_KEYS3.map((k) => /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
11223
+ /* @__PURE__ */ jsx("span", { className: "text-[10px] font-medium uppercase tracking-wide text-muted-foreground", children: k }),
11224
+ /* @__PURE__ */ jsx(
11225
+ Input,
11226
+ {
11227
+ className: "h-8 text-xs",
11228
+ value: safe.socrates[k],
11229
+ onChange: (e) => setSocrates(k, e.target.value),
11230
+ placeholder: k === "radiation" ? "e.g. groin \u2192 ureteric" : k === "character" ? "colicky / dull" : "",
11231
+ disabled
11232
+ }
11233
+ )
11234
+ ] }, k)),
11235
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
11236
+ /* @__PURE__ */ jsx("span", { className: "text-[10px] font-medium uppercase tracking-wide text-muted-foreground", children: "Severity 0\u201310" }),
11237
+ /* @__PURE__ */ jsx(
11238
+ Input,
11239
+ {
11240
+ type: "number",
11241
+ min: 0,
11242
+ max: 10,
11243
+ className: "h-8 text-xs",
11244
+ value: safe.socrates.severity,
11245
+ onChange: (e) => setSocrates("severity", e.target.value),
11246
+ disabled
11247
+ }
11248
+ )
11249
+ ] })
11250
+ ] }) }) : null,
11251
+ showLUTS ? /* @__PURE__ */ jsxs(
11252
+ Panel2,
11253
+ {
11254
+ title: "IPSS \u2014 International Prostate Symptom Score",
11255
+ right: /* @__PURE__ */ jsxs("span", { className: `rounded-full px-2 py-0.5 text-[10px] font-medium ${bandClass}`, children: [
11256
+ ipssTotal,
11257
+ "/35 \u2014 ",
11258
+ ipssBandLabel
11259
+ ] }),
11260
+ children: [
11261
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2 md:grid-cols-4", children: [
11262
+ Object.keys(IPSS_LABELS).map((k) => /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
11263
+ /* @__PURE__ */ jsx("span", { className: "text-[10px] uppercase tracking-wide text-muted-foreground", children: IPSS_LABELS[k] }),
11264
+ /* @__PURE__ */ jsxs(
11265
+ Select,
11266
+ {
11267
+ value: String(safe.ipss[k]),
11268
+ onValueChange: (val) => setIpss(k, Number(val)),
11269
+ disabled,
11270
+ children: [
11271
+ /* @__PURE__ */ jsx(SelectTrigger, { className: "h-8 text-xs", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
11272
+ /* @__PURE__ */ jsx(SelectContent, { children: [0, 1, 2, 3, 4, 5].map((n) => /* @__PURE__ */ jsx(SelectItem, { value: String(n), children: n }, n)) })
11273
+ ]
11274
+ }
11275
+ )
11276
+ ] }, k)),
11277
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
11278
+ /* @__PURE__ */ jsx("span", { className: "text-[10px] uppercase tracking-wide text-muted-foreground", children: "QoL (0\u20136)" }),
11279
+ /* @__PURE__ */ jsxs(
11280
+ Select,
11281
+ {
11282
+ value: String(safe.ipssQoL),
11283
+ onValueChange: (val) => update({ ...safe, ipssQoL: Math.min(6, Math.max(0, Number(val))) }),
11284
+ disabled,
11285
+ children: [
11286
+ /* @__PURE__ */ jsx(SelectTrigger, { className: "h-8 text-xs", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
11287
+ /* @__PURE__ */ jsx(SelectContent, { children: [0, 1, 2, 3, 4, 5, 6].map((n) => /* @__PURE__ */ jsx(SelectItem, { value: String(n), children: n }, n)) })
11288
+ ]
11289
+ }
11290
+ )
11291
+ ] })
11292
+ ] }),
11293
+ /* @__PURE__ */ jsxs("p", { className: "mt-2 text-[10px] text-muted-foreground", children: [
11294
+ "Bands: 0\u20137 mild \xB7 8\u201319 moderate \xB7 20\u201335 severe.",
11295
+ " ",
11296
+ /* @__PURE__ */ jsx("span", { className: "font-semibold text-foreground", children: "IPSS \u2265 20 \u2192 consider surgical intervention." })
11297
+ ] })
11298
+ ]
11299
+ }
11300
+ ) : null,
11301
+ showHaem ? /* @__PURE__ */ jsxs(Panel2, { title: "Haematuria profile", children: [
11302
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-3 text-xs md:grid-cols-4", children: [
11303
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
11304
+ /* @__PURE__ */ jsx(
11305
+ Checkbox,
11306
+ {
11307
+ checked: safe.haematuria.present,
11308
+ onCheckedChange: (c) => update({
11309
+ ...safe,
11310
+ haematuria: { ...safe.haematuria, present: c === true }
11311
+ }),
11312
+ disabled
11313
+ }
11314
+ ),
11315
+ "Present"
11316
+ ] }),
11317
+ /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
11318
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: "Timing" }),
11319
+ /* @__PURE__ */ jsxs(
11320
+ Select,
11321
+ {
11322
+ value: safe.haematuria.timing || "none",
11323
+ onValueChange: (val) => update({
11324
+ ...safe,
11325
+ haematuria: { ...safe.haematuria, timing: val === "none" ? "" : val }
11326
+ }),
11327
+ disabled,
11328
+ children: [
11329
+ /* @__PURE__ */ jsx(SelectTrigger, { className: "h-8 text-xs", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "\u2014" }) }),
11330
+ /* @__PURE__ */ jsxs(SelectContent, { children: [
11331
+ /* @__PURE__ */ jsx(SelectItem, { value: "none", children: "\u2014" }),
11332
+ /* @__PURE__ */ jsx(SelectItem, { value: "Initial", children: "Initial" }),
11333
+ /* @__PURE__ */ jsx(SelectItem, { value: "Terminal", children: "Terminal" }),
11334
+ /* @__PURE__ */ jsx(SelectItem, { value: "Total", children: "Total" })
11335
+ ] })
11336
+ ]
11337
+ }
11338
+ )
11339
+ ] }),
11340
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
11341
+ /* @__PURE__ */ jsx(
11342
+ Checkbox,
11343
+ {
11344
+ checked: safe.haematuria.painful,
11345
+ onCheckedChange: (c) => update({ ...safe, haematuria: { ...safe.haematuria, painful: c === true } }),
11346
+ disabled
11347
+ }
11348
+ ),
11349
+ "Painful"
11350
+ ] }),
11351
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
11352
+ /* @__PURE__ */ jsx(
11353
+ Checkbox,
11354
+ {
11355
+ checked: safe.haematuria.clots,
11356
+ onCheckedChange: (c) => update({ ...safe, haematuria: { ...safe.haematuria, clots: c === true } }),
11357
+ disabled
11358
+ }
11359
+ ),
11360
+ "Clots"
11361
+ ] })
11362
+ ] }),
11363
+ /* @__PURE__ */ jsx("p", { className: "mt-2 text-[10px] text-red-600", children: "Painless haematuria = malignancy until proven otherwise." })
11364
+ ] }) : null,
11365
+ showSex ? /* @__PURE__ */ jsx(Panel2, { title: "Sexual & reproductive history", children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-3 text-xs md:grid-cols-4", children: [
11366
+ /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
11367
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: "Erectile function" }),
11368
+ /* @__PURE__ */ jsxs(
11369
+ Select,
11370
+ {
11371
+ value: safe.sexual.erectile || "none",
11372
+ onValueChange: (val) => update({
11373
+ ...safe,
11374
+ sexual: { ...safe.sexual, erectile: val === "none" ? "" : val }
11375
+ }),
11376
+ disabled,
11377
+ children: [
11378
+ /* @__PURE__ */ jsx(SelectTrigger, { className: "h-8 text-xs", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "\u2014" }) }),
11379
+ /* @__PURE__ */ jsxs(SelectContent, { children: [
11380
+ /* @__PURE__ */ jsx(SelectItem, { value: "none", children: "\u2014" }),
11381
+ /* @__PURE__ */ jsx(SelectItem, { value: "Normal", children: "Normal" }),
11382
+ /* @__PURE__ */ jsx(SelectItem, { value: "Mild", children: "Mild" }),
11383
+ /* @__PURE__ */ jsx(SelectItem, { value: "Moderate", children: "Moderate" }),
11384
+ /* @__PURE__ */ jsx(SelectItem, { value: "Severe", children: "Severe" })
11385
+ ] })
11386
+ ]
11387
+ }
11388
+ )
11389
+ ] }),
11390
+ /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
11391
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: "Libido" }),
11392
+ /* @__PURE__ */ jsxs(
11393
+ Select,
11394
+ {
11395
+ value: safe.sexual.libido || "none",
11396
+ onValueChange: (val) => update({
11397
+ ...safe,
11398
+ sexual: { ...safe.sexual, libido: val === "none" ? "" : val }
11399
+ }),
11400
+ disabled,
11401
+ children: [
11402
+ /* @__PURE__ */ jsx(SelectTrigger, { className: "h-8 text-xs", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "\u2014" }) }),
11403
+ /* @__PURE__ */ jsxs(SelectContent, { children: [
11404
+ /* @__PURE__ */ jsx(SelectItem, { value: "none", children: "\u2014" }),
11405
+ /* @__PURE__ */ jsx(SelectItem, { value: "Normal", children: "Normal" }),
11406
+ /* @__PURE__ */ jsx(SelectItem, { value: "Reduced", children: "Reduced" })
11407
+ ] })
11408
+ ]
11409
+ }
11410
+ )
11411
+ ] }),
11412
+ /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
11413
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: "Ejaculation" }),
11414
+ /* @__PURE__ */ jsxs(
11415
+ Select,
11416
+ {
11417
+ value: safe.sexual.ejaculation || "none",
11418
+ onValueChange: (val) => update({
11419
+ ...safe,
11420
+ sexual: { ...safe.sexual, ejaculation: val === "none" ? "" : val }
11421
+ }),
11422
+ disabled,
11423
+ children: [
11424
+ /* @__PURE__ */ jsx(SelectTrigger, { className: "h-8 text-xs", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "\u2014" }) }),
11425
+ /* @__PURE__ */ jsxs(SelectContent, { children: [
11426
+ /* @__PURE__ */ jsx(SelectItem, { value: "none", children: "\u2014" }),
11427
+ /* @__PURE__ */ jsx(SelectItem, { value: "Normal", children: "Normal" }),
11428
+ /* @__PURE__ */ jsx(SelectItem, { value: "Premature", children: "Premature" }),
11429
+ /* @__PURE__ */ jsx(SelectItem, { value: "Retrograde", children: "Retrograde" }),
11430
+ /* @__PURE__ */ jsx(SelectItem, { value: "Anejaculation", children: "Anejaculation" })
11431
+ ] })
11432
+ ]
11433
+ }
11434
+ )
11435
+ ] }),
11436
+ /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
11437
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: "Infertility (months)" }),
11438
+ /* @__PURE__ */ jsx(
11439
+ Input,
11440
+ {
11441
+ type: "number",
11442
+ min: 0,
11443
+ className: "h-8 text-xs",
11444
+ value: safe.sexual.infertilityMonths,
11445
+ onChange: (e) => update({
11446
+ ...safe,
11447
+ sexual: {
11448
+ ...safe.sexual,
11449
+ infertilityMonths: Math.max(0, Math.round(Number(e.target.value)) || 0)
11450
+ }
11451
+ }),
11452
+ disabled
11453
+ }
11454
+ )
11455
+ ] })
11456
+ ] }) }) : null,
11457
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
11458
+ /* @__PURE__ */ jsx(Label, { className: "text-xs font-medium text-slate-700", children: "Past history (stones / surgeries / drugs)" }),
11459
+ /* @__PURE__ */ jsx(
11460
+ Textarea,
11461
+ {
11462
+ className: "min-h-[72px] rounded-md border border-input bg-white text-sm",
11463
+ placeholder: "Prior calculi, urological surgeries, anticoagulants, DM/HTN\u2026",
11464
+ value: safe.pastNotes,
11465
+ onChange: (e) => update({ ...safe, pastNotes: e.target.value }),
11466
+ disabled
11467
+ }
11468
+ )
11469
+ ] })
11470
+ ] }),
11471
+ showError ? /* @__PURE__ */ jsx("p", { className: "px-3 pb-2 text-xs text-red-500", children: error }) : null
11472
+ ] });
11473
+ };
11474
+ var GENERAL_ROWS = [
11475
+ { key: "pallor", label: "Pallor (chronic dz)" },
11476
+ { key: "oedema", label: "Oedema (renal)" },
11477
+ { key: "icterus", label: "Icterus" },
11478
+ { key: "lymphadenopathy", label: "Lymphadenopathy" }
11479
+ ];
11480
+ var ABD_ROWS = [
11481
+ { key: "distension", label: "Distension" },
11482
+ { key: "scars", label: "Surgical scars" },
11483
+ { key: "mass", label: "Visible mass" },
11484
+ { key: "kidneyPalpable", label: "Kidney palpable" },
11485
+ { key: "bladderPalpable", label: "Bladder palpable" },
11486
+ { key: "renalAngleTender", label: "Renal angle tender" },
11487
+ { key: "bladderDull", label: "Bladder dullness (retention)" }
11488
+ ];
11489
+ var GU_ROWS = [
11490
+ { key: "meatusAbnormal", label: "Meatus abnormal (hypospadias?)" },
11491
+ { key: "phimosis", label: "Phimosis / paraphimosis" },
11492
+ { key: "lesions", label: "Penile lesions / ulcers" },
11493
+ { key: "scrotalSwelling", label: "Scrotal swelling" },
11494
+ { key: "transilluminant", label: "Transilluminant" },
11495
+ { key: "tenderTestis", label: "Tender testis" },
11496
+ { key: "hydrocele", label: "Hydrocele" },
11497
+ { key: "varicocele", label: "Varicocele" },
11498
+ { key: "suspiciousMass", label: "Suspicious mass" }
11499
+ ];
11500
+ var DRE_CONSISTENCY = ["none", "Soft (benign)", "Firm", "Hard / nodular (malignancy?)"];
11501
+ var DRE_SULCUS = ["none", "Preserved", "Obliterated"];
11502
+ var UrologyExaminationWidget = ({ fieldId }) => {
11503
+ const { fieldDef, value, setValue, setTouched, error, touched, disabled } = useField(fieldId);
11504
+ const { state } = useForm();
11505
+ const showError = !!error && (touched || state.submitAttempted);
11506
+ const safe = useMemo(() => normalizeUrologyExamination(value), [value]);
11507
+ const update = (next) => {
11508
+ setValue(next);
11509
+ setTouched();
11510
+ };
11511
+ const toggleGeneral = (key) => {
11512
+ update({ ...safe, general: { ...safe.general, [key]: !safe.general[key] } });
11513
+ };
11514
+ const toggleAbdomen = (key) => {
11515
+ update({ ...safe, abdomen: { ...safe.abdomen, [key]: !safe.abdomen[key] } });
11516
+ };
11517
+ const toggleGu = (key) => {
11518
+ update({ ...safe, gu: { ...safe.gu, [key]: !safe.gu[key] } });
11519
+ };
11520
+ if (!fieldDef) return null;
11521
+ const theme = getThemeConfig("textarea", fieldDef.theme);
11522
+ const wrapperClass = theme?.wrapperClassName ?? "rounded-md overflow-hidden flex flex-col border border-[#D0D0D0]";
11523
+ const labelClass = theme?.labelClassName;
11524
+ const labelContent = /* @__PURE__ */ jsxs(Fragment, { children: [
11525
+ fieldDef.label,
11526
+ fieldDef.required ? /* @__PURE__ */ jsx("span", { className: "ml-1 text-red-500", children: "*" }) : null
11527
+ ] });
11528
+ const labelEl = theme ? /* @__PURE__ */ jsx(Label, { className: labelClass, children: labelContent }) : /* @__PURE__ */ jsx(Label, { className: "text-sm font-medium", children: labelContent });
11529
+ const bodyClass = cn(
11530
+ "-mt-1 flex min-w-0 flex-col gap-3 border-t border-[#D0D0D0] bg-white px-3 py-3",
11531
+ disabled && "pointer-events-none opacity-60"
11532
+ );
11533
+ return /* @__PURE__ */ jsxs("div", { className: cn("w-full min-w-0", wrapperClass), children: [
11534
+ labelEl,
11535
+ /* @__PURE__ */ jsxs("div", { className: bodyClass, children: [
11536
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-3 text-xs md:grid-cols-2 xl:grid-cols-4", children: [
11537
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
11538
+ /* @__PURE__ */ jsx("p", { className: "font-semibold text-slate-800", children: "General" }),
11539
+ GENERAL_ROWS.map((r) => /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
11540
+ /* @__PURE__ */ jsx(
11541
+ Checkbox,
11542
+ {
11543
+ checked: safe.general[r.key],
11544
+ onCheckedChange: () => toggleGeneral(r.key),
11545
+ disabled
11546
+ }
11547
+ ),
11548
+ r.label
11549
+ ] }, r.key))
11550
+ ] }),
11551
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
11552
+ /* @__PURE__ */ jsx("p", { className: "font-semibold text-slate-800", children: "Abdomen" }),
11553
+ ABD_ROWS.map((r) => /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
11554
+ /* @__PURE__ */ jsx(
11555
+ Checkbox,
11556
+ {
11557
+ checked: safe.abdomen[r.key],
11558
+ onCheckedChange: () => toggleAbdomen(r.key),
11559
+ disabled
11560
+ }
11561
+ ),
11562
+ r.label
11563
+ ] }, r.key))
11564
+ ] }),
11565
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
11566
+ /* @__PURE__ */ jsx("p", { className: "font-semibold text-slate-800", children: "External genitalia / scrotum" }),
11567
+ GU_ROWS.map((r) => /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
11568
+ /* @__PURE__ */ jsx(
11569
+ Checkbox,
11570
+ {
11571
+ checked: safe.gu[r.key],
11572
+ onCheckedChange: () => toggleGu(r.key),
11573
+ disabled
11574
+ }
11575
+ ),
11576
+ r.key === "suspiciousMass" ? /* @__PURE__ */ jsx("span", { className: "font-medium text-red-600", children: r.label }) : r.label
11577
+ ] }, r.key))
11578
+ ] }),
11579
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
11580
+ /* @__PURE__ */ jsx("p", { className: "font-semibold text-slate-800", children: "DRE \u2014 Prostate" }),
11581
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
11582
+ /* @__PURE__ */ jsx(
11583
+ Checkbox,
11584
+ {
11585
+ checked: safe.dre.done,
11586
+ onCheckedChange: (c) => update({ ...safe, dre: { ...safe.dre, done: c === true } }),
11587
+ disabled
11588
+ }
11589
+ ),
11590
+ "DRE performed"
11591
+ ] }),
11592
+ /* @__PURE__ */ jsxs("label", { className: "block", children: [
11593
+ /* @__PURE__ */ jsx("span", { className: "mb-1 block font-medium", children: "Estimated size (g)" }),
11594
+ /* @__PURE__ */ jsx(
11595
+ Input,
11596
+ {
11597
+ type: "number",
11598
+ min: 0,
11599
+ className: "h-8 text-xs",
11600
+ value: safe.dre.sizeGrams,
11601
+ onChange: (e) => {
11602
+ const n = Number(e.target.value);
11603
+ update({
11604
+ ...safe,
11605
+ dre: {
11606
+ ...safe.dre,
11607
+ sizeGrams: Number.isFinite(n) && n >= 0 ? Math.round(n) : 0
11608
+ }
11609
+ });
11610
+ },
11611
+ disabled
11612
+ }
11613
+ )
11614
+ ] }),
11615
+ /* @__PURE__ */ jsxs("label", { className: "block", children: [
11616
+ /* @__PURE__ */ jsx("span", { className: "mb-1 block font-medium", children: "Consistency" }),
11617
+ /* @__PURE__ */ jsxs(
11618
+ Select,
11619
+ {
11620
+ value: safe.dre.consistency || "none",
11621
+ onValueChange: (val) => update({
11622
+ ...safe,
11623
+ dre: { ...safe.dre, consistency: val === "none" ? "" : val }
11624
+ }),
11625
+ disabled,
11626
+ children: [
11627
+ /* @__PURE__ */ jsx(SelectTrigger, { className: "h-8 text-xs", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "\u2014" }) }),
11628
+ /* @__PURE__ */ jsx(SelectContent, { children: DRE_CONSISTENCY.map((opt) => /* @__PURE__ */ jsx(SelectItem, { value: opt, children: opt === "none" ? "\u2014" : opt }, opt)) })
11629
+ ]
11630
+ }
11631
+ )
11632
+ ] }),
11633
+ /* @__PURE__ */ jsxs("label", { className: "block", children: [
11634
+ /* @__PURE__ */ jsx("span", { className: "mb-1 block font-medium", children: "Median sulcus" }),
11635
+ /* @__PURE__ */ jsxs(
11636
+ Select,
11637
+ {
11638
+ value: safe.dre.medianSulcus || "none",
11639
+ onValueChange: (val) => update({
11640
+ ...safe,
11641
+ dre: { ...safe.dre, medianSulcus: val === "none" ? "" : val }
11642
+ }),
11643
+ disabled,
11644
+ children: [
11645
+ /* @__PURE__ */ jsx(SelectTrigger, { className: "h-8 text-xs", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "\u2014" }) }),
11646
+ /* @__PURE__ */ jsx(SelectContent, { children: DRE_SULCUS.map((opt) => /* @__PURE__ */ jsx(SelectItem, { value: opt, children: opt === "none" ? "\u2014" : opt }, opt)) })
11647
+ ]
11648
+ }
11649
+ )
11650
+ ] }),
11651
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
11652
+ /* @__PURE__ */ jsx(
11653
+ Checkbox,
11654
+ {
11655
+ checked: safe.dre.tenderness,
11656
+ onCheckedChange: (c) => update({ ...safe, dre: { ...safe.dre, tenderness: c === true } }),
11657
+ disabled
11658
+ }
11659
+ ),
11660
+ "Tender (prostatitis?)"
11661
+ ] })
11662
+ ] })
11663
+ ] }),
11664
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
11665
+ /* @__PURE__ */ jsx(Label, { className: "text-xs font-semibold text-slate-700", children: "Examination notes" }),
11666
+ /* @__PURE__ */ jsx(
11667
+ Textarea,
11668
+ {
11669
+ className: "min-h-[88px] rounded-md border border-input bg-white text-sm",
11670
+ placeholder: "Free-text exam findings\u2026",
11671
+ value: safe.examinationNotes,
11672
+ onChange: (e) => update({ ...safe, examinationNotes: e.target.value }),
11673
+ disabled
11674
+ }
11675
+ )
11676
+ ] })
11677
+ ] }),
11678
+ showError ? /* @__PURE__ */ jsx("p", { className: "px-3 pb-2 text-xs text-red-500", children: error }) : null
11679
+ ] });
11680
+ };
11681
+ var SMART_HISTORY_FIELD = "uro_smart_history";
11682
+ var EXAMINATION_FIELD = "uro_examination";
11683
+ var DRE_HARD = "Hard / nodular (malignancy?)";
11684
+ function Panel3({
11685
+ title,
11686
+ className,
11687
+ children
11688
+ }) {
11689
+ return /* @__PURE__ */ jsxs("div", { className: cn("overflow-hidden rounded-md border border-[#D0D0D0] bg-white", className), children: [
11690
+ /* @__PURE__ */ jsx("div", { className: "border-b border-[#D0D0D0] bg-[#FEE8EC]/50 px-3 py-1.5", children: /* @__PURE__ */ jsx("span", { className: "text-xs font-semibold text-slate-700", children: title }) }),
11691
+ /* @__PURE__ */ jsx("div", { className: "p-3", children })
11692
+ ] });
11693
+ }
11694
+ var UrologyPathwayWidget = ({ fieldId }) => {
11695
+ const { fieldDef, value, setValue, setTouched, error, touched, disabled } = useField(fieldId);
11696
+ const { state } = useForm();
11697
+ const showError = !!error && (touched || state.submitAttempted);
11698
+ const safe = useMemo(() => normalizeUrologyPathway(value), [value]);
11699
+ const smart = useMemo(
11700
+ () => normalizeUrologySmartHistory(state.values[SMART_HISTORY_FIELD]),
11701
+ [state.values]
11702
+ );
11703
+ const exam = useMemo(
11704
+ () => normalizeUrologyExamination(state.values[EXAMINATION_FIELD]),
11705
+ [state.values]
11706
+ );
11707
+ const ipssTotal = urologyIpssSevenTotal(smart.ipss);
11708
+ const ipssBandCls = ipssTotal >= 20 ? "bg-red-500/15 text-red-700" : ipssTotal >= 8 ? "bg-amber-500/15 text-amber-900" : "bg-emerald-500/15 text-emerald-800";
11709
+ const stone = useMemo(
11710
+ () => urologyStoneRecommendation(safe.stoneSizeMm, safe.hydronephrosis),
11711
+ [safe.stoneSizeMm, safe.hydronephrosis]
11712
+ );
11713
+ const prostateLine = useMemo(
11714
+ () => urologyProstateProcedure(safe.prostateVolumeCc),
11715
+ [safe.prostateVolumeCc]
11716
+ );
11717
+ const psaHigh = safe.psaNgMl > 4;
11718
+ const qmaxLow = safe.uroflowQmaxMlSec > 0 && Number.isFinite(safe.uroflowQmaxMlSec) && safe.uroflowQmaxMlSec < 10;
11719
+ const update = (next) => {
11720
+ setValue(next);
11721
+ setTouched();
11722
+ };
11723
+ const setRisk = (key, next) => {
11724
+ update({ ...safe, risk: { ...safe.risk, [key]: next } });
11725
+ };
11726
+ if (!fieldDef) return null;
11727
+ const theme = getThemeConfig("textarea", fieldDef.theme);
11728
+ const wrapperClass = theme?.wrapperClassName ?? "rounded-md overflow-hidden flex flex-col border border-[#D0D0D0]";
11729
+ const labelClass = theme?.labelClassName;
11730
+ const labelContent = /* @__PURE__ */ jsxs(Fragment, { children: [
11731
+ fieldDef.label,
11732
+ fieldDef.required ? /* @__PURE__ */ jsx("span", { className: "ml-1 text-red-500", children: "*" }) : null
11733
+ ] });
11734
+ const labelEl = theme ? /* @__PURE__ */ jsx(Label, { className: labelClass, children: labelContent }) : /* @__PURE__ */ jsx(Label, { className: "text-sm font-medium", children: labelContent });
11735
+ const bodyClass = cn(
11736
+ "-mt-1 flex min-w-0 flex-col gap-3 border-t border-[#D0D0D0] bg-white px-3 py-3",
11737
+ disabled && "pointer-events-none opacity-60"
11738
+ );
11739
+ const subtitle = typeof fieldDef.meta?.subtitle === "string" && fieldDef.meta.subtitle.trim().length > 0 ? fieldDef.meta.subtitle.trim() : "";
11740
+ return /* @__PURE__ */ jsxs("div", { className: cn("w-full min-w-0", wrapperClass), children: [
11741
+ labelEl,
11742
+ /* @__PURE__ */ jsxs("div", { className: bodyClass, children: [
11743
+ subtitle ? /* @__PURE__ */ jsx("p", { className: "-mt-0.5 mb-0 text-xs font-semibold tracking-wide text-slate-700", children: subtitle }) : null,
11744
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-3 text-xs md:grid-cols-2 xl:grid-cols-4", children: [
11745
+ /* @__PURE__ */ jsxs(Panel3, { title: "Stone disease", children: [
11746
+ /* @__PURE__ */ jsxs("label", { className: "block", children: [
11747
+ /* @__PURE__ */ jsx("span", { className: "mb-1 block font-medium text-slate-700", children: "Stone size (mm)" }),
11748
+ /* @__PURE__ */ jsx(
11749
+ Input,
11750
+ {
11751
+ type: "number",
11752
+ min: 0,
11753
+ step: "any",
11754
+ className: cn(
11755
+ "h-8 text-xs",
11756
+ disabled && "pointer-events-none"
11757
+ ),
11758
+ value: safe.stoneSizeMm,
11759
+ onChange: (e) => {
11760
+ const raw = e.target.value;
11761
+ const n = Number(raw);
11762
+ update({
11763
+ ...safe,
11764
+ stoneSizeMm: raw === "" || raw === "-" ? 0 : !Number.isFinite(n) ? 0 : Math.max(0, n)
11765
+ });
11766
+ },
11767
+ disabled
11768
+ }
11769
+ )
11770
+ ] }),
11771
+ /* @__PURE__ */ jsxs("label", { className: "mt-2 flex items-center gap-2", children: [
11772
+ /* @__PURE__ */ jsx(
11773
+ Checkbox,
11774
+ {
11775
+ checked: safe.hydronephrosis,
11776
+ disabled,
11777
+ onCheckedChange: (checked) => update({ ...safe, hydronephrosis: checked === true })
11778
+ }
11779
+ ),
11780
+ /* @__PURE__ */ jsx("span", { className: "text-slate-700", children: "Hydronephrosis on imaging" })
11781
+ ] }),
11782
+ /* @__PURE__ */ jsx(
11783
+ "div",
11784
+ {
11785
+ className: cn(
11786
+ "mt-2 rounded p-2 text-[11px]",
11787
+ stone.surgical && safe.stoneSizeMm > 0 ? "bg-red-500/10 text-red-800" : safe.stoneSizeMm > 0 ? "bg-emerald-500/10 text-emerald-900" : "bg-muted/40 text-muted-foreground"
11788
+ ),
11789
+ children: stone.plan
11790
+ }
11791
+ ),
11792
+ /* @__PURE__ */ jsx("p", { className: "mt-1 text-[10px] text-muted-foreground", children: "Trigger: >10 mm OR obstruction \u2192 surgical." })
11793
+ ] }),
11794
+ /* @__PURE__ */ jsxs(Panel3, { title: "Prostate / BPH", children: [
11795
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
11796
+ /* @__PURE__ */ jsxs("label", { className: "block", children: [
11797
+ /* @__PURE__ */ jsx("span", { className: "mb-1 block font-medium text-slate-700", children: "Volume (cc)" }),
11798
+ /* @__PURE__ */ jsx(
11799
+ Input,
11800
+ {
11801
+ type: "number",
11802
+ min: 0,
11803
+ step: "any",
11804
+ className: cn(
11805
+ "h-8 text-xs",
11806
+ disabled && "pointer-events-none"
11807
+ ),
11808
+ value: safe.prostateVolumeCc,
11809
+ onChange: (e) => {
11810
+ const raw = e.target.value;
11811
+ const n = Number(raw);
11812
+ update({
11813
+ ...safe,
11814
+ prostateVolumeCc: raw === "" || raw === "-" ? 0 : !Number.isFinite(n) ? 0 : Math.max(0, n)
11815
+ });
11816
+ },
11817
+ disabled
11818
+ }
11819
+ )
11820
+ ] }),
11821
+ /* @__PURE__ */ jsxs("label", { className: "block", children: [
11822
+ /* @__PURE__ */ jsx("span", { className: "mb-1 block font-medium text-slate-700", children: "PSA (ng/ml)" }),
11823
+ /* @__PURE__ */ jsx(
11824
+ Input,
11825
+ {
11826
+ type: "number",
11827
+ min: 0,
11828
+ step: 0.1,
11829
+ className: cn(
11830
+ "h-8 text-xs",
11831
+ psaHigh && "border-red-400 text-red-800",
11832
+ disabled && "pointer-events-none"
11833
+ ),
11834
+ value: safe.psaNgMl,
11835
+ onChange: (e) => {
11836
+ const raw = e.target.value;
11837
+ const n = Number(raw);
11838
+ update({
11839
+ ...safe,
11840
+ psaNgMl: raw === "" || raw === "-" ? 0 : !Number.isFinite(n) ? 0 : Math.max(0, n)
11841
+ });
11842
+ },
11843
+ disabled
11844
+ }
11845
+ )
11846
+ ] }),
11847
+ /* @__PURE__ */ jsxs("label", { className: "col-span-2 block", children: [
11848
+ /* @__PURE__ */ jsx("span", { className: "mb-1 block font-medium text-slate-700", children: "Uroflow Qmax (ml/s)" }),
11849
+ /* @__PURE__ */ jsx(
11850
+ Input,
11851
+ {
11852
+ type: "number",
11853
+ min: 0,
11854
+ step: 0.1,
11855
+ className: cn(
11856
+ "h-8 text-xs",
11857
+ qmaxLow && "border-amber-500 text-amber-900",
11858
+ disabled && "pointer-events-none"
11859
+ ),
11860
+ value: safe.uroflowQmaxMlSec,
11861
+ onChange: (e) => {
11862
+ const raw = e.target.value;
11863
+ const n = Number(raw);
11864
+ update({
11865
+ ...safe,
11866
+ uroflowQmaxMlSec: raw === "" || raw === "-" ? 0 : !Number.isFinite(n) ? 0 : Math.max(0, n)
11867
+ });
11868
+ },
11869
+ disabled
11870
+ }
11871
+ )
11872
+ ] })
11873
+ ] }),
11874
+ /* @__PURE__ */ jsx(
11875
+ "div",
11876
+ {
11877
+ className: cn(
11878
+ "mt-2 rounded p-2 text-[11px]",
11879
+ safe.prostateVolumeCc > 30 ? "bg-amber-500/10 text-amber-900" : safe.prostateVolumeCc > 0 ? "bg-emerald-500/10 text-emerald-900" : "bg-muted/40 text-muted-foreground"
11880
+ ),
11881
+ children: prostateLine
11882
+ }
11883
+ ),
11884
+ /* @__PURE__ */ jsx("p", { className: "mt-1 text-[10px] text-muted-foreground", children: "<30 cc medical \xB7 30\u201380 cc TURP \xB7 >80 cc HoLEP/Open" })
11885
+ ] }),
11886
+ /* @__PURE__ */ jsxs(Panel3, { title: "IPSS & cues", children: [
11887
+ /* @__PURE__ */ jsxs("div", { className: "mb-2 flex items-center justify-between", children: [
11888
+ /* @__PURE__ */ jsx("span", { className: "text-slate-700", children: "IPSS total" }),
11889
+ /* @__PURE__ */ jsxs("span", { className: `rounded-full px-2 py-0.5 text-[11px] font-semibold ${ipssBandCls}`, children: [
11890
+ ipssTotal,
11891
+ "/35 \xB7 ",
11892
+ urologyIpssBand(ipssTotal)
11893
+ ] })
11894
+ ] }),
11895
+ /* @__PURE__ */ jsx("div", { className: "mb-3 h-1.5 overflow-hidden rounded-full bg-slate-200", children: /* @__PURE__ */ jsx(
11896
+ "div",
11897
+ {
11898
+ className: cn(
11899
+ "h-full transition-[width]",
11900
+ ipssTotal >= 20 ? "bg-red-500" : ipssTotal >= 8 ? "bg-amber-500" : "bg-emerald-500"
11901
+ ),
11902
+ style: { width: `${Math.min(100, ipssTotal / 35 * 100)}%` }
11903
+ }
11904
+ ) }),
11905
+ /* @__PURE__ */ jsxs("p", { className: "mb-3 text-[10px] text-muted-foreground", children: [
11906
+ "From smart history (",
11907
+ /* @__PURE__ */ jsx("span", { className: "font-mono text-foreground", children: SMART_HISTORY_FIELD }),
11908
+ "). \u226520 \u2192 consider surgical intervention."
11909
+ ] }),
11910
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1.5 text-[11px]", children: [
11911
+ smart.haematuria.present && !smart.haematuria.painful ? /* @__PURE__ */ jsx("div", { className: "rounded bg-red-500/10 p-1.5 text-red-800", children: "Painless haematuria \u2014 mandatory cystoscopy" }) : null,
11912
+ psaHigh ? /* @__PURE__ */ jsx("div", { className: "rounded bg-amber-500/10 p-1.5 text-amber-900", children: "PSA >4 \u2014 workup for Ca prostate" }) : null,
11913
+ exam.dre.consistency === DRE_HARD ? /* @__PURE__ */ jsxs("div", { className: "rounded bg-red-500/10 p-1.5 text-red-800", children: [
11914
+ "Hard / nodular prostate (",
11915
+ /* @__PURE__ */ jsx("span", { className: "font-mono", children: EXAMINATION_FIELD }),
11916
+ ") \u2014 biopsy pathway"
11917
+ ] }) : null,
11918
+ exam.gu.suspiciousMass ? /* @__PURE__ */ jsx("div", { className: "rounded bg-red-500/10 p-1.5 text-red-800", children: "Suspicious scrotal mass \u2014 urgent surgical eval" }) : null
11919
+ ] })
11920
+ ] }),
11921
+ /* @__PURE__ */ jsx(Panel3, { title: "Risk stratification", children: /* @__PURE__ */ jsx("div", { className: "space-y-2", children: [
11922
+ ["ckd", "CKD"],
11923
+ ["diabetes", "Diabetes"],
11924
+ ["anticoagulants", "Anticoagulants"],
11925
+ ["activeInfection", "Active infection"]
11926
+ ].map(([key, lab]) => /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
11927
+ /* @__PURE__ */ jsx(
11928
+ Checkbox,
11929
+ {
11930
+ checked: safe.risk[key],
11931
+ disabled,
11932
+ onCheckedChange: (c) => setRisk(key, c === true)
11933
+ }
11934
+ ),
11935
+ /* @__PURE__ */ jsx("span", { className: "text-slate-700", children: lab })
11936
+ ] }, key)) }) })
11937
+ ] })
11938
+ ] }),
11939
+ showError ? /* @__PURE__ */ jsx("p", { className: "px-3 pb-2 text-xs text-red-500", children: error }) : null
11940
+ ] });
11941
+ };
10176
11942
  var FieldRenderer = ({ fieldId }) => {
10177
11943
  const { fieldDef, visible } = useField(fieldId);
10178
11944
  if (!visible || !fieldDef) {
@@ -10254,6 +12020,12 @@ function renderWidget(fieldId, fieldDef) {
10254
12020
  return /* @__PURE__ */ jsx(GsGradingWidget, { fieldId });
10255
12021
  case "pain_scale_flags":
10256
12022
  return /* @__PURE__ */ jsx(PainScaleFlagsWidget, { fieldId });
12023
+ case "urology_smart_history":
12024
+ return /* @__PURE__ */ jsx(UrologySmartHistoryWidget, { fieldId });
12025
+ case "urology_examination":
12026
+ return /* @__PURE__ */ jsx(UrologyExaminationWidget, { fieldId });
12027
+ case "urology_pathway":
12028
+ return /* @__PURE__ */ jsx(UrologyPathwayWidget, { fieldId });
10257
12029
  case "toggle": {
10258
12030
  const { value, setValue, setTouched, disabled } = useField(fieldId);
10259
12031
  const store = useFormStore();
@@ -11117,7 +12889,43 @@ var ReadOnlyFieldRenderer = ({
11117
12889
  ].join("\n");
11118
12890
  return /* @__PURE__ */ jsx(ReadOnlyText, { fieldDef, value: lines });
11119
12891
  }
11120
- case "general_surgery_smart_history":
12892
+ case "urology_smart_history":
12893
+ return /* @__PURE__ */ jsx(
12894
+ ReadOnlyText,
12895
+ {
12896
+ fieldDef,
12897
+ value: value && typeof value === "object" ? JSON.stringify(value, null, 2) : value == null || value === "" ? "\u2014" : String(value)
12898
+ }
12899
+ );
12900
+ case "urology_examination":
12901
+ return /* @__PURE__ */ jsx(
12902
+ ReadOnlyText,
12903
+ {
12904
+ fieldDef,
12905
+ value: value && typeof value === "object" ? JSON.stringify(value, null, 2) : value == null || value === "" ? "\u2014" : String(value)
12906
+ }
12907
+ );
12908
+ case "urology_pathway":
12909
+ return /* @__PURE__ */ jsx(
12910
+ ReadOnlyText,
12911
+ {
12912
+ fieldDef,
12913
+ value: value && typeof value === "object" ? JSON.stringify(value, null, 2) : value == null || value === "" ? "\u2014" : String(value)
12914
+ }
12915
+ );
12916
+ case "general_surgery_smart_history": {
12917
+ const structuredDisplay = value && typeof value === "object" ? JSON.stringify(normalizeGeneralSurgerySmartHistory(value), null, 2) : value == null || value === "" ? "\u2014" : String(value);
12918
+ const hopcDef = resolveFieldDef?.("symptoms");
12919
+ const hopcRaw = allValues?.["symptoms"];
12920
+ const hopcStr = typeof hopcRaw === "string" ? hopcRaw : hopcRaw != null && hopcRaw !== "" ? String(hopcRaw) : "";
12921
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
12922
+ /* @__PURE__ */ jsx(ReadOnlyText, { fieldDef, value: structuredDisplay }),
12923
+ hopcDef ? /* @__PURE__ */ jsx(ReadOnlyText, { fieldDef: hopcDef, value: hopcStr }) : hopcStr ? /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
12924
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-gray-700", children: "History of presenting complaint" }),
12925
+ /* @__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: hopcStr })
12926
+ ] }) : null
12927
+ ] });
12928
+ }
11121
12929
  case "general_surgery_grading":
11122
12930
  return /* @__PURE__ */ jsx(
11123
12931
  ReadOnlyText,
@@ -11346,6 +13154,6 @@ function createUploadHandler(options) {
11346
13154
  };
11347
13155
  }
11348
13156
 
11349
- export { AddInvestigationField, AddMedicationField, DifferentialDiagnosis, DynamicForm, EMAIL_REGEX, FieldRenderer, FormControls, FormProvider, FormStore, ImageUploadWidget, MAR_MEDICATION_ORDERS_META_KEY, MediaUploadWidget, ReadOnlyForm, ReadOnlyImageUpload, ReadOnlyMediaUpload, ReadOnlySignature, ReadOnlyTable, RichTextWidget, SignatureUploadWidget, SmartForm, SmartTextareaWidget, createUploadHandler, evaluateRules, fieldMetaRequestsMarMedicationOrdersButton, useField, useFieldHandlers, useForm, useFormStore, useFrequentItems, usePackages, useSmartKeywords, validateField, validateForm };
13157
+ export { AddInvestigationField, AddMedicationField, DifferentialDiagnosis, DynamicForm, EMAIL_REGEX, FieldRenderer, FormControls, FormProvider, FormStore, ImageUploadWidget, MAR_MEDICATION_ORDERS_META_KEY, MediaUploadWidget, ReadOnlyForm, ReadOnlyImageUpload, ReadOnlyMediaUpload, ReadOnlySignature, ReadOnlyTable, RichTextWidget, SignatureUploadWidget, SmartForm, SmartTextareaWidget, attachUrologyClinicalPathwayMetadata, createUploadHandler, evaluateRules, fieldMetaRequestsMarMedicationOrdersButton, isUrologyTemplate, shouldFoldUrologyClinicalPathway, useField, useFieldHandlers, useForm, useFormStore, useFrequentItems, usePackages, useSmartKeywords, validateField, validateForm };
11350
13158
  //# sourceMappingURL=index.mjs.map
11351
13159
  //# sourceMappingURL=index.mjs.map