95 lines
3.1 KiB
TypeScript
95 lines
3.1 KiB
TypeScript
"use client";
|
|
|
|
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
|
import { cn, getInitials, formatRelativeDate } from "@/lib/utils";
|
|
import { ScrollArea } from "@/components/ui/scroll-area";
|
|
import {
|
|
Film,
|
|
MessageSquare,
|
|
CheckCircle2,
|
|
XCircle,
|
|
Upload,
|
|
Bell,
|
|
AtSign,
|
|
} from "lucide-react";
|
|
|
|
interface ActivityItem {
|
|
id: string;
|
|
type: string;
|
|
title: string;
|
|
message: string;
|
|
createdAt: Date;
|
|
user?: {
|
|
name: string | null;
|
|
image: string | null;
|
|
} | null;
|
|
}
|
|
|
|
interface RecentActivityProps {
|
|
activities: ActivityItem[];
|
|
}
|
|
|
|
const ACTIVITY_ICONS: Record<string, { icon: React.ElementType; color: string }> = {
|
|
VERSION_UPLOADED: { icon: Upload, color: "text-blue-400 bg-blue-500/10" },
|
|
FEEDBACK_ADDED: { icon: MessageSquare, color: "text-amber-400 bg-amber-500/10" },
|
|
SHOT_APPROVED: { icon: CheckCircle2, color: "text-emerald-400 bg-emerald-500/10" },
|
|
SHOT_REJECTED: { icon: XCircle, color: "text-red-400 bg-red-500/10" },
|
|
COMMENT_REPLY: { icon: MessageSquare, color: "text-purple-400 bg-purple-500/10" },
|
|
MENTION: { icon: AtSign, color: "text-primary bg-primary/10" },
|
|
REVISION_REQUESTED: { icon: Film, color: "text-orange-400 bg-orange-500/10" },
|
|
};
|
|
|
|
export function RecentActivity({ activities }: RecentActivityProps) {
|
|
if (activities.length === 0) {
|
|
return (
|
|
<div className="flex flex-col items-center justify-center py-10 text-zinc-500">
|
|
<Bell className="h-8 w-8 mb-3 opacity-30" />
|
|
<p className="text-sm">No recent activity</p>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<ScrollArea className="h-full">
|
|
<div className="space-y-1 p-1">
|
|
{activities.map((item) => {
|
|
const cfg = ACTIVITY_ICONS[item.type] ?? { icon: Bell, color: "text-muted-foreground bg-muted/20" };
|
|
const Icon = cfg.icon;
|
|
|
|
return (
|
|
<div
|
|
key={item.id}
|
|
className="flex gap-3 px-2 py-2.5 rounded-lg hover:bg-secondary/30 transition-colors"
|
|
>
|
|
<div className={cn("p-1.5 rounded-md shrink-0 mt-0.5", cfg.color.split(" ")[1])}>
|
|
<Icon className={cn("h-3 w-3", cfg.color.split(" ")[0])} />
|
|
</div>
|
|
|
|
<div className="flex-1 min-w-0">
|
|
<p className="text-sm font-medium truncate">{item.title}</p>
|
|
<p className="text-xs text-muted-foreground line-clamp-2 mt-0.5">
|
|
{item.message}
|
|
</p>
|
|
</div>
|
|
|
|
<div className="flex flex-col items-end gap-1 shrink-0">
|
|
{item.user && (
|
|
<Avatar className="h-5 w-5">
|
|
{item.user.image && <AvatarImage src={item.user.image} />}
|
|
<AvatarFallback className="text-[8px]">
|
|
{getInitials(item.user.name)}
|
|
</AvatarFallback>
|
|
</Avatar>
|
|
)}
|
|
<span className="text-xs text-muted-foreground whitespace-nowrap">
|
|
{formatRelativeDate(item.createdAt)}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
</ScrollArea>
|
|
);
|
|
}
|