@get-asset/sdk

ProfitLossCard

Headless compound that fetches twelve month-by-month revenue and expense pairs for a fiscal year. The compound computes a nice scale automatically; override it to align bars across cards. The chart always shows 12 months — the AssetProvider's month is ignored.

Anatomy

Import the primitive and compose the parts you need.

<ProfitLossCard.Root year={2026}>
<ProfitLossCard.Success>
<ProfitLossCard.Period />
<ProfitLossCard.Months>
<ProfitLossCard.Month />
<ProfitLossCard.Revenue />
<ProfitLossCard.RevenueBar />
<ProfitLossCard.Expense />
<ProfitLossCard.ExpenseBar />
</ProfitLossCard.Months>
</ProfitLossCard.Success>
</ProfitLossCard.Root>

Required scopes

The access token used by AssetProvider must include these scopes for this primitive to fetch data successfully:

  • report:read
  • tag:read

API reference

Root props

PropTypeDefaultDescription
yearnumberFiscal year. Falls back to the AssetProvider's year. The chart always shows 12 months for the year (the provider's month is ignored).
monthsProfitLossMonthOverride[]Override fetched data. Each entry: { month, revenue, expense }.
scalenumberOverride the bar chart maximum.
tagFieldsTagFilterField[]Override the fetched tag filter fields ({ name, values }[]) — primarily for testing/storybook. Pass [] to hide the tag filter.
state"loading" | "error" | "empty"Force a specific state for testing.
lockedbooleanGate the report for an unentitled viewer. Activates the Locked state and skips the API fetch. See /docs/sdk/locked-upsell.
upsell{ title?, description?, ctaLabel?, onUpgrade? }Locked-state copy + upgrade handler; merged field-by-field over the card's default copy, then the generic fallback.
childrenrequiredReactNodeCompound parts.

Parts

Container

Always rendered. Provides data and context to its children.

PartDescription
ProfitLossCard.RootFetches monthly P&L (filtered to the selected tags) and the business's tag fields, and provides context.

Success

Renders when monthly data is available.

PartDescription
ProfitLossCard.SuccessState wrapper. Compose the chart inside.
ProfitLossCard.Period
asChild?
Renders the resolved period — defaults to MMM YYYY or YYYY. Pass format(year, month) to override.
ProfitLossCard.MonthsIterates children once per month.
ProfitLossCard.Month
asChild?
Short month label for the current iteration.
ProfitLossCard.Revenue
asChild?
Revenue value for the current month.
ProfitLossCard.Expense
asChild?
Expense value for the current month.
ProfitLossCard.RevenueBar
style?, className?
Proportional bar for the current month's revenue.
ProfitLossCard.ExpenseBar
style?, className?
Proportional bar for the current month's expense.

Loading

Renders while the fetch is in flight.

PartDescription
ProfitLossCard.LoadingState wrapper. Render any skeleton or placeholder UI inside.

Empty

Renders when all months are zero.

PartDescription
ProfitLossCard.EmptyState wrapper. Render an empty-state message inside.

Error

Renders on fetch error.

PartDescription
ProfitLossCard.ErrorState wrapper. Compose the error UI inside.
ProfitLossCard.ErrorMessage
asChild?
Renders the error message string.
ProfitLossCard.Retry
asChild?
Button that re-runs the fetch.

Locked

Renders when `locked` is set — the viewer isn't entitled to the report. Mutually exclusive with the other states, and no data is fetched. See the Locked / upsell guide for composing the teaser + upgrade UI.

PartDescription
ProfitLossCard.LockedState wrapper. Compose the upgrade / upsell UI inside — see LockedUpsell.

Unlocked

Renders whenever the card is NOT locked — the inverse of Locked.

PartDescription
ProfitLossCard.UnlockedState wrapper. Useful for gating extras (like the insights panel) that should also disappear while locked.

Hooks

PartDescription
useProfitLossCard()Hook returning months, scale, loading, error, locked, retry, tagFields, selectedTags, setSelectedTags, toggleTag. Selecting tags refetches the chart filtered to them.
useProfitLossMonth()Hook used inside a Months iteration; returns the current month.