Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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"})

Expand Down
11 changes: 9 additions & 2 deletions services/frontend/src/domains/association/numbers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand Down
19 changes: 19 additions & 0 deletions services/frontend/tests/unit/domains/association/numbers.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {describe, expect, it} from "vitest"
import {
associationFigures,
figuresFor,
figureText,
FLOORS,
MEMBERS_CLAIMED,
Expand Down Expand Up @@ -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")
Expand Down
Loading