import { useEffect, useRef, useState } from "react" import { AnimatePresence, motion } from "motion/react" import { Bot, Handshake, ShieldCheck } from "lucide-react" import { SlateRenderer } from "@/components/ui/slate-renderer" import { EASE_OUT_EXPO } from "@/lib/motion" import type { DialogueStep } from "@/types" /** 스크롤 연동 sticky 협상 데모 — 스크롤 진행률에 따라 대화가 쌓이고 단가가 내려간다. */ export function NegotiationConsole() { // -1 = 아직 섹션 진입 전(온보딩 가이드 표시) const [activeStep, setActiveStep] = useState(-1) const [animatedPrice, setAnimatedPrice] = useState(1200) const sectionRef = useRef(null) const chatContainerRef = useRef(null) // 섹션 내 스크롤 진행률 → 대화 스텝 매핑 useEffect(() => { const handleScroll = () => { if (!sectionRef.current) return const rect = sectionRef.current.getBoundingClientRect() const totalScrollable = rect.height - window.innerHeight if (totalScrollable <= 0) return const scrolled = -rect.top if (scrolled < 0) { setActiveStep(-1) return } const clampedRatio = Math.max(0, Math.min(scrolled / totalScrollable, 0.99)) setActiveStep(Math.floor(clampedRatio * NEGOTIATION_STEPS.length)) } window.addEventListener("scroll", handleScroll, { passive: true }) handleScroll() return () => window.removeEventListener("scroll", handleScroll) }, []) // 단가 오도미터 애니메이션 (500ms ease-out) useEffect(() => { const targetPrice = activeStep === -1 ? 1200 : NEGOTIATION_STEPS[activeStep].price if (animatedPrice === targetPrice) return const start = animatedPrice const duration = 500 const startTime = performance.now() const animate = (currentTime: number) => { const progress = Math.min((currentTime - startTime) / duration, 1) const easeProgress = progress * (2 - progress) setAnimatedPrice(Math.round(start + (targetPrice - start) * easeProgress)) if (progress < 1) requestAnimationFrame(animate) } requestAnimationFrame(animate) }, [activeStep]) // 새 말풍선이 붙으면 채팅 영역을 바닥으로 스크롤 useEffect(() => { chatContainerRef.current?.scrollTo({ top: chatContainerRef.current.scrollHeight, behavior: "smooth" }) }, [activeStep]) return (
{/* 좌: 실시간 단가 패널 */}
실시간 협상 단가
₩ {animatedPrice.toLocaleString()}
{activeStep !== -1 && NEGOTIATION_STEPS[activeStep]?.badge && ( {NEGOTIATION_STEPS[activeStep].badge} )}
{/* 우: 대화 말풍선 (파트너 좌 / 봇 우) */}
{activeStep === -1 ? (

실시간 AI 협상 대화

화면을 스크롤하면 실시간 단가 조율 대화가 시작됩니다.

마우스 휠 스크롤하기 ↓
) : (
{NEGOTIATION_STEPS.slice(0, activeStep + 1).map((item, idx) => { const isBot = item.editorNodes[0].sender === "bot" return (
{isBot ? ( <> NEGOTIUM BOT ) : ( <> PARTNER )}
) })}
)}
) } // 데모 대화 시나리오 — 1,200원 제시에서 1,050원 낙찰까지 6스텝 const NEGOTIATION_STEPS: DialogueStep[] = [ { step: 1, price: 1200, editorNodes: [ { type: 'paragraph', sender: 'supplier', children: [ { text: '협력사', bold: true }, { text: ' : ' }, { text: '현재 글로벌 원재료 상승 요인으로 제안할 수 있는 최선의 단가는 1,200원입니다. 이 이하로는 마진 확보가 어렵습니다.' }, ], }, ], }, { step: 2, price: 1150, editorNodes: [ { type: 'paragraph', sender: 'bot', children: [ { text: 'AI 흥정 봇', bold: true }, { text: ' : ' }, { text: '제시해주신 1,200원은 당사 타 유사 품목 이력 및 시중 원가 인덱스 데이터 대비 약 8.3% 높게 책정되어 있습니다. ', italic: true }, { text: '상호 호혜적 장기 계약 체결을 전제로 조율가 범위를 반영해 제안해 드립니다.', code: true }, ], }, ], }, { step: 3, price: 1150, editorNodes: [ { type: 'paragraph', sender: 'supplier', children: [ { text: '협력사', bold: true }, { text: ' : ' }, { text: '제조 공정상 급격한 인하는 무리가 있으나, 상생 협력 차원에서 1,150원까지는 즉시 조정해 드릴 용의가 있습니다.' }, ], }, ], }, { step: 4, price: 1080, editorNodes: [ { type: 'paragraph', sender: 'bot', children: [ { text: 'AI 흥정 봇', bold: true }, { text: ' : ' }, { text: '적극적인 협조에 감사드립니다. 만약 연간 최소 발주 수량을 보증하고 공급망 일정을 다소 유연화해주신다면, 목표가인 1,080원 선까지 맞출 수 있을까요?', italic: true }, ], }, ], }, { step: 5, price: 1050, editorNodes: [ { type: 'paragraph', sender: 'supplier', children: [ { text: '협력사', bold: true }, { text: ' : ' }, { text: '좋습니다. 제안하신 연간 개런티 확보 및 대금 현금 결제 기한 단축을 승인해 주시는 조건으로, ' }, { text: '최종 조율가 1,050원으로 맞춰서 계약을 체결하겠습니다.', bold: true }, ], }, ], }, { step: 6, price: 1050, badge: '낙찰 성공 · 12.5% 예산 절감', editorNodes: [ { type: 'paragraph', sender: 'bot', children: [ { text: 'AI 흥정 봇', bold: true }, { text: ' : ' }, { text: '최종 합의 접수 완료 — 가이드 상한가(1,200원) 대비 합의 낙찰가 1,050원으로 최종 계약 승인 처리 완료되었습니다. ', bold: true }, { text: '본 흥정 마일스톤 및 단가 타결 히스토리는 사내 투명성 보증을 위해 보존 기록됩니다.', code: true }, ], }, ], }, ]