Skip to content

feat: Add sorting functionality to Sales Log table#36

Open
Tiwari-Harshvardhan wants to merge 7 commits into
rushikesh-bobade:mainfrom
Tiwari-Harshvardhan:feature/sales-log-sorting
Open

feat: Add sorting functionality to Sales Log table#36
Tiwari-Harshvardhan wants to merge 7 commits into
rushikesh-bobade:mainfrom
Tiwari-Harshvardhan:feature/sales-log-sorting

Conversation

@Tiwari-Harshvardhan

Copy link
Copy Markdown
  • Make all column headers clickable for sorting
  • Support ascending/descending toggle
  • Add visual sort indicators (↕ ↑ ↓)
  • Improve accessibility with ARIA attributes
  • Add keyboard navigation support
  • Optimize performance with useMemo
  • Handle empty state gracefully

Closes #32

Description

This PR adds sorting functionality to the Sales Log table, allowing users to sort by any column (Item, Marketplace, Sale Price, Date, Margin, or Profit).

The implementation includes:

  • Clickable column headers that toggle between ascending/descending order
  • Visual sort indicators (↕ ↑ ↓) to show current sort state
  • Default sorting by Date (newest first) for better UX
  • Keyboard navigation support (Enter/Space keys) for accessibility
  • ARIA attributes (aria-sort, aria-label) for screen reader compatibility
  • Performance optimization using React useMemo for sorted data
  • Empty state handling when no sales exist
  • TypeScript type safety throughout the component

Why this is needed: Users currently cannot sort the Sales Log table, making it difficult to find specific sales or analyze data. This feature provides the same sorting capability already available in the Inventory table, creating a consistent user experience across the application.

Related Issues

Fixes #32

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings

Testing Instructions

  1. Navigate to the Sales Log page (/app/sales)
  2. Click on any column header (e.g., "Sale Price")
  3. Verify the table sorts ascending (↑ arrow appears)
  4. Click the same header again to sort descending (↓ arrow appears)
  5. Try clicking different columns and verify sorting works correctly
  6. Test keyboard accessibility by tabbing to a header and pressing Enter/Space
  7. Verify the sort indicator shows the current sort state

Additional Notes

  • The sorting is client-side only, maintaining the existing data fetching pattern
  • Default sort is by Date (newest first) for immediate usability
  • All sorting logic is memoized to prevent unnecessary re-renders
  • Uses the same design patterns as the Inventory table for consistency

- Make all column headers clickable for sorting
- Support ascending/descending toggle
- Add visual sort indicators (↕ ↑ ↓)
- Improve accessibility with ARIA attributes
- Add keyboard navigation support
- Optimize performance with useMemo
- Handle empty state gracefully

Closes #ISSUE_NUMBER
@vercel

vercel Bot commented Jun 30, 2026

Copy link
Copy Markdown

@Tiwari-Harshvardhan is attempting to deploy a commit to the participationcorner2025-8967's projects Team on Vercel.

A member of the Team first needs to authorize it.

@github-actions github-actions Bot added the ECSoC26 Required label for ECSOC Sentinel scoring label Jun 30, 2026
@github-actions

Copy link
Copy Markdown

📝 Summary

The provided pull request diff introduces significant changes to the sales-table.module.css and sales-table.tsx files. The changes include adding sorting functionality to the sales table, improving accessibility, and enhancing the overall user experience. The sorting functionality allows users to sort the table by different fields, such as item, marketplace, sale price, date, margin, and profit. The code also includes improvements to the table's styling, including hover effects, focus states, and responsive design adjustments.

📂 Files Changed

  • app/blocks/sales-log/sales-table.module.css: Updated CSS styles to support sorting functionality, improved accessibility, and enhanced user experience.
  • app/blocks/sales-log/sales-table.tsx: Introduced sorting functionality, improved accessibility, and enhanced user experience.

🎭 Code Poem

Code is clean, and changes are bright,
Sorting functionality, a wonderful sight.
Accessibility improved, with care and might,
User experience enhanced, a true delight.

🚨 Bugs & Warnings * The code does not handle cases where the `sales` array is `null` or `undefined`. It would be better to add a null check to prevent potential errors. * The `sortedSales` array is not memoized correctly when the `sales` array is updated. This could lead to performance issues if the `sales` array is large. * The `handleSort` function does not handle cases where the `sortField` is not a valid field. It would be better to add a check to prevent potential errors. * Looks solid otherwise!
💡 Suggestions & Best Practices * Consider adding a loading indicator when the `sales` array is being fetched or updated. * Use a more robust sorting algorithm, such as the `lodash` library, to handle complex sorting scenarios. * Add more test cases to ensure the sorting functionality works correctly in different scenarios. * Consider using a more modern CSS framework, such as `tailwindcss`, to simplify the styling process. * Use a code formatter, such as `prettier`, to ensure consistent code formatting throughout the project. * Consider adding a `README` file to the project to provide documentation and guidance for other developers.

