import { useEffect } from 'react'; import { Globe2, RefreshCw, Upload, BadgeCheck, Mail, FileDown } from 'lucide-react'; export type QSOMenuState = { x: number; y: number; ids: number[] } | null; type Props = { menu: QSOMenuState; onClose: () => void; onUpdateFromCty: (ids: number[]) => void; onUpdateFromQRZ: (ids: number[]) => void; onUpdateFromClublog?: (ids: number[]) => void; onSendTo?: (service: string, ids: number[]) => void; onSendRecording?: (ids: number[]) => void; onExportSelected?: (ids: number[]) => void; onExportFiltered?: () => void; }; const UPLOAD_TARGETS: { service: string; label: string }[] = [ { service: 'qrz', label: 'Send to QRZ.com' }, { service: 'clublog', label: 'Send to Club Log' }, { service: 'lotw', label: 'Send to LoTW' }, ]; // Lightweight right-click menu for the QSO grids. AG Grid's native context // menu is an Enterprise feature, so this is a plain floating menu driven by // onCellContextMenu. Closes on any outside click, scroll or Escape. export function QSOContextMenu({ menu, onClose, onUpdateFromCty, onUpdateFromQRZ, onUpdateFromClublog, onSendTo, onSendRecording, onExportSelected, onExportFiltered }: Props) { useEffect(() => { if (!menu) return; const close = () => onClose(); const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') onClose(); }; window.addEventListener('mousedown', close); window.addEventListener('scroll', close, true); window.addEventListener('resize', close); window.addEventListener('keydown', onKey); return () => { window.removeEventListener('mousedown', close); window.removeEventListener('scroll', close, true); window.removeEventListener('resize', close); window.removeEventListener('keydown', onKey); }; }, [menu, onClose]); if (!menu) return null; const n = menu.ids.length; // Keep the menu on-screen near the cursor. const x = Math.min(menu.x, window.innerWidth - 248); const y = Math.min(menu.y, window.innerHeight - (onSendTo ? 230 : 110)); return (
e.stopPropagation()} >
{n} QSO{n > 1 ? 's' : ''} selected
{onUpdateFromClublog && ( )} {onSendRecording && ( <>
)} {(onExportSelected || onExportFiltered) && ( <>
{onExportSelected && ( )} {onExportFiltered && ( )} )} {onSendTo && ( <>
{UPLOAD_TARGETS.map((t) => ( ))} )}
); }