@burdenoff/microfe-brainyrich 2026.706.2 → 2026.706.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_virtual/_rolldown/runtime.js +5 -5
- package/dist/brainyrich/components/viz.js +155 -156
- package/dist/brainyrich/components/viz.js.map +1 -1
- package/dist/brainyrich/pages/AccountsPage.js.map +1 -1
- package/dist/brainyrich/pages/AiAssistantPage.js.map +1 -1
- package/dist/brainyrich/pages/AnalyticsPage.js.map +1 -1
- package/dist/brainyrich/pages/DashboardPage.js.map +1 -1
- package/dist/brainyrich/pages/FamilyPage.js.map +1 -1
- package/dist/brainyrich/pages/GoalsPage.js.map +1 -1
- package/dist/brainyrich/pages/InvestmentsPage.js.map +1 -1
- package/dist/brainyrich/pages/PortfoliosPage.js.map +1 -1
- package/dist/brainyrich/pages/ReportsPage.js +2 -1
- package/dist/brainyrich/pages/ReportsPage.js.map +1 -1
- package/dist/brainyrich/pages/RiskPage.js.map +1 -1
- package/dist/brainyrich/pages/_shared.js +76 -68
- package/dist/brainyrich/pages/_shared.js.map +1 -1
- package/package.json +3 -4
- package/dist/_virtual/__vite-optional-peer-dep_@emotion/is-prop-valid_framer-motion.js +0 -10
- package/dist/_virtual/__vite-optional-peer-dep_@emotion/is-prop-valid_framer-motion.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/components/AnimatePresence/use-presence.js +0 -22
- package/dist/node_modules/framer-motion/dist/es/components/AnimatePresence/use-presence.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/context/LayoutGroupContext.js +0 -8
- package/dist/node_modules/framer-motion/dist/es/context/LayoutGroupContext.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/context/LazyContext.js +0 -8
- package/dist/node_modules/framer-motion/dist/es/context/LazyContext.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/context/MotionConfigContext.js +0 -12
- package/dist/node_modules/framer-motion/dist/es/context/MotionConfigContext.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/context/MotionContext/create.js +0 -19
- package/dist/node_modules/framer-motion/dist/es/context/MotionContext/create.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/context/MotionContext/index.js +0 -8
- package/dist/node_modules/framer-motion/dist/es/context/MotionContext/index.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/context/MotionContext/utils.js +0 -17
- package/dist/node_modules/framer-motion/dist/es/context/MotionContext/utils.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/context/PresenceContext.js +0 -8
- package/dist/node_modules/framer-motion/dist/es/context/PresenceContext.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/context/SwitchLayoutGroupContext.js +0 -8
- package/dist/node_modules/framer-motion/dist/es/context/SwitchLayoutGroupContext.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/events/add-pointer-event.js +0 -10
- package/dist/node_modules/framer-motion/dist/es/events/add-pointer-event.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/events/event-info.js +0 -13
- package/dist/node_modules/framer-motion/dist/es/events/event-info.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/gestures/drag/VisualElementDragControls.js +0 -259
- package/dist/node_modules/framer-motion/dist/es/gestures/drag/VisualElementDragControls.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/gestures/drag/index.js +0 -24
- package/dist/node_modules/framer-motion/dist/es/gestures/drag/index.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/gestures/drag/utils/constraints.js +0 -61
- package/dist/node_modules/framer-motion/dist/es/gestures/drag/utils/constraints.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/gestures/focus.js +0 -29
- package/dist/node_modules/framer-motion/dist/es/gestures/focus.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/gestures/hover.js +0 -22
- package/dist/node_modules/framer-motion/dist/es/gestures/hover.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/gestures/pan/PanSession.js +0 -135
- package/dist/node_modules/framer-motion/dist/es/gestures/pan/PanSession.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/gestures/pan/index.js +0 -44
- package/dist/node_modules/framer-motion/dist/es/gestures/pan/index.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/gestures/press.js +0 -28
- package/dist/node_modules/framer-motion/dist/es/gestures/press.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/motion/features/animation/exit.js +0 -41
- package/dist/node_modules/framer-motion/dist/es/motion/features/animation/exit.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/motion/features/animation/index.js +0 -27
- package/dist/node_modules/framer-motion/dist/es/motion/features/animation/index.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/motion/features/animations.js +0 -11
- package/dist/node_modules/framer-motion/dist/es/motion/features/animations.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/motion/features/definitions.js +0 -53
- package/dist/node_modules/framer-motion/dist/es/motion/features/definitions.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/motion/features/drag.js +0 -17
- package/dist/node_modules/framer-motion/dist/es/motion/features/drag.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/motion/features/gestures.js +0 -15
- package/dist/node_modules/framer-motion/dist/es/motion/features/gestures.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/motion/features/layout/MeasureLayout.js +0 -63
- package/dist/node_modules/framer-motion/dist/es/motion/features/layout/MeasureLayout.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/motion/features/layout.js +0 -11
- package/dist/node_modules/framer-motion/dist/es/motion/features/layout.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/motion/features/load-features.js +0 -15
- package/dist/node_modules/framer-motion/dist/es/motion/features/load-features.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/motion/features/viewport/index.js +0 -48
- package/dist/node_modules/framer-motion/dist/es/motion/features/viewport/index.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/motion/features/viewport/observers.js +0 -26
- package/dist/node_modules/framer-motion/dist/es/motion/features/viewport/observers.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/motion/index.js +0 -72
- package/dist/node_modules/framer-motion/dist/es/motion/index.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/motion/utils/symbol.js +0 -6
- package/dist/node_modules/framer-motion/dist/es/motion/utils/symbol.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/motion/utils/use-motion-ref.js +0 -24
- package/dist/node_modules/framer-motion/dist/es/motion/utils/use-motion-ref.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/motion/utils/use-visual-element.js +0 -60
- package/dist/node_modules/framer-motion/dist/es/motion/utils/use-visual-element.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/motion/utils/use-visual-state.js +0 -52
- package/dist/node_modules/framer-motion/dist/es/motion/utils/use-visual-state.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/motion/utils/valid-prop.js +0 -9
- package/dist/node_modules/framer-motion/dist/es/motion/utils/valid-prop.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/render/components/create-proxy.js +0 -12
- package/dist/node_modules/framer-motion/dist/es/render/components/create-proxy.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/render/components/motion/feature-bundle.js +0 -15
- package/dist/node_modules/framer-motion/dist/es/render/components/motion/feature-bundle.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/render/components/motion/proxy.js +0 -9
- package/dist/node_modules/framer-motion/dist/es/render/components/motion/proxy.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/render/dom/create-visual-element.js +0 -10
- package/dist/node_modules/framer-motion/dist/es/render/dom/create-visual-element.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/render/dom/use-render.js +0 -23
- package/dist/node_modules/framer-motion/dist/es/render/dom/use-render.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/render/dom/utils/filter-props.js +0 -21
- package/dist/node_modules/framer-motion/dist/es/render/dom/utils/filter-props.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/render/dom/utils/is-svg-component.js +0 -9
- package/dist/node_modules/framer-motion/dist/es/render/dom/utils/is-svg-component.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/render/html/use-html-visual-state.js +0 -13
- package/dist/node_modules/framer-motion/dist/es/render/html/use-html-visual-state.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/render/html/use-props.js +0 -28
- package/dist/node_modules/framer-motion/dist/es/render/html/use-props.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/render/html/utils/create-render-state.js +0 -11
- package/dist/node_modules/framer-motion/dist/es/render/html/utils/create-render-state.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/render/svg/lowercase-elements.js +0 -32
- package/dist/node_modules/framer-motion/dist/es/render/svg/lowercase-elements.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/render/svg/use-props.js +0 -28
- package/dist/node_modules/framer-motion/dist/es/render/svg/use-props.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/render/svg/use-svg-visual-state.js +0 -13
- package/dist/node_modules/framer-motion/dist/es/render/svg/use-svg-visual-state.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/render/svg/utils/create-render-state.js +0 -10
- package/dist/node_modules/framer-motion/dist/es/render/svg/utils/create-render-state.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/utils/distance.js +0 -10
- package/dist/node_modules/framer-motion/dist/es/utils/distance.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/utils/get-context-window.js +0 -6
- package/dist/node_modules/framer-motion/dist/es/utils/get-context-window.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/utils/is-browser.js +0 -6
- package/dist/node_modules/framer-motion/dist/es/utils/is-browser.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/utils/is-ref-object.js +0 -8
- package/dist/node_modules/framer-motion/dist/es/utils/is-ref-object.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/utils/reduced-motion/use-reduced-motion.js +0 -15
- package/dist/node_modules/framer-motion/dist/es/utils/reduced-motion/use-reduced-motion.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/utils/use-constant.js +0 -11
- package/dist/node_modules/framer-motion/dist/es/utils/use-constant.js.map +0 -1
- package/dist/node_modules/framer-motion/dist/es/utils/use-isomorphic-effect.js +0 -9
- package/dist/node_modules/framer-motion/dist/es/utils/use-isomorphic-effect.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/AsyncMotionValueAnimation.js +0 -109
- package/dist/node_modules/motion-dom/dist/es/animation/AsyncMotionValueAnimation.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/JSAnimation.js +0 -132
- package/dist/node_modules/motion-dom/dist/es/animation/JSAnimation.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/NativeAnimation.js +0 -86
- package/dist/node_modules/motion-dom/dist/es/animation/NativeAnimation.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/NativeAnimationExtended.js +0 -30
- package/dist/node_modules/motion-dom/dist/es/animation/NativeAnimationExtended.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/animate/single-value.js +0 -12
- package/dist/node_modules/motion-dom/dist/es/animation/animate/single-value.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/drivers/frame.js +0 -15
- package/dist/node_modules/motion-dom/dist/es/animation/drivers/frame.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/generators/inertia.js +0 -34
- package/dist/node_modules/motion-dom/dist/es/animation/generators/inertia.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/generators/keyframes.js +0 -24
- package/dist/node_modules/motion-dom/dist/es/animation/generators/keyframes.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/generators/spring.js +0 -168
- package/dist/node_modules/motion-dom/dist/es/animation/generators/spring.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/generators/utils/calc-duration.js +0 -11
- package/dist/node_modules/motion-dom/dist/es/animation/generators/utils/calc-duration.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/generators/utils/create-generator-easing.js +0 -18
- package/dist/node_modules/motion-dom/dist/es/animation/generators/utils/create-generator-easing.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/generators/utils/is-generator.js +0 -8
- package/dist/node_modules/motion-dom/dist/es/animation/generators/utils/is-generator.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/generators/utils/velocity.js +0 -11
- package/dist/node_modules/motion-dom/dist/es/animation/generators/utils/velocity.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/interfaces/motion-value.js +0 -47
- package/dist/node_modules/motion-dom/dist/es/animation/interfaces/motion-value.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/interfaces/visual-element-target.js +0 -56
- package/dist/node_modules/motion-dom/dist/es/animation/interfaces/visual-element-target.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/interfaces/visual-element-variant.js +0 -28
- package/dist/node_modules/motion-dom/dist/es/animation/interfaces/visual-element-variant.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/interfaces/visual-element.js +0 -23
- package/dist/node_modules/motion-dom/dist/es/animation/interfaces/visual-element.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/keyframes/DOMKeyframesResolver.js +0 -63
- package/dist/node_modules/motion-dom/dist/es/animation/keyframes/DOMKeyframesResolver.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/keyframes/KeyframesResolver.js +0 -69
- package/dist/node_modules/motion-dom/dist/es/animation/keyframes/KeyframesResolver.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/keyframes/get-final.js +0 -10
- package/dist/node_modules/motion-dom/dist/es/animation/keyframes/get-final.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/keyframes/offsets/default.js +0 -10
- package/dist/node_modules/motion-dom/dist/es/animation/keyframes/offsets/default.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/keyframes/offsets/fill.js +0 -14
- package/dist/node_modules/motion-dom/dist/es/animation/keyframes/offsets/fill.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/keyframes/offsets/time.js +0 -8
- package/dist/node_modules/motion-dom/dist/es/animation/keyframes/offsets/time.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/keyframes/utils/fill-wildcards.js +0 -8
- package/dist/node_modules/motion-dom/dist/es/animation/keyframes/utils/fill-wildcards.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/keyframes/utils/is-none.js +0 -9
- package/dist/node_modules/motion-dom/dist/es/animation/keyframes/utils/is-none.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/keyframes/utils/make-none-animatable.js +0 -20
- package/dist/node_modules/motion-dom/dist/es/animation/keyframes/utils/make-none-animatable.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/keyframes/utils/unit-conversion.js +0 -38
- package/dist/node_modules/motion-dom/dist/es/animation/keyframes/utils/unit-conversion.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/optimized-appear/data-id.js +0 -6
- package/dist/node_modules/motion-dom/dist/es/animation/optimized-appear/data-id.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/optimized-appear/get-appear-id.js +0 -9
- package/dist/node_modules/motion-dom/dist/es/animation/optimized-appear/get-appear-id.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/utils/WithPromise.js +0 -24
- package/dist/node_modules/motion-dom/dist/es/animation/utils/WithPromise.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/utils/calc-child-stagger.js +0 -9
- package/dist/node_modules/motion-dom/dist/es/animation/utils/calc-child-stagger.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/utils/can-animate.js +0 -20
- package/dist/node_modules/motion-dom/dist/es/animation/utils/can-animate.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/utils/css-variables-conversion.js +0 -27
- package/dist/node_modules/motion-dom/dist/es/animation/utils/css-variables-conversion.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/utils/default-transitions.js +0 -29
- package/dist/node_modules/motion-dom/dist/es/animation/utils/default-transitions.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/utils/get-value-transition.js +0 -10
- package/dist/node_modules/motion-dom/dist/es/animation/utils/get-value-transition.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/utils/is-animatable.js +0 -7
- package/dist/node_modules/motion-dom/dist/es/animation/utils/is-animatable.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/utils/is-css-variable.js +0 -9
- package/dist/node_modules/motion-dom/dist/es/animation/utils/is-css-variable.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/utils/is-transition-defined.js +0 -21
- package/dist/node_modules/motion-dom/dist/es/animation/utils/is-transition-defined.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/utils/make-animation-instant.js +0 -8
- package/dist/node_modules/motion-dom/dist/es/animation/utils/make-animation-instant.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/utils/replace-transition-type.js +0 -18
- package/dist/node_modules/motion-dom/dist/es/animation/utils/replace-transition-type.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/utils/resolve-transition.js +0 -15
- package/dist/node_modules/motion-dom/dist/es/animation/utils/resolve-transition.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/waapi/easing/cubic-bezier.js +0 -6
- package/dist/node_modules/motion-dom/dist/es/animation/waapi/easing/cubic-bezier.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/waapi/easing/map-easing.js +0 -13
- package/dist/node_modules/motion-dom/dist/es/animation/waapi/easing/map-easing.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/waapi/easing/supported.js +0 -37
- package/dist/node_modules/motion-dom/dist/es/animation/waapi/easing/supported.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/waapi/start-waapi-animation.js +0 -27
- package/dist/node_modules/motion-dom/dist/es/animation/waapi/start-waapi-animation.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/waapi/supports/waapi.js +0 -26
- package/dist/node_modules/motion-dom/dist/es/animation/waapi/supports/waapi.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/waapi/utils/accelerated-values.js +0 -11
- package/dist/node_modules/motion-dom/dist/es/animation/waapi/utils/accelerated-values.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/waapi/utils/apply-generator.js +0 -10
- package/dist/node_modules/motion-dom/dist/es/animation/waapi/utils/apply-generator.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/waapi/utils/is-browser-color.js +0 -10
- package/dist/node_modules/motion-dom/dist/es/animation/waapi/utils/is-browser-color.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/waapi/utils/linear.js +0 -10
- package/dist/node_modules/motion-dom/dist/es/animation/waapi/utils/linear.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/animation/waapi/utils/unsupported-easing.js +0 -19
- package/dist/node_modules/motion-dom/dist/es/animation/waapi/utils/unsupported-easing.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/events/add-dom-event.js +0 -8
- package/dist/node_modules/motion-dom/dist/es/events/add-dom-event.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/frameloop/batcher.js +0 -32
- package/dist/node_modules/motion-dom/dist/es/frameloop/batcher.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/frameloop/frame.js +0 -8
- package/dist/node_modules/motion-dom/dist/es/frameloop/frame.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/frameloop/microtask.js +0 -7
- package/dist/node_modules/motion-dom/dist/es/frameloop/microtask.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/frameloop/order.js +0 -15
- package/dist/node_modules/motion-dom/dist/es/frameloop/order.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/frameloop/render-step.js +0 -35
- package/dist/node_modules/motion-dom/dist/es/frameloop/render-step.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/frameloop/sync-time.js +0 -17
- package/dist/node_modules/motion-dom/dist/es/frameloop/sync-time.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/gestures/drag/state/is-active.js +0 -12
- package/dist/node_modules/motion-dom/dist/es/gestures/drag/state/is-active.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/gestures/drag/state/set-active.js +0 -13
- package/dist/node_modules/motion-dom/dist/es/gestures/drag/state/set-active.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/gestures/hover.js +0 -38
- package/dist/node_modules/motion-dom/dist/es/gestures/hover.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/gestures/press/index.js +0 -35
- package/dist/node_modules/motion-dom/dist/es/gestures/press/index.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/gestures/press/utils/is-keyboard-accessible.js +0 -23
- package/dist/node_modules/motion-dom/dist/es/gestures/press/utils/is-keyboard-accessible.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/gestures/press/utils/keyboard.js +0 -30
- package/dist/node_modules/motion-dom/dist/es/gestures/press/utils/keyboard.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/gestures/press/utils/state.js +0 -6
- package/dist/node_modules/motion-dom/dist/es/gestures/press/utils/state.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/gestures/utils/is-node-or-child.js +0 -6
- package/dist/node_modules/motion-dom/dist/es/gestures/utils/is-node-or-child.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/gestures/utils/is-primary-pointer.js +0 -6
- package/dist/node_modules/motion-dom/dist/es/gestures/utils/is-primary-pointer.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/gestures/utils/setup.js +0 -18
- package/dist/node_modules/motion-dom/dist/es/gestures/utils/setup.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/projection/animation/mix-values.js +0 -31
- package/dist/node_modules/motion-dom/dist/es/projection/animation/mix-values.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/projection/geometry/conversion.js +0 -41
- package/dist/node_modules/motion-dom/dist/es/projection/geometry/conversion.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/projection/geometry/copy.js +0 -14
- package/dist/node_modules/motion-dom/dist/es/projection/geometry/copy.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/projection/geometry/delta-apply.js +0 -45
- package/dist/node_modules/motion-dom/dist/es/projection/geometry/delta-apply.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/projection/geometry/delta-calc.js +0 -32
- package/dist/node_modules/motion-dom/dist/es/projection/geometry/delta-calc.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/projection/geometry/delta-remove.js +0 -31
- package/dist/node_modules/motion-dom/dist/es/projection/geometry/delta-remove.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/projection/geometry/models.js +0 -20
- package/dist/node_modules/motion-dom/dist/es/projection/geometry/models.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/projection/geometry/utils.js +0 -30
- package/dist/node_modules/motion-dom/dist/es/projection/geometry/utils.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/projection/node/DocumentProjectionNode.js +0 -15
- package/dist/node_modules/motion-dom/dist/es/projection/node/DocumentProjectionNode.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/projection/node/HTMLProjectionNode.js +0 -24
- package/dist/node_modules/motion-dom/dist/es/projection/node/HTMLProjectionNode.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/projection/node/create-projection-node.js +0 -590
- package/dist/node_modules/motion-dom/dist/es/projection/node/create-projection-node.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/projection/node/state.js +0 -9
- package/dist/node_modules/motion-dom/dist/es/projection/node/state.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/projection/shared/stack.js +0 -53
- package/dist/node_modules/motion-dom/dist/es/projection/shared/stack.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/projection/styles/scale-border-radius.js +0 -15
- package/dist/node_modules/motion-dom/dist/es/projection/styles/scale-border-radius.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/projection/styles/scale-box-shadow.js +0 -15
- package/dist/node_modules/motion-dom/dist/es/projection/styles/scale-box-shadow.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/projection/styles/scale-correction.js +0 -23
- package/dist/node_modules/motion-dom/dist/es/projection/styles/scale-correction.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/projection/styles/transform.js +0 -14
- package/dist/node_modules/motion-dom/dist/es/projection/styles/transform.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/projection/utils/compare-by-depth.js +0 -6
- package/dist/node_modules/motion-dom/dist/es/projection/utils/compare-by-depth.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/projection/utils/each-axis.js +0 -8
- package/dist/node_modules/motion-dom/dist/es/projection/utils/each-axis.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/projection/utils/flat-tree.js +0 -21
- package/dist/node_modules/motion-dom/dist/es/projection/utils/flat-tree.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/projection/utils/has-transform.js +0 -20
- package/dist/node_modules/motion-dom/dist/es/projection/utils/has-transform.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/projection/utils/measure.js +0 -14
- package/dist/node_modules/motion-dom/dist/es/projection/utils/measure.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/render/Feature.js +0 -11
- package/dist/node_modules/motion-dom/dist/es/render/Feature.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/render/VisualElement.js +0 -206
- package/dist/node_modules/motion-dom/dist/es/render/VisualElement.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/render/dom/DOMVisualElement.js +0 -30
- package/dist/node_modules/motion-dom/dist/es/render/dom/DOMVisualElement.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/render/dom/is-css-var.js +0 -6
- package/dist/node_modules/motion-dom/dist/es/render/dom/is-css-var.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/render/dom/parse-transform.js +0 -58
- package/dist/node_modules/motion-dom/dist/es/render/dom/parse-transform.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/render/dom/style-set.js +0 -9
- package/dist/node_modules/motion-dom/dist/es/render/dom/style-set.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/render/dom/utils/camel-to-dash.js +0 -8
- package/dist/node_modules/motion-dom/dist/es/render/dom/utils/camel-to-dash.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/render/html/HTMLVisualElement.js +0 -37
- package/dist/node_modules/motion-dom/dist/es/render/html/HTMLVisualElement.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/render/html/utils/build-styles.js +0 -30
- package/dist/node_modules/motion-dom/dist/es/render/html/utils/build-styles.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/render/html/utils/build-transform.js +0 -37
- package/dist/node_modules/motion-dom/dist/es/render/html/utils/build-transform.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/render/html/utils/render.js +0 -10
- package/dist/node_modules/motion-dom/dist/es/render/html/utils/render.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/render/html/utils/scrape-motion-values.js +0 -13
- package/dist/node_modules/motion-dom/dist/es/render/html/utils/scrape-motion-values.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/render/store.js +0 -6
- package/dist/node_modules/motion-dom/dist/es/render/store.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/render/svg/SVGVisualElement.js +0 -42
- package/dist/node_modules/motion-dom/dist/es/render/svg/SVGVisualElement.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/render/svg/utils/build-attrs.js +0 -24
- package/dist/node_modules/motion-dom/dist/es/render/svg/utils/build-attrs.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/render/svg/utils/camel-case-attrs.js +0 -30
- package/dist/node_modules/motion-dom/dist/es/render/svg/utils/camel-case-attrs.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/render/svg/utils/is-svg-tag.js +0 -6
- package/dist/node_modules/motion-dom/dist/es/render/svg/utils/is-svg-tag.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/render/svg/utils/path.js +0 -17
- package/dist/node_modules/motion-dom/dist/es/render/svg/utils/path.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/render/svg/utils/render.js +0 -12
- package/dist/node_modules/motion-dom/dist/es/render/svg/utils/render.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/render/svg/utils/scrape-motion-values.js +0 -16
- package/dist/node_modules/motion-dom/dist/es/render/svg/utils/scrape-motion-values.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/render/utils/animation-state.js +0 -137
- package/dist/node_modules/motion-dom/dist/es/render/utils/animation-state.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/render/utils/get-variant-context.js +0 -21
- package/dist/node_modules/motion-dom/dist/es/render/utils/get-variant-context.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/render/utils/is-animation-controls.js +0 -8
- package/dist/node_modules/motion-dom/dist/es/render/utils/is-animation-controls.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/render/utils/is-controlling-variants.js +0 -14
- package/dist/node_modules/motion-dom/dist/es/render/utils/is-controlling-variants.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/render/utils/is-forced-motion-value.js +0 -10
- package/dist/node_modules/motion-dom/dist/es/render/utils/is-forced-motion-value.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/render/utils/is-keyframes-target.js +0 -6
- package/dist/node_modules/motion-dom/dist/es/render/utils/is-keyframes-target.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/render/utils/is-variant-label.js +0 -8
- package/dist/node_modules/motion-dom/dist/es/render/utils/is-variant-label.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/render/utils/keys-position.js +0 -15
- package/dist/node_modules/motion-dom/dist/es/render/utils/keys-position.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/render/utils/keys-transform.js +0 -24
- package/dist/node_modules/motion-dom/dist/es/render/utils/keys-transform.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/render/utils/motion-values.js +0 -23
- package/dist/node_modules/motion-dom/dist/es/render/utils/motion-values.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/render/utils/reduced-motion/index.js +0 -13
- package/dist/node_modules/motion-dom/dist/es/render/utils/reduced-motion/index.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/render/utils/reduced-motion/state.js +0 -6
- package/dist/node_modules/motion-dom/dist/es/render/utils/reduced-motion/state.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/render/utils/resolve-dynamic-variants.js +0 -10
- package/dist/node_modules/motion-dom/dist/es/render/utils/resolve-dynamic-variants.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/render/utils/resolve-variants.js +0 -22
- package/dist/node_modules/motion-dom/dist/es/render/utils/resolve-variants.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/render/utils/setters.js +0 -22
- package/dist/node_modules/motion-dom/dist/es/render/utils/setters.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/render/utils/shallow-compare.js +0 -12
- package/dist/node_modules/motion-dom/dist/es/render/utils/shallow-compare.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/render/utils/variant-props.js +0 -14
- package/dist/node_modules/motion-dom/dist/es/render/utils/variant-props.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/resize/handle-element.js +0 -39
- package/dist/node_modules/motion-dom/dist/es/resize/handle-element.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/resize/handle-window.js +0 -24
- package/dist/node_modules/motion-dom/dist/es/resize/handle-window.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/resize/index.js +0 -10
- package/dist/node_modules/motion-dom/dist/es/resize/index.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/stats/animation-count.js +0 -10
- package/dist/node_modules/motion-dom/dist/es/stats/animation-count.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/stats/buffer.js +0 -9
- package/dist/node_modules/motion-dom/dist/es/stats/buffer.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/utils/delay.js +0 -14
- package/dist/node_modules/motion-dom/dist/es/utils/delay.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/utils/interpolate.js +0 -35
- package/dist/node_modules/motion-dom/dist/es/utils/interpolate.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/utils/is-html-element.js +0 -9
- package/dist/node_modules/motion-dom/dist/es/utils/is-html-element.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/utils/is-svg-element.js +0 -9
- package/dist/node_modules/motion-dom/dist/es/utils/is-svg-element.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/utils/is-svg-svg-element.js +0 -9
- package/dist/node_modules/motion-dom/dist/es/utils/is-svg-svg-element.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/utils/mix/color.js +0 -32
- package/dist/node_modules/motion-dom/dist/es/utils/mix/color.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/utils/mix/complex.js +0 -54
- package/dist/node_modules/motion-dom/dist/es/utils/mix/complex.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/utils/mix/immediate.js +0 -8
- package/dist/node_modules/motion-dom/dist/es/utils/mix/immediate.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/utils/mix/index.js +0 -10
- package/dist/node_modules/motion-dom/dist/es/utils/mix/index.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/utils/mix/number.js +0 -6
- package/dist/node_modules/motion-dom/dist/es/utils/mix/number.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/utils/mix/visibility.js +0 -9
- package/dist/node_modules/motion-dom/dist/es/utils/mix/visibility.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/utils/resolve-elements.js +0 -16
- package/dist/node_modules/motion-dom/dist/es/utils/resolve-elements.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/utils/supports/flags.js +0 -6
- package/dist/node_modules/motion-dom/dist/es/utils/supports/flags.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/utils/supports/linear-easing.js +0 -14
- package/dist/node_modules/motion-dom/dist/es/utils/supports/linear-easing.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/utils/supports/memo.js +0 -11
- package/dist/node_modules/motion-dom/dist/es/utils/supports/memo.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/utils/supports/scroll-timeline.js +0 -7
- package/dist/node_modules/motion-dom/dist/es/utils/supports/scroll-timeline.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/value/index.js +0 -94
- package/dist/node_modules/motion-dom/dist/es/value/index.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/value/types/auto.js +0 -9
- package/dist/node_modules/motion-dom/dist/es/value/types/auto.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/value/types/color/hex.js +0 -21
- package/dist/node_modules/motion-dom/dist/es/value/types/color/hex.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/value/types/color/hsla-to-rgba.js +0 -23
- package/dist/node_modules/motion-dom/dist/es/value/types/color/hsla-to-rgba.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/value/types/color/hsla.js +0 -14
- package/dist/node_modules/motion-dom/dist/es/value/types/color/hsla.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/value/types/color/index.js +0 -17
- package/dist/node_modules/motion-dom/dist/es/value/types/color/index.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/value/types/color/rgba.js +0 -17
- package/dist/node_modules/motion-dom/dist/es/value/types/color/rgba.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/value/types/color/utils.js +0 -18
- package/dist/node_modules/motion-dom/dist/es/value/types/color/utils.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/value/types/complex/filter.js +0 -28
- package/dist/node_modules/motion-dom/dist/es/value/types/complex/filter.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/value/types/complex/index.js +0 -54
- package/dist/node_modules/motion-dom/dist/es/value/types/complex/index.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/value/types/complex/mask.js +0 -16
- package/dist/node_modules/motion-dom/dist/es/value/types/complex/mask.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/value/types/dimensions.js +0 -18
- package/dist/node_modules/motion-dom/dist/es/value/types/dimensions.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/value/types/int.js +0 -10
- package/dist/node_modules/motion-dom/dist/es/value/types/int.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/value/types/maps/defaults.js +0 -26
- package/dist/node_modules/motion-dom/dist/es/value/types/maps/defaults.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/value/types/maps/number.js +0 -66
- package/dist/node_modules/motion-dom/dist/es/value/types/maps/number.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/value/types/maps/transform.js +0 -33
- package/dist/node_modules/motion-dom/dist/es/value/types/maps/transform.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/value/types/numbers/index.js +0 -17
- package/dist/node_modules/motion-dom/dist/es/value/types/numbers/index.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/value/types/numbers/units.js +0 -14
- package/dist/node_modules/motion-dom/dist/es/value/types/numbers/units.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/value/types/test.js +0 -6
- package/dist/node_modules/motion-dom/dist/es/value/types/test.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/value/types/utils/animatable-none.js +0 -14
- package/dist/node_modules/motion-dom/dist/es/value/types/utils/animatable-none.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/value/types/utils/color-regex.js +0 -6
- package/dist/node_modules/motion-dom/dist/es/value/types/utils/color-regex.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/value/types/utils/find.js +0 -14
- package/dist/node_modules/motion-dom/dist/es/value/types/utils/find.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/value/types/utils/float-regex.js +0 -6
- package/dist/node_modules/motion-dom/dist/es/value/types/utils/float-regex.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/value/types/utils/get-as-type.js +0 -6
- package/dist/node_modules/motion-dom/dist/es/value/types/utils/get-as-type.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/value/types/utils/is-nullish.js +0 -8
- package/dist/node_modules/motion-dom/dist/es/value/types/utils/is-nullish.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/value/types/utils/sanitize.js +0 -6
- package/dist/node_modules/motion-dom/dist/es/value/types/utils/sanitize.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/value/types/utils/single-color-regex.js +0 -6
- package/dist/node_modules/motion-dom/dist/es/value/types/utils/single-color-regex.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/value/utils/is-motion-value.js +0 -6
- package/dist/node_modules/motion-dom/dist/es/value/utils/is-motion-value.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/value/utils/resolve-motion-value.js +0 -9
- package/dist/node_modules/motion-dom/dist/es/value/utils/resolve-motion-value.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/value/will-change/add-will-change.js +0 -15
- package/dist/node_modules/motion-dom/dist/es/value/will-change/add-will-change.js.map +0 -1
- package/dist/node_modules/motion-dom/dist/es/value/will-change/is.js +0 -9
- package/dist/node_modules/motion-dom/dist/es/value/will-change/is.js.map +0 -1
- package/dist/node_modules/motion-utils/dist/es/array.js +0 -12
- package/dist/node_modules/motion-utils/dist/es/array.js.map +0 -1
- package/dist/node_modules/motion-utils/dist/es/clamp.js +0 -6
- package/dist/node_modules/motion-utils/dist/es/clamp.js.map +0 -1
- package/dist/node_modules/motion-utils/dist/es/easing/anticipate.js +0 -7
- package/dist/node_modules/motion-utils/dist/es/easing/anticipate.js.map +0 -1
- package/dist/node_modules/motion-utils/dist/es/easing/back.js +0 -9
- package/dist/node_modules/motion-utils/dist/es/easing/back.js.map +0 -1
- package/dist/node_modules/motion-utils/dist/es/easing/circ.js +0 -8
- package/dist/node_modules/motion-utils/dist/es/easing/circ.js.map +0 -1
- package/dist/node_modules/motion-utils/dist/es/easing/cubic-bezier.js +0 -19
- package/dist/node_modules/motion-utils/dist/es/easing/cubic-bezier.js.map +0 -1
- package/dist/node_modules/motion-utils/dist/es/easing/ease.js +0 -7
- package/dist/node_modules/motion-utils/dist/es/easing/ease.js.map +0 -1
- package/dist/node_modules/motion-utils/dist/es/easing/modifiers/mirror.js +0 -6
- package/dist/node_modules/motion-utils/dist/es/easing/modifiers/mirror.js.map +0 -1
- package/dist/node_modules/motion-utils/dist/es/easing/modifiers/reverse.js +0 -6
- package/dist/node_modules/motion-utils/dist/es/easing/modifiers/reverse.js.map +0 -1
- package/dist/node_modules/motion-utils/dist/es/easing/utils/is-bezier-definition.js +0 -6
- package/dist/node_modules/motion-utils/dist/es/easing/utils/is-bezier-definition.js.map +0 -1
- package/dist/node_modules/motion-utils/dist/es/easing/utils/is-easing-array.js +0 -6
- package/dist/node_modules/motion-utils/dist/es/easing/utils/is-easing-array.js.map +0 -1
- package/dist/node_modules/motion-utils/dist/es/easing/utils/map.js +0 -33
- package/dist/node_modules/motion-utils/dist/es/easing/utils/map.js.map +0 -1
- package/dist/node_modules/motion-utils/dist/es/errors.js +0 -12
- package/dist/node_modules/motion-utils/dist/es/errors.js.map +0 -1
- package/dist/node_modules/motion-utils/dist/es/format-error-message.js +0 -8
- package/dist/node_modules/motion-utils/dist/es/format-error-message.js.map +0 -1
- package/dist/node_modules/motion-utils/dist/es/global-config.js +0 -6
- package/dist/node_modules/motion-utils/dist/es/global-config.js.map +0 -1
- package/dist/node_modules/motion-utils/dist/es/is-numerical-string.js +0 -6
- package/dist/node_modules/motion-utils/dist/es/is-numerical-string.js.map +0 -1
- package/dist/node_modules/motion-utils/dist/es/is-object.js +0 -8
- package/dist/node_modules/motion-utils/dist/es/is-object.js.map +0 -1
- package/dist/node_modules/motion-utils/dist/es/is-zero-value-string.js +0 -6
- package/dist/node_modules/motion-utils/dist/es/is-zero-value-string.js.map +0 -1
- package/dist/node_modules/motion-utils/dist/es/memo.js +0 -10
- package/dist/node_modules/motion-utils/dist/es/memo.js.map +0 -1
- package/dist/node_modules/motion-utils/dist/es/noop.js +0 -6
- package/dist/node_modules/motion-utils/dist/es/noop.js.map +0 -1
- package/dist/node_modules/motion-utils/dist/es/pipe.js +0 -6
- package/dist/node_modules/motion-utils/dist/es/pipe.js.map +0 -1
- package/dist/node_modules/motion-utils/dist/es/progress.js +0 -9
- package/dist/node_modules/motion-utils/dist/es/progress.js.map +0 -1
- package/dist/node_modules/motion-utils/dist/es/subscription-manager.js +0 -28
- package/dist/node_modules/motion-utils/dist/es/subscription-manager.js.map +0 -1
- package/dist/node_modules/motion-utils/dist/es/time-conversion.js +0 -6
- package/dist/node_modules/motion-utils/dist/es/time-conversion.js.map +0 -1
- package/dist/node_modules/motion-utils/dist/es/velocity-per-second.js +0 -8
- package/dist/node_modules/motion-utils/dist/es/velocity-per-second.js.map +0 -1
- package/dist/node_modules/motion-utils/dist/es/warn-once.js +0 -10
- package/dist/node_modules/motion-utils/dist/es/warn-once.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DashboardPage.js","names":[],"sources":["../../../src/brainyrich/pages/DashboardPage.tsx"],"sourcesContent":["import { useMemo, useState, type FormEvent, type ReactNode } from 'react';\nimport {\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n CardDescription,\n Button,\n Badge,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n Input,\n Label,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from '@burdenoff/fe-libs/ui';\nimport {\n Target,\n Bell,\n Briefcase,\n Wallet,\n PlusCircle,\n MoreHorizontal,\n Check,\n X,\n CircleCheck,\n TrendingUp,\n Coins,\n Landmark,\n TriangleAlert,\n Info,\n ShieldAlert,\n} from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { tWithFallback } from '../utils/i18n';\nimport {\n useNetWorthSummary,\n usePortfolios,\n useGoals,\n useInsights,\n useCreateAccount,\n useAcknowledgeInsight,\n useDismissInsight,\n useResolveInsight,\n} from '../hooks/useBrainyRichApi';\nimport type {\n BraAccountType,\n BraAssetClass,\n BraCreateAccountInput,\n BraInsight,\n BraInsightSeverity,\n} from '../types/bra';\nimport {\n HouseholdPicker,\n ConfirmDialog,\n DonutChart,\n StatTile,\n GlassCard,\n FadeIn,\n type VizTone,\n type DonutDatum,\n} from '../components';\nimport {\n SectionShell,\n EmptyState,\n LoadingState,\n ErrorState,\n formatMoney,\n formatCompact,\n formatDate,\n statusBadgeVariant,\n} from './_shared';\n\nconst ACCOUNT_TYPES: BraAccountType[] = [\n 'BANK',\n 'BROKERAGE',\n 'RETIREMENT',\n 'CASH',\n 'CRYPTO',\n 'REAL_ESTATE',\n 'ALTERNATIVE',\n 'LIABILITY',\n];\n\n/** Distinct, semantic tone per asset class so the donut stays legible + on-brand. */\nconst ASSET_TONE: Record<BraAssetClass, VizTone> = {\n EQUITY: 'brand',\n FIXED_INCOME: 'blue',\n CASH: 'teal',\n REAL_ESTATE: 'indigo',\n COMMODITY: 'warning',\n CRYPTO: 'purple',\n ALTERNATIVE: 'info',\n};\n\n/** Title-case an enum member: FIXED_INCOME → \"Fixed income\". */\nfunction prettyLabel(value: string): string {\n const spaced = value.replace(/_/g, ' ').toLowerCase();\n return spaced.charAt(0).toUpperCase() + spaced.slice(1);\n}\n\nexport function DashboardPage() {\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 summaryQuery = useNetWorthSummary();\n const portfoliosQuery = usePortfolios();\n const goalsQuery = useGoals();\n const insightsQuery = useInsights({ status: 'OPEN' });\n\n const summary = summaryQuery.data;\n const currency = summary?.currency ?? 'USD';\n\n const kpis: HeroStat[] = summary\n ? [\n {\n label: translate('brainyrich.dashboard.metrics.netWorth', 'Net Worth'),\n value: formatCompact(summary.totalNetWorth, currency),\n icon: <Wallet className=\"size-4\" aria-hidden=\"true\" />,\n glow: true,\n },\n {\n label: translate('brainyrich.dashboard.metrics.investedAssets', 'Invested Assets'),\n value: formatCompact(summary.totalMarketValue, currency),\n icon: <TrendingUp className=\"size-4\" aria-hidden=\"true\" />,\n },\n {\n label: translate('brainyrich.dashboard.metrics.liquidity', 'Cash & Liquidity'),\n value: formatCompact(summary.totalCash, currency),\n icon: <Coins className=\"size-4\" aria-hidden=\"true\" />,\n },\n {\n label: translate('brainyrich.dashboard.metrics.accounts', 'Linked Accounts'),\n value: String(summary.accountCount),\n icon: <Landmark className=\"size-4\" aria-hidden=\"true\" />,\n },\n ]\n : [];\n\n const donutData: DonutDatum[] = useMemo(() => {\n if (!summary) return [];\n return summary.byAssetClass\n .filter((row) => Number.isFinite(row.marketValue) && row.marketValue > 0)\n .slice()\n .sort((a, b) => b.marketValue - a.marketValue)\n .map((row) => ({\n label: prettyLabel(row.assetClass),\n value: row.marketValue,\n tone: ASSET_TONE[row.assetClass],\n }));\n }, [summary]);\n\n const topPortfolios = portfoliosQuery.data.slice(0, 5);\n const topGoals = goalsQuery.data.slice(0, 5);\n const openInsights = insightsQuery.data.slice(0, 6);\n\n return (\n <SectionShell\n title={translate('brainyrich.dashboard.title', 'Wealth Dashboard')}\n description={translate(\n 'brainyrich.dashboard.description',\n 'Your consolidated financial overview at a glance'\n )}\n actions={<NewAccountDialog translate={translate} />}\n >\n {/* Hero KPI row — net-worth overview */}\n {summaryQuery.isLoading ? (\n <LoadingState rows={1} />\n ) : summaryQuery.isError ? (\n <ErrorState\n title={translate('brainyrich.dashboard.netWorthError', 'Could not load net worth')}\n onRetry={() => summaryQuery.refetch()}\n />\n ) : summary ? (\n <div className=\"grid gap-4 sm:grid-cols-2 xl:grid-cols-4\">\n {kpis.map((kpi, i) => (\n <FadeIn key={kpi.label} index={i}>\n <StatTile\n label={kpi.label}\n value={kpi.value}\n icon={kpi.icon}\n glow={kpi.glow}\n className=\"h-full\"\n />\n </FadeIn>\n ))}\n </div>\n ) : (\n <EmptyState\n icon={<Wallet className=\"size-6\" aria-hidden=\"true\" />}\n title={translate('brainyrich.dashboard.noSummary', 'No financial data yet')}\n description={translate(\n 'brainyrich.dashboard.noSummaryDesc',\n 'Link your first account to see your net worth here.'\n )}\n />\n )}\n\n <div className=\"grid gap-6 lg:grid-cols-3\">\n {/* Net worth by asset class — donut hero */}\n <FadeIn index={0} className=\"lg:col-span-2\">\n <GlassCard className=\"h-full\">\n <div className=\"mb-4 space-y-1\">\n <h2 className=\"flex items-center gap-2 text-base font-semibold text-text-primary\">\n <Briefcase className=\"size-5\" aria-hidden=\"true\" />\n {translate('brainyrich.dashboard.sections.assetAllocation', 'Net worth by asset class')}\n </h2>\n <p className=\"text-sm text-text-secondary\">\n {translate(\n 'brainyrich.dashboard.sections.assetAllocationDescription',\n 'Market value distributed across asset classes'\n )}\n </p>\n </div>\n {summaryQuery.isLoading ? (\n <LoadingState rows={3} />\n ) : summaryQuery.isError ? (\n <ErrorState onRetry={() => summaryQuery.refetch()} />\n ) : donutData.length > 0 ? (\n <DonutChart\n data={donutData}\n height={260}\n centerValue={formatCompact(summary?.totalMarketValue ?? 0, currency)}\n centerLabel={translate('brainyrich.dashboard.metrics.investedAssets', 'Invested')}\n valueFormatter={(v) => formatMoney(v, currency)}\n />\n ) : (\n <EmptyState\n icon={<Briefcase className=\"size-6\" aria-hidden=\"true\" />}\n title={translate('brainyrich.dashboard.noAllocation', 'No holdings to allocate')}\n description={translate(\n 'brainyrich.dashboard.noAllocationDesc',\n 'Add holdings to your accounts to see how your wealth is allocated.'\n )}\n />\n )}\n </GlassCard>\n </FadeIn>\n\n {/* Right rail — needs attention + goals */}\n <div className=\"space-y-6\">\n {/* Needs attention — open insights */}\n <FadeIn index={1}>\n <Card className=\"motion-safe:transition-shadow motion-safe:hover:shadow-[var(--shadow-pop-hover,var(--shadow-elevation-2))]\">\n <CardHeader className=\"pb-3\">\n <CardTitle className=\"flex items-center gap-2 text-base\">\n <Bell className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.dashboard.sections.needsAttention', 'Needs attention')}\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-2.5\">\n {insightsQuery.isLoading ? (\n <LoadingState rows={2} />\n ) : insightsQuery.isError ? (\n <ErrorState onRetry={() => insightsQuery.refetch()} />\n ) : openInsights.length > 0 ? (\n openInsights.map((insight) => (\n <InsightRow key={insight.id} insight={insight} translate={translate} />\n ))\n ) : (\n <EmptyState\n icon={<CircleCheck className=\"size-6\" aria-hidden=\"true\" />}\n title={translate('brainyrich.dashboard.noInsights', 'All clear')}\n description={translate(\n 'brainyrich.dashboard.noInsightsDesc',\n 'There are no open insights that need your attention.'\n )}\n />\n )}\n </CardContent>\n </Card>\n </FadeIn>\n\n {/* Goals on track */}\n <FadeIn index={2}>\n <Card className=\"motion-safe:transition-shadow motion-safe:hover:shadow-[var(--shadow-pop-hover,var(--shadow-elevation-2))]\">\n <CardHeader className=\"pb-3\">\n <CardTitle className=\"flex items-center gap-2 text-base\">\n <Target className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.dashboard.sections.goals', 'Goals on track')}\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-2.5\">\n {goalsQuery.isLoading ? (\n <LoadingState rows={3} />\n ) : goalsQuery.isError ? (\n <ErrorState onRetry={() => goalsQuery.refetch()} />\n ) : topGoals.length > 0 ? (\n topGoals.map((goal) => (\n <div\n key={goal.id}\n className=\"flex items-start justify-between gap-2 rounded-lg border border-border-subtle p-3 motion-safe:transition-colors hover:border-[var(--color-action-primary-border)]/50 hover:bg-bg-elevated\"\n >\n <div className=\"min-w-0 space-y-0.5\">\n <p className=\"truncate text-sm font-medium text-text-primary\">{goal.name}</p>\n <p className=\"text-xs text-text-secondary\">\n {formatMoney(goal.targetAmount, goal.currency)}\n {' · '}\n {formatDate(goal.targetDate)}\n </p>\n </div>\n <Badge variant={statusBadgeVariant(goal.projection)} className=\"shrink-0\">\n {prettyLabel(goal.projection)}\n </Badge>\n </div>\n ))\n ) : (\n <EmptyState\n icon={<Target className=\"size-6\" aria-hidden=\"true\" />}\n title={translate('brainyrich.dashboard.noGoals', 'No goals yet')}\n description={translate(\n 'brainyrich.dashboard.noGoalsDesc',\n 'Set a financial goal to start tracking progress.'\n )}\n />\n )}\n </CardContent>\n </Card>\n </FadeIn>\n </div>\n </div>\n\n {/* Portfolios mini-list */}\n <FadeIn index={3}>\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <Wallet className=\"size-5\" aria-hidden=\"true\" />\n {translate('brainyrich.dashboard.sections.portfolios', 'Portfolios')}\n </CardTitle>\n <CardDescription>\n {translate(\n 'brainyrich.dashboard.sections.portfoliosDescription',\n 'Your active investment strategies'\n )}\n </CardDescription>\n </CardHeader>\n <CardContent>\n {portfoliosQuery.isLoading ? (\n <LoadingState rows={3} />\n ) : portfoliosQuery.isError ? (\n <ErrorState onRetry={() => portfoliosQuery.refetch()} />\n ) : topPortfolios.length > 0 ? (\n <div className=\"grid gap-3 sm:grid-cols-2\">\n {topPortfolios.map((portfolio) => (\n <div\n key={portfolio.id}\n className=\"flex items-start justify-between gap-2 rounded-lg border border-border-subtle p-3 motion-safe:transition-colors hover:border-[var(--color-action-primary-border)]/50 hover:bg-bg-elevated\"\n >\n <div className=\"min-w-0 space-y-0.5\">\n <p className=\"truncate text-sm font-medium text-text-primary\">\n {portfolio.name}\n </p>\n {portfolio.description ? (\n <p className=\"truncate text-xs text-text-secondary\">\n {portfolio.description}\n </p>\n ) : (\n <p className=\"text-xs text-text-secondary\">{portfolio.baseCurrency}</p>\n )}\n </div>\n <Badge variant={statusBadgeVariant(portfolio.status)} className=\"shrink-0\">\n {portfolio.status}\n </Badge>\n </div>\n ))}\n </div>\n ) : (\n <EmptyState\n icon={<Wallet className=\"size-6\" aria-hidden=\"true\" />}\n title={translate('brainyrich.dashboard.noPortfolios', 'No portfolios yet')}\n description={translate(\n 'brainyrich.dashboard.noPortfoliosDesc',\n 'Create a portfolio to organize your investment strategy.'\n )}\n />\n )}\n </CardContent>\n </Card>\n </FadeIn>\n </SectionShell>\n );\n}\n\ninterface HeroStat {\n label: string;\n value: string;\n icon: ReactNode;\n glow?: boolean;\n}\n\ntype Translate = (\n key: string,\n fallback: string,\n params?: Record<string, string | number>\n) => string;\n\n// ============================================================================\n// Severity chip — tinted, icon + label (colour is never the only signal)\n// ============================================================================\n\nconst SEVERITY_STYLE: Record<\n BraInsightSeverity,\n { chip: string; rail: string; icon: ReactNode }\n> = {\n CRITICAL: {\n chip: 'text-status-error-text bg-status-error-bg',\n rail: 'bg-status-error',\n icon: <ShieldAlert className=\"size-3\" aria-hidden=\"true\" />,\n },\n HIGH: {\n chip: 'text-status-error-text bg-status-error-bg',\n rail: 'bg-status-error',\n icon: <TriangleAlert className=\"size-3\" aria-hidden=\"true\" />,\n },\n MEDIUM: {\n chip: 'text-status-warning-text bg-status-warning-bg',\n rail: 'bg-status-warning',\n icon: <TriangleAlert className=\"size-3\" aria-hidden=\"true\" />,\n },\n LOW: {\n chip: 'text-status-info-text bg-status-info-bg',\n rail: 'bg-status-info',\n icon: <Info className=\"size-3\" aria-hidden=\"true\" />,\n },\n INFO: {\n chip: 'text-status-info-text bg-status-info-bg',\n rail: 'bg-status-info',\n icon: <Info className=\"size-3\" aria-hidden=\"true\" />,\n },\n};\n\nfunction SeverityChip({ severity }: { severity: BraInsightSeverity }) {\n const style = SEVERITY_STYLE[severity] ?? SEVERITY_STYLE.INFO;\n return (\n <span\n className={`inline-flex shrink-0 items-center gap-1 rounded-full px-2 py-0.5 text-[10px] font-semibold uppercase tracking-wide ${style.chip}`}\n >\n {style.icon}\n {severity}\n </span>\n );\n}\n\n// ============================================================================\n// Insight row with acknowledge / dismiss / resolve actions\n// ============================================================================\n\nfunction InsightRow({ insight, translate }: { insight: BraInsight; translate: Translate }) {\n const acknowledge = useAcknowledgeInsight();\n const dismiss = useDismissInsight();\n const resolve = useResolveInsight();\n const [confirmDismiss, setConfirmDismiss] = useState(false);\n const pending = acknowledge.isPending || dismiss.isPending || resolve.isPending;\n const rail = (SEVERITY_STYLE[insight.severity] ?? SEVERITY_STYLE.INFO).rail;\n\n return (\n <div className=\"relative flex items-start justify-between gap-3 overflow-hidden rounded-lg border border-border-subtle p-3 pl-4 motion-safe:transition-colors hover:border-[var(--color-action-primary-border)]/50 hover:bg-bg-elevated\">\n <span\n aria-hidden=\"true\"\n className={`absolute inset-y-0 left-0 w-1 ${rail}`}\n />\n <div className=\"min-w-0 space-y-1\">\n <div className=\"flex items-center gap-2\">\n <SeverityChip severity={insight.severity} />\n <span className=\"truncate text-xs text-text-secondary\">\n {prettyLabel(insight.type)}\n </span>\n </div>\n <p className=\"text-sm font-medium text-text-primary\">{insight.title}</p>\n {insight.detail ? <p className=\"text-xs text-text-secondary\">{insight.detail}</p> : null}\n </div>\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"shrink-0\"\n disabled={pending}\n aria-label={translate('brainyrich.dashboard.insightActions', 'Insight actions')}\n >\n <MoreHorizontal className=\"size-4\" aria-hidden=\"true\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuItem onSelect={() => acknowledge.mutate(insight.id)}>\n <Check className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.dashboard.insight.acknowledge', 'Acknowledge')}\n </DropdownMenuItem>\n <DropdownMenuItem onSelect={() => resolve.mutate(insight.id)}>\n <CircleCheck className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.dashboard.insight.resolve', 'Resolve')}\n </DropdownMenuItem>\n <DropdownMenuItem onSelect={() => setConfirmDismiss(true)}>\n <X className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.dashboard.insight.dismiss', 'Dismiss')}\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n\n <ConfirmDialog\n open={confirmDismiss}\n onOpenChange={setConfirmDismiss}\n title={translate('brainyrich.dashboard.insight.dismissTitle', 'Dismiss this insight?')}\n description={translate(\n 'brainyrich.dashboard.insight.dismissDescription',\n 'It will be removed from Needs Attention. You can still find it in the full insights list.'\n )}\n confirmLabel={translate('brainyrich.dashboard.insight.dismiss', 'Dismiss')}\n pendingLabel={translate('brainyrich.dashboard.insight.dismissing', 'Dismissing…')}\n destructive\n pending={dismiss.isPending}\n onConfirm={() =>\n dismiss.mutate(insight.id, {\n onSuccess: () => setConfirmDismiss(false),\n })\n }\n />\n </div>\n );\n}\n\n// ============================================================================\n// New account dialog — primary create action\n// ============================================================================\n\nfunction NewAccountDialog({ translate }: { translate: Translate }) {\n const [open, setOpen] = useState(false);\n const [name, setName] = useState('');\n const [type, setType] = useState<BraAccountType>('BROKERAGE');\n const [institution, setInstitution] = useState('');\n const [cashBalance, setCashBalance] = useState('');\n const [currency, setCurrency] = useState('USD');\n const [householdId, setHouseholdId] = useState<string | null>(null);\n\n const createAccount = useCreateAccount();\n const trimmedName = name.trim();\n const canSubmit = trimmedName.length > 0 && !createAccount.isPending;\n\n const reset = () => {\n setName('');\n setType('BROKERAGE');\n setInstitution('');\n setCashBalance('');\n setCurrency('USD');\n setHouseholdId(null);\n createAccount.reset();\n };\n\n const handleSubmit = (event: FormEvent) => {\n event.preventDefault();\n if (!canSubmit) return;\n const parsedCash = Number.parseFloat(cashBalance);\n const input: BraCreateAccountInput = {\n name: trimmedName,\n type,\n currency: currency.trim() || 'USD',\n isManual: true,\n ...(institution.trim() ? { institution: institution.trim() } : {}),\n ...(Number.isFinite(parsedCash) ? { cashBalance: parsedCash } : {}),\n ...(householdId ? { householdId } : {}),\n };\n createAccount.mutate(input, {\n onSuccess: () => {\n reset();\n setOpen(false);\n },\n });\n };\n\n return (\n <Dialog\n open={open}\n onOpenChange={(next) => {\n setOpen(next);\n if (!next) reset();\n }}\n >\n <Button size=\"sm\" onClick={() => setOpen(true)}>\n <PlusCircle className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.dashboard.actions.newAccount', 'New Account')}\n </Button>\n <DialogContent>\n <form onSubmit={handleSubmit} className=\"space-y-4\">\n <DialogHeader>\n <DialogTitle>\n {translate('brainyrich.dashboard.newAccount.title', 'New Account')}\n </DialogTitle>\n <DialogDescription>\n {translate(\n 'brainyrich.dashboard.newAccount.description',\n 'Add a manual account to track alongside your linked institutions.'\n )}\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"bra-account-name\">\n {translate('brainyrich.dashboard.newAccount.name', 'Account name')}\n </Label>\n <Input\n id=\"bra-account-name\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n placeholder={translate(\n 'brainyrich.dashboard.newAccount.namePlaceholder',\n 'e.g. Fidelity Brokerage'\n )}\n required\n autoFocus\n />\n </div>\n\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"bra-account-type\">\n {translate('brainyrich.dashboard.newAccount.type', 'Type')}\n </Label>\n <Select value={type} onValueChange={(value) => setType(value as BraAccountType)}>\n <SelectTrigger id=\"bra-account-type\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {ACCOUNT_TYPES.map((accountType) => (\n <SelectItem key={accountType} value={accountType}>\n {accountType.replace(/_/g, ' ')}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"bra-account-currency\">\n {translate('brainyrich.dashboard.newAccount.currency', 'Currency')}\n </Label>\n <Input\n id=\"bra-account-currency\"\n value={currency}\n onChange={(e) => setCurrency(e.target.value.toUpperCase())}\n maxLength={3}\n />\n </div>\n </div>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"bra-account-institution\">\n {translate('brainyrich.dashboard.newAccount.institution', 'Institution (optional)')}\n </Label>\n <Input\n id=\"bra-account-institution\"\n value={institution}\n onChange={(e) => setInstitution(e.target.value)}\n placeholder={translate(\n 'brainyrich.dashboard.newAccount.institutionPlaceholder',\n 'e.g. Fidelity'\n )}\n />\n </div>\n\n <HouseholdPicker\n id=\"bra-account-household\"\n value={householdId}\n onChange={setHouseholdId}\n label={translate('brainyrich.dashboard.newAccount.household', 'Household (optional)')}\n noneLabel={translate('brainyrich.dashboard.newAccount.noHousehold', 'No household')}\n disabled={createAccount.isPending}\n />\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"bra-account-cash\">\n {translate('brainyrich.dashboard.newAccount.cash', 'Cash balance (optional)')}\n </Label>\n <Input\n id=\"bra-account-cash\"\n type=\"number\"\n inputMode=\"decimal\"\n step=\"0.01\"\n value={cashBalance}\n onChange={(e) => setCashBalance(e.target.value)}\n placeholder=\"0.00\"\n />\n </div>\n\n {createAccount.isError ? (\n <p className=\"text-sm text-status-error-text\">\n {createAccount.error instanceof Error\n ? createAccount.error.message\n : translate('brainyrich.dashboard.newAccount.error', 'Could not create account.')}\n </p>\n ) : null}\n\n <DialogFooter>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => setOpen(false)}\n disabled={createAccount.isPending}\n >\n {translate('brainyrich.common.cancel', 'Cancel')}\n </Button>\n <Button type=\"submit\" disabled={!canSubmit}>\n {createAccount.isPending\n ? translate('brainyrich.dashboard.newAccount.creating', 'Creating…')\n : translate('brainyrich.dashboard.newAccount.create', 'Create account')}\n </Button>\n </DialogFooter>\n </form>\n </DialogContent>\n </Dialog>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DashboardPage.js","names":[],"sources":["../../../src/brainyrich/pages/DashboardPage.tsx"],"sourcesContent":["import { useMemo, useState, type FormEvent, type ReactNode } from 'react';\nimport {\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n CardDescription,\n Button,\n Badge,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n Input,\n Label,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from '@burdenoff/fe-libs/ui';\nimport {\n Target,\n Bell,\n Briefcase,\n Wallet,\n PlusCircle,\n MoreHorizontal,\n Check,\n X,\n CircleCheck,\n TrendingUp,\n Coins,\n Landmark,\n TriangleAlert,\n Info,\n ShieldAlert,\n} from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { tWithFallback } from '../utils/i18n';\nimport {\n useNetWorthSummary,\n usePortfolios,\n useGoals,\n useInsights,\n useCreateAccount,\n useAcknowledgeInsight,\n useDismissInsight,\n useResolveInsight,\n} from '../hooks/useBrainyRichApi';\nimport type {\n BraAccountType,\n BraAssetClass,\n BraCreateAccountInput,\n BraInsight,\n BraInsightSeverity,\n} from '../types/bra';\nimport {\n HouseholdPicker,\n ConfirmDialog,\n DonutChart,\n StatTile,\n GlassCard,\n FadeIn,\n type VizTone,\n type DonutDatum,\n} from '../components';\nimport {\n SectionShell,\n EmptyState,\n LoadingState,\n ErrorState,\n formatMoney,\n formatCompact,\n formatDate,\n statusBadgeVariant,\n} from './_shared';\n\nconst ACCOUNT_TYPES: BraAccountType[] = [\n 'BANK',\n 'BROKERAGE',\n 'RETIREMENT',\n 'CASH',\n 'CRYPTO',\n 'REAL_ESTATE',\n 'ALTERNATIVE',\n 'LIABILITY',\n];\n\n/** Distinct, semantic tone per asset class so the donut stays legible + on-brand. */\nconst ASSET_TONE: Record<BraAssetClass, VizTone> = {\n EQUITY: 'brand',\n FIXED_INCOME: 'blue',\n CASH: 'teal',\n REAL_ESTATE: 'indigo',\n COMMODITY: 'warning',\n CRYPTO: 'purple',\n ALTERNATIVE: 'info',\n};\n\n/** Title-case an enum member: FIXED_INCOME → \"Fixed income\". */\nfunction prettyLabel(value: string): string {\n const spaced = value.replace(/_/g, ' ').toLowerCase();\n return spaced.charAt(0).toUpperCase() + spaced.slice(1);\n}\n\nexport function DashboardPage() {\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 summaryQuery = useNetWorthSummary();\n const portfoliosQuery = usePortfolios();\n const goalsQuery = useGoals();\n const insightsQuery = useInsights({ status: 'OPEN' });\n\n const summary = summaryQuery.data;\n const currency = summary?.currency ?? 'USD';\n\n const kpis: HeroStat[] = summary\n ? [\n {\n label: translate('brainyrich.dashboard.metrics.netWorth', 'Net Worth'),\n value: formatCompact(summary.totalNetWorth, currency),\n icon: <Wallet className=\"size-4\" aria-hidden=\"true\" />,\n glow: true,\n },\n {\n label: translate('brainyrich.dashboard.metrics.investedAssets', 'Invested Assets'),\n value: formatCompact(summary.totalMarketValue, currency),\n icon: <TrendingUp className=\"size-4\" aria-hidden=\"true\" />,\n },\n {\n label: translate('brainyrich.dashboard.metrics.liquidity', 'Cash & Liquidity'),\n value: formatCompact(summary.totalCash, currency),\n icon: <Coins className=\"size-4\" aria-hidden=\"true\" />,\n },\n {\n label: translate('brainyrich.dashboard.metrics.accounts', 'Linked Accounts'),\n value: String(summary.accountCount),\n icon: <Landmark className=\"size-4\" aria-hidden=\"true\" />,\n },\n ]\n : [];\n\n const donutData: DonutDatum[] = useMemo(() => {\n if (!summary) return [];\n return summary.byAssetClass\n .filter((row) => Number.isFinite(row.marketValue) && row.marketValue > 0)\n .slice()\n .sort((a, b) => b.marketValue - a.marketValue)\n .map((row) => ({\n label: prettyLabel(row.assetClass),\n value: row.marketValue,\n tone: ASSET_TONE[row.assetClass],\n }));\n }, [summary]);\n\n const topPortfolios = portfoliosQuery.data.slice(0, 5);\n const topGoals = goalsQuery.data.slice(0, 5);\n const openInsights = insightsQuery.data.slice(0, 6);\n\n return (\n <SectionShell\n title={translate('brainyrich.dashboard.title', 'Wealth Dashboard')}\n description={translate(\n 'brainyrich.dashboard.description',\n 'Your consolidated financial overview at a glance'\n )}\n actions={<NewAccountDialog translate={translate} />}\n >\n {/* Hero KPI row — net-worth overview */}\n {summaryQuery.isLoading ? (\n <LoadingState rows={1} />\n ) : summaryQuery.isError ? (\n <ErrorState\n title={translate('brainyrich.dashboard.netWorthError', 'Could not load net worth')}\n onRetry={() => summaryQuery.refetch()}\n />\n ) : summary ? (\n <div className=\"grid gap-4 sm:grid-cols-2 xl:grid-cols-4\">\n {kpis.map((kpi, i) => (\n <FadeIn key={kpi.label} index={i}>\n <StatTile\n label={kpi.label}\n value={kpi.value}\n icon={kpi.icon}\n glow={kpi.glow}\n className=\"h-full\"\n />\n </FadeIn>\n ))}\n </div>\n ) : (\n <EmptyState\n icon={<Wallet className=\"size-6\" aria-hidden=\"true\" />}\n title={translate('brainyrich.dashboard.noSummary', 'No financial data yet')}\n description={translate(\n 'brainyrich.dashboard.noSummaryDesc',\n 'Link your first account to see your net worth here.'\n )}\n />\n )}\n\n <div className=\"grid gap-6 lg:grid-cols-3\">\n {/* Net worth by asset class — donut hero */}\n <FadeIn index={0} className=\"lg:col-span-2\">\n <GlassCard className=\"h-full\">\n <div className=\"mb-4 space-y-1\">\n <h2 className=\"flex items-center gap-2 text-base font-semibold text-text-primary\">\n <Briefcase className=\"size-5\" aria-hidden=\"true\" />\n {translate(\n 'brainyrich.dashboard.sections.assetAllocation',\n 'Net worth by asset class'\n )}\n </h2>\n <p className=\"text-sm text-text-secondary\">\n {translate(\n 'brainyrich.dashboard.sections.assetAllocationDescription',\n 'Market value distributed across asset classes'\n )}\n </p>\n </div>\n {summaryQuery.isLoading ? (\n <LoadingState rows={3} />\n ) : summaryQuery.isError ? (\n <ErrorState onRetry={() => summaryQuery.refetch()} />\n ) : donutData.length > 0 ? (\n <DonutChart\n data={donutData}\n height={260}\n centerValue={formatCompact(summary?.totalMarketValue ?? 0, currency)}\n centerLabel={translate('brainyrich.dashboard.metrics.investedAssets', 'Invested')}\n valueFormatter={(v) => formatMoney(v, currency)}\n />\n ) : (\n <EmptyState\n icon={<Briefcase className=\"size-6\" aria-hidden=\"true\" />}\n title={translate('brainyrich.dashboard.noAllocation', 'No holdings to allocate')}\n description={translate(\n 'brainyrich.dashboard.noAllocationDesc',\n 'Add holdings to your accounts to see how your wealth is allocated.'\n )}\n />\n )}\n </GlassCard>\n </FadeIn>\n\n {/* Right rail — needs attention + goals */}\n <div className=\"space-y-6\">\n {/* Needs attention — open insights */}\n <FadeIn index={1}>\n <Card className=\"motion-safe:transition-shadow motion-safe:hover:shadow-[var(--shadow-pop-hover,var(--shadow-elevation-2))]\">\n <CardHeader className=\"pb-3\">\n <CardTitle className=\"flex items-center gap-2 text-base\">\n <Bell className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.dashboard.sections.needsAttention', 'Needs attention')}\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-2.5\">\n {insightsQuery.isLoading ? (\n <LoadingState rows={2} />\n ) : insightsQuery.isError ? (\n <ErrorState onRetry={() => insightsQuery.refetch()} />\n ) : openInsights.length > 0 ? (\n openInsights.map((insight) => (\n <InsightRow key={insight.id} insight={insight} translate={translate} />\n ))\n ) : (\n <EmptyState\n icon={<CircleCheck className=\"size-6\" aria-hidden=\"true\" />}\n title={translate('brainyrich.dashboard.noInsights', 'All clear')}\n description={translate(\n 'brainyrich.dashboard.noInsightsDesc',\n 'There are no open insights that need your attention.'\n )}\n />\n )}\n </CardContent>\n </Card>\n </FadeIn>\n\n {/* Goals on track */}\n <FadeIn index={2}>\n <Card className=\"motion-safe:transition-shadow motion-safe:hover:shadow-[var(--shadow-pop-hover,var(--shadow-elevation-2))]\">\n <CardHeader className=\"pb-3\">\n <CardTitle className=\"flex items-center gap-2 text-base\">\n <Target className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.dashboard.sections.goals', 'Goals on track')}\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-2.5\">\n {goalsQuery.isLoading ? (\n <LoadingState rows={3} />\n ) : goalsQuery.isError ? (\n <ErrorState onRetry={() => goalsQuery.refetch()} />\n ) : topGoals.length > 0 ? (\n topGoals.map((goal) => (\n <div\n key={goal.id}\n className=\"flex items-start justify-between gap-2 rounded-lg border border-border-subtle p-3 motion-safe:transition-colors hover:border-[var(--color-action-primary-border)]/50 hover:bg-bg-elevated\"\n >\n <div className=\"min-w-0 space-y-0.5\">\n <p className=\"truncate text-sm font-medium text-text-primary\">\n {goal.name}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {formatMoney(goal.targetAmount, goal.currency)}\n {' · '}\n {formatDate(goal.targetDate)}\n </p>\n </div>\n <Badge variant={statusBadgeVariant(goal.projection)} className=\"shrink-0\">\n {prettyLabel(goal.projection)}\n </Badge>\n </div>\n ))\n ) : (\n <EmptyState\n icon={<Target className=\"size-6\" aria-hidden=\"true\" />}\n title={translate('brainyrich.dashboard.noGoals', 'No goals yet')}\n description={translate(\n 'brainyrich.dashboard.noGoalsDesc',\n 'Set a financial goal to start tracking progress.'\n )}\n />\n )}\n </CardContent>\n </Card>\n </FadeIn>\n </div>\n </div>\n\n {/* Portfolios mini-list */}\n <FadeIn index={3}>\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <Wallet className=\"size-5\" aria-hidden=\"true\" />\n {translate('brainyrich.dashboard.sections.portfolios', 'Portfolios')}\n </CardTitle>\n <CardDescription>\n {translate(\n 'brainyrich.dashboard.sections.portfoliosDescription',\n 'Your active investment strategies'\n )}\n </CardDescription>\n </CardHeader>\n <CardContent>\n {portfoliosQuery.isLoading ? (\n <LoadingState rows={3} />\n ) : portfoliosQuery.isError ? (\n <ErrorState onRetry={() => portfoliosQuery.refetch()} />\n ) : topPortfolios.length > 0 ? (\n <div className=\"grid gap-3 sm:grid-cols-2\">\n {topPortfolios.map((portfolio) => (\n <div\n key={portfolio.id}\n className=\"flex items-start justify-between gap-2 rounded-lg border border-border-subtle p-3 motion-safe:transition-colors hover:border-[var(--color-action-primary-border)]/50 hover:bg-bg-elevated\"\n >\n <div className=\"min-w-0 space-y-0.5\">\n <p className=\"truncate text-sm font-medium text-text-primary\">\n {portfolio.name}\n </p>\n {portfolio.description ? (\n <p className=\"truncate text-xs text-text-secondary\">\n {portfolio.description}\n </p>\n ) : (\n <p className=\"text-xs text-text-secondary\">{portfolio.baseCurrency}</p>\n )}\n </div>\n <Badge variant={statusBadgeVariant(portfolio.status)} className=\"shrink-0\">\n {portfolio.status}\n </Badge>\n </div>\n ))}\n </div>\n ) : (\n <EmptyState\n icon={<Wallet className=\"size-6\" aria-hidden=\"true\" />}\n title={translate('brainyrich.dashboard.noPortfolios', 'No portfolios yet')}\n description={translate(\n 'brainyrich.dashboard.noPortfoliosDesc',\n 'Create a portfolio to organize your investment strategy.'\n )}\n />\n )}\n </CardContent>\n </Card>\n </FadeIn>\n </SectionShell>\n );\n}\n\ninterface HeroStat {\n label: string;\n value: string;\n icon: ReactNode;\n glow?: boolean;\n}\n\ntype Translate = (\n key: string,\n fallback: string,\n params?: Record<string, string | number>\n) => string;\n\n// ============================================================================\n// Severity chip — tinted, icon + label (colour is never the only signal)\n// ============================================================================\n\nconst SEVERITY_STYLE: Record<BraInsightSeverity, { chip: string; rail: string; icon: ReactNode }> =\n {\n CRITICAL: {\n chip: 'text-status-error-text bg-status-error-bg',\n rail: 'bg-status-error',\n icon: <ShieldAlert className=\"size-3\" aria-hidden=\"true\" />,\n },\n HIGH: {\n chip: 'text-status-error-text bg-status-error-bg',\n rail: 'bg-status-error',\n icon: <TriangleAlert className=\"size-3\" aria-hidden=\"true\" />,\n },\n MEDIUM: {\n chip: 'text-status-warning-text bg-status-warning-bg',\n rail: 'bg-status-warning',\n icon: <TriangleAlert className=\"size-3\" aria-hidden=\"true\" />,\n },\n LOW: {\n chip: 'text-status-info-text bg-status-info-bg',\n rail: 'bg-status-info',\n icon: <Info className=\"size-3\" aria-hidden=\"true\" />,\n },\n INFO: {\n chip: 'text-status-info-text bg-status-info-bg',\n rail: 'bg-status-info',\n icon: <Info className=\"size-3\" aria-hidden=\"true\" />,\n },\n };\n\nfunction SeverityChip({ severity }: { severity: BraInsightSeverity }) {\n const style = SEVERITY_STYLE[severity] ?? SEVERITY_STYLE.INFO;\n return (\n <span\n className={`inline-flex shrink-0 items-center gap-1 rounded-full px-2 py-0.5 text-[10px] font-semibold uppercase tracking-wide ${style.chip}`}\n >\n {style.icon}\n {severity}\n </span>\n );\n}\n\n// ============================================================================\n// Insight row with acknowledge / dismiss / resolve actions\n// ============================================================================\n\nfunction InsightRow({ insight, translate }: { insight: BraInsight; translate: Translate }) {\n const acknowledge = useAcknowledgeInsight();\n const dismiss = useDismissInsight();\n const resolve = useResolveInsight();\n const [confirmDismiss, setConfirmDismiss] = useState(false);\n const pending = acknowledge.isPending || dismiss.isPending || resolve.isPending;\n const rail = (SEVERITY_STYLE[insight.severity] ?? SEVERITY_STYLE.INFO).rail;\n\n return (\n <div className=\"relative flex items-start justify-between gap-3 overflow-hidden rounded-lg border border-border-subtle p-3 pl-4 motion-safe:transition-colors hover:border-[var(--color-action-primary-border)]/50 hover:bg-bg-elevated\">\n <span aria-hidden=\"true\" className={`absolute inset-y-0 left-0 w-1 ${rail}`} />\n <div className=\"min-w-0 space-y-1\">\n <div className=\"flex items-center gap-2\">\n <SeverityChip severity={insight.severity} />\n <span className=\"truncate text-xs text-text-secondary\">{prettyLabel(insight.type)}</span>\n </div>\n <p className=\"text-sm font-medium text-text-primary\">{insight.title}</p>\n {insight.detail ? <p className=\"text-xs text-text-secondary\">{insight.detail}</p> : null}\n </div>\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"shrink-0\"\n disabled={pending}\n aria-label={translate('brainyrich.dashboard.insightActions', 'Insight actions')}\n >\n <MoreHorizontal className=\"size-4\" aria-hidden=\"true\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuItem onSelect={() => acknowledge.mutate(insight.id)}>\n <Check className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.dashboard.insight.acknowledge', 'Acknowledge')}\n </DropdownMenuItem>\n <DropdownMenuItem onSelect={() => resolve.mutate(insight.id)}>\n <CircleCheck className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.dashboard.insight.resolve', 'Resolve')}\n </DropdownMenuItem>\n <DropdownMenuItem onSelect={() => setConfirmDismiss(true)}>\n <X className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.dashboard.insight.dismiss', 'Dismiss')}\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n\n <ConfirmDialog\n open={confirmDismiss}\n onOpenChange={setConfirmDismiss}\n title={translate('brainyrich.dashboard.insight.dismissTitle', 'Dismiss this insight?')}\n description={translate(\n 'brainyrich.dashboard.insight.dismissDescription',\n 'It will be removed from Needs Attention. You can still find it in the full insights list.'\n )}\n confirmLabel={translate('brainyrich.dashboard.insight.dismiss', 'Dismiss')}\n pendingLabel={translate('brainyrich.dashboard.insight.dismissing', 'Dismissing…')}\n destructive\n pending={dismiss.isPending}\n onConfirm={() =>\n dismiss.mutate(insight.id, {\n onSuccess: () => setConfirmDismiss(false),\n })\n }\n />\n </div>\n );\n}\n\n// ============================================================================\n// New account dialog — primary create action\n// ============================================================================\n\nfunction NewAccountDialog({ translate }: { translate: Translate }) {\n const [open, setOpen] = useState(false);\n const [name, setName] = useState('');\n const [type, setType] = useState<BraAccountType>('BROKERAGE');\n const [institution, setInstitution] = useState('');\n const [cashBalance, setCashBalance] = useState('');\n const [currency, setCurrency] = useState('USD');\n const [householdId, setHouseholdId] = useState<string | null>(null);\n\n const createAccount = useCreateAccount();\n const trimmedName = name.trim();\n const canSubmit = trimmedName.length > 0 && !createAccount.isPending;\n\n const reset = () => {\n setName('');\n setType('BROKERAGE');\n setInstitution('');\n setCashBalance('');\n setCurrency('USD');\n setHouseholdId(null);\n createAccount.reset();\n };\n\n const handleSubmit = (event: FormEvent) => {\n event.preventDefault();\n if (!canSubmit) return;\n const parsedCash = Number.parseFloat(cashBalance);\n const input: BraCreateAccountInput = {\n name: trimmedName,\n type,\n currency: currency.trim() || 'USD',\n isManual: true,\n ...(institution.trim() ? { institution: institution.trim() } : {}),\n ...(Number.isFinite(parsedCash) ? { cashBalance: parsedCash } : {}),\n ...(householdId ? { householdId } : {}),\n };\n createAccount.mutate(input, {\n onSuccess: () => {\n reset();\n setOpen(false);\n },\n });\n };\n\n return (\n <Dialog\n open={open}\n onOpenChange={(next) => {\n setOpen(next);\n if (!next) reset();\n }}\n >\n <Button size=\"sm\" onClick={() => setOpen(true)}>\n <PlusCircle className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.dashboard.actions.newAccount', 'New Account')}\n </Button>\n <DialogContent>\n <form onSubmit={handleSubmit} className=\"space-y-4\">\n <DialogHeader>\n <DialogTitle>\n {translate('brainyrich.dashboard.newAccount.title', 'New Account')}\n </DialogTitle>\n <DialogDescription>\n {translate(\n 'brainyrich.dashboard.newAccount.description',\n 'Add a manual account to track alongside your linked institutions.'\n )}\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"bra-account-name\">\n {translate('brainyrich.dashboard.newAccount.name', 'Account name')}\n </Label>\n <Input\n id=\"bra-account-name\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n placeholder={translate(\n 'brainyrich.dashboard.newAccount.namePlaceholder',\n 'e.g. Fidelity Brokerage'\n )}\n required\n autoFocus\n />\n </div>\n\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"bra-account-type\">\n {translate('brainyrich.dashboard.newAccount.type', 'Type')}\n </Label>\n <Select value={type} onValueChange={(value) => setType(value as BraAccountType)}>\n <SelectTrigger id=\"bra-account-type\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {ACCOUNT_TYPES.map((accountType) => (\n <SelectItem key={accountType} value={accountType}>\n {accountType.replace(/_/g, ' ')}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"bra-account-currency\">\n {translate('brainyrich.dashboard.newAccount.currency', 'Currency')}\n </Label>\n <Input\n id=\"bra-account-currency\"\n value={currency}\n onChange={(e) => setCurrency(e.target.value.toUpperCase())}\n maxLength={3}\n />\n </div>\n </div>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"bra-account-institution\">\n {translate('brainyrich.dashboard.newAccount.institution', 'Institution (optional)')}\n </Label>\n <Input\n id=\"bra-account-institution\"\n value={institution}\n onChange={(e) => setInstitution(e.target.value)}\n placeholder={translate(\n 'brainyrich.dashboard.newAccount.institutionPlaceholder',\n 'e.g. Fidelity'\n )}\n />\n </div>\n\n <HouseholdPicker\n id=\"bra-account-household\"\n value={householdId}\n onChange={setHouseholdId}\n label={translate('brainyrich.dashboard.newAccount.household', 'Household (optional)')}\n noneLabel={translate('brainyrich.dashboard.newAccount.noHousehold', 'No household')}\n disabled={createAccount.isPending}\n />\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"bra-account-cash\">\n {translate('brainyrich.dashboard.newAccount.cash', 'Cash balance (optional)')}\n </Label>\n <Input\n id=\"bra-account-cash\"\n type=\"number\"\n inputMode=\"decimal\"\n step=\"0.01\"\n value={cashBalance}\n onChange={(e) => setCashBalance(e.target.value)}\n placeholder=\"0.00\"\n />\n </div>\n\n {createAccount.isError ? (\n <p className=\"text-sm text-status-error-text\">\n {createAccount.error instanceof Error\n ? createAccount.error.message\n : translate('brainyrich.dashboard.newAccount.error', 'Could not create account.')}\n </p>\n ) : null}\n\n <DialogFooter>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => setOpen(false)}\n disabled={createAccount.isPending}\n >\n {translate('brainyrich.common.cancel', 'Cancel')}\n </Button>\n <Button type=\"submit\" disabled={!canSubmit}>\n {createAccount.isPending\n ? translate('brainyrich.dashboard.newAccount.creating', 'Creating…')\n : translate('brainyrich.dashboard.newAccount.create', 'Create account')}\n </Button>\n </DialogFooter>\n </form>\n </DialogContent>\n </Dialog>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FamilyPage.js","names":[],"sources":["../../../src/brainyrich/pages/FamilyPage.tsx"],"sourcesContent":["import { useMemo, useState, type ReactNode } from 'react';\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n Dialog,\n DialogClose,\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 Separator,\n Sheet,\n SheetContent,\n SheetDescription,\n SheetHeader,\n SheetTitle,\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n Textarea,\n} from '@burdenoff/fe-libs/ui';\nimport {\n Users,\n MoreHorizontal,\n Pencil,\n Archive,\n Eye,\n Mail,\n Wallet,\n Target,\n Briefcase,\n Building2,\n TrendingUp,\n UserCircle2,\n} from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { tWithFallback } from '../utils/i18n';\nimport {\n usePagedHouseholds,\n useHousehold,\n useCreateHousehold,\n useUpdateHousehold,\n useArchiveHousehold,\n useAccounts,\n usePortfolios,\n useGoals,\n} from '../hooks/useBrainyRichApi';\nimport {\n ConfirmDialog,\n LoadMore,\n ActorName,\n StatTile,\n GlassCard,\n FadeIn,\n DonutChart,\n type DonutDatum,\n} from '../components';\nimport { TagField } from '../components/reuse/TagField';\nimport { DocumentsPanel } from '../components/reuse/DocumentsPanel';\nimport { CommentThread } from '../components/reuse/CommentThread';\nimport type {\n BraHousehold,\n BraHouseholdStatus,\n BraRiskProfile,\n BraCreateHouseholdInput,\n BraUpdateHouseholdInput,\n BraAccount,\n BraGoal,\n} from '../types/bra';\nimport {\n SectionShell,\n EmptyState,\n LoadingState,\n ErrorState,\n formatMoney,\n formatCompact,\n formatDate,\n statusBadgeVariant,\n} from './_shared';\n\nconst STATUS_OPTIONS: BraHouseholdStatus[] = ['PROSPECT', 'ONBOARDING', 'ACTIVE', 'INACTIVE'];\nconst RISK_OPTIONS: BraRiskProfile[] = [\n 'CONSERVATIVE',\n 'MODERATE',\n 'BALANCED',\n 'GROWTH',\n 'AGGRESSIVE',\n];\nconst CURRENCY_OPTIONS = ['USD', 'EUR', 'GBP', 'INR', 'AED', 'SGD'];\n\n/** Per-status donut tone (semantic — colour is never the only signal). */\nconst STATUS_TONE: Record<BraHouseholdStatus, DonutDatum['tone']> = {\n ACTIVE: 'brand',\n ONBOARDING: 'info',\n PROSPECT: 'warning',\n INACTIVE: 'neutral',\n};\n\ninterface HouseholdFormState {\n name: string;\n status: BraHouseholdStatus;\n riskProfile: BraRiskProfile;\n currency: string;\n advisorId: string;\n primaryContactName: string;\n primaryContactEmail: string;\n notes: string;\n tags: string;\n}\n\nconst emptyForm: HouseholdFormState = {\n name: '',\n status: 'PROSPECT',\n riskProfile: 'BALANCED',\n currency: 'USD',\n advisorId: '',\n primaryContactName: '',\n primaryContactEmail: '',\n notes: '',\n tags: '',\n};\n\nfunction toTags(raw: string): string[] {\n return raw\n .split(',')\n .map((t) => t.trim())\n .filter(Boolean);\n}\n\n/** Real market value of an account: settled cash + marked-to-market holdings. */\nfunction accountValue(a: BraAccount): number {\n const holdings = (a.holdings ?? []).reduce(\n (sum, h) => sum + (Number.isFinite(h.marketValue) ? h.marketValue : 0),\n 0\n );\n const cash = Number.isFinite(a.cashBalance) ? a.cashBalance : 0;\n return cash + holdings;\n}\n\nexport function FamilyPage() {\n const { t } = useI18n();\n const tr = (key: string, fallback: string, params?: Record<string, string | number>) =>\n tWithFallback(t, key, fallback, params);\n\n const {\n items: households,\n hasMore,\n loadMore,\n isLoading,\n isFetchingNextPage,\n isError,\n refetch,\n } = usePagedHouseholds();\n\n const createHousehold = useCreateHousehold();\n const updateHousehold = useUpdateHousehold();\n const archiveHousehold = useArchiveHousehold();\n\n const [formOpen, setFormOpen] = useState(false);\n const [editing, setEditing] = useState<BraHousehold | null>(null);\n const [form, setForm] = useState<HouseholdFormState>(emptyForm);\n const [detailId, setDetailId] = useState<string | undefined>(undefined);\n const [archiveTarget, setArchiveTarget] = useState<BraHousehold | null>(null);\n\n const setField = <K extends keyof HouseholdFormState>(key: K, value: HouseholdFormState[K]) =>\n setForm((prev) => ({ ...prev, [key]: value }));\n\n const openCreate = () => {\n setEditing(null);\n setForm(emptyForm);\n setFormOpen(true);\n };\n\n const openEdit = (h: BraHousehold) => {\n setEditing(h);\n setForm({\n name: h.name,\n status: h.status,\n riskProfile: h.riskProfile,\n currency: h.currency,\n advisorId: h.advisorId ?? '',\n primaryContactName: h.primaryContactName ?? '',\n primaryContactEmail: h.primaryContactEmail ?? '',\n notes: h.notes ?? '',\n tags: h.tags.join(', '),\n });\n setFormOpen(true);\n };\n\n const firm = useMemo(() => {\n const currency = households[0]?.currency ?? 'USD';\n const total = households.length;\n const active = households.filter((h) => h.status === 'ACTIVE').length;\n const prospects = households.filter((h) => h.status === 'PROSPECT').length;\n const onboarding = households.filter((h) => h.status === 'ONBOARDING').length;\n const aum = households.reduce((sum, h) => sum + (Number.isFinite(h.aum) ? h.aum : 0), 0);\n\n // AUM grouped by advisor (empty advisorId → unassigned bucket).\n const byAdvisor = new Map<string, number>();\n for (const h of households) {\n const key = h.advisorId?.trim() || '';\n byAdvisor.set(key, (byAdvisor.get(key) ?? 0) + (Number.isFinite(h.aum) ? h.aum : 0));\n }\n const advisors = Array.from(byAdvisor.entries())\n .map(([advisorId, value]) => ({ advisorId, value }))\n .sort((a, b) => b.value - a.value);\n const advisorCount = advisors.filter((a) => a.advisorId).length;\n const advisorMax = advisors.reduce((m, a) => Math.max(m, a.value), 0);\n\n // Book mix by status → donut.\n const statusMix: DonutDatum[] = (STATUS_OPTIONS as BraHouseholdStatus[])\n .map((s) => ({\n label: s.charAt(0) + s.slice(1).toLowerCase(),\n value: households.filter((h) => h.status === s).length,\n tone: STATUS_TONE[s],\n }))\n .filter((d) => d.value > 0);\n\n return {\n currency,\n total,\n active,\n prospects,\n onboarding,\n aum,\n advisors,\n advisorCount,\n advisorMax,\n statusMix,\n };\n }, [households]);\n\n const submitting = createHousehold.isPending || updateHousehold.isPending;\n const canSubmit = form.name.trim().length > 0 && !submitting;\n\n const handleSubmit = () => {\n if (!canSubmit) return;\n if (editing) {\n const input: BraUpdateHouseholdInput = {\n name: form.name.trim(),\n status: form.status,\n riskProfile: form.riskProfile,\n currency: form.currency,\n primaryContactName: form.primaryContactName.trim() || null,\n primaryContactEmail: form.primaryContactEmail.trim() || null,\n notes: form.notes.trim() || null,\n tags: toTags(form.tags),\n };\n updateHousehold.mutate({ id: editing.id, input }, { onSuccess: () => setFormOpen(false) });\n } else {\n const input: BraCreateHouseholdInput = {\n name: form.name.trim(),\n status: form.status,\n riskProfile: form.riskProfile,\n currency: form.currency,\n primaryContactName: form.primaryContactName.trim() || null,\n primaryContactEmail: form.primaryContactEmail.trim() || null,\n notes: form.notes.trim() || null,\n tags: toTags(form.tags),\n };\n if (form.advisorId.trim()) input.advisorId = form.advisorId.trim();\n createHousehold.mutate(input, { onSuccess: () => setFormOpen(false) });\n }\n };\n\n const showFirm = !isLoading && !isError && households.length > 0;\n\n return (\n <SectionShell\n title={tr('brainyrich.households.title', 'Households')}\n description={tr(\n 'brainyrich.households.description',\n 'Client households and family units under advisement'\n )}\n badges={\n households.length\n ? [tr('brainyrich.households.count', '{count} households', { count: households.length })]\n : []\n }\n actionLabel={tr('brainyrich.households.new', 'New household')}\n onAction={openCreate}\n >\n {showFirm ? (\n <FirmOverview firm={firm} tr={tr} />\n ) : (\n <div className=\"grid gap-4 md:grid-cols-2 xl:grid-cols-4\">\n <StatTile label={tr('brainyrich.households.kpi.aum', 'Total AUM')} value=\"—\" glow />\n <StatTile label={tr('brainyrich.households.kpi.total', 'Households')} value=\"—\" />\n <StatTile label={tr('brainyrich.households.kpi.active', 'Active')} value=\"—\" />\n <StatTile label={tr('brainyrich.households.kpi.prospects', 'Prospects')} value=\"—\" />\n </div>\n )}\n\n {isLoading ? (\n <LoadingState rows={5} />\n ) : isError ? (\n <ErrorState\n title={tr('brainyrich.households.error.title', 'Could not load households')}\n onRetry={() => refetch()}\n />\n ) : households.length === 0 ? (\n <EmptyState\n icon={<Users className=\"size-6\" aria-hidden=\"true\" />}\n title={tr('brainyrich.households.empty.title', 'No households yet')}\n description={tr(\n 'brainyrich.households.empty.description',\n 'Create your first client household to start organizing accounts, portfolios and goals.'\n )}\n action={\n <Button size=\"sm\" onClick={openCreate}>\n {tr('brainyrich.households.new', 'New household')}\n </Button>\n }\n />\n ) : (\n <FadeIn as=\"section\">\n <Card className=\"overflow-hidden\">\n <CardContent className=\"p-0\">\n <div className=\"overflow-x-auto\">\n <Table>\n <TableHeader>\n <TableRow className=\"hover:bg-transparent\">\n <TableHead>{tr('brainyrich.households.col.name', 'Household')}</TableHead>\n <TableHead>{tr('brainyrich.households.col.status', 'Status')}</TableHead>\n <TableHead className=\"hidden md:table-cell\">\n {tr('brainyrich.households.col.risk', 'Risk profile')}\n </TableHead>\n <TableHead className=\"hidden lg:table-cell\">\n {tr('brainyrich.households.col.contact', 'Primary contact')}\n </TableHead>\n <TableHead className=\"hidden sm:table-cell\">\n {tr('brainyrich.households.col.advisor', 'Advisor')}\n </TableHead>\n <TableHead className=\"text-right\">\n {tr('brainyrich.households.col.aum', 'AUM')}\n </TableHead>\n <TableHead className=\"w-12 text-right\">\n <span className=\"sr-only\">\n {tr('brainyrich.households.col.actions', 'Actions')}\n </span>\n </TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {households.map((h) => {\n const share = firm.aum > 0 ? Math.min(100, (h.aum / firm.aum) * 100) : 0;\n return (\n <TableRow\n key={h.id}\n className=\"group cursor-pointer transition-colors\"\n onClick={() => setDetailId(h.id)}\n >\n <TableCell>\n <span className=\"font-medium text-text-primary transition-colors group-hover:text-[var(--color-action-primary-text)]\">\n {h.name}\n </span>\n {h.tags.length > 0 ? (\n <div className=\"mt-1 flex flex-wrap gap-1\">\n {h.tags.slice(0, 3).map((tag) => (\n <Badge key={tag} variant=\"outline\" className=\"text-xs\">\n {tag}\n </Badge>\n ))}\n {h.tags.length > 3 ? (\n <Badge variant=\"outline\" className=\"text-xs\">\n +{h.tags.length - 3}\n </Badge>\n ) : null}\n </div>\n ) : null}\n </TableCell>\n <TableCell>\n <Badge variant={statusBadgeVariant(h.status)}>{h.status}</Badge>\n </TableCell>\n <TableCell className=\"hidden md:table-cell\">\n <Badge variant=\"secondary\">{h.riskProfile}</Badge>\n </TableCell>\n <TableCell className=\"hidden lg:table-cell\">\n {h.primaryContactName ? (\n <div className=\"space-y-0.5\">\n <p className=\"text-sm text-text-primary\">{h.primaryContactName}</p>\n {h.primaryContactEmail ? (\n <p className=\"flex items-center gap-1 text-xs text-text-secondary\">\n <Mail className=\"size-3\" aria-hidden=\"true\" />\n {h.primaryContactEmail}\n </p>\n ) : null}\n </div>\n ) : (\n <span className=\"text-sm text-text-muted\">—</span>\n )}\n </TableCell>\n <TableCell className=\"hidden sm:table-cell\">\n {h.advisorId ? (\n <span className=\"flex items-center gap-1.5 text-sm text-text-secondary\">\n <UserCircle2 className=\"size-3.5\" aria-hidden=\"true\" />\n <ActorName id={h.advisorId} />\n </span>\n ) : (\n <span className=\"text-sm text-text-muted\">\n {tr('brainyrich.common.unassigned', 'Unassigned')}\n </span>\n )}\n </TableCell>\n <TableCell className=\"text-right\">\n <div className=\"flex flex-col items-end gap-1\">\n <span className=\"font-medium tabular-nums text-text-primary\">\n {formatMoney(h.aum, h.currency)}\n </span>\n <span\n className=\"h-1 w-16 overflow-hidden rounded-full bg-bg-sunken\"\n aria-hidden=\"true\"\n >\n <span\n className=\"block h-full rounded-full bg-[var(--color-action-primary-bg)]\"\n style={{ width: `${share}%` }}\n />\n </span>\n </div>\n </TableCell>\n <TableCell\n className=\"text-right\"\n onClick={(e) => e.stopPropagation()}\n >\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label={tr(\n 'brainyrich.households.rowMenu',\n 'Household actions'\n )}\n >\n <MoreHorizontal className=\"size-4\" aria-hidden=\"true\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuItem onClick={() => setDetailId(h.id)}>\n <Eye className=\"size-4\" aria-hidden=\"true\" />\n {tr('brainyrich.households.action.view', 'View details')}\n </DropdownMenuItem>\n <DropdownMenuItem onClick={() => openEdit(h)}>\n <Pencil className=\"size-4\" aria-hidden=\"true\" />\n {tr('brainyrich.households.action.edit', 'Edit')}\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n className=\"text-status-error-text focus:text-status-error-text\"\n onClick={() => setArchiveTarget(h)}\n >\n <Archive className=\"size-4\" aria-hidden=\"true\" />\n {tr('brainyrich.households.action.archive', 'Archive')}\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </TableCell>\n </TableRow>\n );\n })}\n </TableBody>\n </Table>\n </div>\n </CardContent>\n </Card>\n </FadeIn>\n )}\n\n {!isLoading && !isError && households.length > 0 ? (\n <LoadMore\n hasMore={hasMore}\n onClick={loadMore}\n loading={isFetchingNextPage}\n label={tr('brainyrich.households.loadMore', 'Load more households')}\n />\n ) : null}\n\n <HouseholdFormDialog\n open={formOpen}\n onOpenChange={setFormOpen}\n editing={editing}\n form={form}\n setField={setField}\n onSubmit={handleSubmit}\n canSubmit={canSubmit}\n submitting={submitting}\n tr={tr}\n />\n\n <HouseholdDetailSheet\n householdId={detailId}\n onClose={() => setDetailId(undefined)}\n onEdit={(h) => {\n setDetailId(undefined);\n openEdit(h);\n }}\n tr={tr}\n />\n\n <ConfirmDialog\n open={Boolean(archiveTarget)}\n onOpenChange={(o) => (!o ? setArchiveTarget(null) : undefined)}\n title={tr('brainyrich.households.archive.title', 'Archive household?')}\n description={tr(\n 'brainyrich.households.archive.description',\n 'Archiving “{name}” removes it from the active list. You can still access its records, but it will no longer appear here.',\n { name: archiveTarget?.name ?? '' }\n )}\n confirmLabel={tr('brainyrich.households.action.archive', 'Archive')}\n pendingLabel={tr('brainyrich.households.archive.pending', 'Archiving…')}\n destructive\n pending={archiveHousehold.isPending}\n onConfirm={() => {\n if (!archiveTarget) return;\n archiveHousehold.mutate(archiveTarget.id, {\n onSuccess: () => setArchiveTarget(null),\n });\n }}\n />\n </SectionShell>\n );\n}\n\n// ============================================================================\n// Firm overview — practice-wide KPIs + AUM-by-advisor + book mix\n// ============================================================================\n\ninterface FirmData {\n currency: string;\n total: number;\n active: number;\n prospects: number;\n onboarding: number;\n aum: number;\n advisors: { advisorId: string; value: number }[];\n advisorCount: number;\n advisorMax: number;\n statusMix: DonutDatum[];\n}\n\nfunction FirmOverview({\n firm,\n tr,\n}: {\n firm: FirmData;\n tr: (key: string, fallback: string, params?: Record<string, string | number>) => string;\n}) {\n return (\n <FadeIn as=\"section\" className=\"space-y-4\">\n <div className=\"grid gap-4 md:grid-cols-2 xl:grid-cols-4\">\n <StatTile\n label={tr('brainyrich.households.kpi.aum', 'Total AUM')}\n value={formatMoney(firm.aum, firm.currency)}\n glow\n icon={<Wallet className=\"size-4\" aria-hidden=\"true\" />}\n />\n <StatTile\n label={tr('brainyrich.households.kpi.total', 'Households')}\n value={String(firm.total)}\n icon={<Users className=\"size-4\" aria-hidden=\"true\" />}\n />\n <StatTile\n label={tr('brainyrich.households.kpi.active', 'Active')}\n value={String(firm.active)}\n icon={<TrendingUp className=\"size-4\" aria-hidden=\"true\" />}\n />\n <StatTile\n label={tr('brainyrich.households.kpi.prospects', 'Prospects')}\n value={String(firm.prospects)}\n icon={<Target className=\"size-4\" aria-hidden=\"true\" />}\n />\n </div>\n\n <div className=\"grid gap-4 lg:grid-cols-3\">\n <GlassCard className=\"lg:col-span-2\">\n <div className=\"mb-4 flex items-center justify-between gap-2\">\n <div>\n <h2 className=\"text-sm font-semibold text-text-primary\">\n {tr('brainyrich.households.firm.byAdvisor', 'AUM by advisor')}\n </h2>\n <p className=\"text-xs text-text-secondary\">\n {tr('brainyrich.households.firm.advisorCount', '{count} advisors', {\n count: firm.advisorCount,\n })}\n </p>\n </div>\n <Building2 className=\"size-4 text-text-secondary\" aria-hidden=\"true\" />\n </div>\n <ul className=\"space-y-3.5\" aria-label={tr('brainyrich.households.firm.byAdvisor', 'AUM by advisor')}>\n {firm.advisors.map((a) => {\n const width =\n firm.advisorMax > 0 ? Math.max(2, (a.value / firm.advisorMax) * 100) : 0;\n return (\n <li key={a.advisorId || 'unassigned'} className=\"space-y-1.5\">\n <div className=\"flex items-center justify-between gap-3 text-xs\">\n <span className=\"flex items-center gap-1.5 truncate font-medium text-text-primary\">\n <UserCircle2 className=\"size-3.5 shrink-0 text-text-secondary\" aria-hidden=\"true\" />\n {a.advisorId ? (\n <ActorName id={a.advisorId} />\n ) : (\n tr('brainyrich.common.unassigned', 'Unassigned')\n )}\n </span>\n <span className=\"shrink-0 tabular-nums text-text-secondary\">\n {formatCompact(a.value, firm.currency)}\n </span>\n </div>\n <div\n className=\"h-2 w-full overflow-hidden rounded-full bg-bg-sunken\"\n role=\"progressbar\"\n aria-valuenow={Math.round(width)}\n aria-valuemin={0}\n aria-valuemax={100}\n aria-label={a.advisorId || 'Unassigned'}\n >\n <div\n className=\"h-full rounded-full bg-[var(--color-action-primary-bg)] transition-[width] duration-500 ease-out\"\n style={{ width: `${width}%` }}\n />\n </div>\n </li>\n );\n })}\n </ul>\n </GlassCard>\n\n <GlassCard>\n <div className=\"mb-2 flex items-center justify-between gap-2\">\n <h2 className=\"text-sm font-semibold text-text-primary\">\n {tr('brainyrich.households.firm.bookMix', 'Book by status')}\n </h2>\n </div>\n {firm.statusMix.length > 0 ? (\n <DonutChart\n data={firm.statusMix}\n centerValue={String(firm.total)}\n centerLabel={tr('brainyrich.households.kpi.total', 'Households')}\n legend\n height={200}\n valueFormatter={(v) => String(v)}\n />\n ) : (\n <p className=\"text-sm text-text-secondary\">\n {tr('brainyrich.households.firm.noMix', 'No households to chart yet.')}\n </p>\n )}\n </GlassCard>\n </div>\n </FadeIn>\n );\n}\n\n// ============================================================================\n// Create / edit dialog\n// ============================================================================\n\ninterface HouseholdFormDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n editing: BraHousehold | null;\n form: HouseholdFormState;\n setField: <K extends keyof HouseholdFormState>(key: K, value: HouseholdFormState[K]) => void;\n onSubmit: () => void;\n canSubmit: boolean;\n submitting: boolean;\n tr: (key: string, fallback: string, params?: Record<string, string | number>) => string;\n}\n\nfunction HouseholdFormDialog({\n open,\n onOpenChange,\n editing,\n form,\n setField,\n onSubmit,\n canSubmit,\n submitting,\n tr,\n}: HouseholdFormDialogProps) {\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 {editing\n ? tr('brainyrich.households.form.editTitle', 'Edit household')\n : tr('brainyrich.households.form.createTitle', 'New household')}\n </DialogTitle>\n <DialogDescription>\n {tr(\n 'brainyrich.households.form.subtitle',\n 'A household groups a client family’s accounts, portfolios and goals.'\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-2\">\n <Label htmlFor=\"hh-name\">{tr('brainyrich.households.form.name', 'Name')} *</Label>\n <Input\n id=\"hh-name\"\n value={form.name}\n onChange={(e) => setField('name', e.target.value)}\n placeholder={tr('brainyrich.households.form.namePh', 'e.g. The Raghavan Family')}\n required\n />\n </div>\n\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>{tr('brainyrich.households.form.status', 'Status')}</Label>\n <Select\n value={form.status}\n onValueChange={(v) => setField('status', v as BraHouseholdStatus)}\n >\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {STATUS_OPTIONS.map((s) => (\n <SelectItem key={s} value={s}>\n {s}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n <div className=\"space-y-2\">\n <Label>{tr('brainyrich.households.form.risk', 'Risk profile')}</Label>\n <Select\n value={form.riskProfile}\n onValueChange={(v) => setField('riskProfile', v as BraRiskProfile)}\n >\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {RISK_OPTIONS.map((r) => (\n <SelectItem key={r} value={r}>\n {r}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"hh-contact-name\">\n {tr('brainyrich.households.form.contactName', 'Primary contact')}\n </Label>\n <Input\n id=\"hh-contact-name\"\n value={form.primaryContactName}\n onChange={(e) => setField('primaryContactName', e.target.value)}\n placeholder={tr('brainyrich.households.form.contactNamePh', 'Full name')}\n />\n </div>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"hh-contact-email\">\n {tr('brainyrich.households.form.contactEmail', 'Contact email')}\n </Label>\n <Input\n id=\"hh-contact-email\"\n type=\"email\"\n value={form.primaryContactEmail}\n onChange={(e) => setField('primaryContactEmail', e.target.value)}\n placeholder=\"name@example.com\"\n />\n </div>\n </div>\n\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>{tr('brainyrich.households.form.currency', 'Currency')}</Label>\n <Select value={form.currency} onValueChange={(v) => setField('currency', v)}>\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {CURRENCY_OPTIONS.map((c) => (\n <SelectItem key={c} value={c}>\n {c}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {!editing ? (\n <div className=\"space-y-2\">\n <Label htmlFor=\"hh-advisor\">\n {tr('brainyrich.households.form.advisor', 'Advisor ID')}\n </Label>\n <Input\n id=\"hh-advisor\"\n value={form.advisorId}\n onChange={(e) => setField('advisorId', e.target.value)}\n placeholder={tr('brainyrich.households.form.advisorPh', 'Optional')}\n />\n </div>\n ) : null}\n </div>\n\n {editing ? (\n <TagField\n entityType=\"brainyrich-household\"\n entityId={editing.id}\n label={tr('brainyrich.households.form.tags', 'Tags')}\n />\n ) : (\n <div className=\"space-y-2\">\n <Label htmlFor=\"hh-tags\">{tr('brainyrich.households.form.tags', 'Tags')}</Label>\n <Input\n id=\"hh-tags\"\n value={form.tags}\n onChange={(e) => setField('tags', e.target.value)}\n placeholder={tr('brainyrich.households.form.tagsPh', 'Comma-separated')}\n />\n </div>\n )}\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"hh-notes\">{tr('brainyrich.households.form.notes', 'Notes')}</Label>\n <Textarea\n id=\"hh-notes\"\n value={form.notes}\n onChange={(e) => setField('notes', e.target.value)}\n rows={3}\n />\n </div>\n\n <DialogFooter>\n <DialogClose asChild>\n <Button type=\"button\" variant=\"outline\">\n {tr('brainyrich.common.cancel', 'Cancel')}\n </Button>\n </DialogClose>\n <Button type=\"submit\" disabled={!canSubmit}>\n {submitting\n ? tr('brainyrich.common.saving', 'Saving…')\n : editing\n ? tr('brainyrich.common.save', 'Save changes')\n : tr('brainyrich.households.form.create', 'Create household')}\n </Button>\n </DialogFooter>\n </form>\n </DialogContent>\n </Dialog>\n );\n}\n\n// ============================================================================\n// Detail sheet\n// ============================================================================\n\ninterface HouseholdDetailSheetProps {\n householdId: string | undefined;\n onClose: () => void;\n onEdit: (h: BraHousehold) => void;\n tr: (key: string, fallback: string, params?: Record<string, string | number>) => string;\n}\n\nfunction HouseholdDetailSheet({ householdId, onClose, onEdit, tr }: HouseholdDetailSheetProps) {\n const { data: household, isLoading, isError, refetch } = useHousehold(householdId);\n const { data: accounts } = useAccounts(householdId ? { householdId } : {});\n const { data: portfolios } = usePortfolios(householdId ? { householdId } : {});\n const { data: goals } = useGoals(householdId ? { householdId } : {});\n\n const open = Boolean(householdId);\n\n const accountRows = useMemo(\n () =>\n [...accounts]\n .map((a) => ({ account: a, value: accountValue(a) }))\n .sort((x, y) => y.value - x.value),\n [accounts]\n );\n const invested = accountRows.reduce((s, r) => s + r.value, 0);\n const allocDonut: DonutDatum[] = accountRows\n .filter((r) => r.value > 0)\n .slice(0, 6)\n .map((r) => ({ label: r.account.name, value: r.value }));\n\n return (\n <Sheet open={open} onOpenChange={(o) => (!o ? onClose() : undefined)}>\n <SheetContent className=\"flex w-full flex-col gap-0 overflow-y-auto p-0 sm:max-w-xl\">\n {isLoading ? (\n <div className=\"p-6\">\n <LoadingState rows={4} />\n </div>\n ) : isError ? (\n <div className=\"p-6\">\n <ErrorState\n title={tr('brainyrich.households.detail.error', 'Could not load household')}\n onRetry={() => refetch()}\n />\n </div>\n ) : !household ? (\n <div className=\"p-6\">\n <EmptyState\n icon={<Users className=\"size-6\" aria-hidden=\"true\" />}\n title={tr('brainyrich.households.detail.missing', 'Household not found')}\n />\n </div>\n ) : (\n <div className=\"space-y-5 p-6\">\n <SheetHeader className=\"space-y-2 p-0 text-left\">\n <SheetTitle className=\"text-xl\">{household.name}</SheetTitle>\n <SheetDescription className=\"sr-only\">\n {tr('brainyrich.households.detail.subtitle', 'Household overview')}\n </SheetDescription>\n <div className=\"flex flex-wrap items-center gap-2 pt-1\">\n <Badge variant={statusBadgeVariant(household.status)}>{household.status}</Badge>\n <Badge variant=\"secondary\">{household.riskProfile}</Badge>\n </div>\n </SheetHeader>\n\n {/* Hero — AUM + primary contact on a glass surface with emerald glow */}\n <GlassCard glow>\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <p className=\"text-xs uppercase tracking-wide text-text-secondary\">\n {tr('brainyrich.households.detail.aum', 'AUM')}\n </p>\n <p className=\"mt-1 text-3xl font-semibold tracking-tight text-text-primary\">\n {formatMoney(household.aum, household.currency)}\n </p>\n <p className=\"mt-1 text-xs text-text-secondary\">{household.currency}</p>\n </div>\n <div className=\"sm:text-right\">\n <p className=\"text-xs uppercase tracking-wide text-text-secondary\">\n {tr('brainyrich.households.detail.contact', 'Primary contact')}\n </p>\n <p className=\"mt-1 text-base font-medium text-text-primary\">\n {household.primaryContactName ?? '—'}\n </p>\n {household.primaryContactEmail ? (\n <a\n href={`mailto:${household.primaryContactEmail}`}\n className=\"mt-0.5 inline-flex items-center gap-1 text-xs text-text-secondary hover:text-[var(--color-action-primary-text)] sm:justify-end\"\n >\n <Mail className=\"size-3\" aria-hidden=\"true\" />\n {household.primaryContactEmail}\n </a>\n ) : null}\n </div>\n </div>\n </GlassCard>\n\n {/* Portfolio counts */}\n <div className=\"grid grid-cols-3 gap-3\">\n <SummaryTile\n icon={<Wallet className=\"size-4\" aria-hidden=\"true\" />}\n label={tr('brainyrich.households.detail.accounts', 'Accounts')}\n value={String(accounts.length)}\n />\n <SummaryTile\n icon={<Briefcase className=\"size-4\" aria-hidden=\"true\" />}\n label={tr('brainyrich.households.detail.portfolios', 'Portfolios')}\n value={String(portfolios.length)}\n />\n <SummaryTile\n icon={<Target className=\"size-4\" aria-hidden=\"true\" />}\n label={tr('brainyrich.households.detail.goals', 'Goals')}\n value={String(goals.length)}\n />\n </div>\n\n {household.tags.length > 0 ? (\n <div className=\"flex flex-wrap gap-1\">\n {household.tags.map((tag) => (\n <Badge key={tag} variant=\"outline\">\n {tag}\n </Badge>\n ))}\n </div>\n ) : null}\n\n <Tabs defaultValue=\"overview\" className=\"w-full\">\n <TabsList className=\"w-full justify-start overflow-x-auto\">\n <TabsTrigger value=\"overview\">\n {tr('brainyrich.households.tab.overview', 'Overview')}\n </TabsTrigger>\n <TabsTrigger value=\"accounts\">\n {tr('brainyrich.households.detail.accounts', 'Accounts')}\n </TabsTrigger>\n <TabsTrigger value=\"goals\">\n {tr('brainyrich.households.detail.goals', 'Goals')}\n </TabsTrigger>\n <TabsTrigger value=\"documents\">\n {tr('brainyrich.households.detail.documents', 'Documents')}\n </TabsTrigger>\n <TabsTrigger value=\"discussion\">\n {tr('brainyrich.households.detail.discussion', 'Discussion')}\n </TabsTrigger>\n </TabsList>\n\n {/* Overview */}\n <TabsContent value=\"overview\" className=\"mt-4 space-y-4\">\n {allocDonut.length > 0 ? (\n <Card>\n <CardContent className=\"p-4\">\n <h3 className=\"mb-3 text-sm font-medium text-text-primary\">\n {tr('brainyrich.households.detail.allocation', 'Where assets sit')}\n </h3>\n <DonutChart\n data={allocDonut}\n centerValue={formatCompact(invested, household.currency)}\n centerLabel={tr('brainyrich.households.detail.invested', 'Invested')}\n height={200}\n valueFormatter={(v) => formatMoney(v, household.currency)}\n />\n </CardContent>\n </Card>\n ) : null}\n\n <Card>\n <CardContent className=\"space-y-3 p-4 text-sm\">\n <div className=\"flex items-center justify-between gap-4\">\n <span className=\"text-text-secondary\">\n {tr('brainyrich.households.detail.advisor', 'Advisor')}\n </span>\n <span className=\"text-right font-medium text-text-primary\">\n {household.advisorId ? (\n <ActorName id={household.advisorId} />\n ) : (\n tr('brainyrich.common.unassigned', 'Unassigned')\n )}\n </span>\n </div>\n <Separator />\n <DetailRow\n label={tr('brainyrich.households.detail.created', 'Created')}\n value={formatDate(household.createdAt)}\n />\n <DetailRow\n label={tr('brainyrich.households.detail.updated', 'Last updated')}\n value={formatDate(household.updatedAt)}\n />\n </CardContent>\n </Card>\n\n {household.notes ? (\n <Card>\n <CardContent className=\"space-y-1 p-4\">\n <p className=\"text-xs font-medium uppercase tracking-wide text-text-secondary\">\n {tr('brainyrich.households.detail.summary', 'Summary')}\n </p>\n <p className=\"text-sm text-text-primary\">{household.notes}</p>\n </CardContent>\n </Card>\n ) : null}\n </TabsContent>\n\n {/* Accounts */}\n <TabsContent value=\"accounts\" className=\"mt-4 space-y-2\">\n {accountRows.length === 0 ? (\n <EmptyState\n icon={<Wallet className=\"size-6\" aria-hidden=\"true\" />}\n title={tr('brainyrich.households.detail.noAccounts', 'No accounts linked')}\n />\n ) : (\n accountRows.map(({ account, value }) => (\n <div\n key={account.id}\n className=\"flex items-center justify-between gap-3 rounded-lg border border-border-subtle bg-bg-surface p-3 transition-colors hover:border-[var(--color-action-primary-border)]\"\n >\n <div className=\"min-w-0\">\n <p className=\"truncate text-sm font-medium text-text-primary\">\n {account.name}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {account.institution ?? account.type}\n {account.accountMask ? ` ·••${account.accountMask}` : ''}\n </p>\n </div>\n <span className=\"shrink-0 text-sm font-semibold tabular-nums text-status-success-text\">\n {formatMoney(value, account.currency)}\n </span>\n </div>\n ))\n )}\n </TabsContent>\n\n {/* Goals */}\n <TabsContent value=\"goals\" className=\"mt-4 space-y-2\">\n {goals.length === 0 ? (\n <EmptyState\n icon={<Target className=\"size-6\" aria-hidden=\"true\" />}\n title={tr('brainyrich.households.detail.noGoals', 'No goals set')}\n />\n ) : (\n goals.map((g: BraGoal) => (\n <div\n key={g.id}\n className=\"flex items-center justify-between gap-3 rounded-lg border border-border-subtle bg-bg-surface p-3\"\n >\n <div className=\"min-w-0\">\n <p className=\"truncate text-sm font-medium text-text-primary\">{g.name}</p>\n <p className=\"text-xs text-text-secondary\">\n {tr('brainyrich.households.detail.goalTarget', 'Target')}{' '}\n {formatMoney(g.targetAmount, g.currency)} · {formatDate(g.targetDate)}\n </p>\n </div>\n <Badge variant={statusBadgeVariant(g.projection)} className=\"shrink-0\">\n {g.projection.replace(/_/g, ' ')}\n </Badge>\n </div>\n ))\n )}\n </TabsContent>\n\n {/* Documents */}\n <TabsContent value=\"documents\" className=\"mt-4\">\n <DocumentsPanel\n entityType=\"brainyrich-household\"\n entityId={household.id}\n heading={tr('brainyrich.households.detail.documents', 'Documents')}\n />\n </TabsContent>\n\n {/* Discussion */}\n <TabsContent value=\"discussion\" className=\"mt-4\">\n <CommentThread\n entityType=\"brainyrich-household\"\n entityId={household.id}\n heading={tr('brainyrich.households.detail.discussion', 'Discussion')}\n />\n </TabsContent>\n </Tabs>\n\n <Button variant=\"outline\" className=\"w-full\" onClick={() => onEdit(household)}>\n <Pencil className=\"size-4\" aria-hidden=\"true\" />\n {tr('brainyrich.households.action.edit', 'Edit')}\n </Button>\n </div>\n )}\n </SheetContent>\n </Sheet>\n );\n}\n\nfunction SummaryTile({ icon, label, value }: { icon: ReactNode; label: string; value: string }) {\n return (\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-3 text-center transition-shadow motion-safe:hover:shadow-[var(--shadow-pop-hover,var(--shadow-elevation-2))]\">\n <div className=\"mx-auto mb-1 flex size-8 items-center justify-center rounded-full bg-bg-sunken text-text-secondary\">\n {icon}\n </div>\n <p className=\"text-lg font-semibold text-text-primary\">{value}</p>\n <p className=\"text-xs text-text-secondary\">{label}</p>\n </div>\n );\n}\n\nfunction DetailRow({ label, value }: { label: string; value: string }) {\n return (\n <div className=\"flex items-center justify-between gap-4\">\n <span className=\"text-text-secondary\">{label}</span>\n <span className=\"text-right font-medium text-text-primary\">{value}</span>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"FamilyPage.js","names":[],"sources":["../../../src/brainyrich/pages/FamilyPage.tsx"],"sourcesContent":["import { useMemo, useState, type ReactNode } from 'react';\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n Dialog,\n DialogClose,\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 Separator,\n Sheet,\n SheetContent,\n SheetDescription,\n SheetHeader,\n SheetTitle,\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n Textarea,\n} from '@burdenoff/fe-libs/ui';\nimport {\n Users,\n MoreHorizontal,\n Pencil,\n Archive,\n Eye,\n Mail,\n Wallet,\n Target,\n Briefcase,\n Building2,\n TrendingUp,\n UserCircle2,\n} from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { tWithFallback } from '../utils/i18n';\nimport {\n usePagedHouseholds,\n useHousehold,\n useCreateHousehold,\n useUpdateHousehold,\n useArchiveHousehold,\n useAccounts,\n usePortfolios,\n useGoals,\n} from '../hooks/useBrainyRichApi';\nimport {\n ConfirmDialog,\n LoadMore,\n ActorName,\n StatTile,\n GlassCard,\n FadeIn,\n DonutChart,\n type DonutDatum,\n} from '../components';\nimport { TagField } from '../components/reuse/TagField';\nimport { DocumentsPanel } from '../components/reuse/DocumentsPanel';\nimport { CommentThread } from '../components/reuse/CommentThread';\nimport type {\n BraHousehold,\n BraHouseholdStatus,\n BraRiskProfile,\n BraCreateHouseholdInput,\n BraUpdateHouseholdInput,\n BraAccount,\n BraGoal,\n} from '../types/bra';\nimport {\n SectionShell,\n EmptyState,\n LoadingState,\n ErrorState,\n formatMoney,\n formatCompact,\n formatDate,\n statusBadgeVariant,\n} from './_shared';\n\nconst STATUS_OPTIONS: BraHouseholdStatus[] = ['PROSPECT', 'ONBOARDING', 'ACTIVE', 'INACTIVE'];\nconst RISK_OPTIONS: BraRiskProfile[] = [\n 'CONSERVATIVE',\n 'MODERATE',\n 'BALANCED',\n 'GROWTH',\n 'AGGRESSIVE',\n];\nconst CURRENCY_OPTIONS = ['USD', 'EUR', 'GBP', 'INR', 'AED', 'SGD'];\n\n/** Per-status donut tone (semantic — colour is never the only signal). */\nconst STATUS_TONE: Record<BraHouseholdStatus, DonutDatum['tone']> = {\n ACTIVE: 'brand',\n ONBOARDING: 'info',\n PROSPECT: 'warning',\n INACTIVE: 'neutral',\n};\n\ninterface HouseholdFormState {\n name: string;\n status: BraHouseholdStatus;\n riskProfile: BraRiskProfile;\n currency: string;\n advisorId: string;\n primaryContactName: string;\n primaryContactEmail: string;\n notes: string;\n tags: string;\n}\n\nconst emptyForm: HouseholdFormState = {\n name: '',\n status: 'PROSPECT',\n riskProfile: 'BALANCED',\n currency: 'USD',\n advisorId: '',\n primaryContactName: '',\n primaryContactEmail: '',\n notes: '',\n tags: '',\n};\n\nfunction toTags(raw: string): string[] {\n return raw\n .split(',')\n .map((t) => t.trim())\n .filter(Boolean);\n}\n\n/** Real market value of an account: settled cash + marked-to-market holdings. */\nfunction accountValue(a: BraAccount): number {\n const holdings = (a.holdings ?? []).reduce(\n (sum, h) => sum + (Number.isFinite(h.marketValue) ? h.marketValue : 0),\n 0\n );\n const cash = Number.isFinite(a.cashBalance) ? a.cashBalance : 0;\n return cash + holdings;\n}\n\nexport function FamilyPage() {\n const { t } = useI18n();\n const tr = (key: string, fallback: string, params?: Record<string, string | number>) =>\n tWithFallback(t, key, fallback, params);\n\n const {\n items: households,\n hasMore,\n loadMore,\n isLoading,\n isFetchingNextPage,\n isError,\n refetch,\n } = usePagedHouseholds();\n\n const createHousehold = useCreateHousehold();\n const updateHousehold = useUpdateHousehold();\n const archiveHousehold = useArchiveHousehold();\n\n const [formOpen, setFormOpen] = useState(false);\n const [editing, setEditing] = useState<BraHousehold | null>(null);\n const [form, setForm] = useState<HouseholdFormState>(emptyForm);\n const [detailId, setDetailId] = useState<string | undefined>(undefined);\n const [archiveTarget, setArchiveTarget] = useState<BraHousehold | null>(null);\n\n const setField = <K extends keyof HouseholdFormState>(key: K, value: HouseholdFormState[K]) =>\n setForm((prev) => ({ ...prev, [key]: value }));\n\n const openCreate = () => {\n setEditing(null);\n setForm(emptyForm);\n setFormOpen(true);\n };\n\n const openEdit = (h: BraHousehold) => {\n setEditing(h);\n setForm({\n name: h.name,\n status: h.status,\n riskProfile: h.riskProfile,\n currency: h.currency,\n advisorId: h.advisorId ?? '',\n primaryContactName: h.primaryContactName ?? '',\n primaryContactEmail: h.primaryContactEmail ?? '',\n notes: h.notes ?? '',\n tags: h.tags.join(', '),\n });\n setFormOpen(true);\n };\n\n const firm = useMemo(() => {\n const currency = households[0]?.currency ?? 'USD';\n const total = households.length;\n const active = households.filter((h) => h.status === 'ACTIVE').length;\n const prospects = households.filter((h) => h.status === 'PROSPECT').length;\n const onboarding = households.filter((h) => h.status === 'ONBOARDING').length;\n const aum = households.reduce((sum, h) => sum + (Number.isFinite(h.aum) ? h.aum : 0), 0);\n\n // AUM grouped by advisor (empty advisorId → unassigned bucket).\n const byAdvisor = new Map<string, number>();\n for (const h of households) {\n const key = h.advisorId?.trim() || '';\n byAdvisor.set(key, (byAdvisor.get(key) ?? 0) + (Number.isFinite(h.aum) ? h.aum : 0));\n }\n const advisors = Array.from(byAdvisor.entries())\n .map(([advisorId, value]) => ({ advisorId, value }))\n .sort((a, b) => b.value - a.value);\n const advisorCount = advisors.filter((a) => a.advisorId).length;\n const advisorMax = advisors.reduce((m, a) => Math.max(m, a.value), 0);\n\n // Book mix by status → donut.\n const statusMix: DonutDatum[] = (STATUS_OPTIONS as BraHouseholdStatus[])\n .map((s) => ({\n label: s.charAt(0) + s.slice(1).toLowerCase(),\n value: households.filter((h) => h.status === s).length,\n tone: STATUS_TONE[s],\n }))\n .filter((d) => d.value > 0);\n\n return {\n currency,\n total,\n active,\n prospects,\n onboarding,\n aum,\n advisors,\n advisorCount,\n advisorMax,\n statusMix,\n };\n }, [households]);\n\n const submitting = createHousehold.isPending || updateHousehold.isPending;\n const canSubmit = form.name.trim().length > 0 && !submitting;\n\n const handleSubmit = () => {\n if (!canSubmit) return;\n if (editing) {\n const input: BraUpdateHouseholdInput = {\n name: form.name.trim(),\n status: form.status,\n riskProfile: form.riskProfile,\n currency: form.currency,\n primaryContactName: form.primaryContactName.trim() || null,\n primaryContactEmail: form.primaryContactEmail.trim() || null,\n notes: form.notes.trim() || null,\n tags: toTags(form.tags),\n };\n updateHousehold.mutate({ id: editing.id, input }, { onSuccess: () => setFormOpen(false) });\n } else {\n const input: BraCreateHouseholdInput = {\n name: form.name.trim(),\n status: form.status,\n riskProfile: form.riskProfile,\n currency: form.currency,\n primaryContactName: form.primaryContactName.trim() || null,\n primaryContactEmail: form.primaryContactEmail.trim() || null,\n notes: form.notes.trim() || null,\n tags: toTags(form.tags),\n };\n if (form.advisorId.trim()) input.advisorId = form.advisorId.trim();\n createHousehold.mutate(input, { onSuccess: () => setFormOpen(false) });\n }\n };\n\n const showFirm = !isLoading && !isError && households.length > 0;\n\n return (\n <SectionShell\n title={tr('brainyrich.households.title', 'Households')}\n description={tr(\n 'brainyrich.households.description',\n 'Client households and family units under advisement'\n )}\n badges={\n households.length\n ? [tr('brainyrich.households.count', '{count} households', { count: households.length })]\n : []\n }\n actionLabel={tr('brainyrich.households.new', 'New household')}\n onAction={openCreate}\n >\n {showFirm ? (\n <FirmOverview firm={firm} tr={tr} />\n ) : (\n <div className=\"grid gap-4 md:grid-cols-2 xl:grid-cols-4\">\n <StatTile label={tr('brainyrich.households.kpi.aum', 'Total AUM')} value=\"—\" glow />\n <StatTile label={tr('brainyrich.households.kpi.total', 'Households')} value=\"—\" />\n <StatTile label={tr('brainyrich.households.kpi.active', 'Active')} value=\"—\" />\n <StatTile label={tr('brainyrich.households.kpi.prospects', 'Prospects')} value=\"—\" />\n </div>\n )}\n\n {isLoading ? (\n <LoadingState rows={5} />\n ) : isError ? (\n <ErrorState\n title={tr('brainyrich.households.error.title', 'Could not load households')}\n onRetry={() => refetch()}\n />\n ) : households.length === 0 ? (\n <EmptyState\n icon={<Users className=\"size-6\" aria-hidden=\"true\" />}\n title={tr('brainyrich.households.empty.title', 'No households yet')}\n description={tr(\n 'brainyrich.households.empty.description',\n 'Create your first client household to start organizing accounts, portfolios and goals.'\n )}\n action={\n <Button size=\"sm\" onClick={openCreate}>\n {tr('brainyrich.households.new', 'New household')}\n </Button>\n }\n />\n ) : (\n <FadeIn as=\"section\">\n <Card className=\"overflow-hidden\">\n <CardContent className=\"p-0\">\n <div className=\"overflow-x-auto\">\n <Table>\n <TableHeader>\n <TableRow className=\"hover:bg-transparent\">\n <TableHead>{tr('brainyrich.households.col.name', 'Household')}</TableHead>\n <TableHead>{tr('brainyrich.households.col.status', 'Status')}</TableHead>\n <TableHead className=\"hidden md:table-cell\">\n {tr('brainyrich.households.col.risk', 'Risk profile')}\n </TableHead>\n <TableHead className=\"hidden lg:table-cell\">\n {tr('brainyrich.households.col.contact', 'Primary contact')}\n </TableHead>\n <TableHead className=\"hidden sm:table-cell\">\n {tr('brainyrich.households.col.advisor', 'Advisor')}\n </TableHead>\n <TableHead className=\"text-right\">\n {tr('brainyrich.households.col.aum', 'AUM')}\n </TableHead>\n <TableHead className=\"w-12 text-right\">\n <span className=\"sr-only\">\n {tr('brainyrich.households.col.actions', 'Actions')}\n </span>\n </TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {households.map((h) => {\n const share = firm.aum > 0 ? Math.min(100, (h.aum / firm.aum) * 100) : 0;\n return (\n <TableRow\n key={h.id}\n className=\"group cursor-pointer transition-colors\"\n onClick={() => setDetailId(h.id)}\n >\n <TableCell>\n <span className=\"font-medium text-text-primary transition-colors group-hover:text-[var(--color-action-primary-text)]\">\n {h.name}\n </span>\n {h.tags.length > 0 ? (\n <div className=\"mt-1 flex flex-wrap gap-1\">\n {h.tags.slice(0, 3).map((tag) => (\n <Badge key={tag} variant=\"outline\" className=\"text-xs\">\n {tag}\n </Badge>\n ))}\n {h.tags.length > 3 ? (\n <Badge variant=\"outline\" className=\"text-xs\">\n +{h.tags.length - 3}\n </Badge>\n ) : null}\n </div>\n ) : null}\n </TableCell>\n <TableCell>\n <Badge variant={statusBadgeVariant(h.status)}>{h.status}</Badge>\n </TableCell>\n <TableCell className=\"hidden md:table-cell\">\n <Badge variant=\"secondary\">{h.riskProfile}</Badge>\n </TableCell>\n <TableCell className=\"hidden lg:table-cell\">\n {h.primaryContactName ? (\n <div className=\"space-y-0.5\">\n <p className=\"text-sm text-text-primary\">{h.primaryContactName}</p>\n {h.primaryContactEmail ? (\n <p className=\"flex items-center gap-1 text-xs text-text-secondary\">\n <Mail className=\"size-3\" aria-hidden=\"true\" />\n {h.primaryContactEmail}\n </p>\n ) : null}\n </div>\n ) : (\n <span className=\"text-sm text-text-muted\">—</span>\n )}\n </TableCell>\n <TableCell className=\"hidden sm:table-cell\">\n {h.advisorId ? (\n <span className=\"flex items-center gap-1.5 text-sm text-text-secondary\">\n <UserCircle2 className=\"size-3.5\" aria-hidden=\"true\" />\n <ActorName id={h.advisorId} />\n </span>\n ) : (\n <span className=\"text-sm text-text-muted\">\n {tr('brainyrich.common.unassigned', 'Unassigned')}\n </span>\n )}\n </TableCell>\n <TableCell className=\"text-right\">\n <div className=\"flex flex-col items-end gap-1\">\n <span className=\"font-medium tabular-nums text-text-primary\">\n {formatMoney(h.aum, h.currency)}\n </span>\n <span\n className=\"h-1 w-16 overflow-hidden rounded-full bg-bg-sunken\"\n aria-hidden=\"true\"\n >\n <span\n className=\"block h-full rounded-full bg-[var(--color-action-primary-bg)]\"\n style={{ width: `${share}%` }}\n />\n </span>\n </div>\n </TableCell>\n <TableCell className=\"text-right\" onClick={(e) => e.stopPropagation()}>\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label={tr(\n 'brainyrich.households.rowMenu',\n 'Household actions'\n )}\n >\n <MoreHorizontal className=\"size-4\" aria-hidden=\"true\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuItem onClick={() => setDetailId(h.id)}>\n <Eye className=\"size-4\" aria-hidden=\"true\" />\n {tr('brainyrich.households.action.view', 'View details')}\n </DropdownMenuItem>\n <DropdownMenuItem onClick={() => openEdit(h)}>\n <Pencil className=\"size-4\" aria-hidden=\"true\" />\n {tr('brainyrich.households.action.edit', 'Edit')}\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n className=\"text-status-error-text focus:text-status-error-text\"\n onClick={() => setArchiveTarget(h)}\n >\n <Archive className=\"size-4\" aria-hidden=\"true\" />\n {tr('brainyrich.households.action.archive', 'Archive')}\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </TableCell>\n </TableRow>\n );\n })}\n </TableBody>\n </Table>\n </div>\n </CardContent>\n </Card>\n </FadeIn>\n )}\n\n {!isLoading && !isError && households.length > 0 ? (\n <LoadMore\n hasMore={hasMore}\n onClick={loadMore}\n loading={isFetchingNextPage}\n label={tr('brainyrich.households.loadMore', 'Load more households')}\n />\n ) : null}\n\n <HouseholdFormDialog\n open={formOpen}\n onOpenChange={setFormOpen}\n editing={editing}\n form={form}\n setField={setField}\n onSubmit={handleSubmit}\n canSubmit={canSubmit}\n submitting={submitting}\n tr={tr}\n />\n\n <HouseholdDetailSheet\n householdId={detailId}\n onClose={() => setDetailId(undefined)}\n onEdit={(h) => {\n setDetailId(undefined);\n openEdit(h);\n }}\n tr={tr}\n />\n\n <ConfirmDialog\n open={Boolean(archiveTarget)}\n onOpenChange={(o) => (!o ? setArchiveTarget(null) : undefined)}\n title={tr('brainyrich.households.archive.title', 'Archive household?')}\n description={tr(\n 'brainyrich.households.archive.description',\n 'Archiving “{name}” removes it from the active list. You can still access its records, but it will no longer appear here.',\n { name: archiveTarget?.name ?? '' }\n )}\n confirmLabel={tr('brainyrich.households.action.archive', 'Archive')}\n pendingLabel={tr('brainyrich.households.archive.pending', 'Archiving…')}\n destructive\n pending={archiveHousehold.isPending}\n onConfirm={() => {\n if (!archiveTarget) return;\n archiveHousehold.mutate(archiveTarget.id, {\n onSuccess: () => setArchiveTarget(null),\n });\n }}\n />\n </SectionShell>\n );\n}\n\n// ============================================================================\n// Firm overview — practice-wide KPIs + AUM-by-advisor + book mix\n// ============================================================================\n\ninterface FirmData {\n currency: string;\n total: number;\n active: number;\n prospects: number;\n onboarding: number;\n aum: number;\n advisors: { advisorId: string; value: number }[];\n advisorCount: number;\n advisorMax: number;\n statusMix: DonutDatum[];\n}\n\nfunction FirmOverview({\n firm,\n tr,\n}: {\n firm: FirmData;\n tr: (key: string, fallback: string, params?: Record<string, string | number>) => string;\n}) {\n return (\n <FadeIn as=\"section\" className=\"space-y-4\">\n <div className=\"grid gap-4 md:grid-cols-2 xl:grid-cols-4\">\n <StatTile\n label={tr('brainyrich.households.kpi.aum', 'Total AUM')}\n value={formatMoney(firm.aum, firm.currency)}\n glow\n icon={<Wallet className=\"size-4\" aria-hidden=\"true\" />}\n />\n <StatTile\n label={tr('brainyrich.households.kpi.total', 'Households')}\n value={String(firm.total)}\n icon={<Users className=\"size-4\" aria-hidden=\"true\" />}\n />\n <StatTile\n label={tr('brainyrich.households.kpi.active', 'Active')}\n value={String(firm.active)}\n icon={<TrendingUp className=\"size-4\" aria-hidden=\"true\" />}\n />\n <StatTile\n label={tr('brainyrich.households.kpi.prospects', 'Prospects')}\n value={String(firm.prospects)}\n icon={<Target className=\"size-4\" aria-hidden=\"true\" />}\n />\n </div>\n\n <div className=\"grid gap-4 lg:grid-cols-3\">\n <GlassCard className=\"lg:col-span-2\">\n <div className=\"mb-4 flex items-center justify-between gap-2\">\n <div>\n <h2 className=\"text-sm font-semibold text-text-primary\">\n {tr('brainyrich.households.firm.byAdvisor', 'AUM by advisor')}\n </h2>\n <p className=\"text-xs text-text-secondary\">\n {tr('brainyrich.households.firm.advisorCount', '{count} advisors', {\n count: firm.advisorCount,\n })}\n </p>\n </div>\n <Building2 className=\"size-4 text-text-secondary\" aria-hidden=\"true\" />\n </div>\n <ul\n className=\"space-y-3.5\"\n aria-label={tr('brainyrich.households.firm.byAdvisor', 'AUM by advisor')}\n >\n {firm.advisors.map((a) => {\n const width =\n firm.advisorMax > 0 ? Math.max(2, (a.value / firm.advisorMax) * 100) : 0;\n return (\n <li key={a.advisorId || 'unassigned'} className=\"space-y-1.5\">\n <div className=\"flex items-center justify-between gap-3 text-xs\">\n <span className=\"flex items-center gap-1.5 truncate font-medium text-text-primary\">\n <UserCircle2\n className=\"size-3.5 shrink-0 text-text-secondary\"\n aria-hidden=\"true\"\n />\n {a.advisorId ? (\n <ActorName id={a.advisorId} />\n ) : (\n tr('brainyrich.common.unassigned', 'Unassigned')\n )}\n </span>\n <span className=\"shrink-0 tabular-nums text-text-secondary\">\n {formatCompact(a.value, firm.currency)}\n </span>\n </div>\n <div\n className=\"h-2 w-full overflow-hidden rounded-full bg-bg-sunken\"\n role=\"progressbar\"\n aria-valuenow={Math.round(width)}\n aria-valuemin={0}\n aria-valuemax={100}\n aria-label={a.advisorId || 'Unassigned'}\n >\n <div\n className=\"h-full rounded-full bg-[var(--color-action-primary-bg)] transition-[width] duration-500 ease-out\"\n style={{ width: `${width}%` }}\n />\n </div>\n </li>\n );\n })}\n </ul>\n </GlassCard>\n\n <GlassCard>\n <div className=\"mb-2 flex items-center justify-between gap-2\">\n <h2 className=\"text-sm font-semibold text-text-primary\">\n {tr('brainyrich.households.firm.bookMix', 'Book by status')}\n </h2>\n </div>\n {firm.statusMix.length > 0 ? (\n <DonutChart\n data={firm.statusMix}\n centerValue={String(firm.total)}\n centerLabel={tr('brainyrich.households.kpi.total', 'Households')}\n legend\n height={200}\n valueFormatter={(v) => String(v)}\n />\n ) : (\n <p className=\"text-sm text-text-secondary\">\n {tr('brainyrich.households.firm.noMix', 'No households to chart yet.')}\n </p>\n )}\n </GlassCard>\n </div>\n </FadeIn>\n );\n}\n\n// ============================================================================\n// Create / edit dialog\n// ============================================================================\n\ninterface HouseholdFormDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n editing: BraHousehold | null;\n form: HouseholdFormState;\n setField: <K extends keyof HouseholdFormState>(key: K, value: HouseholdFormState[K]) => void;\n onSubmit: () => void;\n canSubmit: boolean;\n submitting: boolean;\n tr: (key: string, fallback: string, params?: Record<string, string | number>) => string;\n}\n\nfunction HouseholdFormDialog({\n open,\n onOpenChange,\n editing,\n form,\n setField,\n onSubmit,\n canSubmit,\n submitting,\n tr,\n}: HouseholdFormDialogProps) {\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 {editing\n ? tr('brainyrich.households.form.editTitle', 'Edit household')\n : tr('brainyrich.households.form.createTitle', 'New household')}\n </DialogTitle>\n <DialogDescription>\n {tr(\n 'brainyrich.households.form.subtitle',\n 'A household groups a client family’s accounts, portfolios and goals.'\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-2\">\n <Label htmlFor=\"hh-name\">{tr('brainyrich.households.form.name', 'Name')} *</Label>\n <Input\n id=\"hh-name\"\n value={form.name}\n onChange={(e) => setField('name', e.target.value)}\n placeholder={tr('brainyrich.households.form.namePh', 'e.g. The Raghavan Family')}\n required\n />\n </div>\n\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>{tr('brainyrich.households.form.status', 'Status')}</Label>\n <Select\n value={form.status}\n onValueChange={(v) => setField('status', v as BraHouseholdStatus)}\n >\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {STATUS_OPTIONS.map((s) => (\n <SelectItem key={s} value={s}>\n {s}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n <div className=\"space-y-2\">\n <Label>{tr('brainyrich.households.form.risk', 'Risk profile')}</Label>\n <Select\n value={form.riskProfile}\n onValueChange={(v) => setField('riskProfile', v as BraRiskProfile)}\n >\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {RISK_OPTIONS.map((r) => (\n <SelectItem key={r} value={r}>\n {r}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"hh-contact-name\">\n {tr('brainyrich.households.form.contactName', 'Primary contact')}\n </Label>\n <Input\n id=\"hh-contact-name\"\n value={form.primaryContactName}\n onChange={(e) => setField('primaryContactName', e.target.value)}\n placeholder={tr('brainyrich.households.form.contactNamePh', 'Full name')}\n />\n </div>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"hh-contact-email\">\n {tr('brainyrich.households.form.contactEmail', 'Contact email')}\n </Label>\n <Input\n id=\"hh-contact-email\"\n type=\"email\"\n value={form.primaryContactEmail}\n onChange={(e) => setField('primaryContactEmail', e.target.value)}\n placeholder=\"name@example.com\"\n />\n </div>\n </div>\n\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>{tr('brainyrich.households.form.currency', 'Currency')}</Label>\n <Select value={form.currency} onValueChange={(v) => setField('currency', v)}>\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {CURRENCY_OPTIONS.map((c) => (\n <SelectItem key={c} value={c}>\n {c}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {!editing ? (\n <div className=\"space-y-2\">\n <Label htmlFor=\"hh-advisor\">\n {tr('brainyrich.households.form.advisor', 'Advisor ID')}\n </Label>\n <Input\n id=\"hh-advisor\"\n value={form.advisorId}\n onChange={(e) => setField('advisorId', e.target.value)}\n placeholder={tr('brainyrich.households.form.advisorPh', 'Optional')}\n />\n </div>\n ) : null}\n </div>\n\n {editing ? (\n <TagField\n entityType=\"brainyrich-household\"\n entityId={editing.id}\n label={tr('brainyrich.households.form.tags', 'Tags')}\n />\n ) : (\n <div className=\"space-y-2\">\n <Label htmlFor=\"hh-tags\">{tr('brainyrich.households.form.tags', 'Tags')}</Label>\n <Input\n id=\"hh-tags\"\n value={form.tags}\n onChange={(e) => setField('tags', e.target.value)}\n placeholder={tr('brainyrich.households.form.tagsPh', 'Comma-separated')}\n />\n </div>\n )}\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"hh-notes\">{tr('brainyrich.households.form.notes', 'Notes')}</Label>\n <Textarea\n id=\"hh-notes\"\n value={form.notes}\n onChange={(e) => setField('notes', e.target.value)}\n rows={3}\n />\n </div>\n\n <DialogFooter>\n <DialogClose asChild>\n <Button type=\"button\" variant=\"outline\">\n {tr('brainyrich.common.cancel', 'Cancel')}\n </Button>\n </DialogClose>\n <Button type=\"submit\" disabled={!canSubmit}>\n {submitting\n ? tr('brainyrich.common.saving', 'Saving…')\n : editing\n ? tr('brainyrich.common.save', 'Save changes')\n : tr('brainyrich.households.form.create', 'Create household')}\n </Button>\n </DialogFooter>\n </form>\n </DialogContent>\n </Dialog>\n );\n}\n\n// ============================================================================\n// Detail sheet\n// ============================================================================\n\ninterface HouseholdDetailSheetProps {\n householdId: string | undefined;\n onClose: () => void;\n onEdit: (h: BraHousehold) => void;\n tr: (key: string, fallback: string, params?: Record<string, string | number>) => string;\n}\n\nfunction HouseholdDetailSheet({ householdId, onClose, onEdit, tr }: HouseholdDetailSheetProps) {\n const { data: household, isLoading, isError, refetch } = useHousehold(householdId);\n const { data: accounts } = useAccounts(householdId ? { householdId } : {});\n const { data: portfolios } = usePortfolios(householdId ? { householdId } : {});\n const { data: goals } = useGoals(householdId ? { householdId } : {});\n\n const open = Boolean(householdId);\n\n const accountRows = useMemo(\n () =>\n [...accounts]\n .map((a) => ({ account: a, value: accountValue(a) }))\n .sort((x, y) => y.value - x.value),\n [accounts]\n );\n const invested = accountRows.reduce((s, r) => s + r.value, 0);\n const allocDonut: DonutDatum[] = accountRows\n .filter((r) => r.value > 0)\n .slice(0, 6)\n .map((r) => ({ label: r.account.name, value: r.value }));\n\n return (\n <Sheet open={open} onOpenChange={(o) => (!o ? onClose() : undefined)}>\n <SheetContent className=\"flex w-full flex-col gap-0 overflow-y-auto p-0 sm:max-w-xl\">\n {isLoading ? (\n <div className=\"p-6\">\n <LoadingState rows={4} />\n </div>\n ) : isError ? (\n <div className=\"p-6\">\n <ErrorState\n title={tr('brainyrich.households.detail.error', 'Could not load household')}\n onRetry={() => refetch()}\n />\n </div>\n ) : !household ? (\n <div className=\"p-6\">\n <EmptyState\n icon={<Users className=\"size-6\" aria-hidden=\"true\" />}\n title={tr('brainyrich.households.detail.missing', 'Household not found')}\n />\n </div>\n ) : (\n <div className=\"space-y-5 p-6\">\n <SheetHeader className=\"space-y-2 p-0 text-left\">\n <SheetTitle className=\"text-xl\">{household.name}</SheetTitle>\n <SheetDescription className=\"sr-only\">\n {tr('brainyrich.households.detail.subtitle', 'Household overview')}\n </SheetDescription>\n <div className=\"flex flex-wrap items-center gap-2 pt-1\">\n <Badge variant={statusBadgeVariant(household.status)}>{household.status}</Badge>\n <Badge variant=\"secondary\">{household.riskProfile}</Badge>\n </div>\n </SheetHeader>\n\n {/* Hero — AUM + primary contact on a glass surface with emerald glow */}\n <GlassCard glow>\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <p className=\"text-xs uppercase tracking-wide text-text-secondary\">\n {tr('brainyrich.households.detail.aum', 'AUM')}\n </p>\n <p className=\"mt-1 text-3xl font-semibold tracking-tight text-text-primary\">\n {formatMoney(household.aum, household.currency)}\n </p>\n <p className=\"mt-1 text-xs text-text-secondary\">{household.currency}</p>\n </div>\n <div className=\"sm:text-right\">\n <p className=\"text-xs uppercase tracking-wide text-text-secondary\">\n {tr('brainyrich.households.detail.contact', 'Primary contact')}\n </p>\n <p className=\"mt-1 text-base font-medium text-text-primary\">\n {household.primaryContactName ?? '—'}\n </p>\n {household.primaryContactEmail ? (\n <a\n href={`mailto:${household.primaryContactEmail}`}\n className=\"mt-0.5 inline-flex items-center gap-1 text-xs text-text-secondary hover:text-[var(--color-action-primary-text)] sm:justify-end\"\n >\n <Mail className=\"size-3\" aria-hidden=\"true\" />\n {household.primaryContactEmail}\n </a>\n ) : null}\n </div>\n </div>\n </GlassCard>\n\n {/* Portfolio counts */}\n <div className=\"grid grid-cols-3 gap-3\">\n <SummaryTile\n icon={<Wallet className=\"size-4\" aria-hidden=\"true\" />}\n label={tr('brainyrich.households.detail.accounts', 'Accounts')}\n value={String(accounts.length)}\n />\n <SummaryTile\n icon={<Briefcase className=\"size-4\" aria-hidden=\"true\" />}\n label={tr('brainyrich.households.detail.portfolios', 'Portfolios')}\n value={String(portfolios.length)}\n />\n <SummaryTile\n icon={<Target className=\"size-4\" aria-hidden=\"true\" />}\n label={tr('brainyrich.households.detail.goals', 'Goals')}\n value={String(goals.length)}\n />\n </div>\n\n {household.tags.length > 0 ? (\n <div className=\"flex flex-wrap gap-1\">\n {household.tags.map((tag) => (\n <Badge key={tag} variant=\"outline\">\n {tag}\n </Badge>\n ))}\n </div>\n ) : null}\n\n <Tabs defaultValue=\"overview\" className=\"w-full\">\n <TabsList className=\"w-full justify-start overflow-x-auto\">\n <TabsTrigger value=\"overview\">\n {tr('brainyrich.households.tab.overview', 'Overview')}\n </TabsTrigger>\n <TabsTrigger value=\"accounts\">\n {tr('brainyrich.households.detail.accounts', 'Accounts')}\n </TabsTrigger>\n <TabsTrigger value=\"goals\">\n {tr('brainyrich.households.detail.goals', 'Goals')}\n </TabsTrigger>\n <TabsTrigger value=\"documents\">\n {tr('brainyrich.households.detail.documents', 'Documents')}\n </TabsTrigger>\n <TabsTrigger value=\"discussion\">\n {tr('brainyrich.households.detail.discussion', 'Discussion')}\n </TabsTrigger>\n </TabsList>\n\n {/* Overview */}\n <TabsContent value=\"overview\" className=\"mt-4 space-y-4\">\n {allocDonut.length > 0 ? (\n <Card>\n <CardContent className=\"p-4\">\n <h3 className=\"mb-3 text-sm font-medium text-text-primary\">\n {tr('brainyrich.households.detail.allocation', 'Where assets sit')}\n </h3>\n <DonutChart\n data={allocDonut}\n centerValue={formatCompact(invested, household.currency)}\n centerLabel={tr('brainyrich.households.detail.invested', 'Invested')}\n height={200}\n valueFormatter={(v) => formatMoney(v, household.currency)}\n />\n </CardContent>\n </Card>\n ) : null}\n\n <Card>\n <CardContent className=\"space-y-3 p-4 text-sm\">\n <div className=\"flex items-center justify-between gap-4\">\n <span className=\"text-text-secondary\">\n {tr('brainyrich.households.detail.advisor', 'Advisor')}\n </span>\n <span className=\"text-right font-medium text-text-primary\">\n {household.advisorId ? (\n <ActorName id={household.advisorId} />\n ) : (\n tr('brainyrich.common.unassigned', 'Unassigned')\n )}\n </span>\n </div>\n <Separator />\n <DetailRow\n label={tr('brainyrich.households.detail.created', 'Created')}\n value={formatDate(household.createdAt)}\n />\n <DetailRow\n label={tr('brainyrich.households.detail.updated', 'Last updated')}\n value={formatDate(household.updatedAt)}\n />\n </CardContent>\n </Card>\n\n {household.notes ? (\n <Card>\n <CardContent className=\"space-y-1 p-4\">\n <p className=\"text-xs font-medium uppercase tracking-wide text-text-secondary\">\n {tr('brainyrich.households.detail.summary', 'Summary')}\n </p>\n <p className=\"text-sm text-text-primary\">{household.notes}</p>\n </CardContent>\n </Card>\n ) : null}\n </TabsContent>\n\n {/* Accounts */}\n <TabsContent value=\"accounts\" className=\"mt-4 space-y-2\">\n {accountRows.length === 0 ? (\n <EmptyState\n icon={<Wallet className=\"size-6\" aria-hidden=\"true\" />}\n title={tr('brainyrich.households.detail.noAccounts', 'No accounts linked')}\n />\n ) : (\n accountRows.map(({ account, value }) => (\n <div\n key={account.id}\n className=\"flex items-center justify-between gap-3 rounded-lg border border-border-subtle bg-bg-surface p-3 transition-colors hover:border-[var(--color-action-primary-border)]\"\n >\n <div className=\"min-w-0\">\n <p className=\"truncate text-sm font-medium text-text-primary\">\n {account.name}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {account.institution ?? account.type}\n {account.accountMask ? ` ·••${account.accountMask}` : ''}\n </p>\n </div>\n <span className=\"shrink-0 text-sm font-semibold tabular-nums text-status-success-text\">\n {formatMoney(value, account.currency)}\n </span>\n </div>\n ))\n )}\n </TabsContent>\n\n {/* Goals */}\n <TabsContent value=\"goals\" className=\"mt-4 space-y-2\">\n {goals.length === 0 ? (\n <EmptyState\n icon={<Target className=\"size-6\" aria-hidden=\"true\" />}\n title={tr('brainyrich.households.detail.noGoals', 'No goals set')}\n />\n ) : (\n goals.map((g: BraGoal) => (\n <div\n key={g.id}\n className=\"flex items-center justify-between gap-3 rounded-lg border border-border-subtle bg-bg-surface p-3\"\n >\n <div className=\"min-w-0\">\n <p className=\"truncate text-sm font-medium text-text-primary\">{g.name}</p>\n <p className=\"text-xs text-text-secondary\">\n {tr('brainyrich.households.detail.goalTarget', 'Target')}{' '}\n {formatMoney(g.targetAmount, g.currency)} · {formatDate(g.targetDate)}\n </p>\n </div>\n <Badge variant={statusBadgeVariant(g.projection)} className=\"shrink-0\">\n {g.projection.replace(/_/g, ' ')}\n </Badge>\n </div>\n ))\n )}\n </TabsContent>\n\n {/* Documents */}\n <TabsContent value=\"documents\" className=\"mt-4\">\n <DocumentsPanel\n entityType=\"brainyrich-household\"\n entityId={household.id}\n heading={tr('brainyrich.households.detail.documents', 'Documents')}\n />\n </TabsContent>\n\n {/* Discussion */}\n <TabsContent value=\"discussion\" className=\"mt-4\">\n <CommentThread\n entityType=\"brainyrich-household\"\n entityId={household.id}\n heading={tr('brainyrich.households.detail.discussion', 'Discussion')}\n />\n </TabsContent>\n </Tabs>\n\n <Button variant=\"outline\" className=\"w-full\" onClick={() => onEdit(household)}>\n <Pencil className=\"size-4\" aria-hidden=\"true\" />\n {tr('brainyrich.households.action.edit', 'Edit')}\n </Button>\n </div>\n )}\n </SheetContent>\n </Sheet>\n );\n}\n\nfunction SummaryTile({ icon, label, value }: { icon: ReactNode; label: string; value: string }) {\n return (\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-3 text-center transition-shadow motion-safe:hover:shadow-[var(--shadow-pop-hover,var(--shadow-elevation-2))]\">\n <div className=\"mx-auto mb-1 flex size-8 items-center justify-center rounded-full bg-bg-sunken text-text-secondary\">\n {icon}\n </div>\n <p className=\"text-lg font-semibold text-text-primary\">{value}</p>\n <p className=\"text-xs text-text-secondary\">{label}</p>\n </div>\n );\n}\n\nfunction DetailRow({ label, value }: { label: string; value: string }) {\n return (\n <div className=\"flex items-center justify-between gap-4\">\n <span className=\"text-text-secondary\">{label}</span>\n <span className=\"text-right font-medium text-text-primary\">{value}</span>\n </div>\n );\n}\n"],"mappings":"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"}
|