gendesign/tradein-mvp/frontend/src/components/trade-in/v2/SupportChatContext.tsx
lekss361 a0647a53a9
All checks were successful
Deploy Trade-In / changes (push) Successful in 12s
Deploy Trade-In / test (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / build-backend (push) Has been skipped
Deploy Trade-In / build-frontend (push) Successful in 2m11s
Deploy Trade-In / deploy (push) Successful in 51s
feat(tradein/ui): окно чата поддержки на сайте вместо ухода в Telegram (#2533)
2026-07-26 20:52:30 +00:00

62 lines
2.1 KiB
TypeScript

"use client";
// Shared open/closed state for the on-site support chat window. It needs a
// single source of truth reachable from two components that are NOT parent/
// child of each other in the render tree: `SupportButton` (mounted once in
// app/v2/layout.tsx, portals the floating trigger + the chat panel to
// document.body) and `TopNav`'s "Помощь" menu item (mounted deep inside
// app/v2/page.tsx, i.e. inside `{children}` of that same layout). A React
// Context provided by the layout, wrapping both `{children}` and
// `<SupportButton />`, is the plain way to bridge that without prop-drilling
// through everything page.tsx passes down to TopNav.
import { createContext, useContext, useMemo, useState } from "react";
// Same bot as the Telegram support bridge (backend PR #2526). Kept here (not
// in SupportButton.tsx) so SupportChatPanel can import it without a
// SupportButton <-> SupportChatPanel circular import (SupportButton renders
// the panel). This is still the single source of truth for the URL — the
// panel's small "написать в Telegram" fallback link imports it from here.
export const SUPPORT_BOT_URL = "https://t.me/MERAsupport_bot";
interface SupportChatContextValue {
open: boolean;
openChat: () => void;
closeChat: () => void;
toggleChat: () => void;
}
const SupportChatContext = createContext<SupportChatContextValue | null>(null);
export function SupportChatProvider({
children,
}: {
children: React.ReactNode;
}) {
const [open, setOpen] = useState(false);
const value = useMemo<SupportChatContextValue>(
() => ({
open,
openChat: () => setOpen(true),
closeChat: () => setOpen(false),
toggleChat: () => setOpen((o) => !o),
}),
[open],
);
return (
<SupportChatContext.Provider value={value}>
{children}
</SupportChatContext.Provider>
);
}
export function useSupportChat(): SupportChatContextValue {
const ctx = useContext(SupportChatContext);
if (!ctx) {
throw new Error(
"useSupportChat must be used within <SupportChatProvider> (app/v2/layout.tsx)",
);
}
return ctx;
}