2025-05-28 00:41:23 +02:00

126 lines
4.4 KiB
TypeScript

'use client'
import Button from './Button'
import Image from 'next/image'
type MiniCardProps = {
title: string
avatar: string
steamId: string
selected?: boolean
onSelect?: (steamId: string) => void
onKick?: (steamId: string) => void
isLeader?: boolean
draggable?: boolean
currentUserSteamId: string
teamLeaderSteamId: string
location?: string
dragListeners?: any
hoverEffect?: boolean
onPromote?: (steamId: string) => void
hideActions?: boolean
hideOverlay?: boolean
}
export default function MiniCard({
title,
avatar,
steamId,
selected,
onSelect,
onKick,
isLeader = false,
draggable,
currentUserSteamId,
teamLeaderSteamId,
location,
dragListeners,
hoverEffect = false,
onPromote,
hideActions = false,
hideOverlay = false,
}: MiniCardProps) {
const isSelectable = typeof onSelect === 'function'
const canKick = currentUserSteamId === teamLeaderSteamId && steamId !== teamLeaderSteamId
const cardClasses = `
relative flex flex-col items-center p-4 border rounded-lg transition
max-h-[154px] w-full overflow-hidden
bg-white dark:bg-neutral-800 border shadow-2xs rounded-xl
${selected ? 'ring-1 ring-blue-500 border-blue-500 dark:ring-blue-400' : 'border-gray-200 dark:border-neutral-700'}
${hoverEffect ? 'hover:cursor-grab hover:scale-105' : ''}
${isSelectable ? 'hover:border-blue-400 dark:hover:border-blue-400 cursor-pointer' : ''}
`
const avatarWrapper = 'relative w-16 h-16 mb-2'
const handleCardClick = () => {
if (isSelectable) onSelect?.(steamId)
}
const handleKickClick = (e: React.MouseEvent) => {
onKick?.(steamId)
}
const handlePromoteClick = (e: React.MouseEvent) => {
onPromote?.(steamId)
}
const stopDrag = (e: React.PointerEvent | React.MouseEvent) => {
e.stopPropagation()
}
return (
<div className={`${cardClasses} group`} onClick={handleCardClick} {...dragListeners}>
{canKick && !hideActions && !hideOverlay && (
<div className={`absolute inset-0 bg-white dark:bg-black bg-opacity-50 flex flex-col items-center justify-center gap-2 transition-opacity z-10 ${
hideOverlay ? 'opacity-0 pointer-events-none' : 'opacity-0 group-hover:opacity-100'
}`}>
<span className="text-gray-800 dark:text-neutral-200 font-semibold text-sm mb-1 truncate px-2 max-w-[90%] text-center">{title}</span>
<div className="pointer-events-auto" onPointerDown={stopDrag}>
<Button title="Kicken" color="red" variant="solid" size="sm" onClick={handleKickClick} />
</div>
{typeof onPromote === 'function' && (
<div className="pointer-events-auto" onPointerDown={stopDrag}>
<Button title="Leader" color="blue" variant="solid" size="sm" onClick={handlePromoteClick} />
</div>
)}
</div>
)}
<div className="flex flex-col items-center z-0">
<div className={avatarWrapper}>
<div className="relative w-16 h-16 mb-2">
<Image
src={avatar}
alt={title}
fill
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
quality={75}
className="rounded-full object-cover"
draggable={false}
/>
{isLeader && (
<div className="absolute -top-1 -right-1 bg-yellow-400 rounded-full p-0.5 shadow ring-2 ring-white dark:ring-neutral-800" draggable={false}>
<svg className="w-3.5 h-3.5 text-white" fill="currentColor" viewBox="0 0 20 20">
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.286 3.965a1 1 0 00.95.69h4.172c.969 0 1.371 1.24.588 1.81l-3.375 2.455a1 1 0 00-.364 1.118l1.287 3.966c.3.92-.755 1.688-1.54 1.118l-3.375-2.455a1 1 0 00-1.175 0l-3.375 2.455c-.784.57-1.838-.197-1.539-1.118l1.286-3.966a1 1 0 00-.364-1.118L2.05 9.392c-.783-.57-.38-1.81.588-1.81h4.172a1 1 0 00.95-.69l1.286-3.965z" />
</svg>
</div>
)}
</div>
</div>
<span className="text-sm text-gray-800 dark:text-neutral-200 text-center mt-1 truncate max-w-[100px] w-full block">
{title}
</span>
{location ? (
<span className={`fi fi-${location.toLowerCase()} text-xl mt-1`} title={location} />
) : (
<span className="text-xl mt-1" title="Weltweit">🌐</span>
)}
</div>
</div>
)
}