Skip to content

Commit

Permalink
mills currency
Browse files Browse the repository at this point in the history
  • Loading branch information
zovington committed Sep 20, 2024
1 parent 646362b commit 90e0cec
Showing 6 changed files with 38 additions and 4 deletions.
9 changes: 9 additions & 0 deletions src/forms/BoundNumberField.test.tsx
Original file line number Diff line number Diff line change
@@ -57,6 +57,14 @@ describe("BoundNumberField", () => {
expect(r.royalties).toHaveValue("$1.00");
});

it("drops the 'in mills' suffix from labels", async () => {
const author = createObjectState(formConfig, { royaltiesInMills: 1_00 });
const r = await render(<BoundNumberField field={author.royaltiesInMills} />);
expect(r.royalties_label).toHaveTextContent("Royalties");
expect(r.royalties_label).not.toHaveTextContent("Cents");
expect(r.royalties).toHaveValue("$0.100");
});

it("retains 0 value", async () => {
const author = createObjectState(formConfig, { royaltiesInCents: 1_00 });
const r = await render(<BoundNumberField field={author.royaltiesInCents} />);
@@ -117,4 +125,5 @@ describe("BoundNumberField", () => {
const formConfig: ObjectConfig<AuthorInput> = {
heightInInches: { type: "value", rules: [required] },
royaltiesInCents: { type: "value" },
royaltiesInMills: { type: "value" },
};
4 changes: 2 additions & 2 deletions src/forms/BoundNumberField.tsx
Original file line number Diff line number Diff line change
@@ -18,8 +18,8 @@ export function BoundNumberField(props: BoundNumberFieldProps) {
field,
readOnly,
onChange = (value) => field.set(value),
label = defaultLabel(field.key.replace(/InCents$/, "")),
type = field.key.endsWith("InCents") ? "cents" : undefined,
label = defaultLabel(field.key.replace(/(InCents|InMills)$/, "")),
type = field.key.endsWith("InCents") ? "cents" : field.key.endsWith("InMills") ? "mills" : undefined,
onFocus,
onBlur,
onEnter,
1 change: 1 addition & 0 deletions src/forms/formStateDomain.ts
Original file line number Diff line number Diff line change
@@ -26,6 +26,7 @@ export interface AuthorInput {
birthday?: Date | null;
heightInInches?: number | null;
royaltiesInCents?: number | null;
royaltiesInMills?: number | null;
books?: BookInput[] | null;
address?: AuthorAddress | null;
favoriteSport?: string | null;
2 changes: 2 additions & 0 deletions src/inputs/NumberField.stories.tsx
Original file line number Diff line number Diff line change
@@ -45,6 +45,7 @@ export function NumberFieldStyles() {
<div css={Css.df.fdc.gap2.$}>
<h1 css={Css.lg.$}>Unit Types</h1>
<TestNumberField label="Percent" type="percent" value={12.55} numFractionDigits={2} truncate />
<TestNumberField label="Mills" type="mills" value={1000} />
<TestNumberField label="Cents" type="cents" value={1000} />
<TestNumberField label="Dollars" type="dollars" value={1000} />
<TestNumberField label="Margin" type="basisPoints" value={1275} />
@@ -80,6 +81,7 @@ export function NumberFieldReadOnly() {
<TextField label="First Name" value="first" onChange={() => {}} readOnly={true} />
<TestNumberField label="Name" value={100} readOnly={true} />
<TestNumberField label="Name" value={100} labelStyle="hidden" readOnly={true} />
<TestNumberField label="Name" value={100} readOnly={true} type="mills" />
<TestNumberField label="Name" value={100} readOnly={true} type="cents" />
<TestNumberField label="Name" value={100} readOnly={true} type="percent" />
</div>
18 changes: 18 additions & 0 deletions src/inputs/NumberField.test.tsx
Original file line number Diff line number Diff line change
@@ -60,6 +60,14 @@ describe("NumberFieldTest", () => {
expect(onChange).toBeCalledTimes(2); // change and blur
});

it("can set mills as dollars", async () => {
const r = await render(<TestNumberField label="Cost" type="mills" value={1200} />);
expect(r.cost).toHaveValue("$1.200");
type(r.cost, "14");
expect(r.cost).toHaveValue("$14.000");
expect(lastSet).toEqual(14000);
});

it("can set cents as dollars", async () => {
const r = await render(<TestNumberField label="Cost" type="cents" value={1200} />);
expect(r.cost).toHaveValue("$12.00");
@@ -92,6 +100,14 @@ describe("NumberFieldTest", () => {
expect(onChange).toBeCalledTimes(2); // change and blur
});

it("can set mills as mills", async () => {
const r = await render(<TestNumberField label="Cost" type="mills" value={12000} />);
expect(r.cost).toHaveValue("$12.000");
type(r.cost, ".145");
expect(r.cost).toHaveValue("$0.145");
expect(lastSet).toEqual(145);
});

it("can set cents as cents", async () => {
const r = await render(<TestNumberField label="Cost" type="cents" value={1200} />);
expect(r.cost).toHaveValue("$12.00");
@@ -153,13 +169,15 @@ describe("NumberFieldTest", () => {
const r = await render(
<>
<TestNumberField label="Days" type="days" value={123} displayDirection />
<TestNumberField label="Mills" type="mills" value={456} displayDirection />
<TestNumberField label="Cents" type="cents" value={456} displayDirection />
<TestNumberField label="Basis Points" type="basisPoints" value={789} displayDirection />
<TestNumberField label="Percent" type="percent" value={123} displayDirection />
<TestNumberField label="Zero Percent" type="percent" value={0} displayDirection />
</>,
);
expect(r.days).toHaveValue("+123 days");
expect(r.mills).toHaveValue("+$0.456");
expect(r.cents).toHaveValue("+$4.56");
expect(r.basisPoints).toHaveValue("+7.89%");
expect(r.percent).toHaveValue("+123%");
8 changes: 6 additions & 2 deletions src/inputs/NumberField.tsx
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@ import { Css, Xss } from "src/Css";
import { maybeCall } from "src/utils";
import { TextFieldBase } from "./TextFieldBase";

export type NumberFieldType = "cents" | "dollars" | "percent" | "basisPoints" | "days";
export type NumberFieldType = "cents" | "dollars" | "percent" | "basisPoints" | "days" | "mills";

// exported for testing purposes
export interface NumberFieldProps extends Pick<PresentationFieldProps, "labelStyle" | "fullWidth"> {
@@ -85,7 +85,9 @@ export function NumberField(props: NumberFieldProps) {

const isDisabled = !!disabled;
const isReadOnly = !!readOnly;
const factor = type === "percent" || type === "cents" ? 100 : type === "basisPoints" ? 10_000 : 1;
const factor =
type === "percent" ? 100 : type === "cents" ? 100 : type === "mills" ? 1_000 : type === "basisPoints" ? 10_000 : 1;

const signDisplay = displayDirection ? "always" : "auto";
const defaultFormatOptions: Intl.NumberFormatOptions = useMemo(
() => ({
@@ -111,6 +113,8 @@ export function NumberField(props: NumberFieldProps) {
? { style: "percent", minimumFractionDigits: 2 }
: type === "cents"
? { style: "currency", currency: "USD", minimumFractionDigits: 2 }
: type === "mills"
? { style: "currency", currency: "USD", minimumFractionDigits: 3 }
: type === "dollars"
? { style: "currency", currency: "USD", minimumFractionDigits: numFractionDigits ?? 2 }
: type === "days"

0 comments on commit 90e0cec

Please sign in to comment.