Chatbot Component with Session Management

Desktop Light Mobile Light
DesktopChatbotLight
MobileChatbotLight
Desktop Dark Mobile Dark
DesktopChatbotDark
MobileChatbotDark

The Chatbot component provides a dynamic and interactive chat interface with advanced session management capabilities. It renders chat messages between a user and a chatbot, including features like typing simulation, automatic scrolling, persistent chat sessions, and a collapsible session history drawer using the Neo4j Needle Design Library.

Key Features

  • Session Management: Create, switch between, edit, and delete multiple chat sessions

  • Persistent Storage: Sessions are automatically saved to localStorage and restored on page reload

  • Interactive UI: Collapsible drawer with session history and intuitive hover effects

  • Typing Simulation: Realistic character-by-character typing effect for chatbot responses

  • Source Integration: Support for message sources and retrieval information

  • Responsive Design: Full-screen layout optimized for desktop and mobile devices

  • Neo4j Needle Integration: Uses official Neo4j Needle Design Library components

Pre-requisite

Ensure you have the @neo4j-ndl library installed in your project to use this Chatbot component.

You also need to set up the ChatSessionContext provider to enable session management functionality.

Usage

To integrate the Chatbot component into your application, you will first need to import both the component and the context provider:

import Chatbot from './path/to/Chatbot';
import { ChatSessionProvider } from './path/to/ChatSessionContext';

Next, wrap your application (or the part that uses the chatbot) with the ChatSessionProvider and render the Chatbot component:

<ChatSessionProvider>
  <Chatbot messages={listMessages} />
</ChatSessionProvider>

listMessages should be an array of message objects that you want to display initially. If not provided, the component will create an empty session.

Context Provider Setup

The ChatSessionProvider must wrap any component that uses Chatbot. This provider handles:

  • Session state management

  • localStorage persistence

  • Session CRUD operations

  • Message management within sessions

import { ChatSessionProvider } from './context/ChatSessionContext';

function App() {
  return (
    <ChatSessionProvider>
      <Chatbot />
    </ChatSessionProvider>
  );
}

Component Props

The Chatbot component accepts the following props:

Name Description Required

messages

An array of message objects that the chatbot will render initially. Each message object should contain id, user, message, datetime, and optionally isTyping and src fields. These messages will be used to populate the first session if no sessions exist in localStorage.

No (defaults to empty array)

Session Management Features

Chat Sessions

The component automatically manages multiple chat sessions with the following capabilities:

  • Create New Session: Start a fresh conversation

  • Switch Between Sessions: Navigate between different chat histories

  • Edit Session Titles: Rename sessions for better organization

  • Delete Sessions: Remove unwanted conversations

  • Persistent Storage: All sessions are saved to localStorage and restored on page load

Message Object Structure

Each message object in the messages array prop should follow this structure:

{
  id: number; // Unique identifier for the message
  user: string; // "user" for user messages, "chatbot" for chatbot messages
  message: string; // The message text
  datetime: string; // Timestamp of the message
  isTyping?: boolean; // Optional, simulates typing effect for chatbot messages
  src?: Array<string>; // Optional, source references for chatbot responses
}

Session Object Structure

Sessions are managed internally by the ChatSessionContext and follow this structure:

{
  id: string; // Unique session identifier
  title: string; // Display name for the session
  messages: ChatMessage[]; // Array of messages in this session
  createdAt: string; // ISO timestamp when session was created
  updatedAt: string; // ISO timestamp when session was last modified
}

Key components

Session Management Context

The component uses the useChatSession hook to access session management functionality:

  • sessions: Array of all available chat sessions

  • currentSession: Currently active session

  • createNewSession(): Create a new chat session

  • switchSession(id): Switch to a different session

  • deleteSession(id): Remove a session

  • updateSessionTitle(id, title): Rename a session

  • addMessageToCurrentSession(message): Add a message to the active session

Session Persistence

All sessions are automatically persisted to localStorage with the following keys:

  • neo4j-chat-sessions: Stores the array of all sessions

  • neo4j-current-session: Stores the ID of the currently active session

Sessions are restored when the application loads, providing a seamless user experience across browser sessions.

Example

Here is a basic example of using the Chatbot component with initial messages:

import { ChatSessionProvider } from './context/ChatSessionContext';
import Chatbot from './components/Chatbot';

const initialMessages = [
  {
    id: 1,
    user: 'chatbot',
    message: 'Hello! How can I assist you today?',
    datetime: '01/01/2025 00:00:00',
  }
];

