feat: add video support to CarouselAnnuncio and integrate VideoPlayer component
This commit is contained in:
parent
1f1d9f3559
commit
0bc1a0915c
4 changed files with 79 additions and 17 deletions
|
|
@ -20,6 +20,7 @@ import {
|
||||||
import { camereTesti, handleConsegna } from "~/lib/annuncio_details";
|
import { camereTesti, handleConsegna } from "~/lib/annuncio_details";
|
||||||
import { cn, formatCurrency } from "~/lib/utils";
|
import { cn, formatCurrency } from "~/lib/utils";
|
||||||
import { useTranslation } from "~/providers/I18nProvider";
|
import { useTranslation } from "~/providers/I18nProvider";
|
||||||
|
import { VideoPlayer } from "./videoPlayer";
|
||||||
|
|
||||||
type CardAnnuncioProps = {
|
type CardAnnuncioProps = {
|
||||||
id: number;
|
id: number;
|
||||||
|
|
@ -205,9 +206,11 @@ export const CardAnnuncio = ({
|
||||||
export const CarouselAnnuncio = ({
|
export const CarouselAnnuncio = ({
|
||||||
single,
|
single,
|
||||||
immagini,
|
immagini,
|
||||||
|
videos,
|
||||||
}: {
|
}: {
|
||||||
single?: boolean;
|
single?: boolean;
|
||||||
immagini: string[] | null;
|
immagini: string[] | null;
|
||||||
|
videos: string[] | null;
|
||||||
}) => {
|
}) => {
|
||||||
const [openModal, setOpenModal] = useState(false);
|
const [openModal, setOpenModal] = useState(false);
|
||||||
const [idxModal, setIdxModal] = useState(0);
|
const [idxModal, setIdxModal] = useState(0);
|
||||||
|
|
@ -215,7 +218,6 @@ export const CarouselAnnuncio = ({
|
||||||
setIdxModal(position);
|
setIdxModal(position);
|
||||||
setOpenModal(true);
|
setOpenModal(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="mx-auto my-4 w-full rounded-md text-clip">
|
<div className="mx-auto my-4 w-full rounded-md text-clip">
|
||||||
|
|
@ -245,11 +247,43 @@ export const CarouselAnnuncio = ({
|
||||||
width={800}
|
width={800}
|
||||||
/>
|
/>
|
||||||
<Maximize2
|
<Maximize2
|
||||||
className="absolute right-2 bottom-2 size-6 rounded-md bg-white/70 stroke-2 p-1 transition-opacity duration-150 group-hover:opacity-100 sm:opacity-0"
|
className="absolute right-2 bottom-2 transition-all duration-300 hover:scale-150 origin-bottom-right ease-in-out cursor-pointer size-7 rounded-md bg-white/70 stroke-2 p-1 group-hover:opacity-100 sm:opacity-0"
|
||||||
onClick={() => handleOpenModal(idx)}
|
onClick={() => handleOpenModal(idx)}
|
||||||
/>
|
/>
|
||||||
</CarouselItem>
|
</CarouselItem>
|
||||||
))}
|
))}
|
||||||
|
{videos?.map((video, idx) => {
|
||||||
|
if (!video) return null;
|
||||||
|
if (video.includes("youtu")) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<CarouselItem
|
||||||
|
className={cn(
|
||||||
|
"group relative",
|
||||||
|
immagini && immagini.length === 1
|
||||||
|
? ""
|
||||||
|
: !single && "md:basis-1/2 lg:basis-1/3",
|
||||||
|
)}
|
||||||
|
key={`videoplayer-${video}`}
|
||||||
|
>
|
||||||
|
<VideoPlayer
|
||||||
|
className="h-72 "
|
||||||
|
coverImage={immagini?.[0] ? immagini[0] : ""}
|
||||||
|
key={`videoplayer-${idx}-${openModal}`}
|
||||||
|
videoSrc={video}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Maximize2
|
||||||
|
className="absolute right-2 bottom-2 transition-all duration-300 hover:scale-150 origin-bottom-right ease-in-out cursor-pointer size-7 rounded-md bg-white/70 stroke-2 p-1 group-hover:opacity-100 sm:opacity-0"
|
||||||
|
onClick={() =>
|
||||||
|
handleOpenModal(immagini?.length || 0 + idx)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</CarouselItem>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})}
|
||||||
</CarouselContent>
|
</CarouselContent>
|
||||||
|
|
||||||
<CarouselPrevious
|
<CarouselPrevious
|
||||||
|
|
@ -277,13 +311,32 @@ export const CarouselAnnuncio = ({
|
||||||
<CarouselItem key={`${img}-${idx}-cD`}>
|
<CarouselItem key={`${img}-${idx}-cD`}>
|
||||||
<Image
|
<Image
|
||||||
alt={`carousel-img-${idx}`}
|
alt={`carousel-img-${idx}`}
|
||||||
className="mx-auto h-[90vh] w-full rounded-md object-contain sm:w-[80vw]"
|
className="mx-auto h-[90vh] w-full rounded-md object-contain sm:w-[80vw] "
|
||||||
height={1080}
|
height={1080}
|
||||||
src={img}
|
src={img}
|
||||||
width={1920}
|
width={1920}
|
||||||
/>
|
/>
|
||||||
</CarouselItem>
|
</CarouselItem>
|
||||||
))}
|
))}
|
||||||
|
{videos?.map((video) => {
|
||||||
|
if (!video) return null;
|
||||||
|
if (video.includes("youtu")) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<CarouselItem
|
||||||
|
className="relative flex items-center justify-center"
|
||||||
|
key={`carousel-videoplayer-${video}`}
|
||||||
|
>
|
||||||
|
<VideoPlayer
|
||||||
|
className="h-[90vh] absolute w-full mx-auto max-w-fit rounded-md object-contain"
|
||||||
|
coverImage={immagini?.[0] ? immagini[0] : ""}
|
||||||
|
videoSrc={video}
|
||||||
|
/>
|
||||||
|
</CarouselItem>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})}
|
||||||
</CarouselContent>
|
</CarouselContent>
|
||||||
|
|
||||||
<CarouselPrevious
|
<CarouselPrevious
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { AnimatePresence, motion } from "framer-motion";
|
import { AnimatePresence, motion, useInView } from "framer-motion";
|
||||||
import { Play } from "lucide-react";
|
import { Play } from "lucide-react";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import { useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import { cn } from "~/lib/utils";
|
import { cn } from "~/lib/utils";
|
||||||
|
|
||||||
interface VideoPlayerProps {
|
interface VideoPlayerProps {
|
||||||
|
|
@ -22,6 +22,14 @@ export function VideoPlayer({
|
||||||
className,
|
className,
|
||||||
}: VideoPlayerProps) {
|
}: VideoPlayerProps) {
|
||||||
const [isPlaying, setIsPlaying] = useState(false);
|
const [isPlaying, setIsPlaying] = useState(false);
|
||||||
|
const videoRef = useRef<HTMLDivElement>(null);
|
||||||
|
const inView = useInView(videoRef);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!inView) {
|
||||||
|
setIsPlaying(false);
|
||||||
|
}
|
||||||
|
}, [inView]);
|
||||||
|
|
||||||
const aspectRatioClasses = {
|
const aspectRatioClasses = {
|
||||||
square: "aspect-square",
|
square: "aspect-square",
|
||||||
|
|
@ -36,6 +44,7 @@ export function VideoPlayer({
|
||||||
aspectRatioClasses[aspectRatio],
|
aspectRatioClasses[aspectRatio],
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
|
ref={videoRef}
|
||||||
>
|
>
|
||||||
<AnimatePresence mode="wait">
|
<AnimatePresence mode="wait">
|
||||||
{!isPlaying ? (
|
{!isPlaying ? (
|
||||||
|
|
|
||||||
|
|
@ -454,18 +454,15 @@ export const AnnuncioEditForm = ({ data }: { data: Annunci }) => {
|
||||||
<CardTitle>Imagini Annuncio</CardTitle>
|
<CardTitle>Imagini Annuncio</CardTitle>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
{data.url_immagini && data.url_immagini.length > 0 ? (
|
<CarouselAnnuncio
|
||||||
<CarouselAnnuncio
|
immagini={
|
||||||
immagini={data.url_immagini.map(
|
data.url_immagini?.map(
|
||||||
(v) => `/go-api/images/get/${v}`,
|
(v) => `/go-api/images/get/${v}`,
|
||||||
)}
|
) || null
|
||||||
single
|
}
|
||||||
/>
|
single
|
||||||
) : (
|
videos={data.url_video}
|
||||||
<div className="text-center text-gray-500">
|
/>
|
||||||
Nessuna immagine disponibile
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -133,7 +133,10 @@ const AnnuncioView = ({ cod, flag }: Omit<AnnuncioProps, "meta">) => {
|
||||||
<AnnuncioContext.Provider value={data}>
|
<AnnuncioContext.Provider value={data}>
|
||||||
<TouchProvider>
|
<TouchProvider>
|
||||||
<div className="mx-auto w-full px-2 sm:px-8">
|
<div className="mx-auto w-full px-2 sm:px-8">
|
||||||
<CarouselAnnuncio immagini={data.url_immagini} />
|
<CarouselAnnuncio
|
||||||
|
immagini={data.url_immagini}
|
||||||
|
videos={data.url_video}
|
||||||
|
/>
|
||||||
|
|
||||||
<div className="flex flex-col sm:py-8 md:flex-row-reverse md:gap-2">
|
<div className="flex flex-col sm:py-8 md:flex-row-reverse md:gap-2">
|
||||||
<div className="mb-6 flex flex-col md:mb-0 md:w-1/3">
|
<div className="mb-6 flex flex-col md:mb-0 md:w-1/3">
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue