diff --git a/app-config.yaml b/app-config.yaml index ef133491af..7064d406f7 100644 --- a/app-config.yaml +++ b/app-config.yaml @@ -372,6 +372,7 @@ auth: myproxy: development: {} costInsights: + baseCurrency: 'EUR' engineerCost: 200000 products: computeEngine: diff --git a/plugins/cost-insights/config.d.ts b/plugins/cost-insights/config.d.ts index 4144b6d6a5..7c725eef8c 100644 --- a/plugins/cost-insights/config.d.ts +++ b/plugins/cost-insights/config.d.ts @@ -21,6 +21,11 @@ export interface Config { */ engineerCost: number; + /** + * @visibility frontend + */ + baseCurrency?: string; + products?: { [kind: string]: { /** diff --git a/plugins/cost-insights/src/components/BarChart/BarChart.test.tsx b/plugins/cost-insights/src/components/BarChart/BarChart.test.tsx index 4e3ca9d78c..530ca16e8f 100644 --- a/plugins/cost-insights/src/components/BarChart/BarChart.test.tsx +++ b/plugins/cost-insights/src/components/BarChart/BarChart.test.tsx @@ -18,7 +18,7 @@ import React from 'react'; import { fireEvent } from '@testing-library/react'; import { BarChart, BarChartProps } from './BarChart'; import { ResourceData } from '../../types'; -import { createMockEntity } from '../../testUtils'; +import { createMockEntity, MockConfigProvider } from '../../testUtils'; import { resourceSort } from '../../utils/sort'; import { renderInTestApp } from '@backstage/test-utils'; @@ -46,11 +46,13 @@ const renderWithProps = ({ resources = MockResources, }: BarChartProps) => { return renderInTestApp( - , + + + , ); }; diff --git a/plugins/cost-insights/src/components/BarChart/BarChart.tsx b/plugins/cost-insights/src/components/BarChart/BarChart.tsx index 4f4dea8ddd..fa97e640bd 100644 --- a/plugins/cost-insights/src/components/BarChart/BarChart.tsx +++ b/plugins/cost-insights/src/components/BarChart/BarChart.tsx @@ -40,20 +40,26 @@ import { notEmpty } from '../../utils/assert'; import { useBarChartStyles } from '../../utils/styles'; import { resourceSort } from '../../utils/sort'; import { isInvalid, titleOf, tooltipItemOf } from '../../utils/graphs'; -import { TooltipRenderer } from '../../types/Tooltip'; +import { TooltipRenderer } from '../../types'; +import { useConfig } from '../../hooks'; -export const defaultTooltip: TooltipRenderer = ({ label, payload = [] }) => { - if (isInvalid({ label, payload })) return null; +const defaultTooltip = (baseCurrency: string) => { + const tooltip: TooltipRenderer = ({ label, payload = [] }) => { + if (isInvalid({ label, payload })) return null; - const title = titleOf(label); - const items = payload.map(tooltipItemOf).filter(notEmpty); - return ( - - {items.map((item, index) => ( - - ))} - - ); + const title = titleOf(label); + const items = payload + .map(p => tooltipItemOf(baseCurrency, p)) + .filter(notEmpty); + return ( + + {items.map((item, index) => ( + + ))} + + ); + }; + return tooltip; }; /** @public */ @@ -69,12 +75,14 @@ export type BarChartProps = { /** @public */ export const BarChart = (props: BarChartProps) => { + const { baseCurrency } = useConfig(); + const { resources, responsive = true, displayAmount = 6, options = {}, - tooltip = defaultTooltip, + tooltip = defaultTooltip(baseCurrency), onClick, onMouseMove, } = props; @@ -164,7 +172,7 @@ export const BarChart = (props: BarChartProps) => { tick={BarChartTick} /> 0, globalResourcesMax]} tick={styles.axis} /> diff --git a/plugins/cost-insights/src/components/BarChart/BarChartLegend.test.tsx b/plugins/cost-insights/src/components/BarChart/BarChartLegend.test.tsx index 07ff144862..690f0bbcd8 100644 --- a/plugins/cost-insights/src/components/BarChart/BarChartLegend.test.tsx +++ b/plugins/cost-insights/src/components/BarChart/BarChartLegend.test.tsx @@ -17,11 +17,14 @@ import React from 'react'; import { renderInTestApp } from '@backstage/test-utils'; import { BarChartLegend } from './BarChartLegend'; +import { MockConfigProvider } from '../../testUtils'; describe('', () => { it(`Should display the correct cost start and end`, async () => { const rendered = await renderInTestApp( - , + + , + , ); expect(rendered.getByText(/\$1,000/)).toBeInTheDocument(); expect(rendered.queryByText(/\$5,000/)).toBeInTheDocument(); diff --git a/plugins/cost-insights/src/components/BarChart/BarChartLegend.tsx b/plugins/cost-insights/src/components/BarChart/BarChartLegend.tsx index 72c3120dd4..becd5467d1 100644 --- a/plugins/cost-insights/src/components/BarChart/BarChartLegend.tsx +++ b/plugins/cost-insights/src/components/BarChart/BarChartLegend.tsx @@ -20,6 +20,7 @@ import { LegendItem } from '../LegendItem'; import { currencyFormatter } from '../../utils/formatters'; import { CostInsightsTheme } from '../../types'; import { useBarChartLayoutStyles as useStyles } from '../../utils/styles'; +import { useConfig } from '../../hooks'; /** @public */ export type BarChartLegendOptions = { @@ -45,6 +46,7 @@ export const BarChartLegend = ( const theme = useTheme(); const classes = useStyles(); + const { baseCurrency } = useConfig(); const data = Object.assign( { @@ -63,7 +65,7 @@ export const BarChartLegend = ( title={data.previousName} markerColor={options.hideMarker ? undefined : data.previousFill} > - {currencyFormatter.format(costStart)} + {currencyFormatter(baseCurrency).format(costStart)} @@ -71,7 +73,7 @@ export const BarChartLegend = ( title={data.currentName} markerColor={options.hideMarker ? undefined : data.currentFill} > - {currencyFormatter.format(costEnd)} + {currencyFormatter(baseCurrency).format(costEnd)} {children} diff --git a/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewBreakdownChart.tsx b/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewBreakdownChart.tsx index 962dc6b332..838da0d1f4 100644 --- a/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewBreakdownChart.tsx +++ b/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewBreakdownChart.tsx @@ -16,41 +16,41 @@ import React, { useState } from 'react'; import { DateTime } from 'luxon'; import { - useTheme, Box, - Typography, Divider, emphasize, + Typography, + useTheme, } from '@material-ui/core'; import { default as FullScreenIcon } from '@material-ui/icons/Fullscreen'; import { + Area, AreaChart, + CartesianGrid, + ResponsiveContainer, + Tooltip as RechartsTooltip, XAxis, YAxis, - Tooltip as RechartsTooltip, - Area, - ResponsiveContainer, - CartesianGrid, } from 'recharts'; -import { Cost, DEFAULT_DATE_FORMAT, CostInsightsTheme } from '../../types'; +import { Cost, CostInsightsTheme, DEFAULT_DATE_FORMAT } from '../../types'; import { + BarChartLegend, BarChartTooltip as Tooltip, BarChartTooltipItem as TooltipItem, - BarChartLegend, } from '../BarChart'; import { - overviewGraphTickFormatter, formatGraphValue, isInvalid, + overviewGraphTickFormatter, } from '../../utils/graphs'; import { useCostOverviewStyles as useStyles } from '../../utils/styles'; -import { useFilters, useLastCompleteBillingDate } from '../../hooks'; +import { useConfig, useFilters, useLastCompleteBillingDate } from '../../hooks'; import { mapFiltersToProps } from './selector'; import { getPreviousPeriodTotalCost } from '../../utils/change'; import { formatPeriod } from '../../utils/formatters'; import { aggregationSum } from '../../utils/sum'; -import { BarChartLegendOptions } from '../BarChart/BarChartLegend'; -import { TooltipRenderer } from '../../types/Tooltip'; +import { BarChartLegendOptions } from '../BarChart'; +import { TooltipRenderer } from '../../types'; export type CostOverviewBreakdownChartProps = { costBreakdown: Cost[]; @@ -65,6 +65,7 @@ export const CostOverviewBreakdownChart = ({ }: CostOverviewBreakdownChartProps) => { const theme = useTheme(); const classes = useStyles(theme); + const { baseCurrency } = useConfig(); const lastCompleteBillingDate = useLastCompleteBillingDate(); const { duration } = useFilters(mapFiltersToProps); const [isExpanded, setExpanded] = useState(false); @@ -187,7 +188,7 @@ export const CostOverviewBreakdownChart = ({ const dateTitle = date.toUTC().toFormat(DEFAULT_DATE_FORMAT); const items = payload.map((p, i) => ({ label: p.dataKey as string, - value: formatGraphValue(Number(p.value), i), + value: formatGraphValue(baseCurrency)(Number(p.value), i), fill: p.color!, })); const expandText = ( @@ -253,7 +254,7 @@ export const CostOverviewBreakdownChart = ({ 0, 'dataMax']} tick={{ fill: classes.axis.fill }} - tickFormatter={formatGraphValue} + tickFormatter={formatGraphValue(baseCurrency)} width={classes.yAxis.width} /> {renderAreas()} diff --git a/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewChart.tsx b/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewChart.tsx index 1c58bf58e6..4232c56ffc 100644 --- a/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewChart.tsx +++ b/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewChart.tsx @@ -48,7 +48,8 @@ import { useCostOverviewStyles as useStyles } from '../../utils/styles'; import { groupByDate, toDataMax, trendFrom } from '../../utils/charts'; import { aggregationSort } from '../../utils/sort'; import { CostOverviewLegend } from './CostOverviewLegend'; -import { TooltipRenderer } from '../../types/Tooltip'; +import { TooltipRenderer } from '../../types'; +import { useConfig } from '../../hooks'; type CostOverviewChartProps = { metric: Maybe; @@ -65,6 +66,7 @@ export const CostOverviewChart = ({ }: CostOverviewChartProps) => { const theme = useTheme(); const styles = useStyles(theme); + const { baseCurrency } = useConfig(); const data = { dailyCost: { @@ -115,8 +117,16 @@ export const CostOverviewChart = ({ : data.metric.name, value: p.dataKey === data.dailyCost.dataKey - ? formatGraphValue(Number(p.value), i, data.dailyCost.format) - : formatGraphValue(Number(p.value), i, data.metric.format), + ? formatGraphValue(baseCurrency)( + Number(p.value), + i, + data.dailyCost.format, + ) + : formatGraphValue(baseCurrency)( + Number(p.value), + i, + data.metric.format, + ), fill: p.dataKey === data.dailyCost.dataKey ? theme.palette.blue @@ -157,7 +167,7 @@ export const CostOverviewChart = ({ 0, 'dataMax']} tick={{ fill: styles.axis.fill }} - tickFormatter={formatGraphValue} + tickFormatter={formatGraphValue(baseCurrency)} width={styles.yAxis.width} yAxisId={data.dailyCost.dataKey} /> diff --git a/plugins/cost-insights/src/components/ProductInsightsCard/ProductEntityDialog.test.tsx b/plugins/cost-insights/src/components/ProductInsightsCard/ProductEntityDialog.test.tsx index d3d12abe74..fef201ec12 100644 --- a/plugins/cost-insights/src/components/ProductInsightsCard/ProductEntityDialog.test.tsx +++ b/plugins/cost-insights/src/components/ProductInsightsCard/ProductEntityDialog.test.tsx @@ -19,6 +19,7 @@ import { wrapInTestApp } from '@backstage/test-utils'; import { ProductEntityDialog } from './ProductEntityDialog'; import { render } from '@testing-library/react'; import { Entity } from '../../types'; +import { MockConfigProvider } from '../../testUtils'; const atomicEntity: Entity = { id: null, @@ -86,11 +87,13 @@ describe('', () => { it('Should show a tab for a single sub-entity type', () => { const { getByText } = render( wrapInTestApp( - , + + + , ), ); expect(getByText('Breakdown by SKU')).toBeInTheDocument(); @@ -99,11 +102,13 @@ describe('', () => { it('Should show tabs when multiple sub-entity types exist', () => { const { getByText } = render( wrapInTestApp( - , + + + , ), ); expect(getByText('Breakdown by SKU')).toBeInTheDocument(); diff --git a/plugins/cost-insights/src/components/ProductInsightsCard/ProductEntityTable.tsx b/plugins/cost-insights/src/components/ProductInsightsCard/ProductEntityTable.tsx index 95ba4f2f2d..0d943d66a5 100644 --- a/plugins/cost-insights/src/components/ProductInsightsCard/ProductEntityTable.tsx +++ b/plugins/cost-insights/src/components/ProductInsightsCard/ProductEntityTable.tsx @@ -22,6 +22,7 @@ import { useEntityDialogStyles as useStyles } from '../../utils/styles'; import { CostGrowthIndicator } from '../CostGrowth'; import { BarChartOptions, ChangeStatistic, Entity } from '../../types'; import { Table, TableColumn } from '@backstage/core-components'; +import { useConfig } from '../../hooks'; export type ProductEntityTableOptions = Partial< Pick @@ -35,7 +36,11 @@ type RowData = { change: ChangeStatistic; }; -function createRenderer(col: keyof RowData, classes: Record) { +function createRenderer( + baseCurrency: string, + col: keyof RowData, + classes: Record, +) { return function render(rowData: {}): JSX.Element { const row = rowData as RowData; const rowStyles = classnames(classes.row, { @@ -49,7 +54,7 @@ function createRenderer(col: keyof RowData, classes: Record) { case 'current': return ( - {costFormatter.format(row[col])} + {costFormatter(baseCurrency).format(row[col])} ); case 'change': @@ -99,6 +104,7 @@ export const ProductEntityTable = ({ options, }: ProductEntityTableProps) => { const classes = useStyles(); + const { baseCurrency } = useConfig(); const entities = entity.entities[entityLabel]; const data = Object.assign( @@ -116,7 +122,7 @@ export const ProductEntityTable = ({ { field: 'label', title: {entityLabel}, - render: createRenderer('label', classes), + render: createRenderer(baseCurrency, 'label', classes), customSort: createSorter('label'), width: '33.33%', }, @@ -126,7 +132,7 @@ export const ProductEntityTable = ({ {data.previousName} ), align: 'right', - render: createRenderer('previous', classes), + render: createRenderer(baseCurrency, 'previous', classes), customSort: createSorter('previous'), }, { @@ -135,14 +141,14 @@ export const ProductEntityTable = ({ {data.currentName} ), align: 'right', - render: createRenderer('current', classes), + render: createRenderer(baseCurrency, 'current', classes), customSort: createSorter('current'), }, { field: 'change', title: Change, align: 'right', - render: createRenderer('change', classes), + render: createRenderer(baseCurrency, 'change', classes), customSort: createSorter('change'), }, ]; diff --git a/plugins/cost-insights/src/components/ProductInsightsCard/ProductInsightsChart.tsx b/plugins/cost-insights/src/components/ProductInsightsCard/ProductInsightsChart.tsx index b77b415e1e..cc11eb40b5 100644 --- a/plugins/cost-insights/src/components/ProductInsightsCard/ProductInsightsChart.tsx +++ b/plugins/cost-insights/src/components/ProductInsightsCard/ProductInsightsChart.tsx @@ -50,7 +50,8 @@ import { } from '../../utils/styles'; import { Duration, Entity, Maybe } from '../../types'; import { choose } from '../../utils/change'; -import { TooltipRenderer } from '../../types/Tooltip'; +import { TooltipRenderer } from '../../types'; +import { useConfig } from '../../hooks'; export type ProductInsightsChartProps = { billingDate: string; @@ -65,6 +66,7 @@ export const ProductInsightsChart = ({ }: ProductInsightsChartProps) => { const classes = useStyles(); const layoutClasses = useLayoutStyles(); + const { baseCurrency } = useConfig(); // Only a single entities Record for the root product entity is supported const entities = useMemo(() => { @@ -131,7 +133,9 @@ export const ProductInsightsChart = ({ const id = label === '' ? null : label; const title = titleOf(label); - const items = payload.map(tooltipItemOf).filter(notEmpty); + const items = payload + .map(p => tooltipItemOf(baseCurrency, p)) + .filter(notEmpty); const activeEntity = findAlways(entities, e => e.id === id); const breakdowns = Object.keys(activeEntity.entities); diff --git a/plugins/cost-insights/src/components/UnlabeledDataflowAlertCard/UnlabeledDataflowAlertCard.test.tsx b/plugins/cost-insights/src/components/UnlabeledDataflowAlertCard/UnlabeledDataflowAlertCard.test.tsx index 06353535a5..3ef6e54a53 100644 --- a/plugins/cost-insights/src/components/UnlabeledDataflowAlertCard/UnlabeledDataflowAlertCard.test.tsx +++ b/plugins/cost-insights/src/components/UnlabeledDataflowAlertCard/UnlabeledDataflowAlertCard.test.tsx @@ -19,6 +19,7 @@ import { UnlabeledDataflowAlertCard } from './UnlabeledDataflowAlertCard'; import { createMockUnlabeledDataflowData, createMockUnlabeledDataflowAlertProject, + MockConfigProvider, } from '../../testUtils'; import { renderInTestApp } from '@backstage/test-utils'; @@ -61,9 +62,11 @@ describe('', () => { 'projects with unlabeled Dataflow jobs in the last 30 days.', ); const rendered = await renderInTestApp( - , + + + , ); expect(rendered.getByText(subheader)).toBeInTheDocument(); }); @@ -71,9 +74,11 @@ describe('', () => { it('renders the correct subheader for a single project', async () => { const subheader = new RegExp('1 project'); const rendered = await renderInTestApp( - , + + + , ); expect(rendered.getByText(subheader)).toBeInTheDocument(); }); diff --git a/plugins/cost-insights/src/hooks/useConfig.tsx b/plugins/cost-insights/src/hooks/useConfig.tsx index 322e1e35f1..ce2681844e 100644 --- a/plugins/cost-insights/src/hooks/useConfig.tsx +++ b/plugins/cost-insights/src/hooks/useConfig.tsx @@ -46,6 +46,7 @@ import { configApiRef, useApi } from '@backstage/core-plugin-api'; * default: true * metricB: * name: Metric B + * baseCurrency: 'EUR' * currencies: * currencyA: * label: Currency A @@ -60,6 +61,7 @@ import { configApiRef, useApi } from '@backstage/core-plugin-api'; /** @public */ export type ConfigContextProps = { + baseCurrency: string; metrics: Metric[]; products: Product[]; icons: Icon[]; @@ -72,6 +74,7 @@ export const ConfigContext = createContext( ); const defaultState: ConfigContextProps = { + baseCurrency: 'USD', metrics: [], products: [], icons: [], @@ -110,6 +113,15 @@ export const ConfigProvider = ({ children }: PropsWithChildren<{}>) => { return []; } + function getBaseCurrency(): string { + const baseCurrency = c.getOptionalString('costInsights.baseCurrency'); + if (baseCurrency) { + return baseCurrency; + } + + return defaultState.baseCurrency; + } + function getCurrencies(): Currency[] { const currencies = c.getOptionalConfig('costInsights.currencies'); if (currencies) { @@ -141,6 +153,7 @@ export const ConfigProvider = ({ children }: PropsWithChildren<{}>) => { } function getConfig() { + const baseCurrency = getBaseCurrency(); const products = getProducts(); const metrics = getMetrics(); const engineerCost = getEngineerCost(); @@ -152,6 +165,7 @@ export const ConfigProvider = ({ children }: PropsWithChildren<{}>) => { setConfig(prevState => ({ ...prevState, + baseCurrency, metrics, products, engineerCost, diff --git a/plugins/cost-insights/src/testUtils/providers.tsx b/plugins/cost-insights/src/testUtils/providers.tsx index 8088fca3c6..764e90d547 100644 --- a/plugins/cost-insights/src/testUtils/providers.tsx +++ b/plugins/cost-insights/src/testUtils/providers.tsx @@ -15,16 +15,13 @@ */ import React, { PropsWithChildren } from 'react'; -import { LoadingContext, LoadingContextProps } from '../hooks/useLoading'; -import { GroupsContext, GroupsContextProps } from '../hooks/useGroups'; -import { FilterContext, FilterContextProps } from '../hooks/useFilters'; -import { ConfigContext, ConfigContextProps } from '../hooks/useConfig'; -import { CurrencyContext, CurrencyContextProps } from '../hooks/useCurrency'; -import { - BillingDateContext, - BillingDateContextProps, -} from '../hooks/useLastCompleteBillingDate'; -import { ScrollContext, ScrollContextProps } from '../hooks/useScroll'; +import { LoadingContext, LoadingContextProps } from '../hooks'; +import { GroupsContext, GroupsContextProps } from '../hooks'; +import { FilterContext, FilterContextProps } from '../hooks'; +import { ConfigContext, ConfigContextProps } from '../hooks'; +import { CurrencyContext, CurrencyContextProps } from '../hooks'; +import { BillingDateContext, BillingDateContextProps } from '../hooks'; +import { ScrollContext, ScrollContextProps } from '../hooks'; import { Group, Duration } from '../types'; export const MockGroups: Group[] = [{ id: 'tech' }, { id: 'mock-group' }]; @@ -85,6 +82,7 @@ export const MockConfigProvider = (props: MockConfigProviderProps) => { const { children, ...context } = props; const defaultContext: ConfigContextProps = { + baseCurrency: 'USD', metrics: [], products: [], icons: [], diff --git a/plugins/cost-insights/src/utils/formatters.test.ts b/plugins/cost-insights/src/utils/formatters.test.ts index 8bf0a6a9d7..87a2b335d9 100644 --- a/plugins/cost-insights/src/utils/formatters.test.ts +++ b/plugins/cost-insights/src/utils/formatters.test.ts @@ -39,7 +39,7 @@ describe('date formatters', () => { 0.00000040925, 0.21, 0.0000004, 0.4139877878, 0.00000234566, ]; const formattedValues = values.map(val => - lengthyCurrencyFormatter.format(val), + lengthyCurrencyFormatter('USD').format(val), ); expect(formattedValues).toEqual([ '$0.00000041', diff --git a/plugins/cost-insights/src/utils/formatters.ts b/plugins/cost-insights/src/utils/formatters.ts index e9b19097a4..4258b1bfce 100644 --- a/plugins/cost-insights/src/utils/formatters.ts +++ b/plugins/cost-insights/src/utils/formatters.ts @@ -17,7 +17,7 @@ import { DateTime, Duration as LuxonDuration } from 'luxon'; import pluralize from 'pluralize'; import { ChangeStatistic, Duration } from '../types'; -import { inclusiveEndDateOf, inclusiveStartDateOf } from '../utils/duration'; +import { inclusiveEndDateOf, inclusiveStartDateOf } from './duration'; import { notEmpty } from './assert'; export type Period = { @@ -25,25 +25,28 @@ export type Period = { periodEnd: string; }; -export const costFormatter = new Intl.NumberFormat('en-US', { - style: 'currency', - currency: 'USD', -}); +export const costFormatter = (currency: string) => + new Intl.NumberFormat('en-US', { + style: 'currency', + currency, + }); -export const currencyFormatter = new Intl.NumberFormat('en-US', { - style: 'currency', - currency: 'USD', - minimumFractionDigits: 0, - maximumFractionDigits: 0, -}); +export const currencyFormatter = (currency: string) => + new Intl.NumberFormat('en-US', { + style: 'currency', + currency, + minimumFractionDigits: 0, + maximumFractionDigits: 0, + }); -export const lengthyCurrencyFormatter = new Intl.NumberFormat('en-US', { - style: 'currency', - currency: 'USD', - minimumFractionDigits: 0, - minimumSignificantDigits: 2, - maximumSignificantDigits: 2, -}); +export const lengthyCurrencyFormatter = (currency: string) => + new Intl.NumberFormat('en-US', { + style: 'currency', + currency, + minimumFractionDigits: 0, + minimumSignificantDigits: 2, + maximumSignificantDigits: 2, + }); export const numberFormatter = new Intl.NumberFormat('en-US', { minimumFractionDigits: 0, diff --git a/plugins/cost-insights/src/utils/graphs.ts b/plugins/cost-insights/src/utils/graphs.ts index 172f6cd7e3..2d63967c82 100644 --- a/plugins/cost-insights/src/utils/graphs.ts +++ b/plugins/cost-insights/src/utils/graphs.ts @@ -23,29 +23,30 @@ import { lengthyCurrencyFormatter, } from './formatters'; -export function formatGraphValue( - value: number, - _index: number, - format?: string, -) { - if (format === 'number') { - return value.toLocaleString(); - } +export const formatGraphValue = + (baseCurrency: string) => + (value: number, _index: number, format?: string) => { + if (format === 'number') { + return value.toLocaleString(); + } - if (value < 1) { - return lengthyCurrencyFormatter.format(value); - } + if (value < 1) { + return lengthyCurrencyFormatter(baseCurrency).format(value); + } - return currencyFormatter.format(value); -} + return currencyFormatter(baseCurrency).format(value); + }; export const overviewGraphTickFormatter = (millis: string | number) => typeof millis === 'number' ? dateFormatter.format(millis) : millis; -export const tooltipItemOf = (payload: Payload) => { +export const tooltipItemOf = ( + baseCurrency: string, + payload: Payload, +) => { const value = typeof payload.value === 'number' - ? currencyFormatter.format(payload.value) + ? currencyFormatter(baseCurrency).format(payload.value) : payload.value; const fill = payload.color as string;