diff --git a/README.md b/README.md index e58709c..1487314 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,255 @@ -# award +# Ham Radio Award Portal -To install dependencies: +A web application for amateur radio operators to track QSOs (contacts) and award progress using Logbook of the World (LoTW) data. +## Features + +- **User Authentication**: Register and login with callsign, email, and password +- **LoTW Integration**: Sync QSOs from ARRL's Logbook of the World + - Background job queue for non-blocking sync operations + - Incremental sync using last confirmation date + - Wavelog-compatible download logic with proper validation + - One sync job per user enforcement +- **QSO Log**: View and manage confirmed QSOs + - Pagination support for large QSO collections + - Filter by band, mode, and confirmation status + - Statistics dashboard (total QSOs, confirmed, DXCC entities, bands) + - Delete all QSOs with confirmation +- **Settings**: Configure LoTW credentials securely + +## Tech Stack + +### Backend +- **Runtime**: Bun +- **Framework**: Elysia.js +- **Database**: SQLite with Drizzle ORM +- **Authentication**: JWT tokens + +### Frontend +- **Framework**: SvelteKit +- **Language**: JavaScript +- **Styling**: Custom CSS + +## Project Structure + +``` +award/ +├── src/ +│ ├── backend/ +│ │ ├── config/ +│ │ │ ├── database.js # Database connection +│ │ │ └── jwt.js # JWT configuration +│ │ ├── db/ +│ │ │ └── schema/ +│ │ │ └── index.js # Database schema (users, qsos, sync_jobs) +│ │ ├── services/ +│ │ │ ├── auth.service.js # User authentication +│ │ │ ├── lotw.service.js # LoTW sync & QSO management +│ │ │ └── job-queue.service.js # Background job queue +│ │ └── index.js # API routes and server +│ └── frontend/ +│ ├── src/ +│ │ ├── lib/ +│ │ │ ├── api.js # API client +│ │ │ └── stores.js # Svelte stores (auth) +│ │ └── routes/ +│ │ ├── +page.svelte # Main menu +│ │ ├── login/+page.svelte # Login page +│ │ ├── register/+page.svelte # Registration page +│ │ ├── qsos/+page.svelte # QSO log with pagination +│ │ └── settings/+page.svelte # Settings & LoTW credentials +│ └── package.json +├── award.db # SQLite database (auto-created) +├── drizzle.config.js # Drizzle ORM configuration +├── package.json +└── README.md +``` + +## Setup + +### Prerequisites +- [Bun](https://bun.sh) v1.3.6 or later + +### Installation + +1. Clone the repository: +```bash +git clone +cd award +``` + +2. Install dependencies: ```bash bun install ``` -To run: - -```bash -bun run index.ts +3. Set up environment variables (optional): +Create a `.env` file in the project root: +```env +JWT_SECRET=your-secret-key-here ``` -This project was created using `bun init` in bun v1.3.6. [Bun](https://bun.com) is a fast all-in-one JavaScript runtime. +If not provided, a default secret will be used. + +4. Initialize the database: +```bash +bun run db:push +``` + +This creates the SQLite database with required tables (users, qsos, sync_jobs). + +## Running the Application + +Start both backend and frontend: + +```bash +# Start backend (port 3001) +bun run backend/index.js + +# Start frontend (port 5173) +cd src/frontend && bun run dev +``` + +Or use the convenience scripts: +```bash +# Backend only +bun run backend + +# Frontend only +bun run frontend +``` + +The application will be available at: +- Frontend: http://localhost:5173 +- Backend API: http://localhost:3001 + +## API Endpoints + +### Authentication +- `POST /api/auth/register` - Register new user +- `POST /api/auth/login` - Login user +- `GET /api/auth/me` - Get current user profile +- `PUT /api/auth/lotw-credentials` - Update LoTW credentials + +### LoTW Sync +- `POST /api/lotw/sync` - Queue a LoTW sync job (returns job ID) + +### Jobs +- `GET /api/jobs/:jobId` - Get job status +- `GET /api/jobs/active` - Get user's active job +- `GET /api/jobs` - Get recent jobs (query: `?limit=10`) + +### QSOs +- `GET /api/qsos` - Get user's QSOs with pagination + - Query parameters: `?page=1&limit=100&band=20m&mode=CW&confirmed=true` +- `GET /api/qsos/stats` - Get QSO statistics +- `DELETE /api/qsos/all` - Delete all QSOs (requires confirmation) + +### Health +- `GET /api/health` - Health check endpoint + +## Database Schema + +### Users Table +```sql +CREATE TABLE users ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + email TEXT UNIQUE NOT NULL, + password TEXT NOT NULL, + callsign TEXT NOT NULL, + lotwUsername TEXT, + lotwPassword TEXT, + createdAt TEXT NOT NULL +); +``` + +### QSOs Table +```sql +CREATE TABLE qsos ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + userId INTEGER NOT NULL, + callsign TEXT NOT NULL, + qsoDate TEXT NOT NULL, + timeOn TEXT NOT NULL, + band TEXT, + mode TEXT, + entity TEXT, + grid TEXT, + lotwQslRstatus TEXT, + lotwQslRdate TEXT, + FOREIGN KEY (userId) REFERENCES users(id) +); +``` + +### Sync Jobs Table +```sql +CREATE TABLE sync_jobs ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + userId INTEGER NOT NULL, + status TEXT NOT NULL, -- pending, running, completed, failed + type TEXT NOT NULL, -- lotw_sync + startedAt INTEGER, + completedAt INTEGER, + result TEXT, -- JSON + error TEXT, + createdAt INTEGER NOT NULL, + FOREIGN KEY (userId) REFERENCES users(id) +); +``` + +## Features in Detail + +### Background Job Queue + +The application uses an in-memory job queue system for async operations: +- Jobs are persisted to database for recovery +- Only one active job per user (enforced at queue level) +- Status tracking: pending → running → completed/failed +- Real-time progress updates via job result field +- Client polls job status every 2 seconds + +### LoTW Sync Logic + +Following Wavelog's proven approach: +1. **First sync**: Uses date `2000-01-01` to retrieve all QSOs +2. **Subsequent syncs**: Uses `MAX(lotwQslRdate)` from database +3. **Validation**: + - Checks for "Username/password incorrect" in response + - Validates file starts with "ARRL Logbook of the World Status Report" +4. **Timeout handling**: 30-second connection timeout +5. **Query parameters**: Matches Wavelog's LoTW download + +### Pagination + +- Default page size: 100 QSOs per page +- Supports custom page size via `limit` parameter +- Shows page numbers with ellipsis for large page counts +- Displays "Showing X-Y of Z" info +- Previous/Next navigation buttons + +## Development + +### Database Migrations + +```bash +# Push schema changes to database +bun run db:push + +# Open Drizzle Studio (database GUI) +bun run db:studio +``` + +### Linting + +```bash +bun run lint +``` + +## License + +MIT + +## Credits + +- LoTW integration inspired by [Wavelog](https://github.com/magicbug/CloudLog) +- Built with [Bun](https://bun.sh), [Elysia](https://elysiajs.com), and [SvelteKit](https://kit.svelte.dev)