Skip to content

Commit 765198c

Browse files
authored
Merge branch 'listOfMed' into 284-hide-options-for-patient-summary-in-a-kebab-menu-on-mobile
2 parents 5cff3f1 + 47b2028 commit 765198c

12 files changed

Lines changed: 538 additions & 160 deletions

File tree

frontend/src/App.css

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,6 @@ Error message. Please see ErrorMessages.tsx under components folder
256256
}
257257

258258
.thinking {
259-
260259
font-size: 16px;
261260

262261
animation: ellipsis 1.5s infinite;

frontend/src/api/apiClient.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,18 @@ const handleSendDrugSummary = async (message: FormValues["message"], guid: strin
5656
}
5757
};
5858

59+
const handleRuleExtraction = async (guid: string) => {
60+
try {
61+
const response = await api.get(`/v1/api/rule_extraction_openai?guid=${guid}`);
62+
// console.log("Rule extraction response:", JSON.stringify(response.data, null, 2));
63+
return response.data;
64+
} catch (error) {
65+
console.error("Error(s) during handleRuleExtraction: ", error);
66+
throw error;
67+
}
68+
};
69+
70+
5971
interface StreamCallbacks {
6072
onContent?: (content: string) => void;
6173
onComplete?: (data: { embeddings_info: any[]; done: boolean }) => void;
@@ -244,9 +256,11 @@ const updateConversationTitle = async (
244256
}
245257
};
246258

