94 lines
3.1 KiB
TypeScript
94 lines
3.1 KiB
TypeScript
"use client";
|
|
|
|
import { useRef, useState } from "react";
|
|
import { useRouter } from "next/navigation";
|
|
|
|
import FavoriteToggle from "./FavoriteToggle";
|
|
|
|
type WorkHeroGalleryProps = {
|
|
gallery: string[];
|
|
title: string;
|
|
workId: string;
|
|
shareUrl?: string;
|
|
};
|
|
|
|
export default function WorkHeroGallery({ gallery, title, workId, shareUrl }: WorkHeroGalleryProps) {
|
|
const router = useRouter();
|
|
const galleryRef = useRef<HTMLDivElement>(null);
|
|
const [activeIndex, setActiveIndex] = useState(0);
|
|
|
|
function updateActiveSlide() {
|
|
const galleryNode = galleryRef.current;
|
|
if (!galleryNode) {
|
|
return;
|
|
}
|
|
|
|
const nextIndex = Math.round(galleryNode.scrollLeft / Math.max(galleryNode.clientWidth, 1));
|
|
setActiveIndex(Math.min(Math.max(nextIndex, 0), gallery.length - 1));
|
|
}
|
|
|
|
function goBack() {
|
|
if (typeof window !== "undefined" && window.history.length > 1) {
|
|
router.back();
|
|
return;
|
|
}
|
|
|
|
router.push("/discover");
|
|
}
|
|
|
|
async function shareWork() {
|
|
const url = shareUrl || (typeof window !== "undefined" ? window.location.href : "");
|
|
if (!url) {
|
|
return;
|
|
}
|
|
|
|
if (typeof navigator !== "undefined" && navigator.share) {
|
|
await navigator.share({
|
|
title,
|
|
text: `Mira este trabajo que encontre en Makers3D: ${title}`,
|
|
url
|
|
}).catch(() => undefined);
|
|
return;
|
|
}
|
|
|
|
await navigator.clipboard?.writeText(url).catch(() => undefined);
|
|
}
|
|
|
|
return (
|
|
<section className="work-detail-hero">
|
|
<div ref={galleryRef} className="work-detail-hero-gallery" onScroll={updateActiveSlide} aria-label={`Galeria de ${title}`}>
|
|
{gallery.map((image, index) => (
|
|
<div key={`${image}-${index}`} className="work-detail-hero-slide">
|
|
<img src={image} alt={`${title} - foto ${index + 1}`} />
|
|
</div>
|
|
))}
|
|
</div>
|
|
|
|
{gallery.length > 1 ? (
|
|
<div className="work-detail-hero-dots" aria-hidden="true">
|
|
{gallery.map((image, index) => (
|
|
<span key={`${image}-dot-${index}`} className={index === activeIndex ? "is-active" : ""} />
|
|
))}
|
|
</div>
|
|
) : null}
|
|
|
|
<div className="work-detail-top-actions">
|
|
<button className="work-detail-circle-action" type="button" onClick={goBack} aria-label="Volver"><</button>
|
|
<div className="work-detail-action-pair">
|
|
<FavoriteToggle targetType="work" targetId={workId} compact icon="bookmark" />
|
|
<button className="work-detail-circle-action" type="button" onClick={() => void shareWork()} aria-label="Compartir trabajo">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.9" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
|
|
<circle cx="18" cy="5" r="3" />
|
|
<circle cx="6" cy="12" r="3" />
|
|
<circle cx="18" cy="19" r="3" />
|
|
<path d="m8.6 10.5 6.8-4" />
|
|
<path d="m8.6 13.5 6.8 4" />
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<span className="work-detail-gallery-count">{activeIndex + 1}/{gallery.length}</span>
|
|
</section>
|
|
);
|
|
}
|