feat: rebuild 3 demo pages with interactive features + local SEO pages
- Rebuild /macon with cert badge popups, before/after slider, intelligent form with urgency detection - Rebuild /paysagiste with filterable gallery, seasonal banner, WhatsApp floating button, devis form - Rebuild /plombier with sticky call bar, 3-step diagnostic wizard, transparent tariffs, zone map - Add MagicReveal component (interactive before/after slider) - Update Navbar with real phone number (06 04 40 81 57) - Update DemosLive cards with new titles and subtitles - Create sitemap.ts targeting local SEO zones (Douai, Orchies, Valenciennes, Saint-Amand, Arleux, Denain) - Create LocalSeoPage template + 6 city-specific landing pages https://claude.ai/code/session_01H2aRGDaKgarPvhay2HxN6Y
This commit is contained in:
197
app/macon/MaconClient.tsx
Normal file
197
app/macon/MaconClient.tsx
Normal file
@@ -0,0 +1,197 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import MagicReveal from "@/components/ui/MagicReveal";
|
||||
import Button from "@/components/ui/Button";
|
||||
|
||||
interface MaconClientProps {
|
||||
type?: "slider" | "form" | "cert";
|
||||
certName?: string;
|
||||
avantLabel?: string;
|
||||
apresLabel?: string;
|
||||
}
|
||||
|
||||
export default function MaconClient({ type, certName, avantLabel, apresLabel }: MaconClientProps) {
|
||||
// Cert badge with popup
|
||||
if (!type || type === "cert") {
|
||||
return <CertBadge name={certName || ""} />;
|
||||
}
|
||||
|
||||
if (type === "slider") {
|
||||
return (
|
||||
<MagicReveal
|
||||
avantLabel={avantLabel || ""}
|
||||
apresLabel={apresLabel || ""}
|
||||
avantColor="bg-red-50"
|
||||
apresColor="bg-green-50"
|
||||
height="h-64"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (type === "form") {
|
||||
return <DevisForm />;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function CertBadge({ name }: { name: string }) {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const infos: Record<string, string> = {
|
||||
"D\u00e9cennale": "La garantie d\u00e9cennale couvre tous les dommages compromettant la solidit\u00e9 de l\u2019ouvrage pendant 10 ans apr\u00e8s la r\u00e9ception des travaux.",
|
||||
"Qualibat": "Qualibat est l\u2019organisme de r\u00e9f\u00e9rence pour la qualification des entreprises du b\u00e2timent. Gage de comp\u00e9tence et de s\u00e9rieux.",
|
||||
"RGE": "Le label RGE (Reconnu Garant de l\u2019Environnement) vous permet de b\u00e9n\u00e9ficier des aides de l\u2019\u00c9tat : MaPrimeR\u00e9nov\u2019, CEE, \u00e9co-PTZ.",
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<button
|
||||
onClick={() => setOpen(true)}
|
||||
className="flex items-center gap-2 bg-white/10 hover:bg-white/20 border border-white/20 rounded-full px-4 py-1.5 transition-colors cursor-pointer"
|
||||
>
|
||||
<svg className="w-4 h-4 text-green-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z" />
|
||||
</svg>
|
||||
<span className="text-white text-xs font-semibold">{name}</span>
|
||||
</button>
|
||||
|
||||
{/* Popup */}
|
||||
{open && (
|
||||
<div className="fixed inset-0 z-[100] flex items-center justify-center bg-black/50 p-4" onClick={() => setOpen(false)}>
|
||||
<div className="bg-white rounded-2xl p-6 max-w-sm w-full shadow-2xl" onClick={(e) => e.stopPropagation()}>
|
||||
<div className="flex items-center gap-3 mb-4">
|
||||
<div className="w-10 h-10 bg-green-100 rounded-full flex items-center justify-center">
|
||||
<svg className="w-5 h-5 text-green-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 className="text-[#1b2a4a] font-bold text-lg">{name}</h3>
|
||||
</div>
|
||||
<p className="text-gray-600 text-sm leading-relaxed mb-5">
|
||||
{infos[name] || "Certification professionnelle v\u00e9rifi\u00e9e."}
|
||||
</p>
|
||||
<button
|
||||
onClick={() => setOpen(false)}
|
||||
className="w-full bg-[#1b2a4a] text-white font-semibold text-sm py-2.5 rounded-xl hover:bg-[#1b2a4a]/90 transition-colors cursor-pointer"
|
||||
>
|
||||
Compris
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function DevisForm() {
|
||||
const [step, setStep] = useState<"type" | "details" | "urgence">("type");
|
||||
const [projectType, setProjectType] = useState("");
|
||||
|
||||
if (step === "urgence") {
|
||||
return (
|
||||
<div className="bg-white rounded-2xl p-6 sm:p-8 text-center">
|
||||
<div className="w-16 h-16 bg-red-100 rounded-full flex items-center justify-center mx-auto mb-4">
|
||||
<svg className="w-8 h-8 text-red-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L4.082 16.5c-.77.833.192 2.5 1.732 2.5z" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 className="text-[#1b2a4a] font-bold text-xl mb-2">Urgence d\u00e9tect\u00e9e !</h3>
|
||||
<p className="text-gray-500 text-sm mb-6">Pour une intervention rapide, appelez directement le patron :</p>
|
||||
<a
|
||||
href="tel:+33604408157"
|
||||
className="inline-flex items-center justify-center gap-3 bg-red-600 hover:bg-red-700 text-white font-bold text-lg px-8 py-4 rounded-xl transition-colors w-full"
|
||||
>
|
||||
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z" />
|
||||
</svg>
|
||||
APPELER LE PATRON
|
||||
</a>
|
||||
<p className="text-gray-400 text-xs mt-3">Disponible 7j/7 pour les urgences</p>
|
||||
<button onClick={() => setStep("type")} className="text-gray-400 hover:text-gray-600 text-sm mt-4 underline cursor-pointer">
|
||||
← Retour au formulaire
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (step === "details") {
|
||||
return (
|
||||
<div className="bg-white rounded-2xl p-6 sm:p-8">
|
||||
<div className="flex items-center gap-2 mb-6">
|
||||
<span className="bg-orange text-white text-xs font-bold px-2.5 py-1 rounded-full">2/2</span>
|
||||
<h3 className="text-[#1b2a4a] font-bold text-lg">D\u00e9tails du projet</h3>
|
||||
</div>
|
||||
<p className="text-gray-400 text-sm mb-5">Type : <strong className="text-[#1b2a4a]">{projectType}</strong></p>
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1.5">Surface approximative</label>
|
||||
<select className="w-full px-4 py-3 bg-[#f8f6f3] border border-gray-200 rounded-xl text-gray-800 text-sm focus:border-orange focus:ring-1 focus:ring-orange outline-none">
|
||||
<option>Moins de 50m\u00b2</option>
|
||||
<option>50 \u00e0 100m\u00b2</option>
|
||||
<option>100 \u00e0 200m\u00b2</option>
|
||||
<option>Plus de 200m\u00b2</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1.5">Votre nom</label>
|
||||
<input type="text" placeholder="Marc Dupont" className="w-full px-4 py-3 bg-[#f8f6f3] border border-gray-200 rounded-xl text-gray-800 text-sm placeholder:text-gray-400 focus:border-orange focus:ring-1 focus:ring-orange outline-none" />
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1.5">T\u00e9l\u00e9phone</label>
|
||||
<input type="tel" placeholder="06 12 34 56 78" className="w-full px-4 py-3 bg-[#f8f6f3] border border-gray-200 rounded-xl text-gray-800 text-sm placeholder:text-gray-400 focus:border-orange focus:ring-1 focus:ring-orange outline-none" />
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1.5">Ville</label>
|
||||
<input type="text" placeholder="Douai, Orchies, Valenciennes..." className="w-full px-4 py-3 bg-[#f8f6f3] border border-gray-200 rounded-xl text-gray-800 text-sm placeholder:text-gray-400 focus:border-orange focus:ring-1 focus:ring-orange outline-none" />
|
||||
</div>
|
||||
<Button size="lg" className="w-full">Envoyer ma demande de devis</Button>
|
||||
<button onClick={() => setStep("type")} className="w-full text-gray-400 hover:text-gray-600 text-sm underline cursor-pointer">
|
||||
← Retour
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="bg-white rounded-2xl p-6 sm:p-8">
|
||||
<div className="flex items-center gap-2 mb-6">
|
||||
<span className="bg-orange text-white text-xs font-bold px-2.5 py-1 rounded-full">1/2</span>
|
||||
<h3 className="text-[#1b2a4a] font-bold text-lg">Quel type de projet ?</h3>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
|
||||
{[
|
||||
{ label: "Urgence fuite / d\u00e9g\u00e2t", urgent: true },
|
||||
{ label: "R\u00e9novation toiture", urgent: false },
|
||||
{ label: "Ravalement fa\u00e7ade", urgent: false },
|
||||
{ label: "Ma\u00e7onnerie neuve", urgent: false },
|
||||
{ label: "Charpente / Isolation", urgent: false },
|
||||
{ label: "Autre projet", urgent: false },
|
||||
].map((item) => (
|
||||
<button
|
||||
key={item.label}
|
||||
onClick={() => {
|
||||
setProjectType(item.label);
|
||||
if (item.urgent) {
|
||||
setStep("urgence");
|
||||
} else {
|
||||
setStep("details");
|
||||
}
|
||||
}}
|
||||
className={`p-4 rounded-xl border-2 text-left transition-all cursor-pointer hover:shadow-md ${
|
||||
item.urgent
|
||||
? "border-red-300 bg-red-50 hover:border-red-500"
|
||||
: "border-gray-200 bg-[#f8f6f3] hover:border-orange"
|
||||
}`}
|
||||
>
|
||||
<p className={`font-semibold text-sm ${item.urgent ? "text-red-600" : "text-[#1b2a4a]"}`}>
|
||||
{item.urgent && "\u26a0\ufe0f "}{item.label}
|
||||
</p>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,148 +1,208 @@
|
||||
import type { Metadata } from "next";
|
||||
import Link from "next/link";
|
||||
import Button from "@/components/ui/Button";
|
||||
import MaconClient from "./MaconClient";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "D\u00e9mo Site Ma\u00e7on / Couvreur - Pack Gros \u0152uvre",
|
||||
title: "D\u00e9mo Site Ma\u00e7on / Couvreur - L'Expertise Solide | HookLab",
|
||||
description:
|
||||
"D\u00e9couvrez le mod\u00e8le de site HookLab pour ma\u00e7ons et couvreurs. Galerie Avant/Apr\u00e8s, bouton Urgence Fuite, optimis\u00e9 SEO local.",
|
||||
"Mod\u00e8le de site HookLab pour ma\u00e7ons, couvreurs et charpentiers. Slider Avant/Apr\u00e8s interactif, badges garanties, formulaire intelligent, bouton urgence.",
|
||||
};
|
||||
|
||||
const avantApres = [
|
||||
{ avant: "Toiture v\u00e9tuste - Tuiles cass\u00e9es", apres: "R\u00e9fection compl\u00e8te en tuiles m\u00e9caniques" },
|
||||
{ avant: "Fa\u00e7ade fissur\u00e9e - Enduit d\u00e9grad\u00e9", apres: "Ravalement complet + isolation" },
|
||||
{ avant: "Chemin\u00e9e en ruine", apres: "Reconstruction + \u00e9tanch\u00e9it\u00e9" },
|
||||
];
|
||||
|
||||
export default function MaconDemo() {
|
||||
return (
|
||||
<main className="min-h-screen bg-bg">
|
||||
{/* Nav simplifi\u00e9e */}
|
||||
<nav className="sticky top-0 z-50 bg-navy border-b border-white/10">
|
||||
<main className="min-h-screen bg-[#f8f6f3]">
|
||||
{/* Nav avec badge dispo */}
|
||||
<nav className="sticky top-0 z-50 bg-[#1b2a4a] border-b border-white/10">
|
||||
<div className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8 flex items-center justify-between h-16">
|
||||
<div className="flex items-center gap-3">
|
||||
<Link href="/" className="text-white/60 hover:text-white text-sm transition-colors">
|
||||
← Retour HookLab
|
||||
← HookLab
|
||||
</Link>
|
||||
<span className="text-white/30">|</span>
|
||||
<span className="text-white font-bold text-sm">
|
||||
D\u00e9mo : <span className="text-orange">Pack Gros \u0152uvre</span>
|
||||
[Votre Entreprise] — <span className="text-orange">Ma\u00e7onnerie & Couverture</span>
|
||||
</span>
|
||||
</div>
|
||||
<a
|
||||
href="tel:+33600000000"
|
||||
className="bg-red-600 hover:bg-red-700 text-white font-bold text-sm px-4 py-2 rounded-lg transition-colors flex items-center gap-2"
|
||||
>
|
||||
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z" />
|
||||
</svg>
|
||||
Urgence Fuite
|
||||
</a>
|
||||
<div className="flex items-center gap-3">
|
||||
{/* Badge dispo */}
|
||||
<div className="hidden sm:flex items-center gap-2 bg-green-500/20 border border-green-500/30 rounded-full px-3 py-1">
|
||||
<span className="w-2 h-2 bg-green-400 rounded-full animate-pulse" />
|
||||
<span className="text-green-400 text-xs font-semibold">Dispo imm\u00e9diate</span>
|
||||
</div>
|
||||
<a
|
||||
href="tel:+33604408157"
|
||||
className="bg-red-600 hover:bg-red-700 text-white font-bold text-sm px-4 py-2 rounded-lg transition-colors flex items-center gap-2"
|
||||
>
|
||||
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z" />
|
||||
</svg>
|
||||
<span className="hidden sm:inline">Urgence Fuite</span>
|
||||
<span className="sm:hidden">Appeler</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
{/* Certifications en haut - immanquables */}
|
||||
<div className="bg-[#1b2a4a] border-b border-white/5">
|
||||
<div className="max-w-6xl mx-auto px-4 py-3 flex flex-wrap items-center justify-center gap-4 sm:gap-8">
|
||||
{["D\u00e9cennale", "Qualibat", "RGE"].map((cert) => (
|
||||
<MaconClient key={cert} certName={cert} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Hero */}
|
||||
<section className="py-20 md:py-28 bg-navy text-center">
|
||||
<section className="py-20 md:py-28 bg-[#1b2a4a] text-center">
|
||||
<div className="max-w-4xl mx-auto px-4">
|
||||
<span className="inline-block px-3 py-1.5 bg-orange/20 border border-orange/30 rounded-full text-orange text-xs font-semibold mb-6">
|
||||
Ma\u00e7onnerie & Couverture
|
||||
Ma\u00e7onnerie · Couverture · Charpente
|
||||
</span>
|
||||
<h1 className="text-3xl sm:text-4xl md:text-5xl font-extrabold text-white leading-tight mb-6">
|
||||
[Votre Entreprise] — Ma\u00e7on Couvreur <span className="text-orange">dans le Nord</span>
|
||||
<h1 className="text-3xl sm:text-4xl md:text-5xl font-extrabold text-white leading-tight mb-4">
|
||||
Vos chantiers parlent pour vous.{" "}
|
||||
<span className="text-orange">Votre site aussi.</span>
|
||||
</h1>
|
||||
<p className="text-white/60 text-lg max-w-2xl mx-auto mb-8">
|
||||
Plus de 15 ans d’exp\u00e9rience en ma\u00e7onnerie et couverture. Devis gratuit sous 24h.
|
||||
Intervention rapide sur Douai, Orchies et Valenciennes.
|
||||
<p className="text-white/60 text-lg max-w-2xl mx-auto mb-4">
|
||||
Dans le gros \u0153uvre, le client a peur. Peur que \u00e7a s’\u00e9croule, peur des fuites,
|
||||
peur que vous partiez avec l’acompte. Ce site est une machine \u00e0 tuer les objections.
|
||||
</p>
|
||||
<p className="text-white/40 text-sm mb-8">
|
||||
Intervention rapide sur Douai, Orchies, Valenciennes et environs.
|
||||
</p>
|
||||
<div className="flex flex-col sm:flex-row gap-4 justify-center">
|
||||
<Button size="lg" className="pulse-glow">
|
||||
Demander un Devis Gratuit
|
||||
</Button>
|
||||
<a href="#devis">
|
||||
<Button size="lg" className="w-full sm:w-auto pulse-glow">
|
||||
Demander un Devis Toiture
|
||||
</Button>
|
||||
</a>
|
||||
<a
|
||||
href="tel:+33600000000"
|
||||
href="tel:+33604408157"
|
||||
className="inline-flex items-center justify-center gap-2 bg-red-600 hover:bg-red-700 text-white font-bold px-6 py-3 rounded-xl transition-colors"
|
||||
>
|
||||
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z" />
|
||||
</svg>
|
||||
Urgence Fuite : Appeler Maintenant
|
||||
APPELER LE PATRON
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Avant / Apr\u00e8s */}
|
||||
<section className="py-16 md:py-24 bg-bg-white">
|
||||
{/* Slider Magic Reveal - Avant/Apr\u00e8s */}
|
||||
<section className="py-16 md:py-24 bg-white">
|
||||
<div className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="text-center mb-12">
|
||||
<h2 className="text-2xl md:text-3xl font-bold text-navy mb-3">
|
||||
Galerie <span className="text-orange">Avant / Apr\u00e8s</span>
|
||||
<h2 className="text-2xl md:text-3xl font-bold text-[#1b2a4a] mb-3">
|
||||
La preuve par l’image — <span className="text-orange">Avant / Apr\u00e8s</span>
|
||||
</h2>
|
||||
<p className="text-text-light">La preuve par l’image. Nos chantiers parlent d’eux-m\u00eames.</p>
|
||||
<p className="text-gray-500">Glissez la barre pour voir la transformation. Impact visuel imm\u00e9diat.</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
{[
|
||||
{ avant: "Toiture v\u00e9tuste \u2014 Tuiles cass\u00e9es, infiltrations", apres: "R\u00e9fection compl\u00e8te en tuiles m\u00e9caniques" },
|
||||
{ avant: "Fa\u00e7ade fissur\u00e9e \u2014 Enduit d\u00e9grad\u00e9", apres: "Ravalement complet + isolation thermique" },
|
||||
{ avant: "Chemin\u00e9e en ruine \u2014 Danger effondrement", apres: "Reconstruction + \u00e9tanch\u00e9it\u00e9 garantie" },
|
||||
].map((item, i) => (
|
||||
<MaconClient key={i} type="slider" avantLabel={item.avant} apresLabel={item.apres} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Garanties */}
|
||||
<section className="py-16 md:py-24 bg-[#f8f6f3]">
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="text-center mb-12">
|
||||
<h2 className="text-2xl md:text-3xl font-bold text-[#1b2a4a] mb-3">
|
||||
Vos <span className="text-orange">garanties</span>
|
||||
</h2>
|
||||
<p className="text-gray-500">Des certifications qui prot\u00e8gent votre investissement.</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
{avantApres.map((item, i) => (
|
||||
<div key={i} className="bg-bg border border-border rounded-2xl overflow-hidden">
|
||||
<div className="grid grid-cols-2">
|
||||
<div className="h-40 bg-red-50 flex items-center justify-center border-r border-border">
|
||||
<div className="text-center p-3">
|
||||
<p className="text-red-500 text-xs font-bold uppercase mb-1">Avant</p>
|
||||
<p className="text-text-muted text-xs">{item.avant}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="h-40 bg-green-50 flex items-center justify-center">
|
||||
<div className="text-center p-3">
|
||||
<p className="text-green-600 text-xs font-bold uppercase mb-1">Apr\u00e8s</p>
|
||||
<p className="text-text-muted text-xs">{item.apres}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{[
|
||||
{
|
||||
name: "Garantie D\u00e9cennale",
|
||||
desc: "Votre ouvrage est couvert pendant 10 ans. En cas de d\u00e9faut structurel, les r\u00e9parations sont prises en charge int\u00e9gralement.",
|
||||
icon: "\ud83d\udee1\ufe0f",
|
||||
},
|
||||
{
|
||||
name: "Qualibat RGE",
|
||||
desc: "Cette certification vous garantit des aides de l\u2019\u00c9tat (MaPrimeR\u00e9nov\u2019, CEE). Jusqu\u2019\u00e0 90% de vos travaux financ\u00e9s.",
|
||||
icon: "\u2705",
|
||||
},
|
||||
{
|
||||
name: "Assurance Responsabilit\u00e9",
|
||||
desc: "Chaque chantier est assur\u00e9. Vous ne prenez aucun risque financier, m\u00eame en cas d\u2019impr\u00e9vu.",
|
||||
icon: "\ud83d\udcbc",
|
||||
},
|
||||
].map((g, i) => (
|
||||
<div key={i} className="bg-white border border-gray-200 rounded-2xl p-6 text-center hover:shadow-md transition-shadow">
|
||||
<div className="text-4xl mb-4">{g.icon}</div>
|
||||
<h3 className="text-[#1b2a4a] font-bold text-lg mb-2">{g.name}</h3>
|
||||
<p className="text-gray-500 text-sm leading-relaxed">{g.desc}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Avis */}
|
||||
<section className="py-16 md:py-24 bg-bg">
|
||||
{/* Avis clients */}
|
||||
<section className="py-16 md:py-24 bg-white">
|
||||
<div className="max-w-4xl mx-auto px-4 text-center">
|
||||
<h2 className="text-2xl md:text-3xl font-bold text-navy mb-10">
|
||||
<h2 className="text-2xl md:text-3xl font-bold text-[#1b2a4a] mb-10">
|
||||
Ce que disent <span className="text-orange">nos clients</span>
|
||||
</h2>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
{[
|
||||
{ name: "Marc D.", ville: "Douai", text: "Toiture refaite en 3 jours. Propre, ponctuel, prix respect\u00e9. Je recommande \u00e0 100%." },
|
||||
{ name: "Sophie L.", ville: "Orchies", text: "Fuite d\u2019urgence un dimanche. Ils sont venus en 2h. Travail impeccable." },
|
||||
{ name: "Marc D.", ville: "Douai", text: "Toiture refaite en 3 jours. Propre, ponctuel, prix respect\u00e9. Je recommande \u00e0 100%.", note: 5 },
|
||||
{ name: "Sophie L.", ville: "Orchies", text: "Fuite d\u2019urgence un dimanche. Ils sont venus en 2h. Travail impeccable et prix honn\u00eate.", note: 5 },
|
||||
{ name: "Patrick M.", ville: "Valenciennes", text: "Ravalement fa\u00e7ade complet. R\u00e9sultat magnifique, les voisins nous demandent le contact !", note: 5 },
|
||||
{ name: "Isabelle R.", ville: "Arleux", text: "Charpente trait\u00e9e et renforc\u00e9e. \u00c9quipe s\u00e9rieuse, devis respect\u00e9 au centime pr\u00e8s.", note: 5 },
|
||||
].map((avis, i) => (
|
||||
<div key={i} className="bg-bg-white border border-border rounded-xl p-6 text-left">
|
||||
<div key={i} className="bg-[#f8f6f3] border border-gray-200 rounded-xl p-6 text-left">
|
||||
<div className="flex gap-1 mb-3">
|
||||
{[...Array(5)].map((_, j) => (
|
||||
{[...Array(avis.note)].map((_, j) => (
|
||||
<svg key={j} className="w-4 h-4 text-orange" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z" />
|
||||
</svg>
|
||||
))}
|
||||
</div>
|
||||
<p className="text-text-light text-sm leading-relaxed mb-3">“{avis.text}”</p>
|
||||
<p className="text-navy font-semibold text-sm">{avis.name} — <span className="text-text-muted font-normal">{avis.ville}</span></p>
|
||||
<p className="text-gray-600 text-sm leading-relaxed mb-3">“{avis.text}”</p>
|
||||
<p className="text-[#1b2a4a] font-semibold text-sm">{avis.name} — <span className="text-gray-400 font-normal">{avis.ville}</span></p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* CTA */}
|
||||
<section className="py-16 bg-navy text-center">
|
||||
{/* Formulaire intelligent */}
|
||||
<section id="devis" className="py-16 md:py-24 bg-[#1b2a4a]">
|
||||
<div className="max-w-2xl mx-auto px-4">
|
||||
<p className="text-orange text-xs font-semibold uppercase tracking-wider mb-3">Ceci est une d\u00e9mo HookLab</p>
|
||||
<div className="text-center mb-10">
|
||||
<h2 className="text-2xl md:text-3xl font-bold text-white mb-3">
|
||||
Demander un <span className="text-orange">devis gratuit</span>
|
||||
</h2>
|
||||
<p className="text-white/60">Formulaire intelligent : on filtre pour ne recevoir que les vrais projets.</p>
|
||||
</div>
|
||||
<MaconClient type="form" />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* CTA HookLab */}
|
||||
<section className="py-16 bg-orange text-center">
|
||||
<div className="max-w-2xl mx-auto px-4">
|
||||
<p className="text-white/80 text-xs font-semibold uppercase tracking-wider mb-3">Ceci est une d\u00e9mo HookLab</p>
|
||||
<h2 className="text-2xl md:text-3xl font-bold text-white mb-4">
|
||||
Vous voulez le m\u00eame site pour votre entreprise ?
|
||||
Vous voulez le m\u00eame site pour votre entreprise ?
|
||||
</h2>
|
||||
<p className="text-white/60 mb-6">
|
||||
Imaginez votre logo, vos photos et votre num\u00e9ro \u00e0 la place. C’est exactement ce que je construis pour vous.
|
||||
<p className="text-white/80 mb-6">
|
||||
Imaginez votre logo, vos photos de chantier et votre num\u00e9ro \u00e0 la place. C’est exactement ce que je construis pour vous.
|
||||
</p>
|
||||
<Link href="/#contact">
|
||||
<Button size="lg" className="pulse-glow">
|
||||
<Button size="lg" className="bg-[#1b2a4a] hover:bg-[#1b2a4a]/90 border-[#1b2a4a]">
|
||||
Demander Mon Audit Gratuit
|
||||
</Button>
|
||||
</Link>
|
||||
|
||||
105
app/paysagiste/PaysagisteClient.tsx
Normal file
105
app/paysagiste/PaysagisteClient.tsx
Normal file
@@ -0,0 +1,105 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
|
||||
interface Realisation {
|
||||
titre: string;
|
||||
type: string;
|
||||
lieu: string;
|
||||
saison: string;
|
||||
}
|
||||
|
||||
interface PaysagisteClientProps {
|
||||
realisations?: Realisation[];
|
||||
whatsapp?: boolean;
|
||||
}
|
||||
|
||||
export default function PaysagisteClient({ realisations, whatsapp }: PaysagisteClientProps) {
|
||||
if (whatsapp) {
|
||||
return <WhatsAppButton />;
|
||||
}
|
||||
|
||||
if (realisations) {
|
||||
return <GalerieFiltrable realisations={realisations} />;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function WhatsAppButton() {
|
||||
return (
|
||||
<a
|
||||
href="https://wa.me/33604408157?text=Bonjour%2C%20je%20souhaite%20un%20devis%20pour%20mon%20jardin"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="fixed bottom-6 right-6 z-50 bg-[#25D366] hover:bg-[#1fb855] text-white rounded-full p-4 shadow-lg hover:shadow-xl transition-all group"
|
||||
aria-label="Contacter sur WhatsApp"
|
||||
>
|
||||
<svg className="w-7 h-7" fill="currentColor" viewBox="0 0 24 24">
|
||||
<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>
|
||||
<span className="absolute -top-2 -left-2 bg-white text-gray-800 text-[10px] font-bold px-2 py-0.5 rounded-full shadow-md opacity-0 group-hover:opacity-100 transition-opacity whitespace-nowrap">
|
||||
Je veux le m\u00eame jardin !
|
||||
</span>
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
function GalerieFiltrable({ realisations }: { realisations: Realisation[] }) {
|
||||
const [filter, setFilter] = useState("Tous");
|
||||
const types = ["Tous", "Terrasses", "Plantations", "All\u00e9es", "Entretien"];
|
||||
|
||||
const filtered = filter === "Tous" ? realisations : realisations.filter((r) => r.type === filter);
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* Filtres */}
|
||||
<div className="flex flex-wrap justify-center gap-2 mb-8">
|
||||
{types.map((t) => (
|
||||
<button
|
||||
key={t}
|
||||
onClick={() => setFilter(t)}
|
||||
className={`px-4 py-2 text-sm font-semibold rounded-full transition-colors cursor-pointer ${
|
||||
filter === t
|
||||
? "bg-green-600 text-white"
|
||||
: "bg-gray-100 text-gray-500 hover:bg-gray-200"
|
||||
}`}
|
||||
>
|
||||
{t}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Grille */}
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-5">
|
||||
{filtered.map((r, i) => (
|
||||
<div key={i} className="bg-[#f0f5ed] border border-gray-100 rounded-2xl overflow-hidden group hover:shadow-lg transition-shadow">
|
||||
<div className="h-48 bg-gradient-to-br from-green-100 to-green-50 flex items-center justify-center relative overflow-hidden">
|
||||
<div className="text-center">
|
||||
<svg className="w-12 h-12 text-green-300 mx-auto mb-2 group-hover:scale-110 transition-transform" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1} d="M5 3v4M3 5h4M6 17v4m-2-2h4m5-16l2.286 6.857L21 12l-5.714 2.143L13 21l-2.286-6.857L5 12l5.714-2.143L13 3z" />
|
||||
</svg>
|
||||
<p className="text-gray-400 text-xs">Photo HD du projet</p>
|
||||
</div>
|
||||
{/* Tag type */}
|
||||
<span className={`absolute top-3 left-3 text-[10px] font-bold px-2 py-0.5 rounded-full ${
|
||||
r.type === "Entretien" ? "bg-amber-100 text-amber-700" : "bg-green-100 text-green-700"
|
||||
}`}>
|
||||
{r.type}
|
||||
</span>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
<h3 className="text-gray-800 font-bold text-sm mb-1">{r.titre}</h3>
|
||||
<p className="text-gray-400 text-xs flex items-center gap-1">
|
||||
<svg className="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z" />
|
||||
</svg>
|
||||
{r.lieu}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,129 +1,187 @@
|
||||
import type { Metadata } from "next";
|
||||
import Link from "next/link";
|
||||
import Button from "@/components/ui/Button";
|
||||
import PaysagisteClient from "./PaysagisteClient";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "D\u00e9mo Site Paysagiste / Peintre - Pack Esth\u00e9tique",
|
||||
title: "D\u00e9mo Site Paysagiste / Peintre - L'Artisan Cr\u00e9ateur | HookLab",
|
||||
description:
|
||||
"D\u00e9couvrez le mod\u00e8le de site HookLab pour paysagistes et peintres. Design \u00e9pur\u00e9, galerie photo immersive, filtrage Cr\u00e9ation vs Entretien.",
|
||||
"Mod\u00e8le de site HookLab pour paysagistes, peintres et d\u00e9corateurs. Galerie filtrable, saisonnalit\u00e9 intelligente, bouton WhatsApp flottant.",
|
||||
};
|
||||
|
||||
const realisations = [
|
||||
{ titre: "Jardin contemporain", type: "Cr\u00e9ation", lieu: "Douai" },
|
||||
{ titre: "Terrasse bois & pergola", type: "Cr\u00e9ation", lieu: "Orchies" },
|
||||
{ titre: "Entretien parc 2000m\u00b2", type: "Entretien", lieu: "Valenciennes" },
|
||||
{ titre: "Am\u00e9nagement piscine", type: "Cr\u00e9ation", lieu: "Arleux" },
|
||||
{ titre: "Taille de haies & \u00e9lagage", type: "Entretien", lieu: "Flines-lez-Raches" },
|
||||
{ titre: "Jardin japonais", type: "Cr\u00e9ation", lieu: "Saint-Amand" },
|
||||
{ titre: "Jardin contemporain avec terrasse composite", type: "Terrasses", lieu: "Orchies", saison: "printemps" },
|
||||
{ titre: "Am\u00e9nagement complet piscine + cl\u00f4ture", type: "Terrasses", lieu: "Douai", saison: "printemps" },
|
||||
{ titre: "Cr\u00e9ation massif fleuri 4 saisons", type: "Plantations", lieu: "Valenciennes", saison: "printemps" },
|
||||
{ titre: "Haie brise-vue naturelle en bambou", type: "Plantations", lieu: "Arleux", saison: "automne" },
|
||||
{ titre: "All\u00e9e carrossable en pav\u00e9s anciens", type: "All\u00e9es", lieu: "Saint-Amand", saison: "automne" },
|
||||
{ titre: "Jardin japonais zen avec bassin", type: "Plantations", lieu: "Flines-lez-Raches", saison: "printemps" },
|
||||
{ titre: "Taille architecturale haies buis", type: "Entretien", lieu: "Denain", saison: "automne" },
|
||||
{ titre: "Entretien annuel parc 3000m\u00b2", type: "Entretien", lieu: "Douai", saison: "automne" },
|
||||
];
|
||||
|
||||
export default function PaysagisteDemo() {
|
||||
const currentMonth = new Date().getMonth();
|
||||
const isSpringSummer = currentMonth >= 2 && currentMonth <= 8;
|
||||
|
||||
return (
|
||||
<main className="min-h-screen bg-bg">
|
||||
{/* Nav simplifi\u00e9e */}
|
||||
<nav className="sticky top-0 z-50 bg-bg-white/90 backdrop-blur-md border-b border-border">
|
||||
<main className="min-h-screen bg-white">
|
||||
{/* Nav \u00e9pur\u00e9e */}
|
||||
<nav className="sticky top-0 z-50 bg-white/90 backdrop-blur-md border-b border-gray-100">
|
||||
<div className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8 flex items-center justify-between h-16">
|
||||
<div className="flex items-center gap-3">
|
||||
<Link href="/" className="text-text-muted hover:text-navy text-sm transition-colors">
|
||||
← Retour HookLab
|
||||
<Link href="/" className="text-gray-400 hover:text-gray-700 text-sm transition-colors">
|
||||
← HookLab
|
||||
</Link>
|
||||
<span className="text-border">|</span>
|
||||
<span className="text-navy font-bold text-sm">
|
||||
D\u00e9mo : <span className="text-orange">Pack Esth\u00e9tique</span>
|
||||
<span className="text-gray-200">|</span>
|
||||
<span className="text-gray-800 font-bold text-sm">
|
||||
[Votre Entreprise] — <span className="text-green-600">Paysagiste</span>
|
||||
</span>
|
||||
</div>
|
||||
<a
|
||||
href="tel:+33600000000"
|
||||
className="bg-orange hover:bg-orange/90 text-white font-bold text-sm px-4 py-2 rounded-lg transition-colors"
|
||||
href="tel:+33604408157"
|
||||
className="bg-green-600 hover:bg-green-700 text-white font-bold text-sm px-5 py-2 rounded-lg transition-colors"
|
||||
>
|
||||
Devis Gratuit
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
{/* Banni\u00e8re saisonni\u00e8re */}
|
||||
<div className={`text-center py-2 text-xs font-semibold ${isSpringSummer ? "bg-green-50 text-green-700" : "bg-amber-50 text-amber-700"}`}>
|
||||
{isSpringSummer
|
||||
? "C\u2019est la saison ! Cr\u00e9ation de terrasses & plantations \u2014 Demandez votre devis maintenant"
|
||||
: "Pr\u00e9parez le printemps ! Taille, \u00e9lagage & entretien d\u2019automne \u2014 Planifiez vos travaux"
|
||||
}
|
||||
</div>
|
||||
|
||||
{/* Hero \u00e9pur\u00e9 */}
|
||||
<section className="py-24 md:py-36 bg-[#1a2e1a] text-center relative overflow-hidden">
|
||||
<div className="absolute inset-0 bg-[radial-gradient(circle_at_50%_80%,rgba(34,139,34,0.15),transparent_70%)]" />
|
||||
<section className="py-24 md:py-36 bg-[#f0f5ed] text-center relative overflow-hidden">
|
||||
<div className="absolute inset-0 bg-[radial-gradient(circle_at_50%_80%,rgba(34,139,34,0.08),transparent_70%)]" />
|
||||
<div className="relative max-w-4xl mx-auto px-4">
|
||||
<span className="inline-block px-3 py-1.5 bg-green-500/20 border border-green-500/30 rounded-full text-green-400 text-xs font-semibold mb-6">
|
||||
Paysagisme & Espaces Verts
|
||||
<span className="inline-block px-3 py-1.5 bg-green-100 border border-green-200 rounded-full text-green-700 text-xs font-semibold mb-6">
|
||||
Paysagisme · Espaces Verts · D\u00e9coration
|
||||
</span>
|
||||
<h1 className="text-3xl sm:text-4xl md:text-5xl font-extrabold text-white leading-tight mb-6">
|
||||
[Votre Entreprise] — Paysagiste <span className="text-green-400">dans le Nord</span>
|
||||
<h1 className="text-3xl sm:text-4xl md:text-5xl font-extrabold text-gray-900 leading-tight mb-4">
|
||||
Ne vendez pas des travaux,{" "}
|
||||
<span className="text-green-600">vendez du r\u00eave.</span>
|
||||
</h1>
|
||||
<p className="text-white/60 text-lg max-w-2xl mx-auto mb-8">
|
||||
Cr\u00e9ation de jardins d’exception et entretien d’espaces verts.
|
||||
La nature est notre m\u00e9tier, la beaut\u00e9 notre signature.
|
||||
<p className="text-gray-500 text-lg max-w-2xl mx-auto mb-4">
|
||||
Pour un jardin ou un int\u00e9rieur, votre client n’ach\u00e8te pas de la technique,
|
||||
il ach\u00e8te une « ambiance ». Ce site est votre galerie d’art.
|
||||
</p>
|
||||
<p className="text-gray-400 text-sm mb-8">
|
||||
Cr\u00e9ations à Douai, Orchies, Valenciennes, Saint-Amand et environs.
|
||||
</p>
|
||||
<div className="flex flex-col sm:flex-row gap-4 justify-center">
|
||||
<Button size="lg" className="bg-green-600 hover:bg-green-700 border-green-600">
|
||||
Demander un Devis Cr\u00e9ation
|
||||
</Button>
|
||||
<Button size="lg" variant="outline" className="border-white/30 text-white hover:bg-white/10">
|
||||
Devis Entretien
|
||||
</Button>
|
||||
<a href="#devis">
|
||||
<Button size="lg" className="bg-green-600 hover:bg-green-700 border-green-600">
|
||||
Demander un Devis Cr\u00e9ation
|
||||
</Button>
|
||||
</a>
|
||||
<a href="#devis">
|
||||
<Button size="lg" variant="outline" className="border-green-300 text-green-700 hover:bg-green-50">
|
||||
Devis Entretien
|
||||
</Button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* R\u00e9alisations avec filtrage */}
|
||||
<section className="py-16 md:py-24 bg-bg-white">
|
||||
{/* R\u00e9alisations filtrables */}
|
||||
<section className="py-16 md:py-24 bg-white">
|
||||
<div className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="text-center mb-12">
|
||||
<h2 className="text-2xl md:text-3xl font-bold text-navy mb-3">
|
||||
Nos <span className="text-orange">r\u00e9alisations</span>
|
||||
<h2 className="text-2xl md:text-3xl font-bold text-gray-900 mb-3">
|
||||
Nos <span className="text-green-600">r\u00e9alisations</span>
|
||||
</h2>
|
||||
<p className="text-text-light mb-6">
|
||||
Filtrez par type de projet pour trouver l’inspiration.
|
||||
<p className="text-gray-500 mb-2">
|
||||
Des cr\u00e9ations dans des lieux que vous connaissez. Projetez-vous.
|
||||
</p>
|
||||
{/* Filtre visuel (d\u00e9mo statique) */}
|
||||
<div className="flex justify-center gap-3">
|
||||
<span className="px-4 py-2 bg-navy text-white text-sm font-semibold rounded-full">Tous</span>
|
||||
<span className="px-4 py-2 bg-bg border border-border text-text-light text-sm rounded-full cursor-pointer hover:border-navy transition-colors">Cr\u00e9ation</span>
|
||||
<span className="px-4 py-2 bg-bg border border-border text-text-light text-sm rounded-full cursor-pointer hover:border-navy transition-colors">Entretien</span>
|
||||
</div>
|
||||
</div>
|
||||
<PaysagisteClient realisations={realisations} />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
{realisations.map((r, i) => (
|
||||
<div key={i} className="bg-bg border border-border rounded-2xl overflow-hidden group">
|
||||
<div className="h-48 bg-green-50 flex items-center justify-center">
|
||||
<div className="text-center">
|
||||
<svg className="w-12 h-12 text-green-300 mx-auto mb-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1} d="M5 3v4M3 5h4M6 17v4m-2-2h4m5-16l2.286 6.857L21 12l-5.714 2.143L13 21l-2.286-6.857L5 12l5.714-2.143L13 3z" />
|
||||
</svg>
|
||||
<p className="text-text-muted text-xs">Photo du projet</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
<div className="flex items-center justify-between mb-2">
|
||||
<h3 className="text-navy font-bold text-sm">{r.titre}</h3>
|
||||
<span className={`text-xs font-semibold px-2 py-0.5 rounded-full ${
|
||||
r.type === "Cr\u00e9ation" ? "bg-green-100 text-green-700" : "bg-blue-100 text-blue-700"
|
||||
}`}>
|
||||
{r.type}
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-text-muted text-xs">{r.lieu}</p>
|
||||
{/* Immersion locale */}
|
||||
<section className="py-16 md:py-24 bg-[#f0f5ed]">
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
|
||||
<h2 className="text-2xl md:text-3xl font-bold text-gray-900 mb-10">
|
||||
Des jardins pr\u00e8s de <span className="text-green-600">chez vous</span>
|
||||
</h2>
|
||||
<div className="grid grid-cols-2 md:grid-cols-3 gap-4">
|
||||
{["Douai", "Orchies", "Valenciennes", "Arleux", "Saint-Amand", "Denain"].map((ville) => (
|
||||
<div key={ville} className="bg-white rounded-xl p-4 border border-gray-100 hover:shadow-md transition-shadow">
|
||||
<div className="w-10 h-10 bg-green-100 rounded-full flex items-center justify-center mx-auto mb-2">
|
||||
<svg className="w-5 h-5 text-green-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z" />
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 11a3 3 0 11-6 0 3 3 0 016 0z" />
|
||||
</svg>
|
||||
</div>
|
||||
<p className="text-gray-800 font-semibold text-sm">Jardin \u00e0 {ville}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* CTA */}
|
||||
<section className="py-16 bg-[#1a2e1a] text-center">
|
||||
{/* Formulaire */}
|
||||
<section id="devis" className="py-16 md:py-24 bg-gray-900">
|
||||
<div className="max-w-2xl mx-auto px-4">
|
||||
<p className="text-orange text-xs font-semibold uppercase tracking-wider mb-3">Ceci est une d\u00e9mo HookLab</p>
|
||||
<div className="text-center mb-10">
|
||||
<h2 className="text-2xl md:text-3xl font-bold text-white mb-3">
|
||||
Demander un <span className="text-green-400">devis gratuit</span>
|
||||
</h2>
|
||||
<p className="text-white/60">D\u00e9crivez votre projet, on vous recontacte sous 24h.</p>
|
||||
</div>
|
||||
<div className="bg-white rounded-2xl p-6 sm:p-8">
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1.5">Type de projet</label>
|
||||
<select className="w-full px-4 py-3 bg-gray-50 border border-gray-200 rounded-xl text-gray-800 text-sm focus:border-green-500 focus:ring-1 focus:ring-green-500 outline-none">
|
||||
<option>Cr\u00e9ation de jardin complet</option>
|
||||
<option>Terrasse / Am\u00e9nagement</option>
|
||||
<option>Plantation / Massifs</option>
|
||||
<option>Entretien r\u00e9gulier</option>
|
||||
<option>Taille / \u00c9lagage</option>
|
||||
<option>Cl\u00f4ture / Brise-vue</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1.5">Votre nom</label>
|
||||
<input type="text" placeholder="Votre nom" className="w-full px-4 py-3 bg-gray-50 border border-gray-200 rounded-xl text-gray-800 text-sm placeholder:text-gray-400 focus:border-green-500 focus:ring-1 focus:ring-green-500 outline-none" />
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1.5">T\u00e9l\u00e9phone</label>
|
||||
<input type="tel" placeholder="06 12 34 56 78" className="w-full px-4 py-3 bg-gray-50 border border-gray-200 rounded-xl text-gray-800 text-sm placeholder:text-gray-400 focus:border-green-500 focus:ring-1 focus:ring-green-500 outline-none" />
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1.5">D\u00e9crivez votre projet</label>
|
||||
<textarea rows={3} placeholder="Surface, style souhait\u00e9, budget approximatif..." className="w-full px-4 py-3 bg-gray-50 border border-gray-200 rounded-xl text-gray-800 text-sm placeholder:text-gray-400 focus:border-green-500 focus:ring-1 focus:ring-green-500 outline-none resize-none" />
|
||||
</div>
|
||||
<Button size="lg" className="w-full bg-green-600 hover:bg-green-700 border-green-600">
|
||||
Envoyer ma demande
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* WhatsApp flottant */}
|
||||
<PaysagisteClient whatsapp />
|
||||
|
||||
{/* CTA HookLab */}
|
||||
<section className="py-16 bg-green-600 text-center">
|
||||
<div className="max-w-2xl mx-auto px-4">
|
||||
<p className="text-white/80 text-xs font-semibold uppercase tracking-wider mb-3">Ceci est une d\u00e9mo HookLab</p>
|
||||
<h2 className="text-2xl md:text-3xl font-bold text-white mb-4">
|
||||
Ce design vous pla\u00eet ? Il peut être à vous.
|
||||
Ce design vous pla\u00eet ? Il peut \u00eatre \u00e0 vous.
|
||||
</h2>
|
||||
<p className="text-white/60 mb-6">
|
||||
<p className="text-white/80 mb-6">
|
||||
Imaginez vos plus beaux jardins mis en valeur comme \u00e7a. C’est ce que je cr\u00e9e pour les paysagistes du Nord.
|
||||
</p>
|
||||
<Link href="/#contact">
|
||||
<Button size="lg" className="bg-green-600 hover:bg-green-700 border-green-600">
|
||||
<Button size="lg" className="bg-gray-900 hover:bg-gray-800 border-gray-900">
|
||||
Demander Mon Audit Gratuit
|
||||
</Button>
|
||||
</Link>
|
||||
|
||||
189
app/plombier/PlombierClient.tsx
Normal file
189
app/plombier/PlombierClient.tsx
Normal file
@@ -0,0 +1,189 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import Button from "@/components/ui/Button";
|
||||
|
||||
interface PlombierClientProps {
|
||||
type: "diagnostic" | "sticky";
|
||||
}
|
||||
|
||||
export default function PlombierClient({ type }: PlombierClientProps) {
|
||||
if (type === "sticky") return <StickyCall />;
|
||||
if (type === "diagnostic") return <Diagnostic />;
|
||||
return null;
|
||||
}
|
||||
|
||||
function StickyCall() {
|
||||
return (
|
||||
<div className="fixed bottom-0 left-0 right-0 z-50 md:hidden bg-[#0a1628] border-t border-white/10 p-3 safe-area-bottom">
|
||||
<a
|
||||
href="tel:+33604408157"
|
||||
className="flex items-center justify-center gap-3 bg-[#3b82f6] hover:bg-[#2563eb] text-white font-bold text-base py-3.5 rounded-xl w-full transition-colors"
|
||||
>
|
||||
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z" />
|
||||
</svg>
|
||||
Appeler maintenant — 06 04 40 81 57
|
||||
</a>
|
||||
<p className="text-white/40 text-[10px] text-center mt-1">Devis gratuit · Pas de surprise</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function Diagnostic() {
|
||||
const [step, setStep] = useState(0);
|
||||
const [answers, setAnswers] = useState<string[]>([]);
|
||||
|
||||
const questions = [
|
||||
{
|
||||
question: "Quel est le probl\u00e8me ?",
|
||||
options: [
|
||||
{ icon: "\ud83d\udca7", label: "Fuite d\u2019eau" },
|
||||
{ icon: "\ud83d\udebd", label: "Canalisation bouch\u00e9e" },
|
||||
{ icon: "\ud83d\udd25", label: "Panne chauffe-eau" },
|
||||
{ icon: "\ud83d\udee0\ufe0f", label: "Autre probl\u00e8me" },
|
||||
],
|
||||
},
|
||||
{
|
||||
question: "Quel niveau d\u2019urgence ?",
|
||||
options: [
|
||||
{ icon: "\ud83d\udea8", label: "Urgent (fuite active)" },
|
||||
{ icon: "\u23f0", label: "Sous 48h" },
|
||||
{ icon: "\ud83d\udcc5", label: "Travaux planifi\u00e9s" },
|
||||
],
|
||||
},
|
||||
{
|
||||
question: "O\u00f9 \u00eates-vous situ\u00e9 ?",
|
||||
options: [
|
||||
{ icon: "\ud83d\udccd", label: "Douai / Environs" },
|
||||
{ icon: "\ud83d\udccd", label: "Orchies / Environs" },
|
||||
{ icon: "\ud83d\udccd", label: "Valenciennes / Environs" },
|
||||
{ icon: "\ud83d\udccd", label: "Autre secteur" },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
if (step >= questions.length) {
|
||||
const isUrgent = answers[1]?.includes("Urgent");
|
||||
const isOutOfZone = answers[2]?.includes("Autre");
|
||||
|
||||
if (isOutOfZone) {
|
||||
return (
|
||||
<div className="bg-white rounded-2xl p-6 sm:p-8 text-center">
|
||||
<div className="w-16 h-16 bg-amber-100 rounded-full flex items-center justify-center mx-auto mb-4">
|
||||
<span className="text-3xl">\ud83d\udccd</span>
|
||||
</div>
|
||||
<h3 className="text-gray-900 font-bold text-xl mb-2">Vous \u00eates hors de notre zone principale</h3>
|
||||
<p className="text-gray-500 text-sm mb-6">
|
||||
Notre rayon d’action est Douai + 25km. Appelez-nous quand m\u00eame,
|
||||
on trouvera peut-\u00eatre une solution !
|
||||
</p>
|
||||
<a
|
||||
href="tel:+33604408157"
|
||||
className="inline-flex items-center justify-center gap-2 bg-[#3b82f6] hover:bg-[#2563eb] text-white font-bold px-6 py-3 rounded-xl transition-colors"
|
||||
>
|
||||
Appeler quand m\u00eame
|
||||
</a>
|
||||
<button onClick={() => { setStep(0); setAnswers([]); }} className="block mx-auto mt-4 text-gray-400 hover:text-gray-600 text-sm underline cursor-pointer">
|
||||
Recommencer le diagnostic
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (isUrgent) {
|
||||
return (
|
||||
<div className="bg-white rounded-2xl p-6 sm:p-8 text-center">
|
||||
<div className="w-16 h-16 bg-red-100 rounded-full flex items-center justify-center mx-auto mb-4 animate-pulse">
|
||||
<span className="text-3xl">\ud83d\udea8</span>
|
||||
</div>
|
||||
<h3 className="text-gray-900 font-bold text-xl mb-2">Urgence d\u00e9tect\u00e9e !</h3>
|
||||
<p className="text-gray-500 text-sm mb-2">
|
||||
<strong>{answers[0]}</strong> — {answers[2]}
|
||||
</p>
|
||||
<p className="text-gray-400 text-sm mb-6">Pour une intervention imm\u00e9diate, appelez directement :</p>
|
||||
<a
|
||||
href="tel:+33604408157"
|
||||
className="inline-flex items-center justify-center gap-3 bg-red-600 hover:bg-red-700 text-white font-bold text-lg px-8 py-4 rounded-xl transition-colors w-full"
|
||||
>
|
||||
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z" />
|
||||
</svg>
|
||||
APPELER MAINTENANT
|
||||
</a>
|
||||
<p className="text-gray-400 text-xs mt-3">Disponible 7j/7 · Devis gratuit</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Non urgent
|
||||
return (
|
||||
<div className="bg-white rounded-2xl p-6 sm:p-8">
|
||||
<div className="text-center mb-6">
|
||||
<div className="w-16 h-16 bg-blue-100 rounded-full flex items-center justify-center mx-auto mb-4">
|
||||
<span className="text-3xl">\u2705</span>
|
||||
</div>
|
||||
<h3 className="text-gray-900 font-bold text-xl mb-1">Diagnostic re\u00e7u !</h3>
|
||||
<p className="text-gray-500 text-sm">
|
||||
<strong>{answers[0]}</strong> — {answers[1]} — {answers[2]}
|
||||
</p>
|
||||
</div>
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1.5">Votre t\u00e9l\u00e9phone</label>
|
||||
<input type="tel" placeholder="06 12 34 56 78" className="w-full px-4 py-3 bg-gray-50 border border-gray-200 rounded-xl text-gray-800 text-sm placeholder:text-gray-400 focus:border-blue-500 focus:ring-1 focus:ring-blue-500 outline-none" />
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1.5">Pr\u00e9cisions (facultatif)</label>
|
||||
<textarea rows={2} placeholder="D\u00e9crivez votre probl\u00e8me en quelques mots..." className="w-full px-4 py-3 bg-gray-50 border border-gray-200 rounded-xl text-gray-800 text-sm placeholder:text-gray-400 focus:border-blue-500 focus:ring-1 focus:ring-blue-500 outline-none resize-none" />
|
||||
</div>
|
||||
<Button size="lg" className="w-full bg-[#3b82f6] hover:bg-[#2563eb] border-[#3b82f6]">
|
||||
Envoyer — On vous rappelle sous 24h
|
||||
</Button>
|
||||
</div>
|
||||
<button onClick={() => { setStep(0); setAnswers([]); }} className="block mx-auto mt-4 text-gray-400 hover:text-gray-600 text-sm underline cursor-pointer">
|
||||
Recommencer
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const q = questions[step];
|
||||
|
||||
return (
|
||||
<div className="bg-white rounded-2xl p-6 sm:p-8">
|
||||
{/* Progress */}
|
||||
<div className="flex items-center gap-2 mb-6">
|
||||
{questions.map((_, i) => (
|
||||
<div key={i} className={`h-1.5 flex-1 rounded-full transition-colors ${i <= step ? "bg-[#3b82f6]" : "bg-gray-200"}`} />
|
||||
))}
|
||||
</div>
|
||||
|
||||
<h3 className="text-gray-900 font-bold text-lg mb-5">{q.question}</h3>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
|
||||
{q.options.map((opt) => (
|
||||
<button
|
||||
key={opt.label}
|
||||
onClick={() => {
|
||||
setAnswers([...answers, opt.label]);
|
||||
setStep(step + 1);
|
||||
}}
|
||||
className="p-4 rounded-xl border-2 border-gray-200 bg-gray-50 hover:border-[#3b82f6] hover:shadow-md text-left transition-all cursor-pointer"
|
||||
>
|
||||
<span className="text-2xl block mb-1">{opt.icon}</span>
|
||||
<p className="text-gray-900 font-semibold text-sm">{opt.label}</p>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{step > 0 && (
|
||||
<button
|
||||
onClick={() => { setStep(step - 1); setAnswers(answers.slice(0, -1)); }}
|
||||
className="mt-4 text-gray-400 hover:text-gray-600 text-sm underline cursor-pointer"
|
||||
>
|
||||
← Retour
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,169 +1,210 @@
|
||||
import type { Metadata } from "next";
|
||||
import Link from "next/link";
|
||||
import Button from "@/components/ui/Button";
|
||||
import PlombierClient from "./PlombierClient";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "D\u00e9mo Site Plombier / \u00c9lectricien - Pack Urgence & Service",
|
||||
title: "D\u00e9mo Site Plombier / \u00c9lectricien - L'Intervention \u00c9clair | HookLab",
|
||||
description:
|
||||
"D\u00e9couvrez le mod\u00e8le de site HookLab pour plombiers et \u00e9lectriciens. Chargement \u00e9clair, tarifs clairs, formulaire de diagnostic rapide.",
|
||||
"Mod\u00e8le de site HookLab pour plombiers, \u00e9lectriciens et serruriers. Bouton d\u2019appel sticky, diagnostic en ligne, zone d\u2019intervention, tarifs clairs.",
|
||||
};
|
||||
|
||||
const tarifs = [
|
||||
{ service: "D\u00e9pannage fuite", prix: "\u00c0 partir de 89\u20ac", urgence: true },
|
||||
{ service: "Remplacement chauffe-eau", prix: "\u00c0 partir de 350\u20ac", urgence: false },
|
||||
{ service: "D\u00e9bouchage canalisation", prix: "\u00c0 partir de 120\u20ac", urgence: true },
|
||||
{ service: "Installation sanitaire", prix: "Sur devis", urgence: false },
|
||||
{ service: "Remplacement chauffe-eau", prix: "\u00c0 partir de 350\u20ac", urgence: false },
|
||||
{ service: "Installation sanitaire compl\u00e8te", prix: "Sur devis", urgence: false },
|
||||
{ service: "Recherche de fuite", prix: "\u00c0 partir de 150\u20ac", urgence: true },
|
||||
{ service: "R\u00e9novation salle de bain", prix: "Sur devis", urgence: false },
|
||||
];
|
||||
|
||||
const avis = [
|
||||
{ name: "Laurent P.", ville: "Douai", text: "Fuite \u00e0 22h un samedi. Intervention en 45 min. Prix correct, travail pro. Merci !", note: 5 },
|
||||
{ name: "Marie C.", ville: "Orchies", text: "Chauffe-eau en panne en plein hiver. Remplac\u00e9 le lendemain matin. Service impeccable.", note: 5 },
|
||||
{ name: "Jean-Marc B.", ville: "Valenciennes", text: "Canalisation bouch\u00e9e, devis clair au t\u00e9l\u00e9phone, pas de surprise \u00e0 la facture. Rare !", note: 5 },
|
||||
];
|
||||
|
||||
export default function PlombierDemo() {
|
||||
return (
|
||||
<main className="min-h-screen bg-bg">
|
||||
{/* Nav urgence */}
|
||||
<nav className="sticky top-0 z-50 bg-navy border-b border-white/10">
|
||||
<main className="min-h-screen bg-[#0a1628]">
|
||||
{/* Nav avec avis + t\u00e9l */}
|
||||
<nav className="sticky top-0 z-50 bg-[#0a1628] border-b border-white/10">
|
||||
<div className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8 flex items-center justify-between h-16">
|
||||
<div className="flex items-center gap-3">
|
||||
<Link href="/" className="text-white/60 hover:text-white text-sm transition-colors">
|
||||
← Retour HookLab
|
||||
<Link href="/" className="text-white/50 hover:text-white text-sm transition-colors">
|
||||
← HookLab
|
||||
</Link>
|
||||
<span className="text-white/30">|</span>
|
||||
<span className="text-white/20">|</span>
|
||||
<span className="text-white font-bold text-sm">
|
||||
D\u00e9mo : <span className="text-orange">Pack Urgence</span>
|
||||
[Votre Entreprise] — <span className="text-[#3b82f6]">Plombier</span>
|
||||
</span>
|
||||
</div>
|
||||
<a
|
||||
href="tel:+33600000000"
|
||||
className="bg-red-600 hover:bg-red-700 text-white font-bold text-sm px-5 py-2.5 rounded-lg transition-colors animate-pulse flex items-center gap-2"
|
||||
>
|
||||
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z" />
|
||||
</svg>
|
||||
URGENCE 7j/7
|
||||
</a>
|
||||
<div className="flex items-center gap-3">
|
||||
{/* Avis Google */}
|
||||
<div className="hidden sm:flex items-center gap-1.5 bg-yellow-500/10 border border-yellow-500/20 rounded-full px-3 py-1">
|
||||
<div className="flex gap-0.5">
|
||||
{[...Array(5)].map((_, i) => (
|
||||
<svg key={i} className="w-3 h-3 text-yellow-400" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z" />
|
||||
</svg>
|
||||
))}
|
||||
</div>
|
||||
<span className="text-yellow-300 text-xs font-semibold">4.9/5</span>
|
||||
</div>
|
||||
<a
|
||||
href="tel:+33604408157"
|
||||
className="bg-[#3b82f6] hover:bg-[#2563eb] text-white font-bold text-sm px-4 py-2 rounded-lg transition-colors flex items-center gap-2"
|
||||
>
|
||||
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z" />
|
||||
</svg>
|
||||
06 04 40 81 57
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
{/* Hero rapide */}
|
||||
<section className="py-16 md:py-24 bg-navy text-center">
|
||||
{/* Hero ultra-direct */}
|
||||
<section className="py-16 md:py-24 bg-[#0a1628] text-center">
|
||||
<div className="max-w-4xl mx-auto px-4">
|
||||
<div className="inline-flex items-center gap-2 bg-red-600/20 border border-red-500/30 rounded-full px-4 py-2 mb-6">
|
||||
<span className="w-2 h-2 bg-red-500 rounded-full animate-pulse" />
|
||||
<span className="text-red-400 text-xs font-semibold">Disponible 7j/7 — Intervention rapide</span>
|
||||
</div>
|
||||
<h1 className="text-3xl sm:text-4xl md:text-5xl font-extrabold text-white leading-tight mb-6">
|
||||
[Votre Entreprise] — Plombier <span className="text-orange">dans le Nord</span>
|
||||
<h1 className="text-3xl sm:text-4xl md:text-5xl font-extrabold text-white leading-tight mb-4">
|
||||
Convaincre en{" "}
|
||||
<span className="text-[#facc15]">3 secondes chrono.</span>
|
||||
</h1>
|
||||
<p className="text-white/60 text-lg max-w-2xl mx-auto mb-8">
|
||||
Fuite, panne, urgence ? Intervention rapide sur Douai, Orchies
|
||||
et Valenciennes. Tarifs transparents, devis gratuit.
|
||||
<p className="text-white/50 text-lg max-w-2xl mx-auto mb-4">
|
||||
Quand un client a une fuite d’eau ou une panne de courant, il ne veut pas lire
|
||||
votre histoire. Il veut un num\u00e9ro, un prix, et une arriv\u00e9e rapide.
|
||||
</p>
|
||||
<p className="text-white/30 text-sm mb-8">
|
||||
D\u00e9pannage Douai · Orchies · Valenciennes · Denain · Saint-Amand · Arleux
|
||||
</p>
|
||||
<a
|
||||
href="tel:+33600000000"
|
||||
className="inline-flex items-center gap-3 bg-red-600 hover:bg-red-700 text-white font-bold text-lg px-8 py-4 rounded-xl transition-colors"
|
||||
href="tel:+33604408157"
|
||||
className="inline-flex items-center gap-3 bg-[#3b82f6] hover:bg-[#2563eb] text-white font-bold text-xl px-10 py-5 rounded-2xl transition-colors shadow-lg shadow-blue-500/20"
|
||||
>
|
||||
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<svg className="w-7 h-7" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z" />
|
||||
</svg>
|
||||
Appeler Maintenant
|
||||
</a>
|
||||
<p className="text-white/40 text-sm mt-3">Pas de surprise : devis gratuit avant intervention</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Tarifs clairs */}
|
||||
<section className="py-16 md:py-24 bg-bg-white">
|
||||
<section className="py-16 md:py-24 bg-white">
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="text-center mb-12">
|
||||
<h2 className="text-2xl md:text-3xl font-bold text-navy mb-3">
|
||||
Tarifs <span className="text-orange">transparents</span>
|
||||
<h2 className="text-2xl md:text-3xl font-bold text-gray-900 mb-3">
|
||||
Tarifs <span className="text-[#3b82f6]">transparents</span>
|
||||
</h2>
|
||||
<p className="text-text-light">Pas de surprise. Vous savez ce que vous payez.</p>
|
||||
<p className="text-gray-500">Pas de surprise. Vous savez ce que vous payez avant qu’on se d\u00e9place.</p>
|
||||
</div>
|
||||
|
||||
<div className="space-y-3">
|
||||
{tarifs.map((t, i) => (
|
||||
<div key={i} className="flex items-center justify-between bg-bg border border-border rounded-xl p-5">
|
||||
<div key={i} className="flex items-center justify-between bg-gray-50 border border-gray-200 rounded-xl p-5 hover:shadow-sm transition-shadow">
|
||||
<div className="flex items-center gap-3">
|
||||
{t.urgence && (
|
||||
<span className="w-2 h-2 bg-red-500 rounded-full shrink-0" />
|
||||
)}
|
||||
<span className="text-navy font-semibold text-sm">{t.service}</span>
|
||||
{t.urgence && (
|
||||
<span className="text-xs bg-red-100 text-red-600 font-semibold px-2 py-0.5 rounded-full">Urgence</span>
|
||||
)}
|
||||
{t.urgence && <span className="w-2 h-2 bg-red-500 rounded-full shrink-0" />}
|
||||
<span className="text-gray-900 font-semibold text-sm">{t.service}</span>
|
||||
{t.urgence && <span className="text-xs bg-red-100 text-red-600 font-semibold px-2 py-0.5 rounded-full">Urgence</span>}
|
||||
</div>
|
||||
<span className="text-orange font-bold text-sm">{t.prix}</span>
|
||||
<span className="text-[#3b82f6] font-bold text-sm">{t.prix}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Diagnostic rapide */}
|
||||
<section className="py-16 md:py-24 bg-bg">
|
||||
{/* Diagnostic en ligne */}
|
||||
<section className="py-16 md:py-24 bg-gray-50">
|
||||
<div className="max-w-2xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="text-center mb-10">
|
||||
<h2 className="text-2xl md:text-3xl font-bold text-navy mb-3">
|
||||
Diagnostic <span className="text-orange">rapide</span>
|
||||
<h2 className="text-2xl md:text-3xl font-bold text-gray-900 mb-3">
|
||||
Diagnostic <span className="text-[#3b82f6]">en ligne</span>
|
||||
</h2>
|
||||
<p className="text-text-light">D\u00e9crivez votre probl\u00e8me en 30 secondes. On vous rappelle avec une solution.</p>
|
||||
<p className="text-gray-500">3 questions simples. On qualifie la panne avant de d\u00e9crocher.</p>
|
||||
</div>
|
||||
<PlombierClient type="diagnostic" />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div className="bg-bg-white border border-border rounded-2xl p-6 sm:p-8">
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-text mb-1.5">Type de probl\u00e8me</label>
|
||||
<select className="w-full px-4 py-3 bg-bg border border-border rounded-xl text-text text-sm focus:border-orange focus:ring-1 focus:ring-orange outline-none">
|
||||
<option>Fuite d'eau</option>
|
||||
<option>Canalisation bouch\u00e9e</option>
|
||||
<option>Panne chauffe-eau</option>
|
||||
<option>Probl\u00e8me radiateur</option>
|
||||
<option>Autre</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-text mb-1.5">Niveau d'urgence</label>
|
||||
<div className="grid grid-cols-3 gap-3">
|
||||
<div className="border-2 border-red-300 bg-red-50 rounded-xl p-3 text-center cursor-pointer">
|
||||
<p className="text-red-600 font-bold text-sm">Urgent</p>
|
||||
<p className="text-text-muted text-xs">Fuite active</p>
|
||||
</div>
|
||||
<div className="border border-border rounded-xl p-3 text-center cursor-pointer hover:border-orange transition-colors">
|
||||
<p className="text-navy font-bold text-sm">Mod\u00e9r\u00e9</p>
|
||||
<p className="text-text-muted text-xs">Sous 48h</p>
|
||||
</div>
|
||||
<div className="border border-border rounded-xl p-3 text-center cursor-pointer hover:border-orange transition-colors">
|
||||
<p className="text-navy font-bold text-sm">Planifi\u00e9</p>
|
||||
<p className="text-text-muted text-xs">Travaux</p>
|
||||
</div>
|
||||
{/* Avis */}
|
||||
<section className="py-16 md:py-24 bg-white">
|
||||
<div className="max-w-4xl mx-auto px-4 text-center">
|
||||
<h2 className="text-2xl md:text-3xl font-bold text-gray-900 mb-10">
|
||||
Avis <span className="text-[#facc15]">Google</span> v\u00e9rifi\u00e9s
|
||||
</h2>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
{avis.map((a, i) => (
|
||||
<div key={i} className="bg-gray-50 border border-gray-200 rounded-xl p-6 text-left">
|
||||
<div className="flex gap-0.5 mb-3">
|
||||
{[...Array(a.note)].map((_, j) => (
|
||||
<svg key={j} className="w-4 h-4 text-yellow-400" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z" />
|
||||
</svg>
|
||||
))}
|
||||
</div>
|
||||
<p className="text-gray-600 text-sm leading-relaxed mb-3">“{a.text}”</p>
|
||||
<p className="text-gray-900 font-semibold text-sm">{a.name} — <span className="text-gray-400 font-normal">{a.ville}</span></p>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-text mb-1.5">Votre t\u00e9l\u00e9phone</label>
|
||||
<input
|
||||
type="tel"
|
||||
placeholder="06 12 34 56 78"
|
||||
className="w-full px-4 py-3 bg-bg border border-border rounded-xl text-text text-sm placeholder:text-text-muted focus:border-orange focus:ring-1 focus:ring-orange outline-none"
|
||||
/>
|
||||
</div>
|
||||
<Button size="lg" className="w-full">
|
||||
Envoyer le Diagnostic
|
||||
</Button>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* CTA */}
|
||||
<section className="py-16 bg-navy text-center">
|
||||
{/* Zone d'intervention avec carte */}
|
||||
<section className="py-16 md:py-24 bg-gray-50">
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="text-center mb-10">
|
||||
<h2 className="text-2xl md:text-3xl font-bold text-gray-900 mb-3">
|
||||
Zone <span className="text-[#3b82f6]">d’intervention</span>
|
||||
</h2>
|
||||
<p className="text-gray-500">Douai + 25km. D\u00e9pannage rapide dans tout le secteur.</p>
|
||||
</div>
|
||||
<div className="bg-white border border-gray-200 rounded-2xl overflow-hidden">
|
||||
<div className="relative h-64 sm:h-80">
|
||||
<iframe
|
||||
src="https://www.openstreetmap.org/export/embed.html?bbox=2.6%2C50.2%2C3.8%2C50.55&layer=mapnik&marker=50.4267%2C3.2372"
|
||||
className="absolute inset-0 w-full h-full border-0"
|
||||
title="Zone d'intervention plombier"
|
||||
loading="lazy"
|
||||
/>
|
||||
</div>
|
||||
<div className="p-4 border-t border-gray-100">
|
||||
<div className="flex flex-wrap gap-2 justify-center">
|
||||
{["Douai", "Orchies", "Valenciennes", "Denain", "Saint-Amand", "Arleux", "Flines-lez-Raches"].map((v) => (
|
||||
<span key={v} className="bg-blue-50 text-[#3b82f6] text-xs font-semibold px-3 py-1 rounded-full">{v}</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-gray-400 text-xs text-center mt-4">
|
||||
Vous \u00eates hors zone ? Contactez-nous, on trouvera une solution.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Sticky Call Mobile */}
|
||||
<PlombierClient type="sticky" />
|
||||
|
||||
{/* CTA HookLab */}
|
||||
<section className="py-16 bg-[#3b82f6] text-center">
|
||||
<div className="max-w-2xl mx-auto px-4">
|
||||
<p className="text-orange text-xs font-semibold uppercase tracking-wider mb-3">Ceci est une d\u00e9mo HookLab</p>
|
||||
<p className="text-white/80 text-xs font-semibold uppercase tracking-wider mb-3">Ceci est une d\u00e9mo HookLab</p>
|
||||
<h2 className="text-2xl md:text-3xl font-bold text-white mb-4">
|
||||
Ce site peut être le vôtre demain.
|
||||
Ce site peut \u00eatre le v\u00f4tre demain.
|
||||
</h2>
|
||||
<p className="text-white/60 mb-6">
|
||||
Un site qui rassure, qui qualifie les urgences, et qui vous fait gagner du temps. C’est ce que je construis pour les plombiers et \u00e9lectriciens du Nord.
|
||||
<p className="text-white/80 mb-6">
|
||||
Un site qui rassure, qui qualifie les urgences, et qui vous fait gagner du temps.
|
||||
C’est ce que je construis pour les plombiers et \u00e9lectriciens du Nord.
|
||||
</p>
|
||||
<Link href="/#contact">
|
||||
<Button size="lg" className="pulse-glow">
|
||||
<Button size="lg" className="bg-[#0a1628] hover:bg-[#0a1628]/90 border-[#0a1628]">
|
||||
Demander Mon Audit Gratuit
|
||||
</Button>
|
||||
</Link>
|
||||
|
||||
19
app/site-internet-artisan-arleux/page.tsx
Normal file
19
app/site-internet-artisan-arleux/page.tsx
Normal file
@@ -0,0 +1,19 @@
|
||||
import type { Metadata } from "next";
|
||||
import LocalSeoPage from "@/components/marketing/LocalSeoPage";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Création Site Internet Artisan Arleux (59) | HookLab",
|
||||
description:
|
||||
"Création de sites internet pour artisans à Arleux et environs. Visibilité Google, site ultra-rapide, système de confiance. Audit gratuit.",
|
||||
};
|
||||
|
||||
export default function Page() {
|
||||
return (
|
||||
<LocalSeoPage
|
||||
ville="Arleux"
|
||||
villeSlug="arleux"
|
||||
codePostal="59151"
|
||||
voisines={["Douai", "Orchies", "Flines-lez-Raches"]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
19
app/site-internet-artisan-denain/page.tsx
Normal file
19
app/site-internet-artisan-denain/page.tsx
Normal file
@@ -0,0 +1,19 @@
|
||||
import type { Metadata } from "next";
|
||||
import LocalSeoPage from "@/components/marketing/LocalSeoPage";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Création Site Internet Artisan Denain (59) | HookLab",
|
||||
description:
|
||||
"Sites web professionnels pour artisans du bâtiment à Denain. Maçon, couvreur, plombier, paysagiste. SEO local + audit offert.",
|
||||
};
|
||||
|
||||
export default function Page() {
|
||||
return (
|
||||
<LocalSeoPage
|
||||
ville="Denain"
|
||||
villeSlug="denain"
|
||||
codePostal="59220"
|
||||
voisines={["Valenciennes", "Douai", "Saint-Amand-les-Eaux"]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
19
app/site-internet-artisan-douai/page.tsx
Normal file
19
app/site-internet-artisan-douai/page.tsx
Normal file
@@ -0,0 +1,19 @@
|
||||
import type { Metadata } from "next";
|
||||
import LocalSeoPage from "@/components/marketing/LocalSeoPage";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Création Site Internet Artisan Douai (59) | HookLab",
|
||||
description:
|
||||
"Spécialiste création de sites web pour artisans du bâtiment à Douai et environs. Couvreur, maçon, paysagiste, plombier. Audit gratuit.",
|
||||
};
|
||||
|
||||
export default function Page() {
|
||||
return (
|
||||
<LocalSeoPage
|
||||
ville="Douai"
|
||||
villeSlug="douai"
|
||||
codePostal="59500"
|
||||
voisines={["Orchies", "Arleux", "Flines-lez-Raches"]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
19
app/site-internet-artisan-orchies/page.tsx
Normal file
19
app/site-internet-artisan-orchies/page.tsx
Normal file
@@ -0,0 +1,19 @@
|
||||
import type { Metadata } from "next";
|
||||
import LocalSeoPage from "@/components/marketing/LocalSeoPage";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Création Site Internet Artisan Orchies (59) | HookLab",
|
||||
description:
|
||||
"Création de sites web professionnels pour artisans à Orchies. Couvreur, maçon, paysagiste. Site rapide + SEO local. Audit offert.",
|
||||
};
|
||||
|
||||
export default function Page() {
|
||||
return (
|
||||
<LocalSeoPage
|
||||
ville="Orchies"
|
||||
villeSlug="orchies"
|
||||
codePostal="59310"
|
||||
voisines={["Douai", "Flines-lez-Raches", "Saint-Amand-les-Eaux"]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
19
app/site-internet-artisan-saint-amand-les-eaux/page.tsx
Normal file
19
app/site-internet-artisan-saint-amand-les-eaux/page.tsx
Normal file
@@ -0,0 +1,19 @@
|
||||
import type { Metadata } from "next";
|
||||
import LocalSeoPage from "@/components/marketing/LocalSeoPage";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Création Site Internet Artisan Saint-Amand-les-Eaux (59) | HookLab",
|
||||
description:
|
||||
"Votre site web professionnel d'artisan à Saint-Amand-les-Eaux. Couvreur, plombier, paysagiste. Conçu pour générer des chantiers. Audit offert.",
|
||||
};
|
||||
|
||||
export default function Page() {
|
||||
return (
|
||||
<LocalSeoPage
|
||||
ville="Saint-Amand-les-Eaux"
|
||||
villeSlug="saint-amand-les-eaux"
|
||||
codePostal="59230"
|
||||
voisines={["Valenciennes", "Orchies", "Denain"]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
19
app/site-internet-artisan-valenciennes/page.tsx
Normal file
19
app/site-internet-artisan-valenciennes/page.tsx
Normal file
@@ -0,0 +1,19 @@
|
||||
import type { Metadata } from "next";
|
||||
import LocalSeoPage from "@/components/marketing/LocalSeoPage";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Création Site Internet Artisan Valenciennes (59) | HookLab",
|
||||
description:
|
||||
"Sites web pour artisans du bâtiment à Valenciennes et Valenciennois. Technologie ultra-rapide, SEO local, résultats concrets. Audit gratuit.",
|
||||
};
|
||||
|
||||
export default function Page() {
|
||||
return (
|
||||
<LocalSeoPage
|
||||
ville="Valenciennes"
|
||||
villeSlug="valenciennes"
|
||||
codePostal="59300"
|
||||
voisines={["Denain", "Saint-Amand-les-Eaux", "Douai"]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -1,26 +1,101 @@
|
||||
import type { MetadataRoute } from "next";
|
||||
|
||||
const BASE_URL = process.env.NEXT_PUBLIC_APP_URL || "https://hooklab.eu";
|
||||
const BASE_URL = "https://www.hooklab.eu";
|
||||
|
||||
export default function sitemap(): MetadataRoute.Sitemap {
|
||||
const now = new Date();
|
||||
|
||||
return [
|
||||
// Page d'accueil - priorit\u00e9 max
|
||||
{
|
||||
url: BASE_URL,
|
||||
lastModified: new Date(),
|
||||
lastModified: now,
|
||||
changeFrequency: "weekly",
|
||||
priority: 1.0,
|
||||
},
|
||||
|
||||
// D\u00e9mos m\u00e9tiers - pages strat\u00e9giques SEO
|
||||
{
|
||||
url: `${BASE_URL}/macon`,
|
||||
lastModified: now,
|
||||
changeFrequency: "monthly",
|
||||
priority: 0.9,
|
||||
},
|
||||
{
|
||||
url: `${BASE_URL}/paysagiste`,
|
||||
lastModified: now,
|
||||
changeFrequency: "monthly",
|
||||
priority: 0.9,
|
||||
},
|
||||
{
|
||||
url: `${BASE_URL}/plombier`,
|
||||
lastModified: now,
|
||||
changeFrequency: "monthly",
|
||||
priority: 0.9,
|
||||
},
|
||||
|
||||
// Pages SEO locales - site internet artisan + ville
|
||||
// Douai
|
||||
{
|
||||
url: `${BASE_URL}/site-internet-artisan-douai`,
|
||||
lastModified: now,
|
||||
changeFrequency: "monthly",
|
||||
priority: 0.8,
|
||||
},
|
||||
// Orchies
|
||||
{
|
||||
url: `${BASE_URL}/site-internet-artisan-orchies`,
|
||||
lastModified: now,
|
||||
changeFrequency: "monthly",
|
||||
priority: 0.8,
|
||||
},
|
||||
// Valenciennes
|
||||
{
|
||||
url: `${BASE_URL}/site-internet-artisan-valenciennes`,
|
||||
lastModified: now,
|
||||
changeFrequency: "monthly",
|
||||
priority: 0.8,
|
||||
},
|
||||
// Saint-Amand-les-Eaux
|
||||
{
|
||||
url: `${BASE_URL}/site-internet-artisan-saint-amand-les-eaux`,
|
||||
lastModified: now,
|
||||
changeFrequency: "monthly",
|
||||
priority: 0.8,
|
||||
},
|
||||
// Arleux
|
||||
{
|
||||
url: `${BASE_URL}/site-internet-artisan-arleux`,
|
||||
lastModified: now,
|
||||
changeFrequency: "monthly",
|
||||
priority: 0.8,
|
||||
},
|
||||
// Denain
|
||||
{
|
||||
url: `${BASE_URL}/site-internet-artisan-denain`,
|
||||
lastModified: now,
|
||||
changeFrequency: "monthly",
|
||||
priority: 0.8,
|
||||
},
|
||||
|
||||
// L\u00e9gal
|
||||
{
|
||||
url: `${BASE_URL}/mentions-legales`,
|
||||
lastModified: new Date(),
|
||||
lastModified: now,
|
||||
changeFrequency: "yearly",
|
||||
priority: 0.3,
|
||||
priority: 0.2,
|
||||
},
|
||||
{
|
||||
url: `${BASE_URL}/confidentialite`,
|
||||
lastModified: new Date(),
|
||||
lastModified: now,
|
||||
changeFrequency: "yearly",
|
||||
priority: 0.3,
|
||||
priority: 0.2,
|
||||
},
|
||||
{
|
||||
url: `${BASE_URL}/plan-du-site`,
|
||||
lastModified: now,
|
||||
changeFrequency: "yearly",
|
||||
priority: 0.2,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
@@ -3,11 +3,11 @@ import Link from "next/link";
|
||||
|
||||
const demos = [
|
||||
{
|
||||
title: "Le Pack \u00ab\u00a0Gros \u0152uvre\u00a0\u00bb",
|
||||
subtitle: "Ma\u00e7on / Couvreur",
|
||||
title: "L\u2019Expertise Solide",
|
||||
subtitle: "Pour ceux dont le travail doit durer 100 ans.",
|
||||
pourQui: "Ma\u00e7ons, Couvreurs, Charpentiers.",
|
||||
pointFort: "La galerie \u00ab\u00a0Avant / Apr\u00e8s\u00a0\u00bb qui prouve votre technique et justifie vos devis.",
|
||||
fonctionnalite: "Bouton \u00ab\u00a0Urgence Fuite\u00a0\u00bb qui d\u00e9clenche l\u2019appel imm\u00e9diat.",
|
||||
pointFort: "Slider \u00ab\u00a0Avant / Apr\u00e8s\u00a0\u00bb interactif + badges garanties (D\u00e9cennale, Qualibat, RGE) immanquables.",
|
||||
fonctionnalite: "Formulaire intelligent : si Urgence Fuite \u2192 bouton rouge \u00ab\u00a0APPELER LE PATRON\u00a0\u00bb.",
|
||||
cta: "Voir la D\u00e9mo Ma\u00e7onnerie",
|
||||
href: "/macon",
|
||||
icon: (
|
||||
@@ -17,11 +17,11 @@ const demos = [
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "Le Pack \u00ab\u00a0Esth\u00e9tique\u00a0\u00bb",
|
||||
subtitle: "Paysagiste / Peintre",
|
||||
title: "L\u2019Artisan Cr\u00e9ateur",
|
||||
subtitle: "Pour ceux qui vendent du beau et du confort.",
|
||||
pourQui: "Paysagistes, Peintres, D\u00e9corateurs.",
|
||||
pointFort: "Un design \u00e9pur\u00e9 qui laisse toute la place \u00e0 la beaut\u00e9 de vos r\u00e9alisations.",
|
||||
fonctionnalite: "Filtrage \u00ab\u00a0Cr\u00e9ation vs Entretien\u00a0\u00bb pour ne recevoir que les projets \u00e0 forte valeur.",
|
||||
pointFort: "Galerie filtrable par type + saisonnalit\u00e9 intelligente (le site change selon la saison).",
|
||||
fonctionnalite: "Bouton WhatsApp flottant \u00ab\u00a0Je veux le m\u00eame jardin\u00a0\u00bb + immersion locale par ville.",
|
||||
cta: "Voir la D\u00e9mo Paysagiste",
|
||||
href: "/paysagiste",
|
||||
icon: (
|
||||
@@ -31,11 +31,11 @@ const demos = [
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "Le Pack \u00ab\u00a0Urgence & Service\u00a0\u00bb",
|
||||
subtitle: "Plombier / \u00c9lec",
|
||||
title: "L\u2019Intervention \u00c9clair",
|
||||
subtitle: "Pour ceux qui sauvent la mise (et veulent \u00eatre pay\u00e9s vite).",
|
||||
pourQui: "Plombiers, \u00c9lectriciens, Serruriers.",
|
||||
pointFort: "Vitesse de chargement \u00e9clair et rassurance imm\u00e9diate (Avis + Tarifs clairs).",
|
||||
fonctionnalite: "Formulaire de diagnostic rapide pour qualifier la panne avant de vous d\u00e9placer.",
|
||||
pointFort: "Avis Google en haut + tarifs transparents + bouton d\u2019appel sticky sur mobile.",
|
||||
fonctionnalite: "Diagnostic en 3 clics : qualifie la panne + d\u00e9tecte si hors zone.",
|
||||
cta: "Voir la D\u00e9mo Plombier",
|
||||
href: "/plombier",
|
||||
icon: (
|
||||
|
||||
142
components/marketing/LocalSeoPage.tsx
Normal file
142
components/marketing/LocalSeoPage.tsx
Normal file
@@ -0,0 +1,142 @@
|
||||
import Link from "next/link";
|
||||
import Button from "@/components/ui/Button";
|
||||
import Navbar from "@/components/marketing/Navbar";
|
||||
import Footer from "@/components/marketing/Footer";
|
||||
|
||||
interface LocalSeoPageProps {
|
||||
ville: string;
|
||||
villeSlug: string;
|
||||
codePostal: string;
|
||||
voisines: string[];
|
||||
}
|
||||
|
||||
export default function LocalSeoPage({ ville, codePostal, voisines }: LocalSeoPageProps) {
|
||||
return (
|
||||
<main className="min-h-screen">
|
||||
<Navbar />
|
||||
|
||||
{/* Hero local */}
|
||||
<section className="py-20 md:py-28 bg-navy text-center">
|
||||
<div className="max-w-4xl mx-auto px-4">
|
||||
<span className="inline-block px-3 py-1.5 bg-orange/20 border border-orange/30 rounded-full text-orange text-xs font-semibold mb-6">
|
||||
{ville} ({codePostal}) et environs
|
||||
</span>
|
||||
<h1 className="text-3xl sm:text-4xl md:text-5xl font-extrabold text-white leading-tight mb-6">
|
||||
Création de site internet pour{" "}
|
||||
<span className="text-orange">artisans à {ville}</span>
|
||||
</h1>
|
||||
<p className="text-white/60 text-lg max-w-2xl mx-auto mb-8">
|
||||
Vous êtes artisan à {ville} ou dans le secteur de {voisines[0]} / {voisines[1]} ?
|
||||
Je crée votre site web professionnel et votre présence Google pour générer
|
||||
des chantiers qualifiés. Basé à Flines-lez-Raches, je suis votre voisin.
|
||||
</p>
|
||||
<a href="/#contact">
|
||||
<Button size="lg" className="pulse-glow">
|
||||
DÉMARRER MON AUDIT GRATUIT
|
||||
</Button>
|
||||
</a>
|
||||
<p className="mt-4 text-white/40 text-sm">
|
||||
Réponse sous 24h · 100% gratuit · Sans engagement
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* M\u00e9tiers couverts */}
|
||||
<section className="py-16 md:py-24 bg-bg">
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<h2 className="text-2xl md:text-3xl font-bold text-navy text-center mb-10">
|
||||
Sites web pour <span className="text-orange">tous les métiers du bâtiment</span> à {ville}
|
||||
</h2>
|
||||
<div className="grid grid-cols-2 md:grid-cols-3 gap-4">
|
||||
{[
|
||||
"Couvreur", "Ma\u00e7on", "Paysagiste",
|
||||
"Plombier", "\u00c9lectricien", "Menuisier",
|
||||
"Charpentier", "Peintre", "Serrurier",
|
||||
].map((metier) => (
|
||||
<div key={metier} className="bg-bg-white border border-border rounded-xl p-4 text-center hover:shadow-md transition-shadow">
|
||||
<p className="text-navy font-semibold text-sm">Site internet {metier}</p>
|
||||
<p className="text-text-muted text-xs mt-1">{ville} et environs</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Pourquoi HookLab */}
|
||||
<section className="py-16 md:py-24 bg-bg-white">
|
||||
<div className="max-w-3xl mx-auto px-4 text-center">
|
||||
<h2 className="text-2xl md:text-3xl font-bold text-navy mb-6">
|
||||
Pourquoi choisir <span className="text-orange">HookLab</span> à {ville} ?
|
||||
</h2>
|
||||
<div className="space-y-4 text-left">
|
||||
{[
|
||||
{
|
||||
title: "Proximit\u00e9 locale",
|
||||
desc: `Bas\u00e9 \u00e0 Flines-lez-Raches, je connais ${ville} et ses artisans. On peut se voir en vrai.`,
|
||||
},
|
||||
{
|
||||
title: "Technologie des g\u00e9ants",
|
||||
desc: "Sites ultra-rapides avec la m\u00eame technologie que Netflix. Google adore la vitesse.",
|
||||
},
|
||||
{
|
||||
title: "R\u00e9sultats concrets",
|
||||
desc: "Pas un site pour faire joli. Un syst\u00e8me qui fait sonner votre t\u00e9l\u00e9phone avec des vrais clients.",
|
||||
},
|
||||
].map((item, i) => (
|
||||
<div key={i} className="flex items-start gap-4 bg-bg border border-border rounded-xl p-5">
|
||||
<div className="w-8 h-8 bg-orange/10 rounded-full flex items-center justify-center shrink-0 mt-0.5">
|
||||
<svg className="w-4 h-4 text-orange" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2.5} d="M5 13l4 4L19 7" />
|
||||
</svg>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-navy font-bold text-base mb-1">{item.title}</p>
|
||||
<p className="text-text-light text-sm leading-relaxed">{item.desc}</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* D\u00e9mos */}
|
||||
<section className="py-16 md:py-24 bg-bg">
|
||||
<div className="max-w-4xl mx-auto px-4 text-center">
|
||||
<h2 className="text-2xl md:text-3xl font-bold text-navy mb-6">
|
||||
Testez nos <span className="text-orange">modèles</span>
|
||||
</h2>
|
||||
<div className="flex flex-wrap gap-4 justify-center">
|
||||
<Link href="/macon" className="bg-navy text-white font-bold text-sm px-6 py-3 rounded-xl hover:bg-navy/90 transition-colors">
|
||||
Démo Maçon / Couvreur
|
||||
</Link>
|
||||
<Link href="/paysagiste" className="bg-green-600 text-white font-bold text-sm px-6 py-3 rounded-xl hover:bg-green-700 transition-colors">
|
||||
Démo Paysagiste
|
||||
</Link>
|
||||
<Link href="/plombier" className="bg-[#3b82f6] text-white font-bold text-sm px-6 py-3 rounded-xl hover:bg-[#2563eb] transition-colors">
|
||||
Démo Plombier
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Zone */}
|
||||
<section className="py-16 bg-navy text-center">
|
||||
<div className="max-w-2xl mx-auto px-4">
|
||||
<h2 className="text-2xl font-bold text-white mb-4">
|
||||
Aussi disponible à {voisines.join(", ")}
|
||||
</h2>
|
||||
<p className="text-white/60 mb-6">
|
||||
Je travaille avec des artisans dans tout le Douaisis, l’Orchésien et le Valenciennois.
|
||||
</p>
|
||||
<a href="/#contact">
|
||||
<Button size="lg" className="pulse-glow">
|
||||
Réserver Mon Audit Gratuit
|
||||
</Button>
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<Footer />
|
||||
</main>
|
||||
);
|
||||
}
|
||||
@@ -36,13 +36,13 @@ export default function Navbar() {
|
||||
{/* CTA desktop - Phone */}
|
||||
<div className="hidden md:block">
|
||||
<a
|
||||
href="tel:+33600000000"
|
||||
href="tel:+33604408157"
|
||||
className="inline-flex items-center gap-2 bg-orange text-white font-bold text-sm px-5 py-2.5 rounded-xl hover:bg-orange/90 transition-colors"
|
||||
>
|
||||
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z" />
|
||||
</svg>
|
||||
06 XX XX XX XX
|
||||
06 04 40 81 57
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -78,14 +78,14 @@ export default function Navbar() {
|
||||
Qui suis-je
|
||||
</a>
|
||||
<a
|
||||
href="tel:+33600000000"
|
||||
href="tel:+33604408157"
|
||||
onClick={() => setOpen(false)}
|
||||
className="flex items-center justify-center gap-2 bg-orange text-white font-bold text-sm px-5 py-3 rounded-xl mt-2"
|
||||
>
|
||||
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z" />
|
||||
</svg>
|
||||
06 XX XX XX XX
|
||||
06 04 40 81 57
|
||||
</a>
|
||||
</div>
|
||||
)}
|
||||
|
||||
91
components/ui/MagicReveal.tsx
Normal file
91
components/ui/MagicReveal.tsx
Normal file
@@ -0,0 +1,91 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useRef, useCallback } from "react";
|
||||
|
||||
interface MagicRevealProps {
|
||||
avantLabel: string;
|
||||
apresLabel: string;
|
||||
avantColor?: string;
|
||||
apresColor?: string;
|
||||
height?: string;
|
||||
}
|
||||
|
||||
export default function MagicReveal({
|
||||
avantLabel,
|
||||
apresLabel,
|
||||
avantColor = "bg-red-50",
|
||||
apresColor = "bg-green-50",
|
||||
height = "h-64",
|
||||
}: MagicRevealProps) {
|
||||
const [position, setPosition] = useState(50);
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const dragging = useRef(false);
|
||||
|
||||
const updatePosition = useCallback((clientX: number) => {
|
||||
if (!containerRef.current) return;
|
||||
const rect = containerRef.current.getBoundingClientRect();
|
||||
const x = clientX - rect.left;
|
||||
const percent = Math.max(0, Math.min(100, (x / rect.width) * 100));
|
||||
setPosition(percent);
|
||||
}, []);
|
||||
|
||||
const handlePointerDown = useCallback((e: React.PointerEvent) => {
|
||||
dragging.current = true;
|
||||
(e.target as HTMLElement).setPointerCapture(e.pointerId);
|
||||
updatePosition(e.clientX);
|
||||
}, [updatePosition]);
|
||||
|
||||
const handlePointerMove = useCallback((e: React.PointerEvent) => {
|
||||
if (!dragging.current) return;
|
||||
updatePosition(e.clientX);
|
||||
}, [updatePosition]);
|
||||
|
||||
const handlePointerUp = useCallback(() => {
|
||||
dragging.current = false;
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={containerRef}
|
||||
className={`relative ${height} rounded-xl overflow-hidden cursor-col-resize select-none border border-border`}
|
||||
onPointerDown={handlePointerDown}
|
||||
onPointerMove={handlePointerMove}
|
||||
onPointerUp={handlePointerUp}
|
||||
>
|
||||
{/* Apr\u00e8s (fond complet) */}
|
||||
<div className={`absolute inset-0 ${apresColor} flex items-center justify-center`}>
|
||||
<div className="text-center">
|
||||
<p className="text-green-600 font-bold text-sm uppercase tracking-wider mb-1">Apr\u00e8s</p>
|
||||
<p className="text-green-800 text-sm font-medium px-4">{apresLabel}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Avant (clip\u00e9 \u00e0 gauche) */}
|
||||
<div
|
||||
className={`absolute inset-0 ${avantColor} flex items-center justify-center`}
|
||||
style={{ clipPath: `inset(0 ${100 - position}% 0 0)` }}
|
||||
>
|
||||
<div className="text-center">
|
||||
<p className="text-red-600 font-bold text-sm uppercase tracking-wider mb-1">Avant</p>
|
||||
<p className="text-red-800 text-sm font-medium px-4">{avantLabel}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Barre de s\u00e9paration */}
|
||||
<div
|
||||
className="absolute top-0 bottom-0 w-1 bg-white shadow-lg z-10"
|
||||
style={{ left: `${position}%`, transform: "translateX(-50%)" }}
|
||||
>
|
||||
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-10 h-10 bg-white rounded-full shadow-lg flex items-center justify-center border-2 border-orange">
|
||||
<svg className="w-5 h-5 text-orange" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 9l4-4 4 4m0 6l-4 4-4-4" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Labels gauche/droite */}
|
||||
<div className="absolute top-2 left-3 bg-red-600 text-white text-[10px] font-bold px-2 py-0.5 rounded-full z-20">AVANT</div>
|
||||
<div className="absolute top-2 right-3 bg-green-600 text-white text-[10px] font-bold px-2 py-0.5 rounded-full z-20">APR\u00c8S</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user