Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 21 additions & 16 deletions frontend/src/api/apiClient.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import axios from "axios";
import { FormValues } from "../pages/Feedback/FeedbackForm";
import { Conversation } from "../components/Header/Chat";
const baseURL = import.meta.env.VITE_API_BASE_URL;
import {
V1_API_ENDPOINTS,
CONVERSATION_ENDPOINTS,
endpoints,
} from "./endpoints";

// Use empty string for relative URLs - all API calls will be relative to current domain
const baseURL = "";

export const publicApi = axios.create({ baseURL });

Expand Down Expand Up @@ -31,7 +38,7 @@ const handleSubmitFeedback = async (
message: FormValues["message"],
) => {
try {
const response = await publicApi.post(`/v1/api/feedback/`, {
const response = await publicApi.post(V1_API_ENDPOINTS.FEEDBACK, {
feedbacktype: feedbackType,
name,
email,
Expand All @@ -49,7 +56,7 @@ const handleSendDrugSummary = async (
guid: string,
) => {
try {
const endpoint = guid ? `/v1/api/embeddings/ask_embeddings?guid=${guid}` : '/v1/api/embeddings/ask_embeddings';
const endpoint = endpoints.embeddingsAsk(guid);
const response = await adminApi.post(endpoint, {
message,
});
Expand All @@ -63,7 +70,7 @@ const handleSendDrugSummary = async (

const handleRuleExtraction = async (guid: string) => {
try {
const response = await adminApi.get(`/v1/api/rule_extraction_openai?guid=${guid}`);
const response = await adminApi.get(endpoints.ruleExtraction(guid));
// console.log("Rule extraction response:", JSON.stringify(response.data, null, 2));
return response.data;
} catch (error) {
Expand All @@ -77,7 +84,7 @@ const fetchRiskDataWithSources = async (
source: "include" | "diagnosis" | "diagnosis_depressed" = "include",
) => {
try {
const response = await publicApi.post(`/v1/api/riskWithSources`, {
const response = await publicApi.post(V1_API_ENDPOINTS.RISK_WITH_SOURCES, {
drug: medication,
source: source,
});
Expand All @@ -101,12 +108,10 @@ const handleSendDrugSummaryStream = async (
callbacks: StreamCallbacks,
): Promise<void> => {
const token = localStorage.getItem("access");
const endpoint = `/v1/api/embeddings/ask_embeddings?stream=true${
guid ? `&guid=${guid}` : ""
}`;
const endpoint = endpoints.embeddingsAskStream(guid);

try {
const response = await fetch(baseURL + endpoint, {
const response = await fetch(endpoint, {
method: "POST",
headers: {
"Content-Type": "application/json",
Expand Down Expand Up @@ -206,7 +211,7 @@ const handleSendDrugSummaryStreamLegacy = async (

const fetchConversations = async (): Promise<Conversation[]> => {
try {
const response = await publicApi.get(`/chatgpt/conversations/`);
const response = await publicApi.get(CONVERSATION_ENDPOINTS.CONVERSATIONS);
return response.data;
} catch (error) {
console.error("Error(s) during getConversations: ", error);
Expand All @@ -216,7 +221,7 @@ const fetchConversations = async (): Promise<Conversation[]> => {

const fetchConversation = async (id: string): Promise<Conversation> => {
try {
const response = await publicApi.get(`/chatgpt/conversations/${id}/`);
const response = await publicApi.get(endpoints.conversation(id));
return response.data;
} catch (error) {
console.error("Error(s) during getConversation: ", error);
Expand All @@ -226,7 +231,7 @@ const fetchConversation = async (id: string): Promise<Conversation> => {

const newConversation = async (): Promise<Conversation> => {
try {
const response = await adminApi.post(`/chatgpt/conversations/`, {
const response = await adminApi.post(CONVERSATION_ENDPOINTS.CONVERSATIONS, {
messages: [],
});
return response.data;
Expand All @@ -243,7 +248,7 @@ const continueConversation = async (
): Promise<{ response: string; title: Conversation["title"] }> => {
try {
const response = await adminApi.post(
`/chatgpt/conversations/${id}/continue_conversation/`,
endpoints.continueConversation(id),
{
message,
page_context,
Expand All @@ -258,7 +263,7 @@ const continueConversation = async (

const deleteConversation = async (id: string) => {
try {
const response = await adminApi.delete(`/chatgpt/conversations/${id}/`);
const response = await adminApi.delete(endpoints.conversation(id));
return response.data;
} catch (error) {
console.error("Error(s) during deleteConversation: ", error);
Expand All @@ -273,7 +278,7 @@ const updateConversationTitle = async (
{ status: string; title: Conversation["title"] } | { error: string }
> => {
try {
const response = await adminApi.patch(`/chatgpt/conversations/${id}/update_title/`, {
const response = await adminApi.patch(endpoints.updateConversationTitle(id), {
title: newTitle,
});
return response.data;
Expand All @@ -289,7 +294,7 @@ const sendAssistantMessage = async (
previousResponseId?: string,
) => {
try {
const response = await publicApi.post(`/v1/api/assistant`, {
const response = await publicApi.post(V1_API_ENDPOINTS.ASSISTANT, {
message,
previous_response_id: previousResponseId,
});
Expand Down
137 changes: 137 additions & 0 deletions frontend/src/api/endpoints.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
/**
* Centralized API endpoints configuration
*
* This file contains all API endpoint paths used throughout the application.
* Update endpoints here to change them across the entire frontend.
*/

const API_BASE = '/api';

/**
* Authentication endpoints
*/
export const AUTH_ENDPOINTS = {
JWT_VERIFY: `${API_BASE}/auth/jwt/verify/`,
JWT_CREATE: `${API_BASE}/auth/jwt/create/`,
USER_ME: `${API_BASE}/auth/users/me/`,
RESET_PASSWORD: `${API_BASE}/auth/users/reset_password/`,
RESET_PASSWORD_CONFIRM: `${API_BASE}/auth/users/reset_password_confirm/`,
} as const;

/**
* V1 API endpoints
*/
export const V1_API_ENDPOINTS = {
// Feedback
FEEDBACK: `${API_BASE}/v1/api/feedback/`,

// Embeddings
EMBEDDINGS_ASK: `${API_BASE}/v1/api/embeddings/ask_embeddings`,
RULE_EXTRACTION: `${API_BASE}/v1/api/rule_extraction_openai`,

// Risk
RISK_WITH_SOURCES: `${API_BASE}/v1/api/riskWithSources`,

// Assistant
ASSISTANT: `${API_BASE}/v1/api/assistant`,

// File Management
UPLOAD_FILE: `${API_BASE}/v1/api/uploadFile`,
EDIT_METADATA: `${API_BASE}/v1/api/editmetadata`,

// Medications
GET_FULL_LIST_MED: `${API_BASE}/v1/api/get_full_list_med`,
GET_MED_RECOMMEND: `${API_BASE}/v1/api/get_med_recommend`,
ADD_MEDICATION: `${API_BASE}/v1/api/add_medication`,
DELETE_MED: `${API_BASE}/v1/api/delete_med`,

// Medication Rules
MED_RULES: `${API_BASE}/v1/api/medRules`,
} as const;

/**
* ChatGPT/Conversations endpoints
*/
export const CONVERSATION_ENDPOINTS = {
CONVERSATIONS: `${API_BASE}/chatgpt/conversations/`,
EXTRACT_TEXT: `${API_BASE}/chatgpt/extract_text/`,
} as const;

/**
* AI Settings endpoints
*/
export const AI_SETTINGS_ENDPOINTS = {
SETTINGS: `${API_BASE}/ai_settings/settings/`,
} as const;

/**
* Helper functions for dynamic endpoints
*/
export const endpoints = {
/**
* Get embeddings endpoint with optional GUID
*/
embeddingsAsk: (guid?: string): string => {
const base = V1_API_ENDPOINTS.EMBEDDINGS_ASK;
return guid ? `${base}?guid=${guid}` : base;
},

/**
* Get embeddings streaming endpoint
*/
embeddingsAskStream: (guid?: string): string => {
const base = `${V1_API_ENDPOINTS.EMBEDDINGS_ASK}?stream=true`;
return guid ? `${base}&guid=${guid}` : base;
},

/**
* Get rule extraction endpoint with GUID
*/
ruleExtraction: (guid: string): string => {
return `${V1_API_ENDPOINTS.RULE_EXTRACTION}?guid=${guid}`;
},

/**
* Get conversation by ID
*/
conversation: (id: string): string => {
return `${CONVERSATION_ENDPOINTS.CONVERSATIONS}${id}/`;
},

/**
* Continue conversation endpoint
*/
continueConversation: (id: string): string => {
return `${CONVERSATION_ENDPOINTS.CONVERSATIONS}${id}/continue_conversation/`;
},

/**
* Update conversation title endpoint
*/
updateConversationTitle: (id: string): string => {
return `${CONVERSATION_ENDPOINTS.CONVERSATIONS}${id}/update_title/`;
},

/**
* Get upload file endpoint with GUID
*/
uploadFile: (guid: string): string => {
return `${V1_API_ENDPOINTS.UPLOAD_FILE}/${guid}`;
},

/**
* Edit metadata endpoint with GUID
*/
editMetadata: (guid: string): string => {
return `${V1_API_ENDPOINTS.EDIT_METADATA}/${guid}`;
},
} as const;

/**
* Type-safe endpoint values
*/
export type AuthEndpoint = typeof AUTH_ENDPOINTS[keyof typeof AUTH_ENDPOINTS];
export type V1ApiEndpoint = typeof V1_API_ENDPOINTS[keyof typeof V1_API_ENDPOINTS];
export type ConversationEndpoint = typeof CONVERSATION_ENDPOINTS[keyof typeof CONVERSATION_ENDPOINTS];
export type AiSettingsEndpoint = typeof AI_SETTINGS_ENDPOINTS[keyof typeof AI_SETTINGS_ENDPOINTS];

3 changes: 1 addition & 2 deletions frontend/src/pages/DocumentManager/UploadFile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,8 @@ const UploadFile: React.FC = () => {
formData.append("file", file);

try {
const baseUrl = import.meta.env.VITE_API_BASE_URL;
const response = await axios.post(
`${baseUrl}/v1/api/uploadFile`,
`/api/v1/api/uploadFile`,
formData,
{
headers: {
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/pages/DrugSummary/PDFViewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
import { Document, Page, pdfjs } from "react-pdf";
import { useLocation, useNavigate } from "react-router-dom";
import axios from "axios";
import { endpoints } from "../../api/endpoints";
import "react-pdf/dist/esm/Page/AnnotationLayer.css";
import "react-pdf/dist/esm/Page/TextLayer.css";
import ZoomMenu from "./ZoomMenu";
Expand Down Expand Up @@ -50,11 +51,10 @@ const PDFViewer = () => {
const params = new URLSearchParams(location.search);
const guid = params.get("guid");
const pageParam = params.get("page");
const baseURL = import.meta.env.VITE_API_BASE_URL as string | undefined;

const pdfUrl = useMemo(() => {
return guid && baseURL ? `${baseURL}/v1/api/uploadFile/${guid}` : null;
}, [guid, baseURL]);
return guid ? endpoints.uploadFile(guid) : null;
}, [guid]);

useEffect(() => setUiScalePct(Math.round(scale * 100)), [scale]);

Expand Down
4 changes: 2 additions & 2 deletions frontend/src/pages/Files/FileRow.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { useState } from "react";
import { Link } from "react-router-dom";
import { endpoints } from "../../api/endpoints";

interface File {
id: number;
Expand Down Expand Up @@ -42,8 +43,7 @@ const FileRow: React.FC<FileRowProps> = ({
const handleSave = async () => {
setLoading(true);
try {
const baseUrl = import.meta.env.VITE_API_BASE_URL as string;
await fetch(`${baseUrl}/v1/api/editmetadata/${file.guid}`, {
await fetch(endpoints.editMetadata(file.guid), {
method: "PATCH",
headers: {
"Content-Type": "application/json",
Expand Down
6 changes: 2 additions & 4 deletions frontend/src/pages/Files/ListOfFiles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,10 @@ const ListOfFiles: React.FC<{ showTable?: boolean }> = ({
const [downloading, setDownloading] = useState<string | null>(null);
const [opening, setOpening] = useState<string | null>(null);

const baseUrl = import.meta.env.VITE_API_BASE_URL;

useEffect(() => {
const fetchFiles = async () => {
try {
const url = `${baseUrl}/v1/api/uploadFile`;
const url = `/api/v1/api/uploadFile`;

const { data } = await publicApi.get(url);

Expand All @@ -50,7 +48,7 @@ const ListOfFiles: React.FC<{ showTable?: boolean }> = ({
};

fetchFiles();
}, [baseUrl]);
}, []);

const updateFileName = (guid: string, updatedFile: Partial<File>) => {
setFiles((prevFiles) =>
Expand Down
3 changes: 1 addition & 2 deletions frontend/src/pages/Layout/Layout_V2_Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@ const Sidebar: React.FC = () => {
useEffect(() => {
const fetchFiles = async () => {
try {
const baseUrl = import.meta.env.VITE_API_BASE_URL;
const response = await axios.get(`${baseUrl}/v1/api/uploadFile`);
const response = await axios.get(`/api/v1/api/uploadFile`);
if (Array.isArray(response.data)) {
setFiles(response.data);
}
Expand Down
6 changes: 2 additions & 4 deletions frontend/src/pages/ListMeds/useMedications.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,10 @@ export function useMedications() {
const [medications, setMedications] = useState<MedData[]>([]);
const [errors, setErrors] = useState<string[]>([]);

const baseUrl = import.meta.env.VITE_API_BASE_URL;

useEffect(() => {
const fetchMedications = async () => {
try {
const url = `${baseUrl}/v1/api/get_full_list_med`;
const url = `/api/v1/api/get_full_list_med`;

const { data } = await publicApi.get(url);

Expand Down Expand Up @@ -44,7 +42,7 @@ export function useMedications() {
};

fetchMedications();
}, [baseUrl]);
}, []);

console.log(medications);

Expand Down
Loading
Loading