Files
verde-scanner/lib
admin 240c5f7adc feat(mobile-scanner): Phase 2 — offline buffer + manual entry
Two production must-haves for field staff: scans don't disappear
when signal drops, and there's a fallback when the camera can't
read a damaged QR.

Offline buffer:
- PendingScan model (local uuid + serial + DOP id + lat/lng +
  timestamp). JSON-encoded.
- ScanQueue: shared_preferences-backed FIFO, capped at 500 items
  (oldest dropped on overflow). API: readAll / add / removeByLocalIds
  / clear / count.
- ScanRepository.scan() now branches on outcome:
  - Server reachable + OK → accepted
  - Server reachable + 4xx with reason → rejected (duplicate /
    expired / invalid). NOT queued — these are permanent answers.
  - DioException / unexpected exception → enqueued + return
    networkError with "Saved offline · {message}".
- ScanSyncer: drains up to 100 items per call to /scanner/scan/bulk,
  removes the batch on success regardless of per-scan acceptance
  (the server has the canonical state now), reports
  (processed, accepted, kept) so the UI can announce the outcome.
- pendingCountProvider state syncs from disk via
  pendingCountInitProvider on home-screen mount.

Home screen surface:
- New amber "X scan(s) waiting to sync" banner appears whenever
  pending > 0. Has a "Sync now" button that runs ScanSyncer.drain()
  and shows a SnackBar with the result.

Manual entry:
- Keyboard icon in the camera-screen top bar opens the
  ManualEntrySheet (bottom sheet with a monospace input).
- Loose client-side validation against the PSGC serial format
  (PH-AREA-YYMM-BBBB-CCCCCC-XX). Strict validation happens server-side.
- Submitting goes through the same scan flow → same outcome
  feedback, same offline-queue behavior.
- Camera is paused while the sheet is up so the same code can't
  double-record.

Bug fix in scan_models:
- ScanResult.scannedAt is non-nullable; the constructor required
  it but had no default — analyzer was angry. Promoted to
  `required this.scannedAt`.

Tests still pass. flutter analyze: 6 style infos, no errors.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 23:55:51 +08:00
..