Mobile PWA für Baustellen-Doku — Foto-Upload, Sprachnotizen, Skizzen, offline-fähig. SvelteKit + Workbox.
|
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 14s
- Auth-Doku von JWT auf zentrales SSO (HttpOnly-Cookie awl_sso, same-origin) umgestellt: Stack, Feature-Login, lib-Beschreibung, /auth.php, photo.php/pdf.php (?jwt= entfaellt, Cookie wird same-origin auch fuer img/object mitgeschickt) - Feature 'Neuer Auftrag' dokumentiert (Ihr Zeichen/Beschreibung/Liefertermin/Freigabe) |
||
|---|---|---|
| .forgejo/workflows | ||
| icons | ||
| lib | ||
| .gitignore | ||
| app.css | ||
| app.js | ||
| index.php | ||
| manifest.webmanifest | ||
| README.md | ||
| share.html | ||
| sw.js | ||
Baustelle PWA
Mobile Progressive Web App für die Baustellen-Doku — Foto-Upload, Sprachnotizen, Skizzen, offline-fähig. Spricht die REST-API des Dolibarr-Bericht-Moduls.
Stack
- Vanilla JavaScript — kein Build, keine Framework-Abhängigkeit
- Service Worker für App-Shell-Cache (Workbox-frei, eigene Implementierung)
- IndexedDB für die Offline-Upload-Queue (Auth-Session steckt im HttpOnly-Cookie, nicht in IndexedDB)
- REST API des
bericht-Dolibarr-Moduls unter/custom/bericht/api/
Features
Aufträge
- ✅ Login mit Dolibarr-Credentials → zentrales SSO (HttpOnly-Cookie
awl_sso, same-origin; Single-Sign-On/-Logout über alle AWL-Apps). WebAuthn/Passkey-Login möglich - ✅ Auftragsliste mit Suche, gefiltert auf eigene Aufträge (Multi-User)
- ✅ Toggle "Auch abgeschlossene" (Filter in localStorage persistiert)
- ✅ Auftragsdetail mit Kunde, Adresse, Telefon (Click-to-Call)
- ✅ Neuer Auftrag (FAB): Kunde per Suche/Zuletzt-verwendet wählen, dann Ihr Zeichen (Pflicht), Auftragsbeschreibung (optional), Geplanter Liefertermin (Datum + Uhrzeit) und Checkbox Auftrag direkt freigeben. Kunden-Defaults (Zahlungsbedingung/Zahlart, Ansprechpartner) werden übernommen. Bei „direkt freigeben" hängt das Backend automatisch eine Std-Lohn-Zeile an (Kundenkarten-Default bzw. Fallback-Produkt, kundenspezifischer Preis) und validiert den Auftrag.
Foto-Upload
- ✅ Live-Kamera-Modal (getUserMedia): bleibt für Serien-Aufnahmen offen — Auslöser + Filmstreifen mit Upload-Status je Foto (💾 gesichert → ⏳ lädt hoch → ✓ fertig), Front-/Rückkamera-Umschaltung, Fehlschuss löschbar
- ✅ Alternativ Aufnahme aus der Galerie
- ✅ Clientseitige Bild-Verkleinerung auf 2000px (JPEG q=0.85)
- ✅ Persist-First / Datenverlust-Schutz: jedes Foto wird beim Auslösen ZUERST in IndexedDB gesichert, Upload erst danach; Queue-Item wird nur nach bestätigtem Upload (HTTP 2xx mit gültigem
relpath) gelöscht — überlebt fehlendes/schwaches Netz, hängende Uploads (45s-Timeout) und App-Kill. Erkennt 2xx-HTML (abgelaufene Session/Proxy-Loginseite) als Fehler statt als Erfolg - ✅ Auto-Sync bei "online", periodisch (15s) und bei App-Fokus; Status-Badge (🟢 alles gesichert / 🟡 lädt hoch / 🔴 offline / ⚠️ fehlgeschlagen)
- ✅ Recovery: Tipp auf das Status-Badge öffnet die Warteschlange → erneut senden / teilen; Warnung beim Schließen mit noch ungesicherten Fotos
- ✅ Foto-Viewer mit Zoom + Swipe
- ✅ Foto-Skizze: Annotationen mit Pfeilen, Kreisen, Rechtecken, Text
Sprachnotizen
- ✅ Sprachaufnahme via MediaRecorder (webm)
- ✅ Whisper-Transkription (serverseitig, API-Aufruf)
Berichte
- ✅ Berichte pro Auftrag anzeigen
- ✅ Bericht erstellen mit Template-Auswahl
- ✅ Seiten umordnen per Drag&Drop
- ✅ Seite löschen, Notiz bearbeiten
- ✅ Touch-Unterschrift abnehmen (mit GPS + Name)
- ✅ Bericht finalisieren → PDF-Vorschau
- ✅ PDF-Download
Lieferungen + Kundenunterschrift
- ✅ Lieferungen-Liste pro Auftrag mit Status + Signed-Badge
- ✅ Lieferschein-PDF inline (PDF.js, alle Seiten)
- ✅ Vollbild-Querformat-Unterschrift mit HiDPI-Canvas, transparent (kein Hintergrund)
- ✅ Trimmt Canvas automatisch auf bemalte Fläche
- ✅ Name des Unterzeichners aus Kundendaten vorausgefüllt
- ✅ GPS-Koordinaten (optional, timeout 3s)
- ✅ Unterschrift wird via ODT-Hook in das Lieferschein-PDF gestempelt
- ✅ Expedition wird nach Unterschrift automatisch validiert + geschlossen
- ✅ Signed-PDF direkt nach Bestätigung als Vorschau
Materialliste
- ✅ Material pro Auftrag erfassen (Label, Menge, Einheit, Notiz)
- ✅ Material löschen
PWA
- ✅ Service Worker für Offline-Start
- ✅ Installierbar als PWA (Home-Screen-Icon)
- ✅ Web Share Target API (Fotos aus anderer App teilen)
- ✅ Nativer Android-Share-Sheet für Fotos, PDFs und Dokumente (
navigator.share) — direkt an WhatsApp / Signal / Mail - ✅ Mehrfachauswahl in Foto- und Dokument-Liste mit Batch-Teilen
- ✅ Android-Hardware-Back-Button schließt Modale/Ansichten sauber (History-Modal-Stack), bricht Mehrfachauswahl ab statt App zu verlassen
- ✅ „Nochmal drücken zum Beenden"-Toast auf Top-Level-Routen
- ✅ PIN-Schutz (optional)
Geplant
- Push-Notifications für neue Aufträge
Hosting
Deploy per Forgejo-Pipeline (Commit-Tag [deploy]) nach /mnt/appdata/firma/dolibarr-202509/modules/baustelle/. Erreichbar unter https://awl.data-it-solution.de/custom/baustelle/. Cache-Busting automatisch via filemtime() in index.php (?v=<mtime> an JS/CSS) — kein manuelles Versions-Hochzählen nötig, die PWA aktualisiert sich beim nächsten Laden.
Verzeichnis-Struktur
baustelle-pwa/
├── index.php App-Shell (Cache-Busting via filemtime → ?v=<mtime>)
├── share.html Web-Share-Target-Empfänger
├── manifest.webmanifest PWA Manifest
├── sw.js Service Worker (Network-First, API pass-through)
├── app.js Hauptlogik (Routes, Views)
├── app.css Mobile-first Styling
├── lib/
│ ├── idb.js IndexedDB-Wrapper (Foto-Queue)
│ ├── api.js REST-API-Client (SSO-Cookie same-origin, JSON-Guard, Timeout)
│ ├── offline.js Offline-Queue + Sync (Persist-First)
│ ├── router.js Hash-Router
│ ├── pdf.min.js PDF.js (Lieferschein-Vorschau)
│ └── pdf.worker.min.js PDF.js Worker
└── icons/
├── icon-192.png
└── icon-512.png
API
Die App spricht die Bericht-API unter /custom/bericht/api/:
Auth
POST /auth.php— Login mit Dolibarr-Credentials → setzt HttpOnly-Cookieawl_sso(zentrales SSO via awlauth). Folge-Requests authentisieren same-origin über das Cookie (kein Bearer-Token)
Aufträge
GET /orders.php— Aufträge des Users (Filter:?open=1,?q=suche)GET /orders.php?id=X— Auftrag-Detail inkl. verknüpfte BerichteGET /orders.php?id=X&action=photos— Anhang-ListePOST /orders.php?id=X&action=upload_photo— Foto-Upload (multipart)
Kunden
GET /customers.php— Kundenliste (Filter:?q=suche)GET /customers.php?id=X— Kundendetail
Berichte
GET /reports.php— Alle Berichte des UsersGET /reports.php?id=X— Bericht-Detail mit SeitenPOST /reports.php?action=create— Neuen Bericht anlegenPOST /reports.php?id=X&action=finalize— Bericht finalisierenDELETE /reports.php?id=X— Bericht löschen
Seiten
DELETE /pages.php?id=X— Seite löschenPOST /pages.php?id=X— Seite aktualisieren (note, rotation)POST /pages.php?action=signature&bericht_id=X— Unterschrift hinzufügenPOST /pages.php?action=reorder— Seiten umordnen
Material
GET /materials.php?element_type=X&element_id=Y— MateriallistePOST /materials.php?element_type=X&element_id=Y— Material hinzufügenPOST /materials.php?id=X&delete=1— Material löschen
Lieferungen
GET /shipments.php?order_id=X— Lieferungen zu einem AuftragGET /shipments.php?id=X— Lieferung-Detail (inkl. bericht_id falls Unterschrift vorhanden)GET /shipments.php?id=X&action=pdf[&variant=auto|signed|unsigned]— Lieferschein-PDFPOST /shipments.php?id=X&action=confirm— Kunden-Unterschrift einstempeln (FormData mit signature_png, signer_name, gps_lat, gps_lon, signed_at). Backend setzt signed_status=1 und schließt die Expedition
Medien
GET /photo.php?relpath=X— Foto abrufen (mit Thumbnail:&size=thumb); Auth überawl_sso-Cookie (same-origin, auch für<img>-Tags — kein?jwt=mehr nötig)POST /delete_photo.php— Foto löschenPOST /voice.php?order_id=X— Sprachnotiz hochladenPOST /transcribe.php— Whisper-Transkription anfordernGET /pdf.php?id=X— PDF abrufen (Final oder Preview); Auth überawl_sso-Cookie (same-origin)
Templates
GET /templates.php— Bericht-VorlagenGET /odt_templates.php— ODT-Deckblatt-Vorlagen
Lizenz
GPL v3+