Skip to content

Commit

Permalink
billboard component and dummy league videos
Browse files Browse the repository at this point in the history
  • Loading branch information
teachmetw committed Sep 11, 2023
1 parent f563b57 commit 249088a
Show file tree
Hide file tree
Showing 12 changed files with 336 additions and 9 deletions.
33 changes: 33 additions & 0 deletions components/AccountMenu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { signOut } from 'next-auth/react';
import React from 'react';

import useCurrentUser from '@/hooks/useCurrentUser';

interface AccountMenuProps {
visible?: boolean;
}

const AccountMenu: React.FC<AccountMenuProps> = ({ visible }) => {
const { data: currentUser } = useCurrentUser();

if (!visible) {
return null;
}

return (
<div className="bg-black w-56 absolute top-14 right-0 py-5 flex-col border-2 border-gray-800 flex">
<div className="flex flex-col gap-3">
<div className="px-3 group/item flex flex-row gap-3 items-center w-full">
<img className="w-10 rounded-md" src="/images/profiles/5992.png" alt="Profile"></img>
<p className="text-white text-sm group-hover/item:underline">{currentUser?.name}</p>
</div>
</div>
<hr className="bg-gray-600 border-0 h-px my-4" />
<div onClick={() => signOut()} className="px-3 text-center text-white text-sm hover:underline">
Sign out of NeetHub
</div>
</div>
)
}

export default AccountMenu;
41 changes: 41 additions & 0 deletions components/Billboard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import useBillboard from '@/hooks/useBillboard';
import React, { useCallback } from 'react';
import { AiOutlineInfoCircle } from 'react-icons/ai';

const Billboard = () => {
const { data } = useBillboard();

return (
<div className='relative h-[56.25vw]'>
<video poster={data?.thumbnailUrl} className="w-full h-[56.25vw] object-cover brightness-[60%] transition duration-500" autoPlay muted loop src={data?.videoUrl}></video>
<div className="absolute top-[30%] md:top-[40%] ml-4 md:ml-16">
<p className="text-white text-1xl md:text-5xl h-full w-[70%] lg:text-6xl font-bold drop-shadow-xl m-0 p-0 white-space-nowrap">
{data?.title}
</p>
<p className="text-white text-[8px] md:text-lg mt-3 md:mt-8 w-[90%] md:w-[80%] lg:w-[50%] drop-shadow-xl">
{data?.description}
</p>
<div className='flex flex-row items-center mt-3 md:mt-4 gap-3'>
<button className='bg-white
text-white
bg-opacity-30
rounded-md
py-1 md:py-2
px-2 md:px-4
w-auto
text-xs lg:text-lg
font-semibold
flex flex-row
items-center
hover:bg-opacity-20
transition'>
<AiOutlineInfoCircle className="mr-1"/>
More Info
</button>
</div>
</div>
</div>
)
}

export default Billboard;
32 changes: 32 additions & 0 deletions components/MobileMenu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React from 'react';

interface MobileMenuProps {
visible?: boolean;
}

const MobileMenu: React.FC<MobileMenuProps> = ({visible}) => {
if (!visible) return null;
return (
<div className='bg-black w-56 absolute top-8 left-0 py-5 flex-col border-2 border-gray-800 flex'>
<div className='flex flex-col gap-4'>
<div className='px-3 text-center text-white hover:underline'>
Home
</div>
<div className='px-3 text-center text-white hover:underline'>
Educational
</div>
<div className='px-3 text-center text-white hover:underline'>
Entertainment
</div>
<div className='px-3 text-center text-white hover:underline'>
New & Popular
</div>
<div className='px-3 text-center text-white hover:underline'>
My Watch List
</div>
</div>
</div>
)
}

export default MobileMenu;
90 changes: 90 additions & 0 deletions components/Navbar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import NavbarItem from "./Navbaritem"
import MobileMenu from "./MobileMenu"
import { FaChevronDown } from "react-icons/fa"
import { useCallback, useEffect, useState } from "react"
import { BsSearch, BsBell } from "react-icons/bs"
import AccountMenu from "./AccountMenu"


const TOP_OFFSET = 66;

