Skip to content

feat: implement sorting functionality in OrdersGrid with pagination a… - #5

Merged
atelesjr merged 12 commits into
mainfrom
order-grid-filter
Mar 16, 2026
Merged

feat: implement sorting functionality in OrdersGrid with pagination a…#5
atelesjr merged 12 commits into
mainfrom
order-grid-filter

Conversation

@atelesjr

@atelesjr atelesjr commented Mar 15, 2026

Copy link
Copy Markdown
Owner

…nd update related components

Summary by CodeRabbit

  • New Features

    • Sortable column headers with accessible indicators and persistent sort links
    • Full filter bar with text/select/date controls and Apply/Clear actions
    • Toolbar with Create Order action and top pagination; interactive filter toggle
    • Client-side date picker and select controls for filtering
  • Improvements

    • Contextual empty-state messages reflecting active filters
    • Responsive layout and adjusted column widths for readability
    • Pagination and heading spacing refinements
  • Tests

    • Expanded unit tests covering sorting, filtering, empty states and toolbar behavior

@coderabbitai

coderabbitai Bot commented Mar 15, 2026

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR adds full sorting, filtering, and pagination support to the Order Grid: new sorting utilities and types, filter normalization and UI (text/select/date), presenter to build a view model, toolbar and filter bar UI, updated grid head/body to surface sort state and empty messages, and service-level sorting/filtering/pagination.

Changes

