Merge version_2_1776426692577 into main #1

Merged
bender merged 1 commits from version_2_1776426692577 into main 2026-04-17 11:54:13 +00:00
3 changed files with 95 additions and 1 deletions

View File

@@ -1,11 +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';
export default function App() {
return (
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/" element={<><HomePage /><Testimonials /></>} />
<Route path="/privacy" element={<PrivacyPage />} />
</Routes>
);

View File

@@ -0,0 +1,71 @@
import { useState, useEffect } from 'react';
import { testimonials } from '../../../data/testimonials';
const ChevronUp = () => (
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="m18 15-6-6-6 6"/></svg>
);
const ChevronDown = () => (
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="m6 9 6 6 6-6"/></svg>
);
const Testimonials = () => {
const [activeIndex, setActiveIndex] = useState(0);
const slideHeight = 250;
useEffect(() => {
const interval = setInterval(() => {
setActiveIndex(prev => (prev + 1) % testimonials.length);
}, 5000);
return () => clearInterval(interval);
}, []);
const handlePrev = () => {
setActiveIndex(prev => (prev - 1 + testimonials.length) % testimonials.length);
};
const handleNext = () => {
setActiveIndex(prev => (prev + 1) % testimonials.length);
};
return (
<section className="testimonials-section" aria-label="Student Testimonials">
<div className="testimonials-container">
<div className="testimonials-content">
<h2>What Our Students Say</h2>
<p>Hear from our graduates who have transformed their careers with our programs.</p>
</div>
<div className="testimonials-slider-container">
<div className="testimonials-slider">
<div
className="testimonials-slider-wrapper"
style={{ transform: `translateY(-${activeIndex * slideHeight}px)` }}
>
{testimonials.map((testimonial, index) => (
<div key={index} className="testimonial-card card">
<blockquote className="testimonial-quote">
"{testimonial.quote}"
</blockquote>
<div className="testimonial-author-info">
<p className="testimonial-author">{testimonial.name}</p>
<p className="testimonial-course">{testimonial.course}</p>
</div>
</div>
))}
</div>
</div>
<div className="testimonial-controls">
<button onClick={handlePrev} aria-label="Previous testimonial">
<ChevronUp />
</button>
<button onClick={handleNext} aria-label="Next testimonial">
<ChevronDown />
</button>
</div>
</div>
</div>
</section>
);
};
export default Testimonials;

22
src/data/testimonials.ts Normal file
View File

@@ -0,0 +1,22 @@
export const testimonials = [
{
name: "John Doe",
quote: "This academy changed my life. The hands-on projects were incredibly valuable.",
course: "Full-Stack Web Development"
},
{
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: "Samuel Green",
quote: "I came in with zero coding experience and now I'm a confident software engineer. Highly recommended!",
course: "Cybersecurity"
},
{
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"
}
];