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
62 lines
2.1 KiB
TypeScript
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;
|
|
}
|