'use client'; /** * Chat Panel (v3.0) * * Chat interface met scrollable message list, auto-scroll, en scroll-lock detection. * * Epic: E2 (Chat Panel & Messages) * Story: E2.S3 (ChatPanel component - scrolling) */ import { useRef, useEffect, useState, useCallback } from 'react'; import { ArrowDown } from 'lucide-react'; import { ChatMessage } from './chat-message'; import { ChatInput } from './chat-input'; import { useSwiftStore } from '@/stores/swift-store'; import { cn } from '@/lib/utils'; export function ChatPanel() { const chatMessages = useSwiftStore((s) => s.chatMessages); // Refs for scrolling const scrollContainerRef = useRef(null); const messagesEndRef = useRef(null); // Scroll-lock state const [isScrolledUp, setIsScrolledUp] = useState(false); const [showScrollButton, setShowScrollButton] = useState(false); const hasMessages = chatMessages.length > 0; // Scroll to bottom function const scrollToBottom = useCallback((behavior: ScrollBehavior = 'smooth') => { messagesEndRef.current?.scrollIntoView({ behavior }); setIsScrolledUp(false); setShowScrollButton(false); }, []); // Detect scroll position (scroll-lock detection) const handleScroll = useCallback(() => { if (!scrollContainerRef.current) return; const { scrollTop, scrollHeight, clientHeight } = scrollContainerRef.current; const isNearBottom = scrollHeight - scrollTop - clientHeight < 100; // 100px threshold setIsScrolledUp(!isNearBottom); // Show scroll button only if scrolled up AND there are messages setShowScrollButton(!isNearBottom && hasMessages); }, [hasMessages]); // Auto-scroll to latest message when new message arrives (unless user scrolled up) useEffect(() => { if (!isScrolledUp && hasMessages) { scrollToBottom('smooth'); } }, [chatMessages.length, isScrolledUp, hasMessages, scrollToBottom]); // Initial scroll to bottom on mount useEffect(() => { scrollToBottom('auto'); }, [scrollToBottom]); return (
{/* Chat messages area - scrollable */}
{hasMessages ? (
{chatMessages.map((message) => ( ))} {/* Invisible element to scroll to */}
) : (
💬

Welkom bij Swift Medical Scribe

Typ of spreek wat je wilt doen...

Voorbeelden:

• “Notitie voor Jan: medicatie gegeven”

• “Zoek Marie van den Berg”

• “Maak overdracht voor deze dienst”

)} {/* Scroll to bottom button */} {showScrollButton && ( )}
{/* Chat input */} { // Handle send (AI response will be added in E3) console.log('User sent:', message); }} />
); }