@burdenoff/microfe-kadaikodi 2026.704.3 → 2026.704.5
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/kadaikodi/KadaikodiRoutes.js +34 -26
- package/dist/kadaikodi/KadaikodiRoutes.js.map +1 -1
- package/dist/kadaikodi/components/viz/AllocationBar.js +68 -0
- package/dist/kadaikodi/components/viz/AllocationBar.js.map +1 -0
- package/dist/kadaikodi/components/viz/AreaChart.js +102 -0
- package/dist/kadaikodi/components/viz/AreaChart.js.map +1 -0
- package/dist/kadaikodi/components/viz/AvatarStack.js +36 -0
- package/dist/kadaikodi/components/viz/AvatarStack.js.map +1 -0
- package/dist/kadaikodi/components/viz/BarChart.js +83 -0
- package/dist/kadaikodi/components/viz/BarChart.js.map +1 -0
- package/dist/kadaikodi/components/viz/CertificateCard.js +4 -0
- package/dist/kadaikodi/components/viz/DonutChart.js +109 -0
- package/dist/kadaikodi/components/viz/DonutChart.js.map +1 -0
- package/dist/kadaikodi/components/viz/HBarFunnel.js +54 -0
- package/dist/kadaikodi/components/viz/HBarFunnel.js.map +1 -0
- package/dist/kadaikodi/components/viz/Heatmap.js +3 -0
- package/dist/kadaikodi/components/viz/KanbanBoard.js +50 -0
- package/dist/kadaikodi/components/viz/KanbanBoard.js.map +1 -0
- package/dist/kadaikodi/components/viz/LineChart.js +4 -0
- package/dist/kadaikodi/components/viz/OrgTree.js +2 -0
- package/dist/kadaikodi/components/viz/PathSteps.js +3 -0
- package/dist/kadaikodi/components/viz/ProgressRing.js +68 -0
- package/dist/kadaikodi/components/viz/ProgressRing.js.map +1 -0
- package/dist/kadaikodi/components/viz/RatingStars.js +51 -0
- package/dist/kadaikodi/components/viz/RatingStars.js.map +1 -0
- package/dist/kadaikodi/components/viz/SegmentedTabs.js +69 -0
- package/dist/kadaikodi/components/viz/SegmentedTabs.js.map +1 -0
- package/dist/kadaikodi/components/viz/SkillBar.js +3 -0
- package/dist/kadaikodi/components/viz/Sparkline.js +74 -0
- package/dist/kadaikodi/components/viz/Sparkline.js.map +1 -0
- package/dist/kadaikodi/components/viz/StatCard.js +60 -0
- package/dist/kadaikodi/components/viz/StatCard.js.map +1 -0
- package/dist/kadaikodi/components/viz/StepProgress.js +64 -0
- package/dist/kadaikodi/components/viz/StepProgress.js.map +1 -0
- package/dist/kadaikodi/components/viz/Timeline.js +66 -0
- package/dist/kadaikodi/components/viz/Timeline.js.map +1 -0
- package/dist/kadaikodi/components/viz/index.js +23 -0
- package/dist/kadaikodi/components/viz/lib/Avatar.js +30 -0
- package/dist/kadaikodi/components/viz/lib/Avatar.js.map +1 -0
- package/dist/kadaikodi/components/viz/lib/CartesianFrame.js +119 -0
- package/dist/kadaikodi/components/viz/lib/CartesianFrame.js.map +1 -0
- package/dist/kadaikodi/components/viz/lib/ResponsiveSvg.js +35 -0
- package/dist/kadaikodi/components/viz/lib/ResponsiveSvg.js.map +1 -0
- package/dist/kadaikodi/components/viz/lib/format.js +21 -0
- package/dist/kadaikodi/components/viz/lib/format.js.map +1 -0
- package/dist/kadaikodi/components/viz/lib/geometry.js +61 -0
- package/dist/kadaikodi/components/viz/lib/geometry.js.map +1 -0
- package/dist/kadaikodi/components/viz/lib/hooks.js +39 -0
- package/dist/kadaikodi/components/viz/lib/hooks.js.map +1 -0
- package/dist/kadaikodi/components/viz/lib/palette.js +27 -0
- package/dist/kadaikodi/components/viz/lib/palette.js.map +1 -0
- package/dist/kadaikodi/hooks/useKadaikodiApi.js +84 -6
- package/dist/kadaikodi/hooks/useKadaikodiApi.js.map +1 -1
- package/dist/kadaikodi/pages/HomePage.js +373 -631
- package/dist/kadaikodi/pages/HomePage.js.map +1 -1
- package/dist/kadaikodi/pages/admin/AdminAnalyticsPage.js +304 -169
- package/dist/kadaikodi/pages/admin/AdminAnalyticsPage.js.map +1 -1
- package/dist/kadaikodi/pages/admin/AdminDashboard.js +255 -271
- package/dist/kadaikodi/pages/admin/AdminDashboard.js.map +1 -1
- package/dist/kadaikodi/pages/admin/AdminFinancialPage.js +185 -125
- package/dist/kadaikodi/pages/admin/AdminFinancialPage.js.map +1 -1
- package/dist/kadaikodi/pages/admin/AdminOrdersPage.js +141 -102
- package/dist/kadaikodi/pages/admin/AdminOrdersPage.js.map +1 -1
- package/dist/kadaikodi/pages/admin/AdminProfilePage.js.map +1 -1
- package/dist/kadaikodi/pages/admin/AdminSettingsPage.js +332 -276
- package/dist/kadaikodi/pages/admin/AdminSettingsPage.js.map +1 -1
- package/dist/kadaikodi/pages/admin/CartManagementPage.js +564 -729
- package/dist/kadaikodi/pages/admin/CartManagementPage.js.map +1 -1
- package/dist/kadaikodi/pages/admin/UserManagementPage.js +310 -366
- package/dist/kadaikodi/pages/admin/UserManagementPage.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/AnalyticsDashboard.js +201 -120
- package/dist/kadaikodi/pages/cart-owner/AnalyticsDashboard.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/BusinessSettingsPage.js +290 -257
- package/dist/kadaikodi/pages/cart-owner/BusinessSettingsPage.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/CartOwnerDashboard.js +173 -194
- package/dist/kadaikodi/pages/cart-owner/CartOwnerDashboard.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/CartOwnerProfilePage.js +270 -228
- package/dist/kadaikodi/pages/cart-owner/CartOwnerProfilePage.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/CartServiceConfigPage.js +194 -173
- package/dist/kadaikodi/pages/cart-owner/CartServiceConfigPage.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/InventoryManagementPage.js +428 -347
- package/dist/kadaikodi/pages/cart-owner/InventoryManagementPage.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/InvestmentListingPage.js +332 -0
- package/dist/kadaikodi/pages/cart-owner/InvestmentListingPage.js.map +1 -0
- package/dist/kadaikodi/pages/cart-owner/MerchantOnboardingPage.js +373 -0
- package/dist/kadaikodi/pages/cart-owner/MerchantOnboardingPage.js.map +1 -0
- package/dist/kadaikodi/pages/cart-owner/OrderManagementPage.js +294 -162
- package/dist/kadaikodi/pages/cart-owner/OrderManagementPage.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/StaffManagementPage.js +180 -181
- package/dist/kadaikodi/pages/cart-owner/StaffManagementPage.js.map +1 -1
- package/dist/kadaikodi/pages/common/HelpSupportPage.js +310 -317
- package/dist/kadaikodi/pages/common/HelpSupportPage.js.map +1 -1
- package/dist/kadaikodi/pages/common/NotificationCenterPage.js.map +1 -1
- package/dist/kadaikodi/pages/common/SettingsPage.js +502 -586
- package/dist/kadaikodi/pages/common/SettingsPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/BookingDetailsPage.js +239 -156
- package/dist/kadaikodi/pages/customer/BookingDetailsPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/CartDetailPage.js +405 -248
- package/dist/kadaikodi/pages/customer/CartDetailPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/CartDiscoveryPage.js +258 -232
- package/dist/kadaikodi/pages/customer/CartDiscoveryPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/CheckoutPage.js +254 -205
- package/dist/kadaikodi/pages/customer/CheckoutPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/CustomerDashboard.js +5 -5
- package/dist/kadaikodi/pages/customer/CustomerDashboard.js.map +1 -1
- package/dist/kadaikodi/pages/customer/CustomerProfilePage.js +189 -199
- package/dist/kadaikodi/pages/customer/CustomerProfilePage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/DirectServiceBookingPage.js +272 -230
- package/dist/kadaikodi/pages/customer/DirectServiceBookingPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/FavoritesPage.js +150 -413
- package/dist/kadaikodi/pages/customer/FavoritesPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/OrderHistoryPage.js +173 -134
- package/dist/kadaikodi/pages/customer/OrderHistoryPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/OrderTrackingPage.js +411 -305
- package/dist/kadaikodi/pages/customer/OrderTrackingPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/ReviewsPage.js +310 -406
- package/dist/kadaikodi/pages/customer/ReviewsPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/SavedAddressesPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/shared.js +181 -0
- package/dist/kadaikodi/pages/customer/shared.js.map +1 -0
- package/dist/kadaikodi/pages/investor/InvestmentDetailsPage.js +438 -311
- package/dist/kadaikodi/pages/investor/InvestmentDetailsPage.js.map +1 -1
- package/dist/kadaikodi/pages/investor/InvestmentOpportunitiesPage.js +320 -293
- package/dist/kadaikodi/pages/investor/InvestmentOpportunitiesPage.js.map +1 -1
- package/dist/kadaikodi/pages/investor/InvestorAnalyticsPage.js +159 -91
- package/dist/kadaikodi/pages/investor/InvestorAnalyticsPage.js.map +1 -1
- package/dist/kadaikodi/pages/investor/InvestorDashboard.js +137 -107
- package/dist/kadaikodi/pages/investor/InvestorDashboard.js.map +1 -1
- package/dist/kadaikodi/pages/investor/InvestorInvestmentsPage.js +157 -135
- package/dist/kadaikodi/pages/investor/InvestorInvestmentsPage.js.map +1 -1
- package/dist/kadaikodi/pages/investor/InvestorPortfolioPage.js +280 -206
- package/dist/kadaikodi/pages/investor/InvestorPortfolioPage.js.map +1 -1
- package/dist/kadaikodi/pages/investor/InvestorProfilePage.js +441 -514
- package/dist/kadaikodi/pages/investor/InvestorProfilePage.js.map +1 -1
- package/dist/kadaikodi/pages/worker/TaskDetailsPage.js +428 -431
- package/dist/kadaikodi/pages/worker/TaskDetailsPage.js.map +1 -1
- package/dist/kadaikodi/pages/worker/WorkerDashboard.js +328 -445
- package/dist/kadaikodi/pages/worker/WorkerDashboard.js.map +1 -1
- package/dist/kadaikodi/pages/worker/WorkerOrdersPage.js +141 -164
- package/dist/kadaikodi/pages/worker/WorkerOrdersPage.js.map +1 -1
- package/dist/kadaikodi/pages/worker/WorkerProfilePage.js +360 -288
- package/dist/kadaikodi/pages/worker/WorkerProfilePage.js.map +1 -1
- package/dist/kadaikodi/pages/worker/WorkerSchedulePage.js +303 -281
- package/dist/kadaikodi/pages/worker/WorkerSchedulePage.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CheckoutPage.js","names":[],"sources":["../../../../src/kadaikodi/pages/customer/CheckoutPage.tsx"],"sourcesContent":["/**\n * Checkout Page\n * @module kadaikodi/pages/customer\n *\n * Full checkout flow with delivery address form, payment method selection,\n * tip selection, special instructions, price breakdown, and Place Order CTA.\n */\n\nimport { useState, useEffect, useMemo } from 'react';\nimport {\n ArrowLeft,\n MapPin,\n CreditCard,\n Wallet,\n Banknote,\n Smartphone,\n CheckCircle2,\n ShoppingBag,\n Heart,\n AlertCircle,\n Loader2,\n} from 'lucide-react';\nimport { GlassCard, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { useKadaikodi } from '../../context/KadaikodiContext';\nimport { useOrders, usePlaceOrder } from '../../hooks/useKadaikodiApi';\nimport { cn } from '../../utils/cn';\nimport { formatCurrency } from '../../utils/formatters';\n\ntype PaymentMethod = 'cash' | 'card' | 'upi' | 'wallet';\n\ninterface DeliveryAddress {\n addressLine1: string;\n addressLine2: string;\n city: string;\n state: string;\n pincode: string;\n}\n\ninterface PaymentDetails {\n cardNumber: string;\n expiryDate: string;\n cvv: string;\n upiId: string;\n}\n\nconst paymentMethods: Array<{\n id: PaymentMethod;\n label: string;\n icon: typeof CreditCard;\n description: string;\n}> = [\n { id: 'cash', label: 'Cash on Delivery', icon: Banknote, description: 'Pay when you receive' },\n {\n id: 'card',\n label: 'Credit / Debit Card',\n icon: CreditCard,\n description: 'Visa, Mastercard, RuPay',\n },\n { id: 'upi', label: 'UPI', icon: Smartphone, description: 'Google Pay, PhonePe, Paytm' },\n { id: 'wallet', label: 'Digital Wallet', icon: Wallet, description: 'Kadaikodi Wallet Balance' },\n];\n\nconst quickTips = [0, 10, 20, 30];\n\nexport function CheckoutPage() {\n const { navigateTo, currentUser } = useKadaikodi();\n const { data: allOrders = [], isLoading } = useOrders({ customerId: currentUser?.id });\n const placeOrderMutation = usePlaceOrder();\n\n // Use the first pending order as the \"current order\" being placed, or most recent\n const order = useMemo(() => {\n return allOrders.find((o) => o.status === 'pending') || allOrders[0];\n }, [allOrders]);\n\n const [deliveryAddress, setDeliveryAddress] = useState<DeliveryAddress>({\n addressLine1: '',\n addressLine2: '',\n city: '',\n state: '',\n pincode: '',\n });\n\n const [selectedPayment, setSelectedPayment] = useState<PaymentMethod>('cash');\n const [paymentDetails, setPaymentDetails] = useState<PaymentDetails>({\n cardNumber: '',\n expiryDate: '',\n cvv: '',\n upiId: '',\n });\n\n const [tip, setTip] = useState(0);\n const [customTipInput, setCustomTipInput] = useState('');\n const [specialInstructions, setSpecialInstructions] = useState('');\n const [isPlacing, setIsPlacing] = useState(false);\n\n // Calculate order summary dynamically\n const orderSummary = useMemo(() => {\n if (!order) return { subtotal: 0, deliveryFee: 0, tax: 0, total: 0 };\n const subtotal = order.subtotal;\n const deliveryFee = order.deliveryFee;\n const tax = order.taxes;\n const discount = order.discount ?? 0;\n const total = subtotal + deliveryFee + tax + tip - discount;\n return { subtotal, deliveryFee, tax, discount, total };\n }, [order, tip]);\n\n const totalItems = useMemo(() => {\n if (!order) return 0;\n return order.items.reduce((sum, item) => sum + item.quantity, 0);\n }, [order]);\n\n const handleAddressChange = (field: keyof DeliveryAddress, value: string) => {\n setDeliveryAddress((prev) => ({ ...prev, [field]: value }));\n };\n\n const handlePaymentDetailsChange = (field: keyof PaymentDetails, value: string) => {\n setPaymentDetails((prev) => ({ ...prev, [field]: value }));\n };\n\n const validateForm = (): boolean => {\n if (!deliveryAddress.addressLine1.trim()) {\n alert('Please enter delivery address');\n return false;\n }\n if (!deliveryAddress.pincode.trim() || deliveryAddress.pincode.length !== 6) {\n alert('Please enter a valid 6-digit pincode');\n return false;\n }\n if (selectedPayment === 'card') {\n if (!paymentDetails.cardNumber || paymentDetails.cardNumber.length < 16) {\n alert('Please enter a valid 16-digit card number');\n return false;\n }\n if (!paymentDetails.expiryDate) {\n alert('Please enter card expiry date');\n return false;\n }\n if (!paymentDetails.cvv || paymentDetails.cvv.length < 3) {\n alert('Please enter a valid 3-digit CVV');\n return false;\n }\n }\n if (selectedPayment === 'upi' && !paymentDetails.upiId.trim()) {\n alert('Please enter UPI ID');\n return false;\n }\n return true;\n };\n\n const handlePlaceOrder = async () => {\n if (!validateForm() || !order) return;\n\n try {\n const result = await placeOrderMutation.mutateAsync({\n providerId: order.cartId,\n customerId: currentUser?.id,\n items: order.items.map((i) => ({\n offeringId: i.id,\n quantity: i.quantity,\n customizations: i.customizations,\n })),\n deliveryAddress: `${deliveryAddress.addressLine1}, ${deliveryAddress.addressLine2}, ${deliveryAddress.city}, ${deliveryAddress.state} - ${deliveryAddress.pincode}`,\n paymentMethod: selectedPayment.toUpperCase(),\n notes: specialInstructions,\n deliveryFee: orderSummary.deliveryFee,\n tax: orderSummary.tax,\n tip: tip,\n total: orderSummary.total,\n });\n\n alert('Order placed successfully!');\n navigateTo(`/customer/order/${result.id}`);\n } catch (err) {\n alert('Failed to place order. Please try again.');\n }\n };\n\n if (isLoading) {\n return (\n <PageLayout title=\"Checkout\">\n <div className=\"flex h-[60vh] items-center justify-center\">\n <Loader2 className=\"h-8 w-8 animate-spin text-primary\" />\n </div>\n </PageLayout>\n );\n }\n\n if (!order) {\n return (\n <PageLayout title=\"Checkout\">\n <div className=\"flex flex-col items-center justify-center py-16 text-center\">\n <ShoppingBag className=\"h-16 w-16 text-text-secondary/40 mb-4\" />\n <h3 className=\"text-lg font-semibold text-text-primary mb-2\">Your cart is empty</h3>\n <p className=\"text-sm text-text-secondary mb-6\">\n Add some items to proceed with checkout\n </p>\n <button\n type=\"button\"\n onClick={() => navigateTo('/customer/carts')}\n className=\"rounded-lg bg-foreground px-6 py-3 text-sm font-medium text-background hover:opacity-90 transition-opacity\"\n >\n Browse Carts\n </button>\n </div>\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>Checkout</span>\n </div>\n }\n description=\"Review your order and complete payment\"\n >\n <PagePurpose className=\"mb-6\">\n The last step before your food is on its way — confirm where it's going, pick how you'd like\n to pay, add a tip or special instructions, and review the total. Everything checks out?\n Place your order from the summary on the right.\n </PagePurpose>\n\n <div className=\"grid grid-cols-1 gap-6 lg:grid-cols-3\">\n {/* Left: Checkout Form */}\n <div className=\"lg:col-span-2 space-y-6\">\n {/* Delivery Address */}\n <section className=\"rounded-lg border border-border-subtle bg-bg-surface p-5\">\n <h2 className=\"text-base font-semibold text-text-primary mb-4 flex items-center gap-2\">\n <MapPin className=\"h-4 w-4 text-text-secondary\" />\n Delivery Address\n </h2>\n <div className=\"space-y-4\">\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">\n Address Line 1 <span className=\"text-status-error-text\">*</span>\n </label>\n <input\n type=\"text\"\n placeholder=\"Building, Street, Area\"\n value={deliveryAddress.addressLine1}\n onChange={(e) => handleAddressChange('addressLine1', e.target.value)}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2.5 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 <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">\n Address Line 2\n </label>\n <input\n type=\"text\"\n placeholder=\"Apartment, Suite, Floor (Optional)\"\n value={deliveryAddress.addressLine2}\n onChange={(e) => handleAddressChange('addressLine2', e.target.value)}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2.5 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 <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-4\">\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">\n City <span className=\"text-status-error-text\">*</span>\n </label>\n <input\n type=\"text\"\n placeholder=\"City\"\n value={deliveryAddress.city}\n onChange={(e) => handleAddressChange('city', e.target.value)}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2.5 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 <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">\n State <span className=\"text-status-error-text\">*</span>\n </label>\n <input\n type=\"text\"\n placeholder=\"State\"\n value={deliveryAddress.state}\n onChange={(e) => handleAddressChange('state', e.target.value)}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2.5 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 </div>\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">\n Pincode <span className=\"text-status-error-text\">*</span>\n </label>\n <input\n type=\"text\"\n placeholder=\"560001\"\n maxLength={6}\n value={deliveryAddress.pincode}\n onChange={(e) =>\n handleAddressChange('pincode', e.target.value.replace(/\\D/g, ''))\n }\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2.5 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 </div>\n </section>\n\n {/* Payment Method */}\n <section className=\"rounded-lg border border-border-subtle bg-bg-surface p-5\">\n <h2 className=\"text-base font-semibold text-text-primary mb-4 flex items-center gap-2\">\n <CreditCard className=\"h-4 w-4 text-text-secondary\" />\n Payment Method\n </h2>\n <div className=\"space-y-2\">\n {paymentMethods.map((method) => {\n const Icon = method.icon;\n return (\n <button\n key={method.id}\n type=\"button\"\n onClick={() => setSelectedPayment(method.id)}\n className={cn(\n 'flex w-full items-center gap-4 rounded-lg border p-3 transition-colors text-left',\n selectedPayment === method.id\n ? 'border-foreground bg-accent'\n : 'border-border-subtle bg-bg-surface hover:bg-accent'\n )}\n >\n <div className=\"flex h-9 w-9 shrink-0 items-center justify-center rounded-md bg-bg-sunken\">\n <Icon className=\"h-4 w-4 text-text-secondary\" />\n </div>\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-sm font-medium text-text-primary\">{method.label}</p>\n <p className=\"text-xs text-text-secondary\">{method.description}</p>\n </div>\n {selectedPayment === method.id && (\n <CheckCircle2 className=\"h-5 w-5 text-text-primary shrink-0\" />\n )}\n </button>\n );\n })}\n </div>\n\n {/* Card Payment Details */}\n {selectedPayment === 'card' && (\n <div className=\"mt-4 space-y-4 border-t border-border-subtle pt-4\">\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">\n Card Number <span className=\"text-status-error-text\">*</span>\n </label>\n <input\n type=\"text\"\n placeholder=\"1234 5678 9012 3456\"\n maxLength={16}\n value={paymentDetails.cardNumber}\n onChange={(e) =>\n handlePaymentDetailsChange('cardNumber', e.target.value.replace(/\\D/g, ''))\n }\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2.5 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 <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-4\">\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">\n Expiry Date <span className=\"text-status-error-text\">*</span>\n </label>\n <input\n type=\"text\"\n placeholder=\"MM/YY\"\n maxLength={5}\n value={paymentDetails.expiryDate}\n onChange={(e) => {\n let value = e.target.value.replace(/\\D/g, '');\n if (value.length >= 2) {\n value = value.slice(0, 2) + '/' + value.slice(2, 4);\n }\n handlePaymentDetailsChange('expiryDate', value);\n }}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2.5 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 <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">\n CVV <span className=\"text-status-error-text\">*</span>\n </label>\n <input\n type=\"text\"\n placeholder=\"123\"\n maxLength={3}\n value={paymentDetails.cvv}\n onChange={(e) =>\n handlePaymentDetailsChange('cvv', e.target.value.replace(/\\D/g, ''))\n }\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2.5 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 </div>\n </div>\n )}\n\n {/* UPI ID */}\n {selectedPayment === 'upi' && (\n <div className=\"mt-4 border-t border-border-subtle pt-4\">\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">\n UPI ID <span className=\"text-status-error-text\">*</span>\n </label>\n <input\n type=\"text\"\n placeholder=\"user@paytm\"\n value={paymentDetails.upiId}\n onChange={(e) => handlePaymentDetailsChange('upiId', e.target.value)}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2.5 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 )}\n\n {/* Wallet notice */}\n {selectedPayment === 'wallet' && (\n <div className=\"mt-4 flex items-start gap-3 rounded-lg bg-[var(--color-accent-soft)] p-4 border border-border-focus/20\">\n <AlertCircle className=\"h-4 w-4 text-text-primary mt-0.5 shrink-0\" />\n <p className=\"text-sm text-text-primary\">\n Digital wallet integration coming soon. Please choose another payment method.\n </p>\n </div>\n )}\n </section>\n\n {/* Tip and Special Instructions */}\n <section className=\"rounded-lg border border-border-subtle bg-bg-surface p-5\">\n <h2 className=\"text-base font-semibold text-text-primary mb-4 flex items-center gap-2\">\n <Heart className=\"h-4 w-4 text-text-secondary\" />\n Additional Options\n </h2>\n <div className=\"space-y-5\">\n {/* Tip Selection */}\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-2\">\n Tip for delivery partner\n </label>\n <div className=\"flex flex-wrap gap-2 mb-3\">\n {quickTips.map((amount) => (\n <button\n key={amount}\n type=\"button\"\n onClick={() => {\n setTip(amount);\n setCustomTipInput('');\n }}\n className={cn(\n 'flex-1 min-w-[64px] rounded-lg px-3 py-2.5 text-sm font-medium transition-colors',\n tip === amount && customTipInput === ''\n ? 'bg-foreground text-background'\n : 'bg-bg-sunken text-text-secondary hover:bg-accent hover:text-text-primary'\n )}\n >\n {amount === 0 ? 'No Tip' : `₹${amount}`}\n </button>\n ))}\n </div>\n <input\n type=\"number\"\n placeholder=\"Custom tip amount\"\n value={customTipInput}\n onChange={(e) => {\n const val = e.target.value;\n setCustomTipInput(val);\n setTip(parseInt(val) || 0);\n }}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2.5 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\n {/* Special Instructions */}\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-2\">\n Special Instructions\n </label>\n <textarea\n rows={3}\n placeholder=\"Any special requests for your order...\"\n value={specialInstructions}\n onChange={(e) => setSpecialInstructions(e.target.value)}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2.5 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] resize-none\"\n />\n </div>\n </div>\n </section>\n </div>\n\n {/* Right: Order Summary & Place Order — the one emphasis zone */}\n <div className=\"lg:col-span-1\">\n <GlassCard treatment=\"glass\" glow className=\"sticky top-6 p-5\">\n <h2 className=\"text-base font-semibold text-text-primary mb-4\">Order Summary</h2>\n\n {/* Cart Info */}\n <div className=\"flex items-center gap-3 mb-4 pb-4 border-b border-border-subtle\">\n <div className=\"h-12 w-12 rounded-md bg-bg-sunken overflow-hidden\">\n <img\n src={order.cartImage}\n alt={order.cartName}\n className=\"h-full w-full object-cover\"\n />\n </div>\n <div>\n <p className=\"text-sm font-medium text-text-primary\">{order.cartName}</p>\n <p className=\"text-xs text-text-secondary\">\n {order.items.length} item{order.items.length !== 1 ? 's' : ''}\n </p>\n </div>\n </div>\n\n {/* Cart Items */}\n <div className=\"space-y-2 mb-4\">\n {order.items.map((item) => (\n <div key={item.id} className=\"flex justify-between items-start\">\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-sm text-text-primary\">{item.name}</p>\n {item.customizations && item.customizations.length > 0 && (\n <p className=\"text-xs text-text-secondary mt-0.5\">\n {item.customizations.join(', ')}\n </p>\n )}\n <p className=\"text-xs text-text-secondary\">\n {formatCurrency(item.price, { minimumFractionDigits: 0 })} x {item.quantity}\n </p>\n </div>\n <span className=\"text-sm font-medium text-text-primary\">\n {formatCurrency(item.price * item.quantity, { minimumFractionDigits: 0 })}\n </span>\n </div>\n ))}\n </div>\n\n {/* Price Breakdown */}\n <div className=\"border-t border-border-subtle pt-4 space-y-2.5 text-sm\">\n <div className=\"flex justify-between\">\n <span className=\"text-text-secondary\">Subtotal ({totalItems} items)</span>\n <span className=\"text-text-primary\">\n {formatCurrency(orderSummary.subtotal, { minimumFractionDigits: 0 })}\n </span>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-text-secondary\">Delivery Fee</span>\n <span className=\"text-text-primary\">\n {orderSummary.deliveryFee === 0\n ? 'FREE'\n : formatCurrency(orderSummary.deliveryFee, { minimumFractionDigits: 0 })}\n </span>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-text-secondary\">Tax</span>\n <span className=\"text-text-primary\">\n {formatCurrency(orderSummary.tax, { minimumFractionDigits: 0 })}\n </span>\n </div>\n {tip > 0 && (\n <div className=\"flex justify-between\">\n <span className=\"text-text-secondary\">Tip</span>\n <span className=\"text-text-primary\">\n {formatCurrency(tip, { minimumFractionDigits: 0 })}\n </span>\n </div>\n )}\n {orderSummary.discount && orderSummary.discount > 0 && (\n <div className=\"flex justify-between\">\n <span className=\"text-status-success-text\">Discount</span>\n <span className=\"text-status-success-text\">\n -{formatCurrency(orderSummary.discount, { minimumFractionDigits: 0 })}\n </span>\n </div>\n )}\n </div>\n\n <div className=\"mt-4 flex justify-between border-t border-border-subtle pt-4\">\n <span className=\"text-base font-semibold text-text-primary\">Total</span>\n <span className=\"text-base font-bold text-text-primary\">\n {formatCurrency(orderSummary.total, { minimumFractionDigits: 0 })}\n </span>\n </div>\n\n <button\n type=\"button\"\n onClick={handlePlaceOrder}\n disabled={placeOrderMutation.isPending}\n className={cn(\n 'mt-6 flex w-full items-center justify-center gap-2 rounded-lg py-3 text-sm font-medium transition-opacity',\n 'bg-foreground text-background',\n placeOrderMutation.isPending ? 'opacity-60 cursor-not-allowed' : 'hover:opacity-90'\n )}\n >\n {placeOrderMutation.isPending ? (\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n ) : (\n <ShoppingBag className=\"h-4 w-4\" />\n )}\n {placeOrderMutation.isPending\n ? 'Placing Order...'\n : `Place Order - ${formatCurrency(orderSummary.total, { minimumFractionDigits: 0 })}`}\n </button>\n\n <p className=\"mt-3 text-center text-xs text-text-secondary\">\n By placing this order, you agree to our Terms of Service and Privacy Policy\n </p>\n </GlassCard>\n </div>\n </div>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CheckoutPage.js","names":[],"sources":["../../../../src/kadaikodi/pages/customer/CheckoutPage.tsx"],"sourcesContent":["/**\n * Checkout Page\n * @module kadaikodi/pages/customer\n *\n * Full checkout flow with delivery address form, payment method selection,\n * tip selection, special instructions, price breakdown, and Place Order CTA.\n */\n\nimport { useState, useEffect, useMemo } from 'react';\nimport {\n ArrowLeft,\n MapPin,\n CreditCard,\n Wallet,\n Banknote,\n Smartphone,\n CheckCircle2,\n ShoppingBag,\n Heart,\n AlertCircle,\n Loader2,\n} from 'lucide-react';\nimport { GlassCard, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { SegmentedTabs } from '../../components/viz';\nimport { useKadaikodi } from '../../context/KadaikodiContext';\nimport { useOrders, usePlaceOrder } from '../../hooks/useKadaikodiApi';\nimport { cn } from '../../utils/cn';\nimport { formatCurrency } from '../../utils/formatters';\nimport { ProviderImage } from './shared';\n\ntype PaymentMethod = 'cash' | 'card' | 'upi' | 'wallet';\ntype FulfilmentType = 'delivery' | 'pickup' | 'on_location';\n\ninterface DeliveryAddress {\n addressLine1: string;\n addressLine2: string;\n city: string;\n state: string;\n pincode: string;\n}\n\ninterface PaymentDetails {\n cardNumber: string;\n expiryDate: string;\n cvv: string;\n upiId: string;\n}\n\nconst paymentMethods: Array<{\n id: PaymentMethod;\n label: string;\n icon: typeof CreditCard;\n description: string;\n}> = [\n { id: 'cash', label: 'Cash on Delivery', icon: Banknote, description: 'Pay when you receive' },\n {\n id: 'card',\n label: 'Credit / Debit Card',\n icon: CreditCard,\n description: 'Visa, Mastercard, RuPay',\n },\n { id: 'upi', label: 'UPI', icon: Smartphone, description: 'Google Pay, PhonePe, Paytm' },\n { id: 'wallet', label: 'Digital Wallet', icon: Wallet, description: 'Kadaikodi Wallet Balance' },\n];\n\nconst quickTips = [0, 10, 20, 30];\n\nexport function CheckoutPage() {\n const { navigateTo, currentUser } = useKadaikodi();\n const { data: allOrders = [], isLoading } = useOrders({ customerId: currentUser?.id });\n const placeOrderMutation = usePlaceOrder();\n\n // Use the first pending order as the \"current order\" being placed, or most recent\n const order = useMemo(() => {\n return allOrders.find((o) => o.status === 'pending') || allOrders[0];\n }, [allOrders]);\n\n const [deliveryAddress, setDeliveryAddress] = useState<DeliveryAddress>({\n addressLine1: '',\n addressLine2: '',\n city: '',\n state: '',\n pincode: '',\n });\n\n const [fulfilment, setFulfilment] = useState<FulfilmentType>('delivery');\n const [selectedPayment, setSelectedPayment] = useState<PaymentMethod>('cash');\n const [paymentDetails, setPaymentDetails] = useState<PaymentDetails>({\n cardNumber: '',\n expiryDate: '',\n cvv: '',\n upiId: '',\n });\n\n const [tip, setTip] = useState(0);\n const [customTipInput, setCustomTipInput] = useState('');\n const [specialInstructions, setSpecialInstructions] = useState('');\n const [isPlacing, setIsPlacing] = useState(false);\n\n // Calculate order summary dynamically\n const orderSummary = useMemo(() => {\n if (!order) return { subtotal: 0, deliveryFee: 0, tax: 0, total: 0 };\n const subtotal = order.subtotal;\n const deliveryFee = fulfilment === 'delivery' ? order.deliveryFee : 0;\n const tax = order.taxes;\n const discount = order.discount ?? 0;\n const total = subtotal + deliveryFee + tax + tip - discount;\n return { subtotal, deliveryFee, tax, discount, total };\n }, [order, tip, fulfilment]);\n\n const totalItems = useMemo(() => {\n if (!order) return 0;\n return order.items.reduce((sum, item) => sum + item.quantity, 0);\n }, [order]);\n\n const handleAddressChange = (field: keyof DeliveryAddress, value: string) => {\n setDeliveryAddress((prev) => ({ ...prev, [field]: value }));\n };\n\n const handlePaymentDetailsChange = (field: keyof PaymentDetails, value: string) => {\n setPaymentDetails((prev) => ({ ...prev, [field]: value }));\n };\n\n const validateForm = (): boolean => {\n // Address is only required when the order is being delivered.\n if (fulfilment === 'delivery') {\n if (!deliveryAddress.addressLine1.trim()) {\n alert('Please enter delivery address');\n return false;\n }\n if (!deliveryAddress.pincode.trim() || deliveryAddress.pincode.length !== 6) {\n alert('Please enter a valid 6-digit pincode');\n return false;\n }\n }\n if (selectedPayment === 'card') {\n if (!paymentDetails.cardNumber || paymentDetails.cardNumber.length < 16) {\n alert('Please enter a valid 16-digit card number');\n return false;\n }\n if (!paymentDetails.expiryDate) {\n alert('Please enter card expiry date');\n return false;\n }\n if (!paymentDetails.cvv || paymentDetails.cvv.length < 3) {\n alert('Please enter a valid 3-digit CVV');\n return false;\n }\n }\n if (selectedPayment === 'upi' && !paymentDetails.upiId.trim()) {\n alert('Please enter UPI ID');\n return false;\n }\n if (selectedPayment === 'wallet') {\n alert('Digital wallet integration is coming soon. Please choose another payment method.');\n return false;\n }\n return true;\n };\n\n const handlePlaceOrder = async () => {\n if (!validateForm() || !order) return;\n\n try {\n const result = await placeOrderMutation.mutateAsync({\n providerId: order.cartId,\n customerId: currentUser?.id,\n fulfillmentType: fulfilment,\n items: order.items.map((i) => ({\n offeringId: i.id,\n quantity: i.quantity,\n customizations: i.customizations,\n })),\n deliveryAddress:\n fulfilment === 'delivery'\n ? `${deliveryAddress.addressLine1}, ${deliveryAddress.addressLine2}, ${deliveryAddress.city}, ${deliveryAddress.state} - ${deliveryAddress.pincode}`\n : undefined,\n paymentMethod: selectedPayment.toUpperCase(),\n notes: specialInstructions,\n deliveryFee: orderSummary.deliveryFee,\n tax: orderSummary.tax,\n tip: tip,\n total: orderSummary.total,\n });\n\n alert('Order placed successfully!');\n navigateTo(`/customer/orders/${result.id}/track`);\n } catch (err) {\n alert('Failed to place order. Please try again.');\n }\n };\n\n if (isLoading) {\n return (\n <PageLayout title=\"Checkout\">\n <div className=\"flex h-[60vh] items-center justify-center\">\n <Loader2 className=\"h-8 w-8 animate-spin text-primary\" />\n </div>\n </PageLayout>\n );\n }\n\n if (!order) {\n return (\n <PageLayout title=\"Checkout\">\n <div className=\"flex flex-col items-center justify-center py-16 text-center\">\n <ShoppingBag className=\"h-16 w-16 text-text-secondary/40 mb-4\" />\n <h3 className=\"text-lg font-semibold text-text-primary mb-2\">Your cart is empty</h3>\n <p className=\"text-sm text-text-secondary mb-6\">\n Add some items to proceed with checkout\n </p>\n <button\n type=\"button\"\n onClick={() => navigateTo('/customer/discover')}\n className=\"rounded-lg bg-foreground px-6 py-3 text-sm font-medium text-background hover:opacity-90 transition-opacity\"\n >\n Browse Carts\n </button>\n </div>\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/discover')}\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>Checkout</span>\n </div>\n }\n description=\"Review your order and complete payment\"\n >\n <PagePurpose className=\"mb-6\">\n The last step before your food is on its way — confirm where it's going, pick how you'd like\n to pay, add a tip or special instructions, and review the total. Everything checks out?\n Place your order from the summary on the right.\n </PagePurpose>\n\n <div className=\"grid grid-cols-1 gap-6 lg:grid-cols-3\">\n {/* Left: Checkout Form */}\n <div className=\"lg:col-span-2 space-y-6\">\n {/* Fulfilment */}\n <section className=\"rounded-lg border border-border-subtle bg-bg-surface p-5\">\n <h2 className=\"text-base font-semibold text-text-primary mb-4\">Fulfilment</h2>\n <SegmentedTabs\n fill\n aria-label=\"Fulfilment method\"\n tabs={[\n { id: 'delivery', label: 'Delivery' },\n { id: 'pickup', label: 'Pickup' },\n { id: 'on_location', label: 'On-location' },\n ]}\n value={fulfilment}\n onChange={(id) => setFulfilment(id as FulfilmentType)}\n />\n <p className=\"mt-3 text-xs text-text-secondary\">\n {fulfilment === 'delivery'\n ? 'A delivery partner brings your order to the address below.'\n : fulfilment === 'pickup'\n ? 'Collect your order from the cart — no delivery fee.'\n : 'The cart serves you at your location — no delivery fee.'}\n </p>\n </section>\n\n {/* Delivery Address */}\n {fulfilment === 'delivery' && (\n <section className=\"rounded-lg border border-border-subtle bg-bg-surface p-5\">\n <h2 className=\"text-base font-semibold text-text-primary mb-4 flex items-center gap-2\">\n <MapPin className=\"h-4 w-4 text-text-secondary\" />\n Delivery Address\n </h2>\n <div className=\"space-y-4\">\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">\n Address Line 1 <span className=\"text-status-error-text\">*</span>\n </label>\n <input\n type=\"text\"\n placeholder=\"Building, Street, Area\"\n value={deliveryAddress.addressLine1}\n onChange={(e) => handleAddressChange('addressLine1', e.target.value)}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2.5 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 <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">\n Address Line 2\n </label>\n <input\n type=\"text\"\n placeholder=\"Apartment, Suite, Floor (Optional)\"\n value={deliveryAddress.addressLine2}\n onChange={(e) => handleAddressChange('addressLine2', e.target.value)}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2.5 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 <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-4\">\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">\n City <span className=\"text-status-error-text\">*</span>\n </label>\n <input\n type=\"text\"\n placeholder=\"City\"\n value={deliveryAddress.city}\n onChange={(e) => handleAddressChange('city', e.target.value)}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2.5 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 <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">\n State <span className=\"text-status-error-text\">*</span>\n </label>\n <input\n type=\"text\"\n placeholder=\"State\"\n value={deliveryAddress.state}\n onChange={(e) => handleAddressChange('state', e.target.value)}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2.5 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 </div>\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">\n Pincode <span className=\"text-status-error-text\">*</span>\n </label>\n <input\n type=\"text\"\n placeholder=\"560001\"\n maxLength={6}\n value={deliveryAddress.pincode}\n onChange={(e) =>\n handleAddressChange('pincode', e.target.value.replace(/\\D/g, ''))\n }\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2.5 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 </div>\n </section>\n )}\n\n {/* Payment Method */}\n <section className=\"rounded-lg border border-border-subtle bg-bg-surface p-5\">\n <h2 className=\"text-base font-semibold text-text-primary mb-4 flex items-center gap-2\">\n <CreditCard className=\"h-4 w-4 text-text-secondary\" />\n Payment Method\n </h2>\n <div className=\"space-y-2\">\n {paymentMethods.map((method) => {\n const Icon = method.icon;\n return (\n <button\n key={method.id}\n type=\"button\"\n onClick={() => setSelectedPayment(method.id)}\n className={cn(\n 'flex w-full items-center gap-4 rounded-lg border p-3 transition-colors text-left',\n selectedPayment === method.id\n ? 'border-foreground bg-accent'\n : 'border-border-subtle bg-bg-surface hover:bg-accent'\n )}\n >\n <div className=\"flex h-9 w-9 shrink-0 items-center justify-center rounded-md bg-bg-sunken\">\n <Icon className=\"h-4 w-4 text-text-secondary\" />\n </div>\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-sm font-medium text-text-primary\">{method.label}</p>\n <p className=\"text-xs text-text-secondary\">{method.description}</p>\n </div>\n {selectedPayment === method.id && (\n <CheckCircle2 className=\"h-5 w-5 text-text-primary shrink-0\" />\n )}\n </button>\n );\n })}\n </div>\n\n {/* Card Payment Details */}\n {selectedPayment === 'card' && (\n <div className=\"mt-4 space-y-4 border-t border-border-subtle pt-4\">\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">\n Card Number <span className=\"text-status-error-text\">*</span>\n </label>\n <input\n type=\"text\"\n placeholder=\"1234 5678 9012 3456\"\n maxLength={16}\n value={paymentDetails.cardNumber}\n onChange={(e) =>\n handlePaymentDetailsChange('cardNumber', e.target.value.replace(/\\D/g, ''))\n }\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2.5 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 <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-4\">\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">\n Expiry Date <span className=\"text-status-error-text\">*</span>\n </label>\n <input\n type=\"text\"\n placeholder=\"MM/YY\"\n maxLength={5}\n value={paymentDetails.expiryDate}\n onChange={(e) => {\n let value = e.target.value.replace(/\\D/g, '');\n if (value.length >= 2) {\n value = value.slice(0, 2) + '/' + value.slice(2, 4);\n }\n handlePaymentDetailsChange('expiryDate', value);\n }}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2.5 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 <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">\n CVV <span className=\"text-status-error-text\">*</span>\n </label>\n <input\n type=\"text\"\n placeholder=\"123\"\n maxLength={3}\n value={paymentDetails.cvv}\n onChange={(e) =>\n handlePaymentDetailsChange('cvv', e.target.value.replace(/\\D/g, ''))\n }\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2.5 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 </div>\n </div>\n )}\n\n {/* UPI ID */}\n {selectedPayment === 'upi' && (\n <div className=\"mt-4 border-t border-border-subtle pt-4\">\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">\n UPI ID <span className=\"text-status-error-text\">*</span>\n </label>\n <input\n type=\"text\"\n placeholder=\"user@paytm\"\n value={paymentDetails.upiId}\n onChange={(e) => handlePaymentDetailsChange('upiId', e.target.value)}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2.5 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 )}\n\n {/* Wallet notice */}\n {selectedPayment === 'wallet' && (\n <div className=\"mt-4 flex items-start gap-3 rounded-lg bg-[var(--color-accent-soft)] p-4 border border-border-focus/20\">\n <AlertCircle className=\"h-4 w-4 text-text-primary mt-0.5 shrink-0\" />\n <p className=\"text-sm text-text-primary\">\n Digital wallet integration coming soon. Please choose another payment method.\n </p>\n </div>\n )}\n </section>\n\n {/* Tip and Special Instructions */}\n <section className=\"rounded-lg border border-border-subtle bg-bg-surface p-5\">\n <h2 className=\"text-base font-semibold text-text-primary mb-4 flex items-center gap-2\">\n <Heart className=\"h-4 w-4 text-text-secondary\" />\n Additional Options\n </h2>\n <div className=\"space-y-5\">\n {/* Tip Selection */}\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-2\">\n Tip for delivery partner\n </label>\n <div className=\"flex flex-wrap gap-2 mb-3\">\n {quickTips.map((amount) => (\n <button\n key={amount}\n type=\"button\"\n onClick={() => {\n setTip(amount);\n setCustomTipInput('');\n }}\n className={cn(\n 'flex-1 min-w-[64px] rounded-lg px-3 py-2.5 text-sm font-medium transition-colors',\n tip === amount && customTipInput === ''\n ? 'bg-foreground text-background'\n : 'bg-bg-sunken text-text-secondary hover:bg-accent hover:text-text-primary'\n )}\n >\n {amount === 0 ? 'No Tip' : `₹${amount}`}\n </button>\n ))}\n </div>\n <input\n type=\"number\"\n placeholder=\"Custom tip amount\"\n value={customTipInput}\n onChange={(e) => {\n const val = e.target.value;\n setCustomTipInput(val);\n setTip(parseInt(val) || 0);\n }}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2.5 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\n {/* Special Instructions */}\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-2\">\n Special Instructions\n </label>\n <textarea\n rows={3}\n placeholder=\"Any special requests for your order...\"\n value={specialInstructions}\n onChange={(e) => setSpecialInstructions(e.target.value)}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2.5 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] resize-none\"\n />\n </div>\n </div>\n </section>\n </div>\n\n {/* Right: Order Summary & Place Order — the one emphasis zone */}\n <div className=\"lg:col-span-1\">\n <GlassCard treatment=\"glass\" glow className=\"sticky top-6 p-5\">\n <h2 className=\"text-base font-semibold text-text-primary mb-4\">Order Summary</h2>\n\n {/* Cart Info */}\n <div className=\"flex items-center gap-3 mb-4 pb-4 border-b border-border-subtle\">\n <div className=\"h-12 w-12 rounded-md bg-bg-sunken overflow-hidden\">\n <ProviderImage src={order.cartImage} alt={order.cartName} seed={order.cartName} />\n </div>\n <div className=\"min-w-0\">\n <p className=\"text-sm font-medium text-text-primary truncate\">{order.cartName}</p>\n <p className=\"text-xs text-text-secondary capitalize\">\n {order.items.length} item{order.items.length !== 1 ? 's' : ''} ·{' '}\n {fulfilment.replace('_', '-')}\n </p>\n </div>\n </div>\n\n {/* Cart Items */}\n <div className=\"space-y-2 mb-4\">\n {order.items.map((item) => (\n <div key={item.id} className=\"flex justify-between items-start\">\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-sm text-text-primary\">{item.name}</p>\n {item.customizations && item.customizations.length > 0 && (\n <p className=\"text-xs text-text-secondary mt-0.5\">\n {item.customizations.join(', ')}\n </p>\n )}\n <p className=\"text-xs text-text-secondary\">\n {formatCurrency(item.price, { minimumFractionDigits: 0 })} x {item.quantity}\n </p>\n </div>\n <span className=\"text-sm font-medium text-text-primary\">\n {formatCurrency(item.price * item.quantity, { minimumFractionDigits: 0 })}\n </span>\n </div>\n ))}\n </div>\n\n {/* Price Breakdown */}\n <div className=\"border-t border-border-subtle pt-4 space-y-2.5 text-sm\">\n <div className=\"flex justify-between\">\n <span className=\"text-text-secondary\">Subtotal ({totalItems} items)</span>\n <span className=\"text-text-primary\">\n {formatCurrency(orderSummary.subtotal, { minimumFractionDigits: 0 })}\n </span>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-text-secondary\">Delivery Fee</span>\n <span className=\"text-text-primary\">\n {orderSummary.deliveryFee === 0\n ? 'FREE'\n : formatCurrency(orderSummary.deliveryFee, { minimumFractionDigits: 0 })}\n </span>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-text-secondary\">Tax</span>\n <span className=\"text-text-primary\">\n {formatCurrency(orderSummary.tax, { minimumFractionDigits: 0 })}\n </span>\n </div>\n {tip > 0 && (\n <div className=\"flex justify-between\">\n <span className=\"text-text-secondary\">Tip</span>\n <span className=\"text-text-primary\">\n {formatCurrency(tip, { minimumFractionDigits: 0 })}\n </span>\n </div>\n )}\n {orderSummary.discount && orderSummary.discount > 0 && (\n <div className=\"flex justify-between\">\n <span className=\"text-status-success-text\">Discount</span>\n <span className=\"text-status-success-text\">\n -{formatCurrency(orderSummary.discount, { minimumFractionDigits: 0 })}\n </span>\n </div>\n )}\n </div>\n\n <div className=\"mt-4 flex justify-between border-t border-border-subtle pt-4\">\n <span className=\"text-base font-semibold text-text-primary\">Total</span>\n <span className=\"text-base font-bold text-text-primary\">\n {formatCurrency(orderSummary.total, { minimumFractionDigits: 0 })}\n </span>\n </div>\n\n <button\n type=\"button\"\n onClick={handlePlaceOrder}\n disabled={placeOrderMutation.isPending}\n className={cn(\n 'mt-6 flex w-full items-center justify-center gap-2 rounded-lg py-3 text-sm font-medium transition-opacity',\n 'bg-foreground text-background',\n placeOrderMutation.isPending ? 'opacity-60 cursor-not-allowed' : 'hover:opacity-90'\n )}\n >\n {placeOrderMutation.isPending ? (\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n ) : (\n <ShoppingBag className=\"h-4 w-4\" />\n )}\n {placeOrderMutation.isPending\n ? 'Placing Order...'\n : `Place Order - ${formatCurrency(orderSummary.total, { minimumFractionDigits: 0 })}`}\n </button>\n\n <p className=\"mt-3 text-center text-xs text-text-secondary\">\n By placing this order, you agree to our Terms of Service and Privacy Policy\n </p>\n </GlassCard>\n </div>\n </div>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|
|
@@ -59,7 +59,7 @@ function w() {
|
|
|
59
59
|
id: "discover",
|
|
60
60
|
label: "Discover carts near you",
|
|
61
61
|
description: "Browse open mobile carts in your area and view their menus.",
|
|
62
|
-
onClick: () => w("/customer/
|
|
62
|
+
onClick: () => w("/customer/discover")
|
|
63
63
|
},
|
|
64
64
|
{
|
|
65
65
|
id: "address",
|
|
@@ -128,7 +128,7 @@ function w() {
|
|
|
128
128
|
children: [
|
|
129
129
|
/* @__PURE__ */ y("button", {
|
|
130
130
|
type: "button",
|
|
131
|
-
onClick: () => w("/customer/
|
|
131
|
+
onClick: () => w("/customer/discover"),
|
|
132
132
|
className: t("flex items-center gap-3 rounded-lg border border-border-subtle bg-bg-surface p-4 shadow-sm transition-colors text-left", "hover:bg-accent hover:shadow-md"),
|
|
133
133
|
children: [/* @__PURE__ */ v("div", {
|
|
134
134
|
className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-[var(--color-accent-soft)]",
|
|
@@ -233,7 +233,7 @@ function w() {
|
|
|
233
233
|
]
|
|
234
234
|
}), /* @__PURE__ */ v("button", {
|
|
235
235
|
type: "button",
|
|
236
|
-
onClick: () => w(`/customer/orders/${e.id}`),
|
|
236
|
+
onClick: () => w(`/customer/orders/${e.id}/track`),
|
|
237
237
|
className: "rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium text-text-primary hover:bg-accent transition-colors",
|
|
238
238
|
children: M("kadaikodi.customerDashboard.viewDetails", "View Details")
|
|
239
239
|
})]
|
|
@@ -245,7 +245,7 @@ function w() {
|
|
|
245
245
|
description: M("kadaikodi.customerDashboard.noRecentOrdersDesc", "Your orders will show up here once you place one. Discover a cart to get started."),
|
|
246
246
|
action: /* @__PURE__ */ v("button", {
|
|
247
247
|
type: "button",
|
|
248
|
-
onClick: () => w("/customer/
|
|
248
|
+
onClick: () => w("/customer/discover"),
|
|
249
249
|
className: "rounded-lg bg-foreground px-4 py-2 text-sm font-medium text-background hover:opacity-90 transition-opacity",
|
|
250
250
|
children: M("kadaikodi.customerDashboard.discoverCarts", "Discover Carts")
|
|
251
251
|
})
|
|
@@ -306,7 +306,7 @@ function w() {
|
|
|
306
306
|
/* @__PURE__ */ v("button", {
|
|
307
307
|
type: "button",
|
|
308
308
|
disabled: !e.isOpen,
|
|
309
|
-
onClick: () => e.isOpen && w(`/customer/
|
|
309
|
+
onClick: () => e.isOpen && w(`/customer/cart/${e.id}`),
|
|
310
310
|
className: t("w-full rounded-lg py-2 text-sm font-medium transition-opacity", e.isOpen ? "bg-foreground text-background hover:opacity-90" : "bg-bg-sunken text-text-secondary cursor-not-allowed"),
|
|
311
311
|
children: e.isOpen ? M("kadaikodi.customerDashboard.viewMenu", "View Menu") : M("kadaikodi.customerDashboard.currentlyClosed", "Currently Closed")
|
|
312
312
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CustomerDashboard.js","names":[],"sources":["../../../../src/kadaikodi/pages/customer/CustomerDashboard.tsx"],"sourcesContent":["/**\n * Customer Dashboard Page\n * @module kadaikodi/pages/customer\n *\n * Welcome dashboard with time-of-day greeting, AI insights panel,\n * stats grid, recent orders with per-item display, recommended carts,\n * quick links sidebar, current location card, and special offers.\n */\n\nimport { useCallback } from 'react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n Heart,\n Star,\n CreditCard,\n ArrowRight,\n Search,\n Clock,\n MapPin,\n Package,\n User,\n} from 'lucide-react';\nimport { EmphasisPanel, PagePurpose, NextSteps } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { EmptyState } from '../../components/EmptyState';\nimport { useKadaikodi } from '../../context/KadaikodiContext';\nimport { useOrders, useProviders } from '../../hooks/useKadaikodiApi';\nimport { cn } from '../../utils/cn';\nimport { formatCurrency } from '../../utils/formatters';\n\ninterface CustomerStats {\n totalOrders: number;\n totalSpent: number;\n}\n\nfunction getTimeOfDayGreeting(): string {\n const hour = new Date().getHours();\n if (hour < 12) return 'Good morning';\n if (hour < 17) return 'Good afternoon';\n return 'Good evening';\n}\n\nexport function CustomerDashboard() {\n const { navigateTo, currentUser } = useKadaikodi();\n const { t: translate } = useI18n();\n\n const { data: orders = [], isLoading: isLoadingOrders } = useOrders({\n customerId: currentUser?.id,\n });\n const { data: providers = [], isLoading: isLoadingProviders } = useProviders();\n\n const isLoading = isLoadingOrders || isLoadingProviders;\n\n const t = useCallback(\n (key: string, fallback: string): string => {\n const value = translate(key);\n return value === key ? fallback : value;\n },\n [translate]\n );\n\n const firstName = currentUser?.firstName ?? currentUser?.name ?? 'Customer';\n\n const recentOrders = orders.slice(0, 3);\n const recommendedCarts = providers.slice(0, 3);\n\n const stats: CustomerStats = {\n totalOrders: orders.length,\n totalSpent: orders.reduce((acc, order) => acc + order.total, 0),\n };\n\n const getStatusColor = (status: string) => {\n switch (status) {\n case 'delivered':\n return 'bg-status-success-bg-subtle text-status-success-text';\n case 'preparing':\n return 'bg-status-warning-bg-subtle text-status-warning-text';\n case 'out_for_delivery':\n return 'bg-[var(--color-accent-soft)] text-text-primary';\n case 'confirmed':\n return 'bg-[var(--color-accent-soft)] text-text-primary';\n case 'cancelled':\n return 'bg-status-error-bg-subtle text-status-error-text';\n default:\n return 'bg-bg-sunken text-text-secondary';\n }\n };\n\n if (isLoading) {\n return (\n <PageLayout title={t('kadaikodi.customerDashboard.title', 'Dashboard')}>\n <div className=\"flex items-center justify-center py-20\">\n <div className=\"text-center\">\n <div className=\"mx-auto mb-4 h-12 w-12 animate-spin rounded-full border-b-2 border-foreground\" />\n <p className=\"text-sm text-text-secondary\">\n {t('kadaikodi.customerDashboard.loading', 'Loading your dashboard...')}\n </p>\n </div>\n </div>\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title={t('kadaikodi.customerDashboard.welcomeBack', 'Welcome Back!')}\n description={`${getTimeOfDayGreeting()}, ${firstName}`}\n >\n <PagePurpose className=\"mb-6\">\n Your home base on Kadaikodi — discover mobile food carts near you, reorder favourites in a\n tap, and keep an eye on your orders and spending. Start by exploring nearby carts or\n revisiting a recent order below.\n </PagePurpose>\n\n <NextSteps\n storageKey=\"kadaikodi-customer-dashboard\"\n className=\"mb-6\"\n steps={[\n {\n id: 'discover',\n label: 'Discover carts near you',\n description: 'Browse open mobile carts in your area and view their menus.',\n onClick: () => navigateTo('/customer/carts'),\n },\n {\n id: 'address',\n label: 'Set your delivery address',\n description: 'Save your home or work address for faster checkout.',\n onClick: () => navigateTo('/customer/addresses'),\n },\n {\n id: 'payment',\n label: 'Add a payment method',\n description: 'Securely store a card or UPI so ordering is one tap.',\n onClick: () => navigateTo('/customer/payment-methods'),\n },\n ]}\n />\n\n {/* Stats Overview — the one emphasis zone for this dashboard */}\n {stats && (\n <EmphasisPanel className=\"mb-8\">\n <h2 className=\"mb-4 text-lg font-semibold text-text-primary\">\n {t('kadaikodi.customerDashboard.yourActivity', 'Your Activity')}\n </h2>\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-4\">\n <div className=\"flex items-center gap-3\">\n <div className=\"flex h-10 w-10 items-center justify-center rounded-lg bg-bg-sunken\">\n <Package className=\"h-5 w-5 text-text-secondary\" />\n </div>\n <div>\n <p className=\"text-2xl font-bold text-text-primary\">{stats.totalOrders}</p>\n <p className=\"text-xs text-text-secondary\">\n {t('kadaikodi.customerDashboard.totalOrders', 'Total Orders')}\n </p>\n </div>\n </div>\n </div>\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-4\">\n <div className=\"flex items-center gap-3\">\n <div className=\"flex h-10 w-10 items-center justify-center rounded-lg bg-bg-sunken\">\n <CreditCard className=\"h-5 w-5 text-text-secondary\" />\n </div>\n <div>\n <p className=\"text-2xl font-bold text-text-primary\">\n {formatCurrency(stats.totalSpent, { minimumFractionDigits: 0 })}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {t('kadaikodi.customerDashboard.totalSpent', 'Total Spent')}\n </p>\n </div>\n </div>\n </div>\n </div>\n </EmphasisPanel>\n )}\n\n <div className=\"mt-8 grid grid-cols-1 gap-8 lg:grid-cols-3\">\n {/* Main Content */}\n <div className=\"lg:col-span-2 space-y-8\">\n {/* Quick Actions */}\n <section>\n <h2 className=\"text-lg font-semibold text-text-primary mb-4\">\n {t('kadaikodi.customerDashboard.quickActions', 'Quick Actions')}\n </h2>\n <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-3\">\n <button\n type=\"button\"\n onClick={() => navigateTo('/customer/carts')}\n className={cn(\n 'flex items-center gap-3 rounded-lg border border-border-subtle bg-bg-surface p-4 shadow-sm transition-colors text-left',\n 'hover:bg-accent hover:shadow-md'\n )}\n >\n <div className=\"flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-[var(--color-accent-soft)]\">\n <Search className=\"h-5 w-5 text-text-primary\" />\n </div>\n <div className=\"min-w-0\">\n <p className=\"text-sm font-semibold text-text-primary\">\n {t('kadaikodi.customerDashboard.discoverCarts', 'Discover Carts')}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {t('kadaikodi.customerDashboard.findNearbyCarts', 'Find nearby carts')}\n </p>\n </div>\n </button>\n\n <button\n type=\"button\"\n onClick={() => navigateTo('/customer/orders')}\n className={cn(\n 'flex items-center gap-3 rounded-lg border border-border-subtle bg-bg-surface p-4 shadow-sm transition-colors text-left',\n 'hover:bg-accent hover:shadow-md'\n )}\n >\n <div className=\"flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-status-success-bg-subtle\">\n <Clock className=\"h-5 w-5 text-status-success-text\" />\n </div>\n <div className=\"min-w-0\">\n <p className=\"text-sm font-semibold text-text-primary\">\n {t('kadaikodi.customerDashboard.orderHistory', 'Order History')}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {t('kadaikodi.customerDashboard.viewPastOrders', 'View past orders')}\n </p>\n </div>\n </button>\n\n <button\n type=\"button\"\n onClick={() => navigateTo('/customer/favorites')}\n className={cn(\n 'flex items-center gap-3 rounded-lg border border-border-subtle bg-bg-surface p-4 shadow-sm transition-colors text-left',\n 'hover:bg-accent hover:shadow-md'\n )}\n >\n <div className=\"flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-status-error-bg-subtle\">\n <Heart className=\"h-5 w-5 text-status-error-text\" />\n </div>\n <div className=\"min-w-0\">\n <p className=\"text-sm font-semibold text-text-primary\">\n {t('kadaikodi.customerDashboard.favorites', 'Favorites')}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {t('kadaikodi.customerDashboard.savedCarts', 'Saved carts')}\n </p>\n </div>\n </button>\n </div>\n </section>\n\n {/* Recent Orders */}\n <section>\n <div className=\"flex items-center justify-between mb-4\">\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {t('kadaikodi.customerDashboard.recentOrders', 'Recent Orders')}\n </h2>\n <button\n type=\"button\"\n onClick={() => navigateTo('/customer/orders')}\n className=\"flex items-center gap-1 text-sm font-medium text-text-secondary hover:text-text-primary transition-colors\"\n >\n {t('kadaikodi.common.viewAll', 'View All')}\n <ArrowRight className=\"h-4 w-4\" />\n </button>\n </div>\n\n {recentOrders.length > 0 ? (\n <div className=\"space-y-3\">\n {recentOrders.map((order) => (\n <div\n key={order.id}\n className=\"rounded-lg border border-border-subtle bg-bg-surface p-4\"\n >\n <div className=\"flex flex-col sm:flex-row sm:items-start sm:justify-between gap-3\">\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex flex-wrap items-center gap-2 mb-1\">\n <h3 className=\"text-sm font-semibold text-text-primary\">\n {order.cartName}\n </h3>\n <span\n className={cn(\n 'inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium capitalize',\n getStatusColor(order.status)\n )}\n >\n {order.status.replace(/_/g, ' ')}\n </span>\n </div>\n <p className=\"text-xs text-text-secondary mb-2 leading-relaxed\">\n {order.items.map((item) => `${item.name} (${item.quantity})`).join(', ')}\n </p>\n <div className=\"flex flex-wrap items-center gap-3 text-xs text-text-secondary\">\n <span className=\"font-medium text-text-primary\">\n {formatCurrency(order.total, { minimumFractionDigits: 0 })}\n </span>\n <span>{new Date(order.orderDate).toLocaleDateString()}</span>\n {order.rating && (\n <span className=\"flex items-center gap-1\">\n <Star className=\"h-3 w-3 fill-status-warning-text text-status-warning-text\" />\n {order.rating}\n </span>\n )}\n </div>\n </div>\n <button\n type=\"button\"\n onClick={() => navigateTo(`/customer/orders/${order.id}`)}\n className=\"rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium text-text-primary hover:bg-accent transition-colors\"\n >\n {t('kadaikodi.customerDashboard.viewDetails', 'View Details')}\n </button>\n </div>\n </div>\n ))}\n </div>\n ) : (\n <EmptyState\n illustration=\"empty-data\"\n title={t('kadaikodi.customerDashboard.noRecentOrders', 'No recent orders')}\n description={t(\n 'kadaikodi.customerDashboard.noRecentOrdersDesc',\n 'Your orders will show up here once you place one. Discover a cart to get started.'\n )}\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 {t('kadaikodi.customerDashboard.discoverCarts', 'Discover Carts')}\n </button>\n }\n />\n )}\n </section>\n\n {/* Recommended Carts */}\n <section>\n <h2 className=\"text-lg font-semibold text-text-primary mb-4\">\n {t('kadaikodi.customerDashboard.recommendedForYou', 'Recommended for You')}\n </h2>\n {recommendedCarts.length > 0 ? (\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n {recommendedCarts.map((cart) => (\n <div\n key={cart.id}\n className=\"rounded-lg border border-border-subtle bg-bg-surface overflow-hidden shadow-sm hover:shadow-md transition-shadow\"\n >\n <div className=\"p-4\">\n <div className=\"flex items-start justify-between mb-2\">\n <div className=\"min-w-0 flex-1\">\n <h3 className=\"text-sm font-semibold text-text-primary\">{cart.name}</h3>\n <p className=\"text-xs text-text-secondary\">{cart.category}</p>\n </div>\n <div className=\"flex items-center gap-2\">\n <span\n className={cn(\n 'inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium',\n cart.isOpen\n ? 'bg-status-success-bg-subtle text-status-success-text'\n : 'bg-status-error-bg-subtle text-status-error-text'\n )}\n >\n {cart.isOpen\n ? t('kadaikodi.customerDashboard.open', 'Open')\n : t('kadaikodi.customerDashboard.closed', 'Closed')}\n </span>\n </div>\n </div>\n <div className=\"flex items-center gap-3 text-xs text-text-secondary mb-3\">\n {cart.totalRatings > 0 && (\n <span className=\"flex items-center gap-1\">\n <Star className=\"h-3 w-3 fill-status-warning-text text-status-warning-text\" />\n <span className=\"font-medium text-text-primary\">\n {(cart.rating ?? 0).toFixed(1)}\n </span>\n <span>({cart.totalRatings})</span>\n </span>\n )}\n {cart.location.address && (\n <span className=\"flex items-center gap-1 truncate\">\n <MapPin className=\"h-3 w-3 shrink-0\" />\n <span className=\"truncate\">{cart.location.address}</span>\n </span>\n )}\n </div>\n <button\n type=\"button\"\n disabled={!cart.isOpen}\n onClick={() => cart.isOpen && navigateTo(`/customer/carts/${cart.id}`)}\n className={cn(\n 'w-full rounded-lg py-2 text-sm 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 {cart.isOpen\n ? t('kadaikodi.customerDashboard.viewMenu', 'View Menu')\n : t('kadaikodi.customerDashboard.currentlyClosed', 'Currently Closed')}\n </button>\n </div>\n </div>\n ))}\n </div>\n ) : (\n <EmptyState\n illustration=\"empty-data\"\n title={t('kadaikodi.customerDashboard.noCarts', 'No carts available yet')}\n description={t(\n 'kadaikodi.customerDashboard.noCartsDesc',\n 'Carts will appear here as vendors join the platform. Check back soon.'\n )}\n />\n )}\n </section>\n </div>\n\n {/* Sidebar */}\n <div className=\"space-y-6\">\n {/* Quick Links */}\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-5\">\n <h3 className=\"text-base font-semibold text-text-primary mb-3\">\n {t('kadaikodi.customerDashboard.quickLinks', 'Quick Links')}\n </h3>\n <div className=\"space-y-2\">\n <button\n type=\"button\"\n onClick={() => navigateTo('/customer/profile')}\n className=\"flex w-full items-center gap-2 rounded-lg border border-border-subtle px-3 py-2.5 text-sm text-text-primary hover:bg-accent transition-colors text-left\"\n >\n <User className=\"h-4 w-4 text-text-secondary\" />\n {t('kadaikodi.customerDashboard.profileSettings', 'Profile Settings')}\n </button>\n <button\n type=\"button\"\n onClick={() => navigateTo('/customer/addresses')}\n className=\"flex w-full items-center gap-2 rounded-lg border border-border-subtle px-3 py-2.5 text-sm text-text-primary hover:bg-accent transition-colors text-left\"\n >\n <MapPin className=\"h-4 w-4 text-text-secondary\" />\n {t('kadaikodi.customerDashboard.savedAddresses', 'Saved Addresses')}\n </button>\n <button\n type=\"button\"\n onClick={() => navigateTo('/customer/payment-methods')}\n className=\"flex w-full items-center gap-2 rounded-lg border border-border-subtle px-3 py-2.5 text-sm text-text-primary hover:bg-accent transition-colors text-left\"\n >\n <CreditCard className=\"h-4 w-4 text-text-secondary\" />\n {t('kadaikodi.customerDashboard.paymentMethods', 'Payment Methods')}\n </button>\n </div>\n </div>\n </div>\n </div>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CustomerDashboard.js","names":[],"sources":["../../../../src/kadaikodi/pages/customer/CustomerDashboard.tsx"],"sourcesContent":["/**\n * Customer Dashboard Page\n * @module kadaikodi/pages/customer\n *\n * Welcome dashboard with time-of-day greeting, AI insights panel,\n * stats grid, recent orders with per-item display, recommended carts,\n * quick links sidebar, current location card, and special offers.\n */\n\nimport { useCallback } from 'react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n Heart,\n Star,\n CreditCard,\n ArrowRight,\n Search,\n Clock,\n MapPin,\n Package,\n User,\n} from 'lucide-react';\nimport { EmphasisPanel, PagePurpose, NextSteps } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { EmptyState } from '../../components/EmptyState';\nimport { useKadaikodi } from '../../context/KadaikodiContext';\nimport { useOrders, useProviders } from '../../hooks/useKadaikodiApi';\nimport { cn } from '../../utils/cn';\nimport { formatCurrency } from '../../utils/formatters';\n\ninterface CustomerStats {\n totalOrders: number;\n totalSpent: number;\n}\n\nfunction getTimeOfDayGreeting(): string {\n const hour = new Date().getHours();\n if (hour < 12) return 'Good morning';\n if (hour < 17) return 'Good afternoon';\n return 'Good evening';\n}\n\nexport function CustomerDashboard() {\n const { navigateTo, currentUser } = useKadaikodi();\n const { t: translate } = useI18n();\n\n const { data: orders = [], isLoading: isLoadingOrders } = useOrders({\n customerId: currentUser?.id,\n });\n const { data: providers = [], isLoading: isLoadingProviders } = useProviders();\n\n const isLoading = isLoadingOrders || isLoadingProviders;\n\n const t = useCallback(\n (key: string, fallback: string): string => {\n const value = translate(key);\n return value === key ? fallback : value;\n },\n [translate]\n );\n\n const firstName = currentUser?.firstName ?? currentUser?.name ?? 'Customer';\n\n const recentOrders = orders.slice(0, 3);\n const recommendedCarts = providers.slice(0, 3);\n\n const stats: CustomerStats = {\n totalOrders: orders.length,\n totalSpent: orders.reduce((acc, order) => acc + order.total, 0),\n };\n\n const getStatusColor = (status: string) => {\n switch (status) {\n case 'delivered':\n return 'bg-status-success-bg-subtle text-status-success-text';\n case 'preparing':\n return 'bg-status-warning-bg-subtle text-status-warning-text';\n case 'out_for_delivery':\n return 'bg-[var(--color-accent-soft)] text-text-primary';\n case 'confirmed':\n return 'bg-[var(--color-accent-soft)] text-text-primary';\n case 'cancelled':\n return 'bg-status-error-bg-subtle text-status-error-text';\n default:\n return 'bg-bg-sunken text-text-secondary';\n }\n };\n\n if (isLoading) {\n return (\n <PageLayout title={t('kadaikodi.customerDashboard.title', 'Dashboard')}>\n <div className=\"flex items-center justify-center py-20\">\n <div className=\"text-center\">\n <div className=\"mx-auto mb-4 h-12 w-12 animate-spin rounded-full border-b-2 border-foreground\" />\n <p className=\"text-sm text-text-secondary\">\n {t('kadaikodi.customerDashboard.loading', 'Loading your dashboard...')}\n </p>\n </div>\n </div>\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title={t('kadaikodi.customerDashboard.welcomeBack', 'Welcome Back!')}\n description={`${getTimeOfDayGreeting()}, ${firstName}`}\n >\n <PagePurpose className=\"mb-6\">\n Your home base on Kadaikodi — discover mobile food carts near you, reorder favourites in a\n tap, and keep an eye on your orders and spending. Start by exploring nearby carts or\n revisiting a recent order below.\n </PagePurpose>\n\n <NextSteps\n storageKey=\"kadaikodi-customer-dashboard\"\n className=\"mb-6\"\n steps={[\n {\n id: 'discover',\n label: 'Discover carts near you',\n description: 'Browse open mobile carts in your area and view their menus.',\n onClick: () => navigateTo('/customer/discover'),\n },\n {\n id: 'address',\n label: 'Set your delivery address',\n description: 'Save your home or work address for faster checkout.',\n onClick: () => navigateTo('/customer/addresses'),\n },\n {\n id: 'payment',\n label: 'Add a payment method',\n description: 'Securely store a card or UPI so ordering is one tap.',\n onClick: () => navigateTo('/customer/payment-methods'),\n },\n ]}\n />\n\n {/* Stats Overview — the one emphasis zone for this dashboard */}\n {stats && (\n <EmphasisPanel className=\"mb-8\">\n <h2 className=\"mb-4 text-lg font-semibold text-text-primary\">\n {t('kadaikodi.customerDashboard.yourActivity', 'Your Activity')}\n </h2>\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-4\">\n <div className=\"flex items-center gap-3\">\n <div className=\"flex h-10 w-10 items-center justify-center rounded-lg bg-bg-sunken\">\n <Package className=\"h-5 w-5 text-text-secondary\" />\n </div>\n <div>\n <p className=\"text-2xl font-bold text-text-primary\">{stats.totalOrders}</p>\n <p className=\"text-xs text-text-secondary\">\n {t('kadaikodi.customerDashboard.totalOrders', 'Total Orders')}\n </p>\n </div>\n </div>\n </div>\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-4\">\n <div className=\"flex items-center gap-3\">\n <div className=\"flex h-10 w-10 items-center justify-center rounded-lg bg-bg-sunken\">\n <CreditCard className=\"h-5 w-5 text-text-secondary\" />\n </div>\n <div>\n <p className=\"text-2xl font-bold text-text-primary\">\n {formatCurrency(stats.totalSpent, { minimumFractionDigits: 0 })}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {t('kadaikodi.customerDashboard.totalSpent', 'Total Spent')}\n </p>\n </div>\n </div>\n </div>\n </div>\n </EmphasisPanel>\n )}\n\n <div className=\"mt-8 grid grid-cols-1 gap-8 lg:grid-cols-3\">\n {/* Main Content */}\n <div className=\"lg:col-span-2 space-y-8\">\n {/* Quick Actions */}\n <section>\n <h2 className=\"text-lg font-semibold text-text-primary mb-4\">\n {t('kadaikodi.customerDashboard.quickActions', 'Quick Actions')}\n </h2>\n <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-3\">\n <button\n type=\"button\"\n onClick={() => navigateTo('/customer/discover')}\n className={cn(\n 'flex items-center gap-3 rounded-lg border border-border-subtle bg-bg-surface p-4 shadow-sm transition-colors text-left',\n 'hover:bg-accent hover:shadow-md'\n )}\n >\n <div className=\"flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-[var(--color-accent-soft)]\">\n <Search className=\"h-5 w-5 text-text-primary\" />\n </div>\n <div className=\"min-w-0\">\n <p className=\"text-sm font-semibold text-text-primary\">\n {t('kadaikodi.customerDashboard.discoverCarts', 'Discover Carts')}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {t('kadaikodi.customerDashboard.findNearbyCarts', 'Find nearby carts')}\n </p>\n </div>\n </button>\n\n <button\n type=\"button\"\n onClick={() => navigateTo('/customer/orders')}\n className={cn(\n 'flex items-center gap-3 rounded-lg border border-border-subtle bg-bg-surface p-4 shadow-sm transition-colors text-left',\n 'hover:bg-accent hover:shadow-md'\n )}\n >\n <div className=\"flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-status-success-bg-subtle\">\n <Clock className=\"h-5 w-5 text-status-success-text\" />\n </div>\n <div className=\"min-w-0\">\n <p className=\"text-sm font-semibold text-text-primary\">\n {t('kadaikodi.customerDashboard.orderHistory', 'Order History')}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {t('kadaikodi.customerDashboard.viewPastOrders', 'View past orders')}\n </p>\n </div>\n </button>\n\n <button\n type=\"button\"\n onClick={() => navigateTo('/customer/favorites')}\n className={cn(\n 'flex items-center gap-3 rounded-lg border border-border-subtle bg-bg-surface p-4 shadow-sm transition-colors text-left',\n 'hover:bg-accent hover:shadow-md'\n )}\n >\n <div className=\"flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-status-error-bg-subtle\">\n <Heart className=\"h-5 w-5 text-status-error-text\" />\n </div>\n <div className=\"min-w-0\">\n <p className=\"text-sm font-semibold text-text-primary\">\n {t('kadaikodi.customerDashboard.favorites', 'Favorites')}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {t('kadaikodi.customerDashboard.savedCarts', 'Saved carts')}\n </p>\n </div>\n </button>\n </div>\n </section>\n\n {/* Recent Orders */}\n <section>\n <div className=\"flex items-center justify-between mb-4\">\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {t('kadaikodi.customerDashboard.recentOrders', 'Recent Orders')}\n </h2>\n <button\n type=\"button\"\n onClick={() => navigateTo('/customer/orders')}\n className=\"flex items-center gap-1 text-sm font-medium text-text-secondary hover:text-text-primary transition-colors\"\n >\n {t('kadaikodi.common.viewAll', 'View All')}\n <ArrowRight className=\"h-4 w-4\" />\n </button>\n </div>\n\n {recentOrders.length > 0 ? (\n <div className=\"space-y-3\">\n {recentOrders.map((order) => (\n <div\n key={order.id}\n className=\"rounded-lg border border-border-subtle bg-bg-surface p-4\"\n >\n <div className=\"flex flex-col sm:flex-row sm:items-start sm:justify-between gap-3\">\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex flex-wrap items-center gap-2 mb-1\">\n <h3 className=\"text-sm font-semibold text-text-primary\">\n {order.cartName}\n </h3>\n <span\n className={cn(\n 'inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium capitalize',\n getStatusColor(order.status)\n )}\n >\n {order.status.replace(/_/g, ' ')}\n </span>\n </div>\n <p className=\"text-xs text-text-secondary mb-2 leading-relaxed\">\n {order.items.map((item) => `${item.name} (${item.quantity})`).join(', ')}\n </p>\n <div className=\"flex flex-wrap items-center gap-3 text-xs text-text-secondary\">\n <span className=\"font-medium text-text-primary\">\n {formatCurrency(order.total, { minimumFractionDigits: 0 })}\n </span>\n <span>{new Date(order.orderDate).toLocaleDateString()}</span>\n {order.rating && (\n <span className=\"flex items-center gap-1\">\n <Star className=\"h-3 w-3 fill-status-warning-text text-status-warning-text\" />\n {order.rating}\n </span>\n )}\n </div>\n </div>\n <button\n type=\"button\"\n onClick={() => navigateTo(`/customer/orders/${order.id}/track`)}\n className=\"rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium text-text-primary hover:bg-accent transition-colors\"\n >\n {t('kadaikodi.customerDashboard.viewDetails', 'View Details')}\n </button>\n </div>\n </div>\n ))}\n </div>\n ) : (\n <EmptyState\n illustration=\"empty-data\"\n title={t('kadaikodi.customerDashboard.noRecentOrders', 'No recent orders')}\n description={t(\n 'kadaikodi.customerDashboard.noRecentOrdersDesc',\n 'Your orders will show up here once you place one. Discover a cart to get started.'\n )}\n action={\n <button\n type=\"button\"\n onClick={() => navigateTo('/customer/discover')}\n className=\"rounded-lg bg-foreground px-4 py-2 text-sm font-medium text-background hover:opacity-90 transition-opacity\"\n >\n {t('kadaikodi.customerDashboard.discoverCarts', 'Discover Carts')}\n </button>\n }\n />\n )}\n </section>\n\n {/* Recommended Carts */}\n <section>\n <h2 className=\"text-lg font-semibold text-text-primary mb-4\">\n {t('kadaikodi.customerDashboard.recommendedForYou', 'Recommended for You')}\n </h2>\n {recommendedCarts.length > 0 ? (\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n {recommendedCarts.map((cart) => (\n <div\n key={cart.id}\n className=\"rounded-lg border border-border-subtle bg-bg-surface overflow-hidden shadow-sm hover:shadow-md transition-shadow\"\n >\n <div className=\"p-4\">\n <div className=\"flex items-start justify-between mb-2\">\n <div className=\"min-w-0 flex-1\">\n <h3 className=\"text-sm font-semibold text-text-primary\">{cart.name}</h3>\n <p className=\"text-xs text-text-secondary\">{cart.category}</p>\n </div>\n <div className=\"flex items-center gap-2\">\n <span\n className={cn(\n 'inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium',\n cart.isOpen\n ? 'bg-status-success-bg-subtle text-status-success-text'\n : 'bg-status-error-bg-subtle text-status-error-text'\n )}\n >\n {cart.isOpen\n ? t('kadaikodi.customerDashboard.open', 'Open')\n : t('kadaikodi.customerDashboard.closed', 'Closed')}\n </span>\n </div>\n </div>\n <div className=\"flex items-center gap-3 text-xs text-text-secondary mb-3\">\n {cart.totalRatings > 0 && (\n <span className=\"flex items-center gap-1\">\n <Star className=\"h-3 w-3 fill-status-warning-text text-status-warning-text\" />\n <span className=\"font-medium text-text-primary\">\n {(cart.rating ?? 0).toFixed(1)}\n </span>\n <span>({cart.totalRatings})</span>\n </span>\n )}\n {cart.location.address && (\n <span className=\"flex items-center gap-1 truncate\">\n <MapPin className=\"h-3 w-3 shrink-0\" />\n <span className=\"truncate\">{cart.location.address}</span>\n </span>\n )}\n </div>\n <button\n type=\"button\"\n disabled={!cart.isOpen}\n onClick={() => cart.isOpen && navigateTo(`/customer/cart/${cart.id}`)}\n className={cn(\n 'w-full rounded-lg py-2 text-sm 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 {cart.isOpen\n ? t('kadaikodi.customerDashboard.viewMenu', 'View Menu')\n : t('kadaikodi.customerDashboard.currentlyClosed', 'Currently Closed')}\n </button>\n </div>\n </div>\n ))}\n </div>\n ) : (\n <EmptyState\n illustration=\"empty-data\"\n title={t('kadaikodi.customerDashboard.noCarts', 'No carts available yet')}\n description={t(\n 'kadaikodi.customerDashboard.noCartsDesc',\n 'Carts will appear here as vendors join the platform. Check back soon.'\n )}\n />\n )}\n </section>\n </div>\n\n {/* Sidebar */}\n <div className=\"space-y-6\">\n {/* Quick Links */}\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-5\">\n <h3 className=\"text-base font-semibold text-text-primary mb-3\">\n {t('kadaikodi.customerDashboard.quickLinks', 'Quick Links')}\n </h3>\n <div className=\"space-y-2\">\n <button\n type=\"button\"\n onClick={() => navigateTo('/customer/profile')}\n className=\"flex w-full items-center gap-2 rounded-lg border border-border-subtle px-3 py-2.5 text-sm text-text-primary hover:bg-accent transition-colors text-left\"\n >\n <User className=\"h-4 w-4 text-text-secondary\" />\n {t('kadaikodi.customerDashboard.profileSettings', 'Profile Settings')}\n </button>\n <button\n type=\"button\"\n onClick={() => navigateTo('/customer/addresses')}\n className=\"flex w-full items-center gap-2 rounded-lg border border-border-subtle px-3 py-2.5 text-sm text-text-primary hover:bg-accent transition-colors text-left\"\n >\n <MapPin className=\"h-4 w-4 text-text-secondary\" />\n {t('kadaikodi.customerDashboard.savedAddresses', 'Saved Addresses')}\n </button>\n <button\n type=\"button\"\n onClick={() => navigateTo('/customer/payment-methods')}\n className=\"flex w-full items-center gap-2 rounded-lg border border-border-subtle px-3 py-2.5 text-sm text-text-primary hover:bg-accent transition-colors text-left\"\n >\n <CreditCard className=\"h-4 w-4 text-text-secondary\" />\n {t('kadaikodi.customerDashboard.paymentMethods', 'Payment Methods')}\n </button>\n </div>\n </div>\n </div>\n </div>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|