199 lines
9.9 KiB
TypeScript
199 lines
9.9 KiB
TypeScript
'use client'
|
||
|
||
import { signIn, signOut } from 'next-auth/react'
|
||
import { useSteamProfile } from '@/app/hooks/useSteamProfile'
|
||
import { useRouter } from 'next/navigation'
|
||
import { useEffect, useState } from 'react'
|
||
import { AnimatePresence, motion } from 'framer-motion'
|
||
import { usePathname } from 'next/navigation'
|
||
import Script from "next/script";
|
||
import LoadingSpinner from '@/app/components/LoadingSpinner'
|
||
import Image from 'next/image'
|
||
import Button from './Button'
|
||
|
||
export default function SidebarFooter() {
|
||
const router = useRouter()
|
||
const { session, steamProfile, status } = useSteamProfile()
|
||
const [isOpen, setIsOpen] = useState(false)
|
||
const pathname = usePathname()
|
||
const [teamName, setTeamName] = useState<string | null>(null)
|
||
|
||
useEffect(() => {
|
||
const loadTeamName = async () => {
|
||
const teamId = session?.user?.team
|
||
if (!teamId) {
|
||
setTeamName(null)
|
||
return
|
||
}
|
||
try {
|
||
const res = await fetch(`/api/team/${teamId}`)
|
||
const data = await res.json()
|
||
setTeamName(data?.teamname ?? null)
|
||
} catch (err) {
|
||
console.error('[SidebarFooter] Team‑Name konnte nicht geladen werden:', err)
|
||
setTeamName(null)
|
||
}
|
||
}
|
||
|
||
loadTeamName()
|
||
}, [session?.user?.team])
|
||
|
||
if (status === 'loading') return <LoadingSpinner />
|
||
|
||
if (status === 'unauthenticated') {
|
||
return (
|
||
<>
|
||
<button
|
||
onClick={() => signIn('steam')}
|
||
className="flex items-center justify-center gap-2 w-full py-4 px-6 bg-green-800 text-white text-md font-medium hover:bg-green-900 transition"
|
||
>
|
||
<i className="fab fa-steam" />
|
||
<span>Mit Steam anmelden</span>
|
||
</button>
|
||
</>
|
||
)
|
||
}
|
||
|
||
const user = session!.user
|
||
|
||
const subline =
|
||
teamName // 1. Teamname, wenn vorhanden
|
||
?? steamProfile?.steamId // 2. Steam‑ID (wenn bereits vom Hook gemappt)
|
||
?? user.id // 3. Fallback auf JWT‑id
|
||
|
||
return (
|
||
<>
|
||
<div className="relative w-full">
|
||
{/* Button */}
|
||
<button
|
||
onClick={() => setIsOpen(!isOpen)}
|
||
className={`w-full inline-flex items-center gap-x-2 px-4 py-3 text-sm text-left text-gray-800 transition-all duration-100
|
||
${isOpen ? 'bg-gray-100 dark:bg-neutral-700' : 'hover:bg-gray-100 dark:hover:bg-neutral-700'}
|
||
`}
|
||
>
|
||
<div className="shrink-0 group block">
|
||
<div className="flex items-center">
|
||
<Image
|
||
src={steamProfile?.avatarfull || user?.image || '/default-avatar.png'}
|
||
quality={75}
|
||
width={40}
|
||
height={40}
|
||
className="inline-block shrink-0 size-10 rounded-full"
|
||
draggable={false}
|
||
alt="Avatar"
|
||
/>
|
||
<div className="ms-3">
|
||
<h3 className="font-semibold text-gray-800 dark:text-white">{steamProfile?.personaname || user?.name}</h3>
|
||
<p className="text-xs font-medium text-gray-400 dark:text-neutral-500">{subline}</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<svg
|
||
className={`ms-auto size-4 group-hover:text-gray-500 ${
|
||
isOpen ? 'rotate-180' : ''
|
||
} text-gray-600 dark:text-neutral-400`}
|
||
xmlns="http://www.w3.org/2000/svg"
|
||
fill="none"
|
||
viewBox="0 0 24 24"
|
||
stroke="currentColor"
|
||
>
|
||
<path strokeWidth={2} d="m5 15 7-7 7 7" />
|
||
</svg>
|
||
</button>
|
||
|
||
{/* Menü */}
|
||
<AnimatePresence>
|
||
{isOpen && (
|
||
<motion.div
|
||
initial={{ opacity: 0, height: 0 }}
|
||
animate={{ opacity: 1, height: 'auto' }}
|
||
exit={{ opacity: 0, height: 0 }}
|
||
transition={{ duration: 0.2 }}
|
||
className="overflow-hidden w-full bg-white shadow-lg dark:bg-neutral-800 dark:border-neutral-600 z-20"
|
||
>
|
||
<div className="p-2 flex flex-col gap-1">
|
||
<Button
|
||
onClick={() => router.push('/matches')}
|
||
size='sm'
|
||
variant='link'
|
||
className={`flex items-center gap-x-3.5 py-2 px-2.5 text-sm rounded-lg transition-colors
|
||
${pathname === '/matches'
|
||
? 'bg-gray-100 dark:bg-neutral-700 text-gray-900 dark:text-white'
|
||
: 'text-gray-800 hover:bg-gray-100 dark:text-neutral-300 dark:hover:bg-neutral-700'
|
||
}`}
|
||
>
|
||
<svg className="size-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth="1.5" stroke="currentColor">
|
||
<path strokeLinecap="round" strokeLinejoin="round" d="M9 17.25V15.75C9 14.2312 10.2312 13 11.75 13H12.25C13.7688 13 15 14.2312 15 15.75V17.25M4.5 12.75C4.5 11.2312 5.73122 10 7.25 10H7.75C9.26878 10 10.5 11.2312 10.5 12.75V14.25M13.5 10C13.5 8.48122 14.7312 7.25 16.25 7.25H16.75C18.2688 7.25 19.5 8.48122 19.5 10V11.5M4.5 4.5H19.5C20.3284 4.5 21 5.17157 21 6V18C21 18.8284 20.3284 19.5 19.5 19.5H4.5C3.67157 19.5 3 18.8284 3 18V6C3 5.17157 3.67157 4.5 4.5 4.5Z" />
|
||
</svg>
|
||
Matches
|
||
</Button>
|
||
<Button
|
||
onClick={() => router.push(`/profile/${user.steamId}`)}
|
||
size='sm'
|
||
variant='link'
|
||
className={`flex items-center gap-x-3.5 py-2 px-2.5 text-sm rounded-lg transition-colors
|
||
${pathname === `/profile/${user.steamId}`
|
||
? 'bg-gray-100 dark:bg-neutral-700 text-gray-900 dark:text-white'
|
||
: 'text-gray-800 hover:bg-gray-100 dark:text-neutral-300 dark:hover:bg-neutral-700'
|
||
}`}
|
||
>
|
||
<svg className="size-4" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" >
|
||
<path d="M15 9h3m-3 3h3m-3 3h3m-6 1c-.306-.613-.933-1-1.618-1H7.618c-.685 0-1.312.387-1.618 1M4 5h16a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V6a1 1 0 0 1 1-1Zm7 5a2 2 0 1 1-4 0 2 2 0 0 1 4 0Z"/>
|
||
</svg>
|
||
Mein Profil
|
||
</Button>
|
||
<Button
|
||
onClick={() => router.push('/settings')}
|
||
size='sm'
|
||
variant='link'
|
||
className={`flex items-center gap-x-3.5 py-2 px-2.5 text-sm rounded-lg transition-colors
|
||
${pathname.startsWith('/settings')
|
||
? 'bg-gray-100 dark:bg-neutral-700 text-gray-900 dark:text-white'
|
||
: 'text-gray-800 hover:bg-gray-100 dark:text-neutral-300 dark:hover:bg-neutral-700'
|
||
}`}
|
||
>
|
||
<svg className="size-4" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" >
|
||
<path d="M10 19H5a1 1 0 0 1-1-1v-1a3 3 0 0 1 3-3h2m10 1a3 3 0 0 1-3 3m3-3a3 3 0 0 0-3-3m3 3h1m-4 3a3 3 0 0 1-3-3m3 3v1m-3-4a3 3 0 0 1 3-3m-3 3h-1m4-3v-1m-2.121 1.879-.707-.707m5.656 5.656-.707-.707m-4.242 0-.707.707m5.656-5.656-.707.707M12 8a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z"/>
|
||
</svg>
|
||
|
||
Einstellungen
|
||
</Button>
|
||
{user?.isAdmin && (
|
||
<Button
|
||
onClick={() => router.push('/admin')}
|
||
size='sm'
|
||
variant='link'
|
||
className={`flex items-center gap-x-3.5 py-2 px-2.5 text-sm rounded-lg transition-colors
|
||
${pathname.startsWith('/settings/admin')
|
||
? 'bg-gray-100 dark:bg-neutral-700 text-gray-900 dark:text-white'
|
||
: 'text-gray-800 hover:bg-gray-100 dark:text-neutral-300 dark:hover:bg-neutral-700'
|
||
}`}
|
||
>
|
||
<svg className="size-4" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" >
|
||
<path transform="scale(0.046875)" d="M78.6 5C69.1-2.4 55.6-1.5 47 7L7 47c-8.5 8.5-9.4 22-2.1 31.6l80 104c4.5 5.9 11.6 9.4 19 9.4l54.1 0 109 109c-14.7 29-10 65.4 14.3 89.6l112 112c12.5 12.5 32.8 12.5 45.3 0l64-64c12.5-12.5 12.5-32.8 0-45.3l-112-112c-24.2-24.2-60.6-29-89.6-14.3l-109-109 0-54.1c0-7.5-3.5-14.5-9.4-19L78.6 5zM19.9 396.1C7.2 408.8 0 426.1 0 444.1C0 481.6 30.4 512 67.9 512c18 0 35.3-7.2 48-19.9L233.7 374.3c-7.8-20.9-9-43.6-3.6-65.1l-61.7-61.7L19.9 396.1zM512 144c0-10.5-1.1-20.7-3.2-30.5c-2.4-11.2-16.1-14.1-24.2-6l-63.9 63.9c-3 3-7.1 4.7-11.3 4.7L352 176c-8.8 0-16-7.2-16-16l0-57.4c0-4.2 1.7-8.3 4.7-11.3l63.9-63.9c8.1-8.1 5.2-21.8-6-24.2C388.7 1.1 378.5 0 368 0C288.5 0 224 64.5 224 144l0 .8 85.3 85.3c36-9.1 75.8 .5 104 28.7L429 274.5c49-23 83-72.8 83-130.5zM56 432a24 24 0 1 1 48 0 24 24 0 1 1 -48 0z"/>
|
||
</svg>
|
||
Administration
|
||
</Button>
|
||
)}
|
||
<Button
|
||
onClick={() => signOut({ callbackUrl: '/' })}
|
||
size='sm'
|
||
variant='link'
|
||
color='red'
|
||
className={`flex items-center gap-x-3.5 py-2 px-2.5 text-sm rounded-lg transition-colors text-gray-800 hover:bg-red-100 dark:text-neutral-300 dark:hover:bg-red-700`} >
|
||
<svg className="size-4" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" >
|
||
<path d="M20 12H8m12 0-4 4m4-4-4-4M9 4H7a3 3 0 0 0-3 3v10a3 3 0 0 0 3 3h2"/>
|
||
</svg>
|
||
|
||
|
||
Abmelden
|
||
</Button>
|
||
</div>
|
||
</motion.div>
|
||
)}
|
||
</AnimatePresence>
|
||
</div>
|
||
</>
|
||
)
|
||
}
|