ishaq101's picture
Feat: Integrate STT and TTS, Audio Buffer
8172156
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>
);
}