Commit graph

54 commits

Author SHA1 Message Date
Eddy
ad8779ce75 Feature: Neuer-Auftrag-Formular — Ihr Zeichen Pflicht, Liefertermin, Freigabe [deploy]
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 13s
- Feldreihenfolge getauscht: "Ihr Zeichen" (ref_client) jetzt an erster
  Stelle und Pflicht; "Auftragsbeschreibung" (Titel) an zweiter Stelle
  und optional (vorher genau umgekehrt)
- Neues Feld "Geplanter Liefertermin" (datetime-local -> date_livraison)
- Neue Checkbox "Auftrag direkt freigeben" (validate-Flag ans Backend)
- Erfolgsmeldung zeigt Freigabe-Status bzw. Warnung aus dem Backend
2026-07-18 13:35:41 +02:00
Eddy
125e2fd196 PWA-Login: Fingerabdruck-/Passkey-Anmeldung (WebAuthn) [deploy]
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 13s
Zweiter, gleichwertiger Login-Weg neben Passwort — nutzt die zentrale
awlauth-WebAuthn-JS (/custom/awlauth/js/awlauth-webauthn.js), analog zum
Stundenzettel-Pilot.

- Script-Einbindung nach app.js in index.php (same-origin, /custom/awlauth).
- Neuer Button "Mit Fingerabdruck anmelden" im Login-Template (app.js),
  type="button", versteckt bis awlauthWebAuthn.isSupported() true ist.
- Klick-Handler: awlauthWebAuthn.login() -> bei Erfolg Profil aus dem
  Login-Result in idb('user') ablegen (wie api.login es tut, sonst zeigt
  Einstellungen nach reinem Passkey-Login "Unbekannt") -> showToast +
  router.go('#/orders') wie der Passwort-Login-Pfad.
- Passkey ist domainweit (RP awl.data-it-solution.de): ein z.B. ueber
  Stundenzettel registrierter Passkey funktioniert hier direkt mit.

Lokal verifiziert: php -l / node --check sauber, Playwright + Virtual-
Authenticator (CDP) — Button korrekt sichtbar/gestylt (eigene Dark-Palette),
Klick loest webauthn_login_options.php (200) aus, Fehlerpfad reaktiviert den
Button, bleibt auf #/login, 0 Console-Errors. Adversarialer Code-Review fand
1 kosmetischen Befund (fehlendes idb-Profil) — bereits gefixt.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 15:41:37 +02:00
Eddy
b8ed5f2276 PWA-Login: Passwort-Sichtbar-Toggle (Auge-Icon)
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 13s
Auge-Button im Passwort-Feld schaltet zwischen Klartext und Punkten um.
Hilft Tippfehler zu vermeiden (z.B. bei EN-Tastaturlayout via Remote-Desktop).

[deploy]
2026-07-06 16:16:10 +02:00
Eddy
17575f38e4 Baustelle-PWA: SSO-Migration auf awlauth (JWT -> awl_sso-Cookie)
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 13s
- lib/api.js request(): Authorization:Bearer raus, X-Requested-With +
  credentials:same-origin rein (Vanilla fetch setzt X-Requested-With nicht
  automatisch -> ohne ihn 403 an awlauth_require).
- login(): kein setToken mehr (Session im HttpOnly-Cookie); logout() ruft
  jetzt /logout.php (Single-Logout).
- Blob-Loader (photo/pdf/file/shipment-pdf): jwt-Query raus, credentials rein;
  Shipment-PDF setzt zusaetzlich X-Requested-With (shipments.php=CSRF).
- app.js: ensureAuth() prueft /verify.php (offline nicht ausloggen),
  Token-Preload raus, confirm-POST mit X-Requested-With, Audio-/PDF-Download
  ohne jwt-Query.

[deploy]
2026-07-06 15:25:53 +02:00
Eddy
3608fef216 Doku: README auf Live-Kamera + Persist-First, korrekter Deploy-Pfad/URL, Struktur
All checks were successful
Deploy baustelle-pwa / deploy (push) Has been skipped
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-03 11:33:23 +02:00
Eddy
5e7b1a9ec7 Feature: Live-Kamera (Schnellschuss + Filmstreifen), Datenverlust-Schutz (Persist-First) [deploy]
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 14s
- Kamera bleibt nach jedem Schnappschuss offen (getUserMedia Live-Video statt
  native capture-Input, der nach jedem Foto schliesst)