259+
247260
export {
248261
handleSubmitFeedback,
249262
handleSendDrugSummary,
263+
handleRuleExtraction,
250264
fetchConversations,
251265
fetchConversation,
252266
newConversation,
Lines changed: 62 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,76 @@
1-
import React, {createContext, useContext, useState} from 'react';
1+
import React, { createContext, useContext, useState } from "react";
22

33
interface GlobalContextType {
4-
showSummary: boolean;
5-
setShowSummary: React.Dispatch<React.SetStateAction<boolean>>;
6-
enterNewPatient: boolean;
7-
setEnterNewPatient: React.Dispatch<React.SetStateAction<boolean>>;
8-
resetFormValues: boolean;
9-
triggerFormReset: () => void;
10-
isEditing: boolean;
11-
setIsEditing: React.Dispatch<React.SetStateAction<boolean>>;
4+
showSummary: boolean;
5+
setShowSummary: React.Dispatch<React.SetStateAction<boolean>>;
6+
enterNewPatient: boolean;
7+
setEnterNewPatient: React.Dispatch<React.SetStateAction<boolean>>;
8+
resetFormValues: boolean;
9+
triggerFormReset: () => void;
10+
isEditing: boolean;
11+
setIsEditing: React.Dispatch<React.SetStateAction<boolean>>;
12+
showMetaPanel: boolean;
13+
setShowMetaPanel: React.Dispatch<React.SetStateAction<boolean>>;
1214
}
1315

14-
15-
//redux / context issue need to provide default to avoid undefined
16-
//if we don't the login errors out
16+
// Provide default no-op values to prevent errors during initialization
17+
// eslint-disable-next-line @typescript-eslint/no-empty-function
18+
const noop: () => void = () => {};
1719
const defaultContextValue: GlobalContextType = {
18-
enterNewPatient: false,
19-
setEnterNewPatient: () => {
20-
}, //no-op default
21-
showSummary: false,
22-
setShowSummary: () => {
23-
}, //no-op default
24-
resetFormValues: false,
25-
triggerFormReset: () => {
26-
}, //no-op default
27-
isEditing: false,
28-
setIsEditing: () => {
29-
}, //no-op default
20+
enterNewPatient: false,
21+
setEnterNewPatient: noop,
22+
showSummary: false,
23+
setShowSummary: noop,
24+
resetFormValues: false,
25+
triggerFormReset: noop,
26+
isEditing: false,
27+
setIsEditing: noop,
28+
showMetaPanel: false,
29+
setShowMetaPanel: noop,
3030
};
3131

32-
3332
const GlobalContext = createContext<GlobalContextType>(defaultContextValue);
3433

34+
export const GlobalProvider: React.FC<{ children: React.ReactNode }> = ({
35+
children,
36+
}) => {
37+
const [showSummary, setShowSummary] = useState<boolean>(false);
38+
const [enterNewPatient, setEnterNewPatient] = useState<boolean>(true);
39+
const [resetFormValues, setResetFormValues] = useState<boolean>(false);
40+
const [isEditing, setIsEditing] = useState<boolean>(false);
41+
const [showMetaPanel, setShowMetaPanel] = useState<boolean>(false);
3542

36-
export const GlobalProvider: React.FC<{ children: React.ReactNode }> = ({children}) => {
37-
const [showSummary, setShowSummary] = useState<boolean>(false);
38-
const [enterNewPatient, setEnterNewPatient] = useState<boolean>(true);
39-
const [resetFormValues, setResetFormValues] = useState<boolean>(false);
40-
const [isEditing, setIsEditing] = useState<boolean>(false);
43+
const triggerFormReset = () => {
44+
setResetFormValues(true);
45+
setTimeout(() => {
46+
setResetFormValues(false);
47+
}, 100);
48+
};
4149

42-
const triggerFormReset = () => {
43-
setResetFormValues(true);
44-
// Reset the flag after a short delay
45-
setTimeout(() => {
46-
setResetFormValues(false);
47-
}, 100);
48-
};
49-
50-
return (
51-
<GlobalContext.Provider
52-
value={{
53-
showSummary,
54-
setShowSummary,
55-
enterNewPatient,
56-
setEnterNewPatient,
57-
resetFormValues,
58-
triggerFormReset,
59-
isEditing,
60-
setIsEditing
61-
}}
62-
>
63-
{children}
64-
</GlobalContext.Provider>
65-
);
50+
return (
51+
<GlobalContext.Provider
52+
value={{
53+
showSummary,
54+
setShowSummary,
55+
enterNewPatient,
56+
setEnterNewPatient,
57+
resetFormValues,
58+
triggerFormReset,
59+
isEditing,
60+
setIsEditing,
61+
showMetaPanel,
62+
setShowMetaPanel,
63+
}}
64+
>
65+
{children}
66+
</GlobalContext.Provider>
67+
);
6668
};
6769

6870
export const useGlobalContext = () => {
69-
const context = useContext(GlobalContext);
70-
if (context === undefined) {
71-
throw new Error('useGlobalContext must be used within a GlobalProvider');
72-
}
73-
return context;
74-
};
71+
const context = useContext(GlobalContext);
72+
if (context === undefined) {
73+
throw new Error("useGlobalContext must be used within a GlobalProvider");
74+
}
75+
return context;
76+
};

frontend/src/pages/DrugSummary/DrugSummary.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
import DrugSummaryForm from "./DrugSummaryForm";
22
import Layout_V2_Main from "../Layout/Layout_V2_Main";
3+
import { GlobalProvider } from "../../../src/contexts/GlobalContext";
34

45
const DocContextualChat: React.FC = () => {
56
return (
6-
<Layout_V2_Main>
7-
<DrugSummaryForm />
8-
</Layout_V2_Main>
7+
<GlobalProvider>
8+
<Layout_V2_Main>
9+
<DrugSummaryForm />
10+
</Layout_V2_Main>
11+
</GlobalProvider>
912
);
1013
};
1114

frontend/src/pages/DrugSummary/DrugSummaryForm.tsx

Lines changed: 69 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@ import { handleSendDrugSummaryStream } from "../../api/apiClient.ts";
55
import { ChatMessageItem } from "./type";
66
import ParseStringWithLinks from "../../services/parsing/ParseWithSource.tsx";
77
import PDFViewer from "./PDFViewer";
8+
import { useGlobalContext } from "../../../src/contexts/GlobalContext.tsx";
9+
import Insights from "./Insights";
810

911
const DrugSummaryForm = () => {
12+
const { showMetaPanel } = useGlobalContext();
1013
const [inputValue, setInputValue] = useState("");
1114
const [inputHeight, setInputHeight] = useState(50);
1215
const [chatLog, setChatLog] = useState<ChatMessageItem[]>([]);
@@ -16,7 +19,7 @@ const DrugSummaryForm = () => {
1619
const [streamingMessageIndex, setStreamingMessageIndex] = useState<
1720
number | null
1821
>(null);
19-
22+
const showChat = true;
2023
const chatContainerRef = useRef<HTMLDivElement>(null);
2124
const scrollToBottomRef = useRef<HTMLDivElement | null>(null);
2225
const maxInputHeight = 150;
@@ -166,39 +169,57 @@ const DrugSummaryForm = () => {
166169
}
167170
};
168171

172+
const visiblePanels = [
173+
hasPDF ? "pdf" : null,
174+
showChat ? "chat" : null,
175+
showMetaPanel ? "meta" : null,
176+
].filter(Boolean);
177+
178+
const panelCount = visiblePanels.length;
179+
180+
const panelWidthClass =
181+
panelCount === 3 ? "w-1/3" : panelCount === 2 ? "w-1/2" : "w-full";
182+
169183
return (
170184
<div className="flex h-full w-full justify-center">
171185
{hasPDF && (
172-
<div className="w-1/2 h-full">
186+
<div className={`${panelWidthClass} h-full`}>
173187
<PDFViewer />
174188
</div>
175189
)}
176-
<div
177-
className={`${hasPDF ? "w-1/2" : "w-full"} h-full flex flex-col p-2`}
178-
>
190+
<div className={`${panelWidthClass} h-full flex flex-col p-2`}>
179191
<div ref={chatContainerRef} className="flex-grow overflow-y-auto">
180192
{chatLog.length === 0 ? (
181193
<div className="flex flex-col gap-4 p-3 font-quicksand">
182-
<div className="max-w-[310px] rounded-lg border-2 bg-stone-50 p-2 text-sky-950">
194+
<div className="max-w-[310px] border bg-blue-50 bg-opacity-50 border-sky-400 text-sm font-quicksand shadow-md rounded-lg p-2 relative">
183195
You can ask about the content on this page.
184196
</div>
185-
<div className="max-w-[190px] rounded-lg border-2 bg-stone-50 p-2 text-sky-950">
197+
<div className="max-w-[190px] border bg-blue-50 bg-opacity-50 border-sky-400 text-sm font-quicksand shadow-md rounded-lg p-2 relative">
186198
Or questions in general.
187199
</div>
188200
</div>
189201
) : (
190202
chatLog.map((message, index) => (
191-
<div key={index} className="flex flex-col gap-4 p-3">
203+
<div key={index} className="flex flex-col gap-4 p-2">
204+
{message.type === "user" ? null : (
205+
<div className=" flex items-center justify-between">
206+
<div className="flex items-center">
207+
<span className="font-bold text-sm font-quicksand text-sky-950">
208+
Balancer
209+
</span>
210+
</div>
211+
</div>
212+
)}
192213
<div
193-
className={`${
214+
className={`flex ${
194215
message.type === "user" ? "justify-end" : "justify-start"
195-
} `}
216+
}`}
196217
>
197218
<div
198219
className={`${
199220
message.type === "user"
200-
? "border border-black text-sm font-quicksand"
201-
: "border bg-blue-50 bg-opacity-50 border-sky-400 text-sm font-quicksand "
221+
? "border border-black text-sm font-quicksand shadow-md"
222+
: "border bg-blue-50 bg-opacity-50 border-sky-400 text-sm font-quicksand shadow-md"
202223
} rounded-lg p-2 relative`}
203224
>
204225
{typeof message.message === "string" ? (
@@ -215,7 +236,9 @@ const DrugSummaryForm = () => {
215236
message.message.llm_response.length === 0 && (
216237
<div className="flex justify-start">
217238
<div className="items-center justify-center p-1">
218-
<span className="thinking">Let me think</span>
239+
<span className="thinking bg-blue-50 bg-opacity-50 text-sm font-quicksand">
240+
Let me think
241+
</span>
219242
</div>
220243
</div>
221244
)}
@@ -243,27 +266,41 @@ const DrugSummaryForm = () => {
243266
))
244267
)}
245268
</div>
246-
<form onSubmit={handleSubmit} className="p-3 font-quicksand mt-8">
247-
<div className="relative flex items-center border border-sky-400 rounded-lg bg-white shadow-sm px-3 py-2">
248-
<textarea
249-
ref={textareaRef}
250-
placeholder="Ask the document a question..."
251-
className="w-full resize-none bg-transparent outline-none text-gray-700 placeholder-gray-400"
252-
rows={1}
253-
value={inputValue}
254-
onChange={handleInputChange}
255-
onKeyDown={handleKeyDown}
256-
disabled={isStreaming}
257-
style={{ height: `${inputHeight}px`, maxHeight: "150px" }}
258-
/>
259-
<div className="absolute left-3 bottom-full mb-1 text-xs text-gray-500 flex items-center gap-2">
260-
<span>Balancer 1.0</span>
261-
<span></span>
262-
<span>{inputValue.trim().split(/\s+/).length} words</span>
269+
<div className="p-3 font-quicksand mt-8 bg-gray-100 rounded-2xl shadow-inner">
270+
<form onSubmit={handleSubmit} className="space-y-2">
271+
<div className="relative flex items-center border border-gray-300 rounded-xl bg-white shadow-sm px-4 py-3">
272+
<textarea
273+
ref={textareaRef}
274+
placeholder="Ask the document a question..."
275+
className="w-full resize-none bg-transparent outline-none text-sm font-quicksand placeholder-gray-500"
276+
rows={1}
277+
value={inputValue}
278+
onChange={handleInputChange}
279+
onKeyDown={handleKeyDown}
280+
disabled={isStreaming}
281+
style={{ height: `${inputHeight}px`, maxHeight: "150px" }}
282+
/>
263283
</div>
264-
</div>
265-
</form>
284+
285+
<div className="text-xs text-gray-500 flex items-center justify-between px-1">
286+
<div className="flex items-center gap-2">
287+
<span>Balancer 1.0</span>
288+
<span></span>
289+
<span>
290+
{inputValue.trim().split(/\s+/).filter(Boolean).length} words
291+
</span>
292+
</div>
293+
</div>
294+
</form>
295+
</div>
266296
</div>
297+
{showMetaPanel && (
298+
<div
299+
className={`${panelWidthClass} h-full bg-white border-l border-sky-200 p-4 shadow-inner`}
300+
>
301+
<Insights />
302+
</div>
303+
)}
267304
</div>
268305
);
269306
};

0 commit comments

Comments
 (0)