import { useEffect } from 'react'; import { Globe2, RefreshCw, Upload, BadgeCheck, Mail, FileDown, PencilLine, Trash2 } 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; onSendEQSL?: (ids: number[]) => void; onBulkEdit?: (ids: number[]) => void; onExportSelected?: (ids: number[]) => void; onExportFiltered?: () => void; onDelete?: (ids: number[]) => void; }; const UPLOAD_TARGETS: { service: string; label: string }[] = [ { service: 'qrz', label: 'Send to QRZ.com' }, { service: 'clublog', label: 'Send to Club Log' }, { service: 'hrdlog', label: 'Send to HRDLog.net' }, { service: 'eqsl', label: 'Send to eQSL.cc' }, { 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. Stays open until the user clicks outside, presses Escape, // or picks a command. (We deliberately do NOT close on scroll/resize: the QSO // list auto-refreshes and AG Grid fires internal scroll events on refresh, // which used to dismiss the menu the instant it appeared.) export function QSOContextMenu({ menu, onClose, onUpdateFromCty, onUpdateFromQRZ, onUpdateFromClublog, onSendTo, onSendRecording, onSendEQSL, onBulkEdit, onExportSelected, onExportFiltered, onDelete }: Props) { useEffect(() => { if (!menu) return; const close = () => onClose(); const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') onClose(); }; window.addEventListener('mousedown', close); window.addEventListener('keydown', onKey); return () => { window.removeEventListener('mousedown', 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 || onSendEQSL) && ( <>
{onSendEQSL && ( )} {onSendRecording && ( )} )} {onBulkEdit && ( <>
)} {(onExportSelected || onExportFiltered) && ( <>
{onExportSelected && ( )} {onExportFiltered && ( )} )} {onSendTo && ( <>
{UPLOAD_TARGETS.map((t) => ( ))} )} {onDelete && ( <>
)}
); }