120 lines
5.0 KiB
Markdown
120 lines
5.0 KiB
Markdown
# Architecture
|
|
|
|
This document describes behavior confirmed from the current repository. Proposed changes should be labeled as proposals rather than added here as existing behavior.
|
|
|
|
## System overview
|
|
|
|
Court Pilot is a local-first Angular/Ionic application packaged as a Tauri desktop application. There is no backend API in the repository. Domain data is persisted in IndexedDB through Dexie.
|
|
|
|
```mermaid
|
|
flowchart TD
|
|
Pages[Angular and Ionic pages] --> Services[Domain and persistence services]
|
|
Pages --> I18n[Translation service and pipe]
|
|
Services --> Dexie[Dexie]
|
|
Dexie --> IndexedDB[IndexedDB in browser or webview]
|
|
Tauri[Tauri desktop shell] --> WebApp[Built Angular application]
|
|
Tauri --> Updates[OS, process, and updater plugins]
|
|
WebApp --> Pages
|
|
```
|
|
|
|
## Frontend structure
|
|
|
|
The root route lazy-loads the tab routes. The three primary routes are:
|
|
|
|
| Route | Source | Responsibility |
|
|
|---|---|---|
|
|
| `/tabs/pilot` | `src/app/tab1/` | Waiting queues, court assignments, drag and drop, and rotation actions |
|
|
| `/tabs/umpires` | `src/app/tab2/` | Court-official roster management |
|
|
| `/tabs/settings` | `src/app/tab3/` | Court count, service-judge mode, alerts, and language |
|
|
|
|
Pages are standalone Angular components and directly import the Ionic standalone components they use. Services are root-provided and injected with Angular's `inject()` function.
|
|
|
|
## Reactive state
|
|
|
|
Persistence services use Dexie's `liveQuery()` and Angular's `toSignal()` to expose reactive data. Pages derive lookup maps, ID sets, filtered lists, and other display state with `computed()`.
|
|
|
|
`Tab1Page` currently coordinates multi-service operations such as moving officials between waiting queues and courts. These operations span multiple Dexie tables but are not currently wrapped in database transactions.
|
|
|
|
## Persistence model
|
|
|
|
`db.ts` declares a `CourtPilot` Dexie database at schema version 1.
|
|
|
|
```mermaid
|
|
erDiagram
|
|
UMPIRE ||--o{ COURT_UMPIRE : assigned_as
|
|
UMPIRE ||--o{ COURT_SERVICE_JUDGE : assigned_as
|
|
UMPIRE ||--o{ WAITING_UMPIRE : queued_as
|
|
UMPIRE ||--o{ WAITING_SERVICE_JUDGE : queued_as
|
|
|
|
UMPIRE {
|
|
number id PK
|
|
string firstName
|
|
string lastName
|
|
string country
|
|
string gender
|
|
number courtNo
|
|
}
|
|
COURT_UMPIRE {
|
|
number id PK
|
|
number umpireId
|
|
number courtNo
|
|
}
|
|
COURT_SERVICE_JUDGE {
|
|
number id PK
|
|
number umpireId
|
|
number courtNo
|
|
}
|
|
WAITING_UMPIRE {
|
|
number id PK
|
|
number umpireId
|
|
number order
|
|
}
|
|
WAITING_SERVICE_JUDGE {
|
|
number id PK
|
|
number serviceJudgeId
|
|
number order
|
|
}
|
|
```
|
|
|
|
Settings use a singleton row with ID `1`. Defaults are five courts, service judges enabled, and confirmation alerts enabled.
|
|
|
|
### Schema-change policy
|
|
|
|
Once data may exist in released clients, do not modify schema version 1 in place. Add a new `db.version(n)` declaration and define upgrade behavior when existing records need transformation.
|
|
|
|
## Localization
|
|
|
|
`src/app/i18n/translations.ts` defines the translation catalog and derives TypeScript types from it. English is the fallback language; Hungarian is also supported. The selected language is stored in `localStorage` under `language`.
|
|
|
|
Templates use `TranslatePipe`. Imperative UI such as Ionic alerts uses `TranslationService`.
|
|
|
|
## Desktop integration
|
|
|
|
The Tauri shell loads the Angular build from `www/`. Its Rust layer registers:
|
|
|
|
- OS plugin
|
|
- process plugin
|
|
- updater plugin
|
|
- debug-only logging plugin
|
|
|
|
At application startup, the Angular root component checks for desktop updates when running under Tauri. It skips the in-app updater on Linux because Snap manages Linux updates.
|
|
|
|
Windows and macOS updater artifacts are distributed through CrabNebula. Linux is packaged and published as a strict-confinement Snap.
|
|
|
|
## Supported platforms
|
|
|
|
The supported targets are browser/web, Windows, macOS, and Linux Snap. Android and iOS are not supported or planned at this stage. `capacitor.config.ts` remains as possible future scaffolding, but agents must not treat mobile builds as active.
|
|
|
|
Tauri development intentionally expects the Ionic frontend on port `8103`. The command used by `beforeDevCommand` must explicitly or otherwise reliably start the frontend on that port.
|
|
|
|
## Domain invariants affecting architecture
|
|
|
|
Each court official must be represented in exactly one operational state: not on duty, one waiting queue, or one court assignment. The two role queues are FIFO by numeric `order`. When service judges rotate off a court, the officials swap role queues. Reducing the court count removes assignments from eliminated courts and leaves those officials not on duty.
|
|
|
|
Operations that move an official between states should preserve exclusivity even when multiple Dexie tables are involved.
|
|
|
|
## Known architectural questions
|
|
|
|
- Should moves spanning multiple tables use Dexie transactions to prevent partial updates?
|
|
- Should domain entities and database setup remain in root-level `db.ts`, or move under `src/app/`?
|