200 lines
9.6 KiB
TypeScript
200 lines
9.6 KiB
TypeScript
'use client'
|
|
|
|
import Link from 'next/link'
|
|
import { useSession, signIn, signOut } from 'next-auth/react'
|
|
import { Button } from '@/components/ui/button'
|
|
import {
|
|
DropdownMenu,
|
|
DropdownMenuContent,
|
|
DropdownMenuItem,
|
|
DropdownMenuSeparator,
|
|
DropdownMenuTrigger,
|
|
} from '@/components/ui/dropdown-menu'
|
|
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
|
|
import useSWR from 'swr'
|
|
import {
|
|
LgGeminiAi,
|
|
LgFolderInvoices,
|
|
LgComboChart,
|
|
LgPlus,
|
|
LgExit,
|
|
LgIdea // using LgIdea for rewards icon temporarily or can import another
|
|
} from '@/components/icons'
|
|
import { useRouter } from 'next/navigation'
|
|
import { UserBadges } from './ui/user-badges'
|
|
|
|
const fetcher = (url: string) => fetch(url).then((res) => res.json())
|
|
|
|
export function Header() {
|
|
const { data: session, status } = useSession()
|
|
const { data: userData } = useSWR(session ? '/api/user' : null, fetcher, {
|
|
refreshInterval: 10000,
|
|
})
|
|
const { data: solPrice } = useSWR('/api/sol-price', fetcher, {
|
|
refreshInterval: 60000,
|
|
})
|
|
|
|
// userouter -> login
|
|
const router = useRouter();
|
|
|
|
return (
|
|
<header className="sticky top-0 z-50 border-b border-border bg-background">
|
|
<div className="mx-auto flex h-16 max-w-7xl items-center justify-between px-4">
|
|
<div className="flex items-center gap-8">
|
|
<Link href="/" className="flex items-center gap-3">
|
|
<div className="relative">
|
|
<div className="relative flex h-10 w-10 items-center justify-center">
|
|
{/* <LgGeminiAi className="h-6 w-6" /> */}
|
|
<img src="/logo.svg" alt="Logo" className="h-10 w-10" />
|
|
</div>
|
|
</div>
|
|
<span className="text-xl font-semibold tracking-tight">
|
|
{/* pummmp - make this a gradient */}
|
|
{/* <span style={{ background: 'linear-gradient(90deg, #286eca, #ffffff)', WebkitBackgroundClip: 'text', WebkitTextFillColor: 'transparent' }}>pummmp</span> */}
|
|
pummmp<span className="text-[#286eca]">.fun</span>
|
|
</span>
|
|
</Link>
|
|
|
|
<nav className="hidden items-center gap-6 md:flex">
|
|
<Link
|
|
href="/"
|
|
className="text-sm text-muted-foreground transition-colors hover:text-foreground"
|
|
>
|
|
Explore
|
|
</Link>
|
|
<Link
|
|
href="/create"
|
|
className="text-sm text-muted-foreground transition-colors hover:text-foreground"
|
|
>
|
|
Create
|
|
</Link>
|
|
<Link
|
|
href="/swap"
|
|
className="text-sm text-muted-foreground transition-colors hover:text-foreground"
|
|
>
|
|
Swap
|
|
</Link>
|
|
<Link
|
|
href="/rewards"
|
|
className="text-sm text-muted-foreground transition-colors hover:text-foreground"
|
|
>
|
|
Daily Rewards
|
|
</Link>
|
|
{session && (
|
|
<Link
|
|
href="/dashboard"
|
|
className="text-sm text-muted-foreground transition-colors hover:text-foreground"
|
|
>
|
|
Dashboard
|
|
</Link>
|
|
)}
|
|
</nav>
|
|
</div>
|
|
|
|
<div className="flex items-center gap-4">
|
|
{solPrice && (
|
|
<div className="hidden items-center gap-2 rounded-xl bg-card px-3 py-1.5 md:flex">
|
|
{/* <LgFolderInvoices className="h-4 w-4" /> */}
|
|
<img src="/solana.svg" alt="SOL" className="h-4 w-4" />
|
|
<span className="text-sm font-medium">${solPrice.price?.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })} <span className='text-muted-foreground' style={{fontSize: '8px'}}>USD</span></span>
|
|
<span className={`text-xs ${solPrice.change24h >= 0 ? 'text-primary' : 'text-destructive'}`}>
|
|
{solPrice.change24h >= 0 ? '+' : ''}{solPrice.change24h?.toFixed(2)}%
|
|
</span>
|
|
</div>
|
|
)}
|
|
|
|
{status === 'loading' ? (
|
|
<div className="h-9 w-24 animate-pulse rounded-lg bg-muted" />
|
|
) : session ? (
|
|
<div className="flex items-center gap-3">
|
|
<div className="hidden flex-col items-end md:flex">
|
|
<span className="text-sm font-medium">
|
|
{userData?.balance?.toLocaleString('en-US', { minimumFractionDigits: 4, maximumFractionDigits: 4 }) ?? '...'} SOL
|
|
</span>
|
|
<span className="text-xs text-muted-foreground">
|
|
${((userData?.balance ?? 0) * (solPrice?.price ?? 0)).toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })} USD
|
|
</span>
|
|
</div>
|
|
|
|
<DropdownMenu>
|
|
<DropdownMenuTrigger asChild>
|
|
<Button variant="ghost" className="relative h-9 w-9 rounded-full">
|
|
<Avatar className="h-9 w-9 ring-2 ring-primary/20">
|
|
<AvatarImage src={session.user?.image ?? ''} alt={session.user?.name ?? ''} />
|
|
<AvatarFallback className="bg-primary/10 text-primary">
|
|
{session.user?.name?.[0]?.toUpperCase() ?? '?'}
|
|
</AvatarFallback>
|
|
</Avatar>
|
|
</Button>
|
|
</DropdownMenuTrigger>
|
|
<DropdownMenuContent align="end" className="w-56">
|
|
<div className="flex items-center gap-2 p-2">
|
|
<Avatar className="h-8 w-8">
|
|
<AvatarImage src={session.user?.image ?? ''} />
|
|
<AvatarFallback>{session.user?.name?.[0]}</AvatarFallback>
|
|
</Avatar>
|
|
<div className="flex flex-col">
|
|
<div className="flex items-center gap-1">
|
|
<span className="text-sm font-medium">{session.user?.name}</span>
|
|
<UserBadges
|
|
isAdmin={session.user?.isAdmin}
|
|
isVerified={session.user?.verified}
|
|
isBugHunter={session.user?.isBugHunter}
|
|
isBetaTester={session.user?.isBetaTester}
|
|
/>
|
|
</div>
|
|
<span className="text-xs text-muted-foreground">{session.user?.email}</span>
|
|
</div>
|
|
</div>
|
|
<DropdownMenuSeparator />
|
|
<DropdownMenuItem asChild className="cursor-pointer hover:bg-primary/10 focus:bg-primary/10">
|
|
<Link href="/dashboard" className="cursor-pointer">
|
|
<LgComboChart className="mr-2 h-4 w-4" />
|
|
Dashboard
|
|
</Link>
|
|
</DropdownMenuItem>
|
|
<DropdownMenuItem asChild className="cursor-pointer hover:bg-primary/10 focus:bg-primary/10">
|
|
<Link href="/create" className="cursor-pointer">
|
|
<LgPlus className="mr-2 h-4 w-4" />
|
|
Create Coin
|
|
</Link>
|
|
</DropdownMenuItem>
|
|
<DropdownMenuItem asChild className="cursor-pointer hover:bg-primary/10 focus:bg-primary/10">
|
|
<Link href={`/u/${encodeURIComponent(session.user?.name ?? '')}`} className="cursor-pointer">
|
|
<LgFolderInvoices className="mr-2 h-4 w-4" />
|
|
My Profile
|
|
</Link>
|
|
</DropdownMenuItem>
|
|
<DropdownMenuSeparator />
|
|
<DropdownMenuItem
|
|
onClick={() => signOut()}
|
|
className="cursor-pointer hover:bg-primary/10 focus:bg-primary/10"
|
|
>
|
|
<LgExit className="mr-2 h-4 w-4" />
|
|
Sign Out
|
|
</DropdownMenuItem>
|
|
</DropdownMenuContent>
|
|
</DropdownMenu>
|
|
</div>
|
|
) : (
|
|
// <Button
|
|
// onClick={() => signIn('discord')}
|
|
// className="gap-2 bg-[#5865F2] text-foreground hover:bg-[#4752C4]"
|
|
// >
|
|
// <svg className="h-4 w-4" viewBox="0 0 24 24" fill="currentColor">
|
|
// <path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028 14.09 14.09 0 0 0 1.226-1.994.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.956-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.955-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.946 2.418-2.157 2.418z"/>
|
|
// </svg>
|
|
// Sign in with Discord
|
|
// </Button>
|
|
<Button
|
|
onClick={() => router.push('/login')}
|
|
className="gap-2 bg-primary text-primary-foreground hover:bg-primary/90"
|
|
>
|
|
Sign In
|
|
</Button>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</header>
|
|
)
|
|
}
|