Commit Graph

116 Commits

Author SHA1 Message Date
052f0d13bd Add displayField configuration to award definitions
Add configurable displayField to award definitions to control what
is shown in award details instead of always using the entity value.

## Award Definitions Updated
- DXCC: displayField = 'entity' (shows country name)
- DXCC CW: displayField = 'entity' (shows country name)
- WAS: displayField = 'state' (shows state name)
- VUCC: displayField = 'grid' (shows grid square)
- RS-44: displayField = 'callsign' (shows callsign)

## Backend Changes
- Preserve displayField when normalizing award rules
- Use displayField to determine entity name in details
- Fallback logic for awards without displayField
- Add satName to entity data for better display

This fixes VUCC showing grid squares instead of country names.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-16 09:12:07 +01:00
3b7dfd74fe Display entity names instead of IDs in award details
- Add entityName field to backend entity breakdown
- For DXCC: Show country name (e.g., 'Germany') with ID in parentheses
- For WAS: Show state name
- For VUCC: Show grid square
- For RS-44: Show callsign
- Update sorting to use entity names for better UX
- Add subtle styling for entity IDs (gray, smaller font)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-16 09:05:50 +01:00
b3567100c0 Add counter award type support and debug logging
- Handle 'counter' type awards that count unique callsigns
- Add debug logging to track QSO filtering progress
- Normalize counter awards to use entityType: 'callsign'

This fixes RS-44 satellite award to count unique callsigns worked
via RS-44 satellite.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-16 09:00:59 +01:00
111d6d5dd4 Fix entity sorting when entity is a number
Convert entity to string before calling localeCompare to handle
numeric entity IDs (like DXCC entityId values).

Fixes TypeError on award detail pages when sorting by name.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-16 08:55:25 +01:00
d77ee69daa Add award detail page and fix award progress calculation
## Frontend
- Create award detail page at /awards/[id]
- Show all entities with worked/confirmed status
- Add filtering (all, worked, confirmed, unworked)
- Add sorting (name, status)
- Display summary cards (total, confirmed, worked, needed)
- Show entity details (callsign, band, mode, date)

## Backend Fixes
- Fix award progress calculation for filtered awards
- Add normalizeAwardRules to handle "filtered" type awards
- Fix satellite filter to check satName field instead of satellite
- Add case-insensitive contains matching
- Apply normalization to both progress and entity breakdown functions

This fixes the 0/0 issue for DXCC CW, WAS, VUCC, and satellite awards.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-16 08:53:23 +01:00
884bdb436d Add awards system with progress tracking
Implement awards display with progress calculation based on QSO data.

## Backend
- Add awards service with progress calculation logic
- Support for DXCC, WAS, VUCC, and satellite awards
- Filter QSOs by band, mode, and other criteria
- Calculate worked/confirmed entities per award
- API endpoints:
  - GET /api/awards - List all awards
  - GET /api/awards/:id/progress - Get award progress
  - GET /api/awards/:id/entities - Get detailed entity breakdown

## Frontend
- Create awards listing page with progress cards
- Add Awards link to navigation bar
- Display award progress bars with worked/confirmed counts
- Link to individual award detail pages (to be implemented)
- Copy award definitions to static folder

## Award Definitions
- DXCC Mixed Mode (100 entities)
- DXCC CW (100 entities, CW only)
- WAS Mixed Mode (50 states)
- VUCC Satellite (100 grids)
- RS-44 Satellite Award (100 QSOs)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-16 08:47:30 +01:00
31488e556c Fix URI malformed error from browser extensions
Fix the suppressURIErrorPlugin to properly handle malformed URIs from
browser extensions without throwing errors.

Changes:
- Move next() outside try block to only call for valid URLs
- Return 200 OK instead of 400 for malformed URIs
- Early return to prevent further processing of bad requests

Fixes errors appearing on every page load from browser extension requests.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-16 08:26:35 +01:00
a4ed1ec6d6 Add hostname configuration for production deployment
Add environment variable configuration to support deployment on custom
domains like https://awards.dj7nt.de

## Changes
- Add .env.example with configuration template
- Update API client to use VITE_API_BASE_URL with fallback to /api
- Update SvelteKit config to use VITE_APP_URL for CSRF trusted origins
- Update backend CORS to use configurable allowed origins
- Add ALLOWED_ORIGINS environment variable for production
- Add build and preview scripts to package.json
- Update README with production deployment guide and nginx example

