@burdenoff/microfe-adaptercloud 2026.624.1 → 2026.625.2
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 +17 -21
- package/dist/adaptercloud/components/EmptyState.js.map +1 -1
- package/dist/adaptercloud/components/InvestmentCard.js +25 -23
- package/dist/adaptercloud/components/InvestmentCard.js.map +1 -1
- package/dist/adaptercloud/components/MetricsCard.js +18 -12
- package/dist/adaptercloud/components/MetricsCard.js.map +1 -1
- package/dist/adaptercloud/components/PageLayout.js +45 -19
- 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 +36 -16
- package/dist/adaptercloud/components/StatusBadge.js.map +1 -1
- package/dist/adaptercloud/pages/HomePage.js +244 -231
- package/dist/adaptercloud/pages/HomePage.js.map +1 -1
- package/dist/adaptercloud/pages/admin/AdminAnalyticsPage.js +121 -113
- package/dist/adaptercloud/pages/admin/AdminAnalyticsPage.js.map +1 -1
- package/dist/adaptercloud/pages/admin/AdminDashboard.js +102 -76
- package/dist/adaptercloud/pages/admin/AdminDashboard.js.map +1 -1
- package/dist/adaptercloud/pages/admin/AdminFinancialPage.js +70 -65
- package/dist/adaptercloud/pages/admin/AdminFinancialPage.js.map +1 -1
- package/dist/adaptercloud/pages/admin/AdminOrdersPage.js +108 -103
- package/dist/adaptercloud/pages/admin/AdminOrdersPage.js.map +1 -1
- package/dist/adaptercloud/pages/admin/AdminProfilePage.js +61 -59
- package/dist/adaptercloud/pages/admin/AdminProfilePage.js.map +1 -1
- package/dist/adaptercloud/pages/admin/AdminSettingsPage.js +119 -105
- package/dist/adaptercloud/pages/admin/AdminSettingsPage.js.map +1 -1
- package/dist/adaptercloud/pages/admin/CartManagementPage.js +165 -160
- package/dist/adaptercloud/pages/admin/CartManagementPage.js.map +1 -1
- package/dist/adaptercloud/pages/admin/UserManagementPage.js +174 -169
- package/dist/adaptercloud/pages/admin/UserManagementPage.js.map +1 -1
- package/dist/adaptercloud/pages/cart-owner/AnalyticsDashboard.js +103 -97
- package/dist/adaptercloud/pages/cart-owner/AnalyticsDashboard.js.map +1 -1
- package/dist/adaptercloud/pages/cart-owner/BusinessSettingsPage.js +186 -172
- package/dist/adaptercloud/pages/cart-owner/BusinessSettingsPage.js.map +1 -1
- package/dist/adaptercloud/pages/cart-owner/CartOwnerDashboard.js +109 -81
- package/dist/adaptercloud/pages/cart-owner/CartOwnerDashboard.js.map +1 -1
- package/dist/adaptercloud/pages/cart-owner/CartOwnerProfilePage.js +111 -109
- package/dist/adaptercloud/pages/cart-owner/CartOwnerProfilePage.js.map +1 -1
- package/dist/adaptercloud/pages/cart-owner/CartServiceConfigPage.js +127 -124
- package/dist/adaptercloud/pages/cart-owner/CartServiceConfigPage.js.map +1 -1
- package/dist/adaptercloud/pages/cart-owner/InventoryManagementPage.js +310 -316
- package/dist/adaptercloud/pages/cart-owner/InventoryManagementPage.js.map +1 -1
- package/dist/adaptercloud/pages/cart-owner/OrderManagementPage.js +251 -257
- package/dist/adaptercloud/pages/cart-owner/OrderManagementPage.js.map +1 -1
- package/dist/adaptercloud/pages/cart-owner/StaffManagementPage.js +142 -148
- package/dist/adaptercloud/pages/cart-owner/StaffManagementPage.js.map +1 -1
- package/dist/adaptercloud/pages/common/HelpSupportPage.js +287 -283
- package/dist/adaptercloud/pages/common/HelpSupportPage.js.map +1 -1
- package/dist/adaptercloud/pages/common/NotificationCenterPage.js +120 -114
- package/dist/adaptercloud/pages/common/NotificationCenterPage.js.map +1 -1
- package/dist/adaptercloud/pages/common/SettingsPage.js +754 -736
- package/dist/adaptercloud/pages/common/SettingsPage.js.map +1 -1
- package/dist/adaptercloud/pages/customer/BookingDetailsPage.js +83 -80
- package/dist/adaptercloud/pages/customer/BookingDetailsPage.js.map +1 -1
- package/dist/adaptercloud/pages/customer/CartDetailPage.js +120 -117
- package/dist/adaptercloud/pages/customer/CartDetailPage.js.map +1 -1
- package/dist/adaptercloud/pages/customer/CartDiscoveryPage.js +231 -226
- package/dist/adaptercloud/pages/customer/CartDiscoveryPage.js.map +1 -1
- package/dist/adaptercloud/pages/customer/CheckoutPage.js +97 -95
- package/dist/adaptercloud/pages/customer/CheckoutPage.js.map +1 -1
- package/dist/adaptercloud/pages/customer/CustomerDashboard.js +418 -389
- package/dist/adaptercloud/pages/customer/CustomerDashboard.js.map +1 -1
- package/dist/adaptercloud/pages/customer/CustomerProfilePage.js +134 -132
- package/dist/adaptercloud/pages/customer/CustomerProfilePage.js.map +1 -1
- package/dist/adaptercloud/pages/customer/DirectServiceBookingPage.js +108 -102
- package/dist/adaptercloud/pages/customer/DirectServiceBookingPage.js.map +1 -1
- package/dist/adaptercloud/pages/customer/FavoritesPage.js +62 -59
- package/dist/adaptercloud/pages/customer/FavoritesPage.js.map +1 -1
- package/dist/adaptercloud/pages/customer/OrderHistoryPage.js +117 -111
- package/dist/adaptercloud/pages/customer/OrderHistoryPage.js.map +1 -1
- package/dist/adaptercloud/pages/customer/OrderTrackingPage.js +71 -68
- package/dist/adaptercloud/pages/customer/OrderTrackingPage.js.map +1 -1
- package/dist/adaptercloud/pages/customer/PaymentMethodsPage.js +97 -81
- package/dist/adaptercloud/pages/customer/PaymentMethodsPage.js.map +1 -1
- package/dist/adaptercloud/pages/customer/ReviewsPage.js +83 -80
- package/dist/adaptercloud/pages/customer/ReviewsPage.js.map +1 -1
- package/dist/adaptercloud/pages/customer/SavedAddressesPage.js +82 -66
- package/dist/adaptercloud/pages/customer/SavedAddressesPage.js.map +1 -1
- package/dist/adaptercloud/pages/investor/InvestmentDetailsPage.js +93 -91
- package/dist/adaptercloud/pages/investor/InvestmentDetailsPage.js.map +1 -1
- package/dist/adaptercloud/pages/investor/InvestmentOpportunitiesPage.js +100 -97
- package/dist/adaptercloud/pages/investor/InvestmentOpportunitiesPage.js.map +1 -1
- package/dist/adaptercloud/pages/investor/InvestorAnalyticsPage.js +83 -81
- package/dist/adaptercloud/pages/investor/InvestorAnalyticsPage.js.map +1 -1
- package/dist/adaptercloud/pages/investor/InvestorDashboard.js +344 -311
- package/dist/adaptercloud/pages/investor/InvestorDashboard.js.map +1 -1
- package/dist/adaptercloud/pages/investor/InvestorInvestmentsPage.js +43 -40
- package/dist/adaptercloud/pages/investor/InvestorInvestmentsPage.js.map +1 -1
- package/dist/adaptercloud/pages/investor/InvestorPortfolioPage.js +59 -57
- package/dist/adaptercloud/pages/investor/InvestorPortfolioPage.js.map +1 -1
- package/dist/adaptercloud/pages/investor/InvestorProfilePage.js +394 -392
- package/dist/adaptercloud/pages/investor/InvestorProfilePage.js.map +1 -1
- package/dist/adaptercloud/pages/worker/TaskDetailsPage.js +354 -324
- package/dist/adaptercloud/pages/worker/TaskDetailsPage.js.map +1 -1
- package/dist/adaptercloud/pages/worker/WorkerDashboard.js +122 -97
- package/dist/adaptercloud/pages/worker/WorkerDashboard.js.map +1 -1
- package/dist/adaptercloud/pages/worker/WorkerOrdersPage.js +107 -104
- package/dist/adaptercloud/pages/worker/WorkerOrdersPage.js.map +1 -1
- package/dist/adaptercloud/pages/worker/WorkerProfilePage.js +109 -107
- package/dist/adaptercloud/pages/worker/WorkerProfilePage.js.map +1 -1
- package/dist/adaptercloud/pages/worker/WorkerSchedulePage.js +94 -90
- package/dist/adaptercloud/pages/worker/WorkerSchedulePage.js.map +1 -1
- package/package.json +3 -3
|
@@ -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-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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"}
|
|
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 { EmphasisPanel } from '@burdenoff/fe-libs/ui';\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 illustration=\"empty-generic\"\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-accent-blue shrink-0\" />}\n </div>\n }\n description={cart.category}\n purpose=\"See everything this cart offers and decide whether to order — its menu and prices, ratings and reviews, hours and location. Add items to your order, book a direct service, or save it to favorites for later.\"\n >\n {/* Hero Image (emphasis zone) */}\n <EmphasisPanel className=\"relative h-48 overflow-hidden p-0\">\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-status-success-bg-subtle/20 text-status-success-text' : 'bg-status-error-bg-subtle/20 text-status-error-text'\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-status-warning-text text-status-warning-text\" />\n <span className=\"font-medium\">{cart.rating}</span>\n <span className=\"text-white/70\">({cart.totalRatings})</span>\n </div>\n </div>\n </div>\n </EmphasisPanel>\n\n {/* Cart Closed Warning */}\n {!cart.isOpen && (\n <div className=\"mt-4 rounded-lg border border-status-warning-border/30 bg-status-warning-bg-subtle/10 p-3\">\n <p className=\"text-sm text-status-warning-text\">\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-seam bg-bg-surface p-4 bg-gloss-card shadow-pop\"\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-status-success-text\" />\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-seam bg-bg-surface p-4 lg:sticky lg:top-6 bg-gloss-card shadow-pop\">\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-accent-purple-subtle/30 bg-accent-purple-subtle/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-accent-purple\" />\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-accent-purple-subtle py-2 text-xs font-medium text-white hover:bg-accent-purple-subtle 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-accent-blue-subtle/30 bg-accent-blue-subtle/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-accent-blue\" />\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-status-success-border/30 bg-status-success-bg-subtle/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-status-success-text\" />\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-status-success-bg-subtle py-2 text-xs font-medium text-white hover:bg-status-success-bg-subtle 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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"}
|