209 lines
6.5 KiB
Text
209 lines
6.5 KiB
Text
<template>
|
|
<div :id="id" ref="modal" class="modal fade" tabindex="-1">
|
|
<div class="modal-dialog modal-xxl">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title">
|
|
{{ `${item.name} - ${item.teaser}` }}
|
|
</h5>
|
|
<button
|
|
type="button"
|
|
class="btn-close"
|
|
data-bs-dismiss="modal"
|
|
aria-label="Close"
|
|
/>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="row">
|
|
<div class="col-4 text-center">
|
|
<img class="img-fluid" :src="item.img" :title="item.name" :alt="item.name">
|
|
</div>
|
|
<div class="col-8">
|
|
<div v-sane-html="item.description" class="bg-secondary text-bg-secondary p-3 m-3 rounded" />
|
|
<form ref="form" action="#" class="p-3 needs-validation" novalidate>
|
|
<label for="validationEmail" class="form-label mt-5">Votre email</label>
|
|
<div class="input-group has-validation mb-5">
|
|
<span class="input-group-text">@</span>
|
|
<input
|
|
id="validationEmail"
|
|
ref="email"
|
|
v-model="email"
|
|
type="email"
|
|
class="form-control"
|
|
placeholder="monemail@example.fr"
|
|
aria-label="Email"
|
|
aria-describedby="emailHelp"
|
|
required
|
|
autocomplete="off"
|
|
@blur="validateEmail"
|
|
>
|
|
<div class="invalid-feedback">
|
|
Veuillez vérifier la saisie de votre email.
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-check mb-5">
|
|
<input
|
|
id="btn-check-agreed"
|
|
ref="checkbox"
|
|
v-model="interested"
|
|
type="checkbox"
|
|
class="form-check-input d-none"
|
|
autocomplete="off"
|
|
required
|
|
aria-describedby="btn-check-agreed-feedback"
|
|
>
|
|
<label class="form-check-label btn btn-light" for="btn-check-agreed">
|
|
<FontAwesomeIcon v-if="!interested" icon="square" />
|
|
<FontAwesomeIcon v-if="interested" icon="square-check" />
|
|
{{ settings.ctaBtnText }}
|
|
</label>
|
|
<div id="btn-check-agreed-feedback" class="invalid-feedback">
|
|
Vous devez cocher la case pour enregistrer votre demande
|
|
</div>
|
|
<div v-sane-html="settings.ctaDisclaimerText" />
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-primary" @click="($refs.form as HTMLFormElement).requestSubmit()">
|
|
{{ settings.ctaSaveBtn }}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
// eslint-disable-next-line import/named
|
|
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
|
|
import DOMPurify from "dompurify";
|
|
import type { DirectiveBinding, PropType } from "vue";
|
|
import { defineComponent } from "vue";
|
|
|
|
const saneHtml = {
|
|
mounted: (el: HTMLElement, binding: DirectiveBinding) => {
|
|
el.innerHTML = DOMPurify.sanitize(binding.value);
|
|
},
|
|
};
|
|
|
|
export default defineComponent({
|
|
name: "ProductModal",
|
|
components: { FontAwesomeIcon },
|
|
directives: {
|
|
saneHtml,
|
|
},
|
|
props: {
|
|
id: {
|
|
type: String,
|
|
required: true,
|
|
},
|
|
item: {
|
|
type: Object as PropType<Item>,
|
|
required: true,
|
|
},
|
|
settings: {
|
|
type: Object as PropType<Settings>,
|
|
required: true,
|
|
}
|
|
},
|
|
emits: ["saved"],
|
|
data(): {
|
|
modalShow: boolean;
|
|
emailIsValid: boolean;
|
|
email: string;
|
|
interested: boolean;
|
|
} {
|
|
return {
|
|
modalShow: false,
|
|
emailIsValid: false,
|
|
email: "",
|
|
interested: false,
|
|
};
|
|
},
|
|
watch: {
|
|
item() {
|
|
this.modalShow = true;
|
|
},
|
|
emailIsValid(newValue:boolean) {
|
|
this.setEmailValidity(newValue);
|
|
},
|
|
interested(newValue:boolean) {
|
|
this.setInterestedValidity(newValue);
|
|
},
|
|
},
|
|
mounted() {
|
|
this.$nextTick(() => {
|
|
const modal = this.$refs.modal as HTMLElement;
|
|
const form = this.$refs.form as HTMLFormElement;
|
|
form.addEventListener("submit", event => {
|
|
// * Empecher le submit dans tout les cas
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
|
|
this.validateEmail();
|
|
this.setEmailValidity(!!this.emailIsValid);
|
|
this.setInterestedValidity(this.interested);
|
|
|
|
// ? Validation Ok ?
|
|
if(this.emailIsValid && this.interested) {
|
|
this.SaveContact();
|
|
}
|
|
}, false);
|
|
modal.addEventListener("hide.bs.modal", () => {
|
|
this.email = "";
|
|
this.interested = false;
|
|
this.clearValidation();
|
|
});
|
|
});
|
|
},
|
|
methods: {
|
|
matchEmail(email:string):RegExpMatchArray | null {
|
|
return String(email)
|
|
.toLowerCase()
|
|
.match(
|
|
/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|.(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
|
|
);
|
|
},
|
|
validateEmail():void {
|
|
this.emailIsValid = !!this.matchEmail(this.email);
|
|
},
|
|
SaveContact() {
|
|
const contact: Contact = {
|
|
product_id: this.item.id,
|
|
email: this.email,
|
|
consent: this.interested
|
|
};
|
|
this.$emit("saved", contact);
|
|
},
|
|
setEmailValidity(validity: boolean): void {
|
|
const email = this.$refs.email as HTMLInputElement;
|
|
this.setInputValidity(email, validity);
|
|
},
|
|
setInterestedValidity(validity: boolean): void {
|
|
const checkbox = this.$refs.checkbox as HTMLInputElement;
|
|
this.setInputValidity(checkbox, validity);
|
|
},
|
|
setInputValidity(input: HTMLInputElement, validity: boolean): void {
|
|
input.classList.remove("is-valid");
|
|
input.classList.remove("is-invalid");
|
|
if (validity) {
|
|
input.classList.add("is-valid");
|
|
} else {
|
|
input.classList.add("is-invalid");
|
|
}
|
|
},
|
|
clearValidation(): void {
|
|
const email = this.$refs.email as HTMLInputElement;
|
|
const checkbox = this.$refs.checkbox as HTMLInputElement;
|
|
email.classList.remove("is-valid");
|
|
checkbox.classList.remove("is-valid");
|
|
email.classList.remove("is-invalid");
|
|
checkbox.classList.remove("is-invalid");
|
|
}
|
|
},
|
|
});
|
|
</script>
|