Skip to content

Commit

Permalink
[PBNTR-555] Currency Kit Comma Separator (#3867)
Browse files Browse the repository at this point in the history
**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.
  • Loading branch information
jasperfurniss authored Oct 31, 2024
1 parent b5cc921 commit c965ab7
Show file tree
Hide file tree
Showing 10 changed files with 130 additions and 18 deletions.
Empty file.
22 changes: 16 additions & 6 deletions playbook/app/pb_kits/playbook/pb_currency/_currency.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ type CurrencyProps = {
variant?: 'default' | 'light' | 'bold',
unit?: string,
unstyled?: boolean,
commaSeparator?: boolean,
}

const sizes: {lg: 1, md: 3, sm: 4} = {
Expand Down Expand Up @@ -53,6 +54,7 @@ const Currency = (props: CurrencyProps): React.ReactElement => {
variant = 'default',
dark = false,
unstyled = false,
commaSeparator = false,
} = props

const emphasizedClass = emphasized ? '' : '_deemphasized'
Expand All @@ -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)
Expand All @@ -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 (
<div
Expand Down
49 changes: 38 additions & 11 deletions playbook/app/pb_kits/playbook/pb_currency/currency.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ class Currency < Playbook::KitBase
prop :unstyled, type: Playbook::Props::Boolean,
default: false

prop :comma_separator, type: Playbook::Props::Boolean,
default: false

def classname
generate_classname("pb_currency_kit", align, size, dark_class)
end
Expand All @@ -65,7 +68,7 @@ def caption_props
def title_props
{
size: size_value,
text: abbreviate ? abbreviated_value : whole_value,
text: abbreviate ? abbreviated_value : formatted_amount,
classname: "pb_currency_value",
dark: dark,
}
Expand Down Expand Up @@ -96,28 +99,38 @@ def variant_class
private

def whole_value
return amount if decimals == "matching"

amount.split(".").first.to_s
value = amount.split(".").first
if comma_separator
number_with_delimiter(value.gsub(",", ""))
else
value
end
end

def abbreviated_value(index = 0..-2)
value = amount.split(".").first.split(",").join("")
abbreviated_num = number_to_human(value, units: { thousand: "K", million: "M", billion: "B", trillion: "T" }).gsub(/\s+/, "").to_s
abbreviated_num[index]
def decimal_value
amount.split(".")[1] || "00"
end

def units_element
return "" if decimals == "matching" && !abbreviate && !unit

_, decimal_part = amount.split(".")
if unit.nil? && abbreviate == false
decimal_part.nil? ? ".00" : ".#{decimal_part}"
if unit.nil? && !abbreviate
if decimals == "matching"
""
else
".#{decimal_value}"
end
else
abbreviate ? "#{abbreviated_value(-1)}#{unit}" : unit
end
end

def abbreviated_value(index = 0..-2)
value = amount.split(".").first.gsub(",", "").to_i
abbreviated_num = number_to_human(value, units: { thousand: "K", million: "M", billion: "B", trillion: "T" }).gsub(/\s+/, "")
abbreviated_num[index]
end

def size_value
case size
when "lg"
Expand All @@ -132,6 +145,20 @@ def size_value
def dark_class
dark ? "dark" : nil
end

def formatted_amount
return abbreviated_value if abbreviate

if decimals == "matching"
if comma_separator
number_with_delimiter(amount.gsub(",", ""))
else
amount
end
else
whole_value
end
end
end
end
end
35 changes: 35 additions & 0 deletions playbook/app/pb_kits/playbook/pb_currency/currency.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,38 @@ test('decimals default prop returns decimals as body text', () => {
expect(currencyKit.querySelector('.pb_currency_value')).toHaveTextContent('320')
expect(currencyKit.querySelector('.unit')).toHaveTextContent('.20')
})


test('commaSeparator prop returns comma separated amount', () => {
render(
<Currency
amount="1234567890"
commaSeparator
data={{ testid: 'comma-test' }}
/>
)
expect(screen.getByTestId('comma-test')).toHaveTextContent('1,234,567,890')
})

test('commaSeparator prop returns comma separated amount with decimals', () => {
render(
<Currency
amount="1234567890.12"
commaSeparator
data={{ testid: 'comma-test-decimals' }}
/>
)
expect(screen.getByTestId('comma-test-decimals')).toHaveTextContent('1,234,567,890.12')
})

test('commaSeparator prop returns comma separated amount with decimals="matching"', () => {
render(
<Currency
amount="1234567890.12"
commaSeparator
data={{ testid: 'comma-test-decimals-matching' }}
decimals="matching"
/>
)
expect(screen.getByTestId('comma-test-decimals-matching')).toHaveTextContent('1,234,567,890.12')
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<%= pb_rails("currency", props: {
amount: '1234567.89',
comma_separator: true,
size: 'lg',
emphasized: false,
decimals: 'matching',
}) %>
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import React from "react"

import Currency from "../_currency"

const CurrencyCommaSeparator = (props) => {
return (
<Currency
amount='1234567.89'
commaSeparator
decimals="matching"
emphasized={false}
size="lg"
{...props}
/>
)
}

export default CurrencyCommaSeparator
Original file line number Diff line number Diff line change
@@ -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.
4 changes: 3 additions & 1 deletion playbook/app/pb_kits/playbook/pb_currency/docs/example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
1 change: 1 addition & 0 deletions playbook/app/pb_kits/playbook/pb_currency/docs/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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'
9 changes: 9 additions & 0 deletions playbook/spec/pb_kits/playbook/pb_currency/currency_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

0 comments on commit c965ab7

Please sign in to comment.