Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| deccd91a17 | |||
| 1a591040cb | |||
| d1b516580b | |||
| bba3582e04 | |||
| 3e3c5d663f | |||
| 192fd930a5 | |||
| 06c55e3eac | |||
| f8be5a84da |
@@ -2,15 +2,17 @@
|
||||
|
||||
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
|
||||
import NavbarLayoutFloatingOverlay from '@/components/navbar/NavbarLayoutFloatingOverlay/NavbarLayoutFloatingOverlay';
|
||||
import HeroBillboard from '@/components/sections/hero/HeroBillboard';
|
||||
import TextSplitAbout from '@/components/sections/about/TextSplitAbout';
|
||||
import FeatureCardTwentyFive from '@/components/sections/feature/FeatureCardTwentyFive';
|
||||
import MetricCardOne from '@/components/sections/metrics/MetricCardOne';
|
||||
import TestimonialCardOne from '@/components/sections/testimonial/TestimonialCardOne';
|
||||
import { HeroCarouselLogo } from '@/components/sections/hero/HeroCarouselLogo';
|
||||
import { TextImageAbout } from '@/components/sections/about/TextImageAbout';
|
||||
import { FeatureCardTwenty } from '@/components/sections/feature/FeatureCardTwenty';
|
||||
import MetricCardTwo from '@/components/sections/metrics/MetricCardTwo';
|
||||
import TestimonialCardTwo from '@/components/sections/testimonial/TestimonialCardTwo';
|
||||
import ContactSplitForm from '@/components/sections/contact/ContactSplitForm';
|
||||
import FooterSimple from '@/components/sections/footer/FooterSimple';
|
||||
import Link from 'next/link';
|
||||
import { Sparkles, CheckCircle, ArrowRight, Brain, Code, BookOpen, Users, Trophy, TrendingUp, Shield } from 'lucide-react';
|
||||
import TestimonialCardOne from "@/components/sections/testimonial/TestimonialCardOne";
|
||||
import HeroLogo from '@/components/sections/hero/HeroLogo';
|
||||
|
||||
export default function HomePage() {
|
||||
return (
|
||||
@@ -44,40 +46,23 @@ export default function HomePage() {
|
||||
</div>
|
||||
|
||||
<div id="hero-section" data-section="hero-section">
|
||||
<HeroBillboard
|
||||
title="Where Innovation Meets Community"
|
||||
description="Join our vibrant computer club and explore the latest in technology, collaborate on exciting projects, and connect with fellow tech enthusiasts aged 16-25."
|
||||
background={{ variant: "radial-gradient" }}
|
||||
tag="Tech Enthusiasts Welcome"
|
||||
tagIcon={Sparkles}
|
||||
tagAnimation="slide-up"
|
||||
<HeroLogo
|
||||
logoText="Computer Club"
|
||||
description="Join our vibrant community of tech enthusiasts. Explore cutting-edge projects, attend workshops, and connect with fellow innovators."
|
||||
buttons={[
|
||||
{ text: "Explore Events", href: "/events" },
|
||||
{ text: "View Projects", href: "/projects" }
|
||||
{ label: "Join Us", href: "/join", dataWebildId: "hero_logo_join_btn" },
|
||||
{ label: "View Events", href: "/events", dataWebildId: "hero_logo_events_btn" }
|
||||
]}
|
||||
buttonAnimation="slide-up"
|
||||
avatars={[
|
||||
{ src: "http://img.b2bpic.net/free-photo/three-students-working-together-laptops_23-2152025161.jpg", alt: "Club member" },
|
||||
{ src: "http://img.b2bpic.net/free-photo/two-teenage-friends-playing-video-games-together-home_23-2149332883.jpg", alt: "Club member" },
|
||||
{ src: "http://img.b2bpic.net/free-photo/group-people-discussing-business-issues_53876-22915.jpg", alt: "Club member" }
|
||||
]}
|
||||
avatarText="150+ Members"
|
||||
imageSrc="http://img.b2bpic.net/free-photo/group-young-people-doing-experiments-robotics-laboratory-girls-protective-glasses_1268-24389.jpg?_wi=1"
|
||||
imageAlt="Students collaborating on tech projects"
|
||||
mediaAnimation="slide-up"
|
||||
marqueeItems={[
|
||||
{ type: "text", text: "Weekly Workshops" },
|
||||
{ type: "text", text: "Project Showcases" },
|
||||
{ type: "text", text: "Guest Speaker Series" }
|
||||
]}
|
||||
marqueeSpeed={30}
|
||||
showMarqueeCard={true}
|
||||
ariaLabel="Hero section"
|
||||
buttonAnimation="none"
|
||||
imageSrc="https://img.b2bpic.net/free-photo/abstract-luxury-gradient-blue-background_53876-120942.jpg"
|
||||
imageAlt="Computer Club community"
|
||||
showDimOverlay={true}
|
||||
ariaLabel="Computer Club hero section with logo"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="about-section" data-section="about-section">
|
||||
<TextSplitAbout
|
||||
<TextImageAbout
|
||||
title="About Our Tech Club"
|
||||
description={[
|
||||
"We're a vibrant community of students passionate about technology, innovation, and collaboration. Our club provides a welcoming space for learners of all levels to explore coding, robotics, cybersecurity, and emerging tech trends.",
|
||||
@@ -89,11 +74,13 @@ export default function HomePage() {
|
||||
]}
|
||||
buttonAnimation="slide-up"
|
||||
useInvertedBackground={false}
|
||||
imageSrc="https://img.b2bpic.net/free-photo/group-young-people-doing-experiments-robotics-laboratory-girls-protective-glasses_1268-24389.jpg"
|
||||
imageAlt="Computer Club members collaborating"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="events-section" data-section="events-section">
|
||||
<FeatureCardTwentyFive
|
||||
<FeatureCardTwenty
|
||||
title="Upcoming Tech Events"
|
||||
description="Join our community for hands-on workshops, guest lectures, and networking opportunities. Stay updated with our calendar of events designed to spark curiosity and build skills."
|
||||
animationType="slide-up"
|
||||
@@ -136,7 +123,7 @@ export default function HomePage() {
|
||||
</div>
|
||||
|
||||
<div id="projects-section" data-section="projects-section">
|
||||
<MetricCardOne
|
||||
<MetricCardTwo
|
||||
metrics={[
|
||||
{
|
||||
id: "metric-1",
|
||||
@@ -167,7 +154,7 @@ export default function HomePage() {
|
||||
icon: Trophy
|
||||
}
|
||||
]}
|
||||
gridVariant="bento-grid"
|
||||
gridVariant="uniform-all-items-equal"
|
||||
animationType="slide-up"
|
||||
title="Our Impact"
|
||||
description="Discover how our club drives innovation and empowers tech enthusiasts through collaborative projects and learning opportunities."
|
||||
|
||||
134
src/components/sections/about/TextImageAbout.tsx
Normal file
134
src/components/sections/about/TextImageAbout.tsx
Normal file
@@ -0,0 +1,134 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
|
||||
interface Button {
|
||||
text: string;
|
||||
href: string;
|
||||
}
|
||||
|
||||
interface TextImageAboutProps {
|
||||
title: string;
|
||||
description: string[];
|
||||
buttons: Button[];
|
||||
buttonAnimation?: "slide-up" | "fade-in" | "none";
|
||||
useInvertedBackground?: boolean;
|
||||
imageSrc: string;
|
||||
imageAlt: string;
|
||||
}
|
||||
|
||||
export function TextImageAbout({
|
||||
title,
|
||||
description,
|
||||
buttons,
|
||||
buttonAnimation = "slide-up",
|
||||
useInvertedBackground = false,
|
||||
imageSrc,
|
||||
imageAlt,
|
||||
}: TextImageAboutProps) {
|
||||
const bgClass = useInvertedBackground ? "bg-gray-900" : "bg-white";
|
||||
const textClass = useInvertedBackground ? "text-white" : "text-gray-900";
|
||||
const descTextClass = useInvertedBackground ? "text-gray-300" : "text-gray-600";
|
||||
|
||||
const getButtonAnimationClass = () => {
|
||||
switch (buttonAnimation) {
|
||||
case "slide-up":
|
||||
return "animate-slide-up";
|
||||
case "fade-in":
|
||||
return "animate-fade-in";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<section className={`${bgClass} py-16 md:py-24 lg:py-32 transition-colors duration-300`}>
|
||||
<div className="container mx-auto px-4 md:px-6 lg:px-8">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8 lg:gap-12 items-center">
|
||||
{/* Text Content */}
|
||||
<div className="flex flex-col justify-center space-y-6">
|
||||
<div>
|
||||
<h2 className={`text-4xl md:text-5xl font-bold ${textClass} mb-6 leading-tight`}>
|
||||
{title}
|
||||
</h2>
|
||||
<div className="space-y-4">
|
||||
{description.map((paragraph, index) => (
|
||||
<p
|
||||
key={index}
|
||||
className={`text-lg ${descTextClass} leading-relaxed`}
|
||||
>
|
||||
{paragraph}
|
||||
</p>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Buttons */}
|
||||
<div className="flex flex-wrap gap-4 pt-4">
|
||||
{buttons.map((button, index) => (
|
||||
<a
|
||||
key={index}
|
||||
href={button.href}
|
||||
className={`inline-block px-8 py-3 rounded-lg font-semibold transition-all duration-300 ${
|
||||
index === 0
|
||||
? "bg-blue-600 text-white hover:bg-blue-700 shadow-lg hover:shadow-xl"
|
||||
: "border-2 border-blue-600 text-blue-600 hover:bg-blue-50"
|
||||
} ${getButtonAnimationClass()}`}
|
||||
style={{
|
||||
animationDelay: `${index * 100}ms`,
|
||||
}}
|
||||
>
|
||||
{button.text}
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Image */}
|
||||
<div className="flex justify-center lg:justify-end">
|
||||
<div className="relative w-full max-w-md lg:max-w-lg">
|
||||
<div className="absolute inset-0 bg-gradient-to-br from-blue-400 to-blue-600 rounded-2xl transform rotate-3 opacity-20"></div>
|
||||
<img
|
||||
src={imageSrc}
|
||||
alt={imageAlt}
|
||||
className="relative w-full h-auto rounded-2xl shadow-2xl object-cover"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style jsx>{`
|
||||
@keyframes slide-up {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fade-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.animate-slide-up {
|
||||
animation: slide-up 0.6s ease-out forwards;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.animate-fade-in {
|
||||
animation: fade-in 0.6s ease-out forwards;
|
||||
opacity: 0;
|
||||
}
|
||||
`}</style>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
207
src/components/sections/feature/FeatureCardTwenty.tsx
Normal file
207
src/components/sections/feature/FeatureCardTwenty.tsx
Normal file
@@ -0,0 +1,207 @@
|
||||
'use client';
|
||||
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { LucideIcon } from 'lucide-react';
|
||||
|
||||
interface MediaItem {
|
||||
imageSrc: string;
|
||||
imageAlt: string;
|
||||
}
|
||||
|
||||
interface Feature {
|
||||
title: string;
|
||||
description: string;
|
||||
icon: LucideIcon;
|
||||
mediaItems: MediaItem[];
|
||||
}
|
||||
|
||||
interface FeatureCardTwentyProps {
|
||||
title: string;
|
||||
description: string;
|
||||
animationType?: 'slide-up' | 'fade-in' | 'slide-left';
|
||||
textboxLayout?: 'default' | 'centered' | 'compact';
|
||||
useInvertedBackground?: boolean;
|
||||
features: Feature[];
|
||||
}
|
||||
|
||||
export function FeatureCardTwenty({
|
||||
title,
|
||||
description,
|
||||
animationType = 'slide-up',
|
||||
textboxLayout = 'default',
|
||||
useInvertedBackground = false,
|
||||
features,
|
||||
}: FeatureCardTwentyProps) {
|
||||
const [activeFeatureIndex, setActiveFeatureIndex] = useState(0);
|
||||
const [isVisible, setIsVisible] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setIsVisible(true);
|
||||
}, []);
|
||||
|
||||
const getAnimationClass = () => {
|
||||
if (!isVisible) {
|
||||
switch (animationType) {
|
||||
case 'slide-up':
|
||||
return 'opacity-0 translate-y-8';
|
||||
case 'slide-left':
|
||||
return 'opacity-0 -translate-x-8';
|
||||
case 'fade-in':
|
||||
default:
|
||||
return 'opacity-0';
|
||||
}
|
||||
}
|
||||
|
||||
switch (animationType) {
|
||||
case 'slide-up':
|
||||
return 'opacity-100 translate-y-0 transition-all duration-700 ease-out';
|
||||
case 'slide-left':
|
||||
return 'opacity-100 translate-x-0 transition-all duration-700 ease-out';
|
||||
case 'fade-in':
|
||||
default:
|
||||
return 'opacity-100 transition-opacity duration-700 ease-out';
|
||||
}
|
||||
};
|
||||
|
||||
const getTextboxLayoutClass = () => {
|
||||
switch (textboxLayout) {
|
||||
case 'centered':
|
||||
return 'text-center';
|
||||
case 'compact':
|
||||
return 'text-left max-w-2xl';
|
||||
case 'default':
|
||||
default:
|
||||
return 'text-left';
|
||||
}
|
||||
};
|
||||
|
||||
const bgClass = useInvertedBackground ? 'bg-slate-900 text-white' : 'bg-white text-slate-900';
|
||||
const activeFeature = features[activeFeatureIndex];
|
||||
const IconComponent = activeFeature.icon;
|
||||
|
||||
return (
|
||||
<section className={`${bgClass} py-16 md:py-24 px-4 md:px-8 transition-colors duration-300`}>
|
||||
<div className="max-w-7xl mx-auto">
|
||||
{/* Header Section */}
|
||||
<div className={`mb-12 md:mb-16 ${getTextboxLayoutClass()} ${getAnimationClass()}`}>
|
||||
<h2 className="text-3xl md:text-4xl lg:text-5xl font-bold mb-4 leading-tight">
|
||||
{title}
|
||||
</h2>
|
||||
<p className={`text-lg md:text-xl ${useInvertedBackground ? 'text-slate-300' : 'text-slate-600'} max-w-3xl`}>
|
||||
{description}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Features Grid and Detail View */}
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8 md:gap-12">
|
||||
{/* Feature Cards */}
|
||||
<div className="lg:col-span-1 space-y-4">
|
||||
{features.map((feature, index) => {
|
||||
const CardIcon = feature.icon;
|
||||
const isActive = index === activeFeatureIndex;
|
||||
|
||||
return (
|
||||
<button
|
||||
key={index}
|
||||
onClick={() => setActiveFeatureIndex(index)}
|
||||
className={`w-full p-4 md:p-6 rounded-lg transition-all duration-300 text-left ${
|
||||
isActive
|
||||
? useInvertedBackground
|
||||
? 'bg-blue-600 text-white shadow-lg'
|
||||
: 'bg-blue-50 border-2 border-blue-600 text-slate-900'
|
||||
: useInvertedBackground
|
||||
? 'bg-slate-800 text-slate-300 hover:bg-slate-700'
|
||||
: 'bg-slate-50 text-slate-700 hover:bg-slate-100 border-2 border-transparent'
|
||||
}`}
|
||||
>
|
||||
<div className="flex items-start gap-3">
|
||||
<CardIcon className="w-6 h-6 flex-shrink-0 mt-1" />
|
||||
<div className="flex-1">
|
||||
<h3 className="font-semibold text-base md:text-lg mb-1">
|
||||
{feature.title}
|
||||
</h3>
|
||||
<p className={`text-sm ${isActive ? '' : useInvertedBackground ? 'text-slate-400' : 'text-slate-600'}`}>
|
||||
{feature.description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* Active Feature Detail */}
|
||||
<div className="lg:col-span-2">
|
||||
<div className={`rounded-lg overflow-hidden ${useInvertedBackground ? 'bg-slate-800' : 'bg-slate-50'} p-6 md:p-8 transition-all duration-500`}>
|
||||
{/* Feature Header */}
|
||||
<div className="flex items-center gap-4 mb-6">
|
||||
<div className={`p-3 rounded-lg ${useInvertedBackground ? 'bg-blue-600' : 'bg-blue-100'}`}>
|
||||
<IconComponent className={`w-8 h-8 ${useInvertedBackground ? 'text-white' : 'text-blue-600'}`} />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-2xl md:text-3xl font-bold">
|
||||
{activeFeature.title}
|
||||
</h3>
|
||||
<p className={`text-base ${useInvertedBackground ? 'text-slate-400' : 'text-slate-600'} mt-1`}>
|
||||
{activeFeature.description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Media Gallery */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
{activeFeature.mediaItems.map((media, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="relative overflow-hidden rounded-lg aspect-video bg-slate-200 animate-fade-in"
|
||||
>
|
||||
<img
|
||||
src={media.imageSrc}
|
||||
alt={media.imageAlt}
|
||||
className="w-full h-full object-cover hover:scale-105 transition-transform duration-300"
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Indicator Dots */}
|
||||
<div className="flex justify-center gap-2 mt-6">
|
||||
{features.map((_, index) => (
|
||||
<button
|
||||
key={index}
|
||||
onClick={() => setActiveFeatureIndex(index)}
|
||||
className={`w-2 h-2 rounded-full transition-all duration-300 ${
|
||||
index === activeFeatureIndex
|
||||
? useInvertedBackground
|
||||
? 'bg-blue-400 w-8'
|
||||
: 'bg-blue-600 w-8'
|
||||
: useInvertedBackground
|
||||
? 'bg-slate-600'
|
||||
: 'bg-slate-300'
|
||||
}`}
|
||||
aria-label={`Go to feature ${index + 1}`}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style jsx>{`
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.animate-fade-in {
|
||||
animation: fadeIn 0.5s ease-out;
|
||||
}
|
||||
`}</style>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user