diff --git a/src/app/(main)/modules/page.tsx b/src/app/(main)/modules/page.tsx index 30890b2..cc9fa9c 100644 --- a/src/app/(main)/modules/page.tsx +++ b/src/app/(main)/modules/page.tsx @@ -1,196 +1,9 @@ -import Image from 'next/image'; -import images from '../modules/images.json'; +import Modules from "~/components/Modules"; export default function Page() { - return ( -
-
-
-

MORE MODULES

-
- - {/* Container for modules */} -
- {images.map((image) => ( -
- {image.alt} -
- ))} -
-
-
- ); + return ( + <> + + + ); } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// import Image from "next/image"; - -// export default function Page() { -// return ( -//
-//
-//
-//

MORE MODULES

-//
- -// {/* Hardcoded module divs */} -//
{/* Added flex wrap to align modules properly */} -//
-// hello -//
- -//
-// hello -//
- -//
-// hello -//
- -//
-// hello -//
- -//
-// hello -//
- -//
-// hello -//
- -//
-// hello -//
- -//
-// hello -//
- -//
-// hello -//
-//
-//
-//
-// ); -// } \ No newline at end of file diff --git a/src/components/Events.tsx b/src/components/Events.tsx deleted file mode 100644 index a1bdb46..0000000 --- a/src/components/Events.tsx +++ /dev/null @@ -1,147 +0,0 @@ -'use client'; - -import { useState, useLayoutEffect, useRef, useEffect } from "react"; -import gsap from "gsap"; -import { ScrollTrigger } from "gsap/ScrollTrigger"; -import Image from "next/image"; -import axios from "axios"; - -gsap.registerPlugin(ScrollTrigger); - -interface Event { - id: string; - name: string; - posterImage: string; -} - -interface ApiResponse { - status: number; - msg: Event[]; -} - -const Events: React.FC = () => { - const [events, setEvents] = useState([]); - const imagesRef = useRef<(HTMLImageElement | null)[]>([]); - const textRefs = useRef<(HTMLParagraphElement | null)[]>([]); - - useEffect(() => { - const fetchEvents = async () => { - try { - const response = await axios.get(`${process.env.NEXT_PUBLIC_API_URL}/api/event`); - if (response.data.status === 200) { - setEvents(response.data.msg); - } - } catch (error) { - console.error("Error fetching events", error); - } - }; - - void fetchEvents(); - - const script = document.createElement('script'); - script.type = 'module'; - script.src = 'https://unpkg.com/@splinetool/viewer@1.9.28/build/spline-viewer.js'; - document.body.appendChild(script); - }, []); - - useLayoutEffect(() => { - const images = imagesRef.current; - const texts = textRefs.current; - - images.forEach((img) => { - if (img) { - gsap.fromTo( - img, - { - clipPath: "polygon(0% 100%, 100% 100%, 100% 100%, 0% 100%)", - scale: 0.8, - opacity: 0 - }, - { - clipPath: "polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)", - scale: 1, - opacity: 1, - scrollTrigger: { - trigger: img, - start: "top 80%", - end: "bottom 70%", - scrub: true, - }, - } - ); - } - }); - - texts.forEach((text) => { - if (text) { - gsap.fromTo( - text, - { - y: 20, - opacity: 0 - }, - { - y: 0, - opacity: 1, - scrollTrigger: { - trigger: text, - start: "top 90%", - toggleActions: "play none none reverse", - }, - } - ); - } - }); - - return () => { - ScrollTrigger.getAll().forEach((trigger) => trigger.kill()); - }; - }, [events]); - - const setImageRef = (el: HTMLImageElement | null, index: number) => { - imagesRef.current[index] = el; - }; - - const setTextRef = (el: HTMLParagraphElement | null, index: number) => { - textRefs.current[index] = el; - }; - - return ( -
-
`, - }} - >
- -
-
- {Array.from({ length: Math.ceil(events.length / 3) }).map((_, rowIndex) => ( -
- {events.slice(rowIndex * 3, rowIndex * 3 + 3).map((item: Event, index: number) => ( -
- setImageRef(el, rowIndex * 3 + index)} - src={item.posterImage} - alt={item.name} - className="object-cover w-full h-full border-[8px] border-[#B8B8B840] backdrop-blur-[7.6rem]" - unoptimized - width={442} - height={572} - /> -
-

setTextRef(el, rowIndex * 6 + index * 2)} className="text-white pr-9 font-outfit">{item.name}

-
-
- ))} -
- ))} -
-
-
-
- ); -}; - -export default Events; diff --git a/src/components/Gallery.tsx b/src/components/Gallery.tsx index d6be074..4e2ed8a 100644 --- a/src/components/Gallery.tsx +++ b/src/components/Gallery.tsx @@ -92,7 +92,7 @@ const Gallery: React.FC = () => {
`, + __html: ``, }} >
diff --git a/src/components/Modules.tsx b/src/components/Modules.tsx new file mode 100644 index 0000000..11b6a04 --- /dev/null +++ b/src/components/Modules.tsx @@ -0,0 +1,180 @@ +'use client'; + +import { useState, useEffect, useRef } from "react"; +import gsap from "gsap"; +import { ScrollTrigger } from "gsap/ScrollTrigger"; +import axios from "axios"; +import Image from "next/image"; +import Link from "next/link"; + +gsap.registerPlugin(ScrollTrigger); + +interface Module { + id: string; + name: string; + coverImage: string; +} + +const Modules: React.FC = () => { + const [modules, setModules] = useState([]); + + const imagesRef = useRef<(HTMLImageElement | null)[]>([]); + const textRefs = useRef<(HTMLParagraphElement | null)[]>([]); + + useEffect(() => { + const fetchModules = async () => { + try { + const { data } = await axios.get<{ msg: Module[] }>(`${process.env.NEXT_PUBLIC_API_URL}/api/module`); + setModules(data.msg); + } catch (error) { + console.error('Error fetching modules:', error); + } + }; + + void fetchModules(); + }, []); + + useEffect(() => { + const script = document.createElement('script'); + script.type = 'module'; + script.src = 'https://unpkg.com/@splinetool/viewer@1.9.28/build/spline-viewer.js'; + document.body.appendChild(script); + + return () => { + document.body.removeChild(script); + }; + }, []); + + useEffect(() => { + const images = imagesRef.current; + const texts = textRefs.current; + + images.forEach((img) => { + if (img) { + gsap.fromTo( + img, + { + clipPath: "polygon(0% 100%, 100% 100%, 100% 100%, 0% 100%)", + scale: 0.8, + opacity: 0, + }, + { + clipPath: "polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)", + scale: 1, + opacity: 1, + scrollTrigger: { + trigger: img, + start: "top 80%", + end: "bottom 70%", + scrub: true, + }, + } + ); + } + }); + + texts.forEach((text) => { + if (text) { + gsap.fromTo( + text, + { y: 20, opacity: 0 }, + { + y: 0, + opacity: 1, + scrollTrigger: { + trigger: text, + start: "top 90%", + toggleActions: "play none none reverse", + }, + } + ); + } + }); + + return () => { + ScrollTrigger.getAll().forEach((trigger) => trigger.kill()); + }; + }, [modules]); + + const setImageRef = (el: HTMLImageElement | null, index: number) => { + imagesRef.current[index] = el; + }; + + const setTextRef = (el: HTMLParagraphElement | null, index: number) => { + textRefs.current[index] = el; + }; + + return ( +
+
`, + }} + >
+ +
+
+ {modules.map((module, index) => ( +
+ {index % 2 === 0 ? ( + <> +
+
+ +
+ setImageRef(el, index)} + src={module.coverImage} + alt={module.name} + className="object-cover w-full h-full border-[8px] border-[#B8B8B840] backdrop-blur-[7.6rem] cursor-pointer" // Ensures that the image takes the entire space + unoptimized + fill + /> +
+ +
+

setTextRef(el, index * 2)} className="text-white pr-9 font-outfit"> + {module.name} +

+
+
+
+
+ + ) : ( + <> +
+
+
+ +
+ setImageRef(el, index)} + src={module.coverImage} + alt={module.name} + className="object-cover w-full h-full border-[7px] border-[#B8B8B840] backdrop-blur-[121.58px] cursor-pointer" // Ensures that the image takes the entire space + unoptimized + fill + /> +
+ +
+

setTextRef(el, index * 2)} className="text-white pr-9 font-outfit"> + {module.name} +

+
+
+
+ + )} +
+ ))} +
+
+
+
+ ); +}; + +export default Modules;