Offline mode
The cleaner app is a PWA with a service worker — it works when the device is offline.
What runs offline
- Reading the current task's checklist (cached when the app first loaded).
- Marking items done, skipped, with photos or notes.
- Reporting an issue (photos + voice + text — all queued locally).
- Bulk-mark (queues per-item completions).
What does NOT run offline
- Opening a different task (the dispatch link needs the server).
- Login (OTP needs the server).
- Sending the operator digest (queued; sent on reconnect with timestamp = original completion time).
Sync indicator
The header shows one of three states:
Online— all writes go straight to the server.Offline · N changes queued— N writes waiting locally.Syncing… N left— reconnect in progress, draining the queue.
What the cleaner sees on reconnect
When the device comes back online, the queue drains in order. Each write keeps its original timestamp — the server records the action as having happened when the cleaner did it, not when sync ran.
If a write fails on the server (rare — e.g. the task was already closed by the operator), the cleaner sees a toast: 1 change couldn't sync — tap to see details. Tapping opens a per-change view with the reason; the cleaner can copy the photos out before the local queue clears.
What about the basement lift
Designed for exactly this case: signal drops in the basement, cleaner keeps marking items, reception comes back at the lobby. No data lost.
The queue is bounded — up to 200 actions or 50 MB of media. Above that, the oldest queued non-photo actions drop first (photos always preserved). In practice this only matters if the cleaner stayed offline for hours; a typical cleaning hits 20-30 actions.
Implements: gh#524 Slice 3 (offline queue + service worker).