145 lines
5.6 KiB
HTML
145 lines
5.6 KiB
HTML
{{ $action := .Get "action" | default "/api/contact" }}
|
|
{{ $buttonText := .Get "buttonText" | default "Envoyer" }}
|
|
{{ $lastnameLabel := .Get "lastnameLabel" | default "Nom" }}
|
|
{{ $firstnameLabel := .Get "firstnameLabel" | default "Prénom" }}
|
|
{{ $privacyText := .Get "privacyText" | default "La protection de vos données est au coeur de nos préoccupations. Celles-ci sont confidentielles et ne seront utilisées que dans le cadre de la mobilité solidaire. Vous pouvez à tout moment les modifier où demander à les faire supprimer de notre base de données." }}
|
|
|
|
{{/* Récupérer les champs dynamiques : d'abord depuis le paramètre, sinon depuis le front matter */}}
|
|
{{ $fieldsParam := .Get "fields" }}
|
|
{{ $fields := slice }}
|
|
{{ if $fieldsParam }}
|
|
{{ $fields = transform.Unmarshal $fieldsParam }}
|
|
{{ else }}
|
|
{{ $fields = .Page.Params.formFields }}
|
|
{{ end }}
|
|
|
|
<form class="contact-form" x-data="contactForm('{{ $action }}')">
|
|
<!-- Message de succès -->
|
|
<div x-show="success" x-cloak class="contact-form-message contact-form-success">
|
|
Votre message a bien été envoyé. Nous vous répondrons dans les plus brefs délais.
|
|
</div>
|
|
|
|
<!-- Message d'erreur -->
|
|
<div x-show="error" x-cloak class="contact-form-message contact-form-error">
|
|
<span x-text="errorMessage"></span>
|
|
</div>
|
|
|
|
<div x-show="!success">
|
|
<div class="contact-form-row">
|
|
<div class="contact-form-group">
|
|
<label for="lastname">{{ $lastnameLabel }}</label>
|
|
<input type="text" id="lastname" name="lastname" required x-bind:disabled="loading" />
|
|
</div>
|
|
<div class="contact-form-group">
|
|
<label for="firstname">{{ $firstnameLabel }}</label>
|
|
<input type="text" id="firstname" name="firstname" required x-bind:disabled="loading" />
|
|
</div>
|
|
</div>
|
|
|
|
{{/* Champs dynamiques */}}
|
|
{{ if $fields }}
|
|
{{ range $index, $field := $fields }}
|
|
{{ $fieldId := $field.name | default (printf "field_%d" $index) }}
|
|
{{ $fieldRequired := $field.required | default false }}
|
|
|
|
{{ if eq $field.type "multicheckboxes" }}
|
|
<div class="contact-form-group contact-form-checkboxes">
|
|
<span class="contact-form-checkbox-label">{{ $field.label }}</span>
|
|
<div class="contact-form-checkbox-options">
|
|
{{ range $optIndex, $option := $field.options }}
|
|
<label class="contact-form-checkbox">
|
|
<input type="checkbox" name="{{ $fieldId }}[]" value="{{ $option.value | default $option.label }}" x-bind:disabled="loading" />
|
|
<span>{{ $option.label }}</span>
|
|
</label>
|
|
{{ end }}
|
|
</div>
|
|
</div>
|
|
{{ else if eq $field.type "textarea" }}
|
|
<div class="contact-form-group">
|
|
<label for="{{ $fieldId }}">{{ $field.label }}</label>
|
|
<textarea id="{{ $fieldId }}" name="{{ $fieldId }}" rows="{{ $field.rows | default 6 }}" {{ if $fieldRequired }}required{{ end }} x-bind:disabled="loading"></textarea>
|
|
</div>
|
|
{{ else }}
|
|
<div class="contact-form-group">
|
|
<label for="{{ $fieldId }}">{{ $field.label }}</label>
|
|
<input type="{{ $field.type | default "text" }}" id="{{ $fieldId }}" name="{{ $fieldId }}" {{ if $fieldRequired }}required{{ end }} x-bind:disabled="loading" />
|
|
</div>
|
|
{{ end }}
|
|
{{ end }}
|
|
{{ else }}
|
|
{{/* Champs par défaut si aucun champ dynamique n'est défini */}}
|
|
<div class="contact-form-group">
|
|
<label for="email">Votre adresse mail</label>
|
|
<input type="email" id="email" name="email" required x-bind:disabled="loading" />
|
|
</div>
|
|
<div class="contact-form-group">
|
|
<label for="subject">Objet de votre demande</label>
|
|
<input type="text" id="subject" name="subject" x-bind:disabled="loading" />
|
|
</div>
|
|
<div class="contact-form-group">
|
|
<label for="message">Votre message</label>
|
|
<textarea id="message" name="message" rows="6" required x-bind:disabled="loading"></textarea>
|
|
</div>
|
|
{{ end }}
|
|
|
|
<button type="submit" class="contact-form-submit" x-bind:disabled="loading" @click.prevent="submit">
|
|
<span x-show="!loading">{{ $buttonText }}</span>
|
|
<span x-show="loading">Envoi en cours...</span>
|
|
</button>
|
|
<p class="contact-form-privacy">{{ $privacyText }}</p>
|
|
</div>
|
|
</form>
|
|
|
|
<script>
|
|
document.addEventListener('alpine:init', () => {
|
|
Alpine.data('contactForm', (action) => ({
|
|
loading: false,
|
|
success: false,
|
|
error: false,
|
|
errorMessage: '',
|
|
|
|
submit() {
|
|
this.loading = true;
|
|
this.success = false;
|
|
this.error = false;
|
|
this.errorMessage = '';
|
|
|
|
const form = this.$root;
|
|
const formData = new FormData(form);
|
|
const data = {};
|
|
|
|
formData.forEach((value, key) => {
|
|
if (key.endsWith('[]')) {
|
|
const cleanKey = key.slice(0, -2);
|
|
if (!data[cleanKey]) data[cleanKey] = [];
|
|
data[cleanKey].push(value);
|
|
} else {
|
|
data[key] = value;
|
|
}
|
|
});
|
|
|
|
fetch(action, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(data)
|
|
})
|
|
.then(response => {
|
|
if (!response.ok) throw new Error('Erreur lors de l\'envoi');
|
|
return response.json();
|
|
})
|
|
.then(() => {
|
|
this.success = true;
|
|
form.reset();
|
|
})
|
|
.catch(err => {
|
|
this.error = true;
|
|
this.errorMessage = err.message || 'Une erreur est survenue lors de l\'envoi. Veuillez réessayer.';
|
|
})
|
|
.finally(() => {
|
|
this.loading = false;
|
|
});
|
|
}
|
|
}));
|
|
});
|
|
</script>
|