Enhance product management features and update dependencies#4
Conversation
- upgraded @tailwindcss/vite from ^4.1.18 to ^4.3.1 - upgraded @tanstack/react-router from latest to 1.170.16 - upgraded @tanstack/react-start from latest to 1.168.26 - upgraded better-auth from ^1.6.17 to ^1.6.19 - upgraded nodemailer from ^8.0.11 to ^9.0.0 - upgraded react-email from ^6.6.0 to ^6.6.3 - upgraded recharts from 3.8.0 to 3.8.1 - upgraded tailwindcss from ^4.1.18 to ^4.3.1 - upgraded @biomejs/biome from 2.4.16 to 2.5.0 - upgraded @types/node from ^22.19.21 to ^25.9.3 - upgraded jsdom from ^28.1.0 to ^29.1.1 - upgraded react-doctor from ^0.5.1 to ^0.5.6 - upgraded vitest from ^4.1.5 to ^4.1.9
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (7)
📒 Files selected for processing (10)
📝 WalkthroughRelease NotesProduct Management System
Data Management & Validation
UI/UX Improvements
Dependencies & Code Quality
Contribution Summary
WalkthroughAdds a complete products feature module: Zod schemas for all CRUD operations with pricing validation, five authenticated Prisma-backed server functions with audit logging, a React Query options wrapper, product column definitions with selection and actions, a paginated ChangesProducts Module
Sequence Diagram(s)sequenceDiagram
participant Browser
participant ProductsRoute
participant ReactQuery
participant getProducts
participant Prisma
Browser->>ProductsRoute: navigate to /products?page=1&pageSize=10&search=""
ProductsRoute->>ReactQuery: ensureQueryData(getProductsQuery)
ReactQuery->>getProducts: { page: 1, pageSize: 10, search: "" }
getProducts->>Prisma: $transaction([findMany(...), count(...)])
Prisma-->>getProducts: products[], total
getProducts-->>ReactQuery: { products, total, page, pageSize, pageCount }
ReactQuery-->>ProductsRoute: cached data
ProductsRoute->>Browser: render ProductPage with ProductTable + TablePagination
Browser->>ProductsRoute: type search or change page
ProductsRoute->>Browser: navigate URL with updated search/page params
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
|
React Doctor found 7 issues in 3 files · 2 errors & 5 warnings · score 66 / 100 (Needs work) · vs Errors
5 warnings
Reviewed by React Doctor for commit |
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
|
Warning Review the following alerts detected in dependencies. According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.
|
There was a problem hiding this comment.
Actionable comments posted: 17
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@package.json`:
- Line 29: Nodemailer v9.0.0 enforces strict TLS certificate validation for SMTP
connections, which may cause failures if your SMTP server uses self-signed,
expired, or mismatched certificates. Verify your SMTP server certificate is
valid first; if certificate validation issues occur during testing, locate the
SMTP transport configuration in the email transport initialization (around lines
23-34 in src/features/email/functions/index.tsx) and add a tls configuration
object with rejectUnauthorized set to false to disable strict certificate
validation for development/testing purposes.
In `@src/components/shared/table-pagination.tsx`:
- Around line 35-44: When the dataset is empty (total === 0), the current
calculation produces incorrect display text "1–0 of 0 rows". Modify the from and
to variable calculations in the table-pagination component to clamp both values
to 0 when total is 0. Check if total equals 0 at the beginning of the
calculation and set from and to to 0 in that case, otherwise use the existing
logic to compute from as (page - 1) * pageSize + 1 and to as Math.min(from +
pageSize - 1, total). This will display "0–0 of 0 rows" for empty datasets
instead of the incorrect range.
- Around line 76-136: The four pagination buttons in the table-pagination
component lack accessible labels for screen readers. Add aria-label attributes
to each Button element: the button containing IconChevronsLeft should have
aria-label="First page", the button with IconChevronLeft should have
aria-label="Previous page", the button with IconChevronRight should have
aria-label="Next page", and the button with IconChevronsRight should have
aria-label="Last page". This will enable screen readers to properly announce the
purpose of each icon-only button.
- Around line 60-64: Extract the inline array [10, 20, 50, 100] from the map
function in the table-pagination component into a named constant called
PAGE_SIZE_OPTIONS defined at the top of the component file. Then replace the
hardcoded array in the map call with a reference to this new constant to
centralize the configuration and improve maintainability.
- Around line 26-34: The TablePagination component hardcodes route-specific
navigation with useNavigate({ from: "/products/" }), making it unusable across
different routes. Remove the useNavigate hook from the component and instead add
a callback prop (such as onPageChange) to the TablePaginationProps interface
that accepts page number changes. Update all navigation button implementations
throughout the component (in the lines around 79-130 where pagination controls
are rendered) to call this callback prop instead of using the hardcoded
useNavigate. This allows parent components to handle navigation according to
their own routes.
In `@src/components/sidebar/nav-main.tsx`:
- Line 20: The SidebarMenu component on line 20 is currently rendering an empty
object instead of displaying the available menu items. Replace the empty braces
in SidebarMenu with a map function that iterates through the items array and
creates a SidebarMenuItem component for each item, passing the appropriate
properties (title, url, icon) from each item object. Additionally, ensure that
SidebarMenuItem is imported from the sidebar UI component library at the top of
the nav-main.tsx file.
In `@src/features/products/components/product-columns.tsx`:
- Around line 69-74: The icon-only Button within the DropdownMenuTrigger render
prop lacks an accessible label for assistive technologies. Add the aria-label
attribute with the value "Open product actions" to the Button component to
provide an accessible name for the interactive control. Additionally, add
aria-hidden="true" to the IconDots icon component to hide it from assistive
technologies since the accessible name is provided by the button's aria-label.
In `@src/features/products/components/product-table.tsx`:
- Around line 93-98: The Input component in the product-table.tsx file that
handles the global filter (where onChange calls setGlobalFilter) currently
relies only on placeholder text for accessibility. Add an aria-label attribute
to this Input component with an appropriate descriptive label such as "Search
products" to ensure screen readers can properly announce the input's purpose to
users with assistive technology.
- Around line 76-88: The table currently filters only the current page of data
due to manualPagination: true, so searching does not find products on other
pages. Remove getFilteredRowModel() from the useReactTable configuration and
remove the globalFilter state along with the onGlobalFilterChange handler that
wires local filtering. Instead, wire the search input to call the
searchProducts() server function directly when the filter value changes, fetch
the full search results, reset pagination to page 1, and set the new data
accordingly so that search works across the entire product dataset rather than
just the current page.
In `@src/features/products/functions/index.ts`:
- Around line 66-67: The create and update product operations in the products
functions file use inconsistent field names for the reorder quantity: line 67
references `reorderQuantity` in the raw data object passed to
prisma.product.create(), while line 91 references `reorderQty`. Normalize these
field names by choosing one consistent naming convention (either
`reorderQuantity` or `reorderQty`) and ensure both the create operation starting
at line 66 and the update operation at line 91 use the same field name when
mapping the data to be persisted.
- Around line 83-95: The updateProduct function validates sellingPrice in the
input schema but fails to include it in the data object being persisted to the
database (lines 83-95). Add the sellingPrice field to the data object that is
passed to the update operation to ensure selling prices are properly persisted
when products are updated. Include sellingPrice: data.sellingPrice in the data
object alongside the other fields like categoryId, costPrice, and name.
In `@src/features/products/schema/index.ts`:
- Around line 3-6: The page and pageSize fields in the getProductsSchema object
use basic z.number() which accepts decimals, zero, and negative values. Modify
both the page and pageSize field definitions to use z.number().int().positive()
(or equivalently .min(1)) to enforce that these pagination inputs must be
positive integers, preventing invalid skip values and broken pagination
metadata.
- Around line 29-30: The refine predicate condition on line 29 uses the <=
operator to check that sellingPrice is less than or equal to costPrice, but the
error message on line 30 states that selling price must be greater than or equal
to cost price. These are contradictory - fix the condition operator from <= to
>= so that the validation correctly ensures sellingPrice is at least as much as
costPrice, aligning the predicate logic with the error message.
In `@src/lib/utils.ts`:
- Around line 26-30: The formatCurrency function accepts non-numeric string
inputs and passes them to Number() which returns NaN, causing the format method
to output "NaN" and breaking the UI. Add validation at the start of the
formatCurrency function to check if the converted number value is valid (not
NaN) before formatting it. If the value is not a valid number, either return a
default fallback value like "0" or throw an appropriate error to prevent invalid
currency display.
In `@src/routes/_app/products/index.tsx`:
- Around line 17-24: The loader function calls queryClient.ensureQueryData() but
doesn't return the promise it generates, so React Router doesn't wait for the
data prefetch to complete before rendering. Add a return statement before the
queryClient.ensureQueryData() call in the loader function to ensure React Router
waits for the prefetch to finish and caches the data before the component
renders, preventing unnecessary suspense on page load.
- Around line 42-49: The nested Button and Link components in the products index
route create invalid HTML with nested interactive elements. Remove the Button
wrapper and instead apply button styling directly to the Link component with
appropriate className attributes and styling to maintain the visual appearance,
or if the Button component supports a to prop or asChild pattern, refactor to
render the Button as the primary interactive element that handles the navigation
to /products/new instead of nesting Link inside it.
In `@src/routes/_app/products/new.tsx`:
- Line 46: The FieldGroup component on line 46 contains an empty object literal
{} as a child, which React cannot render. Remove the empty object literal and
either convert FieldGroup to a self-closing tag (FieldGroup />) if no children
are needed, or replace it with valid child content if children are required.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 22a0e5a8-4675-4573-95c8-01af7afeefca
⛔ Files ignored due to path filters (1)
bun.lockis excluded by!**/*.lock
📒 Files selected for processing (16)
.gitignorepackage.jsonsrc/components/shared/app-header.tsxsrc/components/shared/table-pagination.tsxsrc/components/sidebar/nav-main.tsxsrc/features/products/components/product-columns.tsxsrc/features/products/components/product-table.tsxsrc/features/products/functions/index.tssrc/features/products/functions/queries.tssrc/features/products/schema/index.tssrc/lib/utils.tssrc/routeTree.gen.tssrc/routes/_app/products/$productId/edit.tsxsrc/routes/_app/products/$productId/index.tsxsrc/routes/_app/products/index.tsxsrc/routes/_app/products/new.tsx
📜 Review details
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: Use explicit types for function parameters and return values when they enhance clarity in TypeScript
Preferunknownoveranywhen the type is genuinely unknown in TypeScript
Use const assertions (as const) for immutable values and literal types in TypeScript
Leverage TypeScript's type narrowing instead of type assertions
Files:
src/lib/utils.tssrc/routes/_app/products/$productId/index.tsxsrc/routes/_app/products/$productId/edit.tsxsrc/routes/_app/products/new.tsxsrc/features/products/schema/index.tssrc/components/shared/app-header.tsxsrc/routes/_app/products/index.tsxsrc/components/sidebar/nav-main.tsxsrc/components/shared/table-pagination.tsxsrc/features/products/functions/queries.tssrc/features/products/components/product-table.tsxsrc/features/products/components/product-columns.tsxsrc/features/products/functions/index.tssrc/routeTree.gen.ts
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{js,jsx,ts,tsx}: Use meaningful variable names instead of magic numbers - extract constants with descriptive names
Use arrow functions for callbacks and short functions in JavaScript/TypeScript
Preferfor...ofloops over.forEach()and indexedforloops in JavaScript/TypeScript
Use optional chaining (?.) and nullish coalescing (??) for safer property access in JavaScript/TypeScript
Prefer template literals over string concatenation in JavaScript/TypeScript
Use destructuring for object and array assignments in JavaScript/TypeScript
Useconstby default,letonly when reassignment is needed, nevervarin JavaScript/TypeScript
Alwaysawaitpromises in async functions - don't forget to use the return value
Useasync/awaitsyntax instead of promise chains for better readability in JavaScript/TypeScript
Handle errors appropriately in async code with try-catch blocks in JavaScript/TypeScript
Don't use async functions as Promise executors in JavaScript/TypeScript
Removeconsole.log,debugger, andalertstatements from production code in JavaScript/TypeScript
ThrowErrorobjects with descriptive messages, not strings or other values in JavaScript/TypeScript
Usetry-catchblocks meaningfully - don't catch errors just to rethrow them in JavaScript/TypeScript
Prefer early returns over nested conditionals for error cases in JavaScript/TypeScript
Extract complex conditions into well-named boolean variables in JavaScript/TypeScript
Use early returns to reduce nesting in JavaScript/TypeScript
Prefer simple conditionals over nested ternary operators in JavaScript/TypeScript
Group related code together and separate concerns in JavaScript/TypeScript
Don't useeval()or assign directly todocument.cookiein JavaScript/TypeScript
Validate and sanitize user input in JavaScript/TypeScript
Avoid spread syntax in accumulators within loops in JavaScript/TypeScript
Use top-level regex literals instead of creating them in loops in JavaScript/TypeScript
...
Files:
src/lib/utils.tssrc/routes/_app/products/$productId/index.tsxsrc/routes/_app/products/$productId/edit.tsxsrc/routes/_app/products/new.tsxsrc/features/products/schema/index.tssrc/components/shared/app-header.tsxsrc/routes/_app/products/index.tsxsrc/components/sidebar/nav-main.tsxsrc/components/shared/table-pagination.tsxsrc/features/products/functions/queries.tssrc/features/products/components/product-table.tsxsrc/features/products/components/product-columns.tsxsrc/features/products/functions/index.tssrc/routeTree.gen.ts
**/*.{jsx,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{jsx,tsx}: Use function components over class components in React
Call hooks at the top level only, never conditionally in React
Specify all dependencies in hook dependency arrays correctly in React
Use thekeyprop for elements in iterables - prefer unique IDs over array indices in React
Nest children between opening and closing tags instead of passing as props in React
Don't define components inside other components in React
Use semantic HTML and ARIA attributes for accessibility: provide meaningful alt text for images, use proper heading hierarchy, add labels for form inputs, include keyboard event handlers alongside mouse events, use semantic elements instead of divs with roles in React
AvoiddangerouslySetInnerHTMLunless absolutely necessary in React
Use proper image components (e.g., Next.js<Image>) over<img>tags in Next.js
Use Next.js<Image>component for images in Next.js
Usenext/heador App Router metadata API for head elements in Next.js
Use Server Components for async data fetching instead of async Client Components in Next.js
Use ref as a prop instead ofReact.forwardRefin React 19+
Files:
src/routes/_app/products/$productId/index.tsxsrc/routes/_app/products/$productId/edit.tsxsrc/routes/_app/products/new.tsxsrc/components/shared/app-header.tsxsrc/routes/_app/products/index.tsxsrc/components/sidebar/nav-main.tsxsrc/components/shared/table-pagination.tsxsrc/features/products/components/product-table.tsxsrc/features/products/components/product-columns.tsx
**/*.{jsx,tsx,html}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{jsx,tsx,html}: Addrel="noopener"when usingtarget="_blank"on links in React/HTML
Consider accessibility, performance, and usability for user experience in React/HTML
Files:
src/routes/_app/products/$productId/index.tsxsrc/routes/_app/products/$productId/edit.tsxsrc/routes/_app/products/new.tsxsrc/components/shared/app-header.tsxsrc/routes/_app/products/index.tsxsrc/components/sidebar/nav-main.tsxsrc/components/shared/table-pagination.tsxsrc/features/products/components/product-table.tsxsrc/features/products/components/product-columns.tsx
**/index.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Avoid barrel files (index files that re-export everything) in JavaScript/TypeScript
Files:
src/routes/_app/products/$productId/index.tsxsrc/features/products/schema/index.tssrc/routes/_app/products/index.tsxsrc/features/products/functions/index.ts
**/*.{jsx,tsx,vue,svelte}
📄 CodeRabbit inference engine (AGENTS.md)
Use
classandforattributes instead ofclassNameandhtmlForin Solid/Svelte/Vue/Qwik
Files:
src/routes/_app/products/$productId/index.tsxsrc/routes/_app/products/$productId/edit.tsxsrc/routes/_app/products/new.tsxsrc/components/shared/app-header.tsxsrc/routes/_app/products/index.tsxsrc/components/sidebar/nav-main.tsxsrc/components/shared/table-pagination.tsxsrc/features/products/components/product-table.tsxsrc/features/products/components/product-columns.tsx
🔇 Additional comments (6)
src/features/products/functions/queries.ts (1)
5-13: LGTM!src/components/shared/app-header.tsx (1)
7-7: LGTM!.gitignore (1)
14-14: LGTM!package.json (1)
9-9: LGTM!Also applies to: 15-16, 18-18, 21-21, 34-34, 37-37, 40-40, 46-46, 53-53, 60-60, 62-62, 67-67
src/routes/_app/products/$productId/edit.tsx (1)
1-9: LGTM!src/routes/_app/products/$productId/index.tsx (1)
1-9: LGTM!
… reorderQuantity to reorderQty
…rice validation logic
… new product navigation
…d Supplier column
…it log for product creation
…oved product filtering
Summary
Introduces a complete product management feature including database schema definitions,
server-side CRUD functions, TanStack Query hooks, a feature-rich product table, and
route pages for listing, creating, and editing products.
Changes
getProductsQueryand CRUD utilities infunctions/products/index.tsx— Product listing page with search, pagination, and "New Product" buttonproducts/new.tsx— New product form page (scaffold)products/$productId/edit.tsx— Edit product page (scaffold)products/$productId/index.tsx— Product detail page (scaffold)PageSizeSelectorPageSizeSelector, addedseed.tsto.gitignoreFiles Changed
11 files,+748lines — all product-related, no side effects on other features.