Add detailed past event viewer
This commit is contained in:
1 parent
6ebd701721
commit
d7376c055c
2 files changed
+60
-17
No files matched your search
@@ -1,10 +1,12 @@
|
||||
import { useState } from 'react';
|
||||
import Carousel from './Carousel.jsx';
|
||||
import Modal from './Modal.jsx';
|
||||
|
||||
// Editorial card for one past event: text on the left, a 1-large-+-2-small
|
||||
// photo grid on the right. Clicking any photo (or "voir les N photos")
|
||||
// opens the full carousel with every photo.
|
||||
export default function PastEventCard({ event }) {
|
||||
// Editorial summary for one past event. The list keeps a controlled excerpt;
|
||||
// clicking the card opens the complete story and gallery, then a photo can be
|
||||
// enlarged in the full-screen carousel.
|
||||
export default function PastEventCard({ event, excerptLines = 2 }) {
|
||||
const [detailOpen, setDetailOpen] = useState(false);
|
||||
const [carouselAt, setCarouselAt] = useState(null); // null | index
|
||||
const photos = event.photos || [];
|
||||
const hasPhotos = photos.length > 0;
|
||||
@@ -14,8 +16,7 @@ export default function PastEventCard({ event }) {
|
||||
return (
|
||||
<div
|
||||
className={photo ? '' : 'placeholder-pattern'}
|
||||
style={{ borderRadius: 3, overflow: 'hidden', cursor: photo ? 'pointer' : 'default', ...extra }}
|
||||
onClick={photo ? (e) => { e.stopPropagation(); setCarouselAt(idx); } : undefined}
|
||||
style={{ borderRadius: 3, overflow: 'hidden', ...extra }}
|
||||
>
|
||||
{photo && <img src={photo.path} alt="" style={{ width: '100%', height: '100%', objectFit: 'cover' }} />}
|
||||
</div>
|
||||
@@ -26,23 +27,21 @@ export default function PastEventCard({ event }) {
|
||||
<>
|
||||
<article
|
||||
className="card hero-grid past-event-card"
|
||||
style={{ display: 'grid', gridTemplateColumns: '1.15fr .85fr', gap: 40, alignItems: 'center', padding: 36, cursor: hasPhotos ? 'pointer' : 'default' }}
|
||||
onClick={hasPhotos ? () => setCarouselAt(0) : undefined}
|
||||
style={{ display: 'grid', gridTemplateColumns: '1.15fr .85fr', gap: 40, alignItems: 'center', padding: 36, cursor: 'pointer' }}
|
||||
onClick={() => setDetailOpen(true)}
|
||||
>
|
||||
<div>
|
||||
<div style={{ fontSize: 12, letterSpacing: '.14em', textTransform: 'uppercase', color: 'var(--gray-light)', fontWeight: 600, marginBottom: 12 }}>
|
||||
{event.date_label} · {event.lieu}
|
||||
</div>
|
||||
<h3 className="serif" style={{ fontSize: 30, fontWeight: 600, lineHeight: 1.12, marginBottom: 16 }}>{event.titre}</h3>
|
||||
<p style={{ fontSize: 15.5, lineHeight: 1.7, color: 'var(--gray)', marginBottom: 20 }}>{event.texte}</p>
|
||||
<p style={{ fontSize: 15.5, lineHeight: 1.7, color: 'var(--gray)', marginBottom: 20, display: '-webkit-box', WebkitLineClamp: excerptLines, WebkitBoxOrient: 'vertical', overflow: 'hidden' }}>{event.texte}</p>
|
||||
<div style={{ display: 'flex', gap: 20, fontSize: 13, color: 'var(--gray-light)', alignItems: 'center', flexWrap: 'wrap' }}>
|
||||
<span>👥 {event.participants} participants</span>
|
||||
<span>📷 {event.nb_photos} photo{event.nb_photos > 1 ? 's' : ''}</span>
|
||||
{hasPhotos && (
|
||||
<button className="btn-link" style={{ fontSize: 13 }} onClick={(e) => { e.stopPropagation(); setCarouselAt(0); }}>
|
||||
Voir les photos →
|
||||
</button>
|
||||
)}
|
||||
<button className="btn-link" style={{ fontSize: 13 }} onClick={(e) => { e.stopPropagation(); setDetailOpen(true); }}>
|
||||
Voir la soirée →
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="past-event-photos" style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gridTemplateRows: '1fr 1fr', gap: 10, height: 240 }}>
|
||||
@@ -50,8 +49,7 @@ export default function PastEventCard({ event }) {
|
||||
{cell(1)}
|
||||
{photos.length > 3 ? (
|
||||
<div
|
||||
style={{ borderRadius: 3, overflow: 'hidden', cursor: 'pointer', position: 'relative' }}
|
||||
onClick={(e) => { e.stopPropagation(); setCarouselAt(2); }}
|
||||
style={{ borderRadius: 3, overflow: 'hidden', position: 'relative' }}
|
||||
>
|
||||
<img src={photos[2].path} alt="" style={{ width: '100%', height: '100%', objectFit: 'cover' }} />
|
||||
<div style={{ position: 'absolute', inset: 0, background: 'rgba(15,14,13,.55)', color: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center', fontFamily: "'Newsreader',serif", fontSize: 22, fontWeight: 600 }}>
|
||||
@@ -64,6 +62,51 @@ export default function PastEventCard({ event }) {
|
||||
</div>
|
||||
</article>
|
||||
|
||||
{detailOpen && (
|
||||
<Modal
|
||||
onClose={() => setDetailOpen(false)}
|
||||
maxWidth={920}
|
||||
header={{
|
||||
kicker: 'Rencontre passée',
|
||||
title: event.titre,
|
||||
meta: `${event.date_label} · ${event.lieu}`,
|
||||
}}
|
||||
>
|
||||
<div style={{ padding: '30px 32px 36px' }}>
|
||||
<div style={{ display: 'flex', gap: 22, flexWrap: 'wrap', fontSize: 13, color: 'var(--gray-light)', marginBottom: 22 }}>
|
||||
<span>👥 {event.participants} participants</span>
|
||||
<span>📷 {event.nb_photos} photo{event.nb_photos > 1 ? 's' : ''}</span>
|
||||
</div>
|
||||
<div style={{ fontSize: 16, lineHeight: 1.8, color: 'var(--gray)', whiteSpace: 'pre-line' }}>
|
||||
{event.texte}
|
||||
</div>
|
||||
|
||||
{hasPhotos ? (
|
||||
<div style={{ marginTop: 30 }}>
|
||||
<h4 className="serif" style={{ fontSize: 21, fontWeight: 600, marginBottom: 16 }}>Toutes les photos</h4>
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(150px, 1fr))', gap: 12 }}>
|
||||
{photos.map((photo, index) => (
|
||||
<button
|
||||
key={photo.id ?? index}
|
||||
type="button"
|
||||
onClick={() => setCarouselAt(index)}
|
||||
aria-label={`Ouvrir la photo ${index + 1}`}
|
||||
style={{ height: 140, padding: 0, border: 'none', borderRadius: 4, overflow: 'hidden', cursor: 'pointer', background: 'var(--beige)' }}
|
||||
>
|
||||
<img src={photo.path} alt="" style={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block' }} />
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<p style={{ marginTop: 26, padding: '16px 18px', background: 'var(--beige)', color: 'var(--gray-light)', fontSize: 13.5 }}>
|
||||
Aucune photo n'a encore été ajoutée à cette soirée.
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</Modal>
|
||||
)}
|
||||
|
||||
{carouselAt !== null && (
|
||||
<Carousel photos={photos} title={event.titre} startIndex={carouselAt} onClose={() => setCarouselAt(null)} />
|
||||
)}
|
||||
|
||||
@@ -364,7 +364,7 @@ export default function Home() {
|
||||
</div>
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 34 }}>
|
||||
{passees.slice(0, 3).map((p) => (
|
||||
<PastEventCard key={p.id} event={p} />
|
||||
<PastEventCard key={p.id} event={p} excerptLines={3} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in new issue
Block a user