-
Notifications
You must be signed in to change notification settings - Fork 0
[feature] Filter posts & categories #7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughThis update introduces dynamic category filtering and search in the articles list, enhances image loading strategies across components, and upgrades the API client and store to support POST requests with filter parameters. TypeScript interfaces for API responses and filters are added, and the package.json is updated with lodash and its type definitions. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant HeaderPartial
participant ApiStore
participant ArticlesListPartial
User->>HeaderPartial: Type in search box
HeaderPartial->>HeaderPartial: Debounce input, validate
HeaderPartial->>ApiStore: setSearchTerm(query)
ApiStore-->>ArticlesListPartial: searchTerm updated (reactive)
ArticlesListPartial->>ApiStore: getPosts({ category, text: searchTerm })
ApiStore->>ApiClient: post('/posts?limit=5', filters)
ApiClient-->>ApiStore: PostsCollectionResponse
ApiStore-->>ArticlesListPartial: PostsCollectionResponse
ArticlesListPartial-->>User: Render filtered posts
sequenceDiagram
participant ArticlesListPartial
participant ApiStore
participant ApiClient
ArticlesListPartial->>ApiStore: getCategories()
ApiStore->>ApiClient: get('/categories?limit=5')
ApiClient-->>ApiStore: CategoriesCollectionResponse
ApiStore-->>ArticlesListPartial: CategoriesCollectionResponse
ArticlesListPartial-->>ArticlesListPartial: Render categories as filter links
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
Note ⚡️ Unit Test Generation is now available in beta!Learn more here, or try it out under "Finishing Touches" below. ✨ Finishing Touches
🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Summary of Changes
Hello @gocanto, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!
This pull request transitions the article category display from static, hardcoded values to dynamic content fetched from an API. It introduces new API client methods and data models to support category retrieval, enhancing the flexibility and maintainability of the article listing page.
Highlights
- Dynamic Category Display: The
ArticlesListPartial.vuecomponent has been updated to dynamically render article categories by iterating over acategoriesdata property usingv-for, replacing previously hardcoded list items. - API Integration for Categories: A new
getCategories()method has been added to theapiStoreto fetch category data from the backend. This method is called within theonMountedlifecycle hook ofArticlesListPartial.vueto populate the categories displayed. - New Data Models: New TypeScript interfaces,
CategoriesCollectionResponseandCategoryResponse, have been introduced insrc/stores/api/response/categories-response.tsto define the structure of the category data received from the API. - API Query Limits: Both the
getCategories()andgetPosts()API calls insrc/stores/api/store.tsnow include alimit=5query parameter, restricting the number of items returned.
Using Gemini Code Assist
The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.
Invoking Gemini
You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.
| Feature | Command | Description |
|---|---|---|
| Code Review | /gemini review |
Performs a code review for the current pull request in its current state. |
| Pull Request Summary | /gemini summary |
Provides a summary of the current pull request in its current state. |
| Comment | @gemini-code-assist | Responds in comments when explicitly tagged, both in issue comments and review comments. |
| Help | /gemini help |
Displays a list of available commands. |
Customization
To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.
Limitations & Feedback
Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments or fill out our survey to provide feedback.
You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.
Footnotes
-
Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request introduces functionality to fetch and display article categories from an API, replacing a previously hardcoded list. The implementation is straightforward, but I've identified a few areas for improvement regarding UI correctness, performance, and code maintainability. My review includes suggestions to fix a UI bug with category selection, optimize data fetching with parallel requests, and improve code clarity by removing magic numbers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
♻️ Duplicate comments (2)
src/stores/api/store.ts (2)
40-48: Address the magic number in getCategories.The hardcoded limit value "5" should be extracted to a named constant as flagged in previous reviews. This same value is used in
getPostson line 50.
49-57: Good API design change but address magic number.The change from GET to POST request for
getPostsis appropriate when adding filtering capabilities. However, the hardcoded limit "5" should be extracted to a named constant as flagged in previous reviews.
🧹 Nitpick comments (2)
package.json (1)
16-16: Consider lightweight alternatives to lodash for debouncing.While lodash is a solid choice, consider if you need the entire library just for debouncing functionality. Lightweight alternatives like
lodash.debounce(individual package) or native implementations might reduce bundle size.For debouncing only, you could use:
lodash.debouncepackage (smaller footprint)- A simple native implementation
- Modern utilities like
@vueuse/corewhich providesuseDebouncedRefCurrent choice is acceptable if you plan to use other lodash utilities.
src/partials/HeaderPartial.vue (1)
66-96: Consider the 5-character minimum requirement.The search implementation is well-structured with proper debouncing and validation. However, the 5-character minimum requirement might be too restrictive for users. Consider whether a shorter minimum (e.g., 3 characters) would provide better UX while still avoiding excessive API calls.
The debounce cancellation in
clearSearchAndErrorand proper state management are excellent practices.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (10)
package.json(2 hunks)src/pages/PostPage.vue(1 hunks)src/partials/ArticleItemPartial.vue(1 hunks)src/partials/ArticlesListPartial.vue(2 hunks)src/partials/AvatarPartial.vue(1 hunks)src/partials/HeaderPartial.vue(2 hunks)src/stores/api/client.ts(1 hunks)src/stores/api/response/categories-response.ts(1 hunks)src/stores/api/response/posts-response.ts(1 hunks)src/stores/api/store.ts(2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
src/stores/api/store.ts (4)
src/stores/api/client.ts (2)
ApiClient(29-134)defaultCreds(5-10)src/stores/api/response/categories-response.ts (1)
CategoriesCollectionResponse(1-7)src/stores/api/http-error.ts (1)
parseError(17-27)src/stores/api/response/posts-response.ts (2)
PostsFilters(48-54)PostsCollectionResponse(1-7)
src/stores/api/client.ts (1)
src/stores/api/http-error.ts (1)
HttpError(1-15)
🔇 Additional comments (17)
package.json (1)
27-27: LGTM - Type definitions properly added.The TypeScript definitions for lodash are correctly added to devDependencies with a compatible version.
src/partials/ArticleItemPartial.vue (1)
4-13: Excellent image optimization for article list items.The image attributes are well-chosen for list item performance:
loading="lazy"appropriately defers loading until neededdecoding="async"prevents blocking the main threadfetchpriority="low"correctly prioritizes these secondary images below critical contentThis optimization strategy will improve initial page load performance while maintaining good UX as users scroll.
src/stores/api/client.ts (1)
83-98: Well-implemented POST method following existing patterns.The
post<T>method implementation is solid:
- Consistent error handling with the existing
getmethod usingHttpError- Proper JSON serialization of request body
- Appropriate omission of caching logic (unlike GET requests)
- Correct use of existing
createHeaders()method- Clean async/await pattern with proper error propagation
The method signature and implementation align well with the existing codebase patterns.
src/stores/api/response/posts-response.ts (1)
48-54: Well-designed filtering interface.The
PostsFiltersinterface is well-structured with optional string properties that provide flexible filtering capabilities. The interface follows TypeScript best practices and integrates cleanly with the rest of the codebase.src/stores/api/response/categories-response.ts (1)
1-14: Consistent and well-structured category interfaces.Both interfaces follow established patterns in the codebase.
CategoriesCollectionResponsemaintains consistency with the existing pagination structure used inPostsCollectionResponse, andCategoryResponseincludes all necessary fields for category data management.src/stores/api/store.ts (2)
12-12: Well-implemented search term management.The addition of
searchTermto the store state and thesetSearchTermaction provides a clean way to manage global search state across components.Also applies to: 20-20
23-25: Clean implementation of search term setter.The
setSearchTermaction is straightforward and properly updates the store state.src/partials/HeaderPartial.vue (4)
6-6: Good form handling with prevent default.Proper use of
@submit.preventto handle form submission without page reload.
11-11: Effective validation feedback implementation.The dynamic class binding provides clear visual feedback for validation errors, and the v-model binding is properly implemented.
13-22: Clean conditional icon rendering.The conditional rendering between search and clear icons based on validation state provides good UX, and the clear functionality is properly implemented.
58-61: Proper imports and store integration.Clean imports including lodash debounce and proper integration with the API store.
src/partials/ArticlesListPartial.vue (6)
7-19: Excellent dynamic category filtering implementation.The dynamic category rendering with conditional styling based on
filters.categoryproperly addresses the previous review comment about hardcoded active states. The implementation correctly applies active/inactive styles based on the selected category.
30-36: Clean imports and proper typing.Good use of lodash debounce and proper TypeScript interface imports for type safety.
41-51: Well-structured reactive state management.The reactive
filtersobject and category state variables are properly typed and organized. TheselectCategoryfunction provides a clean interface for category selection.
53-61: Clean posts fetching implementation.The
fetchPostsfunction is well-structured with proper error handling and type casting.
64-78: Good reactive filtering with debouncing.The watchers for category and search term changes are well-implemented. The debounced category filter prevents excessive API calls, while the immediate search term filter provides quick feedback for user searches.
81-94: Consider parallel API calls for better performance.The sequential API calls for categories and posts could be optimized by running them in parallel, as suggested in previous reviews. However, since posts depend on having a category selected first, the current sequential approach is actually correct for the business logic.
The automatic selection of the first category and subsequent post fetching is a good UX decision.
|
@coderabbitai full review |
✅ Actions performedFull review triggered. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (5)
src/partials/AvatarPartial.vue (1)
2-2: Same accessibility issue as previously identified.The
aria-hidden="true"attribute is still problematic on meaningful avatar images that have descriptive alt text.src/pages/PostPage.vue (1)
89-89: Same accessibility issue as previously identified.The
aria-hidden="true"attribute remains problematic on the meaningful post cover image that has semantic alt text.src/stores/api/store.ts (2)
40-48: LGTM! Consistent API method pattern.The
getCategoriesmethod follows the same error handling pattern as other API methods in the store.
49-57: Verify the design decision to use POST for fetching posts.Changing from GET to POST for fetching posts is an unusual architectural decision, as GET requests are typically used for data retrieval and POST for mutations. This could impact caching, SEO, and API conventions.
#!/bin/bash # Check if there are any comments or documentation explaining why POST is used for getPosts rg -A 5 -B 5 "getPosts.*POST|POST.*getPosts" --type md --type txt rg -A 10 -B 5 "why.*POST|POST.*why" --type md --type txt --type js --type tssrc/partials/ArticlesListPartial.vue (1)
81-94: Consider parallel API calls for better performance.The current sequential API calls could be optimized by running them in parallel since they don't depend on each other.
onMounted(async () => { try { - categoriesCollection.value = await apiStore.getCategories(); - categories.value = categoriesCollection.value.data as CategoryResponse[]; + const [categoriesResult] = await Promise.all([ + apiStore.getCategories() + ]); + + categoriesCollection.value = categoriesResult; + categories.value = categoriesResult.data as CategoryResponse[]; if (categories.value.length > 0) { filters.category = categories.value[0].slug; await fetchPosts(); } } catch (error) { debugError(error); } });
🧹 Nitpick comments (1)
src/partials/HeaderPartial.vue (1)
69-96: LGTM! Well-implemented search functionality with proper debouncing.The search implementation includes:
- Proper debouncing to prevent excessive API calls
- Reasonable validation (5-character minimum)
- Clean error state management
- Proper cleanup when clearing search
Consider whether the 5-character minimum might be too restrictive for some use cases, but the current implementation provides good balance between UX and API efficiency.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (10)
package.json(2 hunks)src/pages/PostPage.vue(1 hunks)src/partials/ArticleItemPartial.vue(1 hunks)src/partials/ArticlesListPartial.vue(2 hunks)src/partials/AvatarPartial.vue(1 hunks)src/partials/HeaderPartial.vue(2 hunks)src/stores/api/client.ts(1 hunks)src/stores/api/response/categories-response.ts(1 hunks)src/stores/api/response/posts-response.ts(1 hunks)src/stores/api/store.ts(2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
src/stores/api/client.ts (1)
src/stores/api/http-error.ts (1)
HttpError(1-15)
src/stores/api/store.ts (4)
src/stores/api/client.ts (2)
ApiClient(29-134)defaultCreds(5-10)src/stores/api/response/categories-response.ts (1)
CategoriesCollectionResponse(1-7)src/stores/api/http-error.ts (1)
parseError(17-27)src/stores/api/response/posts-response.ts (2)
PostsFilters(48-54)PostsCollectionResponse(1-7)
🔇 Additional comments (11)
src/partials/ArticleItemPartial.vue (1)
4-13: Excellent image loading optimization.The combination of
loading="lazy",decoding="async", andfetchpriority="low"is well-suited for article list thumbnails. This improves performance by deferring non-critical image loading while maintaining accessibility with proper alt text.src/stores/api/response/posts-response.ts (1)
48-54: Well-designed filtering interface.The
PostsFiltersinterface provides a clean, flexible contract for post filtering with optional properties that allow various filtering combinations.src/stores/api/client.ts (1)
83-98: Well-implemented POST method following established patterns.The new
post<T>method maintains consistency with the existingget<T>method structure, uses the same error handling approach withHttpError, and appropriately excludes caching logic for POST requests.src/stores/api/response/categories-response.ts (1)
1-14: LGTM! Well-structured TypeScript interfaces.The interfaces follow a consistent pattern with the existing API response structure and provide proper typing for category data. The pagination metadata and category properties are appropriately defined.
src/stores/api/store.ts (1)
12-12: LGTM! Clean search state management.The addition of
searchTermstate andsetSearchTermaction provides a clean way to manage global search state across components.Also applies to: 20-20, 23-25
src/partials/HeaderPartial.vue (2)
6-6: LGTM! Proper form submission handling.The form correctly prevents default submission and delegates to the
performSearchmethod.
11-22: LGTM! Excellent UX with conditional validation feedback.The search input provides clear visual feedback with conditional border styling and icon changes based on validation state. The toggle between search and clear icons enhances usability.
src/partials/ArticlesListPartial.vue (4)
7-19: LGTM! Excellent improvement from hardcoded to dynamic categories.The dynamic category rendering with proper conditional class binding resolves the previous issue with hardcoded active styles. Each category now correctly shows active/inactive state based on the selected filter.
44-51: LGTM! Clean reactive filter management.The
selectCategoryfunction and reactivefiltersobject provide a clean way to manage filtering state.
53-61: LGTM! Well-structured posts fetching with proper error handling.The extracted
fetchPostsfunction provides a clean, reusable way to fetch filtered posts with appropriate error handling.
64-78: LGTM! Appropriate debouncing strategy for different filter types.The implementation correctly uses debouncing for category changes (which are user-initiated clicks) but immediate execution for search term changes (which come from a pre-debounced source). This provides optimal UX.
Summary by CodeRabbit
New Features
Improvements
Chores