import React, { useEffect, useState } from 'react' import { cn } from '@/utils/cn' export type AvatarSize = 'xs' | 'sm' | 'md' | 'lg' export type AvatarStatus = 'online' | 'offline' | 'warning' | 'none' export interface AvatarProps { src?: string | null name?: string | null email?: string | null alt?: string size?: AvatarSize status?: AvatarStatus className?: string } const sizeStyles: Record = { xs: { box: 'h-6 w-6', text: 'text-[10px]', dot: 'h-2 w-2', dotOffset: '-bottom-0.5 -right-0.5' }, sm: { box: 'h-8 w-8', text: 'text-[12px]', dot: 'h-2.5 w-2.5', dotOffset: '-bottom-0.5 -right-0.5' }, md: { box: 'h-10 w-10', text: 'text-[14px]', dot: 'h-3 w-3', dotOffset: '-bottom-0.5 -right-0.5' }, lg: { box: 'h-12 w-12', text: 'text-[16px]', dot: 'h-3.5 w-3.5', dotOffset: '-bottom-0.5 -right-0.5' }, } const statusStyles: Record, string> = { online: 'bg-teal-500', offline: 'bg-slate-300', warning: 'bg-amber-500', } export function getAvatarInitial(name?: string | null, email?: string | null): string { const source = name?.trim() || email?.trim() || 'User' return Array.from(source)[0]?.toLocaleUpperCase() || 'U' } export const Avatar: React.FC = ({ src, name, email, alt, size = 'md', status = 'none', className, }) => { const [showImage, setShowImage] = useState(Boolean(src)) const label = alt ?? name ?? email ?? '사용자' const sizeClass = sizeStyles[size] useEffect(() => { setShowImage(Boolean(src)) }, [src]) return ( {src && showImage ? ( {label} setShowImage(false)} className={cn( 'h-full w-full rounded-full border border-slate-200 bg-slate-100 object-cover', 'shadow-soft-sm' )} /> ) : ( {getAvatarInitial(name, email)} )} {status !== 'none' && ( )} ) }