@burdenoff/microfe-kadaikodi 2026.626.2 → 2026.704.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/kadaikodi/hooks/useKadaikodiApi.js +260 -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/AdminAnalyticsPage.js +341 -461
- package/dist/kadaikodi/pages/admin/AdminAnalyticsPage.js.map +1 -1
- package/dist/kadaikodi/pages/admin/AdminDashboard.js +115 -399
- package/dist/kadaikodi/pages/admin/AdminDashboard.js.map +1 -1
- package/dist/kadaikodi/pages/admin/AdminFinancialPage.js +140 -283
- package/dist/kadaikodi/pages/admin/AdminFinancialPage.js.map +1 -1
- package/dist/kadaikodi/pages/admin/AdminOrdersPage.js +282 -453
- package/dist/kadaikodi/pages/admin/AdminOrdersPage.js.map +1 -1
- package/dist/kadaikodi/pages/admin/AdminProfilePage.js +115 -242
- package/dist/kadaikodi/pages/admin/AdminProfilePage.js.map +1 -1
- package/dist/kadaikodi/pages/admin/AdminSettingsPage.js +2 -2
- package/dist/kadaikodi/pages/admin/AdminSettingsPage.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 +503 -627
- package/dist/kadaikodi/pages/cart-owner/AnalyticsDashboard.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/BusinessSettingsPage.js +339 -282
- package/dist/kadaikodi/pages/cart-owner/BusinessSettingsPage.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/CartOwnerDashboard.js +329 -432
- package/dist/kadaikodi/pages/cart-owner/CartOwnerDashboard.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/CartOwnerProfilePage.js +374 -384
- package/dist/kadaikodi/pages/cart-owner/CartOwnerProfilePage.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/CartServiceConfigPage.js +249 -208
- package/dist/kadaikodi/pages/cart-owner/CartServiceConfigPage.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/InventoryManagementPage.js +276 -279
- package/dist/kadaikodi/pages/cart-owner/InventoryManagementPage.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/OrderManagementPage.js +229 -447
- package/dist/kadaikodi/pages/cart-owner/OrderManagementPage.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/StaffManagementPage.js +171 -627
- package/dist/kadaikodi/pages/cart-owner/StaffManagementPage.js.map +1 -1
- package/dist/kadaikodi/pages/common/HelpSupportPage.js +331 -415
- package/dist/kadaikodi/pages/common/HelpSupportPage.js.map +1 -1
- package/dist/kadaikodi/pages/common/NotificationCenterPage.js +18 -670
- 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/CheckoutPage.js +4 -2
- package/dist/kadaikodi/pages/customer/CheckoutPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/CustomerDashboard.js +191 -369
- package/dist/kadaikodi/pages/customer/CustomerDashboard.js.map +1 -1
- package/dist/kadaikodi/pages/customer/CustomerProfilePage.js +233 -389
- package/dist/kadaikodi/pages/customer/CustomerProfilePage.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/OrderHistoryPage.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/PaymentMethodsPage.js +76 -118
- package/dist/kadaikodi/pages/customer/PaymentMethodsPage.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/customer/SavedAddressesPage.js +135 -213
- package/dist/kadaikodi/pages/customer/SavedAddressesPage.js.map +1 -1
- package/dist/kadaikodi/pages/investor/InvestmentDetailsPage.js +272 -774
- package/dist/kadaikodi/pages/investor/InvestmentDetailsPage.js.map +1 -1
- package/dist/kadaikodi/pages/investor/InvestmentOpportunitiesPage.js +258 -523
- package/dist/kadaikodi/pages/investor/InvestmentOpportunitiesPage.js.map +1 -1
- package/dist/kadaikodi/pages/investor/InvestorAnalyticsPage.js +112 -600
- package/dist/kadaikodi/pages/investor/InvestorAnalyticsPage.js.map +1 -1
- package/dist/kadaikodi/pages/investor/InvestorDashboard.js +128 -295
- package/dist/kadaikodi/pages/investor/InvestorDashboard.js.map +1 -1
- package/dist/kadaikodi/pages/investor/InvestorInvestmentsPage.js +205 -291
- package/dist/kadaikodi/pages/investor/InvestorInvestmentsPage.js.map +1 -1
- package/dist/kadaikodi/pages/investor/InvestorPortfolioPage.js +159 -500
- package/dist/kadaikodi/pages/investor/InvestorPortfolioPage.js.map +1 -1
- package/dist/kadaikodi/pages/investor/InvestorProfilePage.js +426 -514
- package/dist/kadaikodi/pages/investor/InvestorProfilePage.js.map +1 -1
- package/dist/kadaikodi/pages/worker/TaskDetailsPage.js +231 -225
- package/dist/kadaikodi/pages/worker/TaskDetailsPage.js.map +1 -1
- package/dist/kadaikodi/pages/worker/WorkerDashboard.js +197 -301
- package/dist/kadaikodi/pages/worker/WorkerDashboard.js.map +1 -1
- package/dist/kadaikodi/pages/worker/WorkerOrdersPage.js +247 -399
- package/dist/kadaikodi/pages/worker/WorkerOrdersPage.js.map +1 -1
- package/dist/kadaikodi/pages/worker/WorkerProfilePage.js +294 -327
- package/dist/kadaikodi/pages/worker/WorkerProfilePage.js.map +1 -1
- package/dist/kadaikodi/pages/worker/WorkerSchedulePage.js +179 -397
- 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":"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":";;;;;;;;;;AAsFA,IAAM,IAAuC;CAC3C;EACE,IAAI;EACJ,MAAM;EACN,OAAO;EACP,SACE;EACF,UAAU;EACV,QAAQ;EACR,4BAAW,IAAI,KAAK,KAAK,KAAK,GAAG,MAAS,IAAK,EAAC,aAAa;EAC7D,WAAW;EACX,YAAY;EACZ,UAAU;GAAE,SAAS;GAAW,QAAQ;GAAY;EACrD;CACD;EACE,IAAI;EACJ,MAAM;EACN,OAAO;EACP,SACE;EACF,UAAU;EACV,QAAQ;EACR,4BAAW,IAAI,KAAK,KAAK,KAAK,GAAG,OAAU,IAAK,EAAC,aAAa;EAC9D,UAAU;GAAE,SAAS;GAAW,QAAQ;GAAK;EAC9C;CACD;EACE,IAAI;EACJ,MAAM;EACN,OAAO;EACP,SACE;EACF,UAAU;EACV,QAAQ;EACR,4BAAW,IAAI,KAAK,KAAK,KAAK,GAAG,OAAc,IAAK,EAAC,aAAa;EAClE,WAAW;EACX,YAAY;EACZ,UAAU,EAAE,QAAQ,YAAY;EACjC;CACD;EACE,IAAI;EACJ,MAAM;EACN,OAAO;EACP,SACE;EACF,UAAU;EACV,QAAQ;EACR,4BAAW,IAAI,KAAK,KAAK,KAAK,GAAG,QAAc,IAAK,EAAC,aAAa;EAClE,WAAW;EACX,YAAY;EACb;CACD;EACE,IAAI;EACJ,MAAM;EACN,OAAO;EACP,SACE;EACF,UAAU;EACV,QAAQ;EACR,4BAAW,IAAI,KAAK,KAAK,KAAK,GAAG,MAAS,KAAK,IAAK,EAAC,aAAa;EAClE,WAAW;EACX,YAAY;EACb;CACD;EACE,IAAI;EACJ,MAAM;EACN,OAAO;EACP,SACE;EACF,UAAU;EACV,QAAQ;EACR,4BAAW,IAAI,KAAK,KAAK,KAAK,GAAG,OAAc,KAAK,IAAK,EAAC,aAAa;EACvE,WAAW;EACX,YAAY;EACZ,UAAU,EAAE,SAAS,WAAW;EACjC;CACD;EACE,IAAI;EACJ,MAAM;EACN,OAAO;EACP,SACE;EACF,UAAU;EACV,QAAQ;EACR,4BAAW,IAAI,KAAK,KAAK,KAAK,GAAG,OAAc,KAAK,IAAK,EAAC,aAAa;EACvE,WAAW;EACX,YAAY;EACZ,UAAU,EAAE,QAAQ,MAAM;EAC3B;CACD;EACE,IAAI;EACJ,MAAM;EACN,OAAO;EACP,SACE;EACF,UAAU;EACV,QAAQ;EACR,4BAAW,IAAI,KAAK,KAAK,KAAK,GAAG,MAAM,KAAK,KAAK,KAAK,IAAK,EAAC,aAAa;EACzE,UAAU,EAAE,SAAS,WAAW;EACjC;CACD;EACE,IAAI;EACJ,MAAM;EACN,OAAO;EACP,SACE;EACF,UAAU;EACV,QAAQ;EACR,4BAAW,IAAI,KAAK,KAAK,KAAK,GAAG,OAAc,KAAK,IAAK,EAAC,aAAa;EACvE,WAAW;EACX,YAAY;EACb;CACD;EACE,IAAI;EACJ,MAAM;EACN,OAAO;EACP,SACE;EACF,UAAU;EACV,QAAQ;EACR,4BAAW,IAAI,KAAK,KAAK,KAAK,GAAG,OAAc,KAAK,IAAK,EAAC,aAAa;EACvE,WAAW;EACX,YAAY;EACZ,UAAU,EAAE,QAAQ,cAAc;EACnC;CACD;EACE,IAAI;EACJ,MAAM;EACN,OAAO;EACP,SACE;EACF,UAAU;EACV,QAAQ;EACR,4BAAW,IAAI,KAAK,KAAK,KAAK,GAAG,OAAc,KAAK,IAAK,EAAC,aAAa;EACxE;CACD;EACE,IAAI;EACJ,MAAM;EACN,OAAO;EACP,SACE;EACF,UAAU;EACV,QAAQ;EACR,4BAAW,IAAI,KAAK,KAAK,KAAK,GAAG,OAAc,KAAK,IAAK,EAAC,aAAa;EACxE;CACD;EACE,IAAI;EACJ,MAAM;EACN,OAAO;EACP,SACE;EACF,UAAU;EACV,QAAQ;EACR,4BAAW,IAAI,KAAK,KAAK,KAAK,GAAG,OAAc,KAAK,IAAK,EAAC,aAAa;EACvE,WAAW;EACX,YAAY;EACb;CACD;EACE,IAAI;EACJ,MAAM;EACN,OAAO;EACP,SACE;EACF,UAAU;EACV,QAAQ;EACR,4BAAW,IAAI,KAAK,KAAK,KAAK,GAAG,QAAc,KAAK,IAAK,EAAC,aAAa;EACvE,UAAU;GAAE,SAAS;GAAW,QAAQ;GAAK;EAC9C;CACF,EAMK,IACJ;CACE,cAAc;EACZ,MAAM;EACN,OAAO;EACP,IAAI;EACJ,OAAO;EACR;CACD,SAAS;EACP,MAAM;EACN,OAAO;EACP,IAAI;EACJ,OAAO;EACR;CACD,WAAW;EACT,MAAM;EACN,OAAO;EACP,IAAI;EACJ,OAAO;EACR;CACD,QAAQ;EACN,MAAM;EACN,OAAO;EACP,IAAI;EACJ,OAAO;EACR;CACD,QAAQ;EACN,MAAM;EACN,OAAO;EACP,IAAI;EACJ,OAAO;EACR;CACD,OAAO;EACL,MAAM;EACN,OAAO;EACP,IAAI;EACJ,OAAO;EACR;CACD,YAAY;EACV,MAAM;EACN,OAAO;EACP,IAAI;EACJ,OAAO;EACR;CACD,OAAO;EACL,MAAM;EACN,OAAO;EACP,IAAI;EACJ,OAAO;EACR;CACD,UAAU;EACR,MAAM;EACN,OAAO;EACP,IAAI;EACJ,OAAO;EACR;CACD,SAAS;EACP,MAAM;EACN,OAAO;EACP,IAAI;EACJ,OAAO;EACR;CACF,EAMG,IAAuD;CAC3D,QAAQ;CACR,MAAM;CACN,QAAQ;CACR,KAAK;CACN,EAEK,IAA6D;CACjE,QAAQ;CACR,MAAM;CACN,QAAQ;CACR,KAAK;CACN,EAEK,IAAsD;CAC1D,QAAQ;CACR,MAAM;CACN,QAAQ;CACR,KAAK;CACN,EAMK,IAA0D;CAC9D;EAAE,IAAI;EAAO,OAAO;EAAO,MAAM;EAAO;CACxC;EAAE,IAAI;EAAU,OAAO;EAAU,MAAM;EAAa;CACpD;EAAE,IAAI;EAAc,OAAO;EAAc,MAAM;EAAW;CAC1D;EAAE,IAAI;EAAU,OAAO;EAAU,MAAM;EAAa;CACpD;EAAE,IAAI;EAAU,OAAO;EAAU,MAAM;EAAM;CAC9C;AAMD,SAAS,EAAa,GAAyB;CAC7C,IAAM,IAAO,IAAI,KAAK,EAAQ,EACxB,oBAAM,IAAI,MAAM,EAChB,IAAQ,IAAI,KAAK,EAAI,aAAa,EAAE,EAAI,UAAU,EAAE,EAAI,SAAS,CAAC,EAClE,oBAAY,IAAI,KAAK,EAAM,SAAS,GAAG,OAAU,KAAK,IAAK;AAIjE,QAFI,KAAQ,IAAc,UACtB,KAAQ,IAAkB,cACvB;;AAGT,SAAS,EAAY,GAAmE;CACtF,IAAM,IAAqD,EAAE,EACvD,oBAAM,IAAI,KAA6B,EACvC,IAAQ;EAAC;EAAS;EAAa;EAAU;AAE/C,MAAK,IAAM,KAAK,GAAO;EACrB,IAAM,IAAQ,EAAa,EAAE,UAAU;AAEvC,EADK,EAAI,IAAI,EAAM,IAAE,EAAI,IAAI,GAAO,EAAE,CAAC,EACvC,EAAI,IAAI,EAAM,CAAE,KAAK,EAAE;;AAGzB,MAAK,IAAM,KAAS,GAAO;EACzB,IAAM,IAAQ,EAAI,IAAI,EAAM;AAC5B,EAAI,KAAS,EAAM,SAAS,KAC1B,EAAO,KAAK;GAAE;GAAO;GAAO,CAAC;;AAIjC,QAAO;;AAOT,SAAgB,IAAyB;CACvC,IAAM,EAAE,kBAAe,GAAc,EAC/B,CAAC,GAAe,KAAoB,EAAyB,EAAqB,EAClF,CAAC,GAAW,KAAgB,EAAgB,MAAM,EAClD,CAAC,GAAa,KAAkB,EAAS,GAAG,EAC5C,CAAC,GAAQ,KAAa,EAAqB,SAAS,EACpD,CAAC,GAAc,KAAmB,EAAS,GAAM,EAMjD,IAAc,QAAc,EAAc,QAAQ,MAAM,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,EAAc,CAAC,EAE3F,IAAc,QACZ,EAAc,QAAQ,MAAM,EAAE,aAAa,SAAS,CAAC,QAC3D,CAAC,EAAc,CAChB,EAEK,IAAa,QACX,EAAc,QAAQ,MAAM,EAAa,EAAE,UAAU,KAAK,QAAQ,CAAC,QACzE,CAAC,EAAc,CAChB,EAEK,IAAgB,QAAc;EAClC,IAAM,oBAAU,IAAI,KAAK,KAAK,KAAK,GAAG,QAAc,KAAK,IAAK;AAC9D,SAAO,EAAc,QAAQ,MAAM,IAAI,KAAK,EAAE,UAAU,IAAI,EAAQ,CAAC;IACpE,CAAC,EAAc,CAAC,EAEb,IAAY,QAAc;EAC9B,IAAM,IAAgC;GACpC,KAAK;GACL,QAAQ;GACR,YAAY;GACZ,QAAQ;GACR,QAAQ;GACT;AACD,OAAK,IAAM,KAAK,EAKd,CAJA,EAAO,OACF,EAAE,UAAQ,EAAO,WAClB,EAAE,SAAS,kBAAkB,EAAE,SAAS,eAAY,EAAO,UAC3D,EAAE,SAAS,eAAa,EAAO,eAC/B,EAAE,SAAS,YAAY,EAAE,SAAS,WAAW,EAAE,SAAS,cAAW,EAAO;AAEhF,SAAO;IACN,CAAC,EAAc,CAAC,EAMb,IAAwB,QAAc;EAC1C,IAAI,IAAO,CAAC,GAAG,EAAc;AAG7B,UAAQ,GAAR;GACE,KAAK;AACH,QAAO,EAAK,QAAQ,MAAM,EAAE,SAAS,kBAAkB,EAAE,SAAS,WAAW;AAC7E;GACF,KAAK;AACH,QAAO,EAAK,QAAQ,MAAM,EAAE,SAAS,YAAY;AACjD;GACF,KAAK;AACH,QAAO,EAAK,QACT,MAAM,EAAE,SAAS,YAAY,EAAE,SAAS,WAAW,EAAE,SAAS,UAChE;AACD;GACF,KAAK;AACH,QAAO,EAAK,QAAQ,MAAM,CAAC,EAAE,OAAO;AACpC;;AAIJ,MAAI,GAAa;GACf,IAAM,IAAI,EAAY,aAAa;AACnC,OAAO,EAAK,QACT,MAAM,EAAE,MAAM,aAAa,CAAC,SAAS,EAAE,IAAI,EAAE,QAAQ,aAAa,CAAC,SAAS,EAAE,CAChF;;AAIH,UAAQ,GAAR;GACE,KAAK;AACH,MAAK,MAAM,GAAG,MAAM,IAAI,KAAK,EAAE,UAAU,CAAC,SAAS,GAAG,IAAI,KAAK,EAAE,UAAU,CAAC,SAAS,CAAC;AACtF;GACF,KAAK;AACH,MAAK,MAAM,GAAG,MAAM,EAAc,EAAE,YAAY,EAAc,EAAE,UAAU;AAC1E;GACF,KAAK;AACH,MAAK,MAAM,GAAG,MAAO,EAAE,WAAW,EAAE,SAAS,IAAI,EAAE,SAAS,IAAI,GAAI;AACpE;;AAGJ,SAAO;IACN;EAAC;EAAe;EAAW;EAAa;EAAO,CAAC,EAG7C,IAAU,QAAc,EAAY,EAAsB,EAAE,CAAC,EAAsB,CAAC,EAMpF,IAAa,GAAa,MAAe;AAC7C,KAAkB,MAAS,EAAK,KAAK,MAAO,EAAE,OAAO,IAAK;GAAE,GAAG;GAAG,QAAQ;GAAM,GAAG,EAAG,CAAC;IACtF,EAAE,CAAC,EAEA,IAAgB,QAAkB;AACtC,KAAkB,MAAS,EAAK,KAAK,OAAO;GAAE,GAAG;GAAG,QAAQ;GAAM,EAAE,CAAC;IACpE,EAAE,CAAC,EAEA,IAAqB,GAAa,MAAe;AACrD,KAAkB,MAAS,EAAK,QAAQ,MAAM,EAAE,OAAO,EAAG,CAAC;IAC1D,EAAE,CAAC,EAEA,IAAe,GAClB,MAAwB;AAEvB,EADK,EAAM,UAAQ,EAAW,EAAM,GAAG,EACnC,EAAM,aAAW,EAAW,EAAM,UAAU;IAElD,CAAC,GAAY,EAAW,CACzB,EAEK,IAAW,QAAkB;AACjC,EAAI,OAAO,QAAQ,oDAAoD,IACrE,EAAiB,EAAE,CAAC;IAErB,EAAE,CAAC;AAMN,QACE,kBAAC,GAAD;EACE,OAAM;EACN,aACE,IAAc,IACV,GAAG,EAAY,sBAAsB,MAAgB,IAAU,KAAN,QACzD;EAEN,SACE,kBAAC,OAAD;GAAK,WAAU;aAAf,CACG,EAAc,SAAS,KACtB,kBAAC,UAAD;IACE,MAAK;IACL,SAAS;IACT,WAAU;cAHZ,CAKE,kBAAC,GAAD,EAAQ,WAAU,WAAY,CAAA,EAC9B,kBAAC,QAAD;KAAM,WAAU;eAAmB;KAAgB,CAAA,CAC5C;OAEV,IAAc,KACb,kBAAC,UAAD;IACE,MAAK;IACL,SAAS;IACT,WAAU;cAHZ,CAKE,kBAAC,GAAD,EAAY,WAAU,WAAY,CAAA,EAAA,gBAE3B;MAEP;;YA7BV;GAgCE,kBAAC,GAAD;IAAa,WAAU;cAAO;IAKhB,CAAA;GAGd,kBAAC,GAAD;IAAe,WAAU;cAAzB,CACE,kBAAC,MAAD;KAAI,WAAU;eAAiD;KAAgB,CAAA,EAC/E,kBAAC,OAAD;KAAK,WAAU;eAAf;MACA,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,KAAD;QAAG,WAAU;kBAAwC,EAAc;QAAW,CAAA,EAC9E,kBAAC,KAAD;QAAG,WAAU;kBAA8B;QAAS,CAAA,CAChD;;MACN,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,KAAD;QAAG,WAAU;kBAAwC;QAAgB,CAAA,EACrE,kBAAC,KAAD;QAAG,WAAU;kBAA8B;QAAU,CAAA,CACjD;;MACN,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,KAAD;QAAG,WAAU;kBAA6C;QAAgB,CAAA,EAC1E,kBAAC,KAAD;QAAG,WAAU;kBAA8B;QAAU,CAAA,CACjD;;MACN,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,KAAD;QAAG,WAAU;kBAA+C;QAAe,CAAA,EAC3E,kBAAC,KAAD;QAAG,WAAU;kBAA8B;QAAS,CAAA,CAChD;;MACN,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,KAAD;QAAG,WAAU;kBAA+C;QAAkB,CAAA,EAC9E,kBAAC,KAAD;QAAG,WAAU;kBAA8B;QAAa,CAAA,CACpD;;MACA;OACQ;;GAGhB,kBAAC,OAAD;IAAK,WAAU;cACZ,EAAK,KAAK,MAAQ;KACjB,IAAM,IAAU,EAAI;AACpB,YACE,kBAAC,UAAD;MAEE,MAAK;MACL,eAAe,EAAa,EAAI,GAAG;MACnC,WAAW,EACT,qHACA,MAAc,EAAI,KACd,6DACA,qGACL;gBATH;OAWE,kBAAC,GAAD,EAAS,WAAU,eAAgB,CAAA;OAClC,EAAI;OACL,kBAAC,QAAD;QACE,WAAW,EACT,sFACA,MAAc,EAAI,KACd,kDACA,mCACL;kBAEA,EAAU,EAAI;QACV,CAAA;OACA;QAtBF,EAAI,GAsBF;MAEX;IACE,CAAA;GAGN,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD;KAAK,WAAU;eAAf;MACE,kBAAC,GAAD,EAAQ,WAAU,wEAAyE,CAAA;MAC3F,kBAAC,SAAD;OACE,MAAK;OACL,aAAY;OACZ,OAAO;OACP,WAAW,MAAM,EAAe,EAAE,OAAO,MAAM;OAC/C,WAAU;OACV,CAAA;MACD,KACC,kBAAC,UAAD;OACE,MAAK;OACL,eAAe,EAAe,GAAG;OACjC,WAAU;iBAEV,kBAAC,GAAD,EAAG,WAAU,WAAY,CAAA;OAClB,CAAA;MAEP;QAGN,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,UAAD;MACE,MAAK;MACL,eAAe,EAAgB,CAAC,EAAa;MAC7C,WAAU;gBAHZ,CAKE,kBAAC,GAAD,EAAa,WAAU,WAAY,CAAA,EACnC,kBAAC,QAAD;OAAM,WAAU;iBAAmB;OAAW,CAAA,CACvC;SACR,KACC,kBAAA,GAAA,EAAA,UAAA,CAEE,kBAAC,OAAD;MAAK,WAAU;MAAqB,eAAe,EAAgB,GAAM;MAAI,CAAA,EAC7E,kBAAC,OAAD;MAAK,WAAU;gBAEX;OACE;QAAE,OAAO;QAAU,OAAO;QAAe;OACzC;QAAE,OAAO;QAAY,OAAO;QAAe;OAC3C;QAAE,OAAO;QAAU,OAAO;QAAgB;OAC3C,CACD,KAAK,MACL,kBAAC,UAAD;OAEE,MAAK;OACL,eAAe;AAEb,QADA,EAAU,EAAI,MAAM,EACpB,EAAgB,GAAM;;OAExB,WAAW,EACT,wDACA,MAAW,EAAI,QACX,0DACA,8DACL;iBAEA,EAAI;OACE,EAdF,EAAI,MAcF,CACT;MACE,CAAA,CACL,EAAA,CAAA,CAED;OACF;;GAGL,EAAsB,WAAW,IAChC,kBAAC,GAAD;IACE,cAAc,IAAc,iBAAiB;IAC7C,MAAM,kBAAC,GAAD,EAAM,WAAU,aAAc,CAAA;IACpC,OAAM;IACN,aACE,IACI,gEACA,MAAc,WACZ,mDACA;IAER,QACE,IACE,kBAAC,UAAD;KACE,MAAK;KACL,eAAe,EAAe,GAAG;KACjC,WAAU;eACX;KAEQ,CAAA,GACP,MAAc,QAQd,KAAA,IAPF,kBAAC,UAAD;KACE,MAAK;KACL,eAAe,EAAa,MAAM;KAClC,WAAU;eACX;KAEQ,CAAA;IAGb,CAAA,GAEF,kBAAC,OAAD;IAAK,WAAU;cACZ,EAAQ,KAAK,MACZ,kBAAC,OAAD,EAAA,UAAA,CAEE,kBAAC,OAAD;KAAK,WAAU;eAAf;MACE,kBAAC,MAAD;OAAI,WAAU;iBACX,EAAM;OACJ,CAAA;MACL,kBAAC,OAAD,EAAK,WAAU,wCAAyC,CAAA;MACxD,kBAAC,QAAD;OAAM,WAAU;iBAAhB;QACG,EAAM,MAAM;QAAO;QAAc,EAAM,MAAM,WAAW,IAAU,KAAN;QACxD;;MACH;QAGN,kBAAC,OAAD;KAAK,WAAU;eACZ,EAAM,MAAM,KAAK,MAAU;MAC1B,IAAM,IAAS,EAAW,EAAM,SAAS,EAAW,QAC9C,IAAY,EAAO;AAEzB,aACE,kBAAC,OAAD;OAEE,WAAW,EACT,iEACA,EAAqB,EAAM,WAC3B,CAAC,EAAM,UAAU,eAClB;iBANH;QASE,kBAAC,OAAD;SACE,WAAW,EACT,oEACA,EAAO,GACR;mBAED,kBAAC,GAAD,EAAW,WAAW,EAAG,WAAW,EAAO,MAAM,EAAI,CAAA;SACjD,CAAA;QAGN,kBAAC,OAAD;SAAK,WAAU;mBAAf;UAEE,kBAAC,OAAD;WAAK,WAAU;qBAAf;YACE,kBAAC,MAAD;aACE,WAAW,EACT,6BACC,EAAM,SAA2B,gBAAlB,gBACjB;uBAEA,EAAM;aACJ,CAAA;YACJ,CAAC,EAAM,UACN,kBAAC,QAAD,EAAM,WAAU,sDAAuD,CAAA;YAEzE,kBAAC,QAAD;aACE,WAAW,EACT,yEACA,EAAe,EAAM,UACtB;uBAEA,EAAM;aACF,CAAA;YACH;;UAGN,kBAAC,KAAD;WAAG,WAAU;qBACV,EAAM;WACL,CAAA;UAGJ,kBAAC,OAAD;WAAK,WAAU;qBAAf;YACE,kBAAC,QAAD;aAAM,WAAU;uBAAhB,CACE,kBAAC,GAAD,EAAO,WAAU,WAAY,CAAA,EAC5B,EAAmB,EAAM,UAAU,CAC/B;;YACP,kBAAC,QAAD;aACE,WAAW,EACT,yEACA,EAAO,IACP,EAAO,MACR;uBAEA,EAAO;aACH,CAAA;YACN,EAAM,UAAU,WACf,kBAAC,QAAD;aAAM,WAAU;uBAAhB,CAA8C,KAC1C,EAAM,SAAS,QACZ;;YAEL;;UAGN,kBAAC,OAAD;WAAK,WAAU;qBAAf;YACG,EAAM,aACL,kBAAC,UAAD;aACE,MAAK;aACL,eAAe,EAAa,EAAM;aAClC,WAAU;uBAET,EAAM,cAAc;aACd,CAAA;YAEV,CAAC,EAAM,UACN,kBAAC,UAAD;aACE,MAAK;aACL,eAAe,EAAW,EAAM,GAAG;aACnC,OAAM;aACN,WAAU;uBAJZ,CAME,kBAAC,GAAD,EAAO,WAAU,WAAY,CAAA,EAAA,YAEtB;;YAEX,kBAAC,UAAD;aACE,MAAK;aACL,eAAe,EAAmB,EAAM,GAAG;aAC3C,OAAM;aACN,WAAU;uBAJZ,CAME,kBAAC,GAAD,EAAQ,WAAU,WAAY,CAAA,EAAA,SAEvB;;YACL;;UACF;;QAGN,kBAAC,OAAD;SAAK,WAAU;mBACZ,EAAM,SACL,kBAAC,GAAD,EAAU,WAAU,kCAAmC,CAAA,GAEvD,kBAAC,GAAD,EAAM,WAAU,wBAAyB,CAAA;SAEvC,CAAA;QACF;SA/GC,EAAM,GA+GP;OAER;KACE,CAAA,CACF,EAAA,EAvII,EAAM,MAuIV,CACN;IACE,CAAA;GAIP,EAAsB,SAAS,KAC9B,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,KAAD;KAAG,WAAU;eAAb;MAA2C;MAChC,EAAsB;MAAO;MAAK,EAAc;MAAO;MAC9D;QACH,MAAc,SACb,kBAAC,UAAD;KACE,MAAK;KACL,eAAe;AAEb,MADA,EAAa,MAAM,EACnB,EAAe,GAAG;;KAEpB,WAAU;eANZ,CAQE,kBAAC,GAAD,EAAW,WAAU,eAAgB,CAAA,EAAA,WAE9B;OAEP;;GAEG"}
|
|
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 * Central inbox for Kadaikodi alerts and updates. Notifications are not yet\n * wired to a kadaikodi backend for this pre-launch product, so this page shows\n * an honest empty state rather than fabricated activity.\n */\n\nimport { Bell } from 'lucide-react';\nimport { PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { EmptyState } from '../../components/EmptyState';\n\nexport function NotificationCenterPage() {\n return (\n <PageLayout\n title=\"Notifications\"\n description=\"Your alerts and updates, all in one place\"\n >\n <PagePurpose className=\"mb-6\">\n Your single inbox for everything happening on Kadaikodi — orders, payments, alerts and\n updates. When notifications are enabled for your account they will appear here, so you can\n stay on top of what needs attention and jump straight to the relevant screen.\n </PagePurpose>\n\n <EmptyState\n illustration=\"empty-notifications\"\n icon={<Bell className=\"h-12 w-12\" />}\n title=\"No notifications yet\"\n description=\"Notifications aren't available for this account yet. As Kadaikodi rolls out, your order, payment and account alerts will show up here.\"\n />\n </PageLayout>\n );\n}\n"],"mappings":";;;;;;AAcA,SAAgB,IAAyB;AACvC,QACE,kBAAC,GAAD;EACE,OAAM;EACN,aAAY;YAFd,CAIE,kBAAC,GAAD;GAAa,WAAU;aAAO;GAIhB,CAAA,EAEd,kBAAC,GAAD;GACE,cAAa;GACb,MAAM,kBAAC,GAAD,EAAM,WAAU,aAAc,CAAA;GACpC,OAAM;GACN,aAAY;GACZ,CAAA,CACS"}
|
|
@@ -9,14 +9,14 @@ import { EmphasisPanel as P, NextSteps as F, PagePurpose as I } from "@burdenoff
|
|
|
9
9
|
//#region src/kadaikodi/pages/common/SettingsPage.tsx
|
|
10
10
|
var L = {
|
|
11
11
|
profile: {
|
|
12
|
-
firstName: "
|
|
13
|
-
lastName: "
|
|
14
|
-
email: "
|
|
15
|
-
phone: "
|
|
16
|
-
bio: "
|
|
17
|
-
dateOfBirth: "
|
|
18
|
-
gender: "
|
|
19
|
-
profilePicture: "
|
|
12
|
+
firstName: "",
|
|
13
|
+
lastName: "",
|
|
14
|
+
email: "",
|
|
15
|
+
phone: "",
|
|
16
|
+
bio: "",
|
|
17
|
+
dateOfBirth: "",
|
|
18
|
+
gender: "",
|
|
19
|
+
profilePicture: ""
|
|
20
20
|
},
|
|
21
21
|
preferences: {
|
|
22
22
|
theme: "system",
|
|
@@ -37,32 +37,7 @@ var L = {
|
|
|
37
37
|
twoFactorEnabled: !1,
|
|
38
38
|
loginAlerts: !0,
|
|
39
39
|
sessionTimeout: "30",
|
|
40
|
-
trustedDevices: [
|
|
41
|
-
{
|
|
42
|
-
id: "dev-1",
|
|
43
|
-
name: "MacBook Pro",
|
|
44
|
-
browser: "Chrome 126.0",
|
|
45
|
-
os: "macOS Sonoma",
|
|
46
|
-
lastActive: "2024-06-24T09:30:00Z",
|
|
47
|
-
isCurrent: !0
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
id: "dev-2",
|
|
51
|
-
name: "iPhone 15",
|
|
52
|
-
browser: "Safari Mobile",
|
|
53
|
-
os: "iOS 17.5",
|
|
54
|
-
lastActive: "2024-06-23T18:45:00Z",
|
|
55
|
-
isCurrent: !1
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
id: "dev-3",
|
|
59
|
-
name: "Samsung Galaxy S24",
|
|
60
|
-
browser: "Chrome Mobile",
|
|
61
|
-
os: "Android 14",
|
|
62
|
-
lastActive: "2024-06-20T12:00:00Z",
|
|
63
|
-
isCurrent: !1
|
|
64
|
-
}
|
|
65
|
-
]
|
|
40
|
+
trustedDevices: []
|
|
66
41
|
},
|
|
67
42
|
privacy: {
|
|
68
43
|
profileVisibility: "private",
|
|
@@ -75,17 +50,13 @@ var L = {
|
|
|
75
50
|
activityHistory: !0
|
|
76
51
|
},
|
|
77
52
|
billing: {
|
|
78
|
-
paymentMethod:
|
|
79
|
-
type: "card",
|
|
80
|
-
last4: "4532",
|
|
81
|
-
provider: "Visa"
|
|
82
|
-
},
|
|
53
|
+
paymentMethod: null,
|
|
83
54
|
autoRecharge: !1,
|
|
84
55
|
autoRechargeAmount: "1000",
|
|
85
|
-
invoiceEmail: "
|
|
86
|
-
gstNumber: "
|
|
56
|
+
invoiceEmail: "",
|
|
57
|
+
gstNumber: "",
|
|
87
58
|
companyName: "",
|
|
88
|
-
billingAddress: "
|
|
59
|
+
billingAddress: ""
|
|
89
60
|
}
|
|
90
61
|
}, R = [
|
|
91
62
|
{
|
|
@@ -127,8 +98,22 @@ function z({ checked: e, onChange: n, label: r }) {
|
|
|
127
98
|
}
|
|
128
99
|
function B() {
|
|
129
100
|
let { currentUser: T } = e(), { t: E } = o(), [A, B] = a("profile"), [V, H] = a(() => {
|
|
130
|
-
let e =
|
|
131
|
-
return
|
|
101
|
+
let e = T?.firstName ?? T?.name?.split(" ")[0] ?? "", t = T?.lastName ?? T?.name?.split(" ").slice(1).join(" ") ?? "", n = T?.email ?? "";
|
|
102
|
+
return {
|
|
103
|
+
...L,
|
|
104
|
+
profile: {
|
|
105
|
+
...L.profile,
|
|
106
|
+
firstName: e,
|
|
107
|
+
lastName: t,
|
|
108
|
+
email: n,
|
|
109
|
+
phone: T?.phone ?? "",
|
|
110
|
+
profilePicture: T?.avatar ?? T?.profilePicture ?? ""
|
|
111
|
+
},
|
|
112
|
+
billing: {
|
|
113
|
+
...L.billing,
|
|
114
|
+
invoiceEmail: n
|
|
115
|
+
}
|
|
116
|
+
};
|
|
132
117
|
}), [U, W] = a(!1), [G, K] = a(!1), [q, J] = a(""), Y = r((e, t) => {
|
|
133
118
|
let n = E(e);
|
|
134
119
|
return n === e ? t : n;
|
|
@@ -289,10 +274,13 @@ function B() {
|
|
|
289
274
|
className: "flex items-center gap-4",
|
|
290
275
|
children: [/* @__PURE__ */ N("div", {
|
|
291
276
|
className: "relative",
|
|
292
|
-
children: [/* @__PURE__ */ M("img", {
|
|
277
|
+
children: [V.profile.profilePicture ? /* @__PURE__ */ M("img", {
|
|
293
278
|
src: V.profile.profilePicture,
|
|
294
279
|
alt: "Profile",
|
|
295
280
|
className: "h-20 w-20 rounded-full object-cover border border-border-subtle"
|
|
281
|
+
}) : /* @__PURE__ */ M("div", {
|
|
282
|
+
className: "flex h-20 w-20 items-center justify-center rounded-full border border-border-subtle bg-bg-sunken text-lg font-semibold text-text-secondary",
|
|
283
|
+
children: ((V.profile.firstName[0] ?? "") + (V.profile.lastName[0] ?? "")).toUpperCase() || (V.profile.email[0] ?? "?").toUpperCase()
|
|
296
284
|
}), /* @__PURE__ */ M("button", {
|
|
297
285
|
type: "button",
|
|
298
286
|
onClick: () => alert("Photo upload coming soon"),
|
|
@@ -523,7 +511,7 @@ function B() {
|
|
|
523
511
|
Icon: b
|
|
524
512
|
}
|
|
525
513
|
].map(({ value: e, label: n, Icon: r }) => /* @__PURE__ */ N("label", {
|
|
526
|
-
className: t("flex items-center gap-2 rounded-lg border px-4 py-2.5 text-sm font-medium cursor-pointer transition-colors", V.preferences.theme === e ? "border-primary bg-action-primary-bg/10 text-text-primary" : "border-border-subtle text-text-secondary hover:border-
|
|
514
|
+
className: t("flex items-center gap-2 rounded-lg border px-4 py-2.5 text-sm font-medium cursor-pointer transition-colors", V.preferences.theme === e ? "border-primary bg-action-primary-bg/10 text-text-primary" : "border-border-subtle text-text-secondary hover:border-border-strong hover:text-text-primary"),
|
|
527
515
|
children: [
|
|
528
516
|
/* @__PURE__ */ M("input", {
|
|
529
517
|
type: "radio",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SettingsPage.js","names":[],"sources":["../../../../src/kadaikodi/pages/common/SettingsPage.tsx"],"sourcesContent":["/**\n * Settings Page\n * @module kadaikodi/pages/common\n *\n * Full-featured settings with 5 tabs: Profile, Preferences, Security,\n * Privacy, and Billing. Form validation, save state, sidebar navigation.\n */\n\nimport { useState, useCallback, useMemo } from 'react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n User,\n Settings,\n Sun,\n Moon,\n Monitor,\n Globe,\n Bell,\n Shield,\n Eye,\n EyeOff,\n Save,\n RotateCcw,\n Lock,\n Smartphone,\n Laptop,\n LogOut,\n Trash2,\n CreditCard,\n Receipt,\n Building2,\n MapPin,\n Camera,\n AlertTriangle,\n CheckCircle2,\n Loader2,\n} from 'lucide-react';\nimport { EmphasisPanel, PagePurpose, NextSteps } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { useKadaikodi } from '../../context/KadaikodiContext';\nimport { cn } from '../../utils/cn';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype ThemeOption = 'light' | 'dark' | 'system';\ntype LanguageOption = 'en' | 'ta' | 'hi' | 'kn' | 'te' | 'ml';\ntype TabId = 'profile' | 'preferences' | 'security' | 'privacy' | 'billing';\n\ninterface TrustedDevice {\n id: string;\n name: string;\n browser: string;\n os: string;\n lastActive: string;\n isCurrent: boolean;\n}\n\ninterface UserSettings {\n profile: {\n firstName: string;\n lastName: string;\n email: string;\n phone: string;\n bio: string;\n dateOfBirth: string;\n gender: string;\n profilePicture: string;\n };\n preferences: {\n theme: ThemeOption;\n language: LanguageOption;\n timezone: string;\n currency: string;\n notifications: {\n email: boolean;\n sms: boolean;\n push: boolean;\n orderUpdates: boolean;\n promotions: boolean;\n newsletters: boolean;\n security: boolean;\n };\n };\n security: {\n twoFactorEnabled: boolean;\n loginAlerts: boolean;\n sessionTimeout: string;\n trustedDevices: TrustedDevice[];\n };\n privacy: {\n profileVisibility: 'public' | 'private' | 'friends';\n dataSharing: {\n analytics: boolean;\n marketing: boolean;\n thirdParty: boolean;\n };\n locationTracking: boolean;\n activityHistory: boolean;\n };\n billing: {\n paymentMethod: { type: string; last4: string; provider: string } | null;\n autoRecharge: boolean;\n autoRechargeAmount: string;\n invoiceEmail: string;\n gstNumber: string;\n companyName: string;\n billingAddress: string;\n };\n}\n\n// ---------------------------------------------------------------------------\n// Defaults\n// ---------------------------------------------------------------------------\n\nconst defaultSettings: UserSettings = {\n profile: {\n firstName: 'Priya',\n lastName: 'Customer',\n email: 'customer@burdenoff.com',\n phone: '+91 98765 43220',\n bio: 'Food enthusiast and tech lover. Always exploring new services and experiences in Bangalore.',\n dateOfBirth: '1992-08-15',\n gender: 'female',\n profilePicture: 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=200',\n },\n preferences: {\n theme: 'system',\n language: 'en',\n timezone: 'Asia/Kolkata',\n currency: 'INR',\n notifications: {\n email: true,\n sms: true,\n push: true,\n orderUpdates: true,\n promotions: false,\n newsletters: false,\n security: true,\n },\n },\n security: {\n twoFactorEnabled: false,\n loginAlerts: true,\n sessionTimeout: '30',\n trustedDevices: [\n {\n id: 'dev-1',\n name: 'MacBook Pro',\n browser: 'Chrome 126.0',\n os: 'macOS Sonoma',\n lastActive: '2024-06-24T09:30:00Z',\n isCurrent: true,\n },\n {\n id: 'dev-2',\n name: 'iPhone 15',\n browser: 'Safari Mobile',\n os: 'iOS 17.5',\n lastActive: '2024-06-23T18:45:00Z',\n isCurrent: false,\n },\n {\n id: 'dev-3',\n name: 'Samsung Galaxy S24',\n browser: 'Chrome Mobile',\n os: 'Android 14',\n lastActive: '2024-06-20T12:00:00Z',\n isCurrent: false,\n },\n ],\n },\n privacy: {\n profileVisibility: 'private',\n dataSharing: {\n analytics: true,\n marketing: false,\n thirdParty: false,\n },\n locationTracking: true,\n activityHistory: true,\n },\n billing: {\n paymentMethod: { type: 'card', last4: '4532', provider: 'Visa' },\n autoRecharge: false,\n autoRechargeAmount: '1000',\n invoiceEmail: 'customer@burdenoff.com',\n gstNumber: '29ABCDE1234F1Z5',\n companyName: '',\n billingAddress: '123 Tech Park, Koramangala, Bangalore 560034',\n },\n};\n\n// ---------------------------------------------------------------------------\n// Tab config\n// ---------------------------------------------------------------------------\n\nconst tabConfig: { id: TabId; label: string; icon: typeof User }[] = [\n { id: 'profile', label: 'Profile', icon: User },\n { id: 'preferences', label: 'Preferences', icon: Settings },\n { id: 'security', label: 'Security', icon: Shield },\n { id: 'privacy', label: 'Privacy', icon: Eye },\n { id: 'billing', label: 'Billing', icon: CreditCard },\n];\n\n// ---------------------------------------------------------------------------\n// Toggle Switch component (inline)\n// ---------------------------------------------------------------------------\n\nfunction ToggleSwitch({\n checked,\n onChange,\n label,\n}: {\n checked: boolean;\n onChange: (val: boolean) => void;\n label?: string;\n}) {\n return (\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked={checked}\n aria-label={label}\n onClick={() => onChange(!checked)}\n className={cn(\n 'relative inline-flex h-6 w-11 items-center rounded-full transition-colors shrink-0',\n checked ? 'bg-action-primary-bg' : 'bg-bg-sunken'\n )}\n >\n <span\n className={cn(\n 'inline-block h-4 w-4 transform rounded-full bg-white transition-transform',\n checked ? 'translate-x-6' : 'translate-x-1'\n )}\n />\n </button>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nexport function SettingsPage() {\n const { currentUser } = useKadaikodi();\n const { t: translate } = useI18n();\n const [activeTab, setActiveTab] = useState<TabId>('profile');\n const [settings, setSettings] = useState<UserSettings>(() => {\n const s = { ...defaultSettings };\n if (currentUser?.firstName) s.profile.firstName = currentUser.firstName;\n if (currentUser?.lastName) s.profile.lastName = currentUser.lastName;\n if (currentUser?.email) s.profile.email = currentUser.email;\n return s;\n });\n const [hasChanges, setHasChanges] = useState(false);\n const [saving, setSaving] = useState(false);\n const [saveMessage, setSaveMessage] = useState('');\n const t = useCallback(\n (key: string, fallback: string): string => {\n const value = translate(key);\n return value === key ? fallback : value;\n },\n [translate]\n );\n const localizedTabConfig = useMemo(\n () =>\n tabConfig.map((tab) => ({\n ...tab,\n label:\n tab.id === 'profile'\n ? t('kadaikodi.settings.tabs.profile', 'Profile')\n : tab.id === 'preferences'\n ? t('kadaikodi.settings.tabs.preferences', 'Preferences')\n : tab.id === 'security'\n ? t('kadaikodi.settings.tabs.security', 'Security')\n : tab.id === 'privacy'\n ? t('kadaikodi.settings.tabs.privacy', 'Privacy')\n : t('kadaikodi.settings.tabs.billing', 'Billing'),\n })),\n [t]\n );\n\n // Deep update helper\n const update = useCallback(\n <S extends keyof UserSettings, F extends keyof UserSettings[S]>(\n section: S,\n field: F,\n value: UserSettings[S][F]\n ) => {\n setSettings((prev) => ({\n ...prev,\n [section]: { ...prev[section], [field]: value },\n }));\n setHasChanges(true);\n setSaveMessage('');\n },\n []\n );\n\n const updateNested = useCallback(\n (section: keyof UserSettings, sub: string, field: string, value: boolean | string) => {\n setSettings((prev) => ({\n ...prev,\n [section]: {\n ...prev[section],\n [sub]: {\n ...((prev[section] as Record<string, unknown>)[sub] as Record<string, unknown>),\n [field]: value,\n },\n },\n }));\n setHasChanges(true);\n setSaveMessage('');\n },\n []\n );\n\n const resetSettings = useCallback(() => {\n setSettings(defaultSettings);\n setHasChanges(false);\n setSaveMessage('');\n }, []);\n\n const saveSettings = useCallback(async () => {\n // Basic validation\n if (!settings.profile.firstName.trim() || !settings.profile.lastName.trim()) {\n setSaveMessage(\n t('kadaikodi.settings.validation.nameRequired', 'First name and last name are required.')\n );\n setActiveTab('profile');\n return;\n }\n if (!settings.profile.email.trim() || !settings.profile.email.includes('@')) {\n setSaveMessage(\n t('kadaikodi.settings.validation.emailRequired', 'A valid email address is required.')\n );\n setActiveTab('profile');\n return;\n }\n\n setSaving(true);\n setSaveMessage('');\n // Simulate API\n await new Promise((r) => setTimeout(r, 1200));\n setSaving(false);\n setHasChanges(false);\n setSaveMessage(t('kadaikodi.settings.saveSuccess', 'Settings saved successfully!'));\n setTimeout(() => setSaveMessage(''), 3000);\n }, [settings, t]);\n\n const removeDevice = useCallback((id: string) => {\n setSettings((prev) => ({\n ...prev,\n security: {\n ...prev.security,\n trustedDevices: prev.security.trustedDevices.filter((d) => d.id !== id),\n },\n }));\n setHasChanges(true);\n }, []);\n\n const logoutAllDevices = useCallback(() => {\n setSettings((prev) => ({\n ...prev,\n security: {\n ...prev.security,\n trustedDevices: prev.security.trustedDevices.filter((d) => d.isCurrent),\n },\n }));\n setHasChanges(true);\n }, []);\n\n const handleDeleteAccount = useCallback(() => {\n if (\n window.confirm(\n t(\n 'kadaikodi.settings.deleteConfirm',\n 'Are you sure you want to delete your account? This action cannot be undone.'\n )\n )\n ) {\n alert(\n t(\n 'kadaikodi.settings.deleteSubmitted',\n 'Account deletion request submitted. You will receive a confirmation email.'\n )\n );\n }\n }, [t]);\n\n // ---- Profile Tab ----\n const renderProfile = () => (\n <div className=\"space-y-6\">\n <h3 className=\"text-base font-semibold text-text-primary\">Personal Information</h3>\n\n {/* Profile Picture */}\n <div className=\"flex items-center gap-4\">\n <div className=\"relative\">\n <img\n src={settings.profile.profilePicture}\n alt=\"Profile\"\n className=\"h-20 w-20 rounded-full object-cover border border-border-subtle\"\n />\n <button\n type=\"button\"\n onClick={() => alert('Photo upload coming soon')}\n className=\"absolute -bottom-1 -right-1 flex h-7 w-7 items-center justify-center rounded-full bg-action-primary-bg text-action-primary-text shadow-sm hover:bg-action-primary-bg/90\"\n >\n <Camera className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n <div>\n <p className=\"text-sm font-medium text-text-primary\">Profile Picture</p>\n <p className=\"text-xs text-text-secondary\">Upload a new photo (JPG, PNG, max 2MB)</p>\n </div>\n </div>\n\n {/* Name */}\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">First Name *</label>\n <input\n type=\"text\"\n value={settings.profile.firstName}\n onChange={(e) => update('profile', 'firstName', e.target.value)}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface py-2 px-3 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">Last Name *</label>\n <input\n type=\"text\"\n value={settings.profile.lastName}\n onChange={(e) => update('profile', 'lastName', e.target.value)}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface py-2 px-3 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n </div>\n </div>\n\n {/* Email & Phone */}\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">\n Email Address *\n </label>\n <input\n type=\"email\"\n value={settings.profile.email}\n onChange={(e) => update('profile', 'email', e.target.value)}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface py-2 px-3 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">Phone Number</label>\n <input\n type=\"tel\"\n value={settings.profile.phone}\n onChange={(e) => update('profile', 'phone', e.target.value)}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface py-2 px-3 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n </div>\n </div>\n\n {/* Bio */}\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">Bio</label>\n <textarea\n rows={3}\n value={settings.profile.bio}\n onChange={(e) => update('profile', 'bio', e.target.value)}\n placeholder=\"Tell us about yourself...\"\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface py-2 px-3 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] resize-none\"\n />\n </div>\n\n {/* DOB & Gender */}\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">\n Date of Birth\n </label>\n <input\n type=\"date\"\n value={settings.profile.dateOfBirth}\n onChange={(e) => update('profile', 'dateOfBirth', e.target.value)}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface py-2 px-3 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">Gender</label>\n <select\n value={settings.profile.gender}\n onChange={(e) => update('profile', 'gender', e.target.value)}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface py-2 px-3 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n <option value=\"\">Select gender</option>\n <option value=\"male\">Male</option>\n <option value=\"female\">Female</option>\n <option value=\"other\">Other</option>\n <option value=\"prefer-not-to-say\">Prefer not to say</option>\n </select>\n </div>\n </div>\n </div>\n );\n\n // ---- Preferences Tab ----\n const renderPreferences = () => (\n <div className=\"space-y-6\">\n <h3 className=\"text-base font-semibold text-text-primary\">App Preferences</h3>\n\n {/* Language, Timezone, Currency */}\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-3\">\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">\n <span className=\"flex items-center gap-1.5\">\n <Globe className=\"h-4 w-4 text-text-secondary\" /> Language\n </span>\n </label>\n <select\n value={settings.preferences.language}\n onChange={(e) => update('preferences', 'language', e.target.value as LanguageOption)}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface py-2 px-3 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n <option value=\"en\">English</option>\n <option value=\"hi\">Hindi</option>\n <option value=\"ta\">Tamil</option>\n <option value=\"kn\">Kannada</option>\n <option value=\"te\">Telugu</option>\n <option value=\"ml\">Malayalam</option>\n </select>\n </div>\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">Timezone</label>\n <select\n value={settings.preferences.timezone}\n onChange={(e) => update('preferences', 'timezone', e.target.value)}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface py-2 px-3 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n <option value=\"Asia/Kolkata\">India (IST)</option>\n <option value=\"Asia/Dubai\">Dubai (GST)</option>\n <option value=\"Europe/London\">London (GMT)</option>\n <option value=\"America/New_York\">New York (EST)</option>\n </select>\n </div>\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">Currency</label>\n <select\n value={settings.preferences.currency}\n onChange={(e) => update('preferences', 'currency', e.target.value)}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface py-2 px-3 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n <option value=\"INR\">Indian Rupee (₹)</option>\n <option value=\"USD\">US Dollar ($)</option>\n <option value=\"EUR\">Euro (€)</option>\n <option value=\"GBP\">British Pound (£)</option>\n </select>\n </div>\n </div>\n\n {/* Theme */}\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-3\">Theme</label>\n <div className=\"flex gap-3 flex-wrap\">\n {(\n [\n { value: 'light', label: 'Light', Icon: Sun },\n { value: 'dark', label: 'Dark', Icon: Moon },\n { value: 'system', label: 'System', Icon: Monitor },\n ] as const\n ).map(({ value, label, Icon }) => (\n <label\n key={value}\n className={cn(\n 'flex items-center gap-2 rounded-lg border px-4 py-2.5 text-sm font-medium cursor-pointer transition-colors',\n settings.preferences.theme === value\n ? 'border-primary bg-action-primary-bg/10 text-text-primary'\n : 'border-border-subtle text-text-secondary hover:border-accent-foreground/20 hover:text-text-primary'\n )}\n >\n <input\n type=\"radio\"\n name=\"theme\"\n value={value}\n checked={settings.preferences.theme === value}\n onChange={(e) => update('preferences', 'theme', e.target.value as ThemeOption)}\n className=\"sr-only\"\n />\n <Icon className=\"h-4 w-4\" />\n {label}\n </label>\n ))}\n </div>\n </div>\n\n {/* Notification Toggles */}\n <div>\n <div className=\"flex items-center gap-2 mb-4\">\n <Bell className=\"h-4 w-4 text-text-secondary\" />\n <h4 className=\"text-sm font-semibold text-text-primary\">Notification Preferences</h4>\n </div>\n <div className=\"space-y-3\">\n {(\n [\n { key: 'email', label: 'Email notifications' },\n { key: 'sms', label: 'SMS notifications' },\n { key: 'push', label: 'Push notifications' },\n { key: 'orderUpdates', label: 'Order status updates' },\n { key: 'promotions', label: 'Promotional offers' },\n { key: 'newsletters', label: 'Newsletters and updates' },\n { key: 'security', label: 'Security alerts' },\n ] as const\n ).map((item) => (\n <div\n key={item.key}\n className=\"flex items-center justify-between rounded-lg border border-border-subtle p-3\"\n >\n <span className=\"text-sm text-text-primary\">{item.label}</span>\n <ToggleSwitch\n checked={settings.preferences.notifications[item.key]}\n onChange={(val) => updateNested('preferences', 'notifications', item.key, val)}\n label={item.label}\n />\n </div>\n ))}\n </div>\n </div>\n </div>\n );\n\n // ---- Security Tab ----\n const renderSecurity = () => (\n <div className=\"space-y-6\">\n <h3 className=\"text-base font-semibold text-text-primary\">Security Settings</h3>\n\n {/* Warning banner */}\n <div className=\"flex items-start gap-3 rounded-lg border border-status-warning-text/30 bg-status-warning-bg-subtle p-4\">\n <AlertTriangle className=\"h-5 w-5 text-status-warning-text shrink-0 mt-0.5\" />\n <div>\n <p className=\"text-sm font-medium text-text-primary\">Account Security</p>\n <p className=\"text-xs text-text-secondary\">\n Keep your account secure by enabling two-factor authentication and monitoring login\n activity.\n </p>\n </div>\n </div>\n\n {/* 2FA */}\n <div className=\"flex items-center justify-between rounded-lg border border-border-subtle p-4\">\n <div className=\"flex-1\">\n <div className=\"flex items-center gap-2\">\n <Lock className=\"h-4 w-4 text-text-secondary\" />\n <p className=\"text-sm font-medium text-text-primary\">Two-Factor Authentication</p>\n </div>\n <p className=\"text-xs text-text-secondary mt-0.5 ml-6\">\n Add an extra layer of security to your account\n </p>\n </div>\n <ToggleSwitch\n checked={settings.security.twoFactorEnabled}\n onChange={(val) => update('security', 'twoFactorEnabled', val)}\n label=\"Two-factor authentication\"\n />\n </div>\n\n {/* Login Alerts */}\n <div className=\"flex items-center justify-between rounded-lg border border-border-subtle p-4\">\n <div className=\"flex-1\">\n <p className=\"text-sm font-medium text-text-primary\">Login Alerts</p>\n <p className=\"text-xs text-text-secondary mt-0.5\">\n Get notified when someone logs into your account\n </p>\n </div>\n <ToggleSwitch\n checked={settings.security.loginAlerts}\n onChange={(val) => update('security', 'loginAlerts', val)}\n label=\"Login alerts\"\n />\n </div>\n\n {/* Session Timeout */}\n <div className=\"flex items-center justify-between rounded-lg border border-border-subtle p-4\">\n <div className=\"flex-1\">\n <p className=\"text-sm font-medium text-text-primary\">Session Timeout</p>\n <p className=\"text-xs text-text-secondary mt-0.5\">Auto-logout after inactivity</p>\n </div>\n <select\n value={settings.security.sessionTimeout}\n onChange={(e) => update('security', 'sessionTimeout', e.target.value)}\n className=\"rounded-lg border border-border-subtle bg-bg-surface py-2 px-3 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] w-36\"\n >\n <option value=\"15\">15 minutes</option>\n <option value=\"30\">30 minutes</option>\n <option value=\"60\">1 hour</option>\n <option value=\"120\">2 hours</option>\n <option value=\"0\">Never</option>\n </select>\n </div>\n\n {/* Trusted Devices */}\n <div>\n <h4 className=\"text-sm font-semibold text-text-primary mb-3\">Trusted Devices</h4>\n <div className=\"space-y-3\">\n {settings.security.trustedDevices.map((device) => (\n <div\n key={device.id}\n className=\"flex items-center justify-between rounded-lg border border-border-subtle p-4\"\n >\n <div className=\"flex items-center gap-3\">\n {device.os.toLowerCase().includes('mac') ||\n device.os.toLowerCase().includes('windows') ? (\n <Laptop className=\"h-5 w-5 text-text-secondary shrink-0\" />\n ) : (\n <Smartphone className=\"h-5 w-5 text-text-secondary shrink-0\" />\n )}\n <div>\n <div className=\"flex items-center gap-2\">\n <p className=\"text-sm font-medium text-text-primary\">{device.name}</p>\n {device.isCurrent && (\n <span className=\"inline-flex items-center rounded-full bg-status-success-bg-subtle px-2 py-0.5 text-xs font-medium text-status-success-text\">\n Current\n </span>\n )}\n </div>\n <p className=\"text-xs text-text-secondary\">\n {device.browser} · {device.os}\n </p>\n </div>\n </div>\n {!device.isCurrent && (\n <button\n type=\"button\"\n onClick={() => removeDevice(device.id)}\n className=\"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 Remove\n </button>\n )}\n </div>\n ))}\n </div>\n </div>\n\n {/* Actions */}\n <div className=\"flex flex-wrap gap-3\">\n <button\n type=\"button\"\n onClick={() => alert('Password change functionality coming soon')}\n className=\"flex items-center gap-1.5 rounded-lg border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-accent transition-colors\"\n >\n <Lock className=\"h-4 w-4\" />\n Change Password\n </button>\n <button\n type=\"button\"\n onClick={logoutAllDevices}\n className=\"flex items-center gap-1.5 rounded-lg border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-accent transition-colors\"\n >\n <LogOut className=\"h-4 w-4\" />\n Logout All Devices\n </button>\n </div>\n </div>\n );\n\n // ---- Privacy Tab ----\n const renderPrivacy = () => (\n <div className=\"space-y-6\">\n <h3 className=\"text-base font-semibold text-text-primary\">Privacy Controls</h3>\n\n {/* Profile Visibility */}\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">\n <span className=\"flex items-center gap-1.5\">\n <Eye className=\"h-4 w-4 text-text-secondary\" /> Profile Visibility\n </span>\n </label>\n <select\n value={settings.privacy.profileVisibility}\n onChange={(e) =>\n update(\n 'privacy',\n 'profileVisibility',\n e.target.value as 'public' | 'private' | 'friends'\n )\n }\n className=\"w-full max-w-sm rounded-lg border border-border-subtle bg-bg-surface py-2 px-3 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n <option value=\"public\">Public - Anyone can see your profile</option>\n <option value=\"private\">Private - Only you can see your profile</option>\n <option value=\"friends\">Friends - Only friends can see your profile</option>\n </select>\n </div>\n\n {/* Data Sharing */}\n <div>\n <h4 className=\"text-sm font-semibold text-text-primary mb-3\">Data Sharing</h4>\n <div className=\"space-y-3\">\n {(\n [\n { key: 'analytics', label: 'Share usage analytics to improve the app' },\n { key: 'marketing', label: 'Share data for personalized marketing' },\n { key: 'thirdParty', label: 'Share data with third-party partners' },\n ] as const\n ).map((item) => (\n <div\n key={item.key}\n className=\"flex items-center justify-between rounded-lg border border-border-subtle p-3\"\n >\n <span className=\"text-sm text-text-primary\">{item.label}</span>\n <ToggleSwitch\n checked={settings.privacy.dataSharing[item.key]}\n onChange={(val) => updateNested('privacy', 'dataSharing', item.key, val)}\n label={item.label}\n />\n </div>\n ))}\n </div>\n </div>\n\n {/* Location & Activity */}\n <div className=\"space-y-3\">\n <div className=\"flex items-center justify-between rounded-lg border border-border-subtle p-4\">\n <div>\n <p className=\"text-sm font-medium text-text-primary\">Location Tracking</p>\n <p className=\"text-xs text-text-secondary\">\n Allow app to track your location for better service\n </p>\n </div>\n <ToggleSwitch\n checked={settings.privacy.locationTracking}\n onChange={(val) => update('privacy', 'locationTracking', val)}\n label=\"Location tracking\"\n />\n </div>\n <div className=\"flex items-center justify-between rounded-lg border border-border-subtle p-4\">\n <div>\n <p className=\"text-sm font-medium text-text-primary\">Activity History</p>\n <p className=\"text-xs text-text-secondary\">Keep track of your orders and activities</p>\n </div>\n <ToggleSwitch\n checked={settings.privacy.activityHistory}\n onChange={(val) => update('privacy', 'activityHistory', val)}\n label=\"Activity history\"\n />\n </div>\n </div>\n\n {/* Delete Account */}\n <div className=\"rounded-lg border border-status-error-text/30 bg-status-error-bg-subtle p-4\">\n <div className=\"flex items-start gap-3\">\n <Trash2 className=\"h-5 w-5 text-status-error-text shrink-0 mt-0.5\" />\n <div>\n <p className=\"text-sm font-medium text-text-primary\">Delete Account</p>\n <p className=\"text-xs text-text-secondary mt-0.5\">\n Permanently delete your account and all associated data. This action cannot be undone.\n </p>\n <button\n type=\"button\"\n onClick={handleDeleteAccount}\n className=\"mt-3 rounded-lg border border-status-error-text/30 px-4 py-2 text-sm font-medium text-status-error-text hover:bg-status-error-bg/10 transition-colors\"\n >\n Delete Account\n </button>\n </div>\n </div>\n </div>\n </div>\n );\n\n // ---- Billing Tab ----\n const renderBilling = () => (\n <div className=\"space-y-6\">\n <h3 className=\"text-base font-semibold text-text-primary\">Billing & Payments</h3>\n\n {/* Default Payment Method */}\n <div>\n <h4 className=\"text-sm font-semibold text-text-primary mb-3\">\n <span className=\"flex items-center gap-1.5\">\n <CreditCard className=\"h-4 w-4 text-text-secondary\" /> Default Payment Method\n </span>\n </h4>\n {settings.billing.paymentMethod ? (\n <div className=\"flex items-center justify-between rounded-lg border border-border-subtle p-4\">\n <div className=\"flex items-center gap-3\">\n <CreditCard className=\"h-6 w-6 text-text-secondary\" />\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {settings.billing.paymentMethod.provider} ending in{' '}\n {settings.billing.paymentMethod.last4}\n </p>\n <p className=\"text-xs text-text-secondary capitalize\">\n {settings.billing.paymentMethod.type}\n </p>\n </div>\n </div>\n <button\n type=\"button\"\n onClick={() => alert('Change payment method coming soon')}\n className=\"rounded-lg border border-border-subtle px-3 py-1.5 text-sm font-medium text-text-primary hover:bg-accent transition-colors\"\n >\n Change\n </button>\n </div>\n ) : (\n <div className=\"rounded-lg border border-border-subtle p-4 text-center\">\n <p className=\"text-sm text-text-secondary\">No default payment method set</p>\n <button\n type=\"button\"\n onClick={() => alert('Add payment method coming soon')}\n className=\"mt-2 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90 transition-colors\"\n >\n Add Payment Method\n </button>\n </div>\n )}\n </div>\n\n {/* Auto Recharge */}\n <div>\n <h4 className=\"text-sm font-semibold text-text-primary mb-3\">Auto Recharge</h4>\n <div className=\"flex items-center justify-between rounded-lg border border-border-subtle p-4 mb-3\">\n <div>\n <p className=\"text-sm font-medium text-text-primary\">Enable Auto Recharge</p>\n <p className=\"text-xs text-text-secondary\">\n Automatically add money when wallet balance is low\n </p>\n </div>\n <ToggleSwitch\n checked={settings.billing.autoRecharge}\n onChange={(val) => update('billing', 'autoRecharge', val)}\n label=\"Auto recharge\"\n />\n </div>\n {settings.billing.autoRecharge && (\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">\n Auto Recharge Amount (₹)\n </label>\n <input\n type=\"number\"\n value={settings.billing.autoRechargeAmount}\n onChange={(e) => update('billing', 'autoRechargeAmount', e.target.value)}\n placeholder=\"1000\"\n className=\"w-full max-w-xs rounded-lg border border-border-subtle bg-bg-surface py-2 px-3 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n </div>\n )}\n </div>\n\n {/* Invoice Email */}\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">\n <span className=\"flex items-center gap-1.5\">\n <Receipt className=\"h-4 w-4 text-text-secondary\" /> Invoice Email\n </span>\n </label>\n <input\n type=\"email\"\n value={settings.billing.invoiceEmail}\n onChange={(e) => update('billing', 'invoiceEmail', e.target.value)}\n placeholder=\"billing@example.com\"\n className=\"w-full max-w-sm rounded-lg border border-border-subtle bg-bg-surface py-2 px-3 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n </div>\n\n {/* Tax Info */}\n <div>\n <h4 className=\"text-sm font-semibold text-text-primary mb-3\">\n <span className=\"flex items-center gap-1.5\">\n <Building2 className=\"h-4 w-4 text-text-secondary\" /> Tax Information\n </span>\n </h4>\n <div className=\"space-y-4\">\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">GST Number</label>\n <input\n type=\"text\"\n value={settings.billing.gstNumber}\n onChange={(e) => update('billing', 'gstNumber', e.target.value)}\n placeholder=\"29ABCDE1234F1Z5\"\n className=\"w-full max-w-sm rounded-lg border border-border-subtle bg-bg-surface py-2 px-3 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">\n Company Name\n </label>\n <input\n type=\"text\"\n value={settings.billing.companyName}\n onChange={(e) => update('billing', 'companyName', e.target.value)}\n placeholder=\"Your Company Name\"\n className=\"w-full max-w-sm rounded-lg border border-border-subtle bg-bg-surface py-2 px-3 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">\n <span className=\"flex items-center gap-1.5\">\n <MapPin className=\"h-4 w-4 text-text-secondary\" /> Billing Address\n </span>\n </label>\n <textarea\n rows={3}\n value={settings.billing.billingAddress}\n onChange={(e) => update('billing', 'billingAddress', e.target.value)}\n placeholder=\"Enter your complete billing address\"\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface py-2 px-3 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] resize-none\"\n />\n </div>\n </div>\n </div>\n </div>\n );\n\n // ---- Render function map ----\n const renderTab: Record<TabId, () => React.ReactNode> = {\n profile: renderProfile,\n preferences: renderPreferences,\n security: renderSecurity,\n privacy: renderPrivacy,\n billing: renderBilling,\n };\n\n return (\n <PageLayout\n title={t('kadaikodi.settings.title', 'Settings')}\n description={t(\n 'kadaikodi.settings.description',\n 'Manage your preferences and account settings'\n )}\n actions={\n <div className=\"flex items-center gap-2\">\n {hasChanges && (\n <button\n type=\"button\"\n onClick={resetSettings}\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 <RotateCcw className=\"h-4 w-4\" />\n {t('kadaikodi.settings.reset', 'Reset')}\n </button>\n )}\n <button\n type=\"button\"\n disabled={!hasChanges || saving}\n onClick={saveSettings}\n className={cn(\n 'flex items-center gap-1.5 rounded-lg px-4 py-2 text-sm font-medium transition-colors',\n hasChanges && !saving\n ? 'bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg/90'\n : 'bg-bg-sunken text-text-secondary cursor-not-allowed'\n )}\n >\n {saving ? (\n <>\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n {t('kadaikodi.settings.saving', 'Saving...')}\n </>\n ) : (\n <>\n <Save className=\"h-4 w-4\" />\n {t('kadaikodi.settings.save', 'Save Settings')}\n </>\n )}\n </button>\n </div>\n }\n >\n {/* Save message */}\n {saveMessage && (\n <div\n className={cn(\n 'mb-6 flex items-center gap-2 rounded-lg border p-3 text-sm',\n saveMessage.includes('successfully')\n ? 'border-status-success-text/30 bg-status-success-bg-subtle text-status-success-text'\n : 'border-status-error-text/30 bg-status-error-bg-subtle text-status-error-text'\n )}\n >\n {saveMessage.includes('successfully') ? (\n <CheckCircle2 className=\"h-4 w-4 shrink-0\" />\n ) : (\n <AlertTriangle className=\"h-4 w-4 shrink-0\" />\n )}\n {saveMessage}\n </div>\n )}\n\n <PagePurpose className=\"mb-6\">\n {t(\n 'kadaikodi.settings.purpose',\n 'Your personal control center on Kadaikodi. Use this page to manage your profile, app preferences (language, theme, notifications), security and login, privacy choices, and billing — everything about your own account in one place. Pick a section on the left, make your changes, and Save.'\n )}\n </PagePurpose>\n\n <NextSteps\n storageKey=\"kadaikodi-settings\"\n className=\"mb-6\"\n steps={[\n {\n id: 'security',\n label: t('kadaikodi.settings.next.security', 'Secure your account'),\n description: t(\n 'kadaikodi.settings.next.securityDesc',\n 'Update your password and review active devices.'\n ),\n onClick: () => setActiveTab('security'),\n },\n {\n id: 'preferences',\n label: t('kadaikodi.settings.next.preferences', 'Set your preferences'),\n description: t(\n 'kadaikodi.settings.next.preferencesDesc',\n 'Choose language, theme and notification settings.'\n ),\n onClick: () => setActiveTab('preferences'),\n },\n {\n id: 'billing',\n label: t('kadaikodi.settings.next.billing', 'Review billing'),\n description: t(\n 'kadaikodi.settings.next.billingDesc',\n 'Check your plan and payment method.'\n ),\n onClick: () => setActiveTab('billing'),\n },\n ]}\n />\n\n <div className=\"flex flex-col gap-6 lg:flex-row\">\n {/* Sidebar (Desktop) / Tab Row (Mobile) */}\n <div className=\"shrink-0 lg:w-56\">\n {/* Mobile grid */}\n <div className=\"grid grid-cols-5 gap-1 lg:hidden\">\n {localizedTabConfig.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 flex-col items-center gap-1 rounded-lg py-2.5 text-center transition-colors',\n activeTab === tab.id\n ? 'bg-action-primary-bg/10 text-text-primary'\n : 'text-text-secondary hover:text-text-primary hover:bg-accent'\n )}\n >\n <TabIcon className=\"h-4 w-4\" />\n <span className=\"text-xs font-medium\">{tab.label}</span>\n </button>\n );\n })}\n </div>\n {/* Desktop sidebar */}\n <div className=\"hidden lg:block rounded-lg border border-border-subtle bg-bg-surface\">\n <div className=\"p-3 border-b border-border-subtle\">\n <p className=\"text-sm font-semibold text-text-primary\">\n {t('kadaikodi.settings.title', 'Settings')}\n </p>\n </div>\n <nav className=\"p-2\">\n {localizedTabConfig.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 w-full items-center gap-2.5 rounded-lg px-3 py-2 text-sm font-medium transition-colors mb-0.5',\n activeTab === tab.id\n ? 'bg-action-primary-bg/10 text-text-primary'\n : 'text-text-secondary hover:text-text-primary hover:bg-accent'\n )}\n >\n <TabIcon className=\"h-4 w-4\" />\n {tab.label}\n </button>\n );\n })}\n </nav>\n </div>\n </div>\n\n {/* Content — the one emphasis zone for this page */}\n <EmphasisPanel className=\"flex-1 p-6\">{renderTab[activeTab]()}</EmphasisPanel>\n </div>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SettingsPage.js","names":[],"sources":["../../../../src/kadaikodi/pages/common/SettingsPage.tsx"],"sourcesContent":["/**\n * Settings Page\n * @module kadaikodi/pages/common\n *\n * Full-featured settings with 5 tabs: Profile, Preferences, Security,\n * Privacy, and Billing. Form validation, save state, sidebar navigation.\n */\n\nimport { useState, useCallback, useMemo } from 'react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n User,\n Settings,\n Sun,\n Moon,\n Monitor,\n Globe,\n Bell,\n Shield,\n Eye,\n EyeOff,\n Save,\n RotateCcw,\n Lock,\n Smartphone,\n Laptop,\n LogOut,\n Trash2,\n CreditCard,\n Receipt,\n Building2,\n MapPin,\n Camera,\n AlertTriangle,\n CheckCircle2,\n Loader2,\n} from 'lucide-react';\nimport { EmphasisPanel, PagePurpose, NextSteps } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { useKadaikodi } from '../../context/KadaikodiContext';\nimport { cn } from '../../utils/cn';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype ThemeOption = 'light' | 'dark' | 'system';\ntype LanguageOption = 'en' | 'ta' | 'hi' | 'kn' | 'te' | 'ml';\ntype TabId = 'profile' | 'preferences' | 'security' | 'privacy' | 'billing';\n\ninterface TrustedDevice {\n id: string;\n name: string;\n browser: string;\n os: string;\n lastActive: string;\n isCurrent: boolean;\n}\n\ninterface UserSettings {\n profile: {\n firstName: string;\n lastName: string;\n email: string;\n phone: string;\n bio: string;\n dateOfBirth: string;\n gender: string;\n profilePicture: string;\n };\n preferences: {\n theme: ThemeOption;\n language: LanguageOption;\n timezone: string;\n currency: string;\n notifications: {\n email: boolean;\n sms: boolean;\n push: boolean;\n orderUpdates: boolean;\n promotions: boolean;\n newsletters: boolean;\n security: boolean;\n };\n };\n security: {\n twoFactorEnabled: boolean;\n loginAlerts: boolean;\n sessionTimeout: string;\n trustedDevices: TrustedDevice[];\n };\n privacy: {\n profileVisibility: 'public' | 'private' | 'friends';\n dataSharing: {\n analytics: boolean;\n marketing: boolean;\n thirdParty: boolean;\n };\n locationTracking: boolean;\n activityHistory: boolean;\n };\n billing: {\n paymentMethod: { type: string; last4: string; provider: string } | null;\n autoRecharge: boolean;\n autoRechargeAmount: string;\n invoiceEmail: string;\n gstNumber: string;\n companyName: string;\n billingAddress: string;\n };\n}\n\n// ---------------------------------------------------------------------------\n// Defaults\n// ---------------------------------------------------------------------------\n\nconst defaultSettings: UserSettings = {\n profile: {\n firstName: '',\n lastName: '',\n email: '',\n phone: '',\n bio: '',\n dateOfBirth: '',\n gender: '',\n profilePicture: '',\n },\n preferences: {\n theme: 'system',\n language: 'en',\n timezone: 'Asia/Kolkata',\n currency: 'INR',\n notifications: {\n email: true,\n sms: true,\n push: true,\n orderUpdates: true,\n promotions: false,\n newsletters: false,\n security: true,\n },\n },\n security: {\n twoFactorEnabled: false,\n loginAlerts: true,\n sessionTimeout: '30',\n trustedDevices: [],\n },\n privacy: {\n profileVisibility: 'private',\n dataSharing: {\n analytics: true,\n marketing: false,\n thirdParty: false,\n },\n locationTracking: true,\n activityHistory: true,\n },\n billing: {\n paymentMethod: null,\n autoRecharge: false,\n autoRechargeAmount: '1000',\n invoiceEmail: '',\n gstNumber: '',\n companyName: '',\n billingAddress: '',\n },\n};\n\n// ---------------------------------------------------------------------------\n// Tab config\n// ---------------------------------------------------------------------------\n\nconst tabConfig: { id: TabId; label: string; icon: typeof User }[] = [\n { id: 'profile', label: 'Profile', icon: User },\n { id: 'preferences', label: 'Preferences', icon: Settings },\n { id: 'security', label: 'Security', icon: Shield },\n { id: 'privacy', label: 'Privacy', icon: Eye },\n { id: 'billing', label: 'Billing', icon: CreditCard },\n];\n\n// ---------------------------------------------------------------------------\n// Toggle Switch component (inline)\n// ---------------------------------------------------------------------------\n\nfunction ToggleSwitch({\n checked,\n onChange,\n label,\n}: {\n checked: boolean;\n onChange: (val: boolean) => void;\n label?: string;\n}) {\n return (\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked={checked}\n aria-label={label}\n onClick={() => onChange(!checked)}\n className={cn(\n 'relative inline-flex h-6 w-11 items-center rounded-full transition-colors shrink-0',\n checked ? 'bg-action-primary-bg' : 'bg-bg-sunken'\n )}\n >\n <span\n className={cn(\n 'inline-block h-4 w-4 transform rounded-full bg-white transition-transform',\n checked ? 'translate-x-6' : 'translate-x-1'\n )}\n />\n </button>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nexport function SettingsPage() {\n const { currentUser } = useKadaikodi();\n const { t: translate } = useI18n();\n const [activeTab, setActiveTab] = useState<TabId>('profile');\n const [settings, setSettings] = useState<UserSettings>(() => {\n const firstName = currentUser?.firstName ?? currentUser?.name?.split(' ')[0] ?? '';\n const lastName =\n currentUser?.lastName ?? currentUser?.name?.split(' ').slice(1).join(' ') ?? '';\n const email = currentUser?.email ?? '';\n return {\n ...defaultSettings,\n profile: {\n ...defaultSettings.profile,\n firstName,\n lastName,\n email,\n phone: currentUser?.phone ?? '',\n profilePicture: currentUser?.avatar ?? currentUser?.profilePicture ?? '',\n },\n billing: { ...defaultSettings.billing, invoiceEmail: email },\n };\n });\n const [hasChanges, setHasChanges] = useState(false);\n const [saving, setSaving] = useState(false);\n const [saveMessage, setSaveMessage] = useState('');\n const t = useCallback(\n (key: string, fallback: string): string => {\n const value = translate(key);\n return value === key ? fallback : value;\n },\n [translate]\n );\n const localizedTabConfig = useMemo(\n () =>\n tabConfig.map((tab) => ({\n ...tab,\n label:\n tab.id === 'profile'\n ? t('kadaikodi.settings.tabs.profile', 'Profile')\n : tab.id === 'preferences'\n ? t('kadaikodi.settings.tabs.preferences', 'Preferences')\n : tab.id === 'security'\n ? t('kadaikodi.settings.tabs.security', 'Security')\n : tab.id === 'privacy'\n ? t('kadaikodi.settings.tabs.privacy', 'Privacy')\n : t('kadaikodi.settings.tabs.billing', 'Billing'),\n })),\n [t]\n );\n\n // Deep update helper\n const update = useCallback(\n <S extends keyof UserSettings, F extends keyof UserSettings[S]>(\n section: S,\n field: F,\n value: UserSettings[S][F]\n ) => {\n setSettings((prev) => ({\n ...prev,\n [section]: { ...prev[section], [field]: value },\n }));\n setHasChanges(true);\n setSaveMessage('');\n },\n []\n );\n\n const updateNested = useCallback(\n (section: keyof UserSettings, sub: string, field: string, value: boolean | string) => {\n setSettings((prev) => ({\n ...prev,\n [section]: {\n ...prev[section],\n [sub]: {\n ...((prev[section] as Record<string, unknown>)[sub] as Record<string, unknown>),\n [field]: value,\n },\n },\n }));\n setHasChanges(true);\n setSaveMessage('');\n },\n []\n );\n\n const resetSettings = useCallback(() => {\n setSettings(defaultSettings);\n setHasChanges(false);\n setSaveMessage('');\n }, []);\n\n const saveSettings = useCallback(async () => {\n // Basic validation\n if (!settings.profile.firstName.trim() || !settings.profile.lastName.trim()) {\n setSaveMessage(\n t('kadaikodi.settings.validation.nameRequired', 'First name and last name are required.')\n );\n setActiveTab('profile');\n return;\n }\n if (!settings.profile.email.trim() || !settings.profile.email.includes('@')) {\n setSaveMessage(\n t('kadaikodi.settings.validation.emailRequired', 'A valid email address is required.')\n );\n setActiveTab('profile');\n return;\n }\n\n setSaving(true);\n setSaveMessage('');\n // Simulate API\n await new Promise((r) => setTimeout(r, 1200));\n setSaving(false);\n setHasChanges(false);\n setSaveMessage(t('kadaikodi.settings.saveSuccess', 'Settings saved successfully!'));\n setTimeout(() => setSaveMessage(''), 3000);\n }, [settings, t]);\n\n const removeDevice = useCallback((id: string) => {\n setSettings((prev) => ({\n ...prev,\n security: {\n ...prev.security,\n trustedDevices: prev.security.trustedDevices.filter((d) => d.id !== id),\n },\n }));\n setHasChanges(true);\n }, []);\n\n const logoutAllDevices = useCallback(() => {\n setSettings((prev) => ({\n ...prev,\n security: {\n ...prev.security,\n trustedDevices: prev.security.trustedDevices.filter((d) => d.isCurrent),\n },\n }));\n setHasChanges(true);\n }, []);\n\n const handleDeleteAccount = useCallback(() => {\n if (\n window.confirm(\n t(\n 'kadaikodi.settings.deleteConfirm',\n 'Are you sure you want to delete your account? This action cannot be undone.'\n )\n )\n ) {\n alert(\n t(\n 'kadaikodi.settings.deleteSubmitted',\n 'Account deletion request submitted. You will receive a confirmation email.'\n )\n );\n }\n }, [t]);\n\n // ---- Profile Tab ----\n const renderProfile = () => (\n <div className=\"space-y-6\">\n <h3 className=\"text-base font-semibold text-text-primary\">Personal Information</h3>\n\n {/* Profile Picture */}\n <div className=\"flex items-center gap-4\">\n <div className=\"relative\">\n {settings.profile.profilePicture ? (\n <img\n src={settings.profile.profilePicture}\n alt=\"Profile\"\n className=\"h-20 w-20 rounded-full object-cover border border-border-subtle\"\n />\n ) : (\n <div className=\"flex h-20 w-20 items-center justify-center rounded-full border border-border-subtle bg-bg-sunken text-lg font-semibold text-text-secondary\">\n {(\n (settings.profile.firstName[0] ?? '') + (settings.profile.lastName[0] ?? '')\n ).toUpperCase() || (settings.profile.email[0] ?? '?').toUpperCase()}\n </div>\n )}\n <button\n type=\"button\"\n onClick={() => alert('Photo upload coming soon')}\n className=\"absolute -bottom-1 -right-1 flex h-7 w-7 items-center justify-center rounded-full bg-action-primary-bg text-action-primary-text shadow-sm hover:bg-action-primary-bg/90\"\n >\n <Camera className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n <div>\n <p className=\"text-sm font-medium text-text-primary\">Profile Picture</p>\n <p className=\"text-xs text-text-secondary\">Upload a new photo (JPG, PNG, max 2MB)</p>\n </div>\n </div>\n\n {/* Name */}\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">First Name *</label>\n <input\n type=\"text\"\n value={settings.profile.firstName}\n onChange={(e) => update('profile', 'firstName', e.target.value)}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface py-2 px-3 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">Last Name *</label>\n <input\n type=\"text\"\n value={settings.profile.lastName}\n onChange={(e) => update('profile', 'lastName', e.target.value)}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface py-2 px-3 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n </div>\n </div>\n\n {/* Email & Phone */}\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">\n Email Address *\n </label>\n <input\n type=\"email\"\n value={settings.profile.email}\n onChange={(e) => update('profile', 'email', e.target.value)}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface py-2 px-3 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">Phone Number</label>\n <input\n type=\"tel\"\n value={settings.profile.phone}\n onChange={(e) => update('profile', 'phone', e.target.value)}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface py-2 px-3 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n </div>\n </div>\n\n {/* Bio */}\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">Bio</label>\n <textarea\n rows={3}\n value={settings.profile.bio}\n onChange={(e) => update('profile', 'bio', e.target.value)}\n placeholder=\"Tell us about yourself...\"\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface py-2 px-3 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] resize-none\"\n />\n </div>\n\n {/* DOB & Gender */}\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">\n Date of Birth\n </label>\n <input\n type=\"date\"\n value={settings.profile.dateOfBirth}\n onChange={(e) => update('profile', 'dateOfBirth', e.target.value)}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface py-2 px-3 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">Gender</label>\n <select\n value={settings.profile.gender}\n onChange={(e) => update('profile', 'gender', e.target.value)}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface py-2 px-3 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n <option value=\"\">Select gender</option>\n <option value=\"male\">Male</option>\n <option value=\"female\">Female</option>\n <option value=\"other\">Other</option>\n <option value=\"prefer-not-to-say\">Prefer not to say</option>\n </select>\n </div>\n </div>\n </div>\n );\n\n // ---- Preferences Tab ----\n const renderPreferences = () => (\n <div className=\"space-y-6\">\n <h3 className=\"text-base font-semibold text-text-primary\">App Preferences</h3>\n\n {/* Language, Timezone, Currency */}\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-3\">\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">\n <span className=\"flex items-center gap-1.5\">\n <Globe className=\"h-4 w-4 text-text-secondary\" /> Language\n </span>\n </label>\n <select\n value={settings.preferences.language}\n onChange={(e) => update('preferences', 'language', e.target.value as LanguageOption)}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface py-2 px-3 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n <option value=\"en\">English</option>\n <option value=\"hi\">Hindi</option>\n <option value=\"ta\">Tamil</option>\n <option value=\"kn\">Kannada</option>\n <option value=\"te\">Telugu</option>\n <option value=\"ml\">Malayalam</option>\n </select>\n </div>\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">Timezone</label>\n <select\n value={settings.preferences.timezone}\n onChange={(e) => update('preferences', 'timezone', e.target.value)}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface py-2 px-3 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n <option value=\"Asia/Kolkata\">India (IST)</option>\n <option value=\"Asia/Dubai\">Dubai (GST)</option>\n <option value=\"Europe/London\">London (GMT)</option>\n <option value=\"America/New_York\">New York (EST)</option>\n </select>\n </div>\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">Currency</label>\n <select\n value={settings.preferences.currency}\n onChange={(e) => update('preferences', 'currency', e.target.value)}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface py-2 px-3 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n <option value=\"INR\">Indian Rupee (₹)</option>\n <option value=\"USD\">US Dollar ($)</option>\n <option value=\"EUR\">Euro (€)</option>\n <option value=\"GBP\">British Pound (£)</option>\n </select>\n </div>\n </div>\n\n {/* Theme */}\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-3\">Theme</label>\n <div className=\"flex gap-3 flex-wrap\">\n {(\n [\n { value: 'light', label: 'Light', Icon: Sun },\n { value: 'dark', label: 'Dark', Icon: Moon },\n { value: 'system', label: 'System', Icon: Monitor },\n ] as const\n ).map(({ value, label, Icon }) => (\n <label\n key={value}\n className={cn(\n 'flex items-center gap-2 rounded-lg border px-4 py-2.5 text-sm font-medium cursor-pointer transition-colors',\n settings.preferences.theme === value\n ? 'border-primary bg-action-primary-bg/10 text-text-primary'\n : 'border-border-subtle text-text-secondary hover:border-border-strong hover:text-text-primary'\n )}\n >\n <input\n type=\"radio\"\n name=\"theme\"\n value={value}\n checked={settings.preferences.theme === value}\n onChange={(e) => update('preferences', 'theme', e.target.value as ThemeOption)}\n className=\"sr-only\"\n />\n <Icon className=\"h-4 w-4\" />\n {label}\n </label>\n ))}\n </div>\n </div>\n\n {/* Notification Toggles */}\n <div>\n <div className=\"flex items-center gap-2 mb-4\">\n <Bell className=\"h-4 w-4 text-text-secondary\" />\n <h4 className=\"text-sm font-semibold text-text-primary\">Notification Preferences</h4>\n </div>\n <div className=\"space-y-3\">\n {(\n [\n { key: 'email', label: 'Email notifications' },\n { key: 'sms', label: 'SMS notifications' },\n { key: 'push', label: 'Push notifications' },\n { key: 'orderUpdates', label: 'Order status updates' },\n { key: 'promotions', label: 'Promotional offers' },\n { key: 'newsletters', label: 'Newsletters and updates' },\n { key: 'security', label: 'Security alerts' },\n ] as const\n ).map((item) => (\n <div\n key={item.key}\n className=\"flex items-center justify-between rounded-lg border border-border-subtle p-3\"\n >\n <span className=\"text-sm text-text-primary\">{item.label}</span>\n <ToggleSwitch\n checked={settings.preferences.notifications[item.key]}\n onChange={(val) => updateNested('preferences', 'notifications', item.key, val)}\n label={item.label}\n />\n </div>\n ))}\n </div>\n </div>\n </div>\n );\n\n // ---- Security Tab ----\n const renderSecurity = () => (\n <div className=\"space-y-6\">\n <h3 className=\"text-base font-semibold text-text-primary\">Security Settings</h3>\n\n {/* Warning banner */}\n <div className=\"flex items-start gap-3 rounded-lg border border-status-warning-text/30 bg-status-warning-bg-subtle p-4\">\n <AlertTriangle className=\"h-5 w-5 text-status-warning-text shrink-0 mt-0.5\" />\n <div>\n <p className=\"text-sm font-medium text-text-primary\">Account Security</p>\n <p className=\"text-xs text-text-secondary\">\n Keep your account secure by enabling two-factor authentication and monitoring login\n activity.\n </p>\n </div>\n </div>\n\n {/* 2FA */}\n <div className=\"flex items-center justify-between rounded-lg border border-border-subtle p-4\">\n <div className=\"flex-1\">\n <div className=\"flex items-center gap-2\">\n <Lock className=\"h-4 w-4 text-text-secondary\" />\n <p className=\"text-sm font-medium text-text-primary\">Two-Factor Authentication</p>\n </div>\n <p className=\"text-xs text-text-secondary mt-0.5 ml-6\">\n Add an extra layer of security to your account\n </p>\n </div>\n <ToggleSwitch\n checked={settings.security.twoFactorEnabled}\n onChange={(val) => update('security', 'twoFactorEnabled', val)}\n label=\"Two-factor authentication\"\n />\n </div>\n\n {/* Login Alerts */}\n <div className=\"flex items-center justify-between rounded-lg border border-border-subtle p-4\">\n <div className=\"flex-1\">\n <p className=\"text-sm font-medium text-text-primary\">Login Alerts</p>\n <p className=\"text-xs text-text-secondary mt-0.5\">\n Get notified when someone logs into your account\n </p>\n </div>\n <ToggleSwitch\n checked={settings.security.loginAlerts}\n onChange={(val) => update('security', 'loginAlerts', val)}\n label=\"Login alerts\"\n />\n </div>\n\n {/* Session Timeout */}\n <div className=\"flex items-center justify-between rounded-lg border border-border-subtle p-4\">\n <div className=\"flex-1\">\n <p className=\"text-sm font-medium text-text-primary\">Session Timeout</p>\n <p className=\"text-xs text-text-secondary mt-0.5\">Auto-logout after inactivity</p>\n </div>\n <select\n value={settings.security.sessionTimeout}\n onChange={(e) => update('security', 'sessionTimeout', e.target.value)}\n className=\"rounded-lg border border-border-subtle bg-bg-surface py-2 px-3 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] w-36\"\n >\n <option value=\"15\">15 minutes</option>\n <option value=\"30\">30 minutes</option>\n <option value=\"60\">1 hour</option>\n <option value=\"120\">2 hours</option>\n <option value=\"0\">Never</option>\n </select>\n </div>\n\n {/* Trusted Devices */}\n <div>\n <h4 className=\"text-sm font-semibold text-text-primary mb-3\">Trusted Devices</h4>\n <div className=\"space-y-3\">\n {settings.security.trustedDevices.map((device) => (\n <div\n key={device.id}\n className=\"flex items-center justify-between rounded-lg border border-border-subtle p-4\"\n >\n <div className=\"flex items-center gap-3\">\n {device.os.toLowerCase().includes('mac') ||\n device.os.toLowerCase().includes('windows') ? (\n <Laptop className=\"h-5 w-5 text-text-secondary shrink-0\" />\n ) : (\n <Smartphone className=\"h-5 w-5 text-text-secondary shrink-0\" />\n )}\n <div>\n <div className=\"flex items-center gap-2\">\n <p className=\"text-sm font-medium text-text-primary\">{device.name}</p>\n {device.isCurrent && (\n <span className=\"inline-flex items-center rounded-full bg-status-success-bg-subtle px-2 py-0.5 text-xs font-medium text-status-success-text\">\n Current\n </span>\n )}\n </div>\n <p className=\"text-xs text-text-secondary\">\n {device.browser} · {device.os}\n </p>\n </div>\n </div>\n {!device.isCurrent && (\n <button\n type=\"button\"\n onClick={() => removeDevice(device.id)}\n className=\"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 Remove\n </button>\n )}\n </div>\n ))}\n </div>\n </div>\n\n {/* Actions */}\n <div className=\"flex flex-wrap gap-3\">\n <button\n type=\"button\"\n onClick={() => alert('Password change functionality coming soon')}\n className=\"flex items-center gap-1.5 rounded-lg border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-accent transition-colors\"\n >\n <Lock className=\"h-4 w-4\" />\n Change Password\n </button>\n <button\n type=\"button\"\n onClick={logoutAllDevices}\n className=\"flex items-center gap-1.5 rounded-lg border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-accent transition-colors\"\n >\n <LogOut className=\"h-4 w-4\" />\n Logout All Devices\n </button>\n </div>\n </div>\n );\n\n // ---- Privacy Tab ----\n const renderPrivacy = () => (\n <div className=\"space-y-6\">\n <h3 className=\"text-base font-semibold text-text-primary\">Privacy Controls</h3>\n\n {/* Profile Visibility */}\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">\n <span className=\"flex items-center gap-1.5\">\n <Eye className=\"h-4 w-4 text-text-secondary\" /> Profile Visibility\n </span>\n </label>\n <select\n value={settings.privacy.profileVisibility}\n onChange={(e) =>\n update(\n 'privacy',\n 'profileVisibility',\n e.target.value as 'public' | 'private' | 'friends'\n )\n }\n className=\"w-full max-w-sm rounded-lg border border-border-subtle bg-bg-surface py-2 px-3 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n <option value=\"public\">Public - Anyone can see your profile</option>\n <option value=\"private\">Private - Only you can see your profile</option>\n <option value=\"friends\">Friends - Only friends can see your profile</option>\n </select>\n </div>\n\n {/* Data Sharing */}\n <div>\n <h4 className=\"text-sm font-semibold text-text-primary mb-3\">Data Sharing</h4>\n <div className=\"space-y-3\">\n {(\n [\n { key: 'analytics', label: 'Share usage analytics to improve the app' },\n { key: 'marketing', label: 'Share data for personalized marketing' },\n { key: 'thirdParty', label: 'Share data with third-party partners' },\n ] as const\n ).map((item) => (\n <div\n key={item.key}\n className=\"flex items-center justify-between rounded-lg border border-border-subtle p-3\"\n >\n <span className=\"text-sm text-text-primary\">{item.label}</span>\n <ToggleSwitch\n checked={settings.privacy.dataSharing[item.key]}\n onChange={(val) => updateNested('privacy', 'dataSharing', item.key, val)}\n label={item.label}\n />\n </div>\n ))}\n </div>\n </div>\n\n {/* Location & Activity */}\n <div className=\"space-y-3\">\n <div className=\"flex items-center justify-between rounded-lg border border-border-subtle p-4\">\n <div>\n <p className=\"text-sm font-medium text-text-primary\">Location Tracking</p>\n <p className=\"text-xs text-text-secondary\">\n Allow app to track your location for better service\n </p>\n </div>\n <ToggleSwitch\n checked={settings.privacy.locationTracking}\n onChange={(val) => update('privacy', 'locationTracking', val)}\n label=\"Location tracking\"\n />\n </div>\n <div className=\"flex items-center justify-between rounded-lg border border-border-subtle p-4\">\n <div>\n <p className=\"text-sm font-medium text-text-primary\">Activity History</p>\n <p className=\"text-xs text-text-secondary\">Keep track of your orders and activities</p>\n </div>\n <ToggleSwitch\n checked={settings.privacy.activityHistory}\n onChange={(val) => update('privacy', 'activityHistory', val)}\n label=\"Activity history\"\n />\n </div>\n </div>\n\n {/* Delete Account */}\n <div className=\"rounded-lg border border-status-error-text/30 bg-status-error-bg-subtle p-4\">\n <div className=\"flex items-start gap-3\">\n <Trash2 className=\"h-5 w-5 text-status-error-text shrink-0 mt-0.5\" />\n <div>\n <p className=\"text-sm font-medium text-text-primary\">Delete Account</p>\n <p className=\"text-xs text-text-secondary mt-0.5\">\n Permanently delete your account and all associated data. This action cannot be undone.\n </p>\n <button\n type=\"button\"\n onClick={handleDeleteAccount}\n className=\"mt-3 rounded-lg border border-status-error-text/30 px-4 py-2 text-sm font-medium text-status-error-text hover:bg-status-error-bg/10 transition-colors\"\n >\n Delete Account\n </button>\n </div>\n </div>\n </div>\n </div>\n );\n\n // ---- Billing Tab ----\n const renderBilling = () => (\n <div className=\"space-y-6\">\n <h3 className=\"text-base font-semibold text-text-primary\">Billing & Payments</h3>\n\n {/* Default Payment Method */}\n <div>\n <h4 className=\"text-sm font-semibold text-text-primary mb-3\">\n <span className=\"flex items-center gap-1.5\">\n <CreditCard className=\"h-4 w-4 text-text-secondary\" /> Default Payment Method\n </span>\n </h4>\n {settings.billing.paymentMethod ? (\n <div className=\"flex items-center justify-between rounded-lg border border-border-subtle p-4\">\n <div className=\"flex items-center gap-3\">\n <CreditCard className=\"h-6 w-6 text-text-secondary\" />\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {settings.billing.paymentMethod.provider} ending in{' '}\n {settings.billing.paymentMethod.last4}\n </p>\n <p className=\"text-xs text-text-secondary capitalize\">\n {settings.billing.paymentMethod.type}\n </p>\n </div>\n </div>\n <button\n type=\"button\"\n onClick={() => alert('Change payment method coming soon')}\n className=\"rounded-lg border border-border-subtle px-3 py-1.5 text-sm font-medium text-text-primary hover:bg-accent transition-colors\"\n >\n Change\n </button>\n </div>\n ) : (\n <div className=\"rounded-lg border border-border-subtle p-4 text-center\">\n <p className=\"text-sm text-text-secondary\">No default payment method set</p>\n <button\n type=\"button\"\n onClick={() => alert('Add payment method coming soon')}\n className=\"mt-2 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90 transition-colors\"\n >\n Add Payment Method\n </button>\n </div>\n )}\n </div>\n\n {/* Auto Recharge */}\n <div>\n <h4 className=\"text-sm font-semibold text-text-primary mb-3\">Auto Recharge</h4>\n <div className=\"flex items-center justify-between rounded-lg border border-border-subtle p-4 mb-3\">\n <div>\n <p className=\"text-sm font-medium text-text-primary\">Enable Auto Recharge</p>\n <p className=\"text-xs text-text-secondary\">\n Automatically add money when wallet balance is low\n </p>\n </div>\n <ToggleSwitch\n checked={settings.billing.autoRecharge}\n onChange={(val) => update('billing', 'autoRecharge', val)}\n label=\"Auto recharge\"\n />\n </div>\n {settings.billing.autoRecharge && (\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">\n Auto Recharge Amount (₹)\n </label>\n <input\n type=\"number\"\n value={settings.billing.autoRechargeAmount}\n onChange={(e) => update('billing', 'autoRechargeAmount', e.target.value)}\n placeholder=\"1000\"\n className=\"w-full max-w-xs rounded-lg border border-border-subtle bg-bg-surface py-2 px-3 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n </div>\n )}\n </div>\n\n {/* Invoice Email */}\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">\n <span className=\"flex items-center gap-1.5\">\n <Receipt className=\"h-4 w-4 text-text-secondary\" /> Invoice Email\n </span>\n </label>\n <input\n type=\"email\"\n value={settings.billing.invoiceEmail}\n onChange={(e) => update('billing', 'invoiceEmail', e.target.value)}\n placeholder=\"billing@example.com\"\n className=\"w-full max-w-sm rounded-lg border border-border-subtle bg-bg-surface py-2 px-3 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n </div>\n\n {/* Tax Info */}\n <div>\n <h4 className=\"text-sm font-semibold text-text-primary mb-3\">\n <span className=\"flex items-center gap-1.5\">\n <Building2 className=\"h-4 w-4 text-text-secondary\" /> Tax Information\n </span>\n </h4>\n <div className=\"space-y-4\">\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">GST Number</label>\n <input\n type=\"text\"\n value={settings.billing.gstNumber}\n onChange={(e) => update('billing', 'gstNumber', e.target.value)}\n placeholder=\"29ABCDE1234F1Z5\"\n className=\"w-full max-w-sm rounded-lg border border-border-subtle bg-bg-surface py-2 px-3 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">\n Company Name\n </label>\n <input\n type=\"text\"\n value={settings.billing.companyName}\n onChange={(e) => update('billing', 'companyName', e.target.value)}\n placeholder=\"Your Company Name\"\n className=\"w-full max-w-sm rounded-lg border border-border-subtle bg-bg-surface py-2 px-3 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1.5\">\n <span className=\"flex items-center gap-1.5\">\n <MapPin className=\"h-4 w-4 text-text-secondary\" /> Billing Address\n </span>\n </label>\n <textarea\n rows={3}\n value={settings.billing.billingAddress}\n onChange={(e) => update('billing', 'billingAddress', e.target.value)}\n placeholder=\"Enter your complete billing address\"\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface py-2 px-3 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] resize-none\"\n />\n </div>\n </div>\n </div>\n </div>\n );\n\n // ---- Render function map ----\n const renderTab: Record<TabId, () => React.ReactNode> = {\n profile: renderProfile,\n preferences: renderPreferences,\n security: renderSecurity,\n privacy: renderPrivacy,\n billing: renderBilling,\n };\n\n return (\n <PageLayout\n title={t('kadaikodi.settings.title', 'Settings')}\n description={t(\n 'kadaikodi.settings.description',\n 'Manage your preferences and account settings'\n )}\n actions={\n <div className=\"flex items-center gap-2\">\n {hasChanges && (\n <button\n type=\"button\"\n onClick={resetSettings}\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 <RotateCcw className=\"h-4 w-4\" />\n {t('kadaikodi.settings.reset', 'Reset')}\n </button>\n )}\n <button\n type=\"button\"\n disabled={!hasChanges || saving}\n onClick={saveSettings}\n className={cn(\n 'flex items-center gap-1.5 rounded-lg px-4 py-2 text-sm font-medium transition-colors',\n hasChanges && !saving\n ? 'bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg/90'\n : 'bg-bg-sunken text-text-secondary cursor-not-allowed'\n )}\n >\n {saving ? (\n <>\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n {t('kadaikodi.settings.saving', 'Saving...')}\n </>\n ) : (\n <>\n <Save className=\"h-4 w-4\" />\n {t('kadaikodi.settings.save', 'Save Settings')}\n </>\n )}\n </button>\n </div>\n }\n >\n {/* Save message */}\n {saveMessage && (\n <div\n className={cn(\n 'mb-6 flex items-center gap-2 rounded-lg border p-3 text-sm',\n saveMessage.includes('successfully')\n ? 'border-status-success-text/30 bg-status-success-bg-subtle text-status-success-text'\n : 'border-status-error-text/30 bg-status-error-bg-subtle text-status-error-text'\n )}\n >\n {saveMessage.includes('successfully') ? (\n <CheckCircle2 className=\"h-4 w-4 shrink-0\" />\n ) : (\n <AlertTriangle className=\"h-4 w-4 shrink-0\" />\n )}\n {saveMessage}\n </div>\n )}\n\n <PagePurpose className=\"mb-6\">\n {t(\n 'kadaikodi.settings.purpose',\n 'Your personal control center on Kadaikodi. Use this page to manage your profile, app preferences (language, theme, notifications), security and login, privacy choices, and billing — everything about your own account in one place. Pick a section on the left, make your changes, and Save.'\n )}\n </PagePurpose>\n\n <NextSteps\n storageKey=\"kadaikodi-settings\"\n className=\"mb-6\"\n steps={[\n {\n id: 'security',\n label: t('kadaikodi.settings.next.security', 'Secure your account'),\n description: t(\n 'kadaikodi.settings.next.securityDesc',\n 'Update your password and review active devices.'\n ),\n onClick: () => setActiveTab('security'),\n },\n {\n id: 'preferences',\n label: t('kadaikodi.settings.next.preferences', 'Set your preferences'),\n description: t(\n 'kadaikodi.settings.next.preferencesDesc',\n 'Choose language, theme and notification settings.'\n ),\n onClick: () => setActiveTab('preferences'),\n },\n {\n id: 'billing',\n label: t('kadaikodi.settings.next.billing', 'Review billing'),\n description: t(\n 'kadaikodi.settings.next.billingDesc',\n 'Check your plan and payment method.'\n ),\n onClick: () => setActiveTab('billing'),\n },\n ]}\n />\n\n <div className=\"flex flex-col gap-6 lg:flex-row\">\n {/* Sidebar (Desktop) / Tab Row (Mobile) */}\n <div className=\"shrink-0 lg:w-56\">\n {/* Mobile grid */}\n <div className=\"grid grid-cols-5 gap-1 lg:hidden\">\n {localizedTabConfig.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 flex-col items-center gap-1 rounded-lg py-2.5 text-center transition-colors',\n activeTab === tab.id\n ? 'bg-action-primary-bg/10 text-text-primary'\n : 'text-text-secondary hover:text-text-primary hover:bg-accent'\n )}\n >\n <TabIcon className=\"h-4 w-4\" />\n <span className=\"text-xs font-medium\">{tab.label}</span>\n </button>\n );\n })}\n </div>\n {/* Desktop sidebar */}\n <div className=\"hidden lg:block rounded-lg border border-border-subtle bg-bg-surface\">\n <div className=\"p-3 border-b border-border-subtle\">\n <p className=\"text-sm font-semibold text-text-primary\">\n {t('kadaikodi.settings.title', 'Settings')}\n </p>\n </div>\n <nav className=\"p-2\">\n {localizedTabConfig.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 w-full items-center gap-2.5 rounded-lg px-3 py-2 text-sm font-medium transition-colors mb-0.5',\n activeTab === tab.id\n ? 'bg-action-primary-bg/10 text-text-primary'\n : 'text-text-secondary hover:text-text-primary hover:bg-accent'\n )}\n >\n <TabIcon className=\"h-4 w-4\" />\n {tab.label}\n </button>\n );\n })}\n </nav>\n </div>\n </div>\n\n {/* Content — the one emphasis zone for this page */}\n <EmphasisPanel className=\"flex-1 p-6\">{renderTab[activeTab]()}</EmphasisPanel>\n </div>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|