- Filmstreifen mit Status-Badges pro Foto (💾 gesichert →  lädt hoch → ✓ fertig)
- Persist-First: Foto zuerst in IndexedDB schreiben, Upload erst danach
- Foto verlässt Queue NUR nach HTTP-2xx mit gültigem relpath
- 2xx-HTML (abgelaufene Session, Proxy-Loginseite) wird als Fehler erkannt
- HTTP-Status auf Error-Objekt: 5xx/429/408 sind transient (nicht quarantänisiert)
- 45-Sekunden-Upload-Timeout via AbortController
- Quarantäne nach 6 Fehlversuchen, Recovery via Status-Badge-Tipp
- Beforeunload-Warnung wenn Fotos noch nicht gesichert
- idb.queueUpdate() für state-preserving ItemUpdates ohne Datenverlust

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-03 10:46:36 +02:00
Eddy
fdd0ab163d Trigger: Deploy [deploy]
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 13s
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 07:58:48 +02:00
Eddy
0e019d40b7 Doku: README um Lieferungen + Kundenunterschrift erweitert
- Features-Liste: Lieferschein-Vorschau, Vollbild-Querformat-Signatur, GPS,
  Auto-Validate/Close der Expedition
- API-Liste: /shipments.php (order_id list, detail, pdf, confirm)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 07:58:06 +02:00
Eddy
9e5b531ae5 CI: Ntfy-Benachrichtigungen (Start/Success/Failure) via data/ntfy-action
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 13s
[deploy]

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 06:54:44 +02:00
Eddy
e9b5b05b16 Feature: Lieferungen-Liste + Vollbild-Signatur-Modal
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 5s
- Neue Route #/orders/:id/shipments: Lieferungen zum Auftrag laden und anzeigen
- Neue Route #/shipments/🆔 Lieferschein-PDF inline (alle Seiten via PDF.js), Button Unterschreiben
- Vollbild-Landscape-Signatur-Modal: Fullscreen-API + screen.orientation.lock, HiDPI-Canvas
- Canvas transparent (kein fillRect), trimCanvasToInk() schneidet auf bemalte Fläche
- Name des Unterzeichners vorausgefüllt mit Kundenname aus Order
- POST api/shipments.php?action=confirm: Signatur-PNG + signer_name + GPS
- GPS-Abfrage (timeout 3s, graceful bei Verweigerung)
- Signed-PDF direkt nach Bestätigung anzeigen (?variant=signed)
- Fehlermeldung im Modal (kein hinter Fullscreen versteckter Toast)
- lib/api.js: listShipments, getShipment, getShipmentPdfBlobUrl, confirmShipment

[deploy]

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 06:48:56 +02:00
Eddy
2c32093090 Trigger: Deploy README-Update [deploy]
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 5s
2026-04-18 12:43:50 +02:00
Eddy
d51eed49f2 Doku: README um neue Features (Share, Mehrfachauswahl, Back-Button) ergänzt
All checks were successful
Deploy baustelle-pwa / deploy (push) Has been skipped
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 12:43:42 +02:00
Eddy
0a78d9e5d9 PWA: Dokumente (PDFs) in Mehrfachauswahl + Back-Button schließt Auswahl [deploy]
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 4s
- PDFs/Dokumente lassen sich jetzt auch im Auswahl-Modus markieren und
  mitteilen (bisher öffnete der Tap immer den Viewer)
- ☑ Auswählen-Button erscheint auch wenn nur Dokumente vorhanden sind
- Android-Zurück-Button im Select-Modus: hebt die Auswahl auf und
  beendet den Auswahl-Modus (statt die Seite zu verlassen)
