Skip to content

feat: add treasury portfolio page#32

Merged
ECWireless merged 2 commits into
mainfrom
codex/portfolio-page
Jul 3, 2026
Merged

feat: add treasury portfolio page#32
ECWireless merged 2 commits into
mainfrom
codex/portfolio-page

Conversation

@ECWireless

@ECWireless ECWireless commented Jul 2, 2026

Copy link
Copy Markdown
Member

This pull request introduces a new reusable DashboardBackLink component and refactors all major dashboard subpages to use it for consistent navigation back to the main dashboard. It also makes several improvements to the mobile and desktop table layouts for better readability and alignment, and updates documentation to clarify the product scope and architecture. Additionally, a new "Portfolio" link is added to the main navigation. The most important changes are grouped and summarized below:

Navigation and Component Reuse

  • Introduced a new DashboardBackLink component for consistent "Back to Dashboard" navigation and refactored all relevant pages (proposals, reports, rips, membership, admin/providers, admin/quarters, admin/treasury-accounts, raids) to use it instead of duplicating link code. This improves maintainability and UI consistency. [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] [16] [17]

UI/UX Improvements

  • Improved mobile and desktop table layouts by adjusting grid gaps, column widths, padding, and line heights for .mobile-card-table and .mobile-card-table-lg classes in globals.css. This results in better readability and alignment across devices. [1] [2] [3] [4]
  • Added CSS tweaks for anchor padding inside table cells and for portfolio asset tables to improve touch targets and visual consistency. [1] [2]
  • Ensured all direct children of .container-custom have min-width: 0 to prevent layout overflow issues.

Navigation Structure

  • Added a "Portfolio" link to the main DAO navigation in app-header, making it easier for users to access the portfolio view.

Documentation

  • Expanded the README.md to include detailed product scope, architecture, and permissions sections, clarifying the app's purpose, structure, and security practices.

Minor UI Cleanups

  • Removed unnecessary margin classes from status message divs in the rips page for more consistent spacing.

Summary by CodeRabbit

  • New Features
    • Added a Treasury Portfolio page with allocation summaries, asset breakdown, and rebalance guidance.
    • Added a visual allocation chart with tooltips.
    • Introduced consistent “Back to Dashboard” navigation across multiple pages and added Portfolio to the main navigation.
  • Bug Fixes
    • Improved mobile responsive table layout (spacing, sizing, and typography) to reduce overflow and improve readability.
  • Documentation
    • Updated README with Product Scope, Architecture, and Permissions; removed the old project-spec document.
  • Tests
    • Added responsive e2e coverage for the Portfolio page.

Copilot AI review requested due to automatic review settings July 2, 2026 22:08
@vercel

vercel Bot commented Jul 2, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
raidguild-accounting Ready Ready Preview, Comment Jul 3, 2026 12:06am

Request Review

@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2b6308b5-8761-4ba2-8d09-ce23581a9b1c

📥 Commits

Reviewing files that changed from the base of the PR and between 0c67730 and e27569a.

📒 Files selected for processing (4)
  • src/app/globals.css
  • src/app/portfolio/page.tsx
  • src/components/portfolio/asset-allocation-chart.tsx
  • src/lib/portfolio/formatters.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/app/globals.css
  • src/components/portfolio/asset-allocation-chart.tsx
  • src/app/portfolio/page.tsx

📝 Walkthrough

Walkthrough

This PR adds a new /portfolio page with treasury allocation calculations, charting, and access gating; introduces a reusable dashboard back-link component across existing pages; and updates navigation, README content, responsive table styling, and e2e coverage.

Changes

Treasury Portfolio Feature

Layer / File(s) Summary
Portfolio data and formatting
src/app/portfolio/page.tsx, src/lib/portfolio/formatters.ts
Defines formatter helpers, local row types, stable allocation math, account aggregation, and snapshot fallback loading.
Portfolio page rendering
src/app/portfolio/page.tsx
Adds the access gate, allocation/status cards, asset table, account breakdown, and the server page render.
Asset allocation chart
src/components/portfolio/asset-allocation-chart.tsx
Adds the client-side pie chart with tooltip behavior and legend rendering.
Portfolio navigation and test coverage
src/components/app-header.tsx, src/components/treasury/treasury-dashboard.tsx, tests/e2e/responsive-dashboard.spec.ts
Adds portfolio navigation links and responsive e2e coverage for the new route.

