feat(pos-app): activity filters, date range, and Pay API migration#412
feat(pos-app): activity filters, date range, and Pay API migration#412ignaciosantise wants to merge 7 commits intomainfrom
Conversation
…nd add date filtering - Replace horizontal scrollable filter pills with two compact buttons (Status & Date range) - Add date range filtering with options: All Time, Today, 7 Days, This Week, This Month - Status filter button now shows selected filter label instead of generic "Status" - Each filter opens a bottom sheet modal with radio selection list - Add color-coded dots in status filter modal matching transaction states - Add DateRangeFilterType and getDateRange utility for date computation - Extend API with fromDate/toDate query parameters for server-side filtering - Store date range filter preference in Zustand (defaults to "Today") - Bump settings store version to 14 with migration support Co-Authored-By: Claude Haiku 4.5 <[email protected]>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Claude finished @ignaciosantise's task in 2m 29s —— View job PR Review
|
There was a problem hiding this comment.
Pull request overview
This PR updates the POS app Activity screen filtering UX by replacing the horizontal status “pill” tabs with two compact buttons that open bottom-sheet modals, and adds server-side date range filtering via new query parameters.
Changes:
- Introduces a persisted
dateRangeFiltersetting (defaulting to"today") and agetDateRangeutility to computefromDate/toDate. - Extends the transactions API/client hooks to include date range filtering (
from_date/to_date) and updates React Query caching keys accordingly. - Replaces the
FilterTabsUI with newFilterButtons+SettingsBottomSheet+RadioListoptions, including colored status dots.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| dapps/pos-app/utils/types.ts | Adds DateRangeFilterType to represent supported date filters. |
| dapps/pos-app/utils/date-range.ts | New utility to compute fromDate/toDate for server-side date filtering. |
| dapps/pos-app/store/useSettingsStore.ts | Persists dateRangeFilter, adds setter, and bumps persisted store version + migration. |
| dapps/pos-app/services/transactions.ts | Adds fromDate/toDate options and serializes them as from_date/to_date query params. |
| dapps/pos-app/services/hooks.ts | Extends useTransactions to accept dateRangeFilter, compute date ranges, and include them in queryKey + API calls. |
| dapps/pos-app/components/radio-list.tsx | Adds optional dotColor support to render a small colored dot per option. |
| dapps/pos-app/components/filter-tabs.tsx | Removes the old horizontal scroll filter tabs component. |
| dapps/pos-app/components/filter-buttons.tsx | Adds new two-button header component for Status/Date range bottom sheets. |
| dapps/pos-app/app/activity.tsx | Updates Activity screen UI to use the new filter buttons + bottom sheets and wire filters into useTransactions. |
Comments suppressed due to low confidence (2)
dapps/pos-app/services/hooks.ts:228
queryKeyincludessortBy,sortDir, andlimitfromqueryOptions, butqueryFnunconditionally overrides these (sortBy: "date",sortDir: "desc",limit: 20). This makes the cache key imply variability that the request ignores, and can lead to unnecessary cache misses/confusing API. Either honor the passedqueryOptionsvalues or remove these fields from the key/inputs if they’re meant to be fixed.
// Extract relevant fields for query key to avoid cache misses from object reference changes
const { sortBy, sortDir, limit } = queryOptions;
const query = useInfiniteQuery<TransactionsResponse, Error>({
queryKey: ["transactions", filter, dateRangeFilter, sortBy, sortDir, limit],
queryFn: ({ pageParam }) => {
const statusFilter = filterToStatusArray(filter);
const { fromDate, toDate } = getDateRange(dateRangeFilter);
return getTransactions({
...queryOptions,
status: statusFilter,
fromDate,
toDate,
sortBy: "date",
sortDir: "desc",
limit: 20,
cursor: pageParam as string | undefined,
dapps/pos-app/services/hooks.ts:229
useTransactionsnow supportsdateRangeFilterand passesfromDate/toDateintogetTransactions, but the existing hook tests only coveruseStartPaymentandusePaymentStatus. Consider adding tests that assertgetTransactionsis called with the expectedfromDate/toDatefor a givendateRangeFilterand that thequeryKeychanges appropriately when the filter changes.
interface UseTransactionsOptions {
/**
* Whether to enable the query
* @default true
*/
enabled?: boolean;
/**
* Filter transactions by UI filter type
* @default "all"
*/
filter?: TransactionFilterType;
/**
* Filter transactions by date range
* @default "today"
*/
dateRangeFilter?: DateRangeFilterType;
/**
* Additional query options for the API
*/
queryOptions?: GetTransactionsOptions;
}
/**
* Maps UI filter type to API status values
*/
function filterToStatusArray(
filter: TransactionFilterType,
): string[] | undefined {
switch (filter) {
case "completed":
return ["succeeded"];
case "failed":
return ["failed", "expired", "cancelled"];
case "pending":
return ["requires_action", "processing"];
case "all":
default:
return undefined;
}
}
/**
* Hook to fetch merchant transactions with filtering and infinite scrolling
* @param options - Query options including filter type
* @returns Infinite query result with paginated transactions
*/
export function useTransactions(options: UseTransactionsOptions = {}) {
const {
enabled = true,
filter = "all",
dateRangeFilter = "today",
queryOptions = {},
} = options;
const addLog = useLogsStore.getState().addLog;
// Extract relevant fields for query key to avoid cache misses from object reference changes
const { sortBy, sortDir, limit } = queryOptions;
const query = useInfiniteQuery<TransactionsResponse, Error>({
queryKey: ["transactions", filter, dateRangeFilter, sortBy, sortDir, limit],
queryFn: ({ pageParam }) => {
const statusFilter = filterToStatusArray(filter);
const { fromDate, toDate } = getDateRange(dateRangeFilter);
return getTransactions({
...queryOptions,
status: statusFilter,
fromDate,
toDate,
sortBy: "date",
sortDir: "desc",
limit: 20,
cursor: pageParam as string | undefined,
});
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
- Add exhaustive default guard in getDateRange switch to prevent runtime errors - Stabilize toDate across paginated fetches by memoizing getDateRange outside queryFn - Update store version assertion in test from 13 to 14 Co-Authored-By: Claude Opus 4.6 <[email protected]>
|
Re: Fixed in 4773484 — moved Re: Also fixed in 4773484 — added exhaustive |
Rename fromDate/toDate to startTs/endTs across the codebase to match the actual GET /v1/merchants/payments query parameter names. Co-Authored-By: Claude Opus 4.6 <[email protected]>
Split the "Failed" filter into separate Failed, Expired, and Cancelled options to match the backend payment statuses. Each status now maps to its own API value instead of grouping expired/cancelled under failed. Co-Authored-By: Claude Opus 4.6 <[email protected]>
Migrate from old Merchant API (`/merchants/{id}/payments` with separate
`MERCHANT_PORTAL_API_KEY`) to unified Pay API (`/v1/merchants/payments`
with shared `getApiHeaders()`). Update response types from flat
snake_case to nested camelCase DTOs. Replace CAIP-19 token parsing with
server-provided display values. Remove `utils/tokens.ts` and merchant
API env vars.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
|
@claude review |
|
Claude finished @ignaciosantise's task in 2m 6s —— View job PR Review
🔄 Incremental Review: focusing on changes since the previous review. Previously flagged issues — both resolved ✅
Found 2 issue(s)Issue 1:
|
The upstream API can return an empty body on error responses, causing JSON.parse to fail. Read as text first and only parse if non-empty. Co-Authored-By: Claude Opus 4.6 <[email protected]>
…queryOptions Base URL already includes /v1, so endpoint was resolving to /v1/v1/merchants/payments. Also remove unused queryOptions from useTransactions since sort/limit are hardcoded. Co-Authored-By: Claude Opus 4.6 <[email protected]>

Summary
startTs/endTsAPI params/merchants/{id}/paymentswithMERCHANT_PORTAL_API_KEY) to unified Pay API (/v1/merchants/paymentswith sharedgetApiHeaders())AmountWithDisplay,BuyerInfo,TransactionInfo,SettlementInfo)utils/tokens.ts) with server-provided display values (iconUrl,formatted,assetSymbol)EXPO_PUBLIC_MERCHANT_API_URLandEXPO_PUBLIC_MERCHANT_PORTAL_API_KEYTest plan
nextCursor🤖 Generated with Claude Code