- ✕ Abbrechen-Button nutzt denselben History-Back-Pfad

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 12:38:06 +02:00
Eddy
427fdeb0c0 PWA: Android-Zurück-Button-Fix + Datei-Teilen via Share-Sheet [deploy]
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 5s
- Modal-Stack mit History-API: jedes Modal pusht einen History-Eintrag,
  Android-Zurück schließt das Modal statt die App zu beenden
- Top-Level-Routen: "Nochmal drücken zum Beenden"-Toast (2s Fenster)
- shareFile()/shareFiles(): native Android-Share-Sheet für Fotos, PDFs, Dokumente
- Multi-Select in Fotogalerie: Mehrere Fotos gleichzeitig auswählen und teilen
- PDF-Teilen: auto-.pdf-Extension damit Android-Apps die Datei akzeptieren
- openPdfModal: Share-Button neben Download-Button

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 12:33:31 +02:00
Eddy
8be49c279f Fix: Nutze window.pdfjsLib statt window.pdfjs [deploy]
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 5s
2026-04-17 13:13:10 +02:00
Eddy
e2bcb8250e Debug: Detailliertes Logging für PDF.js Init [deploy]
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 5s
2026-04-17 13:12:38 +02:00
Eddy
9930ad2345 Fix: PDF.js-Pfad absolut (/custom/bericht/js/lib/) [deploy]
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 4s
2026-04-17 13:11:59 +02:00
Eddy
cef7c35075 Fix: Lade PDF.js vom Bericht-Modul (js/lib/pdf.min.js) [deploy]
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 5s
2026-04-17 13:11:25 +02:00
Eddy
99cd5876b4 Fix: PDF.js Worker-Pfad SOFORT nach Script-Load setzen [deploy]
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 5s
2026-04-17 13:07:49 +02:00
Eddy
99c5537a2d PWA: Mehr Debug-Logs für File-Viewer (zeigt ob PDF.js geladen ist) [deploy]
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 5s
2026-04-17 13:07:01 +02:00
Eddy
69f50b0fe5 PWA: PDF-Viewer mit ausführlichem Debug-Logging [deploy]
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 5s
2026-04-17 13:04:11 +02:00
Eddy
e579523020 PWA: PDF-Download über API (Content-Disposition, kein Dialog) [deploy]
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 5s
2026-04-17 12:56:22 +02:00
Eddy
0294509ee5 Fix: PDF-Download-Button zeigt kein Dialog, nur Download [deploy]
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 5s
2026-04-17 12:54:07 +02:00
Eddy
125a6302ab PWA: PDF-Viewer mit PDF.js (inline, kein Download nötig) [deploy]
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 5s
2026-04-17 12:52:47 +02:00
Eddy
a192cbfa27 Fix: PDFs + Dokumente direkt zum Download (kein problematischer iframe) [deploy]
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 4s
2026-04-17 12:50:51 +02:00
Eddy
a538dbb744 PWA: Weitere Dokumente anzeigen + öffnen (PDF-Viewer, Download) [deploy]
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 6s
- otherDocs-Sektion mit gestylten doc-items (Icon, Name, Größe, Datum)
- getFileBlobUrl() in api.js ohne Mime-Filter
- PDF/Bilder: Fullscreen-Modal mit iframe/img + Download-Button
- Andere Dateitypen: direkter Download
- CSS analog zu .audio-item

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-04-17 12:49:15 +02:00
Eddy
46f680039d [deploy] Layout-Fix: FAB aus #app-Flex-Container lösen + padding-bottom
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 4s
Der FAB hing als Kind im #app Flex-Layout (display:flex, column) und hat
die bottom-nav nach unten gedrängt. Jetzt sitzt er auf Body-Ebene,
beeinflusst kein Flex mehr. Zusätzlich hat #main padding-bottom:90px
damit der letzte Listeneintrag nicht vom FAB verdeckt wird.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 17:47:29 +02:00
Eddy
d4e4d09366 [deploy] Schnell-Auftrag-Erfassen via FAB + Login-Persistenz-Fix
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 5s
- FAB unten rechts (halbtransparent) öffnet Fullscreen-Modal zur
  Auftrags-Anlage: Kundensuche mit Debounce und "Zuletzt verwendet"-
  Quick-Pick aus IndexedDB → Anzeige der übernommenen Defaults →
  Titel + optional Kunden-Ref → direkter Sprung auf #/orders/<id>
  wo die Fotos aufgenommen werden können.
