@@ -2542,6 +2588,11 @@ export default function App() {
if (m) setMode(m);
}
onCallsignInput(s.dx_call);
+ // A POTA spot carries the park ref — pre-fill the POTA
+ // award reference (like the State→RAC auto-match) so it's
+ // logged without re-typing. n-fer refs (comma-separated)
+ // become one POTA@ entry each.
+ applySpotPOTA((s as any).pota_ref);
// Clicking a spot fills the call programmatically (no blur
// on the call field), so start the QSO recording here too.
if (s.dx_call.trim()) QSOAudioBegin().then(setRecording).catch(() => {});
@@ -2760,6 +2811,7 @@ export default function App() {
if (m) setMode(m);
}
onCallsignInput(s.dx_call);
+ applySpotPOTA((s as any).pota_ref);
if (s.dx_call.trim()) QSOAudioBegin().then(setRecording).catch(() => {});
}}
onClose={() => setShowBandMap(false)}
diff --git a/frontend/src/components/AwardRefSelector.tsx b/frontend/src/components/AwardRefSelector.tsx
index 42d5393..18f05e5 100644
--- a/frontend/src/components/AwardRefSelector.tsx
+++ b/frontend/src/components/AwardRefSelector.tsx
@@ -280,6 +280,19 @@ export function AwardRefSelector({ dxcc, value, onChange, fieldValues }: Props)
value={q}
onChange={(e) => setQ(e.target.value)}
/>
+ {/* Add an UNLISTED reference: type a new code (e.g. a brand-new POTA park
+ not yet in the list) and add it directly. */}
+ {q.trim().length >= 2 && !results.some((r) => r.code.toUpperCase() === q.trim().toUpperCase()) && (
+
+ )}
{busy && (
diff --git a/frontend/src/lib/maidenhead.ts b/frontend/src/lib/maidenhead.ts
index f1c0538..cdbee60 100644
--- a/frontend/src/lib/maidenhead.ts
+++ b/frontend/src/lib/maidenhead.ts
@@ -49,6 +49,31 @@ export function gridToLatLon(grid: string): { lat: number; lon: number } | null
return { lat, lon };
}
+// latLonToGrid encodes a lat/lon to a Maidenhead locator (default 6 chars).
+// Inverse of gridToLatLon. Used to derive a default grid from a cty.dat entity
+// centroid when no provider grid is available (e.g. a portable/rare DX call) —
+// a centre-of-entity locator is more useful than an empty field.
+export function latLonToGrid(lat: number, lon: number, precision = 6): string {
+ let adjLon = Math.min(359.9999, Math.max(0, lon + 180));
+ let adjLat = Math.min(179.9999, Math.max(0, lat + 90));
+ const A = 'A'.charCodeAt(0);
+ const a = 'a'.charCodeAt(0);
+ const fLon = Math.floor(adjLon / 20);
+ const fLat = Math.floor(adjLat / 10);
+ adjLon -= fLon * 20;
+ adjLat -= fLat * 10;
+ const sLon = Math.floor(adjLon / 2);
+ const sLat = Math.floor(adjLat);
+ let grid = String.fromCharCode(A + fLon) + String.fromCharCode(A + fLat) + sLon + sLat;
+ if (precision >= 6) {
+ adjLon -= sLon * 2;
+ adjLat -= sLat;
+ grid += String.fromCharCode(a + Math.min(23, Math.floor(adjLon * 12)))
+ + String.fromCharCode(a + Math.min(23, Math.floor(adjLat * 24)));
+ }
+ return grid;
+}
+
// gridSquareBounds returns the SW/NE corners of a Maidenhead square so a map
// can draw its outline. Half-extents shrink with locator precision.
export function gridSquareBounds(grid: string):