159 lines
5.9 KiB
TypeScript
159 lines
5.9 KiB
TypeScript
import { useEffect, useRef, useState } from "react";
|
|
|
|
import agricultureBio from "&/images/certifications/agriculture-biologique.png";
|
|
import agricultureBioWebp from "&/images/certifications/agriculture-biologique.webp";
|
|
import bienEtre from "&/images/certifications/bien-etre-animal.png";
|
|
import bienEtreWebp from "&/images/certifications/bien-etre-animal.webp";
|
|
import conformite from "&/images/certifications/conformite-certifiee.jpg";
|
|
import conformiteWebp from "&/images/certifications/conformite-certifiee.webp";
|
|
import labelRouge from "&/images/certifications/label-rouge.png";
|
|
import labelRougeWebp from "&/images/certifications/label-rouge.webp";
|
|
import origineGeo from "&/images/certifications/origine-geographique.png";
|
|
import origineGeoWebp from "&/images/certifications/origine-geographique.webp";
|
|
import impact from "&/images/certifications/planet-scrore.png";
|
|
import impactWebp from "&/images/certifications/planet-scrore.webp";
|
|
import { GetTranslation } from "@/lib/utils";
|
|
|
|
const CERTIFICATIONS = [
|
|
{
|
|
webp: labelRougeWebp,
|
|
fallback: labelRouge,
|
|
label: "front.certifications.quality.text",
|
|
alt: "front.certifications.quality.alt",
|
|
title: "front.certifications.quality.title",
|
|
},
|
|
{
|
|
webp: origineGeoWebp,
|
|
fallback: origineGeo,
|
|
label: "front.certifications.origin.text",
|
|
alt: "front.certifications.origin.alt",
|
|
title: "front.certifications.origin.title",
|
|
},
|
|
{
|
|
webp: agricultureBioWebp,
|
|
fallback: agricultureBio,
|
|
label: "front.certifications.organic.text",
|
|
alt: "front.certifications.organic.alt",
|
|
title: "front.certifications.organic.title",
|
|
},
|
|
{
|
|
webp: conformiteWebp,
|
|
fallback: conformite,
|
|
label: "front.certifications.product_cerf.text",
|
|
alt: "front.certifications.product_cerf.alt",
|
|
title: "front.certifications.product_cerf.title",
|
|
},
|
|
{
|
|
webp: bienEtreWebp,
|
|
fallback: bienEtre,
|
|
label: "front.certifications.animalWelfare.text",
|
|
alt: "front.certifications.animalWelfare.alt",
|
|
title: "front.certifications.animalWelfare.title",
|
|
},
|
|
{
|
|
webp: impactWebp,
|
|
fallback: impact,
|
|
label: "front.certifications.environmentalImpact.text",
|
|
alt: "front.certifications.environmentalImpact.text",
|
|
title: "front.certifications.environmentalImpact.title",
|
|
},
|
|
];
|
|
|
|
export default function CertificationsSection() {
|
|
const scrollerRef = useRef<HTMLDivElement>(null);
|
|
const [thumb, setThumb] = useState({ width: 200, left: 0 });
|
|
|
|
useEffect(() => {
|
|
const scroller = scrollerRef.current;
|
|
if (!scroller) return;
|
|
|
|
const updateThumb = () => {
|
|
const { scrollLeft, scrollWidth, clientWidth } = scroller;
|
|
const thumbWidth = (clientWidth / scrollWidth) * 100;
|
|
const maxScroll = scrollWidth - clientWidth;
|
|
const scrollRatio = maxScroll > 0 ? scrollLeft / maxScroll : 0;
|
|
const thumbLeft = scrollRatio * (100 - thumbWidth);
|
|
|
|
setThumb({ width: thumbWidth, left: thumbLeft });
|
|
};
|
|
|
|
updateThumb();
|
|
scroller.addEventListener("scroll", updateThumb, { passive: true });
|
|
window.addEventListener("resize", updateThumb);
|
|
return () => {
|
|
scroller.removeEventListener("scroll", updateThumb);
|
|
window.removeEventListener("resize", updateThumb);
|
|
};
|
|
}, []);
|
|
return (
|
|
<section className="relative w-full overflow-hidden px-8 py-14 md:px-12 lg:px-[60px]">
|
|
<div className="mx-auto max-w-[1320px] text-start lg:text-center">
|
|
<h2 className="font-sans text-[26px] lg:text-[32px] font-extrabold text-neutral-800 whitespace-nowrap">
|
|
{GetTranslation("front.certifications.title")}
|
|
</h2>
|
|
<p className="mx-auto mt-3 max-w-[820px] font-sans text-[18px] leading-relaxed text-neutral-700 ">
|
|
{GetTranslation("front.certifications.subtitle")}
|
|
</p>
|
|
|
|
{/* Mobile */}
|
|
<div
|
|
ref={scrollerRef}
|
|
className="no-scrollbar mt-10 -mx-8 flex snap-x snap-mandatory gap-8 overflow-x-auto px-8 pb-4 md:hidden"
|
|
>
|
|
{CERTIFICATIONS.map((cert) => (
|
|
<div
|
|
key={cert.label}
|
|
className="flex w-[160px] flex-none snap-center flex-col items-center gap-3"
|
|
>
|
|
<picture>
|
|
<source srcSet={cert.webp} type="image/webp" />
|
|
<img
|
|
src={cert.fallback}
|
|
title={GetTranslation(cert.title)}
|
|
alt={GetTranslation(cert.alt)}
|
|
className="h-[90px] w-auto object-contain"
|
|
/>
|
|
</picture>
|
|
<p className="font-sans text-[14px] font-normal uppercase text-neutral-700 text-center">
|
|
{GetTranslation(cert.label)}
|
|
</p>
|
|
</div>
|
|
))}
|
|
</div>
|
|
|
|
{/* Custom progress Bar */}
|
|
<div className="relative mt-2 h-2.5 w-full max-w-[300px] bg-[#eeede7] md:hidden">
|
|
<div
|
|
className="absolute top-0 h-full rounded-full bg-[#D9D9D9] transition-[left,width] duration-150 ease-out"
|
|
style={{
|
|
width: `${thumb.width.toString()}%`,
|
|
left: `${thumb.left.toString()}%`,
|
|
}}
|
|
/>
|
|
</div>
|
|
{/* Desktop */}
|
|
<div className="mt-10 hidden items-start justify-between gap-6 md:flex">
|
|
{CERTIFICATIONS.map((cert) => (
|
|
<div
|
|
key={cert.label}
|
|
className="flex flex-1 flex-col items-center gap-3"
|
|
>
|
|
<picture>
|
|
<source srcSet={cert.webp} type="image/webp" />
|
|
<img
|
|
src={cert.fallback}
|
|
alt={GetTranslation(cert.alt)}
|
|
title={GetTranslation(cert.title)}
|
|
className="h-[90px] w-auto object-contain"
|
|
/>
|
|
</picture>
|
|
<p className="font-sans text-[14px] font-normal uppercase text-neutral-700">
|
|
{GetTranslation(cert.label)}
|
|
</p>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|