UNPKG

@forbespro/lead-agent

Version:
1,109 lines (1,102 loc) 52.9 kB
import { jsx as l, Fragment as D, jsxs as o } from "react/jsx-runtime"; import Ae, { useState as p, useRef as B, useEffect as A, useCallback as ye } from "react"; import { Button as N } from "./index5.js"; import { Input as W } from "./index6.js"; import { Textarea as Ve } from "./index7.js"; import { ChatMessage as Be } from "./index8.js"; import { useChat as We } from "./index9.js"; import { AddressSearch as Se } from "./index10.js"; import Ye from "./index11.js"; import { capitalizeFirstLetter as re } from "./index12.js"; import $e from "./index13.js"; import Ke from "./index14.js"; const se = [ { label: "Accounting", value: "ACCOUNTING" }, { label: "Airlines/Aviation", value: "AIRLINES_AVIATION" }, { label: "Alternative Dispute Resolution", value: "ALTERNATIVE_DISPUTE_RESOLUTION" }, { label: "Alternative Medicine", value: "ALTERNATIVE_MEDICINE" }, { label: "Animation", value: "ANIMATION" }, { label: "Apparel & Fashion", value: "APPAREL_FASHION" }, { label: "Architecture & Planning", value: "ARCHITECTURE_PLANNING" }, { label: "Arts and Crafts", value: "ARTS_AND_CRAFTS" }, { label: "Automotive", value: "AUTOMOTIVE" }, { label: "Aviation & Aerospace", value: "AVIATION_AEROSPACE" }, { label: "Banking", value: "BANKING" }, { label: "Biotechnology", value: "BIOTECHNOLOGY" }, { label: "Broadcast Media", value: "BROADCAST_MEDIA" }, { label: "Building Materials", value: "BUILDING_MATERIALS" }, { label: "Business Supplies and Equipment", value: "BUSINESS_SUPPLIES_AND_EQUIPMENT" }, { label: "Capital Markets", value: "CAPITAL_MARKETS" }, { label: "Chemicals", value: "CHEMICALS" }, { label: "Civic & Social Organization", value: "CIVIC_SOCIAL_ORGANIZATION" }, { label: "Civil Engineering", value: "CIVIL_ENGINEERING" }, { label: "Commercial Real Estate", value: "COMMERCIAL_REAL_ESTATE" }, { label: "Computer & Network Security", value: "COMPUTER_NETWORK_SECURITY" }, { label: "Computer Games", value: "COMPUTER_GAMES" }, { label: "Computer Hardware", value: "COMPUTER_HARDWARE" }, { label: "Computer Networking", value: "COMPUTER_NETWORKING" }, { label: "Computer Software", value: "COMPUTER_SOFTWARE" }, { label: "Construction", value: "CONSTRUCTION" }, { label: "Consumer Electronics", value: "CONSUMER_ELECTRONICS" }, { label: "Consumer Goods", value: "CONSUMER_GOODS" }, { label: "Consumer Services", value: "CONSUMER_SERVICES" }, { label: "Corporate Solutions", value: "Corporate Solutions" }, { label: "Cosmetics", value: "COSMETICS" }, { label: "Dairy", value: "DAIRY" }, { label: "Defense & Space", value: "DEFENSE_SPACE" }, { label: "Design", value: "DESIGN" }, { label: "E-Learning", value: "E_LEARNING" }, { label: "Education Management", value: "EDUCATION_MANAGEMENT" }, { label: "Electrical/Electronic Manufacturing", value: "ELECTRICAL_ELECTRONIC_MANUFACTURING" }, { label: "Emergency Services", value: "Emergency Services" }, { label: "Entertainment", value: "ENTERTAINMENT" }, { label: "Environmental Services", value: "ENVIRONMENTAL_SERVICES" }, { label: "Equestrian and Animal Centres", value: "Equestrian and Animal Centres" }, { label: "Events Services", value: "EVENTS_SERVICES" }, { label: "Executive Office", value: "EXECUTIVE_OFFICE" }, { label: "Facilities Services", value: "FACILITIES_SERVICES" }, { label: "Farming", value: "FARMING" }, { label: "Financial Services", value: "FINANCIAL_SERVICES" }, { label: "Fine Art", value: "FINE_ART" }, { label: "Fishery", value: "FISHERY" }, { label: "Food & Beverages", value: "FOOD_BEVERAGES" }, { label: "Fund-Raising", value: "FUND_RAISING" }, { label: "Furniture", value: "FURNITURE" }, { label: "Gambling & Casinos", value: "GAMBLING_CASINOS" }, { label: "Glass, Ceramics & Concrete", value: "GLASS_CERAMICS_CONCRETE" }, { label: "Government Administration", value: "GOVERNMENT_ADMINISTRATION" }, { label: "Government Relations", value: "GOVERNMENT_RELATIONS" }, { label: "Graphic Design", value: "GRAPHIC_DESIGN" }, { label: "Hair & Beauty Salons", value: "Hair & Beauty Salons" }, { label: "Health, Wellness and Fitness", value: "HEALTH_WELLNESS_AND_FITNESS" }, { label: "Higher Education", value: "HIGHER_EDUCATION" }, { label: "Holiday & Caravan Parks", value: "Holiday & Caravan Parks" }, { label: "Holiday Cottages", value: "Holiday Cottages" }, { label: "Hospital & Health Care", value: "HOSPITAL_HEALTH_CARE" }, { label: "Hospitality", value: "HOSPITALITY" }, { label: "Housing Associations", value: "Housing Associations" }, { label: "Human Resources", value: "HUMAN_RESOURCES" }, { label: "Import and Export", value: "IMPORT_AND_EXPORT" }, { label: "Individual & Family Services", value: "INDIVIDUAL_FAMILY_SERVICES" }, { label: "Industrial Automation", value: "INDUSTRIAL_AUTOMATION" }, { label: "Information Services", value: "INFORMATION_SERVICES" }, { label: "Information Technology and Services", value: "INFORMATION_TECHNOLOGY_AND_SERVICES" }, { label: "Insurance", value: "INSURANCE" }, { label: "International Affairs", value: "INTERNATIONAL_AFFAIRS" }, { label: "International Trade and Development", value: "INTERNATIONAL_TRADE_AND_DEVELOPMENT" }, { label: "Internet", value: "INTERNET" }, { label: "Investment Banking", value: "INVESTMENT_BANKING" }, { label: "Investment Management", value: "INVESTMENT_MANAGEMENT" }, { label: "Judiciary", value: "JUDICIARY" }, { label: "Landlords", value: "Landlords" }, { label: "Launderettes & Dry Cleaners", value: "Launderettes & Dry Cleaners" }, { label: "Law Enforcement", value: "LAW_ENFORCEMENT" }, { label: "Law Practice", value: "LAW_PRACTICE" }, { label: "Legal Services", value: "LEGAL_SERVICES" }, { label: "Legeislative Office", value: "LEGISLATIVE_OFFICE" }, { label: "Leisure Centres, Gyms and Spas", value: "Leisure Centres, Gyms and Spas" }, { label: "Leisure, Travel & Tourism", value: "LEISURE_TRAVEL_TOURISM" }, { label: "Libraries", value: "LIBRARIES" }, { label: "Logistics and Supply Chain", value: "LOGISTICS_AND_SUPPLY_CHAIN" }, { label: "Luxury Goods & Jewelry", value: "LUXURY_GOODS_JEWELRY" }, { label: "Machinery", value: "MACHINERY" }, { label: "Management Consulting", value: "MANAGEMENT_CONSULTING" }, { label: "Marine & Offshore", value: "Marine & Offshore" }, { label: "Maritime", value: "MARITIME" }, { label: "Market Research", value: "MARKET_RESEARCH" }, { label: "Marketing and Advertising", value: "MARKETING_AND_ADVERTISING" }, { label: "Mechanical or Industrial Engineering", value: "MECHANICAL_OR_INDUSTRIAL_ENGINEERING" }, { label: "Media Production", value: "MEDIA_PRODUCTION" }, { label: "Medical Devices", value: "MEDICAL_DEVICES" }, { label: "Medical Practice", value: "MEDICAL_PRACTICE" }, { label: "Mental Health Care", value: "MENTAL_HEALTH_CARE" }, { label: "Military", value: "MILITARY" }, { label: "Mining & Metals", value: "MINING_METALS" }, { label: "Ministry of Defence", value: "Ministry of Defence" }, { label: "Motion Pictures and Film", value: "MOTION_PICTURES_AND_FILM" }, { label: "Museums and Institutions", value: "MUSEUMS_AND_INSTITUTIONS" }, { label: "Music", value: "MUSIC" }, { label: "Nanotechnology", value: "NANOTECHNOLOGY" }, { label: "Newspapers", value: "NEWSPAPERS" }, { label: "Non-Profit Organization Management", value: "NON_PROFIT_ORGANIZATION_MANAGEMENT" }, { label: "Nursing & Care", value: "Nursing & Care" }, { label: "Oil & Energy", value: "OIL_ENERGY" }, { label: "Online Media", value: "ONLINE_MEDIA" }, { label: "Outsourcing/Offshoring", value: "OUTSOURCING_OFFSHORING" }, { label: "Package/Freight Delivery", value: "PACKAGE_FREIGHT_DELIVERY" }, { label: "Packaging and Containers", value: "PACKAGING_AND_CONTAINERS" }, { label: "Paper & Forest Products", value: "PAPER_FOREST_PRODUCTS" }, { label: "PBSA", value: "PBSA" }, { label: "Performing Arts", value: "PERFORMING_ARTS" }, { label: "Pharmaceuticals", value: "PHARMACEUTICALS" }, { label: "Philanthropy", value: "PHILANTHROPY" }, { label: "Photography", value: "PHOTOGRAPHY" }, { label: "Plastics", value: "PLASTICS" }, { label: "Political Organization", value: "POLITICAL_ORGANIZATION" }, { label: "Primary/Secondary Education", value: "PRIMARY_SECONDARY_EDUCATION" }, { label: "Printing", value: "PRINTING" }, { label: "Professional Training & Coaching", value: "PROFESSIONAL_TRAINING_COACHING" }, { label: "Program Development", value: "PROGRAM_DEVELOPMENT" }, { label: "Public Policy", value: "PUBLIC_POLICY" }, { label: "Public Relations and Communications", value: "PUBLIC_RELATIONS_AND_COMMUNICATIONS" }, { label: "Public Safety", value: "PUBLIC_SAFETY" }, { label: "Publishing", value: "PUBLISHING" }, { label: "Railroad Manufacture", value: "RAILROAD_MANUFACTURE" }, { label: "Ranching", value: "RANCHING" }, { label: "Real Estate", value: "REAL_ESTATE" }, { label: "Recreational Facilities and Services", value: "RECREATIONAL_FACILITIES_AND_SERVICES" }, { label: "Religious Institutions", value: "RELIGIOUS_INSTITUTIONS" }, { label: "Renewables & Environment", value: "RENEWABLES_ENVIRONMENT" }, { label: "Research", value: "RESEARCH" }, { label: "Restaurants", value: "RESTAURANTS" }, { label: "Retail", value: "Retail" }, { label: "Security and Investigations", value: "SECURITY_AND_INVESTIGATIONS" }, { label: "Semiconductors", value: "SEMICONDUCTORS" }, { label: "Serviced Apartments", value: "Serviced Apartments" }, { label: "Shipbuilding", value: "SHIPBUILDING" }, { label: "Sporting Goods", value: "SPORTING_GOODS" }, { label: "Sports", value: "SPORTS" }, { label: "Staffing and Recruiting", value: "STAFFING_AND_RECRUITING" }, { label: "Student Apartments", value: "Student Apartments" }, { label: "Supermarkets", value: "SUPERMARKETS" }, { label: "Telecommunications", value: "TELECOMMUNICATIONS" }, { label: "Textiles", value: "TEXTILES" }, { label: "Think Tanks", value: "THINK_TANKS" }, { label: "Tobacco", value: "TOBACCO" }, { label: "Translation and Localization", value: "TRANSLATION_AND_LOCALIZATION" }, { label: "Transportation/Trucking/Railroad", value: "TRANSPORTATION_TRUCKING_RAILROAD" }, { label: "Utilities", value: "UTILITIES" }, { label: "Venture Capital & Private Equity", value: "VENTURE_CAPITAL_PRIVATE_EQUITY" }, { label: "Veterinary", value: "VETERINARY" }, { label: "Warehousing", value: "WAREHOUSING" }, { label: "Wholesale", value: "WHOLESALE" }, { label: "Wine and Spirits", value: "WINE_AND_SPIRITS" }, { label: "Wireless", value: "WIRELESS" }, { label: "Writing and Editing", value: "WRITING_AND_EDITING" } ], _e = () => /* @__PURE__ */ o("div", { className: "fpl-flex fpl-items-center fpl-justify-center fpl-w-6 fpl-h-6 fpl-relative", children: [ /* @__PURE__ */ l("style", { children: ` @keyframes orbitAnimation { 0% { transform: rotate(0deg) translateX(4px) rotate(0deg); } 100% { transform: rotate(360deg) translateX(4px) rotate(-360deg); } } .orb { position: absolute; width: 5px; height: 5px; border-radius: 50%; background-color: white; animation: orbitAnimation 1.5s infinite linear; } .orb:nth-child(1) { animation-delay: 0s; opacity: 0.95; } .orb:nth-child(2) { animation-delay: -0.5s; opacity: 0.85; } .orb:nth-child(3) { animation-delay: -1s; opacity: 0.75; } ` }), /* @__PURE__ */ l("div", { className: "orb" }), /* @__PURE__ */ l("div", { className: "orb" }), /* @__PURE__ */ l("div", { className: "orb" }) ] }), je = ({ options: h, placeholder: s, onSelect: n, id: m, value: E, onChange: F }) => { const [r, b] = p(!1), C = h.filter( (c) => c.toLowerCase().includes(E.toLowerCase()) ).slice(0, 10); return /* @__PURE__ */ o("div", { className: "fpl-relative fpl-w-full", children: [ /* @__PURE__ */ l( W, { id: m, value: E, onChange: (c) => { F(c.target.value), b(!0); }, onFocus: () => b(!0), placeholder: s, className: "fpl-w-full" } ), r && C.length > 0 && /* @__PURE__ */ l("div", { className: "fpl-absolute fpl-z-10 fpl-mt-1 fpl-w-full fpl-bg-white fpl-shadow-lg fpl-max-h-60 fpl-rounded-md fpl-py-1 fpl-text-base fpl-overflow-auto", children: C.map((c, z) => /* @__PURE__ */ l( "div", { onClick: () => { n(c), F(c), b(!1); }, className: "fpl-cursor-pointer fpl-select-none fpl-relative fpl-py-2 fpl-pl-3 fpl-pr-9 hover:fpl-bg-gray-100", children: c }, z )) }) ] }); }, ze = () => /* @__PURE__ */ o( "div", { className: "fpl-flex fpl-items-center fpl-gap-3 fpl-bg-gray-100 fpl-text-gray-700 fpl-rounded-lg fpl-p-3.5 fpl-rounded-bl-none fpl-max-w-[275px] fpl-shadow-sm", role: "status", "aria-live": "polite", children: [ /* @__PURE__ */ l("div", { className: "fpl-text-sm fpl-font-medium", children: "Thinking" }), /* @__PURE__ */ l("div", { className: "fpl-flex fpl-items-center fpl-space-x-1.5", children: /* @__PURE__ */ o("div", { className: "thinking-dots-container", children: [ /* @__PURE__ */ l("style", { children: ` @keyframes pulse { 0%, 100% { transform: scale(0.8); opacity: 0.6; } 50% { transform: scale(1.2); opacity: 1; } } @media (prefers-reduced-motion: reduce) { .thinking-dot { animation: none !important; opacity: 0.8; } } .thinking-dot { height: 0.5rem; width: 0.5rem; border-radius: 50%; background: linear-gradient(135deg, #6366f1, #8b5cf6); animation: pulse 1.5s ease-in-out infinite; box-shadow: 0 0 4px rgba(99, 102, 241, 0.3); } .thinking-dots-container { display: flex; align-items: center; gap: 4px; } ` }), /* @__PURE__ */ l("div", { className: "thinking-dot", style: { animationDelay: "0ms" }, "aria-hidden": "true" }), /* @__PURE__ */ l("div", { className: "thinking-dot", style: { animationDelay: "200ms" }, "aria-hidden": "true" }), /* @__PURE__ */ l("div", { className: "thinking-dot", style: { animationDelay: "400ms" }, "aria-hidden": "true" }) ] }) }), /* @__PURE__ */ l("span", { className: "fpl-sr-only", children: "Assistant is thinking, please wait" }) ] } ), L = (h, s, n) => { h(s, n); }, Qe = async (h) => { if (!h.email || !h.name || !h.phone) return null; try { const s = localStorage.getItem("chatId"); if (!s) return console.error("No chat ID found in localStorage"), null; const n = await fetch("/api/hubspot", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ chatId: s, userData: h }) }); if (!n.ok) throw new Error(`Failed to create HubSpot contact: ${n.statusText}`); const m = await n.json(); return m.hubspotId, m.hubspotId; } catch (s) { return console.error("Error creating HubSpot contact:", s), null; } }, Te = (h, s) => { let n = "", m = ""; return s.toLowerCase().includes("your name") ? (n = "Full Name", m = "Enter your full name") : s.toLowerCase().includes("email") ? (n = "Email Address", m = "Enter your email address") : s.toLowerCase().includes("phone") ? (n = "Phone Number", m = "Enter your phone number") : s.toLowerCase().includes("company name") ? (n = "Company Name", m = "Enter your company name") : s.toLowerCase().includes("type of business") ? (n = "Business Type", m = "Enter your business type") : s.toLowerCase().includes("industry") ? (n = "Industry", m = "Search industries...") : s.toLowerCase().includes("address") ? (n = "address", m = "Search for your business address") : h === "number" || s.toLowerCase().includes("how many") ? (n = "Number of Machines", m = "Enter quantity needed") : s.toLowerCase().includes("requirements") ? (n = "Specific Requirements", m = "Tell us about your requirements") : s.toLowerCase().includes("feedback") ? (n = "Your Feedback", m = "Please share your thoughts with us") : (n = h.charAt(0).toUpperCase() + h.slice(1), m = `Enter your ${h}`), { label: n, placeholder: m }; }; function dl({ initialMessages: h = [], onStageComplete: s, onGoalComplete: n, // Add these props tools: m = {}, onClose: E, initialChatId: F, // Other props ...r }) { const [b, C] = p({}), [c, z] = p(null), [_] = p([]), [oe, Ce] = p(!1), Re = B(null), [y, S] = p(null), [Y, Q] = p(!1), [g, O] = p("text"), [w, P] = p(""), [R, U] = p(""), [J, G] = p([]), [ce, ue] = p(!1), [T, de] = p(null), [fe, X] = p(!1), [$, x] = p(!1), [pe, me] = p([]), H = B(null), be = ({ label: e, value: a }) => { de({ label: e, value: a }), C((t) => ({ ...t, industry: a })), M(a, e), ue(!1); }, [K, Z] = p(!1), [ee, le] = p(null), [he, we] = p([]), [q, ve] = p(0), M = async (e, a) => { if (le(null), (g === "email" || g === "tel") && Y) { Z(!0); try { const f = g === "email" ? `/api/email?Email=${encodeURIComponent(e)}` : `/api/phone?Phone=${encodeURIComponent(e)}`, Ee = await (await fetch(`${f}`)).json(); if (!(g === "email" ? Ee.ResponseCode === "Valid" : Ee.IsValid === "Yes")) { le(g === "email" ? "Please enter a valid email address" : "Please enter a valid phone number"), Z(!1); return; } } catch (f) { console.error(`${g} validation error:`, f); } finally { Z(!1); } } const { label: t } = Te(g, w), i = t.toLowerCase().replace(/\s+/g, "_"), d = { ...b, [i]: e }; if (C(d), I({ role: "user", content: a || e }), y === "personal_info" && i === "phone_number" && d.full_name && d.email && d.phone_number && Qe(d), y) { const f = { [i]: e, ...d }; if (n) switch (y) { case "personal_info": g === "tel" && L(n, "personal_info_completed", f); break; case "business_info": g === "address" && L(n, "business_info_completed", f); break; case "product_info": g === "text" && w.includes("requirements") && L(n, "product_info_completed", f); break; case "feedback": L(n, "feedback_provided", f); break; } s && s(y, { [i]: e }); } U(""), Q(!1), x(!1), Y && w && (q >= he.length - 1 && we((f) => [ ...f.slice(0, q + 1), { question: w, inputType: g, inputLabel: w } ]), ve((f) => f + 1)); }, Le = () => { if (q > 0) { const e = he[q - 1]; O(e.inputType), P(e.question), U(""), ve((a) => a - 1), Q(!0); } }, { messages: u, input: Oe, handleInputChange: Pe, handleSubmit: ge, append: I, status: v } = We({ id: F || void 0, api: r.apiUrl || "/api/chat", initialMessages: h, maxSteps: 1, sendExtraMessageFields: !0, onResponse: (e) => { const a = [ "i've initiated", "i've started", "quote process", "quote flow", "request flow" ], t = e.toString().toLowerCase(); a.some((i) => t.includes(i)) && console.warn("Response contains forbidden phrases:", t); }, async onToolCall({ toolCall: e }) { var a; if ((a = m[e.toolName]) != null && a.execute) return await m[e.toolName].execute(e.args); }, body: { // Add currentProduct to the request body so it's available to API route currentProduct: r.currentProduct ? { id: r.currentProduct.id || r.currentProduct.objectID, name: r.currentProduct.name || r.currentProduct.product_type, model: r.currentProduct.model_number, manufacturer: r.currentProduct.manufacturer, category: r.currentProduct.category } : null } }); A(() => { if (u.length === 0 || v !== "ready") return; const e = u[u.length - 1]; if (e.role !== "assistant") return; const a = e.content; try { if (e.annotations && Array.isArray(e.annotations)) { const t = e.annotations.find( (i) => { var d; return ((d = i.other) == null ? void 0 : d.type) === "ui_trigger"; } ); if (t) { const i = t.other.trigger; switch (i.trigger) { case "input_field": i.type, G([]), O(i.type || "text"), Q(!0), P(a.trim()), x(!0), a.includes("name") ? (S("personal_info"), !y && n && L(n, "quote_started", { trigger: i.trigger })) : a.includes("email") || a.includes("phone") ? S("personal_info") : a.includes("company") || a.includes("address") ? S("business_info") : a.includes("machines") ? S("product_info") : a.includes("requirements") ? (S("product_info"), I({ role: "assistant", content: "Would you like to share feedback, please share it with us." }), n && L(n, "quote_completed", b)) : a.includes("feedback") && n && L(n, "feedback_provided", b); break; case "button_options": i.options, G(i.options || []), O(i.type || "text"), P(a.trim()), S("business_info"), x(!0); break; case "sector_search": G([]), O(i.type || "text"), ue(!0), P(a.trim()), S("business_info"), x(!0); break; case "yes_no_buttons": G([]), O(i.type || "text"), X(!0), P(a.trim()), S("submitted"), x(!0); break; case "welcome_options": G([]), O(i.type || "text"), x(!1), P(a.trim()); break; } } } else { const t = /{(?:[^{}]|{(?:[^{}]|{[^{}]*})*})*}/g, i = a.match(t); if (i) for (const d of i) try { const f = JSON.parse(d); f.trigger; } catch (f) { } } } catch (t) { console.error("Error processing triggers:", t); } }, [u, v]); const xe = () => { const { label: e, placeholder: a } = Te(g, w); return /* @__PURE__ */ o(D, { children: [ Y && /* @__PURE__ */ l("div", { className: "fpl-p-0", "aria-label": w, children: /* @__PURE__ */ o(D, { children: [ /* @__PURE__ */ l("div", { className: "fpl-mb-0", children: /* @__PURE__ */ l("label", { htmlFor: e.toLowerCase().replace(/\s+/g, "_"), "aria-label": e, className: "fpl-text-sm fpl-font-medium fpl-sr-only", children: e }) }), /* @__PURE__ */ o("div", { className: "fpl-flex fpl-flex-col fpl-w-full", children: [ /* @__PURE__ */ o("div", { className: "fpl-flex fpl-gap-2", children: [ q > 0 && j === "quote_flow" && /* @__PURE__ */ l( N, { variant: "outline", onClick: Le, className: "fpl-flex-none", "aria-label": "Back", children: "Back" } ), g === "address" ? ( // Use AddressSearch for address inputs /* @__PURE__ */ l("div", { className: "fpl-flex-1", children: /* @__PURE__ */ l( Se, { id: e.toLowerCase().replace(/\s+/g, "_"), name: e.toLowerCase().replace(/\s+/g, "_"), value: R, "aria-label": "Address input", onChange: (t) => U(t), onKeyDown: (t) => { t.key === "Enter" && M(R); }, onSelect: (t, i) => { U(t), C(i ? (d) => ({ ...d, address: t, street: i.street, city: i.city, state: i.state, postalCode: i.postalCode, country: i.country }) : (d) => ({ ...d, address: t })); }, placeholder: a, children: /* @__PURE__ */ l( N, { onClick: () => M(R), disabled: !R.trim() || K, "aria-label": "Submit address", children: K ? /* @__PURE__ */ o("div", { className: "fpl-flex fpl-items-center", children: [ /* @__PURE__ */ o("svg", { className: "fpl-animate-spin -ml-1 fpl-mr-2 fpl-h-4 fpl-w-4 fpl-text-white", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", children: [ /* @__PURE__ */ l("circle", { className: "fpl-opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }), /* @__PURE__ */ l("path", { className: "fpl-opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" }) ] }), "Validating" ] }) : "Submit" } ) } ) }) ) : /* @__PURE__ */ o(D, { children: [ /* @__PURE__ */ l( W, { id: e.toLowerCase().replace(/\s+/g, "_"), name: e.toLowerCase().replace(/\s+/g, "_"), type: g, value: R, "aria-label": e, onChange: (t) => { U(t.target.value), le(null); }, onKeyDown: (t) => { t.key === "Enter" && M(R); }, placeholder: a, className: `fpl-flex-1 ${ee ? "fpl-border-red-500" : ""}` } ), /* @__PURE__ */ l( N, { onClick: () => M(R), disabled: !R.trim() || K, "aria-label": "Submit input", children: K ? /* @__PURE__ */ o("div", { className: "fpl-flex fpl-items-center", children: [ /* @__PURE__ */ o("svg", { className: "fpl-animate-spin -ml-1 fpl-mr-2 fpl-h-4 fpl-w-4 fpl-text-white", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", children: [ /* @__PURE__ */ l("circle", { className: "fpl-opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }), /* @__PURE__ */ l("path", { className: "fpl-opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" }) ] }), "Validating" ] }) : "Submit" } ) ] }) ] }), ee && /* @__PURE__ */ l("div", { className: "fpl-text-red-500 fpl-text-sm fpl-mt-1", children: ee }) ] }) ] }) }), J.length > 0 && /* @__PURE__ */ l("div", { className: "fpl-p-3", children: /* @__PURE__ */ l("div", { id: e.toLowerCase().replace(/\s+/g, "_"), "aria-label": e.toLowerCase().replace(/\s+/g, "_"), className: "fpl-flex fpl-flex-wrap fpl-gap-2", children: J.map((t, i) => /* @__PURE__ */ l( N, { variant: "outline", "aria-label": t, onClick: () => { re(t), M(re(t)); }, className: "focus:fpl-ring-2 focus:fpl-ring-primary", children: re(t) }, i )) }) }), ce && /* @__PURE__ */ o("div", { className: "fpl-p-3", children: [ /* @__PURE__ */ l("label", { htmlFor: e.toLowerCase().replace(/\s+/g, "_"), "aria-label": e.toLowerCase().replace(/\s+/g, "_"), className: "fpl-mb-2 fpl-sr-only", children: "What industry are you in?" }), /* @__PURE__ */ l( W, { id: e.toLowerCase().replace(/\s+/g, "_"), type: "text", name: e.toLowerCase().replace(/\s+/g, "_"), "aria-label": e.toLowerCase().replace(/\s+/g, "_"), value: (T == null ? void 0 : T.label) || "", onChange: (t) => { var d; const i = (d = se.filter( (f) => f.label.toLowerCase().includes(t.target.value.toLowerCase()) )) == null ? void 0 : d[0]; de({ label: i == null ? void 0 : i.label, value: t.target.value }); }, onKeyDown: (t) => { var i; if (t.key === "Enter") { const d = (i = se.filter( (f) => { var ne; return f.label.toLowerCase().includes(((ne = T == null ? void 0 : T.label) == null ? void 0 : ne.toLowerCase()) || ""); } )) == null ? void 0 : i[0]; d && be({ label: d.label, value: d.value }); } }, placeholder: "Search industries...", className: "fpl-mb-2" } ), /* @__PURE__ */ l("div", { className: "fpl-max-h-60 fpl-overflow-y-auto fpl-border fpl-rounded-md fpl-bg-gray-50 fpl-mt-1", children: se.filter( (t) => { var i; return t.label.toLowerCase().includes(((i = T == null ? void 0 : T.label) == null ? void 0 : i.toLowerCase()) || ""); } ).slice(0, 10).map((t) => /* @__PURE__ */ l( "button", { value: t.value, onClick: () => be({ label: t.label, value: t.value }), className: "fpl-w-full fpl-px-4 fpl-py-2 fpl-text-left hover:fpl-bg-gray-100 fpl-border-b focus:fpl-border-b-0", "aria-label": t.label, children: t.label }, t.value )) }) ] }), fe && /* @__PURE__ */ l("div", { className: "fpl-p-3", children: /* @__PURE__ */ o("div", { id: e.toLowerCase().replace(/\s+/g, "_"), "aria-label": e.toLowerCase().replace(/\s+/g, "_"), className: "fpl-flex fpl-gap-2", children: [ /* @__PURE__ */ l( N, { variant: "outline", "aria-label": "Yes", onClick: () => { var d, f; const t = u[u.length - 1], i = ((d = t == null ? void 0 : t.content) == null ? void 0 : d.toLowerCase().includes("feedback")) || ((f = t == null ? void 0 : t.content) == null ? void 0 : f.toLowerCase().includes("review")); setTimeout(() => { I({ role: "user", content: i ? "I'd like to leave feedback" : "Yes" }), X(!1), s && s("completed", {}); }, 300); }, children: "Yes" } ), /* @__PURE__ */ l( N, { variant: "outline", "aria-label": "No", onClick: () => { I({ role: "assistant", content: "Thanks for your response." }), setTimeout(() => { I({ role: "user", content: "No thanks" }), X(!1), s && s("completed", {}); }, 300); }, children: "No" } ) ] }) }) ] }); }, ae = B(!1); A(() => { u.length === 0 && !ae.current && (ae.current = !0, (async () => { try { r.currentProduct ? (await I({ role: "system", content: `You are a sales assistant for Forbes Professional, focusing on the ${r.currentProduct.name || r.currentProduct.product_type || "product"}. When discussing this product: 1. Always offer two clear choices to the user: learning more about the product OR getting a quote 2. Keep initial responses brief and focused on the product 3. Use button_options instead of yes_no_buttons when presenting choices 4. If the user wants to learn more, provide key features, benefits, and technical specifications 5. If the user wants a quote, follow the structured quote flow`, id: `product-system-${r.currentProduct.id || r.currentProduct.objectID || Date.now()}` }), await I({ role: "assistant", content: `Ready to get a quote for this ${r.currentProduct.name || r.currentProduct.product_type || "product"}?`, id: `product-quote-welcome-${r.currentProduct.id || r.currentProduct.objectID || Date.now()}`, annotations: [ { type: "ui_trigger", other: { trigger: { trigger: "button_options", options: ["Learn more", "Get quote now"] } } } ], parts: [ { type: "tool-invocation", toolInvocation: { state: "result", toolCallId: `product-${r.currentProduct.id || r.currentProduct.objectID || Date.now()}`, toolName: "searchProducts", args: { query: `${r.currentProduct.manufacturer} ${r.currentProduct.name || r.currentProduct.product_type}` }, result: { type: "product", products: [r.currentProduct] } } } ] })) : (await I({ role: "system", content: `You are a sales assistant for Forbes Professional, specializing in commercial laundry equipment. When greeting users: 1. Always offer clear options such as "Learn more" or "Get quote now" 2. Use button_options instead of yes_no_buttons for initial interactions 3. If the user wants to learn about products, ask about their industry needs first 4. If the user wants a quote, follow the structured quote flow sequence 5. For the quote flow, use the appropriate UI triggers: - Use input_field triggers for collecting name, email, phone, etc. - Use button_options for business type selection - Use sector_search for industry selection`, id: "general-system-message" }), await I({ role: "assistant", annotations: [ { type: "ui_trigger", other: { trigger: "button_options", options: ["Learn more", "Get quote now"] } } ], content: "Welcome to Forbes Professional! I'm here to help with your commercial laundry equipment needs. Are you looking for information about specific products, service options, or would you like to request a quote?", id: "welcome-message" })); } catch (a) { console.error("Failed to initialize chat:", a), ae.current = !1; } })()); }, [u.length, I, r.currentProduct]), A(() => { if (H.current) { const e = H.current; setTimeout(() => { e.scrollTo({ top: e.scrollHeight, behavior: "smooth" }); }, 100); } }, [u, pe]); const k = (e, a) => { C((t) => ({ ...t, [e]: a })); }, Me = ye(() => { const e = _.findIndex((t) => t.id === (c == null ? void 0 : c.id)); if (e === _.length - 1) { if (n) { let t = "contact_submitted"; b.appointmentDate || b.appointmentTime || _.some((i) => i.id.includes("appointment")) ? t = "appointment_booked" : b.quoteType || b.budget || _.some((i) => i.id.includes("quote")) ? t = "quote_requested" : (b.demoPreference || _.some((i) => i.id.includes("demo"))) && (t = "demo_requested"), n(t, b); } } else z(_[e + 1]), s && s(`form_field_${c == null ? void 0 : c.id}`, { fieldId: c == null ? void 0 : c.id, value: c != null && c.id ? b[c.id] : void 0 }); }, [c, b, _, n]); A(() => { const e = u.length > 0 ? u[u.length - 1] : null; e && e.role === "assistant" && s && (s("conversation_message", { messageId: e.id, messageCount: u.length }), u.length === 1 && s("welcome_complete", {})); }, [u, s]); const ke = (e) => { if (e.isAI) return null; switch (e.type) { case "select": return /* @__PURE__ */ l( je, { id: e.id, "aria-label": e.label, options: e.options || [], placeholder: e.placeholder || `Select ${e.label}`, value: b[e.id] || "", onChange: (a) => k(e.id, a), onSelect: (a) => k(e.id, a) } ); case "address": return /* @__PURE__ */ l( Se, { id: e.id.toLowerCase().replace(/\s+/g, "_"), name: e.id.toLowerCase().replace(/\s+/g, "_"), "aria-label": e.label, value: b[e.id] || "", onChange: (a) => k(e.id, a), onSelect: (a) => k(e.id, a), placeholder: e.placeholder || "Search for an address..." } ); case "textarea": return /* @__PURE__ */ l( Ve, { id: e.id, "aria-label": e.label, value: b[e.id] || "", onChange: (a) => k(e.id, a.target.value), placeholder: e.placeholder } ); default: return /* @__PURE__ */ l( W, { id: e.id, "aria-label": e.label, type: e.type, value: b[e.id] || "", onChange: (a) => k(e.id, a.target.value), placeholder: e.placeholder } ); } }, De = () => u.length !== 1 && !r.currentProduct || r.currentProduct ? null : /* @__PURE__ */ o("div", { className: "fpl-flex fpl-flex-wrap fpl-gap-2 fpl-mt-3", children: [ /* @__PURE__ */ l( N, { variant: "outline", "aria-label": "Browse products", onClick: () => I({ role: "user", content: "I want to learn about your products" }), children: "Browse Products" } ), /* @__PURE__ */ l( N, { variant: "outline", "aria-label": "Request quote", onClick: () => I({ role: "user", content: "I'd like to request a quote" }), children: "Request Quote" } ), /* @__PURE__ */ l( N, { variant: "outline", "aria-label": "Service support", onClick: () => I({ role: "user", content: "I need service support" }), children: "Service Support" } ) ] }); A(() => { const e = u.filter( (a) => a.role === "assistant" && !pe.includes(a.id) ); e.length > 0 && (me((a) => [ ...a, ...e.map((t) => t.id) ]), e.forEach((a) => { setTimeout(() => { me( (t) => t.filter((i) => i !== a.id) ); }, 1e3); })); }, [u]); const Fe = (e) => /* @__PURE__ */ l("div", { "aria-label": "Booking results", className: "fpl-mt-2 fpl-grid fpl-grid-cols-1 fpl-gap-4", children: e.map((a, t) => /* @__PURE__ */ o("div", { "aria-label": "Booking result", className: "fpl-bg-white fpl-rounded-lg fpl-border fpl-p-3 hover:fpl-shadow-md fpl-transition-shadow", children: [ /* @__PURE__ */ l("h4", { className: "fpl-font-medium fpl-text-primary", children: a.title || "Booking Details" }), /* @__PURE__ */ l("div", { className: "fpl-text-sm fpl-text-gray-700 fpl-mt-1", children: a.description || a.details }), a.time && /* @__PURE__ */ o("div", { className: "fpl-text-xs fpl-mt-1", children: [ "Time: ", a.time ] }), a.date && /* @__PURE__ */ o("div", { className: "fpl-text-xs", children: [ "Date: ", a.date ] }) ] }, t)) }), [j] = p("initial"), [, te] = p(!1); A(() => { const e = u[u.length - 1]; if ((e == null ? void 0 : e.role) === "assistant") { const a = e.content.toLowerCase(), t = a.includes("does this help") || a.includes("would you like") || a.includes("is this useful") || a.endsWith("?"); te( (j === "completed" || j === "quote_flow" && a.includes("quote")) && !t ); } if ((e == null ? void 0 : e.role) === "user") { const a = e.content.toLowerCase(); (a.includes("feedback") || a.includes("review") || a.includes("rate")) && te(!1), (a === "yes" || a.startsWith("yes,") || a === "no" || a.startsWith("no,")) && te(!1); } }, [u, j]); const Ue = B(null), ie = B(null); A(() => { r.isOpen && ie.current && setTimeout(() => { var e; return (e = ie.current) == null ? void 0 : e.focus(); }, 100); }, [r.isOpen]), A(() => { const e = (a) => { a.key === "Escape" && r.isOpen && E && E(); }; return document.addEventListener("keydown", e), () => document.removeEventListener("keydown", e); }, [r.isOpen, E]); const Ge = () => { E == null || E(); }; A(() => () => { }, []); const Ne = ye(() => { if (H.current) { const e = H.current; e.scrollTo({ top: e.scrollHeight, behavior: "smooth" }); } }, []); A(() => { const e = setTimeout(Ne, 100); return () => clearTimeout(e); }, [u.length, Ne]); const [V, Ie] = p(!1); A(() => { document.cookie.split(";").some((t) => t.trim().startsWith("fpl-privacy-")) && Ie(!0); }, []); const He = () => { Ie(!0); const e = Math.random().toString(36).substring(2, 15), a = /* @__PURE__ */ new Date(); a.setDate(a.getDate() + 90), document.cookie = `fpl-privacy-${e}=accepted; expires=${a.toUTCString()}; path=/; SameSite=Strict`, n && n("privacy_accepted", { timestamp: (/* @__PURE__ */ new Date()).toISOString() }); }, qe = () => { s && s("privacy_rejected", { timestamp: (/* @__PURE__ */ new Date()).toISOString() }), E == null || E(); }; return /* @__PURE__ */ l(D, { children: /* @__PURE__ */ l("div", { className: "chat-widget-container", children: /* @__PURE__ */ o( "div", { ref: Ue, role: "dialog", "aria-labelledby": r.title, "aria-describedby": r.subtitle, "aria-modal": "true", className: `chatbot-widget fpl-bg-[#f9fbff] fpl-fixed fpl-bottom-2 fpl-right-0 md:fpl-bottom-[5.5rem] md:fpl-right-4 fpl-w-full fpl-max-w-96 fpl-h-[calc(95vh-32px)] fpl-max-h-[650px] fpl-rounded-lg fpl-shadow-xl fpl-flex fpl-flex-col fpl-overflow-hidden fpl-transition-all fpl-duration-300 fpl-z-[999999999]`, children: [ /* @__PURE__ */ o("div", { className: "fpl-absolute fpl-top-0 fpl-left-0 fpl-w-full fpl-h-full fpl-z-[-2] fpl-overflow-hidden", children: [ /* @__PURE__ */ l("div", { className: "fpl-w-full fpl-h-full", style: { background: ` radial-gradient(circle at 75% 30%, white 0%, transparent 50%), radial-gradient(circle at 25% 80%,rgb(241, 244, 251) 0%, transparent 50%), radial-gradient(circle at 80% 80%,rgb(213, 232, 252) 0%, transparent 60%) `, backgroundSize: "200% 200%", animation: "gradientFlow 20s ease infinite", opacity: "0.15" } }), /* @__PURE__ */ l("div", { className: "fpl-absolute fpl-bottom-0 fpl-left-0 fpl-w-full fpl-h-full", style: { background: "linear-gradient(to top, rgba(217, 218, 255, 0.1) 0%, rgba(215, 225, 250, 0.1) 40%, rgba(218, 223, 253, 0) 100%)", pointerEvents: "none" } }), /* @__PURE__ */ l("style", { children: ` @keyframes gradientFlow { 0% { background-position: 0% 50% } 50% { background-position: 100% 50% } 100% { background-position: 0% 80% } } ` }) ] }), /* @__PURE__ */ o("div", { className: "fpl-bg-[#126dd8] fpl-text-white fpl-p-3 fpl-flex fpl-justify-between fpl-items-center", children: [ /* @__PURE__ */ l(D, { children: /* @__PURE__ */ o("div", { className: "fpl-flex fpl-items-center", children: [ r.logoUrl ? /* @__PURE__ */ l("img", { src: r.logoUrl, alt: "Logo", className: "fpl-h-8 fpl-w-8 fpl-mr-2" }) : /* @__PURE__ */ l("div", { className: "fpl-bg-black/70 fpl-h-[52px] fpl-w-[52px] fpl-rounded-full fpl-mr-3", children: /* @__PURE__ */ l(Ye, { size: 52 }) }), /* @__PURE__ */ o("div", { children: [ /* @__PURE__ */ l("h3", { className: "!fpl-text-white fpl-font-medium", children: r.title }), /* @__PURE__ */ l("p", { className: "!fpl-text-sm !fpl-text-white fpl-opacity-80", children: r.subtitle }) ] }) ] }) }), /* @__PURE__ */ l("div", { className: "fpl-flex fpl-gap-2", children: /* @__PURE__ */ l( "button", { "aria-label": "Close chat", ref: ie, onClick: Ge, className: "fpl-rounded-full fpl-p-1 fpl-text-white fpl-hover:text-white/50 fpl-transition-colors", type: "button", children: /* @__PURE__ */ l($e, { className: "fpl-w-6 fpl-h-6 flp-text-white" }) } ) }) ] }), /* @__PURE__ */ o( "div", { ref: H, className: "fpl-flex-1 fpl-overflow-y-auto fpl-p-4 fpl-space-y-4", children: [ u.map((e, a) => e.role === "system" ? /* @__PURE__ */ l(Ae.Fragment, {}, `${e.id || a}-fragment`) : /* @__PURE__ */ l(Ae.Fragment, { children: e.parts && e.parts.length > 0 ? /* @__PURE__ */ l( Be, { message: e, renderBookingResults: Fe, isStreaming: v === "streaming" && a === u.length - 1 }, `${e.id || a}-message` ) : null }, `${e.id || a}-fragment`)), v === "streaming" && /* @__PURE__ */ l("div", { className: "message-item fpl-flex fpl-justify-start fpl-mb-4", children: /* @__PURE__ */ l(ze, {}) }, "typing-indicator"), u.length === 1 && u[0].role === "assistant" && /* @__PURE__ */ l(De, {}, "quick-replies"), oe && c && /* @__PURE__ */ o("div", { className: "fpl-bg-white fpl-rounded-lg fpl-border fpl-p-4 fpl-my-3", children: [ /* @__PURE__ */ l("h4", { className: "fpl-font-medium fpl-mb-2", children: c.label }), /* @__PURE__ */ o("div", { className: "fpl-space-y-3", children: [ ke(c), /* @__PURE__ */ o("div", { className: "fpl-flex fpl-justify-between fpl-mt-3", children: [ /* @__PURE__ */ l( N, { variant: "outline", onClick: () => Ce(!1), children: "Cancel" } ), /* @__PURE__ */ l( N, { onClick: Me, disabled: c.required && !b[c.id], children: _.indexOf(c) < _.length - 1 ? "Next" : "Submit" } ) ] }) ] }) ] }, "form-ui"), /* @__PURE__ */ l("div", { ref: Re }, "messages-end") ] } ), !oe && /* @__PURE__ */ o("div", { className: "fpl-px-3 fpl-pb-3 fpl-min-h-[62px]", children: [ !V && y && /* @__PURE__ */ l( Je, { onAccept: He, onReject: qe } ), /* @__PURE__ */ l("form", { onSubmit: ge, className: "fpl-p-3 fpl-bg-white fpl-border fpl-shadow-sm fpl-rounded-xl", children: $ && Y || $ && J.length > 0 || $ && ce || $ && fe ? ( // Only show special inputs if privacy is accepted or we're not in quote flow V || !y ? xe() : /* @__PURE__ */ l("div", { className: "fpl-text-center fpl-py-2 fpl-text-gray-500", children: "Please accept the privacy notice to continue" }) ) : ( // Otherwise render normal input /* @__PURE__ */ l(D, { children: /* @__PURE__ */ o("div", { className: "fpl-flex fpl-gap-2", children: [ /* @__PURE__ */ l( W, { id: "message-input", name: "message-input", value: Oe, onChange: Pe, "aria-label": "Message input", onKeyDown: (e) => { e.key === "Enter" && !e.shiftKey && (e.preventDefault(), ge(e)); }, placeholder: v === "streaming" ? "Receiving response..." : v === "submitted" ? "Message sent..." : "Type your message...", disabled: v === "streaming" || v === "submitted" || y !== null && !V, className: `fpl-flex-1 ${v === "streaming" || v === "submitted" || y !== null && !V ? "bg-gray-50" : ""}` } ), /* @__PURE__ */ l( N, { type: "submit", "aria-label": "Send message", disabled: v === "streaming" || v === "submitted" || y !== null && !V, className: `fpl-transition-all ${v === "streaming" ? "bg-blue-400" : v === "submitted" ? "bg-blue-500" : ""}`, children: v === "streaming" ? /* @__PURE__ */ l(_e, {}) : v === "submitted" ? /* @__PURE__ */