From 3cea852f63bb97f3f72b8eb1e1495545510e6a8f Mon Sep 17 00:00:00 2001 From: Nathan Curtis Date: Tue, 17 Dec 2024 13:58:25 -0800 Subject: [PATCH 01/20] [TM-1527] Update the defaults. --- next.config.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/next.config.js b/next.config.js index 2add3246d..a7f8b6f5e 100644 --- a/next.config.js +++ b/next.config.js @@ -45,8 +45,8 @@ const userSentryWebpackPluginOptions = { // Suppresses source map uploading logs during build silent: true, - org: process.env.SENTRY_ORG || "3-sided-cube", - project: process.env.SENTRY_PROJECT || "wri-web-platform-version-2", + org: process.env.SENTRY_ORG ?? "wri-terramatch", + project: process.env.SENTRY_PROJECT ?? "terramatch-frontend", authToken: process.env.SENTRY_AUTH_TOKEN }; From f445d5604fca6819c18bb0968e05f7794ba9738a Mon Sep 17 00:00:00 2001 From: Dotnara Condori Date: Wed, 18 Dec 2024 15:58:12 -0400 Subject: [PATCH 02/20] [TM-1425] fix error color tag in table monitored (#766) * [TM-1425] fix error color tag in table monitored * [TM-1425] fix error table link --- .../components/Fields/CustomChipField.tsx | 5 +- .../MonitoredTab/components/DataCard.tsx | 290 +++++++++--------- 2 files changed, 151 insertions(+), 144 deletions(-) diff --git a/src/admin/components/Fields/CustomChipField.tsx b/src/admin/components/Fields/CustomChipField.tsx index e0a578304..66f1e51c9 100644 --- a/src/admin/components/Fields/CustomChipField.tsx +++ b/src/admin/components/Fields/CustomChipField.tsx @@ -16,7 +16,10 @@ const STATUS_CLASSNAME_MAP: { [key: string]: string } = { "Needs Info": "bg-tertiary-50 text-tertiary-650", "Needs more information": "bg-tertiary-50 text-tertiary-650", "More info requested": "bg-tertiary-50 text-tertiary-650", - "No Update": "bg-grey-200 text-grey-500" + "No Update": "bg-grey-200 text-grey-500", + approved: "bg-green-30 text-green-100", + submitted: "bg-blue-200 text-blue", + "needs-more-information": "bg-tertiary-50 text-tertiary-650" }; const CustomChipField = ({ diff --git a/src/admin/components/ResourceTabs/MonitoredTab/components/DataCard.tsx b/src/admin/components/ResourceTabs/MonitoredTab/components/DataCard.tsx index ec2e28b5c..3abdfde48 100644 --- a/src/admin/components/ResourceTabs/MonitoredTab/components/DataCard.tsx +++ b/src/admin/components/ResourceTabs/MonitoredTab/components/DataCard.tsx @@ -120,144 +120,6 @@ const COMMON_COLUMNS: ColumnDef[] = [ type CustomColumnDefInternal = ColumnDef & { type?: string }; -const TABLE_COLUMNS_HECTARES_STRATEGY: ColumnDef[] = [ - ...COMMON_COLUMNS, - { - accessorKey: "data.tree_planting", - header: "Tree Planting", - cell: (props: any) => { - const value = props.getValue(); - return value ?? "-"; - }, - meta: { style: { width: "11.95%" } } - }, - { - accessorKey: "data.assisted_natural_regeneration", - header: () => ( - <> - Asst. Nat. -
- Regeneration - - ), - cell: (props: any) => { - const value = props.getValue(); - return value ?? "-"; - }, - meta: { style: { width: "12.09%" } } - }, - { - accessorKey: "data.direct_seeding", - header: () => ( - <> - Direct -
- Seeding - - ), - cell: (props: any) => { - const value = props.getValue(); - return value ?? "-"; - }, - meta: { style: { width: "8.57%" } } - }, - { - accessorKey: "more", - header: "", - enableSorting: false, - cell: props => ( -
- -
- ), - meta: { style: { width: "5%" } } - } -]; - -const TABLE_COLUMNS_HECTARES_ECO_REGION: ColumnDef[] = [ - ...COMMON_COLUMNS, - { - accessorKey: "data.australasian", - header: "Australasian", - cell: (props: any) => { - const value = props.getValue(); - return value ?? "-"; - }, - meta: { style: { width: "11.45%" } } - }, - { - accessorKey: "data.afrotropical", - header: "Afrotropical", - cell: (props: any) => { - const value = props.getValue(); - return value ?? "-"; - }, - meta: { style: { width: "11.05%" } } - }, - { - accessorKey: "data.paleartic", - header: "Paleartic11", - cell: (props: any) => { - const value = props.getValue(); - return value ?? "-"; - }, - meta: { style: { width: "10.33%" } } - }, - { - accessorKey: "more", - header: "", - enableSorting: false, - cell: props => ( -
- -
- ), - meta: { style: { width: "5%" } } - } -]; - -const TABLE_COLUMNS_HECTARES_LAND_USE: ColumnDef[] = [ - ...COMMON_COLUMNS, - { - accessorKey: "data.agroforest", - header: "Agroforest", - cell: (props: any) => { - const value = props.getValue(); - return value ?? "-"; - }, - meta: { style: { width: "11.95%" } } - }, - { - accessorKey: "data.natural_forest", - header: "Natural Forest", - cell: (props: any) => { - const value = props.getValue(); - return value ?? "-"; - }, - meta: { style: { width: "12.09%" } } - }, - { - accessorKey: "data.mangrove", - header: "Mangrove", - cell: (props: any) => { - const value = props.getValue(); - return value ?? "-"; - }, - meta: { style: { width: "8.57%" } } - }, - { - accessorKey: "more", - header: "", - enableSorting: false, - cell: props => ( -
- -
- ), - meta: { style: { width: "5%" } } - } -]; - const DROPDOWN_OPTIONS = [ { title: "Tree Cover Loss", @@ -549,7 +411,9 @@ const DataCard = ({ enableSorting: false, cell: props => (
- +
), meta: { style: { top: `${topHeaderFirstTable}`, borderRadius: "0" } } @@ -558,6 +422,150 @@ const DataCard = ({ } ]; + const TABLE_COLUMNS_HECTARES_STRATEGY: ColumnDef[] = [ + ...COMMON_COLUMNS, + { + accessorKey: "data.tree_planting", + header: "Tree Planting", + cell: (props: any) => { + const value = props.getValue(); + return value ?? "-"; + }, + meta: { style: { width: "11.95%" } } + }, + { + accessorKey: "data.assisted_natural_regeneration", + header: () => ( + <> + Asst. Nat. +
+ Regeneration + + ), + cell: (props: any) => { + const value = props.getValue(); + return value ?? "-"; + }, + meta: { style: { width: "12.09%" } } + }, + { + accessorKey: "data.direct_seeding", + header: () => ( + <> + Direct +
+ Seeding + + ), + cell: (props: any) => { + const value = props.getValue(); + return value ?? "-"; + }, + meta: { style: { width: "8.57%" } } + }, + { + accessorKey: "more", + header: "", + enableSorting: false, + cell: props => ( +
+ +
+ ), + meta: { style: { width: "5%" } } + } + ]; + + const TABLE_COLUMNS_HECTARES_ECO_REGION: ColumnDef[] = [ + ...COMMON_COLUMNS, + { + accessorKey: "data.australasian", + header: "Australasian", + cell: (props: any) => { + const value = props.getValue(); + return value ?? "-"; + }, + meta: { style: { width: "11.45%" } } + }, + { + accessorKey: "data.afrotropical", + header: "Afrotropical", + cell: (props: any) => { + const value = props.getValue(); + return value ?? "-"; + }, + meta: { style: { width: "11.05%" } } + }, + { + accessorKey: "data.paleartic", + header: "Paleartic11", + cell: (props: any) => { + const value = props.getValue(); + return value ?? "-"; + }, + meta: { style: { width: "10.33%" } } + }, + { + accessorKey: "more", + header: "", + enableSorting: false, + cell: props => ( +
+ +
+ ), + meta: { style: { width: "5%" } } + } + ]; + + const TABLE_COLUMNS_HECTARES_LAND_USE: ColumnDef[] = [ + ...COMMON_COLUMNS, + { + accessorKey: "data.agroforest", + header: "Agroforest", + cell: (props: any) => { + const value = props.getValue(); + return value ?? "-"; + }, + meta: { style: { width: "11.95%" } } + }, + { + accessorKey: "data.natural_forest", + header: "Natural Forest", + cell: (props: any) => { + const value = props.getValue(); + return value ?? "-"; + }, + meta: { style: { width: "12.09%" } } + }, + { + accessorKey: "data.mangrove", + header: "Mangrove", + cell: (props: any) => { + const value = props.getValue(); + return value ?? "-"; + }, + meta: { style: { width: "8.57%" } } + }, + { + accessorKey: "more", + header: "", + enableSorting: false, + cell: props => ( +
+ +
+ ), + meta: { style: { width: "5%" } } + } + ]; + const TABLE_COLUMNS_MAPPING: Record = { treeCoverLoss: TABLE_COLUMNS_TREE_COVER_LOSS, treeCoverLossFires: TABLE_COLUMNS_TREE_COVER_LOSS, @@ -636,10 +644,6 @@ const DataCard = ({ classNameWrapper="!overflow-visible" visibleRows={50} border={1} - onRowClick={(row: any) => { - navigate(`${basename}/site/${row?.site_id}/show/1`); - setSelectPolygonFromMap?.({ isOpen: true, uuid: row?.poly_id }); - }} /> From f2becf15bc20f13da3e2da7f1406ef7574d363ce Mon Sep 17 00:00:00 2001 From: Limber Mamani <154026979+LimberHope@users.noreply.github.com> Date: Thu, 19 Dec 2024 10:18:49 -0400 Subject: [PATCH 03/20] [TM-1562] update terrafund report landing pages with new fields (#769) --- .../components/Tables/TreeSpeciesTableTF.tsx | 139 +++++++++++++ .../icons/assisted-natural-regeneration.svg | 8 + .../icons/non-scientific name custom.svg | 9 + src/assets/icons/tree-dashboard.svg | 3 + src/components/elements/Field/TextField.tsx | 6 +- src/components/extensive/Icon/Icon.tsx | 5 +- .../project-report/tabs/TFSocioeconomic.tsx | 192 ++++++++++-------- src/pages/reports/site-report/[uuid].page.tsx | 60 +++++- 8 files changed, 327 insertions(+), 95 deletions(-) create mode 100644 src/admin/components/Tables/TreeSpeciesTableTF.tsx create mode 100644 src/assets/icons/assisted-natural-regeneration.svg create mode 100644 src/assets/icons/non-scientific name custom.svg create mode 100644 src/assets/icons/tree-dashboard.svg diff --git a/src/admin/components/Tables/TreeSpeciesTableTF.tsx b/src/admin/components/Tables/TreeSpeciesTableTF.tsx new file mode 100644 index 000000000..f862292d4 --- /dev/null +++ b/src/admin/components/Tables/TreeSpeciesTableTF.tsx @@ -0,0 +1,139 @@ +import { Card, Divider, Typography } from "@mui/material"; +import { Box, Stack } from "@mui/system"; +import { DataGrid, GridColDef } from "@mui/x-data-grid"; +import { useT } from "@transifex/react"; +import { FC } from "react"; +import { Else, If, Then } from "react-if"; + +import Text from "@/components/elements/Text/Text"; +import Icon, { IconNames } from "@/components/extensive/Icon/Icon"; +import { EstablishmentEntityType } from "@/connections/EstablishmentTrees"; +import { useGetV2TreeSpeciesEntityUUID } from "@/generated/apiComponents"; + +type TreeSpeciesTableTFProps = { + uuid: string; + entity: EstablishmentEntityType; + total?: number; + totalText?: string; + title?: string; + countColumnName?: string; + collection?: string; +}; + +const TreeSpeciesTableTF: FC = ({ + uuid, + entity, + total, + totalText, + title, + countColumnName, + collection = "tree-planted" +}) => { + const t = useT(); + const { data: rows } = useGetV2TreeSpeciesEntityUUID({ + pathParams: { + uuid, + entity: entity?.replace("Report", "-report")! + } + }); + + const columns: GridColDef[] = [ + { + field: "name", + headerName: "SPECIES NAME", + flex: 1, + sortable: false, + filterable: false + }, + { + field: "amount", + headerName: countColumnName ?? "TREE COUNT", + type: "number", + flex: 1, + headerAlign: "left", + align: "left", + sortable: false, + filterable: false + } + ]; + + if (!rows || !rows.data) return null; + + return ( + + + + + {title ?? "N/A"} + + + +
+
+ +
+ + {totalText}: + + + {new Intl.NumberFormat("en-US").format(total!) ?? "N/A"} + +
+
+ + + + 0}> + + row.collection == collection) as any} + columns={columns.map(column => + column.field === "name" + ? { + ...column, + renderCell: params => ( +
+ + {params?.row?.name} + +
+ +
+
+ ) + } + : column + )} + getRowId={row => row.uuid} + sx={{ + border: "none", + "& .MuiDataGrid-columnHeader": { + paddingX: 3 + }, + "& .MuiDataGrid-cell": { + paddingX: 3 + } + }} + pageSizeOptions={[5, 10, 25, 50]} + initialState={{ + pagination: { + paginationModel: { page: 0, pageSize: 5 } + } + }} + /> +
+ + + No {title} Recorded + + +
+
+
+ ); +}; + +export default TreeSpeciesTableTF; diff --git a/src/assets/icons/assisted-natural-regeneration.svg b/src/assets/icons/assisted-natural-regeneration.svg new file mode 100644 index 000000000..fc129bce4 --- /dev/null +++ b/src/assets/icons/assisted-natural-regeneration.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/assets/icons/non-scientific name custom.svg b/src/assets/icons/non-scientific name custom.svg new file mode 100644 index 000000000..e92802b97 --- /dev/null +++ b/src/assets/icons/non-scientific name custom.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/icons/tree-dashboard.svg b/src/assets/icons/tree-dashboard.svg new file mode 100644 index 000000000..db1ba8975 --- /dev/null +++ b/src/assets/icons/tree-dashboard.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/elements/Field/TextField.tsx b/src/components/elements/Field/TextField.tsx index 24fabb75a..344b79e12 100644 --- a/src/components/elements/Field/TextField.tsx +++ b/src/components/elements/Field/TextField.tsx @@ -2,18 +2,20 @@ import { DetailedHTMLProps, FC, HTMLAttributes } from "react"; import Text from "@/components/elements/Text/Text"; import { withFrameworkShow } from "@/context/framework.provider"; +import { TextVariants } from "@/types/common"; import BaseField from "./BaseField"; export interface TextFieldProps extends DetailedHTMLProps, HTMLDivElement> { label: string; value: string; + variantLabel?: TextVariants; } -const TextField: FC = ({ label, value, className, ...rest }) => ( +const TextField: FC = ({ label, value, variantLabel = "text-16-bold", className, ...rest }) => (
- {label} + {label} {value || "N/A"}
diff --git a/src/components/extensive/Icon/Icon.tsx b/src/components/extensive/Icon/Icon.tsx index 8aee895d3..1260acbbf 100644 --- a/src/components/extensive/Icon/Icon.tsx +++ b/src/components/extensive/Icon/Icon.tsx @@ -208,7 +208,10 @@ export enum IconNames { TRASH_TA = "trash-ta", EDIT_TA = "edit-ta", NON_SCIENTIFIC_NAME = "non-scientific name", - NEW_TAG_TREE_SPECIES = "new-tag-tree-species" + NEW_TAG_TREE_SPECIES = "new-tag-tree-species", + NON_SCIENTIFIC_NAME_CUSTOM = "non-scientific name custom", + TREE_DASHABOARD = "tree-dashboard", + ASSISTED_NATURAL_REGENERATION = "assisted-natural-regeneration" } export interface IconProps { diff --git a/src/pages/reports/project-report/tabs/TFSocioeconomic.tsx b/src/pages/reports/project-report/tabs/TFSocioeconomic.tsx index f84fe5b6e..c8c5b5c60 100644 --- a/src/pages/reports/project-report/tabs/TFSocioeconomic.tsx +++ b/src/pages/reports/project-report/tabs/TFSocioeconomic.tsx @@ -3,9 +3,6 @@ import { Fragment } from "react"; import LongTextField from "@/components/elements/Field/LongTextField"; import TextField from "@/components/elements/Field/TextField"; -import FilePreviewCard from "@/components/elements/FilePreviewCard/FilePreviewCard"; -import Table from "@/components/elements/Table/Table"; -import { VARIANT_TABLE_SECONDARY } from "@/components/elements/Table/TableVariants"; import { GRID_VARIANT_GREEN } from "@/components/extensive/DemographicsCollapseGrid/DemographicVariant"; import PageBody from "@/components/extensive/PageElements/Body/PageBody"; import PageCard from "@/components/extensive/PageElements/Card/PageCard"; @@ -15,33 +12,12 @@ import Loader from "@/components/generic/Loading/Loader"; import { ContextCondition } from "@/context/ContextCondition"; import { Framework } from "@/context/framework.provider"; import useDemographicData from "@/hooks/useDemographicData"; -import { downloadFile } from "@/utils/network"; interface ReportOverviewTabProps { report: any; dueAt?: string; } -const BreakdownTable = ({ data }: { data: { name: string; value?: number }[] }) => { - const t = useT(); - - return ( - {t("Count")}, - cell: props => {props.getValue() as string} - } - ]} - data={data.map(item => ({ ...item, value: item.value ?? 0 }))} - /> - ); -}; - const TFSocioeconomicTab = ({ report }: ReportOverviewTabProps) => { const t = useT(); const { grids: gridsDirectWorkdays } = useDemographicData( @@ -60,6 +36,7 @@ const TFSocioeconomicTab = ({ report }: ReportOverviewTabProps) => { "Convergence Workdays", GRID_VARIANT_GREEN ); + const sumTotalJobs = (jobs: Array) => jobs.reduce((acc, key) => acc + (report[key] || 0), 0); return ( @@ -74,36 +51,48 @@ const TFSocioeconomicTab = ({ report }: ReportOverviewTabProps) => { )} {report.new_jobs_description} - - {report.new_jobs_description} - + {report.new_jobs_description} + - + + + + + + + + + + - {report.volunteers_work_description} - + {report.volunteers_work_description} + + + + + + + + + {report.beneficiaries_income_increase_description} + @@ -130,28 +119,82 @@ const TFSocioeconomicTab = ({ report }: ReportOverviewTabProps) => { + + + - {report.beneficiaries_description} - - {report.beneficiaries_income_increase_description} + + {report.beneficiaries_description} - + + + + + + + + + {report.beneficiaries_skills_knowledge_increase_description} - + + + + + + + + + {report.indirect_beneficiaries_description} + + - - {gridsConvergenceWorkdays.length == 0 ? ( @@ -179,27 +222,6 @@ const TFSocioeconomicTab = ({ report }: ReportOverviewTabProps) => { - - - - - - - - - - - {report.socioeconomic_benefits && ( - - {report.socioeconomic_benefits.map((item: any) => ( - downloadFile(f.url)} /> - ))} - - )} - diff --git a/src/pages/reports/site-report/[uuid].page.tsx b/src/pages/reports/site-report/[uuid].page.tsx index 5a77973f5..8cb7ad215 100644 --- a/src/pages/reports/site-report/[uuid].page.tsx +++ b/src/pages/reports/site-report/[uuid].page.tsx @@ -1,3 +1,4 @@ +import { Box } from "@mui/system"; import { useT } from "@transifex/react"; import Head from "next/head"; import Link from "next/link"; @@ -5,6 +6,7 @@ import { useRouter } from "next/router"; import { Fragment } from "react"; import { Else, If, Then, When } from "react-if"; +import TreeSpeciesTableTF from "@/admin/components/Tables/TreeSpeciesTableTF"; import EmptyState from "@/components/elements/EmptyState/EmptyState"; import ButtonField from "@/components/elements/Field/ButtonField"; import GenericField from "@/components/elements/Field/GenericField"; @@ -13,7 +15,7 @@ import TextField from "@/components/elements/Field/TextField"; import Paper from "@/components/elements/Paper/Paper"; import Text from "@/components/elements/Text/Text"; import EntityMapAndGalleryCard from "@/components/extensive/EntityMapAndGalleryCard/EntityMapAndGalleryCard"; -import { IconNames } from "@/components/extensive/Icon/Icon"; +import Icon, { IconNames } from "@/components/extensive/Icon/Icon"; import PageBody from "@/components/extensive/PageElements/Body/PageBody"; import PageBreadcrumbs from "@/components/extensive/PageElements/Breadcrumbs/PageBreadcrumbs"; import PageCard from "@/components/extensive/PageElements/Card/PageCard"; @@ -24,6 +26,7 @@ import SeedingsTable from "@/components/extensive/Tables/SeedingsTable"; import TreeSpeciesTable from "@/components/extensive/Tables/TreeSpeciesTable"; import Loader from "@/components/generic/Loading/Loader"; import LoadingContainer from "@/components/generic/Loading/LoadingContainer"; +import { EstablishmentEntityType } from "@/connections/EstablishmentTrees"; import { COLLECTION_SITE_PAID_OTHER, SITE_WORKDAY_COLLECTIONS } from "@/constants/workdayCollections"; import { ContextCondition } from "@/context/ContextCondition"; import FrameworkProvider, { Framework } from "@/context/framework.provider"; @@ -131,11 +134,57 @@ const SiteReportDetailPage = () => { {siteReport.polygon_status} {siteReport.technical_narrative} - + {siteReport.technical_narrative} {siteReport.public_narrative} - + + + + + + {t("Assisted Natural Regeneration")} + + + +
+
+ +
+ + {t("ESTIMATED NUMBER OF TREES REGENERATING (ON REPORT)")}: + + + {new Intl.NumberFormat("en-US").format(siteReport.total_trees_planted_count!) ?? "N/A"} + +
+
+ + + {t("DESCRIPTION OF ANR ACTIVITIES")}: + + + {siteReport.regeneration_description} + + +
+ { - - {siteReport.polygon_status} - @@ -205,7 +251,7 @@ const SiteReportDetailPage = () => { - + From 2d6f02d20ba0136d3beac02fe9c0fd878f710da6 Mon Sep 17 00:00:00 2001 From: Jorge Monroy Date: Thu, 26 Dec 2024 11:49:41 -0400 Subject: [PATCH 04/20] [TM-1531] add job connection (#745) * [TM-1531] add job service url and script * [TM-1531] apiSlice add job resource * [TM-1531] updates for job service * [TM-1531] sort alphabetical * [TM-1531] add connection for list the delayed jobs * [TM-1531] remove unnecesary code and consistency in selector and API request * [TM-1531] add bulk update call on clear * [TM-1531] add entityname and display data in notification * [TM-1531] use store and display only not acknowledged * [TM-1531] remove from apifetcher call and add continous call for delayed jobs * [TM-1531] rollback apifetcher functionality * [TM-1531] adding message to notification * [TM-1531] display error messages in notifications * [TM-1531] add error messages for failed jobs * [TM-1531] improve connection and remove awaits and asyncs * [TM-1531] changes and remove log * [TM-1531] yarn generate:services * [TM-1531] divide names loading for connections * [TM-1531] running with build * [TM-1531] only send not pending * [TM-1531] fix loaded delayedjobs and filter * [TM-1531] remove logs and unused variable * [TM-1531] join both connections * [TM-1531] transifex and fix selector --- .../ResourceTabs/PolygonReviewTab/index.tsx | 8 +- .../modules/sites/components/SiteShow.tsx | 19 +-- .../MapControls/CheckPolygonControl.tsx | 1 + .../ProcessBulkPolygonsControl.tsx | 3 +- .../Notification/FloatNotification.tsx | 146 ++++++++++++++---- src/connections/DelayedJob.ts | 69 +++++++++ src/context/floatNotification.provider.tsx | 2 +- .../v3/jobService/jobServiceSchemas.ts | 12 ++ src/utils/errors.ts | 22 +++ 9 files changed, 229 insertions(+), 53 deletions(-) create mode 100644 src/connections/DelayedJob.ts diff --git a/src/admin/components/ResourceTabs/PolygonReviewTab/index.tsx b/src/admin/components/ResourceTabs/PolygonReviewTab/index.tsx index 9376b94ce..7550902de 100644 --- a/src/admin/components/ResourceTabs/PolygonReviewTab/index.tsx +++ b/src/admin/components/ResourceTabs/PolygonReviewTab/index.tsx @@ -32,7 +32,6 @@ import { IconNames } from "@/components/extensive/Icon/Icon"; import ModalAdd from "@/components/extensive/Modal/ModalAdd"; import ModalConfirm from "@/components/extensive/Modal/ModalConfirm"; import { ModalId } from "@/components/extensive/Modal/ModalConst"; -import { useLoading } from "@/context/loaderAdmin.provider"; import { useMapAreaContext } from "@/context/mapArea.provider"; import { useModalContext } from "@/context/modal.provider"; import { useMonitoredDataContext } from "@/context/monitoredData.provider"; @@ -153,7 +152,6 @@ const PolygonReviewTab: FC = props => { const [saveFlags, setSaveFlags] = useState(false); const [polygonFromMap, setPolygonFromMap] = useState({ isOpen: false, uuid: "" }); const [errorMessage, setErrorMessage] = useState(null); - const { showLoader, hideLoader } = useLoading(); const { setSelectedPolygonsInCheckbox, setPolygonCriteriaMap, @@ -315,8 +313,7 @@ const PolygonReviewTab: FC = props => { }, [shouldRefetchValidation]); const uploadFiles = async () => { const uploadPromises = []; - showLoader(); - + closeModal(ModalId.ADD_POLYGON); for (const file of files) { const fileToUpload = file.rawFile as File; const site_uuid = record.uuid; @@ -351,10 +348,8 @@ const PolygonReviewTab: FC = props => { } refetch(); refetchSiteBbox(); - closeModal(ModalId.ADD_POLYGON); setPolygonLoaded(false); setSubmitPolygonLoaded(false); - hideLoader(); } catch (error) { let errorMessage; @@ -380,7 +375,6 @@ const PolygonReviewTab: FC = props => { errorMessage = t("An unknown error occurred"); } openNotification("error", t("Error uploading file"), errorMessage || t("An unknown error occurred")); - hideLoader(); } }; diff --git a/src/admin/modules/sites/components/SiteShow.tsx b/src/admin/modules/sites/components/SiteShow.tsx index fb0bef090..7662bf547 100644 --- a/src/admin/modules/sites/components/SiteShow.tsx +++ b/src/admin/modules/sites/components/SiteShow.tsx @@ -1,8 +1,7 @@ -import { FC, useState } from "react"; +import { FC } from "react"; import { Show, TabbedShowLayout } from "react-admin"; import ShowActions from "@/admin/components/Actions/ShowActions"; -import DelayedJobsProgressAlert from "@/admin/components/Alerts/DelayedJobsProgressAlert"; import AuditLogTab from "@/admin/components/ResourceTabs/AuditLogTab/AuditLogTab"; import { AuditLogButtonStates } from "@/admin/components/ResourceTabs/AuditLogTab/constants/enum"; import ChangeRequestsTab from "@/admin/components/ResourceTabs/ChangeRequestsTab/ChangeRequestsTab"; @@ -16,9 +15,6 @@ import { RecordFrameworkProvider } from "@/context/framework.provider"; import { MapAreaProvider } from "@/context/mapArea.provider"; const SiteShow: FC = () => { - const [isLoadingDelayedJob, setIsLoadingDelayedJob] = useState(false); - const [alertTitle, setAlertTitle] = useState(""); - return ( record?.name} />} @@ -30,13 +26,7 @@ const SiteShow: FC = () => { - + @@ -46,11 +36,6 @@ const SiteShow: FC = () => { - ); }; diff --git a/src/components/elements/Map-mapbox/MapControls/CheckPolygonControl.tsx b/src/components/elements/Map-mapbox/MapControls/CheckPolygonControl.tsx index 3c824d575..4d919fe53 100644 --- a/src/components/elements/Map-mapbox/MapControls/CheckPolygonControl.tsx +++ b/src/components/elements/Map-mapbox/MapControls/CheckPolygonControl.tsx @@ -200,6 +200,7 @@ const CheckPolygonControl = (props: CheckSitePolygonProps) => { const runFixPolygonOverlaps = () => { if (siteUuid) { + closeModal(ModalId.FIX_POLYGONS); setIsLoadingDelayedJob?.(true); setAlertTitle?.("Fix Polygons"); clipPolygons({ pathParams: { uuid: siteUuid } }); diff --git a/src/components/elements/Map-mapbox/MapControls/ProcessBulkPolygonsControl.tsx b/src/components/elements/Map-mapbox/MapControls/ProcessBulkPolygonsControl.tsx index d57df4bc9..b267f6622 100644 --- a/src/components/elements/Map-mapbox/MapControls/ProcessBulkPolygonsControl.tsx +++ b/src/components/elements/Map-mapbox/MapControls/ProcessBulkPolygonsControl.tsx @@ -111,6 +111,7 @@ const ProcessBulkPolygonsControl = ({ className: "px-8 py-3", variant: "primary", onClick: () => { + closeModal(ModalId.FIX_POLYGONS); setIsLoadingDelayedJob?.(true); setAlertTitle?.("Fix Polygons"); fixPolygons( @@ -124,7 +125,7 @@ const ProcessBulkPolygonsControl = ({ { onSuccess: response => { const processedNames = response?.processed?.map(item => item.poly_name).join(", "); - closeModal(ModalId.FIX_POLYGONS); + setIsLoadingDelayedJob?.(false); ApiSlice.addTotalContent(0); ApiSlice.addProgressContent(0); diff --git a/src/components/elements/Notification/FloatNotification.tsx b/src/components/elements/Notification/FloatNotification.tsx index 45e6e2af9..19bc31633 100644 --- a/src/components/elements/Notification/FloatNotification.tsx +++ b/src/components/elements/Notification/FloatNotification.tsx @@ -1,8 +1,13 @@ +import { LinearProgress } from "@mui/material"; +import { useT } from "@transifex/react"; import classNames from "classnames"; -import { useState } from "react"; +import { useEffect, useState } from "react"; import { When } from "react-if"; import Icon, { IconNames } from "@/components/extensive/Icon/Icon"; +import { triggerBulkUpdate, useDelayedJobs } from "@/connections/DelayedJob"; +import { DelayedJobData, DelayedJobDto } from "@/generated/v3/jobService/jobServiceSchemas"; +import { getErrorMessageFromPayload } from "@/utils/errors"; import LinearProgressBar from "../ProgressBar/LinearProgressBar/LinearProgressBar"; import Text from "../Text/Text"; @@ -17,8 +22,50 @@ export interface FloatNotificationProps { data: FloatNotificationDataProps[]; } -const FloatNotification = ({ data }: FloatNotificationProps) => { +const FloatNotification = () => { + const t = useT(); const [openModalNotification, setOpenModalNotification] = useState(false); + const [isLoaded, { delayedJobs }] = useDelayedJobs(); + const [notAcknowledgedJobs, setNotAcknowledgedJobs] = useState([]); + const clearJobs = () => { + if (delayedJobs === undefined) return; + const newJobsData: DelayedJobData[] = delayedJobs + .filter((job: DelayedJobDto) => job.status !== "pending") + .map((job: DelayedJobDto) => { + return { + uuid: job.uuid, + type: "delayedJobs", + attributes: { + isAcknowledged: true + } + }; + }); + triggerBulkUpdate(newJobsData); + }; + useEffect(() => { + if (delayedJobs === undefined) return; + const notAcknowledgedJobs = delayedJobs.filter((job: DelayedJobDto) => !job.isAcknowledged); + setNotAcknowledgedJobs(notAcknowledgedJobs); + }, [delayedJobs]); + useEffect(() => { + if (!notAcknowledgedJobs.length) { + setOpenModalNotification(false); + } + }, [notAcknowledgedJobs]); + const listOfPolygonsFixed = (data: Record | null) => { + if (data?.updated_polygons) { + const updatedPolygonNames = data.updated_polygons + ?.map((p: any) => p.poly_name) + .filter(Boolean) + .join(", "); + if (updatedPolygonNames) { + return "Success! The following polygons have been fixed: " + updatedPolygonNames; + } else { + return "No polygons were fixed"; + } + } + return null; + }; return (
@@ -31,43 +78,88 @@ const FloatNotification = ({ data }: FloatNotificationProps) => { )} > - Notifications + {t("Notifications")}
- Actions Taken + {t("Actions Taken")} - - Clear completed + + {t("Clear completed")}
- {data.map((item, index) => ( -
-
-
- - {item.label} - -
- - Site: {item.site} - -
- - - {item.value} + {isLoaded && + notAcknowledgedJobs && + notAcknowledgedJobs.map((item, index) => ( +
+
+
+ + {item.name} + +
+ + Site: {item.entityName} +
+ {item.status === "failed" ? ( + + {item.payload ? t(getErrorMessageFromPayload(item.payload)) : t("Failed to complete")} + + ) : ( +
+ {item.name === "Polygon Upload" && + (item.processedContent === null || item.totalContent === null) && + item.status === "pending" ? ( +
+ +
+ ) : ( + + )} + + {item.name === "Polygon Upload" + ? item.status === "succeeded" + ? t("Done!") + : "" + : item.status === "succeeded" + ? t("Done!") + : `${Math.round(((item.processedContent ?? 0) / (item.totalContent ?? 1)) * 100)}%`} + +
+ )} + + {item.status === "succeeded" && ( + + {listOfPolygonsFixed(item.payload)} + + )} +
-
- ))} + ))}
- 0}> + 0}>
- {data.length} + {notAcknowledgedJobs?.length}
); diff --git a/src/components/extensive/Modal/ModalConfirm.tsx b/src/components/extensive/Modal/ModalConfirm.tsx index b0fa4dd8f..64f8d5823 100644 --- a/src/components/extensive/Modal/ModalConfirm.tsx +++ b/src/components/extensive/Modal/ModalConfirm.tsx @@ -43,7 +43,7 @@ const ModalConfirm: FC = ({ }; return ( - +
{title} diff --git a/src/components/extensive/Modal/__snapshots__/ModalConfirm.stories.storyshot b/src/components/extensive/Modal/__snapshots__/ModalConfirm.stories.storyshot index 65df9f6a5..595f4d86d 100644 --- a/src/components/extensive/Modal/__snapshots__/ModalConfirm.stories.storyshot +++ b/src/components/extensive/Modal/__snapshots__/ModalConfirm.stories.storyshot @@ -5,7 +5,7 @@ exports[`Storyshots Components/Extensive/Modal/ModalConfirm Default 1`] = ` className="flex items-center justify-center bg-primary-400 p-8" >
Date: Mon, 30 Dec 2024 13:01:43 -0400 Subject: [PATCH 07/20] [TM-1592] add floatnotif for PD (#784) --- src/pages/_app.tsx | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index c0d979182..a4a28296e 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -118,18 +118,20 @@ const _App = ({ Component, ...rest }: AppProps) => { - - - - - - - - - - - - + + + + + + + + + + + + + + From 32d04274637650a9929f1335acb31d3a18d68935 Mon Sep 17 00:00:00 2001 From: cesarLima1 <105736261+cesarLima1@users.noreply.github.com> Date: Mon, 30 Dec 2024 16:43:26 -0400 Subject: [PATCH 08/20] [TM-1568] change text for logged users (#785) * [TM-1568] change text for logged users * [TM-1568] move function out * [TM-1568] format numbers --- .../extensive/BlurContainer/BlurContainer.tsx | 43 +++++++++++++++++-- .../extensive/PageElements/Card/PageCard.tsx | 7 ++- src/constants/dashboardConsts.ts | 8 +++- .../charts/CustomLabelRestoration.tsx | 2 +- .../dashboard/components/SecDashboard.tsx | 17 +++----- src/pages/dashboard/index.page.tsx | 9 ++-- src/utils/dashboardUtils.ts | 2 +- 7 files changed, 65 insertions(+), 23 deletions(-) diff --git a/src/components/extensive/BlurContainer/BlurContainer.tsx b/src/components/extensive/BlurContainer/BlurContainer.tsx index 98b2e88dc..fdfec180d 100644 --- a/src/components/extensive/BlurContainer/BlurContainer.tsx +++ b/src/components/extensive/BlurContainer/BlurContainer.tsx @@ -1,17 +1,22 @@ +import { useT } from "@transifex/react"; import React from "react"; import { When } from "react-if"; import { twMerge as tw } from "tailwind-merge"; import Text from "@/components/elements/Text/Text"; +import { TEXT_TYPES } from "@/constants/dashboardConsts"; export interface BlurContainerProps { isBlur: boolean; - textInformation?: string | React.ReactNode; + textType?: string; children: React.ReactNode; className?: string; + logout?: () => void; } -const BlurContainer = ({ isBlur, textInformation, children, className, ...props }: BlurContainerProps) => { +const BlurContainer = ({ isBlur, textType, children, className, logout }: BlurContainerProps) => { + const t = useT(); + if (!isBlur) { return <>{children}; } @@ -31,6 +36,36 @@ const BlurContainer = ({ isBlur, textInformation, children, className, ...props ); + const ProjectAccessText = () => ( + <> + {" "} + with an account associated with this project + + ); + + const NoDataText = () => ( + + {t( + "Data is still being collected and checked. This visual will remain empty until data is properly quality assured." + )} + + ); + + const renderText = () => { + switch (textType) { + case TEXT_TYPES.LOGGED_USER: + return ; + case TEXT_TYPES.NOT_LOGGED_USER: + return ; + case TEXT_TYPES.NO_DATA: + return ; + default: + return null; + } + }; + return (
- + - {typeof textInformation === "string" ? textInformation : } + {renderText()}
diff --git a/src/components/extensive/PageElements/Card/PageCard.tsx b/src/components/extensive/PageElements/Card/PageCard.tsx index 4336ad5ac..2c0612a15 100644 --- a/src/components/extensive/PageElements/Card/PageCard.tsx +++ b/src/components/extensive/PageElements/Card/PageCard.tsx @@ -9,7 +9,7 @@ import Paper from "@/components/elements/Paper/Paper"; import Text from "@/components/elements/Text/Text"; import ToolTip from "@/components/elements/Tooltip/Tooltip"; import { useMyUser } from "@/connections/User"; -import { NO_DATA_INFORMATION } from "@/constants/dashboardConsts"; +import { TEXT_TYPES } from "@/constants/dashboardConsts"; import { withFrameworkShow } from "@/context/framework.provider"; import { TextVariants } from "@/types/common"; @@ -70,7 +70,10 @@ const PageCard = ({ return ( - }> +
diff --git a/src/constants/dashboardConsts.ts b/src/constants/dashboardConsts.ts index 71f1f109e..3de691340 100644 --- a/src/constants/dashboardConsts.ts +++ b/src/constants/dashboardConsts.ts @@ -38,10 +38,14 @@ export const ORGANIZATIONS_TYPES = { "for-profit-organization": "Enterprise" }; -export const NO_DATA_INFORMATION = "No data available. You may not have permission to view the project profile."; - export const TERRAFUND_MONITORING_LINK = "https://www.wri.org/update/land-degradation-project-recipe-for-restoration"; +export const TEXT_TYPES = { + LOGGED_USER: "textForLoggedUser", + NOT_LOGGED_USER: "textForNotLoggedUser", + NO_DATA: "noData" +}; + export const TERRAFUND_MRV_LINK = `TerraFund's MRV framework`; export const DEFAULT_POLYGONS_DATA = { diff --git a/src/pages/dashboard/charts/CustomLabelRestoration.tsx b/src/pages/dashboard/charts/CustomLabelRestoration.tsx index 8f30d1271..2b33e8ee6 100644 --- a/src/pages/dashboard/charts/CustomLabelRestoration.tsx +++ b/src/pages/dashboard/charts/CustomLabelRestoration.tsx @@ -14,7 +14,7 @@ export const CustomLabel: React.FC = props => { dominantBaseline={isSmallBar ? "bottom" : "middle"} className="text-12" > - {`${value.toFixed(0)} ha`} + {`${Math.round(value).toLocaleString()} ha`} ); }; diff --git a/src/pages/dashboard/components/SecDashboard.tsx b/src/pages/dashboard/components/SecDashboard.tsx index fcdc432e8..77060009e 100644 --- a/src/pages/dashboard/components/SecDashboard.tsx +++ b/src/pages/dashboard/components/SecDashboard.tsx @@ -18,7 +18,8 @@ import { DUMMY_DATA_FOR_CHART_GROUPED_BAR_CHART_GENDER, DUMMY_DATA_FOR_CHART_MULTI_LINE_CHART, DUMMY_DATA_FOR_CHART_SIMPLE_BAR_CHART, - DUMMY_DATA_TARGET_LAND_USE_TYPES_REPRESENTED + DUMMY_DATA_TARGET_LAND_USE_TYPES_REPRESENTED, + TEXT_TYPES } from "@/constants/dashboardConsts"; import { TextVariants } from "@/types/common"; import { getRestorationGoalDataForChart, getRestorationGoalResumeData, isEmptyChartData } from "@/utils/dashboardUtils"; @@ -84,10 +85,6 @@ const SecDashboard = ({ const [treesPlantedByYear, setTreesPlantedByYear] = useState<{ name: string; values: any }[]>([]); const t = useT(); - const noDataInformation = t( - "Data is still being collected and checked. This visual will remain empty until data is properly quality assured." - ); - const tableColumns = [ { header: isTableProject ? "Organization" : "Specie", @@ -179,7 +176,7 @@ const SecDashboard = ({ { const t = useT(); const [, { user }] = useMyUser(); + const logout = useLogout(); const { filters, setFilters, frameworks } = useDashboardContext(); const { dashboardHeader, @@ -296,7 +298,8 @@ const Dashboard = () => { } + textType={user !== undefined ? TEXT_TYPES.LOGGED_USER : TEXT_TYPES.NOT_LOGGED_USER} + logout={logout} >
{dashboardHeader.map((item, index) => ( diff --git a/src/utils/dashboardUtils.ts b/src/utils/dashboardUtils.ts index d3b339c61..dc6a004ae 100644 --- a/src/utils/dashboardUtils.ts +++ b/src/utils/dashboardUtils.ts @@ -354,7 +354,7 @@ export const parseHectaresUnderRestorationData = ( const formatValueText = (value: number): string => { if (!total_hectares_restored) return "0 ha 0%"; const percentage = (value / total_hectares_restored) * 100; - return `${value.toFixed(0)} ha ${percentage.toFixed(2)}%`; + return `${Math.round(value).toLocaleString()} ha ${percentage.toFixed(0)}%`; }; const getLandUseTypeTitle = (value: string): string => { From b918ed7ec748d56ce9ad0d14b2e49e7aaa15b5c5 Mon Sep 17 00:00:00 2001 From: Jorge Monroy Date: Tue, 31 Dec 2024 10:48:36 -0400 Subject: [PATCH 09/20] [TM-1592] remove loader (#786) --- src/pages/site/[uuid]/tabs/Overview.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/pages/site/[uuid]/tabs/Overview.tsx b/src/pages/site/[uuid]/tabs/Overview.tsx index 2a436bcce..a265e61bd 100644 --- a/src/pages/site/[uuid]/tabs/Overview.tsx +++ b/src/pages/site/[uuid]/tabs/Overview.tsx @@ -96,7 +96,7 @@ const SiteOverviewTab = ({ site, refetch: refetchEntity }: SiteOverviewTabProps) const [files, setFiles] = useState([]); const [saveFlags, setSaveFlags] = useState(false); const { openNotification } = useNotificationContext(); - const { showLoader, hideLoader } = useLoading(); + const { hideLoader } = useLoading(); const [polygonLoaded, setPolygonLoaded] = useState(false); const [submitPolygonLoaded, setSubmitPolygonLoaded] = useState(false); @@ -138,7 +138,6 @@ const SiteOverviewTab = ({ site, refetch: refetchEntity }: SiteOverviewTabProps) formData.append("polygon_loaded", polygonLoaded.toString()); formData.append("submit_polygon_loaded", submitPolygonLoaded.toString()); let newRequest: any = formData; - showLoader(); switch (fileType) { case "geojson": uploadPromises.push(fetchPostV2TerrafundUploadGeojson({ body: newRequest })); @@ -202,7 +201,6 @@ const SiteOverviewTab = ({ site, refetch: refetchEntity }: SiteOverviewTabProps) variant: "primary", onClick: () => { setSaveFlags(true); - showLoader(); } }} acceptedTypes={FileType.AcceptedShapefiles.split(",") as FileType[]} From 3381ab5dc95fa580b48366b3d4ba07823bfb9a61 Mon Sep 17 00:00:00 2001 From: cesarLima1 <105736261+cesarLima1@users.noreply.github.com> Date: Tue, 31 Dec 2024 13:00:31 -0400 Subject: [PATCH 10/20] use new endpoint to avoid multiples request for validation data (#787) --- src/generated/apiComponents.ts | 106 +++++++++++++++++++++ src/generated/apiSchemas.ts | 39 ++++++++ src/hooks/paginated/useLoadCriteriaSite.ts | 23 +++-- 3 files changed, 158 insertions(+), 10 deletions(-) diff --git a/src/generated/apiComponents.ts b/src/generated/apiComponents.ts index a4e07fa0b..de7f64f19 100644 --- a/src/generated/apiComponents.ts +++ b/src/generated/apiComponents.ts @@ -32675,6 +32675,112 @@ export const useGetV2TerrafundValidationCriteriaData = ; + +export type PostV2TerrafundValidationCriteriaDataResponse = { + [key: string]: + | { + /** + * The ID of the polygon + */ + polygon_id: string; + /** + * List of validation criteria + */ + criteria_list: { + /** + * The ID of the criteria + */ + criteria_id?: number; + /** + * The latest created at timestamp of the criteria + * + * @format date-time + */ + latest_created_at?: string; + /** + * Indicates if the criteria is valid or not (1 for valid, 0 for invalid) + */ + valid?: number; + /** + * Extra information about the polygon validation + */ + extra_info?: Record; + }[]; + } + | { + /** + * Error message if the polygon or criteria data is not found + */ + error: string; + }; +}; + +export type PostV2TerrafundValidationCriteriaDataRequestBody = { + /** + * A list of UUIDs of the polygons + */ + uuids?: string[]; +}; + +export type PostV2TerrafundValidationCriteriaDataVariables = { + body?: PostV2TerrafundValidationCriteriaDataRequestBody; +} & ApiContext["fetcherOptions"]; + +export const fetchPostV2TerrafundValidationCriteriaData = ( + variables: PostV2TerrafundValidationCriteriaDataVariables, + signal?: AbortSignal +) => + apiFetch< + PostV2TerrafundValidationCriteriaDataResponse, + PostV2TerrafundValidationCriteriaDataError, + PostV2TerrafundValidationCriteriaDataRequestBody, + {}, + {}, + {} + >({ url: "/v2/terrafund/validation/criteria-data", method: "post", ...variables, signal }); + +export const usePostV2TerrafundValidationCriteriaData = ( + options?: Omit< + reactQuery.UseMutationOptions< + PostV2TerrafundValidationCriteriaDataResponse, + PostV2TerrafundValidationCriteriaDataError, + PostV2TerrafundValidationCriteriaDataVariables + >, + "mutationFn" + > +) => { + const { fetcherOptions } = useApiContext(); + return reactQuery.useMutation< + PostV2TerrafundValidationCriteriaDataResponse, + PostV2TerrafundValidationCriteriaDataError, + PostV2TerrafundValidationCriteriaDataVariables + >( + (variables: PostV2TerrafundValidationCriteriaDataVariables) => + fetchPostV2TerrafundValidationCriteriaData({ ...fetcherOptions, ...variables }), + options + ); +}; + export type PostV2TerrafundValidationSitePolygonsQueryParams = { /** * The UUID of the polygon diff --git a/src/generated/apiSchemas.ts b/src/generated/apiSchemas.ts index c68f2fe35..63f086d25 100644 --- a/src/generated/apiSchemas.ts +++ b/src/generated/apiSchemas.ts @@ -22441,6 +22441,45 @@ export type V2TerrafundCriteriaData = { }[]; }; +export type V2TerrafundCriteriaDataMultiple = { + [key: string]: + | { + /** + * The ID of the polygon + */ + polygon_id: string; + /** + * List of validation criteria + */ + criteria_list: { + /** + * The ID of the criteria + */ + criteria_id?: number; + /** + * The latest created at timestamp of the criteria + * + * @format date-time + */ + latest_created_at?: string; + /** + * Indicates if the criteria is valid or not (1 for valid, 0 for invalid) + */ + valid?: number; + /** + * Extra information about the polygon validation + */ + extra_info?: Record; + }[]; + } + | { + /** + * Error message if the polygon or criteria data is not found + */ + error: string; + }; +}; + export type V2TerrafundCriteriaSite = { /** * The UUID of the polygon. diff --git a/src/hooks/paginated/useLoadCriteriaSite.ts b/src/hooks/paginated/useLoadCriteriaSite.ts index e8f437cd6..be82cce6f 100644 --- a/src/hooks/paginated/useLoadCriteriaSite.ts +++ b/src/hooks/paginated/useLoadCriteriaSite.ts @@ -3,7 +3,7 @@ import { useEffect, useState } from "react"; import { fetchGetV2EntityPolygons, fetchGetV2EntityPolygonsCount, - fetchGetV2TerrafundValidationCriteriaData + fetchPostV2TerrafundValidationCriteriaData } from "@/generated/apiComponents"; interface LoadCriteriaSiteHook { @@ -13,7 +13,7 @@ interface LoadCriteriaSiteHook { progress: number; polygonCriteriaMap: Record; refetch: () => void; - fetchCriteriaData: (uuid: string) => void; + fetchCriteriaData: (uuids: string[]) => void; loadCriteriaInOrder: () => void; } @@ -61,9 +61,8 @@ const useLoadCriteriaSite = ( const partialResponse = (await fetchGetV2EntityPolygons({ queryParams })) as any; - for (const polygon of partialResponse) { - await fetchCriteriaData(polygon.poly_id); - } + const polyUuids = partialResponse.map((polygon: any) => polygon.poly_id); + await fetchCriteriaData(polyUuids); result = result.concat(partialResponse); setData(result as any); if (offset + limit > count!) { @@ -84,15 +83,19 @@ const useLoadCriteriaSite = ( loadInBatches(); }; - const fetchCriteriaData = async (uuid: string) => { - const criteriaData = await fetchGetV2TerrafundValidationCriteriaData({ - queryParams: { - uuid: uuid + const fetchCriteriaData = async (polyUuids: string[]) => { + const criteriaData = await fetchPostV2TerrafundValidationCriteriaData({ + body: { + uuids: polyUuids } }); setPolygonCriteriaMap(prev => { const newMap = { ...prev }; - newMap[uuid] = criteriaData; + polyUuids.forEach(uuid => { + if (criteriaData[uuid]) { + newMap[uuid] = criteriaData[uuid]; + } + }); return newMap; }); }; From 5ab8b12a0e30e74972f0e8acb446ece61d9f6484 Mon Sep 17 00:00:00 2001 From: Dotnara Condori Date: Thu, 2 Jan 2025 12:14:12 -0400 Subject: [PATCH 11/20] [TM-1514] WEB DESIGN: Update project developer pages with enhanced species data (#788) * [TM-1514] add style in page species data * [TM-1514] update snapshots * [TM-1514] fix build * [TM-1514] fix build * [TM-1514] fix build * [TM-1514] change icons style and add tooltips in table in tree species * [TM-1514] update stories * [TM-1514] fix build --------- Co-authored-by: diego-morales-flores-1996 --- public/images/graphic-2.png | Bin 8808 -> 27656 bytes public/images/graphic-5.png | Bin 5071 -> 5674 bytes src/assets/icons/leaf-circle_pd.svg | 16 + src/assets/icons/leaf-native-circle_pd.svg | 11 + src/assets/icons/leaf-planted-circle_pd.svg | 16 + src/assets/icons/native-species.svg | 3 + .../icons/new-tag-tree-species-custom.svg | 8 + src/assets/icons/non-trees-planted-circle.svg | 16 + src/assets/icons/non-trees-planted.svg | 8 + src/assets/icons/refresh-circle_pd.svg | 16 + src/assets/icons/seed-planted.svg | 8 + src/assets/icons/survival-rate.svg | 16 + src/assets/icons/tree-circle-pd.svg | 16 + src/assets/icons/trees-regenerating.svg | 8 + .../GoalProgressCard/GoalProgressCard.tsx | 33 +- .../GoalProgressCard/GoalProgressCardItem.tsx | 38 +- .../GoalProgressCard.stories.storyshot | 20 +- .../GoalProgressCardItem.stories.storyshot | 2 +- .../ItemMonitoringCard.stories.storyshot | 18 +- .../elements/Table/TableVariants.ts | 11 + src/components/elements/Tooltip/Tooltip.tsx | 30 +- .../__snapshots__/Tooltip.stories.storyshot | 18 +- src/components/extensive/Icon/Icon.tsx | 14 +- .../extensive/Tables/TreeSpeciesTablePD.tsx | 221 ++++++ .../project/[uuid]/tabs/GoalsAndProgress.tsx | 673 ++++++++++++++++-- src/pages/reports/site-report/[uuid].page.tsx | 201 +++++- .../site/[uuid]/tabs/GoalsAndProgress.tsx | 401 +++++++++-- tailwind.config.js | 2 + 28 files changed, 1631 insertions(+), 193 deletions(-) create mode 100644 src/assets/icons/leaf-circle_pd.svg create mode 100644 src/assets/icons/leaf-native-circle_pd.svg create mode 100644 src/assets/icons/leaf-planted-circle_pd.svg create mode 100644 src/assets/icons/native-species.svg create mode 100644 src/assets/icons/new-tag-tree-species-custom.svg create mode 100644 src/assets/icons/non-trees-planted-circle.svg create mode 100644 src/assets/icons/non-trees-planted.svg create mode 100644 src/assets/icons/refresh-circle_pd.svg create mode 100644 src/assets/icons/seed-planted.svg create mode 100644 src/assets/icons/survival-rate.svg create mode 100644 src/assets/icons/tree-circle-pd.svg create mode 100644 src/assets/icons/trees-regenerating.svg create mode 100644 src/components/extensive/Tables/TreeSpeciesTablePD.tsx diff --git a/public/images/graphic-2.png b/public/images/graphic-2.png index 9a61624d1be3dc4164affe494a518887642ca2aa..6a2df90c1b77542ee3b80b039b634d175e55d312 100644 GIT binary patch literal 27656 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 mv#=WIsQ#t=F@uyhN8PF-WM! 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 VS`cs~<$L}`>uBn0l&IOf`CrkZrF{SZ diff --git a/public/images/graphic-5.png b/public/images/graphic-5.png index a91366c846af20cc0e2d27567bea3a7c0b0c6cae..dadc650d432cd2563c9c5aa928763f74689b0b09 100644 GIT binary patch literal 5674 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 Q=>Px#07*qoM6N<$f~47~IsgCw delta 5067 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 diff --git a/src/assets/icons/leaf-circle_pd.svg b/src/assets/icons/leaf-circle_pd.svg new file mode 100644 index 000000000..42a6c7ed1 --- /dev/null +++ b/src/assets/icons/leaf-circle_pd.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/src/assets/icons/leaf-native-circle_pd.svg b/src/assets/icons/leaf-native-circle_pd.svg new file mode 100644 index 000000000..0a676c4fd --- /dev/null +++ b/src/assets/icons/leaf-native-circle_pd.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/assets/icons/leaf-planted-circle_pd.svg b/src/assets/icons/leaf-planted-circle_pd.svg new file mode 100644 index 000000000..b43380f13 --- /dev/null +++ b/src/assets/icons/leaf-planted-circle_pd.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/src/assets/icons/native-species.svg b/src/assets/icons/native-species.svg new file mode 100644 index 000000000..2a29fb325 --- /dev/null +++ b/src/assets/icons/native-species.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/new-tag-tree-species-custom.svg b/src/assets/icons/new-tag-tree-species-custom.svg new file mode 100644 index 000000000..7804dfd4a --- /dev/null +++ b/src/assets/icons/new-tag-tree-species-custom.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/assets/icons/non-trees-planted-circle.svg b/src/assets/icons/non-trees-planted-circle.svg new file mode 100644 index 000000000..fbfb66999 --- /dev/null +++ b/src/assets/icons/non-trees-planted-circle.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/src/assets/icons/non-trees-planted.svg b/src/assets/icons/non-trees-planted.svg new file mode 100644 index 000000000..6019c7be3 --- /dev/null +++ b/src/assets/icons/non-trees-planted.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/assets/icons/refresh-circle_pd.svg b/src/assets/icons/refresh-circle_pd.svg new file mode 100644 index 000000000..cf952dc6d --- /dev/null +++ b/src/assets/icons/refresh-circle_pd.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/src/assets/icons/seed-planted.svg b/src/assets/icons/seed-planted.svg new file mode 100644 index 000000000..a7723fa88 --- /dev/null +++ b/src/assets/icons/seed-planted.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/assets/icons/survival-rate.svg b/src/assets/icons/survival-rate.svg new file mode 100644 index 000000000..ec6a118f0 --- /dev/null +++ b/src/assets/icons/survival-rate.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/src/assets/icons/tree-circle-pd.svg b/src/assets/icons/tree-circle-pd.svg new file mode 100644 index 000000000..934676b45 --- /dev/null +++ b/src/assets/icons/tree-circle-pd.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/src/assets/icons/trees-regenerating.svg b/src/assets/icons/trees-regenerating.svg new file mode 100644 index 000000000..91e624540 --- /dev/null +++ b/src/assets/icons/trees-regenerating.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/components/elements/Cards/GoalProgressCard/GoalProgressCard.tsx b/src/components/elements/Cards/GoalProgressCard/GoalProgressCard.tsx index dfa87f3f4..b29536d87 100644 --- a/src/components/elements/Cards/GoalProgressCard/GoalProgressCard.tsx +++ b/src/components/elements/Cards/GoalProgressCard/GoalProgressCard.tsx @@ -4,6 +4,7 @@ import { When } from "react-if"; import Text from "@/components/elements/Text/Text"; import { withFrameworkShow } from "@/context/framework.provider"; +import { TextVariants } from "@/types/common"; import LinearProgressBar from "../../ProgressBar/LinearProgressBar/LinearProgressBar"; import GoalProgressCardItem, { GoalProgressCardItemProps } from "./GoalProgressCardItem"; @@ -11,11 +12,16 @@ import GoalProgressCardItem, { GoalProgressCardItemProps } from "./GoalProgressC export interface GoalProgressCardProps extends DetailedHTMLProps, HTMLDivElement> { value?: number; limit?: number; - label: string; + label?: string; items?: GoalProgressCardItemProps[]; hasProgress?: boolean; progressBarValue?: number; labelValue?: string; + totalValue?: string | number; + classNameLabel?: string; + labelVariant?: TextVariants; + classNameCard?: string; + classNameLabelValue?: string; } const GoalProgressCard: FC = ({ @@ -27,6 +33,11 @@ const GoalProgressCard: FC = ({ hasProgress = true, className, labelValue, + totalValue, + classNameLabel, + labelVariant, + classNameCard, + classNameLabelValue, ...rest }) => { const value = _val ?? 0; @@ -38,17 +49,23 @@ const GoalProgressCard: FC = ({
{/* Left */} -
- +
+ {label} - + + arrow-right + + {value?.toLocaleString()}  - - of {limit?.toLocaleString()} + + of {limit?.toLocaleString() ?? totalValue?.toLocaleString()} + + + {labelValue} - {labelValue} + = ({ {/* Right */} {items && ( -
+
{items.map(item => ( ))} diff --git a/src/components/elements/Cards/GoalProgressCard/GoalProgressCardItem.tsx b/src/components/elements/Cards/GoalProgressCard/GoalProgressCardItem.tsx index 639de32e1..66cbe1857 100644 --- a/src/components/elements/Cards/GoalProgressCard/GoalProgressCardItem.tsx +++ b/src/components/elements/Cards/GoalProgressCard/GoalProgressCardItem.tsx @@ -1,26 +1,54 @@ +import { useT } from "@transifex/react"; import classNames from "classnames"; import { DetailedHTMLProps, FC, HTMLAttributes } from "react"; +import { When } from "react-if"; import Text from "@/components/elements/Text/Text"; import Icon, { IconNames } from "@/components/extensive/Icon/Icon"; +import { TextVariants } from "@/types/common"; export interface GoalProgressCardItemProps extends DetailedHTMLProps, HTMLDivElement> { iconName: IconNames; label: string; - value: number; + value: number | string; + classNameLabel?: string; + classNameLabelValue?: string; + variantLabel?: TextVariants; + limit?: number; } -const GoalProgressCardItem: FC = ({ iconName, label, value: _val, className, ...rest }) => { +const GoalProgressCardItem: FC = ({ + iconName, + label, + value: _val, + className, + classNameLabel, + classNameLabelValue, + variantLabel, + limit, + ...rest +}) => { + const t = useT(); const value = _val || 0; return (
- + - + {label} - {value?.toLocaleString()} + + {value?.toLocaleString()} + + + {t("of")} {limit} + + +
); }; diff --git a/src/components/elements/Cards/GoalProgressCard/__snapshots__/GoalProgressCard.stories.storyshot b/src/components/elements/Cards/GoalProgressCard/__snapshots__/GoalProgressCard.stories.storyshot index 2d1120327..8fb1ab493 100644 --- a/src/components/elements/Cards/GoalProgressCard/__snapshots__/GoalProgressCard.stories.storyshot +++ b/src/components/elements/Cards/GoalProgressCard/__snapshots__/GoalProgressCard.stories.storyshot @@ -22,10 +22,6 @@ exports[`Storyshots Components/Elements/Cards/GoalProgressCard/Card No Progress > 150   -

-

23 @@ -138,7 +130,7 @@ exports[`Storyshots Components/Elements/Cards/GoalProgressCard/Card Progress And Trees Planed

1,332 @@ -162,7 +154,7 @@ exports[`Storyshots Components/Elements/Cards/GoalProgressCard/Card Progress And Trash Removed

530,000 @@ -202,10 +194,6 @@ exports[`Storyshots Components/Elements/Cards/GoalProgressCard/Card Progress No of 150

-

530,000 diff --git a/src/components/elements/Cards/ItemMonitoringCard/__snapshots__/ItemMonitoringCard.stories.storyshot b/src/components/elements/Cards/ItemMonitoringCard/__snapshots__/ItemMonitoringCard.stories.storyshot index c5be3c467..7d340fda7 100644 --- a/src/components/elements/Cards/ItemMonitoringCard/__snapshots__/ItemMonitoringCard.stories.storyshot +++ b/src/components/elements/Cards/ItemMonitoringCard/__snapshots__/ItemMonitoringCard.stories.storyshot @@ -35,10 +35,10 @@ exports[`Storyshots Components/Elements/Cards/ItemMonitoringCards Default 1`] = } >

{ const contentRef = useRef(null); @@ -160,16 +166,22 @@ const ToolTip = ({ ref={tooltipRef} >

@@ -178,7 +190,11 @@ const ToolTip = ({ {t(title)} - + {t(content)}
diff --git a/src/components/elements/Tooltip/__snapshots__/Tooltip.stories.storyshot b/src/components/elements/Tooltip/__snapshots__/Tooltip.stories.storyshot index 3cd3b1afb..f9a5fdee6 100644 --- a/src/components/elements/Tooltip/__snapshots__/Tooltip.stories.storyshot +++ b/src/components/elements/Tooltip/__snapshots__/Tooltip.stories.storyshot @@ -17,10 +17,10 @@ exports[`Storyshots Components/Elements/Tooltip Click 1`] = ` } >

{ + const rowSpeciesName = { + accessorKey: "name", + header: "species Name", + enableSorting: false, + cell: (props: any) => { + const value = props.getValue(); + if (value[0] === "Non-scientific name") { + return ( +

+ {value[0]} + + + +
+ ); + } + if (value[1] === "tree") { + return
{value[0]}
; + } + if (value[1] === "Native species") { + return ( +
+ {value[0]} + + + +
+ ); + } + if (value[1] === "new") { + return ( +
+ {value[0]} + + + +
+ ); + } + } + }; + + const columnTreeCount = [ + rowSpeciesName, + { + accessorKey: "treeCount", + header: "Tree CounT", + enableSorting: false, + cell: (props: any) => { + const value = props.getValue(); + return
{value}
; + } + } + ]; + + const columnSeedCount = [ + rowSpeciesName, + { + accessorKey: "seedCount", + header: "SEED Count", + enableSorting: false, + cell: (props: any) => { + const value = props.getValue(); + return
{value}
; + } + } + ]; + + const columnNonTreeCount = [ + rowSpeciesName, + { + accessorKey: "nonTreeCount", + header: "Non Tree Count", + enableSorting: false, + cell: (props: any) => { + const value = props.getValue(); + return
{value}
; + } + } + ]; + + const columnTreeCountSite = [ + { + accessorKey: "name", + header: "Site Name", + enableSorting: false + }, + { + accessorKey: "treeCount", + header: "Tree Count", + enableSorting: false, + cell: (props: any) => { + const value = props.getValue(); + return
{value}
; + } + } + ]; + + const columnTreeCountGoal = [ + rowSpeciesName, + { + accessorKey: "treeCountGoal", + header: "Tree Count / goal", + enableSorting: false, + cell: (props: any) => { + const value = props.getValue(); + return ( +
+ + + {value[0]} + + of {value[1]} + + +
+ ); + } + } + ]; + const columnSpeciesCountGoal = [ + rowSpeciesName, + { + accessorKey: "speciesCountGoal", + header: "SPECIES Count / goal", + enableSorting: false, + cell: (props: any) => { + const value = props.getValue(); + return ( +
+ + + {value[0]} + + of {value[1]} + + +
+ ); + } + } + ]; + + const columnSaplingsCount = [ + rowSpeciesName, + { + accessorKey: "treeCount", + header: "saplings CounT", + enableSorting: false, + cell: (props: any) => { + const value = props.getValue(); + return
{value}
; + } + } + ]; + + const columnTable: { [key in ModelNameType]: any[] } = { + treeCount: columnTreeCount, + seedCount: columnSeedCount, + nonTreeCount: columnNonTreeCount, + treeCountSite: columnTreeCountSite, + "treeCount/Goal": columnTreeCountGoal, + "speciesCount/Goal": columnSpeciesCountGoal, + saplingsCount: columnSaplingsCount + }; + + return ( +
+
+ + ); +}; + +export default TreeSpeciesTablePD; diff --git a/src/pages/project/[uuid]/tabs/GoalsAndProgress.tsx b/src/pages/project/[uuid]/tabs/GoalsAndProgress.tsx index 7934e3f9f..2389732c3 100644 --- a/src/pages/project/[uuid]/tabs/GoalsAndProgress.tsx +++ b/src/pages/project/[uuid]/tabs/GoalsAndProgress.tsx @@ -1,16 +1,13 @@ import { useT } from "@transifex/react"; import GoalProgressCard from "@/components/elements/Cards/GoalProgressCard/GoalProgressCard"; -import FieldsExpander from "@/components/elements/Field/FieldsExpander"; -import GenericField from "@/components/elements/Field/GenericField"; -import TextField from "@/components/elements/Field/TextField"; -import { VARIANT_TABLE_BORDER } from "@/components/elements/Table/TableVariants"; -import { IconNames } from "@/components/extensive/Icon/Icon"; +import Text from "@/components/elements/Text/Text"; +import Icon, { IconNames } from "@/components/extensive/Icon/Icon"; 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 TreeSpeciesTable from "@/components/extensive/Tables/TreeSpeciesTable"; +import TreeSpeciesTablePD from "@/components/extensive/Tables/TreeSpeciesTablePD"; import { ContextCondition } from "@/context/ContextCondition"; import { Framework } from "@/context/framework.provider"; @@ -18,108 +15,642 @@ interface GoalsAndProgressProps { project: any; } +export const LABEL_LEGEND = [ + { + label: { key: "Trees", render: "Trees" }, + color: "bg-primary" + }, + { + label: { key: "Seeds", render: "Seeds" }, + color: "bg-blueCustom-900" + }, + { + label: { key: "Regenerating", render: "Regenerating" }, + color: "bg-secondary-600" + } +]; + const GoalsAndProgressTab = ({ project }: GoalsAndProgressProps) => { const t = useT(); + const dataTreeCount = [ + { + name: ["Species scientific name", "tree"], + treeCount: "45,000" + }, + { + name: ["Species scientific name", "Native species"], + treeCount: "45,000" + }, + { + name: ["Species scientific name", "tree"], + treeCount: "10,350" + }, + { + name: ["Species scientific name", "tree"], + treeCount: "7,500" + }, + { + name: ["Non-scientific name", "tree"], + treeCount: "4,040" + }, + { + name: ["Species scientific name", "tree"], + treeCount: "3,200" + }, + { + name: ["Species scientific name", "new"], + treeCount: "3,000" + }, + { + name: ["Species scientific name", "tree"], + treeCount: "0" + } + ]; + + const dataSeedCount = [ + { + name: ["Species scientific name", "tree"], + seedCount: "45,000" + }, + { + name: ["Species scientific name", "Native species"], + seedCount: "45,000" + }, + { + name: ["Species scientific name", "tree"], + seedCount: "10,350" + }, + { + name: ["Species scientific name", "tree"], + seedCount: "7,500" + } + ]; + const dataNonTreeCount = [ + { + name: ["Species scientific name", "tree"], + nonTreeCount: "45,000" + }, + { + name: ["Species scientific name", "Native species"], + nonTreeCount: "45,000" + }, + { + name: ["Species scientific name", "tree"], + nonTreeCount: "10,350" + }, + { + name: ["Species scientific name", "tree"], + nonTreeCount: "7,500" + } + ]; + + const dataTreeCountSite = [ + { + name: "Site Name", + treeCount: "2,500" + }, + { + name: "Site Name", + treeCount: "1,850" + }, + { + name: "Site Name", + treeCount: "1,000" + }, + { + name: "Site Name", + treeCount: "960" + }, + { + name: "Site Name", + treeCount: "620" + }, + { + name: "Site Name", + treeCount: "450" + }, + { + name: "Site Name", + treeCount: "300" + } + ]; + + const dataTreeCountGoal = [ + { + name: ["Species scientific name", "tree"], + treeCountGoal: ["45,0000", "90,000"] + }, + { + name: ["Species scientific name", "Native species"], + treeCountGoal: ["35,350", "70,000"] + }, + { + name: ["Species scientific name", "tree"], + treeCountGoal: ["10,350", "35,000"] + }, + { + name: ["Species scientific name", "tree"], + treeCountGoal: ["7,500", "21,000"] + }, + { + name: ["Non-scientific name", "tree"], + treeCountGoal: ["4,040", "15,300"] + }, + { + name: ["Species scientific name", "tree"], + treeCountGoal: ["3,200", "8,000"] + }, + { + name: ["Species scientific name", "new"], + treeCountGoal: ["3,000", "5,000"] + }, + { + name: ["Species scientific name", "tree"], + treeCountGoal: ["1,000", "4,500"] + }, + { + name: ["Species scientific name", "tree"], + treeCountGoal: ["0", "3,000"] + } + ]; + + const dataSpeciesCountGoal = [ + { + name: ["Species scientific name", "tree"], + speciesCountGoal: ["45,0000", "90,000"] + }, + { + name: ["Species scientific name", "Native species"], + speciesCountGoal: ["35,350", "70,000"] + }, + { + name: ["Species scientific name", "tree"], + speciesCountGoal: ["10,350", "35,000"] + }, + { + name: ["Species scientific name", "tree"], + speciesCountGoal: ["7,500", "21,000"] + }, + { + name: ["Non-scientific name", "tree"], + speciesCountGoal: ["4,040", "15,300"] + }, + { + name: ["Species scientific name", "tree"], + speciesCountGoal: ["3,200", "8,000"] + }, + { + name: ["Species scientific name", "new"], + speciesCountGoal: ["3,000", "5,000"] + }, + { + name: ["Species scientific name", "tree"], + speciesCountGoal: ["1,000", "4,500"] + }, + { + name: ["Species scientific name", "tree"], + speciesCountGoal: ["0", "3,000"] + } + ]; + return ( -
+
+ - + + + +
+ + +
+
+ + + + + <> + + {t( + project.framework_key === Framework.TF + ? "Number of Trees Planted:" + : "Number of SAPLINGS Planted:" + )} + +
+ + + + + + + + 113,257 + + of 300,000 + + +
+ + +
+
+
+ + {t("PROGRESS over time:")} + +
+ {LABEL_LEGEND.map((item, index) => ( +
+ + + {t(item.label.key)} + +
+ ))} +
+
+ progress +
+
+ + + + + + + + + +
+
+
- {/* TODO: To be implemented when endpoint is ready */} +
+ + + + + + + + <> + + {t("Number of seeds Planted:")} + +
+ + + + + + + + 5,250 + + of 25,000 + + +
+ + +
+
+ + + + + + +
+
- - - - - - - - - - - - - - - - - - - - - - - - - + + +
+ + {t("Estimated Number of trees regenerating")} + +
+ + + + + + + + 5,250 + + of 25,000 + + +
+
+
+ + -
- - - + +
+ +
+ + + +
+
+ + {t("number of Non-Trees PLANTED:")} + +
+ + + + + + + + 8,400 + + of 90,000 + + +
+ +
+ +
+
+
+
+

diff --git a/src/pages/reports/site-report/[uuid].page.tsx b/src/pages/reports/site-report/[uuid].page.tsx index 54133fdf5..173bbbe9a 100644 --- a/src/pages/reports/site-report/[uuid].page.tsx +++ b/src/pages/reports/site-report/[uuid].page.tsx @@ -1,4 +1,3 @@ -import { Box } from "@mui/system"; import { useT } from "@transifex/react"; import Head from "next/head"; import Link from "next/link"; @@ -6,27 +5,24 @@ import { useRouter } from "next/router"; import { Fragment } from "react"; import { Else, If, Then, When } from "react-if"; -import TreeSpeciesTableTF from "@/admin/components/Tables/TreeSpeciesTableTF"; +import GoalProgressCard from "@/components/elements/Cards/GoalProgressCard/GoalProgressCard"; import EmptyState from "@/components/elements/EmptyState/EmptyState"; import ButtonField from "@/components/elements/Field/ButtonField"; -import GenericField from "@/components/elements/Field/GenericField"; import LongTextField from "@/components/elements/Field/LongTextField"; import TextField from "@/components/elements/Field/TextField"; import Paper from "@/components/elements/Paper/Paper"; import Text from "@/components/elements/Text/Text"; import EntityMapAndGalleryCard from "@/components/extensive/EntityMapAndGalleryCard/EntityMapAndGalleryCard"; -import Icon, { IconNames } from "@/components/extensive/Icon/Icon"; +import { IconNames } from "@/components/extensive/Icon/Icon"; import PageBody from "@/components/extensive/PageElements/Body/PageBody"; import PageBreadcrumbs from "@/components/extensive/PageElements/Breadcrumbs/PageBreadcrumbs"; import PageCard from "@/components/extensive/PageElements/Card/PageCard"; import PageColumn from "@/components/extensive/PageElements/Column/PageColumn"; +import PageFooter from "@/components/extensive/PageElements/Footer/PageFooter"; import PageRow from "@/components/extensive/PageElements/Row/PageRow"; -import DisturbancesTable from "@/components/extensive/Tables/DisturbancesTable"; -import SeedingsTable from "@/components/extensive/Tables/SeedingsTable"; -import TreeSpeciesTable from "@/components/extensive/Tables/TreeSpeciesTable"; +import TreeSpeciesTablePD from "@/components/extensive/Tables/TreeSpeciesTablePD"; import Loader from "@/components/generic/Loading/Loader"; import LoadingContainer from "@/components/generic/Loading/LoadingContainer"; -import { EstablishmentEntityType } from "@/connections/EstablishmentTrees"; import { COLLECTION_SITE_PAID_OTHER, SITE_WORKDAY_COLLECTIONS } from "@/constants/workdayCollections"; import { ContextCondition } from "@/context/ContextCondition"; import FrameworkProvider, { Framework } from "@/context/framework.provider"; @@ -69,6 +65,76 @@ const SiteReportDetailPage = () => { "Site Workdays" ); + const dataTreeCount = [ + { + name: ["Species scientific name", "tree"], + treeCount: "45,000" + }, + { + name: ["Species scientific name", "Native species"], + treeCount: "45,000" + }, + { + name: ["Species scientific name", "tree"], + treeCount: "10,350" + }, + { + name: ["Species scientific name", "tree"], + treeCount: "7,500" + }, + { + name: ["Non-scientific name", "tree"], + treeCount: "4,040" + }, + { + name: ["Species scientific name", "tree"], + treeCount: "3,200" + }, + { + name: ["Species scientific name", "new"], + treeCount: "3,000" + }, + { + name: ["Species scientific name", "tree"], + treeCount: "0" + } + ]; + + const dataNonTreeCount = [ + { + name: ["Species scientific name", "tree"], + nonTreeCount: "45,000" + }, + { + name: ["Species scientific name", "Native species"], + nonTreeCount: "45,000" + }, + { + name: ["Species scientific name", "tree"], + nonTreeCount: "10,350" + }, + { + name: ["Species scientific name", "tree"], + nonTreeCount: "7,500" + }, + { + name: ["Non-scientific name", "tree"], + nonTreeCount: "4,040" + }, + { + name: ["Species scientific name", "tree"], + nonTreeCount: "3,200" + }, + { + name: ["Species scientific name", "new"], + nonTreeCount: "3,000" + }, + { + name: ["Species scientific name", "tree"], + nonTreeCount: "0" + } + ]; + return ( @@ -138,7 +204,117 @@ const SiteReportDetailPage = () => { {siteReport.technical_narrative} {siteReport.public_narrative} - + + {t("Trees Planted")} + +
+ +
+
+ + {t("Saplings Planted")} + +
+ +
+
+ + {t("Seeds Planted")} + +
+ +
+
+ + {t("Non-Trees Planted")} + +
+ +
+
+
+ {t("Assisted Natural Regeneration")} + + + {t("Description of AND Activities:")} + + + {t( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum imperdiet consequat nulla, a dapibus nunc ultricies eget. Aliquam facilisis luctus nibh. Vivamus a lobortis nisl, scelerisque porttitor velit. Phasellus nec hendrerit felis. Proin commodo tortor consequat tortor pulvinar auctor. Nam rhoncus urna dolor, nec scelerisque elit blandit quis. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Etiam sollicitudin lobortis leo, eget laoreet magna fermentum ut. Suspendisse volutpat scelerisque felis, non commodo arcu laoreet vel. Sed facilisis volutpat est, a venenatis orci rhoncus cursus." + )} + +
+ {/* {siteReport.pct_survival_to_date} {siteReport.survival_calculation} @@ -229,7 +405,7 @@ const SiteReportDetailPage = () => { - + */} @@ -327,7 +503,12 @@ const SiteReportDetailPage = () => { +
+
+
+ +
); diff --git a/src/pages/site/[uuid]/tabs/GoalsAndProgress.tsx b/src/pages/site/[uuid]/tabs/GoalsAndProgress.tsx index af0f892ac..8f69b3fe4 100644 --- a/src/pages/site/[uuid]/tabs/GoalsAndProgress.tsx +++ b/src/pages/site/[uuid]/tabs/GoalsAndProgress.tsx @@ -1,40 +1,171 @@ import { useT } from "@transifex/react"; +import { Else, If, Then, When } from "react-if"; import GoalProgressCard from "@/components/elements/Cards/GoalProgressCard/GoalProgressCard"; -import GenericField from "@/components/elements/Field/GenericField"; -import TextField from "@/components/elements/Field/TextField"; -import { VARIANT_TABLE_BORDER } from "@/components/elements/Table/TableVariants"; +import Text from "@/components/elements/Text/Text"; import { IconNames } from "@/components/extensive/Icon/Icon"; 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 TreeSpeciesTable from "@/components/extensive/Tables/TreeSpeciesTable"; -import { ContextCondition } from "@/context/ContextCondition"; +import TreeSpeciesTablePD from "@/components/extensive/Tables/TreeSpeciesTablePD"; import { Framework } from "@/context/framework.provider"; interface GoalsAndProgressTabProps { site: any; } +export const LABEL_LEGEND = [ + { + label: { key: "Trees", render: "Trees" }, + color: "bg-primary" + }, + { + label: { key: "Seeds", render: "Seeds" }, + color: "bg-blueCustom-900" + }, + { + label: { key: "Regenerating", render: "Regenerating" }, + color: "bg-secondary-600" + } +]; + const GoalsAndProgressTab = ({ site }: GoalsAndProgressTabProps) => { const t = useT(); + const dataTreeCount = [ + { + name: ["Species scientific name", "tree"], + treeCount: "45,000" + }, + { + name: ["Species scientific name", "Native species"], + treeCount: "45,000" + }, + { + name: ["Species scientific name", "tree"], + treeCount: "10,350" + }, + { + name: ["Species scientific name", "tree"], + treeCount: "7,500" + }, + { + name: ["Non-scientific name", "tree"], + treeCount: "4,040" + }, + { + name: ["Species scientific name", "tree"], + treeCount: "3,200" + }, + { + name: ["Species scientific name", "new"], + treeCount: "3,000" + }, + { + name: ["Species scientific name", "tree"], + treeCount: "0" + } + ]; + + const dataSeedCount = [ + { + name: ["Species scientific name", "tree"], + seedCount: "45,000" + }, + { + name: ["Species scientific name", "Native species"], + seedCount: "45,000" + }, + { + name: ["Species scientific name", "tree"], + seedCount: "10,350" + }, + { + name: ["Species scientific name", "tree"], + seedCount: "7,500" + } + ]; + const dataNonTreeCount = [ + { + name: ["Species scientific name", "tree"], + nonTreeCount: "45,000" + }, + { + name: ["Species scientific name", "Native species"], + nonTreeCount: "45,000" + }, + { + name: ["Species scientific name", "tree"], + nonTreeCount: "10,350" + }, + { + name: ["Species scientific name", "tree"], + nonTreeCount: "7,500" + } + ]; + return ( -
+
+ + + + { limit={site.trees_grown_goal} hasProgress={false} items={[ - { iconName: IconNames.TREE_CIRCLE, label: t("Trees Planted"), value: site.trees_planted_count }, - { iconName: IconNames.LEAF_CIRCLE, label: t("Seeds Planted"), value: site.seeds_planted_count }, { - iconName: IconNames.REFRESH_CIRCLE, - label: t("Trees Regenerating"), + iconName: IconNames.TREE_CIRCLE_PD, + label: t("Trees Planted:"), + variantLabel: "text-14", + classNameLabel: " text-neutral-650 uppercase", + value: site.trees_planted_count + }, + { + iconName: IconNames.LEAF_CIRCLE_PD, + label: t("Seeds Planted:"), + variantLabel: "text-14", + classNameLabel: " text-neutral-650 uppercase", + value: site.seeds_planted_count + }, + { + iconName: IconNames.REFRESH_CIRCLE_PD, + label: t("Trees Regenerating:"), + variantLabel: "text-14", + classNameLabel: " text-neutral-650 uppercase", value: site.regenerated_trees_count } ]} - className="flex-1" + className="pr-[41px] lg:pr-[150px]" />
- - - {/* TODO: To be added */} - - - - - - - - - - +
+
+ - - - - - - - - +
+
+ + {t("PROGRESS over time:")} + +
+ {LABEL_LEGEND.map((item, index) => ( +
+ + + {t(item.label.key)} + +
+ ))} +
+
+ progress +
+
+
+ +
+
+
+
+ + +
+
+ + + + + + + + + +
+
+ + + + + + + + +
+
+


diff --git a/tailwind.config.js b/tailwind.config.js index 665a4e100..fee122c3d 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -103,9 +103,11 @@ module.exports = { 900: "#3A3A3A", 800: "#5A5A5A", 700: "#737373", + 650: "#747070", 600: "#888888", 500: "#9B9B9B", 400: "#B1B1B1", + 480: "#C4C4C4", 450: "#CCD4D6", 300: "#D8D8D8", 250: "#F7F7F7", From a5b0e569cf339e875535b2ecd4ba0856529c2489 Mon Sep 17 00:00:00 2001 From: diego-morales-flores-1996 <139272044+diego-morales-flores-1996@users.noreply.github.com> Date: Thu, 2 Jan 2025 13:10:35 -0400 Subject: [PATCH 12/20] Tm 1517 web design update admin UI for tree species data (#789) * [TM-1514] add style in page species data * [TM-1514] update snapshots * [TM-1514] fix build * [TM-1514] fix build * [TM-1514] fix build * [TM-1514] change icons style and add tooltips in table in tree species * [TM-1514] update stories * update tree species table for admin * update tree species table for admin * update tree species table for admin * delete console log --------- Co-authored-by: Dotty --- .../ResourceTabs/InformationTab/index.tsx | 96 +++- .../elements/Table/TableVariants.ts | 4 +- .../extensive/Tables/TreeSpeciesTablePD.tsx | 64 ++- .../project/[uuid]/tabs/GoalsAndProgress.tsx | 434 +++++++++++------- 4 files changed, 389 insertions(+), 209 deletions(-) diff --git a/src/admin/components/ResourceTabs/InformationTab/index.tsx b/src/admin/components/ResourceTabs/InformationTab/index.tsx index c3263abcc..478109749 100644 --- a/src/admin/components/ResourceTabs/InformationTab/index.tsx +++ b/src/admin/components/ResourceTabs/InformationTab/index.tsx @@ -7,9 +7,10 @@ import { Else, If, Then, When } from "react-if"; import { MonitoringPartnersTable } from "@/admin/components/ResourceTabs/InformationTab/components/ProjectInformationAside/MonitoringPartners"; import { ProjectManagersTable } from "@/admin/components/ResourceTabs/InformationTab/components/ProjectInformationAside/ProjectManagersTable"; -import SeedingsTable from "@/admin/components/Tables/SeedingsTable"; import { setDefaultConditionalFieldsAnswers } from "@/admin/utils/forms"; +import Text from "@/components/elements/Text/Text"; import List from "@/components/extensive/List/List"; +import TreeSpeciesTablePD from "@/components/extensive/Tables/TreeSpeciesTablePD"; import { ContextCondition } from "@/context/ContextCondition"; import { Framework, useFrameworkContext } from "@/context/framework.provider"; import { @@ -19,15 +20,18 @@ import { } from "@/generated/apiComponents"; import { getCustomFormSteps, normalizedFormDefaultValue } from "@/helpers/customForms"; import { pluralEntityNameToSingular } from "@/helpers/entity"; +import { + dataSeedCountGoal, + dataSeedCountGoalSiteReport, + dataTreeCountGoal +} from "@/pages/project/[uuid]/tabs/GoalsAndProgress"; import { EntityName } from "@/types/common"; -import TreeSpeciesTable from "../../Tables/TreeSpeciesTable"; import InformationTabRow from "./components/InformationTabRow"; import NurseryInformationAside from "./components/NurseryInformationAside"; import ProjectInformationAside from "./components/ProjectInformationAside"; import ReportInformationAside from "./components/ReportInformationAside"; import SiteInformationAside from "./components/SiteInformationAside"; - interface IProps extends Omit { type: EntityName; } @@ -137,30 +141,74 @@ const InformationTab: FC = props => { )} /> + - - - - - Total Trees Planted - - {record?.total_trees_planted_count} - - - - +
+ + +
+ + Total Trees Planted{" "} + in site Report: + + + {record?.total_trees_planted_count ?? 0} + +
+
+
+ + +
+ + Tree Species: + + +
+
+ + + +
+
- - - - - Total Seeds Planted - - {totalSeedlings} - - - + +
+ +
+ + Total Seeds Planted: + + + {totalSeedlings ?? 0} + +
+
+ +
diff --git a/src/components/elements/Table/TableVariants.ts b/src/components/elements/Table/TableVariants.ts index 38c5b5c93..60f0df24b 100644 --- a/src/components/elements/Table/TableVariants.ts +++ b/src/components/elements/Table/TableVariants.ts @@ -205,9 +205,9 @@ export const VARIANT_TABLE_TREE_SPECIES = { table: "border-collapse w-full", name: "border-airtable text-left", trHeader: "!bg-transparent border-b border-neutral-650 text-14 text-neutral-650 ", - thHeader: " text-14 uppercase !px-2 !py-2 font-medium text-14", + thHeader: " text-14 uppercase !pr-4 !pl-0 !py-2 font-medium text-14", tBody: "", trBody: "bg-white border-b border-neutral-200 last:border-0 hover:bg-gray-100", - tdBody: "first:rounded-l-lg last:rounded-r-lg text-16-light text-gray-700 px-2 py-3 border-b border-neutral-200", + tdBody: "first:rounded-l-lg last:rounded-r-lg text-16-light text-gray-700 pr-4 pl-0 py-3 border-b border-neutral-200", thead: "bg-transparent" }; diff --git a/src/components/extensive/Tables/TreeSpeciesTablePD.tsx b/src/components/extensive/Tables/TreeSpeciesTablePD.tsx index 0aca6182b..5780d4710 100644 --- a/src/components/extensive/Tables/TreeSpeciesTablePD.tsx +++ b/src/components/extensive/Tables/TreeSpeciesTablePD.tsx @@ -1,3 +1,5 @@ +import classNames from "classnames"; + import LinearProgressBar from "@/components/elements/ProgressBar/LinearProgressBar/LinearProgressBar"; import Table from "@/components/elements/Table/Table"; import { VARIANT_TABLE_TREE_SPECIES } from "@/components/elements/Table/TableVariants"; @@ -13,17 +15,26 @@ export type ModelNameType = | "treeCountSite" | "treeCount/Goal" | "speciesCount/Goal" + | "saplingsCount" + | "seedCount/Goal" | "saplingsCount"; export interface TreeSpeciesTablePDProps { data: any[]; modelName: ModelNameType; + headerName?: string; + secondColumnWidth?: string; } -const TreeSpeciesTablePD = ({ data, modelName }: TreeSpeciesTablePDProps) => { +const TreeSpeciesTablePD = ({ + data, + modelName, + headerName = "species Name", + secondColumnWidth = "" +}: TreeSpeciesTablePDProps) => { const rowSpeciesName = { accessorKey: "name", - header: "species Name", + header: headerName, enableSorting: false, cell: (props: any) => { const value = props.getValue(); @@ -40,7 +51,10 @@ const TreeSpeciesTablePD = ({ data, modelName }: TreeSpeciesTablePDProps) => { >
@@ -60,7 +74,13 @@ const TreeSpeciesTablePD = ({ data, modelName }: TreeSpeciesTablePDProps) => { placement="right" textVariantContent="text-14" > - +
); @@ -78,7 +98,10 @@ const TreeSpeciesTablePD = ({ data, modelName }: TreeSpeciesTablePDProps) => { > @@ -93,6 +116,7 @@ const TreeSpeciesTablePD = ({ data, modelName }: TreeSpeciesTablePDProps) => { accessorKey: "treeCount", header: "Tree CounT", enableSorting: false, + meta: { width: secondColumnWidth }, cell: (props: any) => { const value = props.getValue(); return
{value}
; @@ -106,6 +130,7 @@ const TreeSpeciesTablePD = ({ data, modelName }: TreeSpeciesTablePDProps) => { accessorKey: "seedCount", header: "SEED Count", enableSorting: false, + meta: { width: secondColumnWidth }, cell: (props: any) => { const value = props.getValue(); return
{value}
; @@ -119,6 +144,7 @@ const TreeSpeciesTablePD = ({ data, modelName }: TreeSpeciesTablePDProps) => { accessorKey: "nonTreeCount", header: "Non Tree Count", enableSorting: false, + meta: { width: secondColumnWidth }, cell: (props: any) => { const value = props.getValue(); return
{value}
; @@ -136,6 +162,7 @@ const TreeSpeciesTablePD = ({ data, modelName }: TreeSpeciesTablePDProps) => { accessorKey: "treeCount", header: "Tree Count", enableSorting: false, + meta: { width: secondColumnWidth }, cell: (props: any) => { const value = props.getValue(); return
{value}
; @@ -149,6 +176,7 @@ const TreeSpeciesTablePD = ({ data, modelName }: TreeSpeciesTablePDProps) => { accessorKey: "treeCountGoal", header: "Tree Count / goal", enableSorting: false, + meta: { width: secondColumnWidth }, cell: (props: any) => { const value = props.getValue(); return ( @@ -165,12 +193,36 @@ const TreeSpeciesTablePD = ({ data, modelName }: TreeSpeciesTablePDProps) => { } } ]; + + const columnSeedCountGoal = [ + rowSpeciesName, + { + accessorKey: "seedCountGoal", + header: "Seed Count / goal", + enableSorting: false, + meta: { width: secondColumnWidth }, + cell: (props: any) => { + const value = props.getValue(); + return ( +
+ + + {value[0]} + of {value[1]} + +
+ ); + } + } + ]; + const columnSpeciesCountGoal = [ rowSpeciesName, { accessorKey: "speciesCountGoal", header: "SPECIES Count / goal", enableSorting: false, + meta: { width: secondColumnWidth }, cell: (props: any) => { const value = props.getValue(); return ( @@ -194,6 +246,7 @@ const TreeSpeciesTablePD = ({ data, modelName }: TreeSpeciesTablePDProps) => { accessorKey: "treeCount", header: "saplings CounT", enableSorting: false, + meta: { width: secondColumnWidth }, cell: (props: any) => { const value = props.getValue(); return
{value}
; @@ -208,6 +261,7 @@ const TreeSpeciesTablePD = ({ data, modelName }: TreeSpeciesTablePDProps) => { treeCountSite: columnTreeCountSite, "treeCount/Goal": columnTreeCountGoal, "speciesCount/Goal": columnSpeciesCountGoal, + "seedCount/Goal": columnSeedCountGoal, saplingsCount: columnSaplingsCount }; diff --git a/src/pages/project/[uuid]/tabs/GoalsAndProgress.tsx b/src/pages/project/[uuid]/tabs/GoalsAndProgress.tsx index 2389732c3..3f0baa290 100644 --- a/src/pages/project/[uuid]/tabs/GoalsAndProgress.tsx +++ b/src/pages/project/[uuid]/tabs/GoalsAndProgress.tsx @@ -30,189 +30,267 @@ export const LABEL_LEGEND = [ } ]; -const GoalsAndProgressTab = ({ project }: GoalsAndProgressProps) => { - const t = useT(); +export const dataTreeCount = [ + { + name: ["Species scientific name", "tree"], + treeCount: "45,000" + }, + { + name: ["Species scientific name", "Native species"], + treeCount: "45,000" + }, + { + name: ["Species scientific name", "tree"], + treeCount: "10,350" + }, + { + name: ["Species scientific name", "tree"], + treeCount: "7,500" + }, + { + name: ["Non-scientific name", "tree"], + treeCount: "4,040" + }, + { + name: ["Species scientific name", "tree"], + treeCount: "3,200" + }, + { + name: ["Species scientific name", "new"], + treeCount: "3,000" + }, + { + name: ["Species scientific name", "tree"], + treeCount: "0" + } +]; + +export const dataSeedCount = [ + { + name: ["Species scientific name", "tree"], + seedCount: "45,000" + }, + { + name: ["Species scientific name", "Native species"], + seedCount: "45,000" + }, + { + name: ["Species scientific name", "tree"], + seedCount: "10,350" + }, + { + name: ["Species scientific name", "tree"], + seedCount: "7,500" + } +]; +export const dataNonTreeCount = [ + { + name: ["Species scientific name", "tree"], + nonTreeCount: "45,000" + }, + { + name: ["Species scientific name", "Native species"], + nonTreeCount: "45,000" + }, + { + name: ["Species scientific name", "tree"], + nonTreeCount: "10,350" + }, + { + name: ["Species scientific name", "tree"], + nonTreeCount: "7,500" + } +]; - const dataTreeCount = [ - { - name: ["Species scientific name", "tree"], - treeCount: "45,000" - }, - { - name: ["Species scientific name", "Native species"], - treeCount: "45,000" - }, - { - name: ["Species scientific name", "tree"], - treeCount: "10,350" - }, - { - name: ["Species scientific name", "tree"], - treeCount: "7,500" - }, - { - name: ["Non-scientific name", "tree"], - treeCount: "4,040" - }, - { - name: ["Species scientific name", "tree"], - treeCount: "3,200" - }, - { - name: ["Species scientific name", "new"], - treeCount: "3,000" - }, - { - name: ["Species scientific name", "tree"], - treeCount: "0" - } - ]; +export const dataTreeCountSite = [ + { + name: "Site Name", + treeCount: "2,500" + }, + { + name: "Site Name", + treeCount: "1,850" + }, + { + name: "Site Name", + treeCount: "1,000" + }, + { + name: "Site Name", + treeCount: "960" + }, + { + name: "Site Name", + treeCount: "620" + }, + { + name: "Site Name", + treeCount: "450" + }, + { + name: "Site Name", + treeCount: "300" + } +]; + +export const dataTreeCountGoal = [ + { + name: ["Species scientific name", "tree"], + treeCountGoal: ["45,0000", "90,000"] + }, + { + name: ["Species scientific name", "Native species"], + treeCountGoal: ["35,350", "70,000"] + }, + { + name: ["Species scientific name", "tree"], + treeCountGoal: ["10,350", "35,000"] + }, + { + name: ["Species scientific name", "tree"], + treeCountGoal: ["7,500", "21,000"] + }, + { + name: ["Non-scientific name", "tree"], + treeCountGoal: ["4,040", "15,300"] + }, + { + name: ["Species scientific name", "tree"], + treeCountGoal: ["3,200", "8,000"] + }, + { + name: ["Species scientific name", "new"], + treeCountGoal: ["3,000", "5,000"] + }, + { + name: ["Species scientific name", "tree"], + treeCountGoal: ["1,000", "4,500"] + }, + { + name: ["Species scientific name", "tree"], + treeCountGoal: ["0", "3,000"] + } +]; - const dataSeedCount = [ - { - name: ["Species scientific name", "tree"], - seedCount: "45,000" - }, - { - name: ["Species scientific name", "Native species"], - seedCount: "45,000" - }, - { - name: ["Species scientific name", "tree"], - seedCount: "10,350" - }, - { - name: ["Species scientific name", "tree"], - seedCount: "7,500" - } - ]; - const dataNonTreeCount = [ - { - name: ["Species scientific name", "tree"], - nonTreeCount: "45,000" - }, - { - name: ["Species scientific name", "Native species"], - nonTreeCount: "45,000" - }, - { - name: ["Species scientific name", "tree"], - nonTreeCount: "10,350" - }, - { - name: ["Species scientific name", "tree"], - nonTreeCount: "7,500" - } - ]; +export const dataSpeciesCountGoal = [ + { + name: ["Species scientific name", "tree"], + speciesCountGoal: ["45,0000", "90,000"] + }, + { + name: ["Species scientific name", "Native species"], + speciesCountGoal: ["35,350", "70,000"] + }, + { + name: ["Species scientific name", "tree"], + speciesCountGoal: ["10,350", "35,000"] + }, + { + name: ["Species scientific name", "tree"], + speciesCountGoal: ["7,500", "21,000"] + }, + { + name: ["Non-scientific name", "tree"], + speciesCountGoal: ["4,040", "15,300"] + }, + { + name: ["Species scientific name", "tree"], + speciesCountGoal: ["3,200", "8,000"] + }, + { + name: ["Species scientific name", "new"], + speciesCountGoal: ["3,000", "5,000"] + }, + { + name: ["Species scientific name", "tree"], + speciesCountGoal: ["1,000", "4,500"] + }, + { + name: ["Species scientific name", "tree"], + speciesCountGoal: ["0", "3,000"] + } +]; - const dataTreeCountSite = [ - { - name: "Site Name", - treeCount: "2,500" - }, - { - name: "Site Name", - treeCount: "1,850" - }, - { - name: "Site Name", - treeCount: "1,000" - }, - { - name: "Site Name", - treeCount: "960" - }, - { - name: "Site Name", - treeCount: "620" - }, - { - name: "Site Name", - treeCount: "450" - }, - { - name: "Site Name", - treeCount: "300" - } - ]; +export const dataSeedCountGoal = [ + { + name: ["Species scientific name", "tree"], + seedCountGoal: ["45,0000", "90,000"] + }, + { + name: ["Species scientific name", "Native species"], + seedCountGoal: ["35,350", "70,000"] + }, + { + name: ["Species scientific name", "tree"], + seedCountGoal: ["10,350", "35,000"] + }, + { + name: ["Species scientific name", "tree"], + seedCountGoal: ["7,500", "21,000"] + }, + { + name: ["Non-scientific name", "tree"], + seedCountGoal: ["4,040", "15,300"] + }, + { + name: ["Species scientific name", "tree"], + seedCountGoal: ["3,200", "8,000"] + }, + { + name: ["Species scientific name", "new"], + seedCountGoal: ["3,000", "5,000"] + }, + { + name: ["Species scientific name", "tree"], + seedCountGoal: ["1,000", "4,500"] + }, + { + name: ["Species scientific name", "tree"], + seedCountGoal: ["0", "3,000"] + } +]; - const dataTreeCountGoal = [ - { - name: ["Species scientific name", "tree"], - treeCountGoal: ["45,0000", "90,000"] - }, - { - name: ["Species scientific name", "Native species"], - treeCountGoal: ["35,350", "70,000"] - }, - { - name: ["Species scientific name", "tree"], - treeCountGoal: ["10,350", "35,000"] - }, - { - name: ["Species scientific name", "tree"], - treeCountGoal: ["7,500", "21,000"] - }, - { - name: ["Non-scientific name", "tree"], - treeCountGoal: ["4,040", "15,300"] - }, - { - name: ["Species scientific name", "tree"], - treeCountGoal: ["3,200", "8,000"] - }, - { - name: ["Species scientific name", "new"], - treeCountGoal: ["3,000", "5,000"] - }, - { - name: ["Species scientific name", "tree"], - treeCountGoal: ["1,000", "4,500"] - }, - { - name: ["Species scientific name", "tree"], - treeCountGoal: ["0", "3,000"] - } - ]; +export const dataSeedCountGoalSiteReport = [ + { + name: ["Species scientific name", "tree"], + seedCountGoal: ["45,0000", "90,000"] + }, + { + name: ["Species scientific name", "Native species", "approved"], + seedCountGoal: ["35,350", "70,000"] + }, + { + name: ["Species scientific name", "tree"], + seedCountGoal: ["10,350", "35,000"] + }, + { + name: ["Species scientific name", "tree"], + seedCountGoal: ["7,500", "21,000"] + }, + { + name: ["Non-scientific name", "tree", "approved"], + seedCountGoal: ["4,040", "15,300"] + }, + { + name: ["Species scientific name", "tree"], + seedCountGoal: ["3,200", "8,000"] + }, + { + name: ["Species scientific name", "new"], + seedCountGoal: ["3,000", "5,000"] + }, + { + name: ["Species scientific name", "tree"], + seedCountGoal: ["1,000", "4,500"] + }, + { + name: ["Species scientific name", "tree"], + seedCountGoal: ["0", "3,000"] + } +]; - const dataSpeciesCountGoal = [ - { - name: ["Species scientific name", "tree"], - speciesCountGoal: ["45,0000", "90,000"] - }, - { - name: ["Species scientific name", "Native species"], - speciesCountGoal: ["35,350", "70,000"] - }, - { - name: ["Species scientific name", "tree"], - speciesCountGoal: ["10,350", "35,000"] - }, - { - name: ["Species scientific name", "tree"], - speciesCountGoal: ["7,500", "21,000"] - }, - { - name: ["Non-scientific name", "tree"], - speciesCountGoal: ["4,040", "15,300"] - }, - { - name: ["Species scientific name", "tree"], - speciesCountGoal: ["3,200", "8,000"] - }, - { - name: ["Species scientific name", "new"], - speciesCountGoal: ["3,000", "5,000"] - }, - { - name: ["Species scientific name", "tree"], - speciesCountGoal: ["1,000", "4,500"] - }, - { - name: ["Species scientific name", "tree"], - speciesCountGoal: ["0", "3,000"] - } - ]; +const GoalsAndProgressTab = ({ project }: GoalsAndProgressProps) => { + const t = useT(); return ( From a4c5a9ed526f0e8d85f828335859335fbb168914 Mon Sep 17 00:00:00 2001 From: Dotnara Condori Date: Thu, 2 Jan 2025 13:35:04 -0400 Subject: [PATCH 13/20] [TM-1593] Hectares By Restoration Strategy Graph Loading Issue (#790) --- .../ResourceTabs/MonitoredTab/components/DataCard.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/admin/components/ResourceTabs/MonitoredTab/components/DataCard.tsx b/src/admin/components/ResourceTabs/MonitoredTab/components/DataCard.tsx index 3abdfde48..d9e7ed1ab 100644 --- a/src/admin/components/ResourceTabs/MonitoredTab/components/DataCard.tsx +++ b/src/admin/components/ResourceTabs/MonitoredTab/components/DataCard.tsx @@ -199,7 +199,7 @@ const indicatorDescription2 = const noDataMap = (
-
+
-
+
No Data to Display @@ -648,7 +648,7 @@ const DataCard = ({
-
+
setSelectedPolygonUuid(option[0])} /> -
+
Indicator Description From 0ca9645ba95a66f50dfbfa20aa0560028d98ed75 Mon Sep 17 00:00:00 2001 From: diego-morales-flores-1996 <139272044+diego-morales-flores-1996@users.noreply.github.com> Date: Thu, 2 Jan 2025 14:13:11 -0400 Subject: [PATCH 14/20] Tm 1517 web design update admin UI for tree species data (#791) * [TM-1514] add style in page species data * [TM-1514] update snapshots * [TM-1514] fix build * [TM-1514] fix build * [TM-1514] fix build * [TM-1514] change icons style and add tooltips in table in tree species * [TM-1514] update stories * update tree species table for admin * update tree species table for admin * update tree species table for admin * delete console log * update pagination variant on table --------- Co-authored-by: Dotty --- .../elements/Table/TableVariants.ts | 31 ++++++++++++------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/src/components/elements/Table/TableVariants.ts b/src/components/elements/Table/TableVariants.ts index 60f0df24b..54f24dd19 100644 --- a/src/components/elements/Table/TableVariants.ts +++ b/src/components/elements/Table/TableVariants.ts @@ -1,7 +1,6 @@ import { VARIANT_PAGINATION_DASHBOARD, VARIANT_PAGINATION_MONITORED, - VARIANT_PAGINATION_TEXT_16, VariantPagination } from "@/components/extensive/Pagination/PaginationVariant"; @@ -31,7 +30,8 @@ export const VARIANT_TABLE_PRIMARY = { tBody: "space-y-4", trBody: "rounded-lg bg-white", tdBody: "first:rounded-tl-lg text-14-light first:rounded-bl-lg last:rounded-br-lg last:rounded-tr-lg px-6 py-4", - thead: "bg-blueCustom-100" + thead: "bg-blueCustom-100", + paginationVariant: VARIANT_PAGINATION_DASHBOARD }; export const VARIANT_TABLE_SECONDARY = { @@ -42,7 +42,8 @@ export const VARIANT_TABLE_SECONDARY = { tBody: "space-y-4", trBody: "bg-neutral-50 rounded-lg", tdBody: "first:rounded-tl-lg first:rounded-bl-lg last:rounded-br-lg last:rounded-tr-lg px-6 py-4", - thead: "bg-blueCustom-100" + thead: "bg-blueCustom-100", + paginationVariant: VARIANT_PAGINATION_DASHBOARD }; export const VARIANT_TABLE_SECONDARY_WHITE = { @@ -53,7 +54,8 @@ export const VARIANT_TABLE_SECONDARY_WHITE = { tBody: "space-y-4", trBody: "bg-white rounded-lg", tdBody: "first:rounded-tl-lg first:rounded-bl-lg last:rounded-br-lg last:rounded-tr-lg px-6 py-4 border-0", - thead: "bg-blueCustom-100" + thead: "bg-blueCustom-100", + paginationVariant: VARIANT_PAGINATION_DASHBOARD }; export const VARIANT_TABLE_BORDER = { @@ -65,7 +67,8 @@ export const VARIANT_TABLE_BORDER = { trBody: "bg-white border rounded-lg", tdBody: "border-neutral-200 border text-16-light first:rounded-tl-lg first:rounded-bl-lg last:rounded-br-lg last:rounded-tr-lg px-6 py-4", - thead: "bg-blueCustom-100" + thead: "bg-blueCustom-100", + paginationVariant: VARIANT_PAGINATION_DASHBOARD }; export const VARIANT_TABLE_BORDER_ALL = { @@ -78,7 +81,8 @@ export const VARIANT_TABLE_BORDER_ALL = { trBody: "bg-white rounded-lg", tdBody: "border-neutral-200 border-t border-b first:border-l last:border-r text-14-light first:rounded-tl-lg first:rounded-bl-lg last:rounded-br-lg last:rounded-tr-lg px-6 py-4", - thead: "bg-blueCustom-100" + thead: "bg-blueCustom-100", + paginationVariant: VARIANT_PAGINATION_DASHBOARD }; export const VARIANT_TABLE_AIRTABLE = { @@ -90,7 +94,7 @@ export const VARIANT_TABLE_AIRTABLE = { trBody: "bg-white border-y border-neutral-200 lastRow", tdBody: "text-16-light px-6 py-3", thead: "bg-blueCustom-100", - paginationVariant: VARIANT_PAGINATION_TEXT_16 + paginationVariant: VARIANT_PAGINATION_DASHBOARD }; export const VARIANT_TABLE_SITE_POLYGON_REVIEW = { @@ -103,7 +107,8 @@ export const VARIANT_TABLE_SITE_POLYGON_REVIEW = { tBody: "", trBody: "bg-white border-y border-neutral-200 last:border-b-0", tdBody: "text-14-light px-2 py-3 first:pl-4 first:pr-2 last:pl-2 last:pr-4 ", - thead: "bg-blueCustom-100" + thead: "bg-blueCustom-100", + paginationVariant: VARIANT_PAGINATION_DASHBOARD }; export const VARIANT_TABLE_VERSION = { @@ -114,7 +119,8 @@ export const VARIANT_TABLE_VERSION = { tBody: "", trBody: "bg-transparent border-y border-neutral-200 lastRow !group hover:bg-[#ffffff33] py-0.5", tdBody: "first:rounded-l-lg last:rounded-r-lg text-10-bold text-white", - thead: "bg-transparent" + thead: "bg-transparent", + paginationVariant: VARIANT_PAGINATION_DASHBOARD }; export const VARIANT_TABLE_ORGANISATION = { @@ -125,7 +131,8 @@ export const VARIANT_TABLE_ORGANISATION = { tBody: "", trBody: "bg-white border-b border-neutral-200 last:border-0 hover:bg-gray-100", tdBody: "first:rounded-l-lg last:rounded-r-lg text-14-light text-gray-700 px-2 py-3 border-b border-neutral-200", - thead: "bg-transparent" + thead: "bg-transparent", + paginationVariant: VARIANT_PAGINATION_DASHBOARD }; export const VARIANT_TABLE_DASHBOARD_COUNTRIES = { @@ -137,7 +144,8 @@ export const VARIANT_TABLE_DASHBOARD_COUNTRIES = { tBody: "", trBody: "bg-white border-y border-neutral-200 last:border-b-0", tdBody: "text-14-light px-3 py-3 first:pl-4 first:pr-2 last:pl-2 last:pr-4", - thead: "bg-blueCustom-100 " + thead: "bg-blueCustom-100 ", + paginationVariant: VARIANT_PAGINATION_DASHBOARD }; export const VARIANT_TABLE_DASHBOARD_COUNTRIES_MODAL = { @@ -209,5 +217,6 @@ export const VARIANT_TABLE_TREE_SPECIES = { tBody: "", trBody: "bg-white border-b border-neutral-200 last:border-0 hover:bg-gray-100", tdBody: "first:rounded-l-lg last:rounded-r-lg text-16-light text-gray-700 pr-4 pl-0 py-3 border-b border-neutral-200", + paginationVariant: VARIANT_PAGINATION_DASHBOARD, thead: "bg-transparent" }; From ab3e848caadce8ea0e4c9c69a45c1cc29daf9b59 Mon Sep 17 00:00:00 2001 From: Dotnara Condori Date: Thu, 2 Jan 2025 14:51:34 -0400 Subject: [PATCH 15/20] Fix/tm 1593 hectares by restoration strategy graph loading issue (#792) * [TM-1593] Hectares By Restoration Strategy Graph Loading Issue * [TM-1593] fixy Graph Hectares By Restoration Strategy --- .../ResourceTabs/MonitoredTab/components/MonitoredCharts.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/admin/components/ResourceTabs/MonitoredTab/components/MonitoredCharts.tsx b/src/admin/components/ResourceTabs/MonitoredTab/components/MonitoredCharts.tsx index 95da0709c..ca3fa3b11 100644 --- a/src/admin/components/ResourceTabs/MonitoredTab/components/MonitoredCharts.tsx +++ b/src/admin/components/ResourceTabs/MonitoredTab/components/MonitoredCharts.tsx @@ -155,7 +155,7 @@ const MonitoredCharts = ({ return (
From a1aba92336a80805617b854bdea4524fb774edb9 Mon Sep 17 00:00:00 2001 From: cesarLima1 <105736261+cesarLima1@users.noreply.github.com> Date: Mon, 6 Jan 2025 09:49:37 -0400 Subject: [PATCH 16/20] [TM-1586] include last updated date on dashboard header (#793) --- src/context/dashboard.provider.tsx | 11 +++++++++-- src/pages/dashboard/components/HeaderDashboard.tsx | 5 ++++- src/pages/dashboard/index.page.tsx | 6 +++++- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/context/dashboard.provider.tsx b/src/context/dashboard.provider.tsx index 3cdb99c51..2032c620c 100644 --- a/src/context/dashboard.provider.tsx +++ b/src/context/dashboard.provider.tsx @@ -31,6 +31,8 @@ type DashboardType = { setFrameworks: React.Dispatch>; dashboardCountries: CountriesProps[]; setDashboardCountries: React.Dispatch>; + lastUpdatedAt?: string; + setLastUpdatedAt?: React.Dispatch>; }; const defaultValues: DashboardType = { filters: { @@ -53,7 +55,9 @@ const defaultValues: DashboardType = { frameworks: [], setFrameworks: () => {}, dashboardCountries: [], - setDashboardCountries: () => {} + setDashboardCountries: () => {}, + lastUpdatedAt: "", + setLastUpdatedAt: () => {} }; const DashboardContext = createContext(defaultValues); @@ -62,6 +66,7 @@ export const DashboardProvider: React.FC<{ children: ReactNode }> = ({ children const [searchTerm, setSearchTerm] = React.useState(""); const [frameworks, setFrameworks] = React.useState<{ framework_slug?: string; name?: string }[]>([]); const [dashboardCountries, setDashboardCountries] = React.useState([]); + const [lastUpdatedAt, setLastUpdatedAt] = React.useState(""); const contextValue: DashboardType = { filters, setFilters, @@ -70,7 +75,9 @@ export const DashboardProvider: React.FC<{ children: ReactNode }> = ({ children frameworks, setFrameworks, dashboardCountries, - setDashboardCountries + setDashboardCountries, + lastUpdatedAt, + setLastUpdatedAt }; return {children}; }; diff --git a/src/pages/dashboard/components/HeaderDashboard.tsx b/src/pages/dashboard/components/HeaderDashboard.tsx index 3dac1e668..d8e1198f1 100644 --- a/src/pages/dashboard/components/HeaderDashboard.tsx +++ b/src/pages/dashboard/components/HeaderDashboard.tsx @@ -46,7 +46,7 @@ const HeaderDashboard = (props: HeaderDashboardProps) => { const t = useT(); const router = useRouter(); const { showLoader, hideLoader } = useLoading(); - const { filters, setFilters, setSearchTerm, searchTerm, setFrameworks, setDashboardCountries } = + const { filters, setFilters, setSearchTerm, searchTerm, setFrameworks, setDashboardCountries, lastUpdatedAt } = useDashboardContext(); const { activeProjects } = useDashboardData(filters); @@ -235,6 +235,9 @@ const HeaderDashboard = (props: HeaderDashboardProps) => {   {t("BETA")} + + {t(lastUpdatedAt ? `Last Updated on ${new Date(lastUpdatedAt).toISOString().split("T")[0]}` : "")} +
diff --git a/src/pages/dashboard/index.page.tsx b/src/pages/dashboard/index.page.tsx index 2fbdf568c..3f98c8387 100644 --- a/src/pages/dashboard/index.page.tsx +++ b/src/pages/dashboard/index.page.tsx @@ -61,7 +61,7 @@ const Dashboard = () => { const t = useT(); const [, { user }] = useMyUser(); const logout = useLogout(); - const { filters, setFilters, frameworks } = useDashboardContext(); + const { filters, setFilters, frameworks, setLastUpdatedAt } = useDashboardContext(); const { dashboardHeader, dashboardRestorationGoalData, @@ -96,6 +96,10 @@ const Dashboard = () => { { tooltip: { key: "Graph", render: "Graph" } } ]; + useEffect(() => { + setLastUpdatedAt?.(totalSectionHeader?.last_updated_at); + }, [totalSectionHeader]); + useEffect(() => { refetchTotalSectionHeader(); }, [filters]); From 53b81bb068f284f1981c559876d7258ea7864c10 Mon Sep 17 00:00:00 2001 From: Limber Mamani <154026979+LimberHope@users.noreply.github.com> Date: Mon, 6 Jan 2025 16:31:21 -0400 Subject: [PATCH 17/20] [TM-1337] add value by default to conditional input (#794) --- src/admin/utils/forms.ts | 2 +- .../elements/Inputs/ConditionalInput/ConditionalInput.tsx | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/admin/utils/forms.ts b/src/admin/utils/forms.ts index 7b1d8137f..74a466487 100644 --- a/src/admin/utils/forms.ts +++ b/src/admin/utils/forms.ts @@ -71,7 +71,7 @@ export const setDefaultConditionalFieldsAnswers = (answers: any, steps: FormStep steps.forEach(step => { step.fields.forEach(field => { if (field.type === FieldType.Conditional && typeof output[field.name] !== "boolean") { - output[field.name] = true; + output[field.name] = false; } }); }); diff --git a/src/components/elements/Inputs/ConditionalInput/ConditionalInput.tsx b/src/components/elements/Inputs/ConditionalInput/ConditionalInput.tsx index 109a2d3d8..0aa512c05 100644 --- a/src/components/elements/Inputs/ConditionalInput/ConditionalInput.tsx +++ b/src/components/elements/Inputs/ConditionalInput/ConditionalInput.tsx @@ -39,6 +39,11 @@ const ConditionalInput = (props: ConditionalInputProps) => { // eslint-disable-next-line react-hooks/exhaustive-deps }, [props.value, formHook]); + useEffect(() => { + if (field.value == null) { + field.onChange(false); + } + }, [field, field.value]); return ( <> Date: Tue, 7 Jan 2025 16:14:25 -0400 Subject: [PATCH 18/20] [TM-1589] add percentages in all tooltips in dashboard (#795) --- src/pages/dashboard/charts/CustomTooltip.tsx | 2 +- .../charts/CustomTooltipJobsCreated.tsx | 17 ++++++++++------- src/pages/dashboard/charts/DoughnutChart.tsx | 2 +- src/pages/dashboard/charts/GroupedBarChart.tsx | 5 ++++- src/utils/dashboardUtils.ts | 14 +++++++++++++- 5 files changed, 29 insertions(+), 11 deletions(-) diff --git a/src/pages/dashboard/charts/CustomTooltip.tsx b/src/pages/dashboard/charts/CustomTooltip.tsx index 73313bcf7..8779b66e4 100644 --- a/src/pages/dashboard/charts/CustomTooltip.tsx +++ b/src/pages/dashboard/charts/CustomTooltip.tsx @@ -11,7 +11,7 @@ export const CustomTooltip: React.FC = ({ active, payload, label }) => { maximumFractionDigits: 1 }); - const formattedPercentage = percentage.toFixed(0); + const formattedPercentage = percentage.toFixed(1); return (
diff --git a/src/pages/dashboard/charts/CustomTooltipJobsCreated.tsx b/src/pages/dashboard/charts/CustomTooltipJobsCreated.tsx index c6b308fe0..170a26983 100644 --- a/src/pages/dashboard/charts/CustomTooltipJobsCreated.tsx +++ b/src/pages/dashboard/charts/CustomTooltipJobsCreated.tsx @@ -1,16 +1,19 @@ import React from "react"; -export const CustomTooltip: React.FC = ({ active, payload, label }) => { +export const CustomTooltip: React.FC = ({ active, payload, label, total }) => { if (!active || !payload || !payload.length) return null; return (

{label}

- {payload.map((item: any, index: number) => ( -

- {item.name}: - {item.value.toLocaleString()} -

- ))} + {payload.map((item: any, index: number) => { + const percentage = ((item.value / total) * 100).toFixed(1); + return ( +

+ {item.name}: + {`${item.value.toLocaleString()} (${percentage}%)`} +

+ ); + })}
); }; diff --git a/src/pages/dashboard/charts/DoughnutChart.tsx b/src/pages/dashboard/charts/DoughnutChart.tsx index 00b195a15..cf3267902 100644 --- a/src/pages/dashboard/charts/DoughnutChart.tsx +++ b/src/pages/dashboard/charts/DoughnutChart.tsx @@ -19,7 +19,7 @@ const DoughnutChart: React.FC<{ data: ChartDataVolunteers }> = ({ data }) => { ))} - } /> + } /> } /> diff --git a/src/pages/dashboard/charts/GroupedBarChart.tsx b/src/pages/dashboard/charts/GroupedBarChart.tsx index 27d3034d0..f92dd8d7e 100644 --- a/src/pages/dashboard/charts/GroupedBarChart.tsx +++ b/src/pages/dashboard/charts/GroupedBarChart.tsx @@ -19,7 +19,10 @@ const GroupedBarChart: React.FC<{ data: GroupedBarChartData }> = ({ data }) => { } /> } /> - } cursor={{ fill: "rgba(0, 0, 0, 0.05)" }} /> + } + cursor={{ fill: "rgba(0, 0, 0, 0.05)" }} + /> } /> { if (!total_hectares_restored) return "0 ha 0%"; + const percentage = (value / total_hectares_restored) * 100; - return `${Math.round(value).toLocaleString()} ha ${percentage.toFixed(0)}%`; + + // Special handling for very small percentages + if (percentage < 0.1 && percentage > 0) { + let decimals = 1; + while (percentage.toFixed(decimals) === "0.000000".slice(0, decimals + 2)) { + decimals++; + if (decimals > 6) break; + } + return `${Math.round(value).toLocaleString()} ha ${percentage.toFixed(decimals)}%`; + } + + return `${Math.round(value).toLocaleString()} ha ${percentage.toFixed(1)}%`; }; const getLandUseTypeTitle = (value: string): string => { From b47f631b3941d0530cb00a37da447cc9cd823287 Mon Sep 17 00:00:00 2001 From: diego-morales-flores-1996 <139272044+diego-morales-flores-1996@users.noreply.github.com> Date: Wed, 8 Jan 2025 15:57:44 -0400 Subject: [PATCH 19/20] Tm 1517 web design update admin UI for tree species data (#797) * [TM-1514] add style in page species data * [TM-1514] update snapshots * [TM-1514] fix build * [TM-1514] fix build * [TM-1514] fix build * [TM-1514] change icons style and add tooltips in table in tree species * [TM-1514] update stories * update tree species table for admin * update tree species table for admin * update tree species table for admin * delete console log * update pagination variant on table * hide tree species udpate on admin --------- Co-authored-by: Dotty --- .../ResourceTabs/InformationTab/index.tsx | 96 +++++-------------- 1 file changed, 24 insertions(+), 72 deletions(-) diff --git a/src/admin/components/ResourceTabs/InformationTab/index.tsx b/src/admin/components/ResourceTabs/InformationTab/index.tsx index 478109749..c3263abcc 100644 --- a/src/admin/components/ResourceTabs/InformationTab/index.tsx +++ b/src/admin/components/ResourceTabs/InformationTab/index.tsx @@ -7,10 +7,9 @@ import { Else, If, Then, When } from "react-if"; import { MonitoringPartnersTable } from "@/admin/components/ResourceTabs/InformationTab/components/ProjectInformationAside/MonitoringPartners"; import { ProjectManagersTable } from "@/admin/components/ResourceTabs/InformationTab/components/ProjectInformationAside/ProjectManagersTable"; +import SeedingsTable from "@/admin/components/Tables/SeedingsTable"; import { setDefaultConditionalFieldsAnswers } from "@/admin/utils/forms"; -import Text from "@/components/elements/Text/Text"; import List from "@/components/extensive/List/List"; -import TreeSpeciesTablePD from "@/components/extensive/Tables/TreeSpeciesTablePD"; import { ContextCondition } from "@/context/ContextCondition"; import { Framework, useFrameworkContext } from "@/context/framework.provider"; import { @@ -20,18 +19,15 @@ import { } from "@/generated/apiComponents"; import { getCustomFormSteps, normalizedFormDefaultValue } from "@/helpers/customForms"; import { pluralEntityNameToSingular } from "@/helpers/entity"; -import { - dataSeedCountGoal, - dataSeedCountGoalSiteReport, - dataTreeCountGoal -} from "@/pages/project/[uuid]/tabs/GoalsAndProgress"; import { EntityName } from "@/types/common"; +import TreeSpeciesTable from "../../Tables/TreeSpeciesTable"; import InformationTabRow from "./components/InformationTabRow"; import NurseryInformationAside from "./components/NurseryInformationAside"; import ProjectInformationAside from "./components/ProjectInformationAside"; import ReportInformationAside from "./components/ReportInformationAside"; import SiteInformationAside from "./components/SiteInformationAside"; + interface IProps extends Omit { type: EntityName; } @@ -141,74 +137,30 @@ const InformationTab: FC = props => { )} /> - -
- - -
- - Total Trees Planted{" "} - in site Report: - - - {record?.total_trees_planted_count ?? 0} - -
-
-
- - -
- - Tree Species: - - -
-
- - - -
-
-
- - -
+ -
- - Total Seeds Planted: - - - {totalSeedlings ?? 0} - -
+ + + Total Trees Planted + + {record?.total_trees_planted_count} +
- -
+
+ + + + + + + + Total Seeds Planted + + {totalSeedlings} + + + From 4708244b4b823b02183fe849da1c0902281c69e0 Mon Sep 17 00:00:00 2001 From: Dotnara Condori Date: Wed, 8 Jan 2025 16:47:46 -0400 Subject: [PATCH 20/20] [TM-1514] hide tree species new design in PD (#798) * [TM-1514] hide tree species new design in PD * [TM-1514] fix build * [TM-1514] update stories --- .../GoalProgressCard/GoalProgressCard.tsx | 2 +- .../GoalProgressCard.stories.storyshot | 6 +- .../project/[uuid]/tabs/GoalsAndProgress.tsx | 751 ++---------------- src/pages/reports/site-report/[uuid].page.tsx | 202 +---- .../site/[uuid]/tabs/GoalsAndProgress.tsx | 401 ++-------- 5 files changed, 142 insertions(+), 1220 deletions(-) diff --git a/src/components/elements/Cards/GoalProgressCard/GoalProgressCard.tsx b/src/components/elements/Cards/GoalProgressCard/GoalProgressCard.tsx index b29536d87..686a5486d 100644 --- a/src/components/elements/Cards/GoalProgressCard/GoalProgressCard.tsx +++ b/src/components/elements/Cards/GoalProgressCard/GoalProgressCard.tsx @@ -69,7 +69,7 @@ const GoalProgressCard: FC = ({ diff --git a/src/components/elements/Cards/GoalProgressCard/__snapshots__/GoalProgressCard.stories.storyshot b/src/components/elements/Cards/GoalProgressCard/__snapshots__/GoalProgressCard.stories.storyshot index 8fb1ab493..80497e80f 100644 --- a/src/components/elements/Cards/GoalProgressCard/__snapshots__/GoalProgressCard.stories.storyshot +++ b/src/components/elements/Cards/GoalProgressCard/__snapshots__/GoalProgressCard.stories.storyshot @@ -24,7 +24,7 @@ exports[`Storyshots Components/Elements/Cards/GoalProgressCard/Card No Progress  

{ const t = useT(); @@ -296,439 +25,103 @@ const GoalsAndProgressTab = ({ project }: GoalsAndProgressProps) => { -
- - - - - +
- + +
- - -
-
- - - - - <> - - {t( - project.framework_key === Framework.TF - ? "Number of Trees Planted:" - : "Number of SAPLINGS Planted:" - )} - -
- - - - - - - - 113,257 - - of 300,000 - - -
- - -
-
-
- - {t("PROGRESS over time:")} - -
- {LABEL_LEGEND.map((item, index) => ( -
- - - {t(item.label.key)} - -
- ))} -
-
- progress -
-
- - - - - - - - - -
-
-
-
- - - - - - - - <> - - {t("Number of seeds Planted:")} - -
- - - - - - - - 5,250 - - of 25,000 - - -
- - -
-
- - - - - - -
-
+ {/* TODO: To be implemented when endpoint is ready */}
- - -
- - {t("Estimated Number of trees regenerating")} - -
- - - - - - - - 5,250 - - of 25,000 - - -
-
-
- - + + + + + + + + + + + + + + + + + + + + + + + + + -
- -
+
+ + + +
- - - -
-
- - {t("number of Non-Trees PLANTED:")} - -
- - - - - - - - 8,400 - - of 90,000 - - -
- -
- -
-
-
-
-

diff --git a/src/pages/reports/site-report/[uuid].page.tsx b/src/pages/reports/site-report/[uuid].page.tsx index 173bbbe9a..bdfddbf38 100644 --- a/src/pages/reports/site-report/[uuid].page.tsx +++ b/src/pages/reports/site-report/[uuid].page.tsx @@ -1,3 +1,4 @@ +import { Box } from "@mui/system"; import { useT } from "@transifex/react"; import Head from "next/head"; import Link from "next/link"; @@ -5,24 +6,28 @@ import { useRouter } from "next/router"; import { Fragment } from "react"; import { Else, If, Then, When } from "react-if"; -import GoalProgressCard from "@/components/elements/Cards/GoalProgressCard/GoalProgressCard"; +import TreeSpeciesTableTF from "@/admin/components/Tables/TreeSpeciesTableTF"; import EmptyState from "@/components/elements/EmptyState/EmptyState"; import ButtonField from "@/components/elements/Field/ButtonField"; +import GenericField from "@/components/elements/Field/GenericField"; import LongTextField from "@/components/elements/Field/LongTextField"; import TextField from "@/components/elements/Field/TextField"; import Paper from "@/components/elements/Paper/Paper"; import Text from "@/components/elements/Text/Text"; import EntityMapAndGalleryCard from "@/components/extensive/EntityMapAndGalleryCard/EntityMapAndGalleryCard"; -import { IconNames } from "@/components/extensive/Icon/Icon"; +import Icon, { IconNames } from "@/components/extensive/Icon/Icon"; import PageBody from "@/components/extensive/PageElements/Body/PageBody"; import PageBreadcrumbs from "@/components/extensive/PageElements/Breadcrumbs/PageBreadcrumbs"; import PageCard from "@/components/extensive/PageElements/Card/PageCard"; import PageColumn from "@/components/extensive/PageElements/Column/PageColumn"; import PageFooter from "@/components/extensive/PageElements/Footer/PageFooter"; import PageRow from "@/components/extensive/PageElements/Row/PageRow"; -import TreeSpeciesTablePD from "@/components/extensive/Tables/TreeSpeciesTablePD"; +import DisturbancesTable from "@/components/extensive/Tables/DisturbancesTable"; +import SeedingsTable from "@/components/extensive/Tables/SeedingsTable"; +import TreeSpeciesTable from "@/components/extensive/Tables/TreeSpeciesTable"; import Loader from "@/components/generic/Loading/Loader"; import LoadingContainer from "@/components/generic/Loading/LoadingContainer"; +import { EstablishmentEntityType } from "@/connections/EstablishmentTrees"; import { COLLECTION_SITE_PAID_OTHER, SITE_WORKDAY_COLLECTIONS } from "@/constants/workdayCollections"; import { ContextCondition } from "@/context/ContextCondition"; import FrameworkProvider, { Framework } from "@/context/framework.provider"; @@ -32,18 +37,15 @@ import useDemographicData from "@/hooks/useDemographicData"; import StatusBar from "@/pages/project/[uuid]/components/StatusBar"; import SiteReportHeader from "@/pages/reports/site-report/components/SiteReportHeader"; import { getFullName } from "@/utils/user"; - const SiteReportDetailPage = () => { const t = useT(); const router = useRouter(); const { format } = useDate(); const siteReportUUID = router.query.uuid as string; - const { data, isLoading } = useGetV2ENTITYUUID({ pathParams: { uuid: siteReportUUID, entity: "site-reports" } }); const siteReport = (data?.data ?? {}) as any; - const { data: site } = useGetV2ENTITYUUID( { pathParams: { uuid: siteReport?.site?.uuid, entity: "sites" } @@ -52,11 +54,9 @@ const SiteReportDetailPage = () => { enabled: !!siteReport?.site?.uuid } ); - const { data: taskReportsData } = useGetV2TasksUUIDReports({ pathParams: { uuid: siteReport.task_uuid } }); const projectReport = taskReportsData?.data?.filter(report => report.type === "project-report")?.[0] ?? {}; const reportTitle = siteReport.report_title ?? siteReport.title ?? t("Site Report"); - const { grids: workdayGrids, title: workdaysTitle } = useDemographicData( "site-report", "workdays", @@ -65,76 +65,6 @@ const SiteReportDetailPage = () => { "Site Workdays" ); - const dataTreeCount = [ - { - name: ["Species scientific name", "tree"], - treeCount: "45,000" - }, - { - name: ["Species scientific name", "Native species"], - treeCount: "45,000" - }, - { - name: ["Species scientific name", "tree"], - treeCount: "10,350" - }, - { - name: ["Species scientific name", "tree"], - treeCount: "7,500" - }, - { - name: ["Non-scientific name", "tree"], - treeCount: "4,040" - }, - { - name: ["Species scientific name", "tree"], - treeCount: "3,200" - }, - { - name: ["Species scientific name", "new"], - treeCount: "3,000" - }, - { - name: ["Species scientific name", "tree"], - treeCount: "0" - } - ]; - - const dataNonTreeCount = [ - { - name: ["Species scientific name", "tree"], - nonTreeCount: "45,000" - }, - { - name: ["Species scientific name", "Native species"], - nonTreeCount: "45,000" - }, - { - name: ["Species scientific name", "tree"], - nonTreeCount: "10,350" - }, - { - name: ["Species scientific name", "tree"], - nonTreeCount: "7,500" - }, - { - name: ["Non-scientific name", "tree"], - nonTreeCount: "4,040" - }, - { - name: ["Species scientific name", "tree"], - nonTreeCount: "3,200" - }, - { - name: ["Species scientific name", "new"], - nonTreeCount: "3,000" - }, - { - name: ["Species scientific name", "tree"], - nonTreeCount: "0" - } - ]; - return ( @@ -204,117 +134,7 @@ const SiteReportDetailPage = () => { {siteReport.technical_narrative} {siteReport.public_narrative} - - {t("Trees Planted")} - -
- -
-
- - {t("Saplings Planted")} - -
- -
-
- - {t("Seeds Planted")} - -
- -
-
- - {t("Non-Trees Planted")} - -
- -
-
-
- {t("Assisted Natural Regeneration")} - - - {t("Description of AND Activities:")} - - - {t( - "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum imperdiet consequat nulla, a dapibus nunc ultricies eget. Aliquam facilisis luctus nibh. Vivamus a lobortis nisl, scelerisque porttitor velit. Phasellus nec hendrerit felis. Proin commodo tortor consequat tortor pulvinar auctor. Nam rhoncus urna dolor, nec scelerisque elit blandit quis. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Etiam sollicitudin lobortis leo, eget laoreet magna fermentum ut. Suspendisse volutpat scelerisque felis, non commodo arcu laoreet vel. Sed facilisis volutpat est, a venenatis orci rhoncus cursus." - )} - -
- {/* + {siteReport.pct_survival_to_date} {siteReport.survival_calculation} @@ -405,7 +225,7 @@ const SiteReportDetailPage = () => { - */} + @@ -507,11 +327,9 @@ const SiteReportDetailPage = () => {

-
); }; - export default SiteReportDetailPage; diff --git a/src/pages/site/[uuid]/tabs/GoalsAndProgress.tsx b/src/pages/site/[uuid]/tabs/GoalsAndProgress.tsx index 8f69b3fe4..27d866acd 100644 --- a/src/pages/site/[uuid]/tabs/GoalsAndProgress.tsx +++ b/src/pages/site/[uuid]/tabs/GoalsAndProgress.tsx @@ -1,171 +1,40 @@ import { useT } from "@transifex/react"; -import { Else, If, Then, When } from "react-if"; import GoalProgressCard from "@/components/elements/Cards/GoalProgressCard/GoalProgressCard"; -import Text from "@/components/elements/Text/Text"; +import GenericField from "@/components/elements/Field/GenericField"; +import TextField from "@/components/elements/Field/TextField"; +import { VARIANT_TABLE_BORDER } from "@/components/elements/Table/TableVariants"; import { IconNames } from "@/components/extensive/Icon/Icon"; 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 TreeSpeciesTablePD from "@/components/extensive/Tables/TreeSpeciesTablePD"; +import TreeSpeciesTable from "@/components/extensive/Tables/TreeSpeciesTable"; +import { ContextCondition } from "@/context/ContextCondition"; import { Framework } from "@/context/framework.provider"; interface GoalsAndProgressTabProps { site: any; } -export const LABEL_LEGEND = [ - { - label: { key: "Trees", render: "Trees" }, - color: "bg-primary" - }, - { - label: { key: "Seeds", render: "Seeds" }, - color: "bg-blueCustom-900" - }, - { - label: { key: "Regenerating", render: "Regenerating" }, - color: "bg-secondary-600" - } -]; - const GoalsAndProgressTab = ({ site }: GoalsAndProgressTabProps) => { const t = useT(); - const dataTreeCount = [ - { - name: ["Species scientific name", "tree"], - treeCount: "45,000" - }, - { - name: ["Species scientific name", "Native species"], - treeCount: "45,000" - }, - { - name: ["Species scientific name", "tree"], - treeCount: "10,350" - }, - { - name: ["Species scientific name", "tree"], - treeCount: "7,500" - }, - { - name: ["Non-scientific name", "tree"], - treeCount: "4,040" - }, - { - name: ["Species scientific name", "tree"], - treeCount: "3,200" - }, - { - name: ["Species scientific name", "new"], - treeCount: "3,000" - }, - { - name: ["Species scientific name", "tree"], - treeCount: "0" - } - ]; - - const dataSeedCount = [ - { - name: ["Species scientific name", "tree"], - seedCount: "45,000" - }, - { - name: ["Species scientific name", "Native species"], - seedCount: "45,000" - }, - { - name: ["Species scientific name", "tree"], - seedCount: "10,350" - }, - { - name: ["Species scientific name", "tree"], - seedCount: "7,500" - } - ]; - const dataNonTreeCount = [ - { - name: ["Species scientific name", "tree"], - nonTreeCount: "45,000" - }, - { - name: ["Species scientific name", "Native species"], - nonTreeCount: "45,000" - }, - { - name: ["Species scientific name", "tree"], - nonTreeCount: "10,350" - }, - { - name: ["Species scientific name", "tree"], - nonTreeCount: "7,500" - } - ]; - return ( -
- - - - - +
+ { limit={site.trees_grown_goal} hasProgress={false} items={[ + { iconName: IconNames.TREE_CIRCLE, label: t("Trees Planted"), value: site.trees_planted_count }, + { iconName: IconNames.LEAF_CIRCLE, label: t("Seeds Planted"), value: site.seeds_planted_count }, { - iconName: IconNames.TREE_CIRCLE_PD, - label: t("Trees Planted:"), - variantLabel: "text-14", - classNameLabel: " text-neutral-650 uppercase", - value: site.trees_planted_count - }, - { - iconName: IconNames.LEAF_CIRCLE_PD, - label: t("Seeds Planted:"), - variantLabel: "text-14", - classNameLabel: " text-neutral-650 uppercase", - value: site.seeds_planted_count - }, - { - iconName: IconNames.REFRESH_CIRCLE_PD, - label: t("Trees Regenerating:"), - variantLabel: "text-14", - classNameLabel: " text-neutral-650 uppercase", + iconName: IconNames.REFRESH_CIRCLE, + label: t("Trees Regenerating"), value: site.regenerated_trees_count } ]} - className="pr-[41px] lg:pr-[150px]" + className="w-[30vw] max-w-[30vw] flex-1" />
- -
-
- + + {/* TODO: To be added */} + + + + + + + -
-
- - {t("PROGRESS over time:")} - -
- {LABEL_LEGEND.map((item, index) => ( -
- - - {t(item.label.key)} - -
- ))} -
-
- progress -
-
-
- -
-
-
-
- - -
-
- - - - - - - - - -
-
- - - - - - - - -
-
-
+ + + + + + + + + + +