Chat Widget, changes in nav bar

Auto Scroll chat and changes in Nav bar
This commit is contained in:
Nikitha
2026-04-15 08:12:16 -06:00
parent f57fe9e233
commit 2fa7b99966
6 changed files with 106 additions and 31 deletions

View File

@@ -6,13 +6,23 @@ const ChatWidgetContext = createContext(null);
const API_BASE = "";
export function ChatWidgetProvider({ children }) {
const [isOpen, setIsOpen] = useState(false);
const [view, setView] = useState("ai"); // "ai" | "history" | "live"
const [isOpen, setIsOpen] = useState(false);
const [view, setView] = useState("ai"); // "ai" | "history" | "live"
// AI chat
const [aiMessages, setAiMessages] = useState([]);
const [aiSending, setAiSending] = useState(false);
const [aiError, setAiError] = useState(null);
const [aiMessages, setAiMessages] = useState(() => {
try {
const saved = localStorage.getItem("fc_aiMessages");
return saved ? JSON.parse(saved) : [];
} catch { return []; }
});
const [aiSending, setAiSending] = useState(false);
const [aiError, setAiError] = useState(null);
// Persist aiMessages to localStorage
useEffect(() => {
localStorage.setItem("fc_aiMessages", JSON.stringify(aiMessages));
}, [aiMessages]);
// Keep a ref so sendAiMessage stays stable (no stale-closure over messages)
const aiMessagesRef = useRef(aiMessages);
@@ -41,17 +51,18 @@ export function ChatWidgetProvider({ children }) {
}
}, []);
//Live chat
const [conversations, setConversations] = useState([]);
const [convsLoading, setConvsLoading] = useState(false);
const [activeConvId, setActiveConvId] = useState(null);
const [activeConv, setActiveConv] = useState(null);
const [liveMessages, setLiveMessages] = useState([]);
const [liveSending, setLiveSending] = useState(false);
// Live chat
const [conversations, setConversations] = useState([]);
const [convsLoading, setConvsLoading] = useState(false);
const [activeConvId, setActiveConvId] = useState(null);
const [activeConv, setActiveConv] = useState(null);
const [liveMessages, setLiveMessages] = useState([]);
const [liveSending, setLiveSending] = useState(false);
const [switchingToHuman, setSwitchingToHuman] = useState(false);
const pollRef = useRef(null);
const pollRef = useRef(null);
const activeConvIdRef = useRef(null);
const tokenRef = useRef(null); // FIX: store token so polling can restart
const stopPolling = useCallback(() => {
if (pollRef.current) { clearInterval(pollRef.current); pollRef.current = null; }
@@ -87,6 +98,7 @@ export function ChatWidgetProvider({ children }) {
const openLiveConversation = useCallback(async (convId, token) => {
if (!convId || !token) return;
stopPolling();
tokenRef.current = token; // FIX: save token for polling restart
setActiveConvId(convId);
activeConvIdRef.current = convId;
setLiveMessages([]);
@@ -137,12 +149,22 @@ export function ChatWidgetProvider({ children }) {
}
}, [switchingToHuman, openLiveConversation]);
// Stop polling when navigating away from live view or closing widget
useEffect(() => { if (view !== "live") stopPolling(); }, [view, stopPolling]);
useEffect(() => { if (!isOpen) stopPolling(); }, [isOpen, stopPolling]);
// FIX: Single effect that handles both stopping AND restarting polling
useEffect(() => {
if (!isOpen || view !== "live") {
stopPolling();
} else if (isOpen && view === "live" && activeConvIdRef.current && tokenRef.current) {
stopPolling();
fetchLiveMessages(activeConvIdRef.current, tokenRef.current);
pollRef.current = setInterval(
() => fetchLiveMessages(activeConvIdRef.current, tokenRef.current),
2500
);
}
}, [isOpen, view, stopPolling, fetchLiveMessages]);
const toggleOpen = useCallback(() => setIsOpen((o) => !o), []);
const openView = useCallback((v) => setView(v), []);
const openView = useCallback((v) => setView(v), []);
return (
<ChatWidgetContext.Provider value={{
@@ -163,4 +185,4 @@ export function useChatWidget() {
const ctx = useContext(ChatWidgetContext);
if (!ctx) throw new Error("useChatWidget must be used within ChatWidgetProvider");
return ctx;
}
}