-
Notifications
You must be signed in to change notification settings - Fork 27
Fix lint #93
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
Fix lint #93
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| "use client"; | ||
|
|
||
| import { SponsorReviewDashboard } from "@/components/bounty/sponsor-review-dashboard"; | ||
| import { ReviewSubmission } from "@/types/participation"; | ||
| import { Button } from "@/components/ui/button"; | ||
| import { ChevronLeft } from "lucide-react"; | ||
| import Link from "next/link"; | ||
|
|
||
| // Mock data for the dashboard | ||
| const mockSubmissions: ReviewSubmission[] = [ | ||
| { | ||
| submissionId: "sub-1", | ||
| contributor: { | ||
| username: "alex_dev", | ||
| avatarUrl: "https://github.com/shadcn.png", | ||
| }, | ||
| milestoneId: "Milestone 1", | ||
| submittedAt: new Date().toISOString(), | ||
| status: "pending", | ||
| }, | ||
| { | ||
| submissionId: "sub-2", | ||
| contributor: { | ||
| username: "sarah_smith", | ||
| }, | ||
| milestoneId: "Milestone 2", | ||
| submittedAt: new Date(Date.now() - 86400000).toISOString(), | ||
| status: "pending", | ||
| }, | ||
| ]; | ||
|
|
||
| export default function ReviewDashboardPage() { | ||
| const handleAction = async (id: string, action: string) => { | ||
| console.log(`Action ${action} on submission ${id}`); | ||
| // In a real app, this would be an API call | ||
| await new Promise((resolve) => setTimeout(resolve, 500)); | ||
| }; | ||
|
|
||
| return ( | ||
| <div className="container mx-auto max-w-5xl px-4 py-8 space-y-8"> | ||
| <div className="flex items-center justify-between"> | ||
| <div className="space-y-1"> | ||
| <Button | ||
| asChild | ||
| variant="ghost" | ||
| size="sm" | ||
| className="-ml-2 text-muted-foreground" | ||
| > | ||
| <Link href="/bounty"> | ||
| <ChevronLeft className="mr-2 h-4 w-4" /> | ||
| Back to Bounties | ||
| </Link> | ||
| </Button> | ||
| <h1 className="text-3xl font-bold tracking-tight"> | ||
| Review Submissions | ||
| </h1> | ||
| <p className="text-muted-foreground"> | ||
| Manage and review contributions submitted for your bounties. | ||
| </p> | ||
| </div> | ||
| </div> | ||
|
|
||
| <div className="rounded-xl border bg-card p-6 shadow-sm"> | ||
| <SponsorReviewDashboard | ||
| submissions={mockSubmissions} | ||
| onAction={handleAction} | ||
| /> | ||
| </div> | ||
| </div> | ||
| ); | ||
|
Comment on lines
+32
to
+70
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Check if there's any auth/middleware protecting the /bounty/review route
echo "=== Checking for middleware files ==="
fd middleware --type f 2>/dev/null | head -20 || echo "No middleware files found"
echo ""
echo "=== Checking for Next.js middleware file ==="
fd -t f 'middleware\.ts|middleware\.js' --max-depth 2 2>/dev/null || echo "No root middleware found"
echo ""
echo "=== Checking for auth patterns in the bounty directory ==="
rg -n "auth|session|protect|guard|middleware|useAuth|getServerSession|protected" --type=ts --type=tsx app/bounty/ 2>/dev/null || echo "No auth patterns found"
echo ""
echo "=== Checking the review page file directly ==="
if [ -f "app/bounty/review/page.tsx" ]; then
echo "=== File exists, checking content ==="
head -35 app/bounty/review/page.tsx
fi
echo ""
echo "=== Checking for layout files with potential auth in bounty routes ==="
find app/bounty -name "layout.tsx" -o -name "layout.ts" | xargs ls -la 2>/dev/null || echo "No layout files found"
echo ""
echo "=== Searching for auth configuration or providers ==="
rg -n "getServerSession|useSession|auth|middleware" --type=ts --type=tsx app/ | grep -E "(auth|session|middleware)" | head -20 || echo "No auth config found"Repository: boundlessfi/bounties Length of output: 3467 🏁 Script executed: #!/bin/bash
echo "=== Full bounty directory structure ==="
find app/bounty -type f | head -30
echo ""
echo "=== Search for auth-related files anywhere in app ==="
find app -name '*auth*' -o -name '*session*' | head -20
echo ""
echo "=== Check providers directory ==="
ls -la providers/ && cat providers/* 2>/dev/null | head -50
echo ""
echo "=== Check root layout file ==="
if [ -f "app/layout.tsx" ]; then
head -80 app/layout.tsx
fi
echo ""
echo "=== Search for useAuth, useSession, or similar hooks ==="
rg "useAuth|useSession|getServerSession" --type ts --type tsx app/ 2>/dev/null | head -20 || echo "No session hooks found"
echo ""
echo "=== Check if there's any import of auth-related code in the review page ==="
cat app/bounty/review/page.tsx | head -20Repository: boundlessfi/bounties Length of output: 4416 🏁 Script executed: #!/bin/bash
echo "=== Contents of app/(auth) directory ==="
find "app/(auth)" -type f 2>/dev/null || echo "Directory not found or check differently"
echo ""
echo "=== Checking auth folder ==="
find app -name "auth" -type d 2>/dev/null
echo ""
echo "=== Check bounty layout or any route protection ==="
if [ -f "app/bounty/layout.tsx" ]; then
echo "=== app/bounty/layout.tsx exists ==="
cat app/bounty/layout.tsx
fi
echo ""
echo "=== Check app/(auth) directory listing ==="
ls -la app/ | grep authRepository: boundlessfi/bounties Length of output: 329 🏁 Script executed: #!/bin/bash
echo "=== Check auth page implementation ==="
cat app/'(auth)'/auth/page.tsx
echo ""
echo "=== Check if review page is in a route segment with protections ==="
ls -la app/bounty/review/
echo ""
echo "=== List all layout files in app ==="
find app -name "layout.tsx" -o -name "layout.ts"Repository: boundlessfi/bounties Length of output: 614 Add access control to the review dashboard. This page is publicly accessible and currently displays with mock data. Review/approval dashboards require sponsor or admin authentication. Add a route guard or middleware protection, or add a TODO comment documenting when auth will be wired. 🤖 Prompt for AI Agents |
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,95 +1,95 @@ | ||
| "use client"; | ||
| import { useRouter } from "next/navigation"; | ||
| import { AlertCircle, ArrowLeft } from "lucide-react"; | ||
| import { Button } from "@/components/ui/button"; | ||
| import { | ||
| ClaimModelInfo, | ||
| MobileCTA, | ||
| SidebarCTA, | ||
| } from "./bounty-detail-sidebar-cta"; | ||
| import { RequirementsCard, ScopeCard } from "./bounty-detail-requirements-card"; | ||
| import { HeaderCard } from "./bounty-detail-header-card"; | ||
| import { DescriptionCard } from "./bounty-detail-description-card"; | ||
| import { BountyDetailSkeleton } from "./bounty-detail-bounty-detail-skeleton"; | ||
| import { useBountyDetail } from "@/hooks/Use-bounty-detail"; | ||
| export function BountyDetailClient({ bountyId }: { bountyId: string }) { | ||
| const router = useRouter(); | ||
| const { data: bounty, isPending, isError, error } = useBountyDetail(bountyId); | ||
| if (isPending) return <BountyDetailSkeleton />; | ||
| if (isError) { | ||
| return ( | ||
| <div className="min-h-screen flex flex-col items-center justify-center gap-4 text-center px-4"> | ||
| <div className="size-16 rounded-full bg-gray-800/50 flex items-center justify-center"> | ||
| <AlertCircle className="size-8 text-gray-600" /> | ||
| </div> | ||
| <h2 className="text-xl font-bold text-gray-200"> | ||
| Failed to load bounty | ||
| </h2> | ||
| <p className="text-gray-400 max-w-sm text-sm"> | ||
| {error instanceof Error | ||
| ? error.message | ||
| : "Something went wrong. Please try again."} | ||
| </p> | ||
| <Button | ||
| variant="outline" | ||
| className="border-gray-700 hover:bg-gray-800 mt-2" | ||
| onClick={() => router.push("/bounties")} | ||
| > | ||
| <ArrowLeft className="size-4 mr-2" /> | ||
| Back to bounties | ||
| </Button> | ||
| </div> | ||
| ); | ||
| } | ||
| if (!bounty) { | ||
| return ( | ||
| <div className="min-h-screen flex flex-col items-center justify-center gap-4 text-center px-4"> | ||
| <div className="size-16 rounded-full bg-gray-800/50 flex items-center justify-center"> | ||
| <AlertCircle className="size-8 text-gray-600" /> | ||
| </div> | ||
| <h2 className="text-xl font-bold text-gray-200">Bounty not found</h2> | ||
| <p className="text-gray-400 max-w-sm text-sm"> | ||
| This bounty may have been removed or doesn't exist. | ||
| </p> | ||
| <Button | ||
| variant="outline" | ||
| className="border-gray-700 hover:bg-gray-800 mt-2" | ||
| onClick={() => router.push("/bounties")} | ||
| > | ||
| <ArrowLeft className="size-4 mr-2" /> | ||
| Back to bounties | ||
| </Button> | ||
| </div> | ||
| ); | ||
| } | ||
| return ( | ||
| <div className="flex flex-col lg:flex-row gap-10"> | ||
| {/* Main content */} | ||
| <div className="flex-1 min-w-0 space-y-6"> | ||
| <HeaderCard bounty={bounty} /> | ||
| <DescriptionCard description={bounty.description} /> | ||
| {bounty.requirements && bounty.requirements.length > 0 && ( | ||
| <RequirementsCard requirements={bounty.requirements} /> | ||
| )} | ||
| {bounty.scope && <ScopeCard scope={bounty.scope} />} | ||
| </div> | ||
| {/* Sidebar */} | ||
| <aside className="w-full lg:w-72 shrink-0"> | ||
| <div className="lg:sticky lg:top-24 space-y-4"> | ||
| <SidebarCTA bounty={bounty} /> | ||
| <ClaimModelInfo claimingModel={bounty.claimingModel} /> | ||
| </div> | ||
| </aside> | ||
| {/* Mobile sticky CTA */} | ||
| <MobileCTA bounty={bounty} /> | ||
| </div> | ||
| ); | ||
| } | ||
| "use client"; | ||
|
|
||
| import { useRouter } from "next/navigation"; | ||
| import { AlertCircle, ArrowLeft } from "lucide-react"; | ||
| import { Button } from "@/components/ui/button"; | ||
| import { | ||
| ClaimModelInfo, | ||
| MobileCTA, | ||
| SidebarCTA, | ||
| } from "./bounty-detail-sidebar-cta"; | ||
| import { RequirementsCard, ScopeCard } from "./bounty-detail-requirements-card"; | ||
| import { HeaderCard } from "./bounty-detail-header-card"; | ||
| import { DescriptionCard } from "./bounty-detail-description-card"; | ||
| import { BountyDetailSkeleton } from "./bounty-detail-bounty-detail-skeleton"; | ||
| import { useBountyDetail } from "@/hooks/Use-bounty-detail"; | ||
|
|
||
| export function BountyDetailClient({ bountyId }: { bountyId: string }) { | ||
| const router = useRouter(); | ||
| const { data: bounty, isPending, isError, error } = useBountyDetail(bountyId); | ||
|
|
||
| if (isPending) return <BountyDetailSkeleton />; | ||
|
|
||
| if (isError) { | ||
| return ( | ||
| <div className="min-h-screen flex flex-col items-center justify-center gap-4 text-center px-4"> | ||
| <div className="size-16 rounded-full bg-gray-800/50 flex items-center justify-center"> | ||
| <AlertCircle className="size-8 text-gray-600" /> | ||
| </div> | ||
| <h2 className="text-xl font-bold text-gray-200"> | ||
| Failed to load bounty | ||
| </h2> | ||
| <p className="text-gray-400 max-w-sm text-sm"> | ||
| {error instanceof Error | ||
| ? error.message | ||
| : "Something went wrong. Please try again."} | ||
| </p> | ||
| <Button | ||
| variant="outline" | ||
| className="border-gray-700 hover:bg-gray-800 mt-2" | ||
| onClick={() => router.push("/bounty")} | ||
| > | ||
| <ArrowLeft className="size-4 mr-2" /> | ||
| Back to bounties | ||
| </Button> | ||
| </div> | ||
| ); | ||
| } | ||
|
|
||
| if (!bounty) { | ||
| return ( | ||
| <div className="min-h-screen flex flex-col items-center justify-center gap-4 text-center px-4"> | ||
| <div className="size-16 rounded-full bg-gray-800/50 flex items-center justify-center"> | ||
| <AlertCircle className="size-8 text-gray-600" /> | ||
| </div> | ||
| <h2 className="text-xl font-bold text-gray-200">Bounty not found</h2> | ||
| <p className="text-gray-400 max-w-sm text-sm"> | ||
| This bounty may have been removed or doesn't exist. | ||
| </p> | ||
| <Button | ||
| variant="outline" | ||
| className="border-gray-700 hover:bg-gray-800 mt-2" | ||
| onClick={() => router.push("/bounty")} | ||
| > | ||
| <ArrowLeft className="size-4 mr-2" /> | ||
| Back to bounties | ||
| </Button> | ||
| </div> | ||
| ); | ||
| } | ||
|
|
||
| return ( | ||
| <div className="flex flex-col lg:flex-row gap-10"> | ||
| {/* Main content */} | ||
| <div className="flex-1 min-w-0 space-y-6"> | ||
| <HeaderCard bounty={bounty} /> | ||
| <DescriptionCard description={bounty.description} /> | ||
| {bounty.requirements && bounty.requirements.length > 0 && ( | ||
| <RequirementsCard requirements={bounty.requirements} /> | ||
| )} | ||
| {bounty.scope && <ScopeCard scope={bounty.scope} />} | ||
| </div> | ||
|
|
||
| {/* Sidebar */} | ||
| <aside className="w-full lg:w-72 shrink-0"> | ||
| <div className="lg:sticky lg:top-24 space-y-4"> | ||
| <SidebarCTA bounty={bounty} /> | ||
| <ClaimModelInfo claimingModel={bounty.claimingModel} /> | ||
| </div> | ||
| </aside> | ||
|
|
||
| {/* Mobile sticky CTA */} | ||
| <MobileCTA bounty={bounty} /> | ||
| </div> | ||
| ); | ||
| } |
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.
🧩 Analysis chain
🏁 Script executed:
Repository: boundlessfi/bounties
Length of output: 20043
🏁 Script executed:
Repository: boundlessfi/bounties
Length of output: 1117
Refactor
BountyCardor remove the<Link>wrapper to avoid conflicting interactive semantics.The
BountyCardcomponent from/components/bounty/bounty-card.tsxis designed as an interactive element withrole="button",onClick, and keyboard handlers (onKeyDown). Wrapping it in a<Link>creates a<a>tag around a<div role="button">, which is semantically confusing. Additionally, since noonClickprop is passed toBountyCard, the component's click and keyboard handlers become dead code while the Link handles navigation independently.Choose one approach:
<Link>wrapper and pass anonClickhandler toBountyCardthat navigates programmatically.BountyCardand use only the<Link>for navigation (recommended, as seen incomponents/bounty/github-bounty-card.tsx).🤖 Prompt for AI Agents