All files / src/hooks/chat useChatMode.ts

100% Statements 72/72
95.23% Branches 20/21
100% Functions 2/2
100% Lines 72/72

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 1071x     1x     1x     1x 1x     1x           1x 21x 21x 21x   21x 3x 21x   21x 1x 21x   21x 21x 8x   8x     8x 3x 3x 3x 3x 3x     5x 8x 8x 21x 21x   21x 1x     1x     1x 1x 1x 21x     21x   19x 5x 19x 14x 14x 21x     21x 16x 1x 1x 1x 1x 1x   16x 16x 16x 16x   16x 16x 16x 16x 16x 16x 21x   21x 21x 21x 21x 21x 21x 21x 21x 21x  
import { useState, useCallback, useEffect } from 'react';
 
// Providers
import { ChatMode, SwitchChatModeOptions } from '@/providers/chatbot';
 
// Constants
import { CHATBOT_EVENTS } from '@shared/constants';
 
// Utils
import { applySidebarClasses } from '@/utils';
import { clearSidebarClasses } from '@shared/utils';
 
// Hooks
import { useBreakpoint } from '@shared/hooks';
 
/**
 * Custom hook for managing chat mode state and transitions
 * Handles popup/sidebar mode switching with responsive behavior
 */
export const useChatMode = () => {
  const { isDesktop } = useBreakpoint();
  const [isOpen, setIsOpen] = useState(false);
  const [chatBotMode, setChatBotMode] = useState<ChatMode>(ChatMode.POPUP);
 
  const toggleVisibility = useCallback(() => {
    setIsOpen((prev) => !prev);
  }, []);
 
  const openPopup = useCallback(() => {
    setIsOpen(true);
  }, []);
 
  const switchChatMode = useCallback(
    (options?: SwitchChatModeOptions) => {
      if (!isDesktop) return;
 
      const { targetMode, forceOpen } = options || {};
 
      // Toggle mode if no target specified
      if (!targetMode) {
        setChatBotMode((prev) =>
          prev === ChatMode.POPUP ? ChatMode.SIDEBAR : ChatMode.POPUP,
        );
        return;
      }
 
      // Direct mode switch
      setChatBotMode(targetMode);
      if (forceOpen) setIsOpen(true);
    },
    [isDesktop],
  );
 
  const handleSwitchMode = useCallback(() => {
    const isCurrentlySidebar = chatBotMode === ChatMode.SIDEBAR;
 
    // Add appropriate transition class for smooth animation
    applySidebarClasses(!isCurrentlySidebar, isDesktop, '.chatbot-rest-side');
 
    // Switch mode after a brief delay to allow CSS transition
    setTimeout(() => {
      switchChatMode();
    }, 50);
  }, [isDesktop, chatBotMode, switchChatMode]);
 
  // Handle responsive behavior and CSS classes
  useEffect(() => {
    // Apply sidebar classes based on current state
    if (isDesktop && chatBotMode === ChatMode.SIDEBAR) {
      applySidebarClasses(isOpen, isDesktop, '.chatbot-rest-side');
    } else {
      clearSidebarClasses();
    }
  }, [isDesktop, chatBotMode, isOpen]);
 
  // Handle sidebar close events from SearchBar
  useEffect(() => {
    const handleSidebarClosed = () => {
      if (chatBotMode === ChatMode.SIDEBAR) {
        switchChatMode({ targetMode: ChatMode.POPUP });
        toggleVisibility();
      }
    };
 
    window.addEventListener(
      CHATBOT_EVENTS.SIDEBAR_CLOSED_BY_SEARCH,
      handleSidebarClosed,
    );
 
    return () => {
      window.removeEventListener(
        CHATBOT_EVENTS.SIDEBAR_CLOSED_BY_SEARCH,
        handleSidebarClosed,
      );
    };
  }, [chatBotMode, switchChatMode, toggleVisibility]);
 
  return {
    isOpen,
    chatBotMode,
    toggleVisibility,
    switchChatMode,
    openPopup,
    handleSwitchMode,
  };
};