chat / client /src /routes /Root.tsx
helloya20's picture
Upload 2345 files
f0743f4 verified
import React, { useState, useEffect } from 'react';
import { Outlet } from 'react-router-dom';
import type { ContextType } from '~/common';
import {
useSearchEnabled,
useAssistantsMap,
useAuthContext,
useAgentsMap,
useFileMap,
} from '~/hooks';
import {
PromptGroupsProvider,
AssistantsMapContext,
AgentsMapContext,
SetConvoProvider,
FileMapContext,
} from '~/Providers';
import { useUserTermsQuery, useGetStartupConfig } from '~/data-provider';
import { TermsAndConditionsModal } from '~/components/ui';
import { Nav, MobileNav } from '~/components/Nav';
import { useHealthCheck } from '~/data-provider';
import { Banner } from '~/components/Banners';
export default function Root() {
const [showTerms, setShowTerms] = useState(false);
const [bannerHeight, setBannerHeight] = useState(0);
const [navVisible, setNavVisible] = useState(() => {
const savedNavVisible = localStorage.getItem('navVisible');
return savedNavVisible !== null ? JSON.parse(savedNavVisible) : true;
});
const { isAuthenticated, logout } = useAuthContext();
// Global health check - runs once per authenticated session
useHealthCheck(isAuthenticated);
const assistantsMap = useAssistantsMap({ isAuthenticated });
const agentsMap = useAgentsMap({ isAuthenticated });
const fileMap = useFileMap({ isAuthenticated });
const { data: config } = useGetStartupConfig();
const { data: termsData } = useUserTermsQuery({
enabled: isAuthenticated && config?.interface?.termsOfService?.modalAcceptance === true,
});
useSearchEnabled(isAuthenticated);
useEffect(() => {
if (termsData) {
setShowTerms(!termsData.termsAccepted);
}
}, [termsData]);
const handleAcceptTerms = () => {
setShowTerms(false);
};
const handleDeclineTerms = () => {
setShowTerms(false);
logout('/login?redirect=false');
};
if (!isAuthenticated) {
return null;
}
return (
<SetConvoProvider>
<FileMapContext.Provider value={fileMap}>
<AssistantsMapContext.Provider value={assistantsMap}>
<AgentsMapContext.Provider value={agentsMap}>
<PromptGroupsProvider>
<Banner onHeightChange={setBannerHeight} />
<div className="flex" style={{ height: `calc(100dvh - ${bannerHeight}px)` }}>
<div className="relative z-0 flex h-full w-full overflow-hidden">
<Nav navVisible={navVisible} setNavVisible={setNavVisible} />
<div className="relative flex h-full max-w-full flex-1 flex-col overflow-hidden">
<MobileNav navVisible={navVisible} setNavVisible={setNavVisible} />
<Outlet context={{ navVisible, setNavVisible } satisfies ContextType} />
</div>
</div>
</div>
</PromptGroupsProvider>
</AgentsMapContext.Provider>
{config?.interface?.termsOfService?.modalAcceptance === true && (
<TermsAndConditionsModal
open={showTerms}
onOpenChange={setShowTerms}
onAccept={handleAcceptTerms}
onDecline={handleDeclineTerms}
title={config.interface.termsOfService.modalTitle}
modalContent={config.interface.termsOfService.modalContent}
/>
)}
</AssistantsMapContext.Provider>
</FileMapContext.Provider>
</SetConvoProvider>
);
}