feat: show return, cash and structure on account cards (#114)
Frontend verify / commits (pull_request) Successful in 29s
Frontend verify / security (pull_request) Successful in 8s
Frontend verify / verify (pull_request) Successful in 5m25s
Frontend verify / commits (push) Skipped
Frontend verify / security (push) Successful in 9s
Frontend verify / verify (push) Failing after 5m20s
Frontend verify / commits (pull_request) Successful in 29s
Frontend verify / security (pull_request) Successful in 8s
Frontend verify / verify (pull_request) Successful in 5m25s
Frontend verify / commits (push) Skipped
Frontend verify / security (push) Successful in 9s
Frontend verify / verify (push) Failing after 5m20s
This commit was merged in pull request #116.
This commit is contained in:
@@ -42,6 +42,18 @@ describe("shared display helpers", () => {
|
||||
formatMoney({ currency: "RUB", value: "1.5" }, { withZeroCents: true }),
|
||||
).toBe("1,50 ₽");
|
||||
expect(formatMoney(null)).toBe("—");
|
||||
expect(formatMoney(
|
||||
{ currency: "RUB", value: "136900" },
|
||||
{ withSign: true },
|
||||
)).toBe("+136 900 ₽");
|
||||
expect(formatMoney(
|
||||
{ currency: "RUB", value: "-4200" },
|
||||
{ withSign: true },
|
||||
)).toBe("−4 200 ₽");
|
||||
expect(formatMoney(
|
||||
{ currency: "RUB", value: "-0.00" },
|
||||
{ withSign: true },
|
||||
)).toBe("0,00 ₽");
|
||||
});
|
||||
|
||||
it("builds the brand logo url from an upstream file name", () => {
|
||||
|
||||
@@ -3,9 +3,17 @@ const CENTS_PRECISION = 2;
|
||||
|
||||
type FormatMoneyOptions = {
|
||||
withRoundedCents?: boolean;
|
||||
withSign?: boolean;
|
||||
withZeroCents?: boolean;
|
||||
};
|
||||
|
||||
const portfolioCategoryPresentation = {
|
||||
BOND: { color: "grape.6", label: "portfolio.bonds" },
|
||||
CASH: { color: "green.6", label: "portfolio.structure.cash" },
|
||||
OTHER: { color: "orange.6", label: "portfolio.structure.other" },
|
||||
STOCK: { color: "blue.6", label: "portfolio.stocks" },
|
||||
} as const;
|
||||
|
||||
type Money = { currency: string; value: string };
|
||||
|
||||
const dateFormatter = new Intl.DateTimeFormat("ru-RU", {
|
||||
@@ -40,7 +48,11 @@ function formatMoney(
|
||||
money: Money
|
||||
| null
|
||||
| undefined,
|
||||
{ withRoundedCents = false, withZeroCents = false }: FormatMoneyOptions = {},
|
||||
{
|
||||
withRoundedCents = false,
|
||||
withSign = false,
|
||||
withZeroCents = false,
|
||||
}: FormatMoneyOptions = {},
|
||||
): string {
|
||||
if (!money) return "—";
|
||||
|
||||
@@ -62,8 +74,25 @@ function formatMoney(
|
||||
: integerPart;
|
||||
|
||||
const currency = money.currency === "RUB" ? "₽" : money.currency;
|
||||
const formatted = `${formatDecimal(decimal)} ${currency}`;
|
||||
|
||||
return `${formatDecimal(decimal)} ${currency}`;
|
||||
if (!withSign) return formatted;
|
||||
if (isZeroDecimal(value))
|
||||
return value.startsWith("-") ? formatted.slice(1) : formatted;
|
||||
|
||||
return value.startsWith("-") ? `−${formatted.slice(1)}` : `+${formatted}`;
|
||||
}
|
||||
|
||||
function isZeroDecimal(value: string) {
|
||||
const unsigned = value.startsWith("-") ? value.slice(1) : value;
|
||||
|
||||
const [integer = "", fraction = ""] = unsigned.split(
|
||||
".",
|
||||
DECIMAL_PART_COUNT,
|
||||
);
|
||||
|
||||
return integer.replaceAll("0", "") === ""
|
||||
&& fraction.replaceAll("0", "") === "";
|
||||
}
|
||||
|
||||
function roundDecimalToCents(value: string): string {
|
||||
@@ -116,4 +145,5 @@ export {
|
||||
formatMoney,
|
||||
formatSnapshotTime,
|
||||
instrumentLogoUrl,
|
||||
portfolioCategoryPresentation,
|
||||
};
|
||||
|
||||
@@ -7,6 +7,7 @@ export {
|
||||
formatMoney,
|
||||
formatSnapshotTime,
|
||||
instrumentLogoUrl,
|
||||
portfolioCategoryPresentation,
|
||||
} from "./display";
|
||||
export { useInitialAvailability } from "./initial-availability";
|
||||
export { useUrlPeriod } from "./useUrlPeriod";
|
||||
|
||||
Reference in New Issue
Block a user