diff --git a/src/app/alerts/[id]/AlertDetail.tsx b/src/app/alerts/[id]/AlertDetail.tsx index 6437e0b..1f5fa23 100644 --- a/src/app/alerts/[id]/AlertDetail.tsx +++ b/src/app/alerts/[id]/AlertDetail.tsx @@ -1,8 +1,10 @@ "use client"; -import { useState } from "react"; +import { useState, useRef, useEffect } from "react"; import Link from "next/link"; -import { Alert, AlertSeverity } from "@/lib/types"; +import { Alert, AlertSeverity, AlertComment } from "@/lib/types"; + +// ── Severity theming ───────────────────────────────────────────────────────── const severityAccent: Record = { danger: "border-l-red-500", @@ -10,6 +12,20 @@ const severityAccent: Record = { info: "border-l-blue-500", }; +const severityText: Record = { + danger: "text-red-400", + warning: "text-yellow-400", + info: "text-blue-400", +}; + +const severityLabel: Record = { + danger: "Critical", + warning: "Warning", + info: "Info", +}; + +// ── Helpers ─────────────────────────────────────────────────────────────────── + function timeAgo(iso: string): string { const diff = Date.now() - new Date(iso).getTime(); const mins = Math.floor(diff / 60_000); @@ -26,12 +42,62 @@ function shortDate(iso: string): string { }); } +// ── Comment row ─────────────────────────────────────────────────────────────── + +function CommentRow({ comment }: { comment: AlertComment }) { + const isSystem = comment.author === "system"; + + if (isSystem) { + return ( +
+
+
+ + + + + {comment.body} + · + {timeAgo(comment.createdAt)} +
+
+
+ ); + } + + return ( +
+
+
+ + + +
+ User + {shortDate(comment.createdAt)} +
+
+

+ {comment.body} +

+
+
+ ); +} + +// ── Main component ──────────────────────────────────────────────────────────── + export default function AlertDetail({ initialAlert }: { initialAlert: Alert }) { const [alert, setAlert] = useState(initialAlert); const [actionLoading, setActionLoading] = useState(false); const [commentText, setCommentText] = useState(""); const [commentLoading, setCommentLoading] = useState(false); const [error, setError] = useState(null); + const bottomRef = useRef(null); + + useEffect(() => { + bottomRef.current?.scrollIntoView({ behavior: "smooth" }); + }, [alert.comments.length]); async function toggleStatus() { setActionLoading(true); @@ -79,7 +145,7 @@ export default function AlertDetail({ initialAlert }: { initialAlert: Alert }) { const statusTime = isOpen ? alert.firstSeen : (alert.closedAt ?? alert.firstSeen); return ( -
+
)} - {/* Alert card */} -
+
- {/* Status row */} -
- - {isOpen && } - {isOpen ? "Open" : isResolved ? "Auto-resolved" : "Closed"} - · - {timeAgo(statusTime)} - + {/* ── Alert detail ─────────────────────────────────────────────── */} +
+
- + {/* Status row */} +
+ + {isOpen && } + {isOpen ? "Open" : isResolved ? "Auto-resolved" : "Closed"} + · + {timeAgo(statusTime)} + + + +
+ + {/* Severity + title + description */} +
+ + {severityLabel[alert.severity]} + +

{alert.title}

+

{alert.description}

+
+ +
- {/* Title + description */} -
-

{alert.title}

-

{alert.description}

+ {/* ── Comments ─────────────────────────────────────────────────── */} +
+ +

+ Comments +

+ +
+ {alert.comments.length === 0 && ( +

No comments yet.

+ )} + {alert.comments.map((c) => ( + + ))} +
+
+ +
+