diff --git a/app/src/app/[lng]/[inventory]/InventoryResultTab/EmissionsForecast/EmissionsForecastChart.tsx b/app/src/app/[lng]/[inventory]/InventoryResultTab/EmissionsForecast/EmissionsForecastChart.tsx index 71b59a85f..c5e6f7b18 100644 --- a/app/src/app/[lng]/[inventory]/InventoryResultTab/EmissionsForecast/EmissionsForecastChart.tsx +++ b/app/src/app/[lng]/[inventory]/InventoryResultTab/EmissionsForecast/EmissionsForecastChart.tsx @@ -1,20 +1,16 @@ import { EmissionsForecastData } from "@/util/types"; import type { TFunction } from "i18next"; import { - getReferenceNumberByName, getSectorByName, getSectorByReferenceNumber, getSubSectorByName, getSubSectorByReferenceNumber, - ISector, } from "@/util/constants"; -import { Box, Card, Heading, HStack, Table, Text } from "@chakra-ui/react"; -import { convertKgToTonnes, toKebabCase } from "@/util/helpers"; +import { Box } from "@chakra-ui/react"; +import { convertKgToTonnes } from "@/util/helpers"; import { ResponsiveLine } from "@nivo/line"; import CustomLegend from "@/app/[lng]/[inventory]/InventoryResultTab/EmissionsForecast/CustomLegend"; -import { ColoredCircle } from "@/components/ColoredCircle"; -import { ButtonSmall } from "@/components/Texts/Button"; -import { TitleMedium } from "@/components/Texts/Title"; +import TooltipCard from "./TooltipCard"; interface LineChartData { id: string; @@ -93,105 +89,18 @@ export const EmissionsForecastChart = ({ format: (value: number) => convertKgToTonnes(value), }} colors={colors} - tooltip={({ point }) => { - const year = point.data.x; - const sumOfYs = data.reduce((sum, series) => { - const yearData = series.data.find(({ x }) => x === year); - return sum + parseInt((yearData?.y as unknown as string) || "0"); - }, 0); - - return ( - - - {t("year")} - - {year as unknown as string} - - - - - - - - {t("sector").toUpperCase()} - - - {t("rate").toUpperCase()} - - - % - - - - {t("total-emissions").toUpperCase()} - - - - - - {data.map(({ data, id }) => { - const yearData = data.find( - ({ x }) => x === point.data.x, - ); - const percentage = yearData - ? ((yearData.y / sumOfYs) * 100).toFixed(2) - : 0; - const sectorRefNo = - getReferenceNumberByName( - toKebabCase(id as string) as keyof ISector, - ) || getSubSectorByName(id)?.referenceNumber; - - const yearGrowthRates = - yearData && - forecast.growthRates[yearData.x as string]; - const growthRate = - yearGrowthRates?.[sectorRefNo!] || - yearGrowthRates?.[point.serieId as string]; - - return ( - - - - - {t(id)} - - - {growthRate} - {percentage}% - - {convertKgToTonnes( - parseInt(yearData?.y as unknown as string), - )} - - - ); - })} - - - {t("total").toUpperCase()} - - - - - {convertKgToTonnes(sumOfYs)} - - - - - - - - ); - }} + tooltip={({ point }) => ( + + )} + enableSlices="x" + sliceTooltip={({ slice }) => ( + + )} enableGridX={false} enableGridY={false} enablePoints={false} diff --git a/app/src/app/[lng]/[inventory]/InventoryResultTab/EmissionsForecast/TooltipCard.tsx b/app/src/app/[lng]/[inventory]/InventoryResultTab/EmissionsForecast/TooltipCard.tsx new file mode 100644 index 000000000..4c2ebb5e6 --- /dev/null +++ b/app/src/app/[lng]/[inventory]/InventoryResultTab/EmissionsForecast/TooltipCard.tsx @@ -0,0 +1,164 @@ +import React, { useCallback, useEffect, useState } from "react"; +import { Box, Card, Heading, HStack, Table, Text } from "@chakra-ui/react"; +import { convertKgToTonnes, toKebabCase } from "@/util/helpers"; +import { + getReferenceNumberByName, + getSubSectorByName, + ISector, +} from "@/util/constants"; +import { ColoredCircle } from "@/components/ColoredCircle"; +import { ButtonSmall } from "@/components/Texts/Button"; +import { TitleMedium } from "@/components/Texts/Title"; +import { getColorForSeries } from "./EmissionsForecastChart"; +import type { TFunction } from "i18next"; +import { EmissionsForecastData } from "@/util/types"; +import type { Point } from "@nivo/line"; + +interface LineChartData { + id: string; + color: string; + data: { x: string; y: number }[]; +} + +interface TooltipCardProps { + point: Point; + data: LineChartData[]; + forecast: EmissionsForecastData; + t: TFunction; +} + +function debounce(func: Function, wait: number) { + let timeout: NodeJS.Timeout; + return function (this: void, ...args: any[]) { + clearTimeout(timeout); + timeout = setTimeout(() => func.apply(this, args), wait); + }; +} + +const TooltipCard = ({ point, data, forecast, t }: TooltipCardProps) => { + const [containerWidth, setContainerWidth] = useState( + typeof window !== "undefined" ? window.innerWidth : 0, + ); + + const handleResize = useCallback(() => { + setContainerWidth(window.innerWidth); + }, []); + + useEffect(() => { + const debouncedResize = debounce(handleResize, 100); + window.addEventListener("resize", debouncedResize); + return () => { + window.removeEventListener("resize", debouncedResize); + }; + }, [handleResize]); + + const year = point.data.x; + const sumOfYs = data.reduce((sum, series) => { + const yearData = series.data.find(({ x }) => x === year); + return sum + parseInt((yearData?.y as unknown as string) || "0"); + }, 0); + + const xPosition = point.x; + const GRAPH_RATIO = 0.68; + const isLeftHalf = xPosition < (containerWidth * GRAPH_RATIO) / 2; + return ( +
+ + + {t("year")} + + {year as unknown as string} + + + + + + + + {t("sector").toUpperCase()} + + + {t("rate").toUpperCase()} + + + % + + + + {t("total-emissions").toUpperCase()} + + + + + + {data.map(({ data, id }) => { + const yearData = data.find(({ x }) => x === point.data.x); + const percentage = yearData + ? ((yearData.y / sumOfYs) * 100).toFixed(2) + : 0; + const sectorRefNo = + getReferenceNumberByName( + toKebabCase(id as string) as keyof ISector, + ) || getSubSectorByName(id)?.referenceNumber; + + const yearGrowthRates = + yearData && forecast.growthRates[yearData.x as string]; + const growthRate = + yearGrowthRates?.[sectorRefNo!] || + yearGrowthRates?.[point.serieId as string]; + + return ( + + + + + {t(id)} + + + {growthRate} + {percentage}% + + {convertKgToTonnes( + parseInt(yearData?.y as unknown as string), + )} + + + ); + })} + + + {t("total").toUpperCase()} + + + + + {convertKgToTonnes(sumOfYs)} + + + + + + +
+ ); +}; + +export default TooltipCard;