- appBoot() preloadet das JWT aktiv aus IndexedDB bevor der Router
  läuft — fixt "nach App-Neustart immer wieder einloggen müssen".
- setNav() steuert zusätzlich die FAB-Sichtbarkeit mit.
- api.createOrder() als neuer Wrapper für POST /orders.php?action=create.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 17:44:14 +02:00
Eddy
cb8dc396b3 Kunden-Bestellnr. in Auftragsliste anzeigen
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 5s
- ref_client wird neben Auftragsnummer angezeigt (wenn vorhanden)
- CSS-Styling für .ref-client

[deploy]

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-04-16 10:49:49 +02:00
Eddy
295ac82f43 Toggle "Auch abgeschlossene" für Auftragsliste + Doku aktualisiert
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 5s
PWA:
- Checkbox in /orders Route hinzugefügt
- Filter in localStorage persistiert
- CSS für .filter-toggle

Doku:
- README.md komplett aktualisiert mit allen Features
- API-Dokumentation erweitert

[deploy]

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-04-16 10:45:25 +02:00
Eddy
0a9c4d4db3 [deploy] Bild-Viewer mit Pinch-Zoom, Swipe und Navigation
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 0s
- Pinch-to-Zoom (2 Finger)
- Doppeltap für Zoom-Toggle
- Swipe links/rechts zum Bildwechsel
- Navigation-Buttons + Counter
- Tastatur: Pfeiltasten + Escape

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-04-13 13:26:56 +02:00
645624eeb6 Bericht löschen: Button + Dialog in Report-Detail, api.deleteReport() [deploy]
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 1s
- Lösch-Button (rot) unter Report-Detail
- Eigener Bestätigungs-Dialog (kein browser-confirm())
- api.deleteReport(id) → DELETE /reports.php?id=X
- CSS: .btn-danger Klasse

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 15:33:32 +02:00
3dad52367c feat: PWA Block D — Mess-Werkzeug, Materialliste, Heute-Tab, ntfy-Push
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 1s
5.4 Mess-Werkzeug mit Skala-Kalibrierung:
- Zwei neue Sketch-Tools: 📏⚙ Kalibrieren + 📏 Messen
- Kalibrieren: 2 Punkte ziehen → reale Länge eingeben (cm/m/mm)
- Messen: 2 Punkte ziehen → Live-Distanz-Label mit berechnetem Wert
- pxPerUnit + unit werden im State gehalten, Linie im Canvas gezeichnet

5.9 Materialliste pro Auftrag:
- 📦 Materialliste-Button im Auftrags-Detail
- Modal: Bezeichnung + Menge + Einheit (Stk/m/m²/kg/l/Set/Pa/h) + Notiz
- Live-Liste mit Löschen pro Eintrag

5.8 Tages-Baustellen-Map:
- Neuer Bottom-Nav-Tab ☀️ Heute (ganz links)
- Filtert Aufträge nach heutigem Datum
- Route-Button öffnet Google Maps mit allen heutigen Adressen als Waypoints
- Darunter noch die offenen Aufträge als Backup

4.d Benachrichtigungen via ntfy (statt VAPID):
- Settings → Benachrichtigungen: ntfy-Server + Topic
- EventSource auf /topic/sse → native Browser-Notifications
- Test-Nachricht-Button sendet POST an das Topic
- Auto-Reconnect bei Fehlern nach 10s
- Auto-Start beim Boot wenn Topic gesetzt und Permission granted

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
[deploy]
2026-04-09 09:18:31 +02:00
54eea0fb22 feat: Block C — Seiten-Titel + api.request exposed
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 1s
- openPageActionsModal bekommt Titel-Feld (wird im PDF groß oben auf
  der Seite gedruckt, wenn gesetzt) zusätzlich zur Notiz
- Save sendet beide Felder zusammen via api.request POST
- Seiten-Thumbs zeigen Titel als Badge unten (ellipsis bei langem
  Text)
