formanitor 0.0.31 → 0.0.33
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 +475 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +32 -3
- package/dist/index.d.ts +32 -3
- package/dist/index.mjs +472 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -58,6 +58,13 @@ var DialogPrimitive__namespace = /*#__PURE__*/_interopNamespace(DialogPrimitive)
|
|
|
58
58
|
var nlp__default = /*#__PURE__*/_interopDefault(nlp);
|
|
59
59
|
var SliderPrimitive__namespace = /*#__PURE__*/_interopNamespace(SliderPrimitive);
|
|
60
60
|
|
|
61
|
+
// src/core/marMedicationOrdersMeta.ts
|
|
62
|
+
var MAR_MEDICATION_ORDERS_META_KEY = "mar_medication_orders";
|
|
63
|
+
function fieldMetaRequestsMarMedicationOrdersButton(meta) {
|
|
64
|
+
if (!meta || typeof meta !== "object") return false;
|
|
65
|
+
return meta[MAR_MEDICATION_ORDERS_META_KEY] === true;
|
|
66
|
+
}
|
|
67
|
+
|
|
61
68
|
// src/core/validate.ts
|
|
62
69
|
var EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
63
70
|
function validateField(value, field) {
|
|
@@ -458,7 +465,7 @@ var FormStore = class {
|
|
|
458
465
|
result[field.id] = parts.length > 0 ? parts.join("\n\n") : null;
|
|
459
466
|
return;
|
|
460
467
|
}
|
|
461
|
-
if (field.type === "image_upload" || field.type === "signature") {
|
|
468
|
+
if (field.type === "image_upload" || field.type === "media_upload" || field.type === "signature") {
|
|
462
469
|
const raw = values[field.id];
|
|
463
470
|
if (raw !== void 0 && raw !== null && raw !== "") {
|
|
464
471
|
const key = typeof raw === "string" ? raw : raw.s3_key || raw.value || null;
|
|
@@ -2186,6 +2193,162 @@ var ImageUploadWidget = ({ fieldId }) => {
|
|
|
2186
2193
|
showError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-red-500", children: error })
|
|
2187
2194
|
] });
|
|
2188
2195
|
};
|
|
2196
|
+
function urlLooksLikePdf(url) {
|
|
2197
|
+
return /\.pdf($|\?)/i.test(url) || url.toLowerCase().includes("application/pdf");
|
|
2198
|
+
}
|
|
2199
|
+
function isAcceptedMediaFile(file) {
|
|
2200
|
+
if (file.type.startsWith("image/")) return true;
|
|
2201
|
+
if (file.type === "application/pdf") return true;
|
|
2202
|
+
if (file.name.toLowerCase().endsWith(".pdf")) return true;
|
|
2203
|
+
return false;
|
|
2204
|
+
}
|
|
2205
|
+
var MediaUploadWidget = ({ fieldId }) => {
|
|
2206
|
+
const { fieldDef, value, setValue, setTouched, error, disabled, touched } = useField(fieldId);
|
|
2207
|
+
const store = useFormStore();
|
|
2208
|
+
const { state } = useForm();
|
|
2209
|
+
const [isUploading, setIsUploading] = React15.useState(false);
|
|
2210
|
+
const [preview, setPreview] = React15.useState(null);
|
|
2211
|
+
const [previewIsPdf, setPreviewIsPdf] = React15.useState(false);
|
|
2212
|
+
const fileInputRef = React15.useRef(null);
|
|
2213
|
+
const pendingPreviewKindRef = React15.useRef(null);
|
|
2214
|
+
const showError = !!error && (touched || state.submitAttempted);
|
|
2215
|
+
if (!fieldDef) return null;
|
|
2216
|
+
const uploadHandler = store.getUploadHandler();
|
|
2217
|
+
if (!uploadHandler) {
|
|
2218
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
2219
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Label, { htmlFor: fieldId, children: [
|
|
2220
|
+
fieldDef.label,
|
|
2221
|
+
fieldDef.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-red-500", children: "*" })
|
|
2222
|
+
] }),
|
|
2223
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-2 border-red-300 rounded-lg p-4 bg-red-50", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-red-600", children: "Upload handler not configured. Please provide an onUpload function in FormProvider config." }) })
|
|
2224
|
+
] });
|
|
2225
|
+
}
|
|
2226
|
+
React15__namespace.default.useEffect(() => {
|
|
2227
|
+
if (value && typeof value === "string") {
|
|
2228
|
+
setPreview(value);
|
|
2229
|
+
if (pendingPreviewKindRef.current) {
|
|
2230
|
+
setPreviewIsPdf(pendingPreviewKindRef.current === "pdf");
|
|
2231
|
+
pendingPreviewKindRef.current = null;
|
|
2232
|
+
} else {
|
|
2233
|
+
setPreviewIsPdf(urlLooksLikePdf(value));
|
|
2234
|
+
}
|
|
2235
|
+
} else {
|
|
2236
|
+
setPreview(null);
|
|
2237
|
+
setPreviewIsPdf(false);
|
|
2238
|
+
}
|
|
2239
|
+
}, [value]);
|
|
2240
|
+
const handleFileSelect = async (event) => {
|
|
2241
|
+
const file = event.target.files?.[0];
|
|
2242
|
+
if (!file) return;
|
|
2243
|
+
if (!isAcceptedMediaFile(file)) {
|
|
2244
|
+
alert("Please select an image or PDF file");
|
|
2245
|
+
return;
|
|
2246
|
+
}
|
|
2247
|
+
const maxSize = 10 * 1024 * 1024;
|
|
2248
|
+
if (file.size > maxSize) {
|
|
2249
|
+
alert("File size must be less than 10MB");
|
|
2250
|
+
return;
|
|
2251
|
+
}
|
|
2252
|
+
const isPdf = file.type === "application/pdf" || file.name.toLowerCase().endsWith(".pdf");
|
|
2253
|
+
setIsUploading(true);
|
|
2254
|
+
setTouched();
|
|
2255
|
+
store.incrementPendingUploads();
|
|
2256
|
+
try {
|
|
2257
|
+
const previewUrl = URL.createObjectURL(file);
|
|
2258
|
+
setPreview(previewUrl);
|
|
2259
|
+
setPreviewIsPdf(isPdf);
|
|
2260
|
+
const s3Key = await uploadHandler(file, file.name);
|
|
2261
|
+
pendingPreviewKindRef.current = isPdf ? "pdf" : "image";
|
|
2262
|
+
setValue(s3Key);
|
|
2263
|
+
} catch (error2) {
|
|
2264
|
+
console.error("Upload failed:", error2);
|
|
2265
|
+
const errorMessage = error2 instanceof Error ? error2.message : "Upload failed. Please try again.";
|
|
2266
|
+
alert(errorMessage);
|
|
2267
|
+
setPreview(null);
|
|
2268
|
+
setPreviewIsPdf(false);
|
|
2269
|
+
} finally {
|
|
2270
|
+
setIsUploading(false);
|
|
2271
|
+
store.decrementPendingUploads();
|
|
2272
|
+
}
|
|
2273
|
+
};
|
|
2274
|
+
const handleRemove = () => {
|
|
2275
|
+
pendingPreviewKindRef.current = null;
|
|
2276
|
+
setValue(null);
|
|
2277
|
+
setPreview(null);
|
|
2278
|
+
setPreviewIsPdf(false);
|
|
2279
|
+
if (fileInputRef.current) {
|
|
2280
|
+
fileInputRef.current.value = "";
|
|
2281
|
+
}
|
|
2282
|
+
setTouched();
|
|
2283
|
+
};
|
|
2284
|
+
const handleUploadClick = () => {
|
|
2285
|
+
fileInputRef.current?.click();
|
|
2286
|
+
};
|
|
2287
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
2288
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Label, { htmlFor: fieldId, children: [
|
|
2289
|
+
fieldDef.label,
|
|
2290
|
+
fieldDef.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-red-500", children: "*" })
|
|
2291
|
+
] }),
|
|
2292
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-2 border-dashed border-gray-300 rounded-lg p-4", children: preview ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
2293
|
+
previewIsPdf ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2294
|
+
"iframe",
|
|
2295
|
+
{
|
|
2296
|
+
src: preview,
|
|
2297
|
+
title: "Uploaded PDF",
|
|
2298
|
+
className: "w-full max-h-48 min-h-36 rounded-lg border border-gray-200 bg-white"
|
|
2299
|
+
}
|
|
2300
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
2301
|
+
"img",
|
|
2302
|
+
{
|
|
2303
|
+
src: preview,
|
|
2304
|
+
alt: "Uploaded image",
|
|
2305
|
+
className: "max-w-full max-h-48 mx-auto rounded-lg"
|
|
2306
|
+
}
|
|
2307
|
+
),
|
|
2308
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2309
|
+
Button,
|
|
2310
|
+
{
|
|
2311
|
+
type: "button",
|
|
2312
|
+
variant: "destructive",
|
|
2313
|
+
size: "sm",
|
|
2314
|
+
className: "absolute top-2 right-2",
|
|
2315
|
+
onClick: handleRemove,
|
|
2316
|
+
disabled: disabled || isUploading,
|
|
2317
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-4 w-4" })
|
|
2318
|
+
}
|
|
2319
|
+
)
|
|
2320
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center py-8", children: [
|
|
2321
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Image, { className: "h-12 w-12 mx-auto text-gray-400 mb-4" }),
|
|
2322
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-600 mb-4", children: "Click to upload an image or PDF, or drag and drop" }),
|
|
2323
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2324
|
+
Button,
|
|
2325
|
+
{
|
|
2326
|
+
type: "button",
|
|
2327
|
+
variant: "outline",
|
|
2328
|
+
onClick: handleUploadClick,
|
|
2329
|
+
disabled: disabled || isUploading,
|
|
2330
|
+
children: [
|
|
2331
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Upload, { className: "h-4 w-4 mr-2" }),
|
|
2332
|
+
isUploading ? "Uploading..." : "Choose Image"
|
|
2333
|
+
]
|
|
2334
|
+
}
|
|
2335
|
+
)
|
|
2336
|
+
] }) }),
|
|
2337
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2338
|
+
"input",
|
|
2339
|
+
{
|
|
2340
|
+
ref: fileInputRef,
|
|
2341
|
+
type: "file",
|
|
2342
|
+
accept: "image/*,application/pdf",
|
|
2343
|
+
onChange: handleFileSelect,
|
|
2344
|
+
className: "hidden",
|
|
2345
|
+
disabled: disabled || isUploading
|
|
2346
|
+
}
|
|
2347
|
+
),
|
|
2348
|
+
fieldDef.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-500", children: fieldDef.description }),
|
|
2349
|
+
showError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-red-500", children: error })
|
|
2350
|
+
] });
|
|
2351
|
+
};
|
|
2189
2352
|
var distance = (a, b) => Math.hypot(a.x - b.x, a.y - b.y);
|
|
2190
2353
|
var smoothPoint = (prev, curr, smoothing = 0.75) => {
|
|
2191
2354
|
if (!prev) return curr;
|
|
@@ -7418,6 +7581,206 @@ var OrthopedicExamWidget = ({ fieldId }) => {
|
|
|
7418
7581
|
) : null
|
|
7419
7582
|
] });
|
|
7420
7583
|
};
|
|
7584
|
+
var MarMedicationOrdersWidget = ({ fieldId }) => {
|
|
7585
|
+
const { fieldDef, value, setTouched, error, disabled, touched } = useField(fieldId);
|
|
7586
|
+
const { state } = useForm();
|
|
7587
|
+
const handlers = useFieldHandlers(fieldId);
|
|
7588
|
+
const showError = !!error && (touched || state.submitAttempted);
|
|
7589
|
+
const onOpen = React15.useCallback(async () => {
|
|
7590
|
+
await handlers.onOpenMedicationOrders?.();
|
|
7591
|
+
setTouched();
|
|
7592
|
+
}, [handlers, setTouched]);
|
|
7593
|
+
if (!fieldDef || fieldDef.type !== "textarea") return null;
|
|
7594
|
+
const textDef = fieldDef;
|
|
7595
|
+
const height = textDef.height;
|
|
7596
|
+
const theme = getThemeConfig("textarea", fieldDef.theme);
|
|
7597
|
+
const wrapperClass = theme?.wrapperClassName ?? "space-y-2";
|
|
7598
|
+
const labelClass = theme?.labelClassName;
|
|
7599
|
+
const labelContent = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
7600
|
+
fieldDef.label,
|
|
7601
|
+
" ",
|
|
7602
|
+
fieldDef.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-red-500", children: "*" })
|
|
7603
|
+
] });
|
|
7604
|
+
const labelEl = theme ? /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: fieldId, className: labelClass, children: labelContent }) : /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: fieldId, children: labelContent });
|
|
7605
|
+
const text = typeof value === "string" ? value : value == null ? "" : String(value);
|
|
7606
|
+
const hasHandler = typeof handlers.onOpenMedicationOrders === "function";
|
|
7607
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: wrapperClass, children: [
|
|
7608
|
+
labelEl,
|
|
7609
|
+
fieldDef.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: fieldDef.description }),
|
|
7610
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2 sm:flex-row sm:items-start sm:justify-between sm:gap-3", children: [
|
|
7611
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7612
|
+
"div",
|
|
7613
|
+
{
|
|
7614
|
+
id: fieldId,
|
|
7615
|
+
className: cn(
|
|
7616
|
+
"min-h-[80px] flex-1 rounded-md border border-input bg-background px-3 py-2 text-sm whitespace-pre-wrap",
|
|
7617
|
+
showError && "border-red-500",
|
|
7618
|
+
!text && "text-muted-foreground"
|
|
7619
|
+
),
|
|
7620
|
+
style: height != null ? { minHeight: height } : void 0,
|
|
7621
|
+
"aria-readonly": "true",
|
|
7622
|
+
children: text || fieldDef.placeholder || "No medication orders added."
|
|
7623
|
+
}
|
|
7624
|
+
),
|
|
7625
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7626
|
+
Button,
|
|
7627
|
+
{
|
|
7628
|
+
type: "button",
|
|
7629
|
+
variant: "default",
|
|
7630
|
+
disabled: disabled || !hasHandler,
|
|
7631
|
+
onClick: onOpen,
|
|
7632
|
+
className: "shrink-0 sm:mt-0",
|
|
7633
|
+
children: "Add medication orders"
|
|
7634
|
+
}
|
|
7635
|
+
)
|
|
7636
|
+
] }),
|
|
7637
|
+
showError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-red-500", children: error })
|
|
7638
|
+
] });
|
|
7639
|
+
};
|
|
7640
|
+
function parseFieldValue(value) {
|
|
7641
|
+
if (value == null) return { orders: [], display_lines: [] };
|
|
7642
|
+
if (Array.isArray(value)) {
|
|
7643
|
+
return {
|
|
7644
|
+
orders: value,
|
|
7645
|
+
display_lines: value.map(() => null)
|
|
7646
|
+
};
|
|
7647
|
+
}
|
|
7648
|
+
if (typeof value === "object") {
|
|
7649
|
+
const v = value;
|
|
7650
|
+
const orders = Array.isArray(v.orders) ? v.orders : [];
|
|
7651
|
+
const rawLines = Array.isArray(v.display_lines) ? v.display_lines : Array.isArray(v.displayLines) ? v.displayLines : [];
|
|
7652
|
+
const display_lines = orders.map((_, i) => rawLines[i] ?? null);
|
|
7653
|
+
return { orders, display_lines };
|
|
7654
|
+
}
|
|
7655
|
+
return { orders: [], display_lines: [] };
|
|
7656
|
+
}
|
|
7657
|
+
function normalizePrescription(res) {
|
|
7658
|
+
const pharmacyOrderId = res.pharmacy_order_id ?? void 0;
|
|
7659
|
+
const orders = Array.isArray(res.orders) ? res.orders : [];
|
|
7660
|
+
const linesRaw = Array.isArray(res.display_lines) ? res.display_lines : [];
|
|
7661
|
+
const mapped = orders.filter((o) => o && typeof o.id === "string").map((o) => ({
|
|
7662
|
+
id: o.id,
|
|
7663
|
+
item_id: o.item_id == null ? void 0 : String(o.item_id),
|
|
7664
|
+
item_name: o.item_name ?? void 0,
|
|
7665
|
+
generic_name: o.generic_name ?? void 0,
|
|
7666
|
+
dose: o.dose == null ? void 0 : String(o.dose),
|
|
7667
|
+
route: o.route ?? void 0,
|
|
7668
|
+
frequency: o.frequency ?? void 0,
|
|
7669
|
+
admin_times: Array.isArray(o.admin_times) ? o.admin_times : void 0,
|
|
7670
|
+
meal_sleep_timing: o.meal_sleep_timing ?? void 0,
|
|
7671
|
+
start_date: o.start_date ?? void 0,
|
|
7672
|
+
end_date: o.end_date ?? void 0,
|
|
7673
|
+
order_type: o.order_type ?? void 0,
|
|
7674
|
+
status: o.status ?? void 0,
|
|
7675
|
+
notes: o.notes ?? null,
|
|
7676
|
+
pharmacy_order_id: pharmacyOrderId
|
|
7677
|
+
}));
|
|
7678
|
+
const display_lines = mapped.map((_, i) => linesRaw[i] ?? null);
|
|
7679
|
+
return { orders: mapped, display_lines };
|
|
7680
|
+
}
|
|
7681
|
+
function formatDuration(start, end) {
|
|
7682
|
+
if (!start && !end) return null;
|
|
7683
|
+
if (start && end) return `${start} \u2192 ${end}`;
|
|
7684
|
+
return start ? `Start: ${start}` : `End: ${end}`;
|
|
7685
|
+
}
|
|
7686
|
+
var DischargeMedicationOrdersWidget = ({ fieldId }) => {
|
|
7687
|
+
const { fieldDef, value, setValue, setTouched, error, disabled, touched, visible } = useField(fieldId);
|
|
7688
|
+
const { state } = useForm();
|
|
7689
|
+
const handlers = useFieldHandlers(fieldId);
|
|
7690
|
+
const showError = !!error && (touched || state.submitAttempted);
|
|
7691
|
+
const { orders, display_lines } = React15.useMemo(() => parseFieldValue(value), [value]);
|
|
7692
|
+
const onAdd = React15.useCallback(async () => {
|
|
7693
|
+
setTouched();
|
|
7694
|
+
const fn = handlers.onOpenDischargeMedicationOrders;
|
|
7695
|
+
if (!fn) return;
|
|
7696
|
+
const res = await fn();
|
|
7697
|
+
if (!res || typeof res !== "object") return;
|
|
7698
|
+
const normalized = normalizePrescription(res);
|
|
7699
|
+
setValue({
|
|
7700
|
+
orders: normalized.orders,
|
|
7701
|
+
display_lines: normalized.display_lines
|
|
7702
|
+
});
|
|
7703
|
+
}, [handlers.onOpenDischargeMedicationOrders, setTouched, setValue]);
|
|
7704
|
+
const onDelete = React15.useCallback(
|
|
7705
|
+
(id) => {
|
|
7706
|
+
setTouched();
|
|
7707
|
+
const idx = orders.findIndex((o) => o.id === id);
|
|
7708
|
+
if (idx === -1) return;
|
|
7709
|
+
setValue({
|
|
7710
|
+
orders: orders.filter((o) => o.id !== id),
|
|
7711
|
+
display_lines: display_lines.filter((_, i) => i !== idx)
|
|
7712
|
+
});
|
|
7713
|
+
},
|
|
7714
|
+
[orders, display_lines, setTouched, setValue]
|
|
7715
|
+
);
|
|
7716
|
+
if (!visible || !fieldDef) return null;
|
|
7717
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
7718
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2", children: [
|
|
7719
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Label, { className: "text-sm font-medium", children: [
|
|
7720
|
+
fieldDef.label,
|
|
7721
|
+
" ",
|
|
7722
|
+
fieldDef.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-red-500", children: "*" })
|
|
7723
|
+
] }),
|
|
7724
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button, { type: "button", onClick: onAdd, disabled: disabled || !handlers.onOpenDischargeMedicationOrders, children: "Add medicine" })
|
|
7725
|
+
] }),
|
|
7726
|
+
fieldDef.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: fieldDef.description }),
|
|
7727
|
+
orders.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
7728
|
+
"div",
|
|
7729
|
+
{
|
|
7730
|
+
className: cn(
|
|
7731
|
+
"rounded-md border border-input bg-background px-3 py-3 text-sm text-muted-foreground",
|
|
7732
|
+
showError && "border-red-500"
|
|
7733
|
+
),
|
|
7734
|
+
children: "No medicines added."
|
|
7735
|
+
}
|
|
7736
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: orders.map((o, rowIdx) => {
|
|
7737
|
+
const line = display_lines[rowIdx];
|
|
7738
|
+
const duration = formatDuration(o.start_date, o.end_date);
|
|
7739
|
+
const header = typeof line?.name === "string" && line.name.trim() || o.item_name || "Medicine";
|
|
7740
|
+
const sub = o.generic_name ? o.generic_name : null;
|
|
7741
|
+
const line1 = [o.dose && `Dose: ${o.dose}`, o.route && `Route: ${o.route}`].filter(Boolean).join(" \u2022 ");
|
|
7742
|
+
const line2 = [
|
|
7743
|
+
o.frequency && `Freq: ${o.frequency}`,
|
|
7744
|
+
o.meal_sleep_timing && `Meal/Sleep: ${o.meal_sleep_timing}`,
|
|
7745
|
+
o.admin_times?.length ? `Times: ${o.admin_times.join(", ")}` : null
|
|
7746
|
+
].filter(Boolean).join(" \u2022 ");
|
|
7747
|
+
const line3 = [
|
|
7748
|
+
duration ? `Duration: ${duration}` : null,
|
|
7749
|
+
o.order_type ? `Type: ${o.order_type}` : null,
|
|
7750
|
+
o.status ? `Status: ${o.status}` : null
|
|
7751
|
+
].filter(Boolean).join(" \u2022 ");
|
|
7752
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-md border border-input bg-background p-3", children: [
|
|
7753
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-3", children: [
|
|
7754
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
|
|
7755
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-semibold text-sm truncate", children: header }),
|
|
7756
|
+
sub && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-muted-foreground mt-0.5 truncate", children: sub })
|
|
7757
|
+
] }),
|
|
7758
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7759
|
+
Button,
|
|
7760
|
+
{
|
|
7761
|
+
type: "button",
|
|
7762
|
+
variant: "ghost",
|
|
7763
|
+
className: "h-8 w-8 p-0 text-destructive",
|
|
7764
|
+
onClick: () => onDelete(o.id),
|
|
7765
|
+
"aria-label": "Delete medicine",
|
|
7766
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "h-4 w-4" })
|
|
7767
|
+
}
|
|
7768
|
+
)
|
|
7769
|
+
] }),
|
|
7770
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 space-y-1 text-xs text-muted-foreground", children: [
|
|
7771
|
+
line1 && /* @__PURE__ */ jsxRuntime.jsx("div", { children: line1 }),
|
|
7772
|
+
line2 && /* @__PURE__ */ jsxRuntime.jsx("div", { children: line2 }),
|
|
7773
|
+
line3 && /* @__PURE__ */ jsxRuntime.jsx("div", { children: line3 }),
|
|
7774
|
+
o.notes && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-foreground/80", children: [
|
|
7775
|
+
"Notes: ",
|
|
7776
|
+
o.notes
|
|
7777
|
+
] })
|
|
7778
|
+
] })
|
|
7779
|
+
] }, o.id);
|
|
7780
|
+
}) }),
|
|
7781
|
+
showError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-red-500", children: error })
|
|
7782
|
+
] });
|
|
7783
|
+
};
|
|
7421
7784
|
var FieldRenderer = ({ fieldId }) => {
|
|
7422
7785
|
const { fieldDef, visible } = useField(fieldId);
|
|
7423
7786
|
if (!visible || !fieldDef) {
|
|
@@ -7431,6 +7794,9 @@ function renderWidget(fieldId, fieldDef) {
|
|
|
7431
7794
|
case "number":
|
|
7432
7795
|
return /* @__PURE__ */ jsxRuntime.jsx(TextWidget, { fieldId });
|
|
7433
7796
|
case "textarea":
|
|
7797
|
+
if (fieldMetaRequestsMarMedicationOrdersButton(fieldDef.meta)) {
|
|
7798
|
+
return /* @__PURE__ */ jsxRuntime.jsx(MarMedicationOrdersWidget, { fieldId });
|
|
7799
|
+
}
|
|
7434
7800
|
return /* @__PURE__ */ jsxRuntime.jsx(TextWidget, { fieldId });
|
|
7435
7801
|
case "richtext":
|
|
7436
7802
|
return /* @__PURE__ */ jsxRuntime.jsx(RichTextWidget, { fieldId });
|
|
@@ -7450,12 +7816,16 @@ function renderWidget(fieldId, fieldDef) {
|
|
|
7450
7816
|
return /* @__PURE__ */ jsxRuntime.jsx(RepeatableWidget, { fieldId });
|
|
7451
7817
|
case "image_upload":
|
|
7452
7818
|
return /* @__PURE__ */ jsxRuntime.jsx(ImageUploadWidget, { fieldId });
|
|
7819
|
+
case "media_upload":
|
|
7820
|
+
return /* @__PURE__ */ jsxRuntime.jsx(MediaUploadWidget, { fieldId });
|
|
7453
7821
|
case "signature":
|
|
7454
7822
|
return /* @__PURE__ */ jsxRuntime.jsx(SignatureUploadWidget, { fieldId });
|
|
7455
7823
|
case "editable_table":
|
|
7456
7824
|
return /* @__PURE__ */ jsxRuntime.jsx(EditableTableWidget, { fieldId });
|
|
7457
7825
|
case "medications":
|
|
7458
7826
|
return /* @__PURE__ */ jsxRuntime.jsx(AddMedicationWidget, { fieldId });
|
|
7827
|
+
case "discharge_medication_orders":
|
|
7828
|
+
return /* @__PURE__ */ jsxRuntime.jsx(DischargeMedicationOrdersWidget, { fieldId });
|
|
7459
7829
|
case "investigations":
|
|
7460
7830
|
return /* @__PURE__ */ jsxRuntime.jsx(AddInvestigationWidget, { fieldId });
|
|
7461
7831
|
case "procedures":
|
|
@@ -7857,6 +8227,55 @@ var ReadOnlyImageUpload = ({
|
|
|
7857
8227
|
fieldDef.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-500", children: fieldDef.description })
|
|
7858
8228
|
] });
|
|
7859
8229
|
};
|
|
8230
|
+
function urlLooksLikePdf2(url) {
|
|
8231
|
+
return /\.pdf($|\?)/i.test(url) || url.toLowerCase().includes("application/pdf");
|
|
8232
|
+
}
|
|
8233
|
+
var ReadOnlyMediaUpload = ({
|
|
8234
|
+
fieldDef,
|
|
8235
|
+
value
|
|
8236
|
+
}) => {
|
|
8237
|
+
const [useIframe, setUseIframe] = React15.useState(false);
|
|
8238
|
+
let url = null;
|
|
8239
|
+
if (typeof value === "string") {
|
|
8240
|
+
url = value;
|
|
8241
|
+
} else if (value && typeof value === "object") {
|
|
8242
|
+
const typed = value;
|
|
8243
|
+
url = typed.presigned_url || typed.value || typed.s3_key || null;
|
|
8244
|
+
}
|
|
8245
|
+
React15.useEffect(() => {
|
|
8246
|
+
setUseIframe(false);
|
|
8247
|
+
}, [url]);
|
|
8248
|
+
const showAsPdf = url && (urlLooksLikePdf2(url) || useIframe);
|
|
8249
|
+
if (!url) {
|
|
8250
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
8251
|
+
/* @__PURE__ */ jsxRuntime.jsx(Label, { children: fieldDef.label }),
|
|
8252
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "border border-gray-200 rounded-lg p-4 bg-gray-50", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center py-4", children: [
|
|
8253
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Image, { className: "h-8 w-8 mx-auto text-gray-400 mb-2" }),
|
|
8254
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-500", children: "No file uploaded" })
|
|
8255
|
+
] }) })
|
|
8256
|
+
] });
|
|
8257
|
+
}
|
|
8258
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
8259
|
+
/* @__PURE__ */ jsxRuntime.jsx(Label, { children: fieldDef.label }),
|
|
8260
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "border border-gray-200 rounded-lg p-4 bg-white", children: showAsPdf ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
8261
|
+
"iframe",
|
|
8262
|
+
{
|
|
8263
|
+
src: url,
|
|
8264
|
+
title: `${fieldDef.label} PDF`,
|
|
8265
|
+
className: "w-full max-h-48 min-h-36 rounded-lg border border-gray-200 bg-white"
|
|
8266
|
+
}
|
|
8267
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
8268
|
+
"img",
|
|
8269
|
+
{
|
|
8270
|
+
src: url,
|
|
8271
|
+
alt: `${fieldDef.label} upload`,
|
|
8272
|
+
className: "max-w-full max-h-48 mx-auto rounded-lg",
|
|
8273
|
+
onError: () => setUseIframe(true)
|
|
8274
|
+
}
|
|
8275
|
+
) }),
|
|
8276
|
+
fieldDef.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-500", children: fieldDef.description })
|
|
8277
|
+
] });
|
|
8278
|
+
};
|
|
7860
8279
|
var ReadOnlySignature = ({
|
|
7861
8280
|
fieldDef,
|
|
7862
8281
|
value
|
|
@@ -8034,6 +8453,53 @@ var ReadOnlyReferral = ({ fieldDef, value }) => {
|
|
|
8034
8453
|
}) })
|
|
8035
8454
|
] });
|
|
8036
8455
|
};
|
|
8456
|
+
function isOrderArray(value) {
|
|
8457
|
+
return Array.isArray(value) && value.every(
|
|
8458
|
+
(v) => v != null && typeof v === "object" && typeof v.id === "string"
|
|
8459
|
+
);
|
|
8460
|
+
}
|
|
8461
|
+
function formatDuration2(start, end) {
|
|
8462
|
+
if (!start && !end) return null;
|
|
8463
|
+
if (start && end) return `${start} \u2192 ${end}`;
|
|
8464
|
+
return start ? `Start: ${start}` : `End: ${end}`;
|
|
8465
|
+
}
|
|
8466
|
+
var ReadOnlyDischargeMedicationOrders = ({ fieldDef, value }) => {
|
|
8467
|
+
const orders = React15.useMemo(() => isOrderArray(value) ? value : [], [value]);
|
|
8468
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
8469
|
+
/* @__PURE__ */ jsxRuntime.jsx(Label, { className: "text-sm font-medium text-gray-700", children: fieldDef.label }),
|
|
8470
|
+
orders.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-gray-900 border border-gray-200 rounded-md p-3 bg-gray-50 min-h-[2.5rem]", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-400 italic", children: "No medicines added" }) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: orders.map((o) => {
|
|
8471
|
+
const duration = formatDuration2(o.start_date, o.end_date);
|
|
8472
|
+
const header = o.item_name ?? "Medicine";
|
|
8473
|
+
const sub = o.generic_name ? o.generic_name : null;
|
|
8474
|
+
const line1 = [o.dose && `Dose: ${o.dose}`, o.route && `Route: ${o.route}`].filter(Boolean).join(" \u2022 ");
|
|
8475
|
+
const line2 = [
|
|
8476
|
+
o.frequency && `Freq: ${o.frequency}`,
|
|
8477
|
+
o.meal_sleep_timing && `Meal/Sleep: ${o.meal_sleep_timing}`,
|
|
8478
|
+
o.admin_times?.length ? `Times: ${o.admin_times.join(", ")}` : null
|
|
8479
|
+
].filter(Boolean).join(" \u2022 ");
|
|
8480
|
+
const line3 = [
|
|
8481
|
+
duration ? `Duration: ${duration}` : null,
|
|
8482
|
+
o.order_type ? `Type: ${o.order_type}` : null,
|
|
8483
|
+
o.status ? `Status: ${o.status}` : null
|
|
8484
|
+
].filter(Boolean).join(" \u2022 ");
|
|
8485
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-md border border-gray-200 bg-gray-50 p-3", children: [
|
|
8486
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
|
|
8487
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-semibold text-sm truncate text-gray-900", children: header }),
|
|
8488
|
+
sub && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-gray-500 mt-0.5 truncate", children: sub })
|
|
8489
|
+
] }),
|
|
8490
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 space-y-1 text-xs text-gray-600", children: [
|
|
8491
|
+
line1 && /* @__PURE__ */ jsxRuntime.jsx("div", { children: line1 }),
|
|
8492
|
+
line2 && /* @__PURE__ */ jsxRuntime.jsx("div", { children: line2 }),
|
|
8493
|
+
line3 && /* @__PURE__ */ jsxRuntime.jsx("div", { children: line3 }),
|
|
8494
|
+
o.notes && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-gray-800/90", children: [
|
|
8495
|
+
"Notes: ",
|
|
8496
|
+
o.notes
|
|
8497
|
+
] })
|
|
8498
|
+
] })
|
|
8499
|
+
] }, o.id);
|
|
8500
|
+
}) })
|
|
8501
|
+
] });
|
|
8502
|
+
};
|
|
8037
8503
|
var ReadOnlyFieldRenderer = ({ fieldDef, value }) => {
|
|
8038
8504
|
if (!fieldDef) return null;
|
|
8039
8505
|
switch (fieldDef.type) {
|
|
@@ -8058,12 +8524,16 @@ var ReadOnlyFieldRenderer = ({ fieldDef, value }) => {
|
|
|
8058
8524
|
return /* @__PURE__ */ jsxRuntime.jsx(ReadOnlyRepeatable, { fieldDef, value });
|
|
8059
8525
|
case "image_upload":
|
|
8060
8526
|
return /* @__PURE__ */ jsxRuntime.jsx(ReadOnlyImageUpload, { fieldDef, value });
|
|
8527
|
+
case "media_upload":
|
|
8528
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ReadOnlyMediaUpload, { fieldDef, value });
|
|
8061
8529
|
case "signature":
|
|
8062
8530
|
return /* @__PURE__ */ jsxRuntime.jsx(ReadOnlySignature, { fieldDef, value });
|
|
8063
8531
|
case "editable_table":
|
|
8064
8532
|
return /* @__PURE__ */ jsxRuntime.jsx(ReadOnlyTable, { fieldDef, value });
|
|
8065
8533
|
case "referral":
|
|
8066
8534
|
return /* @__PURE__ */ jsxRuntime.jsx(ReadOnlyReferral, { fieldDef, value });
|
|
8535
|
+
case "discharge_medication_orders":
|
|
8536
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ReadOnlyDischargeMedicationOrders, { fieldDef, value });
|
|
8067
8537
|
case "static_text": {
|
|
8068
8538
|
const def = fieldDef;
|
|
8069
8539
|
const size = def.size ?? "regular";
|
|
@@ -8275,8 +8745,11 @@ exports.FormControls = FormControls;
|
|
|
8275
8745
|
exports.FormProvider = FormProvider;
|
|
8276
8746
|
exports.FormStore = FormStore;
|
|
8277
8747
|
exports.ImageUploadWidget = ImageUploadWidget;
|
|
8748
|
+
exports.MAR_MEDICATION_ORDERS_META_KEY = MAR_MEDICATION_ORDERS_META_KEY;
|
|
8749
|
+
exports.MediaUploadWidget = MediaUploadWidget;
|
|
8278
8750
|
exports.ReadOnlyForm = ReadOnlyForm;
|
|
8279
8751
|
exports.ReadOnlyImageUpload = ReadOnlyImageUpload;
|
|
8752
|
+
exports.ReadOnlyMediaUpload = ReadOnlyMediaUpload;
|
|
8280
8753
|
exports.ReadOnlySignature = ReadOnlySignature;
|
|
8281
8754
|
exports.ReadOnlyTable = ReadOnlyTable;
|
|
8282
8755
|
exports.RichTextWidget = RichTextWidget;
|
|
@@ -8285,6 +8758,7 @@ exports.SmartForm = SmartForm;
|
|
|
8285
8758
|
exports.SmartTextareaWidget = SmartTextareaWidget;
|
|
8286
8759
|
exports.createUploadHandler = createUploadHandler;
|
|
8287
8760
|
exports.evaluateRules = evaluateRules;
|
|
8761
|
+
exports.fieldMetaRequestsMarMedicationOrdersButton = fieldMetaRequestsMarMedicationOrdersButton;
|
|
8288
8762
|
exports.useField = useField;
|
|
8289
8763
|
exports.useFieldHandlers = useFieldHandlers;
|
|
8290
8764
|
exports.useForm = useForm;
|