Skip to content

Offline Invoice Draft Auto-Save and Recovery #438

Description

@Kingsman-99

Description

Users working on invoice drafts in areas with intermittent connectivity lose all their work when the connection drops and a form submission fails. This issue implements comprehensive offline draft auto-save using IndexedDB (via idb) that persists the full form state every 5 seconds while the user types, detects network availability changes, queues pending saves, and on reconnection uploads the draft to the server. A recovery banner on page load alerts users when an unsaved local draft exists and offers to restore it.

Technical Context

Create hooks/useOfflineDraftAutosave.ts that uses idb to open an invoiceDrafts object store. The hook serialises the current react-hook-form watch() state every 5 seconds via setInterval and writes it to IndexedDB under the key draft-[userId]-[draftId]. Monitor network status via window.addEventListener('online'|'offline'). When online, flush pending drafts to POST /api/invoices/drafts and clear the IndexedDB entry on success. On /invoice/new mount, check for existing local drafts and render components/invoice/DraftRecoveryBanner.tsx with "Restore Draft" and "Discard" options. Restoring calls form.reset() with the recovered data. Multiple draft tabs (same user, different invoices) must coexist in IndexedDB without collision using UUID-based draft keys.

Acceptance Criteria

  • Typing in the invoice form while offline auto-saves the draft to IndexedDB within 5 seconds; confirmed by reading the store in a unit test
  • Going offline mid-session does not block form interaction; an offline indicator badge appears but the form remains fully functional
  • On reconnection, queued drafts are automatically uploaded to the API and the IndexedDB entry is deleted on success
  • On page load with an existing local draft, the recovery banner appears and "Restore Draft" correctly populates all form fields to their saved state
  • Two browser tabs editing different invoices simultaneously each maintain independent draft entries in IndexedDB without overwriting each other
  • All CI checks (npm test, npm run build, ESLint/TypeScript) pass and the branch has no merge conflicts

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions