Files
lynkeduppro-crm/src/components/dashboard/messenger-sdk.tsx
T
maaz519 988b46f6e7 refactor(messaging): drop bespoke messenger/inbox/mail + wrapper page headers
Delete the now-dead pre-SDK stack (messenger/inbox/mail components + their
*-api libs + messenger-socket) — both tabs render the @insignia/iios-messaging-ui
SDK. Remove the redundant <PageHead> from the messenger/inbox SDK wrappers (the
Topbar already shows the title); the SDK itself renders no header.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-22 17:55:10 +05:30

90 lines
3.1 KiB
TypeScript

"use client";
// The CRM messenger, now rendered by the shared @insignia/iios-messaging-ui SDK instead of a
// bespoke in-CRM implementation. The CRM only supplies an adapter (transport) + theming; all the
// UI + messaging logic lives in the SDK. Live path = the be-crm data door (CrmMessagingAdapter);
// demo path = the SDK's own MockAdapter.
import { useEffect, useMemo, useState } from "react";
import { useAppShell, useAuth, useQuery } from "@abe-kap/appshell-sdk/react";
import { MessageSocket } from "@insignia/iios-kernel-client";
import { MessagingProvider, Messenger as SdkMessenger, type MessagingAdapter } from "@insignia/iios-messaging-ui";
import { MockAdapter } from "@insignia/iios-messaging-ui/adapters/mock";
import "@insignia/iios-messaging-ui/styles.css";
import { isShellConfigured } from "@/lib/appshell";
import { CrmMessagingAdapter, type DataDoor } from "@/lib/crm-messaging-adapter";
interface RealtimeDTO { url: string; audience: string; token?: string }
/** Open the IIOS message socket with the delegated token the BFF mints (crm.messenger.realtime). */
function useRealtimeSocket(): MessageSocket | null {
const rt = useQuery<RealtimeDTO>("crm.messenger.realtime", {});
const [socket, setSocket] = useState<MessageSocket | null>(null);
const url = rt.data?.url;
const token = rt.data?.token;
useEffect(() => {
if (!url || !token) return;
const s = new MessageSocket({ serviceUrl: url, token, autoConnect: false });
s.connect();
setSocket(s);
return () => {
s.disconnect();
setSocket(null);
};
}, [url, token]);
return socket;
}
const SHELL = isShellConfigured();
export function MessengerSdk() {
return (
<div className="view">
{!SHELL && (
<div
style={{
margin: "0 0 14px",
padding: "8px 14px",
borderRadius: 10,
background: "var(--panel-2)",
color: "var(--muted)",
fontSize: 13,
border: "1px solid var(--border)",
}}
>
Demo mode running on the SDK&apos;s mock adapter.
</div>
)}
<div className="miu-host">{SHELL ? <LiveHost /> : <DemoHost />}</div>
</div>
);
}
// SHELL is a build-time constant, so exactly one of these mounts for the life of the app
// (Rules-of-Hooks safe — the other branch never renders).
function DemoHost() {
const adapter = useMemo<MessagingAdapter>(() => new MockAdapter(), []);
return (
<MessagingProvider adapter={adapter}>
<SdkMessenger />
</MessagingProvider>
);
}
function LiveHost() {
const { sdk } = useAppShell();
const { user } = useAuth();
const socket = useRealtimeSocket();
// Rebuilds once the socket connects: the first adapter (no socket) polls; the second runs live.
const adapter = useMemo<MessagingAdapter | null>(
() => (user?.id ? new CrmMessagingAdapter(sdk as unknown as DataDoor, user.id, socket ?? undefined) : null),
[sdk, user?.id, socket],
);
if (!adapter) return <div className="miu-empty">Loading</div>;
return (
<MessagingProvider adapter={adapter}>
<SdkMessenger />
</MessagingProvider>
);
}