Skip to content

Commit

Permalink
feat: Integrate IntroModal component and add IntroModalManager for vi…
Browse files Browse the repository at this point in the history
…sibility control
  • Loading branch information
atrincas committed Dec 26, 2024
1 parent c008298 commit 086b759
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 0 deletions.
2 changes: 2 additions & 0 deletions client/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -57,6 +58,7 @@ export default async function RootLayout({
<body className={inter.className}>
<SidebarProvider>
<MainNav />
<IntroModal />
<main className="mx-3 flex h-dvh flex-1">{children}</main>
</SidebarProvider>
<Toaster />
Expand Down
112 changes: 112 additions & 0 deletions client/src/containers/intro-modal/index.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<Dialog open={isOpen} onOpenChange={handleClose}>
<DialogContent>
<DialogHeader className="space-y-5">
<DialogTitle className="text-xl font-semibold">
Welcome to Blue Carbon Cost Tool
</DialogTitle>
<DialogDescription className="text-base font-normal text-foreground">
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.
</DialogDescription>
</DialogHeader>
<ul className="mb-6 space-y-4">
{introItems.map((item) => (
<li key={item.title}>
<div className="flex items-start gap-4 pt-2">
<div className="rounded-full bg-sidebar-accent p-2">
<item.icon
className="size-5 text-big-stone-50"
strokeWidth={1}
/>
</div>
<div className="space-y-2.5">
<h3 className="text-base font-bold">{item.title}</h3>
<p className="text-sm font-normal text-foreground">
{item.description}
</p>
</div>
</div>
</li>
))}
</ul>
<DialogFooter className="flex-col gap-4 sm:items-center sm:justify-between">
<CheckboxWrapper
id="dontShowAgain"
label="Don't show this introduction again."
checked={dontShowAgain}
onCheckedChange={(checked) => setDontShowAgain(checked === true)}
/>
<Button onClick={() => handleClose()}>Discover</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
};

export default IntroModal;
22 changes: 22 additions & 0 deletions client/src/lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();

0 comments on commit 086b759

Please sign in to comment.