From 0640f0db505799cc56a7aeb84e4542309a239d24 Mon Sep 17 00:00:00 2001 From: Obrempong-1 Date: Tue, 20 Oct 2026 05:14:37 +0000 Subject: [PATCH 1/2] Update --- components/home/HeroSection.tsx | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/components/home/HeroSection.tsx b/components/home/HeroSection.tsx index 82d7938..4c1b57e 100644 --- a/components/home/HeroSection.tsx +++ b/components/home/HeroSection.tsx @@ -261,6 +261,22 @@ const HeroSection = ({ }; }, [variant, bend]); + const readyRef = useRef(false); + + const reveal = (node: HTMLImageElement | null) => { + if (!node || !readyRef.current) return; + if (!node.complete || node.naturalWidth === 0) return; + node.setAttribute('data-shown', ''); + }; + + useEffect(() => { + readyRef.current = ready; + if (!ready) return; + for (const row of shots.current.values()) { + for (const node of row) reveal(node); + } + }, [ready]); + const band = layout ?? measureBand(1200, 560, 200, 560, false, bend); const cycles = tiles.length > band.columns; @@ -294,6 +310,7 @@ const HeroSection = ({ const orbit = `hero-orbit-${bandId}`; const peek = `hero-peek-${bandId}`; const tileClass = `hero-tile-${bandId}`; + const shotClass = `hero-shot-${bandId}`; const radiusPct = 100 * arc(bend); const unitOf = (n: number) => `calc(${+n.toFixed(4)} * var(--band-tile))`; const vanish = +(((band.sweep - band.limit) / (2 * band.sweep || 1)) * 100).toFixed(1); @@ -307,7 +324,9 @@ const HeroSection = ({ `@keyframes ${orbit}{` + `from{transform:translateZ(var(--band-r)) rotateY(var(--band-from)) translateZ(calc(-1 * var(--band-r)))}` + `to{transform:translateZ(var(--band-r)) rotateY(var(--band-to)) translateZ(calc(-1 * var(--band-r)))}}` + - `@media(prefers-reduced-motion:reduce){.${tileClass}{animation-play-state:paused}}`; + `@media(prefers-reduced-motion:reduce){.${tileClass}{animation-play-state:paused}}` + + `.${shotClass}{opacity:0;transition:opacity 700ms ease}` + + `.${shotClass}[data-shown]{opacity:1}`; const peekCss = `@keyframes ${peek}{` + @@ -341,7 +360,7 @@ const HeroSection = ({ className='pointer-events-none absolute inset-0 transition-opacity duration-500' style={{ ...bandVars, - opacity: layout && ready ? 1 : 0, + opacity: layout ? 1 : 0, perspective: `${+(radiusPct * CAMERA).toFixed(3)}cqw`, perspectiveOrigin: `50% ${band.axis}%`, maskImage: bandMask, @@ -392,6 +411,7 @@ const HeroSection = ({ maskImage: sliceMask, WebkitMaskImage: sliceMask, backfaceVisibility: 'hidden', + backgroundColor: '#e9ecef', left: unitOf((BAND.aspect - share) / 2), width: k === band.slices - 1 @@ -410,14 +430,16 @@ const HeroSection = ({ const row = shots.current.get(t) ?? []; if (node) row[k] = node; shots.current.set(t, row); + reveal(node); }} + onLoad={(event) => reveal(event.currentTarget)} src={tile.src} srcSet={tile.srcSet || undefined} sizes='(max-width: 768px) 55vw, 30vw' alt='' draggable={false} decoding='async' - className='absolute top-0 max-w-none object-cover' + className={`${shotClass} absolute top-0 max-w-none object-cover`} style={{ left: unitOf(-k * share), width: unitOf(BAND.aspect), From 9bb768d617add0b05bf9cfd7651c84205d7f5a34 Mon Sep 17 00:00:00 2001 From: Obrempong-1 Date: Tue, 20 Oct 2026 07:00:07 +0000 Subject: [PATCH 2/2] . --- app/page.tsx | 6 +++-- components/home/Contribute.tsx | 6 ++--- components/home/HeroSection.tsx | 4 +++- components/home/RecentEvent.tsx | 32 ++++++++++++++++++++++++-- lib/contentful-client.ts | 36 ++++++------------------------ providers/ReactQueryProvider.tsx | 11 ++++++++- public/videos/coenight-poster.jpg | Bin 0 -> 50604 bytes 7 files changed, 57 insertions(+), 38 deletions(-) create mode 100644 public/videos/coenight-poster.jpg diff --git a/app/page.tsx b/app/page.tsx index f048eae..9151a52 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -13,6 +13,7 @@ import { getEventsSafe } from '@/lib/data/event'; import { getClubsSafe } from '@/lib/data/club'; import { getHubsSafe } from '@/lib/data/hub'; import { getGalleriesSafe } from '@/lib/data/gallery'; +import { getBlogsSafe } from '@/lib/data/blog'; import type { Metadata } from 'next'; export const metadata: Metadata = { @@ -20,13 +21,14 @@ export const metadata: Metadata = { }; const Home = async () => { - const [hero, potw, events, clubs, hubs, galleries] = await Promise.all([ + const [hero, potw, events, clubs, hubs, galleries, blogs] = await Promise.all([ getPageHero('home'), getPersonalityOfTheWeek(), getEventsSafe(), getClubsSafe(), getHubsSafe(), getGalleriesSafe(), + getBlogsSafe(), ]); return ( @@ -47,7 +49,7 @@ const Home = async () => { - + ) diff --git a/components/home/Contribute.tsx b/components/home/Contribute.tsx index bbd83f7..342aed0 100644 --- a/components/home/Contribute.tsx +++ b/components/home/Contribute.tsx @@ -3,15 +3,15 @@ import Container from '../custom/Container'; import { Button } from '../ui/button'; import Link from 'next/link'; import { ArrowRight } from 'lucide-react'; -import useBlogCollection from '@/hooks/useBlogCollection'; +import useBlogCollection, { type Blog } from '@/hooks/useBlogCollection'; import BlogCard from '../blog/BlogCard'; import FetchError from '../custom/FetchError'; import { motion } from "framer-motion"; -const Contribute = () => { +const Contribute = ({ initialBlogs }: { initialBlogs?: Blog[] }) => { - const { data: blogs, error } = useBlogCollection() + const { data: blogs, error } = useBlogCollection(initialBlogs) if (error) { return diff --git a/components/home/HeroSection.tsx b/components/home/HeroSection.tsx index 4c1b57e..f06fe76 100644 --- a/components/home/HeroSection.tsx +++ b/components/home/HeroSection.tsx @@ -24,6 +24,7 @@ const BAND = { curve: 80, fade: 18, fill: 0.72, + sizes: '(max-width: 768px) 55vw, 30vw', }; function arc(bend: number) { @@ -284,6 +285,7 @@ const HeroSection = ({ if (variant !== 'band') return; for (const tile of tiles) { const preload = new window.Image(); + preload.sizes = BAND.sizes; if (tile.srcSet) preload.srcset = tile.srcSet; preload.src = tile.src; preload.decode?.().catch(() => {}); @@ -435,7 +437,7 @@ const HeroSection = ({ onLoad={(event) => reveal(event.currentTarget)} src={tile.src} srcSet={tile.srcSet || undefined} - sizes='(max-width: 768px) 55vw, 30vw' + sizes={BAND.sizes} alt='' draggable={false} decoding='async' diff --git a/components/home/RecentEvent.tsx b/components/home/RecentEvent.tsx index adcc984..0deb0da 100644 --- a/components/home/RecentEvent.tsx +++ b/components/home/RecentEvent.tsx @@ -2,6 +2,7 @@ import Image from "next/image"; import { ctfSrc } from '@/lib/contentful-src'; import { format } from "date-fns"; +import { useEffect, useRef, useState } from "react"; import { ArrowRight, CalendarDays, Clock } from "lucide-react"; import Link from "next/link"; import useEventCollection, { type EventItem } from "@/hooks/useEventCollection"; @@ -12,6 +13,31 @@ import * as Tabs from "@radix-ui/react-tabs"; const RecentEvent = ({ initialEvents }: { initialEvents?: EventItem[] }) => { const { data: events, isLoading, error } = useEventCollection(initialEvents); + const sectionRef = useRef(null); + const [showVideo, setShowVideo] = useState(false); + + useEffect(() => { + const node = sectionRef.current; + if (!node || showVideo) return; + if (typeof IntersectionObserver === 'undefined') { + setShowVideo(true); + return; + } + + const observer = new IntersectionObserver( + (entries) => { + if (entries.some((entry) => entry.isIntersecting)) { + setShowVideo(true); + observer.disconnect(); + } + }, + { rootMargin: '600px 0px' } + ); + + observer.observe(node); + return () => observer.disconnect(); + }, [showVideo]); + const now = new Date(); const upcoming = events @@ -39,10 +65,12 @@ const RecentEvent = ({ initialEvents }: { initialEvents?: EventItem[] }) => { } return ( -
+