diff --git a/src/backend/services/dcl.service.js b/src/backend/services/dcl.service.js
index b99391b..a348212 100644
--- a/src/backend/services/dcl.service.js
+++ b/src/backend/services/dcl.service.js
@@ -193,6 +193,8 @@ export async function syncQSOs(userId, dclApiKey, sinceDate = null, jobId = null
let addedCount = 0;
let updatedCount = 0;
const errors = [];
+ const addedQSOs = [];
+ const updatedQSOs = [];
for (let i = 0; i < adifQSOs.length; i++) {
const adifQSO = adifQSOs[i];
@@ -230,10 +232,24 @@ export async function syncQSOs(userId, dclApiKey, sinceDate = null, jobId = null
})
.where(eq(qsos.id, existing[0].id));
updatedCount++;
+ // Track updated QSO (CALL and DATE)
+ updatedQSOs.push({
+ callsign: dbQSO.callsign,
+ date: dbQSO.qsoDate,
+ band: dbQSO.band,
+ mode: dbQSO.mode,
+ });
} else {
// Insert new QSO
await db.insert(qsos).values(dbQSO);
addedCount++;
+ // Track added QSO (CALL and DATE)
+ addedQSOs.push({
+ callsign: dbQSO.callsign,
+ date: dbQSO.qsoDate,
+ band: dbQSO.band,
+ mode: dbQSO.mode,
+ });
}
// Update job progress every 10 QSOs
@@ -258,6 +274,8 @@ export async function syncQSOs(userId, dclApiKey, sinceDate = null, jobId = null
total: adifQSOs.length,
added: addedCount,
updated: updatedCount,
+ addedQSOs,
+ updatedQSOs,
confirmed: adifQSOs.filter(q => q.dcl_qsl_rcvd === 'Y').length,
errors: errors.length > 0 ? errors : undefined,
};
diff --git a/src/backend/services/lotw.service.js b/src/backend/services/lotw.service.js
index 483eaf5..df8be76 100644
--- a/src/backend/services/lotw.service.js
+++ b/src/backend/services/lotw.service.js
@@ -223,6 +223,8 @@ export async function syncQSOs(userId, lotwUsername, lotwPassword, sinceDate = n
let addedCount = 0;
let updatedCount = 0;
const errors = [];
+ const addedQSOs = [];
+ const updatedQSOs = [];
for (let i = 0; i < adifQSOs.length; i++) {
const qsoData = adifQSOs[i];
@@ -254,9 +256,23 @@ export async function syncQSOs(userId, lotwUsername, lotwPassword, sinceDate = n
})
.where(eq(qsos.id, existing[0].id));
updatedCount++;
+ // Track updated QSO (CALL and DATE)
+ updatedQSOs.push({
+ callsign: dbQSO.callsign,
+ date: dbQSO.qsoDate,
+ band: dbQSO.band,
+ mode: dbQSO.mode,
+ });
} else {
await db.insert(qsos).values(dbQSO);
addedCount++;
+ // Track added QSO (CALL and DATE)
+ addedQSOs.push({
+ callsign: dbQSO.callsign,
+ date: dbQSO.qsoDate,
+ band: dbQSO.band,
+ mode: dbQSO.mode,
+ });
}
// Update job progress every 10 QSOs
@@ -279,6 +295,8 @@ export async function syncQSOs(userId, lotwUsername, lotwPassword, sinceDate = n
total: adifQSOs.length,
added: addedCount,
updated: updatedCount,
+ addedQSOs,
+ updatedQSOs,
errors: errors.length > 0 ? errors : undefined,
};
}
diff --git a/src/frontend/src/routes/qsos/+page.svelte b/src/frontend/src/routes/qsos/+page.svelte
index a0aef53..8573962 100644
--- a/src/frontend/src/routes/qsos/+page.svelte
+++ b/src/frontend/src/routes/qsos/+page.svelte
@@ -306,6 +306,68 @@
{/if}
+
+ {#if syncResult.success && (syncResult.addedQSOs?.length > 0 || syncResult.updatedQSOs?.length > 0)}
+
+
Import Log
+
+ {#if syncResult.addedQSOs && syncResult.addedQSOs.length > 0}
+
+
New QSOs ({syncResult.addedQSOs.length})
+
+
+
+
+ | Callsign |
+ Date |
+ Band |
+ Mode |
+
+
+
+ {#each syncResult.addedQSOs as qso}
+
+ | {qso.callsign} |
+ {formatDate(qso.date)} |
+ {qso.band || '-'} |
+ {qso.mode || '-'} |
+
+ {/each}
+
+
+
+
+ {/if}
+
+ {#if syncResult.updatedQSOs && syncResult.updatedQSOs.length > 0}
+
+
Updated QSOs ({syncResult.updatedQSOs.length})
+
+
+
+
+ | Callsign |
+ Date |
+ Band |
+ Mode |
+
+
+
+ {#each syncResult.updatedQSOs as qso}
+
+ | {qso.callsign} |
+ {formatDate(qso.date)} |
+ {qso.band || '-'} |
+ {qso.mode || '-'} |
+
+ {/each}
+
+
+
+
+ {/if}
+
+ {/if}
{/if}
{#if showDeleteConfirm}
@@ -845,4 +907,72 @@
opacity: 0.5;
cursor: not-allowed;
}
+
+ .import-log {
+ background: white;
+ border: 1px solid #e0e0e0;
+ border-radius: 8px;
+ padding: 1.5rem;
+ margin-top: 1rem;
+ }
+
+ .import-log h3 {
+ margin: 0 0 1rem 0;
+ color: #333;
+ font-size: 1.25rem;
+ }
+
+ .log-section {
+ margin-bottom: 1.5rem;
+ }
+
+ .log-section:last-child {
+ margin-bottom: 0;
+ }
+
+ .log-section h4 {
+ margin: 0 0 0.75rem 0;
+ color: #555;
+ font-size: 1rem;
+ font-weight: 600;
+ }
+
+ .log-table-container {
+ overflow-x: auto;
+ border: 1px solid #e0e0e0;
+ border-radius: 4px;
+ }
+
+ .log-table {
+ width: 100%;
+ border-collapse: collapse;
+ font-size: 0.9rem;
+ }
+
+ .log-table th,
+ .log-table td {
+ padding: 0.5rem 0.75rem;
+ text-align: left;
+ border-bottom: 1px solid #e0e0e0;
+ }
+
+ .log-table th {
+ background-color: #f8f9fa;
+ font-weight: 600;
+ color: #333;
+ font-size: 0.85rem;
+ }
+
+ .log-table tr:last-child td {
+ border-bottom: none;
+ }
+
+ .log-table tr:hover {
+ background-color: #f8f9fa;
+ }
+
+ .log-table .callsign {
+ font-weight: 600;
+ color: #4a90e2;
+ }