@burdenoff/microfe-kadaikodi 2026.626.2 → 2026.704.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/kadaikodi/hooks/useKadaikodiApi.js +209 -105
- package/dist/kadaikodi/hooks/useKadaikodiApi.js.map +1 -1
- package/dist/kadaikodi/pages/HomePage.js +4 -4
- package/dist/kadaikodi/pages/HomePage.js.map +1 -1
- package/dist/kadaikodi/pages/admin/AdminDashboard.js +1 -1
- package/dist/kadaikodi/pages/admin/AdminDashboard.js.map +1 -1
- package/dist/kadaikodi/pages/admin/AdminOrdersPage.js +1 -1
- package/dist/kadaikodi/pages/admin/AdminOrdersPage.js.map +1 -1
- package/dist/kadaikodi/pages/admin/CartManagementPage.js +279 -333
- package/dist/kadaikodi/pages/admin/CartManagementPage.js.map +1 -1
- package/dist/kadaikodi/pages/admin/UserManagementPage.js +299 -372
- package/dist/kadaikodi/pages/admin/UserManagementPage.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/AnalyticsDashboard.js +214 -214
- package/dist/kadaikodi/pages/cart-owner/AnalyticsDashboard.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/CartOwnerDashboard.js +226 -230
- package/dist/kadaikodi/pages/cart-owner/CartOwnerDashboard.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/CartOwnerProfilePage.js +255 -256
- package/dist/kadaikodi/pages/cart-owner/CartOwnerProfilePage.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/InventoryManagementPage.js +275 -278
- package/dist/kadaikodi/pages/cart-owner/InventoryManagementPage.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/OrderManagementPage.js +228 -446
- package/dist/kadaikodi/pages/cart-owner/OrderManagementPage.js.map +1 -1
- package/dist/kadaikodi/pages/common/NotificationCenterPage.js +1 -1
- package/dist/kadaikodi/pages/common/NotificationCenterPage.js.map +1 -1
- package/dist/kadaikodi/pages/common/SettingsPage.js +34 -46
- package/dist/kadaikodi/pages/common/SettingsPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/BookingDetailsPage.js +193 -447
- package/dist/kadaikodi/pages/customer/BookingDetailsPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/CartDetailPage.js +6 -6
- package/dist/kadaikodi/pages/customer/CartDetailPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/CartDiscoveryPage.js +2 -2
- package/dist/kadaikodi/pages/customer/CartDiscoveryPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/DirectServiceBookingPage.js +255 -215
- package/dist/kadaikodi/pages/customer/DirectServiceBookingPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/FavoritesPage.js +141 -178
- package/dist/kadaikodi/pages/customer/FavoritesPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/OrderTrackingPage.js +155 -161
- package/dist/kadaikodi/pages/customer/OrderTrackingPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/ReviewsPage.js +14 -140
- package/dist/kadaikodi/pages/customer/ReviewsPage.js.map +1 -1
- package/dist/kadaikodi/pages/investor/InvestmentOpportunitiesPage.js +304 -458
- package/dist/kadaikodi/pages/investor/InvestmentOpportunitiesPage.js.map +1 -1
- package/dist/kadaikodi/pages/investor/InvestorDashboard.js +1 -1
- package/dist/kadaikodi/pages/investor/InvestorDashboard.js.map +1 -1
- package/dist/kadaikodi/pages/investor/InvestorInvestmentsPage.js +2 -2
- package/dist/kadaikodi/pages/investor/InvestorInvestmentsPage.js.map +1 -1
- package/dist/kadaikodi/pages/investor/InvestorProfilePage.js +361 -361
- package/dist/kadaikodi/pages/investor/InvestorProfilePage.js.map +1 -1
- package/dist/kadaikodi/pages/worker/TaskDetailsPage.js +226 -220
- package/dist/kadaikodi/pages/worker/TaskDetailsPage.js.map +1 -1
- package/dist/kadaikodi/pages/worker/WorkerDashboard.js +15 -15
- package/dist/kadaikodi/pages/worker/WorkerDashboard.js.map +1 -1
- package/dist/kadaikodi/pages/worker/WorkerOrdersPage.js +2 -2
- package/dist/kadaikodi/pages/worker/WorkerOrdersPage.js.map +1 -1
- package/dist/kadaikodi/pages/worker/WorkerProfilePage.js +252 -253
- package/dist/kadaikodi/pages/worker/WorkerProfilePage.js.map +1 -1
- package/dist/kadaikodi/pages/worker/WorkerSchedulePage.js +3 -3
- package/dist/kadaikodi/pages/worker/WorkerSchedulePage.js.map +1 -1
- package/package.json +1 -1
- package/dist/kadaikodi/mocks/data.js +0 -1517
- package/dist/kadaikodi/mocks/data.js.map +0 -1
- package/dist/kadaikodi/mocks/users.js +0 -34
- package/dist/kadaikodi/mocks/users.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OrderManagementPage.js","names":[],"sources":["../../../../src/kadaikodi/pages/cart-owner/OrderManagementPage.tsx"],"sourcesContent":["/**\n * Order Management Page\n *\n * Stats overview, status-filtered order list with search/date/sort/fulfillment filters,\n * order detail modal, accept/reject/ready/complete actions, priority highlighting.\n *\n * @module kadaikodi/pages/cart-owner\n */\n\nimport { useState, useMemo } from 'react';\nimport {\n Search,\n Clock,\n CheckCircle2,\n XCircle,\n ChefHat,\n PackageCheck,\n Phone,\n MapPin,\n User,\n RefreshCw,\n Truck,\n ShoppingBag,\n X,\n AlertCircle,\n Filter,\n ChevronDown,\n} from 'lucide-react';\nimport { EmphasisPanel, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { EmptyState } from '../../components/EmptyState';\nimport { useKadaikodi } from '../../context/KadaikodiContext';\nimport { mockOrders } from '../../mocks/data';\nimport { formatCurrency } from '../../utils/formatters';\nimport { cn } from '../../utils/cn';\nimport type { MockOrder, OrderStatus } from '../../types';\n\n// ============================================================================\n// Types\n// ============================================================================\n\ninterface StatusMessage {\n text: string;\n type: 'success' | 'error';\n}\n\ninterface OrderFilters {\n status: string;\n dateRange: string;\n searchQuery: string;\n sortBy: string;\n fulfillmentType: string;\n}\n\n/** Extended order type with cart-owner specific fields */\ninterface ExtendedOrder extends MockOrder {\n customerName?: string;\n customerPhone?: string;\n fulfillmentType?: 'delivery' | 'pickup' | 'cart_dispatch';\n specialInstructions?: string;\n}\n\n// ============================================================================\n// Extended Mock Orders\n// ============================================================================\n\nconst extendedOrders: ExtendedOrder[] = [\n ...mockOrders,\n {\n id: 'ORD-010',\n cartId: 'FOOD-001',\n cartName: 'Dosa Express',\n cartImage: '',\n items: [\n { id: 'food-1', name: 'Masala Dosa', quantity: 3, price: 120 },\n { id: 'food-2', name: 'Filter Coffee', quantity: 3, price: 60 },\n ],\n subtotal: 540,\n taxes: 54,\n deliveryFee: 30,\n total: 624,\n status: 'pending' as OrderStatus,\n orderDate: '2024-01-16T17:30:00Z',\n estimatedDeliveryTime: '2024-01-16T18:00:00Z',\n deliveryAddress: {\n street: '42 Lake Road',\n area: 'Ulsoor',\n city: 'Bangalore',\n pincode: '560008',\n },\n paymentMethod: 'UPI',\n paymentStatus: 'completed' as const,\n timeline: [\n { status: 'pending', timestamp: '2024-01-16T17:30:00Z', description: 'Order placed' },\n ],\n assignedWorker: { id: 'worker-1', name: 'Ravi Kumar', phone: '+91-9876543210', rating: 4.8 },\n customerName: 'Priya Sharma',\n customerPhone: '+91-9876543220',\n fulfillmentType: 'delivery' as const,\n specialInstructions: 'Extra sambar please',\n },\n {\n id: 'ORD-011',\n cartId: 'FOOD-002',\n cartName: 'Chaat Corner',\n cartImage: '',\n items: [\n { id: 'food-3', name: 'Pani Puri', quantity: 2, price: 80 },\n { id: 'food-4', name: 'Bhel Puri', quantity: 1, price: 70 },\n ],\n subtotal: 230,\n taxes: 23,\n deliveryFee: 0,\n total: 253,\n status: 'confirmed' as OrderStatus,\n orderDate: '2024-01-16T16:00:00Z',\n deliveryAddress: {\n street: '88 MG Road',\n area: 'MG Road',\n city: 'Bangalore',\n pincode: '560001',\n },\n paymentMethod: 'Cash',\n paymentStatus: 'pending' as const,\n timeline: [\n { status: 'pending', timestamp: '2024-01-16T15:50:00Z', description: 'Order placed' },\n { status: 'confirmed', timestamp: '2024-01-16T16:00:00Z', description: 'Order confirmed' },\n ],\n customerName: 'Amit Patel',\n customerPhone: '+91-9876543221',\n fulfillmentType: 'pickup' as const,\n },\n {\n id: 'ORD-012',\n cartId: 'FOOD-001',\n cartName: 'Dosa Express',\n cartImage: '',\n items: [{ id: 'food-5', name: 'Rava Dosa', quantity: 2, price: 100 }],\n subtotal: 200,\n taxes: 20,\n deliveryFee: 30,\n total: 250,\n status: 'preparing' as OrderStatus,\n orderDate: '2024-01-16T15:00:00Z',\n deliveryAddress: {\n street: '15 Church Street',\n area: 'Church Street',\n city: 'Bangalore',\n pincode: '560001',\n },\n paymentMethod: 'UPI',\n paymentStatus: 'completed' as const,\n timeline: [\n { status: 'pending', timestamp: '2024-01-16T14:50:00Z', description: 'Order placed' },\n { status: 'confirmed', timestamp: '2024-01-16T14:55:00Z', description: 'Order confirmed' },\n {\n status: 'preparing',\n timestamp: '2024-01-16T15:00:00Z',\n description: 'Preparation started',\n },\n ],\n customerName: 'Deepak Reddy',\n customerPhone: '+91-9876543222',\n fulfillmentType: 'delivery' as const,\n specialInstructions: 'No onions',\n },\n {\n id: 'ORD-013',\n cartId: 'SVC-001',\n cartName: 'Quick Fix Repairs',\n cartImage: '',\n items: [{ id: 'svc-1', name: 'Mobile Screen Repair', quantity: 1, price: 2500 }],\n subtotal: 2500,\n taxes: 250,\n deliveryFee: 0,\n total: 2750,\n status: 'ready' as OrderStatus,\n orderDate: '2024-01-16T12:00:00Z',\n deliveryAddress: {\n street: '22 HSR Layout',\n area: 'HSR Layout',\n city: 'Bangalore',\n pincode: '560102',\n },\n paymentMethod: 'Card',\n paymentStatus: 'completed' as const,\n timeline: [\n { status: 'pending', timestamp: '2024-01-16T11:00:00Z', description: 'Order placed' },\n { status: 'confirmed', timestamp: '2024-01-16T11:10:00Z', description: 'Order confirmed' },\n { status: 'preparing', timestamp: '2024-01-16T11:30:00Z', description: 'Service started' },\n { status: 'ready', timestamp: '2024-01-16T12:00:00Z', description: 'Service completed' },\n ],\n customerName: 'Kiran Nair',\n customerPhone: '+91-9876543223',\n fulfillmentType: 'pickup' as const,\n },\n {\n id: 'ORD-014',\n cartId: 'FOOD-001',\n cartName: 'Dosa Express',\n cartImage: '',\n items: [\n { id: 'food-1', name: 'Masala Dosa', quantity: 1, price: 120 },\n { id: 'food-2', name: 'Filter Coffee', quantity: 2, price: 60 },\n ],\n subtotal: 240,\n taxes: 24,\n deliveryFee: 30,\n total: 294,\n status: 'cancelled' as OrderStatus,\n orderDate: '2024-01-15T18:00:00Z',\n deliveryAddress: {\n street: '5 BTM Layout',\n area: 'BTM Layout',\n city: 'Bangalore',\n pincode: '560076',\n },\n paymentMethod: 'UPI',\n paymentStatus: 'refunded' as const,\n timeline: [\n { status: 'pending', timestamp: '2024-01-15T17:50:00Z', description: 'Order placed' },\n {\n status: 'cancelled',\n timestamp: '2024-01-15T18:00:00Z',\n description: 'Order cancelled by customer',\n },\n ],\n customerName: 'Sneha Gupta',\n customerPhone: '+91-9876543224',\n fulfillmentType: 'delivery' as const,\n },\n];\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nconst statusConfig: Record<string, { color: string; label: string }> = {\n pending: { color: 'bg-status-warning-bg-subtle text-status-warning-text', label: 'New Order' },\n confirmed: { color: 'bg-[var(--color-accent-soft)] text-text-primary', label: 'Confirmed' },\n preparing: { color: 'bg-status-warning-bg-subtle text-status-warning-text', label: 'Preparing' },\n ready: { color: 'bg-status-success-bg-subtle text-status-success-text', label: 'Ready' },\n out_for_delivery: {\n color: 'bg-[var(--color-accent-soft)] text-text-primary',\n label: 'Out for Delivery',\n },\n delivered: { color: 'bg-status-success-bg-subtle text-status-success-text', label: 'Completed' },\n cancelled: { color: 'bg-status-error-bg-subtle text-status-error-text', label: 'Cancelled' },\n};\n\nconst fulfillmentBadge: Record<string, { icon: typeof Truck; label: string; color: string }> = {\n delivery: {\n icon: Truck,\n label: 'Delivery',\n color: 'bg-accent-purple-subtle text-text-primary',\n },\n pickup: {\n icon: ShoppingBag,\n label: 'Pickup',\n color: 'bg-[var(--color-accent-soft)] text-text-primary',\n },\n cart_dispatch: {\n icon: MapPin,\n label: 'Cart Dispatch',\n color: 'bg-bg-sunken text-text-secondary',\n },\n};\n\nconst formatTimeAgo = (dateString: string) => {\n const date = new Date(dateString);\n const now = new Date();\n const diffMin = Math.floor((now.getTime() - date.getTime()) / (1000 * 60));\n if (diffMin < 1) return 'Just now';\n if (diffMin < 60) return `${diffMin} min ago`;\n if (diffMin < 1440) return `${Math.floor(diffMin / 60)} hours ago`;\n return date.toLocaleDateString('en-IN', { day: '2-digit', month: 'short' });\n};\n\nconst formatTime = (dateString: string) => {\n return new Date(dateString).toLocaleTimeString('en-IN', {\n hour: 'numeric',\n minute: '2-digit',\n hour12: true,\n });\n};\n\nconst getPriorityColor = (order: (typeof extendedOrders)[0]) => {\n const ageMin = (new Date().getTime() - new Date(order.orderDate).getTime()) / (1000 * 60);\n if (order.status === 'pending' && ageMin > 10)\n return 'border-status-error-text/50 bg-status-error-bg-subtle';\n if (order.status === 'preparing' && ageMin > 30)\n return 'border-status-warning-text/50 bg-status-warning-bg-subtle';\n return 'border-border-subtle';\n};\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const OrderManagementPage = () => {\n const { navigateTo } = useKadaikodi();\n\n // Data - use inline state so actions can update it\n const [orders, setOrders] = useState(extendedOrders);\n\n // Filters\n const [filters, setFilters] = useState<OrderFilters>({\n status: '',\n dateRange: 'all',\n searchQuery: '',\n sortBy: 'recent',\n fulfillmentType: '',\n });\n\n // Modal\n const [selectedOrder, setSelectedOrder] = useState<(typeof extendedOrders)[0] | null>(null);\n const [showOrderDetails, setShowOrderDetails] = useState(false);\n\n // Status\n const [statusMessage, setStatusMessage] = useState<StatusMessage | null>(null);\n\n const showStatus = (text: string, type: 'success' | 'error') => {\n setStatusMessage({ text, type });\n setTimeout(() => setStatusMessage(null), 3000);\n };\n\n // ---- Stats ----\n const stats = useMemo(() => {\n const total = orders.length;\n const pending = orders.filter((o) => o.status === 'pending').length;\n const active = orders.filter((o) =>\n ['confirmed', 'preparing', 'ready', 'out_for_delivery'].includes(o.status)\n ).length;\n const completed = orders.filter((o) => o.status === 'delivered').length;\n const totalRevenue = orders\n .filter((o) => o.status === 'delivered')\n .reduce((s, o) => s + o.total, 0);\n const avgOrder = completed > 0 ? Math.round(totalRevenue / completed) : 0;\n return { total, pending, active, completed, totalRevenue, avgOrder };\n }, [orders]);\n\n // ---- Filtered orders ----\n const filteredOrders = useMemo(() => {\n let result = [...orders];\n\n if (filters.status) {\n result = result.filter((o) => o.status === filters.status);\n }\n if (filters.fulfillmentType) {\n result = result.filter((o) => o.fulfillmentType === filters.fulfillmentType);\n }\n if (filters.searchQuery) {\n const q = filters.searchQuery.toLowerCase();\n result = result.filter(\n (o) =>\n o.id.toLowerCase().includes(q) ||\n (o.customerName || '').toLowerCase().includes(q) ||\n o.items.some((item) => item.name.toLowerCase().includes(q))\n );\n }\n if (filters.dateRange !== 'all') {\n const now = new Date();\n const limit = new Date();\n if (filters.dateRange === 'today') limit.setHours(0, 0, 0, 0);\n else if (filters.dateRange === '7days') limit.setDate(now.getDate() - 7);\n else if (filters.dateRange === '30days') limit.setDate(now.getDate() - 30);\n result = result.filter((o) => new Date(o.orderDate) >= limit);\n }\n\n switch (filters.sortBy) {\n case 'recent':\n result.sort((a, b) => new Date(b.orderDate).getTime() - new Date(a.orderDate).getTime());\n break;\n case 'oldest':\n result.sort((a, b) => new Date(a.orderDate).getTime() - new Date(b.orderDate).getTime());\n break;\n case 'amount_high':\n result.sort((a, b) => b.total - a.total);\n break;\n case 'amount_low':\n result.sort((a, b) => a.total - b.total);\n break;\n }\n\n return result;\n }, [orders, filters]);\n\n // ---- Actions ----\n const handleOrderAction = (\n orderId: string,\n action: 'accept' | 'reject' | 'ready' | 'complete'\n ) => {\n const statusMap: Record<string, OrderStatus> = {\n accept: 'confirmed',\n reject: 'cancelled',\n ready: 'ready',\n complete: 'delivered',\n };\n const messages: Record<string, string> = {\n accept: 'Order accepted',\n reject: 'Order rejected',\n ready: 'Order marked as ready',\n complete: 'Order completed',\n };\n\n setOrders((prev) =>\n prev.map((o) => (o.id === orderId ? { ...o, status: statusMap[action] } : o))\n );\n showStatus(messages[action], 'success');\n if (showOrderDetails && selectedOrder?.id === orderId) {\n setShowOrderDetails(false);\n }\n };\n\n return (\n <PageLayout\n title=\"Order Management\"\n description=\"Manage incoming and active orders\"\n actions={\n <button\n type=\"button\"\n onClick={() => showStatus('Orders refreshed', 'success')}\n className=\"inline-flex items-center gap-2 rounded-md border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n <RefreshCw className=\"h-4 w-4\" />\n Refresh\n </button>\n }\n >\n <PagePurpose className=\"mb-6\">\n Your live order queue. Use this page to run service as it happens — accept new orders, move\n them through preparing and ready, hand off for pickup, delivery or cart dispatch, and keep\n customers updated. Filter by status or type to focus on what needs doing right now, and watch\n today's totals so you know how the day is going.\n </PagePurpose>\n\n <div className=\"space-y-4\">\n {/* Status Message */}\n {statusMessage && (\n <div\n className={cn(\n 'flex items-center gap-2 rounded-lg border p-3',\n statusMessage.type === 'success'\n ? 'border-status-success-text/30 bg-status-success-bg-subtle'\n : 'border-status-error-text/30 bg-status-error-bg-subtle'\n )}\n >\n {statusMessage.type === 'success' ? (\n <CheckCircle2 className=\"h-4 w-4 text-status-success-text\" />\n ) : (\n <AlertCircle className=\"h-4 w-4 text-status-error-text\" />\n )}\n <span\n className={cn(\n 'text-sm font-medium',\n statusMessage.type === 'success'\n ? 'text-status-success-text'\n : 'text-status-error-text'\n )}\n >\n {statusMessage.text}\n </span>\n </div>\n )}\n\n {/* Stats Overview — the one emphasis zone for this page */}\n <EmphasisPanel>\n <h2 className=\"mb-4 text-base font-semibold text-text-primary\">Today's Orders</h2>\n <div className=\"grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-6 gap-3\">\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-4 shadow-sm\">\n <p className=\"text-xs text-text-secondary\">Total Orders</p>\n <p className=\"text-2xl font-bold text-text-primary\">{stats.total}</p>\n </div>\n <div className=\"rounded-lg border border-status-warning-text/30 bg-status-warning-bg-subtle p-4 shadow-sm\">\n <p className=\"text-xs text-status-warning-text\">Pending</p>\n <p className=\"text-2xl font-bold text-status-warning-text\">{stats.pending}</p>\n </div>\n <div className=\"rounded-lg border border-border-focus/30 bg-[var(--color-accent-soft)] p-4 shadow-sm\">\n <p className=\"text-xs text-text-primary\">Active</p>\n <p className=\"text-2xl font-bold text-text-primary\">{stats.active}</p>\n </div>\n <div className=\"rounded-lg border border-status-success-text/30 bg-status-success-bg-subtle p-4 shadow-sm\">\n <p className=\"text-xs text-status-success-text\">Completed</p>\n <p className=\"text-2xl font-bold text-status-success-text\">{stats.completed}</p>\n </div>\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-4 shadow-sm\">\n <p className=\"text-xs text-text-secondary\">Total Revenue</p>\n <p className=\"text-2xl font-bold text-text-primary\">\n {formatCurrency(stats.totalRevenue, { minimumFractionDigits: 0 })}\n </p>\n </div>\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-4 shadow-sm\">\n <p className=\"text-xs text-text-secondary\">Avg Order</p>\n <p className=\"text-2xl font-bold text-text-primary\">\n {formatCurrency(stats.avgOrder, { minimumFractionDigits: 0 })}\n </p>\n </div>\n </div>\n </EmphasisPanel>\n\n {/* Filters */}\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-4 shadow-sm\">\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-5 gap-3\">\n <div className=\"relative sm:col-span-2 lg:col-span-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 orders...\"\n value={filters.searchQuery}\n onChange={(e) => setFilters((p) => ({ ...p, searchQuery: e.target.value }))}\n className=\"w-full rounded-md border border-border-subtle bg-bg-surface pl-10 pr-4 py-2 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={filters.status}\n onChange={(e) => setFilters((p) => ({ ...p, status: e.target.value }))}\n className=\"rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n >\n <option value=\"\">All Orders</option>\n <option value=\"pending\">New Orders</option>\n <option value=\"confirmed\">Confirmed</option>\n <option value=\"preparing\">Preparing</option>\n <option value=\"ready\">Ready</option>\n <option value=\"delivered\">Completed</option>\n <option value=\"cancelled\">Cancelled</option>\n </select>\n <select\n value={filters.fulfillmentType}\n onChange={(e) => setFilters((p) => ({ ...p, fulfillmentType: e.target.value }))}\n className=\"rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n >\n <option value=\"\">All Types</option>\n <option value=\"pickup\">Pickup</option>\n <option value=\"delivery\">Delivery</option>\n <option value=\"cart_dispatch\">Cart Dispatch</option>\n </select>\n <select\n value={filters.dateRange}\n onChange={(e) => setFilters((p) => ({ ...p, dateRange: e.target.value }))}\n className=\"rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n >\n <option value=\"today\">Today</option>\n <option value=\"7days\">Last 7 Days</option>\n <option value=\"30days\">Last 30 Days</option>\n <option value=\"all\">All Time</option>\n </select>\n <select\n value={filters.sortBy}\n onChange={(e) => setFilters((p) => ({ ...p, sortBy: e.target.value }))}\n className=\"rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n >\n <option value=\"recent\">Most Recent</option>\n <option value=\"oldest\">Oldest First</option>\n <option value=\"amount_high\">Amount: High to Low</option>\n <option value=\"amount_low\">Amount: Low to High</option>\n </select>\n </div>\n </div>\n\n {/* Orders List */}\n {filteredOrders.length === 0 ? (\n <EmptyState\n illustration={filters.searchQuery || filters.status ? 'empty-search' : 'empty-data'}\n title=\"No orders found\"\n description={\n filters.searchQuery || filters.status\n ? 'No orders match your current filters. Try adjusting the status, type or date range.'\n : 'New orders from customers will appear here in real time. Make sure your cart is open and accepting orders.'\n }\n />\n ) : (\n <div className=\"space-y-4\">\n {filteredOrders.map((order) => {\n const status = statusConfig[order.status] || {\n color: 'bg-bg-sunken text-text-secondary',\n label: order.status,\n };\n const fulfillment =\n fulfillmentBadge[order.fulfillmentType || 'delivery'] || fulfillmentBadge.delivery;\n const FulfillmentIcon = fulfillment.icon;\n\n return (\n <div\n key={order.id}\n className={cn(\n 'rounded-lg border bg-bg-surface shadow-sm transition-shadow hover:shadow-md',\n getPriorityColor(order)\n )}\n >\n <div className=\"p-4 sm:p-5\">\n {/* Header */}\n <div className=\"flex flex-col lg:flex-row lg:items-center lg:justify-between gap-3 mb-3\">\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex flex-wrap items-center gap-2 mb-1\">\n <h3 className=\"text-sm sm:text-base font-semibold text-text-primary\">\n Order #{order.id}\n </h3>\n <span\n className={cn(\n 'inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium',\n status.color\n )}\n >\n {status.label}\n </span>\n <span\n className={cn(\n 'inline-flex items-center gap-1 rounded-full px-2.5 py-0.5 text-xs font-medium',\n fulfillment.color\n )}\n >\n <FulfillmentIcon className=\"h-3 w-3\" />\n {fulfillment.label}\n </span>\n </div>\n <p className=\"text-xs text-text-secondary\">\n {order.customerName || 'Customer'} | {formatTimeAgo(order.orderDate)}\n </p>\n </div>\n <div className=\"flex items-center gap-3\">\n <p className=\"text-lg font-bold text-text-primary\">\n {formatCurrency(order.total, { minimumFractionDigits: 0 })}\n </p>\n <button\n type=\"button\"\n onClick={() => {\n setSelectedOrder(order);\n setShowOrderDetails(true);\n }}\n className=\"rounded-md border border-border-subtle px-3 py-1.5 text-xs font-medium text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n View Details\n </button>\n </div>\n </div>\n\n {/* Items */}\n <div className=\"border-t border-border-subtle pt-3 mb-3\">\n <div className=\"flex flex-wrap gap-2\">\n {order.items.map((item, idx) => (\n <span\n key={idx}\n className=\"inline-flex items-center rounded bg-bg-sunken px-2 py-1 text-xs text-text-primary\"\n >\n {item.quantity}x {item.name}\n </span>\n ))}\n </div>\n </div>\n\n {/* Actions */}\n <div className=\"flex flex-wrap gap-2\">\n {order.status === 'pending' && (\n <>\n <button\n type=\"button\"\n onClick={() => handleOrderAction(order.id, 'accept')}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-status-success-bg-subtle px-3 py-2 text-xs font-medium text-status-success-text hover:bg-status-success-bg-subtle transition-colors\"\n >\n <CheckCircle2 className=\"h-3.5 w-3.5\" />\n Accept Order\n </button>\n <button\n type=\"button\"\n onClick={() => handleOrderAction(order.id, 'reject')}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-status-error-bg-subtle px-3 py-2 text-xs font-medium text-status-error-text hover:bg-status-error-bg-subtle transition-colors\"\n >\n <XCircle className=\"h-3.5 w-3.5\" />\n Reject\n </button>\n </>\n )}\n {order.status === 'confirmed' && (\n <button\n type=\"button\"\n onClick={() => handleOrderAction(order.id, 'ready')}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-status-warning-bg-subtle px-3 py-2 text-xs font-medium text-status-warning-text hover:bg-status-warning-bg-subtle transition-colors\"\n >\n <ChefHat className=\"h-3.5 w-3.5\" />\n Start Preparing\n </button>\n )}\n {order.status === 'preparing' && (\n <button\n type=\"button\"\n onClick={() => handleOrderAction(order.id, 'ready')}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-status-success-bg-subtle px-3 py-2 text-xs font-medium text-status-success-text hover:bg-status-success-bg-subtle transition-colors\"\n >\n <PackageCheck className=\"h-3.5 w-3.5\" />\n Mark as Ready\n </button>\n )}\n {order.status === 'ready' && order.fulfillmentType === 'pickup' && (\n <button\n type=\"button\"\n onClick={() => handleOrderAction(order.id, 'complete')}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-status-success-bg-subtle px-3 py-2 text-xs font-medium text-status-success-text hover:bg-status-success-bg-subtle transition-colors\"\n >\n <CheckCircle2 className=\"h-3.5 w-3.5\" />\n Complete Order\n </button>\n )}\n {['confirmed', 'preparing', 'ready'].includes(order.status) && (\n <button\n type=\"button\"\n onClick={() => alert('Contact feature coming soon!')}\n className=\"inline-flex items-center gap-1.5 rounded-md border border-border-subtle px-3 py-2 text-xs font-medium text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n <Phone className=\"h-3.5 w-3.5\" />\n Contact Customer\n </button>\n )}\n </div>\n\n {/* Special Instructions */}\n {order.specialInstructions && (\n <div className=\"mt-3 rounded-md border border-status-warning-text/30 bg-status-warning-bg-subtle p-3\">\n <p className=\"text-xs font-medium text-status-warning-text\">\n Special Instructions:\n </p>\n <p className=\"text-xs text-status-warning-text mt-0.5\">\n {order.specialInstructions}\n </p>\n </div>\n )}\n </div>\n </div>\n );\n })}\n </div>\n )}\n </div>\n\n {/* Order Details Modal */}\n {showOrderDetails && selectedOrder && (\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-2xl max-h-[90vh] overflow-y-auto rounded-lg border border-border-subtle bg-bg-surface shadow-xl\">\n <div className=\"p-6\">\n <div className=\"flex items-center justify-between mb-4\">\n <h3 className=\"text-lg font-semibold text-text-primary\">Order Details</h3>\n <button\n type=\"button\"\n onClick={() => setShowOrderDetails(false)}\n className=\"rounded p-1.5 text-text-secondary hover:text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n <X className=\"h-5 w-5\" />\n </button>\n </div>\n\n <div className=\"space-y-4\">\n {/* Order Meta */}\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <p className=\"text-xs text-text-secondary\">Order ID</p>\n <p className=\"text-sm font-medium text-text-primary\">#{selectedOrder.id}</p>\n </div>\n <div>\n <p className=\"text-xs text-text-secondary\">Status</p>\n <span\n className={cn(\n 'inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium mt-0.5',\n (statusConfig[selectedOrder.status] || statusConfig.pending).color\n )}\n >\n {(statusConfig[selectedOrder.status] || statusConfig.pending).label}\n </span>\n </div>\n <div>\n <p className=\"text-xs text-text-secondary\">Customer</p>\n <p className=\"text-sm font-medium text-text-primary\">\n {selectedOrder.customerName || 'N/A'}\n </p>\n </div>\n <div>\n <p className=\"text-xs text-text-secondary\">Order Time</p>\n <p className=\"text-sm font-medium text-text-primary\">\n {formatTime(selectedOrder.orderDate)}\n </p>\n </div>\n </div>\n\n {/* Items */}\n <div className=\"border-t border-border-subtle pt-4\">\n <h4 className=\"text-sm font-medium text-text-primary mb-3\">Order Items</h4>\n <div className=\"space-y-2\">\n {selectedOrder.items.map((item, idx) => (\n <div key={idx} className=\"flex justify-between items-start\">\n <div>\n <p className=\"text-sm font-medium text-text-primary\">{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 <p className=\"text-sm font-medium text-text-primary\">\n {formatCurrency(item.price * item.quantity, { minimumFractionDigits: 0 })}\n </p>\n </div>\n ))}\n </div>\n </div>\n\n {/* Totals */}\n <div className=\"border-t border-border-subtle pt-4 space-y-2\">\n <div className=\"flex justify-between text-sm text-text-secondary\">\n <span>Subtotal</span>\n <span>\n {formatCurrency(selectedOrder.subtotal, { minimumFractionDigits: 0 })}\n </span>\n </div>\n <div className=\"flex justify-between text-sm text-text-secondary\">\n <span>Delivery Fee</span>\n <span>\n {formatCurrency(selectedOrder.deliveryFee, { minimumFractionDigits: 0 })}\n </span>\n </div>\n <div className=\"flex justify-between text-sm text-text-secondary\">\n <span>Tax</span>\n <span>{formatCurrency(selectedOrder.taxes, { minimumFractionDigits: 0 })}</span>\n </div>\n <div className=\"flex justify-between font-semibold text-text-primary pt-2 border-t border-border-subtle\">\n <span>Total</span>\n <span>{formatCurrency(selectedOrder.total, { minimumFractionDigits: 0 })}</span>\n </div>\n </div>\n\n {/* Delivery Address */}\n {selectedOrder.fulfillmentType === 'delivery' && selectedOrder.deliveryAddress && (\n <div className=\"border-t border-border-subtle pt-4\">\n <h4 className=\"text-sm font-medium text-text-primary mb-2 flex items-center gap-1.5\">\n <MapPin className=\"h-4 w-4 text-text-secondary\" />\n Delivery Address\n </h4>\n <p className=\"text-sm text-text-secondary\">\n {selectedOrder.deliveryAddress.street}, {selectedOrder.deliveryAddress.area}\n <br />\n {selectedOrder.deliveryAddress.city} - {selectedOrder.deliveryAddress.pincode}\n </p>\n </div>\n )}\n\n {/* Modal Actions */}\n <div className=\"flex gap-3 mt-6\">\n <button\n type=\"button\"\n onClick={() => setShowOrderDetails(false)}\n className=\"flex-1 rounded-md border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n Close\n </button>\n {selectedOrder.status === 'pending' && (\n <>\n <button\n type=\"button\"\n onClick={() => handleOrderAction(selectedOrder.id, 'accept')}\n className=\"flex-1 rounded-md bg-status-success-bg-subtle px-4 py-2 text-sm font-medium text-status-success-text hover:bg-status-success-bg-subtle transition-colors\"\n >\n Accept Order\n </button>\n <button\n type=\"button\"\n onClick={() => handleOrderAction(selectedOrder.id, 'reject')}\n className=\"flex-1 rounded-md bg-status-error-bg-subtle px-4 py-2 text-sm font-medium text-status-error-text hover:bg-status-error-bg-subtle transition-colors\"\n >\n Reject Order\n </button>\n </>\n )}\n </div>\n </div>\n </div>\n </div>\n </div>\n )}\n </PageLayout>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"OrderManagementPage.js","names":[],"sources":["../../../../src/kadaikodi/pages/cart-owner/OrderManagementPage.tsx"],"sourcesContent":["/**\n * Order Management Page\n *\n * Stats overview, status-filtered order list with search/date/sort/fulfillment filters,\n * order detail modal, accept/reject/ready/complete actions, priority highlighting.\n *\n * @module kadaikodi/pages/cart-owner\n */\n\nimport { useState, useMemo, useEffect } from 'react';\nimport {\n Search,\n Clock,\n CheckCircle2,\n XCircle,\n ChefHat,\n PackageCheck,\n Phone,\n MapPin,\n User,\n RefreshCw,\n Truck,\n ShoppingBag,\n X,\n AlertCircle,\n Filter,\n ChevronDown,\n} from 'lucide-react';\nimport { EmphasisPanel, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { EmptyState } from '../../components/EmptyState';\nimport { useKadaikodi } from '../../context/KadaikodiContext';\nimport { useOrders, useUpdateOrderStatus, useProviders } from '../../hooks/useKadaikodiApi';\nimport { formatCurrency } from '../../utils/formatters';\nimport { cn } from '../../utils/cn';\nimport type { MockOrder, OrderStatus } from '../../types';\n\n// ============================================================================\n// Types\n// ============================================================================\n\ninterface StatusMessage {\n text: string;\n type: 'success' | 'error';\n}\n\ninterface OrderFilters {\n status: string;\n dateRange: string;\n searchQuery: string;\n sortBy: string;\n fulfillmentType: string;\n}\n\n/** Extended order type with cart-owner specific fields */\ninterface ExtendedOrder extends MockOrder {\n customerName?: string;\n customerPhone?: string;\n fulfillmentType?: 'delivery' | 'pickup' | 'cart_dispatch';\n specialInstructions?: string;\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nconst statusConfig: Record<string, { color: string; label: string }> = {\n pending: { color: 'bg-status-warning-bg-subtle text-status-warning-text', label: 'New Order' },\n confirmed: { color: 'bg-[var(--color-accent-soft)] text-text-primary', label: 'Confirmed' },\n preparing: { color: 'bg-status-warning-bg-subtle text-status-warning-text', label: 'Preparing' },\n ready: { color: 'bg-status-success-bg-subtle text-status-success-text', label: 'Ready' },\n out_for_delivery: {\n color: 'bg-[var(--color-accent-soft)] text-text-primary',\n label: 'Out for Delivery',\n },\n delivered: { color: 'bg-status-success-bg-subtle text-status-success-text', label: 'Completed' },\n cancelled: { color: 'bg-status-error-bg-subtle text-status-error-text', label: 'Cancelled' },\n};\n\nconst fulfillmentBadge: Record<string, { icon: typeof Truck; label: string; color: string }> = {\n delivery: {\n icon: Truck,\n label: 'Delivery',\n color: 'bg-accent-purple-subtle text-text-primary',\n },\n pickup: {\n icon: ShoppingBag,\n label: 'Pickup',\n color: 'bg-[var(--color-accent-soft)] text-text-primary',\n },\n cart_dispatch: {\n icon: MapPin,\n label: 'Cart Dispatch',\n color: 'bg-bg-sunken text-text-secondary',\n },\n};\n\nconst formatTimeAgo = (dateString: string) => {\n const date = new Date(dateString);\n const now = new Date();\n const diffMin = Math.floor((now.getTime() - date.getTime()) / (1000 * 60));\n if (diffMin < 1) return 'Just now';\n if (diffMin < 60) return `${diffMin} min ago`;\n if (diffMin < 1440) return `${Math.floor(diffMin / 60)} hours ago`;\n return date.toLocaleDateString('en-IN', { day: '2-digit', month: 'short' });\n};\n\nconst formatTime = (dateString: string) => {\n return new Date(dateString).toLocaleTimeString('en-IN', {\n hour: 'numeric',\n minute: '2-digit',\n hour12: true,\n });\n};\n\nconst getPriorityColor = (order: ExtendedOrder) => {\n const ageMin = (new Date().getTime() - new Date(order.orderDate).getTime()) / (1000 * 60);\n if (order.status === 'pending' && ageMin > 10)\n return 'border-status-error-text/50 bg-status-error-bg-subtle';\n if (order.status === 'preparing' && ageMin > 30)\n return 'border-status-warning-text/50 bg-status-warning-bg-subtle';\n return 'border-border-subtle';\n};\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const OrderManagementPage = () => {\n const { navigateTo, currentUser } = useKadaikodi();\n\n // Resolve the signed-in owner's provider, then load its real orders.\n const { data: providers = [] } = useProviders();\n const myProvider = useMemo(\n () => providers.find((p) => p.ownerId === currentUser?.id) ?? providers[0],\n [providers, currentUser?.id]\n );\n const { data: fetchedOrders = [], isLoading: isLoadingOrders } = useOrders({\n providerId: myProvider?.id,\n });\n const updateOrderStatus = useUpdateOrderStatus();\n\n // Local working copy so status actions feel instant; kept in sync with the query.\n const [orders, setOrders] = useState<ExtendedOrder[]>([]);\n useEffect(() => {\n setOrders(fetchedOrders);\n }, [fetchedOrders]);\n\n // Filters\n const [filters, setFilters] = useState<OrderFilters>({\n status: '',\n dateRange: 'all',\n searchQuery: '',\n sortBy: 'recent',\n fulfillmentType: '',\n });\n\n // Modal\n const [selectedOrder, setSelectedOrder] = useState<ExtendedOrder | null>(null);\n const [showOrderDetails, setShowOrderDetails] = useState(false);\n\n // Status\n const [statusMessage, setStatusMessage] = useState<StatusMessage | null>(null);\n\n const showStatus = (text: string, type: 'success' | 'error') => {\n setStatusMessage({ text, type });\n setTimeout(() => setStatusMessage(null), 3000);\n };\n\n // ---- Stats ----\n const stats = useMemo(() => {\n const total = orders.length;\n const pending = orders.filter((o) => o.status === 'pending').length;\n const active = orders.filter((o) =>\n ['confirmed', 'preparing', 'ready', 'out_for_delivery'].includes(o.status)\n ).length;\n const completed = orders.filter((o) => o.status === 'delivered').length;\n const totalRevenue = orders\n .filter((o) => o.status === 'delivered')\n .reduce((s, o) => s + o.total, 0);\n const avgOrder = completed > 0 ? Math.round(totalRevenue / completed) : 0;\n return { total, pending, active, completed, totalRevenue, avgOrder };\n }, [orders]);\n\n // ---- Filtered orders ----\n const filteredOrders = useMemo(() => {\n let result = [...orders];\n\n if (filters.status) {\n result = result.filter((o) => o.status === filters.status);\n }\n if (filters.fulfillmentType) {\n result = result.filter((o) => o.fulfillmentType === filters.fulfillmentType);\n }\n if (filters.searchQuery) {\n const q = filters.searchQuery.toLowerCase();\n result = result.filter(\n (o) =>\n o.id.toLowerCase().includes(q) ||\n (o.customerName || '').toLowerCase().includes(q) ||\n o.items.some((item) => item.name.toLowerCase().includes(q))\n );\n }\n if (filters.dateRange !== 'all') {\n const now = new Date();\n const limit = new Date();\n if (filters.dateRange === 'today') limit.setHours(0, 0, 0, 0);\n else if (filters.dateRange === '7days') limit.setDate(now.getDate() - 7);\n else if (filters.dateRange === '30days') limit.setDate(now.getDate() - 30);\n result = result.filter((o) => new Date(o.orderDate) >= limit);\n }\n\n switch (filters.sortBy) {\n case 'recent':\n result.sort((a, b) => new Date(b.orderDate).getTime() - new Date(a.orderDate).getTime());\n break;\n case 'oldest':\n result.sort((a, b) => new Date(a.orderDate).getTime() - new Date(b.orderDate).getTime());\n break;\n case 'amount_high':\n result.sort((a, b) => b.total - a.total);\n break;\n case 'amount_low':\n result.sort((a, b) => a.total - b.total);\n break;\n }\n\n return result;\n }, [orders, filters]);\n\n // ---- Actions ----\n const handleOrderAction = (\n orderId: string,\n action: 'accept' | 'reject' | 'ready' | 'complete'\n ) => {\n const statusMap: Record<string, OrderStatus> = {\n accept: 'confirmed',\n reject: 'cancelled',\n ready: 'ready',\n complete: 'delivered',\n };\n const backendStatusMap: Record<string, string> = {\n accept: 'CONFIRMED',\n reject: 'CANCELLED',\n ready: 'READY',\n complete: 'DELIVERED',\n };\n const messages: Record<string, string> = {\n accept: 'Order accepted',\n reject: 'Order rejected',\n ready: 'Order marked as ready',\n complete: 'Order completed',\n };\n\n setOrders((prev) =>\n prev.map((o) => (o.id === orderId ? { ...o, status: statusMap[action] } : o))\n );\n updateOrderStatus.mutate(\n { id: orderId, status: backendStatusMap[action] },\n { onError: () => showStatus('Could not update the order on the server', 'error') }\n );\n showStatus(messages[action], 'success');\n if (showOrderDetails && selectedOrder?.id === orderId) {\n setShowOrderDetails(false);\n }\n };\n\n return (\n <PageLayout\n title=\"Order Management\"\n description=\"Manage incoming and active orders\"\n actions={\n <button\n type=\"button\"\n onClick={() => showStatus('Orders refreshed', 'success')}\n className=\"inline-flex items-center gap-2 rounded-md border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n <RefreshCw className=\"h-4 w-4\" />\n Refresh\n </button>\n }\n >\n <PagePurpose className=\"mb-6\">\n Your live order queue. Use this page to run service as it happens — accept new orders, move\n them through preparing and ready, hand off for pickup, delivery or cart dispatch, and keep\n customers updated. Filter by status or type to focus on what needs doing right now, and watch\n today's totals so you know how the day is going.\n </PagePurpose>\n\n <div className=\"space-y-4\">\n {/* Status Message */}\n {statusMessage && (\n <div\n className={cn(\n 'flex items-center gap-2 rounded-lg border p-3',\n statusMessage.type === 'success'\n ? 'border-status-success-text/30 bg-status-success-bg-subtle'\n : 'border-status-error-text/30 bg-status-error-bg-subtle'\n )}\n >\n {statusMessage.type === 'success' ? (\n <CheckCircle2 className=\"h-4 w-4 text-status-success-text\" />\n ) : (\n <AlertCircle className=\"h-4 w-4 text-status-error-text\" />\n )}\n <span\n className={cn(\n 'text-sm font-medium',\n statusMessage.type === 'success'\n ? 'text-status-success-text'\n : 'text-status-error-text'\n )}\n >\n {statusMessage.text}\n </span>\n </div>\n )}\n\n {/* Stats Overview — the one emphasis zone for this page */}\n <EmphasisPanel>\n <h2 className=\"mb-4 text-base font-semibold text-text-primary\">Today's Orders</h2>\n <div className=\"grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-6 gap-3\">\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-4 shadow-sm\">\n <p className=\"text-xs text-text-secondary\">Total Orders</p>\n <p className=\"text-2xl font-bold text-text-primary\">{stats.total}</p>\n </div>\n <div className=\"rounded-lg border border-status-warning-text/30 bg-status-warning-bg-subtle p-4 shadow-sm\">\n <p className=\"text-xs text-status-warning-text\">Pending</p>\n <p className=\"text-2xl font-bold text-status-warning-text\">{stats.pending}</p>\n </div>\n <div className=\"rounded-lg border border-border-focus/30 bg-[var(--color-accent-soft)] p-4 shadow-sm\">\n <p className=\"text-xs text-text-primary\">Active</p>\n <p className=\"text-2xl font-bold text-text-primary\">{stats.active}</p>\n </div>\n <div className=\"rounded-lg border border-status-success-text/30 bg-status-success-bg-subtle p-4 shadow-sm\">\n <p className=\"text-xs text-status-success-text\">Completed</p>\n <p className=\"text-2xl font-bold text-status-success-text\">{stats.completed}</p>\n </div>\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-4 shadow-sm\">\n <p className=\"text-xs text-text-secondary\">Total Revenue</p>\n <p className=\"text-2xl font-bold text-text-primary\">\n {formatCurrency(stats.totalRevenue, { minimumFractionDigits: 0 })}\n </p>\n </div>\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-4 shadow-sm\">\n <p className=\"text-xs text-text-secondary\">Avg Order</p>\n <p className=\"text-2xl font-bold text-text-primary\">\n {formatCurrency(stats.avgOrder, { minimumFractionDigits: 0 })}\n </p>\n </div>\n </div>\n </EmphasisPanel>\n\n {/* Filters */}\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-4 shadow-sm\">\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-5 gap-3\">\n <div className=\"relative sm:col-span-2 lg:col-span-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 orders...\"\n value={filters.searchQuery}\n onChange={(e) => setFilters((p) => ({ ...p, searchQuery: e.target.value }))}\n className=\"w-full rounded-md border border-border-subtle bg-bg-surface pl-10 pr-4 py-2 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={filters.status}\n onChange={(e) => setFilters((p) => ({ ...p, status: e.target.value }))}\n className=\"rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n >\n <option value=\"\">All Orders</option>\n <option value=\"pending\">New Orders</option>\n <option value=\"confirmed\">Confirmed</option>\n <option value=\"preparing\">Preparing</option>\n <option value=\"ready\">Ready</option>\n <option value=\"delivered\">Completed</option>\n <option value=\"cancelled\">Cancelled</option>\n </select>\n <select\n value={filters.fulfillmentType}\n onChange={(e) => setFilters((p) => ({ ...p, fulfillmentType: e.target.value }))}\n className=\"rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n >\n <option value=\"\">All Types</option>\n <option value=\"pickup\">Pickup</option>\n <option value=\"delivery\">Delivery</option>\n <option value=\"cart_dispatch\">Cart Dispatch</option>\n </select>\n <select\n value={filters.dateRange}\n onChange={(e) => setFilters((p) => ({ ...p, dateRange: e.target.value }))}\n className=\"rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n >\n <option value=\"today\">Today</option>\n <option value=\"7days\">Last 7 Days</option>\n <option value=\"30days\">Last 30 Days</option>\n <option value=\"all\">All Time</option>\n </select>\n <select\n value={filters.sortBy}\n onChange={(e) => setFilters((p) => ({ ...p, sortBy: e.target.value }))}\n className=\"rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n >\n <option value=\"recent\">Most Recent</option>\n <option value=\"oldest\">Oldest First</option>\n <option value=\"amount_high\">Amount: High to Low</option>\n <option value=\"amount_low\">Amount: Low to High</option>\n </select>\n </div>\n </div>\n\n {/* Orders List */}\n {isLoadingOrders ? (\n <div className=\"flex items-center justify-center py-16\">\n <div className=\"h-10 w-10 animate-spin rounded-full border-b-2 border-foreground\" />\n </div>\n ) : filteredOrders.length === 0 ? (\n <EmptyState\n illustration={filters.searchQuery || filters.status ? 'empty-search' : 'empty-data'}\n title=\"No orders found\"\n description={\n filters.searchQuery || filters.status\n ? 'No orders match your current filters. Try adjusting the status, type or date range.'\n : 'New orders from customers will appear here in real time. Make sure your cart is open and accepting orders.'\n }\n />\n ) : (\n <div className=\"space-y-4\">\n {filteredOrders.map((order) => {\n const status = statusConfig[order.status] || {\n color: 'bg-bg-sunken text-text-secondary',\n label: order.status,\n };\n const fulfillment =\n fulfillmentBadge[order.fulfillmentType || 'delivery'] || fulfillmentBadge.delivery;\n const FulfillmentIcon = fulfillment.icon;\n\n return (\n <div\n key={order.id}\n className={cn(\n 'rounded-lg border bg-bg-surface shadow-sm transition-shadow hover:shadow-md',\n getPriorityColor(order)\n )}\n >\n <div className=\"p-4 sm:p-5\">\n {/* Header */}\n <div className=\"flex flex-col lg:flex-row lg:items-center lg:justify-between gap-3 mb-3\">\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex flex-wrap items-center gap-2 mb-1\">\n <h3 className=\"text-sm sm:text-base font-semibold text-text-primary\">\n Order #{order.id}\n </h3>\n <span\n className={cn(\n 'inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium',\n status.color\n )}\n >\n {status.label}\n </span>\n <span\n className={cn(\n 'inline-flex items-center gap-1 rounded-full px-2.5 py-0.5 text-xs font-medium',\n fulfillment.color\n )}\n >\n <FulfillmentIcon className=\"h-3 w-3\" />\n {fulfillment.label}\n </span>\n </div>\n <p className=\"text-xs text-text-secondary\">\n {order.customerName || 'Customer'} | {formatTimeAgo(order.orderDate)}\n </p>\n </div>\n <div className=\"flex items-center gap-3\">\n <p className=\"text-lg font-bold text-text-primary\">\n {formatCurrency(order.total, { minimumFractionDigits: 0 })}\n </p>\n <button\n type=\"button\"\n onClick={() => {\n setSelectedOrder(order);\n setShowOrderDetails(true);\n }}\n className=\"rounded-md border border-border-subtle px-3 py-1.5 text-xs font-medium text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n View Details\n </button>\n </div>\n </div>\n\n {/* Items */}\n <div className=\"border-t border-border-subtle pt-3 mb-3\">\n <div className=\"flex flex-wrap gap-2\">\n {order.items.map((item, idx) => (\n <span\n key={idx}\n className=\"inline-flex items-center rounded bg-bg-sunken px-2 py-1 text-xs text-text-primary\"\n >\n {item.quantity}x {item.name}\n </span>\n ))}\n </div>\n </div>\n\n {/* Actions */}\n <div className=\"flex flex-wrap gap-2\">\n {order.status === 'pending' && (\n <>\n <button\n type=\"button\"\n onClick={() => handleOrderAction(order.id, 'accept')}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-status-success-bg-subtle px-3 py-2 text-xs font-medium text-status-success-text hover:bg-status-success-bg-subtle transition-colors\"\n >\n <CheckCircle2 className=\"h-3.5 w-3.5\" />\n Accept Order\n </button>\n <button\n type=\"button\"\n onClick={() => handleOrderAction(order.id, 'reject')}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-status-error-bg-subtle px-3 py-2 text-xs font-medium text-status-error-text hover:bg-status-error-bg-subtle transition-colors\"\n >\n <XCircle className=\"h-3.5 w-3.5\" />\n Reject\n </button>\n </>\n )}\n {order.status === 'confirmed' && (\n <button\n type=\"button\"\n onClick={() => handleOrderAction(order.id, 'ready')}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-status-warning-bg-subtle px-3 py-2 text-xs font-medium text-status-warning-text hover:bg-status-warning-bg-subtle transition-colors\"\n >\n <ChefHat className=\"h-3.5 w-3.5\" />\n Start Preparing\n </button>\n )}\n {order.status === 'preparing' && (\n <button\n type=\"button\"\n onClick={() => handleOrderAction(order.id, 'ready')}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-status-success-bg-subtle px-3 py-2 text-xs font-medium text-status-success-text hover:bg-status-success-bg-subtle transition-colors\"\n >\n <PackageCheck className=\"h-3.5 w-3.5\" />\n Mark as Ready\n </button>\n )}\n {order.status === 'ready' && order.fulfillmentType === 'pickup' && (\n <button\n type=\"button\"\n onClick={() => handleOrderAction(order.id, 'complete')}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-status-success-bg-subtle px-3 py-2 text-xs font-medium text-status-success-text hover:bg-status-success-bg-subtle transition-colors\"\n >\n <CheckCircle2 className=\"h-3.5 w-3.5\" />\n Complete Order\n </button>\n )}\n {['confirmed', 'preparing', 'ready'].includes(order.status) && (\n <button\n type=\"button\"\n onClick={() => alert('Contact feature coming soon!')}\n className=\"inline-flex items-center gap-1.5 rounded-md border border-border-subtle px-3 py-2 text-xs font-medium text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n <Phone className=\"h-3.5 w-3.5\" />\n Contact Customer\n </button>\n )}\n </div>\n\n {/* Special Instructions */}\n {order.specialInstructions && (\n <div className=\"mt-3 rounded-md border border-status-warning-text/30 bg-status-warning-bg-subtle p-3\">\n <p className=\"text-xs font-medium text-status-warning-text\">\n Special Instructions:\n </p>\n <p className=\"text-xs text-status-warning-text mt-0.5\">\n {order.specialInstructions}\n </p>\n </div>\n )}\n </div>\n </div>\n );\n })}\n </div>\n )}\n </div>\n\n {/* Order Details Modal */}\n {showOrderDetails && selectedOrder && (\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-2xl max-h-[90vh] overflow-y-auto rounded-lg border border-border-subtle bg-bg-surface shadow-xl\">\n <div className=\"p-6\">\n <div className=\"flex items-center justify-between mb-4\">\n <h3 className=\"text-lg font-semibold text-text-primary\">Order Details</h3>\n <button\n type=\"button\"\n onClick={() => setShowOrderDetails(false)}\n className=\"rounded p-1.5 text-text-secondary hover:text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n <X className=\"h-5 w-5\" />\n </button>\n </div>\n\n <div className=\"space-y-4\">\n {/* Order Meta */}\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <p className=\"text-xs text-text-secondary\">Order ID</p>\n <p className=\"text-sm font-medium text-text-primary\">#{selectedOrder.id}</p>\n </div>\n <div>\n <p className=\"text-xs text-text-secondary\">Status</p>\n <span\n className={cn(\n 'inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium mt-0.5',\n (statusConfig[selectedOrder.status] || statusConfig.pending).color\n )}\n >\n {(statusConfig[selectedOrder.status] || statusConfig.pending).label}\n </span>\n </div>\n <div>\n <p className=\"text-xs text-text-secondary\">Customer</p>\n <p className=\"text-sm font-medium text-text-primary\">\n {selectedOrder.customerName || 'N/A'}\n </p>\n </div>\n <div>\n <p className=\"text-xs text-text-secondary\">Order Time</p>\n <p className=\"text-sm font-medium text-text-primary\">\n {formatTime(selectedOrder.orderDate)}\n </p>\n </div>\n </div>\n\n {/* Items */}\n <div className=\"border-t border-border-subtle pt-4\">\n <h4 className=\"text-sm font-medium text-text-primary mb-3\">Order Items</h4>\n <div className=\"space-y-2\">\n {selectedOrder.items.map((item, idx) => (\n <div key={idx} className=\"flex justify-between items-start\">\n <div>\n <p className=\"text-sm font-medium text-text-primary\">{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 <p className=\"text-sm font-medium text-text-primary\">\n {formatCurrency(item.price * item.quantity, { minimumFractionDigits: 0 })}\n </p>\n </div>\n ))}\n </div>\n </div>\n\n {/* Totals */}\n <div className=\"border-t border-border-subtle pt-4 space-y-2\">\n <div className=\"flex justify-between text-sm text-text-secondary\">\n <span>Subtotal</span>\n <span>\n {formatCurrency(selectedOrder.subtotal, { minimumFractionDigits: 0 })}\n </span>\n </div>\n <div className=\"flex justify-between text-sm text-text-secondary\">\n <span>Delivery Fee</span>\n <span>\n {formatCurrency(selectedOrder.deliveryFee, { minimumFractionDigits: 0 })}\n </span>\n </div>\n <div className=\"flex justify-between text-sm text-text-secondary\">\n <span>Tax</span>\n <span>{formatCurrency(selectedOrder.taxes, { minimumFractionDigits: 0 })}</span>\n </div>\n <div className=\"flex justify-between font-semibold text-text-primary pt-2 border-t border-border-subtle\">\n <span>Total</span>\n <span>{formatCurrency(selectedOrder.total, { minimumFractionDigits: 0 })}</span>\n </div>\n </div>\n\n {/* Delivery Address */}\n {selectedOrder.fulfillmentType === 'delivery' && selectedOrder.deliveryAddress && (\n <div className=\"border-t border-border-subtle pt-4\">\n <h4 className=\"text-sm font-medium text-text-primary mb-2 flex items-center gap-1.5\">\n <MapPin className=\"h-4 w-4 text-text-secondary\" />\n Delivery Address\n </h4>\n <p className=\"text-sm text-text-secondary\">\n {selectedOrder.deliveryAddress.street}, {selectedOrder.deliveryAddress.area}\n <br />\n {selectedOrder.deliveryAddress.city} - {selectedOrder.deliveryAddress.pincode}\n </p>\n </div>\n )}\n\n {/* Modal Actions */}\n <div className=\"flex gap-3 mt-6\">\n <button\n type=\"button\"\n onClick={() => setShowOrderDetails(false)}\n className=\"flex-1 rounded-md border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n Close\n </button>\n {selectedOrder.status === 'pending' && (\n <>\n <button\n type=\"button\"\n onClick={() => handleOrderAction(selectedOrder.id, 'accept')}\n className=\"flex-1 rounded-md bg-status-success-bg-subtle px-4 py-2 text-sm font-medium text-status-success-text hover:bg-status-success-bg-subtle transition-colors\"\n >\n Accept Order\n </button>\n <button\n type=\"button\"\n onClick={() => handleOrderAction(selectedOrder.id, 'reject')}\n className=\"flex-1 rounded-md bg-status-error-bg-subtle px-4 py-2 text-sm font-medium text-status-error-text hover:bg-status-error-bg-subtle transition-colors\"\n >\n Reject Order\n </button>\n </>\n )}\n </div>\n </div>\n </div>\n </div>\n </div>\n )}\n </PageLayout>\n );\n};\n"],"mappings":"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"}
|
|
@@ -457,7 +457,7 @@ function H() {
|
|
|
457
457
|
return /* @__PURE__ */ j("button", {
|
|
458
458
|
type: "button",
|
|
459
459
|
onClick: () => v(e.id),
|
|
460
|
-
className: t("flex items-center gap-1.5 whitespace-nowrap rounded-full border px-3 py-1.5 text-sm font-medium transition-colors", g === e.id ? "border-primary bg-action-primary-bg/10 text-text-primary" : "border-border-subtle text-text-secondary hover:text-text-primary hover:border-
|
|
460
|
+
className: t("flex items-center gap-1.5 whitespace-nowrap rounded-full border px-3 py-1.5 text-sm font-medium transition-colors", g === e.id ? "border-primary bg-action-primary-bg/10 text-text-primary" : "border-border-subtle text-text-secondary hover:text-text-primary hover:border-border-strong"),
|
|
461
461
|
children: [
|
|
462
462
|
/* @__PURE__ */ A(n, { className: "h-3.5 w-3.5" }),
|
|
463
463
|
e.label,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NotificationCenterPage.js","names":[],"sources":["../../../../src/kadaikodi/pages/common/NotificationCenterPage.tsx"],"sourcesContent":["/**\n * Notification Center Page\n * @module kadaikodi/pages/common\n *\n * Full-featured notification center with tab filters (All, Orders,\n * Promotions, System, Unread), date grouping (Today, Yesterday, Earlier),\n * mark-as-read / mark-all-as-read, delete notification, search,\n * type/priority badges, action buttons, stats overview, and empty states.\n */\n\nimport { useState, useMemo, useCallback } from 'react';\nimport {\n Bell,\n ShoppingBag,\n TrendingUp,\n Star,\n AlertCircle,\n CheckCircle2,\n CreditCard,\n Users,\n AlertTriangle,\n Megaphone,\n Check,\n CheckCheck,\n Trash2,\n Search,\n X,\n MailOpen,\n Clock,\n Truck,\n UserCheck,\n Inbox,\n RefreshCw,\n SlidersHorizontal,\n ArrowUpDown,\n} from 'lucide-react';\nimport { EmphasisPanel, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { EmptyState } from '../../components/EmptyState';\nimport { useKadaikodi } from '../../context/KadaikodiContext';\nimport { cn } from '../../utils/cn';\nimport { formatRelativeTime } from '../../utils/formatters';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype NotificationType =\n | 'order_update'\n | 'payment'\n | 'promotion'\n | 'system'\n | 'review'\n | 'staff'\n | 'investment'\n | 'alert'\n | 'delivery'\n | 'account';\n\ntype NotificationPriority = 'low' | 'medium' | 'high' | 'urgent';\n\ntype TabId = 'all' | 'orders' | 'promotions' | 'system' | 'unread';\n\ntype SortOption = 'recent' | 'priority' | 'unread';\n\ninterface Notification {\n id: string;\n type: NotificationType;\n title: string;\n message: string;\n priority: NotificationPriority;\n isRead: boolean;\n createdAt: string;\n actionUrl?: string;\n actionText?: string;\n metadata?: {\n orderId?: string;\n cartId?: string;\n amount?: number;\n };\n}\n\n// ---------------------------------------------------------------------------\n// Mock notifications (14 items, rich variety)\n// ---------------------------------------------------------------------------\n\nconst initialNotifications: Notification[] = [\n {\n id: 'n-001',\n type: 'order_update',\n title: 'Order Delivered Successfully!',\n message:\n 'Your order #ORD-001 from Dosa Express has been delivered. Rate your experience to help others!',\n priority: 'medium',\n isRead: false,\n createdAt: new Date(Date.now() - 8 * 60 * 1000).toISOString(),\n actionUrl: '/customer/order/ORD-001',\n actionText: 'Rate Order',\n metadata: { orderId: 'ORD-001', cartId: 'FOOD-001' },\n },\n {\n id: 'n-002',\n type: 'payment',\n title: 'Payment Confirmed',\n message:\n 'Your payment of \\u20B9495 for order #ORD-002 at Quick Cuts Salon has been processed successfully.',\n priority: 'medium',\n isRead: false,\n createdAt: new Date(Date.now() - 35 * 60 * 1000).toISOString(),\n metadata: { orderId: 'ORD-002', amount: 495 },\n },\n {\n id: 'n-003',\n type: 'promotion',\n title: '20% Off Beauty Services This Weekend!',\n message:\n \"Glow Beauty Services is offering 20% off on all treatments this weekend only. Don't miss out!\",\n priority: 'low',\n isRead: false,\n createdAt: new Date(Date.now() - 2 * 60 * 60 * 1000).toISOString(),\n actionUrl: '/customer/cart/SERV-002',\n actionText: 'Book Now',\n metadata: { cartId: 'SERV-002' },\n },\n {\n id: 'n-004',\n type: 'review',\n title: 'New Review Response',\n message:\n 'Dosa Express replied to your review: \"Thank you so much for your kind words! We hope to serve you again soon.\"',\n priority: 'low',\n isRead: false,\n createdAt: new Date(Date.now() - 4 * 60 * 60 * 1000).toISOString(),\n actionUrl: '/customer/reviews',\n actionText: 'View Reply',\n },\n {\n id: 'n-005',\n type: 'system',\n title: 'App Update Available',\n message:\n 'Version 2.4.0 of Kadaikodi is available with improved performance, new category filters, and bug fixes.',\n priority: 'medium',\n isRead: false,\n createdAt: new Date(Date.now() - 7 * 60 * 60 * 1000).toISOString(),\n actionUrl: '/settings',\n actionText: 'Update Now',\n },\n {\n id: 'n-006',\n type: 'order_update',\n title: 'Appointment Confirmed',\n message:\n 'Your appointment at Quick Cuts Salon has been confirmed for tomorrow at 3:00 PM. The stylist Suresh will be serving you.',\n priority: 'medium',\n isRead: true,\n createdAt: new Date(Date.now() - 1 * 24 * 60 * 60 * 1000).toISOString(),\n actionUrl: '/customer/order/ORD-002',\n actionText: 'View Details',\n metadata: { orderId: 'ORD-002' },\n },\n {\n id: 'n-007',\n type: 'investment',\n title: 'Monthly Returns Credited',\n message:\n 'You received \\u20B91,250 in monthly returns from your Quick Cuts Salon investment. Total portfolio value: \\u20B92,12,500.',\n priority: 'medium',\n isRead: true,\n createdAt: new Date(Date.now() - 1 * 24 * 60 * 60 * 1000).toISOString(),\n actionUrl: '/investor/portfolio',\n actionText: 'View Portfolio',\n metadata: { amount: 1250 },\n },\n {\n id: 'n-008',\n type: 'delivery',\n title: 'Delivery Worker Assigned',\n message:\n 'Ravi Kumar (rated 4.8) has been assigned to deliver your order from Biryani Pot. Estimated arrival: 25 minutes.',\n priority: 'high',\n isRead: true,\n createdAt: new Date(Date.now() - 1.5 * 24 * 60 * 60 * 1000).toISOString(),\n metadata: { orderId: 'ORD-003' },\n },\n {\n id: 'n-009',\n type: 'alert',\n title: 'Unusual Login Attempt Detected',\n message:\n 'We detected a login attempt from a new device in Mumbai. If this was not you, please change your password immediately.',\n priority: 'urgent',\n isRead: true,\n createdAt: new Date(Date.now() - 2 * 24 * 60 * 60 * 1000).toISOString(),\n actionUrl: '/settings',\n actionText: 'Review Activity',\n },\n {\n id: 'n-010',\n type: 'promotion',\n title: 'Flash Sale: Mobile Accessories',\n message:\n 'Gadget Zone Brigade is running a flash sale! Up to 30% off on bluetooth headphones, cases, and chargers.',\n priority: 'low',\n isRead: true,\n createdAt: new Date(Date.now() - 3 * 24 * 60 * 60 * 1000).toISOString(),\n actionUrl: '/customer/cart/RETAIL-003',\n actionText: 'Shop Now',\n metadata: { cartId: 'RETAIL-003' },\n },\n {\n id: 'n-011',\n type: 'system',\n title: 'Scheduled Platform Maintenance',\n message:\n 'Platform maintenance is scheduled for Sunday 2:00 AM - 4:00 AM IST. Some services may be briefly unavailable during this window.',\n priority: 'high',\n isRead: true,\n createdAt: new Date(Date.now() - 4 * 24 * 60 * 60 * 1000).toISOString(),\n },\n {\n id: 'n-012',\n type: 'account',\n title: 'KYC Verification Complete',\n message:\n 'Your KYC verification has been completed successfully. You now have full access to all platform features including investments.',\n priority: 'medium',\n isRead: true,\n createdAt: new Date(Date.now() - 5 * 24 * 60 * 60 * 1000).toISOString(),\n },\n {\n id: 'n-013',\n type: 'staff',\n title: 'Staff Schedule Updated',\n message:\n 'Priya Sharma has updated her availability for this week. She will be unavailable on Wednesday and Thursday.',\n priority: 'medium',\n isRead: true,\n createdAt: new Date(Date.now() - 6 * 24 * 60 * 60 * 1000).toISOString(),\n actionUrl: '/owner/staff',\n actionText: 'View Schedule',\n },\n {\n id: 'n-014',\n type: 'payment',\n title: 'Refund Processed',\n message:\n 'Your refund of \\u20B9280 for order #ORD-005 has been processed. The amount will reflect in your account within 3-5 business days.',\n priority: 'medium',\n isRead: true,\n createdAt: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString(),\n metadata: { orderId: 'ORD-005', amount: 280 },\n },\n];\n\n// ---------------------------------------------------------------------------\n// Type icon/color configuration\n// ---------------------------------------------------------------------------\n\nconst typeConfig: Record<string, { icon: typeof Bell; color: string; bg: string; label: string }> =\n {\n order_update: {\n icon: ShoppingBag,\n color: 'text-text-primary',\n bg: 'bg-[var(--color-accent-soft)]',\n label: 'Order',\n },\n payment: {\n icon: CreditCard,\n color: 'text-status-success-text',\n bg: 'bg-status-success-bg-subtle',\n label: 'Payment',\n },\n promotion: {\n icon: Megaphone,\n color: 'text-status-warning-text',\n bg: 'bg-status-warning-bg-subtle',\n label: 'Promo',\n },\n system: {\n icon: AlertCircle,\n color: 'text-text-primary',\n bg: 'bg-accent-purple-subtle',\n label: 'System',\n },\n review: {\n icon: Star,\n color: 'text-status-warning-text',\n bg: 'bg-status-warning-bg-subtle',\n label: 'Review',\n },\n staff: {\n icon: Users,\n color: 'text-text-primary',\n bg: 'bg-[var(--color-accent-soft)]',\n label: 'Staff',\n },\n investment: {\n icon: TrendingUp,\n color: 'text-status-success-text',\n bg: 'bg-status-success-bg-subtle',\n label: 'Investment',\n },\n alert: {\n icon: AlertTriangle,\n color: 'text-status-error-text',\n bg: 'bg-status-error-bg-subtle',\n label: 'Alert',\n },\n delivery: {\n icon: Truck,\n color: 'text-text-primary',\n bg: 'bg-[var(--color-accent-soft)]',\n label: 'Delivery',\n },\n account: {\n icon: UserCheck,\n color: 'text-status-success-text',\n bg: 'bg-status-success-bg-subtle',\n label: 'Account',\n },\n };\n\n// ---------------------------------------------------------------------------\n// Priority styling\n// ---------------------------------------------------------------------------\n\nconst priorityStyles: Record<NotificationPriority, string> = {\n urgent: 'bg-status-error-bg-subtle text-status-error-text',\n high: 'bg-status-warning-bg-subtle text-status-warning-text',\n medium: 'bg-[var(--color-accent-soft)] text-text-primary',\n low: 'bg-bg-sunken text-text-secondary',\n};\n\nconst priorityBorderColors: Record<NotificationPriority, string> = {\n urgent: 'border-l-red-500',\n high: 'border-l-orange-500',\n medium: 'border-l-blue-500',\n low: 'border-l-border',\n};\n\nconst priorityOrder: Record<NotificationPriority, number> = {\n urgent: 4,\n high: 3,\n medium: 2,\n low: 1,\n};\n\n// ---------------------------------------------------------------------------\n// Tab definitions\n// ---------------------------------------------------------------------------\n\nconst tabs: { id: TabId; label: string; icon: typeof Bell }[] = [\n { id: 'all', label: 'All', icon: Inbox },\n { id: 'orders', label: 'Orders', icon: ShoppingBag },\n { id: 'promotions', label: 'Promotions', icon: Megaphone },\n { id: 'system', label: 'System', icon: AlertCircle },\n { id: 'unread', label: 'Unread', icon: Bell },\n];\n\n// ---------------------------------------------------------------------------\n// Date grouping helpers\n// ---------------------------------------------------------------------------\n\nfunction getDateGroup(dateStr: string): string {\n const date = new Date(dateStr);\n const now = new Date();\n const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());\n const yesterday = new Date(today.getTime() - 24 * 60 * 60 * 1000);\n\n if (date >= today) return 'Today';\n if (date >= yesterday) return 'Yesterday';\n return 'Earlier';\n}\n\nfunction groupByDate(items: Notification[]): { label: string; items: Notification[] }[] {\n const groups: { label: string; items: Notification[] }[] = [];\n const map = new Map<string, Notification[]>();\n const order = ['Today', 'Yesterday', 'Earlier'];\n\n for (const n of items) {\n const group = getDateGroup(n.createdAt);\n if (!map.has(group)) map.set(group, []);\n map.get(group)!.push(n);\n }\n\n for (const label of order) {\n const items = map.get(label);\n if (items && items.length > 0) {\n groups.push({ label, items });\n }\n }\n\n return groups;\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nexport function NotificationCenterPage() {\n const { navigateTo } = useKadaikodi();\n const [notifications, setNotifications] = useState<Notification[]>(initialNotifications);\n const [activeTab, setActiveTab] = useState<TabId>('all');\n const [searchQuery, setSearchQuery] = useState('');\n const [sortBy, setSortBy] = useState<SortOption>('recent');\n const [showSortMenu, setShowSortMenu] = useState(false);\n\n // ---------------------------------------------------------------------------\n // Derived counts\n // ---------------------------------------------------------------------------\n\n const unreadCount = useMemo(() => notifications.filter((n) => !n.isRead).length, [notifications]);\n\n const urgentCount = useMemo(\n () => notifications.filter((n) => n.priority === 'urgent').length,\n [notifications]\n );\n\n const todayCount = useMemo(\n () => notifications.filter((n) => getDateGroup(n.createdAt) === 'Today').length,\n [notifications]\n );\n\n const thisWeekCount = useMemo(() => {\n const weekAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000);\n return notifications.filter((n) => new Date(n.createdAt) >= weekAgo).length;\n }, [notifications]);\n\n const tabCounts = useMemo(() => {\n const counts: Record<TabId, number> = {\n all: 0,\n orders: 0,\n promotions: 0,\n system: 0,\n unread: 0,\n };\n for (const n of notifications) {\n counts.all++;\n if (!n.isRead) counts.unread++;\n if (n.type === 'order_update' || n.type === 'delivery') counts.orders++;\n if (n.type === 'promotion') counts.promotions++;\n if (n.type === 'system' || n.type === 'alert' || n.type === 'account') counts.system++;\n }\n return counts;\n }, [notifications]);\n\n // ---------------------------------------------------------------------------\n // Filtered & sorted list\n // ---------------------------------------------------------------------------\n\n const filteredNotifications = useMemo(() => {\n let list = [...notifications];\n\n // Tab filter\n switch (activeTab) {\n case 'orders':\n list = list.filter((n) => n.type === 'order_update' || n.type === 'delivery');\n break;\n case 'promotions':\n list = list.filter((n) => n.type === 'promotion');\n break;\n case 'system':\n list = list.filter(\n (n) => n.type === 'system' || n.type === 'alert' || n.type === 'account'\n );\n break;\n case 'unread':\n list = list.filter((n) => !n.isRead);\n break;\n }\n\n // Search filter\n if (searchQuery) {\n const q = searchQuery.toLowerCase();\n list = list.filter(\n (n) => n.title.toLowerCase().includes(q) || n.message.toLowerCase().includes(q)\n );\n }\n\n // Sort\n switch (sortBy) {\n case 'recent':\n list.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());\n break;\n case 'priority':\n list.sort((a, b) => priorityOrder[b.priority] - priorityOrder[a.priority]);\n break;\n case 'unread':\n list.sort((a, b) => (a.isRead === b.isRead ? 0 : a.isRead ? 1 : -1));\n break;\n }\n\n return list;\n }, [notifications, activeTab, searchQuery, sortBy]);\n\n // Grouped by date\n const grouped = useMemo(() => groupByDate(filteredNotifications), [filteredNotifications]);\n\n // ---------------------------------------------------------------------------\n // Actions\n // ---------------------------------------------------------------------------\n\n const markAsRead = useCallback((id: string) => {\n setNotifications((prev) => prev.map((n) => (n.id === id ? { ...n, isRead: true } : n)));\n }, []);\n\n const markAllAsRead = useCallback(() => {\n setNotifications((prev) => prev.map((n) => ({ ...n, isRead: true })));\n }, []);\n\n const deleteNotification = useCallback((id: string) => {\n setNotifications((prev) => prev.filter((n) => n.id !== id));\n }, []);\n\n const handleAction = useCallback(\n (notif: Notification) => {\n if (!notif.isRead) markAsRead(notif.id);\n if (notif.actionUrl) navigateTo(notif.actionUrl);\n },\n [markAsRead, navigateTo]\n );\n\n const clearAll = useCallback(() => {\n if (window.confirm('Are you sure you want to clear all notifications?')) {\n setNotifications([]);\n }\n }, []);\n\n // ---------------------------------------------------------------------------\n // Render\n // ---------------------------------------------------------------------------\n\n return (\n <PageLayout\n title=\"Notifications\"\n description={\n unreadCount > 0\n ? `${unreadCount} unread notification${unreadCount !== 1 ? 's' : ''}`\n : 'All caught up!'\n }\n actions={\n <div className=\"flex items-center gap-2\">\n {notifications.length > 0 && (\n <button\n type=\"button\"\n onClick={clearAll}\n className=\"flex items-center gap-1.5 rounded-lg border border-border-subtle px-3 py-2 text-sm font-medium text-text-secondary hover:text-text-primary hover:bg-accent transition-colors\"\n >\n <Trash2 className=\"h-4 w-4\" />\n <span className=\"hidden sm:inline\">Clear All</span>\n </button>\n )}\n {unreadCount > 0 && (\n <button\n type=\"button\"\n onClick={markAllAsRead}\n className=\"flex items-center gap-1.5 rounded-lg border border-border-subtle px-3 py-2 text-sm font-medium text-text-primary hover:bg-accent transition-colors\"\n >\n <CheckCheck className=\"h-4 w-4\" />\n Mark All Read\n </button>\n )}\n </div>\n }\n >\n <PagePurpose className=\"mb-6\">\n Your single inbox for everything happening on Kadaikodi — orders, payments, alerts and\n updates. Use this page to stay on top of what needs attention: filter by category, open a\n notification to jump straight to the relevant screen, and mark things read or clear them once\n handled so nothing important slips by.\n </PagePurpose>\n\n {/* ---- Stats Overview — the one emphasis zone for this page ---- */}\n <EmphasisPanel className=\"mb-6\">\n <h2 className=\"mb-4 text-base font-semibold text-text-primary\">At a Glance</h2>\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-5\">\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-3 text-center\">\n <p className=\"text-2xl font-bold text-text-primary\">{notifications.length}</p>\n <p className=\"text-xs text-text-secondary\">Total</p>\n </div>\n <div className=\"rounded-lg border border-border-focus/30 bg-[var(--color-accent-soft)] p-3 text-center\">\n <p className=\"text-2xl font-bold text-text-primary\">{unreadCount}</p>\n <p className=\"text-xs text-text-secondary\">Unread</p>\n </div>\n <div className=\"rounded-lg border border-status-error-text/30 bg-status-error-bg-subtle p-3 text-center\">\n <p className=\"text-2xl font-bold text-status-error-text\">{urgentCount}</p>\n <p className=\"text-xs text-text-secondary\">Urgent</p>\n </div>\n <div className=\"rounded-lg border border-status-success-text/30 bg-status-success-bg-subtle p-3 text-center\">\n <p className=\"text-2xl font-bold text-status-success-text\">{todayCount}</p>\n <p className=\"text-xs text-text-secondary\">Today</p>\n </div>\n <div className=\"rounded-lg border border-status-warning-text/30 bg-status-warning-bg-subtle p-3 text-center\">\n <p className=\"text-2xl font-bold text-status-warning-text\">{thisWeekCount}</p>\n <p className=\"text-xs text-text-secondary\">This Week</p>\n </div>\n </div>\n </EmphasisPanel>\n\n {/* ---- Tabs ---- */}\n <div className=\"flex items-center gap-2 mb-4 overflow-x-auto pb-1\">\n {tabs.map((tab) => {\n const TabIcon = tab.icon;\n return (\n <button\n key={tab.id}\n type=\"button\"\n onClick={() => setActiveTab(tab.id)}\n className={cn(\n 'flex items-center gap-1.5 whitespace-nowrap rounded-full border px-3 py-1.5 text-sm font-medium transition-colors',\n activeTab === tab.id\n ? 'border-primary bg-action-primary-bg/10 text-text-primary'\n : 'border-border-subtle text-text-secondary hover:text-text-primary hover:border-accent-foreground/20'\n )}\n >\n <TabIcon className=\"h-3.5 w-3.5\" />\n {tab.label}\n <span\n className={cn(\n 'inline-flex h-5 min-w-[20px] items-center justify-center rounded-full px-1 text-xs',\n activeTab === tab.id\n ? 'bg-action-primary-bg text-action-primary-text'\n : 'bg-bg-sunken text-text-secondary'\n )}\n >\n {tabCounts[tab.id]}\n </span>\n </button>\n );\n })}\n </div>\n\n {/* ---- Search & Sort ---- */}\n <div className=\"flex items-center gap-3 mb-6\">\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 notifications...\"\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.5 pl-10 pr-9 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n {searchQuery && (\n <button\n type=\"button\"\n onClick={() => setSearchQuery('')}\n className=\"absolute right-3 top-1/2 -translate-y-1/2 text-text-secondary hover:text-text-primary\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n )}\n </div>\n\n {/* Sort dropdown */}\n <div className=\"relative\">\n <button\n type=\"button\"\n onClick={() => setShowSortMenu(!showSortMenu)}\n className=\"flex items-center gap-1.5 rounded-lg border border-border-subtle px-3 py-2.5 text-sm font-medium text-text-primary hover:bg-accent transition-colors\"\n >\n <ArrowUpDown className=\"h-4 w-4\" />\n <span className=\"hidden sm:inline\">Sort</span>\n </button>\n {showSortMenu && (\n <>\n {/* Backdrop */}\n <div className=\"fixed inset-0 z-10\" onClick={() => setShowSortMenu(false)} />\n <div className=\"absolute right-0 top-full mt-1 z-20 w-44 rounded-lg border border-border-subtle bg-bg-surface shadow-lg py-1\">\n {(\n [\n { value: 'recent', label: 'Most Recent' },\n { value: 'priority', label: 'By Priority' },\n { value: 'unread', label: 'Unread First' },\n ] as const\n ).map((opt) => (\n <button\n key={opt.value}\n type=\"button\"\n onClick={() => {\n setSortBy(opt.value);\n setShowSortMenu(false);\n }}\n className={cn(\n 'w-full text-left px-3 py-2 text-sm transition-colors',\n sortBy === opt.value\n ? 'bg-action-primary-bg/10 text-text-primary font-medium'\n : 'text-text-secondary hover:bg-accent hover:text-text-primary'\n )}\n >\n {opt.label}\n </button>\n ))}\n </div>\n </>\n )}\n </div>\n </div>\n\n {/* ---- Notification List ---- */}\n {filteredNotifications.length === 0 ? (\n <EmptyState\n illustration={searchQuery ? 'empty-search' : 'empty-notifications'}\n icon={<Bell className=\"h-12 w-12\" />}\n title=\"No notifications\"\n description={\n searchQuery\n ? 'No notifications match your search. Try different keywords.'\n : activeTab === 'unread'\n ? \"You're all caught up! No unread notifications.\"\n : 'No notifications in this category yet.'\n }\n action={\n searchQuery ? (\n <button\n type=\"button\"\n onClick={() => setSearchQuery('')}\n className=\"rounded-lg border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-accent transition-colors\"\n >\n Clear Search\n </button>\n ) : activeTab !== 'all' ? (\n <button\n type=\"button\"\n onClick={() => setActiveTab('all')}\n className=\"rounded-lg border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-accent transition-colors\"\n >\n View All Notifications\n </button>\n ) : undefined\n }\n />\n ) : (\n <div className=\"space-y-6\">\n {grouped.map((group) => (\n <div key={group.label}>\n {/* Date group header */}\n <div className=\"flex items-center gap-3 mb-2\">\n <h3 className=\"text-xs font-semibold uppercase tracking-wider text-text-secondary\">\n {group.label}\n </h3>\n <div className=\"flex-1 border-t border-border-subtle\" />\n <span className=\"text-xs text-text-secondary\">\n {group.items.length} notification{group.items.length !== 1 ? 's' : ''}\n </span>\n </div>\n\n {/* Notification cards */}\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface divide-y divide-border overflow-hidden\">\n {group.items.map((notif) => {\n const config = typeConfig[notif.type] ?? typeConfig.system;\n const NotifIcon = config.icon;\n\n return (\n <div\n key={notif.id}\n className={cn(\n 'flex items-start gap-3 px-4 py-4 border-l-4 transition-colors',\n priorityBorderColors[notif.priority],\n !notif.isRead && 'bg-accent/30'\n )}\n >\n {/* Type icon */}\n <div\n className={cn(\n 'flex h-10 w-10 shrink-0 items-center justify-center rounded-full',\n config.bg\n )}\n >\n <NotifIcon className={cn('h-5 w-5', config.color)} />\n </div>\n\n {/* Content */}\n <div className=\"flex-1 min-w-0\">\n {/* Title row */}\n <div className=\"flex items-center gap-2 flex-wrap\">\n <h4\n className={cn(\n 'text-sm text-text-primary',\n !notif.isRead ? 'font-semibold' : 'font-medium'\n )}\n >\n {notif.title}\n </h4>\n {!notif.isRead && (\n <span className=\"h-2 w-2 rounded-full bg-action-primary-bg shrink-0\" />\n )}\n <span\n className={cn(\n 'inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium',\n priorityStyles[notif.priority]\n )}\n >\n {notif.priority}\n </span>\n </div>\n\n {/* Message */}\n <p className=\"mt-1 text-sm text-text-secondary leading-relaxed\">\n {notif.message}\n </p>\n\n {/* Metadata row */}\n <div className=\"mt-2 flex items-center gap-3 flex-wrap\">\n <span className=\"flex items-center gap-1 text-xs text-text-secondary\">\n <Clock className=\"h-3 w-3\" />\n {formatRelativeTime(notif.createdAt)}\n </span>\n <span\n className={cn(\n 'inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium',\n config.bg,\n config.color\n )}\n >\n {config.label}\n </span>\n {notif.metadata?.orderId && (\n <span className=\"text-xs text-text-secondary\">\n #{notif.metadata.orderId}\n </span>\n )}\n </div>\n\n {/* Action buttons row */}\n <div className=\"mt-3 flex items-center gap-2 flex-wrap\">\n {notif.actionUrl && (\n <button\n type=\"button\"\n onClick={() => handleAction(notif)}\n className=\"rounded-lg bg-action-primary-bg px-3 py-1.5 text-xs font-medium text-action-primary-text hover:bg-action-primary-bg/90 transition-colors\"\n >\n {notif.actionText ?? 'View'}\n </button>\n )}\n {!notif.isRead && (\n <button\n type=\"button\"\n onClick={() => markAsRead(notif.id)}\n title=\"Mark as read\"\n className=\"flex items-center gap-1 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 <Check className=\"h-3 w-3\" />\n Mark Read\n </button>\n )}\n <button\n type=\"button\"\n onClick={() => deleteNotification(notif.id)}\n title=\"Delete notification\"\n className=\"flex items-center gap-1 rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium text-status-error-text hover:bg-status-error-bg/10 transition-colors\"\n >\n <Trash2 className=\"h-3 w-3\" />\n Delete\n </button>\n </div>\n </div>\n\n {/* Read/unread indicator */}\n <div className=\"shrink-0 pt-1\">\n {notif.isRead ? (\n <MailOpen className=\"h-4 w-4 text-text-secondary/40\" />\n ) : (\n <Bell className=\"h-4 w-4 text-primary\" />\n )}\n </div>\n </div>\n );\n })}\n </div>\n </div>\n ))}\n </div>\n )}\n\n {/* ---- Footer summary ---- */}\n {filteredNotifications.length > 0 && (\n <div className=\"mt-6 flex items-center justify-between rounded-lg border border-border-subtle bg-bg-surface px-4 py-3\">\n <p className=\"text-sm text-text-secondary\">\n Showing {filteredNotifications.length} of {notifications.length} notifications\n </p>\n {activeTab !== 'all' && (\n <button\n type=\"button\"\n onClick={() => {\n setActiveTab('all');\n setSearchQuery('');\n }}\n className=\"flex items-center gap-1.5 text-sm font-medium text-primary hover:underline\"\n >\n <RefreshCw className=\"h-3.5 w-3.5\" />\n Show All\n </button>\n )}\n </div>\n )}\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"NotificationCenterPage.js","names":[],"sources":["../../../../src/kadaikodi/pages/common/NotificationCenterPage.tsx"],"sourcesContent":["/**\n * Notification Center Page\n * @module kadaikodi/pages/common\n *\n * Full-featured notification center with tab filters (All, Orders,\n * Promotions, System, Unread), date grouping (Today, Yesterday, Earlier),\n * mark-as-read / mark-all-as-read, delete notification, search,\n * type/priority badges, action buttons, stats overview, and empty states.\n */\n\nimport { useState, useMemo, useCallback } from 'react';\nimport {\n Bell,\n ShoppingBag,\n TrendingUp,\n Star,\n AlertCircle,\n CheckCircle2,\n CreditCard,\n Users,\n AlertTriangle,\n Megaphone,\n Check,\n CheckCheck,\n Trash2,\n Search,\n X,\n MailOpen,\n Clock,\n Truck,\n UserCheck,\n Inbox,\n RefreshCw,\n SlidersHorizontal,\n ArrowUpDown,\n} from 'lucide-react';\nimport { EmphasisPanel, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { EmptyState } from '../../components/EmptyState';\nimport { useKadaikodi } from '../../context/KadaikodiContext';\nimport { cn } from '../../utils/cn';\nimport { formatRelativeTime } from '../../utils/formatters';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype NotificationType =\n | 'order_update'\n | 'payment'\n | 'promotion'\n | 'system'\n | 'review'\n | 'staff'\n | 'investment'\n | 'alert'\n | 'delivery'\n | 'account';\n\ntype NotificationPriority = 'low' | 'medium' | 'high' | 'urgent';\n\ntype TabId = 'all' | 'orders' | 'promotions' | 'system' | 'unread';\n\ntype SortOption = 'recent' | 'priority' | 'unread';\n\ninterface Notification {\n id: string;\n type: NotificationType;\n title: string;\n message: string;\n priority: NotificationPriority;\n isRead: boolean;\n createdAt: string;\n actionUrl?: string;\n actionText?: string;\n metadata?: {\n orderId?: string;\n cartId?: string;\n amount?: number;\n };\n}\n\n// ---------------------------------------------------------------------------\n// Mock notifications (14 items, rich variety)\n// ---------------------------------------------------------------------------\n\nconst initialNotifications: Notification[] = [\n {\n id: 'n-001',\n type: 'order_update',\n title: 'Order Delivered Successfully!',\n message:\n 'Your order #ORD-001 from Dosa Express has been delivered. Rate your experience to help others!',\n priority: 'medium',\n isRead: false,\n createdAt: new Date(Date.now() - 8 * 60 * 1000).toISOString(),\n actionUrl: '/customer/order/ORD-001',\n actionText: 'Rate Order',\n metadata: { orderId: 'ORD-001', cartId: 'FOOD-001' },\n },\n {\n id: 'n-002',\n type: 'payment',\n title: 'Payment Confirmed',\n message:\n 'Your payment of \\u20B9495 for order #ORD-002 at Quick Cuts Salon has been processed successfully.',\n priority: 'medium',\n isRead: false,\n createdAt: new Date(Date.now() - 35 * 60 * 1000).toISOString(),\n metadata: { orderId: 'ORD-002', amount: 495 },\n },\n {\n id: 'n-003',\n type: 'promotion',\n title: '20% Off Beauty Services This Weekend!',\n message:\n \"Glow Beauty Services is offering 20% off on all treatments this weekend only. Don't miss out!\",\n priority: 'low',\n isRead: false,\n createdAt: new Date(Date.now() - 2 * 60 * 60 * 1000).toISOString(),\n actionUrl: '/customer/cart/SERV-002',\n actionText: 'Book Now',\n metadata: { cartId: 'SERV-002' },\n },\n {\n id: 'n-004',\n type: 'review',\n title: 'New Review Response',\n message:\n 'Dosa Express replied to your review: \"Thank you so much for your kind words! We hope to serve you again soon.\"',\n priority: 'low',\n isRead: false,\n createdAt: new Date(Date.now() - 4 * 60 * 60 * 1000).toISOString(),\n actionUrl: '/customer/reviews',\n actionText: 'View Reply',\n },\n {\n id: 'n-005',\n type: 'system',\n title: 'App Update Available',\n message:\n 'Version 2.4.0 of Kadaikodi is available with improved performance, new category filters, and bug fixes.',\n priority: 'medium',\n isRead: false,\n createdAt: new Date(Date.now() - 7 * 60 * 60 * 1000).toISOString(),\n actionUrl: '/settings',\n actionText: 'Update Now',\n },\n {\n id: 'n-006',\n type: 'order_update',\n title: 'Appointment Confirmed',\n message:\n 'Your appointment at Quick Cuts Salon has been confirmed for tomorrow at 3:00 PM. The stylist Suresh will be serving you.',\n priority: 'medium',\n isRead: true,\n createdAt: new Date(Date.now() - 1 * 24 * 60 * 60 * 1000).toISOString(),\n actionUrl: '/customer/order/ORD-002',\n actionText: 'View Details',\n metadata: { orderId: 'ORD-002' },\n },\n {\n id: 'n-007',\n type: 'investment',\n title: 'Monthly Returns Credited',\n message:\n 'You received \\u20B91,250 in monthly returns from your Quick Cuts Salon investment. Total portfolio value: \\u20B92,12,500.',\n priority: 'medium',\n isRead: true,\n createdAt: new Date(Date.now() - 1 * 24 * 60 * 60 * 1000).toISOString(),\n actionUrl: '/investor/portfolio',\n actionText: 'View Portfolio',\n metadata: { amount: 1250 },\n },\n {\n id: 'n-008',\n type: 'delivery',\n title: 'Delivery Worker Assigned',\n message:\n 'Ravi Kumar (rated 4.8) has been assigned to deliver your order from Biryani Pot. Estimated arrival: 25 minutes.',\n priority: 'high',\n isRead: true,\n createdAt: new Date(Date.now() - 1.5 * 24 * 60 * 60 * 1000).toISOString(),\n metadata: { orderId: 'ORD-003' },\n },\n {\n id: 'n-009',\n type: 'alert',\n title: 'Unusual Login Attempt Detected',\n message:\n 'We detected a login attempt from a new device in Mumbai. If this was not you, please change your password immediately.',\n priority: 'urgent',\n isRead: true,\n createdAt: new Date(Date.now() - 2 * 24 * 60 * 60 * 1000).toISOString(),\n actionUrl: '/settings',\n actionText: 'Review Activity',\n },\n {\n id: 'n-010',\n type: 'promotion',\n title: 'Flash Sale: Mobile Accessories',\n message:\n 'Gadget Zone Brigade is running a flash sale! Up to 30% off on bluetooth headphones, cases, and chargers.',\n priority: 'low',\n isRead: true,\n createdAt: new Date(Date.now() - 3 * 24 * 60 * 60 * 1000).toISOString(),\n actionUrl: '/customer/cart/RETAIL-003',\n actionText: 'Shop Now',\n metadata: { cartId: 'RETAIL-003' },\n },\n {\n id: 'n-011',\n type: 'system',\n title: 'Scheduled Platform Maintenance',\n message:\n 'Platform maintenance is scheduled for Sunday 2:00 AM - 4:00 AM IST. Some services may be briefly unavailable during this window.',\n priority: 'high',\n isRead: true,\n createdAt: new Date(Date.now() - 4 * 24 * 60 * 60 * 1000).toISOString(),\n },\n {\n id: 'n-012',\n type: 'account',\n title: 'KYC Verification Complete',\n message:\n 'Your KYC verification has been completed successfully. You now have full access to all platform features including investments.',\n priority: 'medium',\n isRead: true,\n createdAt: new Date(Date.now() - 5 * 24 * 60 * 60 * 1000).toISOString(),\n },\n {\n id: 'n-013',\n type: 'staff',\n title: 'Staff Schedule Updated',\n message:\n 'Priya Sharma has updated her availability for this week. She will be unavailable on Wednesday and Thursday.',\n priority: 'medium',\n isRead: true,\n createdAt: new Date(Date.now() - 6 * 24 * 60 * 60 * 1000).toISOString(),\n actionUrl: '/owner/staff',\n actionText: 'View Schedule',\n },\n {\n id: 'n-014',\n type: 'payment',\n title: 'Refund Processed',\n message:\n 'Your refund of \\u20B9280 for order #ORD-005 has been processed. The amount will reflect in your account within 3-5 business days.',\n priority: 'medium',\n isRead: true,\n createdAt: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString(),\n metadata: { orderId: 'ORD-005', amount: 280 },\n },\n];\n\n// ---------------------------------------------------------------------------\n// Type icon/color configuration\n// ---------------------------------------------------------------------------\n\nconst typeConfig: Record<string, { icon: typeof Bell; color: string; bg: string; label: string }> =\n {\n order_update: {\n icon: ShoppingBag,\n color: 'text-text-primary',\n bg: 'bg-[var(--color-accent-soft)]',\n label: 'Order',\n },\n payment: {\n icon: CreditCard,\n color: 'text-status-success-text',\n bg: 'bg-status-success-bg-subtle',\n label: 'Payment',\n },\n promotion: {\n icon: Megaphone,\n color: 'text-status-warning-text',\n bg: 'bg-status-warning-bg-subtle',\n label: 'Promo',\n },\n system: {\n icon: AlertCircle,\n color: 'text-text-primary',\n bg: 'bg-accent-purple-subtle',\n label: 'System',\n },\n review: {\n icon: Star,\n color: 'text-status-warning-text',\n bg: 'bg-status-warning-bg-subtle',\n label: 'Review',\n },\n staff: {\n icon: Users,\n color: 'text-text-primary',\n bg: 'bg-[var(--color-accent-soft)]',\n label: 'Staff',\n },\n investment: {\n icon: TrendingUp,\n color: 'text-status-success-text',\n bg: 'bg-status-success-bg-subtle',\n label: 'Investment',\n },\n alert: {\n icon: AlertTriangle,\n color: 'text-status-error-text',\n bg: 'bg-status-error-bg-subtle',\n label: 'Alert',\n },\n delivery: {\n icon: Truck,\n color: 'text-text-primary',\n bg: 'bg-[var(--color-accent-soft)]',\n label: 'Delivery',\n },\n account: {\n icon: UserCheck,\n color: 'text-status-success-text',\n bg: 'bg-status-success-bg-subtle',\n label: 'Account',\n },\n };\n\n// ---------------------------------------------------------------------------\n// Priority styling\n// ---------------------------------------------------------------------------\n\nconst priorityStyles: Record<NotificationPriority, string> = {\n urgent: 'bg-status-error-bg-subtle text-status-error-text',\n high: 'bg-status-warning-bg-subtle text-status-warning-text',\n medium: 'bg-[var(--color-accent-soft)] text-text-primary',\n low: 'bg-bg-sunken text-text-secondary',\n};\n\nconst priorityBorderColors: Record<NotificationPriority, string> = {\n urgent: 'border-l-red-500',\n high: 'border-l-orange-500',\n medium: 'border-l-blue-500',\n low: 'border-l-border',\n};\n\nconst priorityOrder: Record<NotificationPriority, number> = {\n urgent: 4,\n high: 3,\n medium: 2,\n low: 1,\n};\n\n// ---------------------------------------------------------------------------\n// Tab definitions\n// ---------------------------------------------------------------------------\n\nconst tabs: { id: TabId; label: string; icon: typeof Bell }[] = [\n { id: 'all', label: 'All', icon: Inbox },\n { id: 'orders', label: 'Orders', icon: ShoppingBag },\n { id: 'promotions', label: 'Promotions', icon: Megaphone },\n { id: 'system', label: 'System', icon: AlertCircle },\n { id: 'unread', label: 'Unread', icon: Bell },\n];\n\n// ---------------------------------------------------------------------------\n// Date grouping helpers\n// ---------------------------------------------------------------------------\n\nfunction getDateGroup(dateStr: string): string {\n const date = new Date(dateStr);\n const now = new Date();\n const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());\n const yesterday = new Date(today.getTime() - 24 * 60 * 60 * 1000);\n\n if (date >= today) return 'Today';\n if (date >= yesterday) return 'Yesterday';\n return 'Earlier';\n}\n\nfunction groupByDate(items: Notification[]): { label: string; items: Notification[] }[] {\n const groups: { label: string; items: Notification[] }[] = [];\n const map = new Map<string, Notification[]>();\n const order = ['Today', 'Yesterday', 'Earlier'];\n\n for (const n of items) {\n const group = getDateGroup(n.createdAt);\n if (!map.has(group)) map.set(group, []);\n map.get(group)!.push(n);\n }\n\n for (const label of order) {\n const items = map.get(label);\n if (items && items.length > 0) {\n groups.push({ label, items });\n }\n }\n\n return groups;\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nexport function NotificationCenterPage() {\n const { navigateTo } = useKadaikodi();\n const [notifications, setNotifications] = useState<Notification[]>(initialNotifications);\n const [activeTab, setActiveTab] = useState<TabId>('all');\n const [searchQuery, setSearchQuery] = useState('');\n const [sortBy, setSortBy] = useState<SortOption>('recent');\n const [showSortMenu, setShowSortMenu] = useState(false);\n\n // ---------------------------------------------------------------------------\n // Derived counts\n // ---------------------------------------------------------------------------\n\n const unreadCount = useMemo(() => notifications.filter((n) => !n.isRead).length, [notifications]);\n\n const urgentCount = useMemo(\n () => notifications.filter((n) => n.priority === 'urgent').length,\n [notifications]\n );\n\n const todayCount = useMemo(\n () => notifications.filter((n) => getDateGroup(n.createdAt) === 'Today').length,\n [notifications]\n );\n\n const thisWeekCount = useMemo(() => {\n const weekAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000);\n return notifications.filter((n) => new Date(n.createdAt) >= weekAgo).length;\n }, [notifications]);\n\n const tabCounts = useMemo(() => {\n const counts: Record<TabId, number> = {\n all: 0,\n orders: 0,\n promotions: 0,\n system: 0,\n unread: 0,\n };\n for (const n of notifications) {\n counts.all++;\n if (!n.isRead) counts.unread++;\n if (n.type === 'order_update' || n.type === 'delivery') counts.orders++;\n if (n.type === 'promotion') counts.promotions++;\n if (n.type === 'system' || n.type === 'alert' || n.type === 'account') counts.system++;\n }\n return counts;\n }, [notifications]);\n\n // ---------------------------------------------------------------------------\n // Filtered & sorted list\n // ---------------------------------------------------------------------------\n\n const filteredNotifications = useMemo(() => {\n let list = [...notifications];\n\n // Tab filter\n switch (activeTab) {\n case 'orders':\n list = list.filter((n) => n.type === 'order_update' || n.type === 'delivery');\n break;\n case 'promotions':\n list = list.filter((n) => n.type === 'promotion');\n break;\n case 'system':\n list = list.filter(\n (n) => n.type === 'system' || n.type === 'alert' || n.type === 'account'\n );\n break;\n case 'unread':\n list = list.filter((n) => !n.isRead);\n break;\n }\n\n // Search filter\n if (searchQuery) {\n const q = searchQuery.toLowerCase();\n list = list.filter(\n (n) => n.title.toLowerCase().includes(q) || n.message.toLowerCase().includes(q)\n );\n }\n\n // Sort\n switch (sortBy) {\n case 'recent':\n list.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());\n break;\n case 'priority':\n list.sort((a, b) => priorityOrder[b.priority] - priorityOrder[a.priority]);\n break;\n case 'unread':\n list.sort((a, b) => (a.isRead === b.isRead ? 0 : a.isRead ? 1 : -1));\n break;\n }\n\n return list;\n }, [notifications, activeTab, searchQuery, sortBy]);\n\n // Grouped by date\n const grouped = useMemo(() => groupByDate(filteredNotifications), [filteredNotifications]);\n\n // ---------------------------------------------------------------------------\n // Actions\n // ---------------------------------------------------------------------------\n\n const markAsRead = useCallback((id: string) => {\n setNotifications((prev) => prev.map((n) => (n.id === id ? { ...n, isRead: true } : n)));\n }, []);\n\n const markAllAsRead = useCallback(() => {\n setNotifications((prev) => prev.map((n) => ({ ...n, isRead: true })));\n }, []);\n\n const deleteNotification = useCallback((id: string) => {\n setNotifications((prev) => prev.filter((n) => n.id !== id));\n }, []);\n\n const handleAction = useCallback(\n (notif: Notification) => {\n if (!notif.isRead) markAsRead(notif.id);\n if (notif.actionUrl) navigateTo(notif.actionUrl);\n },\n [markAsRead, navigateTo]\n );\n\n const clearAll = useCallback(() => {\n if (window.confirm('Are you sure you want to clear all notifications?')) {\n setNotifications([]);\n }\n }, []);\n\n // ---------------------------------------------------------------------------\n // Render\n // ---------------------------------------------------------------------------\n\n return (\n <PageLayout\n title=\"Notifications\"\n description={\n unreadCount > 0\n ? `${unreadCount} unread notification${unreadCount !== 1 ? 's' : ''}`\n : 'All caught up!'\n }\n actions={\n <div className=\"flex items-center gap-2\">\n {notifications.length > 0 && (\n <button\n type=\"button\"\n onClick={clearAll}\n className=\"flex items-center gap-1.5 rounded-lg border border-border-subtle px-3 py-2 text-sm font-medium text-text-secondary hover:text-text-primary hover:bg-accent transition-colors\"\n >\n <Trash2 className=\"h-4 w-4\" />\n <span className=\"hidden sm:inline\">Clear All</span>\n </button>\n )}\n {unreadCount > 0 && (\n <button\n type=\"button\"\n onClick={markAllAsRead}\n className=\"flex items-center gap-1.5 rounded-lg border border-border-subtle px-3 py-2 text-sm font-medium text-text-primary hover:bg-accent transition-colors\"\n >\n <CheckCheck className=\"h-4 w-4\" />\n Mark All Read\n </button>\n )}\n </div>\n }\n >\n <PagePurpose className=\"mb-6\">\n Your single inbox for everything happening on Kadaikodi — orders, payments, alerts and\n updates. Use this page to stay on top of what needs attention: filter by category, open a\n notification to jump straight to the relevant screen, and mark things read or clear them once\n handled so nothing important slips by.\n </PagePurpose>\n\n {/* ---- Stats Overview — the one emphasis zone for this page ---- */}\n <EmphasisPanel className=\"mb-6\">\n <h2 className=\"mb-4 text-base font-semibold text-text-primary\">At a Glance</h2>\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-5\">\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-3 text-center\">\n <p className=\"text-2xl font-bold text-text-primary\">{notifications.length}</p>\n <p className=\"text-xs text-text-secondary\">Total</p>\n </div>\n <div className=\"rounded-lg border border-border-focus/30 bg-[var(--color-accent-soft)] p-3 text-center\">\n <p className=\"text-2xl font-bold text-text-primary\">{unreadCount}</p>\n <p className=\"text-xs text-text-secondary\">Unread</p>\n </div>\n <div className=\"rounded-lg border border-status-error-text/30 bg-status-error-bg-subtle p-3 text-center\">\n <p className=\"text-2xl font-bold text-status-error-text\">{urgentCount}</p>\n <p className=\"text-xs text-text-secondary\">Urgent</p>\n </div>\n <div className=\"rounded-lg border border-status-success-text/30 bg-status-success-bg-subtle p-3 text-center\">\n <p className=\"text-2xl font-bold text-status-success-text\">{todayCount}</p>\n <p className=\"text-xs text-text-secondary\">Today</p>\n </div>\n <div className=\"rounded-lg border border-status-warning-text/30 bg-status-warning-bg-subtle p-3 text-center\">\n <p className=\"text-2xl font-bold text-status-warning-text\">{thisWeekCount}</p>\n <p className=\"text-xs text-text-secondary\">This Week</p>\n </div>\n </div>\n </EmphasisPanel>\n\n {/* ---- Tabs ---- */}\n <div className=\"flex items-center gap-2 mb-4 overflow-x-auto pb-1\">\n {tabs.map((tab) => {\n const TabIcon = tab.icon;\n return (\n <button\n key={tab.id}\n type=\"button\"\n onClick={() => setActiveTab(tab.id)}\n className={cn(\n 'flex items-center gap-1.5 whitespace-nowrap rounded-full border px-3 py-1.5 text-sm font-medium transition-colors',\n activeTab === tab.id\n ? 'border-primary bg-action-primary-bg/10 text-text-primary'\n : 'border-border-subtle text-text-secondary hover:text-text-primary hover:border-border-strong'\n )}\n >\n <TabIcon className=\"h-3.5 w-3.5\" />\n {tab.label}\n <span\n className={cn(\n 'inline-flex h-5 min-w-[20px] items-center justify-center rounded-full px-1 text-xs',\n activeTab === tab.id\n ? 'bg-action-primary-bg text-action-primary-text'\n : 'bg-bg-sunken text-text-secondary'\n )}\n >\n {tabCounts[tab.id]}\n </span>\n </button>\n );\n })}\n </div>\n\n {/* ---- Search & Sort ---- */}\n <div className=\"flex items-center gap-3 mb-6\">\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 notifications...\"\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.5 pl-10 pr-9 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n {searchQuery && (\n <button\n type=\"button\"\n onClick={() => setSearchQuery('')}\n className=\"absolute right-3 top-1/2 -translate-y-1/2 text-text-secondary hover:text-text-primary\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n )}\n </div>\n\n {/* Sort dropdown */}\n <div className=\"relative\">\n <button\n type=\"button\"\n onClick={() => setShowSortMenu(!showSortMenu)}\n className=\"flex items-center gap-1.5 rounded-lg border border-border-subtle px-3 py-2.5 text-sm font-medium text-text-primary hover:bg-accent transition-colors\"\n >\n <ArrowUpDown className=\"h-4 w-4\" />\n <span className=\"hidden sm:inline\">Sort</span>\n </button>\n {showSortMenu && (\n <>\n {/* Backdrop */}\n <div className=\"fixed inset-0 z-10\" onClick={() => setShowSortMenu(false)} />\n <div className=\"absolute right-0 top-full mt-1 z-20 w-44 rounded-lg border border-border-subtle bg-bg-surface shadow-lg py-1\">\n {(\n [\n { value: 'recent', label: 'Most Recent' },\n { value: 'priority', label: 'By Priority' },\n { value: 'unread', label: 'Unread First' },\n ] as const\n ).map((opt) => (\n <button\n key={opt.value}\n type=\"button\"\n onClick={() => {\n setSortBy(opt.value);\n setShowSortMenu(false);\n }}\n className={cn(\n 'w-full text-left px-3 py-2 text-sm transition-colors',\n sortBy === opt.value\n ? 'bg-action-primary-bg/10 text-text-primary font-medium'\n : 'text-text-secondary hover:bg-accent hover:text-text-primary'\n )}\n >\n {opt.label}\n </button>\n ))}\n </div>\n </>\n )}\n </div>\n </div>\n\n {/* ---- Notification List ---- */}\n {filteredNotifications.length === 0 ? (\n <EmptyState\n illustration={searchQuery ? 'empty-search' : 'empty-notifications'}\n icon={<Bell className=\"h-12 w-12\" />}\n title=\"No notifications\"\n description={\n searchQuery\n ? 'No notifications match your search. Try different keywords.'\n : activeTab === 'unread'\n ? \"You're all caught up! No unread notifications.\"\n : 'No notifications in this category yet.'\n }\n action={\n searchQuery ? (\n <button\n type=\"button\"\n onClick={() => setSearchQuery('')}\n className=\"rounded-lg border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-accent transition-colors\"\n >\n Clear Search\n </button>\n ) : activeTab !== 'all' ? (\n <button\n type=\"button\"\n onClick={() => setActiveTab('all')}\n className=\"rounded-lg border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-accent transition-colors\"\n >\n View All Notifications\n </button>\n ) : undefined\n }\n />\n ) : (\n <div className=\"space-y-6\">\n {grouped.map((group) => (\n <div key={group.label}>\n {/* Date group header */}\n <div className=\"flex items-center gap-3 mb-2\">\n <h3 className=\"text-xs font-semibold uppercase tracking-wider text-text-secondary\">\n {group.label}\n </h3>\n <div className=\"flex-1 border-t border-border-subtle\" />\n <span className=\"text-xs text-text-secondary\">\n {group.items.length} notification{group.items.length !== 1 ? 's' : ''}\n </span>\n </div>\n\n {/* Notification cards */}\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface divide-y divide-border overflow-hidden\">\n {group.items.map((notif) => {\n const config = typeConfig[notif.type] ?? typeConfig.system;\n const NotifIcon = config.icon;\n\n return (\n <div\n key={notif.id}\n className={cn(\n 'flex items-start gap-3 px-4 py-4 border-l-4 transition-colors',\n priorityBorderColors[notif.priority],\n !notif.isRead && 'bg-accent/30'\n )}\n >\n {/* Type icon */}\n <div\n className={cn(\n 'flex h-10 w-10 shrink-0 items-center justify-center rounded-full',\n config.bg\n )}\n >\n <NotifIcon className={cn('h-5 w-5', config.color)} />\n </div>\n\n {/* Content */}\n <div className=\"flex-1 min-w-0\">\n {/* Title row */}\n <div className=\"flex items-center gap-2 flex-wrap\">\n <h4\n className={cn(\n 'text-sm text-text-primary',\n !notif.isRead ? 'font-semibold' : 'font-medium'\n )}\n >\n {notif.title}\n </h4>\n {!notif.isRead && (\n <span className=\"h-2 w-2 rounded-full bg-action-primary-bg shrink-0\" />\n )}\n <span\n className={cn(\n 'inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium',\n priorityStyles[notif.priority]\n )}\n >\n {notif.priority}\n </span>\n </div>\n\n {/* Message */}\n <p className=\"mt-1 text-sm text-text-secondary leading-relaxed\">\n {notif.message}\n </p>\n\n {/* Metadata row */}\n <div className=\"mt-2 flex items-center gap-3 flex-wrap\">\n <span className=\"flex items-center gap-1 text-xs text-text-secondary\">\n <Clock className=\"h-3 w-3\" />\n {formatRelativeTime(notif.createdAt)}\n </span>\n <span\n className={cn(\n 'inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium',\n config.bg,\n config.color\n )}\n >\n {config.label}\n </span>\n {notif.metadata?.orderId && (\n <span className=\"text-xs text-text-secondary\">\n #{notif.metadata.orderId}\n </span>\n )}\n </div>\n\n {/* Action buttons row */}\n <div className=\"mt-3 flex items-center gap-2 flex-wrap\">\n {notif.actionUrl && (\n <button\n type=\"button\"\n onClick={() => handleAction(notif)}\n className=\"rounded-lg bg-action-primary-bg px-3 py-1.5 text-xs font-medium text-action-primary-text hover:bg-action-primary-bg/90 transition-colors\"\n >\n {notif.actionText ?? 'View'}\n </button>\n )}\n {!notif.isRead && (\n <button\n type=\"button\"\n onClick={() => markAsRead(notif.id)}\n title=\"Mark as read\"\n className=\"flex items-center gap-1 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 <Check className=\"h-3 w-3\" />\n Mark Read\n </button>\n )}\n <button\n type=\"button\"\n onClick={() => deleteNotification(notif.id)}\n title=\"Delete notification\"\n className=\"flex items-center gap-1 rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium text-status-error-text hover:bg-status-error-bg/10 transition-colors\"\n >\n <Trash2 className=\"h-3 w-3\" />\n Delete\n </button>\n </div>\n </div>\n\n {/* Read/unread indicator */}\n <div className=\"shrink-0 pt-1\">\n {notif.isRead ? (\n <MailOpen className=\"h-4 w-4 text-text-secondary/40\" />\n ) : (\n <Bell className=\"h-4 w-4 text-primary\" />\n )}\n </div>\n </div>\n );\n })}\n </div>\n </div>\n ))}\n </div>\n )}\n\n {/* ---- Footer summary ---- */}\n {filteredNotifications.length > 0 && (\n <div className=\"mt-6 flex items-center justify-between rounded-lg border border-border-subtle bg-bg-surface px-4 py-3\">\n <p className=\"text-sm text-text-secondary\">\n Showing {filteredNotifications.length} of {notifications.length} notifications\n </p>\n {activeTab !== 'all' && (\n <button\n type=\"button\"\n onClick={() => {\n setActiveTab('all');\n setSearchQuery('');\n }}\n className=\"flex items-center gap-1.5 text-sm font-medium text-primary hover:underline\"\n >\n <RefreshCw className=\"h-3.5 w-3.5\" />\n Show All\n </button>\n )}\n </div>\n )}\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|