Переглянути джерело

add the JobApplication model and implement form

Olivier Massot 1 рік тому
батько
коміт
a97508739e

+ 2 - 2
components/Contact/Form.vue

@@ -152,7 +152,7 @@
         <!-- Policy and  checkboxes -->
         <v-checkbox
           v-model="contactRequest.privacyPolicyAccepted"
-          :rules="[(v) => !!v || 'Vous devez accepter la politique de confidentialité']"
+          :rules="[(v: boolean) => v || 'Vous devez accepter la politique de confidentialité']"
           label="J'ai pris connaissance de la politique de confidentialité et j'accepte le traitement de mes données personnelles par Opentalent."
         />
 
@@ -222,13 +222,13 @@ const defaultRequestType = route.query.request ?? 'CONTACT_REQUEST_INFORMATION'
 //@ts-ignore
 const contactRequest: ContactRequest = reactive(em.newInstance(ContactRequest, { requestType: defaultRequestType }))
 
+// --- Validation ---
 const maxMessageLength = 2000
 
 const leftCars: ComputedRef<number> = computed(() =>
   maxMessageLength - (contactRequest.message ? contactRequest.message.length : 0)
 )
 
-// --- Validation ---
 const validateName = (name: string | null) => !!name || "Le nom est obligatoire";
 
 const validateSurname = (surname: string | null) => !!surname || "Le prénom est obligatoire";

+ 151 - 0
components/JoinUs/Form.vue

@@ -0,0 +1,151 @@
+<template>
+  <v-card>
+    <v-card-title
+      class="text-center"
+    >
+      Formulaire de Candidature
+    </v-card-title>
+
+    <v-card-text>
+      <v-form
+        v-if="!jobApplicationSent"
+        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="jobApplication.resume"
+          label="Dépôt de CV*"
+          accept=".pdf, .jpeg, .png"
+          required
+        />
+
+        <v-file-input
+          id="jobApplicationMotivationLetter"
+          v-model="jobApplication.motivationLetter"
+          label="Dépôt de lettre de motivation"
+          accept=".pdf, .jpeg, .png"
+        />
+
+        <v-textarea
+          id="jobApplicationMessage"
+          v-model="jobApplication.message"
+          :rules="[validateNonEmptyMessage, validateMessageLength]"
+          label="Message*"
+          required
+        />
+        <span class="remaining-cars-notice">{{ leftCars }} caractères restants</span>
+      </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"
+        @click="submit"
+      >
+        Envoyer
+      </v-btn>
+    </v-card-actions>
+  </v-card>
+</template>
+
+<script setup lang="ts">
+import ContactRequest from "~/models/Maestro/ContactRequest";
+import { useEntityManager } from "~/composables/data/useEntityManager";
+import JobApplication from "~/models/Maestro/JobApplication";
+
+const { em } = useEntityManager()
+
+const form: Ref<any | null> = ref(null)
+
+const jobApplicationSent: Ref<boolean> = ref(false)
+
+const emit = defineEmits(['submit'])
+
+//@ts-ignore
+const jobApplication: ContactRequest = reactive(em.newInstance(JobApplication))
+
+// --- Validation ---
+const maxMessageLength = 2000
+
+const leftCars: ComputedRef<number> = computed(() =>
+  maxMessageLength - (jobApplication.message ? jobApplication.message.length : 0)
+)
+
+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 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 () => {
+  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">
+
+</style>

+ 9 - 69
components/JoinUs/Missions.vue

@@ -80,67 +80,17 @@
     <v-dialog
       v-model="dialog"
       max-width="600px"
+      persistent
+      no-click-animation
+      :retain-focus="false"
     >
-      <v-card>
-        <v-card-title
-          class="text-center"
-        >
-          Formulaire de Candidature
-        </v-card-title>
-
-        <v-card-text>
-          <v-form>
-            <v-text-field
-              label="Nom*"
-              required
-            />
-
-            <v-text-field
-              label="Prénom*"
-              required
-            />
-
-            <v-text-field
-              label="Téléphone*"
-              required
-            />
-
-            <v-text-field
-              label="Email*"
-              required
-            />
-
-            <v-file-input
-              label="Dépôt de CV*"
-              accept=".pdf, .jpeg, .png"
-              required
-            />
-
-            <v-file-input
-              label="Dépôt de lettre de motivation"
-              accept=".pdf, .jpeg, .png"
-            />
-
-            <v-textarea
-              label="Message*"
-              required
-            />
-          </v-form>
-        </v-card-text>
-
-        <p class="text-right mr-6">
-          * Champs obligatoires
-        </p>
+      <JoinUsForm />
 
-        <v-card-actions class="justify-center">
-          <v-btn
-            class="btn-more mb-4"
-            @click="sendApplication"
-          >
-            Envoyer
-          </v-btn>
-        </v-card-actions>
-      </v-card>
+      <v-btn
+        @click="dialog = false"
+      >
+        Annuler
+      </v-btn>
     </v-dialog>
   </LayoutContainer>
 </template>
@@ -150,8 +100,6 @@ import { useEntityFetch } from "~/composables/data/useEntityFetch";
 import JobPosting from "~/models/Maestro/JobPosting";
 import type { AnyJson } from "~/types/data";
 
-const i18n = useI18n();
-const router = useRouter()
 const { fetchCollection } = useEntityFetch()
 
 const page: Ref<number> = ref(1);
@@ -191,14 +139,6 @@ const onPageUpdated = async (newVal: number): Promise<void> => {
  * Faut-il afficher la boite de dialogue de candidature
  */
 const dialog = ref(false);
-
-/**
- * Soumet le formulaire de candidature (boite de dialogue)
- */
-const sendApplication = () => {
-  // TODO: implémenter le submit
-  dialog.value = false;
-};
 </script>
 
 <style scoped lang="scss">

+ 2 - 2
models/Maestro/ContactRequest.ts

@@ -2,9 +2,9 @@ import ApiModel from "~/models/ApiModel";
 import {Uid, Str, Bool, Attr} from "pinia-orm/dist/decorators";
 
 /**
- * Maestro Model : JobPosting
+ * Maestro Model : ContactRequest
  *
- * @see https://gitlab.2iopenservice.com/opentalent/maestro/-/blob/master/src/Entity/JobPosting/JobPosting.php?ref_type=heads
+ * @see https://gitlab.2iopenservice.com/opentalent/maestro/-/blob/master/src/ApiResource/ContactRequest.php?ref_type=heads
  */
 export default class ContactRequest extends ApiModel {
   static entity = 'contact-request'

+ 35 - 0
models/Maestro/JobApplication.ts

@@ -0,0 +1,35 @@
+import ApiModel from "~/models/ApiModel";
+import {Uid, Str, Bool, Attr} from "pinia-orm/dist/decorators";
+
+/**
+ * Maestro Model : JobApplication
+ *
+ * @see https://gitlab.2iopenservice.com/opentalent/maestro/-/blob/master/src/ApiResources/JobApplication.php?ref_type=heads
+ */
+export default class JobApplication extends ApiModel {
+  static entity = 'job-application'
+
+  @Uid()
+  declare id: number
+
+  @Str(null)
+  declare name: string | null
+
+  @Str(null)
+  declare surname: string | null
+
+  @Str(null)
+  declare phone: string | null
+
+  @Str(null)
+  declare email: string | null
+
+  @Attr(null)
+  declare resume: object | null
+
+  @Attr(null)
+  declare motivationLetter: object | null
+
+  @Str(null)
+  declare message: string | null
+}