Skip to content

Build the position card and the request list - #115

Merged
luchobonatti merged 13 commits into
mainfrom
feat/111-position-and-request-cards
Sep 16, 2026
Merged

luchobonatti merged 13 commits into
mainfrom
feat/111-position-and-request-cards

Conversation

@luchobonatti

@luchobonatti luchobonatti commented Sep 14, 2026

Copy link
Copy Markdown
Member

Summary

Closes #111

Every request card shows the same four things in the same places: in, out, state, action. The list is scanned down a column.

Changes

  • The position card renders a holding, with a dash when the figure could not be read
  • Every request card renders the same four-part spine
  • Longer explanation opens in a tooltip on click
  • The request list renders its entries in order
  • The lifecycle panel takes any number of steps
  • The vault page is the only route

Acceptance criteria

  • The position card renders a label, a figure, a sub-line, and a note that can be absent
  • Every request card renders the same four parts in the same positions
  • Only the middle part changes meaning
  • An action can be present but unavailable
  • Longer explanation lives in a tooltip that opens on click
  • No batch number reaches the investor
  • The request list renders its entries in the order given
  • The list says so when there are no entries
  • The lifecycle panel takes as many steps as it is given
  • Nothing holds state, and nothing calls a contract
  • Every card lays out from its own width, not the window's

Test plan

  1. npm run test, lint, format:check, build --workspaces --if-present: pass.
  2. npm run dev, open /. Read the list down the state column.
  3. Click the tooltip on the card that cannot be claimed.
  4. Narrow a card under 560px. Its four parts stack.

Breaking changes

None.

Checklist

  • Self-reviewed my own diff
  • Tests added or updated
  • Docs updated (if applicable)
  • No unrelated changes bundled in

Copilot AI lite review requested due to automatic review settings September 14, 2026 13:00
@vercel

vercel Bot commented Sep 14, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated
strata-vault-kit-app Ready Ready Preview Sep 16, 2026 2:06pm UTC

Request Review

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

There are React rendering/accessibility issues in the new components (non-unique list keys and heading level semantics) that should be corrected before approval.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

Builds out the investor-facing “position + requests” surface in the vault preview UI by introducing reusable, prop-driven components for positions, request cards, request grouping, and a now variable-length lifecycle panel (per #111, with the lifecycle panel adaptation noted as a deviation from #100).

Changes:

  • Added PositionCard, RequestCard, and RequestList components (with styling) to render holdings and grouped request entries purely from props.
  • Updated LifecyclePanel to accept any number of steps (and adjusted layout to stack via container queries).
  • Extended the preview page to showcase the new components with representative data and states.
File summaries
File Description
app/src/pages/VaultPreview.tsx Updates the preview page to render the new position/request surfaces and the updated lifecycle panel.
app/src/components/vault/RequestList.tsx Introduces grouped request list rendering with optional banner and empty-state handling.
app/src/components/vault/RequestList.test.tsx Adds tests for banner conditional rendering and skipping empty groups.
app/src/components/vault/RequestList.module.css Styles the request list container, banner, and group layout.
app/src/components/vault/RequestCard.tsx Adds a request card component supporting rows, optional coverage block, notes, footers, and actions.
app/src/components/vault/RequestCard.test.tsx Tests unavailable actions and nested coverage block rendering.
app/src/components/vault/RequestCard.module.css Styles request cards, state chips, rows, coverage inset, and action buttons.
app/src/components/vault/PositionCard.tsx Adds a position/holding card with “unread” (em dash) rendering and optional note.
app/src/components/vault/PositionCard.test.tsx Tests the em dash behavior when the value is unread (null).
app/src/components/vault/PositionCard.module.css Styles the position card layout, figure, and muted text.
app/src/components/vault/LifecyclePanel.tsx Generalizes lifecycle steps to variable length and adds a “complete” state option.
app/src/components/vault/LifecyclePanel.test.tsx Extends tests for out-of-range currentStep behavior.
app/src/components/vault/LifecyclePanel.module.css Updates layout to variable columns and adds container-query-based stacking rules.
Review details

Suppressed comments (3)

app/src/components/vault/RequestCard.tsx:114

  • RequestCard uses action.label as a React key, but labels are not guaranteed unique (e.g., multiple actions with the same copy). Duplicate keys can break reconciliation; include the index (or add a dedicated id) to guarantee uniqueness.
			{entry.actions.map((action) => (
				<button
					key={action.label}

app/src/components/vault/RequestCard.tsx:97

  • RequestCard coverage rows also use row.label as a React key, which can collide if two coverage rows share a label. Use an index (or a row id) to ensure keys are unique.
				{entry.coverage.rows.map((row) => (
					<div className={styles.row} key={row.label}>

app/src/components/vault/RequestList.tsx:57

  • React list keys should be unique and stable; using group.heading as the key can collide if two groups share the same heading, leading to incorrect reconciliation. Include the index (or add a dedicated id field) to guarantee uniqueness.
				groups.map((group) =>
					group.entries.length > 0 ? (
						<div className={styles.group} key={group.heading}>
  • Files reviewed: 13/13 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +80 to +81
{entry.rows.map((row) => (
<div className={styles.row} key={row.label}>

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Fixed in all three places. RequestRow.label is caller-supplied and nothing in the type stops two rows sharing one, so the key is now the index paired with the label.

No fixture produced a collision today, so this was latent rather than live — but the rows come from outside the component and the type offers no guarantee.

Comment thread app/src/components/vault/RequestList.tsx Outdated
@luchobonatti
luchobonatti added this pull request to stack #107 September 14, 2026 13:07
@luchobonatti
luchobonatti force-pushed the feat/111-position-and-request-cards branch from 4b4ca68 to b908fec Compare September 14, 2026 15:57
@luchobonatti
luchobonatti force-pushed the feat/111-position-and-request-cards branch from 6f3aa81 to e54e403 Compare September 14, 2026 20:02
@luchobonatti
luchobonatti force-pushed the feat/111-position-and-request-cards branch from e54e403 to bb18747 Compare September 14, 2026 20:37
Base automatically changed from feat/100-metrics-strip-and-lifecycle to main September 14, 2026 20:45
@luchobonatti
luchobonatti force-pushed the feat/111-position-and-request-cards branch from bb18747 to 09c7da1 Compare September 14, 2026 20:45
@luchobonatti
luchobonatti force-pushed the feat/111-position-and-request-cards branch 2 times, most recently from e54e403 to 2e9f6cd Compare September 15, 2026 12:54
@luchobonatti luchobonatti self-assigned this Sep 15, 2026
@luchobonatti
luchobonatti force-pushed the feat/111-position-and-request-cards branch from edacfe2 to aff24ec Compare September 16, 2026 14:06
@luchobonatti
luchobonatti merged commit 0337b33 into main Sep 16, 2026
3 checks passed
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.

Build the position card and the request list

3 participants