mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-10-02 08:33:14 +00:00
Dispatchers see a one-line banner and a one-time toast while a Reactive/Emergency work order is past half of its SEV response window; the banner opens the board on exactly those work orders and dismisses for the session. Missed deadlines stay in the notification center until acknowledged, and Clear all skips them.
94 lines
2.8 KiB
TypeScript
94 lines
2.8 KiB
TypeScript
import { CircularProgress } from "@mui/material";
|
|
import { Inbox } from "lucide-react";
|
|
import { Text } from "@/components/ui/text";
|
|
import type { NotificationCenter } from "./use-notification-center";
|
|
import { NotificationRow } from "./notification-row";
|
|
|
|
type NotificationFeedListProps = {
|
|
center: NotificationCenter;
|
|
};
|
|
|
|
export function NotificationFeedList({ center }: NotificationFeedListProps) {
|
|
if (center.isLoading) {
|
|
return (
|
|
<div className="flex justify-center py-16">
|
|
<CircularProgress size={24} aria-label="Loading notifications" />
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (center.error != null && !center.hasData) {
|
|
return (
|
|
<Text variant="error" className="py-6">
|
|
Notifications could not be loaded. They will retry automatically.
|
|
</Text>
|
|
);
|
|
}
|
|
|
|
if (center.sections.length === 0) {
|
|
return (
|
|
<div className="flex flex-col items-center justify-center gap-2 py-16">
|
|
<Inbox size={24} aria-hidden style={{ color: "var(--color-text-muted)" }} />
|
|
<Text variant="description" sx={{ fontSize: 13, color: "var(--color-text-muted)" }}>
|
|
Nothing needs your attention
|
|
</Text>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div>
|
|
{center.sections.map((section) => (
|
|
<section
|
|
key={section.reason}
|
|
aria-label={`${section.label}, ${section.count}`}
|
|
style={{ marginTop: 16 }}
|
|
>
|
|
<div className="flex items-center gap-2" style={{ marginBottom: 4 }}>
|
|
<Text
|
|
as="h3"
|
|
variant="label"
|
|
sx={{
|
|
fontSize: 11,
|
|
fontWeight: 500,
|
|
textTransform: "uppercase",
|
|
letterSpacing: "0.06em",
|
|
color: "var(--color-text-muted)",
|
|
}}
|
|
>
|
|
{section.label}
|
|
</Text>
|
|
<span
|
|
style={{
|
|
fontSize: 11,
|
|
fontWeight: 500,
|
|
color: "var(--color-text-secondary)",
|
|
background: "var(--color-bg-muted)",
|
|
borderRadius: "var(--radius-sm)",
|
|
padding: "1px 6px",
|
|
}}
|
|
>
|
|
{section.count}
|
|
</span>
|
|
</div>
|
|
<ul className="m-0 list-none p-0">
|
|
{section.items.map((item) => (
|
|
<NotificationRow
|
|
key={item.id}
|
|
item={item}
|
|
unread={center.unreadIds.has(item.id)}
|
|
onOpen={center.open}
|
|
onDismiss={center.dismiss}
|
|
onAcknowledge={center.acknowledge}
|
|
acknowledging={
|
|
item.target.workOrderId != null &&
|
|
item.target.workOrderId === center.acknowledgingWorkOrderId
|
|
}
|
|
/>
|
|
))}
|
|
</ul>
|
|
</section>
|
|
))}
|
|
</div>
|
|
);
|
|
}
|