Files
papercrate/frontend/src/index.tsx
T
2025-11-24 20:42:43 +01:00

107 lines
3.5 KiB
TypeScript

import '@fontsource/inter/400.css';
import React from 'react';
import { createRoot } from 'react-dom/client';
import {
HashRouter,
Navigate,
Outlet,
Route,
Routes,
} from 'react-router-dom';
import './styles/index.css';
import DocumentsRoute from './app/DocumentsRoute';
import DropOverlay from './app/DropOverlay';
import LoginRoute from './app/LoginRoute';
import SettingsRoute from './app/SettingsRoute';
import { AppStateProvider } from './app/appState';
import { useDocumentsPreferences } from './app/useDocumentsPreferences';
import { AppShellContext } from './appShellContext';
import useDocumentsWorkspace from './hooks/documents/useDocumentsWorkspace';
import UploadQueueOverlay from './app/UploadQueueOverlay';
const AppLayout: React.FC = () => {
const documentsPreferences = useDocumentsPreferences();
const {
appStatus,
location,
shellRef,
dropOverlayState,
managementModals,
contextValue,
settingsOpen,
closeSettings,
} = useDocumentsWorkspace({
documentsViewMode: documentsPreferences.documentsViewMode,
documentsSortField: documentsPreferences.documentsSortField,
documentsSortDirection: documentsPreferences.documentsSortDirection,
documentsSortFieldRef: documentsPreferences.documentsSortFieldRef,
documentsSortDirectionRef: documentsPreferences.documentsSortDirectionRef,
onDocumentsViewModeChange: documentsPreferences.handleDocumentsViewModeChange,
onDocumentsSortFieldChange: documentsPreferences.handleDocumentsSortFieldChange,
onDocumentsSortDirectionToggle: documentsPreferences.handleDocumentsSortDirectionToggle,
searchIncludeDescendants: documentsPreferences.searchIncludeDescendants,
onSetSearchIncludeDescendants: documentsPreferences.setSearchIncludeDescendants,
sortRefreshReadyRef: documentsPreferences.sortRefreshReadyRef,
});
if (['logged-out', 'authenticating', 'selecting-tenant'].includes(appStatus)) {
const redirectTarget = `${location.pathname}${location.search}${location.hash || ''}`;
return (
<Navigate
to="/account/login"
replace
state={{ from: redirectTarget }}
/>
);
}
return (
<AppShellContext.Provider value={contextValue}>
<div className="app-shell" ref={shellRef}>
<DropOverlay
active={dropOverlayState.active}
folderName={dropOverlayState.folderName}
/>
<UploadQueueOverlay
queue={contextValue.uploadQueue || []}
onClearQueue={contextValue.clearUploadQueue}
/>
<Outlet />
{managementModals}
{settingsOpen ? (
<SettingsRoute open onClose={closeSettings} />
) : null}
</div>
</AppShellContext.Provider>
);
};
const AppRouter: React.FC = () => (
<Routes>
<Route path="/account/login" element={<LoginRoute />} />
<Route element={<AppLayout />}>
<Route path="/" element={<Navigate to="/documents" replace />} />
<Route path="/documents" element={<DocumentsRoute />} />
<Route path="/documents/folder/:folderId" element={<DocumentsRoute />} />
<Route path="/documents/:documentId" element={<DocumentsRoute />} />
<Route path="*" element={<Navigate to="/documents" replace />} />
</Route>
</Routes>
);
const container = document.getElementById('app');
if (!container) {
throw new Error('App root element #app not found');
}
const root = createRoot(container);
root.render(
<AppStateProvider>
<HashRouter>
<AppRouter />
</HashRouter>
</AppStateProvider>,
);