@mytec: iteration1 implemented

This commit is contained in:
2026-01-30 08:23:29 +02:00
parent f59e63f181
commit 6bc4357a3c
17 changed files with 566 additions and 187 deletions

View File

@@ -0,0 +1,61 @@
import { useEffect } from 'react';
import { useSitesStore } from '@/store/sites.ts';
import { useCoverageStore } from '@/store/coverage.ts';
import { useToastStore } from '@/components/ui/Toast.tsx';
interface ShortcutHandlers {
onCalculate: () => void;
onCloseForm: () => void;
}
export function useKeyboardShortcuts({ onCalculate, onCloseForm }: ShortcutHandlers) {
useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => {
// Ignore if typing in input or textarea
if (
e.target instanceof HTMLInputElement ||
e.target instanceof HTMLTextAreaElement ||
e.target instanceof HTMLSelectElement
) {
return;
}
const isMac = navigator.platform.toLowerCase().includes('mac');
const modKey = isMac ? e.metaKey : e.ctrlKey;
if (modKey) {
switch (e.key.toLowerCase()) {
case 'enter': // Ctrl/Cmd+Enter: Calculate coverage
e.preventDefault();
onCalculate();
break;
case 'n': // Ctrl/Cmd+N: New site (enter placement mode)
e.preventDefault();
useSitesStore.getState().setPlacingMode(true);
useToastStore.getState().addToast('Click on map to place new site', 'info');
break;
}
}
// Non-modifier shortcuts
switch (e.key) {
case 'Escape': // Escape: Cancel/close
useSitesStore.getState().selectSite(null);
useSitesStore.getState().setPlacingMode(false);
onCloseForm();
break;
case 'h': // H: Toggle heatmap
case 'H':
if (!e.ctrlKey && !e.metaKey && !e.altKey) {
useCoverageStore.getState().toggleHeatmap();
}
break;
}
};
window.addEventListener('keydown', handleKeyDown);
return () => window.removeEventListener('keydown', handleKeyDown);
}, [onCalculate, onCloseForm]);
}