mirror of
https://github.com/azaion/ui.git
synced 2026-06-21 07:01:11 +00:00
434854bf3c
- Design system: v2 CSS variables (surface-0/1/2, border-hair, accent-amber/cyan/red/green/blue)
and utility classes (.btn, .inp, .pill, .chip, .bracket, .panel, .seg, .swatch,
.type-sq, .grid-bg, .ibtn, .checkbox, .tab); v1 az-* names aliased to v2 vars
so other pages still render. Google Fonts (IBM Plex Sans + JetBrains Mono)
loaded via <link> in index.html <head> to avoid FOUT.
- Header rebuilt to v2: amber wordmark + // divider, amber-bordered flight pill
with cyan live dot, tab-style nav with amber underline on active, LINK status
pill, cog + sign-out icon buttons.
- AdminPage rewritten to 3-column layout (340 / flex / 280):
- Detection Classes: search + ADD button, table with #/Name/Hex/Ops columns,
name-only inline edit with ringed swatch, sibling-row error alert.
- AI Recognition Engine + GPS Device Link panels with corner-bracket borders,
number steppers, segmented protocol control, dashed telemetry footers.
Hooks (useAiSettings, useGpsSettings) seed factory defaults so the UI is
interactive when GET fails (no backend).
- Default Aircrafts: P/C/F type chips, isDefault star toggle, + ADD AIRCRAFT
modal with model/type/resolution/maxMinutes/default fields.
- Co-located components: Modal (backdrop + ESC + body-scroll-lock),
NumberStepper (▲▼ with clamp on click but not on typing), ClassEditRow.
- Types: Aircraft extended with FixedWing + optional resolution/maxMinutes;
new AiRecognitionSettings/Telemetry, GpsDeviceSettings/Telemetry, GpsProtocol.
- Endpoints: /api/admin/ai-settings, /api/admin/gps-settings (+ /ping, /reconnect).
POST /api/flights/aircrafts (plural REST collection).
- MSW: stateful admin-settings handler with resetAdminSettingsSeed() wired into
tests/setup.ts. Aircraft seed expanded to 6 entries matching the mockup.
- i18n: full admin.{classes,aiEngine,gpsDevice,aircrafts} key sets in en+ua;
nav.dataset shortened to "Dataset"; obsolete users-management keys removed.
- Tests: new AdminPage AI/GPS/aircraft test suites; admin_class_edit selectors
updated for the name-only inline editor and the modal-based add flow.
78 lines
3.0 KiB
TypeScript
78 lines
3.0 KiB
TypeScript
import { http } from 'msw'
|
|
import { jsonResponse, noContent, sse } from '../helpers'
|
|
import { seedFlights } from '../../fixtures/seed_flights'
|
|
import { seedAircraft } from '../../fixtures/seed_aircraft'
|
|
|
|
// Default `/api/flights/*` handlers. Live-GPS SSE returns a deterministic
|
|
// 3-event stream so AC-08 timing assertions have something to drive even
|
|
// without per-test overrides.
|
|
|
|
export const flightsHandlers = [
|
|
http.get('/api/flights', () => jsonResponse(seedFlights)),
|
|
|
|
http.get('/api/flights/:id', ({ params }) => {
|
|
const flight = seedFlights.find((f) => f.id === params.id)
|
|
if (!flight) return new Response(null, { status: 404 })
|
|
return jsonResponse(flight)
|
|
}),
|
|
|
|
http.post('/api/flights', async ({ request }) => {
|
|
const body = (await request.json()) as Record<string, unknown>
|
|
return jsonResponse({ id: 'flight-new', createdDate: new Date().toISOString(), ...body }, { status: 201 })
|
|
}),
|
|
|
|
http.put('/api/flights/:id', async ({ request, params }) => {
|
|
const body = (await request.json()) as Record<string, unknown>
|
|
return jsonResponse({ id: params.id, ...body })
|
|
}),
|
|
|
|
http.delete('/api/flights/:id', () => noContent()),
|
|
|
|
http.get('/api/flights/:id/waypoints', ({ params }) =>
|
|
jsonResponse([
|
|
{
|
|
id: 'wp-1',
|
|
flightId: params.id,
|
|
name: 'WP1',
|
|
latitude: 50.45,
|
|
longitude: 30.52,
|
|
order: 1,
|
|
},
|
|
]),
|
|
),
|
|
|
|
http.post('/api/flights/:id/waypoints', async ({ request, params }) => {
|
|
const body = (await request.json()) as Record<string, unknown>
|
|
return jsonResponse({ id: 'wp-new', flightId: params.id, ...body }, { status: 201 })
|
|
}),
|
|
|
|
http.get('/api/flights/:id/live-gps', ({ params }) =>
|
|
sse([
|
|
{ event: 'gps', data: { flightId: params.id, lat: 50.45, lon: 30.52, t: 0 }, id: '1' },
|
|
{ event: 'gps', data: { flightId: params.id, lat: 50.46, lon: 30.53, t: 1000 }, id: '2' },
|
|
{ event: 'gps', data: { flightId: params.id, lat: 50.47, lon: 30.54, t: 2000 }, id: '3' },
|
|
]),
|
|
),
|
|
|
|
// Production uses the plural path `/api/flights/aircrafts`. Singular alias kept
|
|
// for any future test that follows REST-singular conventions; production paths win.
|
|
http.get('/api/flights/aircrafts', () => jsonResponse(seedAircraft)),
|
|
http.get('/api/flights/aircraft', () => jsonResponse(seedAircraft)),
|
|
|
|
http.patch('/api/flights/aircrafts/:id', async ({ request, params }) => {
|
|
const body = (await request.json()) as Record<string, unknown>
|
|
return jsonResponse({ id: params.id, ...body })
|
|
}),
|
|
|
|
// POST accepts both plural and singular paths. Production convention is
|
|
// plural (REST collection); singular kept as a backward-compat alias.
|
|
http.post('/api/flights/aircrafts', async ({ request }) => {
|
|
const body = (await request.json()) as Record<string, unknown>
|
|
return jsonResponse({ id: 'AC-NEW', ...body }, { status: 201 })
|
|
}),
|
|
http.post('/api/flights/aircraft', async ({ request }) => {
|
|
const body = (await request.json()) as Record<string, unknown>
|
|
return jsonResponse({ id: 'AC-NEW', ...body }, { status: 201 })
|
|
}),
|
|
]
|