feat(blog): add category filtering and navigation#1990
feat(blog): add category filtering and navigation#1990ComputelessComputer merged 1 commit intomainfrom
Conversation
✅ Deploy Preview for hyprnote ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
✅ Deploy Preview for hyprnote-storybook ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
📝 WalkthroughWalkthroughThis PR adds category filtering functionality to the blog by introducing a category field to the articles schema and implementing search parameter validation, category-based filtering logic, and responsive UI sections for category navigation with article counts. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20–25 minutes
Possibly related PRs
Suggested reviewers
Pre-merge checks and finishing touches❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
|
The latest updates on your projects. Learn more about Argos notifications ↗︎
|
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (3)
apps/web/src/routes/_view/blog/index.tsx (3)
18-27: Consider derivingCATEGORIESfrom the schema to avoid duplication.The
CATEGORIESconstant duplicates the enum values defined incontent-collections.ts. If the schema enum changes, this array must be updated manually, risking drift.You could export the category values from the schema or use the generated types:
// Option 1: Import from content-collections if available import { allArticles } from "content-collections"; // Derive categories from actual article data const CATEGORIES = [...new Set(allArticles.map(a => a.category).filter(Boolean))] as const;Alternatively, define a shared constant that both the schema and this file import.
31-36: Consider validating category against known values.The
validateSearchaccepts any string forcategory. An invalid category (e.g.,?category=invalid) will result in showing zero articles with no user feedback.validateSearch: (search: Record<string, unknown>): BlogSearch => { + const validCategories = ["featured", ...CATEGORIES]; + const category = typeof search.category === "string" ? search.category : undefined; return { - category: - typeof search.category === "string" ? search.category : undefined, + category: category && validCategories.includes(category) ? category : undefined, }; },
62-66: MemoizesortedArticlesto prevent unnecessary recalculations.
sortedArticlescreates a new array reference on every render, causingarticlesByCategoryandfilteredArticlesto recompute even whenpublishedArticleshasn't changed.- const sortedArticles = [...publishedArticles].sort((a, b) => { - const aDate = a.updated || a.created; - const bDate = b.updated || b.created; - return new Date(bDate).getTime() - new Date(aDate).getTime(); - }); + const sortedArticles = useMemo(() => { + return [...publishedArticles].sort((a, b) => { + const aDate = a.updated || a.created; + const bDate = b.updated || b.created; + return new Date(bDate).getTime() - new Date(aDate).getTime(); + }); + }, [publishedArticles]);
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
apps/web/content-collections.ts(1 hunks)apps/web/src/routes/_view/blog/index.tsx(11 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.ts: Agent implementations should use TypeScript and follow the established architectural patterns defined in the agent framework
Agent communication should use defined message protocols and interfaces
Files:
apps/web/content-collections.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: Avoid creating a bunch of types/interfaces if they are not shared. Especially for function props, just inline them instead.
Never do manual state management for form/mutation. Use useForm (from tanstack-form) and useQuery/useMutation (from tanstack-query) instead for 99% of cases. Avoid patterns like setError.
If there are many classNames with conditional logic, usecn(import from@hypr/utils). It is similar toclsx. Always pass an array and split by logical grouping.
Usemotion/reactinstead offramer-motion.
Files:
apps/web/content-collections.tsapps/web/src/routes/_view/blog/index.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: Redirect rules - hyprnote
- GitHub Check: Header rules - hyprnote
- GitHub Check: Pages changed - hyprnote
- GitHub Check: fmt
- GitHub Check: ci (macos, macos-14)
🔇 Additional comments (9)
apps/web/content-collections.ts (1)
50-57: LGTM!The optional
categoryenum field is well-defined and aligns with theCATEGORIESconstant in the blog route component. Making it optional is appropriate for backward compatibility with existing articles.apps/web/src/routes/_view/blog/index.tsx (8)
159-214: LGTM!Clean implementation of the mobile category navigation. Good use of
cnwith arrays for conditional styling as per coding guidelines, and proper responsive design with horizontal scrolling.
216-289: LGTM!Well-structured desktop sidebar component with proper sticky positioning, category counts, and consistent styling patterns using
cnwith arrays.
291-329: LGTM!Clean featured section implementation with appropriate grid layout and separation between the most recent featured article and others.
331-359: LGTM!The
AllArticlesSectioncorrectly derives the title fromselectedCategoryand renders the filtered article list appropriately.
370-442: LGTM!Well-implemented featured card with appropriate image loading state management and conditional category badge rendering.
444-538: LGTM!Consistent implementation with
MostRecentFeaturedCard, with appropriate responsive layout adjustments for the smaller card variant.
540-616: LGTM!Clean article list item implementation with appropriate responsive design for both mobile and desktop views, including conditional category badge rendering.
618-652: LGTM!Clean, reusable image component with proper loading state handling and early return for missing sources.
No description provided.