mirror of
https://github.com/R0m1k3/noteflow.git
synced 2026-10-11 17:29:37 +02:00
Keyboard Shortcuts: - Create useKeyboardShortcuts hook with configurable shortcuts - Support Ctrl/Cmd, Alt, Shift modifiers - Add 7 global shortcuts (New note, Search, Quick capture, etc.) - Create KeyboardShortcutsHelp modal with categorized shortcuts - Show formatted shortcut keys (⌘ on Mac, Ctrl on Windows) - Press ? to open shortcuts help Statistics Dashboard: - Create StatsDashboard component with productivity metrics - Calculate productivity score (0-100) based on completion rate - Show notes statistics (total, active, archived, priority) - Display todos statistics with completion rate - Track content stats (notes with todos/images/files, unique tags) - Show recent activity (notes updated in last 7 days) - Visual progress bar for productivity score - Integrate dashboard in left column below calendar
88 lines
2.9 KiB
TypeScript
88 lines
2.9 KiB
TypeScript
import { useEffect } from 'react';
|
|
|
|
export interface KeyboardShortcut {
|
|
key: string;
|
|
ctrl?: boolean;
|
|
alt?: boolean;
|
|
shift?: boolean;
|
|
meta?: boolean;
|
|
description: string;
|
|
handler: () => void;
|
|
preventDefault?: boolean;
|
|
}
|
|
|
|
/**
|
|
* Custom hook for managing keyboard shortcuts
|
|
*/
|
|
export function useKeyboardShortcuts(
|
|
shortcuts: KeyboardShortcut[],
|
|
enabled = true
|
|
) {
|
|
useEffect(() => {
|
|
if (!enabled) return;
|
|
|
|
const handleKeyDown = (event: KeyboardEvent) => {
|
|
for (const shortcut of shortcuts) {
|
|
const keyMatch = event.key.toLowerCase() === shortcut.key.toLowerCase();
|
|
const ctrlMatch = shortcut.ctrl ? (event.ctrlKey || event.metaKey) : !event.ctrlKey && !event.metaKey;
|
|
const altMatch = shortcut.alt ? event.altKey : !event.altKey;
|
|
const shiftMatch = shortcut.shift ? event.shiftKey : !event.shiftKey;
|
|
const metaMatch = shortcut.meta ? event.metaKey : !event.metaKey;
|
|
|
|
if (keyMatch && ctrlMatch && altMatch && shiftMatch && metaMatch) {
|
|
if (shortcut.preventDefault !== false) {
|
|
event.preventDefault();
|
|
}
|
|
shortcut.handler();
|
|
break;
|
|
}
|
|
}
|
|
};
|
|
|
|
window.addEventListener('keydown', handleKeyDown);
|
|
return () => window.removeEventListener('keydown', handleKeyDown);
|
|
}, [shortcuts, enabled]);
|
|
}
|
|
|
|
/**
|
|
* Format keyboard shortcut for display
|
|
*/
|
|
export function formatShortcut(shortcut: KeyboardShortcut): string {
|
|
const parts: string[] = [];
|
|
|
|
if (shortcut.ctrl || shortcut.meta) {
|
|
parts.push(navigator.platform.includes('Mac') ? '⌘' : 'Ctrl');
|
|
}
|
|
if (shortcut.alt) {
|
|
parts.push(navigator.platform.includes('Mac') ? '⌥' : 'Alt');
|
|
}
|
|
if (shortcut.shift) {
|
|
parts.push(navigator.platform.includes('Mac') ? '⇧' : 'Shift');
|
|
}
|
|
|
|
parts.push(shortcut.key.toUpperCase());
|
|
|
|
return parts.join('+');
|
|
}
|
|
|
|
/**
|
|
* Common keyboard shortcuts used across the app
|
|
*/
|
|
export const COMMON_SHORTCUTS = {
|
|
NEW_NOTE: { key: 'n', ctrl: true, description: 'Nouvelle note' },
|
|
SEARCH: { key: 'k', ctrl: true, description: 'Rechercher' },
|
|
QUICK_CAPTURE: { key: 'q', ctrl: true, description: 'Capture rapide' },
|
|
TOGGLE_SIDEBAR: { key: 'b', ctrl: true, description: 'Basculer sidebar' },
|
|
SAVE: { key: 's', ctrl: true, description: 'Sauvegarder' },
|
|
CLOSE: { key: 'Escape', description: 'Fermer' },
|
|
HELP: { key: '?', shift: true, description: 'Aide raccourcis' },
|
|
ARCHIVE: { key: 'e', ctrl: true, description: 'Archiver note' },
|
|
DELETE: { key: 'Delete', ctrl: true, description: 'Supprimer' },
|
|
NEXT: { key: 'j', description: 'Suivant' },
|
|
PREVIOUS: { key: 'k', description: 'Précédent' },
|
|
TOGGLE_TODO: { key: 'Enter', ctrl: true, description: 'Toggle todo' },
|
|
BOLD: { key: 'b', ctrl: true, description: 'Gras' },
|
|
ITALIC: { key: 'i', ctrl: true, description: 'Italique' },
|
|
LINK: { key: 'k', ctrl: true, shift: true, description: 'Lien' },
|
|
};
|