258 lines
8.4 KiB
JavaScript
258 lines
8.4 KiB
JavaScript
import { useMemo, useState } from "react";
|
||
import { Link, useNavigate, useParams } from "react-router";
|
||
import perfumes from "../data/perfumes";
|
||
import "../style/navbar.css";
|
||
import "./ProductDetailPage.css";
|
||
|
||
function ProductDetailContent({ perfumeSlug }) {
|
||
const navigate = useNavigate();
|
||
|
||
const perfume = useMemo(
|
||
() => perfumes.find((item) => item.slug === perfumeSlug) || perfumes[0],
|
||
[perfumeSlug]
|
||
);
|
||
|
||
const [selectedImage, setSelectedImage] = useState(
|
||
perfume.gallery?.[0] || perfume.image
|
||
);
|
||
const [selectedSize, setSelectedSize] = useState("sample");
|
||
|
||
const sizeOptions = [
|
||
{
|
||
key: "sample",
|
||
title: "Sample 2ml",
|
||
price: perfume.prices.sample,
|
||
note: "Zum Testen · ca. 20 Anwendungen",
|
||
},
|
||
{
|
||
key: "full",
|
||
title: "Full Size 50ml",
|
||
price: perfume.prices.full,
|
||
note: "Nachkauf · 500+ Anwendungen",
|
||
},
|
||
];
|
||
|
||
return (
|
||
<div className="detail-page">
|
||
<nav className="navbar navbar--light">
|
||
<div className="nav-pill">
|
||
<Link to="/" className="nav-link">
|
||
Name
|
||
</Link>
|
||
<Link to="/#dufte" className="nav-link active">
|
||
Düfte
|
||
</Link>
|
||
<Link to="/#testen" className="nav-link">
|
||
Testen
|
||
</Link>
|
||
<a href="#cart" className="nav-link">
|
||
Cart
|
||
</a>
|
||
</div>
|
||
</nav>
|
||
|
||
<main className="detail-shell">
|
||
<button className="back-link" type="button" onClick={() => navigate("/")}>
|
||
← Zurück zur Startseite
|
||
</button>
|
||
|
||
<section className="detail-layout">
|
||
<div className="detail-gallery">
|
||
<div className="detail-main-image">
|
||
<img src={selectedImage} alt={perfume.name} />
|
||
</div>
|
||
|
||
<div className="detail-thumbs">
|
||
{[perfume.image, ...(perfume.gallery || [])]
|
||
.slice(0, 3)
|
||
.map((img, index) => (
|
||
<button
|
||
key={`${img}-${index}`}
|
||
type="button"
|
||
className={`thumb-btn ${selectedImage === img ? "active" : ""}`}
|
||
onClick={() => setSelectedImage(img)}
|
||
>
|
||
<img src={img} alt={`${perfume.name} Ansicht ${index + 1}`} />
|
||
</button>
|
||
))}
|
||
</div>
|
||
|
||
<div className="detail-structure">
|
||
<h3>DUFTSTRUKTUR</h3>
|
||
|
||
<div className="structure-block">
|
||
<span className="structure-phase">PHASE 1: TOP NOTES (0–1 H)</span>
|
||
<div className="material-tags">
|
||
{perfume.phases.top.map((note) => (
|
||
<span key={note}>{note}</span>
|
||
))}
|
||
</div>
|
||
</div>
|
||
|
||
<div className="structure-block">
|
||
<span className="structure-phase">PHASE 2: HEART NOTES (1–4 H)</span>
|
||
<div className="material-tags">
|
||
{perfume.phases.heart.map((note) => (
|
||
<span key={note}>{note}</span>
|
||
))}
|
||
</div>
|
||
</div>
|
||
|
||
<div className="structure-block">
|
||
<span className="structure-phase">PHASE 3: BASE NOTES (4 H+)</span>
|
||
<div className="material-tags">
|
||
{perfume.phases.base.map((note) => (
|
||
<span key={note}>{note}</span>
|
||
))}
|
||
</div>
|
||
</div>
|
||
|
||
<div className="mood-box">
|
||
<span className="mood-label">MOODSETTING</span>
|
||
<p>{perfume.mood}</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="detail-meta-grid">
|
||
<div>
|
||
<span>TRAGEHINWEIS</span>
|
||
<p>{perfume.dosage}</p>
|
||
</div>
|
||
|
||
<div>
|
||
<span>HALTBARKEIT</span>
|
||
<p>{perfume.longevity}</p>
|
||
</div>
|
||
|
||
<div>
|
||
<span>ANLASS</span>
|
||
<p>{perfume.occasion}</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="detail-info">
|
||
<div className="detail-heading">
|
||
<h1>{perfume.name}</h1>
|
||
<p>{perfume.shortText}</p>
|
||
</div>
|
||
|
||
<div className="detail-section-block">
|
||
<span className="label-title">MATERIAL-KOMPOSITION</span>
|
||
<div className="material-tags">
|
||
{perfume.materialTags.map((tag) => (
|
||
<span key={tag}>{tag}</span>
|
||
))}
|
||
</div>
|
||
</div>
|
||
|
||
<div className="detail-section-block">
|
||
<span className="label-title">GRÖSSE WÄHLEN</span>
|
||
<div className="size-grid">
|
||
{sizeOptions.map((option) => (
|
||
<button
|
||
key={option.key}
|
||
type="button"
|
||
className={`size-card ${selectedSize === option.key ? "active" : ""}`}
|
||
onClick={() => setSelectedSize(option.key)}
|
||
>
|
||
<span className="size-title">{option.title}</span>
|
||
<strong>{option.price}</strong>
|
||
<small>{option.note}</small>
|
||
</button>
|
||
))}
|
||
</div>
|
||
</div>
|
||
|
||
<div className="discovery-note">
|
||
<div className="discovery-note-text">
|
||
<strong>Discovery Set wird angerechnet</strong>
|
||
<p>
|
||
Hast du das Discovery Set gekauft, wird der volle Preis beim Kauf
|
||
automatisch abgezogen.
|
||
</p>
|
||
</div>
|
||
|
||
<button className="discovery-note-btn" type="button">
|
||
Zum Set
|
||
</button>
|
||
</div>
|
||
|
||
<button className="buy-button" type="button">
|
||
KAUFEN
|
||
</button>
|
||
|
||
<div className="detail-columns">
|
||
<div className="detail-copy-block">
|
||
<span className="label-title">BESCHREIBUNG</span>
|
||
<p>{perfume.description}</p>
|
||
</div>
|
||
|
||
<div className="detail-copy-block">
|
||
<span className="label-title">HERKUNFT</span>
|
||
<p>{perfume.origin}</p>
|
||
</div>
|
||
|
||
<div className="detail-copy-block">
|
||
<span className="label-title">KONZENTRATION</span>
|
||
<p>{perfume.concentration}</p>
|
||
</div>
|
||
|
||
<div className="detail-copy-block">
|
||
<span className="label-title">EDITION</span>
|
||
<p>{perfume.edition}</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="delivery-box">
|
||
<div className="delivery-box-header">
|
||
<span className="label-title">LIEFERUNG</span>
|
||
<span className="delivery-badge">CH</span>
|
||
</div>
|
||
|
||
<div className="delivery-grid">
|
||
<div className="delivery-item">
|
||
<span className="delivery-item-label">VERSAND</span>
|
||
<p>Innerhalb von 1–2 Werktagen</p>
|
||
</div>
|
||
|
||
<div className="delivery-item">
|
||
<span className="delivery-item-label">ZUSTELLUNG</span>
|
||
<p>In der Regel in 5–6 Tagen bei dir</p>
|
||
</div>
|
||
|
||
<div className="delivery-item delivery-item--full">
|
||
<span className="delivery-item-label">HINWEIS</span>
|
||
<p>Sorgfältig verpackt und geschützt versendet.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</section>
|
||
|
||
<section className="detail-bottom-cta">
|
||
<h2>Lieber erst testen?</h2>
|
||
<p>
|
||
Bestelle ein 2ml Sample für CHF 12 oder das komplette Discovery Set
|
||
mit allen 6 Düften für CHF 48. Beide werden beim späteren Full-Size-Kauf
|
||
vollständig angerechnet.
|
||
</p>
|
||
|
||
<div className="detail-bottom-actions">
|
||
<button type="button">SAMPLE BESTELLEN – CHF 12</button>
|
||
<button type="button">DISCOVERY SET – CHF 48</button>
|
||
</div>
|
||
</section>
|
||
</main>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
function ProductDetailPage() {
|
||
const { perfumeSlug = "kalter-beton" } = useParams();
|
||
|
||
return <ProductDetailContent key={perfumeSlug} perfumeSlug={perfumeSlug} />;
|
||
}
|
||
|
||
export default ProductDetailPage; |