SPB Git forge

spb/spb-cloud

Public
10commits 1branches 0releases
3.2 MBsize
maindefault branch
2 h agolast push
JavaScript 56.7% TypeScript 42.6%
1.9 KB · 91 lines tsx
Raw Blame History
1"use client";23import Image from "next/image";45interface UserAvatarProps {6  userId: string;7  name?: string | null;8  avatarPath?: string | null;9  size?: "sm" | "md" | "lg";10}1112const sizeMap = {13  sm: 24,14  md: 32,15  lg: 48,16};1718const textSizeMap = {19  sm: "text-[10px]",20  md: "text-xs",21  lg: "text-sm",22};2324function hashColor(str: string): string {25  let hash = 0;26  for (let i = 0; i < str.length; i++) {27    hash = str.charCodeAt(i) + ((hash << 5) - hash);28  }29  const colors = [30    "bg-blue-600",31    "bg-emerald-600",32    "bg-purple-600",33    "bg-rose-600",34    "bg-amber-600",35    "bg-cyan-600",36    "bg-indigo-600",37    "bg-pink-600",38    "bg-teal-600",39    "bg-orange-600",40  ];41  return colors[Math.abs(hash) % colors.length];42}4344function getInitials(name?: string | null): string {45  if (!name) return "?";46  const parts = name.trim().split(/\s+/);47  if (parts.length >= 2) {48    return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();49  }50  return name.slice(0, 2).toUpperCase();51}5253export default function UserAvatar({54  userId,55  name,56  avatarPath,57  size = "md",58}: UserAvatarProps) {59  const px = sizeMap[size];6061  if (avatarPath) {62    return (63      <div64        className="relative rounded-full overflow-hidden flex-shrink-0 ring-2 ring-white/70 dark:ring-white/10"65        style={{ width: px, height: px }}66      >67        <Image68          src={`/api/users/${userId}/avatar`}69          alt={name || "Avatar"}70          width={px}71          height={px}72          className="object-cover w-full h-full"73          unoptimized74        />75      </div>76    );77  }7879  const bgColor = hashColor(userId);80  const initials = getInitials(name);8182  return (83    <div84      className={`${bgColor} rounded-full flex items-center justify-center flex-shrink-0 text-white font-semibold ring-2 ring-white/70 dark:ring-white/10 shadow-inner ${textSizeMap[size]}`}85      style={{ width: px, height: px }}86    >87      {initials}88    </div>89  );90}91