Merge version_3_1776427183211 into main #2

Merged
bender merged 3 commits from version_3_1776427183211 into main 2026-04-17 12:06:34 +00:00
4 changed files with 129 additions and 16 deletions

View File

@@ -1,12 +1,12 @@
import { Routes, Route } from 'react-router-dom';
import HomePage from './pages/HomePage';
import PrivacyPage from './pages/PrivacyPage';
import Testimonials from './components/sections/testimonials/Testimonials';
import TestimonialsSlider from './components/sections/testimonials/TestimonialsSlider';
export default function App() {
return (
<Routes>
<Route path="/" element={<><HomePage /><Testimonials /></>} />
<Route path="/" element={<><HomePage /><TestimonialsSlider /></>} />
<Route path="/privacy" element={<PrivacyPage />} />
</Routes>
);

View File

@@ -0,0 +1,92 @@
import { useCallback } from 'react';
import useEmblaCarousel from 'embla-carousel-react';
import { Quote, ArrowUp, ArrowDown } from 'lucide-react';
const testimonials = [
{
quote: "The curriculum is top-notch, and the instructors are industry experts. I felt supported every step of the way.",
name: "Jane Smith",
role: "Full-Stack Developer",
avatar: "https://i.pravatar.cc/150?u=a042581f4e29026704d"
},
{
quote: "I went from zero coding knowledge to building complex applications. This academy is the real deal.",
name: "Alex Johnson",
role: "Mobile App Developer",
avatar: "https://i.pravatar.cc/150?u=a042581f4e29026705d"
},
{
quote: "The hands-on projects were invaluable. I built a portfolio that impressed employers and landed me a great job.",
name: "Emily White",
role: "Frontend Engineer",
avatar: "https://i.pravatar.cc/150?u=a042581f4e29026706d"
},
{
quote: "A fantastic learning environment. The community is amazing, and I made lifelong connections.",
name: "Michael Brown",
role: "Backend Specialist",
avatar: "https://i.pravatar.cc/150?u=a042581f4e29026707d"
}
];
export default function TestimonialsSlider() {
const [emblaRef, emblaApi] = useEmblaCarousel({
loop: true,
axis: 'y',
});
const scrollPrev = useCallback(() => {
if (emblaApi) emblaApi.scrollPrev();
}, [emblaApi]);
const scrollNext = useCallback(() => {
if (emblaApi) emblaApi.scrollNext();
}, [emblaApi]);
return (
<section aria-label="Testimonials section" className="py-20">
<div className="flex flex-col items-center gap-8 w-content-width mx-auto">
<div className="flex flex-col items-center gap-3 md:gap-2 text-center">
<span className="px-3 py-1 text-sm card rounded-lg">Testimonials</span>
<h2 className="text-6xl font-medium text-balance">What Our Students Say</h2>
<p className="md:max-w-8/10 text-lg leading-tight text-foreground/75">
Hear from our graduates about their journey and success with our academy.
</p>
</div>
<div className="relative w-full max-w-3xl">
<div className="overflow-hidden h-[320px] rounded-lg" ref={emblaRef}>
<div className="flex flex-col h-full">
{testimonials.map((testimonial, index) => (
<div className="flex-[0_0_100%] min-h-0 p-1" key={index}>
<div className="card p-8 rounded-lg h-full flex flex-col justify-center text-left">
<Quote className="w-10 h-10 text-accent mb-4" />
<blockquote className="text-xl italic text-foreground/80 mb-6">
"{testimonial.quote}"
</blockquote>
<div className="flex items-center">
<img src={testimonial.avatar} alt={testimonial.name} className="w-14 h-14 rounded-full mr-4 object-cover" />
<div>
<p className="font-semibold text-lg text-foreground">{testimonial.name}</p>
<p className="text-base text-foreground/60">{testimonial.role}</p>
</div>
</div>
</div>
</div>
))}
</div>
</div>
<div className="absolute top-1/2 -right-20 -translate-y-1/2 flex-col gap-4 max-lg:hidden flex">
<button onClick={scrollPrev} aria-label="Previous testimonial" className="secondary-button p-3 rounded-full transition-transform hover:scale-110">
<ArrowUp className="w-6 h-6" />
</button>
<button onClick={scrollNext} aria-label="Next testimonial" className="secondary-button p-3 rounded-full transition-transform hover:scale-110">
<ArrowDown className="w-6 h-6" />
</button>
</div>
</div>
</div>
</section>
);
}

View File

@@ -1,22 +1,32 @@
export const testimonials = [
export interface Testimonial {
name: string;
course: string;
quote: string;
}
export const testimonials: Testimonial[] = [
{
name: "John Doe",
quote: "This academy changed my life. The hands-on projects were incredibly valuable.",
course: "Full-Stack Web Development"
name: "Alex Johnson",
course: "Full-Stack Development Graduate",
quote:
"This program completely changed my career trajectory. The hands-on projects and mentorship were invaluable.",
},
{
name: "Jane Smith",
quote: "The instructors are industry experts who are passionate about teaching. I landed a great job right after graduating.",
course: "Data Science & Machine Learning"
name: "Maria Garcia",
course: "Data Science Alumna",
quote:
"I went from knowing nothing about data to landing a job as a data analyst. The curriculum is top-notch and industry-relevant.",
},
{
name: "Samuel Green",
quote: "I came in with zero coding experience and now I'm a confident software engineer. Highly recommended!",
course: "Cybersecurity"
name: "Sam Lee",
course: "UX/UI Design Certificate",
quote:
"The instructors are passionate and the community is incredibly supportive. I built a portfolio I'm proud of.",
},
{
name: "Emily White",
quote: "The curriculum is up-to-date with the latest technologies. The career support team was also fantastic.",
course: "Full-Stack Web Development"
}
name: "Jessica Chen",
course: "Cybersecurity Bootcamp Finisher",
quote:
"The bootcamp was intense but so rewarding. I feel confident and prepared for the challenges of the cybersecurity field.",
},
];

View File

@@ -119,6 +119,17 @@
}
}
@keyframes slide-in-up {
from {
transform: translateY(100%);
opacity: 0;
}
to {
transform: translateY(0);
opacity: 1;
}
}
/* Animation classes */
.animate-pulsate {