Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/229 connect unitconverter to frontend #302

Merged
merged 11 commits into from
Feb 8, 2023
4 changes: 2 additions & 2 deletions frontend/src/components/Item/ItemPreviewGrid.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import Image from "next/image"
import Link from "next/link"
import { routes } from "../../services/routes/routes"
import { generateWeightString } from "../../services/utils/weight"
import { ItemPreviewProps } from "./ItemPreviewList"
import { renderUnitIntoString } from "../../services/unit/unitRenderer"

/**
* Excerpt component for Item
Expand All @@ -13,7 +13,7 @@ import { ItemPreviewProps } from "./ItemPreviewList"
* ```
*/
export const ItemPreviewGrid: React.FC<ItemPreviewProps> = ({ slug, datacy, name, weight, imageUrl }) => {
const weightString = generateWeightString(weight)
const weightString = renderUnitIntoString(weight)

return <Link datacy={datacy} className="flex items-center justify-between rounded-lg bg-white pl-5 pr-2 md:pr-3 py-2 md:py-3" href={routes.weights.single(slug)}>
<div className="pr-3">
Expand Down
7 changes: 4 additions & 3 deletions frontend/src/components/Item/ItemPreviewList.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import Image from "next/image"
import Link from "next/link"
import { routes } from "../../services/routes/routes"
import { generateWeightProgressBarPercentage, generateWeightString } from "../../services/utils/weight"
import { generateWeightProgressBarPercentage } from "../../services/utils/weight"
import { Weight } from "../../types/item"
import { Icon } from "../Icon/Icon"
import { ProgressBar } from "../ProgressBar/ProgressBar"
import { renderUnitIntoString, renderWeightAsNumberIntoString } from "../../services/unit/unitRenderer"

export type ItemPreviewProps = {
/** Name of item. */
Expand Down Expand Up @@ -34,7 +35,7 @@ export type ItemPreviewProps = {
* ```
*/
export const ItemPreviewList: React.FC<ItemPreviewProps & { heaviestWeight: Weight }> = ({ slug, name, weight, heaviestWeight, difference, selectedItem, disableLink, imageUrl, datacy }) => {
const weightString = generateWeightString(weight)
const weightString = renderUnitIntoString(weight)
const percentageProgressbar = generateWeightProgressBarPercentage(weight, heaviestWeight)
const hasDifference = (difference || difference === 0)

Expand All @@ -48,7 +49,7 @@ export const ItemPreviewList: React.FC<ItemPreviewProps & { heaviestWeight: Weig
</div>
<div className={`flex items-center ${hasDifference && selectedItem ? "justify-end" : ""} md:w-2/3`}>
{hasDifference && !selectedItem && <div className={`flex items-center justify-center ${difference === 0 ? "text-gray-500" : (difference > 0 ? "text-green-500" : "text-red-500")} md:px-3 lg:px-0 w-2/6 md:w-1/4`}>
<span className="font-medium mr-1">{Math.abs(difference)} g</span>
<span className="font-medium mr-1">{renderWeightAsNumberIntoString(Math.abs(difference))}</span>
<Icon className="text-xl">{difference === 0 ? "remove" : (difference >= 0 ? "arrow_upward" : "arrow_downward")}</Icon>
</div>}
<h5 className={`${selectedItem ? "text-blue-500" : "text-gray-800"} text-right font-bold ${hasDifference ? selectedItem ? "w-2/3 md:w-1/4" : "w-3/6 md:w-1/4" : "w-1/3"} mr-4`} title={`${name} has a weight of ${weightString}`}>{weightString}</h5>
Expand Down
7 changes: 4 additions & 3 deletions frontend/src/pages/weights/[slug].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import { Tab } from "../../components/Tabs/Tab"
import { Tabs } from "../../components/Tabs/Tabs"
import { queryRequest } from "../../services/axios/axios"
import { routes } from "../../services/routes/routes"
import { calculateMedianWeight, generateWeightString } from "../../services/utils/weight"
import { calculateMedianWeight } from "../../services/utils/weight"
import { renderUnitIntoString } from "../../services/unit/unitRenderer"
import { Item, PaginatedResponse } from "../../types/item"
import Custom404 from "../404"

Expand Down Expand Up @@ -42,8 +43,8 @@ export default function WeightsSingle({ item, relatedItems }: InferGetServerSide
}]
const currentTabIndex = singleWeightTabs.findIndex(singleWeightTab => singleWeightTab.slug === currentTab)

// Strings Generator
const weightString = generateWeightString(item.weight)
// Strings + Unit Generator
const weightString = renderUnitIntoString(item.weight)
const sourceName = item.source ? new URL(item.source).hostname.replace("www.", "") : null

// Throw error when tab does not exist.
Expand Down
8 changes: 4 additions & 4 deletions frontend/src/pages/weights/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ import { Tooltip } from "../../components/Tooltip/Tooltip"
import { useLocalStorage } from "../../hooks/useLocalStorage"
import { queryRequest } from "../../services/axios/axios"
import { routes } from "../../services/routes/routes"
import { renderUnitIntoString, renderWeightAsNumberIntoString } from "../../services/unit/unitRenderer"
import { generatePageString } from "../../services/seo/pageString"
import { generateWeightString } from "../../services/utils/weight"
import { Item, PaginatedResponse } from "../../types/item"

const DEFAULT_ITEMS_PER_PAGE = 16
Expand Down Expand Up @@ -141,9 +141,9 @@ export default function WeightsList({ items, currentPage, totalItems, limit, que
</button>

<div className={`${statisticsExpanded ? "flex flex-col lg:flex-row" : "grid"} flex-grow md:flex-auto gap-2 lg:gap-4`}>
<Card classNameWrapper={`${statisticsExpanded ? "flex-1" : ""}`} to={routes.weights.single(statistics.heaviest.slug)} icon="weight" value={generateWeightString(statistics.heaviest.weight)} descriptionTop={statistics.heaviest.name} descriptionBottom="Heaviest" />
<Card classNameWrapper={`${statisticsExpanded ? "flex-1" : ""}`} to={routes.weights.single(statistics.lightest.slug)} icon="eco" value={generateWeightString(statistics.lightest.weight)} descriptionTop={statistics.lightest.name} descriptionBottom="Lightest" />
<Card classNameWrapper={`${statisticsExpanded ? "flex-1" : ""}`} icon="scale" value={`${Number(statistics.averageWeight).toFixed(2)} g`} descriptionBottom="Average" />
<Card classNameWrapper={`${statisticsExpanded ? "flex-1" : ""}`} to={routes.weights.single(statistics.heaviest.slug)} icon="weight" value={renderUnitIntoString(statistics.heaviest.weight)} descriptionTop={statistics.heaviest.name} descriptionBottom="Heaviest" />
<Card classNameWrapper={`${statisticsExpanded ? "flex-1" : ""}`} to={routes.weights.single(statistics.lightest.slug)} icon="eco" value={renderUnitIntoString(statistics.lightest.weight)} descriptionTop={statistics.lightest.name} descriptionBottom="Lightest" />
<Card classNameWrapper={`${statisticsExpanded ? "flex-1" : ""}`} icon="scale" value={renderWeightAsNumberIntoString(statistics.averageWeight)} descriptionBottom="Average" />
</div>
</div>
</div>
Expand Down
39 changes: 37 additions & 2 deletions frontend/src/services/unit/unitRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@ import { Weight } from "../../types/item"
import { convertWeightIntoTargetUnit } from "./unitConverter"
import { getBestHumanReadableUnit } from "./unitHumanReadable"

/**
* Gets number and and rounds it.
* @param number the number to round.
* @returns string with rounded number.
*/
export const roundNumber = (number: number): string => {
let roundedNumber = Math.round(number * 1000) / 1000
return roundedNumber.toString()
}

/**
* Gets number and formats it to a number with seperation points.
* @param number the number to format.
Expand All @@ -11,9 +21,9 @@ import { getBestHumanReadableUnit } from "./unitHumanReadable"
*/
export const addPointsToNumber = (number: number, formatComma: boolean): string => {
if (formatComma) {
return number.toFixed(2)
return roundNumber(number)
} else {
return new Intl.NumberFormat("de-DE").format(number)
return new Intl.NumberFormat("en-EN").format(number)
}
}

Expand All @@ -34,6 +44,7 @@ export const renderUnitIntoString = (weight: Weight): string => {

//Add weight value to String, if large number it will add Seperation Points.
if (bestHumanReadableUnit.value % 1 !== 0) {
console.log(bestHumanReadableUnit.value)
renderedText += addPointsToNumber(bestHumanReadableUnit.value, true)
} else {
renderedText += addPointsToNumber(bestHumanReadableUnit.value, false)
Expand All @@ -54,4 +65,28 @@ export const renderUnitIntoString = (weight: Weight): string => {

return renderedText

}

/**
* Gets weight as number and renders it into a human readable string.
* @param weight the weight as number to render.
* @returns string with the weight in the best human readable unit.
*/
export const renderWeightAsNumberIntoString = (weight: number): string => {
let renderedText = ""

const bestHumanReadableUnit = getBestHumanReadableUnit(weight)

//Add weight value to String, if large number it will add Seperation Points.
if (bestHumanReadableUnit.value % 1 !== 0) {
renderedText += addPointsToNumber(bestHumanReadableUnit.value, true)
} else {
renderedText += addPointsToNumber(bestHumanReadableUnit.value, false)
}

//Add weight unit to String.
renderedText += ` ${bestHumanReadableUnit.unit}`

return renderedText

}
50 changes: 33 additions & 17 deletions frontend/src/services/unit/unitRenderer.unit.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
import { renderUnitIntoString } from "./unitRenderer"
import { renderUnitIntoString, roundNumber } from "./unitRenderer"
describe("roundNumber Function", () => {
it("it should round number", () => {
expect(roundNumber(1.234)).deep.equal("1.234")
expect(roundNumber(1.2345)).deep.equal("1.235")
expect(roundNumber(1.234567)).deep.equal("1.235")
expect(roundNumber(1.234267)).deep.equal("1.234")
expect(roundNumber(1.23)).deep.equal("1.23")
expect(roundNumber(1.2)).deep.equal("1.2")
expect(roundNumber(5)).deep.equal("5")
})
})

describe("UnitRenderer", () => {
describe("renderUnitIntoString Function", () => {
it("it should display 'ca.'", () => {
expect(renderUnitIntoString({
value: 9,
Expand All @@ -11,7 +22,7 @@ describe("UnitRenderer", () => {
value: 123243342,
additionalValue: 123289765,
isCa: true
})).deep.equal("ca. 123.24 - 123.29 T")
})).deep.equal("ca. 123.243 - 123.29 T")
expect(renderUnitIntoString({
value: 9,
additionalValue: 0,
Expand All @@ -21,7 +32,7 @@ describe("UnitRenderer", () => {
value: 0.0126,
additionalValue: 0.0645,
isCa: true
})).deep.equal("ca. 12.60 - 64.50 mg")
})).deep.equal("ca. 12.6 - 64.5 mg")
})

it("it should NOT display 'ca.'", () => {
Expand All @@ -34,7 +45,7 @@ describe("UnitRenderer", () => {
value: 123243342,
additionalValue: 123289765,
isCa: false
})).deep.equal("123.24 - 123.29 T")
})).deep.equal("123.243 - 123.29 T")
expect(renderUnitIntoString({
value: 9,
additionalValue: 0,
Expand All @@ -44,7 +55,7 @@ describe("UnitRenderer", () => {
value: 0.0126,
additionalValue: 0.0645,
isCa: false
})).deep.equal("12.60 - 64.50 mg")
})).deep.equal("12.6 - 64.5 mg")
})

it("it should display additionalValue", () => {
Expand All @@ -57,7 +68,7 @@ describe("UnitRenderer", () => {
value: 123243342,
additionalValue: 123289765,
isCa: false
})).deep.equal("123.24 - 123.29 T")
})).deep.equal("123.243 - 123.29 T")
expect(renderUnitIntoString({
value: 9,
additionalValue: 40,
Expand All @@ -67,7 +78,7 @@ describe("UnitRenderer", () => {
value: 0.0126,
additionalValue: 0.0645,
isCa: false
})).deep.equal("12.60 - 64.50 mg")
})).deep.equal("12.6 - 64.5 mg")
})

it("it should NOT display additionalValue", () => {
Expand All @@ -80,7 +91,7 @@ describe("UnitRenderer", () => {
value: 123243342,
additionalValue: 0,
isCa: false
})).deep.equal("123.24 T")
})).deep.equal("123.243 T")
expect(renderUnitIntoString({
value: 9,
additionalValue: 0,
Expand All @@ -90,35 +101,35 @@ describe("UnitRenderer", () => {
value: 0.0126,
additionalValue: 0,
isCa: false
})).deep.equal("12.60 mg")
})).deep.equal("12.6 mg")
})

it("it should format numbers to two numbers after comma", () => {
expect(renderUnitIntoString({
value: 9.123,
additionalValue: 99.1233413,
isCa: false
})).deep.equal("9.12 - 99.12 g")
})).deep.equal("9.123 - 99.123 g")
expect(renderUnitIntoString({
value: 123243342.1233413,
additionalValue: 153474223.1233413,
isCa: false
})).deep.equal("123.24 - 153.47 T")
})).deep.equal("123.243 - 153.474 T")
expect(renderUnitIntoString({
value: 0.273213,
additionalValue: 0.671823,
isCa: false
})).deep.equal("273.21 - 671.82 mg")
})).deep.equal("273.213 - 671.823 mg")
expect(renderUnitIntoString({
value: 0.0126,
additionalValue: 0.0234,
isCa: false
})).deep.equal("12.60 - 23.40 mg")
})).deep.equal("12.6 - 23.4 mg")
expect(renderUnitIntoString({
value: 1,
additionalValue: 100000000,
isCa: false
})).deep.equal("1 - 100.000.000 g")
})).deep.equal("1 - 100,000,000 g")
})

it("it should show high numbers correctly", () => {
Expand Down Expand Up @@ -159,11 +170,16 @@ describe("UnitRenderer", () => {
value: 1,
additionalValue: 100000000,
isCa: false
})).deep.equal("1 - 100.000.000 g")
})).deep.equal("1 - 100,000,000 g")
expect(renderUnitIntoString({
value: 1e38,
additionalValue: 0,
isCa: false
})).deep.equal("100.000.000 Qg")
})).deep.equal("100,000,000 Qg")
expect(renderUnitIntoString({
value: 1000,
additionalValue: 1000000,
isCa: false
})).deep.equal("1 - 1,000 kg")
})
})