shoc-frontend-new/src/domain/work-orders/utils/work-order-deep-link.ts
Codex Review Integration ae941bc93d feat(notifications): open comment, mention, assignment and uplift items where they happened
Comment and mention items open the work order on the Comments tab with the
comments they were raised for highlighted; a grouped assignment opens the
dispatcher's own open queue; uplift decisions open the work order's uplifts.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-18 13:42:13 -03:00

92 lines
2.8 KiB
TypeScript

import { WORK_ORDERS_ROUTE } from "@/domain/dashboard/utils/work-order-drilldown-links";
const WORK_ORDER_PARAM = "wo";
const TAB_PARAM = "tab";
const SINCE_PARAM = "since";
const FOCUS_PARAM = "focus";
const MENTIONS_FOCUS = "mentions";
const COMMENTS_FOCUS = "comments";
export const WORK_ORDER_DEEP_LINK_TABS = [
"info",
"comments",
"audit",
"completion",
"extras",
"uplifts",
] as const;
export type WorkOrderDeepLinkTab = (typeof WORK_ORDER_DEEP_LINK_TABS)[number];
/**
* The comments a notification was raised for: everything by someone else from `since` on,
* either the ones that mention the user or the ones that do not.
*/
export type CommentHighlight = {
since: string;
mentions: boolean;
};
export type WorkOrderDeepLink = {
workOrderId: string;
tab: WorkOrderDeepLinkTab;
highlight: CommentHighlight | null;
};
function isDeepLinkTab(value: string | null): value is WorkOrderDeepLinkTab {
return WORK_ORDER_DEEP_LINK_TABS.some((tab) => tab === value);
}
/**
* `/workorders?wo=<id>&tab=<tab>` opens that work order's slide-over on the given tab; `uplifts`
* opens its uplifts dialog. A Comments link can also carry the comments to highlight.
*/
export function workOrderDeepLinkUrl(
workOrderId: string | number,
tab?: string | null,
highlight?: CommentHighlight | null,
): string {
const search = new URLSearchParams({ [WORK_ORDER_PARAM]: String(workOrderId) });
if (isDeepLinkTab(tab ?? null)) {
search.set(TAB_PARAM, String(tab));
}
if (tab === "comments" && highlight != null) {
search.set(SINCE_PARAM, highlight.since);
search.set(FOCUS_PARAM, highlight.mentions ? MENTIONS_FOCUS : COMMENTS_FOCUS);
}
return `${WORK_ORDERS_ROUTE}?${search.toString()}`;
}
function parseHighlight(
params: URLSearchParams,
tab: WorkOrderDeepLinkTab,
): CommentHighlight | null {
const since = params.get(SINCE_PARAM) ?? "";
const focus = params.get(FOCUS_PARAM);
if (tab !== "comments" || Number.isNaN(Date.parse(since))) {
return null;
}
if (focus !== MENTIONS_FOCUS && focus !== COMMENTS_FOCUS) {
return null;
}
return { since, mentions: focus === MENTIONS_FOCUS };
}
export function parseWorkOrderDeepLink(params: URLSearchParams): WorkOrderDeepLink | null {
const workOrderId = (params.get(WORK_ORDER_PARAM) ?? "").trim();
if (!/^\d+$/.test(workOrderId)) {
return null;
}
const requested = params.get(TAB_PARAM);
const tab = isDeepLinkTab(requested) ? requested : "info";
return { workOrderId, tab, highlight: parseHighlight(params, tab) };
}
export function withoutWorkOrderDeepLink(params: URLSearchParams): URLSearchParams {
const next = new URLSearchParams(params);
next.delete(WORK_ORDER_PARAM);
next.delete(TAB_PARAM);
next.delete(SINCE_PARAM);
next.delete(FOCUS_PARAM);
return next;
}