rebours/src/pages/index.astro
2026-04-11 17:42:39 +02:00

311 lines
16 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
import Base from '../layouts/Base.astro';
import { getPublishedProducts, getHomePage, urlFor } from '../lib/sanity.mjs';
const [products, home] = await Promise.all([getPublishedProducts(), getHomePage()]);
const heroImg = home?.heroImage
? urlFor(home.heroImage).width(1024).url()
: products[0]?.images?.[0]
? urlFor(products[0].images[0]).width(1024).url()
: '/assets/table-terrazzo.jpg';
const heroImgAlt = home?.heroImageAlt || 'REBOURS — Mobilier d\'art contemporain, Paris 2026';
const heroLabel = home?.heroLabel || '// ARCHIVE_001 — 2026';
const heroTitleParts = (home?.heroTitle || 'REBOURS|STUDIO').split('|');
const heroSubtitle = home?.heroSubtitle || 'Mobilier d\'art contemporain.\nSpace Age × Memphis.';
const heroStatus = home?.heroStatus || 'STATUS: [PROTOTYPE EN COURS]\nCOLLECTION_001 — BIENTÔT DISPONIBLE';
const collectionLabel = home?.collectionLabel || '// COLLECTION_001';
const collectionCta = home?.collectionCta || 'CLIQUER POUR OUVRIR';
const contactLabel = home?.contactLabel || '// CONTACT';
const contactTitleParts = (home?.contactTitle || 'UNE QUESTION ?|PARLONS-EN').split('|');
const contactDesc = home?.contactDescription || 'Commandes sur mesure, questions techniques,\nou simplement dire bonjour.';
const whatsappNumber = home?.whatsappNumber || '33651755191';
const whatsappBtnText = home?.whatsappButtonText || 'CONTACTEZ-NOUS SUR WHATSAPP';
const contactResponseTime = home?.contactResponseTime || 'RÉPONSE SOUS 24H';
const footerText = home?.footerText || '© 2026 REBOURS STUDIO — PARIS';
const instagramUrl = home?.instagramUrl || 'https://instagram.com/rebour.studio';
const seoTitle = home?.seoTitle || 'REBOURS — Mobilier d\'art contemporain | Collection 001';
const seoDesc = home?.seoDescription || 'REBOURS Studio crée du mobilier d\'art contemporain inspiré du Space Age et du mouvement Memphis. Pièces uniques fabriquées à Paris. Collection 001 en cours.';
const firstImage = heroImg;
const schemaOrg = {
"@context": "https://schema.org",
"@type": "Store",
"name": "REBOURS Studio",
"description": "Mobilier d'art contemporain. Space Age × Memphis. Pièces uniques fabriquées à Paris.",
"url": "https://rebours.studio/",
"image": firstImage,
"address": { "@type": "PostalAddress", "addressLocality": "Paris", "addressCountry": "FR" },
"hasOfferCatalog": {
"@type": "OfferCatalog",
"name": "Collection 001",
"itemListElement": products.filter(p => p.price).map(p => ({
"@type": "Offer",
"itemOffered": {
"@type": "Product",
"name": p.productDisplayName,
"description": p.seoDescription || p.description?.substring(0, 155),
"image": p.images?.[0] ? urlFor(p.images[0]).width(1024).url() : undefined,
},
"price": String(p.price / 100),
"priceCurrency": p.currency || 'EUR',
"availability": p.availability,
})),
}
};
---
<Base
title={seoTitle}
description={seoDesc}
canonical="https://rebours.studio/"
>
<Fragment slot="head">
<script type="application/ld+json" set:html={JSON.stringify(schemaOrg)} />
</Fragment>
<!-- Grid background -->
<div id="interactive-grid" class="interactive-grid"></div>
<!-- PRODUCT PANEL (overlay) -->
<div id="product-panel" class="product-panel" aria-hidden="true">
<div class="panel-close" id="panel-close">
<span>← RETOUR</span>
</div>
<div class="panel-inner">
<div class="panel-img-col">
<div class="panel-gallery" id="panel-gallery">
<img id="panel-img" src="" alt="Image produit REBOURS Studio">
</div>
<div class="panel-gallery-nav" id="panel-gallery-nav"></div>
</div>
<div class="panel-info-col">
<p class="panel-index" id="panel-index"></p>
<h2 id="panel-name"></h2>
<hr>
<div class="panel-meta">
<div class="panel-meta-row">
<span class="meta-key">TYPE</span>
<span id="panel-type"></span>
</div>
<div class="panel-meta-row">
<span class="meta-key">MATÉRIAUX</span>
<span id="panel-mat"></span>
</div>
<div class="panel-meta-row">
<span class="meta-key">ANNÉE</span>
<span id="panel-year"></span>
</div>
<div class="panel-meta-row">
<span class="meta-key">STATUS</span>
<span id="panel-status" class="red"></span>
</div>
</div>
<hr>
<p id="panel-desc" class="panel-desc"></p>
<hr>
<details class="accordion" open>
<summary>SPÉCIFICATIONS TECHNIQUES <span>↓</span></summary>
<div class="accordion-body" id="panel-specs"></div>
</details>
<details class="accordion" open>
<summary>NOTES DE CONCEPTION <span>↓</span></summary>
<div class="accordion-body" id="panel-notes"></div>
</details>
<hr>
<div id="checkout-section" style="display:none;">
<div class="checkout-price-line">
<span class="checkout-price"></span>
<span class="checkout-edition">ÉDITION UNIQUE — 1/1</span>
</div>
<button id="checkout-toggle-btn" class="checkout-btn">
[ COMMANDER CETTE PIÈCE ]
</button>
<div id="checkout-form-wrap" class="checkout-form-wrap" style="display:none;">
<form id="checkout-form" class="checkout-form">
<div class="checkout-form-field">
<label for="checkout-email">EMAIL *</label>
<input type="email" id="checkout-email" name="email" placeholder="votre@email.com" required autocomplete="off">
</div>
<div class="checkout-form-note">
Pièce fabriquée à Paris. Délai : 6 à 8 semaines.<br>
Paiement sécurisé via Stripe.
</div>
<button type="submit" class="checkout-submit" id="checkout-submit-btn">
PROCÉDER AU PAIEMENT →
</button>
</form>
</div>
</div>
<div class="panel-footer">
<span class="blink">■</span> COLLECTION_001 — W.I.P
</div>
</div>
</div>
</div>
<div class="page-wrapper">
<header class="header">
<a href="/" class="logo-text" aria-label="REBOURS — Accueil">REBOURS</a>
<nav class="header-nav" aria-label="Navigation principale">
<a href="#collection">COLLECTION_001</a>
<a href="#" class="contact-trigger">CONTACT</a>
<span class="wip-tag"><span class="blink">■</span> W.I.P</span>
</nav>
</header>
<main>
<!-- HERO -->
<section class="hero" aria-label="Introduction">
<div class="hero-left">
<p class="label">{heroLabel}</p>
<h1>{heroTitleParts.map((part, i) => <>{i > 0 && <br/>}{part}</>)}</h1>
<p class="hero-sub" set:html={heroSubtitle.replace(/\n/g, '<br>')} />
<p class="hero-sub mono-sm" set:html={heroStatus.replace(/\n/g, '<br>')} />
</div>
<div class="hero-right">
<img
src={heroImg}
alt={heroImgAlt}
class="hero-img"
width="1024" height="1024"
fetchpriority="high">
</div>
</section>
<hr>
<!-- COLLECTION GRID -->
<section class="collection" id="collection" aria-label="Collection 001">
<div class="collection-header">
<p class="label">{collectionLabel}</p>
<span class="label">{products.length} OBJETS — {collectionCta}</span>
</div>
<div class="product-grid">
{products.map((p, i) => {
const mainImg = p.images?.[0];
const imgUrl = mainImg ? urlFor(mainImg).width(800).url() : '';
const alt = p.imageAlt || `${p.productDisplayName} — mobilier d'art contemporain, REBOURS Studio Paris`;
const allImgs = (p.images || []).map(img => ({
url: urlFor(img).width(1200).url(),
alt: img.alt || alt,
}));
return (
<article class="product-card"
data-index={p.index}
data-name={p.name}
data-type={p.type}
data-mat={p.materials}
data-year={p.year}
data-status={p.status}
data-desc={p.description}
data-specs={p.specs || ''}
data-notes={p.notes || ''}
data-img={mainImg ? urlFor(mainImg).width(1200).url() : ''}
data-images={JSON.stringify(allImgs)}
data-price={p.price ? String(p.price) : ''}
data-slug={p.slug}
data-img-alt={alt}
aria-label={`Ouvrir le détail de ${p.productDisplayName}`}>
<div class="card-img-wrap">
<img src={imgUrl}
alt={alt}
width="600" height="600"
loading={i === 0 ? "eager" : "lazy"}>
</div>
<div class="card-meta">
<span class="card-index">{String(i + 1).padStart(3, '0')}</span>
<span class="card-name">{p.name}</span>
<span class="card-arrow">↗</span>
</div>
</article>
);
})}
</div>
</section>
<!-- CONTACT WHATSAPP -->
<section class="newsletter" id="contact" aria-label="Contact WhatsApp">
<div class="nl-left">
<p class="label">{contactLabel}</p>
<h2>{contactTitleParts.map((part, i) => <>{i > 0 && <br/>}{part}</>)}</h2>
</div>
<div class="nl-right">
<div class="nl-form" style="pointer-events: auto;">
<p class="mono-sm" style="line-height: 1.9; margin-bottom: 0.5rem;" set:html={contactDesc.replace(/\n/g, '<br>')} />
<a href={`https://wa.me/${whatsappNumber}`} target="_blank" rel="noopener" class="whatsapp-btn" aria-label="Nous contacter sur WhatsApp">
<svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor" style="flex-shrink:0;">
<path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413z"/>
</svg>
{whatsappBtnText}
</a>
<p class="mono-sm"><span class="blink">■</span> {contactResponseTime}</p>
</div>
</div>
</section>
</main>
<footer class="footer">
<span>{footerText}</span>
<nav aria-label="Liens secondaires">
<a href={instagramUrl} rel="noopener" target="_blank">INSTAGRAM</a>
&nbsp;/&nbsp;
<a href="#" class="contact-trigger">CONTACT</a>
</nav>
</footer>
</div>
<!-- CONTACT MODAL -->
<div id="contact-modal" class="contact-modal" aria-hidden="true" data-whatsapp={whatsappNumber}>
<div class="contact-modal-backdrop"></div>
<div class="contact-modal-content">
<div class="contact-modal-header">
<p class="label">// CONTACT</p>
<button class="contact-modal-close" aria-label="Fermer">✕</button>
</div>
<hr>
<h2 class="contact-modal-title">ENVOYER<br>UN MESSAGE</h2>
<form id="contact-form" class="contact-form">
<div class="contact-field">
<label for="contact-name">NOM *</label>
<input type="text" id="contact-name" name="name" placeholder="Votre nom" required autocomplete="name">
</div>
<div class="contact-field">
<label for="contact-email">EMAIL *</label>
<input type="email" id="contact-email" name="email" placeholder="votre@email.com" required autocomplete="email">
</div>
<div class="contact-field">
<label for="contact-subject">OBJET</label>
<input type="text" id="contact-subject" name="subject" placeholder="Objet du message" autocomplete="off">
</div>
<div class="contact-field">
<label for="contact-message">MESSAGE *</label>
<textarea id="contact-message" name="message" rows="5" placeholder="Votre message..." required></textarea>
</div>
<button type="submit" class="contact-submit">
ENVOYER LE MESSAGE →
</button>
<p class="mono-sm contact-note"><span class="blink">■</span> REDIRECTION VERS WHATSAPP</p>
</form>
</div>
</div>
<div class="cursor-dot"></div>
<div class="cursor-outline"></div>
</Base>