|
|
|
|
@@ -2,45 +2,49 @@
|
|
|
|
|
|
|
|
|
|
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
|
|
|
|
|
import NavbarLayoutFloatingOverlay from "@/components/navbar/NavbarLayoutFloatingOverlay/NavbarLayoutFloatingOverlay";
|
|
|
|
|
import { useEffect, useRef, useState } from "react";
|
|
|
|
|
import { Play } from "lucide-react";
|
|
|
|
|
import { useEffect, useRef } from "react";
|
|
|
|
|
|
|
|
|
|
interface Clip {
|
|
|
|
|
id: string;
|
|
|
|
|
src: string;
|
|
|
|
|
type: "video" | "image";
|
|
|
|
|
title: string;
|
|
|
|
|
link: string;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const clips: Clip[] = [
|
|
|
|
|
{
|
|
|
|
|
id: "1", src: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3Ab38TzdGBnNuMLrvS5uTUM2zMr/uploaded-1772881146961-mr1xedhd.jpg", type: "image", title: "Viral Clip 1"},
|
|
|
|
|
id: "1", src: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3Ab38TzdGBnNuMLrvS5uTUM2zMr/uploaded-1773164050845-95xbsbl4.png", title: "Viral Clip 1", link: "https://www.tiktok.com/@brandonclipd/video/7593877522681564446"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: "2", src: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3Ab38TzdGBnNuMLrvS5uTUM2zMr/uploaded-1772881146961-h65hjshx.jpg", type: "image", title: "Viral Clip 2"},
|
|
|
|
|
id: "2", src: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3Ab38TzdGBnNuMLrvS5uTUM2zMr/uploaded-1773164050845-z2orboa3.png", title: "Viral Clip 2", link: "https://www.tiktok.com/@brandonclipd/video/7594523303847415070"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: "3", src: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3Ab38TzdGBnNuMLrvS5uTUM2zMr/uploaded-1772881750051-0ym5nbmx.jpg", type: "image", title: "Viral Clip 3"},
|
|
|
|
|
id: "3", src: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3Ab38TzdGBnNuMLrvS5uTUM2zMr/uploaded-1773164050845-4o4uoqq6.png", title: "Viral Clip 3", link: "https://drive.google.com/file/d/1QbP28qpbNlyWE-kJcLQXlZ70ai5ccjuw/view?usp=drivesdk"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: "4", src: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3Ab38TzdGBnNuMLrvS5uTUM2zMr/uploaded-1772881146961-1pjxjkc4.jpg", type: "image", title: "Viral Clip 4"},
|
|
|
|
|
id: "4", src: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3Ab38TzdGBnNuMLrvS5uTUM2zMr/uploaded-1773164050845-jhs1oav4.png", title: "Viral Clip 4", link: "https://drive.google.com/file/d/1TFDj__ZvlvGQah-3T6YRsw6wwCGrR2YW/view?usp=drivesdk"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: "5", src: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3Ab38TzdGBnNuMLrvS5uTUM2zMr/uploaded-1772881146961-mr1xedhd.jpg", type: "image", title: "Viral Clip 5"},
|
|
|
|
|
id: "5", src: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3Ab38TzdGBnNuMLrvS5uTUM2zMr/uploaded-1773164050845-j8dxb4nc.png", title: "Viral Clip 5", link: "https://drive.google.com/file/d/1Pt43OPdW-tMbRB_3DLumnhedP87cDZzo/view?usp=share_link"
|
|
|
|
|
}
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
export default function WorkPage() {
|
|
|
|
|
const scrollContainerRef = useRef<HTMLDivElement>(null);
|
|
|
|
|
const [playingId, setPlayingId] = useState<string | null>(null);
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
const scrollContainer = scrollContainerRef.current;
|
|
|
|
|
if (!scrollContainer) return;
|
|
|
|
|
|
|
|
|
|
let scrollPosition = 0;
|
|
|
|
|
const scrollSpeed = 1;
|
|
|
|
|
const scrollSpeed = 2;
|
|
|
|
|
const containerWidth = scrollContainer.scrollWidth;
|
|
|
|
|
const viewportWidth = scrollContainer.clientWidth;
|
|
|
|
|
|
|
|
|
|
const scroll = () => {
|
|
|
|
|
scrollPosition += scrollSpeed;
|
|
|
|
|
if (scrollPosition >= containerWidth - viewportWidth) {
|
|
|
|
|
// Loop back to start for infinite scroll
|
|
|
|
|
if (scrollPosition >= containerWidth / 2) {
|
|
|
|
|
scrollPosition = 0;
|
|
|
|
|
}
|
|
|
|
|
scrollContainer.scrollLeft = scrollPosition;
|
|
|
|
|
@@ -50,8 +54,8 @@ export default function WorkPage() {
|
|
|
|
|
return () => clearInterval(interval);
|
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
|
|
const handleClipClick = (clipId: string) => {
|
|
|
|
|
setPlayingId(playingId === clipId ? null : clipId);
|
|
|
|
|
const handleClipClick = (link: string) => {
|
|
|
|
|
window.open(link, "_blank");
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
@@ -75,10 +79,11 @@ export default function WorkPage() {
|
|
|
|
|
{ name: "About", id: "about" },
|
|
|
|
|
{ name: "My Work", id: "/work" },
|
|
|
|
|
{ name: "Process", id: "process" },
|
|
|
|
|
{ name: "Contact", id: "contact" },
|
|
|
|
|
{ name: "Contact", id: "contact" }
|
|
|
|
|
]}
|
|
|
|
|
button={{
|
|
|
|
|
text: "Book A Call", href: "https://calendly.com/ibbiyousuf420/30min"}}
|
|
|
|
|
text: "Book A Call", href: "https://calendly.com/ibbiyousuf420/30min"
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
@@ -93,73 +98,68 @@ export default function WorkPage() {
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{/* Horizontal Scrolling Container */}
|
|
|
|
|
{/* Horizontal Infinite Scrolling Container */}
|
|
|
|
|
<div
|
|
|
|
|
className="w-full overflow-hidden rounded-2xl"
|
|
|
|
|
style={{
|
|
|
|
|
background: "linear-gradient(135deg, rgba(var(--primary-cta), 0.05), rgba(var(--accent), 0.05))", border: "1px solid rgba(var(--foreground), 0.1)"}}
|
|
|
|
|
background: "linear-gradient(135deg, rgba(var(--primary-cta), 0.05), rgba(var(--accent), 0.05))", border: "1px solid rgba(var(--foreground), 0.1)"
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<div
|
|
|
|
|
ref={scrollContainerRef}
|
|
|
|
|
className="flex gap-4 p-6 overflow-x-scroll scroll-smooth no-scrollbar"
|
|
|
|
|
style={{ scrollBehavior: "smooth", scrollbarWidth: "none" }}
|
|
|
|
|
className="flex gap-6 p-6 overflow-x-scroll"
|
|
|
|
|
style={{
|
|
|
|
|
scrollBehavior: "smooth", scrollbarWidth: "none", msOverflowStyle: "none"
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
{/* Duplicate clips to create infinite loop effect */}
|
|
|
|
|
{/* Duplicate clips for infinite loop effect */}
|
|
|
|
|
{[...clips, ...clips].map((clip, index) => (
|
|
|
|
|
<div
|
|
|
|
|
key={`${clip.id}-${index}`}
|
|
|
|
|
className="flex-shrink-0 relative group cursor-pointer transition-transform duration-300 hover:scale-105"
|
|
|
|
|
className="flex-shrink-0 relative group cursor-pointer transition-all duration-300 hover:scale-110 hover:shadow-2xl"
|
|
|
|
|
style={{
|
|
|
|
|
width: "240px", aspectRatio: "9/16"}}
|
|
|
|
|
onClick={() => handleClipClick(clip.id)}
|
|
|
|
|
width: "280px", aspectRatio: "9/16"
|
|
|
|
|
}}
|
|
|
|
|
onClick={() => handleClipClick(clip.link)}
|
|
|
|
|
role="link"
|
|
|
|
|
tabIndex={0}
|
|
|
|
|
onKeyDown={(e) => {
|
|
|
|
|
if (e.key === "Enter" || e.key === " ") {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
handleClipClick(clip.link);
|
|
|
|
|
}
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
{/* Clip Container */}
|
|
|
|
|
{/* Clip Card Container */}
|
|
|
|
|
<div
|
|
|
|
|
className="w-full h-full rounded-xl overflow-hidden shadow-lg"
|
|
|
|
|
className="w-full h-full rounded-xl overflow-hidden shadow-lg transition-all duration-300"
|
|
|
|
|
style={{
|
|
|
|
|
background: "var(--card)", border: "2px solid rgba(var(--primary-cta), 0.2)"}}
|
|
|
|
|
background: "var(--card)", border: "2px solid rgba(var(--primary-cta), 0.2)", boxShadow: "0 10px 30px rgba(0, 0, 0, 0.1)"
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
{/* Image/Video */}
|
|
|
|
|
{clip.type === "image" ? (
|
|
|
|
|
<img
|
|
|
|
|
src={clip.src}
|
|
|
|
|
alt={clip.title}
|
|
|
|
|
className="w-full h-full object-cover"
|
|
|
|
|
loading="lazy"
|
|
|
|
|
/>
|
|
|
|
|
) : (
|
|
|
|
|
<video
|
|
|
|
|
src={clip.src}
|
|
|
|
|
className="w-full h-full object-cover"
|
|
|
|
|
autoPlay={playingId === clip.id}
|
|
|
|
|
controls={playingId === clip.id}
|
|
|
|
|
muted
|
|
|
|
|
/>
|
|
|
|
|
)}
|
|
|
|
|
{/* Image */}
|
|
|
|
|
<img
|
|
|
|
|
src={clip.src}
|
|
|
|
|
alt={clip.title}
|
|
|
|
|
className="w-full h-full object-cover"
|
|
|
|
|
loading="lazy"
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
{/* Overlay */}
|
|
|
|
|
<div className="absolute inset-0 bg-black/0 group-hover:bg-black/30 transition-colors duration-300 flex items-center justify-center">
|
|
|
|
|
{playingId !== clip.id && (
|
|
|
|
|
<div className="opacity-0 group-hover:opacity-100 transition-opacity duration-300">
|
|
|
|
|
<div
|
|
|
|
|
className="flex items-center justify-center w-16 h-16 rounded-full transition-all duration-300"
|
|
|
|
|
style={{
|
|
|
|
|
background: "var(--primary-cta)", backdropFilter: "blur(10px)"}}
|
|
|
|
|
>
|
|
|
|
|
<Play
|
|
|
|
|
size={28}
|
|
|
|
|
className="text-white fill-white"
|
|
|
|
|
style={{
|
|
|
|
|
filter: "drop-shadow(0 2px 8px rgba(0, 0, 0, 0.3))"}}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
{/* Hover Overlay */}
|
|
|
|
|
<div className="absolute inset-0 bg-gradient-to-b from-transparent via-transparent to-black/40 opacity-0 group-hover:opacity-100 transition-opacity duration-300 flex flex-col items-center justify-end p-4">
|
|
|
|
|
<div
|
|
|
|
|
className="px-4 py-2 rounded-full text-sm font-semibold text-white transition-all duration-300 transform translate-y-8 group-hover:translate-y-0"
|
|
|
|
|
style={{
|
|
|
|
|
background: "var(--primary-cta)", backdropFilter: "blur(10px)"
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
View
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{/* Title */}
|
|
|
|
|
<div className="mt-2">
|
|
|
|
|
<div className="mt-3">
|
|
|
|
|
<p className="text-sm font-medium text-foreground truncate">
|
|
|
|
|
{clip.title}
|
|
|
|
|
</p>
|
|
|
|
|
@@ -169,10 +169,10 @@ export default function WorkPage() {
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{/* Info text */}
|
|
|
|
|
{/* Info Text */}
|
|
|
|
|
<div className="text-center mt-8 text-foreground/60">
|
|
|
|
|
<p className="text-sm md:text-base">
|
|
|
|
|
👆 Scroll horizontally • Click any clip to play
|
|
|
|
|
👆 Continuous scroll • Click any card to view
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|