Skip to content

Relayout offer page - #889

Open
dkackman wants to merge 4 commits into
xch-dev:mainfrom
dkackman:relayout-offer-page
Open

dkackman wants to merge 4 commits into
xch-dev:mainfrom
dkackman:relayout-offer-page

Conversation

@dkackman

@dkackman dkackman commented Sep 26, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Reworks the Offers page so it scales to wallets with many offers. Paging, filtering, search and sort now happen in the database instead of loading every offer. The page also gets the same toolbar, multi-select and card-size options as the NFT list.

Backend

  • get_offers is paged and filterable. GetOffers gains optional offset, limit, status, find_value, find_side (any / offered / requested), sort_mode (created / expiration) and ascending. GetOffersResponse gains total, the match count before paging.
    • Every new field has a serde default, so an empty request still returns all offers, newest first.
  • New offers_page query in sage-database:
    • Search matches asset name or ticker (case-insensitive LIKE, with % and _ escaped). It also matches an exact id: offer id, asset id (hex, 0x optional), or an nft1 / did:chia: / option address.
    • Expiration sort puts offers that never expire last.
    • Ties are broken by row id, so paging stays stable when timestamps are equal.
    • The total comes from COUNT(*) OVER() in the same query.
  • Unit tests for offers_page (in-memory SQLite with migrations) and parse_find_id. sage-database gains tokio / sqlx migrate as dev-dependencies for these.

Frontend

  • Toolbar (OfferOptions): debounced search with a side selector (any / offered / requested), a status filter, a sort-by menu with asc/desc, a small/large card toggle, and a multi-select toggle.
    • Pagination sits in the toolbar and slides out with it on scroll.
    • Filter, sort, page size and card size persist in local storage. Page and query live in the URL.
    • "No offers match your filters" shows a Clear filters button.
  • Data: useOfferParams and useOfferData fetch one page at a time. Responses that arrive after newer params have been requested are dropped.
  • Small cards (OfferTileCard): a compact grid tile with status, one icon per side (extra assets as a +N pill) and a single time.
    • The time is the expiry for active and pending offers, and the age otherwise.
    • Amounts below 0.001 show as <0.001; the exact value is in the tooltip.
    • The grid uses auto-fill columns with an 11rem minimum.
    • Each tile has a spoken summary as its accessible label.
  • Status badge: OfferStatusBadge gives each status its own icon and color.
  • Multi-select:
    • Selections can now span pages.
    • Cancel selected fetches the selected offers fresh and keeps only those still active. This handles offers that were completed or deleted after they were selected.
    • Errors other than not-found are reported.
  • Shared pieces pulled out of NftOptions and NftList, which now use them too:
    • DebouncedSearchInput
    • MultiSelectToggle
    • useMultiSelect
  • i18n: new formatCompactNumber (1.5K, 1.23M, 3 significant digits below 1) and narrow formatRelativeTime (in 3d, 2h ago) helpers.

Notes for reviewers

  • API consumers: GetOffers is no longer Copy, and GetOffersResponse has a new required total field.
  • Lingui catalogs were not re-extracted; new strings will be picked up in the pre-release extraction pass.

Test plan

  • pnpm run test:unit: 46 passing, including new tests for the tile card, search input, multi-select hook and actions, offer data hook, fetchOfferRecords and the i18n helpers
  • tsc, eslint and prettier are clean
  • cargo test -p sage-database -p sage
  • Manual: search, side, status, sort and pagination on a wallet with many offers
  • Manual: switching between small and large cards at several window widths
  • Manual: multi-select across pages, then cancel and delete

🤖 Generated with Claude Code

…fers pages

- Added useMultiSelect hook for managing multi-selection state.
- Created tests for useMultiSelect to ensure correct functionality.
- Refactored NftList component to utilize useMultiSelect for NFT selection.
- Updated Offers component to incorporate multi-select actions and state management.
- Introduced useOfferData and useOfferParams hooks for better offer data handling.
- Added tests for useOfferData to validate API interactions and state management.
- Implemented fetchOfferRecords function to handle offer fetching with error management.
- Enhanced Offers page with pagination and improved user experience for offer management.
…ce OfferTileCard tests, and improve Offers layout
@dkackman

Copy link
Copy Markdown
Collaborator Author

@judeallred i extended you multi-select addition to the offers page into a general update.

This branch has not been deployed

No deployments
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.

1 participant