feat: mise à jour du formulaire de contact, ajout de la gestion des sujets et amélioration de la présentation des images
This commit is contained in:
@@ -13,17 +13,20 @@ contactForm:
|
||||
qrLabel: "ou scannez le code QR :"
|
||||
qrImg: "/images/chill-admin.png"
|
||||
fields:
|
||||
- name: "sujet"
|
||||
- name: "subject"
|
||||
label: "Sujet"
|
||||
type: "select"
|
||||
required: true
|
||||
options:
|
||||
- value: "support"
|
||||
label: "Support technique"
|
||||
- value: "demo"
|
||||
label: "Demander une démo"
|
||||
- value: "quote"
|
||||
label: "Demander un devis"
|
||||
- value: "formation"
|
||||
- value: "training"
|
||||
label: "Formation"
|
||||
- value: "support"
|
||||
label: "Support technique"
|
||||
|
||||
- value: "other"
|
||||
label: "Autre"
|
||||
- name: "email"
|
||||
|
||||
@@ -7,7 +7,7 @@ badge: "Droits d’accès"
|
||||
badgeColor: "rapport-rgpd"
|
||||
demo:
|
||||
description: "Assurez la conformité RGPD et organisez vos rapports et documents."
|
||||
image:
|
||||
images:
|
||||
- "/images/features/HP-droitsdacces.png"
|
||||
|
||||
---
|
||||
|
||||
@@ -7,9 +7,10 @@ badge: "Statistiques"
|
||||
badgeColor: "rapports-statistiques"
|
||||
demo:
|
||||
description: "Générez et exportez des rapports statistiques détaillés."
|
||||
image:
|
||||
images:
|
||||
- "/images/features/HP-exports.png"
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Présentation
|
||||
|
||||
@@ -50,7 +50,7 @@ layout: "simple"
|
||||
"additional_description": "* A partir du 4ème utilisateur: 40€ supplémentaire/an.",
|
||||
"button": {
|
||||
"text": "Demander un devis",
|
||||
"url": "/contact/"
|
||||
"url": "/contact?subject=quote"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -68,7 +68,7 @@ layout: "simple"
|
||||
"additional_description": "* A partir du 4ème utilisateur: 40€ supplémentaire/an.",
|
||||
"button": {
|
||||
"text": "Demander un devis",
|
||||
"url": "/contact/"
|
||||
"url": "/contact?subject=quote"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -82,8 +82,8 @@ layout: "simple"
|
||||
"Mises à jour régulières"
|
||||
],
|
||||
"button": {
|
||||
"text": "Contactez-nous",
|
||||
"url": "/contact/"
|
||||
"text": "Demander un devis",
|
||||
"url": "/contact?subject=quote"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -98,7 +98,7 @@ layout: "simple"
|
||||
],
|
||||
"button": {
|
||||
"text": "Contactez-nous",
|
||||
"url": "/contact/"
|
||||
"url": "/contact?subject=training"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,6 @@ layout: "gradient-card"
|
||||
{{< /gradient-card-section >}}
|
||||
|
||||
{{< gradient-card-section title="Formation des utilisateurs" description="Organisez une journée de formation à l'utilisation de Chill." >}}
|
||||
<a href="/contact" class="btn btn-primary mt-4">Contactez-nous</a>
|
||||
<a href="/contact?subject=training" class="btn btn-primary mt-4">Contactez-nous</a>
|
||||
{{< /gradient-card-section >}}
|
||||
|
||||
|
||||
@@ -100,7 +100,7 @@ pagination = { pagerSize = 6, path = "page" }
|
||||
# Primary button
|
||||
[params.cta.primary_button]
|
||||
text = "Réserver une démo"
|
||||
url = "/contact"
|
||||
url = "/contact?subject=demo"
|
||||
open_tab = false
|
||||
|
||||
# Secondary button
|
||||
|
||||
@@ -765,34 +765,58 @@ body {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.\!container {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
.container {
|
||||
max-width: 640px;
|
||||
}
|
||||
|
||||
.\!container {
|
||||
max-width: 640px !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.container {
|
||||
max-width: 768px;
|
||||
}
|
||||
|
||||
.\!container {
|
||||
max-width: 768px !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
.container {
|
||||
max-width: 1024px;
|
||||
}
|
||||
|
||||
.\!container {
|
||||
max-width: 1024px !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1280px) {
|
||||
.container {
|
||||
max-width: 1280px;
|
||||
}
|
||||
|
||||
.\!container {
|
||||
max-width: 1280px !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1536px) {
|
||||
.container {
|
||||
max-width: 1536px;
|
||||
}
|
||||
|
||||
.\!container {
|
||||
max-width: 1536px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.prose {
|
||||
@@ -1895,6 +1919,28 @@ body {
|
||||
}
|
||||
}
|
||||
|
||||
.\!container {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
max-width: 80rem;
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
.\!container {
|
||||
padding-left: 1.5rem;
|
||||
padding-right: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
.\!container {
|
||||
padding-left: 2rem;
|
||||
padding-right: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
.section {
|
||||
padding-top: 2rem;
|
||||
padding-bottom: 2rem;
|
||||
@@ -2349,10 +2395,6 @@ body {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.mt-5 {
|
||||
margin-top: 1.25rem;
|
||||
}
|
||||
|
||||
.mt-6 {
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
@@ -2428,6 +2470,10 @@ body {
|
||||
height: 10rem;
|
||||
}
|
||||
|
||||
.h-48 {
|
||||
height: 12rem;
|
||||
}
|
||||
|
||||
.h-5 {
|
||||
height: 1.25rem;
|
||||
}
|
||||
@@ -2456,10 +2502,6 @@ body {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.h-48 {
|
||||
height: 12rem;
|
||||
}
|
||||
|
||||
.max-h-12 {
|
||||
max-height: 3rem;
|
||||
}
|
||||
@@ -2496,6 +2538,10 @@ body {
|
||||
width: 10rem;
|
||||
}
|
||||
|
||||
.w-48 {
|
||||
width: 12rem;
|
||||
}
|
||||
|
||||
.w-5 {
|
||||
width: 1.25rem;
|
||||
}
|
||||
@@ -2520,10 +2566,6 @@ body {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.w-48 {
|
||||
width: 12rem;
|
||||
}
|
||||
|
||||
.\!max-w-none {
|
||||
max-width: none !important;
|
||||
}
|
||||
@@ -2950,10 +2992,6 @@ body {
|
||||
background-color: rgb(234 179 8 / var(--tw-bg-opacity, 1));
|
||||
}
|
||||
|
||||
.bg-gradient-to-b {
|
||||
background-image: linear-gradient(to bottom, var(--tw-gradient-stops));
|
||||
}
|
||||
|
||||
.bg-gradient-to-r {
|
||||
background-image: linear-gradient(to right, var(--tw-gradient-stops));
|
||||
}
|
||||
@@ -2964,25 +3002,10 @@ body {
|
||||
--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);
|
||||
}
|
||||
|
||||
.from-secondary-50 {
|
||||
--tw-gradient-from: #ddeef6 var(--tw-gradient-from-position);
|
||||
--tw-gradient-to: rgb(221 238 246 / 0) var(--tw-gradient-to-position);
|
||||
--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);
|
||||
}
|
||||
|
||||
.via-secondary-50 {
|
||||
--tw-gradient-to: rgb(221 238 246 / 0) var(--tw-gradient-to-position);
|
||||
--tw-gradient-stops: var(--tw-gradient-from), #ddeef6 var(--tw-gradient-via-position), var(--tw-gradient-to);
|
||||
}
|
||||
|
||||
.to-primary-700 {
|
||||
--tw-gradient-to: #8c2908 var(--tw-gradient-to-position);
|
||||
}
|
||||
|
||||
.to-white {
|
||||
--tw-gradient-to: #fff var(--tw-gradient-to-position);
|
||||
}
|
||||
|
||||
.object-contain {
|
||||
-o-object-fit: contain;
|
||||
object-fit: contain;
|
||||
@@ -3106,10 +3129,6 @@ body {
|
||||
padding-bottom: 6rem;
|
||||
}
|
||||
|
||||
.pb-32 {
|
||||
padding-bottom: 8rem;
|
||||
}
|
||||
|
||||
.pl-4 {
|
||||
padding-left: 1rem;
|
||||
}
|
||||
@@ -3158,10 +3177,6 @@ body {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.text-start {
|
||||
text-align: start;
|
||||
}
|
||||
|
||||
.font-mono {
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
}
|
||||
@@ -3376,12 +3391,6 @@ body {
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
||||
}
|
||||
|
||||
.shadow-2xl {
|
||||
--tw-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.25);
|
||||
--tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
||||
}
|
||||
|
||||
.shadow-lg {
|
||||
--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
|
||||
--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);
|
||||
|
||||
@@ -77,15 +77,7 @@
|
||||
<p class="mt-6 text-lg leading-8 text-gray-600">{{ .Params.demo.description }}</p>
|
||||
</div>
|
||||
<div class="mt-16 flex justify-center">
|
||||
<div class="relative rounded-xl bg-white p-8 shadow-2xl ring-1 ring-gray-200">
|
||||
<div class="carousel">
|
||||
{{ range .Params.demo.images }}
|
||||
<div class="carousel-item">
|
||||
<img src="{{ . }}" alt="Demo" class="rounded-lg">
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
{{ partial "shortcodes/carousel.html" (dict "images" .Params.demo.images) }}
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
122
themes/chill-theme/layouts/partials/shortcodes/carousel.html
Normal file
122
themes/chill-theme/layouts/partials/shortcodes/carousel.html
Normal file
@@ -0,0 +1,122 @@
|
||||
{{/*
|
||||
Hugo List to Carousel Partial
|
||||
Source: https://hugocodex.org/add-ons/slider-carousel/
|
||||
Author: Jeroen van der Schee
|
||||
*/}}
|
||||
|
||||
{{ $id := printf "carousel-%d" (now.UnixNano) }}
|
||||
<div id="{{ $id }}" class="carousel-container">
|
||||
<div class="carousel-slides">
|
||||
{{ range .images }}
|
||||
<div class="carousel-slide">
|
||||
<img src="{{ . }}" alt="Carousel image" loading="lazy" />
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
{{ if gt (len .images) 1 }}
|
||||
<button class="carousel-prev" aria-label="Précédent">❮</button>
|
||||
<button class="carousel-next" aria-label="Suivant">❯</button>
|
||||
|
||||
<div class="carousel-dots">
|
||||
{{ range $i, $_ := .images }}
|
||||
<span class="carousel-dot" data-index="{{ $i }}"></span>
|
||||
{{ end }}
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.carousel-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.carousel-slides {
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.carousel-slide {
|
||||
min-width: 100%;
|
||||
transition: transform 0.5s ease;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.carousel-slide img {
|
||||
max-width: 100%;
|
||||
border-radius: 1rem;
|
||||
}
|
||||
|
||||
.carousel-prev,
|
||||
.carousel-next {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
border: none;
|
||||
font-size: 2rem;
|
||||
padding: 0.5rem 1rem;
|
||||
cursor: pointer;
|
||||
border-radius: 50%;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.carousel-prev {
|
||||
left: 10px;
|
||||
}
|
||||
|
||||
.carousel-next {
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
.carousel-dots {
|
||||
text-align: center;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.carousel-dot {
|
||||
display: inline-block;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
margin: 0 4px;
|
||||
background: #bbb;
|
||||
border-radius: 50%;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.carousel-dot.active {
|
||||
background: #333;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
var container = document.getElementById('{{ $id }}');
|
||||
if (!container) return;
|
||||
var slides = container.querySelectorAll('.carousel-slide');
|
||||
var prevBtn = container.querySelector('.carousel-prev');
|
||||
var nextBtn = container.querySelector('.carousel-next');
|
||||
var dots = container.querySelectorAll('.carousel-dot');
|
||||
var current = 0;
|
||||
|
||||
function showSlide(idx) {
|
||||
slides.forEach(function (slide, i) {
|
||||
slide.style.transform = 'translateX(' + (-100 * idx) + '%)';
|
||||
});
|
||||
dots.forEach(function (dot, i) {
|
||||
dot.classList.toggle('active', i === idx);
|
||||
});
|
||||
current = idx;
|
||||
}
|
||||
prevBtn.addEventListener('click', function () {
|
||||
showSlide((current - 1 + slides.length) % slides.length);
|
||||
});
|
||||
nextBtn.addEventListener('click', function () {
|
||||
showSlide((current + 1) % slides.length);
|
||||
});
|
||||
dots.forEach(function (dot, i) {
|
||||
dot.addEventListener('click', function () { showSlide(i); });
|
||||
});
|
||||
showSlide(0);
|
||||
});
|
||||
</script>
|
||||
@@ -2,42 +2,56 @@
|
||||
|
||||
|
||||
|
||||
<form id="contactForm" class="max-w-lg mx-auto p-6 bg-white rounded shadow" method="POST" action="{{ $form.action | default "http://localhost:3001/contact" }}">
|
||||
<form id="contactForm" class="max-w-lg mx-auto p-6 bg-white rounded shadow" method="POST"
|
||||
action="{{ $form.action | default " http://localhost:3001/contact" }}">
|
||||
<h3 class="text-2xl font-bold mb-4">{{ $form.title }}</h3>
|
||||
{{ range $form.fields }}
|
||||
<div class="mb-4">
|
||||
{{ if eq .type "textarea" }}
|
||||
<label for="{{ .name }}">{{ .label }}</label>
|
||||
<textarea id="{{ .name }}" name="{{ .name }}" rows="5" {{ if .required }}required{{ end }} class="w-full px-3 py-2 border rounded focus:outline-none focus:ring focus:border-blue-300"></textarea>
|
||||
{{ else if eq .type "select" }}
|
||||
<select id="{{ .name }}" name="{{ .name }}" {{ if .required }}required{{ end }} class="w-full px-3 py-2 border rounded focus:outline-none focus:ring focus:border-blue-300">
|
||||
{{ range .options }}
|
||||
<option value="{{ .value }}">{{ .label | default .value }}</option>
|
||||
{{ end }}
|
||||
</select>
|
||||
{{ else }}
|
||||
<input type="{{ .type }}" placeholder="{{.label}}" id="{{ .name }}" name="{{ .name }}" {{ if .required }}required{{ end }} class="w-full px-3 py-2 border rounded focus:outline-none focus:ring focus:border-blue-300" />
|
||||
<div class="mb-4">
|
||||
{{ if eq .type "textarea" }}
|
||||
<label for="{{ .name }}">{{ .label }}</label>
|
||||
<textarea id="{{ .name }}" name="{{ .name }}" rows="5" {{ if .required }}required{{ end }}
|
||||
class="w-full px-3 py-2 border rounded focus:outline-none focus:ring focus:border-blue-300"></textarea>
|
||||
{{ else if eq .type "select" }}
|
||||
<select id="{{ .name }}" name="{{ .name }}" {{ if .required }}required{{ end }}
|
||||
class="w-full px-3 py-2 border rounded focus:outline-none focus:ring focus:border-blue-300">
|
||||
{{ range .options }}
|
||||
<option value="{{ .value }}">{{ .label | default .value }}</option>
|
||||
{{ end }}
|
||||
</div>
|
||||
</select>
|
||||
{{ else }}
|
||||
<input type="{{ .type }}" placeholder="{{.label}}" id="{{ .name }}" name="{{ .name }}" {{ if .required }}required{{
|
||||
end }} class="w-full px-3 py-2 border rounded focus:outline-none focus:ring focus:border-blue-300" />
|
||||
{{ end }}
|
||||
</div>
|
||||
{{ end }}
|
||||
<!-- Champ honeypot invisible pour les robots -->
|
||||
<div style="position:absolute; left:-9999px; top:auto; width:1px; height:1px; overflow:hidden;">
|
||||
<label for="website">Ne pas remplir ce champ</label>
|
||||
<input type="text" id="website" name="website" tabindex="-1" autocomplete="off" />
|
||||
</div>
|
||||
<div class=" text-md text-gray-500 mt-1 prose prose-sm" >
|
||||
<div class=" text-md text-gray-500 mt-1 prose prose-sm">
|
||||
{{ $form.hint | markdownify | safeHTML }}
|
||||
</div>
|
||||
<div class="flex justify-end mt-4">
|
||||
<button type="submit" class="px-6 py-3 rounded-lg font-bold transition duration-200 ease-in-out border-2 text-primary-400 border-primary-400 hover:border-primary-400 hover:text-primary-400 hover:scale-105">
|
||||
<button type="submit"
|
||||
class="px-6 py-3 rounded-lg font-bold transition duration-200 ease-in-out border-2 text-primary-400 border-primary-400 hover:border-primary-400 hover:text-primary-400 hover:scale-105">
|
||||
{{ $form.button.label | default "Envoyer" }}
|
||||
</button>
|
||||
</div>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const form = document.getElementById('contactForm');
|
||||
const resultDiv = document.getElementById('contact-result');
|
||||
form.addEventListener('submit', function(e) {
|
||||
// Pré-sélectionner le champ "sujet" si paramètre dans l'URL
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const subject = urlParams.get('subject');
|
||||
if (subject) {
|
||||
const select = document.getElementById('subject');
|
||||
if (select) {
|
||||
select.value = subject;
|
||||
}
|
||||
}
|
||||
form.addEventListener('submit', function (e) {
|
||||
e.preventDefault();
|
||||
resultDiv.innerHTML = '';
|
||||
const formData = new FormData(form);
|
||||
@@ -45,18 +59,18 @@
|
||||
method: 'POST',
|
||||
body: formData
|
||||
})
|
||||
.then(async response => {
|
||||
const text = await response.text();
|
||||
if (response.status === 200) {
|
||||
resultDiv.innerHTML = `<div style='background:#e6ffed;color:#228B22;padding:1em;border-radius:6px;border:1px solid #228B22;'>${text}</div>`;
|
||||
form.reset();
|
||||
} else {
|
||||
resultDiv.innerHTML = `<div style='background:#ffe6e6;color:#b22222;padding:1em;border-radius:6px;border:1px solid #b22222;'>${text}</div>`;
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
resultDiv.innerHTML = `<div style='background:#ffe6e6;color:#b22222;padding:1em;border-radius:6px;border:1px solid #b22222;'>Erreur réseau</div>`;
|
||||
});
|
||||
.then(async response => {
|
||||
const text = await response.text();
|
||||
if (response.status === 200) {
|
||||
resultDiv.innerHTML = `<div style='background:#e6ffed;color:#228B22;padding:1em;border-radius:6px;border:1px solid #228B22;'>${text}</div>`;
|
||||
form.reset();
|
||||
} else {
|
||||
resultDiv.innerHTML = `<div style='background:#ffe6e6;color:#b22222;padding:1em;border-radius:6px;border:1px solid #b22222;'>${text}</div>`;
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
resultDiv.innerHTML = `<div style='background:#ffe6e6;color:#b22222;padding:1em;border-radius:6px;border:1px solid #b22222;'>Erreur réseau</div>`;
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user