## Environment Variables
- VITE_APP_URL: Application hostname (e.g., https://awards.dj7nt.de)
- VITE_API_BASE_URL: API base URL (empty = relative paths)
- ALLOWED_ORIGINS: Comma-separated CORS origins
- JWT_SECRET: Strong secret for production
- NODE_ENV: development/production

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-16 08:22:37 +01:00
afe150f15c Add proxy configuration for single-port development
Configure SvelteKit dev server to proxy API requests to Elysia backend,
allowing users to access the application on a single port (5173).

## Changes
- Add proxy config to vite.config.js for /api requests
- Update API client to use relative URLs (/api)
- Add convenience 'dev' script to start both servers
- Update README with single-port instructions
- Add architecture section explaining proxy setup

Benefits:
- Single port to access (5173)
- HMR still works for frontend
- No CORS issues
- Backend runs hidden on port 3001

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-16 08:16:58 +01:00
d959235cdd Add structured logging, navigation bar, and code cleanup
## Backend
- Add Pino logging framework with timestamps and structured output
- Replace all console.error statements (49+) with proper logging levels
- Fix Drizzle ORM bug: replace invalid .get() calls with .limit(1)
- Remove unused auth routes file (already in index.js)
- Make internal functions private (remove unnecessary exports)
- Simplify code by removing excessive debug logging

## Frontend
- Add navigation bar to layout with:
  - User's callsign display
  - Navigation links (Dashboard, QSOs, Settings)
  - Logout button with red color distinction
- Navigation only shows when user is logged in
- Dark themed design matching footer

## Documentation
- Update README.md with new project structure
- Update docs/DOCUMENTATION.md with logging and nav bar info
- Add logger.js to configuration section

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-16 08:11:57 +01:00
512f4f682e Add comprehensive README documentation
- Describe project purpose and features
- Document tech stack (Bun, Elysia, SvelteKit, SQLite, Drizzle)
- Add project structure overview
- Include setup and installation instructions
- Document all API endpoints
- Include database schema for all tables
- Explain background job queue system
- Document LoTW sync logic and pagination features
- Add development commands

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-15 22:11:15 +01:00
40a3e3642e Add pagination to QSO Log and back buttons to pages
- Add backend pagination support for /api/qsos endpoint (page, limit params)
- Return paginated results with metadata (totalCount, totalPages, hasNext, hasPrev)
- Add pagination UI to QSOs page with prev/next buttons and page numbers
- Add back button to QSO Log and Settings pages linking to main menu
- Reset to page 1 when applying filters

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-15 22:10:23 +01:00
dde0c18f51 1st sync Full 2026-01-15 22:05:09 +01:00
f82fc876ce Refactor LoTW sync with background job queue and Wavelog compatibility
Backend changes:
- Add sync_jobs table for background job tracking with Drizzle schema
- Create job queue service (job-queue.service.js) for async job processing
- Only ONE active sync job per user enforced at queue level
- Refactor LoTW service with Wavelog download logic:
  - Validate for "Username/password incorrect" in response
  - Check file starts with "ARRL Logbook of the World Status Report"
  - Use last LoTW QSL date for incremental sync (qso_qslsince)
  - Wavelog-compatible timeouts and error handling
- Add deleteQSOs function to clear all user QSOs
- Fix database path to use absolute path for consistency
- Register job processor for lotw_sync job type

API endpoints:
- POST /api/lotw/sync - Queue background sync job, returns jobId immediately
- GET /api/jobs/:jobId - Get job status with progress tracking
- GET /api/jobs/active - Get user's active job
- GET /api/jobs - Get user's recent jobs
- DELETE /api/qsos/all - Delete all QSOs for authenticated user

Frontend changes:
- Add job polling every 2 seconds during sync
- Show real-time progress indicator during sync
- Add "Clear All QSOs" button with type-to-confirm ("DELETE")
- Check for active job on mount to resume polling after refresh
- Clean up polling interval on component unmount
- Update API client with jobsAPI methods (getStatus, getActive, getRecent)

Database:
- Add sync_jobs table: id, userId, status, type, startedAt, completedAt,
  result, error, createdAt
- Foreign key to users table
- Path fix: now uses src/backend/award.db consistently

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-15 21:47:50 +01:00
44c13e1bdc Add comprehensive documentation and LoTW integration
- Add detailed documentation covering architecture, components, code structure
- Document award system with multiple examples (DXCC, WAS, VUCC, Satellite)
- Implement LoTW sync service with ADIF parsing and long-polling
- Add QSO logbook page with filtering and statistics
- Add settings page for LoTW credentials management
- Add API endpoints for LoTW sync, QSO retrieval, and statistics

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-15 16:39:49 +01:00
8c26fc93e3 Initial commit: Ham Radio Award Portal
Features implemented:
- User authentication (register/login) with JWT
- SQLite database with Drizzle ORM
- SvelteKit frontend with authentication flow
- ElysiaJS backend with CORS enabled
- Award definition JSON schemas (DXCC, WAS, VUCC, SAT)
- Responsive dashboard with user profile

Tech stack:
- Backend: ElysiaJS, Drizzle ORM, SQLite, JWT
- Frontend: SvelteKit, Svelte stores
- Runtime: Bun
- Language: JavaScript

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-15 11:01:10 +01:00