- lib/api.js exposed request() als Low-Level-Funktion für
  Spezialfälle wie dieses Update

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
[deploy]
2026-04-09 09:10:57 +02:00
31a690454c feat: PWA Schnell-Bericht + Template-Dropdown + Whisper-Transkribieren
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 1s
Schnell-Bericht-Modal (Phase 4.a + 4.i):
- '📑 Neuen Bericht anlegen…' Button im Auftrags-Detail
- openNewReportModal: Titel, Format/Orientation, Vorlage-Dropdown,
  ODT-Deckblatt-Dropdown
- Auto-Select der Default-ODT-Vorlage aus Admin-Config
- api.createReport() als Wrapper für /reports.php?action=create
- api.listTemplates() + api.listOdtTemplates()

Whisper-Transkription (Phase 5.7):
- Neuer 📝-Button je Audio-Item
- Tap → api.transcribeAudio(relpath) → Server ruft Whisper-Endpoint
- Transkribierter Text erscheint direkt unter dem Audio-Player
- Text ist wählbar und kann kopiert werden

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
[deploy]
2026-04-09 08:27:46 +02:00
0e8ebed717 feat: PIN-Schutz + Seiten-Reorder + Stamps
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 1s
4.c PIN-Schutz (optional):
- Settings → Sicherheit → Toggle aktiviert PIN
- 4-stelliger Keypad-Dialog (promptPin/promptNewPin)
- SHA256 mit random Salt, beides in IndexedDB
- appBoot() Lockscreen vor Router-Start
- PIN ändern, deaktivieren jederzeit möglich
- Logout löscht PIN-Daten

4.f Seiten umsortieren:
- Long-Press (500ms) auf Seiten-Thumb → Drag-Modus
- Touch-basierter Reorder mit elementFromPoint
- Vibrationshinweis beim Drag-Start
- Beim Release: api.reorderPages + Nummern-Badges updaten

5.1 Stamps im Sketch-Editor:
- Vier vordefinierte Stempel in der Toolbar:
  ⚠ Achtung, ✓ OK, ✗ Mangel, 🔧 Reparatur
- Ein-Klick-Platzierung, Farbe aus Color-Picker,
  weißer Outline damit sie auf jedem Bild sichtbar sind
- 96px Bold-Font

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
[deploy]
2026-04-09 08:18:53 +02:00
503d36bd09 feat: Kundenkarten-Tab + Unterschriften-Härtung im Signature-Modal
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 0s
Kundenkarten:
- Neuer Bottom-Nav Eintrag '👥 Kunden'
- /customers Route: Liste mit Suche, gefiltert über api/customers.php
- /customers/:id Route: Stammdaten mit Click-to-Call, Click-to-Mail,
  Google-Maps-Route-Button, Listen für Aufträge/Berichte/Rechnungen
  mit Mini-Card-Layout
- Mini-Cards navigieren zum jeweiligen Auftrag/Bericht
- formatDate + formatEur Helper (de-DE Locale)

Unterschriften-Härtung (Signature-Modal):
- Pflicht-Input für Signer-Name
- GPS-Checkbox (default an) — fragt navigator.geolocation ab
- Rechtstext als Hinweis
- Beim Save: Name + GPS werden an api.uploadSignature übergeben
- Server brennt Metadaten, Hash und GPS in die PNG ein

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
[deploy]
2026-04-09 08:06:22 +02:00
d19e4eb41e feat: 📲 Install-Button in Topbar — umgeht Chrome Engagement-Heuristik
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 1s
Chrome zeigt 'App installieren' im Menü erst nach mehrmaligem Besuch
mit User-Interaktion. Das ist die sog. Site-Engagement-Heuristik —
keine technische Voraussetzung, sondern UX-Gate.

Workaround: beforeinstallprompt-Event abfangen und manuell auslösen.

- 📲 Install-Button in Topbar (standardmäßig versteckt)
- Bei beforeinstallprompt: Event speichern, Button anzeigen
- Klick → prompt() aufrufen → Install-Dialog öffnet sich
- appinstalled-Event: Button wieder verstecken
- iOS-Fallback: Hinweis zum manuellen 'Zum Home-Bildschirm'