Dashboard Back Link Rollout

Layer / File(s) Summary
Back-link component
src/components/dashboard-back-link.tsx
Creates a reusable link back to / with an arrow icon and dashboard label.
Back-link wiring
src/app/admin/providers/page.tsx, src/app/admin/quarters/page.tsx, src/app/admin/treasury-accounts/page.tsx, src/app/membership/page.tsx, src/app/proposals/page.tsx, src/app/raids/page.tsx, src/app/reports/page.tsx, src/app/rips/page.tsx
Renders the new back-link across multiple page layouts and updates spacing where needed.

Docs and Mobile Table Styling

Layer / File(s) Summary
README updates
README.md
Reworks the README introduction into product scope, architecture, and permissions sections.
Mobile table CSS
src/app/globals.css
Tightens responsive table spacing, widths, leading, and link padding for mobile card tables and portfolio asset tables.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant PortfolioPage
  participant AuthSession
  participant TreasurySnapshot
  User->>PortfolioPage: request /portfolio
  PortfolioPage->>AuthSession: serialize session and check permissions
  AuthSession-->>PortfolioPage: session state
  PortfolioPage->>TreasurySnapshot: getTreasuryBalanceSnapshot()
  TreasurySnapshot-->>PortfolioPage: snapshot or failure state
  PortfolioPage-->>User: render access gate or portfolio dashboard
Loading

Possibly related PRs

  • raid-guild/accounting#3: The new /portfolio page uses the auth session and role checks introduced by the wallet-auth and permissions work.
  • raid-guild/accounting#5: The portfolio page and treasury dashboard link both build on the treasury snapshot and dashboard rendering work from this PR.
  • raid-guild/accounting#31: This PR changes the same responsive mobile table CSS used by the dashboard tables.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: adding a treasury portfolio page.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/portfolio-page

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new member-only Treasury Portfolio page and wires it into the existing dashboard experience, while also standardizing “back to dashboard” navigation across major subpages and tightening responsive table layouts.

Changes:

  • Added a new /portfolio page with allocation, rebalance guidance, asset/account breakdowns, and an interactive allocation chart.
  • Introduced a reusable DashboardBackLink component and refactored multiple dashboard subpages to use it.
  • Updated responsive table CSS + added E2E coverage for the new portfolio route and overflow at a narrow viewport; expanded README and removed the old project spec doc.

Reviewed changes

Copilot reviewed 17 out of 17 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
tests/e2e/responsive-dashboard.spec.ts Adds /portfolio to smoke checks and a 350px overflow regression test.
src/components/treasury/treasury-dashboard.tsx Adds a “View Portfolio” CTA linking to /portfolio.
src/components/portfolio/asset-allocation-chart.tsx New interactive pie chart + legend for allocation breakdown.
src/components/dashboard-back-link.tsx New reusable “Dashboard” back-link component.
src/components/app-header.tsx Adds “Portfolio” to the main DAO navigation links.
src/app/rips/page.tsx Uses DashboardBackLink and adjusts layout spacing.
src/app/reports/page.tsx Uses DashboardBackLink for consistent navigation.
src/app/raids/page.tsx Uses DashboardBackLink for consistent navigation.
src/app/proposals/page.tsx Uses DashboardBackLink for consistent navigation.
src/app/portfolio/page.tsx New server-rendered portfolio page with allocation/rebalance logic and tables.
src/app/membership/page.tsx Uses DashboardBackLink for consistent navigation.
src/app/globals.css Tweaks responsive table grid spacing and adds overflow-prevention styling.
src/app/admin/treasury-accounts/page.tsx Uses DashboardBackLink for consistent navigation.
src/app/admin/quarters/page.tsx Uses DashboardBackLink for consistent navigation.
src/app/admin/providers/page.tsx Uses DashboardBackLink for consistent navigation.
README.md Expands product scope/architecture/permissions documentation.
PROJECT_SPEC.md Removes the previous project spec document.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/app/portfolio/page.tsx
Comment thread src/app/portfolio/page.tsx
Comment thread src/components/portfolio/asset-allocation-chart.tsx Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/app/globals.css (1)

