diff --git a/components/common/NavBar.tsx b/components/common/NavBar.tsx new file mode 100644 index 0000000..1f6d8cf --- /dev/null +++ b/components/common/NavBar.tsx @@ -0,0 +1,102 @@ +import Link from "next/link"; +import { useState, Fragment } from "react"; +import { NavTemplate } from "../../layouts/NavTemplates"; +import Image from "next/image"; +import { m, Variants } from "framer-motion"; + +interface NavProps { + options: NavTemplate[]; +} + +// nav bar animation, fades in and then animates the children +const containerAnimation: Variants = { + initial: { + opacity: 1, + }, + animate: { + opacity: 1, + transition: { + duration: 2, + delayChildren: 0.5, + staggerChildren: 0.25, + }, + }, +}; + +// default animation for nav bar items +const itemAnimation: Variants = { + initial: { + opacity: 0, + x: 100, + }, + animate: { + opacity: 1, + x: 0, + }, +}; + +function NavBar({ options }: NavProps) { + const [navList, setNavList] = useState(options); + return ( + + + + + InvestBot Logo + +

+ InvestBot +

+ +
+ + {navList.map((nav, index) => ( + {nav.content} + ))} + + +

+ Login blah blah +

+
+
+
+ ); +} + +export default NavBar; diff --git a/layouts/HomeLayout.tsx b/layouts/HomeLayout.tsx new file mode 100644 index 0000000..fe56766 --- /dev/null +++ b/layouts/HomeLayout.tsx @@ -0,0 +1,37 @@ +// Layout/container used for the main mostly empty landing page, can be used for related pages (credits, about, etc.) + +import { AnimatePresence, domAnimation, LazyMotion } from "framer-motion"; +import Head from "next/head"; +import NavBar from "../components/common/NavBar"; +import { NavTemplate } from "./NavTemplates"; + +interface HomeLayoutProps { + navOptions: NavTemplate[]; + children: React.ReactNode; +} + +function HomeLayout(props: HomeLayoutProps) { + // get the nav options + const navOptions = props.navOptions; + return ( + <> + + InvestBot + + + + + + + + + + +
{props.children}
+
+
+ + ); +} + +export default HomeLayout; diff --git a/layouts/NavTemplates.tsx b/layouts/NavTemplates.tsx new file mode 100644 index 0000000..4b74c1c --- /dev/null +++ b/layouts/NavTemplates.tsx @@ -0,0 +1,44 @@ +import { m } from "framer-motion"; +import Link from "next/link"; +import { ReactComponentElement, ReactElement } from "react"; + +const DefaultNavOption = ({ + label, + href, +}: { + label: string; + href: string; +}): ReactElement => { + return ( + + +

+ {label} +

+ +
+ ); +}; + +interface NavTemplate { + content: ReactComponentElement | ReactElement; +} + +const homeMain: NavTemplate[] = []; + +export { type NavTemplate, homeMain }; diff --git a/next.config.js b/next.config.js index 3d3bc99..bd38de3 100644 --- a/next.config.js +++ b/next.config.js @@ -2,6 +2,9 @@ const nextConfig = { reactStrictMode: true, swcMinify: true, + images: { + domains: ["cdn.discordapp.com", "static-cdn.jtvnw.net", "cdn.7tv.app"], + }, }; module.exports = nextConfig; diff --git a/pages/index.tsx b/pages/index.tsx index 869ab07..2118f0e 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -1,17 +1,93 @@ -import Head from "next/head"; +import { m } from "framer-motion"; +import { ReactElement, useEffect, useState } from "react"; +import HomeLayout from "../layouts/HomeLayout"; +import { homeMain } from "../layouts/NavTemplates"; +import type { NextPageWithLayout } from "./_app"; +import Image from "next/image"; + +const Home: NextPageWithLayout = () => { + let api7tvEmotes = `/api/7tv/emotes?c=61ad997effa9aba101bcfddf`; + const [emotesUrls, setEmotes] = useState([]); + const [currentEmote, setCurrentEmote] = useState(0); + useEffect(() => { + fetch(api7tvEmotes) + .then((res) => res.json()) + .then((data) => { + // get all emote URLs + let emoteUrls = data.channel.user.emote_sets[0].emotes.map( + (emote: any) => { + let base_url = emote.data.host.url; + // get the largest emote size, append it to the base url + let largest = + emote.data.host.files[emote.data.host.files.length - 1]; + // if width != height, skip it + if (largest.width !== largest.height) { + return null; + } + return `https:${base_url}/${largest.name}`; + } + ); + + // remove null values + + emoteUrls = emoteUrls.filter((emote: any) => emote !== null); + + setEmotes(emoteUrls); + console.log(emoteUrls); + }); + console.log(currentEmote); + + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + useEffect(() => { + const interval = setInterval(() => { + // choose a random emote + let randomEmote = Math.floor(Math.random() * emotesUrls.length); + setCurrentEmote(randomEmote); + }, 5000); + return () => clearInterval(interval); + }, [emotesUrls]); + + // until the emotes are loaded, show the logo as a placeholder + let slideShow = ( + InvestBot Logo + ); + if (emotesUrls) { + slideShow = ( + 7tv emote + ); + } -export default function Home() { return ( -
- - InvestBot - - - - -
-

Hello :o

-
+
+
+
+ Buy high + Sell low + ...or something like that +
+
{slideShow}
+
); -} +}; + +// set the layout for the page, this is used to wrap the page in a layout +Home.getLayout = function getLayout(page: ReactElement) { + return {page}; +}; + +export default Home; diff --git a/public/favicon.ico b/public/favicon.ico index 718d6fe..3ceb202 100644 Binary files a/public/favicon.ico and b/public/favicon.ico differ diff --git a/public/img/logo.webp b/public/img/logo.webp new file mode 100644 index 0000000..740f4d7 Binary files /dev/null and b/public/img/logo.webp differ diff --git a/tailwind.config.js b/tailwind.config.js index 4842997..e189919 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -3,6 +3,7 @@ module.exports = { content: [ "./pages/**/*.{js,ts,jsx,tsx}", "./components/**/*.{js,ts,jsx,tsx}", + "./layouts/**/*.{js,ts,jsx,tsx}", ], theme: { extend: {},