@burdenoff/microfe-kadaikodi 2026.704.4 → 2026.704.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/dist/kadaikodi/KadaikodiRoutes.js +30 -26
  2. package/dist/kadaikodi/KadaikodiRoutes.js.map +1 -1
  3. package/dist/kadaikodi/components/viz/AllocationBar.js +68 -0
  4. package/dist/kadaikodi/components/viz/AllocationBar.js.map +1 -0
  5. package/dist/kadaikodi/components/viz/AreaChart.js +102 -0
  6. package/dist/kadaikodi/components/viz/AreaChart.js.map +1 -0
  7. package/dist/kadaikodi/components/viz/AvatarStack.js +36 -0
  8. package/dist/kadaikodi/components/viz/AvatarStack.js.map +1 -0
  9. package/dist/kadaikodi/components/viz/BarChart.js +83 -0
  10. package/dist/kadaikodi/components/viz/BarChart.js.map +1 -0
  11. package/dist/kadaikodi/components/viz/CertificateCard.js +4 -0
  12. package/dist/kadaikodi/components/viz/DonutChart.js +109 -0
  13. package/dist/kadaikodi/components/viz/DonutChart.js.map +1 -0
  14. package/dist/kadaikodi/components/viz/HBarFunnel.js +54 -0
  15. package/dist/kadaikodi/components/viz/HBarFunnel.js.map +1 -0
  16. package/dist/kadaikodi/components/viz/Heatmap.js +3 -0
  17. package/dist/kadaikodi/components/viz/KanbanBoard.js +50 -0
  18. package/dist/kadaikodi/components/viz/KanbanBoard.js.map +1 -0
  19. package/dist/kadaikodi/components/viz/LineChart.js +4 -0
  20. package/dist/kadaikodi/components/viz/OrgTree.js +2 -0
  21. package/dist/kadaikodi/components/viz/PathSteps.js +3 -0
  22. package/dist/kadaikodi/components/viz/ProgressRing.js +68 -0
  23. package/dist/kadaikodi/components/viz/ProgressRing.js.map +1 -0
  24. package/dist/kadaikodi/components/viz/RatingStars.js +51 -0
  25. package/dist/kadaikodi/components/viz/RatingStars.js.map +1 -0
  26. package/dist/kadaikodi/components/viz/SegmentedTabs.js +69 -0
  27. package/dist/kadaikodi/components/viz/SegmentedTabs.js.map +1 -0
  28. package/dist/kadaikodi/components/viz/SkillBar.js +3 -0
  29. package/dist/kadaikodi/components/viz/Sparkline.js +74 -0
  30. package/dist/kadaikodi/components/viz/Sparkline.js.map +1 -0
  31. package/dist/kadaikodi/components/viz/StatCard.js +60 -0
  32. package/dist/kadaikodi/components/viz/StatCard.js.map +1 -0
  33. package/dist/kadaikodi/components/viz/StepProgress.js +64 -0
  34. package/dist/kadaikodi/components/viz/StepProgress.js.map +1 -0
  35. package/dist/kadaikodi/components/viz/Timeline.js +66 -0
  36. package/dist/kadaikodi/components/viz/Timeline.js.map +1 -0
  37. package/dist/kadaikodi/components/viz/index.js +23 -0
  38. package/dist/kadaikodi/components/viz/lib/Avatar.js +30 -0
  39. package/dist/kadaikodi/components/viz/lib/Avatar.js.map +1 -0
  40. package/dist/kadaikodi/components/viz/lib/CartesianFrame.js +119 -0
  41. package/dist/kadaikodi/components/viz/lib/CartesianFrame.js.map +1 -0
  42. package/dist/kadaikodi/components/viz/lib/ResponsiveSvg.js +35 -0
  43. package/dist/kadaikodi/components/viz/lib/ResponsiveSvg.js.map +1 -0
  44. package/dist/kadaikodi/components/viz/lib/format.js +21 -0
  45. package/dist/kadaikodi/components/viz/lib/format.js.map +1 -0
  46. package/dist/kadaikodi/components/viz/lib/geometry.js +61 -0
  47. package/dist/kadaikodi/components/viz/lib/geometry.js.map +1 -0
  48. package/dist/kadaikodi/components/viz/lib/hooks.js +39 -0
  49. package/dist/kadaikodi/components/viz/lib/hooks.js.map +1 -0
  50. package/dist/kadaikodi/components/viz/lib/palette.js +27 -0
  51. package/dist/kadaikodi/components/viz/lib/palette.js.map +1 -0
  52. package/dist/kadaikodi/hooks/useKadaikodiApi.js +18 -10
  53. package/dist/kadaikodi/hooks/useKadaikodiApi.js.map +1 -1
  54. package/dist/kadaikodi/pages/HomePage.js +373 -631
  55. package/dist/kadaikodi/pages/HomePage.js.map +1 -1
  56. package/dist/kadaikodi/pages/admin/AdminAnalyticsPage.js +304 -169
  57. package/dist/kadaikodi/pages/admin/AdminAnalyticsPage.js.map +1 -1
  58. package/dist/kadaikodi/pages/admin/AdminDashboard.js +255 -271
  59. package/dist/kadaikodi/pages/admin/AdminDashboard.js.map +1 -1
  60. package/dist/kadaikodi/pages/admin/AdminFinancialPage.js +185 -125
  61. package/dist/kadaikodi/pages/admin/AdminFinancialPage.js.map +1 -1
  62. package/dist/kadaikodi/pages/admin/AdminOrdersPage.js +141 -102
  63. package/dist/kadaikodi/pages/admin/AdminOrdersPage.js.map +1 -1
  64. package/dist/kadaikodi/pages/admin/CartManagementPage.js +558 -718
  65. package/dist/kadaikodi/pages/admin/CartManagementPage.js.map +1 -1
  66. package/dist/kadaikodi/pages/admin/UserManagementPage.js.map +1 -1
  67. package/dist/kadaikodi/pages/cart-owner/AnalyticsDashboard.js +142 -55
  68. package/dist/kadaikodi/pages/cart-owner/AnalyticsDashboard.js.map +1 -1
  69. package/dist/kadaikodi/pages/cart-owner/CartOwnerDashboard.js +129 -164
  70. package/dist/kadaikodi/pages/cart-owner/CartOwnerDashboard.js.map +1 -1
  71. package/dist/kadaikodi/pages/cart-owner/InventoryManagementPage.js +379 -361
  72. package/dist/kadaikodi/pages/cart-owner/InventoryManagementPage.js.map +1 -1
  73. package/dist/kadaikodi/pages/cart-owner/InvestmentListingPage.js +266 -166
  74. package/dist/kadaikodi/pages/cart-owner/InvestmentListingPage.js.map +1 -1
  75. package/dist/kadaikodi/pages/cart-owner/MerchantOnboardingPage.js +373 -0
  76. package/dist/kadaikodi/pages/cart-owner/MerchantOnboardingPage.js.map +1 -0
  77. package/dist/kadaikodi/pages/cart-owner/OrderManagementPage.js +288 -161
  78. package/dist/kadaikodi/pages/cart-owner/OrderManagementPage.js.map +1 -1
  79. package/dist/kadaikodi/pages/cart-owner/StaffManagementPage.js +180 -181
  80. package/dist/kadaikodi/pages/cart-owner/StaffManagementPage.js.map +1 -1
  81. package/dist/kadaikodi/pages/common/HelpSupportPage.js.map +1 -1
  82. package/dist/kadaikodi/pages/common/SettingsPage.js.map +1 -1
  83. package/dist/kadaikodi/pages/customer/BookingDetailsPage.js +17 -34
  84. package/dist/kadaikodi/pages/customer/BookingDetailsPage.js.map +1 -1
  85. package/dist/kadaikodi/pages/customer/CartDetailPage.js +405 -248
  86. package/dist/kadaikodi/pages/customer/CartDetailPage.js.map +1 -1
  87. package/dist/kadaikodi/pages/customer/CartDiscoveryPage.js +258 -232
  88. package/dist/kadaikodi/pages/customer/CartDiscoveryPage.js.map +1 -1
  89. package/dist/kadaikodi/pages/customer/CheckoutPage.js +254 -205
  90. package/dist/kadaikodi/pages/customer/CheckoutPage.js.map +1 -1
  91. package/dist/kadaikodi/pages/customer/DirectServiceBookingPage.js +270 -230
  92. package/dist/kadaikodi/pages/customer/DirectServiceBookingPage.js.map +1 -1
  93. package/dist/kadaikodi/pages/customer/FavoritesPage.js +149 -412
  94. package/dist/kadaikodi/pages/customer/FavoritesPage.js.map +1 -1
  95. package/dist/kadaikodi/pages/customer/OrderHistoryPage.js +173 -134
  96. package/dist/kadaikodi/pages/customer/OrderHistoryPage.js.map +1 -1
  97. package/dist/kadaikodi/pages/customer/OrderTrackingPage.js +176 -175
  98. package/dist/kadaikodi/pages/customer/OrderTrackingPage.js.map +1 -1
  99. package/dist/kadaikodi/pages/customer/ReviewsPage.js +295 -438
  100. package/dist/kadaikodi/pages/customer/ReviewsPage.js.map +1 -1
  101. package/dist/kadaikodi/pages/customer/shared.js +181 -0
  102. package/dist/kadaikodi/pages/customer/shared.js.map +1 -0
  103. package/dist/kadaikodi/pages/investor/InvestmentDetailsPage.js +438 -311
  104. package/dist/kadaikodi/pages/investor/InvestmentDetailsPage.js.map +1 -1
  105. package/dist/kadaikodi/pages/investor/InvestmentOpportunitiesPage.js +320 -293
  106. package/dist/kadaikodi/pages/investor/InvestmentOpportunitiesPage.js.map +1 -1
  107. package/dist/kadaikodi/pages/investor/InvestorAnalyticsPage.js +159 -91
  108. package/dist/kadaikodi/pages/investor/InvestorAnalyticsPage.js.map +1 -1
  109. package/dist/kadaikodi/pages/investor/InvestorDashboard.js +137 -107
  110. package/dist/kadaikodi/pages/investor/InvestorDashboard.js.map +1 -1
  111. package/dist/kadaikodi/pages/investor/InvestorInvestmentsPage.js +157 -135
  112. package/dist/kadaikodi/pages/investor/InvestorInvestmentsPage.js.map +1 -1
  113. package/dist/kadaikodi/pages/investor/InvestorPortfolioPage.js +280 -206
  114. package/dist/kadaikodi/pages/investor/InvestorPortfolioPage.js.map +1 -1
  115. package/dist/kadaikodi/pages/investor/InvestorProfilePage.js.map +1 -1
  116. package/dist/kadaikodi/pages/worker/TaskDetailsPage.js +424 -448
  117. package/dist/kadaikodi/pages/worker/TaskDetailsPage.js.map +1 -1
  118. package/dist/kadaikodi/pages/worker/WorkerDashboard.js +328 -445
  119. package/dist/kadaikodi/pages/worker/WorkerDashboard.js.map +1 -1
  120. package/dist/kadaikodi/pages/worker/WorkerOrdersPage.js +141 -164
  121. package/dist/kadaikodi/pages/worker/WorkerOrdersPage.js.map +1 -1
  122. package/dist/kadaikodi/pages/worker/WorkerProfilePage.js +300 -296
  123. package/dist/kadaikodi/pages/worker/WorkerProfilePage.js.map +1 -1
  124. package/dist/kadaikodi/pages/worker/WorkerSchedulePage.js +284 -309
  125. package/dist/kadaikodi/pages/worker/WorkerSchedulePage.js.map +1 -1
  126. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"InvestorInvestmentsPage.js","names":[],"sources":["../../../../src/kadaikodi/pages/investor/InvestorInvestmentsPage.tsx"],"sourcesContent":["/**\n * Investor Investments Page\n * @module kadaikodi/pages/investor\n *\n * Summary cards, status filter tabs with counts, responsive mobile/desktop\n * layouts, P&L display and status icons. All rows come from the live backend\n * (useInvestments) — no fabricated holdings.\n */\n\nimport { useMemo, useState } from 'react';\nimport {\n TrendingUp,\n TrendingDown,\n Eye,\n CheckCircle2,\n Clock,\n Wallet,\n IndianRupee,\n Plus,\n} from 'lucide-react';\nimport { EmphasisPanel, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { MetricsCard } from '../../components/MetricsCard';\nimport { EmptyState } from '../../components/EmptyState';\nimport { useKadaikodi } from '../../context/KadaikodiContext';\nimport { useInvestments } from '../../hooks/useKadaikodiApi';\nimport { cn } from '../../utils/cn';\nimport { formatCurrency, formatDate } from '../../utils/formatters';\nimport type { Investment } from '../../types';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype FilterKey = 'all' | 'active' | 'completed' | 'exited';\n\nconst filterTabs: Array<{ key: FilterKey; label: string }> = [\n { key: 'all', label: 'All Investments' },\n { key: 'active', label: 'Active' },\n { key: 'completed', label: 'Completed' },\n { key: 'exited', label: 'Exited' },\n];\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction getStatusColor(status: string): string {\n switch (status) {\n case 'active':\n return 'bg-status-success-bg-subtle text-status-success-text';\n case 'completed':\n return 'bg-[var(--color-accent-soft)] text-text-primary';\n case 'exited':\n return 'bg-bg-sunken text-text-secondary';\n default:\n return 'bg-bg-sunken text-text-secondary';\n }\n}\n\nfunction getStatusIcon(status: string) {\n switch (status) {\n case 'active':\n return <CheckCircle2 className=\"h-4 w-4\" />;\n case 'completed':\n return <CheckCircle2 className=\"h-4 w-4\" />;\n default:\n return <Clock className=\"h-4 w-4\" />;\n }\n}\n\nfunction profitLoss(inv: Investment): number {\n return inv.currentValue - inv.investedAmount;\n}\n\nfunction profitLossPct(inv: Investment): number {\n return inv.investedAmount > 0 ? (profitLoss(inv) / inv.investedAmount) * 100 : 0;\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nexport function InvestorInvestmentsPage() {\n const { navigateTo, currentUser } = useKadaikodi();\n const { data: investments = [], isLoading } = useInvestments(currentUser?.id || '');\n const [filter, setFilter] = useState<FilterKey>('all');\n\n const filteredInvestments = useMemo(() => {\n if (filter === 'all') return investments;\n return investments.filter((inv) => inv.status === filter);\n }, [filter, investments]);\n\n const summary = useMemo(() => {\n const totalInvested = investments.reduce((s, i) => s + i.investedAmount, 0);\n const currentValue = investments.reduce((s, i) => s + i.currentValue, 0);\n const totalReturns = investments.reduce((s, i) => s + i.returns, 0);\n const pl = currentValue - totalInvested;\n const plPct = totalInvested > 0 ? (pl / totalInvested) * 100 : 0;\n const activeInvestments = investments.filter((i) => i.status === 'active').length;\n return { totalInvested, currentValue, totalReturns, pl, plPct, activeInvestments };\n }, [investments]);\n\n function getCount(key: FilterKey): number {\n if (key === 'all') return investments.length;\n return investments.filter((inv) => inv.status === key).length;\n }\n\n if (isLoading) {\n return (\n <PageLayout title=\"My Investments\" description=\"Loading your investments...\">\n <div className=\"flex items-center justify-center py-20\">\n <div className=\"text-center\">\n <div className=\"mx-auto mb-4 h-12 w-12 animate-spin rounded-full border-b-2 border-primary\" />\n <p className=\"text-sm text-text-secondary\">Loading your investments...</p>\n </div>\n </div>\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title=\"My Investments\"\n description=\"Track and manage your investment portfolio\"\n actions={\n <button\n type=\"button\"\n onClick={() => navigateTo('/investor/opportunities')}\n className=\"flex items-center gap-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 <Plus className=\"h-4 w-4\" />\n New Investment\n </button>\n }\n >\n <PagePurpose className=\"mb-6\">\n Your active holdings in one place. Use this page to track every cart you&apos;ve backed —\n what you put in, what it&apos;s worth now, the returns you&apos;ve earned, and which\n investments are still active. Filter by status to focus, open any investment for the full\n picture, or start a New Investment when you&apos;re ready to grow your portfolio.\n </PagePurpose>\n\n {/* Investment Summary — the one emphasis zone for this page */}\n <EmphasisPanel>\n <h2 className=\"mb-4 text-base font-semibold text-text-primary\">Portfolio Summary</h2>\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n <MetricsCard\n icon={<Wallet className=\"h-5 w-5\" />}\n value={formatCurrency(summary.totalInvested, { minimumFractionDigits: 0 })}\n label=\"Total Invested\"\n />\n <MetricsCard\n icon={<IndianRupee className=\"h-5 w-5\" />}\n value={formatCurrency(summary.currentValue, { minimumFractionDigits: 0 })}\n label=\"Current Value\"\n trend={summary.pl >= 0 ? 'up' : 'down'}\n trendValue={`${summary.plPct >= 0 ? '+' : ''}${summary.plPct.toFixed(1)}%`}\n />\n <MetricsCard\n icon={<TrendingUp className=\"h-5 w-5\" />}\n value={formatCurrency(summary.totalReturns, { minimumFractionDigits: 0 })}\n label=\"Total Returns\"\n />\n <MetricsCard\n icon={<CheckCircle2 className=\"h-5 w-5\" />}\n value={String(summary.activeInvestments)}\n label=\"Active Investments\"\n trend=\"neutral\"\n />\n </div>\n </EmphasisPanel>\n\n {/* Filter Tabs */}\n <div className=\"mt-6 rounded-lg border border-border-subtle bg-bg-surface p-4\">\n <div className=\"flex flex-wrap gap-2\">\n {filterTabs.map((tab) => (\n <button\n key={tab.key}\n type=\"button\"\n onClick={() => setFilter(tab.key)}\n className={cn(\n 'flex items-center gap-2 rounded-lg px-4 py-2 text-sm font-medium transition-colors',\n filter === tab.key\n ? 'bg-action-primary-bg text-action-primary-text'\n : 'bg-bg-sunken text-text-primary hover:bg-bg-sunken/80'\n )}\n >\n {tab.label}\n <span\n className={cn(\n 'rounded-full px-2 py-0.5 text-xs',\n filter === tab.key\n ? 'bg-primary-foreground/20 text-action-primary-text'\n : 'bg-action-primary-bg/10 text-primary'\n )}\n >\n {getCount(tab.key)}\n </span>\n </button>\n ))}\n </div>\n </div>\n\n {/* Investments List */}\n <div className=\"mt-6 space-y-4\">\n {filteredInvestments.length > 0 ? (\n filteredInvestments.map((investment) => {\n const pl = profitLoss(investment);\n const plPct = profitLossPct(investment);\n return (\n <div\n key={investment.id}\n className=\"rounded-lg border border-border-subtle bg-bg-surface p-4 sm:p-6\"\n >\n {/* Mobile Layout */}\n <div className=\"block space-y-4 lg:hidden\">\n <div className=\"flex items-start justify-between\">\n <h3 className=\"text-lg font-semibold text-text-primary\">\n {investment.cartName}\n </h3>\n <span\n className={cn(\n 'flex items-center gap-1 rounded-full px-3 py-1 text-sm font-medium',\n getStatusColor(investment.status)\n )}\n >\n {getStatusIcon(investment.status)}\n <span className=\"capitalize\">{investment.status}</span>\n </span>\n </div>\n\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <p className=\"text-sm text-text-secondary\">Invested</p>\n <p className=\"font-semibold text-text-primary\">\n {formatCurrency(investment.investedAmount, { minimumFractionDigits: 0 })}\n </p>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">Current Value</p>\n <p className=\"font-semibold text-text-primary\">\n {formatCurrency(investment.currentValue, { minimumFractionDigits: 0 })}\n </p>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">P&L</p>\n <p\n className={cn(\n 'font-semibold',\n pl >= 0 ? 'text-status-success-text' : 'text-status-error-text'\n )}\n >\n {pl >= 0 ? '+' : ''}\n {formatCurrency(pl, { minimumFractionDigits: 0 })} ({plPct >= 0 ? '+' : ''}\n {plPct.toFixed(1)}%)\n </p>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">Expected Return</p>\n <p className=\"font-semibold text-text-primary\">\n {investment.returnsPercentage}%\n </p>\n </div>\n </div>\n\n <div className=\"flex items-center justify-between border-t border-border-subtle pt-2\">\n <div>\n <p className=\"text-xs text-text-secondary\">Invested on</p>\n <p className=\"text-sm font-medium text-text-primary\">\n {formatDate(investment.investmentDate, {\n hour: undefined,\n minute: undefined,\n })}\n </p>\n </div>\n <button\n type=\"button\"\n onClick={() => navigateTo(`/investor/investments/${investment.id}`)}\n className=\"flex items-center gap-2 rounded-lg border border-border-subtle px-3 py-2 text-sm font-medium text-text-primary hover:bg-accent transition-colors\"\n >\n <Eye className=\"h-4 w-4\" />\n View Details\n </button>\n </div>\n </div>\n\n {/* Desktop Layout */}\n <div className=\"hidden lg:flex lg:items-center lg:justify-between\">\n <div className=\"min-w-0 flex-1\">\n <div className=\"mb-4 flex items-center justify-between\">\n <h3 className=\"text-lg font-semibold text-text-primary\">\n {investment.cartName}\n </h3>\n <span\n className={cn(\n 'flex items-center gap-1 rounded-full px-3 py-1 text-sm font-medium',\n getStatusColor(investment.status)\n )}\n >\n {getStatusIcon(investment.status)}\n <span className=\"capitalize\">{investment.status}</span>\n </span>\n </div>\n\n <div className=\"grid grid-cols-5 gap-6\">\n <div>\n <p className=\"text-sm text-text-secondary\">Invested</p>\n <p className=\"font-semibold text-text-primary\">\n {formatCurrency(investment.investedAmount, { minimumFractionDigits: 0 })}\n </p>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">Current Value</p>\n <p className=\"font-semibold text-text-primary\">\n {formatCurrency(investment.currentValue, { minimumFractionDigits: 0 })}\n </p>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">P&L</p>\n <p\n className={cn(\n 'font-semibold',\n pl >= 0 ? 'text-status-success-text' : 'text-status-error-text'\n )}\n >\n {pl >= 0 ? '+' : ''}\n {formatCurrency(pl, { minimumFractionDigits: 0 })}\n </p>\n <p\n className={cn(\n 'text-xs',\n pl >= 0 ? 'text-status-success-text' : 'text-status-error-text'\n )}\n >\n ({plPct >= 0 ? '+' : ''}\n {plPct.toFixed(1)}%)\n </p>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">Expected Return</p>\n <p className=\"font-semibold text-text-primary\">\n {investment.returnsPercentage}%\n </p>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">Invested on</p>\n <p className=\"font-semibold text-text-primary\">\n {formatDate(investment.investmentDate, {\n hour: undefined,\n minute: undefined,\n })}\n </p>\n </div>\n </div>\n </div>\n\n <div className=\"ml-6\">\n <button\n type=\"button\"\n onClick={() => navigateTo(`/investor/investments/${investment.id}`)}\n className=\"flex items-center gap-2 rounded-lg border border-border-subtle px-3 py-2 text-sm font-medium text-text-primary hover:bg-accent transition-colors\"\n >\n <Eye className=\"h-4 w-4\" />\n View Details\n </button>\n </div>\n </div>\n </div>\n );\n })\n ) : (\n <EmptyState\n icon={<TrendingDown className=\"h-12 w-12\" />}\n title={`No ${filter !== 'all' ? filter : ''} investments found`}\n description={\n filter === 'all'\n ? \"You haven't made any investments yet. Start exploring opportunities to grow your wealth.\"\n : `You don't have any ${filter} investments at the moment.`\n }\n action={\n <button\n type=\"button\"\n onClick={() => navigateTo('/investor/opportunities')}\n className=\"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 Explore Investment Opportunities\n </button>\n }\n />\n )}\n </div>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"InvestorInvestmentsPage.js","names":[],"sources":["../../../../src/kadaikodi/pages/investor/InvestorInvestmentsPage.tsx"],"sourcesContent":["/**\n * Investor Investments Page\n * @module kadaikodi/pages/investor\n *\n * Summary cards, status filter tabs with counts, responsive mobile/desktop\n * layouts, P&L display and status icons. All rows come from the live backend\n * (useInvestments) — no fabricated holdings.\n */\n\nimport { useMemo, useState } from 'react';\nimport {\n TrendingUp,\n TrendingDown,\n Eye,\n CheckCircle2,\n Clock,\n Wallet,\n IndianRupee,\n Plus,\n} from 'lucide-react';\nimport { EmphasisPanel, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { MetricsCard } from '../../components/MetricsCard';\nimport { EmptyState } from '../../components/EmptyState';\nimport { AllocationBar } from '../../components/viz';\nimport { useKadaikodi } from '../../context/KadaikodiContext';\nimport { useInvestments } from '../../hooks/useKadaikodiApi';\nimport { cn } from '../../utils/cn';\nimport { formatCurrency, formatDate } from '../../utils/formatters';\nimport type { Investment } from '../../types';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype FilterKey = 'all' | 'active' | 'completed' | 'exited';\n\nconst filterTabs: Array<{ key: FilterKey; label: string }> = [\n { key: 'all', label: 'All Investments' },\n { key: 'active', label: 'Active' },\n { key: 'completed', label: 'Completed' },\n { key: 'exited', label: 'Exited' },\n];\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction getStatusColor(status: string): string {\n switch (status) {\n case 'active':\n return 'bg-status-success-bg-subtle text-status-success-text';\n case 'completed':\n return 'bg-[var(--color-accent-soft)] text-text-primary';\n case 'exited':\n return 'bg-bg-sunken text-text-secondary';\n default:\n return 'bg-bg-sunken text-text-secondary';\n }\n}\n\nfunction getStatusIcon(status: string) {\n switch (status) {\n case 'active':\n return <CheckCircle2 className=\"h-4 w-4\" />;\n case 'completed':\n return <CheckCircle2 className=\"h-4 w-4\" />;\n default:\n return <Clock className=\"h-4 w-4\" />;\n }\n}\n\nfunction profitLoss(inv: Investment): number {\n return inv.currentValue - inv.investedAmount;\n}\n\nfunction profitLossPct(inv: Investment): number {\n return inv.investedAmount > 0 ? (profitLoss(inv) / inv.investedAmount) * 100 : 0;\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nexport function InvestorInvestmentsPage() {\n const { navigateTo, currentUser } = useKadaikodi();\n const { data: investments = [], isLoading } = useInvestments(currentUser?.id || '');\n const [filter, setFilter] = useState<FilterKey>('all');\n\n const filteredInvestments = useMemo(() => {\n if (filter === 'all') return investments;\n return investments.filter((inv) => inv.status === filter);\n }, [filter, investments]);\n\n const summary = useMemo(() => {\n const totalInvested = investments.reduce((s, i) => s + i.investedAmount, 0);\n const currentValue = investments.reduce((s, i) => s + i.currentValue, 0);\n const totalReturns = investments.reduce((s, i) => s + i.returns, 0);\n const pl = currentValue - totalInvested;\n const plPct = totalInvested > 0 ? (pl / totalInvested) * 100 : 0;\n const activeInvestments = investments.filter((i) => i.status === 'active').length;\n return { totalInvested, currentValue, totalReturns, pl, plPct, activeInvestments };\n }, [investments]);\n\n // Allocation by cart (current value) — real, derived from the holdings.\n const allocationSegments = useMemo(() => {\n const map = investments.reduce<Record<string, number>>((acc, inv) => {\n acc[inv.cartName] = (acc[inv.cartName] || 0) + inv.currentValue;\n return acc;\n }, {});\n return Object.entries(map)\n .map(([label, value]) => ({ label, value }))\n .sort((a, b) => b.value - a.value);\n }, [investments]);\n\n function getCount(key: FilterKey): number {\n if (key === 'all') return investments.length;\n return investments.filter((inv) => inv.status === key).length;\n }\n\n if (isLoading) {\n return (\n <PageLayout title=\"My Investments\" description=\"Loading your investments...\">\n <div className=\"flex items-center justify-center py-20\">\n <div className=\"text-center\">\n <div className=\"mx-auto mb-4 h-12 w-12 animate-spin rounded-full border-b-2 border-primary\" />\n <p className=\"text-sm text-text-secondary\">Loading your investments...</p>\n </div>\n </div>\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title=\"My Investments\"\n description=\"Track and manage your investment portfolio\"\n actions={\n <button\n type=\"button\"\n onClick={() => navigateTo('/investor/opportunities')}\n className=\"flex items-center gap-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 <Plus className=\"h-4 w-4\" />\n New Investment\n </button>\n }\n >\n <PagePurpose className=\"mb-6\">\n Your active holdings in one place. Use this page to track every cart you&apos;ve backed —\n what you put in, what it&apos;s worth now, the returns you&apos;ve earned, and which\n investments are still active. Filter by status to focus, open any investment for the full\n picture, or start a New Investment when you&apos;re ready to grow your portfolio.\n </PagePurpose>\n\n {/* Investment Summary — the one emphasis zone for this page */}\n <EmphasisPanel>\n <h2 className=\"mb-4 text-base font-semibold text-text-primary\">Portfolio Summary</h2>\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n <MetricsCard\n icon={<Wallet className=\"h-5 w-5\" />}\n value={formatCurrency(summary.totalInvested, { minimumFractionDigits: 0 })}\n label=\"Total Invested\"\n />\n <MetricsCard\n icon={<IndianRupee className=\"h-5 w-5\" />}\n value={formatCurrency(summary.currentValue, { minimumFractionDigits: 0 })}\n label=\"Current Value\"\n trend={summary.pl >= 0 ? 'up' : 'down'}\n trendValue={`${summary.plPct >= 0 ? '+' : ''}${summary.plPct.toFixed(1)}%`}\n />\n <MetricsCard\n icon={<TrendingUp className=\"h-5 w-5\" />}\n value={formatCurrency(summary.totalReturns, { minimumFractionDigits: 0 })}\n label=\"Total Returns\"\n />\n <MetricsCard\n icon={<CheckCircle2 className=\"h-5 w-5\" />}\n value={String(summary.activeInvestments)}\n label=\"Active Investments\"\n trend=\"neutral\"\n />\n </div>\n\n {allocationSegments.length > 1 && (\n <div className=\"mt-4 rounded-lg border border-border-subtle bg-bg-surface p-4\">\n <AllocationBar\n segments={allocationSegments}\n label=\"Allocation by cart\"\n rightLabel={formatCurrency(summary.currentValue, {\n minimumFractionDigits: 0,\n notation: 'compact',\n })}\n />\n </div>\n )}\n </EmphasisPanel>\n\n {/* Filter Tabs */}\n <div className=\"mt-6 rounded-lg border border-border-subtle bg-bg-surface p-4\">\n <div className=\"flex flex-wrap gap-2\">\n {filterTabs.map((tab) => (\n <button\n key={tab.key}\n type=\"button\"\n onClick={() => setFilter(tab.key)}\n className={cn(\n 'flex items-center gap-2 rounded-lg px-4 py-2 text-sm font-medium transition-colors',\n filter === tab.key\n ? 'bg-action-primary-bg text-action-primary-text'\n : 'bg-bg-sunken text-text-primary hover:bg-bg-sunken/80'\n )}\n >\n {tab.label}\n <span\n className={cn(\n 'rounded-full px-2 py-0.5 text-xs',\n filter === tab.key\n ? 'bg-primary-foreground/20 text-action-primary-text'\n : 'bg-action-primary-bg/10 text-primary'\n )}\n >\n {getCount(tab.key)}\n </span>\n </button>\n ))}\n </div>\n </div>\n\n {/* Investments List */}\n <div className=\"mt-6 space-y-4\">\n {filteredInvestments.length > 0 ? (\n filteredInvestments.map((investment) => {\n const pl = profitLoss(investment);\n const plPct = profitLossPct(investment);\n return (\n <div\n key={investment.id}\n className=\"rounded-lg border border-border-subtle bg-bg-surface p-4 sm:p-6\"\n >\n {/* Mobile Layout */}\n <div className=\"block space-y-4 lg:hidden\">\n <div className=\"flex items-start justify-between\">\n <h3 className=\"text-lg font-semibold text-text-primary\">\n {investment.cartName}\n </h3>\n <span\n className={cn(\n 'flex items-center gap-1 rounded-full px-3 py-1 text-sm font-medium',\n getStatusColor(investment.status)\n )}\n >\n {getStatusIcon(investment.status)}\n <span className=\"capitalize\">{investment.status}</span>\n </span>\n </div>\n\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <p className=\"text-sm text-text-secondary\">Invested</p>\n <p className=\"font-semibold text-text-primary\">\n {formatCurrency(investment.investedAmount, { minimumFractionDigits: 0 })}\n </p>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">Current Value</p>\n <p className=\"font-semibold text-text-primary\">\n {formatCurrency(investment.currentValue, { minimumFractionDigits: 0 })}\n </p>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">P&L</p>\n <p\n className={cn(\n 'font-semibold',\n pl >= 0 ? 'text-status-success-text' : 'text-status-error-text'\n )}\n >\n {pl >= 0 ? '+' : ''}\n {formatCurrency(pl, { minimumFractionDigits: 0 })} ({plPct >= 0 ? '+' : ''}\n {plPct.toFixed(1)}%)\n </p>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">Expected Return</p>\n <p className=\"font-semibold text-text-primary\">\n {investment.returnsPercentage}%\n </p>\n </div>\n </div>\n\n <div className=\"flex items-center justify-between border-t border-border-subtle pt-2\">\n <div>\n <p className=\"text-xs text-text-secondary\">Invested on</p>\n <p className=\"text-sm font-medium text-text-primary\">\n {formatDate(investment.investmentDate, {\n hour: undefined,\n minute: undefined,\n })}\n </p>\n </div>\n <button\n type=\"button\"\n onClick={() => navigateTo(`/investor/investments/${investment.id}`)}\n className=\"flex items-center gap-2 rounded-lg border border-border-subtle px-3 py-2 text-sm font-medium text-text-primary hover:bg-accent transition-colors\"\n >\n <Eye className=\"h-4 w-4\" />\n View Details\n </button>\n </div>\n </div>\n\n {/* Desktop Layout */}\n <div className=\"hidden lg:flex lg:items-center lg:justify-between\">\n <div className=\"min-w-0 flex-1\">\n <div className=\"mb-4 flex items-center justify-between\">\n <h3 className=\"text-lg font-semibold text-text-primary\">\n {investment.cartName}\n </h3>\n <span\n className={cn(\n 'flex items-center gap-1 rounded-full px-3 py-1 text-sm font-medium',\n getStatusColor(investment.status)\n )}\n >\n {getStatusIcon(investment.status)}\n <span className=\"capitalize\">{investment.status}</span>\n </span>\n </div>\n\n <div className=\"grid grid-cols-5 gap-6\">\n <div>\n <p className=\"text-sm text-text-secondary\">Invested</p>\n <p className=\"font-semibold text-text-primary\">\n {formatCurrency(investment.investedAmount, { minimumFractionDigits: 0 })}\n </p>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">Current Value</p>\n <p className=\"font-semibold text-text-primary\">\n {formatCurrency(investment.currentValue, { minimumFractionDigits: 0 })}\n </p>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">P&L</p>\n <p\n className={cn(\n 'font-semibold',\n pl >= 0 ? 'text-status-success-text' : 'text-status-error-text'\n )}\n >\n {pl >= 0 ? '+' : ''}\n {formatCurrency(pl, { minimumFractionDigits: 0 })}\n </p>\n <p\n className={cn(\n 'text-xs',\n pl >= 0 ? 'text-status-success-text' : 'text-status-error-text'\n )}\n >\n ({plPct >= 0 ? '+' : ''}\n {plPct.toFixed(1)}%)\n </p>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">Expected Return</p>\n <p className=\"font-semibold text-text-primary\">\n {investment.returnsPercentage}%\n </p>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">Invested on</p>\n <p className=\"font-semibold text-text-primary\">\n {formatDate(investment.investmentDate, {\n hour: undefined,\n minute: undefined,\n })}\n </p>\n </div>\n </div>\n </div>\n\n <div className=\"ml-6\">\n <button\n type=\"button\"\n onClick={() => navigateTo(`/investor/investments/${investment.id}`)}\n className=\"flex items-center gap-2 rounded-lg border border-border-subtle px-3 py-2 text-sm font-medium text-text-primary hover:bg-accent transition-colors\"\n >\n <Eye className=\"h-4 w-4\" />\n View Details\n </button>\n </div>\n </div>\n </div>\n );\n })\n ) : (\n <EmptyState\n icon={<TrendingDown className=\"h-12 w-12\" />}\n title={`No ${filter !== 'all' ? filter : ''} investments found`}\n description={\n filter === 'all'\n ? \"You haven't made any investments yet. Start exploring opportunities to grow your wealth.\"\n : `You don't have any ${filter} investments at the moment.`\n }\n action={\n <button\n type=\"button\"\n onClick={() => navigateTo('/investor/opportunities')}\n className=\"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 Explore Investment Opportunities\n </button>\n }\n />\n )}\n </div>\n </PageLayout>\n );\n}\n"],"mappings":"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"}