From 4b3fb93f49312fdae735935682ec16a25443dd14 Mon Sep 17 00:00:00 2001 From: atrincas Date: Thu, 9 Jan 2025 08:27:52 +0100 Subject: [PATCH] refactor: currency component and intro modal organization --- client/src/components/ui/currency.tsx | 2 +- client/src/components/ui/graph.tsx | 40 ++++++++-------- client/src/containers/intro-modal/index.tsx | 41 +++------------- client/src/containers/intro-modal/utils.ts | 48 +++++++++++++++++++ .../containers/overview/map/popup/index.tsx | 11 +++-- .../overview/table/view/overview/columns.tsx | 2 +- client/src/lib/format.tsx | 19 -------- client/src/lib/utils.ts | 24 ---------- 8 files changed, 83 insertions(+), 104 deletions(-) create mode 100644 client/src/containers/intro-modal/utils.ts diff --git a/client/src/components/ui/currency.tsx b/client/src/components/ui/currency.tsx index 5a6cd1b4..66933d0c 100644 --- a/client/src/components/ui/currency.tsx +++ b/client/src/components/ui/currency.tsx @@ -39,7 +39,7 @@ const Currency: FC = ({ "inline-block": true, "first-letter:align-top first-letter:text-xs first-letter:tracking-[0.1rem] first-letter:text-muted-foreground": !plainSymbol, - "first-letter:pr-1": plainSymbol, + "first-letter:pr-0.5": plainSymbol, }, className, )} diff --git a/client/src/components/ui/graph.tsx b/client/src/components/ui/graph.tsx index 7f5a38a6..da956f10 100644 --- a/client/src/components/ui/graph.tsx +++ b/client/src/components/ui/graph.tsx @@ -1,6 +1,6 @@ import { FC } from "react"; -import { renderCurrency } from "@/lib/format"; +import Currency from "@/components/ui/currency"; interface GraphProps { /** The total value that represents 100% of the graph */ @@ -43,14 +43,14 @@ const Graph: FC = ({ total, leftover, segments }) => { >
- {renderCurrency( - total, - { +
@@ -66,14 +66,14 @@ const Graph: FC = ({ total, leftover, segments }) => { >
- {renderCurrency( - value, - { +
@@ -104,14 +104,14 @@ const Graph: FC = ({ total, leftover, segments }) => { >
- {renderCurrency( - value, - { +
@@ -173,7 +173,7 @@ const GraphWithLegend: FC = ({
- {renderCurrency(leftover || total)} +
{ - const [isOpen, setIsOpen] = useState(introModalManager.showIntroModal()); + const [isOpen, setIsOpen] = useState(showIntroModal()); const [dontShowAgain, setDontShowAgain] = useState(false); const handleClose = useCallback( (open = false) => { setIsOpen(open); if (dontShowAgain) { - introModalManager.setHideIntroModal(); + setHideIntroModal(); } }, [dontShowAgain], diff --git a/client/src/containers/intro-modal/utils.ts b/client/src/containers/intro-modal/utils.ts new file mode 100644 index 00000000..9b6ae60b --- /dev/null +++ b/client/src/containers/intro-modal/utils.ts @@ -0,0 +1,48 @@ +import { + ClipboardPenIcon, + FileQuestionIcon, + LayoutDashboardIcon, + UserIcon, +} from "lucide-react"; + +const isServer = typeof window === "undefined"; + +export const introItems = [ + { + title: "Project Overview", + description: + "Explore and compare over 400 project scenarios with ease. Apply filters for location, ecosystem type, activity, cost, abatement potential and project size. The global map visualizes project blue carbon potential across 9 countries, enabling comparisons based on cost-to-abatement ratios. Additionally, use the comparison table for detailed cost and score analyses, and select a project for additional details.", + icon: LayoutDashboardIcon, + }, + { + title: "Create custom projects", + description: + "Design custom scenarios by modifying default parameters and exploring the resulting data in detail. Save your projects to revisit them anytime and quickly compare all the scenarios you’ve created.", + icon: ClipboardPenIcon, + }, + { + title: "Methodology", + description: + "Explore for detailed information on model assumptions, estimations, and data sources.", + icon: FileQuestionIcon, + }, + { + title: "Profile", + description: "Access information about your personal account.", + icon: UserIcon, + }, +]; + +export const showIntroModal = (): boolean => { + if (isServer) return false; + + return ( + !!process.env.HIDE_INTRO_MODAL || !localStorage.getItem("hideIntroModal") + ); +}; + +export const setHideIntroModal = (): void => { + if (isServer) return; + + localStorage.setItem("hideIntroModal", "true"); +}; diff --git a/client/src/containers/overview/map/popup/index.tsx b/client/src/containers/overview/map/popup/index.tsx index 59355f86..aa607496 100644 --- a/client/src/containers/overview/map/popup/index.tsx +++ b/client/src/containers/overview/map/popup/index.tsx @@ -1,11 +1,12 @@ import { useAtomValue } from "jotai"; -import { renderCurrency } from "@/lib/format"; +import { formatNumber } from "@/lib/format"; import { cn } from "@/lib/utils"; import { popupAtom } from "@/app/(overview)/store"; import MapPopup from "@/components/map/popup"; +import Currency from "@/components/ui/currency"; const HEADER_CLASSES = "py-0.5 text-left font-normal text-muted-foreground"; const CELL_CLASSES = "py-0.5 font-semibold"; @@ -30,16 +31,18 @@ export default function CostAbatementPopup() { - {renderCurrency(popup?.features?.[0]?.properties?.cost)} + - {popup?.features?.[0]?.properties?.abatementPotential} + {formatNumber( + popup?.features?.[0]?.properties?.abatementPotential, + )}

- Values for the SUM of all projects. + Values for the SUM of all project combinations.

); diff --git a/client/src/containers/overview/table/view/overview/columns.tsx b/client/src/containers/overview/table/view/overview/columns.tsx index a99608a8..1c6fc089 100644 --- a/client/src/containers/overview/table/view/overview/columns.tsx +++ b/client/src/containers/overview/table/view/overview/columns.tsx @@ -85,7 +85,7 @@ export const columns = (filters: z.infer) => [ filters.costRangeSelector === "npv" ? "costPerTCO2eNPV" : "costPerTCO2e", { enableSorting: true, - header: () => Cost $(USD)/tCo2, + header: () => Cost $(USD)/tCO2e, cell: (props) => { const value = props.getValue(); if (value === null || value === undefined) { diff --git a/client/src/lib/format.tsx b/client/src/lib/format.tsx index 6cafafa6..e9371158 100644 --- a/client/src/lib/format.tsx +++ b/client/src/lib/format.tsx @@ -1,5 +1,3 @@ -import { cn } from "@/lib/utils"; - export const formatCurrency = ( value: number, options: Intl.NumberFormatOptions = {}, @@ -23,23 +21,6 @@ export const formatNumber = ( }).format(value); }; -export function renderCurrency( - value: number, - options: Intl.NumberFormatOptions = {}, - className?: HTMLSpanElement["className"], -) { - return ( - - {formatCurrency(value, options)} - - ); -} - /** * Converts a large numeric value into a compact format with an "M" suffix * representing millions. diff --git a/client/src/lib/utils.ts b/client/src/lib/utils.ts index 1b7a7e3b..e8738b1e 100644 --- a/client/src/lib/utils.ts +++ b/client/src/lib/utils.ts @@ -43,30 +43,6 @@ export const parseTableData = < value: formatCurrency(data[key as K], { maximumFractionDigits: 0 }), })); }; -class IntroModalManager { - private static instance: IntroModalManager; - private isServer: boolean = typeof window === "undefined"; - - public static getInstance(): IntroModalManager { - if (!IntroModalManager.instance) { - IntroModalManager.instance = new IntroModalManager(); - } - return IntroModalManager.instance; - } - - public showIntroModal(): boolean { - if (this.isServer) return false; - return ( - !!process.env.HIDE_INTRO_MODAL || !localStorage.getItem("hideIntroModal") - ); - } - - public setHideIntroModal(): void { - if (this.isServer) return; - localStorage.setItem("hideIntroModal", "true"); - } -} -export const introModalManager = IntroModalManager.getInstance(); const PRIVATE_PAGES = /^(\/profile|\/my-projects)/; export const isPrivatePath = (pathname: string) => {