chore: add notification to packages

This commit is contained in:
Nathnael
2026-07-06 06:52:47 +00:00
parent c8f65829d1
commit 01b92072aa
6 changed files with 445 additions and 35 deletions

View File

@@ -7,6 +7,7 @@ export * from "./overview";
export * from "./etrade";
export * from "./contracts";
export * from "./clearance-files.catalog";
export * from "./notifications";
export enum TradeDirection {
IMPORT = "IMPORT",

View File

@@ -0,0 +1,101 @@
/**
* Shared contracts for the freight in-app notification system.
*
* The notification *mechanism* (module, gateway, bell) ships first; individual
* domain triggers are wired later. The `NotificationType` values below seed the
* intended trigger set so the frontend can map icons/labels before any producer
* actually emits them.
*/
/** Which app surface a notification is addressed to. */
export enum NotificationAudience {
PORTAL = "PORTAL",
BACKOFFICE = "BACKOFFICE",
}
/** Drives channel fan-out: HIGH also pushes email/SMS, NORMAL is in-app only. */
export enum NotificationPriority {
NORMAL = "NORMAL",
HIGH = "HIGH",
}
/**
* Semantic type of a notification. Used by the frontend to pick an icon/label
* and by producers to categorize. `GENERIC` is the catch-all for ad-hoc calls.
*/
export enum NotificationType {
GENERIC = "GENERIC",
// Portal-facing (customer)
CLEARANCE_DECISION = "CLEARANCE_DECISION",
DOCUMENT_ACTION = "DOCUMENT_ACTION",
BOOKING_STATUS = "BOOKING_STATUS",
INVOICE_ISSUED = "INVOICE_ISSUED",
// Backoffice-facing (staff)
REQUEST_SUBMITTED = "REQUEST_SUBMITTED",
PAYMENT_RECEIVED = "PAYMENT_RECEIVED",
CLEARANCE_REVIEW = "CLEARANCE_REVIEW",
}
/** Optional per-channel delivery outcome recorded on the notification row. */
export interface NotificationChannelsSent {
email?: boolean;
sms?: boolean;
}
/** A persisted in-app notification as returned to the client. */
export interface NotificationDto {
id: string;
recipientUserId: string;
audience: NotificationAudience;
type: NotificationType;
title: string;
body: string;
/** Deep-link path within the app the item points to (e.g. `/contracts/:id`). */
link?: string | null;
/** Arbitrary structured payload (bookingId, invoiceId, contractId, …). */
data?: Record<string, unknown> | null;
priority: NotificationPriority;
isRead: boolean;
readAt?: string | null;
createdAt: string;
}
/** Target selector: any combination resolves to a set of recipient user ids. */
export interface NotificationRecipients {
/** Explicit IAM user ids — always honored. */
userIds?: string[];
/** Portal: all users linked to this company (via external profiles). */
companyId?: string;
/** Portal: resolved to the company, then to that company's users. */
companyProfileId?: string;
/** Backoffice: all current employees of this organization. */
organizationId?: string;
}
/** Input any subsystem passes to `NotificationInboxService.notify(...)`. */
export interface NotifyInput {
recipients: NotificationRecipients;
audience: NotificationAudience;
type: NotificationType;
title: string;
body: string;
link?: string | null;
data?: Record<string, unknown> | null;
priority?: NotificationPriority;
}
/** Paginated list envelope for the notifications list endpoint. */
export interface NotificationListResult {
items: NotificationDto[];
count: number;
unreadCount: number;
}
/** Socket.io event names pushed server → client on the `notifications` namespace. */
export const NOTIFICATION_WS_EVENTS = {
NEW: "notification:new",
UNREAD_COUNT: "notification:unread-count",
} as const;
/** Socket.io namespace the notifications gateway listens on. */
export const NOTIFICATION_WS_NAMESPACE = "notifications";