-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
teachmetw
committed
Sep 11, 2023
1 parent
114cadb
commit 03c78cb
Showing
11 changed files
with
359 additions
and
178 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
Oops, something went wrong.