keep-the-receipts / keepthereceipts-frontend

Frontend to search, explore and download government contracting data
https://keepthereceipts.org.za/
MIT License
0 stars 0 forks source link

more readable ZAR amount formatting #14

Closed jbothma closed 4 years ago

jbothma commented 4 years ago

e.g.

zacharlie commented 4 years ago

I came here after having a look at the site and looking to open an issue for having a "thousands" space separator for the currency value, as I also saw issues with readability.

This "human readable" form does greatly improve readability and impact, but I feel like having "thousand" or "million" strings is problematic for a couple reasons:

  1. It does not accurately represent the data and needs significant rounding... e.g. what happens with a value like 123456789.85?
  2. It may cause significant problems for non-technical folk trying to copy and paste values into their spreadsheet programs.

If you could toggle between a standard numeric/ currency format and a "pretty printed" human readable that would help though, or at least that's the implementation I would aim for...

jbothma commented 4 years ago

Hi! Thanks for coming to report this!

I think the excel export (did you see that button? Not sure it's visible enough) should output the raw number - so for analysis you can still get full precision.

What do you think of showing the full number with thousands separator in a tooltip? So desktop users can still see the full detail without downloading the excel file.

I'm thinking of how we can address your concerns without a toggle button taking up user interface space. But you're very right on the concerns you raised.

The rounding is not as big an issue when you're just glancing, but as soon as you want to do more serious analysis, I think you need the raw numbers.

zacharlie commented 4 years ago

I think a tooltip for displaying the full amount in the UI and having the raw data available in the export is a perfectly suitable compromise...

I did see the download button but I would probably enhance it's visibility, probably by inverting the colours.

So long as people can get the whole story without having to use the export tools (when you're looking at figures in the billions, it would be easy for hundreds of millions to go unaccounted for, which is a pretty big deal).

jbothma commented 4 years ago

Ah yeah - so perhaps the default view could humanise but the expanded view shows the full number with a thousands separator.

On Sun, 18 Oct 2020, 17:31 Charlie, notifications@github.com wrote:

I think a tooltip for displaying the full amount in the UI and having the raw data available in the export is a perfectly suitable compromise...

I did see the download button but I would probably enhance it's visibility, probably by inverting the colours.

So long as people can get the whole story without having to use the export tools (when you're looking at figures in the billions, it would be easy for hundreds of millions to go unaccounted for, which is a pretty big deal).

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/keep-the-receipts/keepthereceipts-frontend/issues/14#issuecomment-711226179, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABZSGL4R7LVD2LNVLJGIELSLMC3ZANCNFSM4SVCHMBA .

jbothma commented 4 years ago

Spec:

This applies to each field that ends with _zar

On the basic result listing, "humanise" the numbers, e.g. R 123.4 million

Screenshot_2020-10-19_09-20-21

On the expanded results view, show the number with space thousand separator and two decimal places (not humanised) Screenshot_2020-10-19_09-26-23

jbothma commented 4 years ago

https://github.com/d3/d3-format might be well-suited to this task.

zacharlie commented 4 years ago

I have a simple function available that I made to convert number to the human readable format described. I'm not sure if it's useful but didn't see anything available in the d3format to do this.

One thing it doesn't yet do is convert a valid number of string type into a number (just does isNaN). You could probably fix this with a regex tweak though.

<div id="foo"></div>

<script>
var input1 = 123.67
var input2 = 1234.67
var input3 = 12345.67
var input4 = 123456.67
var input5 = 1234567.67
var input6 = 12345678.67
var input7 = 123456789.67
var input8 = 1234567891.67
var input9 = 12345678910.67
var input9 = 123456789109.67
var input10 = 123456789109
var input11 = "123456789109"
var input12 = 42
var input13 = "stringVal"
var input14 = "123456789109a.67"
// var something = 123456789109a.67 // this would obviously break javascript

function number_to_humanString(num) {
  if (num >= 1000 && num <= 99999.99) {
    let number = (num/1000).toFixed(2)
    number = number.toString()
    number += ' Thousand'
    return number
  } else if (num >= 100000 && num <= 999999.99) {
    console.log(num)
    let number = (num/100000).toFixed(2)
    number = number.toString()
    number += ' Hundred Thousand'
    return number
  } else if (num >= 1000000 && num <= 999999999.99) {
    console.log(num)
    let number = (num/1000000).toFixed(2)
    number = number.toString()
    number += ' Million'
    return number
  } else if (num >= 1000000) {
    console.log(num)
    let number = (num/1000000000).toFixed(2)
    number = number.toString()
    number += ' Billion'
    return number
  } else if (isNaN(num)) {
    return num
  } else {
    return num.toFixed(2)
  }
}

var var1 = number_to_humanString(input1)
var var2 = number_to_humanString(input2)
var var3 = number_to_humanString(input3)
var var4 = number_to_humanString(input4)
var var5 = number_to_humanString(input5)
var var6 = number_to_humanString(input6)
var var7 = number_to_humanString(input7)
var var8 = number_to_humanString(input8)
var var9 = number_to_humanString(input9)
var var10 = number_to_humanString(input10)
var var11 = number_to_humanString(input11)
var var12 = number_to_humanString(input12)
var var13 = number_to_humanString(input13)
var var14 = number_to_humanString(input14)

var test = "test1: " + var1 + "<br>"
test = test.concat("test2: ", var2, "<br>")
test = test.concat("test3: ", var3, "<br>")
test = test.concat("test4: ", var4, "<br>")
test = test.concat("test5: ", var5, "<br>")
test = test.concat("test6: ", var6, "<br>")
test = test.concat("test7: ", var7, "<br>")
test = test.concat("test8: ", var8, "<br>")
test = test.concat("test9: ", var9, "<br>")
test = test.concat("test10: ", var10, "<br>")
test = test.concat("test11: ", var11, "<br>")
test = test.concat("test12: ", var12, "<br>")
test = test.concat("test13: ", var13, "<br>")
test = test.concat("test14: ", var14, "<br>")

document.getElementById("foo").innerHTML = test
</script>

Results:

test1: 123.67
test2: 1.23 Thousand
test3: 12.35 Thousand
test4: 1.23 Hundred Thousand
test5: 1.23 Million
test6: 12.35 Million
test7: 123.46 Million
test8: 1.23 Billion
test9: 123.46 Billion
test10: 123.46 Billion
test11: 123.46 Billion
test12: 42.00
test13: stringVal
test14: 123456789109a.67
zacharlie commented 4 years ago

I found the d3-format docs a bit unclear and formatting this seemed trivial at first but turned out to be a pain in the neck (for me anyway).

This example might be helpful:

<script src="https://d3js.org/d3-format.v2.min.js"></script>

<div id="foo"></div>

<script>
var inputValue = 123456789.95
x = d3.formatDefaultLocale(
{
"decimal": ".",
"thousands": " ",
"grouping": [3],
"currency": ["R ",""]
})
var formatValue = d3.format("($,.2f")(inputValue)
document.getElementById("foo").innerHTML = formatValue
</script>

Result:

R 123 456 789.95
zacharlie commented 4 years ago

Almost forgot to mention watman:

https://www.destroyallsoftware.com/talks/wat

jbothma commented 4 years ago

Thanks! I didn't see your comment til now.

In the end I copied some code I'd used before after I also couldn't figure out d3-format from the docs :D

Thanks for the usability and code suggestions! Much appreciated.

zacharlie commented 4 years ago

No worries 👍