feat: implement night mode functionality with UI updates and journey tracking

- Added NightScreen component for displaying night mode information and alerts.
- Introduced NextStops component to show upcoming stops during a journey.
- Implemented logic for determining night mode activation based on schedule and user settings.
- Created journey utility functions to manage onward journey data and stop information.
- Updated tests to cover new night mode features and journey logic.
- Added fixture for testing night mode scenarios with specific timestamps.
- Removed QR code from night screen for a cleaner UI experience.
- Enhanced admin settings to manage night mode configurations.
This commit is contained in:
2026-10-11 05:04:00 +03:00
parent d04b364047
commit 5c69f6691d
49 changed files with 590 additions and 121 deletions

View File

@@ -1,7 +1,7 @@
import test from 'node:test';
import assert from 'node:assert/strict';
import { readFile } from 'node:fs/promises';
import { isManagedState } from '../src/lib/device.mjs';
import { hydrateManagedState, isManagedState } from '../src/lib/device.mjs';
import { createDeviceBridge } from '../server/device.mjs';
import { createApp } from '../server/index.mjs';
const source = await readFile(new URL('../src/lib/storage.ts', import.meta.url), 'utf8');
@@ -14,6 +14,9 @@ test('managed configuration validation rejects damaged, mismatched or unsupporte
for (const patch of [{ rowCount: 8 }, { demo: true }, { theme: 'sepia' }, { stopId: 2 }, { colorScheme: 'sky' }, { routeFilter: '-1' }, { holdNear: null }]) assert.equal(isManagedState({ ...value, device: { ...value.device, settings: { ...defaults, ...patch } } }), false);
assert.equal(isManagedState({ ...value, config: { ...value.config, refreshSeconds: 0 } }), false);
assert.equal(isManagedState(null), false);
const legacy = structuredClone(value); delete legacy.device.settings.nightMode;delete legacy.device.settings.nightWakeMinutes;
assert.equal(isManagedState(legacy),true);assert.equal(hydrateManagedState(legacy).device.settings.nightMode,'auto');
assert.equal(isManagedState({...value,device:{...value.device,settings:{...defaults,nightWakeMinutes:5}}}),false);
});
test('pairing bridge keeps secrets in HttpOnly cookies, binds data to the individual device and rejects cross-site writes', async t => {
const tokenA = 'A'.repeat(43), tokenB = 'B'.repeat(43), calls = [];