Cohort / File(s) Summary
Sorting Core
lib/orders/orders.sort.types.ts, lib/orders/orders.sort.ts, lib/orders/orders.constants.ts
Introduce sort types, default sort constants, deterministic sort utilities (resolve/validate sort fields, default directions, getSortedOrders, tie-breakers).
Filtering Core
lib/orders/orders.filter.types.ts, lib/orders/orders.filter.ts
Add OrdersGridFilters type and functions to normalize/validate filters and to filter order arrays (id, instrument, status, side, date).
Service / Pagination
lib/orders/orders.service.ts, lib/orders/__tests__/*
Extend getPaginatedOrdersForGrid to accept sortBy/sortDir/filters, apply filtering→sorting→pagination, and return currentPage/totalPages/prevPage/nextPage; add tests covering filtering, sorting, pagination edge cases.
Query & Navigation
components/OrderGrid/order-grid.query.ts, components/OrderGrid/order-grid.navigation.ts
Add query resolution for page/sort/filters and URL builders for grid hrefs and per-field sort links (preserving filters).
Presenter & Integration
components/OrderGrid/order-grid-with-pagination.presenter.ts, components/OrderGrid/OrderGridWithPagination.tsx, app/page.tsx
New presenter builds view model (orders, filters, pagination, sortState); server component uses it instead of manual parsing; Home props updated to typed query params.
Client Component & Controller
components/OrderGrid/OrderGridWithPaginationClient.tsx, components/OrderGrid/useOrderGridWithPaginationController.ts
Client wired to presenter viewModel; new controller hook manages selection, filters toggle, empty-state message, and modal open/close interactions.
Grid API & Columns
components/OrderGrid/index.tsx, components/OrderGrid/types.ts, components/OrderGrid/columns.ts
OrdersGrid props extended with sortState and emptyStateMessage; column definitions updated (added id, sortKey on sortable columns, adjusted widths); types updated for sort/filter/pagination state.
Head / Body UI
components/OrderGrid/parts/Head.tsx, components/OrderGrid/parts/Body.tsx, components/OrderGrid/__tests__/*
Head now renders sortable links with aria-sort and visual indicators; Body renders configurable empty-state row; tests updated/added for aria-sort and empty messages.
Filter UI & Controller
components/OrderGrid/parts/filters.config.ts, components/OrderGrid/parts/useFiltersBarController.ts, components/OrderGrid/parts/FiltersBar.tsx, components/OrderGrid/parts/FiltersFields.tsx, components/OrderGrid/parts/FilterSelect.tsx, components/OrderGrid/parts/FilterDatePicker.tsx, components/OrderGrid/parts/FiltersActions.tsx
Full filter UI: form config, controller that syncs URL params, filters bar, fields, select, date-picker popover, and apply/clear actions; includes tests for filter components and flows.
Toolbar / Actions / Pagination
components/OrderGrid/parts/Toolbar.tsx, components/OrderGrid/parts/ActionButton.tsx, components/OrderGrid/parts/__tests__/*
New toolbar with action buttons (Create, Filter) and top pagination; action button component with accessible pressed state; tests added.
UI Primitives
components/ui/Button.tsx, components/ui/FormField.tsx, components/ui/TextInput.tsx
Introduce small UI primitives used by filter controls (UIButton, UIFormField, UITextInput).
Styles
components/OrderGrid/OrderGrid.styles.css, styles/base.css
Add styling for sort links, toolbar, filters, date-picker, responsive adjustments; tweak global heading spacing.
Utilities & Empty State
components/OrderGrid/order-grid-empty-state.ts, components/OrderGrid/__tests__/order-grid-empty-state.test.ts
Add utility to produce contextual empty-state messages and tests covering variants.

Sequence Diagram

sequenceDiagram
    actor User
    participant Server as OrderGridWithPagination (Server)
    participant Presenter as Presenter
    participant Service as Order Service
    participant Client as OrderGridWithPaginationClient (Client)
    participant Toolbar as OrdersGridToolbar
    participant FiltersBar as FiltersBar
    participant Grid as OrdersGrid

    User->>Server: request page with query params
    Server->>Presenter: buildOrderGridWithPaginationViewModel(searchParams)
    Presenter->>Presenter: resolveOrderGridQuery(searchParams)
    Presenter->>Service: getPaginatedOrdersForGrid(page, sortBy, sortDir, filters)
    Service->>Service: filterOrders(...) -> getSortedOrders(...)
    Service-->>Presenter: paginated sorted results + prev/next pages
    Presenter->>Presenter: buildOrderGridSortLinks(sortBy, sortDir, filters)
    Presenter-->>Server: viewModel{orders, filters, pagination, sortState}
    Server->>Client: render client with viewModel
    Client->>Toolbar: render toolbar (pagination + filter toggle)
    User->>Toolbar: click Filter
    Toolbar->>Client: toggleFilters()
    Client->>FiltersBar: render FiltersBar (formState from controller)
    User->>FiltersBar: change fields, click Aplicar
    FiltersBar->>Client: applyFilters() -> navigate(newUrl)
    Client->>Server: new request with updated query params
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • Order detail #4: Modifies OrderGrid row selection/modal and toolbar/pagination; strongly overlaps with selection/controller and toolbar changes here.
  • Home #3: Earlier refactor touching OrderGrid columns, Head/Body, types and styles that this PR builds upon.

Poem

🐰
Hop, I sorted every row with care,
Filters fluttered like leaves in air;
A calendar popped, links point the way,
The toolbar hums—now order's at play.
Nibble a carrot, the grid is fair. 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main feature added: implementing sorting functionality in OrdersGrid with pagination. It accurately reflects the core changes across the codebase.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch order-grid-filter
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

You can make CodeRabbit's review stricter and more nitpicky using the `assertive` profile, if that's what you prefer.

Change the reviews.profile setting to assertive to make CodeRabbit's nitpick more issues in your PRs.

@coderabbitai

coderabbitai Bot commented Mar 15, 2026

Copy link
Copy Markdown

Note

Unit test generation is a public access feature. Expect some limitations and changes as we gather feedback and continue to improve it.


Generating unit tests... This may take up to 20 minutes.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
lib/orders/orders.service.ts (1)

31-40: ⚠️ Potential issue | 🟠 Major

Normalize pagination inputs to prevent invalid page math.

Lines 31-40 use pageSize and requestedPage directly. A non-positive or fractional pageSize can produce broken metadata (totalPages/slice boundaries), and fractional pages can yield ambiguous slicing.

Proposed change
 export const getPaginatedOrdersForGrid = async (
 	requestedPage: number,
 	pageSize = DEFAULT_PAGE_SIZE,
 	sortBy: OrdersSortBy = DEFAULT_ORDERS_SORT_BY,
 	sortDir: OrdersSortDir = DEFAULT_ORDERS_SORT_DIR,
 ): Promise<PaginatedOrdersResult> => {
 	const orders = getSortedOrders(await findAllOrders(), sortBy, sortDir);
-	const safeRequestedPage = Number.isFinite(requestedPage) ? requestedPage : 1;
-	const totalPages = Math.max(1, Math.ceil(orders.length / pageSize));
+	const safePageSize =
+		Number.isFinite(pageSize) && pageSize > 0 ? Math.floor(pageSize) : DEFAULT_PAGE_SIZE;
+	const safeRequestedPage =
+		Number.isFinite(requestedPage) && requestedPage > 0
+			? Math.floor(requestedPage)
+			: 1;
+	const totalPages = Math.max(1, Math.ceil(orders.length / safePageSize));
 	const currentPage = Math.min(Math.max(1, safeRequestedPage), totalPages);
-	const startIndex = (currentPage - 1) * pageSize;
-	const items = orders.slice(startIndex, startIndex + pageSize);
+	const startIndex = (currentPage - 1) * safePageSize;
+	const items = orders.slice(startIndex, startIndex + safePageSize);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/orders/orders.service.ts` around lines 31 - 40, Normalize pagination
inputs before computing totals: validate and coerce pageSize and requestedPage
to positive integers (e.g., set pageSize = Math.floor(Number(pageSize)) and if
pageSize < 1 set to DEFAULT_PAGE_SIZE; set requestedPage =
Math.floor(Number(requestedPage)) and if requestedPage < 1 set to 1) before
calling getSortedOrders/findAllOrders and before computing totalPages,
startIndex, slice bounds; update code around the parameters and variables
(pageSize, requestedPage, currentPage) in the function that returns
PaginatedOrdersResult so rounding/guarding prevents fractional or non-positive
page math.
🧹 Nitpick comments (1)
components/OrderGrid/__tests__/order-grid.navigation.test.ts (1)

1-4: Prefer a partial mock to keep this test resilient.

Line 1 fully replaces @/lib/orders/orders.sort. If order-grid.navigation.ts later imports another export from that module, this test can fail for unrelated reasons. Keep real exports and mock only getDefaultSortDirForField.

Proposed change
-jest.mock('@/lib/orders/orders.sort', () => ({
-	getDefaultSortDirForField: (field: string) =>
-		field === 'timestamp' ? 'desc' : 'asc',
-}));
+jest.mock('@/lib/orders/orders.sort', () => {
+	const actual = jest.requireActual('@/lib/orders/orders.sort');
+	return {
+		...actual,
+		getDefaultSortDirForField: (field: string) =>
+			field === 'timestamp' ? 'desc' : 'asc',
+	};
+});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/OrderGrid/__tests__/order-grid.navigation.test.ts` around lines 1
- 4, The test currently fully replaces the module '@/lib/orders/orders.sort',
which is brittle; update the mock to use the real module and only override
getDefaultSortDirForField by calling
jest.requireActual('@/lib/orders/orders.sort') (or jest.requireActual with the
same specifier) and spreading its exports, then replace only
getDefaultSortDirForField with a mocked implementation that returns 'desc' for
'timestamp' and 'asc' otherwise; this preserves other real exports while mocking
just the targeted function.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@components/OrderGrid/order-grid.query.ts`:
- Around line 22-23: The page parsing accepts partial numeric strings (e.g.,
"2abc") because Number.parseInt is permissive; change the logic around
parsedPage/requestedPage to first validate query.page with a strict integer
check (e.g., regex /^\d+$/) and only then parse it, defaulting to 1 for anything
that fails validation; update the variables referenced (parsedPage,
requestedPage) so parsedPage is derived from a validated numeric string and
requestedPage uses Math.max(1, parsedPage) as before.

In `@components/OrderGrid/OrderGridWithPagination.tsx`:
- Around line 23-24: The parent component's searchParams type is missing sortBy
and sortDir causing OrderGridWithPagination's resolveOrderGridQuery (which calls
resolveOrdersSortBy and resolveOrdersSortDir) to receive undefined and reset
sorting; update the parent's HomeProps searchParams type in app/page.tsx to
include optional sortBy?: string and sortDir?: string so the values are passed
through to OrderGridWithPagination and preserve user-selected sorting state.

In `@components/OrderGrid/parts/Head.tsx`:
- Around line 16-23: The header currently sets aria-sort for every column via
the computed ariaSort variable (using isActive and sortState), which should be
applied only to the actively sorted column; update the rendering in the
component that returns the <th> (referencing isActive, sortState, ariaSort and
column.key) so that the aria-sort attribute is omitted unless isActive is true
(e.g. conditionally add the attribute or spread an object only when isActive),
ensuring only the active column exposes aria-sort.

In `@lib/orders/orders.sort.ts`:
- Around line 50-51: The comparator for the 'timestamp' case in orders.sort.ts
currently does new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime()
and can produce NaN if either timestamp is invalid; update the comparator (and
the other identical occurrence around the later block referenced) to parse the
timestamps (Date.parse or new Date(...).getTime()), check isNaN for each parsed
value, and replace invalid values with a deterministic fallback (e.g.,
Number.NEGATIVE_INFINITY or 0 depending on desired sort direction) before
subtracting so the comparator always returns a finite number; locate the
'timestamp' case and the duplicated block and apply the same guard logic to
both.

---

Outside diff comments:
In `@lib/orders/orders.service.ts`:
- Around line 31-40: Normalize pagination inputs before computing totals:
validate and coerce pageSize and requestedPage to positive integers (e.g., set
pageSize = Math.floor(Number(pageSize)) and if pageSize < 1 set to
DEFAULT_PAGE_SIZE; set requestedPage = Math.floor(Number(requestedPage)) and if
requestedPage < 1 set to 1) before calling getSortedOrders/findAllOrders and
before computing totalPages, startIndex, slice bounds; update code around the
parameters and variables (pageSize, requestedPage, currentPage) in the function
that returns PaginatedOrdersResult so rounding/guarding prevents fractional or
non-positive page math.

---

Nitpick comments:
In `@components/OrderGrid/__tests__/order-grid.navigation.test.ts`:
- Around line 1-4: The test currently fully replaces the module
'@/lib/orders/orders.sort', which is brittle; update the mock to use the real
module and only override getDefaultSortDirForField by calling
jest.requireActual('@/lib/orders/orders.sort') (or jest.requireActual with the
same specifier) and spreading its exports, then replace only
getDefaultSortDirForField with a mocked implementation that returns 'desc' for
'timestamp' and 'asc' otherwise; this preserves other real exports while mocking
just the targeted function.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 70efe348-0fea-412a-be04-d3f7b6e0f0e5

📥 Commits

Reviewing files that changed from the base of the PR and between 5d274e6 and 0008e7f.

⛔ Files ignored due to path filters (1)
  • public/assets/add_box_60dp.svg is excluded by !**/*.svg
