Skip to content

Invoice Expiry Countdown Banner with Snooze #441

Description

@Kingsman-99

Description

Invoices approaching their due date provide no proactive visual urgency to the payer or creator; the due date is a static field. This issue adds a dynamic expiry countdown banner on both the creator's /invoice/[id] view and the public payer page that shows a live countdown (days, hours, minutes) when the invoice is within 72 hours of its due date, transitions to a red "Overdue" state after the due date passes, and provides a snooze action that suppresses the banner for a configurable duration without modifying the invoice's actual due date.

Technical Context

Create components/invoice/ExpiryCountdownBanner.tsx that receives dueDate: string and computes time remaining using Date.now() inside a setInterval updating every minute. Display { days, hours, minutes } using a countdown format. Apply color transitions: amber for 72 hours or fewer remaining, red for overdue. The snooze action stores { invoiceId, snoozedUntil } in localStorage and suppresses the banner until snoozedUntil. The snooze duration options are: 1 hour, 4 hours, until tomorrow. On the creator side, wire the banner into app/invoice/[id]/page.tsx above the invoice header. On the public page (/pay/[invoiceId]), the same component is rendered but without the snooze option; payers always see the live countdown. Clear snooze state when the invoice is paid.

Acceptance Criteria

  • The banner appears automatically when the due date is within 72 hours, showing a live countdown that decrements every minute
  • The countdown transitions to a red "Overdue by [duration]" display immediately after the due date passes without requiring a page refresh
  • Selecting "Snooze for 1 hour" hides the banner and persists the snooze in localStorage; returning to the page within the snooze window keeps the banner hidden
  • After the snooze duration elapses, the banner reappears on the next minute tick
  • The snooze option is absent from the public payer page; payers always see the live countdown without the snooze control
  • All CI checks (npm test, npm run build, ESLint/TypeScript) pass and the branch has no merge conflicts

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions