id
This commit is contained in:
99
frontend/src/components/DroneVideoCarousel.tsx
Normal file
99
frontend/src/components/DroneVideoCarousel.tsx
Normal file
@@ -0,0 +1,99 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { ChevronLeft, ChevronRight } from 'lucide-react';
|
||||
import { motion, AnimatePresence } from 'framer-motion';
|
||||
|
||||
const DroneVideoCarousel: React.FC = () => {
|
||||
const [currentIndex, setCurrentIndex] = useState(0);
|
||||
|
||||
// Placeholder YouTube video IDs - replace with actual drone video IDs
|
||||
const videos = [
|
||||
{ id: 'dQw4w9WgXcQ', title: 'Drone Footage 1' },
|
||||
{ id: 'dQw4w9WgXcQ', title: 'Drone Footage 2' },
|
||||
{ id: 'dQw4w9WgXcQ', title: 'Drone Footage 3' },
|
||||
{ id: 'dQw4w9WgXcQ', title: 'Drone Footage 4' }
|
||||
];
|
||||
|
||||
const nextSlide = () => {
|
||||
setCurrentIndex((prevIndex) => (prevIndex + 1) % videos.length);
|
||||
};
|
||||
|
||||
const prevSlide = () => {
|
||||
setCurrentIndex((prevIndex) => (prevIndex - 1 + videos.length) % videos.length);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const timer = setInterval(nextSlide, 5000);
|
||||
return () => clearInterval(timer);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<section className="py-20 bg-background">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="text-center mb-12">
|
||||
<h2 className="text-3xl font-bold text-text sm:text-4xl">
|
||||
Drone Videography
|
||||
</h2>
|
||||
<p className="mt-4 text-lg text-lines max-w-2xl mx-auto">
|
||||
Capturing stunning aerial perspectives through professional drone footage
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="relative max-w-4xl mx-auto">
|
||||
<div className="aspect-video bg-background-light rounded-xl overflow-hidden shadow-2xl border border-lines">
|
||||
<AnimatePresence mode="wait">
|
||||
<motion.div
|
||||
key={currentIndex}
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
transition={{ duration: 0.5 }}
|
||||
className="w-full h-full"
|
||||
>
|
||||
<iframe
|
||||
src={`https://www.youtube.com/embed/${videos[currentIndex].id}?autoplay=0&mute=1&loop=1&playlist=${videos[currentIndex].id}`}
|
||||
title={videos[currentIndex].title}
|
||||
className="w-full h-full"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
allowFullScreen
|
||||
/>
|
||||
</motion.div>
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
|
||||
<button
|
||||
onClick={prevSlide}
|
||||
className="absolute left-4 top-1/2 transform -translate-y-1/2 bg-boxes hover:bg-other text-text p-3 rounded-full transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-lines focus:ring-offset-2 focus:ring-offset-background"
|
||||
aria-label="Previous video"
|
||||
>
|
||||
<ChevronLeft className="h-6 w-6" />
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={nextSlide}
|
||||
className="absolute right-4 top-1/2 transform -translate-y-1/2 bg-boxes hover:bg-other text-text p-3 rounded-full transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-lines focus:ring-offset-2 focus:ring-offset-background"
|
||||
aria-label="Next video"
|
||||
>
|
||||
<ChevronRight className="h-6 w-6" />
|
||||
</button>
|
||||
|
||||
<div className="flex justify-center mt-6 space-x-2">
|
||||
{videos.map((_, index) => (
|
||||
<button
|
||||
key={index}
|
||||
onClick={() => setCurrentIndex(index)}
|
||||
className={`w-3 h-3 rounded-full transition-all duration-200 ${
|
||||
index === currentIndex
|
||||
? 'bg-other'
|
||||
: 'bg-lines hover:bg-boxes'
|
||||
}`}
|
||||
aria-label={`Go to video ${index + 1}`}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default DroneVideoCarousel;
|
||||
Reference in New Issue
Block a user