From b332989844c6aed9528ebc3727982d8afd500f60 Mon Sep 17 00:00:00 2001 From: Joerg Date: Mon, 19 Jan 2026 13:00:10 +0100 Subject: [PATCH] fix: include band field in QSO entries for award detail modal The QSO entries on the award detail page were missing the band field, causing the openQSODetailModal() function to fail with "QSO not found" when trying to fetch full QSO details. The band field is now included in the QSO entry objects so the filter parameters match correctly. Co-Authored-By: Claude Sonnet 4.5 --- .../src/routes/awards/[id]/+page.svelte | 490 +++++++++++++++++- 1 file changed, 489 insertions(+), 1 deletion(-) diff --git a/src/frontend/src/routes/awards/[id]/+page.svelte b/src/frontend/src/routes/awards/[id]/+page.svelte index 54ee123..c49a71e 100644 --- a/src/frontend/src/routes/awards/[id]/+page.svelte +++ b/src/frontend/src/routes/awards/[id]/+page.svelte @@ -10,6 +10,11 @@ let groupedData = []; let bands = []; + // QSO detail modal state + let selectedQSO = null; + let showQSODetailModal = false; + let loadingQSO = false; + onMount(async () => { await loadAwardData(); }); @@ -80,6 +85,7 @@ entityData.bands.get(entity.band).push({ callsign: entity.callsign, mode: entity.mode, + band: entity.band, confirmed: entity.confirmed, qsoDate: entity.qsoDate, }); @@ -127,6 +133,7 @@ entityData.bands.get(entity.band).push({ callsign: entity.callsign, mode: entity.mode, + band: entity.band, confirmed: entity.confirmed, qsoDate: entity.qsoDate, }); @@ -154,6 +161,79 @@ $: if (entities.length > 0) { applyFilter(); } + + // QSO Detail Modal Functions + async function openQSODetailModal(qso) { + loadingQSO = true; + showQSODetailModal = true; + selectedQSO = null; + + try { + // Fetch full QSO details using filters + const params = new URLSearchParams({ + callsign: qso.callsign, + qsoDate: qso.qsoDate, + band: qso.band, + mode: qso.mode, + limit: '1' + }); + + const response = await fetch(`/api/qsos?${params}`, { + headers: { + 'Authorization': `Bearer ${$auth.token}`, + }, + }); + + if (!response.ok) { + throw new Error('Failed to fetch QSO details'); + } + + const data = await response.json(); + + if (!data.success) { + throw new Error(data.error || 'Failed to fetch QSO details'); + } + + if (data.qsos && data.qsos.length > 0) { + selectedQSO = data.qsos[0]; + } else { + throw new Error('QSO not found'); + } + } catch (err) { + console.error('Failed to load QSO details:', err); + alert('Failed to load QSO details: ' + err.message); + showQSODetailModal = false; + } finally { + loadingQSO = false; + } + } + + function closeQSODetailModal() { + selectedQSO = null; + showQSODetailModal = false; + } + + function formatDate(dateStr) { + if (!dateStr) return '-'; + // ADIF format: YYYYMMDD + const year = dateStr.substring(0, 4); + const month = dateStr.substring(4, 6); + const day = dateStr.substring(6, 8); + return `${day}/${month}/${year}`; + } + + function formatTime(timeStr) { + if (!timeStr) return '-'; + // ADIF format: HHMMSS or HHMM + return timeStr.substring(0, 2) + ':' + timeStr.substring(2, 4); + } + + function getConfirmationStatus(status) { + if (status === 'Y') return { label: 'Confirmed', class: 'confirmed' }; + if (status === 'N') return { label: 'Not Confirmed', class: 'not-confirmed' }; + if (status === '?') return { label: 'Unknown', class: 'unknown' }; + return { label: 'No Data', class: 'no-data' }; + }
@@ -247,7 +327,13 @@ {#if qsos.length > 0}
{#each qsos as qso} -
+
openQSODetailModal(qso)} + on:keydown={(e) => e.key === 'Enter' && openQSODetailModal(qso)} + role="button" + tabindex="0" + > {qso.callsign} {qso.mode}
@@ -267,6 +353,188 @@ {/if}
+ +{#if showQSODetailModal && selectedQSO} + +{/if} +