LF-5302: Build presentational components for the Profitability widget#4183
Open
litefarm-pr-bot wants to merge 1 commit into
Open
Conversation
Adds the seven prop-driven, Storybook-testable presentational components
that compose the upcoming Profitability home widget: KpiCard (with four
colour-variant tokens and an optional hero-size trend slot), KpiSection
(hero card on top of a 3-column compact row), RevenueExpenseBars (two
columns of labelled MUI LinearProgress bars), EntityProfitTable (a
TableV2 driven by a Crops/Animals/All StateTab), ExpandableSection (a
blue-bordered More data / Less data toggle that mirrors the Additional
Nutrients pattern from ProductDetails), EmptyTransactionsBanner (the
green CTA banner shown when a range has zero transactions), and
ProfitabilityWidgetSkeleton (matching the widget layout with neutral-50
placeholder rectangles).
Each component takes its labels and currency as plain props rather than
calling i18n itself, which keeps every component fully driveable from
Storybook with no Redux store or i18n session required. A new
profitability translation namespace is added to public/locales/en and
registered in i18n.js so the container PR (which lands the
useTranslation('profitability') consumer) can pick it up without further
config; the namespace's DATE_RANGE.YEAR_LABEL key is reserved for that
PR's DateRangeDropdown wrapper. constants.ts exports the EntityTab and
KpiVariant enums alongside TOP_EXPENSE_CATEGORIES_COUNT and
FARM_GENERAL_ROW_ID; a single styles.module.scss carries the colour
tokens from Figma so every component pulls from the same palette.
One Storybook story per component (no play functions, just visual
scaffolds), plus a small expanded-state composition story for KpiCard
to exercise all four variants at once.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
The Profitability home widget is a substantial composition: a hero KPI card with a trend, three secondary KPI cards, a More data / Less data expand toggle, a two-column bars region, an entity table with Crops/Animals/All tabs, an empty-state CTA banner, and a skeleton. None of those parts exist anywhere in the codebase today, and writing them inline in the smart container would produce one ~600-line file that no one can review or visually tune. This PR ships them as seven independent, prop-driven, Storybook-testable presentational components in a new
components/ProfitabilityWidget/directory.Each component takes its labels and currency as plain props rather than calling
useTranslationitself, which keeps every component fully driveable from Storybook with no Redux store and no i18n session. The newprofitabilitytranslation namespace lives atpublic/locales/en/profitability.jsonand is registered ini18n.jsso the upcoming container can resolveuseTranslation('profitability')without further config; the namespace'sDATE_RANGE.YEAR_LABELkey is reserved for the container PR'sDateRangeDropdownwrapper, which depends on the previously-extendedDateRangeSelectorand is intentionally not in this PR. A singlestyles.module.scsscarries the per-variant colour tokens from Figma so every component pulls from the same palette;constants.tsexports theEntityTabandKpiVariantenums alongsideTOP_EXPENSE_CATEGORIES_COUNTandFARM_GENERAL_ROW_ID.The convention worth carrying forward: keep presentational components in this widget pure of i18n and Redux. When localised strings are needed, accept them as props (either a
labelsshape, or individuallabel/ctaLabelstrings), so the same component can be rendered both from the live container and from a Storybook story without context. The smart container will own theuseTranslationcall and pass the resolved strings down.Jira: https://lite-farm.atlassian.net/browse/LF-5302
Type of change
How Has This Been Tested?
NODE_OPTIONS=--max_old_space_size=3000 pnpm exec tsc --noEmitfrompackages/webapppasses with no errors. The existing webapp Vitest suite is unaffected (no source code paths that previous tests exercise were modified beyond appending a new namespace to the i18nnsarray). Storybook stories were added for each component but were not rendered locally — the visual review should happen viapnpm storybookagainst the newComponents/ProfitabilityWidget/*story tree, and the full widget composition will be visually reviewable when the smart container lands.Checklist:
pnpm i18nto help with this)