diff --git a/packages/frontend/src/components/org-icon.tsx b/packages/frontend/src/components/org-icon.tsx new file mode 100644 index 0000000..ae7df8b --- /dev/null +++ b/packages/frontend/src/components/org-icon.tsx @@ -0,0 +1,81 @@ +import { cn } from "@/lib/utils"; + +const FALLBACK_COLOURS = [ + "bg-teal-500", + "bg-rose-500", + "bg-indigo-500", + "bg-amber-500", + "bg-cyan-500", + "bg-purple-500", + "bg-lime-500", + "bg-orange-500", + "bg-sky-500", + "bg-fuchsia-500", + "bg-green-500", + "bg-red-500", + "bg-violet-500", + "bg-yellow-500", + "bg-blue-500", + "bg-emerald-500", + "bg-pink-500", +]; + +function hashStringToIndex(value: string, modulo: number) { + let hash = 0; + for (let i = 0; i < value.length; i++) { + hash = (hash * 31 + value.charCodeAt(i)) >>> 0; + } + return modulo === 0 ? 0 : hash % modulo; +} + +function getInitials(name: string) { + name = name.trim(); + + const parts = name.split(/[^a-zA-Z0-9]+/).filter(Boolean); + if (parts.length === 0) return name.slice(0, 2).toUpperCase(); + + if (parts.length === 1) return parts[0].slice(0, 2).toUpperCase(); + + return `${parts[0][0]}${parts[1][0]}`.toUpperCase(); +} + +export default function OrgIcon({ + name, + slug, + iconURL, + size, + textClass = "text-md", + className, +}: { + name: string; + slug: string; + iconURL?: string | null; + size?: number; + textClass?: string; + className?: string; +}) { + const backgroundClass = FALLBACK_COLOURS[hashStringToIndex(slug, FALLBACK_COLOURS.length)]; + + return ( +
+ {iconURL ? ( + {name} + ) : ( + {getInitials(name)} + )} +
+ ); +}