Skip to content

Commit

Permalink
more components and functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
teachmetw committed Sep 11, 2023
1 parent 114cadb commit 03c78cb
Show file tree
Hide file tree
Showing 11 changed files with 359 additions and 178 deletions.
5 changes: 4 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
{
"extends": "next/core-web-vitals"
"extends": "next/core-web-vitals",
"rules": {
"@next/next/no-img-element": "off"
}
}
88 changes: 52 additions & 36 deletions components/Billboard.tsx
Original file line number Diff line number Diff line change
@@ -1,41 +1,57 @@
import useBillboard from '@/hooks/useBillboard';
import React, { useCallback } from 'react';
import { AiOutlineInfoCircle } from 'react-icons/ai';
import { InformationCircleIcon } from '@heroicons/react/24/outline';

import PlayButton from '@/components/PlayButton';
import useBillboard from '@/hooks/useBillboard';
import useInfoModalStore from '@/hooks/useInfoModalStore';

const Billboard: React.FC = () => {
const { openModal } = useInfoModalStore();
const { data } = useBillboard();

const Billboard = () => {
const { data } = useBillboard();
const handleOpenModal = useCallback(() => {
openModal(data?.id);
}, [openModal, data?.id]);

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>


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-[50%] lg:text-6xl font-bold drop-shadow-xl">
{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">
<PlayButton movieId={data?.id} />
<button
onClick={handleOpenModal}
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
"
>
<InformationCircleIcon className="w-4 md:w-7 mr-1" />
More Info
</button>
</div>
)
</div>
</div>
)
}

export default Billboard;
export default Billboard;
79 changes: 79 additions & 0 deletions components/InfoModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import React, { useCallback, useEffect, useState } from 'react';
import { XMarkIcon } from '@heroicons/react/24/outline';

import PlayButton from '@/components/PlayButton';
import FavoriteButton from '@/components/FavoriteButton';
import useInfoModalStore from '@/hooks/useInfoModalStore';
import useMovie from '@/hooks/useMovie';

interface InfoModalProps {
visible?: boolean;
onClose: any;
}

const InfoModal: React.FC<InfoModalProps> = ({ visible, onClose }) => {
const [isVisible, setIsVisible] = useState<boolean>(!!visible);

const { movieId } = useInfoModalStore();
const { data = {} } = useMovie(movieId);

useEffect(() => {
setIsVisible(!!visible);
}, [visible]);

const handleClose = useCallback(() => {
setIsVisible(false);
setTimeout(() => {
onClose();
}, 300);
}, [onClose]);

if (!visible) {
return null;
}

return (
<div className="z-50 transition duration-300 bg-black bg-opacity-80 flex justify-center items-center overflow-x-hidden overflow-y-auto fixed inset-0">
<div className="relative w-auto mx-auto max-w-3xl rounded-md overflow-hidden">
<div className={`${isVisible ? 'scale-100' : 'scale-0'} transform duration-300 relative flex-auto bg-zinc-900 drop-shadow-md`}>

<div className="relative h-96">
<video poster={data?.thumbnailUrl} autoPlay muted loop src={data?.videoUrl} className="w-full brightness-[60%] object-cover h-full" />
<div onClick={handleClose} className="cursor-pointer absolute top-3 right-3 h-10 w-10 rounded-full bg-black bg-opacity-70 flex items-center justify-center">
<XMarkIcon className="text-white w-6" />
</div>
<div className="absolute bottom-[10%] left-10">
<p className="text-white text-3xl md:text-4xl h-full lg:text-5xl font-bold mb-8">
{data?.title}
</p>
<div className="flex flex-row gap-4 items-center">
<PlayButton movieId={data?.id} />
<FavoriteButton movieId={data?.id} />
</div>
</div>
</div>

<div className="px-12 py-8">
<div className="flex flex-row items-center gap-2 mb-8">
<p className="text-green-400 font-semibold text-lg">
New
</p>
<p className="text-white text-lg">
{data?.duration}
</p>
<p className="text-white text-lg">
{data?.genre}
</p>
</div>
<p className="text-white text-lg">
{data?.description}
</p>
</div>

</div>
</div>
</div>
);
}

export default InfoModal;
195 changes: 95 additions & 100 deletions components/MovieCard.tsx
Original file line number Diff line number Diff line change
@@ -1,113 +1,108 @@
import React from 'react';
import { BsFillPlayFill } from 'react-icons/bs';
import FavoriteButton from './FavoriteButton';
import React, { useCallback } from 'react';
import { useRouter } from 'next/router';
import { ChevronDownIcon } from '@heroicons/react/24/outline';
import { PlayIcon } from '@heroicons/react/24/solid';

