formanitor 0.0.15 → 0.0.17
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 +220 -35
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +59 -3
- package/dist/index.d.ts +59 -3
- package/dist/index.mjs +220 -36
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -368,7 +368,7 @@ var FormStore = class {
|
|
|
368
368
|
}
|
|
369
369
|
};
|
|
370
370
|
this.config.onDraftChange?.(payload);
|
|
371
|
-
},
|
|
371
|
+
}, 5e3);
|
|
372
372
|
}
|
|
373
373
|
async save() {
|
|
374
374
|
const payload = {
|
|
@@ -664,12 +664,27 @@ var FormStore = class {
|
|
|
664
664
|
}
|
|
665
665
|
};
|
|
666
666
|
var FormContext = React11.createContext(null);
|
|
667
|
+
var emptyFrequentItems = {
|
|
668
|
+
medications: [],
|
|
669
|
+
investigations: [],
|
|
670
|
+
procedures: []
|
|
671
|
+
};
|
|
672
|
+
var FrequentItemsContext = React11.createContext(emptyFrequentItems);
|
|
667
673
|
var FieldHandlersContext = React11.createContext({});
|
|
668
674
|
function useFieldHandlers(fieldId) {
|
|
669
675
|
const map = React11.useContext(FieldHandlersContext);
|
|
670
676
|
return map[fieldId] ?? { onSearch: async () => [], recentlyUsed: [] };
|
|
671
677
|
}
|
|
672
|
-
|
|
678
|
+
function useFrequentItems() {
|
|
679
|
+
return React11.useContext(FrequentItemsContext);
|
|
680
|
+
}
|
|
681
|
+
var FormProvider = ({
|
|
682
|
+
schema,
|
|
683
|
+
config,
|
|
684
|
+
fieldHandlers,
|
|
685
|
+
frequentItems,
|
|
686
|
+
children
|
|
687
|
+
}) => {
|
|
673
688
|
const storeRef = React11.useRef(null);
|
|
674
689
|
if (!storeRef.current) {
|
|
675
690
|
storeRef.current = new FormStore(schema, config);
|
|
@@ -682,7 +697,8 @@ var FormProvider = ({ schema, config, fieldHandlers, children }) => {
|
|
|
682
697
|
React11.useEffect(() => {
|
|
683
698
|
storeRef.current?.load();
|
|
684
699
|
}, []);
|
|
685
|
-
|
|
700
|
+
const frequentItemsValue = frequentItems ?? emptyFrequentItems;
|
|
701
|
+
return /* @__PURE__ */ jsxRuntime.jsx(FormContext.Provider, { value: storeRef.current, children: /* @__PURE__ */ jsxRuntime.jsx(FieldHandlersContext.Provider, { value: fieldHandlers ?? {}, children: /* @__PURE__ */ jsxRuntime.jsx(FrequentItemsContext.Provider, { value: frequentItemsValue, children }) }) });
|
|
686
702
|
};
|
|
687
703
|
function useFormStore() {
|
|
688
704
|
const context = React11.useContext(FormContext);
|
|
@@ -2500,6 +2516,7 @@ var AddEntityDialog = ({
|
|
|
2500
2516
|
onClose,
|
|
2501
2517
|
title,
|
|
2502
2518
|
recentlyUsedSlot,
|
|
2519
|
+
chipSectionLabel = "Recently Used",
|
|
2503
2520
|
children,
|
|
2504
2521
|
actionSlot
|
|
2505
2522
|
}) => {
|
|
@@ -2507,7 +2524,7 @@ var AddEntityDialog = ({
|
|
|
2507
2524
|
/* @__PURE__ */ jsxRuntime.jsx(DialogHeader, { className: "px-6 pt-6 pb-4 shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { className: "text-lg font-semibold", children: title }) }),
|
|
2508
2525
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-6 flex flex-col gap-4 overflow-y-auto flex-1 min-h-0 pb-4", children: [
|
|
2509
2526
|
recentlyUsedSlot && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2510
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground mb-2", children:
|
|
2527
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground mb-2", children: chipSectionLabel }),
|
|
2511
2528
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-2", children: recentlyUsedSlot })
|
|
2512
2529
|
] }),
|
|
2513
2530
|
children
|
|
@@ -2532,9 +2549,9 @@ function mapToMedication(result) {
|
|
|
2532
2549
|
};
|
|
2533
2550
|
}
|
|
2534
2551
|
function mapAIMedicationToMedication(ai) {
|
|
2535
|
-
const id =
|
|
2552
|
+
const id = ai.id != null ? String(ai.id) : "";
|
|
2536
2553
|
return {
|
|
2537
|
-
id
|
|
2554
|
+
id,
|
|
2538
2555
|
brand_name: ai.brand_name ?? "",
|
|
2539
2556
|
generic_name: ai.generic_name ?? "",
|
|
2540
2557
|
frequency: "custom",
|
|
@@ -2550,7 +2567,7 @@ function mapAIMedicationToMedication(ai) {
|
|
|
2550
2567
|
}
|
|
2551
2568
|
function createCustomMedication(name, customId) {
|
|
2552
2569
|
return {
|
|
2553
|
-
id: customId,
|
|
2570
|
+
id: String(customId),
|
|
2554
2571
|
brand_name: name.trim(),
|
|
2555
2572
|
generic_name: "",
|
|
2556
2573
|
frequency: "custom",
|
|
@@ -2564,6 +2581,39 @@ function createCustomMedication(name, customId) {
|
|
|
2564
2581
|
notes: ""
|
|
2565
2582
|
};
|
|
2566
2583
|
}
|
|
2584
|
+
function parseDuration(duration) {
|
|
2585
|
+
if (!duration || !duration.trim()) return { value: "3", unit: "days" };
|
|
2586
|
+
const lower = duration.trim().toLowerCase();
|
|
2587
|
+
const match = lower.match(/^(\d+)\s*(day|days|week|weeks|month|months)?$/);
|
|
2588
|
+
if (!match) return { value: "3", unit: "days" };
|
|
2589
|
+
const value = match[1] ?? "3";
|
|
2590
|
+
const unitWord = match[2] ?? "days";
|
|
2591
|
+
const unit = unitWord.startsWith("month") ? "months" : unitWord.startsWith("week") ? "weeks" : "days";
|
|
2592
|
+
return { value, unit };
|
|
2593
|
+
}
|
|
2594
|
+
function mapFrequentItemToMedication(item) {
|
|
2595
|
+
const parsed = parseDuration(item.duration);
|
|
2596
|
+
const duration_value = item.duration_value ?? parsed.value;
|
|
2597
|
+
const duration_unit = item.duration_unit ?? parsed.unit;
|
|
2598
|
+
const before_after = item.before_after === "BEFORE FOOD" ? "BEFORE FOOD" : "AFTER FOOD";
|
|
2599
|
+
const routeNote = item.route ? `Route: ${item.route}` : "";
|
|
2600
|
+
const baseNotes = item.notes?.trim() || "";
|
|
2601
|
+
const combinedNotes = [baseNotes, routeNote.trim()].filter((part) => part.length > 0).join(" \u2014 ");
|
|
2602
|
+
return {
|
|
2603
|
+
id: item.id,
|
|
2604
|
+
brand_name: item.brand_name ?? item.name,
|
|
2605
|
+
generic_name: item.short_name ?? "",
|
|
2606
|
+
frequency: item.frequency ?? "custom",
|
|
2607
|
+
is_custom: false,
|
|
2608
|
+
duration_value,
|
|
2609
|
+
duration_unit,
|
|
2610
|
+
before_after,
|
|
2611
|
+
morning: item.morning ?? "0",
|
|
2612
|
+
afternoon: item.afternoon ?? "0",
|
|
2613
|
+
night: item.night ?? "0",
|
|
2614
|
+
notes: combinedNotes
|
|
2615
|
+
};
|
|
2616
|
+
}
|
|
2567
2617
|
function Spinner({
|
|
2568
2618
|
value,
|
|
2569
2619
|
onChange
|
|
@@ -2611,11 +2661,14 @@ function MedicationCard({
|
|
|
2611
2661
|
onChange: (e) => set("frequency", e.target.value),
|
|
2612
2662
|
children: [
|
|
2613
2663
|
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "custom", children: "select frequency" }),
|
|
2614
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "
|
|
2615
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "
|
|
2616
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "
|
|
2617
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "
|
|
2618
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "
|
|
2664
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "qid", children: "4 times a day (QID)" }),
|
|
2665
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "alternate_day", children: "Alternate day" }),
|
|
2666
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "once_weekly", children: "Once weekly" }),
|
|
2667
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "once_monthly", children: "Once monthly" }),
|
|
2668
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "as_needed", children: "As needed" }),
|
|
2669
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "fort_night", children: "Fort night" }),
|
|
2670
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "at_bed_time", children: "At Bed time" }),
|
|
2671
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "sos", children: "SOS only" })
|
|
2619
2672
|
]
|
|
2620
2673
|
}
|
|
2621
2674
|
),
|
|
@@ -2754,6 +2807,7 @@ var AddMedicationField = ({
|
|
|
2754
2807
|
onChange,
|
|
2755
2808
|
onSearch,
|
|
2756
2809
|
recentlyUsed = [],
|
|
2810
|
+
frequentItems = [],
|
|
2757
2811
|
suggestedMedications = []
|
|
2758
2812
|
}) => {
|
|
2759
2813
|
const [open, setOpen] = React11.useState(false);
|
|
@@ -2799,6 +2853,13 @@ var AddMedicationField = ({
|
|
|
2799
2853
|
onChange([...safeValue, mapToMedication(result)]);
|
|
2800
2854
|
}
|
|
2801
2855
|
}
|
|
2856
|
+
function handleFrequentItemToggle(item) {
|
|
2857
|
+
if (addedIds.has(String(item.id))) {
|
|
2858
|
+
onChange(safeValue.filter((m) => String(m.id) !== String(item.id)));
|
|
2859
|
+
} else {
|
|
2860
|
+
onChange([...safeValue, mapFrequentItemToMedication(item)]);
|
|
2861
|
+
}
|
|
2862
|
+
}
|
|
2802
2863
|
function handleResultClick(result) {
|
|
2803
2864
|
if (addedIds.has(String(result.id))) return;
|
|
2804
2865
|
setAddingResultId(result.id);
|
|
@@ -2849,6 +2910,26 @@ var AddMedicationField = ({
|
|
|
2849
2910
|
r.id
|
|
2850
2911
|
);
|
|
2851
2912
|
});
|
|
2913
|
+
const limitedFrequentItems = frequentItems.slice(0, 25);
|
|
2914
|
+
const frequentItemChips = limitedFrequentItems.length > 0 ? limitedFrequentItems.map((item) => {
|
|
2915
|
+
const isAdded = addedIds.has(String(item.id));
|
|
2916
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2917
|
+
"button",
|
|
2918
|
+
{
|
|
2919
|
+
type: "button",
|
|
2920
|
+
onClick: () => handleFrequentItemToggle(item),
|
|
2921
|
+
className: cn(
|
|
2922
|
+
"rounded-full border text-[11px] px-2 py-0.5 transition-colors cursor-pointer",
|
|
2923
|
+
isAdded ? "border-green-300 bg-green-50 text-green-700" : "border-border bg-white hover:bg-gray-50"
|
|
2924
|
+
),
|
|
2925
|
+
children: [
|
|
2926
|
+
isAdded && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mr-1", children: "\u2713" }),
|
|
2927
|
+
item.brand_name ?? item.name
|
|
2928
|
+
]
|
|
2929
|
+
},
|
|
2930
|
+
item.id
|
|
2931
|
+
);
|
|
2932
|
+
}) : [];
|
|
2852
2933
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-md overflow-hidden flex flex-col border bg-white border-[#D0D0D0] space-y-3 p-3 h-fit", children: [
|
|
2853
2934
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
2854
2935
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold", children: label }),
|
|
@@ -2862,22 +2943,6 @@ var AddMedicationField = ({
|
|
|
2862
2943
|
}
|
|
2863
2944
|
)
|
|
2864
2945
|
] }),
|
|
2865
|
-
suggestedMedications.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-1.5 items-center", children: [
|
|
2866
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground mr-1", children: "Suggestions:" }),
|
|
2867
|
-
suggestedMedications.filter((s) => !addedIds.has(String(s.id))).map((s) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2868
|
-
"button",
|
|
2869
|
-
{
|
|
2870
|
-
type: "button",
|
|
2871
|
-
onClick: () => handleAddSuggestion(s),
|
|
2872
|
-
className: "inline-flex items-center gap-1 rounded-full border border-dashed border-purple-300 bg-purple-50/80 text-purple-800 text-xs px-2.5 py-1 hover:bg-purple-100 transition-colors cursor-pointer",
|
|
2873
|
-
children: [
|
|
2874
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "h-3 w-3" }),
|
|
2875
|
-
s.brand_name || s.generic_name || String(s.id)
|
|
2876
|
-
]
|
|
2877
|
-
},
|
|
2878
|
-
String(s.id)
|
|
2879
|
-
))
|
|
2880
|
-
] }),
|
|
2881
2946
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: safeValue.map((med, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2882
2947
|
MedicationCard,
|
|
2883
2948
|
{
|
|
@@ -2893,7 +2958,8 @@ var AddMedicationField = ({
|
|
|
2893
2958
|
open,
|
|
2894
2959
|
onClose: () => setOpen(false),
|
|
2895
2960
|
title: "Add Medication",
|
|
2896
|
-
recentlyUsedSlot: recentlyUsedChips.length > 0 ? recentlyUsedChips : void 0,
|
|
2961
|
+
recentlyUsedSlot: frequentItemChips.length > 0 ? frequentItemChips : recentlyUsedChips.length > 0 ? recentlyUsedChips : void 0,
|
|
2962
|
+
chipSectionLabel: frequentItemChips.length > 0 ? "Frequently used" : void 0,
|
|
2897
2963
|
actionSlot: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2898
2964
|
"button",
|
|
2899
2965
|
{
|
|
@@ -2918,6 +2984,22 @@ var AddMedicationField = ({
|
|
|
2918
2984
|
className: "border border-border rounded-md focus-visible:ring-0"
|
|
2919
2985
|
}
|
|
2920
2986
|
),
|
|
2987
|
+
suggestedMedications.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-1.5 items-center", children: [
|
|
2988
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground mr-1", children: "Suggestions:" }),
|
|
2989
|
+
suggestedMedications.filter((s) => !addedIds.has(String(s.id))).slice(0, 25).map((s) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2990
|
+
"button",
|
|
2991
|
+
{
|
|
2992
|
+
type: "button",
|
|
2993
|
+
onClick: () => handleAddSuggestion(s),
|
|
2994
|
+
className: "inline-flex items-center gap-1 rounded-full border border-dashed border-purple-300 bg-purple-50/80 text-purple-800 text-[11px] px-2 py-0.5 hover:bg-purple-100 transition-colors cursor-pointer",
|
|
2995
|
+
children: [
|
|
2996
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "h-3 w-3" }),
|
|
2997
|
+
s.brand_name || s.generic_name || String(s.id)
|
|
2998
|
+
]
|
|
2999
|
+
},
|
|
3000
|
+
String(s.id)
|
|
3001
|
+
))
|
|
3002
|
+
] }),
|
|
2921
3003
|
loading && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground text-center py-2", children: "Searching\u2026" }),
|
|
2922
3004
|
!loading && results.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 gap-2 max-h-64 overflow-y-auto", children: results.map((r) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2923
3005
|
SearchResultCard,
|
|
@@ -2937,6 +3019,7 @@ var AddMedicationWidget = ({ fieldId }) => {
|
|
|
2937
3019
|
const { value, setValue } = useField(fieldId);
|
|
2938
3020
|
const handlers = useFieldHandlers(fieldId);
|
|
2939
3021
|
const { medications: suggestedMedications } = useAISuggestions();
|
|
3022
|
+
const { medications: frequentMedications } = useFrequentItems();
|
|
2940
3023
|
const safeValue = Array.isArray(value) ? value : [];
|
|
2941
3024
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2942
3025
|
AddMedicationField,
|
|
@@ -2945,6 +3028,7 @@ var AddMedicationWidget = ({ fieldId }) => {
|
|
|
2945
3028
|
onChange: setValue,
|
|
2946
3029
|
onSearch: handlers.onSearch,
|
|
2947
3030
|
recentlyUsed: handlers.recentlyUsed,
|
|
3031
|
+
frequentItems: frequentMedications,
|
|
2948
3032
|
suggestedMedications
|
|
2949
3033
|
}
|
|
2950
3034
|
);
|
|
@@ -2963,13 +3047,15 @@ var AddInvestigationField = ({
|
|
|
2963
3047
|
value,
|
|
2964
3048
|
onChange,
|
|
2965
3049
|
onSearch,
|
|
2966
|
-
recentlyUsed = []
|
|
3050
|
+
recentlyUsed = [],
|
|
3051
|
+
frequentItems = []
|
|
2967
3052
|
}) => {
|
|
2968
3053
|
const [open, setOpen] = React11.useState(false);
|
|
2969
3054
|
const [query, setQuery] = React11.useState("");
|
|
2970
3055
|
const [results, setResults] = React11.useState([]);
|
|
2971
3056
|
const [loading, setLoading] = React11.useState(false);
|
|
2972
3057
|
const [addingId, setAddingId] = React11.useState(null);
|
|
3058
|
+
const [addingFrequentId, setAddingFrequentId] = React11.useState(null);
|
|
2973
3059
|
const debounceRef = React11.useRef(null);
|
|
2974
3060
|
const valueRef = React11.useRef([]);
|
|
2975
3061
|
const searchInputRef = React11.useRef(null);
|
|
@@ -2980,6 +3066,7 @@ var AddInvestigationField = ({
|
|
|
2980
3066
|
setQuery("");
|
|
2981
3067
|
setResults([]);
|
|
2982
3068
|
setAddingId(null);
|
|
3069
|
+
setAddingFrequentId(null);
|
|
2983
3070
|
}
|
|
2984
3071
|
}, [open]);
|
|
2985
3072
|
function handleQueryChange(q) {
|
|
@@ -3025,6 +3112,26 @@ var AddInvestigationField = ({
|
|
|
3025
3112
|
addInvestigation(result);
|
|
3026
3113
|
}
|
|
3027
3114
|
}
|
|
3115
|
+
async function handleFrequentItemToggle(item) {
|
|
3116
|
+
const id = String(item.id);
|
|
3117
|
+
const addedById = addedIds.has(id);
|
|
3118
|
+
const addedByName = value.some((inv) => inv.name === item.name);
|
|
3119
|
+
if (addedById || addedByName) {
|
|
3120
|
+
if (addedById) removeInvestigation(id);
|
|
3121
|
+
else onChange(value.filter((inv) => inv.name !== item.name));
|
|
3122
|
+
return;
|
|
3123
|
+
}
|
|
3124
|
+
setAddingFrequentId(id);
|
|
3125
|
+
try {
|
|
3126
|
+
const searchResults = await onSearch(item.name);
|
|
3127
|
+
const first = searchResults?.[0];
|
|
3128
|
+
if (first && !valueRef.current.some((inv) => inv.id === first.id)) {
|
|
3129
|
+
onChange([...valueRef.current, mapToInvestigation(first)]);
|
|
3130
|
+
}
|
|
3131
|
+
} finally {
|
|
3132
|
+
setAddingFrequentId(null);
|
|
3133
|
+
}
|
|
3134
|
+
}
|
|
3028
3135
|
const recentlyUsedChips = recentlyUsed.map((r) => {
|
|
3029
3136
|
const isAdded = addedIds.has(r.id);
|
|
3030
3137
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -3044,6 +3151,30 @@ var AddInvestigationField = ({
|
|
|
3044
3151
|
r.id
|
|
3045
3152
|
);
|
|
3046
3153
|
});
|
|
3154
|
+
const limitedFrequentItems = frequentItems.slice(0, 25);
|
|
3155
|
+
const frequentItemChips = limitedFrequentItems.length > 0 ? limitedFrequentItems.map((item) => {
|
|
3156
|
+
const id = String(item.id);
|
|
3157
|
+
const isAdded = value.some((inv) => inv.id === id) || value.some((inv) => inv.name === item.name);
|
|
3158
|
+
const isAdding = addingFrequentId === id;
|
|
3159
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3160
|
+
"button",
|
|
3161
|
+
{
|
|
3162
|
+
type: "button",
|
|
3163
|
+
disabled: isAdding,
|
|
3164
|
+
onClick: () => handleFrequentItemToggle(item),
|
|
3165
|
+
className: cn(
|
|
3166
|
+
"rounded-full border text-xs px-3 py-1 transition-colors",
|
|
3167
|
+
isAdded ? "border-green-300 bg-green-50 text-green-700" : "border-border bg-white hover:bg-gray-50",
|
|
3168
|
+
isAdding && "opacity-70 pointer-events-none"
|
|
3169
|
+
),
|
|
3170
|
+
children: [
|
|
3171
|
+
isAdded && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mr-1", children: "\u2713" }),
|
|
3172
|
+
isAdding ? "\u2026" : item.name
|
|
3173
|
+
]
|
|
3174
|
+
},
|
|
3175
|
+
item.id
|
|
3176
|
+
);
|
|
3177
|
+
}) : [];
|
|
3047
3178
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-md overflow-hidden flex flex-col bg-white border border-[#D0D0D0] space-y-3 p-3 h-fit", children: [
|
|
3048
3179
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-3", children: [
|
|
3049
3180
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold", children: label }),
|
|
@@ -3082,7 +3213,8 @@ var AddInvestigationField = ({
|
|
|
3082
3213
|
open,
|
|
3083
3214
|
onClose: () => setOpen(false),
|
|
3084
3215
|
title: "Add Investigation",
|
|
3085
|
-
recentlyUsedSlot: recentlyUsedChips.length > 0 ? recentlyUsedChips : void 0,
|
|
3216
|
+
recentlyUsedSlot: frequentItemChips.length > 0 ? frequentItemChips : recentlyUsedChips.length > 0 ? recentlyUsedChips : void 0,
|
|
3217
|
+
chipSectionLabel: frequentItemChips.length > 0 ? "Frequently used" : void 0,
|
|
3086
3218
|
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
3087
3219
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3088
3220
|
Input,
|
|
@@ -3122,13 +3254,15 @@ var AddInvestigationField = ({
|
|
|
3122
3254
|
var AddInvestigationWidget = ({ fieldId }) => {
|
|
3123
3255
|
const { value, setValue } = useField(fieldId);
|
|
3124
3256
|
const handlers = useFieldHandlers(fieldId);
|
|
3257
|
+
const { investigations: frequentInvestigations } = useFrequentItems();
|
|
3125
3258
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3126
3259
|
AddInvestigationField,
|
|
3127
3260
|
{
|
|
3128
3261
|
value: value ?? [],
|
|
3129
3262
|
onChange: setValue,
|
|
3130
3263
|
onSearch: handlers.onSearch,
|
|
3131
|
-
recentlyUsed: handlers.recentlyUsed
|
|
3264
|
+
recentlyUsed: handlers.recentlyUsed,
|
|
3265
|
+
frequentItems: frequentInvestigations
|
|
3132
3266
|
}
|
|
3133
3267
|
);
|
|
3134
3268
|
};
|
|
@@ -3146,13 +3280,15 @@ var AddProcedureField = ({
|
|
|
3146
3280
|
value,
|
|
3147
3281
|
onChange,
|
|
3148
3282
|
onSearch,
|
|
3149
|
-
recentlyUsed = []
|
|
3283
|
+
recentlyUsed = [],
|
|
3284
|
+
frequentItems = []
|
|
3150
3285
|
}) => {
|
|
3151
3286
|
const [open, setOpen] = React11.useState(false);
|
|
3152
3287
|
const [query, setQuery] = React11.useState("");
|
|
3153
3288
|
const [results, setResults] = React11.useState([]);
|
|
3154
3289
|
const [loading, setLoading] = React11.useState(false);
|
|
3155
3290
|
const [addingId, setAddingId] = React11.useState(null);
|
|
3291
|
+
const [addingFrequentId, setAddingFrequentId] = React11.useState(null);
|
|
3156
3292
|
const debounceRef = React11.useRef(null);
|
|
3157
3293
|
const valueRef = React11.useRef([]);
|
|
3158
3294
|
const searchInputRef = React11.useRef(null);
|
|
@@ -3163,6 +3299,7 @@ var AddProcedureField = ({
|
|
|
3163
3299
|
setQuery("");
|
|
3164
3300
|
setResults([]);
|
|
3165
3301
|
setAddingId(null);
|
|
3302
|
+
setAddingFrequentId(null);
|
|
3166
3303
|
}
|
|
3167
3304
|
}, [open]);
|
|
3168
3305
|
function handleQueryChange(q) {
|
|
@@ -3208,6 +3345,26 @@ var AddProcedureField = ({
|
|
|
3208
3345
|
addProcedure(result);
|
|
3209
3346
|
}
|
|
3210
3347
|
}
|
|
3348
|
+
async function handleFrequentItemToggle(item) {
|
|
3349
|
+
const id = String(item.id);
|
|
3350
|
+
const addedById = addedIds.has(id);
|
|
3351
|
+
const addedByName = value.some((proc) => proc.name === item.name);
|
|
3352
|
+
if (addedById || addedByName) {
|
|
3353
|
+
if (addedById) removeProcedure(id);
|
|
3354
|
+
else onChange(value.filter((proc) => proc.name !== item.name));
|
|
3355
|
+
return;
|
|
3356
|
+
}
|
|
3357
|
+
setAddingFrequentId(id);
|
|
3358
|
+
try {
|
|
3359
|
+
const searchResults = await onSearch(item.name);
|
|
3360
|
+
const first = searchResults?.[0];
|
|
3361
|
+
if (first && !valueRef.current.some((proc) => proc.id === first.id)) {
|
|
3362
|
+
onChange([...valueRef.current, mapToProcedure(first)]);
|
|
3363
|
+
}
|
|
3364
|
+
} finally {
|
|
3365
|
+
setAddingFrequentId(null);
|
|
3366
|
+
}
|
|
3367
|
+
}
|
|
3211
3368
|
const recentlyUsedChips = recentlyUsed.map((r) => {
|
|
3212
3369
|
const isAdded = addedIds.has(r.id);
|
|
3213
3370
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -3227,6 +3384,30 @@ var AddProcedureField = ({
|
|
|
3227
3384
|
r.id
|
|
3228
3385
|
);
|
|
3229
3386
|
});
|
|
3387
|
+
const limitedFrequentItems = frequentItems.slice(0, 25);
|
|
3388
|
+
const frequentItemChips = limitedFrequentItems.length > 0 ? limitedFrequentItems.map((item) => {
|
|
3389
|
+
const id = String(item.id);
|
|
3390
|
+
const isAdded = value.some((proc) => proc.id === id) || value.some((proc) => proc.name === item.name);
|
|
3391
|
+
const isAdding = addingFrequentId === id;
|
|
3392
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3393
|
+
"button",
|
|
3394
|
+
{
|
|
3395
|
+
type: "button",
|
|
3396
|
+
disabled: isAdding,
|
|
3397
|
+
onClick: () => handleFrequentItemToggle(item),
|
|
3398
|
+
className: cn(
|
|
3399
|
+
"rounded-full border text-xs px-3 py-1 transition-colors",
|
|
3400
|
+
isAdded ? "border-green-300 bg-green-50 text-green-700" : "border-border bg-white hover:bg-gray-50",
|
|
3401
|
+
isAdding && "opacity-70 pointer-events-none"
|
|
3402
|
+
),
|
|
3403
|
+
children: [
|
|
3404
|
+
isAdded && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mr-1", children: "\u2713" }),
|
|
3405
|
+
isAdding ? "\u2026" : item.name
|
|
3406
|
+
]
|
|
3407
|
+
},
|
|
3408
|
+
item.id
|
|
3409
|
+
);
|
|
3410
|
+
}) : [];
|
|
3230
3411
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-md overflow-hidden flex flex-col bg-white border border-[#D0D0D0] space-y-3 p-3 h-fit", children: [
|
|
3231
3412
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-3", children: [
|
|
3232
3413
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold", children: label }),
|
|
@@ -3265,7 +3446,8 @@ var AddProcedureField = ({
|
|
|
3265
3446
|
open,
|
|
3266
3447
|
onClose: () => setOpen(false),
|
|
3267
3448
|
title: "Add Procedure",
|
|
3268
|
-
recentlyUsedSlot: recentlyUsedChips.length > 0 ? recentlyUsedChips : void 0,
|
|
3449
|
+
recentlyUsedSlot: frequentItemChips.length > 0 ? frequentItemChips : recentlyUsedChips.length > 0 ? recentlyUsedChips : void 0,
|
|
3450
|
+
chipSectionLabel: frequentItemChips.length > 0 ? "Frequently used" : void 0,
|
|
3269
3451
|
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
3270
3452
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3271
3453
|
Input,
|
|
@@ -3305,13 +3487,15 @@ var AddProcedureField = ({
|
|
|
3305
3487
|
var AddProcedureWidget = ({ fieldId }) => {
|
|
3306
3488
|
const { value, setValue } = useField(fieldId);
|
|
3307
3489
|
const handlers = useFieldHandlers(fieldId);
|
|
3490
|
+
const { procedures: frequentProcedures } = useFrequentItems();
|
|
3308
3491
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3309
3492
|
AddProcedureField,
|
|
3310
3493
|
{
|
|
3311
3494
|
value: value ?? [],
|
|
3312
3495
|
onChange: setValue,
|
|
3313
3496
|
onSearch: handlers.onSearch,
|
|
3314
|
-
recentlyUsed: handlers.recentlyUsed
|
|
3497
|
+
recentlyUsed: handlers.recentlyUsed,
|
|
3498
|
+
frequentItems: frequentProcedures
|
|
3315
3499
|
}
|
|
3316
3500
|
);
|
|
3317
3501
|
};
|
|
@@ -5647,6 +5831,7 @@ exports.useField = useField;
|
|
|
5647
5831
|
exports.useFieldHandlers = useFieldHandlers;
|
|
5648
5832
|
exports.useForm = useForm;
|
|
5649
5833
|
exports.useFormStore = useFormStore;
|
|
5834
|
+
exports.useFrequentItems = useFrequentItems;
|
|
5650
5835
|
exports.useSmartKeywords = useSmartKeywords;
|
|
5651
5836
|
exports.validateField = validateField;
|
|
5652
5837
|
exports.validateForm = validateForm;
|