Skip to content

Commit 681b6df

Browse files
Merge pull request #59 from traboda/develop
Changes in Landing page
2 parents 6014fe7 + 9f9044d commit 681b6df

10 files changed

Lines changed: 530 additions & 92 deletions

File tree

app/page.tsx

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ import CrewEligibility from '../src/components/landing/CrewEligibility';
88
import CrewRewards from '../src/components/landing/CrewRewards';
99
import MissionCredentials from '../src/components/landing/MissionCredentials';
1010
import PastSponsorsMarquee from '../src/components/landing/PastSponsorsMarquee';
11-
import PastSpeakers from '../src/components/landing/PastSpeakers';
11+
import CurrentSpeakers from '../src/components/landing/CurrentSpeakers';
12+
import OperationTimeline from '../src/components/landing/OperationTimeline';
1213
import CurrentSponsors from '../src/components/landing/CurrentSponsors';
1314
import Footer from '../src/components/shared/Footer';
1415
import JoinMissionControl from '../src/components/landing/JoinMissionControl';
@@ -47,21 +48,25 @@ export default async function LandingPage() {
4748

4849
<section className="relative z-50 overflow-x-hidden pt-12 md:pt-10 flex flex-col justify-center -mt-4 md:-mt-8">
4950
<LandingHeader />
51+
<CurrentSponsors />
5052
</section>
5153

5254
{/* Past Sponsors Marquee */}
5355
<section className="relative z-10 w-full overflow-hidden bg-obsidian border-t border-sky-digital/20">
5456
<PastSponsorsMarquee />
5557
</section>
5658

57-
{/* Past Speakers Section */}
58-
<PastSpeakers />
59+
{/* Mission Timeline Section */}
60+
<OperationTimeline />
61+
62+
{/* Current Speakers Section */}
63+
<CurrentSpeakers />
5964

6065
{/* Bento Grid Section */}
6166
<section className="py-16 relative z-30" id="mission-grid">
6267
<div className="container mx-auto px-4">
6368
<BentoGridContainer>
64-
69+
6570
{/* 1. Mission Brief (Desktop: 2/3 wide, Row 1 Left | Mobile Rank 1) */}
6671
<div className="md:col-span-2 flex w-full bento-card-wrapper opacity-0">
6772
<BentoCard title="Mission Brief">
@@ -72,7 +77,7 @@ export default async function LandingPage() {
7277
</div>
7378
<div className="mt-auto text-center">
7479
<Link href="/mission-brief">
75-
<button className="px-6 py-2 border border-alert-crimson text-alert-crimson font-mono uppercase tracking-wider text-sm hover:bg-alert-crimson/10 transition shadow-[0_0_12px_rgba(244,63,94,0.25)] hover:shadow-[0_0_20px_rgba(244,63,94,0.5)]">
80+
<button className="px-6 py-2 border border-alert-crimson text-alert-crimson hover:bg-alert-crimson hover:text-white hover:-translate-y-1 font-mono uppercase tracking-wider text-sm transition shadow-[0_0_12px_rgba(244,63,94,0.25)] hover:shadow-[0_0_20px_rgba(244,63,94,0.5)]">
7681
[ Know More ]
7782
</button>
7883
</Link>
@@ -93,7 +98,7 @@ export default async function LandingPage() {
9398
</ul>
9499
<div className="mt-auto text-center">
95100
<Link href="/eligibility">
96-
<button className="px-6 py-2 border border-alert-crimson text-alert-crimson font-mono uppercase tracking-wider text-sm hover:bg-alert-crimson/10 transition shadow-[0_0_12px_rgba(244,63,94,0.25)] hover:shadow-[0_0_20px_rgba(244,63,94,0.5)]">
101+
<button className="px-6 py-2 border border-alert-crimson text-alert-crimson hover:bg-alert-crimson hover:text-white hover:-translate-y-1 font-mono uppercase tracking-wider text-sm transition shadow-[0_0_12px_rgba(244,63,94,0.25)] hover:shadow-[0_0_20px_rgba(244,63,94,0.5)]">
97102
[ Know More ]
98103
</button>
99104
</Link>
@@ -121,10 +126,10 @@ export default async function LandingPage() {
121126
Receive mission updates, briefings, timelines, and official communications.
122127
</p>
123128
<div className="flex flex-col md:flex-row gap-4 justify-center mt-auto">
124-
<BentoHoverButton href="/mission-control" className="w-full md:w-auto px-3 sm:px-6 py-2.5 sm:py-3 bg-gradient-to-br from-red-900 to-red-800 border border-white/40 text-white font-mono font-bold tracking-wider rounded text-xs sm:text-sm hover:brightness-110 shadow-[0_0_12px_rgba(244,63,94,0.3)] hover:shadow-[0_0_22px_rgba(244,63,94,0.6)] transition-all duration-300">
129+
<BentoHoverButton href="/mission-control" className="w-full md:w-auto px-6 sm:px-16 py-4 sm:py-5 bg-gradient-to-br from-red-900 to-red-800 border border-white/40 text-white font-mono font-bold tracking-wider rounded text-[10px] sm:text-sm hover:brightness-110 shadow-[0_0_12px_rgba(244,63,94,0.3)] hover:shadow-[0_0_22px_rgba(244,63,94,0.6)] transition-all duration-300 whitespace-nowrap flex items-center justify-center">
125130
[ Enter Mission Control ]
126131
</BentoHoverButton>
127-
<BentoHoverButton href="/mission-brief" className="w-full md:w-auto px-3 sm:px-6 py-2.5 sm:py-3 bg-gradient-to-br from-red-900 to-red-800 border border-white/40 text-white font-mono font-bold tracking-wider rounded text-xs sm:text-sm hover:brightness-110 shadow-[0_0_12px_rgba(244,63,94,0.3)] hover:shadow-[0_0_22px_rgba(244,63,94,0.6)] transition-all duration-300">
132+
<BentoHoverButton href="/mission-brief" className="w-full md:w-auto px-6 sm:px-16 py-4 sm:py-5 bg-gradient-to-br from-red-900 to-red-800 border border-white/40 text-white font-mono font-bold tracking-wider rounded text-[10px] sm:text-sm hover:brightness-110 shadow-[0_0_12px_rgba(244,63,94,0.3)] hover:shadow-[0_0_22px_rgba(244,63,94,0.6)] transition-all duration-300 whitespace-nowrap flex items-center justify-center">
128133
[ View Mission Brief ]
129134
</BentoHoverButton>
130135
</div>
27.9 KB
Loading
273 KB
Loading
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
'use client';
2+
import React, { useRef } from 'react';
3+
import { motion, useInView } from 'framer-motion';
4+
import { ChevronLeft, ChevronRight } from 'lucide-react';
5+
6+
interface Speaker {
7+
name: string;
8+
title: string;
9+
company: string;
10+
image: string;
11+
}
12+
13+
const speakers: Speaker[] = [
14+
{
15+
name: 'Speaker Name',
16+
title: 'Their Info',
17+
company: 'EXPERT SPEAKER',
18+
image: '/inctf/assets/images/current_speakers/speaker1.jpeg',
19+
},
20+
{
21+
name: 'Speaker Name',
22+
title: 'Their Info',
23+
company: 'EXPERT SPEAKER',
24+
image: '/inctf/assets/images/current_speakers/speaker2.jpeg',
25+
},
26+
];
27+
28+
const SpeakerCard: React.FC<{ speaker: Speaker; index: number }> = ({ speaker, index }) => {
29+
const ref = useRef<HTMLDivElement>(null);
30+
const isInView = useInView(ref, { once: true });
31+
32+
return (
33+
<motion.div
34+
ref={ref}
35+
className="flex-shrink-0 w-[85vw] sm:w-72 md:w-80 snap-center group"
36+
initial={{ opacity: 0, y: 30 }}
37+
animate={isInView ? { opacity: 1, y: 0 } : {}}
38+
transition={{ duration: 0.5, delay: index * 0.1, ease: 'easeOut' }}
39+
>
40+
<div className="relative h-full min-h-[380px] md:min-h-[440px] rounded-lg overflow-hidden border border-sky-400/20 bg-slate-900/60 backdrop-blur-sm transition-all duration-300 group-hover:border-sky-400/80 group-hover:shadow-[0_0_25px_rgba(56,189,248,0.2)] p-5 md:p-8 flex flex-col items-center text-center">
41+
42+
<div className="absolute top-0 left-0 w-4 h-4 border-t-2 border-l-2 border-sky-400 z-10" />
43+
<div className="absolute top-0 right-0 w-4 h-4 border-t-2 border-r-2 border-sky-400 z-10" />
44+
45+
{/* Circular Photo */}
46+
<div className="flex justify-center mb-5 md:mb-6 flex-shrink-0">
47+
<div className="relative w-32 h-32 md:w-44 md:h-44">
48+
{/* Outer gradient ring */}
49+
<div className="absolute inset-0 rounded-full bg-gradient-to-br from-sky-400 via-purple-500 to-pink-500 p-[3px] group-hover:p-[4px] transition-all duration-300">
50+
<div className="w-full h-full rounded-full bg-slate-900 p-[2px]">
51+
<img
52+
src={speaker.image}
53+
alt={speaker.name}
54+
className="w-full h-full rounded-full object-cover grayscale group-hover:grayscale-0 transition-all duration-500"
55+
/>
56+
</div>
57+
</div>
58+
</div>
59+
</div>
60+
61+
{/* Info */}
62+
<div className="flex-grow flex flex-col justify-center w-full">
63+
<h3 className="font-heading font-bold text-white text-lg md:text-xl leading-tight mb-2 md:mb-3 uppercase">
64+
{speaker.name}
65+
</h3>
66+
<p className="font-mono text-white/80 text-[11px] md:text-xs mb-2 md:mb-3 uppercase tracking-wider leading-relaxed line-clamp-3 min-h-[2.5rem]">
67+
{speaker.title}
68+
</p>
69+
<p className="font-mono text-sky-400 text-xs md:text-sm font-semibold tracking-wide mt-auto">
70+
{speaker.company}
71+
</p>
72+
</div>
73+
74+
{/* Bottom Corner Accents */}
75+
<div className="absolute bottom-0 left-0 w-4 h-4 border-b-2 border-l-2 border-sky-400/50 z-10" />
76+
<div className="absolute bottom-0 right-0 w-4 h-4 border-b-2 border-r-2 border-sky-400/50 z-10" />
77+
</div>
78+
</motion.div>
79+
);
80+
};
81+
82+
const CurrentSpeakers: React.FC = () => {
83+
const scrollRef = useRef<HTMLDivElement>(null);
84+
const titleRef = useRef<HTMLDivElement>(null);
85+
const isTitleInView = useInView(titleRef, { once: true });
86+
87+
const scroll = (direction: 'left' | 'right') => {
88+
if (scrollRef.current) {
89+
const amount = 320;
90+
scrollRef.current.scrollBy({
91+
left: direction === 'right' ? amount : -amount,
92+
behavior: 'smooth',
93+
});
94+
}
95+
};
96+
97+
return (
98+
<section className="relative z-10 w-full py-16 md:py-24 overflow-hidden">
99+
{/* Section Header */}
100+
<div ref={titleRef} className="px-6 md:px-16 mb-10 md:mb-16">
101+
<motion.div
102+
initial={{ opacity: 0, y: 20 }}
103+
animate={isTitleInView ? { opacity: 1, y: 0 } : {}}
104+
transition={{ duration: 0.5 }}
105+
className="flex flex-row items-end justify-between gap-2"
106+
>
107+
<div>
108+
<p className="font-mono text-sky-400 text-xs tracking-[0.3em] uppercase mb-3">
109+
[ Expert Speakers ]
110+
</p>
111+
<h2 className="font-heading text-white text-3xl md:text-4xl lg:text-5xl font-bold uppercase tracking-wider">
112+
Current <span className="text-sky-400">Speakers</span>
113+
</h2>
114+
</div>
115+
<div className="flex items-center gap-3 flex-shrink-0 mb-1">
116+
<button
117+
onClick={() => scroll('left')}
118+
className="group flex items-center justify-center p-2 border border-sky-400/30 text-sky-400 hover:bg-sky-400/10 hover:border-sky-400 transition-all duration-200 rounded-sm"
119+
aria-label="Scroll left"
120+
>
121+
<ChevronLeft size={20} />
122+
</button>
123+
<button
124+
onClick={() => scroll('right')}
125+
className="group flex items-center justify-center p-2 border border-sky-400/30 text-sky-400 hover:bg-sky-400/10 hover:border-sky-400 transition-all duration-200 rounded-sm"
126+
aria-label="Scroll right"
127+
>
128+
<ChevronRight size={20} />
129+
</button>
130+
</div>
131+
</motion.div>
132+
133+
<div className="mt-6 h-[1px] w-full bg-gradient-to-r from-sky-400/60 via-sky-400/20 to-transparent" />
134+
</div>
135+
136+
<div
137+
ref={scrollRef}
138+
className="flex gap-6 md:gap-8 px-8 md:px-16 overflow-x-auto snap-x snap-mandatory scrollbar-hide pb-8 pt-4 md:justify-center scroll-smooth"
139+
style={{ scrollbarWidth: 'none', msOverflowStyle: 'none', WebkitOverflowScrolling: 'touch' }}
140+
>
141+
{speakers.map((speaker, index) => (
142+
<SpeakerCard key={`${speaker.name}-${index}`} speaker={speaker} index={index} />
143+
))}
144+
</div>
145+
</section>
146+
);
147+
};
148+
149+
export default CurrentSpeakers;

0 commit comments

Comments
 (0)