"use client"; // Inbox data layer. The inbox is a personalized work/awareness feed IIOS projects from events // (NEEDS_REPLY, MENTION, …). The CRM lists it and transitions item state; items are never created // here. Mock when the Shell isn't configured; live via the be-crm data door (crm.inbox.*) otherwise. // // Live contract (be-crm): // query crm.inbox.list { state? } -> InboxItem[] // cmd crm.inbox.transition { id, state, reason? } -> InboxItem import { useCallback, useMemo, useState } from "react"; import { useAppShell, useQuery } from "@abe-kap/appshell-sdk/react"; import { isShellConfigured } from "./appshell"; export type InboxState = "OPEN" | "SNOOZED" | "DONE" | "ARCHIVED" | "CANCELLED" | "STALE"; export interface UiInboxItem { id: string; kind: string; state: InboxState; title: string; summary?: string; priority: string; threadId?: string; createdAt: string; } const SHELL = isShellConfigured(); export interface InboxData { live: boolean; loading: boolean; error: string | null; items: UiInboxItem[]; transition: (id: string, state: InboxState) => Promise; refetch: () => void; } export function useInboxData(state?: InboxState): InboxData { return SHELL ? useLiveInbox(state) : useMockInbox(state); } function useLiveInbox(state?: InboxState): InboxData { const { sdk } = useAppShell(); const q = useQuery("crm.inbox.list", state ? { state } : {}); const transition = useCallback(async (id: string, next: InboxState) => { await sdk.command("crm.inbox.transition", { id, state: next }); q.refetch(); }, [sdk, q]); return { live: true, loading: q.loading, error: q.error?.message ?? null, items: q.data ?? [], transition, refetch: q.refetch }; } const MOCK_ITEMS: UiInboxItem[] = [ { id: "in_1", kind: "MENTION", state: "OPEN", title: "Sofia mentioned you", summary: "@you — can you confirm the Henderson scope?", priority: "HIGH", threadId: "th_mock_1", createdAt: new Date().toISOString() }, { id: "in_2", kind: "NEEDS_REPLY", state: "OPEN", title: "Reply needed — Storm response", summary: "Dan: Crew is rolling out at 7.", priority: "MEDIUM", threadId: "th_mock_2", createdAt: new Date().toISOString() }, { id: "in_3", kind: "SUPPORT_UPDATE", state: "OPEN", title: "Ticket TK-204 updated", summary: "Customer replied on the roof-leak case.", priority: "LOW", createdAt: new Date().toISOString() }, ]; function useMockInbox(state?: InboxState): InboxData { const [items, setItems] = useState(MOCK_ITEMS); const filtered = useMemo(() => (state ? items.filter((i) => i.state === state) : items), [items, state]); const transition = useCallback(async (id: string, next: InboxState) => { setItems((l) => l.map((i) => (i.id === id ? { ...i, state: next } : i))); }, []); return { live: false, loading: false, error: null, items: filtered, transition, refetch: () => {} }; }