refactor: Reorganize frontend by moving UI components, hooks, and utilities to new components, logic, features, and lib directories

This commit is contained in:
2025-12-04 23:05:35 +01:00
parent 128714a1e0
commit 8aa1872ea5
114 changed files with 199 additions and 199 deletions
@@ -0,0 +1,115 @@
import { MutableRefObject, useCallback } from 'react';
import type { NavigateFunction } from 'react-router-dom';
import type { FolderId, TenantId } from '../../types/identifiers';
import { api, listTenants, switchTenant } from '../../lib/api/apiClient';
interface TenantOption {
id?: TenantId;
name?: string;
}
interface UseTenantManagerOptions {
appDispatch: (action: any) => void;
currentTenantId: TenantId | null;
resetWorkspaceState: () => void;
setStatusMessage: (message: string, variant?: string) => void;
notifyApiError: (error: unknown, message: string) => void;
refreshTags: () => Promise<void>;
refreshCorrespondents: () => Promise<void>;
loadFolder: (folderId: FolderId, options?: { preserveSearch?: boolean }) => Promise<void>;
handleDocumentsViewModeChange: (mode: string) => void;
navigate: NavigateFunction;
tokenRef?: MutableRefObject<string | null>;
tenantIdRef?: MutableRefObject<TenantId | null>;
}
const useTenantManager = ({
appDispatch,
currentTenantId,
resetWorkspaceState,
setStatusMessage,
notifyApiError,
refreshTags,
refreshCorrespondents,
loadFolder,
handleDocumentsViewModeChange,
navigate,
tokenRef,
tenantIdRef,
}: UseTenantManagerOptions) => {
const handleTenantSelect = useCallback(
async (tenantOption: TenantOption | null, { refreshOnly = false }: { refreshOnly?: boolean } = {}) => {
const requestedTenantId = tenantOption?.id ?? null;
if (!refreshOnly && (!requestedTenantId || requestedTenantId === currentTenantId)) {
return;
}
try {
if (refreshOnly) {
const data = await listTenants();
appDispatch({
type: 'SET_TENANTS',
tenants: data,
});
return;
}
const data = await switchTenant(requestedTenantId);
if (!data?.access_token) {
throw new Error('Missing access token in tenant switch response.');
}
appDispatch({ type: 'LOGOUT' });
resetWorkspaceState();
appDispatch({
type: 'LOGIN_SUCCESS',
token: data.access_token,
tenant: data.tenant || null,
});
api.defaults.headers.common.Authorization = `Bearer ${data.access_token}`;
if (tokenRef) {
tokenRef.current = data.access_token;
}
if (tenantIdRef) {
tenantIdRef.current = data?.tenant?.id ?? null;
}
if (Array.isArray(data?.tenants)) {
appDispatch({ type: 'SET_TENANTS', tenants: data.tenants });
}
handleDocumentsViewModeChange('list');
navigate('/documents', { replace: true });
await Promise.all([refreshTags(), refreshCorrespondents()]);
await loadFolder('root', { preserveSearch: false });
const tenantLabel = data?.tenant?.name || data?.tenant?.id || 'tenant';
setStatusMessage(`Switched to ${tenantLabel}.`, 'info');
} catch (error) {
notifyApiError(error, 'Failed to switch tenant.');
}
},
[
appDispatch,
currentTenantId,
handleDocumentsViewModeChange,
loadFolder,
navigate,
notifyApiError,
refreshCorrespondents,
refreshTags,
resetWorkspaceState,
setStatusMessage,
tenantIdRef,
tokenRef,
],
);
return { handleTenantSelect };
};
export default useTenantManager;