mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-10-07 16:19:01 +00:00
94 lines
2.6 KiB
TypeScript
94 lines
2.6 KiB
TypeScript
|
|
import type { LucideIcon } from "lucide-react";
|
||
|
|
import {
|
||
|
|
AlertTriangle,
|
||
|
|
Bell,
|
||
|
|
Clock,
|
||
|
|
Inbox,
|
||
|
|
MessageSquare,
|
||
|
|
ShieldAlert,
|
||
|
|
Wrench,
|
||
|
|
X,
|
||
|
|
} from "lucide-react";
|
||
|
|
import { Text } from "@/components/ui/text";
|
||
|
|
import type { NotificationItem } from "@/domain/notifications/types/notification-feed";
|
||
|
|
import { isDismissable } from "@/domain/notifications/utils/visible-notification-sections";
|
||
|
|
|
||
|
|
const REASON_ICONS: Record<string, LucideIcon> = {
|
||
|
|
"severity-critical": AlertTriangle,
|
||
|
|
sla: AlertTriangle,
|
||
|
|
mentions: MessageSquare,
|
||
|
|
unassigned: Inbox,
|
||
|
|
"due-soon": Clock,
|
||
|
|
"no-vendor": Wrench,
|
||
|
|
"aveta-missing": ShieldAlert,
|
||
|
|
activity: MessageSquare,
|
||
|
|
"vendor-conflict": Wrench,
|
||
|
|
};
|
||
|
|
|
||
|
|
type NotificationRowProps = {
|
||
|
|
item: NotificationItem;
|
||
|
|
unread: boolean;
|
||
|
|
onOpen: (item: NotificationItem) => void;
|
||
|
|
onDismiss: (item: NotificationItem) => void;
|
||
|
|
};
|
||
|
|
|
||
|
|
export function NotificationRow({ item, unread, onOpen, onDismiss }: NotificationRowProps) {
|
||
|
|
const Icon = REASON_ICONS[item.reason] ?? Bell;
|
||
|
|
|
||
|
|
return (
|
||
|
|
<li
|
||
|
|
className="group flex items-start gap-2.5 transition-colors hover:bg-[var(--color-bg-muted)]"
|
||
|
|
style={{
|
||
|
|
padding: "10px 8px",
|
||
|
|
marginInline: -8,
|
||
|
|
borderRadius: "var(--radius-md)",
|
||
|
|
borderBottom: "1px solid var(--color-bg-muted)",
|
||
|
|
}}
|
||
|
|
data-unread={unread}
|
||
|
|
>
|
||
|
|
<button
|
||
|
|
type="button"
|
||
|
|
onClick={() => onOpen(item)}
|
||
|
|
className="flex min-w-0 flex-1 cursor-pointer items-start gap-2.5 text-left"
|
||
|
|
>
|
||
|
|
<span
|
||
|
|
aria-hidden
|
||
|
|
className="shrink-0 rounded-full"
|
||
|
|
style={{
|
||
|
|
width: 6,
|
||
|
|
height: 6,
|
||
|
|
marginTop: 7,
|
||
|
|
background: unread ? "var(--color-primary)" : "transparent",
|
||
|
|
}}
|
||
|
|
/>
|
||
|
|
<Icon
|
||
|
|
size={15}
|
||
|
|
aria-hidden
|
||
|
|
className="shrink-0"
|
||
|
|
style={{ color: "var(--color-text-muted)", marginTop: 2 }}
|
||
|
|
/>
|
||
|
|
<Text
|
||
|
|
as="span"
|
||
|
|
variant="description"
|
||
|
|
sx={{ fontSize: 13, lineHeight: 1.45, fontWeight: unread ? 500 : 400, margin: 0 }}
|
||
|
|
>
|
||
|
|
{unread && <span className="sr-only">Unread: </span>}
|
||
|
|
{item.title}
|
||
|
|
</Text>
|
||
|
|
</button>
|
||
|
|
{isDismissable(item) && (
|
||
|
|
<button
|
||
|
|
type="button"
|
||
|
|
onClick={() => onDismiss(item)}
|
||
|
|
title="Dismiss"
|
||
|
|
aria-label="Dismiss notification"
|
||
|
|
className="shrink-0 cursor-pointer opacity-0 transition-opacity group-hover:opacity-100 focus-visible:opacity-100"
|
||
|
|
style={{ color: "var(--color-text-muted)", marginTop: 2 }}
|
||
|
|
>
|
||
|
|
<X size={13} aria-hidden />
|
||
|
|
</button>
|
||
|
|
)}
|
||
|
|
</li>
|
||
|
|
);
|
||
|
|
}
|