diff --git a/components/dashboard/NavBar.tsx b/components/dashboard/NavBar.tsx new file mode 100644 index 0000000..b8f4a90 --- /dev/null +++ b/components/dashboard/NavBar.tsx @@ -0,0 +1,145 @@ +import { m, Variants } from "framer-motion"; +import Link from "next/link"; + +function NavBar() { + return ( + <m.div + className="mr-2 flex h-full w-24 flex-col items-center justify-between bg-zinc-800 p-1" + variants={navContainerVariants} + initial="initial" + animate="animate" + > + <m.div className="flex flex-col pt-5" variants={navStripVariants}> + <m.div variants={navIconVariants} className="pb-5"> + <Link href="/dashboard"> + <DashIcon /> + </Link> + </m.div> + <m.div variants={navIconVariants} className="pb-5"> + <Link href="/dashboard/ranking"> + <RankingIcon /> + </Link> + </m.div> + </m.div> + <m.div + className="flex w-full flex-col items-center justify-center pb-5" + variants={navStripVariants} + > + <Link href="/"> + <ExitIcon /> + </Link> + </m.div> + </m.div> + ); +} + +const NavSvgWrap = (props: { children: React.ReactNode }) => { + return ( + <m.svg + className="cursor-pointer" + viewBox="0 0 24 24" + width="32" + height="32" + x={0} + y={0} + origin="center" + > + {props.children} + </m.svg> + ); +}; + +const DashIcon = () => { + return ( + <NavSvgWrap> + <m.path + d="M3 13h8V3H3v10zm0 8h8v-6H3v6zm10 0h8V11h-8v10zm0-18v6h8V3h-8z" + fill="white" + stroke="white" + strokeWidth="1" + /> + </NavSvgWrap> + ); +}; + +const ExitIcon = () => { + return ( + <NavSvgWrap> + <m.path + d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z" + fill="white" + stroke="white" + strokeWidth="1" + /> + </NavSvgWrap> + ); +}; + +const RankingIcon = () => { + return ( + <NavSvgWrap> + <m.path + d="M7.5 21H2V9h5.5v12zm7.25-18h-5.5v18h5.5V3zM22 11h-5.5v10H22V11z" + fill="white" + stroke="white" + strokeWidth="1" + /> + </NavSvgWrap> + ); +}; + +const navContainerVariants: Variants = { + initial: { + opacity: 0, + x: -100, + }, + animate: { + opacity: 1, + x: 0, + transition: { + delay: 0.5, + duration: 1.0, + type: "spring", + bounce: 0.5, + stiffness: 80, + delayChildren: 1.25, + staggerChildren: 0.25, + }, + }, +}; + +const navStripVariants: Variants = { + initial: { + opacity: 0, + y: 100, + }, + animate: { + opacity: 1, + y: 0, + transition: { + duration: 1.0, + type: "spring", + bounce: 0.5, + stiffness: 80, + staggerChildren: 0.25, + delayChildren: 0.1, + }, + }, +}; + +const navIconVariants: Variants = { + initial: { + opacity: 0, + }, + animate: { + opacity: 1, + transition: { + duration: 1.0, + type: "spring", + bounce: 0.5, + stiffness: 80, + }, + }, +}; + +export default NavBar; diff --git a/layouts/DashLayout.tsx b/layouts/DashLayout.tsx new file mode 100644 index 0000000..58d6344 --- /dev/null +++ b/layouts/DashLayout.tsx @@ -0,0 +1,70 @@ +import { + AnimatePresence, + domAnimation, + LazyMotion, + m, + Variants, +} from "framer-motion"; +import Head from "next/head"; +import { useRouter } from "next/router"; +import NavBar from "../components/dashboard/NavBar"; +import { NavTemplate } from "./NavTemplates"; + +interface DashLayoutProps { + children: React.ReactNode; +} + +function DashLayout(props: DashLayoutProps) { + // get the current route for animation purposes + const router = useRouter(); + return ( + <> + <Head> + <title>Dashboard - InvestBot</title> + <meta name="description" content="Dashboard statistics for InvestBot" /> + <link rel="icon" href="/favicon.ico" /> + <meta name="theme-color" content="#c084fc" /> + <meta property="og:title" content="InvestBot" /> + <meta + property="og:description" + content="Serving anny's community est. 2022" + /> + <meta property="og:image" content="/img/logo.webp" /> + <meta property="og:type" content="website" /> + <meta property="og:site_name" content="InvestBot" /> + </Head> + + <div className="flex h-screen w-screen flex-row overflow-hidden"> + {/* dashboard nav bar */} + <LazyMotion features={domAnimation}> + <AnimatePresence mode="wait"> + <NavBar /> + </AnimatePresence> + </LazyMotion> + {/* dashboard content */} + <LazyMotion features={domAnimation}> + <AnimatePresence mode="wait"> + <m.div + key={router.route.concat("layout-fade")} + className="h-screen w-screen" + variants={containerVariants} + initial="initial" + animate="animate" + exit="exit" + > + {props.children} + </m.div> + </AnimatePresence> + </LazyMotion> + </div> + </> + ); +} + +const containerVariants: Variants = { + initial: { opacity: 0 }, + animate: { opacity: 1 }, + exit: { opacity: 0 }, +}; + +export default DashLayout; diff --git a/layouts/NavTemplates.tsx b/layouts/NavTemplates.tsx index c15c51e..19de4e2 100644 --- a/layouts/NavTemplates.tsx +++ b/layouts/NavTemplates.tsx @@ -50,6 +50,7 @@ interface NavTemplate { const homeMain: NavTemplate[] = [ { content: <DefaultNavOption label="Home" href="/" /> }, // { content: <DefaultNavOption label="About" href="/about" /> }, + { content: <DefaultNavOption label="Dashboard" href="/dashboard" /> }, { content: <DefaultNavOption label="Team" href="/team" /> }, // { content: <DefaultNavOption label="Contact" href="/contact" /> }, ]; diff --git a/pages/dashboard/index.tsx b/pages/dashboard/index.tsx new file mode 100644 index 0000000..112747d --- /dev/null +++ b/pages/dashboard/index.tsx @@ -0,0 +1,89 @@ +import { m, Variants } from "framer-motion"; +import Head from "next/head"; +import { ReactElement } from "react"; +import DashLayout from "../../layouts/DashLayout"; + +// not very mobile friendly yet +function Dashboard() { + return ( + <> + <Head> + <title>Dashboard - InvestBot</title> + </Head> + <m.div + className="inline-grid h-full w-full grid-cols-2 pt-2 pr-2 xl:grid-cols-5" + variants={gridContainerVariants} + initial="initial" + animate="animate" + > + <m.div + className="col-span-1 m-2 bg-zinc-800" + variants={gridItemVariants} + > + 1 + </m.div> + <m.div + className="col-span-3 m-2 bg-zinc-800" + variants={gridItemVariants} + > + 2 + </m.div> + <m.div + className="col-span-1 m-2 bg-zinc-800" + variants={gridItemVariants} + > + 3 + </m.div> + <m.div + className="col-span-4 m-2 bg-zinc-800" + variants={gridItemVariants} + > + 4 + </m.div> + <m.div + className="col-span-1 m-2 bg-zinc-800" + variants={gridItemVariants} + > + 5 + </m.div> + </m.div> + </> + ); +} + +const gridContainerVariants: Variants = { + initial: { + opacity: 0, + y: -100, + }, + animate: { + opacity: 1, + y: 0, + transition: { + delay: 0.8, + staggerChildren: 0.4, + duration: 1.5, + type: "spring", + bounce: 0.5, + stiffness: 80, + }, + }, +}; + +const gridItemVariants: Variants = { + initial: { + opacity: 0, + }, + animate: { + opacity: 1, + transition: { + duration: 1.0, + }, + }, +}; + +Dashboard.getLayout = function getLayout(page: ReactElement) { + return <DashLayout>{page}</DashLayout>; +}; + +export default Dashboard; diff --git a/pages/dashboard/ranking.tsx b/pages/dashboard/ranking.tsx new file mode 100644 index 0000000..1c35eed --- /dev/null +++ b/pages/dashboard/ranking.tsx @@ -0,0 +1,70 @@ +import { m, Variants } from "framer-motion"; +import Head from "next/head"; +import { ReactElement } from "react"; +import DashLayout from "../../layouts/DashLayout"; + +function Dashboard() { + return ( + <> + <Head> + <title>Ranking - InvestBot</title> + </Head> + <div className="flex min-h-screen flex-col items-center justify-start py-2"> + <m.div + className="grid w-[90vw] grid-cols-1 py-2 sm:grid-cols-2 md:grid-cols-4 lg:w-[75vw]" + variants={containerVariants} + initial="initial" + animate="animate" + > + <m.div + className="col-span-1 flex w-full items-center justify-center bg-gradient-to-r from-purple-400 to-pink-600 bg-clip-text pt-[200px] pb-[100px] font-plusJakarta text-transparent sm:col-span-2 md:col-span-4" + variants={headerVariants} + > + <m.h1 className="text-6xl">rankings</m.h1> + </m.div> + </m.div> + </div> + </> + ); +} + +const containerVariants: Variants = { + initial: { + opacity: 1, + }, + animate: { + opacity: 1, + transition: { + duration: 2, + delayChildren: 0.5, + staggerChildren: 0.25, + type: "spring", + bounce: 0.5, + stiffness: 80, + }, + }, +}; + +const headerVariants: Variants = { + initial: { + opacity: 0, + y: 100, + }, + animate: { + opacity: 1, + y: 0, + transition: { + delay: 0.5, + duration: 1.0, + type: "spring", + bounce: 0.5, + stiffness: 80, + }, + }, +}; + +Dashboard.getLayout = function getLayout(page: ReactElement) { + return <DashLayout>{page}</DashLayout>; +}; + +export default Dashboard;