'use client'; import * as React from 'react'; import { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { Card, CardHeader, CardTitle, CardContent, CardAction } from '../../ui/card'; import { Avatar, AvatarFallback, AvatarImage } from '../../ui/avatar'; import { Badge } from '../../ui/badge'; import { cn } from '../../shared/utils'; export interface ActivityItem { id: string; user: { name: string; avatar?: string; initials: string }; action: string; target: string; time: string; type?: 'create' | 'update' | 'delete' | 'comment' | 'deploy'; } export interface ActivityCardProps extends React.HTMLAttributes { title?: string; items: ActivityItem[]; action?: React.ReactNode; maxItems?: number; } const activityTypeVariant: Record< NonNullable, React.ComponentProps['variant'] > = { create: 'success', update: 'info', delete: 'destructive', comment: 'secondary', deploy: 'default', }; export function ActivityCard({ title, items, action, maxItems = 5, className, ...props }: ActivityCardProps) { const { t } = useTranslation(); const cardTitle = title ?? t('activityCard.title'); const activityTypeBadge = useMemo< Record< NonNullable, { label: string; variant: React.ComponentProps['variant'] } > >( () => ({ create: { label: t('activityCard.type.create'), variant: activityTypeVariant.create }, update: { label: t('activityCard.type.update'), variant: activityTypeVariant.update }, delete: { label: t('activityCard.type.remove'), variant: activityTypeVariant.delete }, comment: { label: t('activityCard.type.comment'), variant: activityTypeVariant.comment }, deploy: { label: t('activityCard.type.deploy'), variant: activityTypeVariant.deploy }, }), [t] ); const visible = items.slice(0, maxItems); return ( {cardTitle} {action && {action}}
    {visible.map(item => { const badge = item.type ? activityTypeBadge[item.type] : null; return (
  • {item.user.avatar && } {item.user.initials}

    {item.user.name} {item.action}{' '} {item.target}

    {item.time}

    {badge && ( {badge.label} )}
  • ); })}
); }