110 lines
3.3 KiB
TypeScript
110 lines
3.3 KiB
TypeScript
import { useState } from 'react';
|
|
import type { GalleryImage } from '../../api/types';
|
|
import { api } from '../../api';
|
|
import { useQueryClient } from '@tanstack/react-query';
|
|
|
|
interface Props {
|
|
images: GalleryImage[];
|
|
catalogId: string;
|
|
}
|
|
|
|
export default function LightboxView({ images, catalogId }: Props) {
|
|
const [lightbox, setLightbox] = useState<GalleryImage | null>(null);
|
|
const qc = useQueryClient();
|
|
|
|
if (images.length === 0) {
|
|
return (
|
|
<div style={{ color: 'var(--text-lo)', fontFamily: 'var(--font-mono)', fontSize: 12, padding: '8px 0' }}>
|
|
No images yet.
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 6 }}>
|
|
{images.map(img => (
|
|
<div
|
|
key={img.id}
|
|
onClick={() => setLightbox(img)}
|
|
style={{
|
|
cursor: 'pointer',
|
|
borderRadius: 3,
|
|
overflow: 'hidden',
|
|
background: 'var(--bg-deep)',
|
|
aspectRatio: '1',
|
|
position: 'relative',
|
|
}}
|
|
>
|
|
<img
|
|
src={img.url}
|
|
alt={img.caption ?? img.filename}
|
|
style={{ width: '100%', height: '100%', objectFit: 'cover' }}
|
|
/>
|
|
</div>
|
|
))}
|
|
</div>
|
|
|
|
{lightbox && (
|
|
<div
|
|
onClick={() => setLightbox(null)}
|
|
style={{
|
|
position: 'fixed',
|
|
inset: 0,
|
|
background: 'rgba(0,0,0,0.92)',
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
zIndex: 1000,
|
|
}}
|
|
>
|
|
<div onClick={e => e.stopPropagation()} style={{ position: 'relative', maxWidth: '90vw', maxHeight: '90vh' }}>
|
|
<img
|
|
src={lightbox.url}
|
|
alt={lightbox.caption ?? lightbox.filename}
|
|
style={{ maxWidth: '100%', maxHeight: '85vh', borderRadius: 4 }}
|
|
/>
|
|
<div style={{ marginTop: 8, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
|
{lightbox.caption && (
|
|
<span style={{ color: 'var(--text-mid)', fontSize: 12, fontFamily: 'var(--font-sans)' }}>
|
|
{lightbox.caption}
|
|
</span>
|
|
)}
|
|
<button
|
|
onClick={() => {
|
|
api.gallery.delete(lightbox.id).then(() => {
|
|
qc.invalidateQueries({ queryKey: ['gallery', catalogId] });
|
|
setLightbox(null);
|
|
});
|
|
}}
|
|
style={{ color: 'var(--danger)', fontSize: 12, marginLeft: 'auto' }}
|
|
>
|
|
Delete
|
|
</button>
|
|
</div>
|
|
<button
|
|
onClick={() => setLightbox(null)}
|
|
style={{
|
|
position: 'absolute',
|
|
top: -12,
|
|
right: -12,
|
|
color: 'var(--text-hi)',
|
|
fontSize: 20,
|
|
background: 'var(--bg-panel)',
|
|
borderRadius: '50%',
|
|
width: 28,
|
|
height: 28,
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
}}
|
|
>
|
|
✕
|
|
</button>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</>
|
|
);
|
|
}
|