@burdenoff/microfe-adaptercloud 2026.614.1 → 2026.624.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/dist/adaptercloud/components/EmptyState.js +3 -3
- package/dist/adaptercloud/components/EmptyState.js.map +1 -1
- package/dist/adaptercloud/components/InvestmentCard.js +9 -9
- package/dist/adaptercloud/components/InvestmentCard.js.map +1 -1
- package/dist/adaptercloud/components/MetricsCard.js +5 -5
- package/dist/adaptercloud/components/MetricsCard.js.map +1 -1
- package/dist/adaptercloud/components/PageLayout.js +3 -3
- package/dist/adaptercloud/components/PageLayout.js.map +1 -1
- package/dist/adaptercloud/components/RatingDisplay.js +3 -3
- package/dist/adaptercloud/components/RatingDisplay.js.map +1 -1
- package/dist/adaptercloud/components/StatusBadge.js +2 -2
- package/dist/adaptercloud/components/StatusBadge.js.map +1 -1
- package/dist/adaptercloud/pages/HomePage.js +54 -54
- package/dist/adaptercloud/pages/HomePage.js.map +1 -1
- package/dist/adaptercloud/pages/admin/AdminAnalyticsPage.js +60 -60
- package/dist/adaptercloud/pages/admin/AdminAnalyticsPage.js.map +1 -1
- package/dist/adaptercloud/pages/admin/AdminDashboard.js +77 -77
- package/dist/adaptercloud/pages/admin/AdminDashboard.js.map +1 -1
- package/dist/adaptercloud/pages/admin/AdminFinancialPage.js +43 -43
- package/dist/adaptercloud/pages/admin/AdminFinancialPage.js.map +1 -1
- package/dist/adaptercloud/pages/admin/AdminOrdersPage.js +85 -85
- package/dist/adaptercloud/pages/admin/AdminOrdersPage.js.map +1 -1
- package/dist/adaptercloud/pages/admin/AdminProfilePage.js +34 -34
- package/dist/adaptercloud/pages/admin/AdminProfilePage.js.map +1 -1
- package/dist/adaptercloud/pages/admin/AdminSettingsPage.js +40 -40
- package/dist/adaptercloud/pages/admin/AdminSettingsPage.js.map +1 -1
- package/dist/adaptercloud/pages/admin/CartManagementPage.js +86 -86
- package/dist/adaptercloud/pages/admin/CartManagementPage.js.map +1 -1
- package/dist/adaptercloud/pages/admin/UserManagementPage.js +80 -80
- package/dist/adaptercloud/pages/admin/UserManagementPage.js.map +1 -1
- package/dist/adaptercloud/pages/cart-owner/AnalyticsDashboard.js +100 -100
- package/dist/adaptercloud/pages/cart-owner/AnalyticsDashboard.js.map +1 -1
- package/dist/adaptercloud/pages/cart-owner/BusinessSettingsPage.js +29 -29
- package/dist/adaptercloud/pages/cart-owner/BusinessSettingsPage.js.map +1 -1
- package/dist/adaptercloud/pages/cart-owner/CartOwnerDashboard.js +81 -81
- package/dist/adaptercloud/pages/cart-owner/CartOwnerDashboard.js.map +1 -1
- package/dist/adaptercloud/pages/cart-owner/CartOwnerProfilePage.js +100 -100
- package/dist/adaptercloud/pages/cart-owner/CartOwnerProfilePage.js.map +1 -1
- package/dist/adaptercloud/pages/cart-owner/CartServiceConfigPage.js +67 -67
- package/dist/adaptercloud/pages/cart-owner/CartServiceConfigPage.js.map +1 -1
- package/dist/adaptercloud/pages/cart-owner/InventoryManagementPage.js +94 -94
- package/dist/adaptercloud/pages/cart-owner/InventoryManagementPage.js.map +1 -1
- package/dist/adaptercloud/pages/cart-owner/OrderManagementPage.js +57 -57
- package/dist/adaptercloud/pages/cart-owner/OrderManagementPage.js.map +1 -1
- package/dist/adaptercloud/pages/cart-owner/StaffManagementPage.js +75 -75
- package/dist/adaptercloud/pages/cart-owner/StaffManagementPage.js.map +1 -1
- package/dist/adaptercloud/pages/common/HelpSupportPage.js +102 -102
- package/dist/adaptercloud/pages/common/HelpSupportPage.js.map +1 -1
- package/dist/adaptercloud/pages/common/NotificationCenterPage.js +35 -35
- package/dist/adaptercloud/pages/common/NotificationCenterPage.js.map +1 -1
- package/dist/adaptercloud/pages/common/SettingsPage.js +109 -109
- package/dist/adaptercloud/pages/common/SettingsPage.js.map +1 -1
- package/dist/adaptercloud/pages/customer/BookingDetailsPage.js +60 -60
- package/dist/adaptercloud/pages/customer/BookingDetailsPage.js.map +1 -1
- package/dist/adaptercloud/pages/customer/CartDetailPage.js +71 -71
- package/dist/adaptercloud/pages/customer/CartDetailPage.js.map +1 -1
- package/dist/adaptercloud/pages/customer/CartDiscoveryPage.js +54 -54
- package/dist/adaptercloud/pages/customer/CartDiscoveryPage.js.map +1 -1
- package/dist/adaptercloud/pages/customer/CheckoutPage.js +75 -75
- package/dist/adaptercloud/pages/customer/CheckoutPage.js.map +1 -1
- package/dist/adaptercloud/pages/customer/CustomerDashboard.js +69 -69
- package/dist/adaptercloud/pages/customer/CustomerDashboard.js.map +1 -1
- package/dist/adaptercloud/pages/customer/CustomerProfilePage.js +72 -72
- package/dist/adaptercloud/pages/customer/CustomerProfilePage.js.map +1 -1
- package/dist/adaptercloud/pages/customer/DirectServiceBookingPage.js +75 -75
- package/dist/adaptercloud/pages/customer/DirectServiceBookingPage.js.map +1 -1
- package/dist/adaptercloud/pages/customer/FavoritesPage.js +30 -30
- package/dist/adaptercloud/pages/customer/FavoritesPage.js.map +1 -1
- package/dist/adaptercloud/pages/customer/OrderHistoryPage.js +41 -41
- package/dist/adaptercloud/pages/customer/OrderHistoryPage.js.map +1 -1
- package/dist/adaptercloud/pages/customer/OrderTrackingPage.js +53 -53
- package/dist/adaptercloud/pages/customer/OrderTrackingPage.js.map +1 -1
- package/dist/adaptercloud/pages/customer/PaymentMethodsPage.js +51 -51
- package/dist/adaptercloud/pages/customer/PaymentMethodsPage.js.map +1 -1
- package/dist/adaptercloud/pages/customer/ReviewsPage.js +33 -33
- package/dist/adaptercloud/pages/customer/ReviewsPage.js.map +1 -1
- package/dist/adaptercloud/pages/customer/SavedAddressesPage.js +33 -33
- package/dist/adaptercloud/pages/customer/SavedAddressesPage.js.map +1 -1
- package/dist/adaptercloud/pages/investor/InvestmentDetailsPage.js +108 -108
- package/dist/adaptercloud/pages/investor/InvestmentDetailsPage.js.map +1 -1
- package/dist/adaptercloud/pages/investor/InvestmentOpportunitiesPage.js +76 -76
- package/dist/adaptercloud/pages/investor/InvestmentOpportunitiesPage.js.map +1 -1
- package/dist/adaptercloud/pages/investor/InvestorAnalyticsPage.js +69 -69
- package/dist/adaptercloud/pages/investor/InvestorAnalyticsPage.js.map +1 -1
- package/dist/adaptercloud/pages/investor/InvestorDashboard.js +53 -53
- package/dist/adaptercloud/pages/investor/InvestorDashboard.js.map +1 -1
- package/dist/adaptercloud/pages/investor/InvestorInvestmentsPage.js +32 -32
- package/dist/adaptercloud/pages/investor/InvestorInvestmentsPage.js.map +1 -1
- package/dist/adaptercloud/pages/investor/InvestorPortfolioPage.js +55 -55
- package/dist/adaptercloud/pages/investor/InvestorPortfolioPage.js.map +1 -1
- package/dist/adaptercloud/pages/investor/InvestorProfilePage.js +138 -138
- package/dist/adaptercloud/pages/investor/InvestorProfilePage.js.map +1 -1
- package/dist/adaptercloud/pages/worker/TaskDetailsPage.js +65 -65
- package/dist/adaptercloud/pages/worker/TaskDetailsPage.js.map +1 -1
- package/dist/adaptercloud/pages/worker/WorkerDashboard.js +74 -74
- package/dist/adaptercloud/pages/worker/WorkerDashboard.js.map +1 -1
- package/dist/adaptercloud/pages/worker/WorkerOrdersPage.js +49 -49
- package/dist/adaptercloud/pages/worker/WorkerOrdersPage.js.map +1 -1
- package/dist/adaptercloud/pages/worker/WorkerProfilePage.js +92 -92
- package/dist/adaptercloud/pages/worker/WorkerProfilePage.js.map +1 -1
- package/dist/adaptercloud/pages/worker/WorkerSchedulePage.js +55 -55
- package/dist/adaptercloud/pages/worker/WorkerSchedulePage.js.map +1 -1
- package/dist/adaptercloud/utils/cn.js +2 -2
- package/dist/node_modules/{.bun/clsx@2.1.1/node_modules/clsx → clsx}/dist/clsx.js +1 -1
- package/dist/node_modules/clsx/dist/clsx.js.map +1 -0
- package/dist/node_modules/{.bun/tailwind-merge@3.5.0/node_modules/tailwind-merge → tailwind-merge}/dist/bundle-mjs.js +212 -170
- package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js.map +1 -0
- package/package.json +1 -1
- package/dist/node_modules/.bun/clsx@2.1.1/node_modules/clsx/dist/clsx.js.map +0 -1
- package/dist/node_modules/.bun/tailwind-merge@3.5.0/node_modules/tailwind-merge/dist/bundle-mjs.js.map +0 -1
|
@@ -1 +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":";;;;;;;;;;;AAoEA,SAAgB,IAAiB;CAC/B,IAAM,EAAE,cAAW,GAA+B,EAC5C,EAAE,kBAAe,GAAiB,EAElC,EAAE,MAAM,IAAY,EAAE,EAAE,WAAW,OAAuB,GAAc,EACxE,EAAE,MAAM,IAAY,EAAE,EAAE,WAAW,OAAuB,EAAa,EAAO,EAC9E,EAAE,MAAM,IAAc,EAAE,EAAE,WAAW,OAAyB,GAA4B,EAE1F,IAAO,QAAc,EAAU,MAAM,MAAM,EAAE,OAAO,EAAO,EAAE,CAAC,GAAW,EAAO,CAAC,EACjF,IAAa,QACX,EAAY,MAAM,MAAM,EAAE,WAAW,EAAO,EAClD,CAAC,GAAa,EAAO,CACtB,EAEK,CAAC,GAAa,KAAkB,EAAS,GAAG,EAC5C,CAAC,GAAkB,KAAuB,EAAS,GAAG,EACtD,CAAC,GAAW,KAAgB,EAAqB,EAAE,CAAC,EACpD,CAAC,GAAmB,KAAwB,EAAS,GAAM,EAC3D,CAAC,GAAe,KAAoB,EAAoC,KAAK,EAE7E,IAAY,QAEd,EAAU,KAAK,OAAO;EACpB,IAAI,EAAE;EACN,MAAM,EAAE;EACR,OAAO,EAAE;EACT,aAAa,EAAE;EACf,OAAO,EAAE,QAAQ,MAAM;EACvB,UAAU,EAAE;EACZ,OAAO;EACP,UAAU,EAAE;EACZ,aAAa,EAAE;EAChB,EAAE,EACL,CAAC,EAAU,CACZ,EAEK,IAAiB,QACR,CAAC,GAAG,IAAI,IAAI,EAAU,KAAK,MAAS,EAAK,SAAS,CAAC,CAAC,EAEhE,CAAC,EAAU,CAAC,EAET,IAAe,QAAc;EACjC,IAAI,IAAQ;AAMZ,MAJI,MACF,IAAQ,EAAM,QAAQ,MAAS,EAAK,aAAa,EAAiB,GAGhE,EAAY,MAAM,EAAE;GACtB,IAAM,IAAI,EAAY,aAAa;AACnC,OAAQ,EAAM,QACX,MAAS,EAAK,KAAK,aAAa,CAAC,SAAS,EAAE,IAAI,EAAK,YAAY,aAAa,CAAC,SAAS,EAAE,CAC5F;;AAGH,SAAO;IACN;EAAC;EAAW;EAAkB;EAAY,CAAC,EAIxC,IAAc,QAAc;EAChC,IAAM,IAAyC,EAAE;AAKjD,SAJA,EAAa,SAAS,MAAS;AAE7B,GADK,EAAO,EAAK,cAAW,EAAO,EAAK,YAAY,EAAE,GACtD,EAAO,EAAK,UAAU,KAAK,EAAK;IAChC,EACK;IACN,CAAC,EAAa,CAAC,EAGZ,KAAa,GAAuB,IAAc,GAAG,MAA0B;AACnF,KAAc,MACK,EAAK,MAAM,MAAS,EAAK,cAAc,EAAQ,GAAG,GAE1D,EAAK,KAAK,MACf,EAAK,cAAc,EAAQ,KAAK;GAAE,GAAG;GAAM,UAAU,EAAK,WAAW;GAAK,GAAG,EAC9E,GAEI,CACL,GAAG,GACH;GACE,IAAI,QAAQ,KAAK,KAAK;GACtB,WAAW,EAAQ;GACnB,MAAM,EAAQ;GACd,OAAO,EAAQ;GACf,UAAU;GACV,qBAAqB;GACtB,CACF,CACD;IAGE,KAAkB,GAAmB,MAAkB;AAC3D,KAAc,MACZ,EACG,KAAK,MACJ,EAAK,cAAc,IACf;GAAE,GAAG;GAAM,UAAU,KAAK,IAAI,GAAG,EAAK,WAAW,EAAM;GAAE,GACzD,EACL,CACA,QAAQ,MAAS,EAAK,WAAW,EAAE,CACvC;IAGG,KAAkB,MAAsB;AAC5C,KAAc,MAAS,EAAK,QAAQ,MAAS,EAAK,cAAc,EAAU,CAAC;IAGvE,MAAmB,MAChB,EAAU,MAAM,MAAS,EAAK,cAAc,EAAU,EAAE,YAAY,GAGvE,KAAY,EAAU,QAAQ,GAAK,MAAS,IAAM,EAAK,QAAQ,EAAK,UAAU,EAAE,EAChF,KAAY,EAAU,QAAQ,GAAK,MAAS,IAAM,EAAK,UAAU,EAAE,EAEnE,MAAmB,MAA0B;AAEjD,EADA,EAAiB;GAAE;GAAS,UAAU;GAAG,qBAAqB;GAAI,CAAC,EACnE,EAAqB,GAAK;;AAgC5B,QArBK,IAsBH,kBAAC,GAAD;EACE,OACE,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,UAAD;KACE,MAAK;KACL,eAAe,EAAW,kBAAkB;KAC5C,WAAU;eAEV,kBAAC,GAAD,EAAW,WAAU,WAAY,CAAA;KAC1B,CAAA;IACT,kBAAC,QAAD;KAAM,WAAU;eAAY,EAAK;KAAY,CAAA;IAC5C,EAAK,cAAc,kBAAC,GAAD,EAAc,WAAU,kCAAmC,CAAA;IAC3E;;EAER,aAAa,EAAK;YAdpB;GAiBE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD;KAAK,KAAK,EAAK;KAAO,KAAK,EAAK;KAAM,WAAU;KAA+B,CAAA,EAC/E,kBAAC,OAAD;KAAK,WAAU;eACb,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,QAAD;OACE,WAAW,EACT,2EACA,EAAK,SAAS,mCAAmC,6BAClD;iBAEA,EAAK,SAAS,aAAa;OACvB,CAAA,EACP,kBAAC,OAAD;OAAK,WAAU;iBAAf;QACE,kBAAC,GAAD,EAAM,WAAU,+CAAgD,CAAA;QAChE,kBAAC,QAAD;SAAM,WAAU;mBAAe,EAAK;SAAc,CAAA;QAClD,kBAAC,QAAD;SAAM,WAAU;mBAAhB;UAAgC;UAAE,EAAK;UAAa;UAAQ;;QACxD;SACF;;KACF,CAAA,CACF;;GAGL,CAAC,EAAK,UACL,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,KAAD;KAAG,WAAU;eAAb,CACE,kBAAC,UAAD,EAAA,UAAQ,kCAAuC,CAAA,EAAA,mEAE7C;;IACA,CAAA;GAIR,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,OAAD;MAAK,WAAU;gBAAf;OACE,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,GAAD,EAAQ,WAAU,eAAgB,CAAA,EAClC,kBAAC,QAAD;SAAM,WAAU;mBAAuC;SAAe,CAAA,CAClE;;OACN,kBAAC,KAAD;QAAG,WAAU;kBAA2B,EAAK,SAAS;QAAY,CAAA;OAClE,kBAAC,KAAD;QAAG,WAAU;kBAAb,CAA8C,EAAe,EAAK,SAAS,EAAC,QAAS;;OACjF;;KACN,kBAAC,OAAD;MAAK,WAAU;gBAAf;OACE,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,GAAD,EAAO,WAAU,eAAgB,CAAA,EACjC,kBAAC,QAAD;SAAM,WAAU;mBAAuC;SAAqB,CAAA,CACxE;;OACN,kBAAC,KAAD;QAAG,WAAU;kBAA2B,EAAe,EAAK,cAAc;QAAK,CAAA;OAC9E,EAAK,qBACJ,kBAAC,KAAD;QAAG,WAAU;kBAAb,CAA6C,QACtC,EAAe,EAAK,mBAAmB,EAAE,uBAAuB,GAAG,CAAC,CACvE;;OAEF;;KACN,kBAAC,OAAD;MAAK,WAAU;gBAAf;OACE,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,GAAD,EAAM,WAAU,eAAgB,CAAA,EAChC,kBAAC,QAAD;SAAM,WAAU;mBAAuC;SAAa,CAAA,CAChE;;OACN,kBAAC,KAAD;QAAG,WAAU;kBAAb,CAAwC,EAAK,QAAO,SAAU;;OAC9D,kBAAC,KAAD;QAAG,WAAU;kBAAb,CAA8C,EAAK,cAAa,WAAY;;OACxE;;KACF;;GAGL,EAAK,iBAAiB,OAAO,KAAK,EAAK,cAAc,CAAC,SAAS,KAC9D,kBAAC,WAAD;IAAS,WAAU;cAAnB,CACE,kBAAC,MAAD;KAAI,WAAU;eAA+C;KAAoB,CAAA,EACjF,kBAAC,OAAD;KAAK,WAAU;eACZ,OAAO,QAAQ,EAAK,cAAc,CAAC,KAAK,CAAC,GAAK,OAC7C,kBAAC,OAAD;MAEE,WAAU;gBAFZ,CAIE,kBAAC,QAAD;OAAM,WAAU;iBAAkD;OAAW,CAAA,EAC5E,EAAM,SACL,kBAAC,QAAD;OAAM,WAAU;iBAAhB;QACG,EAAM;QAAK;QAAI,EAAM;QACjB;WAEP,kBAAC,QAAD;OAAM,WAAU;iBAA2B;OAAa,CAAA,CAEtD;QAXC,EAWD,CACN;KACE,CAAA,CACE;;GAIZ,kBAAC,OAAD;IAAK,WAAU;cAAf,CAEE,kBAAC,OAAD;KAAK,WAAU;eAAf;MAEE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,GAAD,EAAQ,WAAU,0EAA2E,CAAA,EAC7F,kBAAC,SAAD;SACE,MAAK;SACL,aAAY;SACZ,OAAO;SACP,WAAW,MAAM,EAAe,EAAE,OAAO,MAAM;SAC/C,WAAU;SACV,CAAA,CACE;WACN,kBAAC,UAAD;QACE,OAAO;QACP,WAAW,MAAM,EAAoB,EAAE,OAAO,MAAM;QACpD,WAAU;kBAHZ,CAKE,kBAAC,UAAD;SAAQ,OAAM;mBAAG;SAAuB,CAAA,EACvC,EAAe,KAAK,MACnB,kBAAC,UAAD;SAAkB,OAAO;mBACtB;SACM,EAFI,EAEJ,CACT,CACK;UACL;;MAGN,kBAAC,MAAD;OAAI,WAAU;iBAAd;QAA2D;QACvC,EAAa;QAAO;QACnC;;MAEJ,EAAa,WAAW,IACvB,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,GAAD,EAAQ,WAAU,8CAA+C,CAAA,EACjE,kBAAC,KAAD;QAAG,WAAU;kBAAqC;QAAsB,CAAA,CACpE;WAEN,kBAAC,OAAD;OAAK,WAAU;iBACZ,OAAO,QAAQ,EAAY,CAAC,KAAK,CAAC,GAAU,OAC3C,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;QAAI,WAAU;kBAAmD;QAAc,CAAA,EAC/E,kBAAC,OAAD;QAAK,WAAU;kBACZ,EAAM,KAAK,MAAS;SACnB,IAAM,IAAM,GAAgB,EAAK,GAAG;AACpC,gBACE,kBAAC,OAAD;UAEE,WAAU;oBAFZ,CAIE,kBAAC,OAAD;WAAK,WAAU;qBACb,kBAAC,OAAD;YACE,KAAK,EAAK;YACV,KAAK,EAAK;YACV,WAAU;YACV,CAAA;WACE,CAAA,EACN,kBAAC,OAAD;WAAK,WAAU;qBAAf;YACE,kBAAC,OAAD;aAAK,WAAU;uBAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,OAAD;cAAK,WAAU;wBAAf,CACE,kBAAC,MAAD;eAAI,WAAU;yBACX,EAAK;eACH,CAAA,EACJ,EAAK,SACJ,kBAAC,GAAD,EAAM,WAAU,kDAAmD,CAAA,CAEjE;iBACN,kBAAC,KAAD;cAAG,WAAU;wBACV,EAAK;cACJ,CAAA,CACA,EAAA,CAAA,EACN,kBAAC,QAAD;cAAM,WAAU;wBACb,EAAe,EAAK,OAAO,EAAE,uBAAuB,GAAG,CAAC;cACpD,CAAA,CACH;;YACN,kBAAC,KAAD;aAAG,WAAU;uBACV,EAAK;aACJ,CAAA;YACJ,kBAAC,OAAD;aAAK,WAAU;uBAAf;cACG,EAAK,YAAY,QAAQ,EAAK,WAAW,KACxC,kBAAC,QAAD;eAAM,WAAU;yBAAhB,CACE,kBAAC,GAAD,EAAO,WAAU,WAAY,CAAA,EAC5B,EAAe,EAAK,SAAS,CACzB;;cAER,EAAK,eACJ,kBAAC,QAAD;eAAM,WAAU;yBACb,EAAK;eACD,CAAA;cAER,EAAK,cACJ,kBAAC,QAAD;eAAM,WAAU;yBAAhB,CACE,kBAAC,GAAD,EAAO,WAAU,WAAY,CAAA,EAC5B,EAAK,WACD;;cAEL;;YAEN,kBAAC,OAAD;aAAK,WAAU;uBACZ,IAAM,IACL,kBAAC,OAAD;cAAK,WAAU;wBAAf;eACE,kBAAC,UAAD;gBACE,MAAK;gBACL,eAAe,EAAe,EAAK,IAAI,GAAG;gBAC1C,WAAU;0BAEV,kBAAC,GAAD,EAAO,WAAU,eAAgB,CAAA;gBAC1B,CAAA;eACT,kBAAC,QAAD;gBAAM,WAAU;0BACb;gBACI,CAAA;eACP,kBAAC,UAAD;gBACE,MAAK;gBACL,eAAe,EAAe,EAAK,IAAI,EAAE;gBACzC,WAAU;0BAEV,kBAAC,GAAD,EAAM,WAAU,eAAgB,CAAA;gBACzB,CAAA;eACT,kBAAC,UAAD;gBACE,MAAK;gBACL,eAAe,EAAe,EAAK,GAAG;gBACtC,WAAU;0BAEV,kBAAC,GAAD,EAAG,WAAU,eAAgB,CAAA;gBACtB,CAAA;eACL;kBAEN,kBAAC,UAAD;cACE,MAAK;cACL,UAAU,CAAC,EAAK;cAChB,eAAe,GAAgB,EAAK;cACpC,WAAW,EACT,iEACA,EAAK,SACD,mDACA,oDACL;wBACF;cAEQ,CAAA;aAEP,CAAA;YACF;aACF;YAjGC,EAAK,GAiGN;UAER;QACE,CAAA,CACF,EAAA,EA5GI,EA4GJ,CACN;OACE,CAAA;MAEJ;QAGN,kBAAC,OAAD;KAAK,WAAU;eAAf;MAEE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,MAAD;QAAI,WAAU;kBAAd,CACE,kBAAC,GAAD,EAAc,WAAU,WAAY,CAAA,EAAA,aAEjC;WACJ,EAAU,WAAW,IACpB,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,GAAD,EAAc,WAAU,4CAA6C,CAAA,EACrE,kBAAC,KAAD;SAAG,WAAU;mBAAqC;SAAsB,CAAA,CACpE;YAEN,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,OAAD;QAAK,WAAU;kBACZ,EAAU,KAAK,MACd,kBAAC,OAAD;SAAmB,WAAU;mBAA7B,CACE,kBAAC,OAAD;UAAK,WAAU;oBAAf,CACE,kBAAC,KAAD;WAAG,WAAU;qBAAgD,EAAK;WAAS,CAAA,EAC3E,kBAAC,KAAD;WAAG,WAAU;qBAAb;YACG,EAAe,EAAK,OAAO,EAAE,uBAAuB,GAAG,CAAC;YAAC;YAAG;YAC5D,EAAK;YACJ;aACA;aACN,kBAAC,OAAD;UAAK,WAAU;oBAAf;WACE,kBAAC,UAAD;YACE,MAAK;YACL,eAAe,EAAe,EAAK,WAAW,GAAG;YACjD,WAAU;sBACX;YAEQ,CAAA;WACT,kBAAC,QAAD;YAAM,WAAU;sBACb,EAAK;YACD,CAAA;WACP,kBAAC,UAAD;YACE,MAAK;YACL,eAAe,EAAe,EAAK,WAAW,EAAE;YAChD,WAAU;sBACX;YAEQ,CAAA;WACT,kBAAC,UAAD;YACE,MAAK;YACL,eAAe,EAAe,EAAK,UAAU;YAC7C,WAAU;sBAEV,kBAAC,GAAD,EAAG,WAAU,eAAgB,CAAA;YACtB,CAAA;WACL;YACF;WAlCI,EAAK,GAkCT,CACN;QACE,CAAA,EACN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,QAAD;UAAM,WAAU;oBAAhB,CAAwD,WAC9C,EAAe,IAAW,EAAE,uBAAuB,GAAG,CAAC,CAC1D;aACP,kBAAC,QAAD;UAAM,WAAU;oBAAhB,CAAiD,IAAU,SAAa;YACpE;YACN,kBAAC,UAAD;SACE,MAAK;SACL,eAAe,EAAW,qBAAqB;SAC/C,WAAU;mBACX;SAEQ,CAAA,CACL;UACL,EAAA,CAAA,CAED;;MAGL,EAAK,cAAc,SAAS,iBAAiB,IAC5C,kBAAC,OAAD;OAAK,WAAU;iBAAf;QACE,kBAAC,MAAD;SAAI,WAAU;mBAAd,CACE,kBAAC,GAAD,EAAM,WAAU,gDAAiD,CAAA,EAAA,iBAE9D;;QACL,kBAAC,KAAD;SAAG,WAAU;mBAAqC;SAAgC,CAAA;QAClF,kBAAC,UAAD;SACE,MAAK;SACL,eAAe,EAAW,mBAAmB,EAAK,KAAK;SACvD,WAAU;mBACX;SAEQ,CAAA;QACL;;MAIP,EAAK,cAAc,SAAS,cAAc,IACzC,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,MAAD;QAAI,WAAU;kBAAd,CACE,kBAAC,GAAD,EAAU,WAAU,4CAA6C,CAAA,EAAA,yBAE9D;WACL,kBAAC,KAAD;QAAG,WAAU;kBAAgC;QAEzC,CAAA,CACA;;MAIP,KACC,kBAAC,OAAD;OAAK,WAAU;iBAAf;QACE,kBAAC,MAAD;SAAI,WAAU;mBAAd,CACE,kBAAC,IAAD,EAAY,WAAU,8CAA+C,CAAA,EAAA,yBAElE;;QACL,kBAAC,KAAD;SAAG,WAAU;mBAAsC,EAAW;SAAgB,CAAA;QAC9E,kBAAC,OAAD;SAAK,WAAU;mBAAf;UACE,kBAAC,KAAD,EAAA,UAAA,CAAG,YACQ,EAAe,EAAW,cAAc,EAAE,uBAAuB,GAAG,CAAC,CAC5E,EAAA,CAAA;UACJ,kBAAC,KAAD,EAAA,UAAA,CAAG,YACQ,EAAe,EAAW,cAAc,EAAE,uBAAuB,GAAG,CAAC,CAC5E,EAAA,CAAA;UACJ,kBAAC,KAAD,EAAA,UAAA;WAAG;WAAmB,EAAW;WAAgB;WAAK,EAAA,CAAA;UACtD,kBAAC,KAAD,EAAA,UAAA;WAAG;WACe;WACf,EAAe,EAAW,mBAAmB,EAAE,uBAAuB,GAAG,CAAC;WACzE,EAAA,CAAA;UACA;;QACN,kBAAC,UAAD;SACE,MAAK;SACL,eAAe,MAAM,sDAAsD;SAC3E,WAAU;mBACX;SAEQ,CAAA;QACL;;MAEJ;OACF;;GAGL,KAAqB,KACpB,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,OAAD;KAAK,WAAU;eACb,kBAAC,OAAD;MAAK,WAAU;gBAAf;OACE,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,MAAD;SAAI,WAAU;mBACX,EAAc,QAAQ;SACpB,CAAA,EACL,kBAAC,UAAD;SACE,MAAK;SACL,eAAe;AAEb,UADA,EAAqB,GAAM,EAC3B,EAAiB,KAAK;;SAExB,WAAU;mBAEV,kBAAC,GAAD,EAAG,WAAU,WAAY,CAAA;SAClB,CAAA,CACL;;OAEN,kBAAC,KAAD;QAAG,WAAU;kBACV,EAAc,QAAQ;QACrB,CAAA;OACJ,kBAAC,KAAD;QAAG,WAAU;kBACV,EAAe,EAAc,QAAQ,OAAO,EAAE,uBAAuB,GAAG,CAAC;QACxE,CAAA;OAGJ,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,SAAD;SAAO,WAAU;mBAAiD;SAAgB,CAAA,EAClF,kBAAC,OAAD;SAAK,WAAU;mBAAf;UACE,kBAAC,UAAD;WACE,MAAK;WACL,eACE,GAAkB,MAChB,KAAO;YAAE,GAAG;YAAM,UAAU,KAAK,IAAI,GAAG,EAAK,WAAW,EAAE;YAAE,CAC7D;WAEH,WAAU;qBAEV,kBAAC,GAAD,EAAO,WAAU,WAAY,CAAA;WACtB,CAAA;UACT,kBAAC,QAAD;WAAM,WAAU;qBACb,EAAc;WACV,CAAA;UACP,kBAAC,UAAD;WACE,MAAK;WACL,eACE,GAAkB,MAChB,KAAO;YAAE,GAAG;YAAM,UAAU,EAAK,WAAW;YAAG,CAChD;WAEH,WAAU;qBAEV,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA;WACrB,CAAA;UACL;WACF;;OAGN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,SAAD;SAAO,WAAU;mBAAiD;SAE1D,CAAA,EACR,kBAAC,YAAD;SACE,OAAO,EAAc;SACrB,WAAW,MACT,GAAkB,MAChB,KAAO;UAAE,GAAG;UAAM,qBAAqB,EAAE,OAAO;UAAO,CACxD;SAEH,aAAY;SACZ,WAAU;SACV,MAAM;SACN,CAAA,CACE;;OAEN,kBAAC,UAAD;QACE,MAAK;QACL,eA5fiB;AACxB,eACL,EAAU,EAAc,SAAS,EAAc,UAAU,EAAc,oBAAoB,EAC3F,EAAqB,GAAM,EAC3B,EAAiB,KAAK,EACtB,MAAM,GAAG,EAAc,QAAQ,KAAK,gBAAgB;;QAwfxC,WAAU;kBAHZ;SAIC;SACe;SACb,EAAe,EAAc,QAAQ,QAAQ,EAAc,UAAU,EACpE,uBAAuB,GACxB,CAAC;SACK;;OACL;;KACF,CAAA;IACF,CAAA;GAEG;MA9fX,kBAAC,GAAD;EAAY,OAAM;YAChB,kBAAC,GAAD;GACE,MAAM,kBAAC,GAAD,EAAc,WAAU,aAAc,CAAA;GAC5C,OAAM;GACN,aAAa,0BAA0B,EAAO;GAC9C,QACE,kBAAC,UAAD;IACE,MAAK;IACL,eAAe,EAAW,kBAAkB;IAC5C,WAAU;cACX;IAEQ,CAAA;GAEX,CAAA;EACS,CAAA"}
|
|
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-text-secondary hover:bg-accent hover:text-text-primary 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-bg-sunken 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-subtle bg-bg-surface p-3\">\n <div className=\"flex items-center gap-2 text-text-secondary 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-text-primary\">{cart.location.address}</p>\n <p className=\"text-xs text-text-secondary\">{formatDistance(cart.distance)} away</p>\n </div>\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-3\">\n <div className=\"flex items-center gap-2 text-text-secondary 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-text-primary\">{formatDuration(cart.estimatedTime)}</p>\n {cart.averageOrderValue && (\n <p className=\"text-xs text-text-secondary\">\n Avg {formatCurrency(cart.averageOrderValue, { minimumFractionDigits: 0 })}\n </p>\n )}\n </div>\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-3\">\n <div className=\"flex items-center gap-2 text-text-secondary 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-text-primary\">{cart.rating} / 5.0</p>\n <p className=\"text-xs text-text-secondary\">{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-text-primary mb-2\">Operating Hours</h2>\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface 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-subtle last:border-b-0\"\n >\n <span className=\"text-sm font-medium text-text-primary capitalize\">{day}</span>\n {hours.isOpen ? (\n <span className=\"text-sm text-text-secondary\">\n {hours.open} - {hours.close}\n </span>\n ) : (\n <span className=\"text-sm text-status-error-text\">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-text-secondary\" />\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-subtle bg-bg-surface py-2 pl-10 pr-3 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n </div>\n <select\n value={selectedCategory}\n onChange={(e) => setSelectedCategory(e.target.value)}\n className=\"rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-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-text-primary mb-3\">\n Menu & Services ({filteredMenu.length})\n </h2>\n\n {filteredMenu.length === 0 ? (\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-8 text-center\">\n <Search className=\"mx-auto h-10 w-10 text-text-secondary/50\" />\n <p className=\"mt-3 text-sm text-text-secondary\">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-text-primary 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-subtle bg-bg-surface p-4\"\n >\n <div className=\"h-20 w-20 shrink-0 rounded-md bg-bg-sunken 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-text-primary\">\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-text-secondary mt-0.5\">\n {item.category}\n </p>\n </div>\n <span className=\"text-sm font-bold text-text-primary whitespace-nowrap\">\n {formatCurrency(item.price, { minimumFractionDigits: 0 })}\n </span>\n </div>\n <p className=\"mt-1 text-xs text-text-secondary line-clamp-2\">\n {item.description}\n </p>\n <div className=\"mt-2 flex flex-wrap items-center gap-2 text-[10px] text-text-secondary\">\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-bg-sunken 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-bg-sunken 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-bg-sunken text-text-primary 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-text-primary\">\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-status-error-text hover:bg-status-error-bg/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-bg-sunken text-text-secondary 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-subtle bg-bg-surface p-4 lg:sticky lg:top-6\">\n <h3 className=\"text-base font-semibold text-text-primary 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-text-secondary/40\" />\n <p className=\"mt-2 text-sm text-text-secondary\">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-text-primary truncate\">{item.name}</p>\n <p className=\"text-xs text-text-secondary\">\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-bg-sunken text-text-primary 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-bg-sunken text-text-primary text-xs\"\n >\n +\n </button>\n <button\n type=\"button\"\n onClick={() => removeFromCart(item.productId)}\n className=\"ml-1 text-status-error-text hover:text-status-error-text/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-subtle pt-3\">\n <div className=\"flex justify-between items-center mb-3\">\n <span className=\"text-sm font-semibold text-text-primary\">\n Total: {formatCurrency(cartTotal, { minimumFractionDigits: 0 })}\n </span>\n <span className=\"text-xs text-text-secondary\">{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-text-primary 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-text-secondary 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-text-primary 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-text-secondary\">\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-text-primary 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-text-secondary mb-2\">{investment.description}</p>\n <div className=\"space-y-1 text-xs text-text-secondary 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-subtle bg-bg-surface\">\n <div className=\"p-5\">\n <div className=\"flex items-center justify-between mb-4\">\n <h3 className=\"text-lg font-semibold text-text-primary\">\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-text-secondary hover:text-text-primary\"\n >\n <X className=\"h-5 w-5\" />\n </button>\n </div>\n\n <p className=\"text-sm text-text-secondary mb-4\">\n {customization.product.description}\n </p>\n <p className=\"text-lg font-bold text-text-primary 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-text-primary 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-bg-sunken text-text-primary\"\n >\n <Minus className=\"h-4 w-4\" />\n </button>\n <span className=\"min-w-[2ch] text-center font-medium text-text-primary\">\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-bg-sunken text-text-primary\"\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-text-primary 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-subtle bg-bg-surface p-3 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-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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"}
|
|
@@ -71,7 +71,7 @@ function D() {
|
|
|
71
71
|
children: /* @__PURE__ */ T("div", {
|
|
72
72
|
className: "flex h-[60vh] flex-col items-center justify-center gap-4",
|
|
73
73
|
children: [
|
|
74
|
-
/* @__PURE__ */ w(u, { className: "h-12 w-12 text-
|
|
74
|
+
/* @__PURE__ */ w(u, { className: "h-12 w-12 text-status-error-text" }),
|
|
75
75
|
/* @__PURE__ */ w("h2", {
|
|
76
76
|
className: "text-xl font-semibold",
|
|
77
77
|
children: "Error loading service providers"
|
|
@@ -79,7 +79,7 @@ function D() {
|
|
|
79
79
|
/* @__PURE__ */ w("button", {
|
|
80
80
|
type: "button",
|
|
81
81
|
onClick: () => window.location.reload(),
|
|
82
|
-
className: "rounded-lg bg-primary px-4 py-2 text-sm font-medium text-primary-
|
|
82
|
+
className: "rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text",
|
|
83
83
|
children: "Retry"
|
|
84
84
|
})
|
|
85
85
|
]
|
|
@@ -88,25 +88,25 @@ function D() {
|
|
|
88
88
|
title: "Discover Carts",
|
|
89
89
|
description: "Find services and shops near you",
|
|
90
90
|
actions: /* @__PURE__ */ T("span", {
|
|
91
|
-
className: "text-sm text-
|
|
91
|
+
className: "text-sm text-text-secondary",
|
|
92
92
|
children: [Y.length, " carts found"]
|
|
93
93
|
}),
|
|
94
94
|
children: [
|
|
95
95
|
/* @__PURE__ */ T("div", {
|
|
96
96
|
className: "relative",
|
|
97
97
|
children: [
|
|
98
|
-
/* @__PURE__ */ w(v, { className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-
|
|
98
|
+
/* @__PURE__ */ w(v, { className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-secondary" }),
|
|
99
99
|
/* @__PURE__ */ w("input", {
|
|
100
100
|
type: "text",
|
|
101
101
|
placeholder: "Search carts, services, or items...",
|
|
102
102
|
value: O,
|
|
103
103
|
onChange: (e) => k(e.target.value),
|
|
104
|
-
className: t("w-full rounded-lg border border-border bg-
|
|
104
|
+
className: t("w-full rounded-lg border border-border-subtle bg-bg-surface py-2.5 pl-10 pr-10 text-sm text-text-primary", "placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]")
|
|
105
105
|
}),
|
|
106
106
|
O && /* @__PURE__ */ w("button", {
|
|
107
107
|
type: "button",
|
|
108
108
|
onClick: () => k(""),
|
|
109
|
-
className: "absolute right-3 top-1/2 -translate-y-1/2 text-
|
|
109
|
+
className: "absolute right-3 top-1/2 -translate-y-1/2 text-text-secondary hover:text-text-primary",
|
|
110
110
|
children: /* @__PURE__ */ w(S, { className: "h-4 w-4" })
|
|
111
111
|
})
|
|
112
112
|
]
|
|
@@ -116,7 +116,7 @@ function D() {
|
|
|
116
116
|
children: J.map((e) => /* @__PURE__ */ w("button", {
|
|
117
117
|
type: "button",
|
|
118
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-
|
|
119
|
+
className: t("rounded-full px-3 py-1.5 text-xs font-medium transition-colors", A === e ? "bg-foreground text-background" : "bg-bg-sunken text-text-secondary hover:bg-accent hover:text-text-primary"),
|
|
120
120
|
children: e
|
|
121
121
|
}, e))
|
|
122
122
|
}),
|
|
@@ -126,7 +126,7 @@ function D() {
|
|
|
126
126
|
/* @__PURE__ */ T("select", {
|
|
127
127
|
value: M,
|
|
128
128
|
onChange: (e) => N(e.target.value),
|
|
129
|
-
className: "rounded-lg border border-border bg-
|
|
129
|
+
className: "rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-xs text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]",
|
|
130
130
|
children: [
|
|
131
131
|
/* @__PURE__ */ w("option", {
|
|
132
132
|
value: "",
|
|
@@ -149,7 +149,7 @@ function D() {
|
|
|
149
149
|
/* @__PURE__ */ T("select", {
|
|
150
150
|
value: P,
|
|
151
151
|
onChange: (e) => F(e.target.value),
|
|
152
|
-
className: "rounded-lg border border-border bg-
|
|
152
|
+
className: "rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-xs text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]",
|
|
153
153
|
children: [
|
|
154
154
|
/* @__PURE__ */ w("option", {
|
|
155
155
|
value: "",
|
|
@@ -172,7 +172,7 @@ function D() {
|
|
|
172
172
|
/* @__PURE__ */ T("select", {
|
|
173
173
|
value: I,
|
|
174
174
|
onChange: (e) => L(e.target.value),
|
|
175
|
-
className: "rounded-lg border border-border bg-
|
|
175
|
+
className: "rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-xs text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]",
|
|
176
176
|
children: [
|
|
177
177
|
/* @__PURE__ */ w("option", {
|
|
178
178
|
value: "rating",
|
|
@@ -195,7 +195,7 @@ function D() {
|
|
|
195
195
|
Q && /* @__PURE__ */ w("button", {
|
|
196
196
|
type: "button",
|
|
197
197
|
onClick: $,
|
|
198
|
-
className: "rounded-lg border border-border px-3 py-2 text-xs font-medium text-
|
|
198
|
+
className: "rounded-lg border border-border-subtle px-3 py-2 text-xs font-medium text-text-secondary hover:text-text-primary transition-colors",
|
|
199
199
|
children: "Clear All Filters"
|
|
200
200
|
})
|
|
201
201
|
]
|
|
@@ -205,9 +205,9 @@ function D() {
|
|
|
205
205
|
children: X.map((e) => {
|
|
206
206
|
let n = q.find((t) => t.cartId === e.id);
|
|
207
207
|
return /* @__PURE__ */ T("div", {
|
|
208
|
-
className: "rounded-lg border border-border bg-
|
|
208
|
+
className: "rounded-lg border border-border-subtle bg-bg-surface shadow-sm overflow-hidden hover:shadow-md transition-shadow flex flex-col",
|
|
209
209
|
children: [/* @__PURE__ */ T("div", {
|
|
210
|
-
className: "relative h-40 bg-
|
|
210
|
+
className: "relative h-40 bg-bg-sunken",
|
|
211
211
|
children: [
|
|
212
212
|
/* @__PURE__ */ w("img", {
|
|
213
213
|
src: e.image,
|
|
@@ -238,18 +238,18 @@ function D() {
|
|
|
238
238
|
/* @__PURE__ */ T("div", {
|
|
239
239
|
className: "flex items-start justify-between gap-2 mb-1",
|
|
240
240
|
children: [/* @__PURE__ */ w("h3", {
|
|
241
|
-
className: "text-sm font-semibold text-
|
|
241
|
+
className: "text-sm font-semibold text-text-primary truncate flex-1",
|
|
242
242
|
children: e.name
|
|
243
243
|
}), /* @__PURE__ */ T("div", {
|
|
244
244
|
className: "flex items-center gap-1 shrink-0",
|
|
245
245
|
children: [
|
|
246
246
|
/* @__PURE__ */ w(y, { className: "h-3.5 w-3.5 fill-yellow-400 text-yellow-400" }),
|
|
247
247
|
/* @__PURE__ */ w("span", {
|
|
248
|
-
className: "text-xs font-medium text-
|
|
248
|
+
className: "text-xs font-medium text-text-primary",
|
|
249
249
|
children: e.rating
|
|
250
250
|
}),
|
|
251
251
|
/* @__PURE__ */ T("span", {
|
|
252
|
-
className: "text-xs text-
|
|
252
|
+
className: "text-xs text-text-secondary",
|
|
253
253
|
children: [
|
|
254
254
|
"(",
|
|
255
255
|
e.totalRatings,
|
|
@@ -260,18 +260,18 @@ function D() {
|
|
|
260
260
|
})]
|
|
261
261
|
}),
|
|
262
262
|
/* @__PURE__ */ w("p", {
|
|
263
|
-
className: "text-xs text-
|
|
263
|
+
className: "text-xs text-text-secondary mb-2",
|
|
264
264
|
children: e.category
|
|
265
265
|
}),
|
|
266
266
|
/* @__PURE__ */ w("div", {
|
|
267
|
-
className: "flex items-center gap-3 text-xs text-
|
|
267
|
+
className: "flex items-center gap-3 text-xs text-text-secondary mb-2",
|
|
268
268
|
children: /* @__PURE__ */ T("span", {
|
|
269
269
|
className: "flex items-center gap-1",
|
|
270
270
|
children: [/* @__PURE__ */ w(_, { className: "h-3 w-3" }), e.location?.address?.split(",")[0] || "Unknown"]
|
|
271
271
|
})
|
|
272
272
|
}),
|
|
273
273
|
/* @__PURE__ */ T("div", {
|
|
274
|
-
className: "flex items-center gap-3 text-xs text-
|
|
274
|
+
className: "flex items-center gap-3 text-xs text-text-secondary mb-3",
|
|
275
275
|
children: [e.averageOrderValue && /* @__PURE__ */ T("span", { children: ["Avg ", o(e.averageOrderValue, { minimumFractionDigits: 0 })] }), /* @__PURE__ */ T("span", {
|
|
276
276
|
className: "flex items-center gap-1",
|
|
277
277
|
children: [/* @__PURE__ */ w(_, { className: "h-3 w-3" }), s(e.distance)]
|
|
@@ -300,7 +300,7 @@ function D() {
|
|
|
300
300
|
e.serviceTypes && e.serviceTypes.length > 0 && /* @__PURE__ */ w("div", {
|
|
301
301
|
className: "flex flex-wrap gap-1 mb-3",
|
|
302
302
|
children: e.serviceTypes.slice(0, 3).map((e) => /* @__PURE__ */ w("span", {
|
|
303
|
-
className: "rounded-full bg-
|
|
303
|
+
className: "rounded-full bg-bg-sunken px-2 py-0.5 text-[10px] text-text-secondary",
|
|
304
304
|
children: e.replace(/_/g, " ")
|
|
305
305
|
}, e))
|
|
306
306
|
}),
|
|
@@ -311,13 +311,13 @@ function D() {
|
|
|
311
311
|
type: "button",
|
|
312
312
|
onClick: () => D(`/customer/cart/${e.id}`),
|
|
313
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-
|
|
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-bg-sunken text-text-secondary cursor-not-allowed"),
|
|
315
315
|
children: e.isOpen ? "View Services" : "Closed"
|
|
316
316
|
}),
|
|
317
317
|
e.serviceTypes?.includes("direct_service") && /* @__PURE__ */ w("button", {
|
|
318
318
|
type: "button",
|
|
319
319
|
onClick: () => D(`/customer/cart/${e.id}`),
|
|
320
|
-
className: "rounded-lg border border-border px-2 py-2 text-xs text-
|
|
320
|
+
className: "rounded-lg border border-border-subtle px-2 py-2 text-xs text-text-primary hover:bg-accent transition-colors",
|
|
321
321
|
title: "Book Direct Service",
|
|
322
322
|
children: /* @__PURE__ */ w(m, { className: "h-3.5 w-3.5" })
|
|
323
323
|
}),
|
|
@@ -333,7 +333,7 @@ function D() {
|
|
|
333
333
|
onClick: () => {
|
|
334
334
|
U(e), V(!0);
|
|
335
335
|
},
|
|
336
|
-
className: "rounded-lg border border-border px-2 py-2 text-xs text-
|
|
336
|
+
className: "rounded-lg border border-border-subtle px-2 py-2 text-xs text-text-primary hover:bg-accent transition-colors",
|
|
337
337
|
title: "Cart Info",
|
|
338
338
|
children: /* @__PURE__ */ w(h, { className: "h-3.5 w-3.5" })
|
|
339
339
|
})
|
|
@@ -348,7 +348,7 @@ function D() {
|
|
|
348
348
|
children: /* @__PURE__ */ w("button", {
|
|
349
349
|
type: "button",
|
|
350
350
|
onClick: () => z((e) => e + 9),
|
|
351
|
-
className: "rounded-lg border border-border px-6 py-2.5 text-sm font-medium text-
|
|
351
|
+
className: "rounded-lg border border-border-subtle px-6 py-2.5 text-sm font-medium text-text-primary hover:bg-accent transition-colors",
|
|
352
352
|
children: "Load More Carts"
|
|
353
353
|
})
|
|
354
354
|
})] }) : /* @__PURE__ */ w("div", {
|
|
@@ -368,19 +368,19 @@ function D() {
|
|
|
368
368
|
B && H && /* @__PURE__ */ w("div", {
|
|
369
369
|
className: "fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4",
|
|
370
370
|
children: /* @__PURE__ */ w("div", {
|
|
371
|
-
className: "w-full max-w-2xl max-h-[90vh] overflow-y-auto rounded-lg border border-border bg-
|
|
371
|
+
className: "w-full max-w-2xl max-h-[90vh] overflow-y-auto rounded-lg border border-border-subtle bg-bg-surface",
|
|
372
372
|
children: /* @__PURE__ */ T("div", {
|
|
373
373
|
className: "p-5",
|
|
374
374
|
children: [
|
|
375
375
|
/* @__PURE__ */ T("div", {
|
|
376
376
|
className: "flex items-center justify-between mb-4",
|
|
377
377
|
children: [/* @__PURE__ */ w("h3", {
|
|
378
|
-
className: "text-lg font-semibold text-
|
|
378
|
+
className: "text-lg font-semibold text-text-primary",
|
|
379
379
|
children: "Cart Information"
|
|
380
380
|
}), /* @__PURE__ */ w("button", {
|
|
381
381
|
type: "button",
|
|
382
382
|
onClick: () => V(!1),
|
|
383
|
-
className: "rounded-md p-1 text-
|
|
383
|
+
className: "rounded-md p-1 text-text-secondary hover:text-text-primary transition-colors",
|
|
384
384
|
children: /* @__PURE__ */ w(S, { className: "h-5 w-5" })
|
|
385
385
|
})]
|
|
386
386
|
}),
|
|
@@ -393,7 +393,7 @@ function D() {
|
|
|
393
393
|
})
|
|
394
394
|
}),
|
|
395
395
|
/* @__PURE__ */ w("h4", {
|
|
396
|
-
className: "text-xl font-semibold text-
|
|
396
|
+
className: "text-xl font-semibold text-text-primary mb-1",
|
|
397
397
|
children: H.name
|
|
398
398
|
}),
|
|
399
399
|
/* @__PURE__ */ T("div", {
|
|
@@ -407,7 +407,7 @@ function D() {
|
|
|
407
407
|
children: H.rating
|
|
408
408
|
}),
|
|
409
409
|
/* @__PURE__ */ T("span", {
|
|
410
|
-
className: "text-xs text-
|
|
410
|
+
className: "text-xs text-text-secondary",
|
|
411
411
|
children: [
|
|
412
412
|
"(",
|
|
413
413
|
H.totalRatings,
|
|
@@ -424,62 +424,62 @@ function D() {
|
|
|
424
424
|
className: "grid grid-cols-1 gap-3 sm:grid-cols-2 mb-4",
|
|
425
425
|
children: [
|
|
426
426
|
/* @__PURE__ */ T("div", {
|
|
427
|
-
className: "rounded-md bg-
|
|
427
|
+
className: "rounded-md bg-bg-sunken p-3",
|
|
428
428
|
children: [/* @__PURE__ */ T("p", {
|
|
429
|
-
className: "text-xs font-medium text-
|
|
429
|
+
className: "text-xs font-medium text-text-secondary flex items-center gap-1",
|
|
430
430
|
children: [/* @__PURE__ */ w(_, { className: "h-3 w-3" }), " Location"]
|
|
431
431
|
}), /* @__PURE__ */ w("p", {
|
|
432
|
-
className: "mt-1 text-sm text-
|
|
432
|
+
className: "mt-1 text-sm text-text-primary",
|
|
433
433
|
children: H.location.address
|
|
434
434
|
})]
|
|
435
435
|
}),
|
|
436
436
|
/* @__PURE__ */ T("div", {
|
|
437
|
-
className: "rounded-md bg-
|
|
437
|
+
className: "rounded-md bg-bg-sunken p-3",
|
|
438
438
|
children: [/* @__PURE__ */ T("p", {
|
|
439
|
-
className: "text-xs font-medium text-
|
|
439
|
+
className: "text-xs font-medium text-text-secondary flex items-center gap-1",
|
|
440
440
|
children: [/* @__PURE__ */ w(b, { className: "h-3 w-3" }), " Category"]
|
|
441
441
|
}), /* @__PURE__ */ w("p", {
|
|
442
|
-
className: "mt-1 text-sm text-
|
|
442
|
+
className: "mt-1 text-sm text-text-primary",
|
|
443
443
|
children: H.category
|
|
444
444
|
})]
|
|
445
445
|
}),
|
|
446
446
|
H.averageOrderValue && /* @__PURE__ */ T("div", {
|
|
447
|
-
className: "rounded-md bg-
|
|
447
|
+
className: "rounded-md bg-bg-sunken p-3",
|
|
448
448
|
children: [/* @__PURE__ */ w("p", {
|
|
449
|
-
className: "text-xs font-medium text-
|
|
449
|
+
className: "text-xs font-medium text-text-secondary",
|
|
450
450
|
children: "Average Order"
|
|
451
451
|
}), /* @__PURE__ */ w("p", {
|
|
452
|
-
className: "mt-1 text-sm text-
|
|
452
|
+
className: "mt-1 text-sm text-text-primary",
|
|
453
453
|
children: o(H.averageOrderValue, { minimumFractionDigits: 0 })
|
|
454
454
|
})]
|
|
455
455
|
}),
|
|
456
456
|
/* @__PURE__ */ T("div", {
|
|
457
|
-
className: "rounded-md bg-
|
|
457
|
+
className: "rounded-md bg-bg-sunken p-3",
|
|
458
458
|
children: [/* @__PURE__ */ T("p", {
|
|
459
|
-
className: "text-xs font-medium text-
|
|
459
|
+
className: "text-xs font-medium text-text-secondary flex items-center gap-1",
|
|
460
460
|
children: [/* @__PURE__ */ w(p, { className: "h-3 w-3" }), " Estimated Time"]
|
|
461
461
|
}), /* @__PURE__ */ T("p", {
|
|
462
|
-
className: "mt-1 text-sm text-
|
|
462
|
+
className: "mt-1 text-sm text-text-primary",
|
|
463
463
|
children: [H.estimatedTime, " minutes"]
|
|
464
464
|
})]
|
|
465
465
|
}),
|
|
466
466
|
/* @__PURE__ */ T("div", {
|
|
467
|
-
className: "rounded-md bg-
|
|
467
|
+
className: "rounded-md bg-bg-sunken p-3",
|
|
468
468
|
children: [/* @__PURE__ */ w("p", {
|
|
469
|
-
className: "text-xs font-medium text-
|
|
469
|
+
className: "text-xs font-medium text-text-secondary",
|
|
470
470
|
children: "Distance"
|
|
471
471
|
}), /* @__PURE__ */ w("p", {
|
|
472
|
-
className: "mt-1 text-sm text-
|
|
472
|
+
className: "mt-1 text-sm text-text-primary",
|
|
473
473
|
children: s(H.distance)
|
|
474
474
|
})]
|
|
475
475
|
}),
|
|
476
476
|
H.isVerified && /* @__PURE__ */ T("div", {
|
|
477
|
-
className: "rounded-md bg-
|
|
477
|
+
className: "rounded-md bg-bg-sunken p-3",
|
|
478
478
|
children: [/* @__PURE__ */ T("p", {
|
|
479
|
-
className: "text-xs font-medium text-
|
|
479
|
+
className: "text-xs font-medium text-text-secondary flex items-center gap-1",
|
|
480
480
|
children: [/* @__PURE__ */ w(f, { className: "h-3 w-3" }), " Verification"]
|
|
481
481
|
}), /* @__PURE__ */ w("p", {
|
|
482
|
-
className: "mt-1 text-sm text-
|
|
482
|
+
className: "mt-1 text-sm text-text-primary",
|
|
483
483
|
children: "Verified cart"
|
|
484
484
|
})]
|
|
485
485
|
})
|
|
@@ -488,12 +488,12 @@ function D() {
|
|
|
488
488
|
H.serviceTypes && H.serviceTypes.length > 0 && /* @__PURE__ */ T("div", {
|
|
489
489
|
className: "mb-4",
|
|
490
490
|
children: [/* @__PURE__ */ w("p", {
|
|
491
|
-
className: "text-xs font-medium text-
|
|
491
|
+
className: "text-xs font-medium text-text-secondary mb-2",
|
|
492
492
|
children: "Service Types"
|
|
493
493
|
}), /* @__PURE__ */ w("div", {
|
|
494
494
|
className: "flex flex-wrap gap-2",
|
|
495
495
|
children: H.serviceTypes.map((e) => /* @__PURE__ */ w("span", {
|
|
496
|
-
className: "rounded-full bg-
|
|
496
|
+
className: "rounded-full bg-bg-sunken px-2.5 py-1 text-xs text-text-secondary capitalize",
|
|
497
497
|
children: e.replace(/_/g, " ")
|
|
498
498
|
}, e))
|
|
499
499
|
})]
|
|
@@ -501,17 +501,17 @@ function D() {
|
|
|
501
501
|
H.businessHours && Object.keys(H.businessHours).length > 0 && /* @__PURE__ */ T("div", {
|
|
502
502
|
className: "mb-4",
|
|
503
503
|
children: [/* @__PURE__ */ w("p", {
|
|
504
|
-
className: "text-xs font-medium text-
|
|
504
|
+
className: "text-xs font-medium text-text-secondary mb-2",
|
|
505
505
|
children: "Operating Hours"
|
|
506
506
|
}), /* @__PURE__ */ w("div", {
|
|
507
507
|
className: "space-y-1",
|
|
508
508
|
children: Object.entries(H.businessHours).map(([e, t]) => /* @__PURE__ */ T("div", {
|
|
509
509
|
className: "flex justify-between text-xs",
|
|
510
510
|
children: [/* @__PURE__ */ w("span", {
|
|
511
|
-
className: "capitalize text-
|
|
511
|
+
className: "capitalize text-text-primary",
|
|
512
512
|
children: e
|
|
513
513
|
}), /* @__PURE__ */ w("span", {
|
|
514
|
-
className: "text-
|
|
514
|
+
className: "text-text-secondary",
|
|
515
515
|
children: t.isOpen ? `${t.open} - ${t.close}` : "Closed"
|
|
516
516
|
})]
|
|
517
517
|
}, e))
|
|
@@ -525,12 +525,12 @@ function D() {
|
|
|
525
525
|
V(!1), D(`/customer/carts/${H.id}`);
|
|
526
526
|
},
|
|
527
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-
|
|
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-bg-sunken text-text-secondary cursor-not-allowed"),
|
|
529
529
|
children: H.isOpen ? "View Menu" : "Currently Closed"
|
|
530
530
|
}), /* @__PURE__ */ w("button", {
|
|
531
531
|
type: "button",
|
|
532
532
|
onClick: () => V(!1),
|
|
533
|
-
className: "rounded-lg border border-border px-4 py-2.5 text-sm font-medium text-
|
|
533
|
+
className: "rounded-lg border border-border-subtle px-4 py-2.5 text-sm font-medium text-text-primary hover:bg-accent transition-colors",
|
|
534
534
|
children: "Close"
|
|
535
535
|
})]
|
|
536
536
|
})
|