formanitor 0.0.40 → 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.cjs +1900 -93
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +34 -3
- package/dist/index.d.ts +34 -3
- package/dist/index.mjs +1898 -94
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
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
|
-
|
|
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:
|
|
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
|
-
|
|
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
|
|
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:
|
|
5726
|
-
P:
|
|
5727
|
-
A:
|
|
5728
|
-
L:
|
|
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:
|
|
5762
|
-
P:
|
|
5763
|
-
A:
|
|
5764
|
-
L:
|
|
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:
|
|
5783
|
-
P:
|
|
5784
|
-
A:
|
|
5785
|
-
L:
|
|
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
|
|
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;
|
|
@@ -9236,6 +10075,7 @@ var SliderWidget = ({ fieldId }) => {
|
|
|
9236
10075
|
] });
|
|
9237
10076
|
};
|
|
9238
10077
|
var CHIEF_CHIPS_FIELD = "chief_complaints_chips";
|
|
10078
|
+
var GS_SYMPTOMS_FIELD = "symptoms";
|
|
9239
10079
|
var SWELLING_OPTS = [
|
|
9240
10080
|
{ value: "reducible_hernia", label: "Reducible (hernia)" },
|
|
9241
10081
|
{ value: "cough_impulse", label: "Cough impulse" },
|
|
@@ -9261,7 +10101,7 @@ var THYROID_OPTS = [
|
|
|
9261
10101
|
{ value: "voice_change", label: "Voice change" },
|
|
9262
10102
|
{ value: "thyrotoxicosis", label: "Thyrotoxicosis symptoms" }
|
|
9263
10103
|
];
|
|
9264
|
-
var
|
|
10104
|
+
var SOCRATES_KEYS2 = [
|
|
9265
10105
|
"site",
|
|
9266
10106
|
"onset",
|
|
9267
10107
|
"character",
|
|
@@ -9276,16 +10116,26 @@ function Panel({ title, children }) {
|
|
|
9276
10116
|
/* @__PURE__ */ jsx("div", { className: "p-3", children })
|
|
9277
10117
|
] });
|
|
9278
10118
|
}
|
|
9279
|
-
function
|
|
9280
|
-
const raw = state.values[CHIEF_CHIPS_FIELD];
|
|
10119
|
+
function chipListFromRaw(raw) {
|
|
9281
10120
|
return Array.isArray(raw) ? raw.filter((x) => typeof x === "string") : [];
|
|
9282
10121
|
}
|
|
9283
10122
|
var GsSmartHistoryWidget = ({ fieldId }) => {
|
|
9284
10123
|
const { fieldDef, value, setValue, setTouched, error, touched, disabled } = useField(fieldId);
|
|
10124
|
+
const hopcField = useField(GS_SYMPTOMS_FIELD);
|
|
9285
10125
|
const { state } = useForm();
|
|
9286
10126
|
const showError = !!error && (touched || state.submitAttempted);
|
|
9287
10127
|
const safe = useMemo(() => normalizeGeneralSurgerySmartHistory(value), [value]);
|
|
9288
|
-
const
|
|
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]);
|
|
9289
10139
|
const showPain = chips.includes("pain");
|
|
9290
10140
|
const showSwelling = chips.includes("swelling_lump");
|
|
9291
10141
|
const showGI = chips.includes("bleeding") || chips.includes("obstruction");
|
|
@@ -9345,7 +10195,7 @@ var GsSmartHistoryWidget = ({ fieldId }) => {
|
|
|
9345
10195
|
labelEl,
|
|
9346
10196
|
/* @__PURE__ */ jsxs("div", { className: bodyClass, children: [
|
|
9347
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: [
|
|
9348
|
-
|
|
10198
|
+
SOCRATES_KEYS2.map((k) => /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
9349
10199
|
/* @__PURE__ */ jsx("span", { className: "text-[10px] font-medium uppercase tracking-wide text-muted-foreground", children: k }),
|
|
9350
10200
|
/* @__PURE__ */ jsx(
|
|
9351
10201
|
Input,
|
|
@@ -9551,15 +10401,51 @@ var GsSmartHistoryWidget = ({ fieldId }) => {
|
|
|
9551
10401
|
] }, o.value)) })
|
|
9552
10402
|
] }) : null,
|
|
9553
10403
|
/* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
9554
|
-
/* @__PURE__ */
|
|
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,
|
|
9555
10437
|
/* @__PURE__ */ jsx(
|
|
9556
10438
|
Textarea,
|
|
9557
10439
|
{
|
|
9558
|
-
className: "min-h-[
|
|
9559
|
-
placeholder: "
|
|
9560
|
-
value:
|
|
9561
|
-
onChange: (e) =>
|
|
9562
|
-
|
|
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
|
|
9563
10449
|
}
|
|
9564
10450
|
)
|
|
9565
10451
|
] })
|
|
@@ -9611,12 +10497,72 @@ function RegionCard({ title, children }) {
|
|
|
9611
10497
|
/* @__PURE__ */ jsx("div", { className: "p-3", children })
|
|
9612
10498
|
] });
|
|
9613
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
|
+
}
|
|
9614
10554
|
var GsExaminationWidget = ({ fieldId }) => {
|
|
9615
10555
|
const { fieldDef, value, setValue, setTouched, error, touched, disabled } = useField(fieldId);
|
|
9616
10556
|
const clinicalField = useField(GS_CLINICAL_EXAMINATION_FIELD);
|
|
9617
10557
|
const { state } = useForm();
|
|
9618
10558
|
const showError = !!error && (touched || state.submitAttempted);
|
|
9619
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]);
|
|
9620
10566
|
const update = (next) => {
|
|
9621
10567
|
setValue(next);
|
|
9622
10568
|
setTouched();
|
|
@@ -9808,15 +10754,41 @@ var GsExaminationWidget = ({ fieldId }) => {
|
|
|
9808
10754
|
"Tenderness"
|
|
9809
10755
|
] })
|
|
9810
10756
|
] }) }) : null,
|
|
9811
|
-
has("breast") ? /* @__PURE__ */ jsx(RegionCard, { title: "Breast exam", children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-
|
|
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: [
|
|
9812
10784
|
/* @__PURE__ */ jsxs("label", { className: "block", children: [
|
|
9813
|
-
/* @__PURE__ */ jsx("span", { className: "mb-1 block font-medium", children: "
|
|
10785
|
+
/* @__PURE__ */ jsx("span", { className: "mb-1 block font-medium", children: "Size" }),
|
|
9814
10786
|
/* @__PURE__ */ jsx(
|
|
9815
10787
|
Input,
|
|
9816
10788
|
{
|
|
9817
10789
|
className: "h-8 text-xs",
|
|
9818
|
-
value: safe.
|
|
9819
|
-
onChange: (e) => update({ ...safe,
|
|
10790
|
+
value: safe.thyroid.size,
|
|
10791
|
+
onChange: (e) => update({ ...safe, thyroid: { ...safe.thyroid, size: e.target.value } }),
|
|
9820
10792
|
disabled
|
|
9821
10793
|
}
|
|
9822
10794
|
)
|
|
@@ -9825,55 +10797,8 @@ var GsExaminationWidget = ({ fieldId }) => {
|
|
|
9825
10797
|
/* @__PURE__ */ jsx(
|
|
9826
10798
|
Checkbox,
|
|
9827
10799
|
{
|
|
9828
|
-
checked: safe.
|
|
9829
|
-
onCheckedChange: (c) => update({ ...safe,
|
|
9830
|
-
disabled
|
|
9831
|
-
}
|
|
9832
|
-
),
|
|
9833
|
-
"Mobile"
|
|
9834
|
-
] }),
|
|
9835
|
-
/* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
|
|
9836
|
-
/* @__PURE__ */ jsx(
|
|
9837
|
-
Checkbox,
|
|
9838
|
-
{
|
|
9839
|
-
checked: safe.breast.skinInvolvement,
|
|
9840
|
-
onCheckedChange: (c) => update({ ...safe, breast: { ...safe.breast, skinInvolvement: c === true } }),
|
|
9841
|
-
disabled
|
|
9842
|
-
}
|
|
9843
|
-
),
|
|
9844
|
-
"Skin involvement"
|
|
9845
|
-
] }),
|
|
9846
|
-
/* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
|
|
9847
|
-
/* @__PURE__ */ jsx(
|
|
9848
|
-
Checkbox,
|
|
9849
|
-
{
|
|
9850
|
-
checked: safe.breast.axillaryNodes,
|
|
9851
|
-
onCheckedChange: (c) => update({ ...safe, breast: { ...safe.breast, axillaryNodes: c === true } }),
|
|
9852
|
-
disabled
|
|
9853
|
-
}
|
|
9854
|
-
),
|
|
9855
|
-
"Axillary nodes"
|
|
9856
|
-
] })
|
|
9857
|
-
] }) }) : null,
|
|
9858
|
-
has("thyroid") ? /* @__PURE__ */ jsx(RegionCard, { title: "Thyroid exam", children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-3 text-xs md:grid-cols-4", children: [
|
|
9859
|
-
/* @__PURE__ */ jsxs("label", { className: "block", children: [
|
|
9860
|
-
/* @__PURE__ */ jsx("span", { className: "mb-1 block font-medium", children: "Size" }),
|
|
9861
|
-
/* @__PURE__ */ jsx(
|
|
9862
|
-
Input,
|
|
9863
|
-
{
|
|
9864
|
-
className: "h-8 text-xs",
|
|
9865
|
-
value: safe.thyroid.size,
|
|
9866
|
-
onChange: (e) => update({ ...safe, thyroid: { ...safe.thyroid, size: e.target.value } }),
|
|
9867
|
-
disabled
|
|
9868
|
-
}
|
|
9869
|
-
)
|
|
9870
|
-
] }),
|
|
9871
|
-
/* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
|
|
9872
|
-
/* @__PURE__ */ jsx(
|
|
9873
|
-
Checkbox,
|
|
9874
|
-
{
|
|
9875
|
-
checked: safe.thyroid.mobileDeglutition,
|
|
9876
|
-
onCheckedChange: (c) => update({ ...safe, thyroid: { ...safe.thyroid, mobileDeglutition: c === true } }),
|
|
10800
|
+
checked: safe.thyroid.mobileDeglutition,
|
|
10801
|
+
onCheckedChange: (c) => update({ ...safe, thyroid: { ...safe.thyroid, mobileDeglutition: c === true } }),
|
|
9877
10802
|
disabled
|
|
9878
10803
|
}
|
|
9879
10804
|
),
|
|
@@ -9988,13 +10913,43 @@ var GsExaminationWidget = ({ fieldId }) => {
|
|
|
9988
10913
|
] }) }) : null
|
|
9989
10914
|
] }),
|
|
9990
10915
|
/* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
9991
|
-
/* @__PURE__ */
|
|
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,
|
|
9992
10946
|
/* @__PURE__ */ jsx(
|
|
9993
10947
|
Textarea,
|
|
9994
10948
|
{
|
|
9995
10949
|
className: "min-h-[88px] rounded-md border border-input bg-white text-sm",
|
|
9996
10950
|
value: typeof clinicalField.value === "string" ? clinicalField.value : clinicalField.value == null ? "" : String(clinicalField.value),
|
|
9997
10951
|
onChange: (e) => {
|
|
10952
|
+
setClinicalNarrativeLocked(true);
|
|
9998
10953
|
clinicalField.setValue(e.target.value);
|
|
9999
10954
|
clinicalField.setTouched();
|
|
10000
10955
|
},
|
|
@@ -10008,7 +10963,7 @@ var GsExaminationWidget = ({ fieldId }) => {
|
|
|
10008
10963
|
};
|
|
10009
10964
|
var CHIEF_CHIPS_FIELD2 = "chief_complaints_chips";
|
|
10010
10965
|
var GS_EXAMINATION_FIELD = "gs_examination";
|
|
10011
|
-
function
|
|
10966
|
+
function chipList(state) {
|
|
10012
10967
|
const raw = state.values[CHIEF_CHIPS_FIELD2];
|
|
10013
10968
|
return Array.isArray(raw) ? raw.filter((x) => typeof x === "string") : [];
|
|
10014
10969
|
}
|
|
@@ -10022,7 +10977,7 @@ var GsGradingWidget = ({ fieldId }) => {
|
|
|
10022
10977
|
const { state } = useForm();
|
|
10023
10978
|
const showError = !!error && (touched || state.submitAttempted);
|
|
10024
10979
|
const safe = useMemo(() => normalizeGeneralSurgeryGrading(value), [value]);
|
|
10025
|
-
const chips = useMemo(() =>
|
|
10980
|
+
const chips = useMemo(() => chipList(state), [state]);
|
|
10026
10981
|
const regions = useMemo(() => regionList(state), [state]);
|
|
10027
10982
|
const visibleRows = useMemo(() => {
|
|
10028
10983
|
return ALL_GS_CONDITIONS.filter(
|
|
@@ -10177,6 +11132,813 @@ var PainScaleFlagsWidget = ({ fieldId }) => {
|
|
|
10177
11132
|
showError && /* @__PURE__ */ jsx("p", { className: "text-xs text-red-500", children: error })
|
|
10178
11133
|
] });
|
|
10179
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
|
+
};
|
|
10180
11942
|
var FieldRenderer = ({ fieldId }) => {
|
|
10181
11943
|
const { fieldDef, visible } = useField(fieldId);
|
|
10182
11944
|
if (!visible || !fieldDef) {
|
|
@@ -10258,6 +12020,12 @@ function renderWidget(fieldId, fieldDef) {
|
|
|
10258
12020
|
return /* @__PURE__ */ jsx(GsGradingWidget, { fieldId });
|
|
10259
12021
|
case "pain_scale_flags":
|
|
10260
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 });
|
|
10261
12029
|
case "toggle": {
|
|
10262
12030
|
const { value, setValue, setTouched, disabled } = useField(fieldId);
|
|
10263
12031
|
const store = useFormStore();
|
|
@@ -11121,7 +12889,43 @@ var ReadOnlyFieldRenderer = ({
|
|
|
11121
12889
|
].join("\n");
|
|
11122
12890
|
return /* @__PURE__ */ jsx(ReadOnlyText, { fieldDef, value: lines });
|
|
11123
12891
|
}
|
|
11124
|
-
case "
|
|
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
|
+
}
|
|
11125
12929
|
case "general_surgery_grading":
|
|
11126
12930
|
return /* @__PURE__ */ jsx(
|
|
11127
12931
|
ReadOnlyText,
|
|
@@ -11350,6 +13154,6 @@ function createUploadHandler(options) {
|
|
|
11350
13154
|
};
|
|
11351
13155
|
}
|
|
11352
13156
|
|
|
11353
|
-
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 };
|
|
11354
13158
|
//# sourceMappingURL=index.mjs.map
|
|
11355
13159
|
//# sourceMappingURL=index.mjs.map
|