Extract admin dashboard from ghabilee-frontend2 into a dedicated Next.js app for backoffice.ghabilee.ir (no SEO indexing / Clarity).
63 lines
1.7 KiB
TypeScript
63 lines
1.7 KiB
TypeScript
'use client'
|
|
|
|
/**
|
|
* UserAvatar — circular or square avatar with UserFillIcon fallback.
|
|
*
|
|
* Purpose
|
|
* - Shared avatar for host cards, chat, profile, and follow lists.
|
|
* - Empty/missing `src` shows a neutral background + UserFillIcon (decorative).
|
|
*
|
|
* Agent notes
|
|
* - Pass explicit `size` in pixels; Next/Image uses `fill` inside that box.
|
|
* - Prefer this over ad-hoc Image + fallback icon pairs in consumer UI.
|
|
*/
|
|
|
|
import Image from 'next/image'
|
|
|
|
import UserFillIcon from '@/components/icons/UserFillIcon'
|
|
import { cn } from '@/lib/cn'
|
|
|
|
export type UserAvatarVariant = 'circle' | 'square'
|
|
|
|
interface UserAvatarProps {
|
|
src?: string | null
|
|
alt: string
|
|
variant: UserAvatarVariant
|
|
/** Pixel size (width and height). */
|
|
size: number
|
|
className?: string
|
|
/** Extra class on the fallback UserFillIcon. */
|
|
iconClassName?: string
|
|
}
|
|
|
|
const UserAvatar = ({ src, alt, variant, size, className, iconClassName }: UserAvatarProps) => {
|
|
const trimmed = src?.trim() || null
|
|
const radiusClass = variant === 'circle' ? 'rounded-full' : 'rounded-[12px]'
|
|
|
|
return (
|
|
<span
|
|
aria-hidden={trimmed ? undefined : true}
|
|
className={cn(
|
|
'relative inline-flex shrink-0 items-center justify-center overflow-hidden bg-secondary-45 text-secondary-10',
|
|
radiusClass,
|
|
className
|
|
)}
|
|
style={{ width: size, height: size }}
|
|
>
|
|
{trimmed ? (
|
|
<Image
|
|
fill
|
|
alt={alt}
|
|
className="object-cover"
|
|
sizes={`${size}px`}
|
|
src={trimmed}
|
|
/>
|
|
) : (
|
|
<UserFillIcon className={cn(size >= 64 ? 'size-8' : 'size-5', iconClassName)} />
|
|
)}
|
|
</span>
|
|
)
|
|
}
|
|
|
|
export default UserAvatar
|