-
Notifications
You must be signed in to change notification settings - Fork 4
update navigation #39
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| import React, { useMemo } from "react"; | ||
| import Image from "next/image"; | ||
|
|
||
| export default function Banner({ name, imageUrl }: { name: string, imageUrl?: string }) { | ||
| const gradient = useMemo(() => { | ||
| let hash = 0; | ||
|
Comment on lines
+1
to
+6
|
||
| for (let i = 0; i < name.length; i++) { | ||
| hash = name.charCodeAt(i) + ((hash << 5) - hash); | ||
| } | ||
| const c1 = `hsl(${Math.abs(hash) % 360}, 70%, 40%)`; | ||
| const c2 = `hsl(${(Math.abs(hash) + 60) % 360}, 80%, 30%)`; | ||
| const c3 = `hsl(${(Math.abs(hash) + 120) % 360}, 60%, 20%)`; | ||
|
|
||
| return `linear-gradient(135deg, ${c1}, ${c2}, ${c3})`; | ||
| }, [name]); | ||
|
|
||
| return ( | ||
| <div className="w-full relative sm:rounded-2xl md:rounded-3xl overflow-hidden h-40 sm:h-56 md:h-72 shadow-2xl border-t border-b sm:border border-white/5 bg-[#121226]"> | ||
| {imageUrl ? ( | ||
| <Image | ||
| src={imageUrl} | ||
| alt={`${name} banner`} | ||
| fill | ||
| className="object-cover opacity-80" | ||
| priority | ||
| /> | ||
| ) : ( | ||
| <div | ||
| className="absolute inset-0 opacity-80" | ||
| style={{ background: gradient }} | ||
| /> | ||
| )} | ||
| {/* Decorative patterns */} | ||
| <div className="absolute inset-0 mix-blend-overlay opacity-30" style={{ | ||
| backgroundImage: "radial-gradient(circle at 2px 2px, rgba(255,255,255,0.2) 1px, transparent 0)", | ||
| backgroundSize: "32px 32px" | ||
| }} /> | ||
| <div className="absolute inset-x-0 bottom-0 h-1/2 bg-gradient-to-t from-[#0a0a1a] to-transparent opacity-80" /> | ||
| </div> | ||
| ); | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -8,6 +8,9 @@ import { toast } from "react-toastify"; | |||||||||
| import { useRouter } from "next/navigation"; | ||||||||||
| import Image from "next/image"; | ||||||||||
| import { Database } from "@/app/supabase-types"; | ||||||||||
| import Banner from "./Banner"; | ||||||||||
| import BackButton from "./BackButton"; | ||||||||||
| import InviteFriendsButton from "./InviteFriendsButton"; | ||||||||||
|
|
||||||||||
| type LeaderboardRow = Database["public"]["Tables"]["leaderboards"]["Row"]; | ||||||||||
|
|
||||||||||
|
|
@@ -69,26 +72,49 @@ export default function LeaderboardHeader({ | |||||||||
|
|
||||||||||
| return ( | ||||||||||
| <> | ||||||||||
| <div className="group relative mb-8 text-center"> | ||||||||||
| <div className="flex justify-center items-center gap-3"> | ||||||||||
| <Image src="/logo.svg" alt="DevPulse Logo" width={36} height={36} /> | ||||||||||
| <h1 className="text-3xl font-bold text-white">{leaderboard.name}</h1> | ||||||||||
|
|
||||||||||
| {isOwner && ( | ||||||||||
| <button | ||||||||||
| onClick={() => setOpen(true)} | ||||||||||
| className="opacity-0 group-hover:opacity-100 transition text-gray-600 hover:text-indigo-400 p-1.5" | ||||||||||
| > | ||||||||||
| <FontAwesomeIcon icon={faPencil} className="text-sm" /> | ||||||||||
| </button> | ||||||||||
| )} | ||||||||||
| <div className="group relative mb-20 sm:mb-24"> | ||||||||||
| {/* Using a temporary placeholder banner image */} | ||||||||||
| <Banner name={leaderboard.name} imageUrl="https://images.unsplash.com/photo-1550751827-4bd374c3f58b?q=80&w=2070&auto=format&fit=crop" /> | ||||||||||
|
Comment on lines
+76
to
+77
|
||||||||||
| {/* Using a temporary placeholder banner image */} | |
| <Banner name={leaderboard.name} imageUrl="https://images.unsplash.com/photo-1550751827-4bd374c3f58b?q=80&w=2070&auto=format&fit=crop" /> | |
| {/* Using the default banner background (gradient fallback) */} | |
| <Banner name={leaderboard.name} /> |
Copilot
AI
Mar 22, 2026
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.
PR title/description say “update navigation”, but this change set also adds new leaderboard UI components, animations, and dependencies. Please update the PR description to reflect the full scope (or split into smaller PRs) so reviewers can assess impact accurately.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| "use client"; | ||
|
|
||
| import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; | ||
| import { faShareNodes } from "@fortawesome/free-solid-svg-icons"; | ||
| import { toast } from "react-toastify"; | ||
|
|
||
| export default function InviteFriendsButton({ joinCode, leaderboardName }: { joinCode?: string; leaderboardName?: string }) { | ||
| const handleInvite = () => { | ||
| if (typeof window !== "undefined") { | ||
| const inviteUrl = joinCode | ||
| ? `${window.location.origin}/join/${joinCode}` | ||
| : window.location.href; // fallback | ||
|
|
||
| const message = leaderboardName | ||
| ? `Join my coding leaderboard "${leaderboardName}" on DevPulse!\n\nTrack metrics, compete with fellow developers, and showcase your engineering skills.\n\nJoin here: ${inviteUrl}` | ||
| : `Join my coding leaderboard on DevPulse!\n\nJoin here: ${inviteUrl}`; | ||
|
|
||
| navigator.clipboard.writeText(message); | ||
| toast.success("Invite message copied to clipboard!"); | ||
| } | ||
|
Comment on lines
+7
to
+20
|
||
| }; | ||
|
|
||
| return ( | ||
| <button | ||
| onClick={handleInvite} | ||
| className="flex items-center gap-2 text-sm font-medium bg-indigo-600/20 text-indigo-400 hover:bg-indigo-600/30 hover:text-indigo-300 border border-indigo-500/30 px-4 py-2 rounded-lg transition-all" | ||
| > | ||
| <FontAwesomeIcon icon={faShareNodes} className="w-4 h-4" /> | ||
| Invite Friends | ||
| </button> | ||
| ); | ||
| } | ||
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.
The standalone
{}JSX expression renders an object, which will throw at runtime (“Objects are not valid as a React child”). Remove this expression entirely (it doesn’t appear to be doing anything).