const Navbar = () => {
const [showMobileMenu, setShowMobileMenu] = useState(false);
const [showAccountMenu, setShowAccountMenu] = useState(false);
const [showBackground, setShowBackground] = useState(false);

useEffect(() => {
const handleScroll = () => {
if (window.scrollY >= TOP_OFFSET) {
setShowBackground(true);
} else {
setShowBackground(false);
}
}
window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
}, []);



const toggleMobileMenu = useCallback(() => {
setShowMobileMenu((current) => !current);
}, []);
const toggleAccountMenu = useCallback(() => {
setShowAccountMenu((current) => !current);
}, []);

return (
<nav className="w-full fixed z-40">
<div className={`
px-4
md:px-16
py-6
flex
flex-row
items-center
transition
duration-500
${showBackground ? 'bg-zinc-900 bg-opacity-90' : ''}
`}>
<img src="/images/logo.png" alt="Logo" className="h-10 lg:h-20"></img>
<div className="
flex-row
ml-8
gap-7
hidden
lg:flex
">
<NavbarItem label="Home"/>
<NavbarItem label="Educational"/>
<NavbarItem label="Entertainment"/>
<NavbarItem label="New & Popular"/>
<NavbarItem label="My Watch List"/>
</div>
<div onClick= {toggleMobileMenu} className="lg:hidden flex flex-row items-center gap-2 ml-8 cursor-pointer relative">
<p className="text-white text-sm">Browse</p>
<FaChevronDown className={`text-white transition ${showMobileMenu ? 'rotate-180': 'rotate-0' }`}/>
<MobileMenu visible={showMobileMenu}/>
</div>
<div className="flex flex-row ml-auto gap-7 items-center">
<div className="text-gray-200 hover:text-gray-300 cursor-pointer transition">
<BsSearch />
</div>
<div className="text-gray-200 hover:text-gray-300 cursor-pointer transition">
<BsBell />
</div>

<div onClick={toggleAccountMenu} className="flex flex-row items-center gap-2 cursor-pointer relative">
<div className="w-6 h-6 lg:w-10 lg:h-10 rounded-md overflow-hidden">
<img src="/images/profiles/5992.png" alt="Profile"></img>
</div>
<FaChevronDown className={`text-white transition ${showAccountMenu ? 'rotate-180': 'rotate-0' }`}/>
<AccountMenu visible={showAccountMenu}/>
</div>
</div>
</div>
</nav>
)
}

export default Navbar
15 changes: 15 additions & 0 deletions components/Navbaritem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react';

interface NavbarItemProps {
label: string;
}

const NavbarItem: React.FC<NavbarItemProps> = ({label}) => {
return (
<div className="text-white cursor-pointer hover:text-gray-300 transition">
{label}
</div>
)
}

export default NavbarItem;
17 changes: 17 additions & 0 deletions hooks/useBillboard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import useSwr from 'swr'
import fetcher from '@/lib/fetcher';

const useBillboard = () => {
const { data, error, isLoading } = useSwr('/api/random', fetcher, {
revalidateIfStale: false,
revalidateOnFocus: false,
revalidateOnReconnect: false,
});
return {
data,
error,
isLoading
}
};

export default useBillboard;
17 changes: 17 additions & 0 deletions hooks/useMovieLists.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import useSWR from 'swr';
import fetcher from '@/lib/fetcher';

const useMovieLists = () => {
const { data, error, isLoading } = useSWR('/api/movies', fetcher, {
revalidateIfStale: false,
revalidateOnFocus: false,
revalidateOnReconnect: false,
});
return {
data,
error,
isLoading
}
};

