Skip to content

State Management

State is managed with Pinia 3. Stores are in app/stores/ and are auto-imported by Nuxt.

Boot Order Requirement

WARNING

Do not read SQLite-dependent store data before DeviceSyncedEvent is received. The boot sequence is:

sqlite.ts emits SqlInitializedEvent
    → initializeApp.ts runs migrations + syncDeviceData()
        → DeviceSyncedEvent emitted
            → Components can safely read stores

Use useEventBus().on(DeviceSyncedEvent, ...) to wait for sync completion.

app/stores/device.ts

The core store. Manages authentication state, tenant data, enrollments, locale, and sync orchestration.

State

PropertyTypeDescription
isAuthenticatedbooleanDevice has valid auth tokens
tenantsTenant[]Registered tenants from SQLite
enrollmentsEnrollment[]Active enrollments
userLocalestringCurrent locale code (e.g., en_GB)
colorModestringlight / dark / system
zoomLevelnumberAccessibility zoom level (80–140%)
availableLocalesLocale[]Supported locales list

Actions

ActionDescription
authenticate(token)Decrypts deep link token, calls deviceLogin, stores credentials in SQLite
register()Registers device with tenant
acceptEnrollment(id)Accepts enrollment consent, persists to SQLite
dropEnrollment(id)Removes an enrollment
syncDeviceData()Fetches latest data from all tenant APIs, updates SQLite
downloadQuestionnaireEngine()Downloads questionnaire engine ZIP for offline use
scheduleAccessWindows()Computes access windows and schedules local notifications

app/stores/questionnaires.ts

Manages questionnaire definitions and enrollment state from local SQLite.

State

PropertyTypeDescription
questionnairesQuestionnaire[]All questionnaire definitions
enrollmentsEnrollment[]Enrollments with schedule/availability
pendingSubmissionsPendingSubmit[]Submissions queued for sending

Actions

ActionDescription
loadQuestionnairesFromSQL()Reads questionnaire rows from SQLite into store
loadEnrollmentsFromSQL()Reads enrollment rows from SQLite into store
sendPendingSubmissions()Sends each pending submission via useTenantApi, moves to submits on success

app/stores/eventBus.ts

Lightweight pub/sub system using RxJS Subject. Used to coordinate async initialization across plugins and stores.

Events

EventPublished WhenConsumed By
SqlInitializedEventSQLite readyinitializeApp plugin
DeviceSyncedEventsyncDeviceData() completesComponents needing fresh data
AuthenticatedEventDevice authenticatesAuth-gated UI
NotAuthenticatedEventAuth check fails / logoutRedirect logic
RequestDeviceSyncEventComponent requests syncdevice.ts

Usage

ts
const { publish, on } = useEventBus();

// Publish
publish(new DeviceSyncedEvent());

// Subscribe
on(DeviceSyncedEvent, () => {
  loadData();
});