diff --git a/app/bounty/[bountyId]/page.tsx b/app/bounty/[bountyId]/page.tsx
index 9f266a8..304edb4 100644
--- a/app/bounty/[bountyId]/page.tsx
+++ b/app/bounty/[bountyId]/page.tsx
@@ -21,7 +21,7 @@ export default async function BountyDetailPage({ params }: Props) {
className="flex items-center gap-1.5 text-xs text-gray-500 mb-8"
>
Bounties
diff --git a/app/bounty/page.tsx b/app/bounty/page.tsx
index bb231e5..444e64c 100644
--- a/app/bounty/page.tsx
+++ b/app/bounty/page.tsx
@@ -1,6 +1,7 @@
"use client";
import { useState, useMemo, useCallback } from "react";
+import Link from "next/link";
import { useBounties } from "@/hooks/use-bounties";
import { BountyCard } from "@/components/bounty/bounty-card";
import { BountyListSkeleton } from "@/components/bounty/bounty-card-skeleton";
@@ -156,14 +157,11 @@ export default function BountiesPage() {
);
}, []);
- const toggleTag = useCallback(
- (tag: string) => {
- setSelectedTags((prev) =>
- prev.includes(tag) ? prev.filter((t) => t !== tag) : [...prev, tag],
- );
- },
- [],
- );
+ const toggleTag = useCallback((tag: string) => {
+ setSelectedTags((prev) =>
+ prev.includes(tag) ? prev.filter((t) => t !== tag) : [...prev, tag],
+ );
+ }, []);
const clearFilters = () => {
setSearchQuery("");
@@ -208,23 +206,21 @@ export default function BountiesPage() {
rewardRange[0] !== 0 ||
rewardRange[1] !== 5000 ||
statusFilter !== "open") && (
-
- )}
+
+ )}
{/* Search */}
-
+
0 ? (
{filteredBounties.map((bounty) => (
-
+
-
+
))}
) : (
@@ -501,7 +501,7 @@ export default function BountiesPage() {
)}
-
-
+
+
);
}
diff --git a/app/bounty/review/page.tsx b/app/bounty/review/page.tsx
new file mode 100644
index 0000000..d038b18
--- /dev/null
+++ b/app/bounty/review/page.tsx
@@ -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 (
+
+
+
+
+
+ Review Submissions
+
+
+ Manage and review contributions submitted for your bounties.
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/components/bounty-detail/bounty-detail-client.tsx b/components/bounty-detail/bounty-detail-client.tsx
index 9467c5b..5e38854 100644
--- a/components/bounty-detail/bounty-detail-client.tsx
+++ b/components/bounty-detail/bounty-detail-client.tsx
@@ -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 ;
-
- if (isError) {
- return (
-
-
-
- Failed to load bounty
-
-
- {error instanceof Error
- ? error.message
- : "Something went wrong. Please try again."}
-
-
-
- );
- }
-
- if (!bounty) {
- return (
-
-
-
Bounty not found
-
- This bounty may have been removed or doesn't exist.
-
-
-
- );
- }
-
- return (
-
- {/* Main content */}
-
-
-
- {bounty.requirements && bounty.requirements.length > 0 && (
-
- )}
- {bounty.scope && }
-
-
- {/* Sidebar */}
-
-
- {/* Mobile sticky CTA */}
-
-
- );
-}
+"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 ;
+
+ if (isError) {
+ return (
+
+
+
+ Failed to load bounty
+
+
+ {error instanceof Error
+ ? error.message
+ : "Something went wrong. Please try again."}
+
+
+
+ );
+ }
+
+ if (!bounty) {
+ return (
+
+
+
Bounty not found
+
+ This bounty may have been removed or doesn't exist.
+
+
+
+ );
+ }
+
+ return (
+
+ {/* Main content */}
+
+
+
+ {bounty.requirements && bounty.requirements.length > 0 && (
+
+ )}
+ {bounty.scope && }
+
+
+ {/* Sidebar */}
+
+
+ {/* Mobile sticky CTA */}
+
+
+ );
+}
diff --git a/components/bounty/bounty-list.tsx b/components/bounty/bounty-list.tsx
index aa855fe..365539d 100644
--- a/components/bounty/bounty-list.tsx
+++ b/components/bounty/bounty-list.tsx
@@ -1,49 +1,65 @@
-'use client';
+"use client";
-import { BountyCard } from './bounty-card';
-import { BountyListSkeleton } from './bounty-card-skeleton';
-import { BountyError } from './bounty-error';
-import { BountyEmpty } from './bounty-empty';
-import { useBounties } from '@/hooks/use-bounties';
-import type { BountyListParams } from '@/lib/api';
-import type { Bounty } from '@/types/bounty';
+import Link from "next/link";
+import { BountyCard } from "./bounty-card";
+import { BountyListSkeleton } from "./bounty-card-skeleton";
+import { BountyError } from "./bounty-error";
+import { BountyEmpty } from "./bounty-empty";
+import { useBounties } from "@/hooks/use-bounties";
+import type { BountyListParams } from "@/lib/api";
+import type { Bounty } from "@/types/bounty";
interface BountyListProps {
- params?: BountyListParams;
- hasFilters?: boolean;
- onClearFilters?: () => void;
- onBountyClick?: (bounty: Bounty) => void;
+ params?: BountyListParams;
+ hasFilters?: boolean;
+ onClearFilters?: () => void;
+ onBountyClick?: (bounty: Bounty) => void;
}
-export function BountyList({ params, hasFilters = false, onClearFilters, onBountyClick }: BountyListProps) {
- const { data, isLoading, isError, error, refetch } = useBounties(params);
+export function BountyList({
+ params,
+ hasFilters = false,
+ onClearFilters,
+ onBountyClick,
+}: BountyListProps) {
+ const { data, isLoading, isError, error, refetch } = useBounties(params);
- if (isLoading) {
- return ;
- }
+ if (isLoading) {
+ return ;
+ }
- if (isError) {
- return (
- refetch()}
- />
- );
- }
-
- const bounties = data?.data ?? [];
+ if (isError) {
+ return (
+ refetch()}
+ />
+ );
+ }
- if (bounties.length === 0) {
- return ;
- }
+ const bounties = data?.data ?? [];
+ if (bounties.length === 0) {
return (
-
- {bounties.map((bounty) => (
-
- onBountyClick?.(bounty)} />
-
- ))}
-
+
);
+ }
+
+ return (
+
+ {bounties.map((bounty) => (
+
+ {onBountyClick ? (
+ onBountyClick(bounty)} />
+ ) : (
+
+
+
+ )}
+
+ ))}
+
+ );
}
diff --git a/components/global-navbar.tsx b/components/global-navbar.tsx
index a1b1a04..df91580 100644
--- a/components/global-navbar.tsx
+++ b/components/global-navbar.tsx
@@ -29,40 +29,54 @@ export function GlobalNavbar() {
Explore
Projects
Leaderboard
Wallet
+
+ Review
+