"use client"; /** * ChatDock — floating right-docked wrapper around for the Site * Finder analysis report (#958 follow-up). * * The chat used to be mounted inline at the bottom of the report; that meant the * user had to scroll all the way down to ask anything. ChatDock keeps it * always reachable: a fixed launcher (bottom-right) opens a fixed popover panel * that stays put while the report scrolls. * * Open/close: * - launcher click → toggles the panel open * - close button (X) → closes * - Esc → closes (keydown listener active only while open, cleaned up) * * Double-card avoidance: already renders its own bordered
* card with the «Чат по участку» header. So the dock's own chrome is just a thin * header bar carrying the X close button (NO duplicate title) — ChatPanel's own * header provides the title inside the scrollable body. No nested boxes. * * box-shadow is allowed here (floating popover / launcher), unlike in-page cards. */ import { useEffect, useState } from "react"; import { MessageSquare, X } from "lucide-react"; import { ChatPanel } from "@/components/site-finder/ChatPanel"; // ── Props ───────────────────────────────────────────────────────────────────── interface Props { cadNum: string; } // ── ChatDock ─────────────────────────────────────────────────────────────────── export function ChatDock({ cadNum }: Props) { const [open, setOpen] = useState(false); // Esc closes the panel (listener active only while open). useEffect(() => { if (!open) return; function onKeyDown(e: KeyboardEvent) { if (e.key === "Escape") setOpen(false); } window.addEventListener("keydown", onKeyDown); return () => window.removeEventListener("keydown", onKeyDown); }, [open]); // ── Collapsed: floating launcher ───────────────────────────────────────────── if (!open) { return ( ); } // ── Expanded: floating popover panel ───────────────────────────────────────── return (
{/* Thin header bar — close affordance only. The title lives in ChatPanel's own header below, so there's no duplicate heading / nested card. */}
{/* Scrollable body — ChatPanel renders normally (its own card + header). */}
); }