🤖 This review was automatically generated by an AI using the Groq Llama 3 API. Please verify suggestions before applying them.

@rushikesh-bobade

Copy link
Copy Markdown
Owner

Hey @Tiwari-Harshvardhan , this is a fantastic implementation! The UI, hover states, and especially the ARIA accessibility improvements are top-tier.

However, we have a slight architectural conflict. We just merged PR #39, which introduced Server-Side Pagination to this exact table. Because the table is now paginated on the server (10 items at a time), we can no longer use client-side sorting. If we do, it will only sort the 10 items on the current page instead of the whole database!

Requested Changes:

  1. Please pull the latest main branch to resolve the merge conflicts on sales-log.tsx.
  2. Move your sortField and sortDirection state into URL Search Parameters (e.g., ?sort=profit&dir=desc) using useSearchParams.
  3. Update the loader function in app/routes/sales-log.tsx to read those URL parameters and apply them to the Prisma orderBy clause on the server before it paginates!

Let me know if you need any help wiring up the Remix server-side sorting!

@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown

📝 Summary

The provided pull request diff introduces significant changes to the sales log feature, including the addition of sorting and pagination functionality. The changes affect multiple files, including sales-table.module.css, sales-table.tsx, and sales-log.tsx. The updates aim to enhance the user experience by allowing users to sort sales data by various fields and navigate through multiple pages of data.

📂 Files Changed

  • app/blocks/sales-log/sales-table.module.css: Updated CSS styles for the sales table, including new classes for sorting and pagination.
  • app/blocks/sales-log/sales-table.tsx: Modified the SalesTable component to include sorting and pagination functionality.
  • app/routes/sales-log.tsx: Updated the loader function to fetch sales data with pagination and sorting, and added new functions for handling sort and page change events.

🎭 Code Poem

Sales log updates, a wondrous sight
Sorting and pagination, making it right
User experience, now more refined
Data navigation, a joy to design

🚨 Bugs & Architectural Violations The provided code appears to be well-structured and follows the specified architectural rules. However, a few potential issues were identified: * In `sales-table.tsx`, the `renderSortableHeader` function uses the `aria-hidden` attribute on the sort indicator span. While this is correct for accessibility, it's essential to ensure that the sort indicator is still visible to users who rely on visual cues. * The `getSortParams` function in `sales-log.tsx` does not handle cases where the `sort` or `dir` query parameters are missing or invalid. It's recommended to add more robust error handling to handle such scenarios. * The `loader` function in `sales-log.tsx` fetches sales data with pagination and sorting. However, it does not handle cases where the `page` or `pageSize` query parameters are invalid or missing. It's recommended to add more robust error handling to handle such scenarios. Looks solid overall, but these minor issues should be addressed to ensure a robust and accessible implementation.
💡 Suggestions & Best Practices To further improve the code, consider the following suggestions: * In `sales-table.tsx`, the `renderSortableHeader` function can be optimized by using a more efficient data structure, such as a `Map`, to store the sort indicators. * The `getSortParams` function in `sales-log.tsx` can be improved by using a more robust validation mechanism, such as a schema validation library, to ensure that the `sort` and `dir` query parameters conform to the expected format. * The `loader` function in `sales-log.tsx` can be optimized by using a more efficient data fetching mechanism, such as a caching layer, to reduce the number of database queries. * Consider adding more comprehensive testing to ensure that the sorting and pagination functionality works correctly in different scenarios. * To improve performance, consider using a more efficient data structure, such as a `VirtualizedList`, to render the sales data.

@rushikesh-bobade

Copy link
Copy Markdown
Owner

Hey @Tiwari-Harshvardhan, thanks for pushing this update!

Unfortunately, there are two major architectural bugs in this implementation that break the page's core functionality:

  1. Broken Summary Cards: You removed the allSalesMetrics Prisma query from the loader and removed the summary prop from <SalesSummaryCards>. Because the sales array now only contains 10 items (one page), the summary cards will only show the revenue and profit for the current page, instead of the user's lifetime total! Please restore the allSalesMetrics query.
  2. Fake Pagination on Calculated Fields: When sorting by margin or profit, you are fetching 10 items from Prisma (sorted by date) and then sorting those 10 items in JavaScript (sortedSales = [...sales].sort(...)). This is a critical bug. It means the user is not seeing the 10 most profitable items in their database; they are just seeing the 10 most recent items sorted by profit.