function App() {
  return (
    <ChatSessionProvider>
      <Chatbot messages={initialMessages} />
    </ChatSessionProvider>
  );
}

This will render a full-screen chat interface with session management capabilities. If no sessions exist in localStorage, it will create an initial session with the provided messages.

Advanced Usage with Custom Sessions

You can also initialize the provider with predefined sessions:

const predefinedSessions = [
  {
    id: 'session-1',
    title: 'Technical Support',
    messages: [/* array of messages */],
    createdAt: '2024-01-01T00:00:00.000Z',
    updatedAt: '2024-01-01T01:00:00.000Z',
  },
  {
    id: 'session-2',
    title: 'Product Questions',
    messages: [/* array of messages */],
    createdAt: '2024-01-01T02:00:00.000Z',
    updatedAt: '2024-01-01T03:00:00.000Z',
  },
];

<ChatSessionProvider initialSessions={predefinedSessions}>
  <Chatbot />
</ChatSessionProvider>

Component Integration

Backend Integration

Here is a complete example of how to set up a local running demo with backend integration for the Chatbot component:

Step 1: Configure Vite Proxy

First, update your vite.config.ts to add a proxy configuration for your backend API:

// vite.config.ts
import { defineConfig } from 'vite'

export default defineConfig({
  // ... other config
  server: {
    proxy: {
      '/ask': {
        target: 'http://localhost:8001',
        changeOrigin: true,
        secure: false,
      },
    },
  },
})

This configuration will proxy any requests to /ask to your backend server running on http://localhost:8001.

Step 2: Update handleSubmit Function

Replace the existing handleSubmit function in your Chatbot component with this implementation that calls your backend API:

const handleSubmit = async (e: { preventDefault: () => void }) => {
  e.preventDefault();
  if (!inputMessage.trim() || !currentSession) {
    return;
  }

  const date = new Date();
  const datetime = `${date.toLocaleDateString()} ${date.toLocaleTimeString()}`;
  const userMessage: ChatMessage = {
    id: Date.now(),
    user: 'user',
    message: inputMessage,
    datetime: datetime
  };

  addMessageToCurrentSession(userMessage);
  setInputMessage('');

  setIsLoading(true);

  try {
    // Call your backend API through the Vite proxy
    const response = await fetch('/ask', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        question: inputMessage,
        session_id: currentSession?.id,
      }),
    });

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    const data = await response.json();

    const chatbotReply = {
      response: data.response, // Your API should return { response: string, src: string[] }
      src: data.src || [], // Sources array from your API
    };

    setIsLoading(false);
    simulateTypingEffect(chatbotReply);

  } catch (error) {
    console.error("API call failed:", error);

    // Fallback response in case of error
    const errorReply = {
      response: 'Sorry, I encountered an error while processing your request. Please try again.',
      src: [],
    };

    setIsLoading(false);
    simulateTypingEffect(errorReply);
  }
};

Step 3: Enhanced Source Visualization (Optional)

If you want to integrate real Neo4j data visualization for the sources, you can update your RetrievalInformation.tsx component:

// RetrievalInformation.tsx
import { runRAGQuery, setDriver } from '../utils/Driver';

// In your retrieveSources() function:
const retrieveSources = () => {
  // Configure your Neo4j connection
  setDriver('neo4j+s://your-database-url', 'username', 'password');

  // Query Neo4j for actual source data
  runRAGQuery(props.sources).then((nvlGraph) => {
    setNodes(nvlGraph.nodes);
    setRels(nvlGraph.relationships);
  });
};

This replaces the mock data with actual Neo4j query results for source visualization.

Backend API Requirements

Your backend API endpoint (/ask) should accept a POST request with this structure:

{
  "question": "User's question text",
  "session_id": "optional-session-identifier"
}

And return a response in this format:

{
  "response": "Chatbot's response text",
  "src": ["source1", "source2", "source3"]
}
For production use, consider implementing proper authentication and authorization for your backend API calls, as well as using state management libraries like @tanstack/react-query for better caching and error handling.

Session-Aware Backend Integration

For more advanced use cases, you can send session context to your backend to maintain conversation history and provide more contextual responses:

const fetchContextualResponse = async () => {
  const requestBody = {
    message: inputMessage,
    sessionId: currentSession?.id,
    conversationHistory: currentSession?.messages.slice(-5), // Last 5 messages for context
  };

  // ... API call logic
};

Or even store the sessions and messages history in your Neo4j database.