import { useEffect, useRef, memo } from 'react' import { cn } from '@/lib' import { useChatStore } from '@/features/chat/stores/useChatStore' import type { ChatMessage as ChatMessageType } from '@/features/chat/types' import { Indicator } from '@/features/chat/components/templates/Indicator' import { Summary } from '@/features/chat/components/templates/Summary' import { BidSummary } from '@/features/chat/components/templates/BidSummary' import { RejectRSP } from '@/features/chat/components/templates/RejectRSP' import { RejectCM } from '@/features/chat/components/templates/RejectCM' export function ChatMessage() { return (
{/* pt-[64px]: 첫 메시지를 우측 협상절차 카드 상단과 맞추되, 스크롤 시 여백도 함께 밀려 올라가도록 스크롤 컨테이너 안쪽에 둔다 */}
) } function ChatList() { const bottomRef = useRef(null) const chats = useChatStore((s) => s.messages) const isLoading = useChatStore((s) => s.isLoading) // 메시지 추가/타이핑 표시 시 항상 맨 아래로 스크롤 useEffect(() => { bottomRef.current?.scrollIntoView({ behavior: 'smooth' }) }, [chats, isLoading]) if (!chats || chats.length === 0) { return (

채팅 내역이 없습니다.

) } return (
{chats.map((message, index) => ( ))} {isLoading && }
) } // agent 응답을 기다리는 동안(협상 중) 대화 흐름에 표시하는 타이핑 인디케이터. function TypingBubble() { return (
) } const MessageItem = memo(function MessageItem({ message, isFirst, messages, currentIndex, }: { message: ChatMessageType isFirst: boolean messages: ChatMessageType[] currentIndex: number }) { const isBot = message.sender === 'bot' // 직전이 reject 폼이면 사용자 답변은 숨기고 구분선만 표시 if (!isBot && currentIndex > 0) { const prev = messages[currentIndex - 1] if (prev?.bot_chat_type === 'rejectRSP' || prev?.bot_chat_type === 'rejectCM') { return ( <>
) } } return
{isBot ? : }
}) const BotMessage = memo(function BotMessage({ message, isFirst }: { message: ChatMessageType; isFirst?: boolean }) { return (
{message.script || ''}
{message.bot_chat_type === 'indicator' && message.indicator_value != null && ( )} {message.bot_chat_type === 'summaryRSP' && message.summary && } {message.bot_chat_type === 'summaryCM' && message.summary && ( )} {message.bot_chat_type === 'rejectRSP' && } {message.bot_chat_type === 'rejectCM' && }
) }) const UserMessage = memo(function UserMessage({ text }: { text: string }) { return ( <>
{text}
) })