Banner.vue 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. <template>
  2. <LayoutContainer>
  3. <LayoutUITitlePage
  4. title="Besoin d'aide ?"
  5. subtitle="Notre équipe est là pour vous. contactez-nous!. "
  6. />
  7. <v-row>
  8. <v-col cols="12" style="position: relative">
  9. <img
  10. src="/images/formation/banner.jpg"
  11. alt="line"
  12. class="cover-image"
  13. />
  14. </v-col>
  15. </v-row>
  16. <div class="container-contact">
  17. <v-form ref="form" v-model="valid" lazy-validation>
  18. <v-container>
  19. <h4 class="title-h4">Veuillez remplir le formulaire ci-dessous</h4>
  20. <h6 class="infos">Vos coordonnées</h6>
  21. <!-- Gender selection in one row -->
  22. <v-row>
  23. <v-col cols="12">
  24. <v-radio-group v-model="gender" row mandatory inline>
  25. <v-radio label="Madame" value="Madame"></v-radio>
  26. <v-radio label="Monsieur" value="Monsieur"></v-radio>
  27. </v-radio-group>
  28. </v-col>
  29. </v-row>
  30. <!-- Name and Surname on the same line -->
  31. <v-row>
  32. <v-col cols="12" md="6">
  33. <v-text-field
  34. v-model="name"
  35. :rules="nameRules"
  36. label="Nom*"
  37. required
  38. ></v-text-field>
  39. </v-col>
  40. <v-col cols="12" md="6">
  41. <v-text-field
  42. v-model="surname"
  43. :rules="surnameRules"
  44. label="Prénom*"
  45. required
  46. ></v-text-field>
  47. </v-col>
  48. </v-row>
  49. <!-- Postal code and city on the same line -->
  50. <v-row>
  51. <v-col cols="12" md="6">
  52. <v-text-field
  53. v-model="postalCode"
  54. label="Code postal"
  55. type="number"
  56. ></v-text-field>
  57. </v-col>
  58. <v-col cols="12" md="6">
  59. <v-text-field v-model="city" label="Ville"></v-text-field>
  60. </v-col>
  61. </v-row>
  62. <!-- Email and phone on the same line -->
  63. <v-row>
  64. <v-col cols="12" md="6">
  65. <v-text-field
  66. v-model="email"
  67. :rules="emailRules"
  68. label="Email*"
  69. required
  70. type="email"
  71. ></v-text-field>
  72. </v-col>
  73. <v-col cols="12" md="6">
  74. <v-text-field
  75. v-model="phone"
  76. label="Téléphone"
  77. type="tel"
  78. ></v-text-field>
  79. </v-col>
  80. </v-row>
  81. <!-- Structure name on its own line -->
  82. <v-row>
  83. <v-col cols="12">
  84. <v-text-field
  85. v-model="structureName"
  86. :rules="structureNameRules"
  87. label="Nom de la structure*"
  88. required
  89. ></v-text-field>
  90. </v-col>
  91. </v-row>
  92. <h6 class="infos">Votre demande concerne</h6>
  93. <!-- Request type and product concerned on the same line -->
  94. <v-row>
  95. <v-col cols="12" md="6">
  96. <v-select
  97. v-model="requestType"
  98. :items="requestTypes"
  99. label="Votre demande concerne"
  100. outlined
  101. dense
  102. ></v-select>
  103. </v-col>
  104. <v-col cols="12" md="6">
  105. <v-text-field
  106. v-model="concernedProduct"
  107. label="Le produit concerné"
  108. outlined
  109. dense
  110. ></v-text-field>
  111. </v-col>
  112. </v-row>
  113. <h6 class="infos">Votre message</h6>
  114. <!-- Message on its own line -->
  115. <v-row>
  116. <v-col cols="12">
  117. <v-textarea
  118. v-model="message"
  119. :rules="messageRules"
  120. label="Votre message*"
  121. required
  122. outlined
  123. dense
  124. maxlength="400"
  125. ></v-textarea>
  126. </v-col>
  127. </v-row>
  128. <!-- Policy and checkboxes -->
  129. <v-row>
  130. <v-col cols="12">
  131. <v-checkbox
  132. v-model="privacyPolicy"
  133. :rules="[(v) => !!v || 'You must accept the privacy policy']"
  134. label="J'ai pris connaissance de la politique de confidentialité et j'accepte le traitement de mes données personnelles par Opentalent."
  135. ></v-checkbox>
  136. </v-col>
  137. </v-row>
  138. <v-row>
  139. <v-col cols="12">
  140. <v-checkbox
  141. v-model="newsletterSubscription"
  142. label="Je souhaite recevoir des communications d'Opentalent par email (promotions, informations logiciel…). Je pourrai me désinscrire à tout moment."
  143. ></v-checkbox>
  144. </v-col>
  145. </v-row>
  146. <v-row>
  147. <v-col cols="12">
  148. <v-checkbox
  149. v-model="captchaChecked"
  150. :rules="[(v) => !!v || 'You must pass the captcha']"
  151. label="Captcha"
  152. ></v-checkbox>
  153. </v-col>
  154. </v-row>
  155. <!-- Submit Button -->
  156. <v-row>
  157. <v-col cols="12">
  158. <v-btn :disabled="!valid" @click="submitForm">Envoyer</v-btn>
  159. </v-col>
  160. </v-row>
  161. </v-container>
  162. </v-form>
  163. <div v-if="submissionStatus">
  164. {{ submissionStatus }}
  165. </div>
  166. </div>
  167. <div id="map" style="height: 500px"></div>
  168. </LayoutContainer>
  169. </template>
  170. <script setup>
  171. import { ref, reactive, computed, toRefs } from "vue";
  172. import { useRoute } from "vue-router";
  173. import { onMounted } from "vue";
  174. import L from "leaflet";
  175. import "leaflet/dist/leaflet.css";
  176. onMounted(() => {
  177. const map = L.map("map").setView([46.075245, 6.570162], 16);
  178. L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
  179. maxZoom: 19,
  180. attribution: "© OpenStreetMap contributors",
  181. }).addTo(map);
  182. const marker = L.marker([46.075245, 6.570162]).addTo(map);
  183. });
  184. const route = useRoute();
  185. const defaultRequestType = route.query.request;
  186. const captchaChecked = ref(false);
  187. const name = ref("");
  188. const surname = ref("");
  189. const email = ref("");
  190. const structureName = ref("");
  191. const message = ref("");
  192. const privacyPolicy = ref(false);
  193. const gender = ref(null);
  194. const postalCode = ref(null);
  195. const city = ref("");
  196. const phone = ref(null);
  197. const concernedProduct = ref("");
  198. const newsletterSubscription = ref(false);
  199. const submissionStatus = ref("");
  200. const validateName = (name) => !!name || "Name is required";
  201. const validateSurname = (surname) => !!surname || "Surname is required";
  202. const validateEmail = (email) =>
  203. (!!email && /.+@.+\..+/.test(email)) || "E-mail must be valid";
  204. const validateStructureName = (structureName) =>
  205. !!structureName || "Structure name is required";
  206. const validateMessage = (message) =>
  207. (!!message && message.length <= 400) ||
  208. "Message cannot exceed 400 characters";
  209. const valid = computed(() => {
  210. return (
  211. validateName(name.value) === true &&
  212. validateSurname(surname.value) === true &&
  213. validateEmail(email.value) === true &&
  214. validateStructureName(structureName.value) === true &&
  215. validateMessage(message.value) === true &&
  216. privacyPolicy.value === true &&
  217. captchaChecked.value === true
  218. );
  219. });
  220. const requestTypes = [
  221. "Demande d'information",
  222. "Demande de devis",
  223. "Demande de démonstration",
  224. "Demande d'option supplémentaire",
  225. "Autre",
  226. ];
  227. const requestType = ref(
  228. defaultRequestType === "demo" ? "Demande de démonstration" : null
  229. );
  230. const formData = reactive({
  231. gender: null,
  232. postalCode: null,
  233. city: "",
  234. phone: null,
  235. requestType: null,
  236. concernedProduct: "",
  237. newsletterSubscription,
  238. });
  239. // Methods
  240. const submitForm = () => {
  241. if (valid.value) {
  242. // Logique d'envoi du formulaire
  243. submissionStatus.value = "Mail envoyé à contact@opentalent.fr";
  244. } else {
  245. console.log("Validation failed!");
  246. submissionStatus.value = "";
  247. }
  248. };
  249. const formDataRefs = toRefs(formData);
  250. const formRefs = {
  251. ...formDataRefs,
  252. name,
  253. surname,
  254. email,
  255. structureName,
  256. message,
  257. privacyPolicy,
  258. valid,
  259. };
  260. </script>
  261. <style scoped>
  262. #map {
  263. height: 100%;
  264. width: 70%;
  265. margin-left: auto;
  266. margin-right: auto;
  267. }
  268. .infos {
  269. font-size: 20px;
  270. color: #000000;
  271. margin-bottom: 1rem;
  272. }
  273. .container-contact {
  274. max-width: 1400px;
  275. margin: 0 auto;
  276. }
  277. .title-h4 {
  278. font-size: 40px;
  279. line-height: 95px;
  280. color: #000000;
  281. margin-bottom: 1rem;
  282. color: rgba(0, 0, 0, 0.3);
  283. }
  284. .image-text {
  285. position: absolute;
  286. top: 40px;
  287. left: 20px;
  288. font-family: "Barlow";
  289. color: white;
  290. font-size: 3rem;
  291. width: 30rem;
  292. font-style: italic;
  293. font-weight: 300;
  294. line-height: 40px;
  295. }
  296. :deep().subtitle {
  297. font-size: 1.5rem;
  298. line-height: 2rem;
  299. letter-spacing: 0.1rem;
  300. margin-bottom: 1rem;
  301. text-transform: uppercase;
  302. }
  303. .formation {
  304. font-family: "Barlow";
  305. font-style: normal;
  306. font-weight: 600;
  307. font-size: 90px;
  308. line-height: 85px;
  309. text-align: center;
  310. color: #000000;
  311. margin-bottom: 1rem;
  312. }
  313. .menu-container {
  314. display: flex;
  315. justify-content: space-around;
  316. padding: 1rem 10rem;
  317. background: white;
  318. color: #bbb8b8;
  319. font-family: "Barlow";
  320. font-size: 12px;
  321. line-height: 16px;
  322. display: flex;
  323. align-items: center;
  324. text-align: center;
  325. letter-spacing: 0.18em;
  326. text-transform: uppercase;
  327. }
  328. .v-chip.active-menu {
  329. background: black;
  330. color: white;
  331. }
  332. .cover-image {
  333. width: 100%;
  334. height: 15rem;
  335. object-fit: cover;
  336. object-position: center 30%;
  337. margin: 0 auto;
  338. transform: scaleX(-1);
  339. }
  340. </style>