import { useState } from "react"; import { Icon } from "../../icon"; import { formatRelativeTime } from "../../../utils/time"; import type { NotificationItem as NotificationItemType } from "../../../api/notifications"; export interface NotificationItemProps { notification: NotificationItemType; onMarkRead: (id: string) => void; onDismiss: (id: string) => void; } import type { IconName } from "../../../utils/icons"; const severityIconMap: Record = { info: "info", warning: "warning", error: "error", success: "success", }; function formatMetadataValue(value: unknown): string { if (value === null || value === undefined) return "—"; if (typeof value === "string") return value; if (typeof value === "number") return String(value); if (typeof value === "boolean") return value ? "Yes" : "No"; try { return JSON.stringify(value); } catch { return String(value); } } export function NotificationItem({ notification, onMarkRead, onDismiss, }: NotificationItemProps) { const isUnread = notification.read_at === null; const iconName = severityIconMap[notification.severity] ?? "info"; const [expanded, setExpanded] = useState(false); const hasDetails = !!notification.message || Object.keys(notification.metadata || {}).length > 0; return (
  • {notification.title}
    {notification.message && (
    {notification.message}
    )}
    {formatRelativeTime(notification.created_at)}
    {expanded && notification.metadata && (
    {Object.entries(notification.metadata).map(([key, value]) => (
    {key.replace(/_/g, " ")}
    {formatMetadataValue(value)}
    ))}
    )}
    {hasDetails && ( )} {isUnread && ( )}
  • ); }