Since profit and margin are calculated fields that don't exist as columns in the Prisma schema, you cannot easily sort them on the server without raw SQL. For now, please remove profit and margin from the validFields list and disable sorting on those two columns entirely.

Let me know when you've pushed a fix for these two issues!

- Restore allSalesMetrics query for accurate lifetime summary cards
- Remove margin and profit from sortable fields (calculated values)
- Remove fake pagination on calculated fields
- Add proper summary prop to SalesSummaryCards
- Add non-sortable header styles for Margin and Profit columns

This ensures:
- Summary cards show lifetime totals, not just current page
- Sorting works correctly for database columns only
- No fake pagination or misleading data
@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown

📝 Summary

The provided pull request diff introduces significant changes to the sales log feature, including improvements to the sales table, sorting, and pagination. The changes aim to enhance the user experience and provide more intuitive navigation and data visualization.

📂 Files Changed

  • app/blocks/sales-log/sales-table.module.css: Updated CSS styles for the sales table, including new classes for sorting and pagination.
  • app/blocks/sales-log/sales-table.tsx: Modified the sales table component to include sorting and pagination functionality.
  • app/routes/sales-log.tsx: Updated the sales log page to handle sorting and pagination, and to fetch data from the database using the new sorting and pagination parameters.

🎭 Code Poem

Sales log updates, a wondrous sight
Sorting and pagination, making everything right
Improved user experience, a joy to behold
Code changes, a story to be told

🚨 Bugs & Architectural Violations The provided code changes appear to be well-structured and follow the specified architectural rules. However, a few potential issues were identified: * In `app/blocks/sales-log/sales-table.tsx`, the `renderSortableHeader` function uses the `aria-sort` attribute, but it's not clear if this is properly handled for screen readers. It's recommended to test the accessibility of this feature. * In `app/routes/sales-log.tsx`, the `getSortParams` function does not handle cases where the `sort` or `dir` parameters are missing or invalid. It's recommended to add error handling for these scenarios. * The code uses `parseInt` to parse the `page` parameter, which can lead to unexpected behavior if the parameter is not a valid integer. It's recommended to use a more robust parsing method, such as `Number` or a dedicated parsing library. Looks solid, but these minor issues should be addressed.
💡 Suggestions & Best Practices To further improve the code, consider the following suggestions: * In `app/blocks/sales-log/sales-table.tsx`, the `SalesTable` component has a complex render method. Consider breaking it down into smaller, more manageable functions to improve readability and maintainability. * In `app/routes/sales-log.tsx`, the `loader` function fetches data from the database using the `prisma` client. Consider adding error handling for database errors and implementing a retry mechanism to improve robustness. * The code uses a mix of `const` and `let` declarations. It's recommended to use `const` by default and only use `let` when necessary to improve code readability and avoid unintended side effects. * Consider adding more comprehensive testing for the sales log feature, including unit tests, integration tests, and end-to-end tests to ensure the feature works as expected.

@rushikesh-bobade

Copy link
Copy Markdown
Owner

@Tiwari-Harshvardhan Hey there! I just reviewed your latest commit (fd61276) and you absolutely nailed the architectural fixes. The allSales query is restored for the lifetime summary cards, and disabling sorting on the calculated profit/margin fields is exactly what we needed to prevent the fake pagination bug. Beautiful work!

Since a few days have passed, we've merged some other PRs into main which has caused a small merge conflict in your branch.

Could you please pull the latest main branch into yours and resolve the conflicts?

git fetch origin main
git merge origin/main

Once you've resolved the conflicts in sales-table.tsx and sales-log.tsx and pushed back up, this is fully approved and ready to merge!

- Keep sorting implementation with URL parameters
- Integrate platform fees and shipping costs from main
- Use raw SQL query for accurate summary calculations
- Maintain non-sortable status for Margin and Profit columns
- Preserve all accessibility features
@github-actions

github-actions Bot commented Jul 5, 2026

Copy link
Copy Markdown

📝 Summary

The provided pull request diff introduces significant changes to the sales log feature, including the implementation of sorting, pagination, and improved accessibility. The changes affect multiple files, including CSS, TypeScript, and React components.

📂 Files Changed

  • app/blocks/sales-log/sales-table.module.css: Updated CSS styles for the sales table, including new classes for sorting and pagination.
  • app/blocks/sales-log/sales-table.tsx: Modified the SalesTable component to include sorting and pagination functionality.
  • app/routes/sales-log.tsx: Updated the sales log route to handle sorting and pagination parameters, and to fetch data from the database accordingly.

🎭 Code Poem

