Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…e_nextjs into clean
  • Loading branch information
kleenpulse committed Jul 24, 2024
2 parents 33e43e5 + ead7587 commit 981e567
Show file tree
Hide file tree
Showing 40 changed files with 1,638 additions and 32 deletions.
Binary file added public/email/email-verification.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/logo/dashboard-logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/logo/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
92 changes: 92 additions & 0 deletions src/app/(admin)/_components/layout/Sidebar/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
"use client";

import { Box, House, LucideProps, Mail, Settings, Users } from "lucide-react";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { FC, ForwardRefExoticComponent, RefAttributes } from "react";

import DashboardLogo from "../logo";

const sideItems = [
{
route: "Dashboard",
link: "/admin/dashboard",
icon: House,
id: "dashboard",
},
{
route: "Products",
link: "/admin/products",
icon: Box,
id: "products",
},
{
route: "Users",
link: "/admin/users",
icon: Users,
id: "users",
},
{
route: "Email Templates",
link: "/admin/email",
icon: Mail,
id: "email",
},
{
route: "Squeeze Pages",
link: "/admin/squeeze-pages",
icon: Users,
id: "squeeze",
},
{
route: "Waitlist Page",
link: "/admin/waitlist-page",
icon: Mail,
id: "waitlist",
},
{
route: "Settings",
link: "/admin/settings",
icon: Settings,
id: "settings",
},
];
interface Iproperties {
sideNavitems?: {
route: string;
link: string;
icon: ForwardRefExoticComponent<
Omit<LucideProps, "ref"> & RefAttributes<SVGSVGElement>
>;
id: string;
}[];
currenPathName?: string;
}
const Sidebar: FC<Iproperties> = ({
sideNavitems = sideItems,
currenPathName,
}) => {
const pathname = usePathname();
const currentPath = pathname?.split("/")[2];
return (
<div className="flex flex-col items-center justify-start border-r bg-muted/40 md:block md:px-4">
<DashboardLogo />
<section className="flex flex-col items-center gap-5 pt-6 md:items-stretch">
{sideNavitems.map((item, index) => (
<Link
key={index}
href={item.link}
data-testid={item.id}
role="sidebar-link"
className={`${currenPathName || currentPath === item.id ? "bg-primary text-white" : "bg-transparent text-neutral-dark-2"} flex h-10 w-10 items-center justify-center gap-3 rounded-full px-2.5 py-4 transition-all duration-300 hover:bg-primary hover:text-white md:h-auto md:w-auto md:justify-start md:rounded-[8px]`}
>
<item.icon className="h-5 w-5" role="sidebar-icon" />
<span className="hidden md:block">{item.route}</span>
</Link>
))}
</section>
</div>
);
};

export default Sidebar;
83 changes: 83 additions & 0 deletions src/app/(admin)/_components/layout/Sidebar/sidebar.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { Box, House, Mail, Settings, Users } from "lucide-react";

import { render, screen } from "~/test/utils";
import Sidebar from "./";

const sideItems = [
{
route: "Dashboard",
link: "/admin/dashboard",
icon: House,
id: "dashboard",
},
{
route: "Products",
link: "/admin/products",
icon: Box,
id: "products",
},
{
route: "Users",
link: "/admin/users",
icon: Users,
id: "users",
},
{
route: "Email Templates",
link: "/admin/email",
icon: Mail,
id: "email",
},
{
route: "Squeeze Pages",
link: "/admin/squeeze-pages",
icon: Users,
id: "squeeze",
},
{
route: "Waitlist Page",
link: "/admin/waitlist-page",
icon: Mail,
id: "waitlist",
},
{
route: "Settings",
link: "/admin/settings",
icon: Settings,
id: "settings",
},
];

describe("page tests", () => {
const renderComponent = () => {
render(<Sidebar sideNavitems={sideItems} currenPathName="dashboard" />);

return {
logo: screen.getByTestId("admin-logo"),
logoText: screen.getByTestId("admin-logo-text"),
dashboardlink: screen.getByTestId("dashboard"),
};
};
it("side logo renders", () => {
expect.assertions(2);

const { logo, logoText } = renderComponent();

expect(logo).toBeInTheDocument();
expect(logoText).toBeInTheDocument();
});

it("renders all sidebar items", () => {
expect.assertions(1);
renderComponent();
expect(screen.getAllByRole("sidebar-link")).toHaveLength(sideItems.length);
});

it("highlights active link", () => {
expect.assertions(1);
renderComponent();
expect(screen.getByTestId("dashboard")).toHaveClass(
"bg-primary text-white",
);
});
});
28 changes: 28 additions & 0 deletions src/app/(admin)/_components/layout/logo/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import Image from "next/image";
import Link from "next/link";

const DashboardLogo = () => {
return (
<Link
href="/"
className="flex w-full max-w-[24px] items-center justify-center gap-2.5 py-[14px] md:justify-start"
>
<Image
src="/logo/logo.png"
alt="Hgn boiler plate logo"
height={24}
width={24}
data-testid="admin-logo"
className="h-full w-full object-contain"
/>
<span
className="neutral-dark hidden text-2xl font-semibold md:block"
data-testid="admin-logo-text"
>
Boilerplate
</span>
</Link>
);
};

