ajoute un lightbox et optimise les images

This commit is contained in:
Jalil Arfaoui 2025-01-05 22:37:35 +01:00
parent 1dc2e8c1c3
commit b36d9dc858
13 changed files with 3278 additions and 193 deletions

3147
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -15,6 +15,7 @@
"@astrojs/react": "^4.1.2",
"@astrojs/sitemap": "^3.2.1",
"@astrojs/tailwind": "^5.1.4",
"@nextui-org/react": "^2.6.11",
"@preline/accordion": "^2.5.0",
"@preline/collapse": "^2.6.0",
"@preline/dropdown": "^2.6.0",
@ -25,6 +26,7 @@
"astro": "^5.1.2",
"astro-compressor": "^1.0.0",
"clipboard": "^2.0.11",
"framer-motion": "^11.15.0",
"globby": "^14.0.2",
"gsap": "^3.12.5",
"html-minifier-terser": "^7.2.0",
@ -44,6 +46,6 @@
"prettier": "^3.4.2",
"prettier-plugin-astro": "^0.14.1",
"prettier-plugin-tailwindcss": "^0.6.9",
"typescript": "^5.7.2"
"typescript": "5.4.5"
}
}

View file

@ -1,6 +1,7 @@
---
import { Image } from "astro:assets";
import type { ImageMetadata } from "astro";
import { LightboxImage} from "@components/LightboxImage"
const { src, alt } = Astro.props;
@ -11,12 +12,14 @@ interface Props {
---
<div class="relative mb-6 overflow-hidden md:mb-8">
<LightboxImage client:idle image={src} alt={alt}>
<Image
src={src}
alt={alt}
width={1600}
densities={[1, 1.5, 2]}
class="h-full w-full object-cover object-center"
draggable={"false"}
format={"avif"}
loading={"eager"}
loading="eager"
/>
</LightboxImage>
</div>

View file

@ -0,0 +1,46 @@
import React from "react";
import {
Modal,
ModalBody,
ModalContent,
ModalHeader,
useDisclosure,
} from "@nextui-org/react";
type Props = React.PropsWithChildren<{
titre?: string;
alt: string;
image: ImageMetadata;
}>;
export function LightboxImage({ titre, alt, image, children }: Props) {
const { isOpen, onOpen, onOpenChange } = useDisclosure();
return (
<>
<a onClick={onOpen}>{children}</a>
<Modal isOpen={isOpen} onOpenChange={onOpenChange} size="full">
<ModalContent>
{(onClose) => (
<>
<ModalHeader>
<div className="inline-block pr-8">{titre ? titre : alt}</div>
</ModalHeader>
<ModalBody>
<div className="flex h-screen w-full items-center justify-center">
<img
src={image.src}
alt={alt}
onClick={onClose}
className="h-full w-full object-contain"
/>
</div>
</ModalBody>
</>
)}
</ModalContent>
</Modal>
</>
);
}

View file

@ -4,6 +4,7 @@ import { Image } from "astro:assets";
import PrimaryCTA from "@components/ui/buttons/PrimaryCTA.astro";
import SecondaryCTA from "@components/ui/buttons/SecondaryCTA.astro";
import ReviewComponent from "@components/ui/blocks/ReviewComponent.astro";
import { LightboxImage } from "../../LightboxImage";
// Define props from Astro
const {
@ -59,7 +60,8 @@ interface Props {
>
{subTitle}
</p>
<span class="block text-balance text-3xl font-bold tracking-tight text-neutral-800 dark:text-neutral-200 sm:text-4xl lg:text-6xl lg:leading-tight text-yellow-500 dark:text-yellow-400">
<span
class="block text-balance text-3xl font-bold tracking-tight text-neutral-800 dark:text-neutral-200 sm:text-4xl lg:text-6xl lg:leading-tight text-yellow-500 dark:text-yellow-400">
365 000 €
</span>
}
@ -74,23 +76,25 @@ interface Props {
</div>
<!-- Review Section: This section presents avatars, review ratings and the number of reviews -->
{ withReview ? (
{withReview ? (
<ReviewComponent avatars={avatars} starCount={starCount} rating={rating} reviews={reviews} />
) : "" }
) : ""}
</div>
<!-- Hero Image Section -->
<div class="flex w-full">
<div class="top-12 overflow-hidden">
{src && alt &&
<LightboxImage alt={alt} image={src} client:idle>
<Image
src={src}
alt={alt}
class="h-full w-full scale-110 object-cover object-center"
draggable={"false"}
loading={"eager"}
format={"avif"}
width={800}
densities={[1, 1.5, 2]}
loading="eager"
/>
</LightboxImage>
}
</div>
</div>

View file

@ -0,0 +1,34 @@
---
import { Image } from "astro:assets";
import { LightboxImage } from "@components/LightboxImage";
import photoBureau from "@images/grand-bureau-tout-equipe.jpg";
import type { image } from "framer-motion/m";
---
<section
class="mx-auto max-w-[85rem] px-4 py-10 sm:px-6 lg:px-8 lg:py-14 2xl:max-w-full"
>
<!-- Section heading and sub-heading -->
<div class="mx-auto mb-10 max-w-2xl text-center lg:mb-14">
<h2
class="text-balance text-2xl font-bold tracking-tight text-neutral-800 dark:text-neutral-200 md:text-4xl md:leading-tight"
>
Un grand bureau tout équipé
</h2>
<p class="mt-1 text-pretty text-neutral-600 dark:text-neutral-400">
Bureau en chêne-liège massif, réglage en hauteur et motorisé, 16 prises de courant, 6 prises RJ-45, radiateur
indépendant…
</p>
</div>
<LightboxImage client:idle image={photoBureau}
alt="Grand bureau tout équipé, bois massif, bureau ajustable en hauteur, grande fresque murale">
<Image
src={photoBureau}
alt="Grand bureau tout équipé, bois massif, bureau ajustable en hauteur, grande fresque murale"
class="h-full w-full object-cover object-center"
width={1600}
densities={[1, 1.5, 2]}
loading="eager"
/>
</LightboxImage>
</section>

View file

@ -1,60 +0,0 @@
---
// Import SecondaryCTA component for use in this module
import { Image } from "astro:assets";
import SecondaryCTA from "@components/ui/buttons/SecondaryCTA.astro";
import Icon from "@components/ui/icons/Icon.astro";
import photoBureau from "../../../images/grand-bureau-tout-equipe.jpg"
// Define props from Astro
const { pricing } = Astro.props;
// Define TypeScript type for products.
type Product = {
name: string;
description: string;
price: string;
cents: string;
billingFrequency: string;
features: Array<string>;
purchaseBtnTitle: string;
purchaseLink: string;
};
interface PricingSectionProps {
title: string;
subTitle: string;
badge: string;
thirdOption: string;
btnText: string;
pricing: {
title: string;
subTitle: string;
starterKit: Product;
professionalToolbox: Product;
};
}
---
<section
class="mx-auto max-w-[85rem] px-4 py-10 sm:px-6 lg:px-8 lg:py-14 2xl:max-w-full"
>
<!-- Section heading and sub-heading -->
<div class="mx-auto mb-10 max-w-2xl text-center lg:mb-14">
<h2
class="text-balance text-2xl font-bold tracking-tight text-neutral-800 dark:text-neutral-200 md:text-4xl md:leading-tight"
>
Un grand bureau tout équipé
</h2>
<p class="mt-1 text-pretty text-neutral-600 dark:text-neutral-400">
Bureau en chêne-liège massif, réglage en hauteur et motorisé, 16 prises de courant, 6 prises RJ-45, radiateur indépendant…
</p>
</div>
<Image
src={photoBureau}
alt="Grand bureau tout équipé, bois massif, bureau ajustable en hauteur, grande fresque murale"
class="h-full w-full object-cover object-center"
draggable={"false"}
format={"avif"}
loading={"eager"}
/>
</section>

View file

@ -1,6 +1,7 @@
---
// Import the Image component from astro:assets
import { Image } from "astro:assets";
import { LightboxImage } from "@/components/LightboxImage";
// Destructure the component properties from Astro.props
const { id, aria, src, alt, first, second } = Astro.props;
@ -42,13 +43,14 @@ This is the full example:
<!-- Container for tab content that controls visibility and accessibility -->
<div id={id} role="tabpanel" class={firstClass} aria-labelledby={aria}>
<!-- Astro Image component to display the image with dynamic classes based on the 'second' property -->
<LightboxImage client:idle image={src} alt={alt} >
<Image
src={src}
alt={alt}
class={secondClass}
draggable={"false"}
format={"avif"}
loading={"eager"}
width={800}
densities={[1, 1.5, 2]}
loading="eager"
/>
</LightboxImage>
</div>

View file

@ -1,29 +0,0 @@
{
"subTitle": "Posez-nous toutes vos questions sur notre marque et nos produits, et obtenez des réponses factuelles.",
"faqs": [
{
"question": "Quels types d'outils sont inclus dans le Kit de Démarrage?",
"answer": "Le Kit de Démarrage comprend des outils à main et électriques essentiels pour différents projets de bricolage, notamment des marteaux, des perceuses, des tournevis et une variété de fixations. C'est une sélection soigneusement élaborée pour aider les débutants et les bricoleurs expérimentés à aborder la plupart des tâches d'amélioration de l'habitat."
},
{
"question": "Puis-je passer du Kit de Démarrage à la Boîte à Outils Professionnelle?",
"answer": "Absolument ! Vous pouvez passer à la Boîte à Outils Professionnelle à tout moment pour accéder à une gamme plus large d'outils de haute qualité, bénéficier d'un support client prioritaire et recevoir un contenu exclusif. Contactez notre équipe de support pour une transition sans problème."
},
{
"question": "Quels sont les rabais disponibles pour les commandes en gros via le plan Boîte à Outils Professionnelle?",
"answer": "Les membres de la Boîte à Outils Professionnelle ont droit à des rabais exclusifs sur les commandes en gros, dont le pourcentage peut varier en fonction du volume de la commande. Contactez-nous pour discuter de vos besoins, et nous vous fournirons une structure de rabais personnalisée."
},
{
"question": "À quoi puis-je m'attendre en termes de support client?",
"answer": "Tous nos clients bénéficient d'un support par e-mail dédié. Avec le Kit de Démarrage, vous recevrez notre support standard, tandis que le plan Boîte à Outils Professionnelle vous mettra à niveau vers un support prioritaire, ce qui signifie des temps de réponse plus rapides et une assistance spécialisée."
},
{
"question": "À quelle fréquence sont mises à jour les ressources en ligne et les tutoriels?",
"answer": "Nous mettons régulièrement à jour nos ressources en ligne et nos tutoriels pour refléter les dernières tendances en matière de bricolage et de construction, ainsi que les introductions de nouveaux outils et techniques. Notre matériel vise à être complet et convivial pour tous les niveaux de compétence."
},
{
"question": "ScrewFast propose-t-il des services pour les grands projets de construction?",
"answer": "Oui, nos Solutions Entreprise sont conçues pour les grandes entreprises ayant besoin de services complets. Nous fournissons des consultations, de la planification et de l'approvisionnement en outils et matériaux de haute qualité, ainsi que des solutions de personnel pour des besoins de construction importants. Contactez-nous pour un devis personnalisé."
}
]
}

View file

@ -1,22 +0,0 @@
[
{
"heading": "Équipes dédiées",
"content": "Bénéficiez de nos équipes engagées qui veillent à ce que votre réussite soit personnelle. Comptez sur un accompagnement expert et des résultats exceptionnels tout au long de votre parcours de projet.",
"svg": "groups"
},
{
"heading": "Simplicité et accessibilité",
"content": "Trouvez des solutions faciles à utiliser et abordables avec la gamme d'outils et d'équipements de ScrewFast. Nos produits simplifient l'approvisionnement et permettent de respecter les budgets de projet.",
"svg": "verified"
},
{
"heading": "Documentation complète",
"content": "Intégrez facilement grâce aux guides exhaustifs et aux bibliothèques de ScrewFast. Réalisez une adoption de produit sans faille avec notre ensemble complet de documentation conçu pour votre succès.",
"svg": "books"
},
{
"heading": "Conception centrée sur l'utilisateur",
"content": "Faites l'expérience de la différence avec la conception axée sur l'utilisateur de ScrewFast, où la fonctionnalité rencontre la praticité pour une expérience de travail améliorée.",
"svg": "frame"
}
]

View file

@ -1,38 +0,0 @@
{
"title": "Tarification Simple et Transparente",
"subTitle": "Augmentez l'efficacité avec les plans clairs et axés sur la valeur de ScrewFast.",
"badge": "Meilleure valeur",
"thirdOption": "Solutions Entreprise?",
"btnText": "Obtenez un Devis Personnalisé",
"starterKit": {
"name": "Kit de Démarrage",
"description": "Meilleure option pour les projets de bricolage",
"price": "$49",
"cents": ".00",
"billingFrequency": "USD / mensuel",
"features": [
"Outils matériels essentiels",
"Accès aux guides et tutoriels",
"Support standard"
],
"purchaseBtnTitle": "Obtenez le Kit de Démarrage",
"purchaseLink": "#"
},
"professionalToolbox": {
"name": "Boîte à Outils Professionnelle",
"description": "Idéale pour les utilisations à grande échelle",
"price": "$89",
"cents": ".00",
"billingFrequency": "USD / mensuel",
"features": [
"Sélection d'outils premium",
"Support prioritaire",
"Contenu et offres exclusifs",
"Remises sur les commandes en gros"
],
"purchaseBtnTitle": "Obtenez la Boîte à Outils Professionnelle",
"purchaseLink": "#"
}
}

View file

@ -6,7 +6,7 @@ import DiagnosticsSection from "@components/sections/landing/ClientsSection.astr
import FeaturesGeneral from "@components/sections/features/FeaturesGeneral.astro";
import FeaturesNavs from "@components/sections/features/FeaturesNavs.astro";
import TestimonialsSection from "@components/sections/testimonials/TestimonialsSection.astro";
import BureauSection from "@components/sections/pricing/PricingSection.astro";
import BureauSection from "../components/sections/pricing/BureauSection.astro";
import FAQ from "@components/sections/misc/FAQ.astro";
import faqs from "@data/faqs.json";
import features from "@data/features.json";
@ -54,7 +54,7 @@ import photoVueZenith from "@images/vue-zenith.jpg";
title="Rien ne manque"
subTitle="Une cuisine, une grande pièce de vie, 5 chambres, 3 salles deau, un bureau, une salle de jeu, une buanderie et un garage."
src={photoVuePiscine}
alt="ScrewFast products in floating boxes"
alt="Un extérieur intimiste dans un écrin de verdure et de calme"
features={features}
/>

View file

@ -1,9 +1,12 @@
/** @type {import('tailwindcss').Config} */
import colors from 'tailwindcss/colors';
const { nextui } = require("@nextui-org/react");
export default {
content: [
"./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}",
"./node_modules/preline/preline.js",
"./node_modules/@nextui-org/theme/dist/**/*.{js,ts,jsx,tsx}",
],
darkMode: "class",
theme: {
@ -38,5 +41,6 @@ export default {
require("tailwindcss/nesting"),
require("preline/plugin"),
require("@tailwindcss/forms"),
nextui()
],
};