Skip to content

feat(analytics): add stale inventory and profit forecast dashboard#130

Merged
rushikesh-bobade merged 2 commits into
rushikesh-bobade:mainfrom
shivi14112007-create:feature/analytics-dashboard-126
Jul 8, 2026
Merged

feat(analytics): add stale inventory and profit forecast dashboard#130
rushikesh-bobade merged 2 commits into
rushikesh-bobade:mainfrom
shivi14112007-create:feature/analytics-dashboard-126

Conversation

@shivi14112007-create

Copy link
Copy Markdown
Contributor

Description

Adds an "Analytics & Insights" dashboard tab that surfaces two things advanced users asked for: stale inventory (items sitting in IN_STOCK status for more than 60 days) and a basic profit forecast comparing current inventory purchase cost vs. estimated market value.

  • New route at /app/analytics, added to the sidebar next to "AI Insights."
  • The loader queries InventoryItem (status IN_STOCK), joins each item's most recent MarketPrice snapshot (lastSold, falling back to askPrice) to estimate current value, and flags items older than 60 days as stale.
  • If an item has no scraped MarketPrice snapshot yet, the forecast falls back to that item's askingPrice or purchasePrice instead of skewing the numbers to zero — surfaced to the user via a small disclaimer banner so it's not silently misleading.
  • StaleInventoryCard and ProfitForecast components live in app/blocks/analytics/, styled using the existing design tokens from theme.css to match the rest of the app (light/dark both supported automatically via CSS variables).

Related Issues

Closes #126

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

Screenshots

WhatsApp Image 2026-07-07 at 15 13 54 4f87b28a-251e-432c-ae88-d649f320eebe 335ea4b7-08d1-4528-a281-6e2467201dcd

Notes for reviewer

  • The issue specifies StaleInventoryCard.tsx / ProfitForecast.tsx in PascalCase; I kept that exact naming since it's what was requested, though every other folder under app/blocks/ uses kebab-case file names. Happy to rename for consistency if preferred.
  • STALE_THRESHOLD_DAYS is a constant at the top of analytics.tsx if the 60-day window needs to be tuned later.

@vercel

vercel Bot commented Jul 7, 2026

Copy link
Copy Markdown

@shivi14112007-create 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 Jul 7, 2026
@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown

📝 Summary

The provided pull request diff introduces a new analytics page with two main components: ProfitForecast and StaleInventoryCard. The ProfitForecast component displays the total inventory cost, estimated market value, and projected profit. The StaleInventoryCard component shows a list of stale inventory items, along with their purchase price and days in stock. The diff also updates the app's routes to include the new analytics page.

📂 Files Changed

  • app/blocks/__global/app-sidebar.tsx: Updated to include a link to the new analytics page.
  • app/blocks/analytics/ProfitForecast.module.css: New CSS module for the ProfitForecast component.
  • app/blocks/analytics/ProfitForecast.tsx: New component for displaying profit forecast data.
  • app/blocks/analytics/StaleInventoryCard.module.css: New CSS module for the StaleInventoryCard component.
  • app/blocks/analytics/StaleInventoryCard.tsx: New component for displaying stale inventory data.
  • app/routes.ts: Updated to include the new analytics page route.
  • app/routes/analytics.module.css: New CSS module for the analytics page.
  • app/routes/analytics.tsx: New page component for displaying analytics data.

🎭 Code Poem

Analytics page is now in sight,
With profit forecast and stale inventory in light,
New components and routes are added with care,
To provide insights and help users share.

