@burdenoff/microfe-brainyrich 2026.805.1 → 2026.825.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (504) hide show
  1. package/dist/_virtual/_rolldown/runtime.js +1 -1
  2. package/dist/brainyrich/BrainyRichRoot.d.ts +0 -1
  3. package/dist/brainyrich/BrainyRichRoot.js.map +1 -1
  4. package/dist/brainyrich/BrainyRichRoutes.d.ts.map +1 -1
  5. package/dist/brainyrich/BrainyRichRoutes.js +21 -17
  6. package/dist/brainyrich/BrainyRichRoutes.js.map +1 -1
  7. package/dist/brainyrich/components/ActorName.js.map +1 -1
  8. package/dist/brainyrich/components/ConfirmDialog.d.ts +0 -1
  9. package/dist/brainyrich/components/ConfirmDialog.js.map +1 -1
  10. package/dist/brainyrich/components/LoadMore.js.map +1 -1
  11. package/dist/brainyrich/components/notify.js.map +1 -1
  12. package/dist/brainyrich/components/pickers.js.map +1 -1
  13. package/dist/brainyrich/components/reuse/CommentThread.js.map +1 -1
  14. package/dist/brainyrich/components/reuse/DocumentsPanel.js.map +1 -1
  15. package/dist/brainyrich/components/reuse/TagField.js.map +1 -1
  16. package/dist/brainyrich/components/reuse/transport.js.map +1 -1
  17. package/dist/brainyrich/components/viz.d.ts +0 -1
  18. package/dist/brainyrich/components/viz.js.map +1 -1
  19. package/dist/brainyrich/hooks/useBrainyRichAnalytics.js.map +1 -1
  20. package/dist/brainyrich/hooks/useBrainyRichApi.d.ts +3 -2
  21. package/dist/brainyrich/hooks/useBrainyRichApi.d.ts.map +1 -1
  22. package/dist/brainyrich/hooks/useBrainyRichApi.js +20 -12
  23. package/dist/brainyrich/hooks/useBrainyRichApi.js.map +1 -1
  24. package/dist/brainyrich/pages/AccountsPage.d.ts.map +1 -1
  25. package/dist/brainyrich/pages/AccountsPage.js +367 -363
  26. package/dist/brainyrich/pages/AccountsPage.js.map +1 -1
  27. package/dist/brainyrich/pages/AdminFirmPage.d.ts +2 -0
  28. package/dist/brainyrich/pages/AdminFirmPage.d.ts.map +1 -0
  29. package/dist/brainyrich/pages/AdminFirmPage.js +137 -0
  30. package/dist/brainyrich/pages/AdminFirmPage.js.map +1 -0
  31. package/dist/brainyrich/pages/AiAssistantPage.js.map +1 -1
  32. package/dist/brainyrich/pages/AnalyticsPage.js.map +1 -1
  33. package/dist/brainyrich/pages/DashboardPage.js.map +1 -1
  34. package/dist/brainyrich/pages/FamilyPage.js.map +1 -1
  35. package/dist/brainyrich/pages/FirmPage.js.map +1 -1
  36. package/dist/brainyrich/pages/GoalsPage.js.map +1 -1
  37. package/dist/brainyrich/pages/InvestmentsPage.js.map +1 -1
  38. package/dist/brainyrich/pages/PortfoliosPage.js.map +1 -1
  39. package/dist/brainyrich/pages/ReportsPage.js.map +1 -1
  40. package/dist/brainyrich/pages/RiskPage.js.map +1 -1
  41. package/dist/brainyrich/pages/TaxPage.js.map +1 -1
  42. package/dist/brainyrich/pages/_shared.d.ts +0 -1
  43. package/dist/brainyrich/pages/_shared.js.map +1 -1
  44. package/dist/brainyrich/providers/BrainyRichProvider.d.ts +0 -1
  45. package/dist/brainyrich/providers/BrainyRichProvider.js.map +1 -1
  46. package/dist/brainyrich/services/createSandboxAssistantTransport.js.map +1 -1
  47. package/dist/brainyrich/types/bra.d.ts +15 -0
  48. package/dist/brainyrich/types/bra.d.ts.map +1 -1
  49. package/dist/brainyrich/types/index.d.ts +0 -1
  50. package/dist/brainyrich/utils/cn.d.ts +0 -1
  51. package/dist/brainyrich/utils/i18n.d.ts +0 -1
  52. package/dist/brainyrich/utils/i18n.js.map +1 -1
  53. package/dist/brainyrich/utils/nativeControls.d.ts +0 -1
  54. package/dist/brainyrich/utils/nativeControls.js.map +1 -1
  55. package/dist/brainyrich/utils/navigation.js.map +1 -1
  56. package/dist/brainyrich/utils/pageContext.js.map +1 -1
  57. package/dist/dev/main.d.ts +0 -1
  58. package/dist/node_modules/clsx/dist/clsx.js.map +1 -1
  59. package/dist/node_modules/d3-array/src/ascending.js.map +1 -1
  60. package/dist/node_modules/d3-array/src/bisect.js.map +1 -1
  61. package/dist/node_modules/d3-array/src/bisector.js.map +1 -1
  62. package/dist/node_modules/d3-array/src/descending.js.map +1 -1
  63. package/dist/node_modules/d3-array/src/max.js.map +1 -1
  64. package/dist/node_modules/d3-array/src/min.js.map +1 -1
  65. package/dist/node_modules/d3-array/src/number.js.map +1 -1
  66. package/dist/node_modules/d3-array/src/quantile.js.map +1 -1
  67. package/dist/node_modules/d3-array/src/quickselect.js.map +1 -1
  68. package/dist/node_modules/d3-array/src/range.js.map +1 -1
  69. package/dist/node_modules/d3-array/src/sort.js.map +1 -1
  70. package/dist/node_modules/d3-array/src/ticks.js.map +1 -1
  71. package/dist/node_modules/d3-color/src/color.js.map +1 -1
  72. package/dist/node_modules/d3-color/src/define.js.map +1 -1
  73. package/dist/node_modules/d3-format/src/defaultLocale.js.map +1 -1
  74. package/dist/node_modules/d3-format/src/exponent.js.map +1 -1
  75. package/dist/node_modules/d3-format/src/formatDecimal.js.map +1 -1
  76. package/dist/node_modules/d3-format/src/formatGroup.js.map +1 -1
  77. package/dist/node_modules/d3-format/src/formatNumerals.js.map +1 -1
  78. package/dist/node_modules/d3-format/src/formatPrefixAuto.js.map +1 -1
  79. package/dist/node_modules/d3-format/src/formatRounded.js.map +1 -1
  80. package/dist/node_modules/d3-format/src/formatSpecifier.js.map +1 -1
  81. package/dist/node_modules/d3-format/src/formatTrim.js.map +1 -1
  82. package/dist/node_modules/d3-format/src/formatTypes.js.map +1 -1
  83. package/dist/node_modules/d3-format/src/identity.js.map +1 -1
  84. package/dist/node_modules/d3-format/src/locale.js.map +1 -1
  85. package/dist/node_modules/d3-format/src/precisionFixed.js.map +1 -1
  86. package/dist/node_modules/d3-format/src/precisionPrefix.js.map +1 -1
  87. package/dist/node_modules/d3-format/src/precisionRound.js.map +1 -1
  88. package/dist/node_modules/d3-interpolate/src/array.js.map +1 -1
  89. package/dist/node_modules/d3-interpolate/src/basis.js.map +1 -1
  90. package/dist/node_modules/d3-interpolate/src/basisClosed.js.map +1 -1
  91. package/dist/node_modules/d3-interpolate/src/color.js.map +1 -1
  92. package/dist/node_modules/d3-interpolate/src/date.js.map +1 -1
  93. package/dist/node_modules/d3-interpolate/src/number.js.map +1 -1
  94. package/dist/node_modules/d3-interpolate/src/numberArray.js.map +1 -1
  95. package/dist/node_modules/d3-interpolate/src/object.js.map +1 -1
  96. package/dist/node_modules/d3-interpolate/src/piecewise.js.map +1 -1
  97. package/dist/node_modules/d3-interpolate/src/rgb.js.map +1 -1
  98. package/dist/node_modules/d3-interpolate/src/round.js.map +1 -1
  99. package/dist/node_modules/d3-interpolate/src/string.js.map +1 -1
  100. package/dist/node_modules/d3-interpolate/src/value.js.map +1 -1
  101. package/dist/node_modules/d3-path/src/path.js.map +1 -1
  102. package/dist/node_modules/d3-scale/src/band.js.map +1 -1
  103. package/dist/node_modules/d3-scale/src/constant.js.map +1 -1
  104. package/dist/node_modules/d3-scale/src/continuous.js.map +1 -1
  105. package/dist/node_modules/d3-scale/src/diverging.js.map +1 -1
  106. package/dist/node_modules/d3-scale/src/identity.js.map +1 -1
  107. package/dist/node_modules/d3-scale/src/init.js.map +1 -1
  108. package/dist/node_modules/d3-scale/src/linear.js.map +1 -1
  109. package/dist/node_modules/d3-scale/src/log.js.map +1 -1
  110. package/dist/node_modules/d3-scale/src/nice.js.map +1 -1
  111. package/dist/node_modules/d3-scale/src/number.js.map +1 -1
  112. package/dist/node_modules/d3-scale/src/ordinal.js.map +1 -1
  113. package/dist/node_modules/d3-scale/src/pow.js.map +1 -1
  114. package/dist/node_modules/d3-scale/src/quantile.js.map +1 -1
  115. package/dist/node_modules/d3-scale/src/quantize.js.map +1 -1
  116. package/dist/node_modules/d3-scale/src/radial.js.map +1 -1
  117. package/dist/node_modules/d3-scale/src/sequential.js.map +1 -1
  118. package/dist/node_modules/d3-scale/src/sequentialQuantile.js.map +1 -1
  119. package/dist/node_modules/d3-scale/src/symlog.js.map +1 -1
  120. package/dist/node_modules/d3-scale/src/threshold.js.map +1 -1
  121. package/dist/node_modules/d3-scale/src/tickFormat.js.map +1 -1
  122. package/dist/node_modules/d3-scale/src/time.js.map +1 -1
  123. package/dist/node_modules/d3-scale/src/utcTime.js.map +1 -1
  124. package/dist/node_modules/d3-shape/src/area.js.map +1 -1
  125. package/dist/node_modules/d3-shape/src/array.js.map +1 -1
  126. package/dist/node_modules/d3-shape/src/constant.js.map +1 -1
  127. package/dist/node_modules/d3-shape/src/curve/basis.js.map +1 -1
  128. package/dist/node_modules/d3-shape/src/curve/basisClosed.js.map +1 -1
  129. package/dist/node_modules/d3-shape/src/curve/basisOpen.js.map +1 -1
  130. package/dist/node_modules/d3-shape/src/curve/bump.js.map +1 -1
  131. package/dist/node_modules/d3-shape/src/curve/linear.js.map +1 -1
  132. package/dist/node_modules/d3-shape/src/curve/linearClosed.js.map +1 -1
  133. package/dist/node_modules/d3-shape/src/curve/monotone.js.map +1 -1
  134. package/dist/node_modules/d3-shape/src/curve/natural.js.map +1 -1
  135. package/dist/node_modules/d3-shape/src/curve/step.js.map +1 -1
  136. package/dist/node_modules/d3-shape/src/line.js.map +1 -1
  137. package/dist/node_modules/d3-shape/src/noop.js.map +1 -1
  138. package/dist/node_modules/d3-shape/src/offset/expand.js.map +1 -1
  139. package/dist/node_modules/d3-shape/src/offset/none.js.map +1 -1
  140. package/dist/node_modules/d3-shape/src/offset/silhouette.js.map +1 -1
  141. package/dist/node_modules/d3-shape/src/offset/wiggle.js.map +1 -1
  142. package/dist/node_modules/d3-shape/src/order/none.js.map +1 -1
  143. package/dist/node_modules/d3-shape/src/path.js.map +1 -1
  144. package/dist/node_modules/d3-shape/src/point.js.map +1 -1
  145. package/dist/node_modules/d3-shape/src/stack.js.map +1 -1
  146. package/dist/node_modules/d3-shape/src/symbol/circle.js.map +1 -1
  147. package/dist/node_modules/d3-shape/src/symbol/cross.js.map +1 -1
  148. package/dist/node_modules/d3-shape/src/symbol/diamond.js.map +1 -1
  149. package/dist/node_modules/d3-shape/src/symbol/square.js.map +1 -1
  150. package/dist/node_modules/d3-shape/src/symbol/star.js.map +1 -1
  151. package/dist/node_modules/d3-shape/src/symbol/triangle.js.map +1 -1
  152. package/dist/node_modules/d3-shape/src/symbol/wye.js.map +1 -1
  153. package/dist/node_modules/d3-shape/src/symbol.js.map +1 -1
  154. package/dist/node_modules/d3-time/src/day.js.map +1 -1
  155. package/dist/node_modules/d3-time/src/hour.js.map +1 -1
  156. package/dist/node_modules/d3-time/src/interval.js.map +1 -1
  157. package/dist/node_modules/d3-time/src/millisecond.js.map +1 -1
  158. package/dist/node_modules/d3-time/src/minute.js.map +1 -1
  159. package/dist/node_modules/d3-time/src/month.js.map +1 -1
  160. package/dist/node_modules/d3-time/src/second.js.map +1 -1
  161. package/dist/node_modules/d3-time/src/ticks.js.map +1 -1
  162. package/dist/node_modules/d3-time/src/week.js.map +1 -1
  163. package/dist/node_modules/d3-time/src/year.js.map +1 -1
  164. package/dist/node_modules/d3-time-format/src/defaultLocale.js.map +1 -1
  165. package/dist/node_modules/d3-time-format/src/locale.js.map +1 -1
  166. package/dist/node_modules/decimal.js-light/decimal.js.map +1 -1
  167. package/dist/node_modules/eventemitter3/index.js.map +1 -1
  168. package/dist/node_modules/fast-equals/dist/es/index.js.map +1 -1
  169. package/dist/node_modules/internmap/src/index.js.map +1 -1
  170. package/dist/node_modules/lodash/_DataView.js.map +1 -1
  171. package/dist/node_modules/lodash/_Hash.js.map +1 -1
  172. package/dist/node_modules/lodash/_ListCache.js.map +1 -1
  173. package/dist/node_modules/lodash/_Map.js.map +1 -1
  174. package/dist/node_modules/lodash/_MapCache.js.map +1 -1
  175. package/dist/node_modules/lodash/_Promise.js.map +1 -1
  176. package/dist/node_modules/lodash/_Set.js.map +1 -1
  177. package/dist/node_modules/lodash/_SetCache.js.map +1 -1
  178. package/dist/node_modules/lodash/_Stack.js +2 -1
  179. package/dist/node_modules/lodash/_Stack.js.map +1 -1
  180. package/dist/node_modules/lodash/_Symbol.js.map +1 -1
  181. package/dist/node_modules/lodash/_Uint8Array.js.map +1 -1
  182. package/dist/node_modules/lodash/_WeakMap.js.map +1 -1
  183. package/dist/node_modules/lodash/_apply.js.map +1 -1
  184. package/dist/node_modules/lodash/_arrayEvery.js.map +1 -1
  185. package/dist/node_modules/lodash/_arrayFilter.js.map +1 -1
  186. package/dist/node_modules/lodash/_arrayIncludes.js.map +1 -1
  187. package/dist/node_modules/lodash/_arrayIncludesWith.js.map +1 -1
  188. package/dist/node_modules/lodash/_arrayLikeKeys.js.map +1 -1
  189. package/dist/node_modules/lodash/_arrayMap.js.map +1 -1
  190. package/dist/node_modules/lodash/_arrayPush.js.map +1 -1
  191. package/dist/node_modules/lodash/_arraySome.js.map +1 -1
  192. package/dist/node_modules/lodash/_asciiToArray.js.map +1 -1
  193. package/dist/node_modules/lodash/_assocIndexOf.js.map +1 -1
  194. package/dist/node_modules/lodash/_baseAssignValue.js.map +1 -1
  195. package/dist/node_modules/lodash/_baseEach.js.map +1 -1
  196. package/dist/node_modules/lodash/_baseEvery.js.map +1 -1
  197. package/dist/node_modules/lodash/_baseExtremum.js.map +1 -1
  198. package/dist/node_modules/lodash/_baseFindIndex.js.map +1 -1
  199. package/dist/node_modules/lodash/_baseFlatten.js.map +1 -1
  200. package/dist/node_modules/lodash/_baseFor.js.map +1 -1
  201. package/dist/node_modules/lodash/_baseForOwn.js.map +1 -1
  202. package/dist/node_modules/lodash/_baseGet.js.map +1 -1
  203. package/dist/node_modules/lodash/_baseGetAllKeys.js.map +1 -1
  204. package/dist/node_modules/lodash/_baseGetTag.js.map +1 -1
  205. package/dist/node_modules/lodash/_baseGt.js.map +1 -1
  206. package/dist/node_modules/lodash/_baseHasIn.js.map +1 -1
  207. package/dist/node_modules/lodash/_baseIndexOf.js.map +1 -1
  208. package/dist/node_modules/lodash/_baseIsArguments.js.map +1 -1
  209. package/dist/node_modules/lodash/_baseIsEqual.js.map +1 -1
  210. package/dist/node_modules/lodash/_baseIsEqualDeep.js.map +1 -1
  211. package/dist/node_modules/lodash/_baseIsMatch.js.map +1 -1
  212. package/dist/node_modules/lodash/_baseIsNaN.js.map +1 -1
  213. package/dist/node_modules/lodash/_baseIsNative.js.map +1 -1
  214. package/dist/node_modules/lodash/_baseIsTypedArray.js.map +1 -1
  215. package/dist/node_modules/lodash/_baseIteratee.js.map +1 -1
  216. package/dist/node_modules/lodash/_baseKeys.js.map +1 -1
  217. package/dist/node_modules/lodash/_baseLt.js.map +1 -1
  218. package/dist/node_modules/lodash/_baseMap.js.map +1 -1
  219. package/dist/node_modules/lodash/_baseMatches.js.map +1 -1
  220. package/dist/node_modules/lodash/_baseMatchesProperty.js.map +1 -1
  221. package/dist/node_modules/lodash/_baseOrderBy.js.map +1 -1
  222. package/dist/node_modules/lodash/_baseProperty.js.map +1 -1
  223. package/dist/node_modules/lodash/_basePropertyDeep.js.map +1 -1
  224. package/dist/node_modules/lodash/_baseRange.js.map +1 -1
  225. package/dist/node_modules/lodash/_baseRest.js.map +1 -1
  226. package/dist/node_modules/lodash/_baseSetToString.js.map +1 -1
  227. package/dist/node_modules/lodash/_baseSlice.js.map +1 -1
  228. package/dist/node_modules/lodash/_baseSome.js.map +1 -1
  229. package/dist/node_modules/lodash/_baseSortBy.js.map +1 -1
  230. package/dist/node_modules/lodash/_baseTimes.js.map +1 -1
  231. package/dist/node_modules/lodash/_baseToString.js.map +1 -1
  232. package/dist/node_modules/lodash/_baseTrim.js.map +1 -1
  233. package/dist/node_modules/lodash/_baseUnary.js.map +1 -1
  234. package/dist/node_modules/lodash/_baseUniq.js.map +1 -1
  235. package/dist/node_modules/lodash/_cacheHas.js.map +1 -1
  236. package/dist/node_modules/lodash/_castPath.js.map +1 -1
  237. package/dist/node_modules/lodash/_castSlice.js.map +1 -1
  238. package/dist/node_modules/lodash/_compareAscending.js.map +1 -1
  239. package/dist/node_modules/lodash/_compareMultiple.js.map +1 -1
  240. package/dist/node_modules/lodash/_coreJsData.js.map +1 -1
  241. package/dist/node_modules/lodash/_createBaseEach.js.map +1 -1
  242. package/dist/node_modules/lodash/_createBaseFor.js.map +1 -1
  243. package/dist/node_modules/lodash/_createCaseFirst.js.map +1 -1
  244. package/dist/node_modules/lodash/_createFind.js.map +1 -1
  245. package/dist/node_modules/lodash/_createRange.js.map +1 -1
  246. package/dist/node_modules/lodash/_createSet.js.map +1 -1
  247. package/dist/node_modules/lodash/_defineProperty.js.map +1 -1
  248. package/dist/node_modules/lodash/_equalArrays.js.map +1 -1
  249. package/dist/node_modules/lodash/_equalByTag.js.map +1 -1
  250. package/dist/node_modules/lodash/_equalObjects.js.map +1 -1
  251. package/dist/node_modules/lodash/_freeGlobal.js.map +1 -1
  252. package/dist/node_modules/lodash/_getAllKeys.js.map +1 -1
  253. package/dist/node_modules/lodash/_getMapData.js.map +1 -1
  254. package/dist/node_modules/lodash/_getMatchData.js.map +1 -1
  255. package/dist/node_modules/lodash/_getNative.js.map +1 -1
  256. package/dist/node_modules/lodash/_getPrototype.js.map +1 -1
  257. package/dist/node_modules/lodash/_getRawTag.js.map +1 -1
  258. package/dist/node_modules/lodash/_getSymbols.js.map +1 -1
  259. package/dist/node_modules/lodash/_getTag.js.map +1 -1
  260. package/dist/node_modules/lodash/_getValue.js.map +1 -1
  261. package/dist/node_modules/lodash/_hasPath.js.map +1 -1
  262. package/dist/node_modules/lodash/_hasUnicode.js.map +1 -1
  263. package/dist/node_modules/lodash/_hashClear.js.map +1 -1
  264. package/dist/node_modules/lodash/_hashDelete.js.map +1 -1
  265. package/dist/node_modules/lodash/_hashGet.js.map +1 -1
  266. package/dist/node_modules/lodash/_hashHas.js.map +1 -1
  267. package/dist/node_modules/lodash/_hashSet.js.map +1 -1
  268. package/dist/node_modules/lodash/_isFlattenable.js.map +1 -1
  269. package/dist/node_modules/lodash/_isIndex.js.map +1 -1
  270. package/dist/node_modules/lodash/_isIterateeCall.js.map +1 -1
  271. package/dist/node_modules/lodash/_isKey.js.map +1 -1
  272. package/dist/node_modules/lodash/_isKeyable.js.map +1 -1
  273. package/dist/node_modules/lodash/_isMasked.js.map +1 -1
  274. package/dist/node_modules/lodash/_isPrototype.js.map +1 -1
  275. package/dist/node_modules/lodash/_isStrictComparable.js.map +1 -1
  276. package/dist/node_modules/lodash/_listCacheClear.js.map +1 -1
  277. package/dist/node_modules/lodash/_listCacheDelete.js.map +1 -1
  278. package/dist/node_modules/lodash/_listCacheGet.js.map +1 -1
  279. package/dist/node_modules/lodash/_listCacheHas.js.map +1 -1
  280. package/dist/node_modules/lodash/_listCacheSet.js.map +1 -1
  281. package/dist/node_modules/lodash/_mapCacheClear.js.map +1 -1
  282. package/dist/node_modules/lodash/_mapCacheDelete.js.map +1 -1
  283. package/dist/node_modules/lodash/_mapCacheGet.js.map +1 -1
  284. package/dist/node_modules/lodash/_mapCacheHas.js.map +1 -1
  285. package/dist/node_modules/lodash/_mapCacheSet.js.map +1 -1
  286. package/dist/node_modules/lodash/_mapToArray.js.map +1 -1
  287. package/dist/node_modules/lodash/_matchesStrictComparable.js.map +1 -1
  288. package/dist/node_modules/lodash/_memoizeCapped.js.map +1 -1
  289. package/dist/node_modules/lodash/_nativeCreate.js.map +1 -1
  290. package/dist/node_modules/lodash/_nativeKeys.js.map +1 -1
  291. package/dist/node_modules/lodash/_nodeUtil.js.map +1 -1
  292. package/dist/node_modules/lodash/_objectToString.js.map +1 -1
  293. package/dist/node_modules/lodash/_overArg.js.map +1 -1
  294. package/dist/node_modules/lodash/_overRest.js.map +1 -1
  295. package/dist/node_modules/lodash/_root.js.map +1 -1
  296. package/dist/node_modules/lodash/_setCacheAdd.js.map +1 -1
  297. package/dist/node_modules/lodash/_setCacheHas.js.map +1 -1
  298. package/dist/node_modules/lodash/_setToArray.js.map +1 -1
  299. package/dist/node_modules/lodash/_setToString.js.map +1 -1
  300. package/dist/node_modules/lodash/_shortOut.js.map +1 -1
  301. package/dist/node_modules/lodash/_stackClear.js.map +1 -1
  302. package/dist/node_modules/lodash/_stackDelete.js.map +1 -1
  303. package/dist/node_modules/lodash/_stackGet.js.map +1 -1
  304. package/dist/node_modules/lodash/_stackHas.js.map +1 -1
  305. package/dist/node_modules/lodash/_stackSet.js.map +1 -1
  306. package/dist/node_modules/lodash/_strictIndexOf.js.map +1 -1
  307. package/dist/node_modules/lodash/_stringToArray.js.map +1 -1
  308. package/dist/node_modules/lodash/_stringToPath.js.map +1 -1
  309. package/dist/node_modules/lodash/_toKey.js.map +1 -1
  310. package/dist/node_modules/lodash/_toSource.js.map +1 -1
  311. package/dist/node_modules/lodash/_trimmedEndIndex.js.map +1 -1
  312. package/dist/node_modules/lodash/_unicodeToArray.js.map +1 -1
  313. package/dist/node_modules/lodash/constant.js.map +1 -1
  314. package/dist/node_modules/lodash/debounce.js.map +1 -1
  315. package/dist/node_modules/lodash/eq.js.map +1 -1
  316. package/dist/node_modules/lodash/every.js.map +1 -1
  317. package/dist/node_modules/lodash/find.js.map +1 -1
  318. package/dist/node_modules/lodash/findIndex.js.map +1 -1
  319. package/dist/node_modules/lodash/flatMap.js.map +1 -1
  320. package/dist/node_modules/lodash/get.js.map +1 -1
  321. package/dist/node_modules/lodash/hasIn.js.map +1 -1
  322. package/dist/node_modules/lodash/identity.js.map +1 -1
  323. package/dist/node_modules/lodash/isArguments.js.map +1 -1
  324. package/dist/node_modules/lodash/isArray.js.map +1 -1
  325. package/dist/node_modules/lodash/isArrayLike.js.map +1 -1
  326. package/dist/node_modules/lodash/isBoolean.js.map +1 -1
  327. package/dist/node_modules/lodash/isBuffer.js.map +1 -1
  328. package/dist/node_modules/lodash/isEqual.js.map +1 -1
  329. package/dist/node_modules/lodash/isFunction.js.map +1 -1
  330. package/dist/node_modules/lodash/isLength.js.map +1 -1
  331. package/dist/node_modules/lodash/isNaN.js.map +1 -1
  332. package/dist/node_modules/lodash/isNil.js.map +1 -1
  333. package/dist/node_modules/lodash/isNumber.js.map +1 -1
  334. package/dist/node_modules/lodash/isObject.js.map +1 -1
  335. package/dist/node_modules/lodash/isObjectLike.js.map +1 -1
  336. package/dist/node_modules/lodash/isPlainObject.js.map +1 -1
  337. package/dist/node_modules/lodash/isString.js.map +1 -1
  338. package/dist/node_modules/lodash/isSymbol.js.map +1 -1
  339. package/dist/node_modules/lodash/isTypedArray.js.map +1 -1
  340. package/dist/node_modules/lodash/keys.js.map +1 -1
  341. package/dist/node_modules/lodash/last.js.map +1 -1
  342. package/dist/node_modules/lodash/map.js.map +1 -1
  343. package/dist/node_modules/lodash/mapValues.js.map +1 -1
  344. package/dist/node_modules/lodash/max.js.map +1 -1
  345. package/dist/node_modules/lodash/maxBy.js.map +1 -1
  346. package/dist/node_modules/lodash/memoize.js.map +1 -1
  347. package/dist/node_modules/lodash/min.js.map +1 -1
  348. package/dist/node_modules/lodash/minBy.js.map +1 -1
  349. package/dist/node_modules/lodash/noop.js.map +1 -1
  350. package/dist/node_modules/lodash/now.js.map +1 -1
  351. package/dist/node_modules/lodash/property.js.map +1 -1
  352. package/dist/node_modules/lodash/range.js.map +1 -1
  353. package/dist/node_modules/lodash/some.js.map +1 -1
  354. package/dist/node_modules/lodash/sortBy.js.map +1 -1
  355. package/dist/node_modules/lodash/stubArray.js.map +1 -1
  356. package/dist/node_modules/lodash/stubFalse.js.map +1 -1
  357. package/dist/node_modules/lodash/throttle.js.map +1 -1
  358. package/dist/node_modules/lodash/toFinite.js.map +1 -1
  359. package/dist/node_modules/lodash/toInteger.js.map +1 -1
  360. package/dist/node_modules/lodash/toNumber.js.map +1 -1
  361. package/dist/node_modules/lodash/toString.js.map +1 -1
  362. package/dist/node_modules/lodash/uniqBy.js.map +1 -1
  363. package/dist/node_modules/lodash/upperFirst.js.map +1 -1
  364. package/dist/node_modules/object-assign/index.js.map +1 -1
  365. package/dist/node_modules/prop-types/checkPropTypes.js.map +1 -1
  366. package/dist/node_modules/prop-types/factoryWithThrowingShims.js.map +1 -1
  367. package/dist/node_modules/prop-types/factoryWithTypeCheckers.js.map +1 -1
  368. package/dist/node_modules/prop-types/index.js.map +1 -1
  369. package/dist/node_modules/prop-types/lib/ReactPropTypesSecret.js.map +1 -1
  370. package/dist/node_modules/prop-types/lib/has.js.map +1 -1
  371. package/dist/node_modules/prop-types/node_modules/react-is/cjs/react-is.development.js.map +1 -1
  372. package/dist/node_modules/prop-types/node_modules/react-is/cjs/react-is.production.min.js.map +1 -1
  373. package/dist/node_modules/prop-types/node_modules/react-is/index.js.map +1 -1
  374. package/dist/node_modules/react-is/cjs/react-is.development.js.map +1 -1
  375. package/dist/node_modules/react-is/cjs/react-is.production.min.js.map +1 -1
  376. package/dist/node_modules/react-is/index.js.map +1 -1
  377. package/dist/node_modules/react-smooth/es6/Animate.js +2 -2
  378. package/dist/node_modules/react-smooth/es6/Animate.js.map +1 -1
  379. package/dist/node_modules/react-smooth/es6/AnimateManager.js.map +1 -1
  380. package/dist/node_modules/react-smooth/es6/configUpdate.js.map +1 -1
  381. package/dist/node_modules/react-smooth/es6/easing.js.map +1 -1
  382. package/dist/node_modules/react-smooth/es6/setRafTimeout.js.map +1 -1
  383. package/dist/node_modules/react-smooth/es6/util.js.map +1 -1
  384. package/dist/node_modules/recharts/es6/cartesian/Area.js +13 -13
  385. package/dist/node_modules/recharts/es6/cartesian/Area.js.map +1 -1
  386. package/dist/node_modules/recharts/es6/cartesian/Bar.js +9 -9
  387. package/dist/node_modules/recharts/es6/cartesian/Bar.js.map +1 -1
  388. package/dist/node_modules/recharts/es6/cartesian/Brush.js +12 -12
  389. package/dist/node_modules/recharts/es6/cartesian/Brush.js.map +1 -1
  390. package/dist/node_modules/recharts/es6/cartesian/CartesianAxis.js +7 -7
  391. package/dist/node_modules/recharts/es6/cartesian/CartesianAxis.js.map +1 -1
  392. package/dist/node_modules/recharts/es6/cartesian/ErrorBar.js +4 -4
  393. package/dist/node_modules/recharts/es6/cartesian/ErrorBar.js.map +1 -1
  394. package/dist/node_modules/recharts/es6/cartesian/ReferenceArea.js +3 -3
  395. package/dist/node_modules/recharts/es6/cartesian/ReferenceArea.js.map +1 -1
  396. package/dist/node_modules/recharts/es6/cartesian/ReferenceDot.js +3 -3
  397. package/dist/node_modules/recharts/es6/cartesian/ReferenceDot.js.map +1 -1
  398. package/dist/node_modules/recharts/es6/cartesian/ReferenceLine.js +4 -4
  399. package/dist/node_modules/recharts/es6/cartesian/ReferenceLine.js.map +1 -1
  400. package/dist/node_modules/recharts/es6/cartesian/XAxis.js +3 -3
  401. package/dist/node_modules/recharts/es6/cartesian/XAxis.js.map +1 -1
  402. package/dist/node_modules/recharts/es6/cartesian/YAxis.js +3 -3
  403. package/dist/node_modules/recharts/es6/cartesian/YAxis.js.map +1 -1
  404. package/dist/node_modules/recharts/es6/cartesian/getEquidistantTicks.js.map +1 -1
  405. package/dist/node_modules/recharts/es6/cartesian/getTicks.js.map +1 -1
  406. package/dist/node_modules/recharts/es6/chart/AccessibilityManager.js +1 -1
  407. package/dist/node_modules/recharts/es6/chart/AccessibilityManager.js.map +1 -1
  408. package/dist/node_modules/recharts/es6/chart/AreaChart.js.map +1 -1
  409. package/dist/node_modules/recharts/es6/chart/BarChart.js.map +1 -1
  410. package/dist/node_modules/recharts/es6/chart/PieChart.js.map +1 -1
  411. package/dist/node_modules/recharts/es6/chart/generateCategoricalChart.js +22 -22
  412. package/dist/node_modules/recharts/es6/chart/generateCategoricalChart.js.map +1 -1
  413. package/dist/node_modules/recharts/es6/component/Cell.js.map +1 -1
  414. package/dist/node_modules/recharts/es6/component/Cursor.js +1 -1
  415. package/dist/node_modules/recharts/es6/component/Cursor.js.map +1 -1
  416. package/dist/node_modules/recharts/es6/component/DefaultLegendContent.js +11 -11
  417. package/dist/node_modules/recharts/es6/component/DefaultLegendContent.js.map +1 -1
  418. package/dist/node_modules/recharts/es6/component/DefaultTooltipContent.js +6 -6
  419. package/dist/node_modules/recharts/es6/component/DefaultTooltipContent.js.map +1 -1
  420. package/dist/node_modules/recharts/es6/component/Label.js +14 -14
  421. package/dist/node_modules/recharts/es6/component/Label.js.map +1 -1
  422. package/dist/node_modules/recharts/es6/component/LabelList.js +6 -6
  423. package/dist/node_modules/recharts/es6/component/LabelList.js.map +1 -1
  424. package/dist/node_modules/recharts/es6/component/Legend.js +5 -5
  425. package/dist/node_modules/recharts/es6/component/Legend.js.map +1 -1
  426. package/dist/node_modules/recharts/es6/component/ResponsiveContainer.js +3 -3
  427. package/dist/node_modules/recharts/es6/component/ResponsiveContainer.js.map +1 -1
  428. package/dist/node_modules/recharts/es6/component/Text.js +2 -2
  429. package/dist/node_modules/recharts/es6/component/Text.js.map +1 -1
  430. package/dist/node_modules/recharts/es6/component/Tooltip.js +3 -3
  431. package/dist/node_modules/recharts/es6/component/Tooltip.js.map +1 -1
  432. package/dist/node_modules/recharts/es6/component/TooltipBoundingBox.js +2 -2
  433. package/dist/node_modules/recharts/es6/component/TooltipBoundingBox.js.map +1 -1
  434. package/dist/node_modules/recharts/es6/container/Layer.js +2 -2
  435. package/dist/node_modules/recharts/es6/container/Layer.js.map +1 -1
  436. package/dist/node_modules/recharts/es6/container/Surface.js +2 -2
  437. package/dist/node_modules/recharts/es6/container/Surface.js.map +1 -1
  438. package/dist/node_modules/recharts/es6/context/chartLayoutContext.js +2 -2
  439. package/dist/node_modules/recharts/es6/context/chartLayoutContext.js.map +1 -1
  440. package/dist/node_modules/recharts/es6/polar/Pie.js +13 -13
  441. package/dist/node_modules/recharts/es6/polar/Pie.js.map +1 -1
  442. package/dist/node_modules/recharts/es6/polar/PolarAngleAxis.js +8 -8
  443. package/dist/node_modules/recharts/es6/polar/PolarAngleAxis.js.map +1 -1
  444. package/dist/node_modules/recharts/es6/polar/PolarRadiusAxis.js +6 -6
  445. package/dist/node_modules/recharts/es6/polar/PolarRadiusAxis.js.map +1 -1
  446. package/dist/node_modules/recharts/es6/shape/Cross.js +1 -1
  447. package/dist/node_modules/recharts/es6/shape/Cross.js.map +1 -1
  448. package/dist/node_modules/recharts/es6/shape/Curve.js +1 -1
  449. package/dist/node_modules/recharts/es6/shape/Curve.js.map +1 -1
  450. package/dist/node_modules/recharts/es6/shape/Dot.js +1 -1
  451. package/dist/node_modules/recharts/es6/shape/Dot.js.map +1 -1
  452. package/dist/node_modules/recharts/es6/shape/Polygon.js +4 -4
  453. package/dist/node_modules/recharts/es6/shape/Polygon.js.map +1 -1
  454. package/dist/node_modules/recharts/es6/shape/Rectangle.js +4 -4
  455. package/dist/node_modules/recharts/es6/shape/Rectangle.js.map +1 -1
  456. package/dist/node_modules/recharts/es6/shape/Sector.js +1 -1
  457. package/dist/node_modules/recharts/es6/shape/Sector.js.map +1 -1
  458. package/dist/node_modules/recharts/es6/shape/Symbols.js +1 -1
  459. package/dist/node_modules/recharts/es6/shape/Symbols.js.map +1 -1
  460. package/dist/node_modules/recharts/es6/shape/Trapezoid.js +4 -4
  461. package/dist/node_modules/recharts/es6/shape/Trapezoid.js.map +1 -1
  462. package/dist/node_modules/recharts/es6/util/ActiveShapeUtils.js +9 -9
  463. package/dist/node_modules/recharts/es6/util/ActiveShapeUtils.js.map +1 -1
  464. package/dist/node_modules/recharts/es6/util/BarUtils.js +1 -1
  465. package/dist/node_modules/recharts/es6/util/BarUtils.js.map +1 -1
  466. package/dist/node_modules/recharts/es6/util/CartesianUtils.js +1 -1
  467. package/dist/node_modules/recharts/es6/util/CartesianUtils.js.map +1 -1
  468. package/dist/node_modules/recharts/es6/util/ChartUtils.js.map +1 -1
  469. package/dist/node_modules/recharts/es6/util/CssPrefixUtils.js.map +1 -1
  470. package/dist/node_modules/recharts/es6/util/DOMUtils.js.map +1 -1
  471. package/dist/node_modules/recharts/es6/util/DataUtils.js.map +1 -1
  472. package/dist/node_modules/recharts/es6/util/DetectReferenceElementsDomain.js.map +1 -1
  473. package/dist/node_modules/recharts/es6/util/Events.js.map +1 -1
  474. package/dist/node_modules/recharts/es6/util/Global.js.map +1 -1
  475. package/dist/node_modules/recharts/es6/util/IfOverflowMatches.js.map +1 -1
  476. package/dist/node_modules/recharts/es6/util/LogUtils.js.map +1 -1
  477. package/dist/node_modules/recharts/es6/util/PolarUtils.js +1 -1
  478. package/dist/node_modules/recharts/es6/util/PolarUtils.js.map +1 -1
  479. package/dist/node_modules/recharts/es6/util/ReactUtils.js +1 -1
  480. package/dist/node_modules/recharts/es6/util/ReactUtils.js.map +1 -1
  481. package/dist/node_modules/recharts/es6/util/ReduceCSSCalc.js +1 -1
  482. package/dist/node_modules/recharts/es6/util/ReduceCSSCalc.js.map +1 -1
  483. package/dist/node_modules/recharts/es6/util/ShallowEqual.js.map +1 -1
  484. package/dist/node_modules/recharts/es6/util/TickUtils.js.map +1 -1
  485. package/dist/node_modules/recharts/es6/util/calculateViewBox.js.map +1 -1
  486. package/dist/node_modules/recharts/es6/util/cursor/getCursorPoints.js.map +1 -1
  487. package/dist/node_modules/recharts/es6/util/cursor/getCursorRectangle.js.map +1 -1
  488. package/dist/node_modules/recharts/es6/util/cursor/getRadialCursorPoints.js.map +1 -1
  489. package/dist/node_modules/recharts/es6/util/getEveryNthWithCondition.js.map +1 -1
  490. package/dist/node_modules/recharts/es6/util/getLegendProps.js.map +1 -1
  491. package/dist/node_modules/recharts/es6/util/isDomainSpecifiedByUser.js.map +1 -1
  492. package/dist/node_modules/recharts/es6/util/payload/getUniqPayload.js.map +1 -1
  493. package/dist/node_modules/recharts/es6/util/tooltip/translate.js.map +1 -1
  494. package/dist/node_modules/recharts/es6/util/types.js +1 -1
  495. package/dist/node_modules/recharts/es6/util/types.js.map +1 -1
  496. package/dist/node_modules/recharts-scale/es6/getNiceTickValues.js.map +1 -1
  497. package/dist/node_modules/recharts-scale/es6/util/arithmetic.js.map +1 -1
  498. package/dist/node_modules/recharts-scale/es6/util/utils.js.map +1 -1
  499. package/dist/node_modules/sonner/dist/index.js.map +1 -1
  500. package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js +1 -1
  501. package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js.map +1 -1
  502. package/dist/node_modules/tiny-invariant/dist/esm/tiny-invariant.js.map +1 -1
  503. package/dist/stories/LoadMore.stories.d.ts +0 -1
  504. package/package.json +15 -7