Sales log updates, a wondrous sight
Sorting and pagination, now in flight
Accessibility improved, for all to see
A better user experience, for you and me

🚨 Bugs & Architectural Violations * The `app/blocks/sales-log/sales-table.tsx` file uses the `aria-hidden` attribute correctly, but it's essential to ensure that all interactive elements have a clear and consistent focus state. * The `app/routes/sales-log.tsx` file uses the `useLoaderData` hook to fetch data, but it's crucial to handle potential errors and loading states to prevent the application from crashing. * The `getSortParams` function in `app/routes/sales-log.tsx` does not validate the `searchParams` object, which could lead to errors if the object is null or undefined. * The `loader` function in `app/routes/sales-log.tsx` uses the `prisma` client to fetch data, but it's essential to ensure that the client is properly configured and authenticated to prevent data inconsistencies. * The `action` function in `app/routes/sales-log.tsx` does not validate the `formData` object, which could lead to errors if the object is null or undefined. Looks solid in terms of architectural rules, as it uses Remix, Prisma, and Vanilla CSS Modules, and places UI components in the correct directory.
💡 Suggestions & Best Practices * Consider adding a loading state to the SalesTable component to handle cases where the data is still being fetched. * Use a more robust validation library, such as `zod` or `joi`, to validate the `formData` object and prevent potential errors. * Implement a more efficient pagination system, such as using a cursor-based approach, to reduce the number of database queries. * Use a library like `react-query` to handle data fetching and caching, which can improve performance and reduce the number of database queries. * Consider adding a `try-catch` block to the `loader` function to handle potential errors and prevent the application from crashing. * Use a consistent naming convention throughout the codebase, such as using camelCase or PascalCase for variable and function names. * Consider adding a `README` file to the `app/blocks/sales-log` directory to provide a brief overview of the component and its functionality.

@rushikesh-bobade

Copy link
Copy Markdown
Owner

@Tiwari-Harshvardhan You're so close! It looks like when you resolved the merge conflicts, a few TypeScript errors slipped in that are failing the Typecheck and Build CI check.

Here is exactly what you need to fix:

  1. In app/blocks/sales-log/sales-table.tsx, the <Pagination> component only takes one prop (totalPages). It manages URL search params internally, so please remove currentPage and onPageChange from the <Pagination> usage.
  2. In app/routes/sales-log.tsx, you passed totalCount={totalSales} to <SalesTable />, but the variable from the loader is named totalCount, not totalSales.
  3. In app/routes/sales-log.tsx, make sure you cast sortField and sortDirection properly when passing them into <SalesTable /> since they are inferred from the URL search params as strings (e.g., sortField={sortField as SortField}).

You can run npm run typecheck locally to verify it's green. Push those minor fixes up, and we'll get this merged!

- Remove unused currentPage and onPageChange props from SalesTable
- Change totalSales to totalCount in loader return
- Add type casting for sortField and sortDirection
- Update Pagination component to use only totalPages prop
@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown

📝 Summary

The provided pull request diff introduces several changes to the sales log feature, including improvements to the sales table, sorting functionality, and pagination. The changes aim to enhance the user experience and provide more intuitive navigation and data visualization.

📂 Files Changed

  • app/blocks/sales-log/sales-table.module.css: Updated CSS styles for the sales table, including new classes for sorting indicators and empty state.
  • app/blocks/sales-log/sales-table.tsx: Modified the sales table component to include sorting functionality, pagination, and improved accessibility features.
  • app/routes/sales-log.tsx: Updated the sales log route to handle sorting and pagination parameters, and to fetch data from the database using the new sorting and pagination logic.

🎭 Code Poem

Sales log updates, a new delight
Sorting and pagination, shining bright
Improved accessibility, a welcome sight
Enhancing user experience, day and night

