From 086b759143a7becd7e98d0d7a1ad913d543404b2 Mon Sep 17 00:00:00 2001 From: atrincas Date: Thu, 26 Dec 2024 11:12:51 +0100 Subject: [PATCH] feat: Integrate IntroModal component and add IntroModalManager for visibility control --- client/src/app/layout.tsx | 2 + client/src/containers/intro-modal/index.tsx | 112 ++++++++++++++++++++ client/src/lib/utils.ts | 22 ++++ 3 files changed, 136 insertions(+) create mode 100644 client/src/containers/intro-modal/index.tsx diff --git a/client/src/app/layout.tsx b/client/src/app/layout.tsx index e39dc88e..c261c203 100644 --- a/client/src/app/layout.tsx +++ b/client/src/app/layout.tsx @@ -9,6 +9,7 @@ import { NuqsAdapter } from "nuqs/adapters/next/app"; import { config } from "@/app/auth/api/[...nextauth]/config"; +import IntroModal from "@/containers/intro-modal"; import MainNav from "@/containers/nav"; import { SidebarProvider } from "@/components/ui/sidebar"; @@ -57,6 +58,7 @@ export default async function RootLayout({ +
{children}
diff --git a/client/src/containers/intro-modal/index.tsx b/client/src/containers/intro-modal/index.tsx new file mode 100644 index 00000000..beb920e9 --- /dev/null +++ b/client/src/containers/intro-modal/index.tsx @@ -0,0 +1,112 @@ +"use client"; +import { useCallback, useState } from "react"; + +import { + ClipboardPenIcon, + FileQuestionIcon, + LayoutDashboardIcon, + UserIcon, +} from "lucide-react"; + +import { introModalManager } from "@/lib/utils"; + +import { Button } from "@/components/ui/button"; +import { CheckboxWrapper } from "@/components/ui/checkbox"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog"; + +const introItems = [ + { + title: "Project Overview", + description: + "Explore and compare project scenarios with ease. Apply filters for location, ecosystem type, activity, cost, abatement potential, and more. The global map visualizes project distributions, 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 original 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 assumptions, estimations, and data sources.", + icon: FileQuestionIcon, + }, + { + title: "User area", + description: "Access information about your personal account.", + icon: UserIcon, + }, +]; + +const IntroModal = () => { + const [isOpen, setIsOpen] = useState(introModalManager.showIntroModal()); + const [dontShowAgain, setDontShowAgain] = useState(false); + const handleClose = useCallback( + (open = false) => { + setIsOpen(open); + + if (dontShowAgain) { + introModalManager.setHideIntroModal(); + } + }, + [dontShowAgain], + ); + + return ( + + + + + Welcome to Blue Carbon Cost Tool + + + The Blue Carbon Cost Tool estimates project costs and carbon + benefits of Blue Carbon Market projects, providing a high-level view + for comparisons and prioritization among different project + scenarios. + + +
    + {introItems.map((item) => ( +
  • +
    +
    + +
    +
    +

    {item.title}

    +

    + {item.description} +

    +
    +
    +
  • + ))} +
+ + setDontShowAgain(checked === true)} + /> + + +
+
+ ); +}; + +export default IntroModal; diff --git a/client/src/lib/utils.ts b/client/src/lib/utils.ts index 0ea627fb..af13e998 100644 --- a/client/src/lib/utils.ts +++ b/client/src/lib/utils.ts @@ -43,3 +43,25 @@ 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 !localStorage.getItem("hideIntroModal"); + } + + public setHideIntroModal(): void { + if (this.isServer) return; + localStorage.setItem("hideIntroModal", "true"); + } +} +export const introModalManager = IntroModalManager.getInstance();