@@ -1 +1 @@
1
- {"version":3,"file":"AiAssistantPage.js","names":[],"sources":["../../../src/brainyrich/pages/AiAssistantPage.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n Input,\n Label,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n Textarea,\n} from '@burdenoff/fe-libs/ui';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n AlertTriangle,\n BellRing,\n CheckCircle2,\n Info,\n Lightbulb,\n MoreHorizontal,\n Plus,\n ShieldAlert,\n XCircle,\n} from 'lucide-react';\nimport { tWithFallback } from '../utils/i18n';\nimport {\n useAccounts,\n useAcknowledgeInsight,\n useCreateInsight,\n useDismissInsight,\n useGoals,\n useHouseholds,\n usePagedInsights,\n usePortfolios,\n useResolveInsight,\n} from '../hooks/useBrainyRichApi';\nimport { ConfirmDialog, LoadMore, SubjectPicker, parseSubject } from '../components';\nimport {\n DonutChart,\n FadeIn,\n GlassCard,\n LifecycleStepper,\n StatTile,\n type VizTone,\n} from '../components/viz';\nimport type {\n BraCreateInsightInput,\n BraInsight,\n BraInsightSeverity,\n BraInsightStatus,\n BraInsightType,\n} from '../types/bra';\nimport {\n EmptyState,\n ErrorState,\n LoadingState,\n SectionShell,\n formatDate,\n statusBadgeVariant,\n} from './_shared';\n\nconst INSIGHT_TYPES: BraInsightType[] = [\n 'REBALANCE_DUE',\n 'DRIFT',\n 'CONCENTRATION_RISK',\n 'CASH_DRAG',\n 'FEE_ANOMALY',\n 'TAX_OPPORTUNITY',\n 'GOAL_AT_RISK',\n];\n\nconst INSIGHT_SEVERITIES: BraInsightSeverity[] = ['INFO', 'LOW', 'MEDIUM', 'HIGH', 'CRITICAL'];\n\nconst INSIGHT_STATUSES: BraInsightStatus[] = ['OPEN', 'ACKNOWLEDGED', 'RESOLVED', 'DISMISSED'];\n\nconst ALL = '__all__';\n\nfunction humanize(value: string): string {\n return value\n .toLowerCase()\n .split('_')\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join(' ');\n}\n\ninterface SeverityMeta {\n icon: typeof Info;\n tone: string;\n}\n\nfunction severityMeta(severity: BraInsightSeverity): SeverityMeta {\n switch (severity) {\n case 'CRITICAL':\n return { icon: ShieldAlert, tone: 'text-status-error-text' };\n case 'HIGH':\n return { icon: AlertTriangle, tone: 'text-status-error-text' };\n case 'MEDIUM':\n return { icon: BellRing, tone: 'text-status-warning-text' };\n case 'LOW':\n return { icon: Lightbulb, tone: 'text-status-warning-text' };\n case 'INFO':\n default:\n return { icon: Info, tone: 'text-text-secondary' };\n }\n}\n\nfunction severityTone(severity: BraInsightSeverity): VizTone {\n switch (severity) {\n case 'CRITICAL':\n return 'error';\n case 'HIGH':\n return 'purple';\n case 'MEDIUM':\n return 'warning';\n case 'LOW':\n return 'teal';\n case 'INFO':\n default:\n return 'info';\n }\n}\n\n/** Lifecycle steps for the triage stepper (DISMISSED is a terminal side-state). */\nconst LIFECYCLE_STEPS = ['Open', 'Acknowledged', 'Resolved'];\n\ninterface InsightFormState {\n title: string;\n type: BraInsightType;\n severity: BraInsightSeverity;\n /** Encoded `SUBJECT_TYPE:id` token from <SubjectPicker>. */\n subject: string;\n detail: string;\n metrics: string;\n ownerId: string;\n}\n\nfunction emptyForm(): InsightFormState {\n return {\n title: '',\n type: 'DRIFT',\n severity: 'MEDIUM',\n subject: '',\n detail: '',\n metrics: '',\n ownerId: '',\n };\n}\n\nexport function AiAssistantPage() {\n const { t } = useI18n();\n const translate = (key: string, fallback: string, params?: Record<string, string | number>) =>\n tWithFallback(t, key, fallback, params);\n\n const [severityFilter, setSeverityFilter] = useState<string>(ALL);\n const [statusFilter, setStatusFilter] = useState<string>(ALL);\n const [typeFilter, setTypeFilter] = useState<string>(ALL);\n\n const {\n items: insights,\n hasMore,\n loadMore,\n isLoading,\n isFetchingNextPage,\n isError,\n refetch,\n } = usePagedInsights({\n ...(severityFilter !== ALL ? { severity: severityFilter as BraInsightSeverity } : {}),\n ...(statusFilter !== ALL ? { status: statusFilter as BraInsightStatus } : {}),\n });\n\n // Resolve subjectId -> referenced entity name via the list queries (react-query\n // dedupes these with the SubjectPicker's own calls).\n const accounts = useAccounts();\n const portfolios = usePortfolios();\n const goals = useGoals();\n const households = useHouseholds();\n const subjectNames = useMemo(() => {\n const map = new Map<string, string>();\n for (const a of accounts.data) map.set(a.id, a.name);\n for (const p of portfolios.data) map.set(p.id, p.name);\n for (const g of goals.data) map.set(g.id, g.name);\n for (const h of households.data) map.set(h.id, h.name);\n return map;\n }, [accounts.data, portfolios.data, goals.data, households.data]);\n\n const acknowledge = useAcknowledgeInsight();\n const dismiss = useDismissInsight();\n const resolve = useResolveInsight();\n const createInsight = useCreateInsight();\n\n const [createOpen, setCreateOpen] = useState(false);\n const [form, setForm] = useState<InsightFormState>(emptyForm);\n\n const setField = <K extends keyof InsightFormState>(key: K, value: InsightFormState[K]) =>\n setForm((prev) => ({ ...prev, [key]: value }));\n\n // Type is not a backend filter arg — narrow client-side.\n const filtered = useMemo(\n () => (typeFilter === ALL ? insights : insights.filter((i) => i.type === typeFilter)),\n [insights, typeFilter]\n );\n\n const counts = useMemo(() => {\n const open = insights.filter((i) => i.status === 'OPEN').length;\n const critical = insights.filter((i) => i.severity === 'CRITICAL').length;\n const urgent = insights.filter(\n (i) => i.severity === 'HIGH' || i.severity === 'CRITICAL'\n ).length;\n const resolved = insights.filter((i) => i.status === 'RESOLVED').length;\n return { open, critical, urgent, resolved };\n }, [insights]);\n\n // Severity mix across the loaded inbox — drives the hero donut (real data only).\n const severityDist = useMemo(\n () =>\n INSIGHT_SEVERITIES.map((s) => ({\n label: humanize(s),\n value: insights.filter((i) => i.severity === s).length,\n tone: severityTone(s),\n })).filter((d) => d.value > 0),\n [insights]\n );\n\n const metricsValid = useMemo(() => {\n if (!form.metrics.trim()) return true;\n try {\n JSON.parse(form.metrics);\n return true;\n } catch {\n return false;\n }\n }, [form.metrics]);\n\n const formValid =\n form.title.trim().length > 0 && parseSubject(form.subject) !== null && metricsValid;\n\n const openCreate = () => {\n setForm(emptyForm());\n setCreateOpen(true);\n };\n\n const handleCreate = () => {\n if (!formValid) return;\n const subject = parseSubject(form.subject);\n if (!subject) return;\n let metrics: Record<string, unknown> | undefined;\n if (form.metrics.trim()) {\n try {\n metrics = JSON.parse(form.metrics) as Record<string, unknown>;\n } catch {\n return;\n }\n }\n const input: BraCreateInsightInput = {\n title: form.title.trim(),\n type: form.type,\n severity: form.severity,\n subjectType: subject.subjectType,\n subjectId: subject.subjectId,\n detail: form.detail.trim() || null,\n ...(metrics ? { metrics } : {}),\n ...(form.ownerId.trim() ? { ownerId: form.ownerId.trim() } : {}),\n };\n createInsight.mutate(input, { onSuccess: () => setCreateOpen(false) });\n };\n\n const anyFilterActive = severityFilter !== ALL || statusFilter !== ALL || typeFilter !== ALL;\n\n const body = () => {\n if (isLoading) return <LoadingState rows={4} />;\n if (isError)\n return (\n <ErrorState\n title={translate('brainyrich.insights.error.title', 'Could not load insights')}\n description={translate(\n 'brainyrich.insights.error.description',\n 'We could not reach the insights service. Please try again.'\n )}\n onRetry={() => refetch()}\n />\n );\n\n return (\n <>\n {/* Hero — premium KPI tiles + severity-mix donut, wired to the live inbox */}\n <FadeIn className=\"grid gap-4 lg:grid-cols-[minmax(0,1.55fr)_minmax(0,1fr)]\">\n <div className=\"grid grid-cols-2 gap-4 sm:grid-cols-4 lg:grid-cols-2 xl:grid-cols-4\">\n <StatTile\n label={translate('brainyrich.insights.metrics.total', 'Signals')}\n value={String(insights.length)}\n glow\n icon={<BellRing className=\"size-4\" aria-hidden=\"true\" />}\n />\n <StatTile\n label={translate('brainyrich.insights.metrics.open', 'Open')}\n value={String(counts.open)}\n icon={<Info className=\"size-4\" aria-hidden=\"true\" />}\n />\n <StatTile\n label={translate('brainyrich.insights.metrics.critical', 'Critical')}\n value={String(counts.critical)}\n deltaTone={counts.critical > 0 ? 'negative' : 'positive'}\n icon={<ShieldAlert className=\"size-4\" aria-hidden=\"true\" />}\n />\n <StatTile\n label={translate('brainyrich.insights.metrics.resolved', 'Resolved')}\n value={String(counts.resolved)}\n deltaTone=\"positive\"\n icon={<CheckCircle2 className=\"size-4\" aria-hidden=\"true\" />}\n />\n </div>\n\n <GlassCard className=\"flex min-w-0 flex-col p-5\">\n <p className=\"text-sm font-medium text-text-primary\">\n {translate('brainyrich.insights.hero.severityMix', 'Severity mix')}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {translate(\n 'brainyrich.insights.hero.severityMixHint',\n 'Distribution across the loaded inbox'\n )}\n </p>\n {severityDist.length > 0 ? (\n <div className=\"mt-2 min-w-0\">\n <DonutChart\n data={severityDist}\n centerLabel={translate('brainyrich.insights.hero.center', 'Signals')}\n centerValue={String(insights.length)}\n height={200}\n />\n </div>\n ) : (\n <p className=\"mt-6 text-sm text-text-secondary\">\n {translate('brainyrich.insights.hero.noData', 'No signals to chart yet.')}\n </p>\n )}\n </GlassCard>\n </FadeIn>\n\n {/* Quick-triage summary chips — toggle the underlying filters */}\n <FadeIn index={1} className=\"flex flex-wrap gap-2\">\n <SummaryChip\n label={translate('brainyrich.insights.metrics.open', 'Open')}\n count={counts.open}\n tone=\"info\"\n active={statusFilter === 'OPEN'}\n onClick={() => {\n setStatusFilter(statusFilter === 'OPEN' ? ALL : 'OPEN');\n setSeverityFilter(ALL);\n }}\n />\n <SummaryChip\n label={translate('brainyrich.insights.metrics.critical', 'Critical')}\n count={counts.critical}\n tone=\"error\"\n active={severityFilter === 'CRITICAL'}\n onClick={() => {\n setSeverityFilter(severityFilter === 'CRITICAL' ? ALL : 'CRITICAL');\n setStatusFilter(ALL);\n }}\n />\n <SummaryChip\n label={translate('brainyrich.insights.metrics.resolved', 'Resolved')}\n count={counts.resolved}\n tone=\"success\"\n active={statusFilter === 'RESOLVED'}\n onClick={() => {\n setStatusFilter(statusFilter === 'RESOLVED' ? ALL : 'RESOLVED');\n setSeverityFilter(ALL);\n }}\n />\n </FadeIn>\n\n {/* Filters */}\n <Card>\n <CardContent className=\"flex flex-col gap-3 p-4 sm:flex-row sm:items-end\">\n <div className=\"w-full space-y-1.5 sm:w-48\">\n <Label htmlFor=\"insight-filter-severity\">\n {translate('brainyrich.insights.filters.severity', 'Severity')}\n </Label>\n <Select value={severityFilter} onValueChange={setSeverityFilter}>\n <SelectTrigger id=\"insight-filter-severity\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={ALL}>\n {translate('brainyrich.insights.filters.all', 'All')}\n </SelectItem>\n {INSIGHT_SEVERITIES.map((s) => (\n <SelectItem key={s} value={s}>\n {humanize(s)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"w-full space-y-1.5 sm:w-48\">\n <Label htmlFor=\"insight-filter-status\">\n {translate('brainyrich.insights.filters.status', 'Status')}\n </Label>\n <Select value={statusFilter} onValueChange={setStatusFilter}>\n <SelectTrigger id=\"insight-filter-status\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={ALL}>\n {translate('brainyrich.insights.filters.all', 'All')}\n </SelectItem>\n {INSIGHT_STATUSES.map((s) => (\n <SelectItem key={s} value={s}>\n {humanize(s)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"w-full space-y-1.5 sm:w-56\">\n <Label htmlFor=\"insight-filter-type\">\n {translate('brainyrich.insights.filters.type', 'Type')}\n </Label>\n <Select value={typeFilter} onValueChange={setTypeFilter}>\n <SelectTrigger id=\"insight-filter-type\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={ALL}>\n {translate('brainyrich.insights.filters.all', 'All')}\n </SelectItem>\n {INSIGHT_TYPES.map((s) => (\n <SelectItem key={s} value={s}>\n {humanize(s)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </CardContent>\n </Card>\n\n {filtered.length === 0 ? (\n <EmptyState\n icon={<BellRing className=\"size-6\" aria-hidden=\"true\" />}\n title={\n anyFilterActive\n ? translate('brainyrich.insights.empty.filteredTitle', 'No matching insights')\n : translate('brainyrich.insights.empty.title', 'No advisory insights yet')\n }\n description={\n anyFilterActive\n ? translate(\n 'brainyrich.insights.empty.filteredDescription',\n 'No insights match the selected filters. Adjust or clear them to see more.'\n )\n : translate(\n 'brainyrich.insights.empty.description',\n 'Advisory insights flag rebalancing, drift, concentration and other opportunities. Create one to get started.'\n )\n }\n action={\n anyFilterActive ? (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => {\n setSeverityFilter(ALL);\n setStatusFilter(ALL);\n setTypeFilter(ALL);\n }}\n >\n {translate('brainyrich.insights.actions.clearFilters', 'Clear filters')}\n </Button>\n ) : (\n <Button size=\"sm\" onClick={openCreate}>\n <Plus className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.insights.actions.create', 'New insight')}\n </Button>\n )\n }\n />\n ) : (\n <div className=\"space-y-3\">\n {filtered.map((insight, idx) => (\n <InsightCard\n key={insight.id}\n index={idx}\n insight={insight}\n subjectName={subjectNames.get(insight.subjectId)}\n translate={translate}\n onAcknowledge={() => acknowledge.mutate(insight.id)}\n onDismiss={() => dismiss.mutate(insight.id)}\n onResolve={() => resolve.mutate(insight.id)}\n acknowledgePending={acknowledge.isPending}\n dismissPending={dismiss.isPending}\n resolvePending={resolve.isPending}\n />\n ))}\n </div>\n )}\n\n <LoadMore\n hasMore={hasMore}\n onClick={loadMore}\n loading={isFetchingNextPage}\n label={translate('brainyrich.insights.actions.loadMore', 'Load more insights')}\n />\n </>\n );\n };\n\n return (\n <>\n <SectionShell\n title={translate('brainyrich.insights.title', 'Insights')}\n description={translate(\n 'brainyrich.insights.description',\n 'Advisory insights across portfolios, accounts and goals — triage, acknowledge and resolve.'\n )}\n badges={[translate('brainyrich.insights.badges.advisory', 'Advisory')]}\n actionLabel={translate('brainyrich.insights.actions.create', 'New insight')}\n onAction={openCreate}\n >\n {body()}\n </SectionShell>\n\n <InsightFormDialog\n open={createOpen}\n form={form}\n setField={setField}\n metricsValid={metricsValid}\n valid={formValid}\n pending={createInsight.isPending}\n onSubmit={handleCreate}\n onOpenChange={(v) => setCreateOpen(v)}\n translate={translate}\n />\n </>\n );\n}\n\ntype Translate = (\n key: string,\n fallback: string,\n params?: Record<string, string | number>\n) => string;\n\ninterface SummaryChipProps {\n label: string;\n count: number;\n tone: 'info' | 'error' | 'success';\n active: boolean;\n onClick: () => void;\n}\n\nfunction SummaryChip({ label, count, tone, active, onClick }: SummaryChipProps) {\n const dotClass =\n tone === 'error'\n ? 'bg-status-error-text'\n : tone === 'success'\n ? 'bg-status-success-text'\n : 'bg-status-info-text';\n return (\n <button\n type=\"button\"\n onClick={onClick}\n aria-pressed={active}\n className={`group inline-flex items-center gap-2 rounded-full border px-3.5 py-1.5 text-sm font-medium transition-colors motion-safe:transition-shadow focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-action-primary-border)] ${\n active\n ? 'border-[var(--color-action-primary-border)] bg-bg-elevated text-text-primary shadow-[var(--shadow-elevation-1)]'\n : 'border-border-subtle bg-bg-surface text-text-secondary hover:border-[var(--color-action-primary-border)] hover:text-text-primary'\n }`}\n >\n <span className={`size-2 rounded-full ${dotClass}`} aria-hidden=\"true\" />\n {label}\n <span className=\"rounded-full bg-bg-sunken px-2 py-0.5 text-xs tabular-nums text-text-primary\">\n {count}\n </span>\n </button>\n );\n}\n\ninterface InsightCardProps {\n index: number;\n insight: BraInsight;\n /** Referenced entity name resolved from the list queries, if known. */\n subjectName?: string;\n translate: Translate;\n onAcknowledge: () => void;\n onDismiss: () => void;\n onResolve: () => void;\n acknowledgePending: boolean;\n dismissPending: boolean;\n resolvePending: boolean;\n}\n\nfunction InsightCard({\n index,\n insight,\n subjectName,\n translate,\n onAcknowledge,\n onDismiss,\n onResolve,\n acknowledgePending,\n dismissPending,\n resolvePending,\n}: InsightCardProps) {\n const meta = severityMeta(insight.severity);\n const SeverityIcon = meta.icon;\n const isClosed = insight.status === 'RESOLVED' || insight.status === 'DISMISSED';\n const isDismissed = insight.status === 'DISMISSED';\n const [dismissOpen, setDismissOpen] = useState(false);\n\n return (\n <FadeIn as=\"div\" index={index}>\n <Card className=\"overflow-hidden transition-shadow motion-safe:hover:shadow-[var(--shadow-elevation-2)]\">\n <CardHeader className=\"pb-3\">\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"flex min-w-0 items-start gap-3\">\n <span\n className={`mt-0.5 flex size-9 shrink-0 items-center justify-center rounded-full bg-bg-sunken ${meta.tone}`}\n >\n <SeverityIcon className=\"size-5\" aria-hidden=\"true\" />\n </span>\n <div className=\"min-w-0\">\n <CardTitle className=\"text-base\">{insight.title}</CardTitle>\n <CardDescription className=\"mt-1 flex flex-wrap items-center gap-2\">\n <Badge variant=\"outline\">{humanize(insight.type)}</Badge>\n <Badge variant={statusBadgeVariant(insight.severity)}>\n <span className={`inline-flex items-center gap-1 ${meta.tone}`}>\n <SeverityIcon className=\"size-3\" aria-hidden=\"true\" />\n {humanize(insight.severity)}\n </span>\n </Badge>\n <Badge variant={statusBadgeVariant(insight.status)}>\n {humanize(insight.status)}\n </Badge>\n </CardDescription>\n </div>\n </div>\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label={translate('brainyrich.insights.actions.menu', 'Insight actions')}\n >\n <MoreHorizontal className=\"size-4\" aria-hidden=\"true\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuItem\n disabled={acknowledgePending || insight.status === 'ACKNOWLEDGED' || isClosed}\n onSelect={onAcknowledge}\n >\n <CheckCircle2 className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.insights.actions.acknowledge', 'Acknowledge')}\n </DropdownMenuItem>\n <DropdownMenuItem\n disabled={resolvePending || insight.status === 'RESOLVED'}\n onSelect={onResolve}\n >\n <CheckCircle2 className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.insights.actions.resolve', 'Resolve')}\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n className=\"text-status-error-text focus:text-status-error-text\"\n disabled={dismissPending || insight.status === 'DISMISSED'}\n onSelect={(e) => {\n e.preventDefault();\n setDismissOpen(true);\n }}\n >\n <XCircle className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.insights.actions.dismiss', 'Dismiss')}\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {insight.detail ? <p className=\"text-sm text-text-secondary\">{insight.detail}</p> : null}\n <dl className=\"grid grid-cols-2 gap-3 rounded-lg bg-bg-sunken p-3 text-sm sm:grid-cols-3\">\n <div>\n <dt className=\"text-xs text-text-secondary\">\n {translate('brainyrich.insights.card.subjectType', 'Subject')}\n </dt>\n <dd className=\"font-medium text-text-primary\">{humanize(insight.subjectType)}</dd>\n </div>\n <div className=\"min-w-0\">\n <dt className=\"text-xs text-text-secondary\">\n {translate('brainyrich.insights.card.subject', 'Reference')}\n </dt>\n <dd\n className=\"truncate font-medium text-text-primary\"\n title={subjectName ? `${subjectName} (${insight.subjectId})` : insight.subjectId}\n >\n {subjectName ?? insight.subjectId}\n </dd>\n </div>\n <div>\n <dt className=\"text-xs text-text-secondary\">\n {translate('brainyrich.insights.card.created', 'Created')}\n </dt>\n <dd className=\"font-medium text-text-primary\">{formatDate(insight.createdAt)}</dd>\n </div>\n </dl>\n {isDismissed ? (\n <div className=\"flex items-center gap-2 rounded-lg bg-bg-sunken px-3 py-2 text-sm text-text-secondary\">\n <XCircle className=\"size-4 text-status-error-text\" aria-hidden=\"true\" />\n {translate('brainyrich.insights.card.dismissed', 'Dismissed from active triage')}\n </div>\n ) : (\n <LifecycleStepper steps={LIFECYCLE_STEPS} current={humanize(insight.status)} />\n )}\n <div className=\"flex flex-wrap items-center gap-2\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={acknowledgePending || insight.status === 'ACKNOWLEDGED' || isClosed}\n onClick={onAcknowledge}\n >\n <CheckCircle2 className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.insights.actions.acknowledge', 'Acknowledge')}\n </Button>\n <Button\n size=\"sm\"\n disabled={resolvePending || insight.status === 'RESOLVED'}\n onClick={onResolve}\n >\n <CheckCircle2 className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.insights.actions.resolve', 'Resolve')}\n </Button>\n </div>\n </CardContent>\n\n <ConfirmDialog\n open={dismissOpen}\n onOpenChange={setDismissOpen}\n title={translate('brainyrich.insights.dismiss.title', 'Dismiss this insight?')}\n description={translate(\n 'brainyrich.insights.dismiss.description',\n 'Dismissing removes this insight from active triage. You can still find it by filtering for dismissed insights.'\n )}\n confirmLabel={translate('brainyrich.insights.actions.dismiss', 'Dismiss')}\n pendingLabel={translate('brainyrich.insights.dismiss.pending', 'Dismissing…')}\n destructive\n pending={dismissPending}\n onConfirm={onDismiss}\n />\n </Card>\n </FadeIn>\n );\n}\n\ninterface InsightFormDialogProps {\n open: boolean;\n form: InsightFormState;\n setField: <K extends keyof InsightFormState>(key: K, value: InsightFormState[K]) => void;\n metricsValid: boolean;\n valid: boolean;\n pending: boolean;\n onSubmit: () => void;\n onOpenChange: (open: boolean) => void;\n translate: Translate;\n}\n\nfunction InsightFormDialog({\n open,\n form,\n setField,\n metricsValid,\n valid,\n pending,\n onSubmit,\n onOpenChange,\n translate,\n}: InsightFormDialogProps) {\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent className=\"max-h-[90vh] overflow-y-auto sm:max-w-lg\">\n <DialogHeader>\n <DialogTitle>\n {translate('brainyrich.insights.form.createTitle', 'New insight')}\n </DialogTitle>\n <DialogDescription>\n {translate(\n 'brainyrich.insights.form.subtitle',\n 'Flag an advisory insight against a portfolio, account, goal or household.'\n )}\n </DialogDescription>\n </DialogHeader>\n\n <form\n className=\"space-y-4\"\n onSubmit={(e) => {\n e.preventDefault();\n onSubmit();\n }}\n >\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"insight-title\">\n {translate('brainyrich.insights.form.title', 'Title')}\n </Label>\n <Input\n id=\"insight-title\"\n value={form.title}\n onChange={(e) => setField('title', e.target.value)}\n placeholder={translate(\n 'brainyrich.insights.form.titlePlaceholder',\n 'e.g. Technology concentration above threshold'\n )}\n required\n />\n </div>\n\n <div className=\"grid grid-cols-2 gap-3\">\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"insight-type\">\n {translate('brainyrich.insights.form.type', 'Type')}\n </Label>\n <Select\n value={form.type}\n onValueChange={(v) => setField('type', v as BraInsightType)}\n >\n <SelectTrigger id=\"insight-type\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {INSIGHT_TYPES.map((tpe) => (\n <SelectItem key={tpe} value={tpe}>\n {humanize(tpe)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"insight-severity\">\n {translate('brainyrich.insights.form.severity', 'Severity')}\n </Label>\n <Select\n value={form.severity}\n onValueChange={(v) => setField('severity', v as BraInsightSeverity)}\n >\n <SelectTrigger id=\"insight-severity\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {INSIGHT_SEVERITIES.map((s) => (\n <SelectItem key={s} value={s}>\n {humanize(s)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n\n <SubjectPicker\n id=\"insight-subject\"\n label={translate('brainyrich.insights.form.subject', 'Subject')}\n placeholder={translate(\n 'brainyrich.insights.form.subjectPlaceholder',\n 'Select an account, portfolio, goal or household'\n )}\n value={form.subject}\n onChange={(v) => setField('subject', v)}\n />\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"insight-owner\">\n {translate('brainyrich.insights.form.ownerId', 'Owner ID (optional)')}\n </Label>\n <Input\n id=\"insight-owner\"\n value={form.ownerId}\n onChange={(e) => setField('ownerId', e.target.value)}\n placeholder={translate(\n 'brainyrich.insights.form.ownerIdPlaceholder',\n 'Defaults to the current owner'\n )}\n />\n </div>\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"insight-detail\">\n {translate('brainyrich.insights.form.detail', 'Detail')}\n </Label>\n <Textarea\n id=\"insight-detail\"\n value={form.detail}\n onChange={(e) => setField('detail', e.target.value)}\n rows={3}\n placeholder={translate(\n 'brainyrich.insights.form.detailPlaceholder',\n 'Explain the finding and recommended action.'\n )}\n />\n </div>\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"insight-metrics\">\n {translate('brainyrich.insights.form.metrics', 'Metrics JSON (optional)')}\n </Label>\n <Textarea\n id=\"insight-metrics\"\n value={form.metrics}\n onChange={(e) => setField('metrics', e.target.value)}\n rows={3}\n className=\"font-mono text-xs\"\n placeholder='{ \"driftPct\": 8.2 }'\n aria-invalid={!metricsValid}\n />\n {!metricsValid ? (\n <p className=\"flex items-center gap-1 text-xs text-status-error-text\">\n <AlertTriangle className=\"size-3.5\" aria-hidden=\"true\" />\n {translate(\n 'brainyrich.insights.form.metricsInvalid',\n 'Enter valid JSON or leave blank.'\n )}\n </p>\n ) : null}\n </div>\n\n <DialogFooter>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => onOpenChange(false)}\n disabled={pending}\n >\n {translate('brainyrich.insights.form.cancel', 'Cancel')}\n </Button>\n <Button type=\"submit\" disabled={!valid || pending}>\n {pending\n ? translate('brainyrich.insights.form.saving', 'Saving…')\n : translate('brainyrich.insights.form.create', 'Create insight')}\n </Button>\n </DialogFooter>\n </form>\n </DialogContent>\n </Dialog>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"AiAssistantPage.js","names":[],"sources":["../../../src/brainyrich/pages/AiAssistantPage.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n Input,\n Label,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n Textarea,\n} from '@burdenoff/fe-libs/ui';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n AlertTriangle,\n BellRing,\n CheckCircle2,\n Info,\n Lightbulb,\n MoreHorizontal,\n Plus,\n ShieldAlert,\n XCircle,\n} from 'lucide-react';\nimport { tWithFallback } from '../utils/i18n';\nimport {\n useAccounts,\n useAcknowledgeInsight,\n useCreateInsight,\n useDismissInsight,\n useGoals,\n useHouseholds,\n usePagedInsights,\n usePortfolios,\n useResolveInsight,\n} from '../hooks/useBrainyRichApi';\nimport { ConfirmDialog, LoadMore, SubjectPicker, parseSubject } from '../components';\nimport {\n DonutChart,\n FadeIn,\n GlassCard,\n LifecycleStepper,\n StatTile,\n type VizTone,\n} from '../components/viz';\nimport type {\n BraCreateInsightInput,\n BraInsight,\n BraInsightSeverity,\n BraInsightStatus,\n BraInsightType,\n} from '../types/bra';\nimport {\n EmptyState,\n ErrorState,\n LoadingState,\n SectionShell,\n formatDate,\n statusBadgeVariant,\n} from './_shared';\n\nconst INSIGHT_TYPES: BraInsightType[] = [\n 'REBALANCE_DUE',\n 'DRIFT',\n 'CONCENTRATION_RISK',\n 'CASH_DRAG',\n 'FEE_ANOMALY',\n 'TAX_OPPORTUNITY',\n 'GOAL_AT_RISK',\n];\n\nconst INSIGHT_SEVERITIES: BraInsightSeverity[] = ['INFO', 'LOW', 'MEDIUM', 'HIGH', 'CRITICAL'];\n\nconst INSIGHT_STATUSES: BraInsightStatus[] = ['OPEN', 'ACKNOWLEDGED', 'RESOLVED', 'DISMISSED'];\n\nconst ALL = '__all__';\n\nfunction humanize(value: string): string {\n return value\n .toLowerCase()\n .split('_')\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join(' ');\n}\n\ninterface SeverityMeta {\n icon: typeof Info;\n tone: string;\n}\n\nfunction severityMeta(severity: BraInsightSeverity): SeverityMeta {\n switch (severity) {\n case 'CRITICAL':\n return { icon: ShieldAlert, tone: 'text-status-error-text' };\n case 'HIGH':\n return { icon: AlertTriangle, tone: 'text-status-error-text' };\n case 'MEDIUM':\n return { icon: BellRing, tone: 'text-status-warning-text' };\n case 'LOW':\n return { icon: Lightbulb, tone: 'text-status-warning-text' };\n case 'INFO':\n default:\n return { icon: Info, tone: 'text-text-secondary' };\n }\n}\n\nfunction severityTone(severity: BraInsightSeverity): VizTone {\n switch (severity) {\n case 'CRITICAL':\n return 'error';\n case 'HIGH':\n return 'purple';\n case 'MEDIUM':\n return 'warning';\n case 'LOW':\n return 'teal';\n case 'INFO':\n default:\n return 'info';\n }\n}\n\n/** Lifecycle steps for the triage stepper (DISMISSED is a terminal side-state). */\nconst LIFECYCLE_STEPS = ['Open', 'Acknowledged', 'Resolved'];\n\ninterface InsightFormState {\n title: string;\n type: BraInsightType;\n severity: BraInsightSeverity;\n /** Encoded `SUBJECT_TYPE:id` token from <SubjectPicker>. */\n subject: string;\n detail: string;\n metrics: string;\n ownerId: string;\n}\n\nfunction emptyForm(): InsightFormState {\n return {\n title: '',\n type: 'DRIFT',\n severity: 'MEDIUM',\n subject: '',\n detail: '',\n metrics: '',\n ownerId: '',\n };\n}\n\nexport function AiAssistantPage() {\n const { t } = useI18n();\n const translate = (key: string, fallback: string, params?: Record<string, string | number>) =>\n tWithFallback(t, key, fallback, params);\n\n const [severityFilter, setSeverityFilter] = useState<string>(ALL);\n const [statusFilter, setStatusFilter] = useState<string>(ALL);\n const [typeFilter, setTypeFilter] = useState<string>(ALL);\n\n const {\n items: insights,\n hasMore,\n loadMore,\n isLoading,\n isFetchingNextPage,\n isError,\n refetch,\n } = usePagedInsights({\n ...(severityFilter !== ALL ? { severity: severityFilter as BraInsightSeverity } : {}),\n ...(statusFilter !== ALL ? { status: statusFilter as BraInsightStatus } : {}),\n });\n\n // Resolve subjectId -> referenced entity name via the list queries (react-query\n // dedupes these with the SubjectPicker's own calls).\n const accounts = useAccounts();\n const portfolios = usePortfolios();\n const goals = useGoals();\n const households = useHouseholds();\n const subjectNames = useMemo(() => {\n const map = new Map<string, string>();\n for (const a of accounts.data) map.set(a.id, a.name);\n for (const p of portfolios.data) map.set(p.id, p.name);\n for (const g of goals.data) map.set(g.id, g.name);\n for (const h of households.data) map.set(h.id, h.name);\n return map;\n }, [accounts.data, portfolios.data, goals.data, households.data]);\n\n const acknowledge = useAcknowledgeInsight();\n const dismiss = useDismissInsight();\n const resolve = useResolveInsight();\n const createInsight = useCreateInsight();\n\n const [createOpen, setCreateOpen] = useState(false);\n const [form, setForm] = useState<InsightFormState>(emptyForm);\n\n const setField = <K extends keyof InsightFormState>(key: K, value: InsightFormState[K]) =>\n setForm((prev) => ({ ...prev, [key]: value }));\n\n // Type is not a backend filter arg — narrow client-side.\n const filtered = useMemo(\n () => (typeFilter === ALL ? insights : insights.filter((i) => i.type === typeFilter)),\n [insights, typeFilter]\n );\n\n const counts = useMemo(() => {\n const open = insights.filter((i) => i.status === 'OPEN').length;\n const critical = insights.filter((i) => i.severity === 'CRITICAL').length;\n const urgent = insights.filter(\n (i) => i.severity === 'HIGH' || i.severity === 'CRITICAL'\n ).length;\n const resolved = insights.filter((i) => i.status === 'RESOLVED').length;\n return { open, critical, urgent, resolved };\n }, [insights]);\n\n // Severity mix across the loaded inbox — drives the hero donut (real data only).\n const severityDist = useMemo(\n () =>\n INSIGHT_SEVERITIES.map((s) => ({\n label: humanize(s),\n value: insights.filter((i) => i.severity === s).length,\n tone: severityTone(s),\n })).filter((d) => d.value > 0),\n [insights]\n );\n\n const metricsValid = useMemo(() => {\n if (!form.metrics.trim()) return true;\n try {\n JSON.parse(form.metrics);\n return true;\n } catch {\n return false;\n }\n }, [form.metrics]);\n\n const formValid =\n form.title.trim().length > 0 && parseSubject(form.subject) !== null && metricsValid;\n\n const openCreate = () => {\n setForm(emptyForm());\n setCreateOpen(true);\n };\n\n const handleCreate = () => {\n if (!formValid) return;\n const subject = parseSubject(form.subject);\n if (!subject) return;\n let metrics: Record<string, unknown> | undefined;\n if (form.metrics.trim()) {\n try {\n metrics = JSON.parse(form.metrics) as Record<string, unknown>;\n } catch {\n return;\n }\n }\n const input: BraCreateInsightInput = {\n title: form.title.trim(),\n type: form.type,\n severity: form.severity,\n subjectType: subject.subjectType,\n subjectId: subject.subjectId,\n detail: form.detail.trim() || null,\n ...(metrics ? { metrics } : {}),\n ...(form.ownerId.trim() ? { ownerId: form.ownerId.trim() } : {}),\n };\n createInsight.mutate(input, { onSuccess: () => setCreateOpen(false) });\n };\n\n const anyFilterActive = severityFilter !== ALL || statusFilter !== ALL || typeFilter !== ALL;\n\n const body = () => {\n if (isLoading) return <LoadingState rows={4} />;\n if (isError)\n return (\n <ErrorState\n title={translate('brainyrich.insights.error.title', 'Could not load insights')}\n description={translate(\n 'brainyrich.insights.error.description',\n 'We could not reach the insights service. Please try again.'\n )}\n onRetry={() => refetch()}\n />\n );\n\n return (\n <>\n {/* Hero — premium KPI tiles + severity-mix donut, wired to the live inbox */}\n <FadeIn className=\"grid gap-4 lg:grid-cols-[minmax(0,1.55fr)_minmax(0,1fr)]\">\n <div className=\"grid grid-cols-2 gap-4 sm:grid-cols-4 lg:grid-cols-2 xl:grid-cols-4\">\n <StatTile\n label={translate('brainyrich.insights.metrics.total', 'Signals')}\n value={String(insights.length)}\n glow\n icon={<BellRing className=\"size-4\" aria-hidden=\"true\" />}\n />\n <StatTile\n label={translate('brainyrich.insights.metrics.open', 'Open')}\n value={String(counts.open)}\n icon={<Info className=\"size-4\" aria-hidden=\"true\" />}\n />\n <StatTile\n label={translate('brainyrich.insights.metrics.critical', 'Critical')}\n value={String(counts.critical)}\n deltaTone={counts.critical > 0 ? 'negative' : 'positive'}\n icon={<ShieldAlert className=\"size-4\" aria-hidden=\"true\" />}\n />\n <StatTile\n label={translate('brainyrich.insights.metrics.resolved', 'Resolved')}\n value={String(counts.resolved)}\n deltaTone=\"positive\"\n icon={<CheckCircle2 className=\"size-4\" aria-hidden=\"true\" />}\n />\n </div>\n\n <GlassCard className=\"flex min-w-0 flex-col p-5\">\n <p className=\"text-sm font-medium text-text-primary\">\n {translate('brainyrich.insights.hero.severityMix', 'Severity mix')}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {translate(\n 'brainyrich.insights.hero.severityMixHint',\n 'Distribution across the loaded inbox'\n )}\n </p>\n {severityDist.length > 0 ? (\n <div className=\"mt-2 min-w-0\">\n <DonutChart\n data={severityDist}\n centerLabel={translate('brainyrich.insights.hero.center', 'Signals')}\n centerValue={String(insights.length)}\n height={200}\n />\n </div>\n ) : (\n <p className=\"mt-6 text-sm text-text-secondary\">\n {translate('brainyrich.insights.hero.noData', 'No signals to chart yet.')}\n </p>\n )}\n </GlassCard>\n </FadeIn>\n\n {/* Quick-triage summary chips — toggle the underlying filters */}\n <FadeIn index={1} className=\"flex flex-wrap gap-2\">\n <SummaryChip\n label={translate('brainyrich.insights.metrics.open', 'Open')}\n count={counts.open}\n tone=\"info\"\n active={statusFilter === 'OPEN'}\n onClick={() => {\n setStatusFilter(statusFilter === 'OPEN' ? ALL : 'OPEN');\n setSeverityFilter(ALL);\n }}\n />\n <SummaryChip\n label={translate('brainyrich.insights.metrics.critical', 'Critical')}\n count={counts.critical}\n tone=\"error\"\n active={severityFilter === 'CRITICAL'}\n onClick={() => {\n setSeverityFilter(severityFilter === 'CRITICAL' ? ALL : 'CRITICAL');\n setStatusFilter(ALL);\n }}\n />\n <SummaryChip\n label={translate('brainyrich.insights.metrics.resolved', 'Resolved')}\n count={counts.resolved}\n tone=\"success\"\n active={statusFilter === 'RESOLVED'}\n onClick={() => {\n setStatusFilter(statusFilter === 'RESOLVED' ? ALL : 'RESOLVED');\n setSeverityFilter(ALL);\n }}\n />\n </FadeIn>\n\n {/* Filters */}\n <Card>\n <CardContent className=\"flex flex-col gap-3 p-4 sm:flex-row sm:items-end\">\n <div className=\"w-full space-y-1.5 sm:w-48\">\n <Label htmlFor=\"insight-filter-severity\">\n {translate('brainyrich.insights.filters.severity', 'Severity')}\n </Label>\n <Select value={severityFilter} onValueChange={setSeverityFilter}>\n <SelectTrigger id=\"insight-filter-severity\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={ALL}>\n {translate('brainyrich.insights.filters.all', 'All')}\n </SelectItem>\n {INSIGHT_SEVERITIES.map((s) => (\n <SelectItem key={s} value={s}>\n {humanize(s)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"w-full space-y-1.5 sm:w-48\">\n <Label htmlFor=\"insight-filter-status\">\n {translate('brainyrich.insights.filters.status', 'Status')}\n </Label>\n <Select value={statusFilter} onValueChange={setStatusFilter}>\n <SelectTrigger id=\"insight-filter-status\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={ALL}>\n {translate('brainyrich.insights.filters.all', 'All')}\n </SelectItem>\n {INSIGHT_STATUSES.map((s) => (\n <SelectItem key={s} value={s}>\n {humanize(s)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"w-full space-y-1.5 sm:w-56\">\n <Label htmlFor=\"insight-filter-type\">\n {translate('brainyrich.insights.filters.type', 'Type')}\n </Label>\n <Select value={typeFilter} onValueChange={setTypeFilter}>\n <SelectTrigger id=\"insight-filter-type\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={ALL}>\n {translate('brainyrich.insights.filters.all', 'All')}\n </SelectItem>\n {INSIGHT_TYPES.map((s) => (\n <SelectItem key={s} value={s}>\n {humanize(s)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </CardContent>\n </Card>\n\n {filtered.length === 0 ? (\n <EmptyState\n icon={<BellRing className=\"size-6\" aria-hidden=\"true\" />}\n title={\n anyFilterActive\n ? translate('brainyrich.insights.empty.filteredTitle', 'No matching insights')\n : translate('brainyrich.insights.empty.title', 'No advisory insights yet')\n }\n description={\n anyFilterActive\n ? translate(\n 'brainyrich.insights.empty.filteredDescription',\n 'No insights match the selected filters. Adjust or clear them to see more.'\n )\n : translate(\n 'brainyrich.insights.empty.description',\n 'Advisory insights flag rebalancing, drift, concentration and other opportunities. Create one to get started.'\n )\n }\n action={\n anyFilterActive ? (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => {\n setSeverityFilter(ALL);\n setStatusFilter(ALL);\n setTypeFilter(ALL);\n }}\n >\n {translate('brainyrich.insights.actions.clearFilters', 'Clear filters')}\n </Button>\n ) : (\n <Button size=\"sm\" onClick={openCreate}>\n <Plus className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.insights.actions.create', 'New insight')}\n </Button>\n )\n }\n />\n ) : (\n <div className=\"space-y-3\">\n {filtered.map((insight, idx) => (\n <InsightCard\n key={insight.id}\n index={idx}\n insight={insight}\n subjectName={subjectNames.get(insight.subjectId)}\n translate={translate}\n onAcknowledge={() => acknowledge.mutate(insight.id)}\n onDismiss={() => dismiss.mutate(insight.id)}\n onResolve={() => resolve.mutate(insight.id)}\n acknowledgePending={acknowledge.isPending}\n dismissPending={dismiss.isPending}\n resolvePending={resolve.isPending}\n />\n ))}\n </div>\n )}\n\n <LoadMore\n hasMore={hasMore}\n onClick={loadMore}\n loading={isFetchingNextPage}\n label={translate('brainyrich.insights.actions.loadMore', 'Load more insights')}\n />\n </>\n );\n };\n\n return (\n <>\n <SectionShell\n title={translate('brainyrich.insights.title', 'Insights')}\n description={translate(\n 'brainyrich.insights.description',\n 'Advisory insights across portfolios, accounts and goals — triage, acknowledge and resolve.'\n )}\n badges={[translate('brainyrich.insights.badges.advisory', 'Advisory')]}\n actionLabel={translate('brainyrich.insights.actions.create', 'New insight')}\n onAction={openCreate}\n >\n {body()}\n </SectionShell>\n\n <InsightFormDialog\n open={createOpen}\n form={form}\n setField={setField}\n metricsValid={metricsValid}\n valid={formValid}\n pending={createInsight.isPending}\n onSubmit={handleCreate}\n onOpenChange={(v) => setCreateOpen(v)}\n translate={translate}\n />\n </>\n );\n}\n\ntype Translate = (\n key: string,\n fallback: string,\n params?: Record<string, string | number>\n) => string;\n\ninterface SummaryChipProps {\n label: string;\n count: number;\n tone: 'info' | 'error' | 'success';\n active: boolean;\n onClick: () => void;\n}\n\nfunction SummaryChip({ label, count, tone, active, onClick }: SummaryChipProps) {\n const dotClass =\n tone === 'error'\n ? 'bg-status-error-text'\n : tone === 'success'\n ? 'bg-status-success-text'\n : 'bg-status-info-text';\n return (\n <button\n type=\"button\"\n onClick={onClick}\n aria-pressed={active}\n className={`group inline-flex items-center gap-2 rounded-full border px-3.5 py-1.5 text-sm font-medium transition-colors motion-safe:transition-shadow focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-action-primary-border)] ${\n active\n ? 'border-[var(--color-action-primary-border)] bg-bg-elevated text-text-primary shadow-[var(--shadow-elevation-1)]'\n : 'border-border-subtle bg-bg-surface text-text-secondary hover:border-[var(--color-action-primary-border)] hover:text-text-primary'\n }`}\n >\n <span className={`size-2 rounded-full ${dotClass}`} aria-hidden=\"true\" />\n {label}\n <span className=\"rounded-full bg-bg-sunken px-2 py-0.5 text-xs tabular-nums text-text-primary\">\n {count}\n </span>\n </button>\n );\n}\n\ninterface InsightCardProps {\n index: number;\n insight: BraInsight;\n /** Referenced entity name resolved from the list queries, if known. */\n subjectName?: string;\n translate: Translate;\n onAcknowledge: () => void;\n onDismiss: () => void;\n onResolve: () => void;\n acknowledgePending: boolean;\n dismissPending: boolean;\n resolvePending: boolean;\n}\n\nfunction InsightCard({\n index,\n insight,\n subjectName,\n translate,\n onAcknowledge,\n onDismiss,\n onResolve,\n acknowledgePending,\n dismissPending,\n resolvePending,\n}: InsightCardProps) {\n const meta = severityMeta(insight.severity);\n const SeverityIcon = meta.icon;\n const isClosed = insight.status === 'RESOLVED' || insight.status === 'DISMISSED';\n const isDismissed = insight.status === 'DISMISSED';\n const [dismissOpen, setDismissOpen] = useState(false);\n\n return (\n <FadeIn as=\"div\" index={index}>\n <Card className=\"overflow-hidden transition-shadow motion-safe:hover:shadow-[var(--shadow-elevation-2)]\">\n <CardHeader className=\"pb-3\">\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"flex min-w-0 items-start gap-3\">\n <span\n className={`mt-0.5 flex size-9 shrink-0 items-center justify-center rounded-full bg-bg-sunken ${meta.tone}`}\n >\n <SeverityIcon className=\"size-5\" aria-hidden=\"true\" />\n </span>\n <div className=\"min-w-0\">\n <CardTitle className=\"text-base\">{insight.title}</CardTitle>\n <CardDescription className=\"mt-1 flex flex-wrap items-center gap-2\">\n <Badge variant=\"outline\">{humanize(insight.type)}</Badge>\n <Badge variant={statusBadgeVariant(insight.severity)}>\n <span className={`inline-flex items-center gap-1 ${meta.tone}`}>\n <SeverityIcon className=\"size-3\" aria-hidden=\"true\" />\n {humanize(insight.severity)}\n </span>\n </Badge>\n <Badge variant={statusBadgeVariant(insight.status)}>\n {humanize(insight.status)}\n </Badge>\n </CardDescription>\n </div>\n </div>\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label={translate('brainyrich.insights.actions.menu', 'Insight actions')}\n >\n <MoreHorizontal className=\"size-4\" aria-hidden=\"true\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuItem\n disabled={acknowledgePending || insight.status === 'ACKNOWLEDGED' || isClosed}\n onSelect={onAcknowledge}\n >\n <CheckCircle2 className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.insights.actions.acknowledge', 'Acknowledge')}\n </DropdownMenuItem>\n <DropdownMenuItem\n disabled={resolvePending || insight.status === 'RESOLVED'}\n onSelect={onResolve}\n >\n <CheckCircle2 className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.insights.actions.resolve', 'Resolve')}\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n className=\"text-status-error-text focus:text-status-error-text\"\n disabled={dismissPending || insight.status === 'DISMISSED'}\n onSelect={(e) => {\n e.preventDefault();\n setDismissOpen(true);\n }}\n >\n <XCircle className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.insights.actions.dismiss', 'Dismiss')}\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {insight.detail ? <p className=\"text-sm text-text-secondary\">{insight.detail}</p> : null}\n <dl className=\"grid grid-cols-2 gap-3 rounded-lg bg-bg-sunken p-3 text-sm sm:grid-cols-3\">\n <div>\n <dt className=\"text-xs text-text-secondary\">\n {translate('brainyrich.insights.card.subjectType', 'Subject')}\n </dt>\n <dd className=\"font-medium text-text-primary\">{humanize(insight.subjectType)}</dd>\n </div>\n <div className=\"min-w-0\">\n <dt className=\"text-xs text-text-secondary\">\n {translate('brainyrich.insights.card.subject', 'Reference')}\n </dt>\n <dd\n className=\"truncate font-medium text-text-primary\"\n title={subjectName ? `${subjectName} (${insight.subjectId})` : insight.subjectId}\n >\n {subjectName ?? insight.subjectId}\n </dd>\n </div>\n <div>\n <dt className=\"text-xs text-text-secondary\">\n {translate('brainyrich.insights.card.created', 'Created')}\n </dt>\n <dd className=\"font-medium text-text-primary\">{formatDate(insight.createdAt)}</dd>\n </div>\n </dl>\n {isDismissed ? (\n <div className=\"flex items-center gap-2 rounded-lg bg-bg-sunken px-3 py-2 text-sm text-text-secondary\">\n <XCircle className=\"size-4 text-status-error-text\" aria-hidden=\"true\" />\n {translate('brainyrich.insights.card.dismissed', 'Dismissed from active triage')}\n </div>\n ) : (\n <LifecycleStepper steps={LIFECYCLE_STEPS} current={humanize(insight.status)} />\n )}\n <div className=\"flex flex-wrap items-center gap-2\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={acknowledgePending || insight.status === 'ACKNOWLEDGED' || isClosed}\n onClick={onAcknowledge}\n >\n <CheckCircle2 className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.insights.actions.acknowledge', 'Acknowledge')}\n </Button>\n <Button\n size=\"sm\"\n disabled={resolvePending || insight.status === 'RESOLVED'}\n onClick={onResolve}\n >\n <CheckCircle2 className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.insights.actions.resolve', 'Resolve')}\n </Button>\n </div>\n </CardContent>\n\n <ConfirmDialog\n open={dismissOpen}\n onOpenChange={setDismissOpen}\n title={translate('brainyrich.insights.dismiss.title', 'Dismiss this insight?')}\n description={translate(\n 'brainyrich.insights.dismiss.description',\n 'Dismissing removes this insight from active triage. You can still find it by filtering for dismissed insights.'\n )}\n confirmLabel={translate('brainyrich.insights.actions.dismiss', 'Dismiss')}\n pendingLabel={translate('brainyrich.insights.dismiss.pending', 'Dismissing…')}\n destructive\n pending={dismissPending}\n onConfirm={onDismiss}\n />\n </Card>\n </FadeIn>\n );\n}\n\ninterface InsightFormDialogProps {\n open: boolean;\n form: InsightFormState;\n setField: <K extends keyof InsightFormState>(key: K, value: InsightFormState[K]) => void;\n metricsValid: boolean;\n valid: boolean;\n pending: boolean;\n onSubmit: () => void;\n onOpenChange: (open: boolean) => void;\n translate: Translate;\n}\n\nfunction InsightFormDialog({\n open,\n form,\n setField,\n metricsValid,\n valid,\n pending,\n onSubmit,\n onOpenChange,\n translate,\n}: InsightFormDialogProps) {\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent className=\"max-h-[90vh] overflow-y-auto sm:max-w-lg\">\n <DialogHeader>\n <DialogTitle>\n {translate('brainyrich.insights.form.createTitle', 'New insight')}\n </DialogTitle>\n <DialogDescription>\n {translate(\n 'brainyrich.insights.form.subtitle',\n 'Flag an advisory insight against a portfolio, account, goal or household.'\n )}\n </DialogDescription>\n </DialogHeader>\n\n <form\n className=\"space-y-4\"\n onSubmit={(e) => {\n e.preventDefault();\n onSubmit();\n }}\n >\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"insight-title\">\n {translate('brainyrich.insights.form.title', 'Title')}\n </Label>\n <Input\n id=\"insight-title\"\n value={form.title}\n onChange={(e) => setField('title', e.target.value)}\n placeholder={translate(\n 'brainyrich.insights.form.titlePlaceholder',\n 'e.g. Technology concentration above threshold'\n )}\n required\n />\n </div>\n\n <div className=\"grid grid-cols-2 gap-3\">\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"insight-type\">\n {translate('brainyrich.insights.form.type', 'Type')}\n </Label>\n <Select\n value={form.type}\n onValueChange={(v) => setField('type', v as BraInsightType)}\n >\n <SelectTrigger id=\"insight-type\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {INSIGHT_TYPES.map((tpe) => (\n <SelectItem key={tpe} value={tpe}>\n {humanize(tpe)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"insight-severity\">\n {translate('brainyrich.insights.form.severity', 'Severity')}\n </Label>\n <Select\n value={form.severity}\n onValueChange={(v) => setField('severity', v as BraInsightSeverity)}\n >\n <SelectTrigger id=\"insight-severity\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {INSIGHT_SEVERITIES.map((s) => (\n <SelectItem key={s} value={s}>\n {humanize(s)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n\n <SubjectPicker\n id=\"insight-subject\"\n label={translate('brainyrich.insights.form.subject', 'Subject')}\n placeholder={translate(\n 'brainyrich.insights.form.subjectPlaceholder',\n 'Select an account, portfolio, goal or household'\n )}\n value={form.subject}\n onChange={(v) => setField('subject', v)}\n />\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"insight-owner\">\n {translate('brainyrich.insights.form.ownerId', 'Owner ID (optional)')}\n </Label>\n <Input\n id=\"insight-owner\"\n value={form.ownerId}\n onChange={(e) => setField('ownerId', e.target.value)}\n placeholder={translate(\n 'brainyrich.insights.form.ownerIdPlaceholder',\n 'Defaults to the current owner'\n )}\n />\n </div>\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"insight-detail\">\n {translate('brainyrich.insights.form.detail', 'Detail')}\n </Label>\n <Textarea\n id=\"insight-detail\"\n value={form.detail}\n onChange={(e) => setField('detail', e.target.value)}\n rows={3}\n placeholder={translate(\n 'brainyrich.insights.form.detailPlaceholder',\n 'Explain the finding and recommended action.'\n )}\n />\n </div>\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"insight-metrics\">\n {translate('brainyrich.insights.form.metrics', 'Metrics JSON (optional)')}\n </Label>\n <Textarea\n id=\"insight-metrics\"\n value={form.metrics}\n onChange={(e) => setField('metrics', e.target.value)}\n rows={3}\n className=\"font-mono text-xs\"\n placeholder='{ \"driftPct\": 8.2 }'\n aria-invalid={!metricsValid}\n />\n {!metricsValid ? (\n <p className=\"flex items-center gap-1 text-xs text-status-error-text\">\n <AlertTriangle className=\"size-3.5\" aria-hidden=\"true\" />\n {translate(\n 'brainyrich.insights.form.metricsInvalid',\n 'Enter valid JSON or leave blank.'\n )}\n </p>\n ) : null}\n </div>\n\n <DialogFooter>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => onOpenChange(false)}\n disabled={pending}\n >\n {translate('brainyrich.insights.form.cancel', 'Cancel')}\n </Button>\n <Button type=\"submit\" disabled={!valid || pending}>\n {pending\n ? translate('brainyrich.insights.form.saving', 'Saving…')\n : translate('brainyrich.insights.form.create', 'Create insight')}\n </Button>\n </DialogFooter>\n </form>\n </DialogContent>\n </Dialog>\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"AnalyticsPage.js","names":[],"sources":["../../../src/brainyrich/pages/AnalyticsPage.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport {\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n CardDescription,\n Button,\n Badge,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n Input,\n Label,\n Textarea,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@burdenoff/fe-libs/ui';\nimport {\n ArrowDownRight,\n ArrowUpRight,\n BarChart3,\n Coins,\n Minus,\n PieChart,\n Plus,\n TrendingDown,\n TrendingUp,\n Wallet,\n} from 'lucide-react';\nimport {\n useNetWorthSummary,\n useAllTransactions,\n useAccounts,\n useHoldings,\n useRecordTransaction,\n} from '../hooks/useBrainyRichApi';\nimport type { BraAssetClass, BraHolding, BraTransaction, BraTransactionType } from '../types/bra';\nimport {\n DonutChart,\n TrendBars,\n StatTile,\n GlassCard,\n FadeIn,\n ProgressRing,\n type DonutDatum,\n type VizTone,\n} from '../components';\nimport {\n SectionShell,\n EmptyState,\n LoadingState,\n ErrorState,\n formatMoney,\n formatCompact,\n formatPct,\n formatDate,\n} from './_shared';\nimport type { AllocationDatum } from './_shared';\n\n// Map each asset class to a distinct semantic tone (color never the only signal —\n// the donut also carries a labelled legend and a full data table beneath it).\nconst ASSET_TONE: Record<BraAssetClass, VizTone> = {\n EQUITY: 'brand',\n FIXED_INCOME: 'blue',\n CASH: 'teal',\n REAL_ESTATE: 'purple',\n COMMODITY: 'warning',\n CRYPTO: 'indigo',\n ALTERNATIVE: 'info',\n};\n\n// ---------------------------------------------------------------------------\n// Pure derivation helpers (every value traces back to backend rows — no mocks)\n// ---------------------------------------------------------------------------\n\nconst TITLE_CASE = (raw: string): string =>\n raw\n .toLowerCase()\n .split('_')\n .map((w) => (w ? w[0].toUpperCase() + w.slice(1) : w))\n .join(' ');\n\nconst INFLOW_TYPES: readonly BraTransactionType[] = ['DEPOSIT', 'DIVIDEND', 'INTEREST', 'SELL'];\nconst OUTFLOW_TYPES: readonly BraTransactionType[] = ['WITHDRAWAL', 'FEE', 'BUY'];\n\nconst flowDirection = (type: BraTransactionType): 'in' | 'out' | 'neutral' => {\n if (INFLOW_TYPES.includes(type)) return 'in';\n if (OUTFLOW_TYPES.includes(type)) return 'out';\n return 'neutral';\n};\n\ninterface MonthFlow {\n key: string;\n label: string;\n inflow: number;\n outflow: number;\n}\n\nconst monthKey = (iso: string): { key: string; label: string } | null => {\n const d = new Date(iso);\n if (Number.isNaN(d.getTime())) return null;\n const key = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}`;\n const label = new Intl.DateTimeFormat('en-US', { month: 'short', year: 'numeric' }).format(d);\n return { key, label };\n};\n\nconst aggregateByMonth = (transactions: BraTransaction[]): MonthFlow[] => {\n const buckets = new Map<string, MonthFlow>();\n for (const tx of transactions) {\n const parsed = monthKey(tx.tradeDate);\n if (!parsed) continue;\n const dir = flowDirection(tx.type);\n if (dir === 'neutral') continue;\n const value = Math.abs(tx.amount);\n const existing = buckets.get(parsed.key) ?? {\n key: parsed.key,\n label: parsed.label,\n inflow: 0,\n outflow: 0,\n };\n if (dir === 'in') existing.inflow += value;\n else existing.outflow += value;\n buckets.set(parsed.key, existing);\n }\n return Array.from(buckets.values()).sort((a, b) => a.key.localeCompare(b.key));\n};\n\nconst aggregateByType = (\n transactions: BraTransaction[]\n): Array<{ type: BraTransactionType; total: number; dir: 'in' | 'out' | 'neutral' }> => {\n const buckets = new Map<BraTransactionType, number>();\n for (const tx of transactions) {\n buckets.set(tx.type, (buckets.get(tx.type) ?? 0) + Math.abs(tx.amount));\n }\n return Array.from(buckets.entries())\n .map(([type, total]) => ({ type, total, dir: flowDirection(type) }))\n .sort((a, b) => b.total - a.total);\n};\n\n// ---------------------------------------------------------------------------\n// Signed gain/loss cell — color is never the only signal (icon + sign + color)\n// ---------------------------------------------------------------------------\n\nfunction GainCell({\n value,\n currency,\n pct,\n}: {\n value: number;\n currency: string;\n pct?: number | null;\n}) {\n const positive = value > 0;\n const negative = value < 0;\n const Icon = positive ? ArrowUpRight : negative ? ArrowDownRight : Minus;\n const tone = positive\n ? 'text-status-success-text'\n : negative\n ? 'text-status-error-text'\n : 'text-text-secondary';\n const sign = positive ? '+' : negative ? '-' : '';\n const showPct = pct !== undefined && pct !== null && Number.isFinite(pct);\n return (\n <span className={`inline-flex items-center justify-end gap-1 font-medium tabular-nums ${tone}`}>\n <Icon className=\"size-3.5 shrink-0\" aria-hidden=\"true\" />\n {sign}\n {formatMoney(Math.abs(value), currency)}\n {showPct ? (\n <span className=\"text-xs opacity-80\">\n ({pct > 0 ? '+' : ''}\n {pct.toFixed(1)}%)\n </span>\n ) : null}\n </span>\n );\n}\n\nconst emptyTransactionForm = {\n accountId: '',\n type: 'DEPOSIT' as BraTransactionType,\n amount: '',\n symbol: '',\n tradeDate: '',\n notes: '',\n};\n\nconst TRANSACTION_TYPES: readonly BraTransactionType[] = [\n 'DEPOSIT',\n 'WITHDRAWAL',\n 'DIVIDEND',\n 'INTEREST',\n 'FEE',\n 'BUY',\n 'SELL',\n 'TRANSFER',\n];\n\nexport function AnalyticsPage() {\n const summaryQuery = useNetWorthSummary();\n // Aggregate cash flow / net cash flow over the FULL transaction set (all pages),\n // not just a truncated first page, so totals and the KPI are accurate.\n const txQuery = useAllTransactions();\n const accountsQuery = useAccounts();\n\n const [selectedAccountId, setSelectedAccountId] = useState<string | undefined>(undefined);\n const accounts = accountsQuery.data;\n const effectiveAccountId = selectedAccountId ?? accounts[0]?.id;\n const holdingsQuery = useHoldings({ accountId: effectiveAccountId });\n\n // Record-transaction dialog (real create action → refreshes cashflow)\n const recordTx = useRecordTransaction();\n const [dialogOpen, setDialogOpen] = useState(false);\n const [form, setForm] = useState(emptyTransactionForm);\n\n const summary = summaryQuery.data;\n const currency = summary?.currency ?? 'USD';\n const transactions = txQuery.data;\n\n const assetAllocation = useMemo<AllocationDatum[]>(() => {\n if (!summary || summary.totalMarketValue <= 0) return [];\n return summary.byAssetClass\n .filter((row) => row.marketValue !== 0)\n .map((row) => ({\n label: TITLE_CASE(row.assetClass as BraAssetClass),\n value: (row.marketValue / summary.totalMarketValue) * 100,\n caption: formatMoney(row.marketValue, currency),\n tone: 'accent' as const,\n }))\n .sort((a, b) => b.value - a.value);\n }, [summary, currency]);\n\n // Donut slices keyed on absolute market value (legend/tooltip show currency).\n const donutAllocation = useMemo<DonutDatum[]>(() => {\n if (!summary || summary.totalMarketValue <= 0) return [];\n return summary.byAssetClass\n .filter((row) => row.marketValue > 0)\n .map((row) => ({\n label: TITLE_CASE(row.assetClass as BraAssetClass),\n value: row.marketValue,\n tone: ASSET_TONE[row.assetClass as BraAssetClass],\n }))\n .sort((a, b) => b.value - a.value);\n }, [summary]);\n\n const composition = useMemo<DonutDatum[]>(() => {\n if (!summary) return [];\n const base = summary.totalMarketValue + summary.totalCash;\n if (base <= 0) return [];\n return [\n { label: 'Invested', value: summary.totalMarketValue, tone: 'brand' as const },\n { label: 'Cash', value: summary.totalCash, tone: 'teal' as const },\n ].filter((d) => d.value > 0);\n }, [summary]);\n\n const investedPct = useMemo(() => {\n if (!summary) return 0;\n const base = summary.totalMarketValue + summary.totalCash;\n return base > 0 ? (summary.totalMarketValue / base) * 100 : 0;\n }, [summary]);\n\n const monthFlows = useMemo(() => aggregateByMonth(transactions), [transactions]);\n const typeFlows = useMemo(() => aggregateByType(transactions), [transactions]);\n const flowTotals = useMemo(() => {\n let inflow = 0;\n let outflow = 0;\n for (const m of monthFlows) {\n inflow += m.inflow;\n outflow += m.outflow;\n }\n return { inflow, outflow, net: inflow - outflow };\n }, [monthFlows]);\n // Real per-month net series (inflow − outflow) — decorative spark on the KPI.\n const netFlowSeries = useMemo(() => monthFlows.map((m) => m.inflow - m.outflow), [monthFlows]);\n\n const holdings = holdingsQuery.data;\n const performance = useMemo(() => {\n const rows = holdings\n .map((h: BraHolding) => {\n const unrealized = h.marketValue - h.costBasis;\n const pct = h.costBasis > 0 ? (unrealized / h.costBasis) * 100 : null;\n return { holding: h, unrealized, pct };\n })\n .sort((a, b) => b.unrealized - a.unrealized);\n const totalUnrealized = rows.reduce((s, r) => s + r.unrealized, 0);\n const totalCost = holdings.reduce((s, h) => s + h.costBasis, 0);\n const gainers = rows.filter((r) => r.unrealized > 0).slice(0, 4);\n const losers = rows\n .filter((r) => r.unrealized < 0)\n .sort((a, b) => a.unrealized - b.unrealized)\n .slice(0, 4);\n return { rows, totalUnrealized, totalCost, gainers, losers };\n }, [holdings]);\n\n // --- Top-level loading / error gates (summary drives KPIs + allocation) ---\n if (summaryQuery.isLoading) {\n return (\n <SectionShell\n title=\"Wealth Analytics\"\n description=\"Allocation, cash flow, and holdings performance derived from your real accounts.\"\n >\n <LoadingState rows={5} />\n </SectionShell>\n );\n }\n\n if (summaryQuery.isError || !summary) {\n return (\n <SectionShell\n title=\"Wealth Analytics\"\n description=\"Allocation, cash flow, and holdings performance derived from your real accounts.\"\n >\n <ErrorState\n title=\"Could not load analytics\"\n description=\"We couldn't reach the wealth service. Please retry.\"\n onRetry={() => summaryQuery.refetch()}\n />\n </SectionShell>\n );\n }\n\n const amountNum = Number(form.amount);\n const canSubmit =\n Boolean(form.accountId) &&\n Boolean(form.tradeDate) &&\n form.amount.trim() !== '' &&\n Number.isFinite(amountNum) &&\n amountNum > 0 &&\n !recordTx.isPending;\n\n const submitTransaction = () => {\n if (!canSubmit) return;\n recordTx.mutate(\n {\n accountId: form.accountId,\n type: form.type,\n amount: amountNum,\n symbol: form.symbol.trim() ? form.symbol.trim() : undefined,\n tradeDate: new Date(form.tradeDate).toISOString(),\n notes: form.notes.trim() ? form.notes.trim() : undefined,\n },\n {\n onSuccess: () => {\n setDialogOpen(false);\n setForm(emptyTransactionForm);\n },\n }\n );\n };\n\n const recordAction = (\n <Dialog\n open={dialogOpen}\n onOpenChange={(next) => {\n setDialogOpen(next);\n if (!next) setForm(emptyTransactionForm);\n }}\n >\n <DialogTrigger asChild>\n <Button size=\"sm\">\n <Plus className=\"mr-1 size-4\" aria-hidden=\"true\" />\n Record Transaction\n </Button>\n </DialogTrigger>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>Record Transaction</DialogTitle>\n <DialogDescription>\n Log a real cash flow or trade. It updates your cash-flow analytics immediately.\n </DialogDescription>\n </DialogHeader>\n {accounts.length === 0 ? (\n <EmptyState\n icon={<Wallet className=\"size-6\" aria-hidden=\"true\" />}\n title=\"Create an account first\"\n description=\"You need at least one account before you can record a transaction. Open the Accounts page to add one, then come back here.\"\n />\n ) : (\n <div className=\"space-y-4\">\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"tx-account\">Account</Label>\n <Select\n value={form.accountId}\n onValueChange={(v) => setForm((f) => ({ ...f, accountId: v }))}\n >\n <SelectTrigger id=\"tx-account\">\n <SelectValue placeholder=\"Select an account\" />\n </SelectTrigger>\n <SelectContent>\n {accounts.map((a) => (\n <SelectItem key={a.id} value={a.id}>\n {a.name}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"grid grid-cols-2 gap-4\">\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"tx-type\">Type</Label>\n <Select\n value={form.type}\n onValueChange={(v) => setForm((f) => ({ ...f, type: v as BraTransactionType }))}\n >\n <SelectTrigger id=\"tx-type\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {TRANSACTION_TYPES.map((t) => (\n <SelectItem key={t} value={t}>\n {TITLE_CASE(t)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"tx-amount\">Amount ({currency})</Label>\n <Input\n id=\"tx-amount\"\n type=\"number\"\n min=\"0\"\n step=\"0.01\"\n inputMode=\"decimal\"\n placeholder=\"0.00\"\n value={form.amount}\n onChange={(e) => setForm((f) => ({ ...f, amount: e.target.value }))}\n />\n </div>\n </div>\n <div className=\"grid grid-cols-2 gap-4\">\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"tx-date\">Trade date</Label>\n <Input\n id=\"tx-date\"\n type=\"date\"\n value={form.tradeDate}\n onChange={(e) => setForm((f) => ({ ...f, tradeDate: e.target.value }))}\n />\n </div>\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"tx-symbol\">Symbol (optional)</Label>\n <Input\n id=\"tx-symbol\"\n placeholder=\"e.g. AAPL\"\n value={form.symbol}\n onChange={(e) => setForm((f) => ({ ...f, symbol: e.target.value }))}\n />\n </div>\n </div>\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"tx-notes\">Notes (optional)</Label>\n <Textarea\n id=\"tx-notes\"\n rows={2}\n placeholder=\"Context for this transaction\"\n value={form.notes}\n onChange={(e) => setForm((f) => ({ ...f, notes: e.target.value }))}\n />\n </div>\n {recordTx.isError ? (\n <p className=\"text-sm text-status-error-text\">\n {recordTx.error instanceof Error\n ? recordTx.error.message\n : 'Could not record transaction.'}\n </p>\n ) : null}\n </div>\n )}\n <DialogFooter>\n <Button variant=\"outline\" onClick={() => setDialogOpen(false)}>\n {accounts.length === 0 ? 'Close' : 'Cancel'}\n </Button>\n {accounts.length > 0 ? (\n <Button onClick={submitTransaction} disabled={!canSubmit}>\n {recordTx.isPending ? 'Recording…' : 'Record'}\n </Button>\n ) : null}\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n\n return (\n <SectionShell\n title=\"Wealth Analytics\"\n description=\"Allocation, cash flow, and holdings performance derived from your real accounts.\"\n badges={[`${summary.accountCount} accounts`]}\n actions={recordAction}\n >\n <div className=\"grid gap-4 md:grid-cols-2 xl:grid-cols-4\">\n <FadeIn index={0}>\n <StatTile\n label=\"Net Worth\"\n value={formatMoney(summary.totalNetWorth, currency)}\n icon={<Wallet className=\"size-4\" aria-hidden=\"true\" />}\n glow\n />\n </FadeIn>\n <FadeIn index={1}>\n <StatTile\n label=\"Invested Value\"\n value={formatMoney(summary.totalMarketValue, currency)}\n icon={<TrendingUp className=\"size-4\" aria-hidden=\"true\" />}\n />\n </FadeIn>\n <FadeIn index={2}>\n <StatTile\n label=\"Cash\"\n value={formatMoney(summary.totalCash, currency)}\n icon={<Coins className=\"size-4\" aria-hidden=\"true\" />}\n />\n </FadeIn>\n <FadeIn index={3}>\n <StatTile\n label=\"Net Cash Flow\"\n value={formatMoney(flowTotals.net, currency)}\n deltaTone={\n flowTotals.net > 0 ? 'positive' : flowTotals.net < 0 ? 'negative' : 'neutral'\n }\n delta={flowTotals.inflow > 0 ? (flowTotals.net / flowTotals.inflow) * 100 : undefined}\n deltaSuffix=\"% of inflows\"\n spark={netFlowSeries.length > 1 ? netFlowSeries : undefined}\n sparkTone={flowTotals.net >= 0 ? 'positive' : 'negative'}\n icon={<BarChart3 className=\"size-4\" aria-hidden=\"true\" />}\n />\n </FadeIn>\n </div>\n\n <Tabs defaultValue=\"allocation\" className=\"space-y-4\">\n <TabsList className=\"grid w-full grid-cols-3\">\n <TabsTrigger value=\"allocation\">Allocation</TabsTrigger>\n <TabsTrigger value=\"cashflow\">Cash Flow</TabsTrigger>\n <TabsTrigger value=\"performance\">Performance</TabsTrigger>\n </TabsList>\n\n {/* ---------------------------------------------------------------- */}\n {/* Allocation */}\n {/* ---------------------------------------------------------------- */}\n <TabsContent value=\"allocation\" className=\"space-y-4\">\n <FadeIn>\n <GlassCard glow className=\"space-y-5\">\n <div className=\"flex items-center gap-2\">\n <PieChart className=\"size-5 text-text-secondary\" aria-hidden=\"true\" />\n <div>\n <h2 className=\"text-base font-semibold text-text-primary\">Asset Allocation</h2>\n <p className=\"text-sm text-text-secondary\">\n Share of invested value by asset class, from your holdings.\n </p>\n </div>\n </div>\n {assetAllocation.length === 0 ? (\n <EmptyState\n icon={<PieChart className=\"size-6\" aria-hidden=\"true\" />}\n title=\"No invested holdings yet\"\n description=\"Add holdings to your accounts to see an asset-class breakdown here.\"\n />\n ) : (\n <div className=\"grid gap-6 lg:grid-cols-[minmax(0,1fr)_minmax(0,1.1fr)] lg:items-center\">\n <DonutChart\n data={donutAllocation}\n height={240}\n centerValue={formatCompact(summary.totalMarketValue, currency)}\n centerLabel=\"Invested\"\n valueFormatter={(v) => formatMoney(v, currency)}\n />\n <div className=\"overflow-x-auto\">\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>Asset class</TableHead>\n <TableHead className=\"text-right\">Weight</TableHead>\n <TableHead className=\"text-right\">Market value</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {assetAllocation.map((row) => (\n <TableRow key={row.label}>\n <TableCell className=\"font-medium text-text-primary\">\n {row.label}\n </TableCell>\n <TableCell className=\"text-right tabular-nums text-text-secondary\">\n {formatPct(row.value)}\n </TableCell>\n <TableCell className=\"text-right tabular-nums font-medium text-text-primary\">\n {row.caption}\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </div>\n </div>\n )}\n </GlassCard>\n </FadeIn>\n\n <FadeIn index={1}>\n <Card className=\"transition-shadow motion-safe:hover:shadow-[var(--shadow-pop-hover,var(--shadow-elevation-2))]\">\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <Wallet className=\"size-5\" aria-hidden=\"true\" />\n Net Worth Composition\n </CardTitle>\n <CardDescription>Invested value versus liquid cash.</CardDescription>\n </CardHeader>\n <CardContent>\n {composition.length === 0 ? (\n <EmptyState\n icon={<Wallet className=\"size-6\" aria-hidden=\"true\" />}\n title=\"No balances yet\"\n description=\"Add accounts with balances or holdings to see your composition.\"\n />\n ) : (\n <div className=\"flex flex-col items-center gap-6 sm:flex-row sm:justify-around\">\n <ProgressRing value={investedPct} label=\"Invested\" tone=\"brand\" size={140} />\n <div className=\"min-w-0 flex-1\">\n <DonutChart\n data={composition}\n height={180}\n centerValue={formatCompact(summary.totalNetWorth, currency)}\n centerLabel=\"Net worth\"\n valueFormatter={(v) => formatMoney(v, currency)}\n />\n </div>\n </div>\n )}\n </CardContent>\n </Card>\n </FadeIn>\n </TabsContent>\n\n {/* ---------------------------------------------------------------- */}\n {/* Cash flow */}\n {/* ---------------------------------------------------------------- */}\n <TabsContent value=\"cashflow\" className=\"space-y-4\">\n <FadeIn>\n <GlassCard className=\"space-y-5\">\n <div className=\"flex items-center gap-2\">\n <BarChart3 className=\"size-5 text-text-secondary\" aria-hidden=\"true\" />\n <div>\n <h2 className=\"text-base font-semibold text-text-primary\">\n Inflows vs Outflows by month\n </h2>\n <p className=\"text-sm text-text-secondary\">\n Monthly cash flow aggregated from your recorded transactions.\n {transactions.length > 0\n ? ` Based on ${transactions.length.toLocaleString()} ${\n transactions.length === 1 ? 'transaction' : 'transactions'\n }.`\n : ''}\n </p>\n </div>\n </div>\n {txQuery.isLoading ? (\n <LoadingState rows={4} />\n ) : txQuery.isError ? (\n <ErrorState onRetry={() => txQuery.refetch()} />\n ) : monthFlows.length === 0 ? (\n <EmptyState\n icon={<BarChart3 className=\"size-6\" aria-hidden=\"true\" />}\n title=\"No cash flow to analyze yet\"\n description=\"Record deposits, withdrawals, or trades to build a cash-flow history.\"\n action={\n <Button size=\"sm\" onClick={() => setDialogOpen(true)}>\n <Plus className=\"mr-1 size-4\" aria-hidden=\"true\" />\n Record Transaction\n </Button>\n }\n />\n ) : (\n <div className=\"space-y-4\">\n <TrendBars\n data={monthFlows}\n height={280}\n valueFormatter={(v) => formatCompact(v, currency)}\n />\n <div className=\"flex flex-wrap gap-4 text-xs text-text-secondary\">\n <span className=\"inline-flex items-center gap-1.5\">\n <ArrowUpRight\n className=\"size-3.5 text-status-success-text\"\n aria-hidden=\"true\"\n />\n Inflow\n </span>\n <span className=\"inline-flex items-center gap-1.5\">\n <ArrowDownRight\n className=\"size-3.5 text-status-error-text\"\n aria-hidden=\"true\"\n />\n Outflow\n </span>\n </div>\n </div>\n )}\n </GlassCard>\n </FadeIn>\n\n {monthFlows.length > 0 ? (\n <div className=\"grid gap-4 sm:grid-cols-3\">\n <FadeIn index={0}>\n <StatTile\n label=\"Total inflows\"\n value={formatMoney(flowTotals.inflow, currency)}\n icon={<ArrowUpRight className=\"size-4\" aria-hidden=\"true\" />}\n sparkTone=\"positive\"\n />\n </FadeIn>\n <FadeIn index={1}>\n <StatTile\n label=\"Total outflows\"\n value={formatMoney(flowTotals.outflow, currency)}\n icon={<ArrowDownRight className=\"size-4\" aria-hidden=\"true\" />}\n />\n </FadeIn>\n <FadeIn index={2}>\n <StatTile\n label=\"Net\"\n value={formatMoney(flowTotals.net, currency)}\n deltaTone={\n flowTotals.net > 0 ? 'positive' : flowTotals.net < 0 ? 'negative' : 'neutral'\n }\n delta={\n flowTotals.inflow > 0 ? (flowTotals.net / flowTotals.inflow) * 100 : undefined\n }\n deltaSuffix=\"% of inflows\"\n glow\n />\n </FadeIn>\n </div>\n ) : null}\n\n {typeFlows.length > 0 ? (\n <FadeIn>\n <Card className=\"transition-shadow motion-safe:hover:shadow-[var(--shadow-pop-hover,var(--shadow-elevation-2))]\">\n <CardHeader>\n <CardTitle>By Transaction Type</CardTitle>\n <CardDescription>Total value moved per transaction type.</CardDescription>\n </CardHeader>\n <CardContent className=\"overflow-x-auto\">\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>Type</TableHead>\n <TableHead>Direction</TableHead>\n <TableHead className=\"text-right\">Total</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {typeFlows.map((row) => (\n <TableRow key={row.type} className=\"transition-colors hover:bg-bg-elevated\">\n <TableCell className=\"font-medium text-text-primary\">\n {TITLE_CASE(row.type)}\n </TableCell>\n <TableCell>\n <Badge\n variant={\n row.dir === 'in'\n ? 'default'\n : row.dir === 'out'\n ? 'destructive'\n : 'secondary'\n }\n >\n {row.dir === 'in'\n ? 'Inflow'\n : row.dir === 'out'\n ? 'Outflow'\n : 'Neutral'}\n </Badge>\n </TableCell>\n <TableCell className=\"text-right font-medium tabular-nums\">\n {formatMoney(row.total, currency)}\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </CardContent>\n </Card>\n </FadeIn>\n ) : null}\n </TabsContent>\n\n {/* ---------------------------------------------------------------- */}\n {/* Performance */}\n {/* ---------------------------------------------------------------- */}\n <TabsContent value=\"performance\" className=\"space-y-4\">\n <Card>\n <CardHeader className=\"flex flex-col gap-3 md:flex-row md:items-start md:justify-between\">\n <div>\n <CardTitle>Holdings Performance</CardTitle>\n <CardDescription>\n Unrealized gain or loss — market value versus cost basis.\n </CardDescription>\n </div>\n {accounts.length > 0 ? (\n <div className=\"w-full md:w-56\">\n <Label htmlFor=\"perf-account\" className=\"sr-only\">\n Account\n </Label>\n <Select\n value={effectiveAccountId ?? ''}\n onValueChange={(v) => setSelectedAccountId(v)}\n >\n <SelectTrigger id=\"perf-account\">\n <SelectValue placeholder=\"Select account\" />\n </SelectTrigger>\n <SelectContent>\n {accounts.map((a) => (\n <SelectItem key={a.id} value={a.id}>\n {a.name}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n ) : null}\n </CardHeader>\n <CardContent>\n {accountsQuery.isLoading ? (\n <LoadingState rows={3} />\n ) : accounts.length === 0 ? (\n <EmptyState\n icon={<Wallet className=\"size-6\" aria-hidden=\"true\" />}\n title=\"No accounts yet\"\n description=\"Create an account and add holdings to analyze performance.\"\n />\n ) : holdingsQuery.isLoading ? (\n <LoadingState rows={3} />\n ) : holdingsQuery.isError ? (\n <ErrorState onRetry={() => holdingsQuery.refetch()} />\n ) : performance.rows.length === 0 ? (\n <EmptyState\n icon={<BarChart3 className=\"size-6\" aria-hidden=\"true\" />}\n title=\"No holdings in this account\"\n description=\"Add holdings to this account to see unrealized gains and losses.\"\n />\n ) : (\n <div className=\"space-y-4\">\n <div className=\"grid gap-4 sm:grid-cols-3\">\n <StatTile\n label=\"Total unrealized\"\n value={`${performance.totalUnrealized >= 0 ? '+' : '-'}${formatMoney(\n Math.abs(performance.totalUnrealized),\n currency\n )}`}\n deltaTone={\n performance.totalUnrealized > 0\n ? 'positive'\n : performance.totalUnrealized < 0\n ? 'negative'\n : 'neutral'\n }\n delta={\n performance.totalCost > 0\n ? (performance.totalUnrealized / performance.totalCost) * 100\n : undefined\n }\n glow={performance.totalUnrealized >= 0}\n />\n <StatTile\n label=\"Cost basis\"\n value={formatMoney(performance.totalCost, currency)}\n />\n <StatTile\n label=\"Return on cost\"\n value={formatPct(\n performance.totalCost > 0\n ? (performance.totalUnrealized / performance.totalCost) * 100\n : null\n )}\n />\n </div>\n <div className=\"overflow-x-auto\">\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>Holding</TableHead>\n <TableHead className=\"text-right\">Market value</TableHead>\n <TableHead className=\"text-right\">Cost basis</TableHead>\n <TableHead className=\"text-right\">Unrealized gain/loss</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {performance.rows.map(({ holding, unrealized, pct }) => (\n <TableRow\n key={holding.id}\n className=\"transition-colors hover:bg-bg-elevated\"\n >\n <TableCell>\n <div className=\"font-medium text-text-primary\">{holding.symbol}</div>\n <div className=\"text-xs text-text-secondary\">\n {holding.name ?? TITLE_CASE(holding.assetClass)} · as of{' '}\n {formatDate(holding.asOf)}\n </div>\n </TableCell>\n <TableCell className=\"text-right tabular-nums\">\n {formatMoney(holding.marketValue, holding.currency)}\n </TableCell>\n <TableCell className=\"text-right tabular-nums text-text-secondary\">\n {formatMoney(holding.costBasis, holding.currency)}\n </TableCell>\n <TableCell className=\"text-right\">\n <GainCell value={unrealized} currency={holding.currency} pct={pct} />\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </div>\n </div>\n )}\n </CardContent>\n </Card>\n\n {performance.rows.length > 0 &&\n (performance.gainers.length > 0 || performance.losers.length > 0) ? (\n <div className=\"grid gap-4 md:grid-cols-2\">\n {performance.gainers.length > 0 ? (\n <FadeIn index={0}>\n <GlassCard className=\"space-y-3\">\n <div className=\"flex items-center gap-2\">\n <TrendingUp className=\"size-4 text-status-success-text\" aria-hidden=\"true\" />\n <h3 className=\"text-sm font-semibold text-text-primary\">Top gainers</h3>\n </div>\n <ul className=\"space-y-2\">\n {performance.gainers.map(({ holding, unrealized, pct }) => (\n <li\n key={holding.id}\n className=\"flex items-center justify-between gap-3 text-sm\"\n >\n <span className=\"font-medium text-text-primary\">{holding.symbol}</span>\n <GainCell value={unrealized} currency={holding.currency} pct={pct} />\n </li>\n ))}\n </ul>\n </GlassCard>\n </FadeIn>\n ) : null}\n {performance.losers.length > 0 ? (\n <FadeIn index={1}>\n <GlassCard className=\"space-y-3\">\n <div className=\"flex items-center gap-2\">\n <TrendingDown className=\"size-4 text-status-error-text\" aria-hidden=\"true\" />\n <h3 className=\"text-sm font-semibold text-text-primary\">Top losers</h3>\n </div>\n <ul className=\"space-y-2\">\n {performance.losers.map(({ holding, unrealized, pct }) => (\n <li\n key={holding.id}\n className=\"flex items-center justify-between gap-3 text-sm\"\n >\n <span className=\"font-medium text-text-primary\">{holding.symbol}</span>\n <GainCell value={unrealized} currency={holding.currency} pct={pct} />\n </li>\n ))}\n </ul>\n </GlassCard>\n </FadeIn>\n ) : null}\n </div>\n ) : null}\n </TabsContent>\n </Tabs>\n </SectionShell>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"AnalyticsPage.js","names":[],"sources":["../../../src/brainyrich/pages/AnalyticsPage.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport {\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n CardDescription,\n Button,\n Badge,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n Input,\n Label,\n Textarea,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@burdenoff/fe-libs/ui';\nimport {\n ArrowDownRight,\n ArrowUpRight,\n BarChart3,\n Coins,\n Minus,\n PieChart,\n Plus,\n TrendingDown,\n TrendingUp,\n Wallet,\n} from 'lucide-react';\nimport {\n useNetWorthSummary,\n useAllTransactions,\n useAccounts,\n useHoldings,\n useRecordTransaction,\n} from '../hooks/useBrainyRichApi';\nimport type { BraAssetClass, BraHolding, BraTransaction, BraTransactionType } from '../types/bra';\nimport {\n DonutChart,\n TrendBars,\n StatTile,\n GlassCard,\n FadeIn,\n ProgressRing,\n type DonutDatum,\n type VizTone,\n} from '../components';\nimport {\n SectionShell,\n EmptyState,\n LoadingState,\n ErrorState,\n formatMoney,\n formatCompact,\n formatPct,\n formatDate,\n} from './_shared';\nimport type { AllocationDatum } from './_shared';\n\n// Map each asset class to a distinct semantic tone (color never the only signal —\n// the donut also carries a labelled legend and a full data table beneath it).\nconst ASSET_TONE: Record<BraAssetClass, VizTone> = {\n EQUITY: 'brand',\n FIXED_INCOME: 'blue',\n CASH: 'teal',\n REAL_ESTATE: 'purple',\n COMMODITY: 'warning',\n CRYPTO: 'indigo',\n ALTERNATIVE: 'info',\n};\n\n// ---------------------------------------------------------------------------\n// Pure derivation helpers (every value traces back to backend rows — no mocks)\n// ---------------------------------------------------------------------------\n\nconst TITLE_CASE = (raw: string): string =>\n raw\n .toLowerCase()\n .split('_')\n .map((w) => (w ? w[0].toUpperCase() + w.slice(1) : w))\n .join(' ');\n\nconst INFLOW_TYPES: readonly BraTransactionType[] = ['DEPOSIT', 'DIVIDEND', 'INTEREST', 'SELL'];\nconst OUTFLOW_TYPES: readonly BraTransactionType[] = ['WITHDRAWAL', 'FEE', 'BUY'];\n\nconst flowDirection = (type: BraTransactionType): 'in' | 'out' | 'neutral' => {\n if (INFLOW_TYPES.includes(type)) return 'in';\n if (OUTFLOW_TYPES.includes(type)) return 'out';\n return 'neutral';\n};\n\ninterface MonthFlow {\n key: string;\n label: string;\n inflow: number;\n outflow: number;\n}\n\nconst monthKey = (iso: string): { key: string; label: string } | null => {\n const d = new Date(iso);\n if (Number.isNaN(d.getTime())) return null;\n const key = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}`;\n const label = new Intl.DateTimeFormat('en-US', { month: 'short', year: 'numeric' }).format(d);\n return { key, label };\n};\n\nconst aggregateByMonth = (transactions: BraTransaction[]): MonthFlow[] => {\n const buckets = new Map<string, MonthFlow>();\n for (const tx of transactions) {\n const parsed = monthKey(tx.tradeDate);\n if (!parsed) continue;\n const dir = flowDirection(tx.type);\n if (dir === 'neutral') continue;\n const value = Math.abs(tx.amount);\n const existing = buckets.get(parsed.key) ?? {\n key: parsed.key,\n label: parsed.label,\n inflow: 0,\n outflow: 0,\n };\n if (dir === 'in') existing.inflow += value;\n else existing.outflow += value;\n buckets.set(parsed.key, existing);\n }\n return Array.from(buckets.values()).sort((a, b) => a.key.localeCompare(b.key));\n};\n\nconst aggregateByType = (\n transactions: BraTransaction[]\n): Array<{ type: BraTransactionType; total: number; dir: 'in' | 'out' | 'neutral' }> => {\n const buckets = new Map<BraTransactionType, number>();\n for (const tx of transactions) {\n buckets.set(tx.type, (buckets.get(tx.type) ?? 0) + Math.abs(tx.amount));\n }\n return Array.from(buckets.entries())\n .map(([type, total]) => ({ type, total, dir: flowDirection(type) }))\n .sort((a, b) => b.total - a.total);\n};\n\n// ---------------------------------------------------------------------------\n// Signed gain/loss cell — color is never the only signal (icon + sign + color)\n// ---------------------------------------------------------------------------\n\nfunction GainCell({\n value,\n currency,\n pct,\n}: {\n value: number;\n currency: string;\n pct?: number | null;\n}) {\n const positive = value > 0;\n const negative = value < 0;\n const Icon = positive ? ArrowUpRight : negative ? ArrowDownRight : Minus;\n const tone = positive\n ? 'text-status-success-text'\n : negative\n ? 'text-status-error-text'\n : 'text-text-secondary';\n const sign = positive ? '+' : negative ? '-' : '';\n const showPct = pct !== undefined && pct !== null && Number.isFinite(pct);\n return (\n <span className={`inline-flex items-center justify-end gap-1 font-medium tabular-nums ${tone}`}>\n <Icon className=\"size-3.5 shrink-0\" aria-hidden=\"true\" />\n {sign}\n {formatMoney(Math.abs(value), currency)}\n {showPct ? (\n <span className=\"text-xs opacity-80\">\n ({pct > 0 ? '+' : ''}\n {pct.toFixed(1)}%)\n </span>\n ) : null}\n </span>\n );\n}\n\nconst emptyTransactionForm = {\n accountId: '',\n type: 'DEPOSIT' as BraTransactionType,\n amount: '',\n symbol: '',\n tradeDate: '',\n notes: '',\n};\n\nconst TRANSACTION_TYPES: readonly BraTransactionType[] = [\n 'DEPOSIT',\n 'WITHDRAWAL',\n 'DIVIDEND',\n 'INTEREST',\n 'FEE',\n 'BUY',\n 'SELL',\n 'TRANSFER',\n];\n\nexport function AnalyticsPage() {\n const summaryQuery = useNetWorthSummary();\n // Aggregate cash flow / net cash flow over the FULL transaction set (all pages),\n // not just a truncated first page, so totals and the KPI are accurate.\n const txQuery = useAllTransactions();\n const accountsQuery = useAccounts();\n\n const [selectedAccountId, setSelectedAccountId] = useState<string | undefined>(undefined);\n const accounts = accountsQuery.data;\n const effectiveAccountId = selectedAccountId ?? accounts[0]?.id;\n const holdingsQuery = useHoldings({ accountId: effectiveAccountId });\n\n // Record-transaction dialog (real create action → refreshes cashflow)\n const recordTx = useRecordTransaction();\n const [dialogOpen, setDialogOpen] = useState(false);\n const [form, setForm] = useState(emptyTransactionForm);\n\n const summary = summaryQuery.data;\n const currency = summary?.currency ?? 'USD';\n const transactions = txQuery.data;\n\n const assetAllocation = useMemo<AllocationDatum[]>(() => {\n if (!summary || summary.totalMarketValue <= 0) return [];\n return summary.byAssetClass\n .filter((row) => row.marketValue !== 0)\n .map((row) => ({\n label: TITLE_CASE(row.assetClass as BraAssetClass),\n value: (row.marketValue / summary.totalMarketValue) * 100,\n caption: formatMoney(row.marketValue, currency),\n tone: 'accent' as const,\n }))\n .sort((a, b) => b.value - a.value);\n }, [summary, currency]);\n\n // Donut slices keyed on absolute market value (legend/tooltip show currency).\n const donutAllocation = useMemo<DonutDatum[]>(() => {\n if (!summary || summary.totalMarketValue <= 0) return [];\n return summary.byAssetClass\n .filter((row) => row.marketValue > 0)\n .map((row) => ({\n label: TITLE_CASE(row.assetClass as BraAssetClass),\n value: row.marketValue,\n tone: ASSET_TONE[row.assetClass as BraAssetClass],\n }))\n .sort((a, b) => b.value - a.value);\n }, [summary]);\n\n const composition = useMemo<DonutDatum[]>(() => {\n if (!summary) return [];\n const base = summary.totalMarketValue + summary.totalCash;\n if (base <= 0) return [];\n return [\n { label: 'Invested', value: summary.totalMarketValue, tone: 'brand' as const },\n { label: 'Cash', value: summary.totalCash, tone: 'teal' as const },\n ].filter((d) => d.value > 0);\n }, [summary]);\n\n const investedPct = useMemo(() => {\n if (!summary) return 0;\n const base = summary.totalMarketValue + summary.totalCash;\n return base > 0 ? (summary.totalMarketValue / base) * 100 : 0;\n }, [summary]);\n\n const monthFlows = useMemo(() => aggregateByMonth(transactions), [transactions]);\n const typeFlows = useMemo(() => aggregateByType(transactions), [transactions]);\n const flowTotals = useMemo(() => {\n let inflow = 0;\n let outflow = 0;\n for (const m of monthFlows) {\n inflow += m.inflow;\n outflow += m.outflow;\n }\n return { inflow, outflow, net: inflow - outflow };\n }, [monthFlows]);\n // Real per-month net series (inflow − outflow) — decorative spark on the KPI.\n const netFlowSeries = useMemo(() => monthFlows.map((m) => m.inflow - m.outflow), [monthFlows]);\n\n const holdings = holdingsQuery.data;\n const performance = useMemo(() => {\n const rows = holdings\n .map((h: BraHolding) => {\n const unrealized = h.marketValue - h.costBasis;\n const pct = h.costBasis > 0 ? (unrealized / h.costBasis) * 100 : null;\n return { holding: h, unrealized, pct };\n })\n .sort((a, b) => b.unrealized - a.unrealized);\n const totalUnrealized = rows.reduce((s, r) => s + r.unrealized, 0);\n const totalCost = holdings.reduce((s, h) => s + h.costBasis, 0);\n const gainers = rows.filter((r) => r.unrealized > 0).slice(0, 4);\n const losers = rows\n .filter((r) => r.unrealized < 0)\n .sort((a, b) => a.unrealized - b.unrealized)\n .slice(0, 4);\n return { rows, totalUnrealized, totalCost, gainers, losers };\n }, [holdings]);\n\n // --- Top-level loading / error gates (summary drives KPIs + allocation) ---\n if (summaryQuery.isLoading) {\n return (\n <SectionShell\n title=\"Wealth Analytics\"\n description=\"Allocation, cash flow, and holdings performance derived from your real accounts.\"\n >\n <LoadingState rows={5} />\n </SectionShell>\n );\n }\n\n if (summaryQuery.isError || !summary) {\n return (\n <SectionShell\n title=\"Wealth Analytics\"\n description=\"Allocation, cash flow, and holdings performance derived from your real accounts.\"\n >\n <ErrorState\n title=\"Could not load analytics\"\n description=\"We couldn't reach the wealth service. Please retry.\"\n onRetry={() => summaryQuery.refetch()}\n />\n </SectionShell>\n );\n }\n\n const amountNum = Number(form.amount);\n const canSubmit =\n Boolean(form.accountId) &&\n Boolean(form.tradeDate) &&\n form.amount.trim() !== '' &&\n Number.isFinite(amountNum) &&\n amountNum > 0 &&\n !recordTx.isPending;\n\n const submitTransaction = () => {\n if (!canSubmit) return;\n recordTx.mutate(\n {\n accountId: form.accountId,\n type: form.type,\n amount: amountNum,\n symbol: form.symbol.trim() ? form.symbol.trim() : undefined,\n tradeDate: new Date(form.tradeDate).toISOString(),\n notes: form.notes.trim() ? form.notes.trim() : undefined,\n },\n {\n onSuccess: () => {\n setDialogOpen(false);\n setForm(emptyTransactionForm);\n },\n }\n );\n };\n\n const recordAction = (\n <Dialog\n open={dialogOpen}\n onOpenChange={(next) => {\n setDialogOpen(next);\n if (!next) setForm(emptyTransactionForm);\n }}\n >\n <DialogTrigger asChild>\n <Button size=\"sm\">\n <Plus className=\"mr-1 size-4\" aria-hidden=\"true\" />\n Record Transaction\n </Button>\n </DialogTrigger>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>Record Transaction</DialogTitle>\n <DialogDescription>\n Log a real cash flow or trade. It updates your cash-flow analytics immediately.\n </DialogDescription>\n </DialogHeader>\n {accounts.length === 0 ? (\n <EmptyState\n icon={<Wallet className=\"size-6\" aria-hidden=\"true\" />}\n title=\"Create an account first\"\n description=\"You need at least one account before you can record a transaction. Open the Accounts page to add one, then come back here.\"\n />\n ) : (\n <div className=\"space-y-4\">\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"tx-account\">Account</Label>\n <Select\n value={form.accountId}\n onValueChange={(v) => setForm((f) => ({ ...f, accountId: v }))}\n >\n <SelectTrigger id=\"tx-account\">\n <SelectValue placeholder=\"Select an account\" />\n </SelectTrigger>\n <SelectContent>\n {accounts.map((a) => (\n <SelectItem key={a.id} value={a.id}>\n {a.name}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"grid grid-cols-2 gap-4\">\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"tx-type\">Type</Label>\n <Select\n value={form.type}\n onValueChange={(v) => setForm((f) => ({ ...f, type: v as BraTransactionType }))}\n >\n <SelectTrigger id=\"tx-type\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {TRANSACTION_TYPES.map((t) => (\n <SelectItem key={t} value={t}>\n {TITLE_CASE(t)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"tx-amount\">Amount ({currency})</Label>\n <Input\n id=\"tx-amount\"\n type=\"number\"\n min=\"0\"\n step=\"0.01\"\n inputMode=\"decimal\"\n placeholder=\"0.00\"\n value={form.amount}\n onChange={(e) => setForm((f) => ({ ...f, amount: e.target.value }))}\n />\n </div>\n </div>\n <div className=\"grid grid-cols-2 gap-4\">\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"tx-date\">Trade date</Label>\n <Input\n id=\"tx-date\"\n type=\"date\"\n value={form.tradeDate}\n onChange={(e) => setForm((f) => ({ ...f, tradeDate: e.target.value }))}\n />\n </div>\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"tx-symbol\">Symbol (optional)</Label>\n <Input\n id=\"tx-symbol\"\n placeholder=\"e.g. AAPL\"\n value={form.symbol}\n onChange={(e) => setForm((f) => ({ ...f, symbol: e.target.value }))}\n />\n </div>\n </div>\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"tx-notes\">Notes (optional)</Label>\n <Textarea\n id=\"tx-notes\"\n rows={2}\n placeholder=\"Context for this transaction\"\n value={form.notes}\n onChange={(e) => setForm((f) => ({ ...f, notes: e.target.value }))}\n />\n </div>\n {recordTx.isError ? (\n <p className=\"text-sm text-status-error-text\">\n {recordTx.error instanceof Error\n ? recordTx.error.message\n : 'Could not record transaction.'}\n </p>\n ) : null}\n </div>\n )}\n <DialogFooter>\n <Button variant=\"outline\" onClick={() => setDialogOpen(false)}>\n {accounts.length === 0 ? 'Close' : 'Cancel'}\n </Button>\n {accounts.length > 0 ? (\n <Button onClick={submitTransaction} disabled={!canSubmit}>\n {recordTx.isPending ? 'Recording…' : 'Record'}\n </Button>\n ) : null}\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n\n return (\n <SectionShell\n title=\"Wealth Analytics\"\n description=\"Allocation, cash flow, and holdings performance derived from your real accounts.\"\n badges={[`${summary.accountCount} accounts`]}\n actions={recordAction}\n >\n <div className=\"grid gap-4 md:grid-cols-2 xl:grid-cols-4\">\n <FadeIn index={0}>\n <StatTile\n label=\"Net Worth\"\n value={formatMoney(summary.totalNetWorth, currency)}\n icon={<Wallet className=\"size-4\" aria-hidden=\"true\" />}\n glow\n />\n </FadeIn>\n <FadeIn index={1}>\n <StatTile\n label=\"Invested Value\"\n value={formatMoney(summary.totalMarketValue, currency)}\n icon={<TrendingUp className=\"size-4\" aria-hidden=\"true\" />}\n />\n </FadeIn>\n <FadeIn index={2}>\n <StatTile\n label=\"Cash\"\n value={formatMoney(summary.totalCash, currency)}\n icon={<Coins className=\"size-4\" aria-hidden=\"true\" />}\n />\n </FadeIn>\n <FadeIn index={3}>\n <StatTile\n label=\"Net Cash Flow\"\n value={formatMoney(flowTotals.net, currency)}\n deltaTone={\n flowTotals.net > 0 ? 'positive' : flowTotals.net < 0 ? 'negative' : 'neutral'\n }\n delta={flowTotals.inflow > 0 ? (flowTotals.net / flowTotals.inflow) * 100 : undefined}\n deltaSuffix=\"% of inflows\"\n spark={netFlowSeries.length > 1 ? netFlowSeries : undefined}\n sparkTone={flowTotals.net >= 0 ? 'positive' : 'negative'}\n icon={<BarChart3 className=\"size-4\" aria-hidden=\"true\" />}\n />\n </FadeIn>\n </div>\n\n <Tabs defaultValue=\"allocation\" className=\"space-y-4\">\n <TabsList className=\"grid w-full grid-cols-3\">\n <TabsTrigger value=\"allocation\">Allocation</TabsTrigger>\n <TabsTrigger value=\"cashflow\">Cash Flow</TabsTrigger>\n <TabsTrigger value=\"performance\">Performance</TabsTrigger>\n </TabsList>\n\n {/* ---------------------------------------------------------------- */}\n {/* Allocation */}\n {/* ---------------------------------------------------------------- */}\n <TabsContent value=\"allocation\" className=\"space-y-4\">\n <FadeIn>\n <GlassCard glow className=\"space-y-5\">\n <div className=\"flex items-center gap-2\">\n <PieChart className=\"size-5 text-text-secondary\" aria-hidden=\"true\" />\n <div>\n <h2 className=\"text-base font-semibold text-text-primary\">Asset Allocation</h2>\n <p className=\"text-sm text-text-secondary\">\n Share of invested value by asset class, from your holdings.\n </p>\n </div>\n </div>\n {assetAllocation.length === 0 ? (\n <EmptyState\n icon={<PieChart className=\"size-6\" aria-hidden=\"true\" />}\n title=\"No invested holdings yet\"\n description=\"Add holdings to your accounts to see an asset-class breakdown here.\"\n />\n ) : (\n <div className=\"grid gap-6 lg:grid-cols-[minmax(0,1fr)_minmax(0,1.1fr)] lg:items-center\">\n <DonutChart\n data={donutAllocation}\n height={240}\n centerValue={formatCompact(summary.totalMarketValue, currency)}\n centerLabel=\"Invested\"\n valueFormatter={(v) => formatMoney(v, currency)}\n />\n <div className=\"overflow-x-auto\">\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>Asset class</TableHead>\n <TableHead className=\"text-right\">Weight</TableHead>\n <TableHead className=\"text-right\">Market value</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {assetAllocation.map((row) => (\n <TableRow key={row.label}>\n <TableCell className=\"font-medium text-text-primary\">\n {row.label}\n </TableCell>\n <TableCell className=\"text-right tabular-nums text-text-secondary\">\n {formatPct(row.value)}\n </TableCell>\n <TableCell className=\"text-right tabular-nums font-medium text-text-primary\">\n {row.caption}\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </div>\n </div>\n )}\n </GlassCard>\n </FadeIn>\n\n <FadeIn index={1}>\n <Card className=\"transition-shadow motion-safe:hover:shadow-[var(--shadow-pop-hover,var(--shadow-elevation-2))]\">\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <Wallet className=\"size-5\" aria-hidden=\"true\" />\n Net Worth Composition\n </CardTitle>\n <CardDescription>Invested value versus liquid cash.</CardDescription>\n </CardHeader>\n <CardContent>\n {composition.length === 0 ? (\n <EmptyState\n icon={<Wallet className=\"size-6\" aria-hidden=\"true\" />}\n title=\"No balances yet\"\n description=\"Add accounts with balances or holdings to see your composition.\"\n />\n ) : (\n <div className=\"flex flex-col items-center gap-6 sm:flex-row sm:justify-around\">\n <ProgressRing value={investedPct} label=\"Invested\" tone=\"brand\" size={140} />\n <div className=\"min-w-0 flex-1\">\n <DonutChart\n data={composition}\n height={180}\n centerValue={formatCompact(summary.totalNetWorth, currency)}\n centerLabel=\"Net worth\"\n valueFormatter={(v) => formatMoney(v, currency)}\n />\n </div>\n </div>\n )}\n </CardContent>\n </Card>\n </FadeIn>\n </TabsContent>\n\n {/* ---------------------------------------------------------------- */}\n {/* Cash flow */}\n {/* ---------------------------------------------------------------- */}\n <TabsContent value=\"cashflow\" className=\"space-y-4\">\n <FadeIn>\n <GlassCard className=\"space-y-5\">\n <div className=\"flex items-center gap-2\">\n <BarChart3 className=\"size-5 text-text-secondary\" aria-hidden=\"true\" />\n <div>\n <h2 className=\"text-base font-semibold text-text-primary\">\n Inflows vs Outflows by month\n </h2>\n <p className=\"text-sm text-text-secondary\">\n Monthly cash flow aggregated from your recorded transactions.\n {transactions.length > 0\n ? ` Based on ${transactions.length.toLocaleString()} ${\n transactions.length === 1 ? 'transaction' : 'transactions'\n }.`\n : ''}\n </p>\n </div>\n </div>\n {txQuery.isLoading ? (\n <LoadingState rows={4} />\n ) : txQuery.isError ? (\n <ErrorState onRetry={() => txQuery.refetch()} />\n ) : monthFlows.length === 0 ? (\n <EmptyState\n icon={<BarChart3 className=\"size-6\" aria-hidden=\"true\" />}\n title=\"No cash flow to analyze yet\"\n description=\"Record deposits, withdrawals, or trades to build a cash-flow history.\"\n action={\n <Button size=\"sm\" onClick={() => setDialogOpen(true)}>\n <Plus className=\"mr-1 size-4\" aria-hidden=\"true\" />\n Record Transaction\n </Button>\n }\n />\n ) : (\n <div className=\"space-y-4\">\n <TrendBars\n data={monthFlows}\n height={280}\n valueFormatter={(v) => formatCompact(v, currency)}\n />\n <div className=\"flex flex-wrap gap-4 text-xs text-text-secondary\">\n <span className=\"inline-flex items-center gap-1.5\">\n <ArrowUpRight\n className=\"size-3.5 text-status-success-text\"\n aria-hidden=\"true\"\n />\n Inflow\n </span>\n <span className=\"inline-flex items-center gap-1.5\">\n <ArrowDownRight\n className=\"size-3.5 text-status-error-text\"\n aria-hidden=\"true\"\n />\n Outflow\n </span>\n </div>\n </div>\n )}\n </GlassCard>\n </FadeIn>\n\n {monthFlows.length > 0 ? (\n <div className=\"grid gap-4 sm:grid-cols-3\">\n <FadeIn index={0}>\n <StatTile\n label=\"Total inflows\"\n value={formatMoney(flowTotals.inflow, currency)}\n icon={<ArrowUpRight className=\"size-4\" aria-hidden=\"true\" />}\n sparkTone=\"positive\"\n />\n </FadeIn>\n <FadeIn index={1}>\n <StatTile\n label=\"Total outflows\"\n value={formatMoney(flowTotals.outflow, currency)}\n icon={<ArrowDownRight className=\"size-4\" aria-hidden=\"true\" />}\n />\n </FadeIn>\n <FadeIn index={2}>\n <StatTile\n label=\"Net\"\n value={formatMoney(flowTotals.net, currency)}\n deltaTone={\n flowTotals.net > 0 ? 'positive' : flowTotals.net < 0 ? 'negative' : 'neutral'\n }\n delta={\n flowTotals.inflow > 0 ? (flowTotals.net / flowTotals.inflow) * 100 : undefined\n }\n deltaSuffix=\"% of inflows\"\n glow\n />\n </FadeIn>\n </div>\n ) : null}\n\n {typeFlows.length > 0 ? (\n <FadeIn>\n <Card className=\"transition-shadow motion-safe:hover:shadow-[var(--shadow-pop-hover,var(--shadow-elevation-2))]\">\n <CardHeader>\n <CardTitle>By Transaction Type</CardTitle>\n <CardDescription>Total value moved per transaction type.</CardDescription>\n </CardHeader>\n <CardContent className=\"overflow-x-auto\">\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>Type</TableHead>\n <TableHead>Direction</TableHead>\n <TableHead className=\"text-right\">Total</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {typeFlows.map((row) => (\n <TableRow key={row.type} className=\"transition-colors hover:bg-bg-elevated\">\n <TableCell className=\"font-medium text-text-primary\">\n {TITLE_CASE(row.type)}\n </TableCell>\n <TableCell>\n <Badge\n variant={\n row.dir === 'in'\n ? 'default'\n : row.dir === 'out'\n ? 'destructive'\n : 'secondary'\n }\n >\n {row.dir === 'in'\n ? 'Inflow'\n : row.dir === 'out'\n ? 'Outflow'\n : 'Neutral'}\n </Badge>\n </TableCell>\n <TableCell className=\"text-right font-medium tabular-nums\">\n {formatMoney(row.total, currency)}\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </CardContent>\n </Card>\n </FadeIn>\n ) : null}\n </TabsContent>\n\n {/* ---------------------------------------------------------------- */}\n {/* Performance */}\n {/* ---------------------------------------------------------------- */}\n <TabsContent value=\"performance\" className=\"space-y-4\">\n <Card>\n <CardHeader className=\"flex flex-col gap-3 md:flex-row md:items-start md:justify-between\">\n <div>\n <CardTitle>Holdings Performance</CardTitle>\n <CardDescription>\n Unrealized gain or loss — market value versus cost basis.\n </CardDescription>\n </div>\n {accounts.length > 0 ? (\n <div className=\"w-full md:w-56\">\n <Label htmlFor=\"perf-account\" className=\"sr-only\">\n Account\n </Label>\n <Select\n value={effectiveAccountId ?? ''}\n onValueChange={(v) => setSelectedAccountId(v)}\n >\n <SelectTrigger id=\"perf-account\">\n <SelectValue placeholder=\"Select account\" />\n </SelectTrigger>\n <SelectContent>\n {accounts.map((a) => (\n <SelectItem key={a.id} value={a.id}>\n {a.name}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n ) : null}\n </CardHeader>\n <CardContent>\n {accountsQuery.isLoading ? (\n <LoadingState rows={3} />\n ) : accounts.length === 0 ? (\n <EmptyState\n icon={<Wallet className=\"size-6\" aria-hidden=\"true\" />}\n title=\"No accounts yet\"\n description=\"Create an account and add holdings to analyze performance.\"\n />\n ) : holdingsQuery.isLoading ? (\n <LoadingState rows={3} />\n ) : holdingsQuery.isError ? (\n <ErrorState onRetry={() => holdingsQuery.refetch()} />\n ) : performance.rows.length === 0 ? (\n <EmptyState\n icon={<BarChart3 className=\"size-6\" aria-hidden=\"true\" />}\n title=\"No holdings in this account\"\n description=\"Add holdings to this account to see unrealized gains and losses.\"\n />\n ) : (\n <div className=\"space-y-4\">\n <div className=\"grid gap-4 sm:grid-cols-3\">\n <StatTile\n label=\"Total unrealized\"\n value={`${performance.totalUnrealized >= 0 ? '+' : '-'}${formatMoney(\n Math.abs(performance.totalUnrealized),\n currency\n )}`}\n deltaTone={\n performance.totalUnrealized > 0\n ? 'positive'\n : performance.totalUnrealized < 0\n ? 'negative'\n : 'neutral'\n }\n delta={\n performance.totalCost > 0\n ? (performance.totalUnrealized / performance.totalCost) * 100\n : undefined\n }\n glow={performance.totalUnrealized >= 0}\n />\n <StatTile\n label=\"Cost basis\"\n value={formatMoney(performance.totalCost, currency)}\n />\n <StatTile\n label=\"Return on cost\"\n value={formatPct(\n performance.totalCost > 0\n ? (performance.totalUnrealized / performance.totalCost) * 100\n : null\n )}\n />\n </div>\n <div className=\"overflow-x-auto\">\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>Holding</TableHead>\n <TableHead className=\"text-right\">Market value</TableHead>\n <TableHead className=\"text-right\">Cost basis</TableHead>\n <TableHead className=\"text-right\">Unrealized gain/loss</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {performance.rows.map(({ holding, unrealized, pct }) => (\n <TableRow\n key={holding.id}\n className=\"transition-colors hover:bg-bg-elevated\"\n >\n <TableCell>\n <div className=\"font-medium text-text-primary\">{holding.symbol}</div>\n <div className=\"text-xs text-text-secondary\">\n {holding.name ?? TITLE_CASE(holding.assetClass)} · as of{' '}\n {formatDate(holding.asOf)}\n </div>\n </TableCell>\n <TableCell className=\"text-right tabular-nums\">\n {formatMoney(holding.marketValue, holding.currency)}\n </TableCell>\n <TableCell className=\"text-right tabular-nums text-text-secondary\">\n {formatMoney(holding.costBasis, holding.currency)}\n </TableCell>\n <TableCell className=\"text-right\">\n <GainCell value={unrealized} currency={holding.currency} pct={pct} />\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </div>\n </div>\n )}\n </CardContent>\n </Card>\n\n {performance.rows.length > 0 &&\n (performance.gainers.length > 0 || performance.losers.length > 0) ? (\n <div className=\"grid gap-4 md:grid-cols-2\">\n {performance.gainers.length > 0 ? (\n <FadeIn index={0}>\n <GlassCard className=\"space-y-3\">\n <div className=\"flex items-center gap-2\">\n <TrendingUp className=\"size-4 text-status-success-text\" aria-hidden=\"true\" />\n <h3 className=\"text-sm font-semibold text-text-primary\">Top gainers</h3>\n </div>\n <ul className=\"space-y-2\">\n {performance.gainers.map(({ holding, unrealized, pct }) => (\n <li\n key={holding.id}\n className=\"flex items-center justify-between gap-3 text-sm\"\n >\n <span className=\"font-medium text-text-primary\">{holding.symbol}</span>\n <GainCell value={unrealized} currency={holding.currency} pct={pct} />\n </li>\n ))}\n </ul>\n </GlassCard>\n </FadeIn>\n ) : null}\n {performance.losers.length > 0 ? (\n <FadeIn index={1}>\n <GlassCard className=\"space-y-3\">\n <div className=\"flex items-center gap-2\">\n <TrendingDown className=\"size-4 text-status-error-text\" aria-hidden=\"true\" />\n <h3 className=\"text-sm font-semibold text-text-primary\">Top losers</h3>\n </div>\n <ul className=\"space-y-2\">\n {performance.losers.map(({ holding, unrealized, pct }) => (\n <li\n key={holding.id}\n className=\"flex items-center justify-between gap-3 text-sm\"\n >\n <span className=\"font-medium text-text-primary\">{holding.symbol}</span>\n <GainCell value={unrealized} currency={holding.currency} pct={pct} />\n </li>\n ))}\n </ul>\n </GlassCard>\n </FadeIn>\n ) : null}\n </div>\n ) : null}\n </TabsContent>\n </Tabs>\n </SectionShell>\n );\n}\n"],"mappings":"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"}