2025-04-28 00:47:36 +00:00
"use client"
import { ArrowLeft2 , Setting2 } from 'iconsax-react' ;
import Image from 'next/image' ;
import React , { useState , useEffect , useRef , useCallback } from 'react' ;
import Link from 'next/link' ;
import HoverCards from '@/components/cards/HoverCards' ;
import { Button } from '@/components/ui/button' ;
interface Page {
id : number ;
content : React.ReactNode ;
videoSrc : string ;
}
export default function Reader() {
2025-04-28 14:42:01 +00:00
const [ currentPageIndex , setCurrentPageIndex ] = useState ( 0 ) ;
const [ transitioning , setTransitioning ] = useState ( false ) ;
const videoRefs = useRef < ( HTMLVideoElement | null ) [ ] > ( [ ] ) ;
2025-04-28 00:47:36 +00:00
2025-04-28 14:42:01 +00:00
// Content structured to match your design
const pages : Page [ ] = [
{
id : 1 ,
videoSrc : "/videos/background1.mp4" ,
content : (
< >
< h1 className = "text-4xl font-bold mb-8 text-center" > BRUTAL < / h1 >
< div className = "space-y-6 text-center max-w-3xl" >
< p className = "text-lg" >
Through the rain , flickering neon lights spell out of { " " }
< HoverCards
triggerText = "SEPHORA"
videourl = "/images/card1.png"
isImage = { true }
description = "Bloomberg, COMEX, Dubai Gold & Commodities Exchange, ICE Benchmark Administration, London Metal Exchange, Multi Commodity Exchange of India, Nasdaq, Shanghai Gold Exchange, Shanghai Futures Exchange, Tokyo Commodities Exchange, World Gold Council;"
link = " https://www.gold.org/goldhub/data/gold-trading"
/ > { " " }
and illuminate an entrance to nightclub .
< / p >
< p className = "text-lg" >
A stunning light show cascades across a dance floor crowded by
partiers and adorned by dozens of video monitors .
< / p >
< p className = "text-lg" >
WADE HARPER , an anxious businessman dressed in a black suit ,
follows two burly bouncers up a flight of stairs toward the { " " }
< HoverCards
triggerText = "VIP Suite"
videourl = "/videos/background2.mp4"
description = '"Man, yes! Didn’ t I tell you not to question this man! I knew he was going to come through for us!," Handsome Twin #1 gloats. Handsome Twin #2 sighs in satisfaction. “Gold!,” he says, his tense demeanor turning to relief. '
/ > { " " }
at the back of the warehouse .
< / p >
< / div >
< / >
) ,
} ,
{
id : 2 ,
videoSrc : "/videos/background3.mp4" ,
2025-04-28 00:47:36 +00:00
2025-04-28 14:42:01 +00:00
content : (
< >
< div className = "space-y-6 text-center max-w-3xl" >
< p className = "text-lg" >
& quot ; Wade Harper ! What is up , old friend ! It & # 39 ; s been too long ,
man ! & quot ; exclaims HANDSOME TWIN # 1 .
< / p >
< p className = "text-lg" >
HANDSOME TWIN # 2 , more anxious and pushy , quickly interjects ,
& quot ; So do you have it for us ? & quot ;
< / p >
< p className = "text-lg" > Wade reaches into his breast pocket . < / p >
< p className = "text-lg" > & quot ; Yes , I do . & quot ; < / p >
< div className = "text-lg" >
Wade considers the { " " }
< HoverCards
triggerText = "USB drive"
videourl = "/videos/usb.mp4"
description = "The USB drive Wade carries holds classified footage from a secret government surveillance project called Project Echo, which monitored paranormal activities around an abandoned research facility in Nevada."
/ > { " " }
in his hand and fiddles with the device . The twins smile widely
with delight .
< / div >
< / div >
< / >
) ,
} ,
{
id : 3 ,
videoSrc : "/videos/background2.mp4" ,
content : (
< >
< div className = "space-y-6 text-center max-w-3xl" >
< p className = "text-lg" >
Man , yes ! Didn & # 39 ; t I tell you not to question this man ! I knew
he was going to come through for us ! & quot ; Handsome Twin # 1
gloats .
< / p >
< p className = "text-lg" >
Handsome Twin # 2 sighs in satisfaction . & quot ;
< HoverCards
triggerText = "Gold"
videourl = "/videos/trend.mp4"
description = "Bloomberg, COMEX, Dubai Gold & Commodities Exchange, ICE Benchmark Administration, London Metal Exchange, Multi Commodity Exchange of India, Nasdaq, Shanghai Gold Exchange, Shanghai Futures Exchange, Tokyo Commodities Exchange, World Gold Council;"
link = " https://www.gold.org/goldhub/data/gold-trading"
/ >
, & quot ; he says , his tense demeanor turning to relief .
< / p >
< p className = "text-lg" >
Wade hands the device to Handsome Twin # 2 .
< / p >
< p className = "text-lg" >
& quot ; You will find all of the credentials you need on the drive .
The shipment will arrive at the { " " }
< HoverCards
triggerText = "Port of Dreytown"
videourl = "/videos/man.mp4"
description = " A young , sobbing visitor sat unusually close to the pulpit in the empty church , catching Pastor Evan ’ s attention .
Typically , even regular members avoided those front pews , out of reverence , fear , or habit .
But this man seemed untouched by such conventions , and that stood out to the pastor . . . "
link = ""
/ > { " " }
tomorrow night , & quot ; Wade explains .
< / p >
< / div >
< / >
) ,
} ,
] ;
2025-04-28 00:47:36 +00:00
2025-04-28 14:42:01 +00:00
const handleNextPage = useCallback ( ( ) = > {
if ( transitioning ) return ;
2025-04-28 00:47:36 +00:00
2025-04-28 14:42:01 +00:00
setTransitioning ( true ) ;
2025-04-28 00:47:36 +00:00
2025-04-28 14:42:01 +00:00
if ( currentPageIndex < pages . length - 1 ) {
setCurrentPageIndex ( ( prev ) = > prev + 1 ) ;
} else {
setCurrentPageIndex ( 0 ) ;
}
2025-04-28 00:47:36 +00:00
2025-04-28 14:42:01 +00:00
setTimeout ( ( ) = > {
setTransitioning ( false ) ;
} , 1000 ) ;
} , [ currentPageIndex , transitioning , pages . length ] ) ;
2025-04-28 00:47:36 +00:00
2025-04-28 14:42:01 +00:00
// Add previous page handler
const handlePreviousPage = useCallback ( ( ) = > {
if ( transitioning ) return ;
setTransitioning ( true ) ;
if ( currentPageIndex > 0 ) {
setCurrentPageIndex ( ( prev ) = > prev - 1 ) ;
} else {
setCurrentPageIndex ( pages . length - 1 ) ;
}
setTimeout ( ( ) = > {
setTransitioning ( false ) ;
} , 1000 ) ;
} , [ currentPageIndex , transitioning , pages . length ] ) ;
2025-04-28 00:47:36 +00:00
2025-04-28 14:42:01 +00:00
// Add wheel event handler
const handleWheel = useCallback (
( event : WheelEvent ) = > {
if ( transitioning ) return ;
// Scroll down
if ( event . deltaY > 0 ) {
handleNextPage ( ) ;
}
// Scroll up
else if ( event . deltaY < 0 ) {
handlePreviousPage ( ) ;
}
} ,
[ handleNextPage , handlePreviousPage , transitioning ]
) ;
// Add useEffect for wheel event listener
useEffect ( ( ) = > {
window . addEventListener ( "wheel" , handleWheel ) ;
return ( ) = > {
window . removeEventListener ( "wheel" , handleWheel ) ;
2025-04-28 00:47:36 +00:00
} ;
2025-04-28 14:42:01 +00:00
} , [ currentPageIndex , transitioning , handleWheel ] ) ; // Add dependencies
// Add this function to validate video sources
const isValidVideoSrc = ( src : string ) : boolean = > {
return Boolean ( src && src . length > 0 ) ;
} ;
2025-04-28 00:47:36 +00:00
2025-04-28 14:42:01 +00:00
useEffect ( ( ) = > {
// Start playing the current video when the page changes
if ( videoRefs . current [ currentPageIndex ] ) {
videoRefs . current . forEach ( ( video , index ) = > {
if ( index === currentPageIndex && video ) {
video . currentTime = 0 ;
video
. play ( )
. catch ( ( err ) = > console . error ( "Error playing video:" , err ) ) ;
} else if ( video ) {
video . pause ( ) ;
2025-04-28 00:47:36 +00:00
}
2025-04-28 14:42:01 +00:00
} ) ;
}
} , [ currentPageIndex ] ) ;
2025-04-28 00:47:36 +00:00
2025-04-28 14:42:01 +00:00
return (
< div className = "h-screen overflow-hidden relative bg-black" >
{ /* NavBar */ }
< div className = "w-full h-[80px] fixed top-0 z-30 flex items-center justify-between px-6 bg-transparent" >
{ /* Logo */ }
2025-04-28 00:47:36 +00:00
2025-04-28 14:42:01 +00:00
< div className = "flex items-center text-white" >
< Link href = "/creator" className = "mr-4 " >
< Button size = "icon" className = "bg-white" >
< ArrowLeft2 size = "24" color = "#555555" / >
< / Button >
< / Link >
< Image
src = "/images/logo2.png"
alt = "Wodey"
width = { 60 }
height = { 60 }
className = "mr-2"
/ >
< span className = "text-xl font-semibold" > Wodey < / span >
< / div >
2025-04-28 00:47:36 +00:00
2025-04-28 14:42:01 +00:00
{ /* Brutal Logo - Center */ }
< div className = "absolute left-1/2 transform -translate-x-1/2" >
< Image
src = "/images/brutal.png"
alt = "Wodey"
width = { 91 }
height = { 55 }
className = "mr-2"
/ >
< / div >
2025-04-28 00:47:36 +00:00
2025-04-28 14:42:01 +00:00
{ /* Settings */ }
< button className = "flex items-center text-white" >
< Setting2 size = { 20 } className = "mr-2" color = "#ffffff" / >
< span > Settings < / span >
< / button >
< / div >
2025-04-28 00:47:36 +00:00
2025-04-28 14:42:01 +00:00
{ /* Video Sections */ }
< div className = "relative h-full" >
{ pages . map ( ( page , index ) = > (
< section
key = { page . id }
className = { ` absolute w-full h-full transition-opacity duration-1000 ${
currentPageIndex === index ? "opacity-100 z-10" : "opacity-0 z-0"
} ` }
>
{ /* Background Video */ }
< video
ref = { ( el : HTMLVideoElement | null ) = > {
videoRefs . current [ index ] = el ;
} }
className = "absolute top-0 left-0 w-full h-full object-cover"
muted
loop
playsInline
src = { isValidVideoSrc ( page . videoSrc ) ? page.videoSrc : undefined }
poster = "/images/fallback-background.png" // Add a fallback image
onError = { ( e ) = > {
console . warn ( ` Failed to load video: ${ page . videoSrc } ` ) ;
// Optionally set a fallback background color or image
e . currentTarget . style . backgroundColor = "#000000" ;
} }
> < / video >
2025-04-28 00:47:36 +00:00
2025-04-28 14:42:01 +00:00
{ /* Dark Overlay */ }
< div className = "absolute inset-0 bg-black opacity-60" > < / div >
{ /* Content */ }
< div className = "absolute inset-0 flex items-center justify-center text-white z-10 px-5" >
< div className = "mt-16 max-w-4xl" > { page . content } < / div >
2025-04-28 00:47:36 +00:00
< / div >
2025-04-28 14:42:01 +00:00
< / section >
) ) }
< / div >
2025-04-28 00:47:36 +00:00
2025-04-28 14:42:01 +00:00
{ /* Navigation Button - Down Arrow */ }
< button
onClick = { handleNextPage }
disabled = { transitioning }
className = "fixed bottom-8 left-1/2 transform -translate-x-1/2 z-30 bg-transparent text-white rounded-full w-12 h-12 flex items-center justify-center transition-opacity duration-300 hover:opacity-70"
>
< svg
xmlns = "http://www.w3.org/2000/svg"
className = "h-8 w-8"
fill = "none"
viewBox = "0 0 24 24"
stroke = "currentColor"
>
< path
strokeLinecap = "round"
strokeLinejoin = "round"
strokeWidth = { 2 }
d = "M19 9l-7 7-7-7"
/ >
< / svg >
< / button >
< / div >
) ;
2025-04-28 00:47:36 +00:00
}