ldc-ker-chant/resources/ts/front/Components/ValeursSection.tsx
2026-07-10 11:32:24 +02:00

350 lines
11 KiB
TypeScript
Raw Permalink 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 { useState, type ReactNode } from "react";
import bgSection from "&/images/global/paysage.png";
import bgSectionWebp from "&/images/global/paysage.webp";
// Icons
import ico1 from "&/images/icons/logo1.svg";
import ico2 from "&/images/icons/logo2.svg";
import ico3 from "&/images/icons/logo3.png";
import ico4 from "&/images/icons/logo4.svg";
import arrowRight from "&/images/icons/next_arrow.svg";
import arrowLeft from "&/images/icons/prev_arrow.svg";
import pinValeur from "&/images/icons/valeur-simplicite.svg";
// Images valeur
import img4 from "&/images/valeurs/FIABILITE ET SINCERITE.jpg";
import img4Webp from "&/images/valeurs/FIABILITE ET SINCERITE.webp";
import img3 from "&/images/valeurs/HUMILITE ET BIENVEILLANCE.jpg";
import img3Webp from "&/images/valeurs/HUMILITE ET BIENVEILLANCE.webp";
import img2 from "&/images/valeurs/PROXIMITE ET ENGAGEMENT.jpg";
import img2Webp from "&/images/valeurs/PROXIMITE ET ENGAGEMENT.webp";
import img1 from "&/images/valeurs/SIMPLICITÉ ET GÉNÉROSITÉ.jpg";
import img1Webp from "&/images/valeurs/SIMPLICITÉ ET GÉNÉROSITÉ.webp";
import VideoFrame from "./videoFrame";
interface Valeur {
id: string;
label: string;
icon: ImageValeur;
titre: string;
sousTitre: string;
image: ImageValeur;
contenu: ReactNode;
}
interface ImageValeur {
value: string;
webp?: string;
alt: string;
title: string;
}
const RED = "#E01B1B";
const VALEURS: Valeur[] = [
{
id: "simplicite",
label: "Simplicité et générosité",
icon: {
value: ico1,
alt: "Icône représentant la simplicité",
title: "Simplicité",
},
titre: "SIMPLICITÉ ET GÉNÉROSITÉ",
sousTitre: "Le goût des plaisirs vrais",
image: {
value: img1,
webp: img1Webp,
alt: "Poulet rôti accompagné de pommes de terre",
title: "Recette de poulet Ker Chant",
},
contenu: (
<>
<p>
Nous mettons en avant le meilleur de notre <strong>terroir</strong>{" "}
pour offrir des <strong>produits accessibles et gourmands.</strong>
</p>
<p>
Parce que la volaille est au <strong>cœur des repas</strong> qui{" "}
<strong>rassemblent</strong>, nous croyons aux{" "}
<strong>plaisirs simples</strong> et aux{" "}
<strong>moments partagés</strong>.
</p>
</>
),
},
{
id: "proximite",
label: "PROXIMITÉ ET ENGAGEMENT",
icon: {
value: ico2,
alt: "Icône représentant la proximité",
title: "Proximité",
},
titre: "PROXIMITÉ ET ENGAGEMENT",
sousTitre: "Une filière qui vit ici",
image: {
value: img2,
webp: img2Webp,
alt: "Paysage de champ avec paille",
title: "Champ éleveur Ker Chant",
},
contenu: (
<>
<p>
Nous sommes{" "}
<strong>proches de nos éleveurs et de nos consommateurs.</strong>
</p>
<p>
{" "}
Nous défendons une filière qui participe à l’économie régionale et
nous <strong>nous engageons à préserver son dynamisme.</strong>
</p>
</>
),
},
{
id: "humilite",
label: "humilité et bienveillance",
icon: {
value: ico3,
alt: "Icône représentant la qualité",
title: "Qualité des volailles Ker Chant",
},
titre: "HUMILITÉ ET BIENVEILLANCE",
sousTitre: "Avancer ensemble",
image: {
value: img3,
webp: img3Webp,
alt: "Repas de famille avec plat de volaille",
title: "Repas de famille",
},
contenu: (
<>
<p>
Nous avançons avec simplicité, en écoutant et en respectant ceux qui
nous entourent.
</p>
<p>
Nous voulons être <strong>une marque qui accompagne</strong>, qui
rassure et qui améliore sans cesse ses pratiques pour{" "}
<strong>répondre aux attentes de chacun.</strong>
</p>
</>
),
},
{
id: "fiabilite",
label: "fiabilité et sincérité",
icon: {
value: ico4,
alt: "Icône représentant le savoir-faire",
title: "Savoir-faire Ker Chant",
},
titre: "FIABILITÉ ET SINCÉRITÉ",
sousTitre: "La transparence avant tout",
image: {
value: img4,
webp: img4Webp,
alt: "Eleveur dans son poulailler",
title: "Eleveur Ker Chant",
},
contenu: (
<>
<p>
<strong>Nous garantissons des volailles élevées avec soin</strong>,
dans le respect du <strong>bien-être animal.</strong>
</p>
<p>
Chaque produit Ker Chant est le fruit d’un{" "}
<strong>savoir-faire authentique</strong> et d’une{" "}
<strong>traçabilité irréprochable.</strong>
</p>
</>
),
},
];
export default function ValeursSection() {
const [index, setIndex] = useState(0);
const v = VALEURS[index];
const go = (i: number) => {
setIndex(((i % VALEURS.length) + VALEURS.length) % VALEURS.length);
};
return (
<section
id="nos-valeurs"
className="relative w-full pt-16 pb-12 font-baloo overflow-hidden"
>
<picture className="absolute inset-0 -z-10">
<source srcSet={bgSectionWebp} type="image/webp" />
<img
src={bgSection}
alt=""
aria-hidden="true"
className="h-full w-full object-cover"
/>
</picture>
<VideoFrame />
<div className="pointer-events-none absolute right-[26%] top-0 z-5 hidden h-full w-[5px] translate-x-1/2 bg-[#E01B1B] lg:block" />
<h2 className="my-10 flex justify-center sm:my-14">
<span
className="banner-clip px-10 py-4 text-xl font-extrabold uppercase tracking-wide text-white sm:text-2xl"
style={{ background: RED }}
>
Nos valeurs
</span>
</h2>
<div className="relative mx-auto w-[92%] max-w-[1020px] px-6 lg:px-0">
{/* Onglets */}
<div className="relative z-20 flex items-end md:justify-center justify-start">
{VALEURS.map((val, i) => {
const active = i === index;
const showDivider = i > 0 && i !== index && i - 1 !== index;
return (
<div key={val.id} className="flex items-stretch">
{showDivider && (
<span
className="my-2 w-px self-center h-8 bg-red-500/80"
aria-hidden="true"
/>
)}
<button
type="button"
onClick={() => {
go(i);
}}
aria-label={val.label}
aria-current={active ? "true" : undefined}
className={
"group flex h-16 w-22 md:w-30 cursor-pointer items-center justify-center rounded-t-2xl transition-colors " +
(active ? "" : "hover:bg-(--red)")
}
style={
{
"--red": RED,
background: active ? RED : undefined,
} as React.CSSProperties
}
>
<img
src={val.icon.value}
alt=""
className={
"sm:h-14 sm:w-14 h-11 w-11 object-contain transition-[filter] " +
(active
? "brightness-0 invert"
: "group-hover:brightness-0 group-hover:invert")
}
/>
</button>
</div>
);
})}
</div>
{/* card */}
<div className="relative z-10 min-h-[400px] rounded-b-3xl bg-white px-6 py-10 shadow-xl lg:h-[400px] lg:px-14 lg:py-12">
<div className="pointer-events-none absolute right-0 top-0 z-20 hidden h-full translate-x-1/2 lg:block">
<div className="absolute right-[40%] -top-1 z-30 hidden -translate-y-10 lg:block">
<div
className="flex h-30 w-30 items-center justify-center rounded-full"
style={{
background: "#1D1E1C",
boxShadow: "0 4px 4px rgba(0,0,0,.25)",
}}
>
<img src={pinValeur} alt="" className="h-32 w-24" />
</div>
</div>
</div>
{/* Prev */}
<button
type="button"
onClick={() => {
go(index - 1);
}}
aria-label="Valeur précédente"
className="absolute left-2 top-1/2 z-30 flex sm:h-10 sm:w-10 h-7 w-7 -translate-y-1/2 cursor-pointer items-center justify-center rounded-full bg-black text-white transition-transform hover:scale-105 hover:bg-[#E01B1B] md:-left-11 lg:-left-16"
>
<img
src={arrowLeft}
alt=""
className="sm:h-5 sm:w-5 h-3.5 w-3.5 object-contain"
/>
</button>
{/* Next */}
<button
type="button"
onClick={() => {
go(index + 1);
}}
aria-label="Valeur suivante"
className="absolute right-2 top-1/2 z-30 flex sm:h-10 sm:w-10 h-7 w-7 -translate-y-1/2 cursor-pointer items-center justify-center rounded-full bg-black text-white transition-transform hover:scale-105 hover:bg-[#E01B1B] md:-right-11 lg:-right-16"
>
<img
src={arrowRight}
alt=""
className="sm:h-5 sm:w-5 h-3.5 w-3.5 object-contain"
/>
</button>
{/* texte + image */}
<div className="flex flex-col items-center gap-8 lg:flex-row lg:gap-16">
<div className="flex-1">
<h3
className="text-xl font-extrabold uppercase lg:text-[36px]"
style={{ color: RED }}
>
{v.titre}
</h3>
<h4 className="-mt-2 text-xl font-bold text-neutral-900 lg:text-[28px]">
{v.sousTitre}
</h4>
<div className="mt-6 space-y-4 text-lg leading-snug text-neutral-800 lg:px-0 px-8 lg:max-w-[454px] lg:text-xl">
{v.contenu}
</div>
</div>
<picture>
<source srcSet={v.image.webp} type="image/webp" />
<img
src={v.image.value}
alt={v.image.alt}
title={v.image.title}
className="h-[168px] w-[234px] -rotate-2 object-cover lg:h-[270px] lg:w-[280px] lg:pt-18"
/>
</picture>
</div>
</div>
{/* Pagination */}
<div className="mx-auto mt-10 flex w-[280px] max-w-full items-center gap-0 overflow-hidden">
{VALEURS.map((val, i) => {
const active = i === index;
return (
<button
key={val.id}
type="button"
onClick={() => {
go(i);
}}
aria-label={`Aller à : ${val.label}`}
className="flex-1 rounded-full transition-all"
style={{
height: active ? "5px" : "2px",
background: active ? RED : "#1D1E1C",
opacity: active ? 1 : 0.7,
}}
/>
);
})}
</div>
</div>
</section>
);
}