From c965ab789e1d3048ee52fa9f5432598aba91552b Mon Sep 17 00:00:00 2001 From: Jasper Furniss Date: Thu, 31 Oct 2024 09:31:34 -0400 Subject: [PATCH] [PBNTR-555] Currency Kit Comma Separator (#3867) **What does this PR do?** A clear and concise description with your runway ticket url. **Screenshots:** Screenshots to visualize your addition/change **How to test?** Steps to confirm the desired behavior: 1. Go to '...' 2. Click on '....' 3. Scroll down to '....' 4. See addition/change #### Checklist: - [ ] **LABELS** Add a label: `enhancement`, `bug`, `improvement`, `new kit`, `deprecated`, or `breaking`. See [Changelog & Labels](https://github.com/powerhome/playbook/wiki/Changelog-&-Labels) for details. - [ ] **DEPLOY** I have added the `milano` label to show I'm ready for a review. - [ ] **TESTS** I have added test coverage to my code. --- .../workflows/github-actions-check-labels.yml | 0 .../playbook/pb_currency/_currency.tsx | 22 ++++++--- .../pb_kits/playbook/pb_currency/currency.rb | 49 ++++++++++++++----- .../playbook/pb_currency/currency.test.js | 35 +++++++++++++ .../docs/_currency_comma_separator.html.erb | 7 +++ .../docs/_currency_comma_separator.jsx | 18 +++++++ .../docs/_currency_comma_separator.md | 3 ++ .../playbook/pb_currency/docs/example.yml | 4 +- .../playbook/pb_currency/docs/index.js | 1 + .../playbook/pb_currency/currency_spec.rb | 9 ++++ 10 files changed, 130 insertions(+), 18 deletions(-) create mode 100644 .github/workflows/github-actions-check-labels.yml create mode 100644 playbook/app/pb_kits/playbook/pb_currency/docs/_currency_comma_separator.html.erb create mode 100644 playbook/app/pb_kits/playbook/pb_currency/docs/_currency_comma_separator.jsx create mode 100644 playbook/app/pb_kits/playbook/pb_currency/docs/_currency_comma_separator.md diff --git a/.github/workflows/github-actions-check-labels.yml b/.github/workflows/github-actions-check-labels.yml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/playbook/app/pb_kits/playbook/pb_currency/_currency.tsx b/playbook/app/pb_kits/playbook/pb_currency/_currency.tsx index f0673c777b..c03f683541 100644 --- a/playbook/app/pb_kits/playbook/pb_currency/_currency.tsx +++ b/playbook/app/pb_kits/playbook/pb_currency/_currency.tsx @@ -26,6 +26,7 @@ type CurrencyProps = { variant?: 'default' | 'light' | 'bold', unit?: string, unstyled?: boolean, + commaSeparator?: boolean, } const sizes: {lg: 1, md: 3, sm: 4} = { @@ -53,6 +54,7 @@ const Currency = (props: CurrencyProps): React.ReactElement => { variant = 'default', dark = false, unstyled = false, + commaSeparator = false, } = props const emphasizedClass = emphasized ? '' : '_deemphasized' @@ -74,7 +76,7 @@ const Currency = (props: CurrencyProps): React.ReactElement => { className ) - const getFormattedNumber = (input: number | any ) => new Intl.NumberFormat('en-US', { + const getFormattedNumber = (input: number | any) => new Intl.NumberFormat('en-US', { notation: 'compact', maximumFractionDigits: 1, }).format(input) @@ -88,12 +90,20 @@ const Currency = (props: CurrencyProps): React.ReactElement => { return isAmount ? num.slice(0, -1) : isUnit ? num.slice(-1) : '' } - const getMatchingDecimalAmount = decimals === "matching" ? amount : whole, - getMatchingDecimalValue = decimals === "matching" ? '' : `.${decimal}` + const getMatchingDecimalAmount = decimals === "matching" ? amount : whole + const getMatchingDecimalValue = decimals === "matching" ? '' : `.${decimal}` - const getAmount = abbreviate ? getAbbreviatedValue('amount') : getMatchingDecimalAmount, - getAbbreviation = abbreviate ? getAbbreviatedValue('unit') : null, - getDecimalValue = abbreviate ? '' : getMatchingDecimalValue + const formatAmount = (amount: string) => { + if (!commaSeparator) return amount; + + const [wholePart, decimalPart] = amount.split('.'); + const formattedWhole = new Intl.NumberFormat('en-US').format(parseInt(wholePart)); + return decimalPart ? `${formattedWhole}.${decimalPart}` : formattedWhole; + } + + const getAmount = abbreviate ? getAbbreviatedValue('amount') : formatAmount(getMatchingDecimalAmount) + const getAbbreviation = abbreviate ? getAbbreviatedValue('unit') : null + const getDecimalValue = abbreviate ? '' : getMatchingDecimalValue return (
{ expect(currencyKit.querySelector('.pb_currency_value')).toHaveTextContent('320') expect(currencyKit.querySelector('.unit')).toHaveTextContent('.20') }) + + +test('commaSeparator prop returns comma separated amount', () => { + render( + + ) + expect(screen.getByTestId('comma-test')).toHaveTextContent('1,234,567,890') +}) + +test('commaSeparator prop returns comma separated amount with decimals', () => { + render( + + ) + expect(screen.getByTestId('comma-test-decimals')).toHaveTextContent('1,234,567,890.12') +}) + +test('commaSeparator prop returns comma separated amount with decimals="matching"', () => { + render( + + ) + expect(screen.getByTestId('comma-test-decimals-matching')).toHaveTextContent('1,234,567,890.12') +}) diff --git a/playbook/app/pb_kits/playbook/pb_currency/docs/_currency_comma_separator.html.erb b/playbook/app/pb_kits/playbook/pb_currency/docs/_currency_comma_separator.html.erb new file mode 100644 index 0000000000..48f0548013 --- /dev/null +++ b/playbook/app/pb_kits/playbook/pb_currency/docs/_currency_comma_separator.html.erb @@ -0,0 +1,7 @@ +<%= pb_rails("currency", props: { + amount: '1234567.89', + comma_separator: true, + size: 'lg', + emphasized: false, + decimals: 'matching', +}) %> diff --git a/playbook/app/pb_kits/playbook/pb_currency/docs/_currency_comma_separator.jsx b/playbook/app/pb_kits/playbook/pb_currency/docs/_currency_comma_separator.jsx new file mode 100644 index 0000000000..851cf52a10 --- /dev/null +++ b/playbook/app/pb_kits/playbook/pb_currency/docs/_currency_comma_separator.jsx @@ -0,0 +1,18 @@ +import React from "react" + +import Currency from "../_currency" + +const CurrencyCommaSeparator = (props) => { + return ( + + ) +} + +export default CurrencyCommaSeparator diff --git a/playbook/app/pb_kits/playbook/pb_currency/docs/_currency_comma_separator.md b/playbook/app/pb_kits/playbook/pb_currency/docs/_currency_comma_separator.md new file mode 100644 index 0000000000..b2c926c110 --- /dev/null +++ b/playbook/app/pb_kits/playbook/pb_currency/docs/_currency_comma_separator.md @@ -0,0 +1,3 @@ +The optional `commaSeparator` can be used to auto-format the use of commas as a thousands separator. + +**NOTE:** If the value passed into the `amount` prop is already comma-dilineated, it will not add additional commas. diff --git a/playbook/app/pb_kits/playbook/pb_currency/docs/example.yml b/playbook/app/pb_kits/playbook/pb_currency/docs/example.yml index a8354bce15..8568c2a514 100644 --- a/playbook/app/pb_kits/playbook/pb_currency/docs/example.yml +++ b/playbook/app/pb_kits/playbook/pb_currency/docs/example.yml @@ -8,7 +8,8 @@ examples: - currency_abbreviated: Abbreviate Larger Amounts - currency_matching_decimals: Matching Decimals - currency_unstyled: Unstyled - + - currency_comma_separator: Comma Separator + react: - currency_variants: Variants - currency_size: Size @@ -17,6 +18,7 @@ examples: - currency_abbreviated: Abbreviate Larger Amounts - currency_matching_decimals: Matching Decimals - currency_unstyled: Unstyled + - currency_comma_separator: Comma Separator swift: - currency_size_swift: Size diff --git a/playbook/app/pb_kits/playbook/pb_currency/docs/index.js b/playbook/app/pb_kits/playbook/pb_currency/docs/index.js index e0ab2b0b99..86ae571909 100644 --- a/playbook/app/pb_kits/playbook/pb_currency/docs/index.js +++ b/playbook/app/pb_kits/playbook/pb_currency/docs/index.js @@ -5,3 +5,4 @@ export { default as CurrencyNoSymbol } from './_currency_no_symbol.jsx' export { default as CurrencyAbbreviated } from './_currency_abbreviated.jsx' export { default as CurrencyMatchingDecimals } from './_currency_matching_decimals.jsx' export { default as CurrencyUnstyled } from './_currency_unstyled.jsx' +export { default as CurrencyCommaSeparator } from './_currency_comma_separator.jsx' diff --git a/playbook/spec/pb_kits/playbook/pb_currency/currency_spec.rb b/playbook/spec/pb_kits/playbook/pb_currency/currency_spec.rb index 6a5d8bf3e6..f69e4a8449 100644 --- a/playbook/spec/pb_kits/playbook/pb_currency/currency_spec.rb +++ b/playbook/spec/pb_kits/playbook/pb_currency/currency_spec.rb @@ -15,6 +15,7 @@ it { is_expected.to define_enum_prop(:variant).with_default("default").with_values("default", "light", "bold") } it { is_expected.to define_prop(:abbreviate).with_default(false).of_type(Playbook::Props::Boolean) } it { is_expected.to define_enum_prop(:decimals).with_default("default").with_values("default", "matching") } + it { is_expected.to define_prop(:comma_separator).with_default(false).of_type(Playbook::Props::Boolean) } describe "#classname" do it "returns namespaced class name", :aggregate_failures do @@ -75,4 +76,12 @@ expect(num.body_props[:text]).to eq ".20" end end + + describe "when prop commaSeparator is set to true" do + it "returns comma separated amount" do + num = subject.new(comma_separator: true, amount: "1234567890") + + expect(num.title_props[:text]).to eq "1,234,567,890" + end + end end