328-331: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Avoid stacking padding on mobile-card-table-lg link cells
.mobile-card-table-lg td, th adds lg:px-4 lg:py-3, and direct a.block cells add another lg:px-3 lg:py-3 on top. That makes those cells noticeably larger than the rest of the table; drop one layer if that isn’t intentional.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/globals.css` around lines 328 - 331, The `mobile-card-table-lg` table
cells are stacking padding between the shared `td, th` rule and the direct
`a.block` cell styles, making link cells larger than the rest. Update the
padding in `globals.css` so the `mobile-card-table-lg` link cells only use one
padding layer, adjusting either the shared `mobile-card-table-lg td, th` rule or
the direct `a.block` rule to keep spacing consistent.
🧹 Nitpick comments (3)
src/app/portfolio/page.tsx (1)

63-84: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate formatting helpers across files.

formatCurrency and formatPercent here are near-identical to the implementations in src/components/portfolio/asset-allocation-chart.tsx (lines 20-34). Consider extracting to a shared util module to avoid drift if formatting rules change later.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/portfolio/page.tsx` around lines 63 - 84, `formatCurrency` and
`formatPercent` in `src/app/portfolio/page.tsx` duplicate the same formatting
logic used in `asset-allocation-chart.tsx`, so extract the shared
number-formatting helpers into a common utility module and have both `page.tsx`
and `AssetAllocationChart` import them. Keep the existing behavior intact while
centralizing the implementations to prevent drift if formatting rules change
later.
src/components/portfolio/asset-allocation-chart.tsx (1)

105-167: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Mutating outer cursor variable during render map is fragile.

cursor is incrementally mutated as a side effect inside .map, relying on Array.prototype.map's guaranteed sequential execution order. This works correctly today but is an unusual pattern for a render function; using reduce to carry cumulative angle state would be clearer and safer against future refactors (e.g., someone reordering/parallelizing the map).

