init
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
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">
|
||||
↗
|
||||
</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">↗</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}`}
|
||||
>
|
||||
×
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user