-
Notifications
You must be signed in to change notification settings - Fork 19
implement discover page with bounty and project cards, filtering, and sorting capabilities. #10
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
…g, and sorting capabilities.
|
@0xdevcollins pls kindly review and merge |
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.
Pull request overview
Implements a new /discover page that lists mock Projects and Bounties with card UIs and client-side filtering/sorting, with filter state reflected in the URL.
Changes:
- Added shared types/config (tabs, sort options, available tags) and mock datasets for projects/bounties.
- Introduced filter UI components (search, tags, sort) and card components for projects/bounties.
- Created the Discover page with tabs, skeleton loading state, filtering/sorting logic, and empty states.
Reviewed changes
Copilot reviewed 9 out of 10 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| lib/types.ts | Adds shared type definitions and UI config for tags/tabs/sort options. |
| lib/mock-data.ts | Provides mock project and bounty datasets for the discover experience. |
| components/filters/tags-filter.tsx | Adds a tag-selection popover filter UI. |
| components/filters/sort-dropdown.tsx | Adds sort selection dropdown with optional hidden options. |
| components/filters/search-filter.tsx | Adds debounced search input for filtering. |
| components/filters/filter-panel.tsx | Composes search/tags/sort controls for desktop + mobile sheet. |
| components/cards/project-card.tsx | Adds project card presentation and navigation link. |
| components/cards/bounty-card.tsx | Adds bounty card presentation and navigation link. |
| app/discover/page.tsx | Implements the discover page (tabs, filtering/sorting, URL sync, empty/loading states). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@martinvibes implement the copilot corrections |
|
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. 📝 WalkthroughWalkthroughAdds a client-side Discover page with Projects/Bounties tabs, shared filter components, URL-synced debounced state, mock data, and new Project/Bounty card UIs plus supporting types and mock data. Changes
Sequence Diagram(s)sequenceDiagram
actor User
participant Discover as DiscoverPage
participant Filter as FilterPanel
participant Router as Router/URL
participant Data as Client Filtering/MockData
participant Cards as Card Components
User->>Discover: Open page / click tab
Discover->>Router: Read URL params (tab, search, tags, sort)
Discover->>Discover: Initialize state from params
Discover->>Filter: Render filters with state
User->>Filter: Update search/tags/sort
Filter->>Discover: onFiltersChange(newFilters)
Discover->>Router: Debounced replace URL (300ms)
Discover->>Data: Apply filters & sort to mock data
Data->>Cards: Provide filtered/sorted items
Cards->>User: Render ProjectCard / BountyCard list
alt No results
Cards->>User: Show EmptyState
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related issues
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
Comment |
|
@0xdevcollins i have fixed it ser |
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
🤖 Fix all issues with AI agents
In `@components/cards/project-card.tsx`:
- Around line 49-51: The ProjectCard component is styled as interactive (uses
className "block group" plus "cursor-pointer" and hover classes on the Card) but
has no navigation; either wrap the component in a Next.js Link to
`/projects/${project.id}` (import Link from "next/link" and replace the outer
div with a Link or wrap the Card so clicking navigates to
`/projects/${project.id}` while preserving the existing className and Card
props), or remove the interactive classes ("cursor-pointer" and the hover:...
classes on the Card) so the UI no longer implies clickability; locate this
change in components/cards/project-card.tsx and update the outer container or
Card accordingly.
In `@components/filters/sort-dropdown.tsx`:
- Around line 24-30: The Sort dropdown can end up with a hidden current value
(e.g., "highestReward") when tabs change; update SortDropdown (look for
visibleOptions, SORT_OPTIONS, hiddenOptions, value and onChange usage) to handle
this by adding fallback logic: on mount and whenever value or hiddenOptions
change, if value is not in visibleOptions call onChange with the first
visibleOptions[0] (or default "newest") so the UI always shows a valid option;
alternatively implement a useEffect in the parent that watches activeTab and
resets filters.sort to "newest" when the tab changes (update wherever
filters.sort is set).
🧹 Nitpick comments (5)
components/cards/bounty-card.tsx (1)
63-65: Guard against unexpected status/difficulty values.
If runtime data ever includes an unsupported status or difficulty,statusConfig[...]becomes undefined andstatus.iconwill throw. Consider a safe fallback or an explicit “Unknown” entry.♻️ Suggested fallback (example)
- const status = statusConfig[bounty.status]; - const difficulty = difficultyConfig[bounty.difficulty]; + const status = statusConfig[bounty.status] ?? statusConfig.open; + const difficulty = + difficultyConfig[bounty.difficulty] ?? difficultyConfig.beginner;app/discover/page.tsx (3)
144-145: UseuseMemoinstead of calling filter functions on every render.
filteredProjects()andfilteredBounties()are invoked on every render, defeating the purpose ofuseCallback. The callbacks themselves are memoized, but their results are not.♻️ Suggested refactor using useMemo
- const filteredProjects = useCallback(() => { + const filteredProjects = useMemo(() => { let result = [...mockProjects]; // ... filtering logic ... return result; - }, [filters]); + }, [filters]); - const filteredBounties = useCallback(() => { + const filteredBounties = useMemo(() => { let result = [...mockBounties]; // ... filtering logic ... return result; - }, [filters]); + }, [filters]); - const projects = filteredProjects(); - const bounties = filteredBounties(); + const projects = filteredProjects; + const bounties = filteredBounties;
147-162: MoveEmptyStateoutside the component to avoid recreation on each render.Defining components inside the render function creates a new component identity on every render, which can cause unnecessary unmount/remount cycles and break React's reconciliation.
♻️ Suggested refactor
Move
EmptyStateaboveDiscoverPage:const EmptyState = ({ type }: { type: "projects" | "bounties" }) => ( <div className="flex flex-col items-center justify-center py-16 px-4 text-center"> <div className="mb-4 p-6 bg-primary/5 rounded-full"> {type === "projects" ? ( <PackageOpen className="h-16 w-16 text-primary/50" /> ) : ( <Coins className="h-16 w-16 text-primary/50" /> )} </div> <h3 className="text-xl font-semibold mb-2">No {type} found</h3> <p className="text-muted-foreground max-w-md"> Try adjusting your filters or search terms to find what you're looking for. </p> </div> ); export default function DiscoverPage() { // ... }This also eliminates the need for the
eslint-disablecomment on line 239.
183-186: Validate tab value inonValueChangefor consistency.The initial tab parameter is validated using
isValidTab, but theonValueChangehandler casts the value directly without validation. While the Tabs component should only emit valid values, this creates an inconsistency.♻️ Suggested fix
<Tabs value={activeTab} - onValueChange={(val) => setActiveTab(val as TabType)} + onValueChange={(val) => { + if (isValidTab(val)) setActiveTab(val); + }} >components/filters/filter-panel.tsx (1)
103-106: Mobile badge count doesn't reflect sort filter changes.
hasActiveFilters(line 46-47) considerssort !== "newest"as an active filter, but the mobile badge count only sums search and tags. If a user changes only the sort option, the badge shows "0" while the "Clear filters" button appears.♻️ Suggested fix for consistency
{hasActiveFilters && ( <span className="ml-2 flex h-5 w-5 items-center justify-center rounded-full bg-primary text-xs text-primary-foreground"> - {(filters.search ? 1 : 0) + filters.tags.length} + {(filters.search ? 1 : 0) + filters.tags.length + (filters.sort !== "newest" ? 1 : 0)} </span> )}
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
🤖 Fix all issues with AI agents
In `@components/cards/project-card.tsx`:
- Around line 43-103: Normalize project.completedMilestones into a local
variable (e.g., completedOrZero) and use it both for the progress calculation
(instead of repeating project.completedMilestones) and for the label that
currently renders "{project.completedMilestones} of {project.milestones}
milestones", so the UI never shows "undefined"; update the existing progress
constant (progress) to use this normalized value and replace the label's
project.completedMilestones reference with the same variable.
♻️ Duplicate comments (1)
components/cards/project-card.tsx (1)
49-51: Card looks interactive but has no navigation.The hover styling + group wrapper imply clickability, but there’s no
Linkor click handler. Either add navigation or remove the interactive styling to avoid a misleading UX.
|
@0xdevcollins i have fixed all of it |
|
@0xdevcollins pls be kind to give me some compliment points 🤲 |
Description
feat: implement discover page with bounty and project cards, filtering, and sorting capabilities.
closes #3
Screen.Recording.2026-01-22.at.1.mp4
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.