69 lines
2.1 KiB
TypeScript
69 lines
2.1 KiB
TypeScript
import { BadgeCheck, ExternalLink } from 'lucide-react';
|
|
import { cn } from '@/lib/utils';
|
|
import { SKATESPOTS_SITE, type ProfileBadge } from '@/lib/badges';
|
|
import { sanitizeUrl } from '@/lib/sanitizeUrl';
|
|
|
|
/** The app logo is already served with the site. */
|
|
const SKATESPOTS_LOGO = '/images/logo-icon.png';
|
|
|
|
const isApp = (b: ProfileBadge) => b.label === 'SkateSpots' && b.url === SKATESPOTS_SITE;
|
|
|
|
/**
|
|
* ProfileBadges — the row of badges on a profile (own or someone else's).
|
|
* Clicking a badge with a link opens it in a new tab.
|
|
*/
|
|
export function ProfileBadges({
|
|
badges,
|
|
size = 'md',
|
|
className,
|
|
}: {
|
|
badges: ProfileBadge[];
|
|
size?: 'sm' | 'md';
|
|
className?: string;
|
|
}) {
|
|
if (badges.length === 0) return null;
|
|
|
|
return (
|
|
<div className={cn('flex flex-wrap items-center gap-2', className)}>
|
|
{badges.map((b, i) => {
|
|
const app = isApp(b);
|
|
const safeUrl = b.url ? sanitizeUrl(b.url) : null;
|
|
const cls = cn(
|
|
'inline-flex items-center gap-1.5 rounded-full border font-bold transition-colors',
|
|
size === 'sm' ? 'px-2 py-0.5 text-[11px]' : 'px-3 py-1.5 text-sm',
|
|
app
|
|
? 'border-[#ccff00]/40 bg-[#ccff00]/10 text-[#ccff00] hover:bg-[#ccff00]/20'
|
|
: 'border-pink-500/25 bg-pink-500/10 text-gray-100 hover:bg-pink-500/20',
|
|
);
|
|
const inner = (
|
|
<>
|
|
{app ? (
|
|
<img src={SKATESPOTS_LOGO} alt="" className="h-4 w-4 rounded-full object-contain" />
|
|
) : (
|
|
<BadgeCheck className={size === 'sm' ? 'h-3 w-3' : 'h-3.5 w-3.5'} />
|
|
)}
|
|
<span className="max-w-[12rem] truncate">{b.label}</span>
|
|
{safeUrl && !app && <ExternalLink className="h-3 w-3 opacity-60" />}
|
|
</>
|
|
);
|
|
|
|
return safeUrl ? (
|
|
<a
|
|
key={`${b.label}-${i}`}
|
|
href={safeUrl}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
title={safeUrl}
|
|
className={cls}
|
|
>
|
|
{inner}
|
|
</a>
|
|
) : (
|
|
<span key={`${b.label}-${i}`} className={cls}>
|
|
{inner}
|
|
</span>
|
|
);
|
|
})}
|
|
</div>
|
|
);
|
|
}
|