perfect-postcode/video/src/routes.ts
2026-06-22 22:04:20 +01:00

59 lines
2.1 KiB
TypeScript

import type { Page } from 'playwright';
import { APP_URL, DASHBOARD_PATH } from './config.js';
import type { Storyboard } from './script.js';
export async function installDemoRoutes(page: Page, storyboard: Storyboard) {
await Promise.all([stubAiFilters(page, storyboard), stubExport(page)]);
}
export function dashboardUrl(storyboard: Storyboard): string {
const view = storyboard.content.initialMapView;
const params = new URLSearchParams({
lat: String(view.lat),
lon: String(view.lon),
zoom: String(view.zoom),
});
// Cold-open filters: applied through the URL so the first frame already
// shows a filtered map. Numeric features use name:min:max, enums name:a|b.
for (const [name, value] of Object.entries(storyboard.content.initialFilters ?? {})) {
const entry =
typeof value[0] === 'number'
? `${name}:${value[0]}:${value[1]}`
: `${name}:${(value as string[]).join('|')}`;
params.append('filter', entry);
}
for (const tt of storyboard.content.stubbedTravelTimeFilters) {
params.append('tt', `${tt.mode}:${tt.slug}:${tt.label}:${tt.min ?? 0}:${tt.max ?? 120}`);
}
return `${APP_URL}${DASHBOARD_PATH}?${params}`;
}
async function stubAiFilters(page: Page, storyboard: Storyboard) {
await page.route('**/api/ai-filters', async (route) => {
await new Promise((r) => setTimeout(r, 120));
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({
filters: storyboard.content.stubbedFilters,
travel_time_filters: storyboard.content.stubbedTravelTimeFilters,
notes: '',
match_count: storyboard.content.matchCount ?? 1247,
}),
});
});
}
async function stubExport(page: Page) {
await page.route('**/api/export?**', async (route) => {
await new Promise((r) => setTimeout(r, 120));
await route.fulfill({
status: 200,
contentType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
headers: {
'content-disposition': 'attachment; filename="perfect-postcode-export.xlsx"',
},
body: Buffer.from('Perfect Postcode demo export\n'),
});
});
}