UNPKG

@jutech-devs/agent-sdk

Version:

Modern embeddable AI agent chat widget with voice support and payment integration

1,359 lines (1,345 loc) 92 kB
"use client" // src/AgentWidget.tsx import { useState as useState6, useEffect as useEffect5 } from "react"; // src/components/ChatBubble.tsx import { jsx, jsxs } from "react/jsx-runtime"; function ChatBubble({ isOpen, onClick, primaryColor = "#3b82f6", unreadCount = 0 }) { return /* @__PURE__ */ jsxs( "button", { onClick, style: { position: "fixed", bottom: "24px", right: "24px", width: "64px", height: "64px", borderRadius: "50%", background: `linear-gradient(135deg, ${primaryColor}, ${primaryColor}dd)`, border: "none", cursor: "pointer", display: "flex", alignItems: "center", justifyContent: "center", boxShadow: "0 8px 25px rgba(102, 126, 234, 0.35), 0 3px 10px rgba(0, 0, 0, 0.1)", transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)", zIndex: 999999 }, "aria-label": "Open chat", children: [ unreadCount > 0 && /* @__PURE__ */ jsx("div", { style: { position: "absolute", top: "-8px", right: "-8px", width: "24px", height: "24px", background: "linear-gradient(135deg, #ef4444, #dc2626)", color: "white", borderRadius: "50%", display: "flex", alignItems: "center", justifyContent: "center", fontSize: "12px", fontWeight: "bold", border: "2px solid white", boxShadow: "0 4px 12px rgba(239, 68, 68, 0.4)" }, children: unreadCount > 9 ? "9+" : unreadCount }), /* @__PURE__ */ jsx( "svg", { width: "24", height: "24", fill: "none", stroke: "white", viewBox: "0 0 24 24", style: { filter: "drop-shadow(0 1px 2px rgba(0, 0, 0, 0.2))" }, children: /* @__PURE__ */ jsx( "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2.5, d: "M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" } ) } ) ] } ); } // src/components/ChatWindow.tsx import { useState as useState2, useRef as useRef2, useEffect as useEffect2 } from "react"; // src/components/MessageList.tsx import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime"; var messageStyles = ` @keyframes fade-in { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } .animate-fade-in { animation: fade-in 0.3s ease-out; } `; if (typeof document !== "undefined") { const styleSheet = document.createElement("style"); styleSheet.textContent = messageStyles; document.head.appendChild(styleSheet); } function MessageList({ messages, primaryColor }) { return /* @__PURE__ */ jsx2("div", { className: "space-y-4", children: messages.map((message, index) => /* @__PURE__ */ jsxs2( "div", { className: `flex ${message.role === "user" ? "justify-end" : "justify-start"} animate-fade-in`, style: { animationDelay: `${index * 100}ms` }, children: [ message.role === "assistant" && /* @__PURE__ */ jsx2("div", { className: "flex-shrink-0 mr-3", children: /* @__PURE__ */ jsx2( "div", { className: "w-8 h-8 rounded-full flex items-center justify-center shadow-md", style: { background: `linear-gradient(135deg, ${primaryColor}, ${primaryColor}dd)` }, children: /* @__PURE__ */ jsx2("svg", { className: "w-4 h-4 text-white", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx2("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" }) }) } ) }), /* @__PURE__ */ jsx2( "div", { className: `max-w-[280px] rounded-2xl px-4 py-3 text-sm shadow-lg backdrop-blur-sm transition-all duration-200 hover:shadow-xl ${message.role === "user" ? "text-white rounded-br-md" : "bg-white/90 text-gray-800 rounded-bl-md border border-gray-200/50"}`, style: { background: message.role === "user" ? `linear-gradient(135deg, ${primaryColor}, ${primaryColor}dd)` : void 0, boxShadow: message.role === "user" ? `0 8px 25px -8px ${primaryColor}40` : "0 4px 20px rgba(0,0,0,0.08)" }, children: message.content || (message.isStreaming ? /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2", children: [ /* @__PURE__ */ jsxs2("div", { className: "flex space-x-1", children: [ /* @__PURE__ */ jsx2( "div", { className: "w-2 h-2 bg-gray-400 rounded-full animate-bounce", style: { animationDelay: "0ms" } } ), /* @__PURE__ */ jsx2( "div", { className: "w-2 h-2 bg-gray-400 rounded-full animate-bounce", style: { animationDelay: "150ms" } } ), /* @__PURE__ */ jsx2( "div", { className: "w-2 h-2 bg-gray-400 rounded-full animate-bounce", style: { animationDelay: "300ms" } } ) ] }), /* @__PURE__ */ jsx2("span", { className: "text-xs text-gray-500", children: "AI is typing..." }) ] }) : /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2", children: [ /* @__PURE__ */ jsxs2("div", { className: "flex space-x-1", children: [ /* @__PURE__ */ jsx2("div", { className: "w-2 h-2 bg-gray-400 rounded-full animate-pulse" }), /* @__PURE__ */ jsx2("div", { className: "w-2 h-2 bg-gray-400 rounded-full animate-pulse", style: { animationDelay: "0.5s" } }), /* @__PURE__ */ jsx2("div", { className: "w-2 h-2 bg-gray-400 rounded-full animate-pulse", style: { animationDelay: "1s" } }) ] }), /* @__PURE__ */ jsx2("span", { className: "text-xs text-gray-500", children: "Thinking..." }) ] })) } ), message.role === "user" && /* @__PURE__ */ jsx2("div", { className: "flex-shrink-0 ml-3", children: /* @__PURE__ */ jsx2("div", { className: "w-8 h-8 rounded-full bg-gradient-to-br from-gray-400 to-gray-600 flex items-center justify-center shadow-md", children: /* @__PURE__ */ jsx2("svg", { className: "w-4 h-4 text-white", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx2("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z" }) }) }) }) ] }, message.id )) }); } // src/components/VoiceButton.tsx import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime"; function VoiceButton({ isListening, isSupported, onToggle, primaryColor }) { if (!isSupported) return null; return /* @__PURE__ */ jsx3( "button", { onClick: onToggle, style: { background: isListening ? primaryColor : "rgba(255, 255, 255, 0.1)", border: `1px solid ${isListening ? "white" : "rgba(255, 255, 255, 0.3)"}`, borderRadius: "50%", width: "40px", height: "40px", display: "flex", alignItems: "center", justifyContent: "center", cursor: "pointer", transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)", backdropFilter: "blur(10px)", boxShadow: isListening ? `0 0 20px ${primaryColor}40, 0 4px 16px rgba(0, 0, 0, 0.1)` : "0 4px 16px rgba(0, 0, 0, 0.1)", animation: isListening ? "pulse 2s infinite" : "none" }, title: isListening ? "Stop listening" : "Start voice input", children: /* @__PURE__ */ jsxs3( "svg", { width: "18", height: "18", fill: "none", stroke: "white", viewBox: "0 0 24 24", style: { filter: isListening ? "drop-shadow(0 0 4px rgba(255,255,255,0.5))" : "none" }, children: [ /* @__PURE__ */ jsx3( "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z" } ), /* @__PURE__ */ jsx3( "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 10v2a7 7 0 0 1-14 0v-2" } ), /* @__PURE__ */ jsx3( "line", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, x1: "12", y1: "19", x2: "12", y2: "23" } ), /* @__PURE__ */ jsx3( "line", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, x1: "8", y1: "23", x2: "16", y2: "23" } ) ] } ) } ); } // src/hooks/useVoice.ts import { useState, useCallback, useRef, useEffect } from "react"; function useVoice({ onTranscript, enabled = true }) { const [isListening, setIsListening] = useState(false); const [isSupported, setIsSupported] = useState(false); const recognitionRef = useRef(null); useEffect(() => { if (typeof window !== "undefined") { const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition; setIsSupported(!!SpeechRecognition && enabled); if (SpeechRecognition && enabled) { const recognition = new SpeechRecognition(); recognition.continuous = false; recognition.interimResults = false; recognition.lang = "en-US"; recognition.onstart = () => { setIsListening(true); }; recognition.onresult = (event) => { const transcript = event.results[0]?.transcript; if (transcript) { onTranscript(transcript); } }; recognition.onend = () => { setIsListening(false); }; recognition.onerror = (event) => { console.error("Speech recognition error:", event.error); setIsListening(false); }; recognitionRef.current = recognition; } } return () => { if (recognitionRef.current) { recognitionRef.current.abort(); } }; }, [onTranscript, enabled]); const startListening = useCallback(() => { if (recognitionRef.current && !isListening) { try { recognitionRef.current.start(); } catch (error) { console.error("Failed to start speech recognition:", error); } } }, [isListening]); const stopListening = useCallback(() => { if (recognitionRef.current && isListening) { recognitionRef.current.stop(); } }, [isListening]); const speak = useCallback((text) => { if (typeof window !== "undefined" && window.speechSynthesis && enabled) { window.speechSynthesis.cancel(); const utterance = new SpeechSynthesisUtterance(text); utterance.rate = 0.9; utterance.pitch = 1; utterance.volume = 0.8; window.speechSynthesis.speak(utterance); } }, [enabled]); return { isListening, isSupported, startListening, stopListening, speak }; } // src/components/MessageInput.tsx import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime"; function MessageInput({ value, onChange, onSend, isLoading, placeholder, primaryColor, voiceEnabled = false }) { const { isListening, isSupported, startListening, stopListening } = useVoice({ onTranscript: (text) => { onChange(value + (value ? " " : "") + text); }, enabled: voiceEnabled }); const handleKeyPress = (e) => { if (e.key === "Enter" && !e.shiftKey) { e.preventDefault(); onSend(); } }; const handleVoiceToggle = () => { if (isListening) { stopListening(); } else { startListening(); } }; return /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-3 p-4 bg-gradient-to-t from-gray-50/80 to-transparent backdrop-blur-sm", children: [ /* @__PURE__ */ jsxs4("div", { className: "flex-1 relative", children: [ /* @__PURE__ */ jsx4( "input", { type: "text", value, onChange: (e) => onChange(e.target.value), onKeyPress: handleKeyPress, placeholder, disabled: isLoading, className: "w-full rounded-2xl border-0 bg-white/90 backdrop-blur-sm px-4 py-3 pr-12 text-sm placeholder-gray-500 text-gray-900 focus:outline-none focus:ring-2 focus:ring-opacity-50 disabled:opacity-50 shadow-lg transition-all duration-200", style: { boxShadow: `0 4px 20px rgba(0,0,0,0.08), 0 0 0 1px ${primaryColor}20`, focusRingColor: `${primaryColor}80` } } ), value.trim() && /* @__PURE__ */ jsx4("div", { className: "absolute right-4 top-1/2 transform -translate-y-1/2", children: /* @__PURE__ */ jsx4("div", { className: "w-2 h-2 bg-green-500 rounded-full animate-pulse" }) }) ] }), voiceEnabled && /* @__PURE__ */ jsx4( VoiceButton, { isListening, isSupported, onToggle: handleVoiceToggle, primaryColor } ), /* @__PURE__ */ jsx4( "button", { onClick: onSend, disabled: !value.trim() || isLoading, className: `flex h-12 w-12 items-center justify-center rounded-2xl text-white transition-all duration-200 transform ${!value.trim() || isLoading ? "bg-gray-300 cursor-not-allowed scale-95" : "hover:scale-105 active:scale-95 shadow-lg hover:shadow-xl"}`, style: { background: !value.trim() || isLoading ? void 0 : `linear-gradient(135deg, ${primaryColor}, ${primaryColor}dd)`, boxShadow: !value.trim() || isLoading ? void 0 : `0 8px 25px -8px ${primaryColor}60` }, "aria-label": "Send message", children: isLoading ? /* @__PURE__ */ jsx4("div", { className: "h-5 w-5 animate-spin rounded-full border-2 border-white border-t-transparent" }) : /* @__PURE__ */ jsx4("svg", { className: "h-5 w-5 transition-transform duration-200", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx4("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2.5, d: "M12 19l9 2-9-18-9 18 9-2zm0 0v-8" }) }) } ) ] }); } // src/components/ProductCard.tsx import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime"; function ProductCard({ product, onBuyNow, primaryColor }) { return /* @__PURE__ */ jsxs5( "div", { style: { border: "1px solid #e5e7eb", borderRadius: "8px", padding: "16px", margin: "8px 0", backgroundColor: "#ffffff" }, children: [ (product.imageUrl || product.images?.[0]) && /* @__PURE__ */ jsx5( "img", { src: product.imageUrl || product.images[0], alt: product.name, style: { width: "100%", height: "120px", objectFit: "cover", borderRadius: "6px", marginBottom: "12px" } } ), /* @__PURE__ */ jsx5( "h3", { style: { fontSize: "16px", fontWeight: "600", margin: "0 0 8px 0", color: "#1f2937" }, children: product.name } ), /* @__PURE__ */ jsx5( "p", { style: { fontSize: "14px", color: "#6b7280", margin: "0 0 12px 0", lineHeight: "1.4" }, children: product.description } ), /* @__PURE__ */ jsxs5( "div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center" }, children: [ /* @__PURE__ */ jsxs5( "span", { style: { fontSize: "18px", fontWeight: "700", color: primaryColor }, children: [ product.currency, " ", product.price ] } ), /* @__PURE__ */ jsx5( "button", { onClick: () => onBuyNow(product), style: { backgroundColor: primaryColor, color: "white", border: "none", borderRadius: "6px", padding: "8px 16px", fontSize: "14px", fontWeight: "500", cursor: "pointer" }, children: "Buy Now" } ) ] } ) ] } ); } // src/components/OrdersView.tsx import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime"; function OrdersView({ orders, onClose, onPayOrder }) { const formatDate = (dateString) => { return new Date(dateString).toLocaleDateString("en-US", { year: "numeric", month: "short", day: "numeric", hour: "2-digit", minute: "2-digit" }); }; const getStatusColor = (status) => { switch (status) { case "completed": return "#10b981"; case "processing": return "#3b82f6"; case "shipped": return "#8b5cf6"; case "delivered": return "#059669"; case "pending": return "#f59e0b"; case "failed": return "#ef4444"; case "cancelled": return "#6b7280"; default: return "#6b7280"; } }; return /* @__PURE__ */ jsxs6("div", { style: { padding: "20px" }, children: [ /* @__PURE__ */ jsxs6("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: "20px" }, children: [ /* @__PURE__ */ jsx6("h3", { style: { fontSize: "18px", fontWeight: "600", margin: 0, color: "#1f2937" }, children: "My Orders" }), /* @__PURE__ */ jsx6( "button", { onClick: onClose, style: { background: "none", border: "none", fontSize: "24px", cursor: "pointer", color: "#6b7280", padding: "4px" }, children: "\xD7" } ) ] }), orders.length === 0 ? /* @__PURE__ */ jsx6("div", { style: { textAlign: "center", padding: "40px 20px", color: "#6b7280" }, children: /* @__PURE__ */ jsx6("p", { children: "No orders found" }) }) : /* @__PURE__ */ jsx6("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: orders.map((order) => /* @__PURE__ */ jsx6( "div", { style: { border: "1px solid #e5e7eb", borderRadius: "8px", padding: "16px", backgroundColor: "#ffffff" }, children: /* @__PURE__ */ jsxs6("div", { style: { display: "flex", gap: "12px" }, children: [ order.productId && order.productId.imageUrl && /* @__PURE__ */ jsx6( "img", { src: order.productId.imageUrl, alt: order.productId.name, style: { width: "60px", height: "60px", objectFit: "cover", borderRadius: "6px" } } ), /* @__PURE__ */ jsxs6("div", { style: { flex: 1 }, children: [ /* @__PURE__ */ jsx6("h4", { style: { fontSize: "16px", fontWeight: "600", margin: "0 0 4px 0", color: "#1f2937" }, children: order.productId ? order.productId.name : order.itemName || "Service Order" }), /* @__PURE__ */ jsx6("p", { style: { fontSize: "14px", color: "#6b7280", margin: "0 0 8px 0" }, children: order.productId ? order.productId.description : "Service booking order" }), /* @__PURE__ */ jsxs6("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center" }, children: [ /* @__PURE__ */ jsxs6("span", { style: { fontSize: "16px", fontWeight: "600", color: "#1f2937" }, children: [ order.currency, " ", order.amount ] }), /* @__PURE__ */ jsx6("span", { style: { fontSize: "12px", padding: "4px 8px", borderRadius: "12px", backgroundColor: `${getStatusColor(order.status)}20`, color: getStatusColor(order.status), fontWeight: "500", textTransform: "capitalize" }, children: order.status }) ] }), /* @__PURE__ */ jsx6("p", { style: { fontSize: "12px", color: "#9ca3af", margin: "8px 0 0 0" }, children: formatDate(order.createdAt) }), order.trackingNumber && /* @__PURE__ */ jsxs6("p", { style: { fontSize: "12px", color: "#3b82f6", margin: "4px 0 0 0", fontWeight: "500" }, children: [ "Tracking: ", order.trackingNumber ] }), order.deliveryAddress && /* @__PURE__ */ jsxs6("p", { style: { fontSize: "12px", color: "#6b7280", margin: "4px 0 0 0" }, children: [ order.deliveryAddress.street, ", ", order.deliveryAddress.city, ", ", order.deliveryAddress.state, " ", order.deliveryAddress.zipCode ] }), order.status === "pending" && onPayOrder && /* @__PURE__ */ jsx6( "button", { onClick: () => onPayOrder(order), style: { marginTop: "8px", padding: "6px 12px", backgroundColor: "#3b82f6", color: "white", border: "none", borderRadius: "4px", fontSize: "12px", fontWeight: "500", cursor: "pointer" }, children: "Pay Now" } ) ] }) ] }) }, order._id )) }) ] }); } // src/components/ServiceCard.tsx import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime"; function ServiceCard({ service, onBook }) { return /* @__PURE__ */ jsxs7( "div", { style: { border: "1px solid #e5e7eb", borderRadius: "8px", padding: "16px", backgroundColor: "white", boxShadow: "0 1px 3px rgba(0, 0, 0, 0.1)" }, children: [ service.imageUrl && /* @__PURE__ */ jsx7( "img", { src: service.imageUrl, alt: service.name, style: { width: "100%", height: "120px", objectFit: "cover", borderRadius: "6px", marginBottom: "12px" } } ), /* @__PURE__ */ jsx7("h4", { style: { fontSize: "16px", fontWeight: "600", margin: "0 0 8px 0" }, children: service.name }), /* @__PURE__ */ jsx7("p", { style: { fontSize: "14px", color: "#6b7280", margin: "0 0 12px 0", lineHeight: "1.4" }, children: service.description }), /* @__PURE__ */ jsxs7("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center" }, children: [ /* @__PURE__ */ jsxs7("div", { children: [ /* @__PURE__ */ jsxs7("span", { style: { fontSize: "18px", fontWeight: "700", color: "#1f2937" }, children: [ service.currency, " ", service.price ] }), service.duration && /* @__PURE__ */ jsxs7("div", { style: { fontSize: "12px", color: "#6b7280" }, children: [ service.duration, " minutes" ] }) ] }), /* @__PURE__ */ jsx7( "button", { onClick: () => onBook(service), style: { padding: "8px 16px", backgroundColor: "#3b82f6", color: "white", border: "none", borderRadius: "6px", fontSize: "14px", fontWeight: "500", cursor: "pointer" }, children: "Book Now" } ) ] }) ] } ); } // src/components/BookingsView.tsx import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime"; function BookingsView({ bookings, onClose }) { return /* @__PURE__ */ jsxs8("div", { style: { padding: "16px" }, children: [ /* @__PURE__ */ jsxs8("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: "16px" }, children: [ /* @__PURE__ */ jsx8("h3", { style: { fontSize: "18px", fontWeight: "600", margin: 0 }, children: "My Bookings" }), /* @__PURE__ */ jsx8( "button", { onClick: onClose, style: { background: "none", border: "none", fontSize: "20px", cursor: "pointer", color: "#6b7280" }, children: "\xD7" } ) ] }), bookings.length === 0 ? /* @__PURE__ */ jsx8("div", { style: { textAlign: "center", padding: "32px", color: "#6b7280" }, children: /* @__PURE__ */ jsx8("p", { children: "No bookings found" }) }) : /* @__PURE__ */ jsx8("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: bookings.map((booking) => /* @__PURE__ */ jsxs8( "div", { style: { border: "1px solid #e5e7eb", borderRadius: "8px", padding: "12px", backgroundColor: "#f9fafb" }, children: [ /* @__PURE__ */ jsxs8("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "start", marginBottom: "8px" }, children: [ /* @__PURE__ */ jsx8("h4", { style: { fontSize: "16px", fontWeight: "600", margin: 0 }, children: booking.serviceName }), /* @__PURE__ */ jsx8( "span", { style: { padding: "2px 8px", borderRadius: "12px", fontSize: "12px", backgroundColor: booking.status === "confirmed" ? "#dcfce7" : "#fef3c7", color: booking.status === "confirmed" ? "#166534" : "#92400e" }, children: booking.status } ) ] }), /* @__PURE__ */ jsxs8("div", { style: { fontSize: "14px", color: "#6b7280", marginBottom: "4px" }, children: [ "\u{1F4C5} ", new Date(booking.date).toLocaleDateString(), " at ", booking.time ] }), booking.notes && /* @__PURE__ */ jsxs8("div", { style: { fontSize: "14px", color: "#6b7280" }, children: [ "\u{1F4DD} ", booking.notes ] }) ] }, booking._id )) }) ] }); } // src/components/ChatWindow.tsx import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime"; function ChatWindow({ isOpen, onClose, messages, isLoading, error, onSendMessage, onClearMessages, primaryColor, title, subtitle, placeholder, position, products, onBuyProduct, showProducts, onToggleProducts, voiceEnabled, orders, onToggleOrders, showOrders, onPayOrder, services, onBookService, showServices, onToggleServices, bookings, onToggleBookings, showBookings, bookingEnabled }) { const [input, setInput] = useState2(""); const messagesEndRef = useRef2(null); const scrollToBottom = () => { messagesEndRef.current?.scrollIntoView({ behavior: "smooth" }); }; useEffect2(() => { if (isOpen) { scrollToBottom(); } }, [messages, isOpen]); const handleSend = () => { if (input.trim() && !isLoading) { onSendMessage(input.trim()); setInput(""); } }; if (!isOpen) return null; return /* @__PURE__ */ jsxs9("div", { style: { position: "fixed", bottom: "96px", right: "24px", width: "400px", height: "600px", maxWidth: "calc(100vw - 48px)", maxHeight: "calc(100vh - 140px)", background: "linear-gradient(145deg, rgba(255, 255, 255, 0.98) 0%, rgba(248, 250, 252, 0.95) 100%)", backdropFilter: "blur(24px) saturate(180%)", WebkitBackdropFilter: "blur(24px) saturate(180%)", border: "1px solid rgba(255, 255, 255, 0.3)", borderRadius: "24px", boxShadow: "0 32px 80px rgba(0, 0, 0, 0.12), 0 16px 40px rgba(0, 0, 0, 0.08), 0 8px 20px rgba(0, 0, 0, 0.04), 0 0 0 1px rgba(255, 255, 255, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.6)", display: "flex", flexDirection: "column", overflow: "hidden", transformOrigin: "bottom right", animation: "slideInUp 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275)", zIndex: 999999, fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif' }, children: [ /* @__PURE__ */ jsxs9("div", { style: { padding: "24px 28px", background: `linear-gradient(135deg, ${primaryColor} 0%, ${primaryColor}dd 100%)`, color: "white", display: "flex", alignItems: "center", justifyContent: "space-between", position: "relative", overflow: "hidden", borderRadius: "24px 24px 0 0" }, children: [ /* @__PURE__ */ jsx9("div", { style: { position: "absolute", inset: 0, background: "radial-gradient(circle at 15% 15%, rgba(255,255,255,0.3) 0%, transparent 40%), radial-gradient(circle at 85% 85%, rgba(255,255,255,0.15) 0%, transparent 40%), linear-gradient(135deg, rgba(255,255,255,0.15) 0%, transparent 70%)" } }), /* @__PURE__ */ jsxs9("div", { style: { zIndex: 1 }, children: [ /* @__PURE__ */ jsx9("h3", { style: { fontSize: "20px", fontWeight: "700", margin: "0 0 6px 0", letterSpacing: "-0.02em", textShadow: "0 1px 2px rgba(0, 0, 0, 0.1)" }, children: title }), /* @__PURE__ */ jsx9("p", { style: { fontSize: "14px", opacity: 0.95, margin: 0, fontWeight: "400", letterSpacing: "-0.01em" }, children: subtitle }) ] }), /* @__PURE__ */ jsxs9("div", { style: { display: "flex", gap: "8px", zIndex: 2 }, children: [ products.length > 0 && onToggleProducts && /* @__PURE__ */ jsx9( "button", { onClick: onToggleProducts, style: { background: "rgba(255, 255, 255, 0.2)", border: "1px solid rgba(255, 255, 255, 0.3)", borderRadius: "50%", width: "36px", height: "36px", display: "flex", alignItems: "center", justifyContent: "center", cursor: "pointer", transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)", backdropFilter: "blur(10px)", boxShadow: "0 4px 16px rgba(0, 0, 0, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.4)" }, children: /* @__PURE__ */ jsx9("svg", { width: "16", height: "16", fill: "none", stroke: "white", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx9("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M16 11V7a4 4 0 00-8 0v4M5 9h14l1 12H4L5 9z" }) }) } ), products.length > 0 && onToggleOrders && /* @__PURE__ */ jsx9( "button", { onClick: onToggleOrders, style: { background: "rgba(255, 255, 255, 0.2)", border: "1px solid rgba(255, 255, 255, 0.3)", borderRadius: "50%", width: "36px", height: "36px", display: "flex", alignItems: "center", justifyContent: "center", cursor: "pointer", transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)", backdropFilter: "blur(10px)", boxShadow: "0 4px 16px rgba(0, 0, 0, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.4)" }, children: /* @__PURE__ */ jsx9("svg", { width: "16", height: "16", fill: "none", stroke: "white", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx9("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" }) }) } ), bookingEnabled && services.length > 0 && onToggleServices && /* @__PURE__ */ jsx9( "button", { onClick: onToggleServices, style: { background: "rgba(255, 255, 255, 0.2)", border: "1px solid rgba(255, 255, 255, 0.3)", borderRadius: "50%", width: "36px", height: "36px", display: "flex", alignItems: "center", justifyContent: "center", cursor: "pointer", transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)", backdropFilter: "blur(10px)", boxShadow: "0 4px 16px rgba(0, 0, 0, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.4)" }, children: /* @__PURE__ */ jsx9("svg", { width: "16", height: "16", fill: "none", stroke: "white", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx9("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M8 7V3a2 2 0 012-2h4a2 2 0 012 2v4m-6 0V6a2 2 0 012-2h4a2 2 0 012 2v1m-6 0h6m-6 0l-.5 8.5A2 2 0 0013.5 21h-3A2 2 0 018.5 15.5L8 7z" }) }) } ), bookingEnabled && onToggleBookings && /* @__PURE__ */ jsx9( "button", { onClick: onToggleBookings, style: { background: "rgba(255, 255, 255, 0.2)", border: "1px solid rgba(255, 255, 255, 0.3)", borderRadius: "50%", width: "36px", height: "36px", display: "flex", alignItems: "center", justifyContent: "center", cursor: "pointer", transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)", backdropFilter: "blur(10px)", boxShadow: "0 4px 16px rgba(0, 0, 0, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.4)" }, children: /* @__PURE__ */ jsx9("svg", { width: "16", height: "16", fill: "none", stroke: "white", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx9("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M8 7V3a2 2 0 012-2h4a2 2 0 012 2v4m-6 0V6a2 2 0 012-2h4a2 2 0 012 2v1m-6 0h6m-6 0l-.5 8.5A2 2 0 0013.5 21h-3A2 2 0 018.5 15.5L8 7z" }) }) } ), /* @__PURE__ */ jsx9( "button", { onClick: onClose, style: { background: "rgba(255, 255, 255, 0.2)", border: "1px solid rgba(255, 255, 255, 0.3)", borderRadius: "50%", width: "36px", height: "36px", display: "flex", alignItems: "center", justifyContent: "center", cursor: "pointer", transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)", zIndex: 2, backdropFilter: "blur(10px)", boxShadow: "0 4px 16px rgba(0, 0, 0, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.4)" }, onMouseEnter: (e) => { e.currentTarget.style.background = "rgba(255, 255, 255, 0.3)"; e.currentTarget.style.transform = "scale(1.1) rotate(90deg)"; e.currentTarget.style.borderColor = "rgba(255, 255, 255, 0.5)"; }, onMouseLeave: (e) => { e.currentTarget.style.background = "rgba(255, 255, 255, 0.2)"; e.currentTarget.style.transform = "scale(1) rotate(0deg)"; e.currentTarget.style.borderColor = "rgba(255, 255, 255, 0.3)"; }, children: /* @__PURE__ */ jsx9("svg", { width: "16", height: "16", fill: "none", stroke: "white", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx9("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) } ) ] }) ] }), /* @__PURE__ */ jsxs9("div", { style: { flex: 1, padding: "28px", overflowY: "auto", display: "flex", flexDirection: "column", gap: "20px", background: "radial-gradient(circle at 30% 20%, rgba(102, 126, 234, 0.02) 0%, transparent 60%), radial-gradient(circle at 70% 80%, rgba(139, 92, 246, 0.01) 0%, transparent 60%), linear-gradient(180deg, rgba(248, 250, 252, 0.6) 0%, rgba(255, 255, 255, 0.8) 100%)", position: "relative" }, children: [ messages.length === 0 ? /* @__PURE__ */ jsxs9("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", height: "100%", textAlign: "center", padding: "40px 20px" }, children: [ /* @__PURE__ */ jsx9("div", { style: { width: "80px", height: "80px", borderRadius: "50%", background: `linear-gradient(135deg, ${primaryColor}15, ${primaryColor}08)`, display: "flex", alignItems: "center", justifyContent: "center", marginBottom: "20px", boxShadow: "0 8px 32px rgba(102, 126, 234, 0.1)" }, children: /* @__PURE__ */ jsx9("svg", { width: "36", height: "36", fill: "none", stroke: "#9ca3af", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx9("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" }) }) }), /* @__PURE__ */ jsx9("h4", { style: { fontSize: "20px", fontWeight: "600", color: "#1f2937", margin: "0 0 12px 0", letterSpacing: "-0.01em" }, children: title }), /* @__PURE__ */ jsx9("p", { style: { fontSize: "15px", color: "#6b7280", margin: "0 0 8px 0", lineHeight: "1.5" }, children: subtitle }), /* @__PURE__ */ jsx9("p", { style: { fontSize: "13px", color: "#9ca3af", margin: 0 }, children: "Type a message to get started" }) ] }) : showOrders ? /* @__PURE__ */ jsx9( OrdersView, { orders, onClose: () => onToggleOrders && onToggleOrders(), onPayOrder } ) : showProducts ? /* @__PURE__ */ jsxs9("div", { children: [ /* @__PURE__ */ jsx9("h4", { style: { fontSize: "18px", fontWeight: "600", marginBottom: "16px", color: "#1f2937" }, children: "Products" }), products.map((product) => /* @__PURE__ */ jsx9( ProductCard, { product, onBuyNow: onBuyProduct, primaryColor }, product._id )) ] }) : showServices ? /* @__PURE__ */ jsxs9("div", { children: [ /* @__PURE__ */ jsx9("h4", { style: { fontSize: "18px", fontWeight: "600", marginBottom: "16px", color: "#1f2937" }, children: "Services" }), services.map((service) => /* @__PURE__ */ jsx9( ServiceCard, { service, onBook: onBookService }, service._id )) ] }) : showBookings ? /* @__PURE__ */ jsx9( BookingsView, { bookings, onClose: () => onToggleBookings && onToggleBookings() } ) : /* @__PURE__ */ jsx9(MessageList, { messages, primaryColor }), error && /* @__PURE__ */ jsx9("div", { style: { background: "rgba(254, 242, 242, 0.95)", border: "1px solid rgba(252, 165, 165, 0.6)", borderRadius: "16px", padding: "16px", margin: "16px 0", backdropFilter: "blur(10px)" }, children: /* @__PURE__ */ jsxs9("div", { style: { display: "flex", alignItems: "center", gap: "12px" }, children: [ /* @__PURE__ */ jsx9("svg", { width: "20", height: "20", fill: "none", stroke: "#ef4444", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx9("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }), /* @__PURE__ */ jsx9("p", { style: { fontSize: "14px", color: "#dc2626", margin: 0, fontWeight: "500" }, children: error }) ] }) }), /* @__PURE__ */ jsx9("div", { ref: messagesEndRef }) ] }), /* @__PURE__ */ jsx9( MessageInput, { value: input, onChange: setInput, onSend: handleSend, isLoading, placeholder, primaryColor, voiceEnabled } ) ] }); } // src/components/PaymentModal.tsx import { useEffect as useEffect3 } from "react"; import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime"; function PaymentModal({ isOpen, onClose, product, order, customerEmail, paystackPublicKey, onPaymentSuccess, onPaymentError }) { useEffect3(() => { if (isOpen && !window.PaystackPop) { const script = document.createElement("script"); script.src = "https://js.paystack.co/v1/inline.js"; script.async = true; document.body.appendChild(script); } }, [isOpen]); const handlePayment = () => { console.log("Payment attempt with key:", paystackPublicKey); console.log("Order:", order); console.log("Product:", product); if (!paystackPublicKey) { onPaymentError("Paystack public key not configured"); return; } if (!window.PaystackPop || !order || !product) { onPaymentError("Payment system not loaded"); return; } const handler = window.PaystackPop.setup({ key: paystackPublicKey, email: customerEmail, amount: order.amount * 100, // Paystack expects amount in kobo currency: order.currency, ref: `order_${order.orderId}_${Date.now()}`, metadata: { orderId: order.orderId, productName: product.name }, callback: function(response) { onPaymentSuccess(response.reference); onClose(); }, onClose: function() { onClose(); } }); handler.openIframe(); }; if (!isOpen || !product || !order) return null; return /* @__PURE__ */ jsx10( "div", { style: { position: "fixed", inset: 0, backgroundColor: "rgba(0, 0, 0, 0.5)", display: "flex", alignItems: "center", justifyContent: "center", zIndex: 1e6, backdropFilter: "blur(4px)" }, onClick: onClose, children: /* @__PURE__ */ jsxs10( "div", { style: { backgroundColor: "white", borderRadius: "16px", padding: "24px", maxWidth: "400px", width: "90%", boxShadow: "0 20px 40px rgba(0, 0, 0, 0.15)", position: "relative" }, onClick: (e) => e.stopPropagation(), children: [ /* @__PURE__ */ jsx10( "button", { onClick: onClose, style: { position: "absolute", top: "16px", right: "16px", background: "none", border: "none", fontSize: "24px", cursor: "pointer", color: "#6b7280" }, children: "\xD7" } ), /* @__PURE__ */ jsx10( "h3", { style: { fontSize: "20px", fontWeight: "600", marginBottom: "16px", color: "#1f2937" }, children: "Complete Payment" } ), /* @__PURE__ */ jsxs10("div", { style: { marginBottom: "20px" }, children: [ /* @__PURE__ */ jsxs10( "div", { style: { display: "flex", alignItems: "center", gap: "12px", marginBottom: "16px" }, children: [ product.imageUrl && /* @__PURE__ */ jsx10( "img", { src: product.imageUrl, alt: product.name, style: { width: "60px", height: "60px", objectFit: "cover", borderRadius: "8px" } } ), /* @__PURE__ */ jsxs10("div", { children: [ /* @__PURE__ */ jsx10( "h4", { style: { fontSize: "16px", fontWeight: "600", margin: "0 0 4px 0", color: "#1f2937" }, children: product.name } ), /* @__PURE__ */ jsx10( "p", { style: { fontSize: "14px", color: "#6b7280", margin: 0 }, children: product.description } ) ] }) ] } ), /* @__PURE__ */ jsxs10( "div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", padding: "16px", backgroundColor: "#f9fafb", borderRadius: "8px", marginBottom: "20px" }, children: [ /* @__PURE__ */ jsx10("span", { style: { fontSize: "16px", color: "#374151" }, children: "Total:" }), /* @__PURE__ */ jsxs10( "span", { style: { fontSize: "20px", fontWeight: "700", color: "#1f2937" }, children: [ order.currency, " ", order.amount ] } ) ] } ), /* @__PURE__ */ jsx10("p", { style: { fontSize: "14px", color: "#6b7280", marginBottom: "20px" }, children: "Payment will be processed securely through Paystack" }) ] }), /* @__PURE__ */ jsxs10("div", { style: { display: "flex", gap: "12px" }, children: [ /* @__PURE__ */ jsx10( "button", { onClick: onClose, style: { flex: 1, padding: "12px 16px", border: "1px solid #d1d5db", borderRadius: "8px", backgroundColor: "white", color: "#374151", fontSize: "14px", fontWeight: "500", cursor: "pointer" }, children: "Cancel" } ),