mirror of
https://dev.azure.com/globalhealthx/EMR/_git/helix-engage
synced 2026-04-12 02:38:15 +00:00
Merge branch 'dev' into dev-kartik
This commit is contained in:
@@ -51,6 +51,7 @@ const loadPersistedUser = (): User | null => {
|
||||
|
||||
const AuthContext = createContext<AuthContextType | undefined>(undefined);
|
||||
|
||||
// eslint-disable-next-line react-refresh/only-export-components
|
||||
export const useAuth = (): AuthContextType => {
|
||||
const context = useContext(AuthContext);
|
||||
if (context === undefined) {
|
||||
@@ -96,10 +97,21 @@ export const AuthProvider = ({ children }: AuthProviderProps) => {
|
||||
}, []);
|
||||
|
||||
const logout = useCallback(() => {
|
||||
// Notify sidecar to unlock Redis session + Ozonetel logout
|
||||
const token = localStorage.getItem("helix_access_token");
|
||||
if (token) {
|
||||
const apiUrl = import.meta.env.VITE_API_URL ?? "http://localhost:4100";
|
||||
fetch(`${apiUrl}/auth/logout`, {
|
||||
method: "POST",
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
}).catch(() => {});
|
||||
}
|
||||
|
||||
setUser(DEFAULT_USER);
|
||||
setIsAuthenticated(false);
|
||||
localStorage.removeItem("helix_access_token");
|
||||
localStorage.removeItem("helix_refresh_token");
|
||||
localStorage.removeItem("helix_agent_config");
|
||||
localStorage.removeItem(STORAGE_KEY);
|
||||
}, []);
|
||||
|
||||
@@ -118,4 +130,5 @@ export const AuthProvider = ({ children }: AuthProviderProps) => {
|
||||
);
|
||||
};
|
||||
|
||||
// eslint-disable-next-line react-refresh/only-export-components
|
||||
export { getInitials };
|
||||
|
||||
@@ -33,6 +33,7 @@ type DataContextType = {
|
||||
|
||||
const DataContext = createContext<DataContextType | undefined>(undefined);
|
||||
|
||||
// eslint-disable-next-line react-refresh/only-export-components
|
||||
export const useData = (): DataContextType => {
|
||||
const context = useContext(DataContext);
|
||||
|
||||
@@ -76,12 +77,19 @@ export const DataProvider = ({ children }: DataProviderProps) => {
|
||||
const gql = <T,>(query: string) => apiClient.graphql<T>(query, undefined, { silent: true }).catch(() => null);
|
||||
|
||||
const [leadsData, campaignsData, adsData, followUpsData, activitiesData, callsData, patientsData] = await Promise.all([
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
gql<any>(LEADS_QUERY),
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
gql<any>(CAMPAIGNS_QUERY),
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
gql<any>(ADS_QUERY),
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
gql<any>(FOLLOW_UPS_QUERY),
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
gql<any>(LEAD_ACTIVITIES_QUERY),
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
gql<any>(CALLS_QUERY),
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
gql<any>(PATIENTS_QUERY),
|
||||
]);
|
||||
|
||||
@@ -92,6 +100,7 @@ export const DataProvider = ({ children }: DataProviderProps) => {
|
||||
if (activitiesData) setLeadActivities(transformLeadActivities(activitiesData));
|
||||
if (callsData) setCalls(transformCalls(callsData));
|
||||
if (patientsData) setPatients(transformPatients(patientsData));
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
} catch (err: any) {
|
||||
setError(err.message ?? "Failed to load data");
|
||||
} finally {
|
||||
|
||||
@@ -13,12 +13,29 @@ import {
|
||||
} from "@/state/sip-state";
|
||||
import type { SIPConfig } from "@/types/sip";
|
||||
|
||||
const DEFAULT_CONFIG: SIPConfig = {
|
||||
displayName: import.meta.env.VITE_SIP_DISPLAY_NAME ?? "Helix Agent",
|
||||
uri: import.meta.env.VITE_SIP_URI ?? "",
|
||||
password: import.meta.env.VITE_SIP_PASSWORD ?? "",
|
||||
wsServer: import.meta.env.VITE_SIP_WS_SERVER ?? "",
|
||||
stunServers: "stun:stun.l.google.com:19302",
|
||||
const getSipConfig = (): SIPConfig => {
|
||||
try {
|
||||
const stored = localStorage.getItem("helix_agent_config");
|
||||
if (stored) {
|
||||
const config = JSON.parse(stored);
|
||||
return {
|
||||
displayName: "Helix Agent",
|
||||
uri: config.sipUri,
|
||||
password: config.sipPassword,
|
||||
wsServer: config.sipWsServer,
|
||||
stunServers: "stun:stun.l.google.com:19302",
|
||||
};
|
||||
}
|
||||
} catch {
|
||||
/* intentional */
|
||||
}
|
||||
return {
|
||||
displayName: import.meta.env.VITE_SIP_DISPLAY_NAME ?? "Helix Agent",
|
||||
uri: import.meta.env.VITE_SIP_URI ?? "",
|
||||
password: import.meta.env.VITE_SIP_PASSWORD ?? "",
|
||||
wsServer: import.meta.env.VITE_SIP_WS_SERVER ?? "",
|
||||
stunServers: "stun:stun.l.google.com:19302",
|
||||
};
|
||||
};
|
||||
|
||||
export const SipProvider = ({ children }: PropsWithChildren) => {
|
||||
@@ -41,7 +58,7 @@ export const SipProvider = ({ children }: PropsWithChildren) => {
|
||||
|
||||
// Auto-connect SIP on mount
|
||||
useEffect(() => {
|
||||
connectSip(DEFAULT_CONFIG);
|
||||
connectSip(getSipConfig());
|
||||
}, []);
|
||||
|
||||
// Call duration timer
|
||||
@@ -81,6 +98,7 @@ export const SipProvider = ({ children }: PropsWithChildren) => {
|
||||
};
|
||||
|
||||
// Hook for components to access SIP actions + state
|
||||
// eslint-disable-next-line react-refresh/only-export-components
|
||||
export const useSip = () => {
|
||||
const [connectionStatus] = useAtom(sipConnectionStatusAtom);
|
||||
const [callState] = useAtom(sipCallStateAtom);
|
||||
@@ -132,7 +150,7 @@ export const useSip = () => {
|
||||
isInCall: ["ringing-in", "ringing-out", "active"].includes(callState),
|
||||
ozonetelStatus: "logged-in" as const,
|
||||
ozonetelError: null as string | null,
|
||||
connect: () => connectSip(DEFAULT_CONFIG),
|
||||
connect: () => connectSip(getSipConfig()),
|
||||
disconnect: disconnectSip,
|
||||
makeCall,
|
||||
answer,
|
||||
|
||||
@@ -10,6 +10,7 @@ interface ThemeContextType {
|
||||
|
||||
const ThemeContext = createContext<ThemeContextType | undefined>(undefined);
|
||||
|
||||
// eslint-disable-next-line react-refresh/only-export-components
|
||||
export const useTheme = (): ThemeContextType => {
|
||||
const context = useContext(ThemeContext);
|
||||
|
||||
@@ -76,6 +77,7 @@ export const ThemeProvider = ({ children, defaultTheme = "system", storageKey =
|
||||
|
||||
mediaQuery.addEventListener("change", handleChange);
|
||||
return () => mediaQuery.removeEventListener("change", handleChange);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [theme]);
|
||||
|
||||
return <ThemeContext.Provider value={{ theme, setTheme }}>{children}</ThemeContext.Provider>;
|
||||
|
||||
Reference in New Issue
Block a user