Add demo mode with hourly reset, example trips & demo banner

DEMO_MODE=true enables: auto-seeded admin + demo user, 3 example trips
(Tokyo, Barcelona, Wien), hourly reset of demo user data, one-click
demo login, visible banner with feature info. Zero behavior change
when DEMO_MODE is not set.
This commit is contained in:
Maurice
2026-03-19 13:25:37 +01:00
parent f8dcce802e
commit e8acbbd129
13 changed files with 558 additions and 5 deletions

View File

@@ -12,6 +12,7 @@ import AdminPage from './pages/AdminPage'
import SettingsPage from './pages/SettingsPage'
import { ToastContainer } from './components/shared/Toast'
import { TranslationProvider } from './i18n'
import DemoBanner from './components/Layout/DemoBanner'
function ProtectedRoute({ children, adminRequired = false }) {
const { isAuthenticated, user, isLoading } = useAuthStore()
@@ -53,13 +54,19 @@ function RootRedirect() {
}
export default function App() {
const { loadUser, token, isAuthenticated } = useAuthStore()
const { loadUser, token, isAuthenticated, demoMode, setDemoMode } = useAuthStore()
const { loadSettings } = useSettingsStore()
useEffect(() => {
if (token) {
loadUser()
}
// Check if demo mode is active
import('./api/client').then(({ authApi }) => {
authApi.getAppConfig?.().then(config => {
if (config?.demo_mode) setDemoMode(true)
}).catch(() => {})
})
}, [])
const { settings } = useSettingsStore()
@@ -82,6 +89,8 @@ export default function App() {
return (
<TranslationProvider>
<ToastContainer />
{demoMode && isAuthenticated && <DemoBanner />}
<div style={demoMode && isAuthenticated ? { paddingTop: 36 } : undefined}>
<Routes>
<Route path="/" element={<RootRedirect />} />
<Route path="/login" element={<LoginPage />} />
@@ -128,6 +137,7 @@ export default function App() {
/>
<Route path="*" element={<Navigate to="/" replace />} />
</Routes>
</div>
</TranslationProvider>
)
}