@get-asset/sdk

Book Health

Headless compound answering “are my books healthy?” for one fiscal year of the business (twelve months from its fiscal-year start; calendar years when that is January): a fraction of months closed and verified (the denominator is always 12), a per-month tone for a twelve-month grid and meter, and the open tasks waiting on the business, grouped by category. Selecting a month filters the tasks to it; the in-scope list is handed to a nested Tasks compound, actions included. A year dropdown offers previous years back to the business's entries start, and hides when there are none — the component is deliberately decoupled from the AssetProvider's shared date range.

Anatomy

Import the primitive and compose the parts you need.

<BookHealth.Root>
<BookHealth.YearSelect>{/* a Select-Root-shaped child */}</BookHealth.YearSelect>
<BookHealth.Success>
<BookHealth.ReadyCount /> / <BookHealth.MonthCount />
<BookHealth.Months>
<BookHealth.MonthTone /> {/* meter segment */}
</BookHealth.Months>
<BookHealth.Months>
<BookHealth.MonthCell>
<BookHealth.MonthLabel />
<BookHealth.MonthTaskCount />
</BookHealth.MonthCell>
<BookHealth.MonthBreakdown>
<BookHealth.BreakdownLabel />
<BookHealth.BreakdownCount />
</BookHealth.MonthBreakdown>
<BookHealth.BreakdownTotal />
</BookHealth.Months>
<BookHealth.TasksLabel />
<BookHealth.TaskCount />
<BookHealth.ShowAllMonths />
<BookHealth.TasksEmpty>
<BookHealth.TasksEmptyMessage />
</BookHealth.TasksEmpty>
{/* The in-scope tasks render through the Tasks compound: */}
{/* <Tasks.Root tasks={tasks} onUpload={uploadTask} onAddNote={addTaskNote}> ... */}
</BookHealth.Success>
</BookHealth.Root>

Required scopes

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

  • business:read
  • request:read
  • plaid:create
  • document:create
  • journal_entry:read
  • journal_entry:create

API reference

Root props

PropTypeDefaultDescription
monthsBookHealthMonthData[]Override fetched months (skips every API fetch). Each entry is { month: 'YYYY-MM', status, tasks? } — tasks ride on their month.
entriesStartstringOverride the business's entries_start date (YYYY-MM-DD), which decides the fiscal years the picker offers. The picker hides when there are no previous years.
fiscalYearStartstringOverride the business's fiscal-year start anchor (MM/DD), which decides where each twelve-month window begins. Defaults to the business's fiscal_year; January when unknown. With entriesStart, providing it skips the business fetch.
state"loading" | "error" | "empty"Force a specific state for testing.
lockedbooleanGate the card for an unentitled viewer. Activates the Locked state and skips every 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.
onReviewTask(task: TasksTask) => voidHand a month-level review task off to your transactions page for its month; exposed on the context for the nested task list. The hand-off button is a no-op while unset.
childrenrequiredReactNodeCompound parts.

Parts

Container

Always rendered. Provides data and context to its children.

PartDescription
BookHealth.RootFetches the year's books status, the pending tasks, and the business (for the year-picker floor), and provides context.
BookHealth.Year
asChild?
The year on display, as text. Sets data-year.
BookHealth.YearSelectWires the year to a Select-Root-shaped child (injects value + onValueChange). Renders nothing when there are no previous years to switch to.
BookHealth.YearItemsIterates the selectable years (newest first) with per-year context.
BookHealth.YearItem
asChild?
Renders one selectable year. Injects value and the year's label.

Success

Renders when the year has data.

PartDescription
BookHealth.SuccessState wrapper. Compose the card's UI inside.
BookHealth.ReadyCount
asChild?, format?
Months closed and verified — the fraction's numerator.
BookHealth.MonthCount
asChild?, format?
The fraction's denominator: always 12.
BookHealth.MonthsIterates the twelve months in calendar order with per-month context. Compose it once for the month grid and again for the meter.
BookHealth.MonthCell
asChild?
One month cell (a button). Clicking selects the month and filters the task list; clicking again clears. Sets data-tone, data-selected, data-current.
BookHealth.MonthTone
asChild?
A bare element carrying the month's data-tone and data-current — the meter segment, or any tone-coloured wrapper.
BookHealth.MonthLabel
asChild?
The month's short label ("Jun"). Sets data-tone and data-current.
BookHealth.MonthTaskCount
asChild?, format?
The month's open-task count — the count chip's number. Caps at "20+" by default.
BookHealth.MonthClosedMessage
asChild?
Renders only for a closed month; defaults to the copy "Closed and verified".
BookHealth.MonthBreakdownIterates the month's non-empty task buckets with per-row context — the hover snapshot's rows.
BookHealth.BreakdownLabel
asChild?
One bucket's label ("Transactions to review"). Sets data-group.
BookHealth.BreakdownCount
asChild?, format?
One bucket's count for the month.
BookHealth.BreakdownTotal
asChild?, format?
The month's total open tasks — the breakdown's Total row value.
BookHealth.TasksLabel
asChild?
"Open tasks", or "{Month} tasks" while a month is selected.
BookHealth.TaskCount
asChild?, format?
Open tasks in scope — the selected month's, or the whole year's. Sets data-empty at zero.
BookHealth.ShowAllMonths
asChild?
Button clearing the month selection. Renders nothing while no month is selected.
BookHealth.TasksEmpty
asChild?
Renders its children only when the tasks section has nothing to list. Sets data-kind (year-clear / month-clear / month-not-started) and data-tone (success / neutral).
BookHealth.TasksEmptyMessage
asChild?
The notice copy: "Nothing is waiting on you." / "{Month} is all caught up." / "{Month} hasn't started yet."
context.tasks / uploadTask / addTaskNoteThe in-scope tasks plus the completion callbacks, via useBookHealth() — hand them to a nested Tasks list (tasks / onUpload / onAddNote) and the card re-syncs after each action.

Loading

Renders while the fetches are in flight.

PartDescription
BookHealth.LoadingState wrapper. The Months iterator still yields the twelve padded months, so a loading grid can render plain labels.

Empty

Renders when the API has no months for the year.

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

Error

Renders on fetch error (the business lookup never errors the card).

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

Locked

Renders when `locked` is set — the viewer isn't entitled to the card. Mutually exclusive with the other states, and no data is fetched; the Months iterator yields a deterministic teaser.

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

Unlocked

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

PartDescription
BookHealth.UnlockedState wrapper. Renders children whenever the card isn't locked.

Hooks

PartDescription
useBookHealth()Hook returning the full context: year, years, setYear, months, readyCount, selectedMonth, selectMonth, taskCount, tasks, uploadTask, addTaskNote, noticeKind, and the state flags.
useBookHealthMonth()Inside Months: the current month — tone, label, name, counts, per-bucket groupCounts.