Skip to content

feat(watchlist): investor watchlist page with state-change alerts (#474) - #486

Open
solomonadzape95 wants to merge 5 commits into
StellarState:devfrom
solomonadzape95:feature/474-investor-watchlist
Open

solomonadzape95 wants to merge 5 commits into
StellarState:devfrom
solomonadzape95:feature/474-investor-watchlist

Conversation

@solomonadzape95

@solomonadzape95 solomonadzape95 commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Implements #474 — an investor watchlist page with recent state-change alerts and a bell toggle on every invoice card. The watchlist is read from the on-chain registry for the connected wallet, and add/remove calls are optimistic with rollback on failure.

Changes

  • /watchlist page (app/(dashboard)/watchlist/page.tsx) lists watched invoices as full InvoiceCards, with connect-wallet state, loading skeletons, error + retry, and an illustrated empty state whose CTA browses the marketplace.
  • State-change detection (lib/watchlist.ts) — pure detectStateChange() resolves Now Funded, Matured, Settled, or Now Open from an explicit registry transition, then invoice timestamps (funded_at/settled_at), then a funded invoice whose maturity just passed. Missing fields degrade to no badge instead of crashing.
  • StateChangeBadge (components/marketplace/StateChangeBadge.tsx) rendered by InvoiceCard.
  • Bell toggle (components/marketplace/WatchlistButton.tsx, bell / bell-ring) added to InvoiceCard; the invoice-detail header uses the labelled variant (components/invoices/WatchlistButton.tsx).
  • useWatchlist (hooks/useWatchlist.ts) reads fetchWatchlistRegistry(address), hydrates ids into invoices, and layers optimistic add/remove with snapshot rollback and an error toast.
  • API (lib/api/index.ts): registry-aware fetchWatchlistRegistry / watchInvoiceOnRegistry / unwatchInvoiceOnRegistry.
  • Routing: legacy /investor/watchlist redirects to /watchlist; MobileNav updated.

Acceptance criteria

  • Watched invoices listed correctly with accurate card data
  • State-change badges appear for invoices with recent state transitions
  • Bell toggle correctly adds and removes from watchlist on-chain
  • Empty state shown when watchlist is empty
  • Optimistic update reverts correctly on contract call failure

Testing

New coverage (21 tests):

  • lib/__tests__/watchlist.test.ts — state-change detection, recency window, graceful degradation
  • hooks/__tests__/useWatchlist.test.tsx — registry sync per wallet, optimistic add/remove, rollback + toast on failure
  • components/marketplace/__tests__/watchlist-button.test.tsx — bell states, watch/unwatch calls, disconnected disabled state
  • app/(dashboard)/watchlist/__tests__/watchlist-page.test.tsx — empty state, card listing + badge, connect-wallet prompt

Also fixed the pre-existing missing CompareToggleButton import in invoice-card.tsx and wrapped the two existing InvoiceCard tests with the providers the bell now needs.

Targeted run: npx vitest run lib/__tests__/watchlist.test.ts hooks/__tests__/useWatchlist.test.tsx components/marketplace/__tests__/watchlist-button.test.tsx "app/(dashboard)/watchlist/__tests__/watchlist-page.test.tsx" components/marketplace/__tests__/invoice-card.test.tsx components/marketplace/__tests__/invoice-card-suitability.test.tsx → 54 passed.

Note: dev currently has a number of pre-existing failing tests/build errors unrelated to this change. This branch does not introduce new failures (174 → 166 failing in the full suite, with the 8 fixed InvoiceCard tests and 21 new tests passing).

Closes #474


Note on the tsc --noEmit check

npx tsc --noEmit is red on this PR, but it is red on dev itself:

  • Clean origin/dev (1d6099f): 283 errors
  • This branch: 281 errors — i.e. it introduces none and fixes 2 (the duplicated CompareToggleButton import in invoice-card.tsx and its unused useComparison import).

All 281 remaining errors are pre-existing and unrelated to the watchlist. They stem from merge 88e43dc (PR #430) resolving lib/api/index.ts in a way that dropped ~40 functions still referenced elsewhere (fetchAdminUsers, transferInvoicePosition, fetchLeaderboard, uploadDocumentToIpfs, …), plus a handful of stale component/test typings. #487 (KYC tier) was merged with the identical failing check.

Happy to open a separate baseline-fix PR restoring the dropped lib/api exports and driving the type-check to zero — that is a large, repo-wide change and is kept out of this feature PR on purpose.

@drips-wave

drips-wave Bot commented Oct 18, 2026

Copy link
Copy Markdown

@solomonadzape95 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@TS-mfon

TS-mfon commented Oct 18, 2026

Copy link
Copy Markdown
Contributor

conflict

…ellarState#474)

- Add /watchlist page listing watched invoices as InvoiceCard components
- Sync watchlist from the on-chain registry via the connected wallet
- Surface recent state transitions (Now Funded / Matured / Settled) as badges
- Add a bell WatchlistButton to InvoiceCard with optimistic add/remove and rollback
- Add illustrated empty state with Browse Marketplace CTA
- Redirect legacy /investor/watchlist route to /watchlist
- Cover state-change detection, registry sync, optimistic rollback and page states with tests
@solomonadzape95
solomonadzape95 force-pushed the feature/474-investor-watchlist branch from 452259f to 97e64e5 Compare October 18, 2026 10:07
solomonadzape95 and others added 4 commits October 19, 2026 22:11
- Close the unterminated fetchInvestorLoyalty function in lib/api/index.ts (TS1005 parse error inherited from the dev merge; it crashed lint, type-check and every test importing the API module)
- Escape the apostrophe in LimitOrderPanel (react/no-unescaped-entities)
- Use next/link for the marketplace fixture in PlatformOnboardingTour test (@next/next/no-html-link-for-pages)
…ests pass

Port of the baseline repair from StellarState#478:
- Restore the lib/api exports and internal normalisers dropped by the 88e43dc
  merge, still referenced across the app
- Fix stale typings (KycStatus split, RESALE_INVOICE_TYPES, notification
  normalisation, Invoice/NotificationItem/PayoutRecord fields, updateInvoice,
  useTopUpMutation, …)
- Wrap useSearchParams pages in Suspense and the compare page in
  ComparisonProvider so next build prerenders
- Fix the admin suspend target-state bug and the duplicate InvoiceFraudReport
  import; repair test infrastructure and stale expectations

Verified: tsc 0 errors, lint clean, next build passes, 1333/1333 tests pass.
Keep render-with-card-providers identical across the open feature branches so
merging them is conflict-free.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement investor watchlist page with state-change alerts

2 participants