hotel-ai-widget
Version:
A customizable hotel chat widget for React and vanilla HTML
72 lines (71 loc) • 12.6 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { Car, ChevronDown, Clock, CreditCard, Hotel, Landmark, MapPin, Plane, } from "lucide-react";
import { useEffect, useState } from "react";
export const InclusionSection = ({ className = "", isStreaming, itinerary, }) => {
const [expandedInclusionCategories, setExpandedInclusionCategories] = useState([]);
useEffect(() => {
setExpandedInclusionCategories([
"attractions",
"hotels",
"flights",
"transport",
]);
}, []);
return (_jsx("div", { className: `flex-1 flex flex-col overflow-hidden ${className}`, children: isStreaming ? (_jsx("div", { className: "flex-1 flex items-center justify-center", children: _jsx("div", { className: "animate-spin rounded-full h-6 w-6 border-t-2 border-blue-500" }) })) : !itinerary ? (_jsx("div", { className: "flex-1 flex items-center justify-center", children: _jsxs("div", { className: "text-center py-8", children: [_jsx(Hotel, { className: "w-8 h-8 text-gray-300 mx-auto mb-2" }), _jsx("p", { className: "text-gray-500 text-xs", children: "No inclusions available" }), _jsx("p", { className: "text-xs text-gray-400 mt-1", children: "Ask me to create an itinerary!" })] }) })) : (_jsxs(_Fragment, { children: [_jsx("div", { className: "bg-white px-3 py-2 border-b flex-shrink-0 border-gray-300", children: _jsx("h1", { className: "text-sm font-bold", children: "Inclusions" }) }), _jsx("div", { className: "flex-1 px-3 py-2 overflow-y-auto", children: (() => {
const inclusionData = itinerary.data.itinerarySummary.find((item) => item["view-type"] === "inclusions");
if (!inclusionData) {
return (_jsxs("div", { className: "text-center py-8", children: [_jsx(Hotel, { className: "w-8 h-8 text-gray-300 mx-auto mb-2" }), _jsx("p", { className: "text-gray-500 text-xs", children: "No inclusions available" })] }));
}
return (_jsx("div", { className: "space-y-4", children: inclusionData.inclusions.inclusions.length > 0 &&
inclusionData.inclusions.inclusions.map((item, itemIndex) => {
const attractions = item.attractions || [];
const hotels = item.hotels || [];
const flights = item.flights || [];
const transport = item.transport || [];
const validAttractions = attractions.filter((attr) => attr.metadata && attr.metadata.length > 0);
const validFlights = flights.filter((flight) => flight.metadata && flight.metadata.length > 0);
const validTransport = transport.filter((trans) => trans.metadata && trans.metadata.length > 0);
const validHotels = hotels;
return (_jsxs("div", { className: "space-y-3", children: [validAttractions.length > 0 && (_jsxs("div", { children: [_jsxs("button", { onClick: () => {
setExpandedInclusionCategories((prev) => prev.includes("attractions")
? prev.filter((cat) => cat !== "attractions")
: [...prev, "attractions"]);
}, className: "flex items-center gap-2 w-full text-left mb-2", children: [_jsx(ChevronDown, { className: `w-3 h-3 text-gray-500 transition-transform ${expandedInclusionCategories.includes("attractions")
? "rotate-0"
: "-rotate-90"}` }), _jsxs("h3", { className: "text-xs font-semibold", children: ["Attractions (", validAttractions.length, ")"] })] }), _jsx("div", { className: `overflow-hidden transition-all duration-300 ${expandedInclusionCategories.includes("attractions")
? "max-h-96 opacity-100"
: "max-h-0 opacity-0"}`, children: _jsx("div", { className: "space-y-2", children: validAttractions.map((attraction, idx) => (_jsx("div", { className: "border border-gray-100 rounded-lg p-2", children: _jsxs("div", { className: "flex items-start gap-2", children: [_jsx(Landmark, { className: "w-3 h-3 text-gray-500 mt-0.5 flex-shrink-0" }), _jsxs("div", { className: "flex-1 min-w-0", children: [_jsx("h4", { className: "font-medium text-xs mb-1", children: attraction.metadata[0]?.name ||
"Attraction" }), attraction.metadata[0]
?.description && (_jsx("p", { className: "text-xs text-gray-600 mb-1", children: attraction.metadata[0]
.description })), _jsxs("div", { className: "flex flex-wrap gap-2 text-xs text-gray-500", children: [attraction.time && (_jsxs("span", { className: "flex items-center gap-1", children: [_jsx(Clock, { className: "w-2 h-2" }), attraction.time] })), attraction.metadata[0]
?.payment && (_jsxs("span", { className: "flex items-center gap-1", children: [_jsx(CreditCard, { className: "w-2 h-2" }), attraction.metadata[0]
.payment] }))] })] })] }) }, idx))) }) })] })), validHotels.length > 0 && (_jsxs("div", { children: [_jsxs("button", { onClick: () => {
setExpandedInclusionCategories((prev) => prev.includes("hotels")
? prev.filter((cat) => cat !== "hotels")
: [...prev, "hotels"]);
}, className: "flex items-center gap-2 w-full text-left mb-2", children: [_jsx(ChevronDown, { className: `w-3 h-3 text-gray-500 transition-transform ${expandedInclusionCategories.includes("hotels")
? "rotate-0"
: "-rotate-90"}` }), _jsxs("h3", { className: "text-xs font-semibold", children: ["Hotels (", validHotels.length, ")"] })] }), _jsx("div", { className: `overflow-hidden transition-all duration-300 ${expandedInclusionCategories.includes("hotels")
? "max-h-96 opacity-100"
: "max-h-0 opacity-0"}`, children: _jsx("div", { className: "space-y-2", children: validHotels.map((hotel, idx) => (_jsx("div", { className: "border border-gray-100 rounded-lg p-2", children: _jsxs("div", { className: "flex items-start gap-2", children: [_jsx(Hotel, { className: "w-3 h-3 text-gray-500 mt-0.5 flex-shrink-0" }), _jsxs("div", { className: "flex-1 min-w-0", children: [_jsx("h4", { className: "font-medium text-xs mb-1", children: hotel.name || "Hotel" }), _jsxs("div", { className: "flex flex-wrap gap-2 text-xs text-gray-500", children: [hotel["check-in"] && (_jsxs("span", { className: "flex items-center gap-1", children: [_jsx(Clock, { className: "w-2 h-2" }), "Check-in: ", hotel["check-in"]] })), hotel["check-out"] && (_jsxs("span", { className: "flex items-center gap-1", children: [_jsx(Clock, { className: "w-2 h-2" }), "Check-out:", " ", hotel["check-out"]] }))] })] })] }) }, idx))) }) })] })), validFlights.length > 0 && (_jsxs("div", { children: [_jsxs("button", { onClick: () => {
setExpandedInclusionCategories((prev) => prev.includes("flights")
? prev.filter((cat) => cat !== "flights")
: [...prev, "flights"]);
}, className: "flex items-center gap-2 w-full text-left mb-2", children: [_jsx(ChevronDown, { className: `w-3 h-3 text-gray-500 transition-transform ${expandedInclusionCategories.includes("flights")
? "rotate-0"
: "-rotate-90"}` }), _jsxs("h3", { className: "text-xs font-semibold", children: ["Flights (", validFlights.length, ")"] })] }), _jsx("div", { className: `overflow-hidden transition-all duration-300 ${expandedInclusionCategories.includes("flights")
? "max-h-96 opacity-100"
: "max-h-0 opacity-0"}`, children: _jsx("div", { className: "space-y-2", children: validFlights.map((flight, idx) => (_jsx("div", { className: "border border-gray-100 rounded-lg p-2", children: _jsxs("div", { className: "flex items-start gap-2", children: [_jsx(Plane, { className: "w-3 h-3 text-gray-500 mt-0.5 flex-shrink-0" }), _jsxs("div", { className: "flex-1 min-w-0", children: [_jsx("h4", { className: "font-medium text-xs mb-1", children: flight.metadata[0]?.airline ||
"Flight" }), _jsxs("div", { className: "flex flex-wrap gap-2 text-xs text-gray-500", children: [flight.date && (_jsxs("span", { className: "flex items-center gap-1", children: [_jsx(Clock, { className: "w-2 h-2" }), flight.date] })), flight.metadata[0]?.from &&
flight.metadata[0]?.to && (_jsxs("span", { className: "flex items-center gap-1", children: [_jsx(MapPin, { className: "w-2 h-2" }), flight.metadata[0].from, " \u2192", " ", flight.metadata[0].to] }))] })] })] }) }, idx))) }) })] })), validTransport.length > 0 && (_jsxs("div", { children: [_jsxs("button", { onClick: () => {
setExpandedInclusionCategories((prev) => prev.includes("transport")
? prev.filter((cat) => cat !== "transport")
: [...prev, "transport"]);
}, className: "flex items-center gap-2 w-full text-left mb-2", children: [_jsx(ChevronDown, { className: `w-3 h-3 text-gray-500 transition-transform ${expandedInclusionCategories.includes("transport")
? "rotate-0"
: "-rotate-90"}` }), _jsxs("h3", { className: "text-xs font-semibold", children: ["Transport (", validTransport.length, ")"] })] }), _jsx("div", { className: `overflow-hidden transition-all duration-300 ${expandedInclusionCategories.includes("transport")
? "max-h-96 opacity-100"
: "max-h-0 opacity-0"}`, children: _jsx("div", { className: "space-y-2", children: validTransport.map((item, idx) => (_jsx("div", { className: "border border-gray-100 rounded-lg p-2", children: _jsxs("div", { className: "flex items-start gap-2", children: [_jsx(Car, { className: "w-3 h-3 text-gray-500 mt-0.5 flex-shrink-0" }), _jsxs("div", { className: "flex-1 min-w-0", children: [_jsx("h4", { className: "font-medium text-xs mb-1", children: item.metadata[0]?.["transport-type"] || "Transport" }), _jsxs("div", { className: "flex flex-wrap gap-2 text-xs text-gray-500", children: [item.time && (_jsxs("span", { className: "flex items-center gap-1", children: [_jsx(Clock, { className: "w-2 h-2" }), item.time] })), item.metadata[0]?.payment && (_jsxs("span", { className: "flex items-center gap-1", children: [_jsx(CreditCard, { className: "w-2 h-2" }), item.metadata[0].payment] }))] })] })] }) }, idx))) }) })] }))] }, itemIndex));
}) }));
})() })] })) }));
};