Files
wijtransferen/frontend/src/components/dashboard/GalleryCard.tsx
T
2026-08-22 02:59:16 +02:00

85 lines
2.8 KiB
TypeScript

import { useState } from 'react';
import { Link } from 'react-router-dom';
import type { GallerySummary } from '../../types/gallery';
import { formatBytes, formatDate } from '../../lib/format';
interface GalleryCardProps {
gallery: GallerySummary;
onDelete: (gallery: GallerySummary) => void;
}
export function GalleryCard({ gallery, onDelete }: GalleryCardProps) {
const [copied, setCopied] = useState(false);
const clientURL = `${window.location.origin}/g/${gallery.slug}`;
async function copyLink() {
try {
await navigator.clipboard.writeText(clientURL);
setCopied(true);
window.setTimeout(() => setCopied(false), 1800);
} catch {
setCopied(false);
}
}
return (
<article className="gallery-card">
<Link className="gallery-card__cover" to={`/dashboard/galleries/${gallery.id}/edit`}>
{gallery.coverUrl ? (
<img src={gallery.coverUrl} alt="" loading="lazy" />
) : (
<div className="gallery-card__cover-placeholder" aria-hidden="true">
<span>{gallery.clientName.slice(0, 1).toUpperCase()}</span>
</div>
)}
<span className={`status-pill status-pill--${gallery.status}`}>
<i aria-hidden="true" /> {gallery.status}
</span>
<span className="gallery-card__cover-arrow" aria-hidden="true">
&#8599;
</span>
</Link>
<div className="gallery-card__body">
<div className="gallery-card__heading">
<div>
<p>{gallery.clientName}</p>
<h3>{gallery.title}</h3>
</div>
<span className="gallery-card__date">{formatDate(gallery.createdAt)}</span>
</div>
<div className="gallery-card__meta">
<span>{gallery.photoCount} photos</span>
<span>{gallery.videoCount} videos</span>
<span>{formatBytes(gallery.totalBytes)}</span>
</div>
<div className="gallery-card__actions">
<Link className="text-action" to={`/dashboard/galleries/${gallery.id}/edit`}>
Edit <span aria-hidden="true">&#8599;</span>
</Link>
<Link className="text-action text-action--muted" to={`/preview/${gallery.id}`}>
Preview
</Link>
{gallery.status === 'published' && (
<button
className="text-action text-action--muted"
type="button"
onClick={() => void copyLink()}
>
{copied ? 'Copied' : 'Copy link'}
</button>
)}
<button
className="gallery-card__delete"
type="button"
onClick={() => onDelete(gallery)}
aria-label={`Delete ${gallery.title}`}
>
&#215;
</button>
</div>
</div>
</article>
);
}