import { MovieInterface } from '@/types';
import FavoriteButton from '@/components/FavoriteButton';
import useInfoModalStore from '@/hooks/useInfoModalStore';

interface MovieCardProps {
data: Record<string, any>;
data: MovieInterface;
}

const MovieCard: React.FC<MovieCardProps> = ({data}) => {
return (
<div className='group bg-zinc-900 col-span relative h-[12vw]'>
<img className="
cursor-pointer
object-cover
transition
duration
shadow-xl
rounded-md
group-hover:opacity-90
sm:group-hover:opacity-0
delay-300
w-full
h-[12vw]
" src={data?.thumbnailUrl} alt="Movie Poster"></img>
<div
className='
opacity-0
absolute
top-0
transition
duration-200
z-10
invisible
sm:visible
delay-300
w-full
scale-0
group-hover:scale-110
group-hover:-translate-y-[6vw]
group-hover:translate-x-[2vw]
group-hover:opacity-100
'>
<img className='
cursor-pointer
object-cover
transition
duration
shadow-xl
rounded-t-md
w-full
h-[12vw]
' src={data?.thumbnailUrl} alt="Movie"></img>
<div
className='
z-10
bg-zinc-800
p-2
lg:p-4
absolute
w-full
transition
shadow-md
rounded-b-md
'
>
<div className='flex flex-row items-center gap-3'>
<div
className='
cursor-pointer
w-6
h-6
lg:w-10
lg:h-10
bg-white
rounded-full
flex
justify-center
items-center
transition
hover:bg-neutral-300
'
// center this
onClick={() => {}}>
<BsFillPlayFill size={30} />
</div>
<FavoriteButton movieId={data?.id} />
</div>
const MovieCard: React.FC<MovieCardProps> = ({ data }) => {
const router = useRouter();
const { openModal } = useInfoModalStore();

<p className='text-purple-400 font-semibold mt-4'>
New
<span className='text-white'>

const redirectToWatch = useCallback(() => router.push(`/watch/${data.id}`), [router, data.id]);

</span>
</p>
<div className='flex flex-row mt-4 gap-2 items-center'>
<p className='text-white text-[10px] lg:text-sm'>{data.duration}</p>
return (
<div className="group bg-zinc-900 col-span relative h-[12vw]">
<img onClick={redirectToWatch} src={data.thumbnailUrl} alt="Movie" draggable={false} className="
cursor-pointer
object-cover
transition
duration
shadow-xl
rounded-md
group-hover:opacity-90
sm:group-hover:opacity-0
delay-300
w-full
h-[12vw]
" />

</div>
<div className='flex flex-row mt-4 gap-2 items-center'>
<p className='text-white text-[10px] lg:text-sm'>{data.genre}</p>
<div className="
opacity-0
absolute
top-0
transition
duration-200
z-10
invisible
sm:visible
delay-300
w-full
scale-0
group-hover:scale-110
group-hover:-translate-y-[6vw]
group-hover:translate-x-[2vw]
group-hover:opacity-100
">
<img onClick={redirectToWatch} src={data.thumbnailUrl} alt="Movie" draggable={false} className="
cursor-pointer
object-cover
transition
duration
shadow-xl
rounded-t-md
w-full
h-[12vw]
" />

</div>
</div>
<div className="
z-10
bg-zinc-800
p-2
lg:p-4
absolute
w-full
transition
shadow-md
rounded-b-md
">

{/* Movie name */}
<h3 className="text-white text-xl mt-4">{data.name || data.title}</h3>

{/* Movie description */}
<p className="text-white mt-1">{data.description}</p>

<p className="text-green-400 font-semibold mt-4">
</p>

<div className="flex flex-row items-center gap-3">
<div onClick={redirectToWatch} className="cursor-pointer w-6 h-6 lg:w-10 lg:h-10 bg-white rounded-full flex justify-center items-center transition hover:bg-neutral-300">
<PlayIcon className="text-black w-4 lg:w-6" />
</div>
<FavoriteButton movieId={data.id} />
<div onClick={() => openModal(data?.id)} className="cursor-pointer ml-auto group/item w-6 h-6 lg:w-10 lg:h-10 border-white border-2 rounded-full flex justify-center items-center transition hover:border-neutral-300">
<ChevronDownIcon className="text-white group-hover/item:text-neutral-300 w-4 lg:w-6" />
</div>
</div>

<div className="flex flex-row mt-4 gap-2 items-center">
<p className="text-white text-[10px] lg:text-sm">{data.duration}</p>
</div>

<div className="flex flex-row items-center gap-2 mt-4 text-[8px] text-white lg:text-sm">
<p>{data.genre}</p>
</div>
</div>
)
</div>
</div>
)
}

export default MovieCard;
export default MovieCard;
Loading

0 comments on commit 03c78cb

Please sign in to comment.