From f6193bf1801162890c48ca26be5fb5a15a117fbb Mon Sep 17 00:00:00 2001 From: dtoro Date: Mon, 16 Mar 2026 09:30:11 +0100 Subject: [PATCH] freat: initroduce katalogos --- .../app/recollections/FlippingCardView.tsx | 27 ------ .../app/recollections/RecollectionLayout.tsx | 7 +- .../RecollectionViewSwitcher.tsx | 92 +++++++++++++------ .../recollections/katalogos/KatalogosPage.tsx | 31 +++++++ frontend/src/main.tsx | 8 +- 5 files changed, 105 insertions(+), 60 deletions(-) delete mode 100644 frontend/src/app/recollections/FlippingCardView.tsx create mode 100644 frontend/src/app/recollections/katalogos/KatalogosPage.tsx diff --git a/frontend/src/app/recollections/FlippingCardView.tsx b/frontend/src/app/recollections/FlippingCardView.tsx deleted file mode 100644 index 37d9c47..0000000 --- a/frontend/src/app/recollections/FlippingCardView.tsx +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Recollection view switcher: Logos or Flux based on pathname. - * Single container, conditional render — only the active view is mounted (no CSS flip). - */ - -import React from 'react' -import { useLocation, useParams } from 'react-router-dom' -import { LogosPage } from './logos/LogosPage' -import { FluxRoute } from './flux/FluxRoute' - -export function FlippingCardView() { - const { pathname } = useLocation() - const { recollectionId } = useParams<{ recollectionId: string }>() - const isFlux = pathname.endsWith('/flux') - - return ( -
- {isFlux ? ( - recollectionId ? ( - - ) : null - ) : ( - - )} -
- ) -} diff --git a/frontend/src/app/recollections/RecollectionLayout.tsx b/frontend/src/app/recollections/RecollectionLayout.tsx index bbbe184..ca0868c 100644 --- a/frontend/src/app/recollections/RecollectionLayout.tsx +++ b/frontend/src/app/recollections/RecollectionLayout.tsx @@ -1,15 +1,14 @@ /** - * Layout for a single recollection: shared menubar and flipping card (Logos front / Flux back). + * Layout for a single recollection: shared menubar and nested routes for Logos / Katalogos / Flux. */ import React, { useEffect } from 'react' -import { Link, useParams } from 'react-router-dom' +import { Link, Outlet, useParams } from 'react-router-dom' import { usePlatform } from '@/app/kosmos/KosmosContext' import { RecollectionMenubarProvider } from './RecollectionMenubarContext' import { RecollectionActionsProvider } from './RecollectionActionsContext' import { RecollectionTitleContent } from './RecollectionTitleContent' import { RecollectionMenubar } from './RecollectionMenubar' -import { FlippingCardView } from './FlippingCardView' export function RecollectionLayout() { const { recollectionId } = useParams<{ recollectionId: string }>() @@ -40,7 +39,7 @@ export function RecollectionLayout() {
- +
diff --git a/frontend/src/app/recollections/RecollectionViewSwitcher.tsx b/frontend/src/app/recollections/RecollectionViewSwitcher.tsx index e22f4ae..6895782 100644 --- a/frontend/src/app/recollections/RecollectionViewSwitcher.tsx +++ b/frontend/src/app/recollections/RecollectionViewSwitcher.tsx @@ -5,21 +5,12 @@ import React, { useCallback, useEffect } from 'react' import { useLocation, useNavigate, useParams } from 'react-router-dom' -import { FluxIcon, LogosIcon } from '@/lib/icons' +import { FluxIcon, LogosIcon, RecollectionsIcon } from '@/lib/icons' import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip' -const VIEW_TOGGLE_KEYS = { key: 'v', shiftKey: true } - -function matchKey(ev: KeyboardEvent, want: { key: string; shiftKey: boolean }) { - const mod = ev.ctrlKey || ev.metaKey - return ev.key.toLowerCase() === want.key && !!mod && ev.shiftKey === want.shiftKey -} - function shortcutLabel() { - if (typeof navigator !== 'undefined' && /Mac|iPod|iPhone|iPad/.test(navigator.platform)) { - return '⌘⇧V' - } - return 'Ctrl+Shift+V' + const isMac = typeof navigator !== 'undefined' && /Mac|iPod|iPhone|iPad/.test(navigator.platform) + return isMac ? '⌘⇧↑ / ⌘⇧↓' : 'Ctrl+Shift+↑ / Ctrl+Shift+↓' } export function RecollectionViewSwitcher() { @@ -28,30 +19,53 @@ export function RecollectionViewSwitcher() { const navigate = useNavigate() const base = recollectionId ? `/recollections/${recollectionId}` : '' - const isFlux = pathname.endsWith('/flux') + type Mode = 'logos' | 'katalogos' | 'flux' + const mode: Mode = pathname.endsWith('/flux') + ? 'flux' + : pathname.endsWith('/katalogos') + ? 'katalogos' + : 'logos' + + const goRelative = useCallback( + (delta: 1 | -1) => { + if (!base) return + const order: Mode[] = ['logos', 'katalogos', 'flux'] + const currentIndex = order.indexOf(mode) + const nextMode = order[(currentIndex + (delta === 1 ? 1 : order.length - 1)) % order.length] + navigate(`${base}/${nextMode}`) + }, + [base, mode, navigate] + ) const toggle = useCallback(() => { - if (!base) return - navigate(isFlux ? `${base}/logos` : `${base}/flux`) - }, [base, isFlux, navigate]) + goRelative(1) + }, [goRelative]) useEffect(() => { const onKeyDown = (ev: KeyboardEvent) => { - if (matchKey(ev, VIEW_TOGGLE_KEYS)) { - ev.preventDefault() - toggle() + const isMod = ev.ctrlKey || ev.metaKey + const isShortcut = isMod && ev.shiftKey && (ev.key === 'ArrowDown' || ev.key === 'ArrowUp') + if (!isShortcut) return + ev.preventDefault() + if (ev.key === 'ArrowDown') { + goRelative(1) + } else if (ev.key === 'ArrowUp') { + goRelative(-1) } } window.addEventListener('keydown', onKeyDown, true) return () => window.removeEventListener('keydown', onKeyDown, true) - }, [toggle]) + }, [goRelative]) if (!base) return null const shortcut = shortcutLabel() - const tooltipText = isFlux - ? `Flux · Switch to Logos (${shortcut})` - : `Logos · Switch to Flux (${shortcut})` + const tooltipText = + mode === 'logos' + ? `Logos · Next: Katalogos (${shortcut})` + : mode === 'katalogos' + ? `Katalogos · Next: Flux (${shortcut})` + : `Flux · Next: Logos (${shortcut})` return (
@@ -61,20 +75,34 @@ export function RecollectionViewSwitcher() {