📒 Files selected for processing (18)
  • components/OrderGrid/OrderGrid.styles.css
  • components/OrderGrid/OrderGridWithPagination.tsx
  • components/OrderGrid/OrderGridWithPaginationClient.tsx
  • components/OrderGrid/__tests__/OrderGrid.test.tsx
  • components/OrderGrid/__tests__/OrderGridWithPaginationClient.test.tsx
  • components/OrderGrid/__tests__/order-grid.navigation.test.ts
  • components/OrderGrid/__tests__/order-grid.query.test.ts
  • components/OrderGrid/columns.ts
  • components/OrderGrid/index.tsx
  • components/OrderGrid/order-grid.navigation.ts
  • components/OrderGrid/order-grid.query.ts
  • components/OrderGrid/parts/Head.tsx
  • components/OrderGrid/types.ts
  • lib/orders/__tests__/orders.service.test.ts
  • lib/orders/orders.constants.ts
  • lib/orders/orders.service.ts
  • lib/orders/orders.sort.ts
  • lib/orders/orders.sort.types.ts

Comment thread components/OrderGrid/order-grid.query.ts Outdated
Comment thread components/OrderGrid/OrderGridWithPagination.tsx Outdated
Comment thread components/OrderGrid/parts/Head.tsx Outdated
Comment thread lib/orders/orders.sort.ts Outdated
@coderabbitai

