EMAILOUT / frontend /src /lib /ownerAvatar.jsx
Seth
update
ac07ad9
import React from 'react';
import { cn } from '@/lib/utils';
/** Stable accent per user id for owner avatars (table, pipeline, charts). */
const OWNER_AVATAR_PALETTES = [
{ ring: 'border-rose-200', bg: 'bg-rose-100', text: 'text-rose-800' },
{ ring: 'border-amber-200', bg: 'bg-amber-100', text: 'text-amber-900' },
{ ring: 'border-emerald-200', bg: 'bg-emerald-100', text: 'text-emerald-900' },
{ ring: 'border-sky-200', bg: 'bg-sky-100', text: 'text-sky-900' },
{ ring: 'border-violet-200', bg: 'bg-violet-100', text: 'text-violet-800' },
{ ring: 'border-fuchsia-200', bg: 'bg-fuchsia-100', text: 'text-fuchsia-900' },
{ ring: 'border-cyan-200', bg: 'bg-cyan-100', text: 'text-cyan-900' },
{ ring: 'border-orange-200', bg: 'bg-orange-100', text: 'text-orange-900' },
{ ring: 'border-lime-200', bg: 'bg-lime-100', text: 'text-lime-900' },
{ ring: 'border-indigo-200', bg: 'bg-indigo-100', text: 'text-indigo-900' },
{ ring: 'border-teal-200', bg: 'bg-teal-100', text: 'text-teal-900' },
];
const UNASSIGNED_AVATAR_PALETTE = {
ring: 'border-slate-200',
bg: 'bg-slate-100',
text: 'text-slate-500',
};
function hashStringToUint(s) {
let h = 0;
for (let i = 0; i < s.length; i++) h = (Math.imul(31, h) + s.charCodeAt(i)) | 0;
return Math.abs(h);
}
export function ownerAvatarPalette(userId) {
if (userId == null || userId === '') return UNASSIGNED_AVATAR_PALETTE;
const idx = hashStringToUint(String(userId)) % OWNER_AVATAR_PALETTES.length;
return OWNER_AVATAR_PALETTES[idx];
}
export function ownerDisplayLabel(deal) {
if (deal.owner_user_id == null || deal.owner_user_id === '') return 'Unassigned';
return (
deal.owner_display_name ||
deal.owner_initials ||
`User ${deal.owner_user_id}`
);
}
export function OwnerAvatarCircle({ userId, initials, className }) {
const pal = ownerAvatarPalette(userId);
const unassigned = userId == null || userId === '';
const label = unassigned ? '?' : (initials || '?').toString().slice(0, 2).toUpperCase();
return (
<span
className={cn(
'inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-full border text-xs font-semibold leading-none',
pal.ring,
pal.bg,
pal.text,
className
)}
aria-hidden
>
{label}
</span>
);
}