2026-03-28 01:40:18 +08:00
|
|
|
import React, { useEffect, ReactNode } from 'react'
|
2026-03-19 06:58:08 +08:00
|
|
|
import { Routes, Route, Navigate, useLocation } from 'react-router-dom'
|
|
|
|
|
import { useAuthStore } from './store/authStore'
|
|
|
|
|
import { useSettingsStore } from './store/settingsStore'
|
|
|
|
|
import LoginPage from './pages/LoginPage'
|
|
|
|
|
import DashboardPage from './pages/DashboardPage'
|
|
|
|
|
import TripPlannerPage from './pages/TripPlannerPage'
|
|
|
|
|
import FilesPage from './pages/FilesPage'
|
|
|
|
|
import AdminPage from './pages/AdminPage'
|
|
|
|
|
import SettingsPage from './pages/SettingsPage'
|
v2.5.0 — Addon System, Vacay, Atlas, Dashboard Widgets & Mobile Overhaul
The biggest NOMAD update yet. Introduces a modular addon architecture and three major new features.
Addon System:
- Admin panel addon management with enable/disable toggles
- Trip addons (Packing List, Budget, Documents) dynamically show/hide in trip tabs
- Global addons appear in the main navigation for all users
Vacay — Vacation Day Planner (Global Addon):
- Monthly calendar view with international public holidays (100+ countries via Nager.Date API)
- Company holidays with auto-cleanup of conflicting entries
- User-based system: each NOMAD user is a person in the calendar
- Fusion system: invite other users to share a combined calendar with real-time WebSocket sync
- Vacation entitlement tracking with automatic carry-over to next year
- Full settings: block weekends, public holidays, company holidays, carry-over toggle
- Invite/accept/decline flow with forced confirmation modal
- Color management per user with collision detection on fusion
- Dissolve fusion with preserved entries
Atlas — Travel World Map (Global Addon):
- Fullscreen Leaflet world map with colored country polygons (GeoJSON)
- Glass-effect bottom panel with stats, continent breakdown, streak tracking
- Country tooltips with trip count, places visited, first/last visit dates
- Liquid glass hover effect on the stats panel
- Canvas renderer with tile preloading for maximum performance
- Responsive: mobile stats bars, no zoom controls on touch
Dashboard Widgets:
- Currency converter with 50 currencies, CustomSelect dropdowns, localStorage persistence
- Timezone widget with customizable city list, live updating clock
- Per-user toggle via settings button, bottom sheet on mobile
Admin Panel:
- Consistent dark mode across all tabs (CSS variable overrides)
- Online/offline status badges on user list via WebSocket
- Unified heading sizes and subtitles across all sections
- Responsive tab grid on mobile
Mobile Improvements:
- Vacay: slide-in sidebar drawer, floating toolbar, responsive calendar grid
- Atlas: top/bottom glass stat bars, no popups
- Trip Planner: fixed position content container prevents overscroll, portal-based sidebar buttons
- Dashboard: fixed viewport container, mobile widget bottom sheet
- Admin: responsive tab grid, compact buttons
- Global: overscroll-behavior fixes, modal scroll containment
Other:
- Trip tab labels: Planung→Karte, Packliste→Liste, Buchungen→Buchung (DE mobile)
- Reservation form responsive layout
- Backup panel responsive buttons
2026-03-21 06:14:06 +08:00
|
|
|
import VacayPage from './pages/VacayPage'
|
|
|
|
|
import AtlasPage from './pages/AtlasPage'
|
feat: public read-only share links with permissions — closes #79
Share links:
- Generate a public link in the trip share modal
- Choose what to share: Map & Plan, Bookings, Packing, Budget, Chat
- Permissions enforced server-side
- Delete link to revoke access instantly
Shared trip page (/shared/:token):
- Read-only view with TREK logo, cover image, trip details
- Tabbed navigation with Lucide icons (responsive on mobile)
- Interactive map with auto-fit bounds per day
- Day plan, Bookings, Packing, Budget, Chat views
- Language picker, TREK branding footer
Technical:
- share_tokens DB table with per-field permissions
- Public GET /shared/:token endpoint (no auth)
- Two-column share modal (max-w-5xl)
2026-03-31 00:02:53 +08:00
|
|
|
import SharedTripPage from './pages/SharedTripPage'
|
2026-03-19 06:58:08 +08:00
|
|
|
import { ToastContainer } from './components/shared/Toast'
|
v2.5.7: Reservation overhaul, Day Detail Panel, i18n, paste support, auto dark mode
BREAKING: Reservations have been completely rebuilt. Existing place-level
reservations are no longer used. All reservations must be re-created via
the Bookings tab. Your trips, places, and other data are unaffected.
Reservation System (rebuilt from scratch):
- Reservations now link to specific day assignments instead of places
- Same place on different days can have independent reservations
- New assignment picker in booking modal (grouped by day, searchable)
- Removed day/place dropdowns from booking form
- Reservation badges in day plan sidebar with type-specific icons
- Reservation details in place inspector (only for selected assignment)
- Reservation summary in day detail panel
Day Detail Panel (new):
- Opens on day click in the sidebar
- Detailed weather: hourly forecast, precipitation, wind, sunrise/sunset
- Historical climate averages for dates beyond 16 days
- Accommodation management with check-in/check-out, confirmation number
- Hotel assignment across multiple days with day range picker
- Reservation overview for the day
Places:
- Places can now be assigned to the same day multiple times
- Start time + end time fields (replaces single time field)
- Map badges show multiple position numbers (e.g. "1 · 4")
- Route optimization fixed for duplicate places
- File attachments during place editing (not just creation)
- Cover image upload during trip creation (not just editing)
- Paste support (Ctrl+V) for images in trip, place, and file forms
Internationalization:
- 200+ hardcoded German strings translated to i18n (EN + DE)
- Server error messages in English
- Category seeds in English for new installations
- All planner, register, photo, packing components translated
UI/UX:
- Auto dark mode (follows system preference, configurable in settings)
- Navbar toggle switches light/dark (overrides auto)
- Sidebar minimize buttons z-index fixed
- Transport mode selector removed from day plan
- CustomSelect supports grouped headers (isHeader option)
- Optimistic updates for day notes (instant feedback)
- Booking cards redesigned with type-colored headers and structured details
Weather:
- Wind speed in mph when using Fahrenheit setting
- Weather description language matches app language
Admin:
- Weather info panel replaces OpenWeatherMap key input
- "Recommended" badge styling updated
2026-03-25 03:10:45 +08:00
|
|
|
import { TranslationProvider, useTranslation } from './i18n'
|
2026-03-19 21:09:12 +08:00
|
|
|
import { authApi } from './api/client'
|
2026-03-19 06:58:08 +08:00
|
|
|
|
2026-03-28 01:40:18 +08:00
|
|
|
interface ProtectedRouteProps {
|
|
|
|
|
children: ReactNode
|
|
|
|
|
adminRequired?: boolean
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function ProtectedRoute({ children, adminRequired = false }: ProtectedRouteProps) {
|
2026-03-31 04:42:40 +08:00
|
|
|
const { isAuthenticated, user, isLoading, appRequireMfa } = useAuthStore()
|
v2.5.7: Reservation overhaul, Day Detail Panel, i18n, paste support, auto dark mode
BREAKING: Reservations have been completely rebuilt. Existing place-level
reservations are no longer used. All reservations must be re-created via
the Bookings tab. Your trips, places, and other data are unaffected.
Reservation System (rebuilt from scratch):
- Reservations now link to specific day assignments instead of places
- Same place on different days can have independent reservations
- New assignment picker in booking modal (grouped by day, searchable)
- Removed day/place dropdowns from booking form
- Reservation badges in day plan sidebar with type-specific icons
- Reservation details in place inspector (only for selected assignment)
- Reservation summary in day detail panel
Day Detail Panel (new):
- Opens on day click in the sidebar
- Detailed weather: hourly forecast, precipitation, wind, sunrise/sunset
- Historical climate averages for dates beyond 16 days
- Accommodation management with check-in/check-out, confirmation number
- Hotel assignment across multiple days with day range picker
- Reservation overview for the day
Places:
- Places can now be assigned to the same day multiple times
- Start time + end time fields (replaces single time field)
- Map badges show multiple position numbers (e.g. "1 · 4")
- Route optimization fixed for duplicate places
- File attachments during place editing (not just creation)
- Cover image upload during trip creation (not just editing)
- Paste support (Ctrl+V) for images in trip, place, and file forms
Internationalization:
- 200+ hardcoded German strings translated to i18n (EN + DE)
- Server error messages in English
- Category seeds in English for new installations
- All planner, register, photo, packing components translated
UI/UX:
- Auto dark mode (follows system preference, configurable in settings)
- Navbar toggle switches light/dark (overrides auto)
- Sidebar minimize buttons z-index fixed
- Transport mode selector removed from day plan
- CustomSelect supports grouped headers (isHeader option)
- Optimistic updates for day notes (instant feedback)
- Booking cards redesigned with type-colored headers and structured details
Weather:
- Wind speed in mph when using Fahrenheit setting
- Weather description language matches app language
Admin:
- Weather info panel replaces OpenWeatherMap key input
- "Recommended" badge styling updated
2026-03-25 03:10:45 +08:00
|
|
|
const { t } = useTranslation()
|
2026-03-31 04:42:40 +08:00
|
|
|
const location = useLocation()
|
2026-03-19 06:58:08 +08:00
|
|
|
|
|
|
|
|
if (isLoading) {
|
|
|
|
|
return (
|
|
|
|
|
<div className="min-h-screen flex items-center justify-center bg-slate-50">
|
|
|
|
|
<div className="flex flex-col items-center gap-3">
|
|
|
|
|
<div className="w-10 h-10 border-4 border-slate-200 border-t-slate-900 rounded-full animate-spin"></div>
|
v2.5.7: Reservation overhaul, Day Detail Panel, i18n, paste support, auto dark mode
BREAKING: Reservations have been completely rebuilt. Existing place-level
reservations are no longer used. All reservations must be re-created via
the Bookings tab. Your trips, places, and other data are unaffected.
Reservation System (rebuilt from scratch):
- Reservations now link to specific day assignments instead of places
- Same place on different days can have independent reservations
- New assignment picker in booking modal (grouped by day, searchable)
- Removed day/place dropdowns from booking form
- Reservation badges in day plan sidebar with type-specific icons
- Reservation details in place inspector (only for selected assignment)
- Reservation summary in day detail panel
Day Detail Panel (new):
- Opens on day click in the sidebar
- Detailed weather: hourly forecast, precipitation, wind, sunrise/sunset
- Historical climate averages for dates beyond 16 days
- Accommodation management with check-in/check-out, confirmation number
- Hotel assignment across multiple days with day range picker
- Reservation overview for the day
Places:
- Places can now be assigned to the same day multiple times
- Start time + end time fields (replaces single time field)
- Map badges show multiple position numbers (e.g. "1 · 4")
- Route optimization fixed for duplicate places
- File attachments during place editing (not just creation)
- Cover image upload during trip creation (not just editing)
- Paste support (Ctrl+V) for images in trip, place, and file forms
Internationalization:
- 200+ hardcoded German strings translated to i18n (EN + DE)
- Server error messages in English
- Category seeds in English for new installations
- All planner, register, photo, packing components translated
UI/UX:
- Auto dark mode (follows system preference, configurable in settings)
- Navbar toggle switches light/dark (overrides auto)
- Sidebar minimize buttons z-index fixed
- Transport mode selector removed from day plan
- CustomSelect supports grouped headers (isHeader option)
- Optimistic updates for day notes (instant feedback)
- Booking cards redesigned with type-colored headers and structured details
Weather:
- Wind speed in mph when using Fahrenheit setting
- Weather description language matches app language
Admin:
- Weather info panel replaces OpenWeatherMap key input
- "Recommended" badge styling updated
2026-03-25 03:10:45 +08:00
|
|
|
<p className="text-slate-500 text-sm">{t('common.loading')}</p>
|
2026-03-19 06:58:08 +08:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!isAuthenticated) {
|
|
|
|
|
return <Navigate to="/login" replace />
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-31 04:42:40 +08:00
|
|
|
if (
|
|
|
|
|
appRequireMfa &&
|
|
|
|
|
user &&
|
|
|
|
|
!user.mfa_enabled &&
|
|
|
|
|
location.pathname !== '/settings'
|
|
|
|
|
) {
|
|
|
|
|
return <Navigate to="/settings?mfa=required" replace />
|
|
|
|
|
}
|
|
|
|
|
|
v2.5.0 — Addon System, Vacay, Atlas, Dashboard Widgets & Mobile Overhaul
The biggest NOMAD update yet. Introduces a modular addon architecture and three major new features.
Addon System:
- Admin panel addon management with enable/disable toggles
- Trip addons (Packing List, Budget, Documents) dynamically show/hide in trip tabs
- Global addons appear in the main navigation for all users
Vacay — Vacation Day Planner (Global Addon):
- Monthly calendar view with international public holidays (100+ countries via Nager.Date API)
- Company holidays with auto-cleanup of conflicting entries
- User-based system: each NOMAD user is a person in the calendar
- Fusion system: invite other users to share a combined calendar with real-time WebSocket sync
- Vacation entitlement tracking with automatic carry-over to next year
- Full settings: block weekends, public holidays, company holidays, carry-over toggle
- Invite/accept/decline flow with forced confirmation modal
- Color management per user with collision detection on fusion
- Dissolve fusion with preserved entries
Atlas — Travel World Map (Global Addon):
- Fullscreen Leaflet world map with colored country polygons (GeoJSON)
- Glass-effect bottom panel with stats, continent breakdown, streak tracking
- Country tooltips with trip count, places visited, first/last visit dates
- Liquid glass hover effect on the stats panel
- Canvas renderer with tile preloading for maximum performance
- Responsive: mobile stats bars, no zoom controls on touch
Dashboard Widgets:
- Currency converter with 50 currencies, CustomSelect dropdowns, localStorage persistence
- Timezone widget with customizable city list, live updating clock
- Per-user toggle via settings button, bottom sheet on mobile
Admin Panel:
- Consistent dark mode across all tabs (CSS variable overrides)
- Online/offline status badges on user list via WebSocket
- Unified heading sizes and subtitles across all sections
- Responsive tab grid on mobile
Mobile Improvements:
- Vacay: slide-in sidebar drawer, floating toolbar, responsive calendar grid
- Atlas: top/bottom glass stat bars, no popups
- Trip Planner: fixed position content container prevents overscroll, portal-based sidebar buttons
- Dashboard: fixed viewport container, mobile widget bottom sheet
- Admin: responsive tab grid, compact buttons
- Global: overscroll-behavior fixes, modal scroll containment
Other:
- Trip tab labels: Planung→Karte, Packliste→Liste, Buchungen→Buchung (DE mobile)
- Reservation form responsive layout
- Backup panel responsive buttons
2026-03-21 06:14:06 +08:00
|
|
|
if (adminRequired && user && user.role !== 'admin') {
|
2026-03-19 06:58:08 +08:00
|
|
|
return <Navigate to="/dashboard" replace />
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-28 01:40:18 +08:00
|
|
|
return <>{children}</>
|
2026-03-19 06:58:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function RootRedirect() {
|
|
|
|
|
const { isAuthenticated, isLoading } = useAuthStore()
|
|
|
|
|
|
|
|
|
|
if (isLoading) {
|
|
|
|
|
return (
|
|
|
|
|
<div className="min-h-screen flex items-center justify-center bg-slate-50">
|
|
|
|
|
<div className="w-10 h-10 border-4 border-slate-200 border-t-slate-900 rounded-full animate-spin"></div>
|
|
|
|
|
</div>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return <Navigate to={isAuthenticated ? '/dashboard' : '/login'} replace />
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default function App() {
|
2026-03-31 04:42:40 +08:00
|
|
|
const { loadUser, token, isAuthenticated, demoMode, setDemoMode, setHasMapsKey, setServerTimezone, setAppRequireMfa } = useAuthStore()
|
2026-03-19 06:58:08 +08:00
|
|
|
const { loadSettings } = useSettingsStore()
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (token) {
|
|
|
|
|
loadUser()
|
|
|
|
|
}
|
2026-03-31 04:42:40 +08:00
|
|
|
authApi.getAppConfig().then(async (config: { demo_mode?: boolean; has_maps_key?: boolean; version?: string; timezone?: string; require_mfa?: boolean }) => {
|
2026-03-19 21:09:12 +08:00
|
|
|
if (config?.demo_mode) setDemoMode(true)
|
2026-03-20 06:49:07 +08:00
|
|
|
if (config?.has_maps_key !== undefined) setHasMapsKey(config.has_maps_key)
|
2026-03-30 17:24:02 +08:00
|
|
|
if (config?.timezone) setServerTimezone(config.timezone)
|
2026-03-31 04:42:40 +08:00
|
|
|
if (config?.require_mfa !== undefined) setAppRequireMfa(!!config.require_mfa)
|
2026-03-30 16:26:23 +08:00
|
|
|
|
|
|
|
|
if (config?.version) {
|
|
|
|
|
const storedVersion = localStorage.getItem('trek_app_version')
|
|
|
|
|
if (storedVersion && storedVersion !== config.version) {
|
|
|
|
|
try {
|
|
|
|
|
if ('caches' in window) {
|
|
|
|
|
const names = await caches.keys()
|
|
|
|
|
await Promise.all(names.map(n => caches.delete(n)))
|
|
|
|
|
}
|
|
|
|
|
if ('serviceWorker' in navigator) {
|
|
|
|
|
const regs = await navigator.serviceWorker.getRegistrations()
|
|
|
|
|
await Promise.all(regs.map(r => r.unregister()))
|
|
|
|
|
}
|
|
|
|
|
} catch {}
|
|
|
|
|
localStorage.setItem('trek_app_version', config.version)
|
|
|
|
|
window.location.reload()
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
localStorage.setItem('trek_app_version', config.version)
|
|
|
|
|
}
|
2026-03-19 21:09:12 +08:00
|
|
|
}).catch(() => {})
|
2026-03-19 06:58:08 +08:00
|
|
|
}, [])
|
|
|
|
|
|
|
|
|
|
const { settings } = useSettingsStore()
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (isAuthenticated) {
|
|
|
|
|
loadSettings()
|
|
|
|
|
}
|
|
|
|
|
}, [isAuthenticated])
|
|
|
|
|
|
2026-03-31 04:32:58 +08:00
|
|
|
const location = useLocation()
|
|
|
|
|
const isSharedPage = location.pathname.startsWith('/shared/')
|
|
|
|
|
|
2026-03-19 06:58:08 +08:00
|
|
|
useEffect(() => {
|
2026-03-31 04:32:58 +08:00
|
|
|
// Shared page always forces light mode
|
|
|
|
|
if (isSharedPage) {
|
|
|
|
|
document.documentElement.classList.remove('dark')
|
|
|
|
|
const meta = document.querySelector('meta[name="theme-color"]')
|
|
|
|
|
if (meta) meta.setAttribute('content', '#ffffff')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
v2.5.7: Reservation overhaul, Day Detail Panel, i18n, paste support, auto dark mode
BREAKING: Reservations have been completely rebuilt. Existing place-level
reservations are no longer used. All reservations must be re-created via
the Bookings tab. Your trips, places, and other data are unaffected.
Reservation System (rebuilt from scratch):
- Reservations now link to specific day assignments instead of places
- Same place on different days can have independent reservations
- New assignment picker in booking modal (grouped by day, searchable)
- Removed day/place dropdowns from booking form
- Reservation badges in day plan sidebar with type-specific icons
- Reservation details in place inspector (only for selected assignment)
- Reservation summary in day detail panel
Day Detail Panel (new):
- Opens on day click in the sidebar
- Detailed weather: hourly forecast, precipitation, wind, sunrise/sunset
- Historical climate averages for dates beyond 16 days
- Accommodation management with check-in/check-out, confirmation number
- Hotel assignment across multiple days with day range picker
- Reservation overview for the day
Places:
- Places can now be assigned to the same day multiple times
- Start time + end time fields (replaces single time field)
- Map badges show multiple position numbers (e.g. "1 · 4")
- Route optimization fixed for duplicate places
- File attachments during place editing (not just creation)
- Cover image upload during trip creation (not just editing)
- Paste support (Ctrl+V) for images in trip, place, and file forms
Internationalization:
- 200+ hardcoded German strings translated to i18n (EN + DE)
- Server error messages in English
- Category seeds in English for new installations
- All planner, register, photo, packing components translated
UI/UX:
- Auto dark mode (follows system preference, configurable in settings)
- Navbar toggle switches light/dark (overrides auto)
- Sidebar minimize buttons z-index fixed
- Transport mode selector removed from day plan
- CustomSelect supports grouped headers (isHeader option)
- Optimistic updates for day notes (instant feedback)
- Booking cards redesigned with type-colored headers and structured details
Weather:
- Wind speed in mph when using Fahrenheit setting
- Weather description language matches app language
Admin:
- Weather info panel replaces OpenWeatherMap key input
- "Recommended" badge styling updated
2026-03-25 03:10:45 +08:00
|
|
|
const mode = settings.dark_mode
|
2026-03-28 01:40:18 +08:00
|
|
|
const applyDark = (isDark: boolean) => {
|
v2.5.7: Reservation overhaul, Day Detail Panel, i18n, paste support, auto dark mode
BREAKING: Reservations have been completely rebuilt. Existing place-level
reservations are no longer used. All reservations must be re-created via
the Bookings tab. Your trips, places, and other data are unaffected.
Reservation System (rebuilt from scratch):
- Reservations now link to specific day assignments instead of places
- Same place on different days can have independent reservations
- New assignment picker in booking modal (grouped by day, searchable)
- Removed day/place dropdowns from booking form
- Reservation badges in day plan sidebar with type-specific icons
- Reservation details in place inspector (only for selected assignment)
- Reservation summary in day detail panel
Day Detail Panel (new):
- Opens on day click in the sidebar
- Detailed weather: hourly forecast, precipitation, wind, sunrise/sunset
- Historical climate averages for dates beyond 16 days
- Accommodation management with check-in/check-out, confirmation number
- Hotel assignment across multiple days with day range picker
- Reservation overview for the day
Places:
- Places can now be assigned to the same day multiple times
- Start time + end time fields (replaces single time field)
- Map badges show multiple position numbers (e.g. "1 · 4")
- Route optimization fixed for duplicate places
- File attachments during place editing (not just creation)
- Cover image upload during trip creation (not just editing)
- Paste support (Ctrl+V) for images in trip, place, and file forms
Internationalization:
- 200+ hardcoded German strings translated to i18n (EN + DE)
- Server error messages in English
- Category seeds in English for new installations
- All planner, register, photo, packing components translated
UI/UX:
- Auto dark mode (follows system preference, configurable in settings)
- Navbar toggle switches light/dark (overrides auto)
- Sidebar minimize buttons z-index fixed
- Transport mode selector removed from day plan
- CustomSelect supports grouped headers (isHeader option)
- Optimistic updates for day notes (instant feedback)
- Booking cards redesigned with type-colored headers and structured details
Weather:
- Wind speed in mph when using Fahrenheit setting
- Weather description language matches app language
Admin:
- Weather info panel replaces OpenWeatherMap key input
- "Recommended" badge styling updated
2026-03-25 03:10:45 +08:00
|
|
|
document.documentElement.classList.toggle('dark', isDark)
|
|
|
|
|
const meta = document.querySelector('meta[name="theme-color"]')
|
|
|
|
|
if (meta) meta.setAttribute('content', isDark ? '#09090b' : '#ffffff')
|
2026-03-19 06:58:08 +08:00
|
|
|
}
|
v2.5.7: Reservation overhaul, Day Detail Panel, i18n, paste support, auto dark mode
BREAKING: Reservations have been completely rebuilt. Existing place-level
reservations are no longer used. All reservations must be re-created via
the Bookings tab. Your trips, places, and other data are unaffected.
Reservation System (rebuilt from scratch):
- Reservations now link to specific day assignments instead of places
- Same place on different days can have independent reservations
- New assignment picker in booking modal (grouped by day, searchable)
- Removed day/place dropdowns from booking form
- Reservation badges in day plan sidebar with type-specific icons
- Reservation details in place inspector (only for selected assignment)
- Reservation summary in day detail panel
Day Detail Panel (new):
- Opens on day click in the sidebar
- Detailed weather: hourly forecast, precipitation, wind, sunrise/sunset
- Historical climate averages for dates beyond 16 days
- Accommodation management with check-in/check-out, confirmation number
- Hotel assignment across multiple days with day range picker
- Reservation overview for the day
Places:
- Places can now be assigned to the same day multiple times
- Start time + end time fields (replaces single time field)
- Map badges show multiple position numbers (e.g. "1 · 4")
- Route optimization fixed for duplicate places
- File attachments during place editing (not just creation)
- Cover image upload during trip creation (not just editing)
- Paste support (Ctrl+V) for images in trip, place, and file forms
Internationalization:
- 200+ hardcoded German strings translated to i18n (EN + DE)
- Server error messages in English
- Category seeds in English for new installations
- All planner, register, photo, packing components translated
UI/UX:
- Auto dark mode (follows system preference, configurable in settings)
- Navbar toggle switches light/dark (overrides auto)
- Sidebar minimize buttons z-index fixed
- Transport mode selector removed from day plan
- CustomSelect supports grouped headers (isHeader option)
- Optimistic updates for day notes (instant feedback)
- Booking cards redesigned with type-colored headers and structured details
Weather:
- Wind speed in mph when using Fahrenheit setting
- Weather description language matches app language
Admin:
- Weather info panel replaces OpenWeatherMap key input
- "Recommended" badge styling updated
2026-03-25 03:10:45 +08:00
|
|
|
|
|
|
|
|
if (mode === 'auto') {
|
|
|
|
|
const mq = window.matchMedia('(prefers-color-scheme: dark)')
|
|
|
|
|
applyDark(mq.matches)
|
2026-03-28 01:40:18 +08:00
|
|
|
const handler = (e: MediaQueryListEvent) => applyDark(e.matches)
|
v2.5.7: Reservation overhaul, Day Detail Panel, i18n, paste support, auto dark mode
BREAKING: Reservations have been completely rebuilt. Existing place-level
reservations are no longer used. All reservations must be re-created via
the Bookings tab. Your trips, places, and other data are unaffected.
Reservation System (rebuilt from scratch):
- Reservations now link to specific day assignments instead of places
- Same place on different days can have independent reservations
- New assignment picker in booking modal (grouped by day, searchable)
- Removed day/place dropdowns from booking form
- Reservation badges in day plan sidebar with type-specific icons
- Reservation details in place inspector (only for selected assignment)
- Reservation summary in day detail panel
Day Detail Panel (new):
- Opens on day click in the sidebar
- Detailed weather: hourly forecast, precipitation, wind, sunrise/sunset
- Historical climate averages for dates beyond 16 days
- Accommodation management with check-in/check-out, confirmation number
- Hotel assignment across multiple days with day range picker
- Reservation overview for the day
Places:
- Places can now be assigned to the same day multiple times
- Start time + end time fields (replaces single time field)
- Map badges show multiple position numbers (e.g. "1 · 4")
- Route optimization fixed for duplicate places
- File attachments during place editing (not just creation)
- Cover image upload during trip creation (not just editing)
- Paste support (Ctrl+V) for images in trip, place, and file forms
Internationalization:
- 200+ hardcoded German strings translated to i18n (EN + DE)
- Server error messages in English
- Category seeds in English for new installations
- All planner, register, photo, packing components translated
UI/UX:
- Auto dark mode (follows system preference, configurable in settings)
- Navbar toggle switches light/dark (overrides auto)
- Sidebar minimize buttons z-index fixed
- Transport mode selector removed from day plan
- CustomSelect supports grouped headers (isHeader option)
- Optimistic updates for day notes (instant feedback)
- Booking cards redesigned with type-colored headers and structured details
Weather:
- Wind speed in mph when using Fahrenheit setting
- Weather description language matches app language
Admin:
- Weather info panel replaces OpenWeatherMap key input
- "Recommended" badge styling updated
2026-03-25 03:10:45 +08:00
|
|
|
mq.addEventListener('change', handler)
|
|
|
|
|
return () => mq.removeEventListener('change', handler)
|
2026-03-22 05:21:23 +08:00
|
|
|
}
|
v2.5.7: Reservation overhaul, Day Detail Panel, i18n, paste support, auto dark mode
BREAKING: Reservations have been completely rebuilt. Existing place-level
reservations are no longer used. All reservations must be re-created via
the Bookings tab. Your trips, places, and other data are unaffected.
Reservation System (rebuilt from scratch):
- Reservations now link to specific day assignments instead of places
- Same place on different days can have independent reservations
- New assignment picker in booking modal (grouped by day, searchable)
- Removed day/place dropdowns from booking form
- Reservation badges in day plan sidebar with type-specific icons
- Reservation details in place inspector (only for selected assignment)
- Reservation summary in day detail panel
Day Detail Panel (new):
- Opens on day click in the sidebar
- Detailed weather: hourly forecast, precipitation, wind, sunrise/sunset
- Historical climate averages for dates beyond 16 days
- Accommodation management with check-in/check-out, confirmation number
- Hotel assignment across multiple days with day range picker
- Reservation overview for the day
Places:
- Places can now be assigned to the same day multiple times
- Start time + end time fields (replaces single time field)
- Map badges show multiple position numbers (e.g. "1 · 4")
- Route optimization fixed for duplicate places
- File attachments during place editing (not just creation)
- Cover image upload during trip creation (not just editing)
- Paste support (Ctrl+V) for images in trip, place, and file forms
Internationalization:
- 200+ hardcoded German strings translated to i18n (EN + DE)
- Server error messages in English
- Category seeds in English for new installations
- All planner, register, photo, packing components translated
UI/UX:
- Auto dark mode (follows system preference, configurable in settings)
- Navbar toggle switches light/dark (overrides auto)
- Sidebar minimize buttons z-index fixed
- Transport mode selector removed from day plan
- CustomSelect supports grouped headers (isHeader option)
- Optimistic updates for day notes (instant feedback)
- Booking cards redesigned with type-colored headers and structured details
Weather:
- Wind speed in mph when using Fahrenheit setting
- Weather description language matches app language
Admin:
- Weather info panel replaces OpenWeatherMap key input
- "Recommended" badge styling updated
2026-03-25 03:10:45 +08:00
|
|
|
applyDark(mode === true || mode === 'dark')
|
2026-03-31 04:32:58 +08:00
|
|
|
}, [settings.dark_mode, isSharedPage])
|
2026-03-19 06:58:08 +08:00
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<TranslationProvider>
|
|
|
|
|
<ToastContainer />
|
|
|
|
|
<Routes>
|
|
|
|
|
<Route path="/" element={<RootRedirect />} />
|
|
|
|
|
<Route path="/login" element={<LoginPage />} />
|
feat: public read-only share links with permissions — closes #79
Share links:
- Generate a public link in the trip share modal
- Choose what to share: Map & Plan, Bookings, Packing, Budget, Chat
- Permissions enforced server-side
- Delete link to revoke access instantly
Shared trip page (/shared/:token):
- Read-only view with TREK logo, cover image, trip details
- Tabbed navigation with Lucide icons (responsive on mobile)
- Interactive map with auto-fit bounds per day
- Day plan, Bookings, Packing, Budget, Chat views
- Language picker, TREK branding footer
Technical:
- share_tokens DB table with per-field permissions
- Public GET /shared/:token endpoint (no auth)
- Two-column share modal (max-w-5xl)
2026-03-31 00:02:53 +08:00
|
|
|
<Route path="/shared/:token" element={<SharedTripPage />} />
|
2026-03-29 18:49:15 +08:00
|
|
|
<Route path="/register" element={<LoginPage />} />
|
2026-03-19 06:58:08 +08:00
|
|
|
<Route
|
|
|
|
|
path="/dashboard"
|
|
|
|
|
element={
|
|
|
|
|
<ProtectedRoute>
|
|
|
|
|
<DashboardPage />
|
|
|
|
|
</ProtectedRoute>
|
|
|
|
|
}
|
|
|
|
|
/>
|
|
|
|
|
<Route
|
|
|
|
|
path="/trips/:id"
|
|
|
|
|
element={
|
|
|
|
|
<ProtectedRoute>
|
|
|
|
|
<TripPlannerPage />
|
|
|
|
|
</ProtectedRoute>
|
|
|
|
|
}
|
|
|
|
|
/>
|
|
|
|
|
<Route
|
|
|
|
|
path="/trips/:id/files"
|
|
|
|
|
element={
|
|
|
|
|
<ProtectedRoute>
|
|
|
|
|
<FilesPage />
|
|
|
|
|
</ProtectedRoute>
|
|
|
|
|
}
|
|
|
|
|
/>
|
|
|
|
|
<Route
|
|
|
|
|
path="/admin"
|
|
|
|
|
element={
|
|
|
|
|
<ProtectedRoute adminRequired>
|
|
|
|
|
<AdminPage />
|
|
|
|
|
</ProtectedRoute>
|
|
|
|
|
}
|
|
|
|
|
/>
|
|
|
|
|
<Route
|
|
|
|
|
path="/settings"
|
|
|
|
|
element={
|
|
|
|
|
<ProtectedRoute>
|
|
|
|
|
<SettingsPage />
|
|
|
|
|
</ProtectedRoute>
|
|
|
|
|
}
|
|
|
|
|
/>
|
v2.5.0 — Addon System, Vacay, Atlas, Dashboard Widgets & Mobile Overhaul
The biggest NOMAD update yet. Introduces a modular addon architecture and three major new features.
Addon System:
- Admin panel addon management with enable/disable toggles
- Trip addons (Packing List, Budget, Documents) dynamically show/hide in trip tabs
- Global addons appear in the main navigation for all users
Vacay — Vacation Day Planner (Global Addon):
- Monthly calendar view with international public holidays (100+ countries via Nager.Date API)
- Company holidays with auto-cleanup of conflicting entries
- User-based system: each NOMAD user is a person in the calendar
- Fusion system: invite other users to share a combined calendar with real-time WebSocket sync
- Vacation entitlement tracking with automatic carry-over to next year
- Full settings: block weekends, public holidays, company holidays, carry-over toggle
- Invite/accept/decline flow with forced confirmation modal
- Color management per user with collision detection on fusion
- Dissolve fusion with preserved entries
Atlas — Travel World Map (Global Addon):
- Fullscreen Leaflet world map with colored country polygons (GeoJSON)
- Glass-effect bottom panel with stats, continent breakdown, streak tracking
- Country tooltips with trip count, places visited, first/last visit dates
- Liquid glass hover effect on the stats panel
- Canvas renderer with tile preloading for maximum performance
- Responsive: mobile stats bars, no zoom controls on touch
Dashboard Widgets:
- Currency converter with 50 currencies, CustomSelect dropdowns, localStorage persistence
- Timezone widget with customizable city list, live updating clock
- Per-user toggle via settings button, bottom sheet on mobile
Admin Panel:
- Consistent dark mode across all tabs (CSS variable overrides)
- Online/offline status badges on user list via WebSocket
- Unified heading sizes and subtitles across all sections
- Responsive tab grid on mobile
Mobile Improvements:
- Vacay: slide-in sidebar drawer, floating toolbar, responsive calendar grid
- Atlas: top/bottom glass stat bars, no popups
- Trip Planner: fixed position content container prevents overscroll, portal-based sidebar buttons
- Dashboard: fixed viewport container, mobile widget bottom sheet
- Admin: responsive tab grid, compact buttons
- Global: overscroll-behavior fixes, modal scroll containment
Other:
- Trip tab labels: Planung→Karte, Packliste→Liste, Buchungen→Buchung (DE mobile)
- Reservation form responsive layout
- Backup panel responsive buttons
2026-03-21 06:14:06 +08:00
|
|
|
<Route
|
|
|
|
|
path="/vacay"
|
|
|
|
|
element={
|
|
|
|
|
<ProtectedRoute>
|
|
|
|
|
<VacayPage />
|
|
|
|
|
</ProtectedRoute>
|
|
|
|
|
}
|
|
|
|
|
/>
|
|
|
|
|
<Route
|
|
|
|
|
path="/atlas"
|
|
|
|
|
element={
|
|
|
|
|
<ProtectedRoute>
|
|
|
|
|
<AtlasPage />
|
|
|
|
|
</ProtectedRoute>
|
|
|
|
|
}
|
|
|
|
|
/>
|
2026-03-19 06:58:08 +08:00
|
|
|
<Route path="*" element={<Navigate to="/" replace />} />
|
|
|
|
|
</Routes>
|
|
|
|
|
</TranslationProvider>
|
|
|
|
|
)
|
|
|
|
|
}
|