♻️ Possible refactor sketch
-  const visibleRows = rows.filter((row) => row.usdValue > 0);
-  let cursor = 0;
+  const visibleRows = rows.filter((row) => row.usdValue > 0);
+  const slices = visibleRows.reduce<{ cursor: number; items: Array<{ row: AssetAllocationChartRow; startAngle: number; endAngle: number }> }>(
+    (acc, row) => {
+      const startAngle = acc.cursor;
+      const endAngle = startAngle + row.percent * 3.6;
+      acc.items.push({ row, startAngle, endAngle });
+      acc.cursor = endAngle;
+      return acc;
+    },
+    { cursor: 0, items: [] },
+  ).items;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/portfolio/asset-allocation-chart.tsx` around lines 105 - 167,
The render logic in asset-allocation-chart.tsx mutates the outer cursor variable
inside the visibleRows.map loop, which is fragile and harder to maintain.
Refactor the pie-slice rendering in the AssetAllocationChart component to carry
cumulative angle state explicitly instead of side effects, ideally by using
reduce or a precomputed accumulator before rendering each slice. Keep the
existing behavior for getPieSlicePath, getTooltipPosition, and the
row.key/tooltip handlers intact while removing the cursor mutation from the
render path.
src/app/globals.css (1)

226-229: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Broad min-width: 0 on all .container-custom children.

This applies to every direct child regardless of layout context (flex/grid/block), which could unintentionally shrink intrinsic-sized elements that aren't participating in a flex/grid overflow scenario. Given the stated intent is overflow protection, this is likely acceptable, but consider scoping it to flex/grid containers if unintended shrinking of unrelated children surfaces.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/globals.css` around lines 226 - 229, The `.container-custom > *`
selector applies `min-width: 0` to every direct child, which can unintentionally
affect non-flex/grid content. Update the rule in `globals.css` so the
overflow-protection behavior is scoped only to the flex/grid contexts that need
it, using the `.container-custom` selector and its relevant child/layout
wrappers rather than all direct children.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/app/portfolio/page.tsx`:
- Around line 125-127: The `isOutOfRange` logic in `page.tsx` treats a zero
`safeTotalUsd` as “within tolerance,” which makes `AllocationFlag` show a
healthy state while balances are unavailable. Update the allocation state
calculation so `safeTotalUsd === 0` is handled as an unavailable/loading case
rather than falling through to `false`, and keep the
`AllocationFlag`/`rebalanceCopy` messaging consistent with that state.
- Around line 129-142: The rebalance message in portfolio/page.tsx hardcodes
wETH even though the non-stable bucket is derived from `otherUsd` and may
include any non-stable asset. Update the `rebalanceCopy` logic to reference the
actual asset(s) represented by the non-stable holdings instead of a fixed token
name, using the existing portfolio data/model in this component to determine the
label. Keep the `rebalanceCopy` branches inside the same rebalance calculation
flow, but make the buy/sell text dynamic so it accurately reflects what the
treasury actually holds.

---

Outside diff comments:
In `@src/app/globals.css`:
- Around line 328-331: The `mobile-card-table-lg` table cells are stacking
padding between the shared `td, th` rule and the direct `a.block` cell styles,
making link cells larger than the rest. Update the padding in `globals.css` so
the `mobile-card-table-lg` link cells only use one padding layer, adjusting
either the shared `mobile-card-table-lg td, th` rule or the direct `a.block`
rule to keep spacing consistent.

---

Nitpick comments:
In `@src/app/globals.css`:
- Around line 226-229: The `.container-custom > *` selector applies `min-width:
0` to every direct child, which can unintentionally affect non-flex/grid
content. Update the rule in `globals.css` so the overflow-protection behavior is
scoped only to the flex/grid contexts that need it, using the
`.container-custom` selector and its relevant child/layout wrappers rather than
all direct children.

In `@src/app/portfolio/page.tsx`:
- Around line 63-84: `formatCurrency` and `formatPercent` in
`src/app/portfolio/page.tsx` duplicate the same formatting logic used in
`asset-allocation-chart.tsx`, so extract the shared number-formatting helpers
into a common utility module and have both `page.tsx` and `AssetAllocationChart`
import them. Keep the existing behavior intact while centralizing the
implementations to prevent drift if formatting rules change later.

In `@src/components/portfolio/asset-allocation-chart.tsx`:
- Around line 105-167: The render logic in asset-allocation-chart.tsx mutates
the outer cursor variable inside the visibleRows.map loop, which is fragile and
harder to maintain. Refactor the pie-slice rendering in the AssetAllocationChart
component to carry cumulative angle state explicitly instead of side effects,
ideally by using reduce or a precomputed accumulator before rendering each
slice. Keep the existing behavior for getPieSlicePath, getTooltipPosition, and
the row.key/tooltip handlers intact while removing the cursor mutation from the
render path.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 36792112-facf-4dc0-bfc3-a2959ab1ccc2

📥 Commits

Reviewing files that changed from the base of the PR and between df5a25d and 0c67730.

📒 Files selected for processing (17)
  • PROJECT_SPEC.md
  • README.md
  • src/app/admin/providers/page.tsx
  • src/app/admin/quarters/page.tsx
  • src/app/admin/treasury-accounts/page.tsx
  • src/app/globals.css
  • src/app/membership/page.tsx
  • src/app/portfolio/page.tsx
  • src/app/proposals/page.tsx
  • src/app/raids/page.tsx
  • src/app/reports/page.tsx
  • src/app/rips/page.tsx
  • src/components/app-header.tsx
  • src/components/dashboard-back-link.tsx
  • src/components/portfolio/asset-allocation-chart.tsx
  • src/components/treasury/treasury-dashboard.tsx
  • tests/e2e/responsive-dashboard.spec.ts
💤 Files with no reviewable changes (1)
  • PROJECT_SPEC.md

Comment thread src/app/portfolio/page.tsx
Comment thread src/app/portfolio/page.tsx
@ECWireless

Copy link
Copy Markdown
Member Author

Review follow-up posted after e27569a:

  • Fixed the zero-balance allocation state so unavailable treasury data no longer appears as within tolerance.
  • Fixed the chart legend to match the visible non-zero allocation slices.
  • Fixed the outside-diff table link padding issue for mobile card tables.
  • Extracted shared portfolio currency and percent formatters.
  • Removed render-time cursor mutation in the chart and rounded SVG coordinates to avoid hydration mismatches.
  • Narrowed the broad container-custom min-width rule to flex and grid containers.

Validation: pnpm lint, pnpm build, pnpm test:e2e --grep responsive dashboard smoke|350px, and git diff --check all passed locally before the commit.

@ECWireless ECWireless merged commit abff5cb into main Jul 3, 2026
3 checks passed
@ECWireless ECWireless deleted the codex/portfolio-page branch July 3, 2026 00:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants