This commit is contained in:
2026-06-03 21:53:31 +02:00
parent 2b4326b553
commit 1a425a1b0d
15 changed files with 377 additions and 97 deletions
+26 -3
View File
@@ -1,5 +1,5 @@
import { useEffect } from 'react';
import { Globe2, RefreshCw } from 'lucide-react';
import { Globe2, RefreshCw, Upload } from 'lucide-react';
export type QSOMenuState = { x: number; y: number; ids: number[] } | null;
@@ -8,12 +8,19 @@ type Props = {
onClose: () => void;
onUpdateFromCty: (ids: number[]) => void;
onUpdateFromQRZ: (ids: number[]) => void;
onSendTo?: (service: string, 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: '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 }: Props) {
export function QSOContextMenu({ menu, onClose, onUpdateFromCty, onUpdateFromQRZ, onSendTo }: Props) {
useEffect(() => {
if (!menu) return;
const close = () => onClose();
@@ -34,7 +41,7 @@ export function QSOContextMenu({ menu, onClose, onUpdateFromCty, onUpdateFromQRZ
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 - 110);
const y = Math.min(menu.y, window.innerHeight - (onSendTo ? 230 : 110));
return (
<div
@@ -59,6 +66,22 @@ export function QSOContextMenu({ menu, onClose, onUpdateFromCty, onUpdateFromQRZ
<RefreshCw className="size-4 text-sky-600" />
<span>Update from QRZ.com</span>
</button>
{onSendTo && (
<>
<div className="my-1 border-t border-border" />
{UPLOAD_TARGETS.map((t) => (
<button
key={t.service}
className="flex w-full items-center gap-2 px-3 py-1.5 text-left hover:bg-accent/50"
onClick={() => { onSendTo(t.service, menu.ids); onClose(); }}
>
<Upload className="size-4 text-emerald-600" />
<span>{t.label}</span>
</button>
))}
</>
)}
</div>
);
}