Commit 9291a1fc by PLN (Algolia)

feat(Parvagues): iteration

parent 2bdc2a1e
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
"prismjs": "^1.30.0", "prismjs": "^1.30.0",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-icons": "^5.5.0",
"react-instantsearch": "^7.15.7", "react-instantsearch": "^7.15.7",
"react-instantsearch-dom": "^6.40.4", "react-instantsearch-dom": "^6.40.4",
"react-masonry-css": "^1.0.16", "react-masonry-css": "^1.0.16",
......
...@@ -3,14 +3,29 @@ import { getAllLives, getLiveData, getLivesImages } from '../../../lib/livesData ...@@ -3,14 +3,29 @@ import { getAllLives, getLiveData, getLivesImages } from '../../../lib/livesData
import ImageGallery from '../../../components/ImageGallery'; import ImageGallery from '../../../components/ImageGallery';
import Head from 'next/head'; import Head from 'next/head';
import Link from 'next/link'; import Link from 'next/link';
import Image from 'next/image';
import { marked } from 'marked'; import { marked } from 'marked';
import Prism from 'prismjs'; import Prism from 'prismjs';
import 'prismjs/components/prism-haskell'; import 'prismjs/components/prism-haskell';
import 'prismjs/themes/prism-tomorrow.css'; import styles from '../../../styles/parvagues.module.css';
export default function Live({ data, slug, images }) { export default function Live({ data, slug, images }) {
const [timeToEvent, setTimeToEvent] = useState(null); const [timeToEvent, setTimeToEvent] = useState(null);
const [currentTeasing, setCurrentTeasing] = useState(null); const [currentTeasing, setCurrentTeasing] = useState(null);
const [posterImage, setPosterImage] = useState(null);
const [mainColor, setMainColor] = useState('#a855f7');
// Find poster image
useEffect(() => {
if (images && images.length > 0) {
const poster = images.find(img => img.includes('poster.'));
if (poster) {
setPosterImage(poster);
// Here you could use a color extraction library like 'color-thief' to get dominant color
// For now, using default purple
}
}
}, [images]);
useEffect(() => { useEffect(() => {
if (typeof window !== 'undefined') { if (typeof window !== 'undefined') {
...@@ -60,28 +75,58 @@ export default function Live({ data, slug, images }) { ...@@ -60,28 +75,58 @@ export default function Live({ data, slug, images }) {
<meta name="description" content={data.frontmatter.description} /> <meta name="description" content={data.frontmatter.description} />
</Head> </Head>
<div className="min-h-screen bg-gradient-to-br from-gray-900 via-purple-900 to-gray-900 text-white"> <div
<nav className="sticky top-0 bg-black/50 backdrop-blur-sm border-b border-purple-500/20"> className="min-h-screen text-white relative overflow-hidden"
style={{
background: `radial-gradient(circle at 50% 0%, ${mainColor}20 0%, #000 60%)`
}}
>
{/* Gradient overlay */}
<div className="fixed inset-0" style={{
background: `linear-gradient(135deg, #000 0%, ${mainColor}10 50%, #000 100%)`
}} />
<div className="relative z-10">
<nav className="sticky top-0 bg-black/60 backdrop-blur-md border-b border-purple-500/20">
<div className="max-w-6xl mx-auto px-4 py-4"> <div className="max-w-6xl mx-auto px-4 py-4">
<Link href="/parvagues" className="text-purple-400 hover:text-purple-300 transition-colors"> <Link href="/parvagues" className="text-purple-400 hover:text-purple-300 transition-colors">
Retour ParVagues ParVagues
</Link> </Link>
</div> </div>
</nav> </nav>
<main className="max-w-6xl mx-auto px-4 py-8"> <main className="max-w-6xl mx-auto px-4 py-8">
<div className="mb-8"> {/* Visible Poster Section */}
<h1 className="text-4xl font-bold mb-2 bg-gradient-to-r from-purple-400 to-pink-600 bg-clip-text text-transparent"> {posterImage && (
<div className="max-w-2xl mx-auto mb-8">
<div className="relative w-full aspect-[3/4] rounded-lg overflow-hidden shadow-xl shadow-purple-500/20">
<Image
src={posterImage}
alt={data.frontmatter.title}
fill
className="object-cover"
/>
</div>
</div>
)}
<div className="mb-8 text-center">
<h1 className="text-4xl font-bold mb-2">
<span className={`bg-gradient-to-r from-purple-400 via-pink-500 to-purple-600 bg-clip-text text-transparent ${styles.glitchEffect}`}>
{data.frontmatter.title} {data.frontmatter.title}
</span>
</h1> </h1>
<p className="text-gray-400">{data.frontmatter.location} - {data.frontmatter.date}</p> <p className="text-gray-400">{data.frontmatter.location} {data.frontmatter.date}</p>
{data.frontmatter.time && (
<p className="text-gray-500 text-sm">{data.frontmatter.time}</p>
)}
</div> </div>
{timeToEvent !== null && timeToEvent >= 0 ? ( {timeToEvent !== null && timeToEvent >= 0 ? (
// Pre-event view // Pre-event view
<div className="space-y-8"> <div className="space-y-8">
<div className="text-center"> <div className="text-center">
<div className="inline-block bg-gradient-to-r from-purple-500 to-pink-500 p-8 rounded-lg"> <div className="inline-block bg-gradient-to-r from-purple-500 to-pink-500 p-8 rounded-lg shadow-lg shadow-purple-500/20">
<div className="text-6xl font-mono mb-2">{timeToEvent}</div> <div className="text-6xl font-mono mb-2">{timeToEvent}</div>
<div className="text-gray-200">jours restants</div> <div className="text-gray-200">jours restants</div>
</div> </div>
...@@ -92,9 +137,9 @@ export default function Live({ data, slug, images }) { ...@@ -92,9 +137,9 @@ export default function Live({ data, slug, images }) {
</div> </div>
{currentTeasing && ( {currentTeasing && (
<div className="bg-gray-800/50 backdrop-blur-sm rounded-lg p-6 border border-purple-500/20"> <div className="bg-black/40 backdrop-blur-sm rounded-lg p-6 border border-purple-500/20">
<div <div
className="prose prose-purple prose-invert prose-pre:bg-gray-900 prose-pre:border prose-pre:border-purple-500/20 max-w-none" className="prose prose-purple prose-invert prose-pre:bg-gray-900/50 prose-pre:border prose-pre:border-purple-500/20 max-w-none"
dangerouslySetInnerHTML={renderMarkdown(currentTeasing)} dangerouslySetInnerHTML={renderMarkdown(currentTeasing)}
/> />
</div> </div>
...@@ -104,7 +149,7 @@ export default function Live({ data, slug, images }) { ...@@ -104,7 +149,7 @@ export default function Live({ data, slug, images }) {
<div className="text-center"> <div className="text-center">
<a <a
href={data.frontmatter.ctaURL} href={data.frontmatter.ctaURL}
className="inline-block bg-gradient-to-r from-purple-500 to-pink-500 text-white px-8 py-3 rounded-lg font-semibold hover:from-purple-600 hover:to-pink-600 transition-all transform hover:scale-105" className="inline-block bg-gradient-to-r from-purple-500 to-pink-500 text-white px-8 py-3 rounded-lg font-semibold hover:from-purple-600 hover:to-pink-600 transition-all transform hover:scale-105 shadow-lg shadow-purple-500/20"
> >
{data.frontmatter.ctaText || data.frontmatter.title} {data.frontmatter.ctaText || data.frontmatter.title}
</a> </a>
...@@ -121,13 +166,13 @@ export default function Live({ data, slug, images }) { ...@@ -121,13 +166,13 @@ export default function Live({ data, slug, images }) {
{(data.frontmatter.video || data.frontmatter.audio) && ( {(data.frontmatter.video || data.frontmatter.audio) && (
<div className="grid md:grid-cols-2 gap-6"> <div className="grid md:grid-cols-2 gap-6">
{data.frontmatter.video && ( {data.frontmatter.video && (
<a href={data.frontmatter.video} className="block bg-gray-800/50 backdrop-blur-sm rounded-lg p-6 border border-purple-500/20 hover:border-purple-400 transition-colors"> <a href={data.frontmatter.video} className="block bg-black/40 backdrop-blur-sm rounded-lg p-6 border border-purple-500/20 hover:border-purple-400 transition-colors">
<h3 className="text-xl font-semibold mb-2">📹 Vidéo</h3> <h3 className="text-xl font-semibold mb-2">📹 Vidéo</h3>
<p className="text-gray-400">Regarder la session</p> <p className="text-gray-400">Regarder la session</p>
</a> </a>
)} )}
{data.frontmatter.audio && ( {data.frontmatter.audio && (
<a href={data.frontmatter.audio} className="block bg-gray-800/50 backdrop-blur-sm rounded-lg p-6 border border-purple-500/20 hover:border-purple-400 transition-colors"> <a href={data.frontmatter.audio} className="block bg-black/40 backdrop-blur-sm rounded-lg p-6 border border-purple-500/20 hover:border-purple-400 transition-colors">
<h3 className="text-xl font-semibold mb-2">🎵 Audio</h3> <h3 className="text-xl font-semibold mb-2">🎵 Audio</h3>
<p className="text-gray-400">Écouter l'enregistrement</p> <p className="text-gray-400">Écouter l'enregistrement</p>
</a> </a>
...@@ -140,15 +185,15 @@ export default function Live({ data, slug, images }) { ...@@ -140,15 +185,15 @@ export default function Live({ data, slug, images }) {
)} )}
<details className="group"> <details className="group">
<summary className="cursor-pointer p-4 bg-gray-800/30 rounded-lg hover:bg-gray-800/50 transition-colors"> <summary className="cursor-pointer p-4 bg-black/30 rounded-lg hover:bg-black/50 transition-colors border border-purple-500/10">
<span className="font-mono text-purple-400">// decrypt teasings</span> <span className="font-mono text-purple-400">// decrypt teasings</span>
</summary> </summary>
<div className="mt-4 space-y-4 pl-4 border-l-2 border-purple-500/20"> <div className="mt-4 space-y-4 pl-4 border-l-2 border-purple-500/20">
{[data.frontmatter.teasing1, data.frontmatter.teasing2, data.frontmatter.teasing3].map((teasing, i) => {[data.frontmatter.teasing1, data.frontmatter.teasing2, data.frontmatter.teasing3].map((teasing, i) =>
teasing && ( teasing && (
<div key={i} className="bg-gray-800/20 rounded p-4"> <div key={i} className="bg-black/20 rounded p-4">
<div <div
className="prose prose-purple prose-invert prose-pre:bg-gray-900 prose-pre:border prose-pre:border-purple-500/20 max-w-none text-sm" className="prose prose-purple prose-invert prose-pre:bg-gray-900/50 prose-pre:border prose-pre:border-purple-500/20 max-w-none text-sm"
dangerouslySetInnerHTML={renderMarkdown(teasing)} dangerouslySetInnerHTML={renderMarkdown(teasing)}
/> />
</div> </div>
...@@ -160,6 +205,7 @@ export default function Live({ data, slug, images }) { ...@@ -160,6 +205,7 @@ export default function Live({ data, slug, images }) {
)} )}
</main> </main>
</div> </div>
</div>
</> </>
); );
} }
......
/* ParVagues specific styles */
.heroSection {
min-height: 100vh;
position: relative;
overflow: hidden;
}
.bgImage {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
opacity: 0.4;
filter: blur(8px);
transform: scale(1.1);
}
.contentOverlay {
position: relative;
z-index: 10;
min-height: 100vh;
background: linear-gradient(135deg, rgba(9,9,11,0.95) 0%, rgba(88,28,135,0.9) 50%, rgba(9,9,11,0.95) 100%);
}
.heroContent {
padding: 0 1rem;
max-width: 1400px;
margin: 0 auto;
width: 100%;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: space-between;
gap: 4rem;
}
@media (max-width: 768px) {
.heroContent {
flex-direction: column;
justify-content: center;
gap: 2rem;
}
}
.heroTitle {
font-size: clamp(4rem, 12vw, 9rem);
font-weight: 800;
margin-bottom: 1rem;
background: linear-gradient(45deg, #a855f7, #ec4899, #8b5cf6);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
line-height: 0.9;
letter-spacing: -0.05em;
}
.heroSubtitle {
font-size: clamp(1.125rem, 3vw, 1.5rem);
color: rgba(255, 255, 255, 0.8);
max-width: 600px;
line-height: 1.5;
margin-bottom: 3rem;
}
.ctaButton {
position: fixed;
top: 1.5rem;
right: 1.5rem;
z-index: 50;
background: rgba(0, 0, 0, 0.6);
backdrop-filter: blur(8px);
border: 1px solid rgba(168, 85, 247, 0.3);
padding: 0.75rem 1.5rem;
border-radius: 0.5rem;
color: #a855f7;
transition: all 0.3s ease;
text-decoration: none;
font-weight: 500;
}
.ctaButton:hover {
background: rgba(168, 85, 247, 0.1);
border-color: #a855f7;
color: #ec4899;
}
.plungeButton {
display: inline-flex;
align-items: center;
background: linear-gradient(45deg, #a855f7, #ec4899);
color: white;
padding: 1rem 2rem;
border-radius: 0.5rem;
font-weight: 600;
text-decoration: none;
transition: all 0.3s ease;
gap: 0.5rem;
}
.plungeButton:hover {
transform: translateY(-2px);
box-shadow: 0 10px 20px rgba(168, 85, 247, 0.3);
}
.sectionContainer {
padding: 5rem 1rem;
max-width: 1200px;
margin: 0 auto;
width: 100%;
}
.splitSection {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 4rem;
align-items: center;
}
@media (max-width: 768px) {
.splitSection {
grid-template-columns: 1fr;
gap: 2rem;
}
}
.bulletPoint {
margin-bottom: 1.5rem;
padding-left: 2rem;
position: relative;
}
.bulletPoint::before {
content: "→";
position: absolute;
left: 0;
color: #a855f7;
font-weight: bold;
}
.codeContainer {
background: rgba(0, 0, 0, 0.7);
border: 1px solid rgba(168, 85, 247, 0.2);
border-radius: 0.5rem;
overflow: hidden;
position: relative;
}
.terminalContainer {
background: #1e1e1e;
border: 1px solid #333;
border-radius: 0.5rem;
overflow: hidden;
}
.terminalHeader {
background: #363636;
padding: 0.5rem 1rem;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 1px solid #444;
}
.terminalControls {
display: flex;
gap: 0.5rem;
}
.redCircle, .yellowCircle, .greenCircle {
width: 12px;
height: 12px;
border-radius: 50%;
}
.redCircle {
background: #ff5f56;
}
.yellowCircle {
background: #ffbd2e;
}
.greenCircle {
background: #27ca42;
}
.terminalTitle {
font-family: monospace;
font-size: 0.875rem;
color: #ddd;
}
.terminalContainer pre {
background: #1e1e1e;
color: #f8f8f2;
padding: 1rem;
margin: 0;
font-family: 'Menlo', 'Monaco', 'Courier New', monospace;
font-size: 0.875rem;
line-height: 1.5;
}
.codeContainer pre {
max-height: inherit;
overflow-y: auto;
margin: 0;
padding: 1rem;
}
.codeContainer::-webkit-scrollbar,
.terminalContainer pre::-webkit-scrollbar {
width: 6px;
}
.codeContainer::-webkit-scrollbar-track,
.terminalContainer pre::-webkit-scrollbar-track {
background: rgba(0, 0, 0, 0.3);
}
.codeContainer::-webkit-scrollbar-thumb,
.terminalContainer pre::-webkit-scrollbar-thumb {
background: #a855f7;
border-radius: 3px;
}
.albumGrid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 2rem;
margin-top: 3rem;
}
.albumCard {
background: rgba(0, 0, 0, 0.4);
border: 1px solid rgba(168, 85, 247, 0.2);
border-radius: 0.5rem;
padding: 1.5rem;
transition: all 0.3s ease;
}
.albumCard:hover {
background: rgba(168, 85, 247, 0.05);
border-color: #a855f7;
transform: translateY(-2px);
}
.playerContainer {
margin-top: 1rem;
display: grid;
gap: 0.5rem;
}
.playerButton {
display: inline-flex;
align-items: center;
gap: 0.5rem;
color: rgba(255, 255, 255, 0.8);
text-decoration: none;
padding: 0.5rem 0.75rem;
transition: all 0.3s ease;
font-size: 0.875rem;
border-radius: 0.25rem;
background: rgba(168, 85, 247, 0.1);
border: 1px solid rgba(168, 85, 247, 0.2);
}
.playerButton:hover {
color: #a855f7;
background: rgba(168, 85, 247, 0.2);
border-color: #a855f7;
transform: translateY(-1px);
}
.socialLinks {
display: flex;
flex-wrap: wrap;
gap: 1rem;
justify-content: center;
margin-top: 2rem;
}
.socialLink {
color: rgba(255, 255, 255, 0.6);
text-decoration: none;
transition: all 0.3s ease;
padding: 0.75rem 1.5rem;
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 0.5rem;
display: inline-flex;
align-items: center;
gap: 0.5rem;
background: rgba(0, 0, 0, 0.3);
}
.socialLink:hover {
color: #a855f7;
border-color: #a855f7;
background: rgba(168, 85, 247, 0.05);
transform: translateY(-2px);
}
.bulletPoint.cursor-pointer:hover {
background: rgba(168, 85, 247, 0.05);
border-radius: 0.5rem;
}
.footer {
text-align: center;
padding: 2rem;
border-top: 1px solid rgba(168, 85, 247, 0.1);
background: rgba(0, 0, 0, 0.5);
}
.posterCollage {
position: absolute;
inset: 0;
opacity: 0.6;
filter: blur(4px);
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(3, 1fr);
gap: 0.5rem;
}
.posterImage {
width: 100%;
height: 100%;
object-fit: cover;
opacity: 0.7;
}
.glitchEffect {
animation: glitch 8s linear infinite;
}
@keyframes glitch {
0% {
filter: none;
}
2% {
filter: hue-rotate(90deg);
}
3% {
filter: none;
}
4% {
clip-path: polygon(0 0, 100% 0, 100% 35%, 0 35%);
transform: translateX(-2px);
}
5% {
transform: translateX(0);
clip-path: none;
}
97% {
filter: none;
}
98% {
filter: invert(0.1);
}
99% {
filter: none;
}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment