Spaces:
Sleeping
Sleeping
| import { useEffect, useRef } from "react"; | |
| import { motion } from "motion/react"; | |
| import { Bot } from "lucide-react"; | |
| import type { Message } from "./types"; | |
| import MessageBubble from "./MessageBubble"; | |
| import maintivalogo from "@/assets/maintiva-logo.jpg"; | |
| const WELCOME_FEATURES = [ | |
| { emoji: "π", title: "Data Analysis", desc: "Get actionable insights and root cause" }, | |
| { emoji: "π§ ", title: "Knowledge Based", desc: "Handbook, SOP, Documents, or Databases" }, | |
| { emoji: "π€", title: "Voice Mode", desc: "Ask questions using your voice" }, | |
| { emoji: "π¬", title: "Natural language", desc: "Natural interaction" }, | |
| ]; | |
| interface ChatWindowProps { | |
| messages: Message[]; | |
| isLoading: boolean; | |
| streamingMsgId: string | null; | |
| userName?: string; | |
| } | |
| export default function ChatWindow({ messages, isLoading, streamingMsgId, userName }: ChatWindowProps) { | |
| const firstName = userName?.split(" ")[0] ?? ""; | |
| const bottomRef = useRef<HTMLDivElement>(null); | |
| useEffect(() => { | |
| bottomRef.current?.scrollIntoView({ behavior: "smooth" }); | |
| }, [messages, isLoading]); | |
| if (messages.length === 0 && !isLoading) { | |
| return ( | |
| <div className="flex-1 overflow-y-auto flex flex-col items-center justify-center gap-6 px-4 sm:px-6 xl:px-8 pb-4"> | |
| <motion.div | |
| className="flex flex-col items-center gap-4 xl:gap-6 w-full max-w-sm sm:max-w-md xl:max-w-2xl" | |
| initial={{ opacity: 0, scale: 0.9 }} | |
| animate={{ opacity: 1, scale: 1 }} | |
| transition={{ duration: 0.5, ease: "easeOut" }} | |
| > | |
| <div className="w-20 h-20 xl:w-28 xl:h-28 rounded-3xl bg-gradient-to-br from-brand-green-light to-brand-green shadow-xl shadow-brand-green/25 flex items-center justify-center"> | |
| <Bot className="h-10 w-10 xl:h-14 xl:w-14 text-white" /> | |
| </div> | |
| <div className="text-center"> | |
| <h2 className="text-2xl xl:text-4xl font-bold text-neutral-900"> | |
| {firstName ? `Hi, ${firstName}! π` : "Hello! π"} | |
| </h2> | |
| <p className="mt-2 text-neutral-500 text-sm xl:text-base leading-relaxed"> | |
| Welcome to{" "} | |
| <span className="inline-flex items-center gap-1 font-bold text-neutral-800 align-middle"> | |
| <img src={maintivalogo} alt="Maintiva" className="h-4 w-4 xl:h-5 xl:w-5 rounded-sm object-contain" /> | |
| Maintiva Agent | |
| </span>{" "} | |
| Turn your data into fast, intelligent decisions. Instantly uncover root causes, spot hidden patterns, and resolve issues before they escalate. | |
| </p> | |
| </div> | |
| <div className="grid grid-cols-2 xl:grid-cols-4 gap-3 xl:gap-4 w-full mt-2"> | |
| {WELCOME_FEATURES.map((f) => ( | |
| <div | |
| key={f.title} | |
| className="flex flex-col gap-1 xl:gap-2 p-3 xl:p-4 rounded-xl bg-white border border-neutral-100 shadow-sm text-left" | |
| > | |
| <span className="text-xl xl:text-3xl">{f.emoji}</span> | |
| <span className="text-sm xl:text-base font-semibold text-neutral-800">{f.title}</span> | |
| <span className="text-xs xl:text-sm text-neutral-400">{f.desc}</span> | |
| </div> | |
| ))} | |
| </div> | |
| </motion.div> | |
| </div> | |
| ); | |
| } | |
| return ( | |
| <div className="flex-1 overflow-y-auto py-4 space-y-1"> | |
| {/* Constrain message width on large/seminar screens */} | |
| <div className="w-full max-w-4xl xl:max-w-5xl mx-auto"> | |
| {messages.map((message) => ( | |
| <MessageBubble | |
| key={message.id} | |
| message={message} | |
| isStreamingPlaceholder={streamingMsgId === message.id} | |
| /> | |
| ))} | |
| <div ref={bottomRef} /> | |
| </div> | |
| </div> | |
| ); | |
| } | |