From ee9362e71a54a200485e4847f8b762a6f2f8e2b3 Mon Sep 17 00:00:00 2001 From: Limber Mamani <154026979+LimberHope@users.noreply.github.com> Date: Thu, 30 Jan 2025 14:21:47 -0400 Subject: [PATCH] [TM-1605] site landing page progress goals (#858) * [TM-1605] add component to progress and goals pie chart * [TM-1605] add mapping to data charts * [TM-1605] add params to chartData component * [TM-1605] add external component to progress and goals site * [TM-1605] update name chartData * [TM-1605] update styles to tooltip text * [TM-1605] add total trees restored const * [TM-1605] add GoalsAndProgressSiteTab component to overview tab * [TM-1605] update snapshots * [TM-1605] update mapping param * [TM-1605] update ProgressGoalsDoughnutChart component * [TM-1605] change ChartData => ProgressDataCard * [TM-1605] change terrafund => framework --- .../components/ProgressGoalsDoughnutChart.tsx | 92 +++++++++ .../GoalProgressCard/GoalProgressCard.tsx | 25 ++- .../GoalProgressCard.stories.storyshot | 2 + .../components/GoalsAndProgressSiteTab.tsx | 190 ++++++++++++++++++ .../site/[uuid]/tabs/GoalsAndProgress.tsx | 89 +------- src/pages/site/[uuid]/tabs/Overview.tsx | 34 +--- 6 files changed, 302 insertions(+), 130 deletions(-) create mode 100644 src/admin/components/ResourceTabs/MonitoredTab/components/ProgressGoalsDoughnutChart.tsx create mode 100644 src/pages/site/[uuid]/components/GoalsAndProgressSiteTab.tsx diff --git a/src/admin/components/ResourceTabs/MonitoredTab/components/ProgressGoalsDoughnutChart.tsx b/src/admin/components/ResourceTabs/MonitoredTab/components/ProgressGoalsDoughnutChart.tsx new file mode 100644 index 000000000..1cab72c5b --- /dev/null +++ b/src/admin/components/ResourceTabs/MonitoredTab/components/ProgressGoalsDoughnutChart.tsx @@ -0,0 +1,92 @@ +import React from "react"; +import { Cell, Label, Pie, PieChart, ResponsiveContainer } from "recharts"; + +interface ChartDataItem { + name: string; + value: number; +} + +export interface ProgressGoalsData { + chartData: ChartDataItem[]; +} + +interface ProgressGoalsDoughnutChartProps { + data?: ProgressGoalsData; +} +const percentage = (current: number, total: number) => { + const percentValue = Math.min((current / total) * 100, 100); + return percentValue.toFixed(0); +}; + +const ProgressGoalsDoughnutChart: React.FC = ({ data }) => { + const { chartData } = data as any; + + const currentValue = chartData[0]?.value || 0; + const totalValue = chartData[1]?.value || 0; + + const remainingValue = Math.max(totalValue - currentValue, 0); + + const transformedData = + currentValue > totalValue + ? [{ value: 1, isProgress: true }] + : [ + { value: currentValue, isProgress: true }, + { value: remainingValue, isProgress: false } + ]; + const COLORS = ["#27A9E0", "#DFF2FB"]; + + return ( +
+ + + + {totalValue > 0 && ( + + + +
+ ); +}; + +export default ProgressGoalsDoughnutChart; diff --git a/src/components/elements/Cards/GoalProgressCard/GoalProgressCard.tsx b/src/components/elements/Cards/GoalProgressCard/GoalProgressCard.tsx index 73939e398..2fd4c4258 100644 --- a/src/components/elements/Cards/GoalProgressCard/GoalProgressCard.tsx +++ b/src/components/elements/Cards/GoalProgressCard/GoalProgressCard.tsx @@ -1,6 +1,6 @@ import classNames from "classnames"; import { DetailedHTMLProps, FC, HTMLAttributes } from "react"; -import { Else, If, Then, When } from "react-if"; +import { When } from "react-if"; import Text from "@/components/elements/Text/Text"; import { withFrameworkShow } from "@/context/framework.provider"; @@ -22,6 +22,9 @@ export interface GoalProgressCardProps extends DetailedHTMLProps = ({ @@ -38,6 +41,9 @@ const GoalProgressCard: FC = ({ labelVariant, classNameCard, classNameLabelValue, + chart, + hectares = false, + graph = true, ...rest }) => { const value = _val ?? 0; @@ -53,20 +59,13 @@ const GoalProgressCard: FC = ({ {label} - - - - arrow-right - - - arrow-right - - - + {graph ? chart : null} {value?.toLocaleString()}  - - of {limit?.toLocaleString() ?? totalValue?.toLocaleString()} + + + of {limit?.toLocaleString() ?? totalValue?.toLocaleString()} {hectares ? "ha" : null} + {labelValue} diff --git a/src/components/elements/Cards/GoalProgressCard/__snapshots__/GoalProgressCard.stories.storyshot b/src/components/elements/Cards/GoalProgressCard/__snapshots__/GoalProgressCard.stories.storyshot index 60cb08de7..5c2eb30f3 100644 --- a/src/components/elements/Cards/GoalProgressCard/__snapshots__/GoalProgressCard.stories.storyshot +++ b/src/components/elements/Cards/GoalProgressCard/__snapshots__/GoalProgressCard.stories.storyshot @@ -69,6 +69,7 @@ exports[`Storyshots Components/Elements/Cards/GoalProgressCard/Card Progress And > of 732 +

of 150 +

{ + return ( + } + /> + ); +}; + +const GoalsAndProgressSiteTab = ({ site }: GoalsAndProgressSiteTabProps) => { + const t = useT(); + const totaTreesRestoredCount = site?.trees_planted_count + site?.regenerated_trees_count + site?.seeds_planted_count; + const chartDataHectares = { + chartData: [ + { name: t("HECTARES RESTORED"), value: site.total_hectares_restored_sum }, + site.framework_key !== Framework.PPC + ? { + name: t("TOTAL HECTARES RESTORED"), + value: parseFloat(site.hectares_to_restore_goal) + } + : {} + ], + cardValues: { + label: t("HECTARES RESTORED"), + value: site.total_hectares_restored_sum, + totalName: t("TOTAL HECTARES RESTORED"), + totalValue: parseFloat(site.hectares_to_restore_goal) + } + }; + const chartDataTreesRestored = { + chartData: [{ name: t("TREES RESTORED"), value: totaTreesRestoredCount }], + cardValues: { + label: t("TREES RESTORED"), + value: totaTreesRestoredCount + } + }; + const chartDataWorkdays = { + chartData: [ + { + name: t("WORKDAYS CREATED"), + value: site.framework_key == Framework.PPC ? site.combined_workday_count : site.workday_count + } + ], + cardValues: { + label: t("WORKDAYS CREATED"), + value: site.framework_key == Framework.PPC ? site.combined_workday_count : site.workday_count + } + }; + const chartDataSaplings = { + chartData: [{ name: t("SAPLINGS RESTORED"), value: totaTreesRestoredCount }], + cardValues: { + label: t("SAPLINGS RESTORED"), + value: totaTreesRestoredCount + } + }; + + const chartsDataMapping: ChartsData = { + terrafund: [ + , + + ], + ppc: [ + , + , + + ], + hbf: [ + , + , + + ] + }; + const framework = ALL_TF.includes(site.framework_key as Framework) ? "terrafund" : site.framework_key; + return ( +
+ {chartsDataMapping[framework as keyof ChartsData]?.map((chart, index) => ( + {chart} + ))} + +
+ ); +}; +export default GoalsAndProgressSiteTab; diff --git a/src/pages/site/[uuid]/tabs/GoalsAndProgress.tsx b/src/pages/site/[uuid]/tabs/GoalsAndProgress.tsx index 6c4aa4bf2..7aa4cb5de 100644 --- a/src/pages/site/[uuid]/tabs/GoalsAndProgress.tsx +++ b/src/pages/site/[uuid]/tabs/GoalsAndProgress.tsx @@ -1,4 +1,5 @@ import { useT } from "@transifex/react"; +import React from "react"; import { Else, If, Then, When } from "react-if"; import GoalProgressCard from "@/components/elements/Cards/GoalProgressCard/GoalProgressCard"; @@ -11,6 +12,8 @@ import TreeSpeciesTablePD from "@/components/extensive/Tables/TreeSpeciesTablePD import { Framework } from "@/context/framework.provider"; import { TextVariants } from "@/types/common"; +import GoalsAndProgressSiteTab from "../components/GoalsAndProgressSiteTab"; + interface GoalsAndProgressTabProps { site: any; } @@ -109,91 +112,7 @@ const GoalsAndProgressTab = ({ site }: GoalsAndProgressTabProps) => { -
- - - - - - - -
+
diff --git a/src/pages/site/[uuid]/tabs/Overview.tsx b/src/pages/site/[uuid]/tabs/Overview.tsx index 9a9b16eb5..5b0824b5c 100644 --- a/src/pages/site/[uuid]/tabs/Overview.tsx +++ b/src/pages/site/[uuid]/tabs/Overview.tsx @@ -7,7 +7,6 @@ import ModalIdentified from "@/admin/components/extensive/Modal/ModalIdentified" import { AuditLogButtonStates } from "@/admin/components/ResourceTabs/AuditLogTab/constants/enum"; import AddDataButton from "@/admin/components/ResourceTabs/PolygonReviewTab/components/AddDataButton"; import Button from "@/components/elements/Button/Button"; -import GoalProgressCard from "@/components/elements/Cards/GoalProgressCard/GoalProgressCard"; import ItemMonitoringCards from "@/components/elements/Cards/ItemMonitoringCard/ItemMonitoringCards"; import Dropdown from "@/components/elements/Inputs/Dropdown/Dropdown"; import { VARIANT_FILE_INPUT_MODAL_ADD_IMAGES } from "@/components/elements/Inputs/FileInput/FileInputVariants"; @@ -23,7 +22,6 @@ import PageBody from "@/components/extensive/PageElements/Body/PageBody"; import PageCard from "@/components/extensive/PageElements/Card/PageCard"; import PageColumn from "@/components/extensive/PageElements/Column/PageColumn"; import PageRow from "@/components/extensive/PageElements/Row/PageRow"; -import { Framework } from "@/context/framework.provider"; import { useLoading } from "@/context/loaderAdmin.provider"; import { useMapAreaContext } from "@/context/mapArea.provider"; import { useModalContext } from "@/context/modal.provider"; @@ -43,6 +41,7 @@ import { FileType, UploadedFile } from "@/types/common"; import { getErrorMessageFromPayload } from "@/utils/errors"; import Log from "@/utils/log"; +import GoalsAndProgressSiteTab from "../components/GoalsAndProgressSiteTab"; import SiteArea from "../components/SiteArea"; interface SiteOverviewTabProps { @@ -409,36 +408,7 @@ const SiteOverviewTab = ({ site, refetch: refetchEntity }: SiteOverviewTabProps) } > -
-
- - -
-
- -
-
+