almeira-web/src/components/ClientSidebars.tsx

115 lines
4.8 KiB
TypeScript

'use client';
import { useEffect, useState } from 'react';
import MetricObserver from './MetricObserver';
import { ExternalLink, Tag } from 'lucide-react';
export default function ClientSidebars({ groupedAds, rotationSeconds }: { groupedAds: Record<string, any>, rotationSeconds: number }) {
// Si no hay grupos, no mostrar nada
const groups = Object.keys(groupedAds);
if (groups.length === 0) return null;
return (
<div className="space-y-6">
{groups.map(eslogan => (
<ClientCarouselGroup
key={eslogan}
eslogan={eslogan}
ads={groupedAds[eslogan]}
rotationSeconds={rotationSeconds}
/>
))}
</div>
);
}
function ClientCarouselGroup({ eslogan, ads, rotationSeconds }: { eslogan: string, ads: any[], rotationSeconds: number }) {
const [currentIndex, setCurrentIndex] = useState(0);
useEffect(() => {
if (!ads || ads.length <= 1) return;
const delay = (rotationSeconds && rotationSeconds > 0) ? rotationSeconds * 1000 : 5000;
const interval = setInterval(() => {
setCurrentIndex(prev => (prev + 1) % ads.length);
}, delay);
return () => clearInterval(interval);
}, [ads, rotationSeconds]);
if (!ads || ads.length === 0) return null;
const activeAd = ads[currentIndex];
if (!activeAd.imagen_destacada_id) return null;
const ENDPOINT = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT || 'https://appwrite.almeira.com.co/v1';
const PROJECT_ID = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID || '69b84df5003bd8957c5c';
let imgUrl = activeAd.og_image_url || null;
if (activeAd.imagen_destacada_id) {
if (typeof activeAd.imagen_destacada_id === 'object' && activeAd.imagen_destacada_id.bucket_id) {
imgUrl = `${ENDPOINT}/storage/buckets/${activeAd.imagen_destacada_id.bucket_id}/files/${activeAd.imagen_destacada_id.file_id}/view?project=${PROJECT_ID}`;
} else if (typeof activeAd.imagen_destacada_id === 'string') {
imgUrl = `${ENDPOINT}/storage/buckets/media/files/${activeAd.imagen_destacada_id}/view?project=${PROJECT_ID}`;
}
}
const recordClickAndGo = () => {
fetch('/api/metrics', {
method: 'POST',
body: JSON.stringify({ postId: activeAd.$id, tipo: 'click' })
});
if (activeAd.url_destino) {
window.open(activeAd.url_destino, '_blank');
}
};
return (
<div className="bg-slate-900 border border-slate-800 rounded-2xl overflow-hidden shadow-xl shadow-purple-500/5 group">
{/* Eslogan del Contrato / Patrocinador */}
<div className="bg-slate-950 px-4 py-2 flex items-center gap-2 border-b border-slate-800">
<Tag size={12} className="text-pink-500" />
<span className="text-xs font-bold uppercase tracking-widest text-slate-300 truncate">
{eslogan !== 'General' ? eslogan : 'Patrocinado'}
</span>
</div>
{/* Slider de Anuncios */}
<div className={`relative h-[250px] sm:h-[300px] w-full bg-slate-950 ${activeAd.url_destino ? 'cursor-pointer' : ''}`} onClick={recordClickAndGo}>
<MetricObserver key={activeAd.$id} postId={activeAd.$id} />
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
key={activeAd.$id}
src={imgUrl}
alt={activeAd.titulo}
className="w-full h-full object-cover animate-fade-in"
/>
{/* Badge Overlay */}
<div className="absolute top-2 right-2 bg-black/60 backdrop-blur-md px-2 py-1 rounded text-[10px] font-bold text-cyan-400 uppercase tracking-widest border border-cyan-500/30">
{activeAd.tipo_publicacion_id?.descripcion || 'Promoción'}
</div>
{activeAd.url_destino && (
<div className="absolute bottom-2 right-2 bg-black/70 p-1.5 rounded-lg opacity-0 group-hover:opacity-100 transition-opacity">
<ExternalLink className="text-pink-500" size={16} />
</div>
)}
</div>
{/* Progress/Dots */}
{ads.length > 1 && (
<div className="bg-slate-950 py-1.5 flex justify-center gap-1.5 border-t border-slate-800">
{ads.map((_: any, idx: number) => (
<div key={idx} className={`h-1 rounded-full transition-all ${idx === currentIndex ? 'w-4 bg-pink-500' : 'w-1 bg-slate-600'}`}></div>
))}
</div>
)}
</div>
);
}