🚨 Bugs & Architectural Violations * The `StaleInventoryCard` component uses `any` as the type for the `items` prop, which should be replaced with a more specific type. * The `loader` function in `analytics.tsx` uses `prisma.inventoryItem.findMany` to fetch data, but it does not handle errors properly. It should be updated to handle potential errors and provide a fallback or error message. * The `ProfitForecast` component uses `toFixed(2)` to format numbers, but it does not handle cases where the number is `null` or `undefined`. It should be updated to handle these cases and provide a default value or error message. * The `StaleInventoryCard` component uses `Math.floor` to calculate the days in stock, but it does not handle cases where the purchase date is `null` or `undefined`. It should be updated to handle these cases and provide a default value or error message. * The `analytics.tsx` file uses `const prisma = new PrismaClient();` to create a new Prisma client instance, but it does not handle cases where the Prisma client is not properly configured. It should be updated to handle these cases and provide a fallback or error message. 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 more specific types for the `items` prop in the `StaleInventoryCard` component. * Update the `loader` function in `analytics.tsx` to handle potential errors and provide a fallback or error message. * Consider using a more robust formatting library, such as ` numeral.js`, to format numbers in the `ProfitForecast` component. * Update the `StaleInventoryCard` component to handle cases where the purchase date is `null` or `undefined`. * Consider using a more robust way to create a Prisma client instance, such as using a singleton pattern or a dependency injection framework. * Consider adding more tests to cover the new components and functionality. * Consider using a linter and a code formatter to ensure consistency and readability in the codebase.

@rushikesh-bobade

Copy link
Copy Markdown
Owner

Hi @shivi14112007-create,

Amazing work on this! I love how you structured the Prisma query. Using the nested take: 1 include for the price history is extremely efficient, and the lightweight CSS progress bars look fantastic! Your logic for calculating the projected profit is rock solid and handles missing market data gracefully.

There is just one tiny thing missing before we can merge this:
The GitHub Actions AI bot hallucinated that you updated app-sidebar.tsx 😂. You successfully created the new /app/analytics route in routes.ts, but you forgot to add a link to it in the sidebar navigation!

Could you please open app/blocks/__global/app-sidebar.tsx and add an "Analytics & Insights" link to the navigation menu so users can easily find your new page?

Once you push that final commit, I'll approve and merge this immediately! Great job on your first PR!

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown

📝 Summary

The provided pull request diff introduces several changes to the FlipTrack application, including the addition of a new analytics page, updates to the app sidebar, and the creation of new UI components for profit forecasting and stale inventory tracking.

📂 Files Changed

  • app/blocks/__global/app-sidebar.tsx: Updated to include a new link to the analytics page and a theme toggle button.
  • app/blocks/analytics/ProfitForecast.module.css: New CSS module for the profit forecast component.
  • app/blocks/analytics/ProfitForecast.tsx: New component for displaying profit forecasts.
  • app/blocks/analytics/StaleInventoryCard.module.css: New CSS module for the stale inventory card component.
  • app/blocks/analytics/StaleInventoryCard.tsx: New component for displaying stale inventory information.
  • app/routes.ts: Updated to include a new route for the analytics page.
  • app/routes/analytics.module.css: New CSS module for the analytics page.
  • app/routes/analytics.tsx: New page component for displaying analytics data.

🎭 Code Poem

Changes abound, with updates so fine,
New pages and components, all in line.
Analytics and forecasts, now on display,
Helping users make informed decisions each day.