Damit ist die Install-Funktion jederzeit sichtbar und nutzbar,
unabhängig davon wie oft der User die Seite vorher besucht hat.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
[deploy]
2026-04-09 01:31:16 +02:00
7c9563ec90 feat: PWA Cache-Busting via filemtime (claude-db #201) — kein manuelles Hochzählen mehr
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 1s
Das bisherige 'CACHE = baustelle-vN' Pattern erforderte, dass ich bei
jeder Änderung drei Stellen synchron halte (sw.js, index.html ?v=,
manifest). Eddy hat klargestellt dass das nicht akzeptabel ist.

Fix nach KB #201 Pattern (referenz: dolibarr.stundenzettel v2.2.0):

1. index.html → index.php
   PHP berechnet bei jedem Request filemtime() von app.css, app.js,
   lib/*.js, manifest.webmanifest. Die mtimes kommen automatisch
   beim Deploy (rsync preserviert sie default) und werden als ?v=
   an alle Asset-URLs gehängt.

2. sw.js liest Version aus eigener URL-Query:
   const SW_VERSION = (new URL(self.location.href)).searchParams.get('v')
   const CACHE = 'baustelle-' + SW_VERSION
   activate() löscht alle caches die mit 'baustelle-' anfangen aber
   nicht der aktuelle sind.

3. Client-Registration mit Auto-Update:
   - setInterval 60s reg.update()
   - visibilitychange-Listener für Tab-Fokus
   - updatefound → SKIP_WAITING postMessage
   - controllerchange → einmaliger location.reload

4. SHELL pre-cache enthält nur statische Dateien (index.php, share.html,
   icons). CSS/JS werden beim ersten fetch dynamisch gecached — so
   gibt es keinen Mix zwischen alten und neuen ?v= Versionen.

5. manifest.webmanifest start_url auf /custom/baustelle/index.php

Ergebnis: Ich deploye → mtime ändert sich → neue URLs → Browser holt
frische Files → SW aktiviert automatisch beim nächsten Tab-Fokus.
Nie wieder manuelles Hochzählen.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
[deploy]
2026-04-09 01:26:26 +02:00
5e80d78f41 fix: Manifest-Installability-Kriterien für Chrome Android
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 1s
Chrome Android zeigte nur 'Zum Startbildschirm hinzufügen' statt
'App installieren', weil:
1. 'any maskable' als kombinierter purpose reicht Chrome nicht —
   braucht mindestens ein reines 'any'-Icon für den Install-Prompt
2. start_url/scope waren relativ (./) — mit absoluten Pfaden zum
   custom/baustelle/-Root ist der Scope eindeutig

Fixes:
- icons: je 192/512 als 'any' UND zusätzlich als 'maskable' (4 Einträge)
- id, start_url, scope auf '/custom/baustelle/' gesetzt (absolut)
- categories, dir: ltr dazu für vollständiges Manifest

Damit erfüllt die PWA die Chrome-Installability-Kriterien und der
Menü-Eintrag wird zu 'App installieren'. Erst dann funktioniert
auch Web Share Target.

Cache v10.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
[deploy]
2026-04-09 01:21:59 +02:00
f2c41059a6 fix: Service Worker nach claude-db #31 Pattern (Network-First + Auto-Update)
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 1s
Problem: User sehen alte Version weil der SW Cache-First ausliefert
und neue Versionen nur nach App-Neustart aktiv werden.

Fix (Pattern aus PWA Best Practices in claude-db #31):
- Network-First für alle eigenen Assets (fetch → ok → cache update,
  bei offline Fallback zum Cache). Vorher: Cache-First.
- self.skipWaiting() direkt nach Install
- self.clients.claim() nach Activate
- updatefound-Listener im index.html → bei neuem SW SKIP_WAITING
  senden, dann controllerchange-Event löst einmaligen Reload aus
- CSS/JS haben jetzt ?v=9 Query-String (Cache-Buster)
- Cache-Version 'baustelle-v9'

Damit zieht sich jede PWA beim nächsten Start automatisch die neueste
Version ohne manuellen Reinstall. Das Share-Target-Manifest-Caching
ist ein separates Android-Thema (dafür braucht's weiterhin Reinstall
der PWA beim ersten Mal).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
[deploy]
2026-04-09 01:17:57 +02:00
bb02fb247e fix: share_target action als absolute URL (Android-Fix)
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 1s
Laut martin.hjartmyr.se/articles/pwa-web-share-target-android/ ist
relativer action-Pfad ein bekannter Android-Stolperstein — der Share
Sheet zeigt die PWA nicht an obwohl das Manifest korrekt aussieht.

Fix: action auf volle URL setzen
(https://awl.data-it-solution.de/custom/baustelle/share.html).

Außerdem in params.files: explizite MIME-Types zusätzlich zu image/*
(image/jpeg, png, webp) — Chrome Android braucht MIME + Extension.

Service Worker v8 damit das neue Manifest geholt wird.

WICHTIG: PWA muss nach diesem Update komplett deinstalliert und neu
installiert werden, damit Android den Share-Target-Eintrag neu
registriert (Android cached hier sehr aggressiv).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
[deploy]
2026-04-09 01:15:46 +02:00
91a6560f7e feat: Neues PWA-Logo — Klemmbrett mit Schraubenschlüssel (SVG + PNG)
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 1s
Icon ersetzt das PHP/GD-generierte Placeholder durch ein echtes
Baustelle-Doku-Motiv:
- Dunkelblauer Radial-Gradient Hintergrund (rounded rectangle)
- Oranges Klemmbrett mit weißem Papier, Text-Zeilen und grüner
  Checkbox (symbolisiert fertige Arbeit)
- Metallische Klemme oben mit Riegel
- Blauer Schraubenschlüssel diagonal über dem Brett

SVG als Single-Source-of-Truth, PNG-Versionen in 192 und 512 px via
Chromium-Headless aus HTML-Wrapper gerendert (damit viewBox richtig
skaliert wird).

index.html verlinkt jetzt zusätzlich icon.svg als Favicon für Browser
die SVG-Favicons unterstützen.

SW-Cache auf v7.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
[deploy]
2026-04-09 01:12:47 +02:00
391777fdb4 fix: Web Share Target akzeptiert mehr Feldnamen (Android Gallery Varianten)
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 1s
Verschiedene Android-Gallery-Apps senden geteilte Bilder unter
unterschiedlichen Feldnamen — photos, file, files, image, images.
- Manifest listet jetzt alle drei Haupt-Feldnamen mit image/* accept
- Service Worker iteriert alle bekannten Keys UND macht einen Fallback
  über alle FormData-Entries für unbekannte Gallery-Apps
- Cache-Version v6 damit Browser Manifest neu liest

Wichtig: PWA muss nach diesem Update einmal deinstalliert und neu
installiert werden, damit Android das neue share_target registriert.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
[deploy]
2026-04-09 01:10:05 +02:00
02ffdca57c feat: Phase 4 Block 1 — Seite bearbeiten, PDF-Vorschau, Unterschrift, Share Target
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 1s
Bericht-Detail-Ansicht:
- Tap auf Seiten-Thumb → openPageActionsModal mit:
  - Vorschaubild
  - Textarea für Seiten-Notiz (wird im PDF unter der Seite gedruckt)
  - '💾 Notiz speichern' → api.updatePageNote
  - 🗑️ im Header → api.deletePage mit Confirm
- Seiten-Thumbs haben Nummer-Badge oben links (1, 2, 3…)
- Neuer '👁 PDF-Vorschau'-Button öffnet openPdfModal (iframe mit
  Blob-URL) für Final-PDF oder on-the-fly Preview
- Neuer '✍️ Kunden-Unterschrift hinzufügen'-Button öffnet
  openSignatureModal: Touch-Canvas 2:1, Clear, Save → PNG wird als
  neue Bericht-Seite mit note='Unterschrift Kunde' angelegt

Web Share Target API:
- manifest.webmanifest: share_target mit photos array
- share.html: empfängt geteilte Fotos aus IDB (vom SW befüllt),
  zeigt Auftragsliste, Tap → Upload aller Fotos
- Service Worker v5: fängt POST /share.html ab, schreibt Files in
  IDB Key 'shared_files', redirected 303

Cache-Version bumpt damit neue Files geladen werden.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
[deploy]
2026-04-09 01:00:24 +02:00
3f1b462105 feat: Hilfe-Button in Topbar mit kompletter Anleitung
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 1s
-Button oben rechts öffnet ein Vollbild-Modal mit:
- Auftragsfindung und Suche
- Fotos aufnehmen (Kamera/Galerie), Hinweis auf Entwurf-Akkumulation
- Skizzen-Editor (Pen/Pfeil/Rect/Ellipse, Undo, speichern)
- Sprachnotizen aufnehmen + abspielen
- Berichte finalisieren + Status-Erklärung
- Offline-Modus + Status-Badge-Legende
- Installation auf Home-Screen (Android + iOS)
- Einstellungen

Service Worker v4.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
[deploy]
2026-04-09 00:46:52 +02:00
bd9580bd46 fix: Finalisieren-Button immer sichtbar + Sprachnotizen eigene Sektion
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 1s
- Bericht-Detail: Button ist jetzt immer da, bei Final heißt er
  'PDF neu erzeugen'. Bei 0 Seiten disabled statt versteckt, mit
  Hinweis-Empty-State darüber.
- Auftrags-Detail: Audio-Files (webm/mp3/ogg/m4a/wav) werden aus
  'Weitere Dokumente' rausgefiltert und in eine eigene Sektion
  '🎙 Sprachnotizen' mit Play-Button je Eintrag gelegt. Tap auf ▶
  lädt die Datei als Blob (mit JWT) und setzt einen <audio>-Player
  inline ein.
- Service Worker v3.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
[deploy]
2026-04-09 00:43:27 +02:00
a1589a7ae2 feat: Phase 4 — Bericht-Liste, Detail, Foto-Vollbild, Voice, Sketch
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 1s
Der Reports-Tab listet alle Berichte des Users mit Status-Badge,
Quell-Referenz und Seitenzahl. Klick → Bericht-Detail mit:
- Meta (Titel, Format, Status, Seiten)
- Seiten-Thumbnails
- 'Bericht finalisieren' Button (triggert PDF-Generierung via API)
- 'Im Desktop-Editor öffnen' Link

Auftrags-Detail erweitert:
- Tap auf Foto-Thumb → Vollbild-Modal mit Löschen-Button und
  'Zeichnen'-Button (öffnet Skizzen-Editor)
- '🎙 Sprachnotiz aufnehmen' Button → Voice-Modal mit MediaRecorder,
  Live-Timer, Preview, Upload

Skizzen-Editor (Touch-fähig):
- Bild wird in canvas geladen, max 1600px
- Werkzeuge: Pen, Pfeil mit Spitze, Rechteck, Ellipse
- Farbe + Linienstärke
- Undo + Clear
- Speichern → rendert als JPEG und lädt als neue Bericht-Seite hoch

Service Worker Cache-Version auf v2 gebumpt.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
[deploy]
2026-04-09 00:31:39 +02:00
883ea17267 fix: PDF/sonstige Dateien aus Foto-Grid filtern
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 1s
Das Auftrags-Anhang-Verzeichnis enthält nicht nur Bilder sondern auch
das Auftrags-PDF. Das wurde von photo.php korrekt als application/pdf
ausgeliefert, aber die PWA zeigte einen roten Placeholder.

Fix: listOrderPhotos-Result vor dem Rendern nach mime-Type filtern.
Bilder kommen in die photo-grid, PDFs/andere Dokumente in eine
separate 'Weitere Dokumente'-Sektion darunter.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
[deploy]
2026-04-08 23:30:07 +02:00
40fbdb7370 fix: JWT als Query-Param bei photo.php (Apache filtert Header auf prod)
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 1s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
[deploy]
2026-04-08 23:27:27 +02:00