L13 Planung: Menüpunkt Planung mit Plantafel und Live-Lage

Plantafel: Standard heute + nächste 4 Werktage (Kolonnen als Zeilen, heutige Spalte mit Live-Status), Heute mit Kolonnen als parallelen Spalten (6–20 Uhr), Woche/nächste Woche, Auslastung, Konflikte/Hinweise, Verzugs- und Gefährdungs-Badges, Drag & Drop (@dnd-kit/core) mit Bestätigungs-Popover und Tastatur-Alternative, ungeplante Aufträge mit Vorschlägen, früher fertig mit Vorziehen, Kolonnenkapazität-Popup. Live-Lage: Leaflet/OSM-Karte mit einem Marker je Kolonne, Liste, Polling 30 s, Hinweis keine GPS-Ortung; CSP img-src für Kacheln. Dashboard-Kacheln Planung heute und Konflikte diese Woche, Einsatz-Vorschläge im Auftragsdetail, Navigation mit Unterpunkten, Smoke-Prüfungen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-15 10:13:50 +02:00
co-authored by Claude Opus 5
parent 5e10523df6
commit ee17134863
25 changed files with 2557 additions and 3 deletions
+19
View File
@@ -99,6 +99,17 @@ function plans(x: Awaited<ReturnType<typeof ids>>): Plan[] {
{ path: "/search?q=Elbblick", mustContain: "Elbblick", perf: true },
{ path: "/teams" },
{ path: "/settings/users", expect: [200, 307, 403] },
// L13 Planung
{ path: "/planning", mustContain: ["Plantafel", 'data-planning-view="days"', 'data-day-count="5"', "Heute", "Team Nord", "Team Süd", "Ungeplante Aufträge"], perf: true },
{ path: "/planning?view=today", mustContain: ['data-planning-view="today"', "Ganztägig", "Team Nord", "Team Süd"] },
{ path: "/planning?view=week", mustContain: ['data-planning-view="week"', 'data-day-count="7"'] },
{ path: "/dashboard", mustContain: ["Planung heute", "Teams im Einsatz"] },
{ path: `/planning?schedule=${x.d07.id}`, mustContain: "Plantafel" },
{ path: "/planning/live", mustContain: ["Live-Lage", "keine GPS-Ortung", "OpenStreetMap"], mustNotContain: ["startLat", "startLng"], perf: true },
{ path: "/api/v1/planning/board", mustContain: ['"teams"', '"conflictCount"'] },
{ path: "/api/v1/planning/live", mustContain: '"technicians"', mustNotContain: ["startLat", "startLng", "deviceInfo"] },
{ path: `/api/v1/planning/recommendations?workOrderId=${x.d07.id}`, mustContain: '"recommendations"' },
{ path: "/dashboard", mustContain: "Konflikte diese Woche" },
],
},
{
@@ -113,6 +124,9 @@ function plans(x: Awaited<ReturnType<typeof ids>>): Plan[] {
{ path: "/reports" },
...(x.inReview ? [{ path: `/reports/${x.inReview.id}`, mustContain: x.d16?.number }] : []),
{ path: m(x.d08), expect: [404] },
// L13 Planung: team lead read-only, own team only
{ path: "/planning", mustContain: ["Plantafel", "Team Nord", "Nur Lesezugriff"], mustNotContain: ["Team Süd"] },
{ path: "/planning/live", mustContain: "keine GPS-Ortung", mustNotContain: ["Team Süd"] },
],
},
{
@@ -141,6 +155,8 @@ function plans(x: Awaited<ReturnType<typeof ids>>): Plan[] {
{ path: m(x.d08), expect: [404] },
{ path: `/customers/${x.foreignCustomer.id}`, expect: [404, 307] },
{ path: "/dashboard", expect: [307, 308], redirectTo: "/m" },
{ path: "/planning", expect: [404] },
{ path: "/planning/live", expect: [404] },
],
},
{
@@ -167,6 +183,9 @@ function plans(x: Awaited<ReturnType<typeof ids>>): Plan[] {
...(x.emergency ? [{ path: `/work-orders/emergency-review/${x.emergency.id}`, expect: [404] }] : []),
...(x.imp ? [{ path: `/imports/${x.imp.id}`, expect: [404] }] : []),
...(x.photo ? [{ path: `/files/${x.photo.documentId}`, expect: [404] }] : []),
{ path: "/planning", mustNotContain: ["Team Nord", x.d07.number] },
{ path: "/planning/live", mustNotContain: ["Team Nord", "Max Monteur"] },
{ path: `/api/v1/planning/recommendations?workOrderId=${x.d07.id}`, expect: [404] },
],
},
];