@burdenoff/microfe-adaptercloud 2026.614.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -0
- package/dist/adaptercloud/AdapterCloudRoot.js +177 -0
- package/dist/adaptercloud/AdapterCloudRoot.js.map +1 -0
- package/dist/adaptercloud/AdapterCloudRoutes.js +215 -0
- package/dist/adaptercloud/AdapterCloudRoutes.js.map +1 -0
- package/dist/adaptercloud/components/EmptyState.js +28 -0
- package/dist/adaptercloud/components/EmptyState.js.map +1 -0
- package/dist/adaptercloud/components/InvestmentCard.js +96 -0
- package/dist/adaptercloud/components/InvestmentCard.js.map +1 -0
- package/dist/adaptercloud/components/MetricsCard.js +46 -0
- package/dist/adaptercloud/components/MetricsCard.js.map +1 -0
- package/dist/adaptercloud/components/PageLayout.js +26 -0
- package/dist/adaptercloud/components/PageLayout.js.map +1 -0
- package/dist/adaptercloud/components/RatingDisplay.js +35 -0
- package/dist/adaptercloud/components/RatingDisplay.js.map +1 -0
- package/dist/adaptercloud/components/StatusBadge.js +45 -0
- package/dist/adaptercloud/components/StatusBadge.js.map +1 -0
- package/dist/adaptercloud/context/AdapterCloudContext.js +93 -0
- package/dist/adaptercloud/context/AdapterCloudContext.js.map +1 -0
- package/dist/adaptercloud/context/index.js +1 -0
- package/dist/adaptercloud/hooks/useAdapterCloudApi.js +223 -0
- package/dist/adaptercloud/hooks/useAdapterCloudApi.js.map +1 -0
- package/dist/adaptercloud/index.js +7 -0
- package/dist/adaptercloud/mocks/data.js +1517 -0
- package/dist/adaptercloud/mocks/data.js.map +1 -0
- package/dist/adaptercloud/mocks/users.js +34 -0
- package/dist/adaptercloud/mocks/users.js.map +1 -0
- package/dist/adaptercloud/pages/HomePage.js +921 -0
- package/dist/adaptercloud/pages/HomePage.js.map +1 -0
- package/dist/adaptercloud/pages/admin/AdminAnalyticsPage.js +645 -0
- package/dist/adaptercloud/pages/admin/AdminAnalyticsPage.js.map +1 -0
- package/dist/adaptercloud/pages/admin/AdminDashboard.js +639 -0
- package/dist/adaptercloud/pages/admin/AdminDashboard.js.map +1 -0
- package/dist/adaptercloud/pages/admin/AdminFinancialPage.js +421 -0
- package/dist/adaptercloud/pages/admin/AdminFinancialPage.js.map +1 -0
- package/dist/adaptercloud/pages/admin/AdminOrdersPage.js +660 -0
- package/dist/adaptercloud/pages/admin/AdminOrdersPage.js.map +1 -0
- package/dist/adaptercloud/pages/admin/AdminProfilePage.js +259 -0
- package/dist/adaptercloud/pages/admin/AdminProfilePage.js.map +1 -0
- package/dist/adaptercloud/pages/admin/AdminSettingsPage.js +649 -0
- package/dist/adaptercloud/pages/admin/AdminSettingsPage.js.map +1 -0
- package/dist/adaptercloud/pages/admin/CartManagementPage.js +869 -0
- package/dist/adaptercloud/pages/admin/CartManagementPage.js.map +1 -0
- package/dist/adaptercloud/pages/admin/UserManagementPage.js +893 -0
- package/dist/adaptercloud/pages/admin/UserManagementPage.js.map +1 -0
- package/dist/adaptercloud/pages/cart-owner/AnalyticsDashboard.js +834 -0
- package/dist/adaptercloud/pages/cart-owner/AnalyticsDashboard.js.map +1 -0
- package/dist/adaptercloud/pages/cart-owner/BusinessSettingsPage.js +700 -0
- package/dist/adaptercloud/pages/cart-owner/BusinessSettingsPage.js.map +1 -0
- package/dist/adaptercloud/pages/cart-owner/CartOwnerDashboard.js +760 -0
- package/dist/adaptercloud/pages/cart-owner/CartOwnerDashboard.js.map +1 -0
- package/dist/adaptercloud/pages/cart-owner/CartOwnerProfilePage.js +886 -0
- package/dist/adaptercloud/pages/cart-owner/CartOwnerProfilePage.js.map +1 -0
- package/dist/adaptercloud/pages/cart-owner/CartServiceConfigPage.js +631 -0
- package/dist/adaptercloud/pages/cart-owner/CartServiceConfigPage.js.map +1 -0
- package/dist/adaptercloud/pages/cart-owner/InventoryManagementPage.js +913 -0
- package/dist/adaptercloud/pages/cart-owner/InventoryManagementPage.js.map +1 -0
- package/dist/adaptercloud/pages/cart-owner/OrderManagementPage.js +881 -0
- package/dist/adaptercloud/pages/cart-owner/OrderManagementPage.js.map +1 -0
- package/dist/adaptercloud/pages/cart-owner/StaffManagementPage.js +833 -0
- package/dist/adaptercloud/pages/cart-owner/StaffManagementPage.js.map +1 -0
- package/dist/adaptercloud/pages/common/HelpSupportPage.js +1325 -0
- package/dist/adaptercloud/pages/common/HelpSupportPage.js.map +1 -0
- package/dist/adaptercloud/pages/common/NotificationCenterPage.js +665 -0
- package/dist/adaptercloud/pages/common/NotificationCenterPage.js.map +1 -0
- package/dist/adaptercloud/pages/common/SettingsPage.js +964 -0
- package/dist/adaptercloud/pages/common/SettingsPage.js.map +1 -0
- package/dist/adaptercloud/pages/customer/BookingDetailsPage.js +593 -0
- package/dist/adaptercloud/pages/customer/BookingDetailsPage.js.map +1 -0
- package/dist/adaptercloud/pages/customer/CartDetailPage.js +620 -0
- package/dist/adaptercloud/pages/customer/CartDetailPage.js.map +1 -0
- package/dist/adaptercloud/pages/customer/CartDiscoveryPage.js +547 -0
- package/dist/adaptercloud/pages/customer/CartDiscoveryPage.js.map +1 -0
- package/dist/adaptercloud/pages/customer/CheckoutPage.js +532 -0
- package/dist/adaptercloud/pages/customer/CheckoutPage.js.map +1 -0
- package/dist/adaptercloud/pages/customer/CustomerDashboard.js +496 -0
- package/dist/adaptercloud/pages/customer/CustomerDashboard.js.map +1 -0
- package/dist/adaptercloud/pages/customer/CustomerProfilePage.js +621 -0
- package/dist/adaptercloud/pages/customer/CustomerProfilePage.js.map +1 -0
- package/dist/adaptercloud/pages/customer/DirectServiceBookingPage.js +623 -0
- package/dist/adaptercloud/pages/customer/DirectServiceBookingPage.js.map +1 -0
- package/dist/adaptercloud/pages/customer/FavoritesPage.js +477 -0
- package/dist/adaptercloud/pages/customer/FavoritesPage.js.map +1 -0
- package/dist/adaptercloud/pages/customer/OrderHistoryPage.js +438 -0
- package/dist/adaptercloud/pages/customer/OrderHistoryPage.js.map +1 -0
- package/dist/adaptercloud/pages/customer/OrderTrackingPage.js +388 -0
- package/dist/adaptercloud/pages/customer/OrderTrackingPage.js.map +1 -0
- package/dist/adaptercloud/pages/customer/PaymentMethodsPage.js +488 -0
- package/dist/adaptercloud/pages/customer/PaymentMethodsPage.js.map +1 -0
- package/dist/adaptercloud/pages/customer/ReviewsPage.js +606 -0
- package/dist/adaptercloud/pages/customer/ReviewsPage.js.map +1 -0
- package/dist/adaptercloud/pages/customer/SavedAddressesPage.js +443 -0
- package/dist/adaptercloud/pages/customer/SavedAddressesPage.js.map +1 -0
- package/dist/adaptercloud/pages/investor/InvestmentDetailsPage.js +849 -0
- package/dist/adaptercloud/pages/investor/InvestmentDetailsPage.js.map +1 -0
- package/dist/adaptercloud/pages/investor/InvestmentOpportunitiesPage.js +939 -0
- package/dist/adaptercloud/pages/investor/InvestmentOpportunitiesPage.js.map +1 -0
- package/dist/adaptercloud/pages/investor/InvestorAnalyticsPage.js +681 -0
- package/dist/adaptercloud/pages/investor/InvestorAnalyticsPage.js.map +1 -0
- package/dist/adaptercloud/pages/investor/InvestorDashboard.js +419 -0
- package/dist/adaptercloud/pages/investor/InvestorDashboard.js.map +1 -0
- package/dist/adaptercloud/pages/investor/InvestorInvestmentsPage.js +399 -0
- package/dist/adaptercloud/pages/investor/InvestorInvestmentsPage.js.map +1 -0
- package/dist/adaptercloud/pages/investor/InvestorPortfolioPage.js +569 -0
- package/dist/adaptercloud/pages/investor/InvestorPortfolioPage.js.map +1 -0
- package/dist/adaptercloud/pages/investor/InvestorProfilePage.js +1065 -0
- package/dist/adaptercloud/pages/investor/InvestorProfilePage.js.map +1 -0
- package/dist/adaptercloud/pages/worker/TaskDetailsPage.js +496 -0
- package/dist/adaptercloud/pages/worker/TaskDetailsPage.js.map +1 -0
- package/dist/adaptercloud/pages/worker/WorkerDashboard.js +634 -0
- package/dist/adaptercloud/pages/worker/WorkerDashboard.js.map +1 -0
- package/dist/adaptercloud/pages/worker/WorkerOrdersPage.js +675 -0
- package/dist/adaptercloud/pages/worker/WorkerOrdersPage.js.map +1 -0
- package/dist/adaptercloud/pages/worker/WorkerProfilePage.js +687 -0
- package/dist/adaptercloud/pages/worker/WorkerProfilePage.js.map +1 -0
- package/dist/adaptercloud/pages/worker/WorkerSchedulePage.js +578 -0
- package/dist/adaptercloud/pages/worker/WorkerSchedulePage.js.map +1 -0
- package/dist/adaptercloud/store/adaptercloudStore.js +38 -0
- package/dist/adaptercloud/store/adaptercloudStore.js.map +1 -0
- package/dist/adaptercloud/store/index.js +1 -0
- package/dist/adaptercloud/utils/cn.js +10 -0
- package/dist/adaptercloud/utils/cn.js.map +1 -0
- package/dist/adaptercloud/utils/formatters.js +51 -0
- package/dist/adaptercloud/utils/formatters.js.map +1 -0
- package/dist/adaptercloud/utils/navigation.js +9 -0
- package/dist/adaptercloud/utils/navigation.js.map +1 -0
- package/dist/index.js +7 -0
- package/dist/node_modules/.bun/clsx@2.1.1/node_modules/clsx/dist/clsx.js +18 -0
- package/dist/node_modules/.bun/clsx@2.1.1/node_modules/clsx/dist/clsx.js.map +1 -0
- package/dist/node_modules/.bun/tailwind-merge@3.5.0/node_modules/tailwind-merge/dist/bundle-mjs.js +1674 -0
- package/dist/node_modules/.bun/tailwind-merge@3.5.0/node_modules/tailwind-merge/dist/bundle-mjs.js.map +1 -0
- package/package.json +106 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CartDetailPage.js","names":[],"sources":["../../../../src/adaptercloud/pages/customer/CartDetailPage.tsx"],"sourcesContent":["/**\n * Cart Detail Page\n * @module adaptercloud/pages/customer\n *\n * Full detail view with shopping cart sidebar (Your Order with +/- controls,\n * remove, total, Proceed to Checkout), product customization modal,\n * category-grouped product listing, search, category filter,\n * investment opportunity card, scheduled stops, direct service card,\n * veg/vegan icons, availability badges, calories, original price\n * strikethrough, and cart closed warning banner.\n */\n\nimport { useState, useMemo, useEffect } from 'react';\nimport { useParams } from 'react-router-dom';\nimport {\n ArrowLeft,\n Star,\n MapPin,\n Clock,\n CheckCircle2,\n ShoppingCart,\n Search,\n Leaf,\n Minus,\n Plus,\n X,\n TrendingUp,\n Home,\n Calendar,\n Flame,\n} from 'lucide-react';\nimport { PageLayout } from '../../components/PageLayout';\nimport { EmptyState } from '../../components/EmptyState';\nimport { useAdapterCloud } from '../../context/AdapterCloudContext';\nimport {\n useProviders,\n useOfferings,\n useInvestmentOpportunities,\n} from '../../hooks/useAdapterCloudApi';\nimport { cn } from '../../utils/cn';\nimport { formatCurrency, formatDistance, formatDuration } from '../../utils/formatters';\nimport type { CartMenuItem, InvestmentOpportunity } from '../../types';\n\ninterface CartItem {\n id: string;\n productId: string;\n name: string;\n price: number;\n quantity: number;\n specialInstructions?: string;\n}\n\ninterface CustomizationState {\n product: CartMenuItem;\n quantity: number;\n specialInstructions: string;\n}\n\nconst DAY_LABELS: Record<string, string> = {\n monday: 'Mon',\n tuesday: 'Tue',\n wednesday: 'Wed',\n thursday: 'Thu',\n friday: 'Fri',\n saturday: 'Sat',\n sunday: 'Sun',\n};\n\nexport function CartDetailPage() {\n const { cartId } = useParams<{ cartId: string }>();\n const { navigateTo } = useAdapterCloud();\n\n const { data: providers = [], isLoading: isLoadingProviders } = useProviders();\n const { data: offerings = [], isLoading: isLoadingOfferings } = useOfferings(cartId);\n const { data: investments = [], isLoading: isLoadingInvestments } = useInvestmentOpportunities();\n\n const cart = useMemo(() => providers.find((p) => p.id === cartId), [providers, cartId]);\n const investment = useMemo(\n () => investments.find((i) => i.cartId === cartId),\n [investments, cartId]\n );\n\n const [searchQuery, setSearchQuery] = useState('');\n const [selectedCategory, setSelectedCategory] = useState('');\n const [cartItems, setCartItems] = useState<CartItem[]>([]);\n const [showCustomization, setShowCustomization] = useState(false);\n const [customization, setCustomization] = useState<CustomizationState | null>(null);\n\n const menuItems = useMemo(\n () =>\n offerings.map((o) => ({\n id: o.id,\n name: o.name,\n price: o.price,\n description: o.description,\n image: o.media?.[0] || 'https://images.unsplash.com/photo-1567620905732-2d1ec7ab7445?w=400',\n category: o.category,\n isVeg: true,\n duration: o.durationMinutes,\n serviceType: o.serviceType,\n })),\n [offerings]\n );\n\n const menuCategories = useMemo(() => {\n const cats = [...new Set(menuItems.map((item) => item.category))];\n return cats;\n }, [menuItems]);\n\n const filteredMenu = useMemo(() => {\n let items = menuItems;\n\n if (selectedCategory) {\n items = items.filter((item) => item.category === selectedCategory);\n }\n\n if (searchQuery.trim()) {\n const q = searchQuery.toLowerCase();\n items = items.filter(\n (item) => item.name.toLowerCase().includes(q) || item.description.toLowerCase().includes(q)\n );\n }\n\n return items;\n }, [menuItems, selectedCategory, searchQuery]);\n\n const isLoading = isLoadingProviders || isLoadingOfferings || isLoadingInvestments;\n\n const groupedMenu = useMemo(() => {\n const groups: Record<string, CartMenuItem[]> = {};\n filteredMenu.forEach((item) => {\n if (!groups[item.category]) groups[item.category] = [];\n groups[item.category].push(item);\n });\n return groups;\n }, [filteredMenu]);\n\n // Cart operations\n const addToCart = (product: CartMenuItem, qty: number = 1, instructions?: string) => {\n setCartItems((prev) => {\n const existing = prev.find((item) => item.productId === product.id);\n if (existing) {\n return prev.map((item) =>\n item.productId === product.id ? { ...item, quantity: item.quantity + qty } : item\n );\n }\n return [\n ...prev,\n {\n id: `cart-${Date.now()}`,\n productId: product.id,\n name: product.name,\n price: product.price,\n quantity: qty,\n specialInstructions: instructions,\n },\n ];\n });\n };\n\n const updateQuantity = (productId: string, delta: number) => {\n setCartItems((prev) =>\n prev\n .map((item) =>\n item.productId === productId\n ? { ...item, quantity: Math.max(0, item.quantity + delta) }\n : item\n )\n .filter((item) => item.quantity > 0)\n );\n };\n\n const removeFromCart = (productId: string) => {\n setCartItems((prev) => prev.filter((item) => item.productId !== productId));\n };\n\n const getItemQuantity = (productId: string) => {\n return cartItems.find((item) => item.productId === productId)?.quantity ?? 0;\n };\n\n const cartTotal = cartItems.reduce((sum, item) => sum + item.price * item.quantity, 0);\n const cartCount = cartItems.reduce((sum, item) => sum + item.quantity, 0);\n\n const handleAddToCart = (product: CartMenuItem) => {\n setCustomization({ product, quantity: 1, specialInstructions: '' });\n setShowCustomization(true);\n };\n\n const confirmAddToCart = () => {\n if (!customization) return;\n addToCart(customization.product, customization.quantity, customization.specialInstructions);\n setShowCustomization(false);\n setCustomization(null);\n alert(`${customization.product.name} added to cart`);\n };\n\n if (!cart) {\n return (\n <PageLayout title=\"Cart Not Found\">\n <EmptyState\n icon={<ShoppingCart className=\"h-12 w-12\" />}\n title=\"Cart not found\"\n description={`No cart found with ID \"${cartId}\".`}\n action={\n <button\n type=\"button\"\n onClick={() => navigateTo('/customer/carts')}\n className=\"rounded-lg bg-foreground px-4 py-2 text-sm font-medium text-background hover:opacity-90 transition-opacity\"\n >\n Browse Carts\n </button>\n }\n />\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title={\n <div className=\"flex items-center gap-3\">\n <button\n type=\"button\"\n onClick={() => navigateTo('/customer/carts')}\n className=\"rounded-md p-1 text-muted-foreground hover:bg-accent hover:text-foreground transition-colors\"\n >\n <ArrowLeft className=\"h-5 w-5\" />\n </button>\n <span className=\"truncate\">{cart.name}</span>\n {cart.isVerified && <CheckCircle2 className=\"h-5 w-5 text-blue-500 shrink-0\" />}\n </div>\n }\n description={cart.category}\n >\n {/* Hero Image */}\n <div className=\"relative h-48 rounded-lg bg-muted overflow-hidden\">\n <img src={cart.image} alt={cart.name} className=\"h-full w-full object-cover\" />\n <div className=\"absolute bottom-0 inset-x-0 bg-gradient-to-t from-black/60 to-transparent p-4\">\n <div className=\"flex items-center gap-3\">\n <span\n className={cn(\n 'inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium',\n cart.isOpen ? 'bg-green-500/20 text-green-300' : 'bg-red-500/20 text-red-300'\n )}\n >\n {cart.isOpen ? 'Open Now' : 'Closed'}\n </span>\n <div className=\"flex items-center gap-1 text-white text-sm\">\n <Star className=\"h-3.5 w-3.5 fill-yellow-400 text-yellow-400\" />\n <span className=\"font-medium\">{cart.rating}</span>\n <span className=\"text-white/70\">({cart.totalRatings})</span>\n </div>\n </div>\n </div>\n </div>\n\n {/* Cart Closed Warning */}\n {!cart.isOpen && (\n <div className=\"mt-4 rounded-lg border border-yellow-500/30 bg-yellow-500/10 p-3\">\n <p className=\"text-sm text-yellow-700 dark:text-yellow-400\">\n <strong>This cart is currently closed.</strong> You can browse the offerings but orders\n are not being accepted.\n </p>\n </div>\n )}\n\n {/* Info Row */}\n <div className=\"mt-4 grid grid-cols-1 gap-3 sm:grid-cols-3\">\n <div className=\"rounded-lg border border-border bg-card p-3\">\n <div className=\"flex items-center gap-2 text-muted-foreground text-xs mb-1\">\n <MapPin className=\"h-3.5 w-3.5\" />\n <span className=\"font-medium uppercase tracking-wider\">Location</span>\n </div>\n <p className=\"text-sm text-foreground\">{cart.location.address}</p>\n <p className=\"text-xs text-muted-foreground\">{formatDistance(cart.distance)} away</p>\n </div>\n <div className=\"rounded-lg border border-border bg-card p-3\">\n <div className=\"flex items-center gap-2 text-muted-foreground text-xs mb-1\">\n <Clock className=\"h-3.5 w-3.5\" />\n <span className=\"font-medium uppercase tracking-wider\">Estimated Time</span>\n </div>\n <p className=\"text-sm text-foreground\">{formatDuration(cart.estimatedTime)}</p>\n {cart.averageOrderValue && (\n <p className=\"text-xs text-muted-foreground\">\n Avg {formatCurrency(cart.averageOrderValue, { minimumFractionDigits: 0 })}\n </p>\n )}\n </div>\n <div className=\"rounded-lg border border-border bg-card p-3\">\n <div className=\"flex items-center gap-2 text-muted-foreground text-xs mb-1\">\n <Star className=\"h-3.5 w-3.5\" />\n <span className=\"font-medium uppercase tracking-wider\">Rating</span>\n </div>\n <p className=\"text-sm text-foreground\">{cart.rating} / 5.0</p>\n <p className=\"text-xs text-muted-foreground\">{cart.totalRatings} reviews</p>\n </div>\n </div>\n\n {/* Business Hours */}\n {cart.businessHours && Object.keys(cart.businessHours).length > 0 && (\n <section className=\"mt-6\">\n <h2 className=\"text-base font-semibold text-foreground mb-2\">Operating Hours</h2>\n <div className=\"rounded-lg border border-border bg-card overflow-hidden\">\n {Object.entries(cart.businessHours).map(([day, hours]) => (\n <div\n key={day}\n className=\"flex items-center justify-between px-4 py-2 border-b border-border last:border-b-0\"\n >\n <span className=\"text-sm font-medium text-foreground capitalize\">{day}</span>\n {hours.isOpen ? (\n <span className=\"text-sm text-muted-foreground\">\n {hours.open} - {hours.close}\n </span>\n ) : (\n <span className=\"text-sm text-destructive\">Closed</span>\n )}\n </div>\n ))}\n </div>\n </section>\n )}\n\n {/* Main Content: Menu + Sidebar */}\n <div className=\"mt-6 grid grid-cols-1 gap-6 lg:grid-cols-3\">\n {/* Menu Section */}\n <div className=\"lg:col-span-2\">\n {/* Search and Filter */}\n <div className=\"flex flex-col gap-3 sm:flex-row mb-4\">\n <div className=\"relative flex-1\">\n <Search className=\"absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground\" />\n <input\n type=\"text\"\n placeholder=\"Search offerings...\"\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n className=\"w-full rounded-lg border border-border bg-card py-2 pl-10 pr-3 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring\"\n />\n </div>\n <select\n value={selectedCategory}\n onChange={(e) => setSelectedCategory(e.target.value)}\n className=\"rounded-lg border border-border bg-card px-3 py-2 text-sm text-foreground focus:outline-none focus:ring-2 focus:ring-ring\"\n >\n <option value=\"\">All Categories</option>\n {menuCategories.map((cat) => (\n <option key={cat} value={cat}>\n {cat}\n </option>\n ))}\n </select>\n </div>\n\n {/* Menu Items */}\n <h2 className=\"text-lg font-semibold text-foreground mb-3\">\n Menu & Services ({filteredMenu.length})\n </h2>\n\n {filteredMenu.length === 0 ? (\n <div className=\"rounded-lg border border-border bg-card p-8 text-center\">\n <Search className=\"mx-auto h-10 w-10 text-muted-foreground/50\" />\n <p className=\"mt-3 text-sm text-muted-foreground\">No offerings found</p>\n </div>\n ) : (\n <div className=\"space-y-6\">\n {Object.entries(groupedMenu).map(([category, items]) => (\n <div key={category}>\n <h3 className=\"text-sm font-semibold text-foreground mb-2 px-1\">{category}</h3>\n <div className=\"space-y-2\">\n {items.map((item) => {\n const qty = getItemQuantity(item.id);\n return (\n <div\n key={item.id}\n className=\"flex gap-4 rounded-lg border border-border bg-card p-4\"\n >\n <div className=\"h-20 w-20 shrink-0 rounded-md bg-muted overflow-hidden\">\n <img\n src={item.image}\n alt={item.name}\n className=\"h-full w-full object-cover\"\n />\n </div>\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-start justify-between gap-2\">\n <div>\n <div className=\"flex items-center gap-2\">\n <h4 className=\"text-sm font-semibold text-foreground\">\n {item.name}\n </h4>\n {item.isVeg && (\n <Leaf className=\"h-3.5 w-3.5 text-green-600 dark:text-green-400\" />\n )}\n </div>\n <p className=\"text-xs text-muted-foreground mt-0.5\">\n {item.category}\n </p>\n </div>\n <span className=\"text-sm font-bold text-foreground whitespace-nowrap\">\n {formatCurrency(item.price, { minimumFractionDigits: 0 })}\n </span>\n </div>\n <p className=\"mt-1 text-xs text-muted-foreground line-clamp-2\">\n {item.description}\n </p>\n <div className=\"mt-2 flex flex-wrap items-center gap-2 text-[10px] text-muted-foreground\">\n {item.duration != null && item.duration > 0 && (\n <span className=\"flex items-center gap-0.5\">\n <Clock className=\"h-3 w-3\" />\n {formatDuration(item.duration)}\n </span>\n )}\n {item.serviceType && (\n <span className=\"rounded bg-muted px-1.5 py-0.5 capitalize\">\n {item.serviceType}\n </span>\n )}\n {item.spiceLevel && (\n <span className=\"flex items-center gap-0.5 rounded bg-muted px-1.5 py-0.5 capitalize\">\n <Flame className=\"h-3 w-3\" />\n {item.spiceLevel}\n </span>\n )}\n </div>\n {/* Add/Quantity Controls */}\n <div className=\"mt-2 flex justify-end\">\n {qty > 0 ? (\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n onClick={() => updateQuantity(item.id, -1)}\n className=\"flex h-7 w-7 items-center justify-center rounded-full bg-muted text-foreground hover:bg-accent\"\n >\n <Minus className=\"h-3.5 w-3.5\" />\n </button>\n <span className=\"min-w-[2ch] text-center text-sm font-medium text-foreground\">\n {qty}\n </span>\n <button\n type=\"button\"\n onClick={() => updateQuantity(item.id, 1)}\n className=\"flex h-7 w-7 items-center justify-center rounded-full bg-foreground text-background hover:opacity-90\"\n >\n <Plus className=\"h-3.5 w-3.5\" />\n </button>\n <button\n type=\"button\"\n onClick={() => removeFromCart(item.id)}\n className=\"ml-1 flex h-7 w-7 items-center justify-center rounded-full text-destructive hover:bg-destructive/10\"\n >\n <X className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n ) : (\n <button\n type=\"button\"\n disabled={!cart.isOpen}\n onClick={() => handleAddToCart(item)}\n className={cn(\n 'rounded-lg px-4 py-1.5 text-xs font-medium transition-opacity',\n cart.isOpen\n ? 'bg-foreground text-background hover:opacity-90'\n : 'bg-muted text-muted-foreground cursor-not-allowed'\n )}\n >\n Add\n </button>\n )}\n </div>\n </div>\n </div>\n );\n })}\n </div>\n </div>\n ))}\n </div>\n )}\n </div>\n\n {/* Sidebar */}\n <div className=\"space-y-4\">\n {/* Shopping Cart */}\n <div className=\"rounded-lg border border-border bg-card p-4 lg:sticky lg:top-6\">\n <h3 className=\"text-base font-semibold text-foreground mb-3 flex items-center gap-2\">\n <ShoppingCart className=\"h-4 w-4\" />\n Your Order\n </h3>\n {cartItems.length === 0 ? (\n <div className=\"py-6 text-center\">\n <ShoppingCart className=\"mx-auto h-8 w-8 text-muted-foreground/40\" />\n <p className=\"mt-2 text-sm text-muted-foreground\">Your cart is empty</p>\n </div>\n ) : (\n <>\n <div className=\"space-y-2 max-h-64 overflow-y-auto mb-3\">\n {cartItems.map((item) => (\n <div key={item.id} className=\"flex items-center justify-between gap-2\">\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-sm font-medium text-foreground truncate\">{item.name}</p>\n <p className=\"text-xs text-muted-foreground\">\n {formatCurrency(item.price, { minimumFractionDigits: 0 })} x{' '}\n {item.quantity}\n </p>\n </div>\n <div className=\"flex items-center gap-1\">\n <button\n type=\"button\"\n onClick={() => updateQuantity(item.productId, -1)}\n className=\"flex h-6 w-6 items-center justify-center rounded bg-muted text-foreground text-xs\"\n >\n -\n </button>\n <span className=\"min-w-[2ch] text-center text-xs font-medium\">\n {item.quantity}\n </span>\n <button\n type=\"button\"\n onClick={() => updateQuantity(item.productId, 1)}\n className=\"flex h-6 w-6 items-center justify-center rounded bg-muted text-foreground text-xs\"\n >\n +\n </button>\n <button\n type=\"button\"\n onClick={() => removeFromCart(item.productId)}\n className=\"ml-1 text-destructive hover:text-destructive/80\"\n >\n <X className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n </div>\n ))}\n </div>\n <div className=\"border-t border-border pt-3\">\n <div className=\"flex justify-between items-center mb-3\">\n <span className=\"text-sm font-semibold text-foreground\">\n Total: {formatCurrency(cartTotal, { minimumFractionDigits: 0 })}\n </span>\n <span className=\"text-xs text-muted-foreground\">{cartCount} items</span>\n </div>\n <button\n type=\"button\"\n onClick={() => navigateTo('/customer/checkout')}\n className=\"w-full rounded-lg bg-foreground py-2.5 text-sm font-medium text-background hover:opacity-90 transition-opacity\"\n >\n Proceed to Checkout\n </button>\n </div>\n </>\n )}\n </div>\n\n {/* Direct Service Card */}\n {cart.serviceTypes?.includes('direct_service') && (\n <div className=\"rounded-lg border border-purple-500/30 bg-purple-500/10 p-4\">\n <h3 className=\"text-sm font-semibold text-foreground flex items-center gap-2 mb-2\">\n <Home className=\"h-4 w-4 text-purple-600 dark:text-purple-400\" />\n Direct Service\n </h3>\n <p className=\"text-xs text-muted-foreground mb-3\">Cart comes to your location!</p>\n <button\n type=\"button\"\n onClick={() => navigateTo(`/customer/carts/${cart.id}`)}\n className=\"w-full rounded-lg bg-purple-600 py-2 text-xs font-medium text-white hover:bg-purple-700 transition-colors\"\n >\n Book Direct Service\n </button>\n </div>\n )}\n\n {/* Scheduled Stops */}\n {cart.serviceTypes?.includes('appointment') && (\n <div className=\"rounded-lg border border-blue-500/30 bg-blue-500/10 p-4\">\n <h3 className=\"text-sm font-semibold text-foreground flex items-center gap-2 mb-2\">\n <Calendar className=\"h-4 w-4 text-blue-600 dark:text-blue-400\" />\n Appointments Available\n </h3>\n <p className=\"text-xs text-muted-foreground\">\n This service provider accepts appointments. Contact them to schedule.\n </p>\n </div>\n )}\n\n {/* Investment Opportunity */}\n {investment && (\n <div className=\"rounded-lg border border-green-500/30 bg-green-500/10 p-4\">\n <h3 className=\"text-sm font-semibold text-foreground flex items-center gap-2 mb-2\">\n <TrendingUp className=\"h-4 w-4 text-green-600 dark:text-green-400\" />\n Investment Opportunity\n </h3>\n <p className=\"text-xs text-muted-foreground mb-2\">{investment.description}</p>\n <div className=\"space-y-1 text-xs text-muted-foreground mb-3\">\n <p>\n Target: {formatCurrency(investment.targetAmount, { minimumFractionDigits: 0 })}\n </p>\n <p>\n Raised: {formatCurrency(investment.raisedAmount, { minimumFractionDigits: 0 })}\n </p>\n <p>Expected Returns: {investment.expectedReturns}%</p>\n <p>\n Min Investment:{' '}\n {formatCurrency(investment.minimumInvestment, { minimumFractionDigits: 0 })}\n </p>\n </div>\n <button\n type=\"button\"\n onClick={() => alert('Navigate to investor section to fund this business.')}\n className=\"w-full rounded-lg bg-green-600 py-2 text-xs font-medium text-white hover:bg-green-700 transition-colors\"\n >\n Fund This Business\n </button>\n </div>\n )}\n </div>\n </div>\n\n {/* Customization Modal */}\n {showCustomization && customization && (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4\">\n <div className=\"w-full max-w-md max-h-[90vh] overflow-y-auto rounded-lg border border-border bg-card\">\n <div className=\"p-5\">\n <div className=\"flex items-center justify-between mb-4\">\n <h3 className=\"text-lg font-semibold text-foreground\">\n {customization.product.name}\n </h3>\n <button\n type=\"button\"\n onClick={() => {\n setShowCustomization(false);\n setCustomization(null);\n }}\n className=\"rounded-md p-1 text-muted-foreground hover:text-foreground\"\n >\n <X className=\"h-5 w-5\" />\n </button>\n </div>\n\n <p className=\"text-sm text-muted-foreground mb-4\">\n {customization.product.description}\n </p>\n <p className=\"text-lg font-bold text-foreground mb-4\">\n {formatCurrency(customization.product.price, { minimumFractionDigits: 0 })}\n </p>\n\n {/* Quantity */}\n <div className=\"mb-4\">\n <label className=\"block text-sm font-medium text-foreground mb-2\">Quantity</label>\n <div className=\"flex items-center gap-3\">\n <button\n type=\"button\"\n onClick={() =>\n setCustomization((prev) =>\n prev ? { ...prev, quantity: Math.max(1, prev.quantity - 1) } : prev\n )\n }\n className=\"flex h-8 w-8 items-center justify-center rounded-full bg-muted text-foreground\"\n >\n <Minus className=\"h-4 w-4\" />\n </button>\n <span className=\"min-w-[2ch] text-center font-medium text-foreground\">\n {customization.quantity}\n </span>\n <button\n type=\"button\"\n onClick={() =>\n setCustomization((prev) =>\n prev ? { ...prev, quantity: prev.quantity + 1 } : prev\n )\n }\n className=\"flex h-8 w-8 items-center justify-center rounded-full bg-muted text-foreground\"\n >\n <Plus className=\"h-4 w-4\" />\n </button>\n </div>\n </div>\n\n {/* Special Instructions */}\n <div className=\"mb-4\">\n <label className=\"block text-sm font-medium text-foreground mb-2\">\n Special Instructions\n </label>\n <textarea\n value={customization.specialInstructions}\n onChange={(e) =>\n setCustomization((prev) =>\n prev ? { ...prev, specialInstructions: e.target.value } : prev\n )\n }\n placeholder=\"Any special requests...\"\n className=\"w-full rounded-lg border border-border bg-background p-3 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring\"\n rows={3}\n />\n </div>\n\n <button\n type=\"button\"\n onClick={confirmAddToCart}\n className=\"w-full rounded-lg bg-foreground py-2.5 text-sm font-medium text-background hover:opacity-90 transition-opacity\"\n >\n Add to Cart -{' '}\n {formatCurrency(customization.product.price * customization.quantity, {\n minimumFractionDigits: 0,\n })}\n </button>\n </div>\n </div>\n </div>\n )}\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,547 @@
|
|
|
1
|
+
import { useAdapterCloud as e } from "../../context/AdapterCloudContext.js";
|
|
2
|
+
import { cn as t } from "../../utils/cn.js";
|
|
3
|
+
import { PageLayout as n } from "../../components/PageLayout.js";
|
|
4
|
+
import { EmptyState as r } from "../../components/EmptyState.js";
|
|
5
|
+
import { useInvestmentOpportunities as i, useProviders as a } from "../../hooks/useAdapterCloudApi.js";
|
|
6
|
+
import { formatCurrency as o, formatDistance as s } from "../../utils/formatters.js";
|
|
7
|
+
import { useMemo as c, useState as l } from "react";
|
|
8
|
+
import { AlertCircle as u, Calendar as d, CheckCircle2 as f, Clock as p, Home as m, Info as h, Loader2 as g, MapPin as _, Search as v, Star as y, Tag as b, TrendingUp as x, X as S } from "lucide-react";
|
|
9
|
+
import { Fragment as C, jsx as w, jsxs as T } from "react/jsx-runtime";
|
|
10
|
+
//#region src/adaptercloud/pages/customer/CartDiscoveryPage.tsx
|
|
11
|
+
var E = "All";
|
|
12
|
+
function D() {
|
|
13
|
+
let { navigateTo: D } = e(), [O, k] = l(""), [A, j] = l(E), [M, N] = l(""), [P, F] = l(""), [I, L] = l("rating"), [R, z] = l(9), [B, V] = l(!1), [H, U] = l(null), { data: W = [], isLoading: G, isError: K } = a(), { data: q = [] } = i(), J = c(() => {
|
|
14
|
+
let e = /* @__PURE__ */ new Set();
|
|
15
|
+
return W.forEach((t) => {
|
|
16
|
+
t.category && e.add(t.category);
|
|
17
|
+
}), [E, ...Array.from(e)];
|
|
18
|
+
}, [W]), Y = c(() => {
|
|
19
|
+
let e = [...W];
|
|
20
|
+
if (O.trim()) {
|
|
21
|
+
let t = O.toLowerCase();
|
|
22
|
+
e = e.filter((e) => e.name.toLowerCase().includes(t) || e.category.toLowerCase().includes(t));
|
|
23
|
+
}
|
|
24
|
+
if (A !== E && (e = e.filter((e) => e.category === A)), M) {
|
|
25
|
+
let t = parseFloat(M);
|
|
26
|
+
e = e.filter((e) => e.rating >= t);
|
|
27
|
+
}
|
|
28
|
+
switch (P && (e = e.filter((e) => {
|
|
29
|
+
let t = e.averageOrderValue ?? 0;
|
|
30
|
+
switch (P) {
|
|
31
|
+
case "low": return t <= 300;
|
|
32
|
+
case "medium": return t > 300 && t <= 800;
|
|
33
|
+
case "high": return t > 800;
|
|
34
|
+
default: return !0;
|
|
35
|
+
}
|
|
36
|
+
})), I) {
|
|
37
|
+
case "rating":
|
|
38
|
+
e.sort((e, t) => t.rating - e.rating);
|
|
39
|
+
break;
|
|
40
|
+
case "popularity":
|
|
41
|
+
e.sort((e, t) => (t.totalRatings || 0) - (e.totalRatings || 0));
|
|
42
|
+
break;
|
|
43
|
+
case "distance":
|
|
44
|
+
e.sort((e, t) => (e.distance || 0) - (t.distance || 0));
|
|
45
|
+
break;
|
|
46
|
+
case "newest":
|
|
47
|
+
e.sort((e, t) => new Date(t.createdAt || 0).getTime() - new Date(e.createdAt || 0).getTime());
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
return e;
|
|
51
|
+
}, [
|
|
52
|
+
W,
|
|
53
|
+
O,
|
|
54
|
+
A,
|
|
55
|
+
M,
|
|
56
|
+
P,
|
|
57
|
+
I
|
|
58
|
+
]), X = Y.slice(0, R), Z = R < Y.length, Q = A !== E || M !== "" || P !== "" || O.trim() !== "", $ = () => {
|
|
59
|
+
k(""), j(E), N(""), F(""), L("rating"), z(9);
|
|
60
|
+
};
|
|
61
|
+
return G ? /* @__PURE__ */ w(n, {
|
|
62
|
+
title: "Discover Carts",
|
|
63
|
+
description: "Finding services and shops near you...",
|
|
64
|
+
children: /* @__PURE__ */ w("div", {
|
|
65
|
+
className: "flex h-[60vh] items-center justify-center",
|
|
66
|
+
children: /* @__PURE__ */ w(g, { className: "h-8 w-8 animate-spin text-primary" })
|
|
67
|
+
})
|
|
68
|
+
}) : K ? /* @__PURE__ */ w(n, {
|
|
69
|
+
title: "Discover Carts",
|
|
70
|
+
description: "Error loading carts",
|
|
71
|
+
children: /* @__PURE__ */ T("div", {
|
|
72
|
+
className: "flex h-[60vh] flex-col items-center justify-center gap-4",
|
|
73
|
+
children: [
|
|
74
|
+
/* @__PURE__ */ w(u, { className: "h-12 w-12 text-destructive" }),
|
|
75
|
+
/* @__PURE__ */ w("h2", {
|
|
76
|
+
className: "text-xl font-semibold",
|
|
77
|
+
children: "Error loading service providers"
|
|
78
|
+
}),
|
|
79
|
+
/* @__PURE__ */ w("button", {
|
|
80
|
+
type: "button",
|
|
81
|
+
onClick: () => window.location.reload(),
|
|
82
|
+
className: "rounded-lg bg-primary px-4 py-2 text-sm font-medium text-primary-foreground",
|
|
83
|
+
children: "Retry"
|
|
84
|
+
})
|
|
85
|
+
]
|
|
86
|
+
})
|
|
87
|
+
}) : /* @__PURE__ */ T(n, {
|
|
88
|
+
title: "Discover Carts",
|
|
89
|
+
description: "Find services and shops near you",
|
|
90
|
+
actions: /* @__PURE__ */ T("span", {
|
|
91
|
+
className: "text-sm text-muted-foreground",
|
|
92
|
+
children: [Y.length, " carts found"]
|
|
93
|
+
}),
|
|
94
|
+
children: [
|
|
95
|
+
/* @__PURE__ */ T("div", {
|
|
96
|
+
className: "relative",
|
|
97
|
+
children: [
|
|
98
|
+
/* @__PURE__ */ w(v, { className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
|
|
99
|
+
/* @__PURE__ */ w("input", {
|
|
100
|
+
type: "text",
|
|
101
|
+
placeholder: "Search carts, services, or items...",
|
|
102
|
+
value: O,
|
|
103
|
+
onChange: (e) => k(e.target.value),
|
|
104
|
+
className: t("w-full rounded-lg border border-border bg-card py-2.5 pl-10 pr-10 text-sm text-foreground", "placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring")
|
|
105
|
+
}),
|
|
106
|
+
O && /* @__PURE__ */ w("button", {
|
|
107
|
+
type: "button",
|
|
108
|
+
onClick: () => k(""),
|
|
109
|
+
className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
|
|
110
|
+
children: /* @__PURE__ */ w(S, { className: "h-4 w-4" })
|
|
111
|
+
})
|
|
112
|
+
]
|
|
113
|
+
}),
|
|
114
|
+
/* @__PURE__ */ w("div", {
|
|
115
|
+
className: "mt-4 flex flex-wrap gap-2",
|
|
116
|
+
children: J.map((e) => /* @__PURE__ */ w("button", {
|
|
117
|
+
type: "button",
|
|
118
|
+
onClick: () => j(e),
|
|
119
|
+
className: t("rounded-full px-3 py-1.5 text-xs font-medium transition-colors", A === e ? "bg-foreground text-background" : "bg-muted text-muted-foreground hover:bg-accent hover:text-foreground"),
|
|
120
|
+
children: e
|
|
121
|
+
}, e))
|
|
122
|
+
}),
|
|
123
|
+
/* @__PURE__ */ T("div", {
|
|
124
|
+
className: "mt-4 flex flex-wrap items-center gap-3",
|
|
125
|
+
children: [
|
|
126
|
+
/* @__PURE__ */ T("select", {
|
|
127
|
+
value: M,
|
|
128
|
+
onChange: (e) => N(e.target.value),
|
|
129
|
+
className: "rounded-lg border border-border bg-card px-3 py-2 text-xs text-foreground focus:outline-none focus:ring-2 focus:ring-ring",
|
|
130
|
+
children: [
|
|
131
|
+
/* @__PURE__ */ w("option", {
|
|
132
|
+
value: "",
|
|
133
|
+
children: "Any Rating"
|
|
134
|
+
}),
|
|
135
|
+
/* @__PURE__ */ w("option", {
|
|
136
|
+
value: "4.5",
|
|
137
|
+
children: "4.5+ Stars"
|
|
138
|
+
}),
|
|
139
|
+
/* @__PURE__ */ w("option", {
|
|
140
|
+
value: "4.0",
|
|
141
|
+
children: "4.0+ Stars"
|
|
142
|
+
}),
|
|
143
|
+
/* @__PURE__ */ w("option", {
|
|
144
|
+
value: "3.5",
|
|
145
|
+
children: "3.5+ Stars"
|
|
146
|
+
})
|
|
147
|
+
]
|
|
148
|
+
}),
|
|
149
|
+
/* @__PURE__ */ T("select", {
|
|
150
|
+
value: P,
|
|
151
|
+
onChange: (e) => F(e.target.value),
|
|
152
|
+
className: "rounded-lg border border-border bg-card px-3 py-2 text-xs text-foreground focus:outline-none focus:ring-2 focus:ring-ring",
|
|
153
|
+
children: [
|
|
154
|
+
/* @__PURE__ */ w("option", {
|
|
155
|
+
value: "",
|
|
156
|
+
children: "Any Price"
|
|
157
|
+
}),
|
|
158
|
+
/* @__PURE__ */ w("option", {
|
|
159
|
+
value: "low",
|
|
160
|
+
children: "Under ₹300"
|
|
161
|
+
}),
|
|
162
|
+
/* @__PURE__ */ w("option", {
|
|
163
|
+
value: "medium",
|
|
164
|
+
children: "₹300 - ₹800"
|
|
165
|
+
}),
|
|
166
|
+
/* @__PURE__ */ w("option", {
|
|
167
|
+
value: "high",
|
|
168
|
+
children: "₹800+"
|
|
169
|
+
})
|
|
170
|
+
]
|
|
171
|
+
}),
|
|
172
|
+
/* @__PURE__ */ T("select", {
|
|
173
|
+
value: I,
|
|
174
|
+
onChange: (e) => L(e.target.value),
|
|
175
|
+
className: "rounded-lg border border-border bg-card px-3 py-2 text-xs text-foreground focus:outline-none focus:ring-2 focus:ring-ring",
|
|
176
|
+
children: [
|
|
177
|
+
/* @__PURE__ */ w("option", {
|
|
178
|
+
value: "rating",
|
|
179
|
+
children: "Highest Rated"
|
|
180
|
+
}),
|
|
181
|
+
/* @__PURE__ */ w("option", {
|
|
182
|
+
value: "popularity",
|
|
183
|
+
children: "Most Popular"
|
|
184
|
+
}),
|
|
185
|
+
/* @__PURE__ */ w("option", {
|
|
186
|
+
value: "distance",
|
|
187
|
+
children: "Nearest"
|
|
188
|
+
}),
|
|
189
|
+
/* @__PURE__ */ w("option", {
|
|
190
|
+
value: "newest",
|
|
191
|
+
children: "Newest"
|
|
192
|
+
})
|
|
193
|
+
]
|
|
194
|
+
}),
|
|
195
|
+
Q && /* @__PURE__ */ w("button", {
|
|
196
|
+
type: "button",
|
|
197
|
+
onClick: $,
|
|
198
|
+
className: "rounded-lg border border-border px-3 py-2 text-xs font-medium text-muted-foreground hover:text-foreground transition-colors",
|
|
199
|
+
children: "Clear All Filters"
|
|
200
|
+
})
|
|
201
|
+
]
|
|
202
|
+
}),
|
|
203
|
+
X.length > 0 ? /* @__PURE__ */ T(C, { children: [/* @__PURE__ */ w("div", {
|
|
204
|
+
className: "mt-6 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3",
|
|
205
|
+
children: X.map((e) => {
|
|
206
|
+
let n = q.find((t) => t.cartId === e.id);
|
|
207
|
+
return /* @__PURE__ */ T("div", {
|
|
208
|
+
className: "rounded-lg border border-border bg-card shadow-sm overflow-hidden hover:shadow-md transition-shadow flex flex-col",
|
|
209
|
+
children: [/* @__PURE__ */ T("div", {
|
|
210
|
+
className: "relative h-40 bg-muted",
|
|
211
|
+
children: [
|
|
212
|
+
/* @__PURE__ */ w("img", {
|
|
213
|
+
src: e.image,
|
|
214
|
+
alt: e.name,
|
|
215
|
+
className: "h-full w-full object-cover"
|
|
216
|
+
}),
|
|
217
|
+
/* @__PURE__ */ T("div", {
|
|
218
|
+
className: "absolute top-2 left-2 flex gap-1.5",
|
|
219
|
+
children: [/* @__PURE__ */ w("span", {
|
|
220
|
+
className: t("inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium backdrop-blur-sm", e.isOpen ? "bg-green-500/20 text-green-600 dark:text-green-400" : "bg-red-500/20 text-red-600 dark:text-red-400"),
|
|
221
|
+
children: e.isOpen ? "Open" : "Closed"
|
|
222
|
+
}), e.isVerified && /* @__PURE__ */ T("span", {
|
|
223
|
+
className: "inline-flex items-center gap-0.5 rounded-full bg-blue-500/20 px-2 py-0.5 text-xs font-medium text-blue-600 dark:text-blue-400 backdrop-blur-sm",
|
|
224
|
+
children: [/* @__PURE__ */ w(f, { className: "h-3 w-3" }), "Verified"]
|
|
225
|
+
})]
|
|
226
|
+
}),
|
|
227
|
+
/* @__PURE__ */ w("div", {
|
|
228
|
+
className: "absolute top-2 right-2",
|
|
229
|
+
children: /* @__PURE__ */ T("span", {
|
|
230
|
+
className: "rounded-full bg-black/50 px-2 py-0.5 text-xs text-white backdrop-blur-sm",
|
|
231
|
+
children: [e.estimatedTime, " min"]
|
|
232
|
+
})
|
|
233
|
+
})
|
|
234
|
+
]
|
|
235
|
+
}), /* @__PURE__ */ T("div", {
|
|
236
|
+
className: "flex flex-col flex-1 p-4",
|
|
237
|
+
children: [
|
|
238
|
+
/* @__PURE__ */ T("div", {
|
|
239
|
+
className: "flex items-start justify-between gap-2 mb-1",
|
|
240
|
+
children: [/* @__PURE__ */ w("h3", {
|
|
241
|
+
className: "text-sm font-semibold text-foreground truncate flex-1",
|
|
242
|
+
children: e.name
|
|
243
|
+
}), /* @__PURE__ */ T("div", {
|
|
244
|
+
className: "flex items-center gap-1 shrink-0",
|
|
245
|
+
children: [
|
|
246
|
+
/* @__PURE__ */ w(y, { className: "h-3.5 w-3.5 fill-yellow-400 text-yellow-400" }),
|
|
247
|
+
/* @__PURE__ */ w("span", {
|
|
248
|
+
className: "text-xs font-medium text-foreground",
|
|
249
|
+
children: e.rating
|
|
250
|
+
}),
|
|
251
|
+
/* @__PURE__ */ T("span", {
|
|
252
|
+
className: "text-xs text-muted-foreground",
|
|
253
|
+
children: [
|
|
254
|
+
"(",
|
|
255
|
+
e.totalRatings,
|
|
256
|
+
")"
|
|
257
|
+
]
|
|
258
|
+
})
|
|
259
|
+
]
|
|
260
|
+
})]
|
|
261
|
+
}),
|
|
262
|
+
/* @__PURE__ */ w("p", {
|
|
263
|
+
className: "text-xs text-muted-foreground mb-2",
|
|
264
|
+
children: e.category
|
|
265
|
+
}),
|
|
266
|
+
/* @__PURE__ */ w("div", {
|
|
267
|
+
className: "flex items-center gap-3 text-xs text-muted-foreground mb-2",
|
|
268
|
+
children: /* @__PURE__ */ T("span", {
|
|
269
|
+
className: "flex items-center gap-1",
|
|
270
|
+
children: [/* @__PURE__ */ w(_, { className: "h-3 w-3" }), e.location?.address?.split(",")[0] || "Unknown"]
|
|
271
|
+
})
|
|
272
|
+
}),
|
|
273
|
+
/* @__PURE__ */ T("div", {
|
|
274
|
+
className: "flex items-center gap-3 text-xs text-muted-foreground mb-3",
|
|
275
|
+
children: [e.averageOrderValue && /* @__PURE__ */ T("span", { children: ["Avg ", o(e.averageOrderValue, { minimumFractionDigits: 0 })] }), /* @__PURE__ */ T("span", {
|
|
276
|
+
className: "flex items-center gap-1",
|
|
277
|
+
children: [/* @__PURE__ */ w(_, { className: "h-3 w-3" }), s(e.distance)]
|
|
278
|
+
})]
|
|
279
|
+
}),
|
|
280
|
+
e.serviceTypes?.includes("appointment") && /* @__PURE__ */ w("div", {
|
|
281
|
+
className: "mb-3 rounded-md bg-blue-500/10 border border-blue-500/20 p-2",
|
|
282
|
+
children: /* @__PURE__ */ T("div", {
|
|
283
|
+
className: "flex items-center gap-1 text-xs text-blue-600 dark:text-blue-400",
|
|
284
|
+
children: [/* @__PURE__ */ w(d, { className: "h-3 w-3" }), /* @__PURE__ */ w("span", {
|
|
285
|
+
className: "font-medium",
|
|
286
|
+
children: "Appointment available"
|
|
287
|
+
})]
|
|
288
|
+
})
|
|
289
|
+
}),
|
|
290
|
+
e.serviceTypes?.includes("direct_service") && /* @__PURE__ */ w("div", {
|
|
291
|
+
className: "mb-3 rounded-md bg-purple-500/10 border border-purple-500/20 p-2",
|
|
292
|
+
children: /* @__PURE__ */ T("div", {
|
|
293
|
+
className: "flex items-center gap-1 text-xs text-purple-600 dark:text-purple-400",
|
|
294
|
+
children: [/* @__PURE__ */ w(m, { className: "h-3 w-3" }), /* @__PURE__ */ w("span", {
|
|
295
|
+
className: "font-medium",
|
|
296
|
+
children: "Direct Service Available"
|
|
297
|
+
})]
|
|
298
|
+
})
|
|
299
|
+
}),
|
|
300
|
+
e.serviceTypes && e.serviceTypes.length > 0 && /* @__PURE__ */ w("div", {
|
|
301
|
+
className: "flex flex-wrap gap-1 mb-3",
|
|
302
|
+
children: e.serviceTypes.slice(0, 3).map((e) => /* @__PURE__ */ w("span", {
|
|
303
|
+
className: "rounded-full bg-muted px-2 py-0.5 text-[10px] text-muted-foreground",
|
|
304
|
+
children: e.replace(/_/g, " ")
|
|
305
|
+
}, e))
|
|
306
|
+
}),
|
|
307
|
+
/* @__PURE__ */ T("div", {
|
|
308
|
+
className: "mt-auto flex gap-2",
|
|
309
|
+
children: [
|
|
310
|
+
/* @__PURE__ */ w("button", {
|
|
311
|
+
type: "button",
|
|
312
|
+
onClick: () => D(`/customer/cart/${e.id}`),
|
|
313
|
+
disabled: !e.isOpen,
|
|
314
|
+
className: t("flex-1 rounded-lg py-2 text-xs font-medium transition-opacity", e.isOpen ? "bg-foreground text-background hover:opacity-90" : "bg-muted text-muted-foreground cursor-not-allowed"),
|
|
315
|
+
children: e.isOpen ? "View Services" : "Closed"
|
|
316
|
+
}),
|
|
317
|
+
e.serviceTypes?.includes("direct_service") && /* @__PURE__ */ w("button", {
|
|
318
|
+
type: "button",
|
|
319
|
+
onClick: () => D(`/customer/cart/${e.id}`),
|
|
320
|
+
className: "rounded-lg border border-border px-2 py-2 text-xs text-foreground hover:bg-accent transition-colors",
|
|
321
|
+
title: "Book Direct Service",
|
|
322
|
+
children: /* @__PURE__ */ w(m, { className: "h-3.5 w-3.5" })
|
|
323
|
+
}),
|
|
324
|
+
n && /* @__PURE__ */ w("button", {
|
|
325
|
+
type: "button",
|
|
326
|
+
onClick: () => alert("Investment opportunity available! View in Investor section."),
|
|
327
|
+
className: "rounded-lg border border-green-500/30 bg-green-500/10 px-2 py-2 text-xs text-green-600 dark:text-green-400 hover:bg-green-500/20 transition-colors",
|
|
328
|
+
title: "Investment Opportunity",
|
|
329
|
+
children: /* @__PURE__ */ w(x, { className: "h-3.5 w-3.5" })
|
|
330
|
+
}),
|
|
331
|
+
/* @__PURE__ */ w("button", {
|
|
332
|
+
type: "button",
|
|
333
|
+
onClick: () => {
|
|
334
|
+
U(e), V(!0);
|
|
335
|
+
},
|
|
336
|
+
className: "rounded-lg border border-border px-2 py-2 text-xs text-foreground hover:bg-accent transition-colors",
|
|
337
|
+
title: "Cart Info",
|
|
338
|
+
children: /* @__PURE__ */ w(h, { className: "h-3.5 w-3.5" })
|
|
339
|
+
})
|
|
340
|
+
]
|
|
341
|
+
})
|
|
342
|
+
]
|
|
343
|
+
})]
|
|
344
|
+
}, e.id);
|
|
345
|
+
})
|
|
346
|
+
}), Z && /* @__PURE__ */ w("div", {
|
|
347
|
+
className: "mt-8 text-center",
|
|
348
|
+
children: /* @__PURE__ */ w("button", {
|
|
349
|
+
type: "button",
|
|
350
|
+
onClick: () => z((e) => e + 9),
|
|
351
|
+
className: "rounded-lg border border-border px-6 py-2.5 text-sm font-medium text-foreground hover:bg-accent transition-colors",
|
|
352
|
+
children: "Load More Carts"
|
|
353
|
+
})
|
|
354
|
+
})] }) : /* @__PURE__ */ w("div", {
|
|
355
|
+
className: "mt-6",
|
|
356
|
+
children: /* @__PURE__ */ w(r, {
|
|
357
|
+
icon: /* @__PURE__ */ w(v, { className: "h-12 w-12" }),
|
|
358
|
+
title: "No carts found",
|
|
359
|
+
description: O ? `No results for "${O}". Try a different search term.` : "No carts available with these filters.",
|
|
360
|
+
action: /* @__PURE__ */ w("button", {
|
|
361
|
+
type: "button",
|
|
362
|
+
onClick: $,
|
|
363
|
+
className: "rounded-lg bg-foreground px-4 py-2 text-sm font-medium text-background hover:opacity-90 transition-opacity",
|
|
364
|
+
children: "Clear Filters"
|
|
365
|
+
})
|
|
366
|
+
})
|
|
367
|
+
}),
|
|
368
|
+
B && H && /* @__PURE__ */ w("div", {
|
|
369
|
+
className: "fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4",
|
|
370
|
+
children: /* @__PURE__ */ w("div", {
|
|
371
|
+
className: "w-full max-w-2xl max-h-[90vh] overflow-y-auto rounded-lg border border-border bg-card",
|
|
372
|
+
children: /* @__PURE__ */ T("div", {
|
|
373
|
+
className: "p-5",
|
|
374
|
+
children: [
|
|
375
|
+
/* @__PURE__ */ T("div", {
|
|
376
|
+
className: "flex items-center justify-between mb-4",
|
|
377
|
+
children: [/* @__PURE__ */ w("h3", {
|
|
378
|
+
className: "text-lg font-semibold text-foreground",
|
|
379
|
+
children: "Cart Information"
|
|
380
|
+
}), /* @__PURE__ */ w("button", {
|
|
381
|
+
type: "button",
|
|
382
|
+
onClick: () => V(!1),
|
|
383
|
+
className: "rounded-md p-1 text-muted-foreground hover:text-foreground transition-colors",
|
|
384
|
+
children: /* @__PURE__ */ w(S, { className: "h-5 w-5" })
|
|
385
|
+
})]
|
|
386
|
+
}),
|
|
387
|
+
/* @__PURE__ */ w("div", {
|
|
388
|
+
className: "h-48 rounded-lg overflow-hidden mb-4",
|
|
389
|
+
children: /* @__PURE__ */ w("img", {
|
|
390
|
+
src: H.image,
|
|
391
|
+
alt: H.name,
|
|
392
|
+
className: "h-full w-full object-cover"
|
|
393
|
+
})
|
|
394
|
+
}),
|
|
395
|
+
/* @__PURE__ */ w("h4", {
|
|
396
|
+
className: "text-xl font-semibold text-foreground mb-1",
|
|
397
|
+
children: H.name
|
|
398
|
+
}),
|
|
399
|
+
/* @__PURE__ */ T("div", {
|
|
400
|
+
className: "flex flex-wrap items-center gap-3 mb-4",
|
|
401
|
+
children: [/* @__PURE__ */ T("div", {
|
|
402
|
+
className: "flex items-center gap-1",
|
|
403
|
+
children: [
|
|
404
|
+
/* @__PURE__ */ w(y, { className: "h-3.5 w-3.5 fill-yellow-400 text-yellow-400" }),
|
|
405
|
+
/* @__PURE__ */ w("span", {
|
|
406
|
+
className: "text-sm font-medium",
|
|
407
|
+
children: H.rating
|
|
408
|
+
}),
|
|
409
|
+
/* @__PURE__ */ T("span", {
|
|
410
|
+
className: "text-xs text-muted-foreground",
|
|
411
|
+
children: [
|
|
412
|
+
"(",
|
|
413
|
+
H.totalRatings,
|
|
414
|
+
" reviews)"
|
|
415
|
+
]
|
|
416
|
+
})
|
|
417
|
+
]
|
|
418
|
+
}), /* @__PURE__ */ w("span", {
|
|
419
|
+
className: t("inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium", H.isOpen ? "bg-green-500/20 text-green-600 dark:text-green-400" : "bg-red-500/20 text-red-600 dark:text-red-400"),
|
|
420
|
+
children: H.isOpen ? "Open" : "Closed"
|
|
421
|
+
})]
|
|
422
|
+
}),
|
|
423
|
+
/* @__PURE__ */ T("div", {
|
|
424
|
+
className: "grid grid-cols-1 gap-3 sm:grid-cols-2 mb-4",
|
|
425
|
+
children: [
|
|
426
|
+
/* @__PURE__ */ T("div", {
|
|
427
|
+
className: "rounded-md bg-muted p-3",
|
|
428
|
+
children: [/* @__PURE__ */ T("p", {
|
|
429
|
+
className: "text-xs font-medium text-muted-foreground flex items-center gap-1",
|
|
430
|
+
children: [/* @__PURE__ */ w(_, { className: "h-3 w-3" }), " Location"]
|
|
431
|
+
}), /* @__PURE__ */ w("p", {
|
|
432
|
+
className: "mt-1 text-sm text-foreground",
|
|
433
|
+
children: H.location.address
|
|
434
|
+
})]
|
|
435
|
+
}),
|
|
436
|
+
/* @__PURE__ */ T("div", {
|
|
437
|
+
className: "rounded-md bg-muted p-3",
|
|
438
|
+
children: [/* @__PURE__ */ T("p", {
|
|
439
|
+
className: "text-xs font-medium text-muted-foreground flex items-center gap-1",
|
|
440
|
+
children: [/* @__PURE__ */ w(b, { className: "h-3 w-3" }), " Category"]
|
|
441
|
+
}), /* @__PURE__ */ w("p", {
|
|
442
|
+
className: "mt-1 text-sm text-foreground",
|
|
443
|
+
children: H.category
|
|
444
|
+
})]
|
|
445
|
+
}),
|
|
446
|
+
H.averageOrderValue && /* @__PURE__ */ T("div", {
|
|
447
|
+
className: "rounded-md bg-muted p-3",
|
|
448
|
+
children: [/* @__PURE__ */ w("p", {
|
|
449
|
+
className: "text-xs font-medium text-muted-foreground",
|
|
450
|
+
children: "Average Order"
|
|
451
|
+
}), /* @__PURE__ */ w("p", {
|
|
452
|
+
className: "mt-1 text-sm text-foreground",
|
|
453
|
+
children: o(H.averageOrderValue, { minimumFractionDigits: 0 })
|
|
454
|
+
})]
|
|
455
|
+
}),
|
|
456
|
+
/* @__PURE__ */ T("div", {
|
|
457
|
+
className: "rounded-md bg-muted p-3",
|
|
458
|
+
children: [/* @__PURE__ */ T("p", {
|
|
459
|
+
className: "text-xs font-medium text-muted-foreground flex items-center gap-1",
|
|
460
|
+
children: [/* @__PURE__ */ w(p, { className: "h-3 w-3" }), " Estimated Time"]
|
|
461
|
+
}), /* @__PURE__ */ T("p", {
|
|
462
|
+
className: "mt-1 text-sm text-foreground",
|
|
463
|
+
children: [H.estimatedTime, " minutes"]
|
|
464
|
+
})]
|
|
465
|
+
}),
|
|
466
|
+
/* @__PURE__ */ T("div", {
|
|
467
|
+
className: "rounded-md bg-muted p-3",
|
|
468
|
+
children: [/* @__PURE__ */ w("p", {
|
|
469
|
+
className: "text-xs font-medium text-muted-foreground",
|
|
470
|
+
children: "Distance"
|
|
471
|
+
}), /* @__PURE__ */ w("p", {
|
|
472
|
+
className: "mt-1 text-sm text-foreground",
|
|
473
|
+
children: s(H.distance)
|
|
474
|
+
})]
|
|
475
|
+
}),
|
|
476
|
+
H.isVerified && /* @__PURE__ */ T("div", {
|
|
477
|
+
className: "rounded-md bg-muted p-3",
|
|
478
|
+
children: [/* @__PURE__ */ T("p", {
|
|
479
|
+
className: "text-xs font-medium text-muted-foreground flex items-center gap-1",
|
|
480
|
+
children: [/* @__PURE__ */ w(f, { className: "h-3 w-3" }), " Verification"]
|
|
481
|
+
}), /* @__PURE__ */ w("p", {
|
|
482
|
+
className: "mt-1 text-sm text-foreground",
|
|
483
|
+
children: "Verified cart"
|
|
484
|
+
})]
|
|
485
|
+
})
|
|
486
|
+
]
|
|
487
|
+
}),
|
|
488
|
+
H.serviceTypes && H.serviceTypes.length > 0 && /* @__PURE__ */ T("div", {
|
|
489
|
+
className: "mb-4",
|
|
490
|
+
children: [/* @__PURE__ */ w("p", {
|
|
491
|
+
className: "text-xs font-medium text-muted-foreground mb-2",
|
|
492
|
+
children: "Service Types"
|
|
493
|
+
}), /* @__PURE__ */ w("div", {
|
|
494
|
+
className: "flex flex-wrap gap-2",
|
|
495
|
+
children: H.serviceTypes.map((e) => /* @__PURE__ */ w("span", {
|
|
496
|
+
className: "rounded-full bg-muted px-2.5 py-1 text-xs text-muted-foreground capitalize",
|
|
497
|
+
children: e.replace(/_/g, " ")
|
|
498
|
+
}, e))
|
|
499
|
+
})]
|
|
500
|
+
}),
|
|
501
|
+
H.businessHours && Object.keys(H.businessHours).length > 0 && /* @__PURE__ */ T("div", {
|
|
502
|
+
className: "mb-4",
|
|
503
|
+
children: [/* @__PURE__ */ w("p", {
|
|
504
|
+
className: "text-xs font-medium text-muted-foreground mb-2",
|
|
505
|
+
children: "Operating Hours"
|
|
506
|
+
}), /* @__PURE__ */ w("div", {
|
|
507
|
+
className: "space-y-1",
|
|
508
|
+
children: Object.entries(H.businessHours).map(([e, t]) => /* @__PURE__ */ T("div", {
|
|
509
|
+
className: "flex justify-between text-xs",
|
|
510
|
+
children: [/* @__PURE__ */ w("span", {
|
|
511
|
+
className: "capitalize text-foreground",
|
|
512
|
+
children: e
|
|
513
|
+
}), /* @__PURE__ */ w("span", {
|
|
514
|
+
className: "text-muted-foreground",
|
|
515
|
+
children: t.isOpen ? `${t.open} - ${t.close}` : "Closed"
|
|
516
|
+
})]
|
|
517
|
+
}, e))
|
|
518
|
+
})]
|
|
519
|
+
}),
|
|
520
|
+
/* @__PURE__ */ T("div", {
|
|
521
|
+
className: "flex gap-3 mt-6",
|
|
522
|
+
children: [/* @__PURE__ */ w("button", {
|
|
523
|
+
type: "button",
|
|
524
|
+
onClick: () => {
|
|
525
|
+
V(!1), D(`/customer/carts/${H.id}`);
|
|
526
|
+
},
|
|
527
|
+
disabled: !H.isOpen,
|
|
528
|
+
className: t("flex-1 rounded-lg py-2.5 text-sm font-medium transition-opacity", H.isOpen ? "bg-foreground text-background hover:opacity-90" : "bg-muted text-muted-foreground cursor-not-allowed"),
|
|
529
|
+
children: H.isOpen ? "View Menu" : "Currently Closed"
|
|
530
|
+
}), /* @__PURE__ */ w("button", {
|
|
531
|
+
type: "button",
|
|
532
|
+
onClick: () => V(!1),
|
|
533
|
+
className: "rounded-lg border border-border px-4 py-2.5 text-sm font-medium text-foreground hover:bg-accent transition-colors",
|
|
534
|
+
children: "Close"
|
|
535
|
+
})]
|
|
536
|
+
})
|
|
537
|
+
]
|
|
538
|
+
})
|
|
539
|
+
})
|
|
540
|
+
})
|
|
541
|
+
]
|
|
542
|
+
});
|
|
543
|
+
}
|
|
544
|
+
//#endregion
|
|
545
|
+
export { D as CartDiscoveryPage };
|
|
546
|
+
|
|
547
|
+
//# sourceMappingURL=CartDiscoveryPage.js.map
|