311 lines
16 KiB
Plaintext
311 lines
16 KiB
Plaintext
---
|
||
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>
|
||
/
|
||
<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>
|