Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 2x 2x 2x 2x 2x 2x 9x 9x 9x 9x 9x 2x 2x 2x 2x 2x 2x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 1x 1x | /**
* @file AppPublicShell.tsx
* @description
* Enterprise-quality shell for unauthenticated pages (Home, Login, LogoutSuccess).
* Thin orchestrator delegating to header, content, and toast components.
* Minimal header with language toggle and dark/light theme switcher.
* No sidebar, no user profile, no navigation menu.
*
* @enterprise
* - Clean, professional header suitable for public-facing pages
* - Language toggle (π©πͺ/πΊπΈ) persists in localStorage and syncs with i18next
* - Dark/light theme toggle with localStorage persistence
* - Toast context for lightweight notifications
* - Responsive design (mobile-friendly)
* - Full-width content area with proper spacing
*
* @routing
* Unauthenticated routes render as <Outlet /> within the content area.
* Examples: /home, /login, /logout-success
*
* @example
* ```tsx
* <AppPublicShell />
* ```
*/
import * as React from 'react';
import { Box, CssBaseline, ThemeProvider } from '@mui/material';
import { useTranslation } from 'react-i18next';
import { ToastContext } from '../../context/toast';
import { buildTheme } from '../../theme';
import { useThemeMode, useLocale, usePublicShellToast } from './hooks';
import { PublicShellHeader } from './header';
import PublicShellContent from './PublicShellContent';
import PublicShellToastContainer from './PublicShellToastContainer';
/**
* AppPublicShell component (thin orchestrator)
* Manages state and delegates to sub-components
*
* @returns Public shell layout with header, content, and toast notifications
*/
const AppPublicShell: React.FC = () => {
const { i18n, t } = useTranslation('common');
// State management via custom hooks
const { themeMode, toggleThemeMode } = useThemeMode();
const { locale, toggleLocale } = useLocale(i18n);
const { toast, showToast, hideToast, setToast } = usePublicShellToast();
// Build theme based on locale and theme mode
const theme = React.useMemo(() => buildTheme(locale, themeMode), [locale, themeMode]);
/**
* Handle language toggle with toast notification
*/
const handleToggleLocale = () => {
toggleLocale();
showToast(
locale === 'de' ? 'Sprache: Deutsch' : 'Language: English',
'info'
);
};
/**
* Handle theme toggle with toast notification
*/
const handleToggleThemeMode = () => {
toggleThemeMode();
showToast(
themeMode === 'light' ? 'Dark mode enabled' : 'Light mode enabled',
'info'
);
};
return (
<ThemeProvider theme={theme}>
<CssBaseline />
<ToastContext.Provider
value={(msg, severity = 'success') => setToast({ open: true, msg, severity })}
>
{/* Main layout container */}
<Box sx={{ display: 'flex', bgcolor: 'background.default', minHeight: '100vh' }}>
{/* Fixed header */}
<PublicShellHeader
appTitle={t('app.title')}
themeMode={themeMode}
onThemeToggle={handleToggleThemeMode}
locale={locale}
onLocaleToggle={handleToggleLocale}
languageTooltip={t('actions.toggleLanguage')}
/>
{/* Main content area */}
<PublicShellContent />
{/* Toast notifications */}
<PublicShellToastContainer toast={toast} onClose={hideToast} />
</Box>
</ToastContext.Provider>
</ThemeProvider>
);
};
export default AppPublicShell;
|