Skip to content

feat(ui): Step 8 slice C — Portfolio + Radar parity (search, cards, anchors)#84

Merged
fleveque merged 2 commits into
mainfrom
feat/step8-portfolio-radar
Jun 12, 2026
Merged

feat(ui): Step 8 slice C — Portfolio + Radar parity (search, cards, anchors)#84
fleveque merged 2 commits into
mainfrom
feat/step8-portfolio-radar

Conversation

@fleveque

Copy link
Copy Markdown
Owner

Step 8 slice C — the Portfolio and Radar pages reach legacy parity

Companion: yahoo_finance_ex#6 (merged, v0.4.0 publishedsearch/2).

Search-first add flow (← legacy's search → results → add)

  • New Provider.search/1 callback; Yahoo adapter delegates to the package, AlphaVantage implements SYMBOL_SEARCH (types normalized to the shared vocabulary).
  • MarketData.search_stocks/1 ports legacy's merge semantics: local stock rows first (in_db: true), provider matches filtered to EQUITY/ETF/MUTUALFUND (Spanish dividend funds are mutual funds — legacy's rationale), deduped by symbol, capped at 10. Provider errors degrade to DB-only — search never errors at the user.
  • Radar: one-click add with an "On radar" state. Portfolio: the Add button expands into an inline shares/avg-cost form per result.

Cards + compact views (← RadarStockCard / PortfolioStockCard)

  • Card/compact toggle persisted per browser (colocated hook + localStorage, legacy parity); portfolio adds the persisted sort dropdown (market value / gain / gain % / symbol). Radar sorts opportunity-first (pulse's grid order).
  • Cards carry the full legacy payload: dividend-score badge, PER/EPS/Div/Yield/Payout/MA50/MA200 metrics, payment-month grid (shifted months amber), 52-week range bar, ex-div badge (amber ≤ 3 days), status-colored borders + "% below/above target" badges, gain/loss coloring.
  • Compact rows expand: a chevron expands the row into the full card inside the table — keeps legacy's "see everything from compact view" function in a cleaner form than its metric-columns toggle.

Target-price anchors (← TargetPriceAnchorsMenu)

One-click suggested buy targets next to the target price: community average (new Community.community_targets/0, published only with a ≥3-target cohort — same privacy rule as the dashboard), 52-week midpoint, MA200, MA50. Disabled rows explain why (e.g. "Needs 3+ community targets (1 so far)").

Sectors now translate

translate_sector/1 + a dedicated sectors gettext domain (18 provider sector names × 6 locales), applied to every sector bar (public pages, community dashboard, home, portfolio) and the buy-plan "underowned" badge.

Noted deviations (status.md)

  • Held stocks show a disabled "In portfolio" in search results instead of legacy's add-more form — the buy-plan checkout owns position merging.
  • Legacy's DividendCalendar (both pages) deferred to slice D, where the dividend-schedule data work lives.

Test plan

  • mix precommit green — 365 tests (radar/portfolio LiveView suites rewritten for the search-first flow + view toggle + expand; new context tests: search merge/filter/degrade, community-targets cohort gating).
  • Manual via demo mode + puppeteer screenshots: desktop and 390px mobile, card and compact views, expanded rows, dark scheme. Caught and fixed a real crash this way (UUID ids vs String.to_integer).

🤖 Generated with Claude Code

fleveque and others added 2 commits June 12, 2026 22:49
…nchors)

Both pages rebuilt around legacy's card-first design:

- yahoo_finance_ex v0.4 (search/2) consumed; Provider behaviour gains a
  search callback (Yahoo + AlphaVantage SYMBOL_SEARCH adapters);
  MarketData.search_stocks/1 ports legacy merge semantics (DB rows
  first, EQUITY/ETF/MUTUALFUND filter, dedupe, cap 10, errors degrade
  to DB-only).
- Search-first add flow: debounced async search -> results grid; radar
  one-click add, portfolio inline shares/cost form per result.
- Card/compact views with localStorage-persisted toggle; portfolio
  sort dropdown (market value/gain/gain%/symbol, persisted); radar
  sorted opportunity-first.
- Cards: score badge, metrics grid, payment-month grid, 52-week range
  bar, ex-div badge, status borders/badges, gain/loss coloring.
- Target-price anchors menu: community average (Community.
  community_targets/0, >=3 cohort), 52w midpoint, MA200, MA50 —
  one-click apply.
- Compact rows expand into the full card (improvement over legacy's
  metric-columns toggle, same function).
- Sector names translate via a new sectors gettext domain (18 names
  x6 locales), applied to all sector bars + the buy-plan badge.
- ~80 new strings translated x6.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Reworks the compact (list) view to legacy's responsive row-cards and
fixes a batch of issues found in review:

- Compact view is now a stack of status-bordered row-cards (not an HTML
  table): aligned columns on desktop with a global metrics Expand/
  Collapse toggle (persisted), a condensed tap-to-expand list on mobile
  (pure client-side JS, scrolls with the page). Replaces the per-row
  'expand into full card' interaction.
- Metrics-expanded desktop drops the Name column (ticker carries the
  name as a hover title) so columns never collapse/overlap; month grid
  uses the small size + wider column so it no longer overlaps Payout.
- Score badge moved to the end of the symbol line (truncates the ticker
  instead of wrapping the badge under it).
- Portfolio header: total gain/loss (amount + %) and per-currency
  subtotals with FX rate (Portfolio.valuation now exposes
  total_cost_in_preferred + by_currency); totals wrapped in a bordered
  panel so they don't float.
- Target-anchors menu: anchored to the card (absolute, scrolls with the
  page), width-capped so it can't clip off a mobile edge, with a close
  button + click-away backdrop. Cards/rows lost overflow-hidden so the
  menu isn't clipped.
- Sector names already translate via the sectors gettext domain.

New strings (AI/Edit/Remove/Schedule/Value/Expand/Collapse/Tap-a-row)
translated x6.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@fleveque fleveque merged commit 70f312b into main Jun 12, 2026
1 check passed
@fleveque fleveque deleted the feat/step8-portfolio-radar branch June 12, 2026 22:00
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.

1 participant