export default DashboardLogo;
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ import {
PopoverContent,
PopoverTrigger,
} from "~/components/ui/popover";
import UnreadNotificationCard from "../unread-notification-card/UnreadNotificationCard";
import UnreadNotificationCard from "../../unread-notification-card/UnreadNotificationCard";

const AdminNavbar = () => {
const DashboardNavbar = () => {
return (
<nav className="border-b-[0.5px] border-border" role="navbar">
<div className="flex items-center justify-between gap-2 bg-background px-[10px] py-[14px]">
<div className="flex h-10 items-center justify-between gap-2 rounded-[6px] border border-[#E4E4E7] bg-white px-3 text-sm font-normal placeholder:text-sm">
<div className="flex h-10 items-center justify-between gap-2 rounded-[6px] border border-border bg-white px-3 text-sm font-normal placeholder:text-sm">
<SearchIcon
data-testid="search"
className="h-4 w-4 text-neutral-dark-2"
Expand Down Expand Up @@ -71,4 +71,4 @@ const AdminNavbar = () => {
);
};

export default AdminNavbar;
export default DashboardNavbar;
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import DashboardNavbar from ".";
import { fireEvent, render, screen, waitFor } from "@testing-library/react";

import AdminNavbar from "./AdminNavbar";
import { it } from "vitest";

const renderComponents = () => {
render(<AdminNavbar />);
render(<DashboardNavbar />);

return {
helpIcon: screen.getByTestId("help"),
Expand Down
12 changes: 12 additions & 0 deletions src/app/(admin)/admin/dashboard/page.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { render } from "~/test/utils";
import Page from "./page";

describe("page tests", () => {
it("should render correctly", () => {
expect.assertions(1);

render(<Page />);

expect(true).toBeTruthy();
});
});
5 changes: 5 additions & 0 deletions src/app/(admin)/admin/dashboard/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const page = () => {
return <div>Admin dashboard</div>;
};

export default page;
48 changes: 48 additions & 0 deletions src/app/(admin)/admin/email/_components/Toptab/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { FC, ReactNode } from "react";

import { Tabs, TabsContent, TabsList, TabsTrigger } from "~/components/ui/tabs";

interface ITab {
name: string;
value: string;
content: ReactNode;
}

interface IProperties {
tabs: ITab[];
}

const Toptab: FC<IProperties> = ({ tabs }) => {
return (
<Tabs defaultValue={tabs[0].value} className="max-w-[670px]">
<TabsList className="mb-6 rounded-[8px] border-[1px] border-[#CBD5E1B2]/70 bg-transparent p-0">
{tabs?.map((tab, item) => {
return (
<TabsTrigger
data-testid="trigger-btn"
key={item}
value={tab.value}
className="rounded-none bg-transparent text-sm text-[#8E8E93] data-[state=active]:bg-[#F6F7F9] data-[state=active]:text-primary"
>
{tab.name}
</TabsTrigger>
);
})}
</TabsList>
{tabs?.map((tab, item) => {
return (
<TabsContent
data-testid="toptab-content"
key={item}
value={tab.value}
className="w-auto"
>
{tab.content}
</TabsContent>
);
})}
</Tabs>
);
};

export default Toptab;
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { render, screen } from "@testing-library/react";
import { CodeIcon, FileIcon, LucideProps } from "lucide-react";
import { ForwardRefExoticComponent } from "react";

import PageHeader from "../page-header";
import NewTemplate, { Options } from "./NewTemplate";

interface Option {
title: string;
description: string;
icon: ForwardRefExoticComponent<
Omit<LucideProps, "ref"> & React.RefAttributes<SVGSVGElement>
>;
link: string;
}

const options: Option[] = [
{
title: "Generate with HTML",
description:
"Create an email template by pasting your custom-coded template",
icon: CodeIcon,
link: "email/generate-with-html",
},
{
title: "Edit in-built Template",
description:
"Create an email template by choosing from our custom template library",
icon: FileIcon,
link: "generate-with-html",
},
];

describe("newTemplate component", () => {
it("renders admin page cards correctly", () => {
expect.assertions(6);
for (const item of options) {
render(<Options data={item} />);
expect(screen.getByText(item.title)).toBeInTheDocument();
expect(screen.getByText(item.description)).toBeInTheDocument();
expect(screen.getAllByRole("option-icon")).toBeTruthy();
}
});

it("renders page header", () => {
expect.assertions(2);
render(
<PageHeader
title="Create a New Template"
description="Choose an option below to begin crafting your email design."
/>,
);
expect.assertions(2);
expect(screen.getByText("Create a New Template")).toBeInTheDocument();
expect(
screen.getByText(
"Choose an option below to begin crafting your email design.",
),
).toBeInTheDocument();
});

it("renders card with links", () => {
expect.assertions(2);
render(<NewTemplate />);
expect(screen.getAllByRole("link")[0]).toHaveAttribute(
"href",
"email/generate-with-html",
);
expect(screen.getAllByRole("link")[1]).toHaveAttribute(
"href",
"generate-with-html",
);
});
});
Loading

0 comments on commit 981e567

Please sign in to comment.