import { Button } from "@/src/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@/src/components/ui/card"; import { X } from "lucide-react"; import useLocalStorage from "../useLocalStorage"; import Link from "next/link"; import { usePostHogClientCapture } from "@/src/features/posthog-analytics/usePostHogClientCapture"; const TWO_WEEKS_MS = 14 * 24 * 60 * 60 * 1000; type SidebarNotification = { id: string; // Add unique ID for each notification title: string; description: React.ReactNode; createdAt?: string; // optional, used to expire the notification link?: string; // defaults to "Learn more" if no linkContent and no linkTitle linkTitle?: string; linkContent?: React.ReactNode; // Time-to-live in milliseconds from createdAt. Defaults to TWO_WEEKS_MS. ttlMs?: number; }; const notifications: SidebarNotification[] = [ { id: "github-star", title: "Star Langfuse", description: "See the latest releases and help grow the community on GitHub", link: "https://github.com/langfuse/langfuse", linkContent: ( // eslint-disable-next-line @next/next/no-img-element Langfuse GitHub stars ), }, ]; const STORAGE_KEY = "dismissed-sidebar-notifications"; export function SidebarNotifications() { const capture = usePostHogClientCapture(); const [dismissedNotifications, setDismissedNotifications] = useLocalStorage< string[] >(STORAGE_KEY, []); const isExpired = (notif: SidebarNotification) => { if (!notif.createdAt) return false; const created = new Date(notif.createdAt).getTime(); const ttl = notif.ttlMs ?? TWO_WEEKS_MS; return Date.now() > created + ttl; }; const dismissNotification = (id: string) => { setDismissedNotifications([...dismissedNotifications, id]); }; const activeNotifications = notifications.filter( (notif) => !dismissedNotifications.includes(notif.id) && !isExpired(notif), ); if (activeNotifications.length === 0) { return null; } return (
{activeNotifications.map((notification) => ( {notification.title} {notification.description} {notification.link && (notification.linkContent ? ( { capture("notification:click_link", { notification_id: notification.id, }); }} > {notification.linkContent} ) : ( ))} ))}
); }