import { BoltIcon, BuildingOffice2Icon, CodeBracketSquareIcon, FaceSmileIcon, FireIcon, GlobeAltIcon, RocketLaunchIcon, StarIcon, } from "@heroicons/react/20/solid"; import type { Prisma } from "@trigger.dev/database"; import { z } from "zod"; import { logger } from "~/services/logger.server"; import { cn } from "~/utils/cn"; export const AvatarType = z.enum(["icon", "letters", "image"]); export const AvatarData = z.discriminatedUnion("type", [ z.object({ type: z.literal(AvatarType.enum.icon), name: z.string(), hex: z.string(), }), z.object({ type: z.literal(AvatarType.enum.letters), hex: z.string(), }), z.object({ type: z.literal(AvatarType.enum.image), url: z.string(), lastIconHex: z.string().optional(), }), ]); export type Avatar = z.infer; export type IconAvatar = Extract; export type ImageAvatar = Extract; export type LettersAvatar = Extract; export function parseAvatar(json: Prisma.JsonValue, defaultAvatar: Avatar): Avatar { if (!json || typeof json !== "object") { return defaultAvatar; } const parsed = AvatarData.safeParse(json); if (!parsed.success) { logger.error("Invalid org avatar", { json, error: parsed.error }); return defaultAvatar; } return parsed.data; } export function Avatar({ avatar, size, includePadding, orgName, }: { avatar: Avatar; /** Size in rems of the icon */ size: number; includePadding?: boolean; orgName: string; }) { switch (avatar.type) { case "icon": return ; case "letters": return ( ); case "image": return ; } } export const avatarIcons: Record>> = { "hero:building-office-2": BuildingOffice2Icon, "hero:rocket-launch": RocketLaunchIcon, "hero:code-bracket-square": CodeBracketSquareIcon, "hero:fire": FireIcon, "hero:star": StarIcon, "hero:face-smile": FaceSmileIcon, "hero:bolt": BoltIcon, }; export const defaultAvatarColors = [ { hex: "#878C99", name: "Gray" }, { hex: "#713F12", name: "Brown" }, { hex: "#F97316", name: "Orange" }, { hex: "#EAB308", name: "Yellow" }, { hex: "#22C55E", name: "Green" }, { hex: "#3B82F6", name: "Blue" }, { hex: "#6366F1", name: "Purple" }, { hex: "#EC4899", name: "Pink" }, { hex: "#F43F5E", name: "Red" }, ]; // purple export const defaultAvatarHex = defaultAvatarColors[6].hex; export const defaultAvatar: Avatar = { type: "letters", hex: defaultAvatarHex, }; function styleFromSize(size: number) { return { width: `${size}rem`, height: `${size}rem`, }; } function AvatarLetters({ avatar, size, includePadding, orgName, }: { avatar: LettersAvatar; size: number; includePadding?: boolean; orgName: string; }) { const letters = orgName.slice(0, 2); const style = { backgroundColor: avatar.hex, }; const scaleFactor = includePadding ? 0.8 : 1; return ( {/* This is the square container */} {letters} ); } function AvatarIcon({ avatar, size, includePadding, }: { avatar: IconAvatar; size: number; includePadding?: boolean; }) { const style = { color: avatar.hex, }; const IconComponent = avatarIcons[avatar.name]; return ( ); } function AvatarImage({ avatar, size }: { avatar: ImageAvatar; size: number }) { if (!avatar.url) { return ( ); } return ( Organization avatar ); }