diff --git a/services/frontend/src/domains/association/island/NumberBand.vue b/services/frontend/src/domains/association/island/NumberBand.vue index 4afd266a7..e3aa5c9da 100644 --- a/services/frontend/src/domains/association/island/NumberBand.vue +++ b/services/frontend/src/domains/association/island/NumberBand.vue @@ -2,12 +2,13 @@ import {figureText, type Figure} from "../numbers" /** - * The association in four numbers, across the page. + * The association in a handful of numbers, across the page. * * Every figure is drawn the moment the band is: the ones the api counts start on the floors the - * association publishes about itself and are replaced where the counts land, so the band never - * changes height and there is nothing pulsing on the page that is meant to sell membership. A - * figure that is a floor rather than a count says so with a `+`. + * association publishes about itself and are replaced where the counts land, so there is + * nothing pulsing on the page that is meant to sell membership. A figure that is a floor rather + * than a count says so with a `+`. Usually four; a figure the api counted as none is not on the + * band at all, so the band draws what it is given rather than a fixed set. */ defineOptions({name: "NumberBand"}) diff --git a/services/frontend/src/domains/association/numbers.ts b/services/frontend/src/domains/association/numbers.ts index bccfc916b..9ce188f41 100644 --- a/services/frontend/src/domains/association/numbers.ts +++ b/services/frontend/src/domains/association/numbers.ts @@ -84,9 +84,16 @@ const counted = ( label: string, ): Figure => ({id, value: value ?? floor, exact: numbers != null, label}) -/** The figures a page names, in the order it names them. */ +/** + * The figures a page names, in the order it names them, less any the api counted as none. + * + * A page that sells the association does not print `0 Events in the past year`. Nor does it + * fall back to the published floor there: the floor stands for a number nobody has counted yet, + * and a counted zero has been counted. The figure comes off the band, and the ones either side + * of it close up. + */ export function figuresFor(ids: readonly FigureId[], numbers: AssociationNumbers | null): Figure[] { - return ids.map(id => FIGURES[id](numbers)) + return ids.map(id => FIGURES[id](numbers)).filter(figure => !(figure.exact && figure.value === 0)) } /** What the membership page leads with. */ diff --git a/services/frontend/tests/unit/domains/association/numbers.test.ts b/services/frontend/tests/unit/domains/association/numbers.test.ts index 1cf25cb62..f4f834cb9 100644 --- a/services/frontend/tests/unit/domains/association/numbers.test.ts +++ b/services/frontend/tests/unit/domains/association/numbers.test.ts @@ -1,6 +1,7 @@ import {describe, expect, it} from "vitest" import { associationFigures, + figuresFor, figureText, FLOORS, MEMBERS_CLAIMED, @@ -45,6 +46,24 @@ describe("associationFigures", () => { }) describe("figureText", () => { + /** + * A page that sells the association does not print `0 Events in the past year`. + * + * Nor does it fall back to the published floor there: the floor stands for a number nobody + * has counted yet, and a counted zero has been counted. + */ + it("leaves out a figure the api counted as none", () => { + const none = figuresFor(["members", "teams", "events"], {...counted, eventsLastYear: 0}) + + expect(none.map(figure => figure.id)).toEqual(["members", "teams"]) + }) + + it("keeps a figure nobody has counted yet, on its floor", () => { + const unread = figuresFor(["events"], null) + + expect(unread).toMatchObject([{id: "events", value: FLOORS.eventsLastYear, exact: false}]) + }) + it("marks a floor as at least that many and states a count plainly", () => { expect(figureText({id: "members", value: 200, exact: false, label: ""})).toBe("200+") expect(figureText({id: "teams", value: 13, exact: true, label: ""})).toBe("13")