export default useMovieLists;
34 changes: 34 additions & 0 deletions movies.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
[
{
"title":"Ranking the VILLAINS of League from BEST to WORST (ft. Necrit)",
"description":"Diving deep into League's Lore to determine who is the best villain in the game.",
"videoUrl":"https://youtu.be/wnGA023JFqc",
"thumbnailUrl":"https://img.youtube.com/vi/wnGA023JFqc/maxresdefault.jpg",
"genre":"Comedy",
"duration":"33 minutes"
},
{
"title":"The Nexus Slap | Wood Division Adventures",
"description":"Misplays, goofy, funny, and epic moments in League of Legends. From Bronze to Challenger, Korea to Europe.",
"videoUrl":"https://youtu.be/qyiJCM6Y4RM",
"thumbnailUrl":"https://img.youtube.com/vi/qyiJCM6Y4RM/maxresdefault.jpg",
"genre":"Comedy",
"duration":"8 minutes"
},
{
"title":"Kim Jae Aatrox",
"description":"Korean Aatrox montage | Challenger ",
"videoUrl":"https://youtu.be/uF0ngRmRI_A",
"thumbnailUrl":"https://img.youtube.com/vi/uF0ngRmRI_A/maxresdefault.jpg",
"genre":"Gameplay",
"duration":"23 minutes"
},
{
"title":"Aatrox Guide",
"description":"LoL Dobby's Guide on Aatrox",
"videoUrl":"https://youtu.be/FTx23POvqbo",
"thumbnailUrl":"https://img.youtube.com/vi/FTx23POvqbo/maxresdefault.jpg",
"genre":"Educational",
"duration":"10 minutes"
}
]
18 changes: 18 additions & 0 deletions pages/api/movies/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { NextApiRequest, NextApiResponse } from 'next';
import prismadb from '@/lib/prismadb';
import serverAuth from '@/lib/serverAuth';

export default async function handler(req: NextApiRequest, res: NextApiResponse) {

if (req.method !== 'GET') {
return res.status(405).json({ message: 'Method not allowed' });
}

try {
await serverAuth(req, res);
const movies = await prismadb.movie.findMany();
return res.status(200).json(movies);
} catch (error) {
return res.status(401).json({ message: 'Unauthorized' });
}
}
27 changes: 27 additions & 0 deletions pages/api/random.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { NextApiRequest, NextApiResponse } from "next";
import prismadb from '@/lib/prismadb';
import serverAuth from "@/lib/serverAuth";

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
if (req.method !== 'GET') {
return res.status(405).end();
}

await serverAuth(req, res);

const moviesCount = await prismadb.movie.count();
const randomIndex = Math.floor(Math.random() * moviesCount);

const randomMovies = await prismadb.movie.findMany({
take: 1,
skip: randomIndex
});

return res.status(200).json(randomMovies[0]);
} catch (error) {
console.log(error);

return res.status(500).end();
}
}
15 changes: 9 additions & 6 deletions pages/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import useCurrentUser from '@/hooks/useCurrentUser';
import { NextPageContext } from 'next';
import { getSession, signOut } from 'next-auth/react';
import Navbar from '@/components/Navbar';
import Billboard from '@/components/Billboard';

export async function getServerSideProps(context: NextPageContext) {
const session = await getSession(context);
Expand All @@ -21,11 +23,12 @@ export default function Home() {
const { data: user } = useCurrentUser();
return (
<>
<h1 className="text-2xl text-blue-500">
Hello world!
</h1>
<p> Logged in as {user?.email}</p>
<button onClick={() => signOut()}>Sign out</button>
<Navbar />
<Billboard/>
<div className='pb-40'>
<MovieList/>
</div>

</>
)
}
}
6 changes: 3 additions & 3 deletions pages/profiles.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { NextPageContext } from 'next';
import { getSession } from 'next-auth/react';
import useCurrentUser from '@/hooks/useCurrentUser';

import { useRouter } from 'next/router';

export async function getServerSideProps(context: NextPageContext) {
const session = await getSession(context);
Expand All @@ -19,15 +19,15 @@ export async function getServerSideProps(context: NextPageContext) {
}

const Profiles = () => {

const router = useRouter();
const { data: user } = useCurrentUser();

return (
<div className='flex items-center h-full justify-center'>
<div className='flex flex-col'>
<h1 className='text-3xl md:text-6xl text-center text-white'>Who is using?</h1>
<div className='flex items-center justify-center gap-8 mt-10'>
<div onClick={() => {}}>
<div onClick={() => router.push('/')}>
<div className='group flex-row w-44 mx-auto'>
<div className='
w-44
Expand Down

0 comments on commit 249088a

Please sign in to comment.