| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225 |
- <template>
- <div>
- <v-card v-if="!jobApplicationSent">
- <v-card-title class="text-center">
- Formulaire de Candidature
- </v-card-title>
- <v-card-text>
- <v-form ref="form" validate-on="submit lazy" @submit.prevent="submit">
- <v-text-field
- id="jobApplicationName"
- v-model="jobApplication.name"
- :rules="[validateName]"
- label="Nom*"
- required
- />
- <v-text-field
- id="jobApplicationSurname"
- v-model="jobApplication.surname"
- :rules="[validateSurname]"
- label="Prénom*"
- required
- />
- <v-text-field
- id="jobApplicationPhone"
- v-model="jobApplication.phone"
- :rules="[validatePhone]"
- label="Téléphone*"
- required
- />
- <v-text-field
- id="jobApplicationEmail"
- v-model="jobApplication.email"
- :rules="[validateEmail]"
- label="Email*"
- required
- />
- <v-file-input
- id="jobApplicationResume"
- v-model="resumeUpload"
- :rules="[validateResume, validateResumeFileSize]"
- label="Dépôt de CV*"
- accept=".pdf, .jpeg, .png"
- show-size
- required
- />
- <v-file-input
- id="jobApplicationMotivationLetter"
- v-model="motivationLetterUpload"
- :rules="[
- validateMotivationLetter,
- validateMotivationLetterFileSize,
- ]"
- label="Dépôt de lettre de motivation"
- accept=".pdf, .jpeg, .png"
- show-size
- />
- <v-textarea
- id="jobApplicationMessage"
- v-model="jobApplication.message"
- :rules="[validateNonEmptyMessage, validateMessageLength]"
- label="Message*"
- required
- />
- <span class="remaining-cars-notice"
- >{{ leftCars }} caractères restants</span
- >
- <div class="d-flex flex-column align-center mt-4">
- <!-- @see https://github.com/hCaptcha/vue-hcaptcha -->
- <LayoutCaptcha />
- </div>
- </v-form>
- </v-card-text>
- <p class="text-right mr-6">* Champs obligatoires</p>
- <v-card-actions class="justify-center">
- <v-btn class="btn-more mb-4 submit" @click="submit"> Envoyer </v-btn>
- </v-card-actions>
- </v-card>
- </div>
- </template>
- <script setup lang="ts">
- import type { ComputedRef, PropType, Ref } from 'vue'
- import { reactive } from 'vue'
- import ContactRequest from '~/models/Maestro/ContactRequest'
- import { useEntityManager } from '~/composables/data/useEntityManager'
- import JobApplication from '~/models/Maestro/JobApplication'
- import FileUtils from '~/services/utils/FileUtils'
- const props = defineProps({
- jobPostingId: {
- type: Number as PropType<number | null>,
- required: false,
- default: null,
- },
- })
- const { em } = useEntityManager()
- const form: Ref<HTMLElement | null> = ref(null)
- const jobApplicationSent: Ref<boolean> = ref(false)
- const emit = defineEmits(['submit'])
- // @ts-ignore
- const jobApplication: ContactRequest = reactive(em.newInstance(JobApplication))
- const resumeUpload = ref(null)
- const motivationLetterUpload = ref(null)
- // --- Validation ---
- const maxMessageLength = 2000
- const leftCars: ComputedRef<number> = computed(
- () =>
- maxMessageLength -
- (jobApplication.message ? jobApplication.message.length : 0)
- )
- // Taille maximum en Mo
- const maxFileSize = 5
- const validateName = (name: string | null) => !!name || 'Le nom est obligatoire'
- const validateSurname = (surname: string | null) =>
- !!surname || 'Le prénom est obligatoire'
- const validateEmail = (email: string | null) =>
- (!!email && /.+@.+\..+/.test(email)) || "L'adresse e-mail doit être valide"
- const validatePhone = (email: string | null) =>
- (!!email && /^((\+|00)33\s?|0)[1-7]([\s.]?\d{2}){4}$/.test(email)) ||
- 'Le numéro de téléphone doit être valide'
- const validateResume = () =>
- (resumeUpload.value !== null && resumeUpload.value[0] !== null) ||
- "Vous devez joindre un CV à l'un des formats suivants : .pdf, .jpeg, .png"
- const validateResumeFileSize = () =>
- (resumeUpload.value !== null &&
- // @ts-ignore
- resumeUpload.value.size < maxFileSize * 1024 * 1024) ||
- 'La taille du fichier ne doit pas dépasser ' + maxFileSize + ' Mo'
- const validateMotivationLetter = () =>
- motivationLetterUpload.value === null ||
- motivationLetterUpload.value[0] !== null ||
- "Vous devez joindre votre lettre de motivation à l'un des formats suivants : .pdf, .jpeg, .png"
- const validateMotivationLetterFileSize = () =>
- motivationLetterUpload.value === null ||
- // @ts-ignore
- motivationLetterUpload.value.size < maxFileSize * 1024 * 1024 ||
- 'La taille du fichier ne doit pas dépasser ' + maxFileSize + ' Mo'
- const validateNonEmptyMessage = (message: string | null) =>
- (!!message && message.length > 0) || 'Le message ne peut pas être vide'
- const validateMessageLength = (message: string | null) =>
- (!!message && message.length <= maxMessageLength) ||
- 'Le message ne doit pas dépasser ' + maxMessageLength + ' caractères'
- /**
- * Soumet le formulaire de candidature (boite de dialogue)
- */
- const submit = async () => {
- jobApplication.jobPostingId = props.jobPostingId
- jobApplication.resume =
- resumeUpload.value !== null
- ? {
- // @ts-ignore
- name: resumeUpload.value.name,
- content: await FileUtils.blobToBase64(resumeUpload.value),
- }
- : null
- jobApplication.motivationLetter =
- motivationLetterUpload.value !== null
- ? {
- // @ts-ignore
- name: motivationLetterUpload.value.name,
- content: await FileUtils.blobToBase64(motivationLetterUpload.value),
- }
- : null
- // @ts-ignore
- const { valid } = await form.value!.validate()
- if (!valid) {
- jobApplicationSent.value = false
- return
- }
- await em.persist(JobApplication, jobApplication)
- jobApplicationSent.value = true
- emit('submit')
- }
- </script>
- <style scoped lang="scss">
- .submit {
- width: 100%;
- margin-bottom: 0 !important;
- height: 55px;
- background: var(--secondary-color);
- }
- .submit:hover {
- background-color: var(--on-neutral-color-extra-light);
- }
- </style>
|