diff --git a/components/profile/contribution-list.tsx b/components/profile/contribution-list.tsx new file mode 100644 index 0000000..234e4f4 --- /dev/null +++ b/components/profile/contribution-list.tsx @@ -0,0 +1,88 @@ +"use client" + +import Image from "next/image" +import Link from "next/link" +import { Cpu, Clock, TrendingUp, CheckCircle } from "lucide-react" +import { motion } from "motion/react" +import type { ContributionEntry } from "@/types/api" + +interface ContributionListProps { + entries: ContributionEntry[] + showViewAll?: boolean + totalCount?: number +} + +export function ContributionList({ entries, showViewAll = false, totalCount }: ContributionListProps) { + if (entries.length === 0) { + return ( +
+ +

No contributions yet

+
+ ) + } + + return ( +
+ {showViewAll && totalCount && totalCount > entries.length && ( +
+ + Showing {entries.length} of {totalCount} + +
+ )} + {entries.map((entry, i) => ( + + + {entry.gameHeaderImage ? ( + {entry.gameTitle} + ) : ( +
+ )} + +
+

{entry.gameTitle}

+
+ + + {entry.hardwareName} + + + + {new Date(entry.createdAt).toLocaleDateString()} + +
+
+ +
+
+ {entry.fpsAvg.toFixed(0)} FPS +
+ {entry.verifiedAt && ( +
+ + Verified +
+ )} +
+ + + ))} +
+ ) +} diff --git a/components/profile/profile-header.tsx b/components/profile/profile-header.tsx new file mode 100644 index 0000000..6070260 --- /dev/null +++ b/components/profile/profile-header.tsx @@ -0,0 +1,70 @@ +"use client" + +import Image from "next/image" +import { User, Shield, Crown, CheckCircle } from "lucide-react" +import { motion } from "motion/react" + +interface ProfileHeaderProps { + name: string + image: string | null + role: string | null + verified: boolean + createdAt: string +} + +const roleConfig: Record = { + admin: { label: "Admin", color: "bg-yellow-500/20 text-yellow-400 border-yellow-500/30", icon: Crown }, + contributor: { label: "Contributor", color: "bg-blue-500/20 text-blue-400 border-blue-500/30", icon: Shield }, + user: { label: "Member", color: "bg-text/10 text-text/60 border-text/20", icon: User }, +} + +export function ProfileHeader({ name, image, role, verified, createdAt }: ProfileHeaderProps) { + const config = roleConfig[role || "user"] || roleConfig.user + const RoleIcon = config.icon + + const joinDate = new Date(createdAt).toLocaleDateString("en-US", { + month: "long", + year: "numeric", + }) + + return ( + +
+ {image ? ( + {name} + ) : ( +
+ +
+ )} + {verified && ( +
+ +
+ )} +
+ +
+
+

{name}

+ + + {config.label} + +
+

Member since {joinDate}

+
+
+ ) +} diff --git a/components/profile/stats-row.tsx b/components/profile/stats-row.tsx new file mode 100644 index 0000000..a1c2b95 --- /dev/null +++ b/components/profile/stats-row.tsx @@ -0,0 +1,38 @@ +"use client" + +import { TrendingUp, CheckCircle, Star } from "lucide-react" +import { motion } from "motion/react" + +interface StatsRowProps { + contributions: number + verifiedEntries: number + reputation: number +} + +export function StatsRow({ contributions, verifiedEntries, reputation }: StatsRowProps) { + const stats = [ + { label: "Contributions", value: contributions, icon: TrendingUp, color: "text-primary" }, + { label: "Verified", value: verifiedEntries, icon: CheckCircle, color: "text-green-400" }, + { label: "Reputation", value: reputation, icon: Star, color: "text-accent" }, + ] + + return ( + + {stats.map((stat) => ( +
+ + {stat.value} + {stat.label} +
+ ))} +
+ ) +}