Merge version_2 into main
Merge version_2 into main
This commit was merged in pull request #7.
This commit is contained in:
131
src/app/page.tsx
131
src/app/page.tsx
@@ -10,33 +10,36 @@ import TestimonialCardSix from '@/components/sections/testimonial/TestimonialCar
|
||||
import ContactCenter from '@/components/sections/contact/ContactCenter';
|
||||
import FooterBase from '@/components/sections/footer/FooterBase';
|
||||
import { Award, BookOpen, Briefcase, Code, GitBranch, Mail, MessageSquare, Sparkles, TrendingUp, Trophy, Users, Zap } from 'lucide-react';
|
||||
import { useState } from 'react';
|
||||
import React, { useState } from 'react';
|
||||
|
||||
export default function LandingPage() {
|
||||
const [flipped, setFlipped] = useState<Record<string, boolean>>({});
|
||||
const [flippedCards, setFlippedCards] = useState<{ [key: string]: boolean }>({});
|
||||
|
||||
const toggleFlip = (id: string) => {
|
||||
setFlipped(prev => ({ ...prev, [id]: !prev[id] }));
|
||||
setFlippedCards(prev => ({
|
||||
...prev,
|
||||
[id]: !prev[id]
|
||||
}));
|
||||
};
|
||||
|
||||
const testimonialCards = [
|
||||
const testimonials = [
|
||||
{
|
||||
id: "1", name: "Alex Chen", handle: "@AlexDev", testimonial: "CompClub transformed my coding skills. The workshops and mentorship helped me land my dream job at a top tech company. Grateful for this amazing community!", imageSrc: "http://img.b2bpic.net/free-photo/close-up-smiley-woman-library_23-2149204737.jpg?_wi=1", imageAlt: "Alex Chen"
|
||||
id: "1", name: "Alex Chen", handle: "@AlexDev", testimonial: "CompClub transformed my coding skills. The workshops and mentorship helped me land my dream job at a top tech company. Grateful for this amazing community!", imageSrc: "http://img.b2bpic.net/free-photo/close-up-smiley-woman-library_23-2149204737.jpg?_wi=1", imageAlt: "Alex Chen", fullTestimonial: "CompClub transformed my coding skills in ways I never expected. The workshops and mentorship helped me land my dream job at a top tech company. I went from struggling with basic algorithms to confidently tackling system design problems. The community support was incredible throughout my entire journey. Grateful for this amazing community!"
|
||||
},
|
||||
{
|
||||
id: "2", name: "Sarah Mitchell", handle: "@SarahCodes", testimonial: "The collaborative projects here are incredible. I've built friendships and a portfolio that actually impresses recruiters. Best decision ever!", imageSrc: "http://img.b2bpic.net/free-photo/close-up-smiley-woman-library_23-2149204737.jpg?_wi=2", imageAlt: "Sarah Mitchell"
|
||||
id: "2", name: "Sarah Mitchell", handle: "@SarahCodes", testimonial: "The collaborative projects here are incredible. I've built friendships and a portfolio that actually impresses recruiters. Best decision ever!", imageSrc: "http://img.b2bpic.net/free-photo/close-up-smiley-woman-library_23-2149204737.jpg?_wi=2", imageAlt: "Sarah Mitchell", fullTestimonial: "The collaborative projects here are absolutely incredible. I've built lifelong friendships and a portfolio that actually impresses recruiters. Working on real-world applications with talented peers pushed me to learn faster and deeper than I ever could alone. Best decision ever!"
|
||||
},
|
||||
{
|
||||
id: "3", name: "Jordan Lee", handle: "@JordanDev", testimonial: "From zero experience to building full-stack applications in just a few months. The mentorship here is unmatched. Highly recommend CompClub!", imageSrc: "http://img.b2bpic.net/free-photo/close-up-smiley-woman-library_23-2149204737.jpg?_wi=3", imageAlt: "Jordan Lee"
|
||||
id: "3", name: "Jordan Lee", handle: "@JordanDev", testimonial: "From zero experience to building full-stack applications in just a few months. The mentorship here is unmatched. Highly recommend CompClub!", imageSrc: "http://img.b2bpic.net/free-photo/close-up-smiley-woman-library_23-2149204737.jpg?_wi=3", imageAlt: "Jordan Lee", fullTestimonial: "From zero experience to building full-stack applications in just a few months. The mentorship here is truly unmatched. Expert mentors were always available to guide me through challenges and celebrate my wins. The structured learning path made everything clear and achievable. Highly recommend CompClub!"
|
||||
},
|
||||
{
|
||||
id: "4", name: "Maya Patel", handle: "@MayaCode", testimonial: "The hackathons taught me so much about teamwork and problem-solving. Plus, winning first place was the cherry on top!", imageSrc: "http://img.b2bpic.net/free-photo/close-up-smiley-woman-library_23-2149204737.jpg?_wi=4", imageAlt: "Maya Patel"
|
||||
id: "4", name: "Maya Patel", handle: "@MayaCode", testimonial: "The hackathons taught me so much about teamwork and problem-solving. Plus, winning first place was the cherry on top!", imageSrc: "http://img.b2bpic.net/free-photo/close-up-smiley-woman-library_23-2149204737.jpg?_wi=4", imageAlt: "Maya Patel", fullTestimonial: "The hackathons taught me so much about teamwork, time management, and creative problem-solving under pressure. Building amazing projects in 48 hours with brilliant people was exhilarating. Plus, winning first place was the cherry on top!"
|
||||
},
|
||||
{
|
||||
id: "5", name: "David Brown", handle: "@DavidDeveloper", testimonial: "CompClub isn't just about coding. It's about building a network of passionate people who genuinely want to help each other succeed.", imageSrc: "http://img.b2bpic.net/free-photo/close-up-smiley-woman-library_23-2149204737.jpg?_wi=5", imageAlt: "David Brown"
|
||||
id: "5", name: "David Brown", handle: "@DavidDeveloper", testimonial: "CompClub isn't just about coding. It's about building a network of passionate people who genuinely want to help each other succeed.", imageSrc: "http://img.b2bpic.net/free-photo/close-up-smiley-woman-library_23-2149204737.jpg?_wi=5", imageAlt: "David Brown", fullTestimonial: "CompClub isn't just about coding. It's about building a genuine network of passionate people who truly want to help each other succeed. The culture of mentoring and support runs deep in this community. I've made friends who've become collaborators on side projects and potential co-founders."
|
||||
},
|
||||
{
|
||||
id: "6", name: "Lisa Wong", handle: "@LisaTech", testimonial: "The industry expert talks opened my eyes to so many career possibilities. This community has given me the confidence to pursue my tech dreams.", imageSrc: "http://img.b2bpic.net/free-photo/close-up-smiley-woman-library_23-2149204737.jpg?_wi=6", imageAlt: "Lisa Wong"
|
||||
id: "6", name: "Lisa Wong", handle: "@LisaTech", testimonial: "The industry expert talks opened my eyes to so many career possibilities. This community has given me the confidence to pursue my tech dreams.", imageSrc: "http://img.b2bpic.net/free-photo/close-up-smiley-woman-library_23-2149204737.jpg?_wi=6", imageAlt: "Lisa Wong", fullTestimonial: "The industry expert talks opened my eyes to so many career possibilities I didn't even know existed. Hearing directly from engineers at FAANG companies was incredibly inspiring. This community has given me the confidence and skills to pursue my tech dreams with clarity and purpose."
|
||||
}
|
||||
];
|
||||
|
||||
@@ -154,62 +157,97 @@ export default function LandingPage() {
|
||||
</div>
|
||||
|
||||
<div id="testimonials" data-section="testimonials">
|
||||
<div className="w-full py-20 px-6 md:px-12">
|
||||
<div className="max-w-6xl mx-auto">
|
||||
<div className="py-16 px-4 md:px-0">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
{/* Header */}
|
||||
<div className="text-center mb-12">
|
||||
<div className="inline-block mb-4 px-4 py-2 rounded-full bg-accent/10 text-sm font-medium">
|
||||
<span className="flex items-center gap-2">
|
||||
<MessageSquare className="w-4 h-4" />
|
||||
Community Voices
|
||||
</span>
|
||||
<div className="inline-block mb-4 px-4 py-2 rounded-full bg-opacity-10 border border-current border-opacity-20">
|
||||
<span className="text-sm font-medium">Community Voices</span>
|
||||
</div>
|
||||
<h2 className="text-4xl md:text-5xl font-bold mb-4">What Our Members Say</h2>
|
||||
<p className="text-lg text-foreground/70">Real stories from computer club members about their learning journey and growth.</p>
|
||||
<p className="text-lg text-gray-600 max-w-2xl mx-auto">Real stories from computer club members about their learning journey and growth.</p>
|
||||
</div>
|
||||
|
||||
{/* Flip Cards Grid */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
{testimonialCards.map((card) => {
|
||||
const isFlipped = flipped[card.id];
|
||||
{testimonials.map((testimonial) => {
|
||||
const isFlipped = flippedCards[testimonial.id];
|
||||
return (
|
||||
<div
|
||||
key={card.id}
|
||||
className="h-96 cursor-pointer perspective"
|
||||
onClick={() => toggleFlip(card.id)}
|
||||
key={testimonial.id}
|
||||
className="h-80 cursor-pointer perspective"
|
||||
onClick={() => toggleFlip(testimonial.id)}
|
||||
>
|
||||
<div
|
||||
className="relative w-full h-full transition-transform duration-500 [transform-style:preserve-3d]"
|
||||
<div className="relative w-full h-full transition-transform duration-500 transform-gpu"
|
||||
style={{
|
||||
transform: isFlipped ? 'rotateY(180deg)' : 'rotateY(0deg)',
|
||||
transformStyle: 'preserve-3d',
|
||||
transform: isFlipped ? 'rotateY(180deg)' : 'rotateY(0deg)'
|
||||
}}
|
||||
>
|
||||
{/* Front of card */}
|
||||
{/* Front */}
|
||||
<div
|
||||
className="absolute w-full h-full bg-card rounded-lg p-6 flex flex-col items-center justify-center text-center border border-accent/20 [backface-visibility:hidden]"
|
||||
style={{ backfaceVisibility: 'hidden' }}
|
||||
className="absolute w-full h-full rounded-xl p-6 flex flex-col justify-between bg-white dark:bg-gray-900 shadow-lg border border-gray-200 dark:border-gray-700"
|
||||
style={{
|
||||
backfaceVisibility: 'hidden'
|
||||
}}
|
||||
>
|
||||
{card.imageSrc && (
|
||||
{/* Author Info at Top */}
|
||||
<div className="flex items-center gap-3 mb-4">
|
||||
<img
|
||||
src={card.imageSrc}
|
||||
alt={card.imageAlt}
|
||||
className="w-24 h-24 rounded-full object-cover mb-4 border-2 border-primary-cta"
|
||||
src={testimonial.imageSrc}
|
||||
alt={testimonial.imageAlt}
|
||||
className="w-12 h-12 rounded-full object-cover"
|
||||
/>
|
||||
)}
|
||||
<h3 className="text-xl font-bold mb-1">{card.name}</h3>
|
||||
<p className="text-sm text-foreground/60 mb-4">{card.handle}</p>
|
||||
<p className="text-sm text-foreground/80 flex-1 flex items-center justify-center">Click to read testimonial</p>
|
||||
<div>
|
||||
<p className="font-semibold text-gray-900 dark:text-white">{testimonial.name}</p>
|
||||
<p className="text-sm text-gray-500 dark:text-gray-400">{testimonial.handle}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Back of card */}
|
||||
{/* Short Testimonial */}
|
||||
<div className="flex-grow">
|
||||
<p className="text-gray-700 dark:text-gray-300 text-sm leading-relaxed">
|
||||
"{testimonial.testimonial}"
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Flip Hint */}
|
||||
<div className="mt-4 text-center">
|
||||
<p className="text-xs text-gray-500 dark:text-gray-400">Click to read full testimonial →</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Back */}
|
||||
<div
|
||||
className="absolute w-full h-full bg-card rounded-lg p-6 flex items-center justify-center text-center border border-accent/20 [backface-visibility:hidden]"
|
||||
className="absolute w-full h-full rounded-xl p-6 flex flex-col justify-between bg-gradient-to-br from-blue-50 to-indigo-50 dark:from-blue-900 dark:to-indigo-900 shadow-lg border border-blue-200 dark:border-blue-700"
|
||||
style={{
|
||||
backfaceVisibility: 'hidden',
|
||||
transform: 'rotateY(180deg)',
|
||||
transform: 'rotateY(180deg)'
|
||||
}}
|
||||
>
|
||||
<div className="flex flex-col items-center justify-center h-full">
|
||||
<p className="text-sm leading-relaxed mb-4 flex-1 flex items-center">{card.testimonial}</p>
|
||||
<p className="text-xs text-foreground/60">— {card.name}</p>
|
||||
{/* Author Info at Top */}
|
||||
<div className="flex items-center gap-3 mb-4">
|
||||
<img
|
||||
src={testimonial.imageSrc}
|
||||
alt={testimonial.imageAlt}
|
||||
className="w-12 h-12 rounded-full object-cover"
|
||||
/>
|
||||
<div>
|
||||
<p className="font-semibold text-gray-900 dark:text-white">{testimonial.name}</p>
|
||||
<p className="text-sm text-gray-600 dark:text-gray-300">{testimonial.handle}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Full Testimonial */}
|
||||
<div className="flex-grow">
|
||||
<p className="text-gray-800 dark:text-gray-200 text-sm leading-relaxed">
|
||||
"{testimonial.fullTestimonial}"
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Flip Hint */}
|
||||
<div className="mt-4 text-center">
|
||||
<p className="text-xs text-gray-600 dark:text-gray-400">← Click to see summary</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -218,10 +256,13 @@ export default function LandingPage() {
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* CTA Button */}
|
||||
<div className="text-center mt-12">
|
||||
<button
|
||||
onClick={() => window.location.hash = 'contact'}
|
||||
className="px-8 py-3 bg-primary-cta text-primary-cta-text rounded-lg hover:opacity-90 transition-opacity"
|
||||
onClick={() => {
|
||||
window.location.hash = 'contact';
|
||||
}}
|
||||
className="px-8 py-3 bg-black dark:bg-white text-white dark:text-black rounded-full font-semibold hover:shadow-lg transition-shadow"
|
||||
>
|
||||
Join Our Community
|
||||
</button>
|
||||
|
||||
@@ -34,15 +34,6 @@ export default function AboutMetric({
|
||||
const bgClass = useInvertedBackground ? 'bg-slate-900' : 'bg-white';
|
||||
const textClass = useInvertedBackground ? 'text-white' : 'text-slate-900';
|
||||
|
||||
const getAnimationDelay = (index: number) => {
|
||||
if (metricsAnimation === 'slide-up') {
|
||||
return {
|
||||
transitionDelay: `${index * 100}ms`,
|
||||
};
|
||||
}
|
||||
return {};
|
||||
};
|
||||
|
||||
return (
|
||||
<section className={`${bgClass} py-16 px-4 sm:px-6 lg:px-8`}>
|
||||
<div className="max-w-6xl mx-auto">
|
||||
@@ -62,10 +53,11 @@ export default function AboutMetric({
|
||||
key={index}
|
||||
className="h-64 cursor-pointer perspective"
|
||||
onClick={() => toggleFlip(index)}
|
||||
style={getAnimationDelay(index)}
|
||||
>
|
||||
<div
|
||||
className="relative w-full h-full transition-transform duration-500 transform-gpu"
|
||||
className={`relative w-full h-full transition-transform duration-500 transform-gpu ${
|
||||
isFlipped ? '[transform:rotateY(180deg)]' : ''
|
||||
}`}
|
||||
style={{
|
||||
transformStyle: 'preserve-3d',
|
||||
transform: isFlipped ? 'rotateY(180deg)' : 'rotateY(0deg)',
|
||||
@@ -73,36 +65,52 @@ export default function AboutMetric({
|
||||
>
|
||||
{/* Front Side */}
|
||||
<div
|
||||
className={`absolute w-full h-full ${bgClass} rounded-lg shadow-lg p-6 flex flex-col items-center justify-center border border-slate-200`}
|
||||
style={{
|
||||
backfaceVisibility: 'hidden',
|
||||
}}
|
||||
className={`absolute w-full h-full ${
|
||||
useInvertedBackground ? 'bg-slate-800' : 'bg-slate-50'
|
||||
} rounded-lg shadow-lg p-6 flex flex-col items-center justify-center border ${
|
||||
useInvertedBackground ? 'border-slate-700' : 'border-slate-200'
|
||||
}`}
|
||||
style={{ backfaceVisibility: 'hidden' }}
|
||||
>
|
||||
<Icon
|
||||
className={`w-12 h-12 mb-4 ${
|
||||
useInvertedBackground ? 'text-blue-400' : 'text-blue-600'
|
||||
}`}
|
||||
/>
|
||||
<p
|
||||
className={`text-sm font-medium ${
|
||||
useInvertedBackground ? 'text-slate-300' : 'text-slate-600'
|
||||
} text-center mb-2`}
|
||||
>
|
||||
<Icon className={`w-12 h-12 ${useInvertedBackground ? 'text-blue-400' : 'text-blue-600'} mb-4`} />
|
||||
<p className={`text-sm font-semibold ${textClass} text-center mb-2`}>
|
||||
{metric.label}
|
||||
</p>
|
||||
<p className={`text-3xl font-bold ${useInvertedBackground ? 'text-blue-400' : 'text-blue-600'}`}>
|
||||
<p
|
||||
className={`text-3xl font-bold ${textClass} text-center`}
|
||||
>
|
||||
{metric.value}
|
||||
</p>
|
||||
<p className={`text-xs ${useInvertedBackground ? 'text-slate-400' : 'text-slate-500'} mt-4 text-center`}>
|
||||
Click to learn more
|
||||
<p
|
||||
className={`text-xs mt-4 ${
|
||||
useInvertedBackground ? 'text-slate-400' : 'text-slate-500'
|
||||
}`}
|
||||
>
|
||||
Click to flip
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Back Side */}
|
||||
<div
|
||||
className={`absolute w-full h-full ${useInvertedBackground ? 'bg-slate-800' : 'bg-slate-100'} rounded-lg shadow-lg p-6 flex flex-col items-center justify-center border border-slate-200`}
|
||||
className={`absolute w-full h-full ${
|
||||
useInvertedBackground ? 'bg-blue-600' : 'bg-blue-500'
|
||||
} rounded-lg shadow-lg p-6 flex flex-col items-center justify-center`}
|
||||
style={{
|
||||
backfaceVisibility: 'hidden',
|
||||
transform: 'rotateY(180deg)',
|
||||
}}
|
||||
>
|
||||
<p className={`text-sm ${textClass} text-center leading-relaxed`}>
|
||||
{metric.label}: {metric.value} represents our commitment to excellence and continuous growth in this area.
|
||||
</p>
|
||||
<p className={`text-xs ${useInvertedBackground ? 'text-slate-400' : 'text-slate-500'} mt-4 text-center`}>
|
||||
Click to flip back
|
||||
<p className="text-white text-center text-sm leading-relaxed">
|
||||
{metric.label}: {metric.value} represents our commitment to
|
||||
excellence and continuous growth in the tech community.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -47,11 +47,11 @@ export default function ContactCenter({
|
||||
? 'bg-gradient-to-br from-blue-50 via-white to-purple-50'
|
||||
: 'bg-white';
|
||||
|
||||
const invertedBg = useInvertedBackground ? 'bg-slate-900 text-white' : '';
|
||||
const invertedClass = useInvertedBackground ? 'bg-slate-900 text-white' : '';
|
||||
|
||||
return (
|
||||
<section className={`relative py-20 px-4 sm:px-6 lg:px-8 ${bgClass} ${invertedBg}`}>
|
||||
<div className="max-w-2xl mx-auto">
|
||||
<section className={`relative py-20 px-4 sm:px-6 lg:px-8 ${bgClass}`}>
|
||||
<div className="max-w-4xl mx-auto">
|
||||
{/* Tag */}
|
||||
<div
|
||||
className={`flex items-center justify-center gap-2 mb-6 ${
|
||||
@@ -65,42 +65,51 @@ export default function ContactCenter({
|
||||
</div>
|
||||
|
||||
{/* Title */}
|
||||
<h2 className="text-4xl sm:text-5xl font-bold text-center mb-4 leading-tight">
|
||||
<h2 className="text-4xl sm:text-5xl font-bold text-center mb-4 text-slate-900">
|
||||
{title}
|
||||
</h2>
|
||||
|
||||
{/* Description */}
|
||||
<p className={`text-center text-lg mb-10 ${useInvertedBackground ? 'text-gray-300' : 'text-gray-600'}`}>
|
||||
<p className="text-lg text-center text-slate-600 mb-12 max-w-2xl mx-auto">
|
||||
{description}
|
||||
</p>
|
||||
|
||||
{/* Form */}
|
||||
<form onSubmit={handleSubmit} className="flex flex-col sm:flex-row gap-3 mb-6">
|
||||
{/* Form Container */}
|
||||
<div className={`rounded-2xl p-8 sm:p-12 ${invertedClass} ${!useInvertedBackground ? 'bg-white shadow-lg border border-slate-200' : 'bg-slate-900'}`}>
|
||||
<form onSubmit={handleSubmit} className="flex flex-col sm:flex-row gap-3">
|
||||
<input
|
||||
type="email"
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
placeholder={inputPlaceholder}
|
||||
required
|
||||
className={`flex-1 px-4 py-3 rounded-lg border transition-all focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
||||
className={`flex-1 px-4 py-3 rounded-lg border transition-colors focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
||||
useInvertedBackground
|
||||
? 'bg-slate-800 border-slate-700 text-white placeholder-gray-400'
|
||||
: 'bg-white border-gray-300 text-gray-900 placeholder-gray-500'
|
||||
? 'bg-slate-800 border-slate-700 text-white placeholder-slate-400'
|
||||
: 'bg-slate-50 border-slate-300 text-slate-900 placeholder-slate-500'
|
||||
}`}
|
||||
/>
|
||||
<button
|
||||
type="submit"
|
||||
className="px-6 py-3 bg-blue-600 hover:bg-blue-700 text-white font-semibold rounded-lg transition-colors duration-200 whitespace-nowrap"
|
||||
>
|
||||
{isSubmitted ? '✓ Subscribed' : buttonText}
|
||||
{buttonText}
|
||||
</button>
|
||||
</form>
|
||||
|
||||
{/* Success Message */}
|
||||
{isSubmitted && (
|
||||
<div className="mt-4 p-3 bg-green-100 border border-green-300 rounded-lg text-green-800 text-sm font-medium animate-in fade-in">
|
||||
✓ Thank you for signing up!
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Terms Text */}
|
||||
<p className={`text-center text-sm ${useInvertedBackground ? 'text-gray-400' : 'text-gray-500'}`}>
|
||||
<p className={`text-xs mt-6 text-center ${useInvertedBackground ? 'text-slate-400' : 'text-slate-500'}`}>
|
||||
{termsText}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -37,22 +37,20 @@ export default function FeatureCardTwentyOne({
|
||||
return (
|
||||
<section className="w-full py-12 md:py-20 lg:py-24">
|
||||
<div className="container mx-auto px-4 md:px-6">
|
||||
{/* Header Section */}
|
||||
<div className="mb-12 md:mb-16 text-center">
|
||||
<div className="inline-flex items-center gap-2 mb-4 px-4 py-2 bg-blue-50 rounded-full">
|
||||
<div className="mb-12 md:mb-16">
|
||||
<div className="flex items-center gap-2 mb-4">
|
||||
<div className="flex items-center gap-2 px-3 py-1 rounded-full bg-blue-50 border border-blue-200">
|
||||
<TagIcon className="w-4 h-4 text-blue-600" />
|
||||
<span className="text-sm font-semibold text-blue-600">{tag}</span>
|
||||
<span className="text-sm font-medium text-blue-600">{tag}</span>
|
||||
</div>
|
||||
</div>
|
||||
<h2 className="text-3xl md:text-4xl lg:text-5xl font-bold mb-4 text-gray-900">
|
||||
{title}
|
||||
</h2>
|
||||
<p className="text-lg text-gray-600 max-w-2xl mx-auto">
|
||||
{description}
|
||||
</p>
|
||||
<p className="text-lg text-gray-600 max-w-2xl">{description}</p>
|
||||
</div>
|
||||
|
||||
{/* Flip Cards Grid */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 md:gap-8">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
{accordionItems.map((item) => (
|
||||
<div
|
||||
key={item.id}
|
||||
@@ -68,47 +66,64 @@ export default function FeatureCardTwentyOne({
|
||||
: "rotateY(0deg)",
|
||||
}}
|
||||
>
|
||||
{/* Front Side */}
|
||||
{/* Front of card */}
|
||||
<div
|
||||
className="absolute w-full h-full bg-white rounded-lg shadow-lg p-6 flex flex-col justify-between border border-gray-200"
|
||||
className="absolute w-full h-full bg-white rounded-lg border border-gray-200 shadow-md p-6 flex flex-col justify-between"
|
||||
style={{
|
||||
backfaceVisibility: "hidden",
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
<h3 className="text-xl md:text-2xl font-bold text-gray-900 mb-2">
|
||||
<h3 className="text-xl font-bold text-gray-900 mb-2">
|
||||
{item.title}
|
||||
</h3>
|
||||
<p className="text-gray-500 text-sm">
|
||||
Click to read more
|
||||
<p className="text-sm text-gray-500">
|
||||
Click to read full testimonial
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex items-center justify-center w-12 h-12 bg-blue-100 rounded-lg">
|
||||
<span className="text-blue-600 font-bold text-lg">
|
||||
{item.id}
|
||||
</span>
|
||||
<div className="flex items-center justify-center w-10 h-10 rounded-full bg-blue-100">
|
||||
<svg
|
||||
className="w-5 h-5 text-blue-600"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M9 5l7 7-7 7"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Back Side */}
|
||||
{/* Back of card */}
|
||||
<div
|
||||
className="absolute w-full h-full bg-blue-600 rounded-lg shadow-lg p-6 flex flex-col justify-between border border-blue-700"
|
||||
className="absolute w-full h-full bg-blue-600 rounded-lg border border-blue-700 shadow-md p-6 flex flex-col justify-between text-white"
|
||||
style={{
|
||||
backfaceVisibility: "hidden",
|
||||
transform: "rotateY(180deg)",
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
<h3 className="text-xl md:text-2xl font-bold text-white mb-4">
|
||||
{item.title}
|
||||
</h3>
|
||||
<p className="text-blue-50 text-sm leading-relaxed">
|
||||
{item.content}
|
||||
</p>
|
||||
<p className="text-sm leading-relaxed">{item.content}</p>
|
||||
</div>
|
||||
<div className="flex items-center justify-center w-10 h-10 rounded-full bg-blue-500">
|
||||
<svg
|
||||
className="w-5 h-5 text-white"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M15 19l-7-7 7-7"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<p className="text-blue-200 text-xs text-center">
|
||||
Click to flip back
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -21,28 +21,25 @@ interface FooterBaseProps {
|
||||
export default function FooterBase({
|
||||
logoText,
|
||||
copyrightText,
|
||||
columns
|
||||
columns,
|
||||
}: FooterBaseProps) {
|
||||
return (
|
||||
<footer className="bg-slate-900 text-slate-100 py-12 px-4 sm:px-6 lg:px-8">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
{/* Top Section */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-4 gap-8 mb-8">
|
||||
{/* Logo Section */}
|
||||
<div className="flex flex-col justify-start">
|
||||
{/* Logo and Copyright Section */}
|
||||
<div className="mb-12 pb-8 border-b border-slate-700">
|
||||
<h2 className="text-2xl font-bold text-white mb-2">{logoText}</h2>
|
||||
<p className="text-slate-400 text-sm">
|
||||
Building amazing communities together
|
||||
</p>
|
||||
<p className="text-slate-400 text-sm">{copyrightText}</p>
|
||||
</div>
|
||||
|
||||
{/* Footer Columns */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-8 mb-12">
|
||||
{columns.map((column, index) => (
|
||||
<div key={index}>
|
||||
<h3 className="text-lg font-semibold text-white mb-4">
|
||||
{column.title}
|
||||
</h3>
|
||||
<ul className="space-y-2">
|
||||
<ul className="space-y-3">
|
||||
{column.items.map((item, itemIndex) => (
|
||||
<li key={itemIndex}>
|
||||
<a
|
||||
@@ -58,32 +55,29 @@ export default function FooterBase({
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Divider */}
|
||||
<div className="border-t border-slate-700 my-8"></div>
|
||||
|
||||
{/* Bottom Section */}
|
||||
<div className="border-t border-slate-700 pt-8">
|
||||
<div className="flex flex-col sm:flex-row justify-between items-center">
|
||||
<p className="text-slate-400 text-sm mb-4 sm:mb-0">
|
||||
<p className="text-slate-400 text-xs mb-4 sm:mb-0">
|
||||
{copyrightText}
|
||||
</p>
|
||||
<div className="flex gap-6">
|
||||
<div className="flex space-x-6">
|
||||
<a
|
||||
href="#"
|
||||
className="text-slate-400 hover:text-white transition-colors duration-200"
|
||||
aria-label="Privacy Policy"
|
||||
className="text-slate-400 hover:text-white transition-colors duration-200 text-xs"
|
||||
>
|
||||
<span className="text-sm">Privacy Policy</span>
|
||||
Privacy Policy
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
className="text-slate-400 hover:text-white transition-colors duration-200"
|
||||
aria-label="Terms of Service"
|
||||
className="text-slate-400 hover:text-white transition-colors duration-200 text-xs"
|
||||
>
|
||||
<span className="text-sm">Terms of Service</span>
|
||||
Terms of Service
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
);
|
||||
}
|
||||
@@ -94,19 +94,21 @@ export default function HeroLogoBillboardSplit({
|
||||
return (
|
||||
<section className={`w-full min-h-screen flex items-center justify-center ${getBackgroundClass()} py-20 px-4 sm:px-6 lg:px-8`}>
|
||||
<div className="max-w-7xl w-full mx-auto">
|
||||
<div className={`grid grid-cols-1 lg:grid-cols-2 gap-12 lg:gap-16 items-center ${isReverse ? 'lg:grid-flow-dense' : ''}`}>
|
||||
<div className={`grid grid-cols-1 lg:grid-cols-2 gap-12 items-center ${isReverse ? 'lg:grid-cols-2' : ''}`}>
|
||||
{/* Content Section */}
|
||||
<div className={`flex flex-col justify-center space-y-8 ${isReverse ? 'lg:col-start-2' : ''}`}>
|
||||
<div className="space-y-4">
|
||||
<h1 className="text-5xl sm:text-6xl font-bold text-gray-900 leading-tight">
|
||||
<div className={`flex flex-col justify-center ${isReverse ? 'lg:order-2' : 'lg:order-1'}`}>
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h1 className="text-5xl sm:text-6xl font-bold text-gray-900 mb-4">
|
||||
{logoText}
|
||||
</h1>
|
||||
<p className="text-xl text-gray-600 leading-relaxed max-w-lg">
|
||||
{description}
|
||||
</p>
|
||||
<div className="w-20 h-1 bg-gradient-to-r from-blue-500 to-purple-500 rounded-full"></div>
|
||||
</div>
|
||||
|
||||
{/* Buttons */}
|
||||
<p className="text-lg sm:text-xl text-gray-600 leading-relaxed max-w-lg">
|
||||
{description}
|
||||
</p>
|
||||
|
||||
<div className="flex flex-wrap gap-4 pt-4">
|
||||
{buttons.map((button, index) => (
|
||||
<a
|
||||
@@ -114,8 +116,8 @@ export default function HeroLogoBillboardSplit({
|
||||
href={button.href}
|
||||
className={`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'
|
||||
: 'bg-gray-200 text-gray-900 hover:bg-gray-300'
|
||||
? 'bg-gradient-to-r from-blue-500 to-purple-500 text-white hover:shadow-lg hover:from-blue-600 hover:to-purple-600'
|
||||
: 'border-2 border-gray-300 text-gray-700 hover:border-blue-500 hover:text-blue-500'
|
||||
} ${getButtonAnimationClass()}`}
|
||||
>
|
||||
{button.text}
|
||||
@@ -123,16 +125,19 @@ export default function HeroLogoBillboardSplit({
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Image Section with Flip Card */}
|
||||
<div className={`flex justify-center items-center ${isReverse ? 'lg:col-start-1' : ''}`}>
|
||||
{/* Image/Flip Card Section */}
|
||||
<div className={`flex justify-center ${isReverse ? 'lg:order-1' : 'lg:order-2'}`}>
|
||||
<div
|
||||
className="w-full max-w-md h-96 cursor-pointer perspective"
|
||||
onMouseEnter={() => setIsFlipped(true)}
|
||||
onMouseLeave={() => setIsFlipped(false)}
|
||||
onClick={() => setIsFlipped(!isFlipped)}
|
||||
style={{
|
||||
perspective: '1000px',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className={`relative w-full h-full transition-transform duration-500 ${getFrameClass()} ${getMediaAnimationClass()}`}
|
||||
className={`relative w-full h-full transition-transform duration-500 ${getFrameClass()}`}
|
||||
style={{
|
||||
transformStyle: 'preserve-3d',
|
||||
transform: isFlipped ? 'rotateY(180deg)' : 'rotateY(0deg)',
|
||||
@@ -140,7 +145,7 @@ export default function HeroLogoBillboardSplit({
|
||||
>
|
||||
{/* Front Side - Image */}
|
||||
<div
|
||||
className={`absolute w-full h-full ${getFrameClass()}`}
|
||||
className={`absolute w-full h-full ${getFrameClass()} ${getMediaAnimationClass()}`}
|
||||
style={{
|
||||
backfaceVisibility: 'hidden',
|
||||
}}
|
||||
@@ -156,7 +161,7 @@ export default function HeroLogoBillboardSplit({
|
||||
|
||||
{/* Back Side - Testimonial */}
|
||||
<div
|
||||
className={`absolute w-full h-full bg-gradient-to-br from-blue-600 to-purple-600 p-8 flex flex-col justify-center items-center text-white ${getFrameClass()}`}
|
||||
className={`absolute w-full h-full ${getFrameClass()} bg-gradient-to-br from-blue-500 to-purple-600 p-8 flex flex-col justify-center items-center text-white`}
|
||||
style={{
|
||||
backfaceVisibility: 'hidden',
|
||||
transform: 'rotateY(180deg)',
|
||||
@@ -168,13 +173,14 @@ export default function HeroLogoBillboardSplit({
|
||||
fill="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M3 21c3 0 7-1 7-8V5c0-1.25-4.716-5-7-5-6 0-6.002 4-6 7v11c0 1 0 7 6 7z" />
|
||||
<path d="M15 21c3 0 7-1 7-8V5c0-1.25-4.716-5-7-5-6 0-6.002 4-6 7v11c0 1 0 7 6 7z" />
|
||||
<path d="M3 21c3 0 7-1 7-8V5c0-1.25-4.716-5-7-5-6 0-6.002 4-6 7v11c0 1-1 4 6 5z" />
|
||||
</svg>
|
||||
<p className="text-lg font-semibold leading-relaxed">
|
||||
"CompClub has transformed how I connect with fellow tech enthusiasts. The projects are innovative and the community is incredibly supportive!"
|
||||
<p className="text-lg leading-relaxed font-medium">
|
||||
{description}
|
||||
</p>
|
||||
<p className="text-sm opacity-90 pt-4">
|
||||
Click to flip back
|
||||
</p>
|
||||
<p className="text-sm opacity-90">- Sarah Chen, Tech Innovator</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -54,23 +54,22 @@ export default function MetricCardThree({
|
||||
return (
|
||||
<section className={`py-16 px-4 sm:px-6 lg:px-8 ${bgClass}`}>
|
||||
<div className="max-w-6xl mx-auto">
|
||||
{/* Header Section */}
|
||||
<div className="mb-12 text-center">
|
||||
<div className="inline-flex items-center gap-2 mb-4 px-4 py-2 rounded-full bg-blue-100 text-blue-700">
|
||||
<TagIcon className="w-4 h-4" />
|
||||
<span className="text-sm font-semibold">{tag}</span>
|
||||
<div className="mb-12">
|
||||
<div className="flex items-center gap-2 mb-4">
|
||||
<TagIcon className="w-5 h-5 text-blue-500" />
|
||||
<span className="text-sm font-semibold text-blue-500 uppercase tracking-wide">
|
||||
{tag}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<h2 className="text-4xl sm:text-5xl font-bold mb-4">{title}</h2>
|
||||
<p className="text-lg text-slate-600 max-w-2xl mx-auto">
|
||||
<p className={`text-lg ${useInvertedBackground ? "text-slate-300" : "text-slate-600"}`}>
|
||||
{description}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Metrics Grid with Flip Cards */}
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
|
||||
{metrics.map((metric) => {
|
||||
const MetricIcon = metric.icon;
|
||||
const Icon = metric.icon;
|
||||
const isFlipped = flipped[metric.id] || false;
|
||||
|
||||
return (
|
||||
@@ -81,49 +80,47 @@ export default function MetricCardThree({
|
||||
>
|
||||
<div
|
||||
className={`relative w-full h-full transition-transform duration-500 transform-gpu ${
|
||||
isFlipped ? "rotate-y-180" : ""
|
||||
isFlipped ? "scale-x-[-1]" : ""
|
||||
}`}
|
||||
style={{
|
||||
transformStyle: "preserve-3d",
|
||||
transform: isFlipped
|
||||
? "rotateY(180deg)"
|
||||
: "rotateY(0deg)",
|
||||
transform: isFlipped ? "rotateY(180deg)" : "rotateY(0deg)",
|
||||
}}
|
||||
>
|
||||
{/* Front of Card */}
|
||||
<div
|
||||
className="absolute w-full h-full bg-gradient-to-br from-blue-50 to-blue-100 rounded-lg p-6 flex flex-col items-center justify-center text-center border border-blue-200 shadow-lg"
|
||||
style={{
|
||||
backfaceVisibility: "hidden",
|
||||
}}
|
||||
className={`absolute w-full h-full p-6 rounded-lg border-2 flex flex-col justify-between ${
|
||||
useInvertedBackground
|
||||
? "bg-slate-800 border-slate-700 text-white"
|
||||
: "bg-slate-50 border-slate-200 text-slate-900"
|
||||
}`}
|
||||
style={{ backfaceVisibility: "hidden" }}
|
||||
>
|
||||
<MetricIcon className="w-12 h-12 text-blue-600 mb-4" />
|
||||
<h3 className="text-sm font-semibold text-slate-700 mb-3">
|
||||
<div>
|
||||
<div className="mb-4 p-3 bg-blue-100 rounded-lg w-fit">
|
||||
<Icon className="w-6 h-6 text-blue-600" />
|
||||
</div>
|
||||
<h3 className="text-sm font-semibold mb-2 opacity-75">
|
||||
{metric.title}
|
||||
</h3>
|
||||
<p className="text-4xl font-bold text-blue-600">
|
||||
{metric.value}
|
||||
</p>
|
||||
<p className="text-xs text-slate-500 mt-4">
|
||||
Click to see more
|
||||
</p>
|
||||
</div>
|
||||
<div className="text-4xl font-bold">{metric.value}</div>
|
||||
</div>
|
||||
|
||||
{/* Back of Card */}
|
||||
<div
|
||||
className="absolute w-full h-full bg-gradient-to-br from-slate-800 to-slate-900 rounded-lg p-6 flex flex-col items-center justify-center text-center border border-slate-700 shadow-lg text-white"
|
||||
className={`absolute w-full h-full p-6 rounded-lg border-2 flex items-center justify-center ${
|
||||
useInvertedBackground
|
||||
? "bg-slate-800 border-slate-700 text-white"
|
||||
: "bg-slate-50 border-slate-200 text-slate-900"
|
||||
}`}
|
||||
style={{
|
||||
backfaceVisibility: "hidden",
|
||||
transform: "rotateY(180deg)",
|
||||
}}
|
||||
>
|
||||
<p className="text-sm leading-relaxed mb-4">
|
||||
<p className="text-center text-sm leading-relaxed">
|
||||
{metric.title} represents our commitment to excellence and
|
||||
continuous growth in the computer club community.
|
||||
</p>
|
||||
<p className="text-xs text-slate-400">
|
||||
Click to flip back
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -131,14 +128,13 @@ export default function MetricCardThree({
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* Buttons Section */}
|
||||
{buttons.length > 0 && (
|
||||
<div className="flex flex-wrap gap-4 justify-center">
|
||||
<div className="flex flex-wrap gap-4">
|
||||
{buttons.map((button, index) => (
|
||||
<a
|
||||
key={index}
|
||||
href={button.href}
|
||||
className="px-8 py-3 bg-blue-600 text-white font-semibold rounded-lg hover:bg-blue-700 transition-colors duration-300 shadow-md hover:shadow-lg"
|
||||
className="px-6 py-3 bg-blue-600 text-white font-semibold rounded-lg hover:bg-blue-700 transition-colors duration-200"
|
||||
>
|
||||
{button.text}
|
||||
</a>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
'use client';
|
||||
|
||||
import { useState } from "react";
|
||||
import { useState } from 'react';
|
||||
|
||||
interface Testimonial {
|
||||
id: number;
|
||||
@@ -10,156 +10,152 @@ interface Testimonial {
|
||||
shortText: string;
|
||||
fullText: string;
|
||||
avatar?: string;
|
||||
rating?: number;
|
||||
}
|
||||
|
||||
interface TestimonialCardSixProps {
|
||||
testimonials?: Testimonial[];
|
||||
}
|
||||
|
||||
const defaultTestimonials: Testimonial[] = [
|
||||
const testimonials: Testimonial[] = [
|
||||
{
|
||||
id: 1,
|
||||
author: "Sarah Johnson",
|
||||
role: "Product Manager",
|
||||
company: "TechCorp",
|
||||
shortText: "Amazing service!",
|
||||
fullText:
|
||||
"This service has completely transformed how we manage our projects. The intuitive interface and powerful features have saved us countless hours. The support team is incredibly responsive and helpful. I would highly recommend this to any team looking to improve their workflow.",
|
||||
avatar: "https://api.dicebear.com/7.x/avataaars/svg?seed=Sarah",
|
||||
author: 'Sarah Johnson',
|
||||
role: 'Product Manager',
|
||||
company: 'Tech Innovations Inc',
|
||||
shortText: 'Exceptional service and support.',
|
||||
fullText: 'This product has completely transformed how our team works. The exceptional service and support from the team made the transition seamless. We saw a 40% improvement in productivity within the first month.',
|
||||
avatar: '👩💼',
|
||||
rating: 5,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
author: "Michael Chen",
|
||||
role: "CEO",
|
||||
company: "StartupXYZ",
|
||||
shortText: "Game changer!",
|
||||
fullText:
|
||||
"We've been using this platform for 6 months now and the results speak for themselves. Our team productivity has increased by 40%, and the ROI has been exceptional. The platform scales beautifully with our growing needs. Couldn't ask for a better solution.",
|
||||
avatar: "https://api.dicebear.com/7.x/avataaars/svg?seed=Michael",
|
||||
author: 'Michael Chen',
|
||||
role: 'CEO',
|
||||
company: 'Digital Solutions Ltd',
|
||||
shortText: 'Best investment we made this year.',
|
||||
fullText: 'Best investment we made this year. The platform is intuitive, powerful, and the ROI has exceeded our expectations. The team is responsive and genuinely cares about customer success. Highly recommended for any growing business.',
|
||||
avatar: '👨💼',
|
||||
rating: 5,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
author: "Emily Rodriguez",
|
||||
role: "Design Lead",
|
||||
company: "Creative Studios",
|
||||
shortText: "Exceeded expectations!",
|
||||
fullText:
|
||||
"The design and user experience are top-notch. Every detail has been thoughtfully considered. The collaboration features make it easy for our distributed team to work together seamlessly. This is the kind of tool that makes you wonder how you ever worked without it.",
|
||||
avatar: "https://api.dicebear.com/7.x/avataaars/svg?seed=Emily",
|
||||
author: 'Emily Rodriguez',
|
||||
role: 'Operations Director',
|
||||
company: 'Global Enterprises',
|
||||
shortText: 'Streamlined our entire workflow.',
|
||||
fullText: 'Streamlined our entire workflow and reduced operational costs significantly. The implementation was smooth, and the training provided was comprehensive. Our team is now more efficient than ever before.',
|
||||
avatar: '👩💻',
|
||||
rating: 5,
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
author: "David Park",
|
||||
role: "Operations Director",
|
||||
company: "Global Solutions",
|
||||
shortText: "Best investment ever!",
|
||||
fullText:
|
||||
"We've tried many solutions before, but this one stands out. The implementation was smooth, the training was comprehensive, and the ongoing support is exceptional. Our team adopted it immediately and we're seeing measurable improvements in efficiency and accuracy.",
|
||||
avatar: "https://api.dicebear.com/7.x/avataaars/svg?seed=David",
|
||||
author: 'David Thompson',
|
||||
role: 'Founder',
|
||||
company: 'StartUp Ventures',
|
||||
shortText: 'Game-changer for our startup.',
|
||||
fullText: 'A true game-changer for our startup. The scalability and flexibility of the solution allowed us to grow without limitations. Customer support is outstanding and always available when we need them.',
|
||||
avatar: '👨🚀',
|
||||
rating: 5,
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
author: 'Jessica Lee',
|
||||
role: 'Marketing Lead',
|
||||
company: 'Creative Agency Pro',
|
||||
shortText: 'Transformed our client deliverables.',
|
||||
fullText: 'Transformed our client deliverables and improved our team collaboration. The analytics and reporting features are incredibly detailed and actionable. We\'ve already recommended it to several clients.',
|
||||
avatar: '👩🎨',
|
||||
rating: 5,
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
author: 'Robert Martinez',
|
||||
role: 'Technical Director',
|
||||
company: 'Enterprise Solutions',
|
||||
shortText: 'Robust, reliable, and secure.',
|
||||
fullText: 'Robust, reliable, and secure platform that meets all our enterprise requirements. The API documentation is excellent, and integration with our existing systems was straightforward. Outstanding technical support team.',
|
||||
avatar: '👨💻',
|
||||
rating: 5,
|
||||
},
|
||||
];
|
||||
|
||||
export default function TestimonialCardSix({
|
||||
testimonials = defaultTestimonials,
|
||||
}: TestimonialCardSixProps) {
|
||||
const [flipped, setFlipped] = useState<{ [key: number]: boolean }>({});
|
||||
interface CardProps {
|
||||
testimonial: Testimonial;
|
||||
}
|
||||
|
||||
const toggleFlip = (id: number) => {
|
||||
setFlipped((prev) => ({
|
||||
...prev,
|
||||
[id]: !prev[id],
|
||||
}));
|
||||
};
|
||||
function TestimonialCard({ testimonial }: CardProps) {
|
||||
const [isFlipped, setIsFlipped] = useState(false);
|
||||
|
||||
return (
|
||||
<section className="py-12 px-4 sm:px-6 lg:px-8 bg-gradient-to-br from-slate-50 to-slate-100">
|
||||
<div className="max-w-6xl mx-auto">
|
||||
<div className="text-center mb-12">
|
||||
<h2 className="text-3xl sm:text-4xl font-bold text-gray-900 mb-4">
|
||||
What Our Clients Say
|
||||
</h2>
|
||||
<p className="text-lg text-gray-600">
|
||||
Hover over cards to see full testimonials
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
||||
{testimonials.map((testimonial) => (
|
||||
<div
|
||||
key={testimonial.id}
|
||||
className="h-80 cursor-pointer perspective"
|
||||
onClick={() => toggleFlip(testimonial.id)}
|
||||
onMouseEnter={() => setIsFlipped(true)}
|
||||
onMouseLeave={() => setIsFlipped(false)}
|
||||
>
|
||||
<div
|
||||
className="relative w-full h-full transition-transform duration-500 transform-gpu"
|
||||
style={{
|
||||
transformStyle: "preserve-3d",
|
||||
transform: flipped[testimonial.id]
|
||||
? "rotateY(180deg)"
|
||||
: "rotateY(0deg)",
|
||||
transformStyle: 'preserve-3d',
|
||||
transform: isFlipped ? 'rotateY(180deg)' : 'rotateY(0deg)',
|
||||
}}
|
||||
>
|
||||
{/* Front of card */}
|
||||
{/* Front Side */}
|
||||
<div
|
||||
className="absolute w-full h-full bg-white rounded-lg shadow-lg p-6 flex flex-col justify-between"
|
||||
style={{ backfaceVisibility: "hidden" }}
|
||||
className="absolute w-full h-full bg-white rounded-lg shadow-lg p-6 flex flex-col justify-between border border-gray-200"
|
||||
style={{ backfaceVisibility: 'hidden' }}
|
||||
>
|
||||
<div>
|
||||
<div className="flex items-center gap-4 mb-4">
|
||||
{testimonial.avatar && (
|
||||
<img
|
||||
src={testimonial.avatar}
|
||||
alt={testimonial.author}
|
||||
className="w-12 h-12 rounded-full"
|
||||
/>
|
||||
)}
|
||||
<div className="text-4xl">{testimonial.avatar}</div>
|
||||
<div>
|
||||
<h3 className="font-semibold text-gray-900">
|
||||
{testimonial.author}
|
||||
</h3>
|
||||
<p className="text-sm text-gray-600">
|
||||
{testimonial.role}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-gray-700 text-sm mb-4">
|
||||
"{testimonial.shortText}"
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<h3 className="font-semibold text-gray-900">{testimonial.author}</h3>
|
||||
<p className="text-sm text-gray-600">{testimonial.role}</p>
|
||||
<p className="text-xs text-gray-500">{testimonial.company}</p>
|
||||
<div className="flex gap-1">
|
||||
{[...Array(5)].map((_, i) => (
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex gap-1 mb-4">
|
||||
{Array.from({ length: testimonial.rating || 5 }).map((_, i) => (
|
||||
<span key={i} className="text-yellow-400">
|
||||
★
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
<p className="text-gray-700 text-sm leading-relaxed">{testimonial.shortText}</p>
|
||||
</div>
|
||||
<p className="text-xs text-gray-500 text-center mt-4">Hover to read more</p>
|
||||
</div>
|
||||
|
||||
{/* Back of card */}
|
||||
{/* Back Side */}
|
||||
<div
|
||||
className="absolute w-full h-full bg-gradient-to-br from-blue-600 to-blue-800 rounded-lg shadow-lg p-6 flex flex-col justify-between text-white"
|
||||
className="absolute w-full h-full bg-gradient-to-br from-blue-600 to-blue-800 rounded-lg shadow-lg p-6 flex flex-col justify-center border border-blue-700"
|
||||
style={{
|
||||
backfaceVisibility: "hidden",
|
||||
transform: "rotateY(180deg)",
|
||||
backfaceVisibility: 'hidden',
|
||||
transform: 'rotateY(180deg)',
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
<h3 className="font-semibold text-lg mb-3">
|
||||
{testimonial.author}
|
||||
</h3>
|
||||
<p className="text-sm text-blue-100 leading-relaxed">
|
||||
"{testimonial.fullText}"
|
||||
<p className="text-white text-sm leading-relaxed font-medium">
|
||||
{testimonial.fullText}
|
||||
</p>
|
||||
</div>
|
||||
<p className="text-xs text-blue-200 text-center">
|
||||
Click to flip back
|
||||
<p className="text-blue-200 text-xs mt-4 text-center italic">
|
||||
— {testimonial.author}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function TestimonialCardSix() {
|
||||
return (
|
||||
<section className="py-16 px-4 bg-gray-50">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
<div className="text-center mb-12">
|
||||
<h2 className="text-4xl font-bold text-gray-900 mb-4">What Our Clients Say</h2>
|
||||
<p className="text-lg text-gray-600">
|
||||
Hover over any card to read the full testimonial
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
{testimonials.map((testimonial) => (
|
||||
<TestimonialCard key={testimonial.id} testimonial={testimonial} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -23,36 +23,27 @@ const defaultTestimonials: Testimonial[] = [
|
||||
role: 'Product Manager',
|
||||
company: 'TechCorp',
|
||||
excerpt: 'Amazing experience working with this team.',
|
||||
fullText: 'This has been an absolutely transformative experience. The team went above and beyond to ensure our project succeeded. Their attention to detail and commitment to excellence is unmatched. I would highly recommend them to anyone looking for top-tier service.',
|
||||
fullText: 'This has been an absolutely transformative experience. The team went above and beyond to ensure our project succeeded. Their attention to detail and commitment to excellence is unmatched in the industry.',
|
||||
avatar: '👩💼',
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
author: 'Michael Chen',
|
||||
role: 'CEO',
|
||||
company: 'StartupXYZ',
|
||||
company: 'StartupHub',
|
||||
excerpt: 'Exceeded all our expectations.',
|
||||
fullText: 'From day one, they demonstrated exceptional professionalism and expertise. They understood our vision and delivered results that surpassed our expectations. The collaboration was seamless and the outcomes were outstanding. Truly a game-changer for our business.',
|
||||
fullText: 'From day one, they demonstrated exceptional expertise and professionalism. The results speak for themselves - we saw a 300% improvement in our metrics. Highly recommend to anyone looking for top-tier service.',
|
||||
avatar: '👨💼',
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
author: 'Emily Rodriguez',
|
||||
role: 'Design Lead',
|
||||
company: 'Creative Studios',
|
||||
company: 'CreativeStudio',
|
||||
excerpt: 'Best decision we made this year.',
|
||||
fullText: 'Working with this team was the best decision we made all year. Their innovative approach and creative solutions transformed our project completely. They were responsive, professional, and genuinely invested in our success. I cannot recommend them highly enough.',
|
||||
fullText: 'The collaboration was seamless and the final product exceeded our vision. They understood our brand deeply and delivered something truly special. We are already planning our next project together.',
|
||||
avatar: '👩🎨',
|
||||
},
|
||||
{
|
||||
id: '4',
|
||||
author: 'David Park',
|
||||
role: 'Operations Director',
|
||||
company: 'Global Solutions Inc',
|
||||
excerpt: 'Incredible attention to detail.',
|
||||
fullText: 'The level of detail and care they put into every aspect of the project was incredible. They anticipated our needs, solved problems proactively, and delivered exceptional results on time and within budget. Their expertise and dedication made all the difference.',
|
||||
avatar: '👨💼',
|
||||
},
|
||||
];
|
||||
|
||||
export default function Tag({ testimonials = defaultTestimonials }: TagProps) {
|
||||
@@ -66,18 +57,18 @@ export default function Tag({ testimonials = defaultTestimonials }: TagProps) {
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="w-full py-12 px-4 sm:px-6 lg:px-8">
|
||||
<div className="w-full py-12 px-4 bg-gradient-to-br from-slate-50 to-slate-100">
|
||||
<div className="max-w-6xl mx-auto">
|
||||
<div className="text-center mb-12">
|
||||
<h2 className="text-3xl sm:text-4xl font-bold text-gray-900 mb-4">
|
||||
<h2 className="text-4xl font-bold text-slate-900 mb-4">
|
||||
What Our Clients Say
|
||||
</h2>
|
||||
<p className="text-lg text-gray-600">
|
||||
<p className="text-lg text-slate-600">
|
||||
Hover over cards to see full testimonials
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
{testimonials.map((testimonial) => (
|
||||
<div
|
||||
key={testimonial.id}
|
||||
@@ -95,53 +86,52 @@ export default function Tag({ testimonials = defaultTestimonials }: TagProps) {
|
||||
>
|
||||
{/* Front of card */}
|
||||
<div
|
||||
className="absolute w-full h-full bg-white rounded-lg shadow-lg p-6 flex flex-col justify-between border border-gray-200"
|
||||
style={{
|
||||
backfaceVisibility: 'hidden',
|
||||
}}
|
||||
className="absolute w-full h-full bg-white rounded-lg shadow-lg p-8 flex flex-col justify-between border border-slate-200"
|
||||
style={{ backfaceVisibility: 'hidden' }}
|
||||
>
|
||||
<div>
|
||||
<div className="flex items-center gap-4 mb-4">
|
||||
<div className="text-4xl">{testimonial.avatar}</div>
|
||||
<div className="flex items-center gap-4 mb-6">
|
||||
<div className="text-5xl">{testimonial.avatar}</div>
|
||||
<div>
|
||||
<h3 className="font-semibold text-gray-900 text-sm">
|
||||
<h3 className="font-bold text-slate-900">
|
||||
{testimonial.author}
|
||||
</h3>
|
||||
<p className="text-xs text-gray-600">
|
||||
<p className="text-sm text-slate-600">
|
||||
{testimonial.role}
|
||||
</p>
|
||||
<p className="text-xs text-gray-500">
|
||||
<p className="text-xs text-slate-500">
|
||||
{testimonial.company}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-gray-700 text-sm leading-relaxed">
|
||||
<p className="text-slate-700 italic text-lg leading-relaxed">
|
||||
"{testimonial.excerpt}"
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex gap-1">
|
||||
{[...Array(5)].map((_, i) => (
|
||||
<span key={i} className="text-yellow-400">
|
||||
★
|
||||
</span>
|
||||
))}
|
||||
<div className="text-center text-sm text-slate-500 font-medium">
|
||||
Click to read more
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Back of card */}
|
||||
<div
|
||||
className="absolute w-full h-full bg-gradient-to-br from-blue-600 to-blue-800 rounded-lg shadow-lg p-6 flex flex-col justify-center border border-blue-700"
|
||||
className="absolute w-full h-full bg-gradient-to-br from-blue-600 to-blue-700 rounded-lg shadow-lg p-8 flex flex-col justify-between border border-blue-500"
|
||||
style={{
|
||||
backfaceVisibility: 'hidden',
|
||||
transform: 'rotateY(180deg)',
|
||||
}}
|
||||
>
|
||||
<p className="text-white text-sm leading-relaxed font-medium">
|
||||
<div>
|
||||
<h3 className="font-bold text-white mb-4 text-lg">
|
||||
{testimonial.author}
|
||||
</h3>
|
||||
<p className="text-blue-50 leading-relaxed text-sm">
|
||||
{testimonial.fullText}
|
||||
</p>
|
||||
<p className="text-blue-100 text-xs mt-4 font-semibold">
|
||||
— {testimonial.author}
|
||||
</p>
|
||||
</div>
|
||||
<div className="text-center text-xs text-blue-200 font-medium">
|
||||
Click to go back
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user