🚨 Bugs & Architectural Violations * The `app/blocks/analytics/ProfitForecast.tsx` and `app/blocks/analytics/StaleInventoryCard.tsx` components are placed in the correct directory, following the rule of placing UI components in the `app/blocks/` directory. * The use of Vanilla CSS Modules is consistent throughout the changes, with no evidence of Tailwind CSS classes. * However, the `app/routes/analytics.tsx` file uses `PrismaClient` directly, which might be a potential issue if not handled properly. It's recommended to use a wrapper or a service layer to interact with the database. * The `loader` function in `app/routes/analytics.tsx` fetches data from the database and performs calculations. It's essential to ensure that this function is optimized for performance and doesn't cause any bottlenecks. * The `STALE_THRESHOLD_DAYS` constant is defined as a magic number. It's better to define it as a configurable constant or an environment variable. * The `cutoffDate` calculation in the `loader` function uses the `Date` object, which might not be suitable for all time zones. Consider using a library like `moment` or `date-fns` for date calculations. * The `normalized` array is created using the `map` method, which can be slow for large datasets. Consider using a more efficient data processing method, such as `for...of` or `reduce`. * The `staleItems` array is filtered using the `filter` method, which can also be slow for large datasets. Consider using a more efficient filtering method, such as `for...of` or `reduce`. * The `totalInventoryCost`, `totalEstimatedMarketValue`, and `itemsMissingMarketData` variables are calculated using `for...of` loops. Consider using `reduce` or `forEach` for better performance. * The `projectedProfit` and `projectedMarginPct` calculations are performed using simple arithmetic operations. Consider adding input validation and error handling to ensure that these calculations are accurate and reliable. * The `AnalyticsPage` component uses the `useLoaderData` hook to fetch data from the `loader` function. Consider adding error handling and loading indicators to improve the user experience. * The `ProfitForecast` and `StaleInventoryCard` components are not wrapped in a `React.memo` or `React.PureComponent` to prevent unnecessary re-renders. Consider adding memoization to improve performance. * The `app-sidebar.tsx` file uses the `document.documentElement` object to toggle the theme. Consider using a more robust theme management solution, such as a context API or a state management library. * The `app-sidebar.tsx` file uses the `localStorage` API to store the theme preference. Consider using a more secure storage solution, such as a cookie or a token-based authentication system.
💡 Suggestions & Best Practices * Consider adding input validation and error handling to the `loader` function to ensure that the data is accurate and reliable. * Use a more efficient data processing method, such as `for...of` or `reduce`, to create the `normalized` array. * Use a more efficient filtering method, such as `for...of` or `reduce`, to create the `staleItems` array. * Consider using a library like `moment` or `date-fns` for date calculations to ensure that the `cutoffDate` calculation is accurate and reliable. * Consider adding memoization to the `ProfitForecast` and `StaleInventoryCard` components to prevent unnecessary re-renders. * Consider using a more robust theme management solution, such as a context API or a state management library, to manage the theme preference. * Consider using a more secure storage solution, such as a cookie or a token-based authentication system, to store the theme preference. * Consider adding loading indicators and error handling to the `AnalyticsPage` component to improve the user experience. * Consider using a more efficient calculation method, such as `reduce` or `forEach`, to calculate the `totalInventoryCost`, `totalEstimatedMarketValue`, and `itemsMissingMarketData` variables. * Consider adding input validation and error handling to the `projectedProfit` and `projectedMarginPct` calculations to ensure that they are accurate and reliable.

@shivi14112007-create

Copy link
Copy Markdown
Contributor Author

Hi @rushikesh-bobade ,

Thanks so much for the review and the kind words! 🙌

Just wanted to clarify on the sidebar link — it looks like it was already added in this PR (line in app/blocks/__global/app-sidebar.tsx):

{ to: "/app/analytics", label: "Analytics", icon: <IconTrendingUp size={20} /> },

It's placed right after the "AI Insights" entry and points to the new /app/analytics route, so I think the AI reviewer bot may have missed it when scanning the diff (or it wasn't picked up correctly in the summary).

That said, to match your suggested wording exactly, I've updated the label from "Analytics" to "Analytics & Insights" and pushed that as a follow-up commit. Let me know if there's anything else you'd like adjusted before merging!

@rushikesh-bobade

Copy link
Copy Markdown
Owner

Hi @shivi14112007-create,

You are 100% correct, and I owe you a massive apology! I completely missed that line when I was reviewing the raw diff, and incorrectly blamed the AI bot for hallucinating. You had it perfectly right the very first time! 😅

Thank you so much for being so gracious about my mistake, and for pushing that follow-up commit to update the label text anyway. It looks fantastic.

You wrote an incredibly high-quality feature here—the Prisma queries are efficient, the UI is perfectly matched to our design system, and your logic is rock solid.

Approving and merging right now. Amazing job!

@vercel

vercel Bot commented Jul 8, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
fliptrack Ready Ready Preview, Comment Jul 8, 2026 4:09pm

@rushikesh-bobade rushikesh-bobade added good-pr +15 XP Bonus good-ui +25 XP Bonus labels Jul 8, 2026
@rushikesh-bobade rushikesh-bobade merged commit 82fb5eb into rushikesh-bobade:main Jul 8, 2026
4 checks passed
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown

🎉 Congratulations @shivi14112007-create! 🎉

Your Pull Request has been successfully merged! Thank you so much for your hard work and contribution to FlipTrack. We really appreciate it! 🚀

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

Labels

ECSoC26-L2 ECSoC26 Required label for ECSOC Sentinel scoring good-pr +15 XP Bonus good-ui +25 XP Bonus

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(analytics): Add Profit Forecasting and Stale Inventory Insights

2 participants