🚨 Bugs & Architectural Violations * The `app/blocks/sales-log/sales-table.tsx` file uses the `aria-hidden` attribute on the sort indicator element, but it is not necessary as the element is already hidden from screen readers using `display: none`. * The `app/routes/sales-log.tsx` file uses the `PrismaClient` instance without checking if it is already initialized, which could lead to multiple instances being created. * The `getSortParams` function in `app/routes/sales-log.tsx` does not handle cases where the `sort` or `dir` parameters are missing or invalid. * The `loader` function in `app/routes/sales-log.tsx` does not handle errors properly, which could lead to unexpected behavior or crashes. * The `SalesTable` component in `app/blocks/sales-log/sales-table.tsx` uses the `role` attribute on the `th` element, but it is not necessary as the element is already a table header cell. * The `SalesTable` component in `app/blocks/sales-log/sales-table.tsx` uses the `tabIndex` attribute on the `th` element, but it is not necessary as the element is not focusable. * The `app/blocks/sales-log/sales-table.module.css` file uses the `@media` queries to apply different styles based on screen size, but it does not consider other types of devices or screen readers.
💡 Suggestions & Best Practices * Consider using a more robust sorting algorithm, such as the one provided by the `lodash` library, to handle complex sorting scenarios. * Use a more efficient pagination algorithm, such as the one provided by the `react-paginate` library, to reduce the number of database queries. * Improve the accessibility of the sales table by adding more descriptive text for screen readers and providing a clear indication of the sorting direction. * Consider using a more robust error handling mechanism, such as the one provided by the `error-boundary` library, to handle unexpected errors and crashes. * Use a more consistent naming convention throughout the codebase, such as using camelCase or PascalCase for variable and function names. * Consider using a code formatter, such as Prettier, to maintain a consistent code style throughout the codebase. * Use a more robust testing framework, such as Jest or Mocha, to write unit tests and integration tests for the sales log feature.

@rushikesh-bobade

Copy link
Copy Markdown
Owner

Hi @Tiwari-Harshvardhan,

Great job! You successfully fixed the TypeScript errors inside the <SalesTable> component. We are almost at the finish line! 🏁

The CI is currently failing on one last error: Cannot find name 'totalCount' in sales-log.tsx.

If you look at app/routes/sales-log.tsx on line 204:

const { sales, totalPages, summary, sortField, sortDirection, currentPage, pageSize } = useLoaderData<typeof loader>();

You forgot to extract totalCount out of the loader! Since your <SalesTable> now calculates pagination internally and takes totalCount as a prop, you just need to swap out the destructured variables.

Change line 204 to exactly this:

const { sales, summary, sortField, sortDirection, totalCount, pageSize } = useLoaderData<typeof loader>();

Push that one line change and the build will turn green, and I will merge this PR immediately!

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown

📝 Summary

The provided pull request diff introduces several changes to the sales log feature, including improvements to the sales table, sorting functionality, and pagination. The changes aim to enhance the user experience and provide more intuitive navigation and data visualization.

📂 Files Changed

  • app/blocks/sales-log/sales-table.module.css: Updated CSS styles for the sales table, including new classes for sorting and pagination.
  • app/blocks/sales-log/sales-table.tsx: Modified the sales table component to include sorting and pagination functionality.
  • app/routes/sales-log.tsx: Updated the sales log route to handle sorting and pagination parameters, and to fetch data from the database accordingly.

🎭 Code Poem

Sales log updates, a wondrous sight
Sorting and pagination, now in flight
Improved user experience, a joy to see
Code refactored, for you and me

🚨 Bugs & Architectural Violations * The `sales-table.module.css` file has been updated to include new CSS classes, but some of the existing classes have been modified to use `transition` and `transform` properties, which may cause performance issues if not used carefully. * The `sales-table.tsx` file has been updated to include sorting and pagination functionality, but the `getSortIndicator` function uses a hardcoded arrow character (`↕`) which may not be suitable for all languages or cultures. * The `sales-log.tsx` file has been updated to handle sorting and pagination parameters, but the `getSortParams` function does not validate the `sort` and `dir` parameters, which may lead to security vulnerabilities if not properly sanitized. * The `loader` function in `sales-log.tsx` uses a `PrismaClient` instance to fetch data from the database, but it does not handle errors properly, which may lead to unexpected behavior or crashes. * The `action` function in `sales-log.tsx` uses a `PrismaClient` instance to create a new sale, but it does not validate the input data properly, which may lead to security vulnerabilities or data corruption. Looks solid in terms of architectural violations, as the code adheres to the specified rules, including the use of Remix, Prisma, and Vanilla CSS Modules.
💡 Suggestions & Best Practices * Consider using a more robust and flexible sorting algorithm, such as the one provided by the `lodash` library. * Use a more efficient data structure, such as a `Map` or an `Object`, to store the sorting and pagination parameters, instead of using URL search parameters. * Validate and sanitize all input data, including the `sort` and `dir` parameters, to prevent security vulnerabilities. * Use a more robust error handling mechanism, such as try-catch blocks or error boundaries, to handle unexpected errors or crashes. * Consider using a library like `react-query` to handle data fetching and caching, instead of using a custom implementation. * Use a consistent naming convention throughout the codebase, such as using camelCase or PascalCase for variable and function names. * Consider adding more tests to the codebase, including unit tests and integration tests, to ensure that the code is working as expected.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ECSoC26 Required label for ECSOC Sentinel scoring

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Column Sorting to Sales Table

2 participants