Update components/chatbot.tsx

This commit is contained in:
kleap-admin 2026-01-16 17:09:41 +00:00
parent d34d79730b
commit ef572a873d
1 changed files with 94 additions and 0 deletions

94
components/chatbot.tsx Normal file
View File

@ -0,0 +1,94 @@
"use client";
import { useState } from "react";
import { Button } from "@/components/ui/button";
import { Card } from "@/components/ui/card";
import { MessageCircle, X, Send } from "lucide-react";
import { motion, AnimatePresence } from "framer-motion";
export function Chatbot() {
const [isOpen, setIsOpen] = useState(false);
const [messages, setMessages] = useState([
{ role: "bot", text: "Hi! I'm the Apex Assistant. I'm powered by AI to help you while I'm out detailing cars. How can I help you today?" }
]);
const [input, setInput] = useState("");
const handleSend = () => {
if (!input.trim()) return;
const newMessages = [...messages, { role: "user", text: input }];
setMessages(newMessages);
setInput("");
// Simple automated responses
setTimeout(() => {
let response = "I'm not sure about that, but you can book a detail and I'll answer all your questions in person!";
const lowerInput = input.toLowerCase();
if (lowerInput.includes("price") || lowerInput.includes("cost")) response = "Our prices vary by car size: Full Interior starts at $80, Exterior Hand Wash at $40, and Full Detail at $110!";
if (lowerInput.includes("where") || lowerInput.includes("location")) response = "I'm based in Cedar Rapids and I'm mobile—I come right to your driveway!";
if (lowerInput.includes("equipment") || lowerInput.includes("tools")) response = "I use professional-grade pressure washers, steam cleaners, and industrial vacuums to get that better-than-pro finish.";
if (lowerInput.includes("who") || lowerInput.includes("old")) response = "I'm a 13-year-old entrepreneur saving up for my first car and college!";
if (lowerInput.includes("book") || lowerInput.includes("schedule")) response = "You can book directly on our site using the 'Book a Detail' button. We accept Stripe for secure payments!";
setMessages([...newMessages, { role: "bot", text: response }]);
}, 1000);
};
return (
<div className="fixed bottom-6 right-6 z-50">
<AnimatePresence>
{!isOpen ? (
<motion.div
initial={{ scale: 0, opacity: 0 }}
animate={{ scale: 1, opacity: 1 }}
exit={{ scale: 0, opacity: 0 }}
>
<Button onClick={() => setIsOpen(true)} className="rounded-full w-14 h-14 shadow-xl bg-blue-600 hover:bg-blue-700">
<MessageCircle className="w-6 h-6 text-white" />
</Button>
</motion.div>
) : (
<motion.div
initial={{ y: 100, opacity: 0 }}
animate={{ y: 0, opacity: 1 }}
exit={{ y: 100, opacity: 0 }}
>
<Card className="w-80 h-96 flex flex-col shadow-2xl border-neutral-200 dark:border-neutral-800 overflow-hidden">
<div className="p-4 bg-blue-600 text-white flex justify-between items-center">
<div className="flex items-center gap-2">
<div className="w-2 h-2 bg-green-400 rounded-full animate-pulse" />
<span className="font-bold">Apex AI Assistant</span>
</div>
<X className="w-4 h-4 cursor-pointer" onClick={() => setIsOpen(false)} />
</div>
<div className="flex-1 overflow-y-auto p-4 space-y-4 bg-white dark:bg-neutral-950">
{messages.map((m, i) => (
<motion.div
key={i}
initial={{ opacity: 0, x: m.role === "user" ? 20 : -20 }}
animate={{ opacity: 1, x: 0 }}
className={`flex ${m.role === "user" ? "justify-end" : "justify-start"}`}
>
<div className={`max-w-[80%] p-3 rounded-2xl text-sm ${m.role === "user" ? "bg-blue-600 text-white rounded-tr-none" : "bg-neutral-100 dark:bg-neutral-800 rounded-tl-none"}`}>
{m.text}
</div>
</motion.div>
))}
</div>
<div className="p-4 border-t bg-neutral-50 dark:bg-neutral-900 flex gap-2">
<input
className="flex-1 bg-transparent text-sm outline-none"
placeholder="Ask about pricing, equipment..."
value={input}
onChange={(e) => (setInput(e.target.value))}
onKeyDown={(e) => e.key === "Enter" && handleSend()}
/>
<Button size="icon" variant="ghost" className="h-8 w-8 text-blue-600" onClick={handleSend}>
<Send className="w-4 h-4" />
</Button>
</div>
</Card>
</motion.div>
)}
</AnimatePresence>
</div>
);
}