mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-10-03 22:33:13 +00:00
* docs(work-orders): add pending BE contract checklist for design parity gaps * feat(work-orders): add mentions in work-order comments composer * docs(work-orders): align pr description with jira and qa residuals * refactor(workorders): split work order view page into view components * fix(work-orders): export comment assignment vendor input types for view hook * fix(work-orders): drop preferredContact from vendor update payload Align with WorkOrderVendorUpdatePayload on current dev so the mentions branch typechecks. * fix(work-orders): remove Preferred Contact from WO vendor editor (SH-180) EOF * fix(work-orders): harden comment mentions and clear draft on success * fix(work-orders): harden mention highlight boundary and submit catch [SH-217] * fix(work-orders): keep mention cursor sync on current value [SH-217] * fix(work-orders): keep mention menu open after typing @ Pass live text into syncCursor instead of a render-time valueRef. Add a composer interaction regression for @ autocomplete visibility. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: Alexandre Brandizzi <alex_brandizzi@hotmail.com>
59 lines
1.8 KiB
TypeScript
59 lines
1.8 KiB
TypeScript
import { useMemo } from "react";
|
|
import { Box, Stack } from "@mui/material";
|
|
import { CommentBodyWithMentions } from "@/components/common/comment-body-with-mentions";
|
|
import { Text } from "@/components/ui/text";
|
|
import type { MentionLookup } from "@/domain/work-orders/utils/comment-mentions";
|
|
import { formatDateTime } from "@/lib/time-utils";
|
|
|
|
export type CommentTimelineItem = {
|
|
id: string | number;
|
|
author: string;
|
|
createdAt?: string;
|
|
body: string;
|
|
mentions?: string[];
|
|
};
|
|
|
|
type CommentTimelineProps = {
|
|
items: CommentTimelineItem[];
|
|
emptyMessage?: string;
|
|
maxHeightClass?: string;
|
|
mentionUsers?: MentionLookup[];
|
|
};
|
|
export function CommentTimeline({
|
|
items,
|
|
emptyMessage = "No comments yet.",
|
|
maxHeightClass = "max-h-72",
|
|
mentionUsers,
|
|
}: 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 <Text tone="muted">{emptyMessage}</Text>;
|
|
}
|
|
|
|
return (
|
|
<Stack spacing={2} className={`${maxHeightClass} overflow-y-auto`}>
|
|
{sorted.map((item) => (
|
|
<Box key={String(item.id)} className="rounded border border-border p-3">
|
|
<Stack direction="row" className="mb-1" sx={{ justifyContent: "space-between" }}>
|
|
<Text variant="caption" className="font-semibold">
|
|
{item.author}
|
|
</Text>
|
|
<Text variant="caption" tone="muted">
|
|
{item.createdAt ? formatDateTime(item.createdAt) : ""}
|
|
</Text>
|
|
</Stack>
|
|
<CommentBodyWithMentions text={item.body} mentions={item.mentions} users={mentionUsers} />
|
|
</Box>
|
|
))}
|
|
</Stack>
|
|
);
|
|
}
|