infoalloggi-monorepo/apps/infoalloggi/src/components/videoPlayer.tsx

101 lines
2.5 KiB
TypeScript
Raw Normal View History

2025-08-04 17:45:44 +02:00
"use client";
2025-08-28 18:27:07 +02:00
import { AnimatePresence, motion } from "framer-motion";
2025-08-04 17:45:44 +02:00
import { Play } from "lucide-react";
2025-08-28 18:27:07 +02:00
import Image from "next/image";
import { useState } from "react";
2025-08-04 17:45:44 +02:00
import { cn } from "~/lib/utils";
interface VideoPlayerProps {
2025-08-28 18:27:07 +02:00
coverImage: string;
videoSrc: string;
title?: string;
aspectRatio?: "square" | "video" | "vertical";
className?: string;
2025-08-04 17:45:44 +02:00
}
export function VideoPlayer({
2025-08-28 18:27:07 +02:00
coverImage,
videoSrc,
title,
aspectRatio = "video",
className,
2025-08-04 17:45:44 +02:00
}: VideoPlayerProps) {
2025-08-28 18:27:07 +02:00
const [isPlaying, setIsPlaying] = useState(false);
2025-08-04 17:45:44 +02:00
2025-08-28 18:27:07 +02:00
const aspectRatioClasses = {
square: "aspect-square",
video: "aspect-video",
vertical: "aspect-[9/16]",
};
2025-08-04 17:45:44 +02:00
2025-08-28 18:27:07 +02:00
return (
<div
className={cn(
"relative w-full overflow-hidden rounded-lg",
aspectRatioClasses[aspectRatio],
className,
)}
>
<AnimatePresence mode="wait">
{!isPlaying ? (
<motion.div
key="cover"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.3 }}
className="relative h-full w-full cursor-pointer"
onClick={() => setIsPlaying(true)}
>
<Image
src={coverImage || "/fallback-video.png"}
alt={title || "Video thumbnail"}
fill
className="object-cover"
priority
/>
<div className="absolute inset-0 flex items-center justify-center bg-black/20">
<motion.div
whileHover={{ scale: 1.1 }}
whileTap={{ scale: 0.95 }}
className="bg-primary/90 text-primary-foreground flex size-16 items-center justify-center rounded-full shadow-lg"
>
<Play className="size-8" />
</motion.div>
</div>
{title && (
<div className="absolute right-0 bottom-0 left-0 bg-gradient-to-t from-black/80 to-transparent p-4">
<h3 className="text-lg font-medium text-white">{title}</h3>
</div>
)}
</motion.div>
) : (
<motion.div
key="video"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.3 }}
className="h-full w-full"
>
<video
src={videoSrc}
className="h-full w-full rounded-md"
controls
autoPlay
controlsList="play nodownload"
disablePictureInPicture
disableRemotePlayback
muted
onEnded={() => setIsPlaying(false)}
>
Your browser does not support the video tag.
</video>
</motion.div>
)}
</AnimatePresence>
</div>
);
2025-08-04 17:45:44 +02:00
}