feat: prepare database and UI for DCL integration

Add infrastructure for future DARC Community Logbook (DCL) integration:
- Database schema: Add dcl_api_key, my_darc_dok, darc_dok, dcl_qsl_rdate, dcl_qsl_rstatus fields
- Create DCL service stub with placeholder functions for when DCL provides API
- Backend API: Add /api/auth/dcl-credentials endpoint for API key management
- Frontend settings: Add DCL API key input with informational notice about API availability
- QSO table: Add My DOK and DOK columns, update confirmation column for multiple services

Note: DCL download API is not yet available. These changes prepare the application
for future implementation when DCL adds programmatic access.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-17 10:24:43 +01:00
parent 5db7f6b67f
commit 47738c68a9
10 changed files with 1014 additions and 24 deletions

View File

@@ -8,6 +8,7 @@ import { sqliteTable, text, integer } from 'drizzle-orm/sqlite-core';
* @property {string} callsign
* @property {string|null} lotwUsername
* @property {string|null} lotwPassword
* @property {string|null} dclApiKey
* @property {Date} createdAt
* @property {Date} updatedAt
*/
@@ -19,6 +20,7 @@ export const users = sqliteTable('users', {
callsign: text('callsign').notNull(),
lotwUsername: text('lotw_username'),
lotwPassword: text('lotw_password'), // Encrypted
dclApiKey: text('dcl_api_key'), // DCL API key for future use
createdAt: integer('created_at', { mode: 'timestamp' }).notNull().$defaultFn(() => new Date()),
updatedAt: integer('updated_at', { mode: 'timestamp' }).notNull().$defaultFn(() => new Date()),
});
@@ -45,8 +47,12 @@ export const users = sqliteTable('users', {
* @property {string|null} county
* @property {string|null} satName
* @property {string|null} satMode
* @property {string|null} myDarcDok
* @property {string|null} darcDok
* @property {string|null} lotwQslRdate
* @property {string|null} lotwQslRstatus
* @property {string|null} dclQslRdate
* @property {string|null} dclQslRstatus
* @property {Date|null} lotwSyncedAt
* @property {Date} createdAt
*/
@@ -79,10 +85,18 @@ export const qsos = sqliteTable('qsos', {
satName: text('sat_name'),
satMode: text('sat_mode'),
// DARC DOK fields (DARC Ortsverband Kennung - German local club identifier)
myDarcDok: text('my_darc_dok'), // User's own DOK (e.g., 'F03', 'P30')
darcDok: text('darc_dok'), // QSO partner's DOK
// LoTW confirmation
lotwQslRdate: text('lotw_qsl_rdate'), // Confirmation date
lotwQslRstatus: text('lotw_qsl_rstatus'), // 'Y', 'N', '?'
// DCL confirmation (DARC Community Logbook)
dclQslRdate: text('dcl_qsl_rdate'), // Confirmation date
dclQslRstatus: text('dcl_qsl_rstatus'), // 'Y', 'N', '?'
// Cache metadata
lotwSyncedAt: integer('lotw_synced_at', { mode: 'timestamp' }),
createdAt: integer('created_at', { mode: 'timestamp' }).notNull().$defaultFn(() => new Date()),