HyperSaaS
FrontendChat

Session UI

Main chat container with resizable panels and responsive layout.

ChatSessionUI is the top-level container for an active chat conversation. It orchestrates messages, the map panel, the document viewer, and the settings sheet.

Props

interface ChatSessionUIProps {
  chatSession: ChatSession;
  enableDocumentStatusPolling?: boolean;
}

State Management

The component manages several pieces of state:

// Map visibility (synced with URL query params)
const [isMapVisible, setIsMapVisible] = useQueryParam("map");

// Document viewer tabs
const [openDocuments, setOpenDocuments] = useState<DocumentTab[]>([]);
const [activeDocumentId, setActiveDocumentId] = useState<string | null>(null);

// Mobile document sheet
const [isMobileDocumentSheetOpen, setIsMobileDocumentSheetOpen] = useState(false);

// Document processing status
const [documentStatuses, setDocumentStatuses] = useState<DocumentStatus[]>([]);

Desktop Layout (Resizable Panels)

On desktop, the chat uses ResizablePanelGroup for a flexible multi-panel layout:

┌─────────────────┬──────────────┬──────────────────┐
│                  │              │                   │
│   Message List   │  Google Map  │ Document Viewer   │
│   + Input Form   │  (optional)  │   (optional)      │
│                  │              │                   │
└─────────────────┴──────────────┴──────────────────┘
  • Panel 1 (Messages): Always visible, min 30% width
  • Panel 2 (Map): Toggled via header button, shows Google Maps with location markers
  • Panel 3 (Documents): Opens when clicking a citation source, tabbed document viewer

Users can drag panel borders to resize.

Mobile Layout

On mobile, the layout stacks vertically:

┌──────────────────┐
│  Chat Header     │
├──────────────────┤
│                  │
│  Message List    │
│                  │
├──────────────────┤
│  Input Form      │
└──────────────────┘

      + Sheet modals for Map & Documents

Documents and map open in Sheet components (slide-up panels).

Document Status Polling

When enableDocumentStatusPolling is true, the component polls document processing status every 5 seconds:

useEffect(() => {
  if (!enableDocumentStatusPolling) return;

  const interval = setInterval(async () => {
    const statuses = await fetchDocumentStatuses(chatSession.id);
    setDocumentStatuses(statuses);
  }, 5000);

  return () => clearInterval(interval);
}, []);

This keeps the UI updated when documents are being ingested in the background.

Citation Click Flow

When a user clicks a citation source in a message:

  1. onCitationClick(documentId, chunkId) is called
  2. If document not already open, add to openDocuments tabs
  3. Set activeDocumentId to the clicked document
  4. Pass highlightChunkId to the document viewer
  5. On mobile, open the document sheet

Settings Sheet

The ChatSettingsForm opens as a side sheet with:

  • Chat name editor
  • AI model selection (dropdown with all supported models)
  • Temperature, top_p, max_tokens controls
  • Knowledge base management (attach/detach KBs)

Changes are saved via PUT to the chat session API.

Location Sheet

When a location tag is clicked in a message:

  1. onLocationClick(location) is called
  2. A floating sheet opens with LocationDetailView
  3. Shows location name, address, and details
  4. Map panel centers on the location marker

On this page