coderabbitai Bot commented Mar 15, 2026

Copy link
Copy Markdown

✅ Created PR with unit tests: #6

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
components/OrderGrid/parts/ActionButton.tsx (1)

3-8: Avoid enabled-but-inert buttons when no handler is provided.

With optional onClick, the button is still rendered as actionable on Line 17. Consider auto-disabling when onClick is missing (or make onClick required).

Suggested patch
 type OrdersGridActionButtonProps = {
 	label: string;
 	iconAlt: string;
 	iconSrc: string;
 	onClick?: () => void;
 };
@@
 export const OrdersGridActionButton = ({
 	label,
 	iconAlt,
 	iconSrc,
 	onClick,
 }: OrdersGridActionButtonProps) => {
+	const isDisabled = !onClick;
 	return (
 		<button
 			aria-label={label}
 			className="orders-grid__action-button"
+			disabled={isDisabled}
 			onClick={onClick}
 			type="button"
 		>

Also applies to: 17-22

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/OrderGrid/parts/ActionButton.tsx` around lines 3 - 8, The prop
type OrdersGridActionButtonProps allows an optional onClick which results in an
enabled-but-inert button; update the ActionButton component that renders this
prop (the button at the rendering around the previous Line 17) to either make
onClick required in OrdersGridActionButtonProps or, preferred, keep it optional
and set the rendered <button> to disabled when onClick is missing (e.g.,
disabled={!onClick}) and avoid attaching pointer/click handlers when undefined;
also ensure any CSS/class that indicates interactivity is removed for the
disabled state so the button is not perceived as actionable when no handler
exists.
components/OrderGrid/parts/__tests__/Toolbar.test.tsx (1)

5-21: Add click-wiring assertions for toolbar actions.

This test validates presence, but not that onCreateOrderClick/onFilterClick are invoked. Adding click assertions here would harden the new toolbar integration path.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/OrderGrid/parts/__tests__/Toolbar.test.tsx` around lines 5 - 21,
The test currently only checks that OrdersGridToolbar renders UI elements; add
assertions that onCreateOrderClick and onFilterClick are invoked by passing
jest.fn() mocks as props to OrdersGridToolbar, simulate user clicks on the
"Criar ordem" and "Filtro" buttons (using userEvent.click or fireEvent) and
expect the corresponding mock functions to have been called (e.g.,
expect(onCreateOrderClick).toHaveBeenCalled()). Ensure you import and use
userEvent (or fireEvent) and reference the component name OrdersGridToolbar and
prop names onCreateOrderClick and onFilterClick to locate where to update the
test.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@components/OrderGrid/OrderGrid.styles.css`:
- Around line 38-47: The Biome CSS parser is failing on Tailwind `@apply` usages
(e.g., selectors .orders-grid__sort-link, .orders-grid__sort-link--active,
.orders-grid__sort-indicator) because Tailwind directives are not enabled; open
your biome.json and under the css.parser settings add "tailwindDirectives": true
to enable parsing of `@apply` and other Tailwind directives, then re-run the
linter/formatter to confirm the parse errors across the OrdersGrid stylesheet
are resolved.

In `@styles/components/layout.css`:
- Around line 10-12: The .home__title rule in styles/components/layout.css
(which only contains "@apply mb-8;") is unused; either delete that CSS rule or
add the class to the H2 element in app/page.tsx that renders "Gerenciamento de
ordens" (add className="home__title" to that H2). If you keep the `@apply` rule
and want to avoid the Biome static analysis warning about Tailwind syntax,
configure Biome to ignore Tailwind-processed CSS or enable a Tailwind-aware
parser for CSS files so the `@apply` directive is accepted.

---

Nitpick comments:
In `@components/OrderGrid/parts/__tests__/Toolbar.test.tsx`:
- Around line 5-21: The test currently only checks that OrdersGridToolbar
renders UI elements; add assertions that onCreateOrderClick and onFilterClick
are invoked by passing jest.fn() mocks as props to OrdersGridToolbar, simulate
user clicks on the "Criar ordem" and "Filtro" buttons (using userEvent.click or
fireEvent) and expect the corresponding mock functions to have been called
(e.g., expect(onCreateOrderClick).toHaveBeenCalled()). Ensure you import and use
userEvent (or fireEvent) and reference the component name OrdersGridToolbar and
prop names onCreateOrderClick and onFilterClick to locate where to update the
test.

In `@components/OrderGrid/parts/ActionButton.tsx`:
- Around line 3-8: The prop type OrdersGridActionButtonProps allows an optional
onClick which results in an enabled-but-inert button; update the ActionButton
component that renders this prop (the button at the rendering around the
previous Line 17) to either make onClick required in OrdersGridActionButtonProps
or, preferred, keep it optional and set the rendered <button> to disabled when
onClick is missing (e.g., disabled={!onClick}) and avoid attaching pointer/click
handlers when undefined; also ensure any CSS/class that indicates interactivity
is removed for the disabled state so the button is not perceived as actionable
when no handler exists.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 64ecf9c6-2fa1-45fb-8212-a1f162ae9312

📥 Commits

Reviewing files that changed from the base of the PR and between 69a3d03 and 7a4b939.

⛔ Files ignored due to path filters (1)
  • public/assets/filter_list_60dp.svg is excluded by !**/*.svg
📒 Files selected for processing (9)
  • app/page.tsx
  • components/OrderGrid/OrderGrid.styles.css
  • components/OrderGrid/OrderGridWithPaginationClient.tsx
  • components/OrderGrid/parts/ActionButton.tsx
  • components/OrderGrid/parts/Toolbar.tsx
  • components/OrderGrid/parts/__tests__/ActionButton.test.tsx
  • components/OrderGrid/parts/__tests__/Toolbar.test.tsx
  • styles/base.css
  • styles/components/layout.css
✅ Files skipped from review due to trivial changes (1)
  • components/OrderGrid/parts/tests/ActionButton.test.tsx

Comment on lines +38 to +47
.orders-grid__sort-link {
@apply inline-flex w-full items-center justify-between gap-2 text-white no-underline;
}

.orders-grid__sort-link--active {
@apply font-semibold;
}

.orders-grid__sort-indicator {
@apply text-grid-xm;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Biome config files =="
fd -HI 'biome\.jsonc?$' .

CONFIG="$(fd -HI 'biome\.jsonc?$' . | head -n1 || true)"
if [ -n "${CONFIG:-}" ]; then
  echo
  echo "== Tailwind-related parser settings in ${CONFIG} =="
  rg -n -C2 'tailwindDirectives|css|parser' "$CONFIG" || true
else
  echo "No biome.json/biome.jsonc found."
fi

echo
echo "== Tailwind `@apply` usage in components/OrderGrid/OrderGrid.styles.css =="
rg -n -C1 '@apply' components/OrderGrid/OrderGrid.styles.css

Repository: atelesjr/base-orders

Length of output: 3036


Enable Tailwind directives in Biome config to stop parse failures on these CSS rules.

The Biome CSS parser is not configured to support Tailwind's @apply directive. Add "tailwindDirectives": true to the css.parser settings in biome.json to resolve parse errors being reported across lines 39, 43, 47, 79, 83, 87, 95, and 125 (30+ uses of @apply throughout this file).

🧰 Tools
🪛 Biome (2.4.6)

[error] 39-39: Tailwind-specific syntax is disabled.

(parse)


[error] 43-43: Tailwind-specific syntax is disabled.

(parse)


[error] 47-47: Tailwind-specific syntax is disabled.

(parse)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/OrderGrid/OrderGrid.styles.css` around lines 38 - 47, The Biome
CSS parser is failing on Tailwind `@apply` usages (e.g., selectors
.orders-grid__sort-link, .orders-grid__sort-link--active,
.orders-grid__sort-indicator) because Tailwind directives are not enabled; open
your biome.json and under the css.parser settings add "tailwindDirectives": true
to enable parsing of `@apply` and other Tailwind directives, then re-run the
linter/formatter to confirm the parse errors across the OrdersGrid stylesheet
are resolved.

Comment thread styles/components/layout.css Outdated
- Added filtering capabilities for orders based on id, instrument, status, side, and date.
- Introduced a new date picker component for selecting date filters.
- Created a filter select component for status and side filters.
- Implemented a filters bar to manage filter states and actions.
- Enhanced the order grid query to include filters in the request.
- Updated the order service to apply filters before sorting and pagination.
- Added tests for the new filtering functionality and components.
- Refactored existing components to accommodate the new filtering system.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

♻️ Duplicate comments (1)
components/OrderGrid/OrderGrid.styles.css (1)

38-259: ⚠️ Potential issue | 🟠 Major

Biome parse failures remain due to disabled Tailwind directives.

Line 39 and multiple subsequent @apply declarations are still parse-failing under Biome. This is the same unresolved root cause: Tailwind directives must be enabled in Biome config (css.parser.tailwindDirectives: true), otherwise CI/lint remains broken for this stylesheet.

#!/bin/bash
set -euo pipefail

CONFIG="$(fd -HI 'biome\.jsonc?$' . | head -n1 || true)"
if [ -z "${CONFIG:-}" ]; then
  echo "No biome.json/biome.jsonc found"
  exit 1
fi

echo "Biome config: $CONFIG"
rg -n -C2 'css|parser|tailwindDirectives' "$CONFIG" || true

echo
echo "Tailwind `@apply` usage in stylesheet:"
rg -n '@apply' components/OrderGrid/OrderGrid.styles.css
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/OrderGrid/OrderGrid.styles.css` around lines 38 - 259, The
stylesheet components/OrderGrid/OrderGrid.styles.css is failing Biome parsing
because Tailwind `@apply` directives are disabled; open your Biome config
(biome.json or biome.jsonc) and add or update the css.parser.tailwindDirectives
setting to true (ensure the css and parser objects exist and merge this key
rather than replacing unrelated config), save and commit the config change so
Biome will accept the `@apply` rules used by classes like
orders-grid__filter-field and orders-grid__date-picker.
🧹 Nitpick comments (1)
components/OrderGrid/parts/FilterSelect.tsx (1)

65-90: Align ARIA roles with actual interaction model.

Line 65-75 declares listbox/option, but interaction is implemented as nested buttons with tab/enter behavior, not listbox keyboard semantics. This can confuse assistive tech users.

♿ Suggested direction
-				<ul
-					aria-labelledby={id}
-					className="orders-grid__filter-select-menu"
-					role="listbox"
-				>
+				<ul
+					aria-labelledby={id}
+					className="orders-grid__filter-select-menu"
+					role="menu"
+				>
 					{options.map((option) => (
 						<li
-							aria-selected={option.value === value}
 							key={option.value}
-							role="option"
+							role="none"
 						>
 							<button
+								aria-checked={option.value === value}
 								className={`orders-grid__filter-select-option ${
 									option.value === value
 										? 'orders-grid__filter-select-option--selected'
 										: ''
 								}`.trim()}
+								role="menuitemradio"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/OrderGrid/parts/FilterSelect.tsx` around lines 65 - 90, The
component FilterSelect uses listbox/option ARIA roles but implements interaction
as clickable buttons; update the ARIA to match the actual model by changing the
container role from "listbox" to "menu" and each item role from "option" to
"menuitem" (remove aria-selected on items), and keep the existing click handlers
(onChange and setIsOpen) intact in the FilterSelect component so assistive tech
sees a menu/menuitem pattern rather than a listbox; ensure the container still
references id via aria-labelledby if needed and that keyboard behavior remains
handled by the existing buttons or is adjusted to support menu semantics.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@components/OrderGrid/order-grid.query.ts`:
- Around line 14-23: Update the OrderGridQueryParams type to allow string |
string[] | undefined for each field (instead of only string) to match Next.js
searchParams, and at the resolver entry point (where searchParams is received)
coerce each param to a single string by taking the first element when it's an
array (e.g., for id, instrument, status, sortBy, sortDir, side, date): perform
Array.isArray checks and assign the first value or undefined so downstream code
receives plain strings/numbers and not arrays; keep the symbol
OrderGridQueryParams and apply normalization immediately in the resolver that
consumes searchParams.

In `@components/OrderGrid/OrderGridWithPaginationClient.tsx`:
- Around line 46-56: The emptyStateMessage computed in the useMemo
(emptyStateMessage) assumes filters are active in its final fallback; change the
logic to first detect whether any filter is actually set (e.g., derive
hasActiveFilters via checking filters fields or
Object.values(filters).some(Boolean)) and only return "Nenhuma ordem encontrada
para os filtros aplicados." when hasActiveFilters is true—otherwise return a
neutral empty-account message like "Nenhuma ordem encontrada." Keep the checks
for filters.instrument and filters.id, keep the memo dependency on filters, and
update the fallback branch to use the new hasActiveFilters condition.

In `@components/OrderGrid/parts/FilterDatePicker.tsx`:
- Around line 146-148: The dialog created in FilterDatePicker (the div with
className "orders-grid__date-picker-popover" and role="dialog") is missing an
accessible name; update that element to include an accessible label by adding
either aria-label using the existing ariaLabel prop or aria-labelledby
referencing the month heading (monthLabel element) so assistive tech announces
the dialog name; ensure the month heading has an id if you use aria-labelledby
and reuse the visible <strong>{monthLabel}</strong> as the label source.

In `@components/OrderGrid/parts/FilterSelect.tsx`:
- Around line 43-60: selectedOption can be undefined and the hidden input still
submits the original invalid value; update FilterSelect to guard against empty
or missing matches by deriving selectedOption safely from options (e.g., const
selectedOption = options.find(o => o.value === value) ?? options[0] ?? { value:
'', label: '' }) and use selectedOption.value for the hidden input value and
selectedOption.label for the UI; ensure functions/JSX that reference
selectedOption (the span, the hidden input name/value, and any onClick handlers
relying on it) handle the empty fallback so the component never reads
.label/.value on undefined.

In `@lib/orders/orders.filter.ts`:
- Around line 45-51: The date filtering is inconsistent between UTC and local
time: update getTimestampDateKey to return the calendar day in the browser's
local timezone (use parsedDate.getFullYear(), parsedDate.getMonth()+1,
parsedDate.getDate() to produce YYYY-MM-DD) and update normalizeDateFilter to
parse the picker value as local midnight (do not append 'Z' or construct with
Date.parse('${normalized}T00:00:00.000Z'); instead construct a local Date via
new Date(year, month-1, day) or Date.parse('${normalized}T00:00:00') so both
getTimestampDateKey and normalizeDateFilter use the same local-time convention).

---

Duplicate comments:
In `@components/OrderGrid/OrderGrid.styles.css`:
- Around line 38-259: The stylesheet components/OrderGrid/OrderGrid.styles.css
is failing Biome parsing because Tailwind `@apply` directives are disabled; open
your Biome config (biome.json or biome.jsonc) and add or update the
css.parser.tailwindDirectives setting to true (ensure the css and parser objects
exist and merge this key rather than replacing unrelated config), save and
commit the config change so Biome will accept the `@apply` rules used by classes
like orders-grid__filter-field and orders-grid__date-picker.

---

Nitpick comments:
In `@components/OrderGrid/parts/FilterSelect.tsx`:
- Around line 65-90: The component FilterSelect uses listbox/option ARIA roles
but implements interaction as clickable buttons; update the ARIA to match the
actual model by changing the container role from "listbox" to "menu" and each
item role from "option" to "menuitem" (remove aria-selected on items), and keep
the existing click handlers (onChange and setIsOpen) intact in the FilterSelect
component so assistive tech sees a menu/menuitem pattern rather than a listbox;
ensure the container still references id via aria-labelledby if needed and that
keyboard behavior remains handled by the existing buttons or is adjusted to
support menu semantics.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6264f475-4277-442e-807d-410f4f8b552c

📥 Commits

Reviewing files that changed from the base of the PR and between 7a4b939 and 9a156ae.

📒 Files selected for processing (34)
  • components/OrderGrid/OrderGrid.styles.css
  • components/OrderGrid/OrderGridWithPagination.tsx
  • components/OrderGrid/OrderGridWithPaginationClient.tsx
  • components/OrderGrid/__tests__/OrderGrid.test.tsx
  • components/OrderGrid/__tests__/OrderGridWithPaginationClient.test.tsx
  • components/OrderGrid/__tests__/order-grid.navigation.test.ts
  • components/OrderGrid/__tests__/order-grid.query.test.ts
  • components/OrderGrid/columns.ts
  • components/OrderGrid/index.tsx
  • components/OrderGrid/order-grid-with-pagination.presenter.ts
  • components/OrderGrid/order-grid.navigation.ts
  • components/OrderGrid/order-grid.query.ts
  • components/OrderGrid/parts/ActionButton.tsx
  • components/OrderGrid/parts/Body.tsx
  • components/OrderGrid/parts/FilterDatePicker.tsx
  • components/OrderGrid/parts/FilterSelect.tsx
  • components/OrderGrid/parts/FiltersActions.tsx
  • components/OrderGrid/parts/FiltersBar.tsx
  • components/OrderGrid/parts/FiltersFields.tsx
  • components/OrderGrid/parts/Toolbar.tsx
  • components/OrderGrid/parts/__tests__/Body.test.tsx
  • components/OrderGrid/parts/__tests__/FiltersBar.test.tsx
  • components/OrderGrid/parts/__tests__/Toolbar.test.tsx
  • components/OrderGrid/parts/filters.config.ts
  • components/OrderGrid/parts/useFiltersBarController.ts
  • components/OrderGrid/types.ts
  • components/ui/Button.tsx
  • components/ui/FormField.tsx
  • components/ui/TextInput.tsx
  • lib/orders/__tests__/orders.filter.test.ts
  • lib/orders/__tests__/orders.service.test.ts
  • lib/orders/orders.filter.ts
  • lib/orders/orders.filter.types.ts
  • lib/orders/orders.service.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • components/OrderGrid/tests/OrderGrid.test.tsx
  • lib/orders/tests/orders.service.test.ts
  • components/OrderGrid/parts/ActionButton.tsx
  • components/OrderGrid/parts/tests/Toolbar.test.tsx

Comment thread components/OrderGrid/order-grid.query.ts
Comment thread components/OrderGrid/OrderGridWithPaginationClient.tsx Outdated
Comment thread components/OrderGrid/parts/FilterDatePicker.tsx Outdated
Comment thread components/OrderGrid/parts/FilterSelect.tsx
Comment thread lib/orders/orders.filter.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
lib/orders/orders.filter.ts (1)

95-108: Optional: precompute lowercase needles once per filter pass.

You can avoid repeated lowercase conversions per row and slightly simplify the predicate logic.

♻️ Suggested refactor
 export const filterOrders = (
 	orders: Order[],
 	filters: OrdersGridFilters,
 ): Order[] => {
 	const normalizedFilters = resolveOrdersGridFilters(filters);
+	const idNeedle = normalizedFilters.id?.toLowerCase();
+	const instrumentNeedle = normalizedFilters.instrument?.toLowerCase();

 	return orders.filter((order) => {
 		if (
-			normalizedFilters.id &&
-			!order.id.toLowerCase().includes(normalizedFilters.id.toLowerCase())
+			idNeedle &&
+			!order.id.toLowerCase().includes(idNeedle)
 		) {
 			return false;
 		}

 		if (
-			normalizedFilters.instrument &&
-			!order.instrument
-				.toLowerCase()
-				.includes(normalizedFilters.instrument.toLowerCase())
+			instrumentNeedle &&
+			!order.instrument.toLowerCase().includes(instrumentNeedle)
 		) {
 			return false;
 		}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/orders/orders.filter.ts` around lines 95 - 108, Precompute lowercase
"needles" from normalizedFilters once before calling orders.filter to avoid
repeating toLowerCase per row: create local variables like idNeedle =
normalizedFilters.id ? normalizedFilters.id.toLowerCase() : undefined and
instrumentNeedle = normalizedFilters.instrument ?
normalizedFilters.instrument.toLowerCase() : undefined, then update the
predicate inside the orders.filter callback to check idNeedle and
instrumentNeedle (e.g., if (idNeedle &&
!order.id.toLowerCase().includes(idNeedle)) return false) and similarly for
instrument using order.instrument; this keeps the same logic but avoids repeated
lowercase conversions and simplifies the filter checks.
components/OrderGrid/__tests__/order-grid-empty-state.test.ts (1)

3-24: Good test coverage of the main branches.

Consider adding a test case verifying the priority order when both instrument and id filters are set simultaneously, to ensure instrument takes precedence as intended.

💡 Suggested additional test case
+	it('prioritizes instrument over id when both filters are active', () => {
+		expect(
+			getOrderGridEmptyStateMessage({ instrument: 'PETR4', id: '123' }),
+		).toBe('PETR4 nao encontrado.');
+	});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/OrderGrid/__tests__/order-grid-empty-state.test.ts` around lines 3
- 24, Add a test that verifies priority when both instrument and id filters are
provided: update the test suite for getOrderGridEmptyStateMessage to include a
case calling getOrderGridEmptyStateMessage({ instrument: 'READL3', id: '1001' })
and assert it returns the instrument-specific message 'READL3 nao encontrado.'
to ensure the instrument filter takes precedence over id.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@components/OrderGrid/__tests__/order-grid-empty-state.test.ts`:
- Around line 3-24: Add a test that verifies priority when both instrument and
id filters are provided: update the test suite for getOrderGridEmptyStateMessage
to include a case calling getOrderGridEmptyStateMessage({ instrument: 'READL3',
id: '1001' }) and assert it returns the instrument-specific message 'READL3 nao
encontrado.' to ensure the instrument filter takes precedence over id.

In `@lib/orders/orders.filter.ts`:
- Around line 95-108: Precompute lowercase "needles" from normalizedFilters once
before calling orders.filter to avoid repeating toLowerCase per row: create
local variables like idNeedle = normalizedFilters.id ?
normalizedFilters.id.toLowerCase() : undefined and instrumentNeedle =
normalizedFilters.instrument ? normalizedFilters.instrument.toLowerCase() :
undefined, then update the predicate inside the orders.filter callback to check
idNeedle and instrumentNeedle (e.g., if (idNeedle &&
!order.id.toLowerCase().includes(idNeedle)) return false) and similarly for
instrument using order.instrument; this keeps the same logic but avoids repeated
lowercase conversions and simplifies the filter checks.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b62c682b-08f9-44e3-ba08-46aa9cc010a9

📥 Commits

Reviewing files that changed from the base of the PR and between 9a156ae and e93eb12.

📒 Files selected for processing (11)
  • components/OrderGrid/OrderGridWithPaginationClient.tsx
  • components/OrderGrid/__tests__/OrderGridWithPaginationClient.test.tsx
  • components/OrderGrid/__tests__/order-grid-empty-state.test.ts
  • components/OrderGrid/__tests__/order-grid.query.test.ts
  • components/OrderGrid/order-grid-empty-state.ts
  • components/OrderGrid/order-grid.query.ts
  • components/OrderGrid/parts/FilterDatePicker.tsx
  • components/OrderGrid/parts/FilterSelect.tsx
  • components/OrderGrid/parts/__tests__/FilterSelect.test.tsx
  • components/OrderGrid/useOrderGridWithPaginationController.ts
  • lib/orders/orders.filter.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • components/OrderGrid/order-grid.query.ts
  • components/OrderGrid/parts/FilterDatePicker.tsx
  • components/OrderGrid/tests/order-grid.query.test.ts

@atelesjr
atelesjr merged commit c2bd882 into main Mar 16, 2026
3 checks passed
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