diff --git a/client/src/App.tsx b/client/src/App.tsx index aabef14..34f8748 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -30,6 +30,7 @@ import PendingPayments from './components/PendingPayments'; import { useEasterEgg } from './context/eggs'; import { ClientData, Food, MealSlot, PendingQr, PizzaOrder, DepartureTime, PizzaDayState, Restaurant, RestaurantDayMenu, RestaurantDayMenuMap, LunchChoice, LocationLunchChoicesMap, UserLunchChoice, PizzaVariant, getData, getEasterEggImage, addPizza, removePizza, updatePizzaDayNote, createPizzaDay, deletePizzaDay, lockPizzaDay, unlockPizzaDay, finishOrder, finishDelivery, addChoice, jdemeObed, removeChoices, removeChoice, updateNote, changeDepartureTime, setBuyer, generateQr } from '../../types'; import { getLunchChoiceName } from './enums'; +import { isArrowNavigationBlocked } from './utils/arrowNavigation'; // import FallingLeaves, { LEAF_PRESETS, LEAF_COLOR_THEMES } from './FallingLeaves'; // import './FallingLeaves.scss'; @@ -244,6 +245,7 @@ function App() { // Navigace mezi dny pomocí klávesových šípek const handleKeyDown = useCallback((e: any) => { + if (isArrowNavigationBlocked(e)) return; if (e.keyCode === 37 && dayIndex != null && dayIndex > 0) { handleDayChange(dayIndex - 1); } else if (e.keyCode === 39 && dayIndex != null && dayIndex < 4) { diff --git a/client/src/pages/OrderGroupsPage.tsx b/client/src/pages/OrderGroupsPage.tsx index 0f42456..2e2a96e 100644 --- a/client/src/pages/OrderGroupsPage.tsx +++ b/client/src/pages/OrderGroupsPage.tsx @@ -30,6 +30,7 @@ import BoltSimulationModal from '../components/modals/BoltSimulationModal'; import GenerateMockOrdersModal from '../components/modals/GenerateMockOrdersModal'; import PendingPayments from '../components/PendingPayments'; import OrderProgress, { PROVIDER_LABEL } from '../components/OrderProgress'; +import { isArrowNavigationBlocked } from '../utils/arrowNavigation'; const SLOT = MealSlot.EXTRA; const TIME_REGEX = /^([01]\d|2[0-3]):[0-5]\d$/; @@ -224,9 +225,8 @@ export default function OrderGroupsPage() { // Navigace mezi dny pomocí klávesových šipek (←/→), obdobně jako na hlavní stránce const handleKeyDown = useCallback((e: KeyboardEvent) => { - // Ignorujeme, pokud uživatel právě píše do formulářového pole - const tag = (e.target as HTMLElement)?.tagName; - if (tag === 'INPUT' || tag === 'SELECT' || tag === 'TEXTAREA') return; + // Ignorujeme, pokud uživatel právě píše do formulářového pole nebo je otevřený dialog (např. minihra) + if (isArrowNavigationBlocked(e)) return; const currentIso = data?.isoDate; if (!currentIso) return; if (e.keyCode === 37) { diff --git a/client/src/pages/StatsPage.tsx b/client/src/pages/StatsPage.tsx index 6049257..26ade79 100644 --- a/client/src/pages/StatsPage.tsx +++ b/client/src/pages/StatsPage.tsx @@ -12,6 +12,7 @@ import { Legend, Line, LineChart, Tooltip, XAxis, YAxis } from "recharts"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { getLunchChoiceName } from "../enums"; import './StatsPage.scss'; +import { isArrowNavigationBlocked } from '../utils/arrowNavigation'; const CHART_WIDTH = 1400; const CHART_HEIGHT = 700; @@ -131,6 +132,7 @@ export default function StatsPage() { }, [dateRange]); const handleKeyDown = useCallback((e: any) => { + if (isArrowNavigationBlocked(e)) return; if (e.keyCode === 37) { handlePreviousWeek(); } else if (e.keyCode === 39 && !isCurrentOrFutureWeek) { diff --git a/client/src/utils/arrowNavigation.ts b/client/src/utils/arrowNavigation.ts new file mode 100644 index 0000000..e74e66b --- /dev/null +++ b/client/src/utils/arrowNavigation.ts @@ -0,0 +1,11 @@ +/** + * Zda se má stisk klávesy ignorovat pro navigaci šipkami mezi dny/týdny na pozadí stránky. + * Navigace se nemá provádět, pokud uživatel píše do formulářového pole, nebo pokud je otevřený + * modální dialog (typicky minihra jako Tetris či Had, která šipky používá k ovládání) – + * jinak by se stránka na pozadí neustále přepínala a zbytečně přenačítala data ze serveru. + */ +export function isArrowNavigationBlocked(e: KeyboardEvent): boolean { + const target = e.target as HTMLElement | null; + if (target?.closest?.('input, textarea, select, [contenteditable="true"]')) return true; + return document.body.classList.contains('modal-open') || document.querySelector('.modal.show') != null; +} diff --git a/server/changelogs/2026-10-19.json b/server/changelogs/2026-10-19.json index 2c3783d..633bd79 100644 --- a/server/changelogs/2026-10-19.json +++ b/server/changelogs/2026-10-19.json @@ -1,3 +1,4 @@ [ - "Nové nastavení: po založení skupinové objednávky nebo připojení k ní se vaše dnešní volba automaticky přepne na \"Budu objednávat\"" + "Nové nastavení: po založení skupinové objednávky nebo připojení k ní se vaše dnešní volba automaticky přepne na \"Budu objednávat\"", + "Ovládání miniher šipkami už na pozadí nepřepíná dny ani týdny" ]