2026-07-17 11:59:05 -03:00
|
|
|
import { useMemo } from "react";
|
|
|
|
|
import { Box, Stack, Typography } from "@mui/material";
|
|
|
|
|
import { formatDateTime } from "@/lib/time-utils";
|
|
|
|
|
|
|
|
|
|
export type CommentTimelineItem = {
|
|
|
|
|
id: string | number;
|
|
|
|
|
author: string;
|
|
|
|
|
createdAt?: string;
|
|
|
|
|
body: string;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
type CommentTimelineProps = {
|
|
|
|
|
items: CommentTimelineItem[];
|
|
|
|
|
emptyMessage?: string;
|
|
|
|
|
maxHeightClass?: string;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export function CommentTimeline({
|
|
|
|
|
items,
|
|
|
|
|
emptyMessage = "No comments yet.",
|
|
|
|
|
maxHeightClass = "max-h-72",
|
|
|
|
|
}: CommentTimelineProps) {
|
|
|
|
|
const sorted = useMemo(
|
|
|
|
|
() =>
|
|
|
|
|
[...items].sort((a, b) => {
|
|
|
|
|
const aTime = a.createdAt ? new Date(a.createdAt).getTime() : 0;
|
|
|
|
|
const bTime = b.createdAt ? new Date(b.createdAt).getTime() : 0;
|
|
|
|
|
return aTime - bTime;
|
|
|
|
|
}),
|
|
|
|
|
[items],
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (!sorted.length) {
|
|
|
|
|
return <Typography color="text.secondary">{emptyMessage}</Typography>;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<Stack spacing={2} className={`${maxHeightClass} overflow-y-auto`}>
|
|
|
|
|
{sorted.map((item) => (
|
|
|
|
|
<Box key={String(item.id)} className="rounded border border-border p-3">
|
2026-07-17 13:31:56 -03:00
|
|
|
<Stack direction="row" className="mb-1" sx={{ justifyContent: "space-between" }}>
|
2026-07-17 11:59:05 -03:00
|
|
|
<Typography variant="caption" className="font-semibold">
|
|
|
|
|
{item.author}
|
|
|
|
|
</Typography>
|
|
|
|
|
<Typography variant="caption" color="text.secondary">
|
|
|
|
|
{item.createdAt ? formatDateTime(item.createdAt) : ""}
|
|
|
|
|
</Typography>
|
|
|
|
|
</Stack>
|
|
|
|
|
<Typography variant="body2">{item.body}</Typography>
|
|
|
|
|
</Box>
|
|
|
|
|
))}
|
|
|
|
|
</Stack>
|
|
|
|
|
);
|
|
|
|
|
}
|