|
|
@@ -1,42 +1,64 @@
|
|
|
<template>
|
|
|
<LayoutContainer>
|
|
|
- <div v-for="(job, index) in jobs" :key="index" class="mission-container">
|
|
|
- <!-- Première ligne avec alignement vertical -->
|
|
|
- <v-row class="announcement-title ml-6 mr-6 d-flex align-center">
|
|
|
+ <div v-if="pending">
|
|
|
+ <v-row class="justify-center progress">
|
|
|
+ <v-progress-circular
|
|
|
+ indeterminate
|
|
|
+ color="grey"
|
|
|
+ />
|
|
|
+ </v-row>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div
|
|
|
+ v-else
|
|
|
+ v-for="(job, index) in jobs"
|
|
|
+ :key="index"
|
|
|
+ class="mission-container"
|
|
|
+ >
|
|
|
+ <v-row class="title-container">
|
|
|
<NuxtLink
|
|
|
:to="`/nous-rejoindre/${job.id}`"
|
|
|
- class="text-decoration-none"
|
|
|
+ class="title"
|
|
|
>
|
|
|
- <div class="title-job ml-4">
|
|
|
- <!-- Icône étoile pour les annonces 'featured' -->
|
|
|
- {{ job.title }} - {{ job.contractType }}
|
|
|
- <v-icon
|
|
|
- v-if="job.featured"
|
|
|
- class="fas fa-star"
|
|
|
- style="color: yellow"
|
|
|
- ></v-icon>
|
|
|
- </div>
|
|
|
+ {{ job.title }} - {{ job.contractType }}
|
|
|
+
|
|
|
+ <v-icon
|
|
|
+ v-if="job.featured"
|
|
|
+ class="star fas fa-star"
|
|
|
+ />
|
|
|
</NuxtLink>
|
|
|
- <NuxtLink
|
|
|
+
|
|
|
+ <v-btn
|
|
|
:to="`/nous-rejoindre/${job.id}`"
|
|
|
- class="text-decoration-none d-flex align-center"
|
|
|
+ class="btn-more"
|
|
|
>
|
|
|
- <v-icon class="mr-2"> </v-icon>
|
|
|
- <v-btn class="btn-more mr-4" text> En savoir plus </v-btn>
|
|
|
- </NuxtLink>
|
|
|
+ En savoir plus
|
|
|
+ </v-btn>
|
|
|
</v-row>
|
|
|
|
|
|
- <v-row class="announcement-location ml-6 mr-6">
|
|
|
- <v-icon class="icon-location">
|
|
|
- <i class="fas fa-map-marker"></i>
|
|
|
- </v-icon>
|
|
|
+ <v-row class="location-container">
|
|
|
+ <v-icon icon="fas fa-map-marker" />
|
|
|
<div class="location">
|
|
|
{{ job.city }}
|
|
|
</div>
|
|
|
</v-row>
|
|
|
</div>
|
|
|
|
|
|
- <v-row class="apply-row ml-6 mb-6">
|
|
|
+ <v-row>
|
|
|
+ <v-col cols="12">
|
|
|
+ <v-pagination
|
|
|
+ v-if="lastPage"
|
|
|
+ :model-value="page"
|
|
|
+ :length="lastPage"
|
|
|
+ rounded="circle"
|
|
|
+ max="10"
|
|
|
+ class="pagination"
|
|
|
+ @update:model-value="pageUpdated"
|
|
|
+ />
|
|
|
+ </v-col>
|
|
|
+ </v-row>
|
|
|
+
|
|
|
+ <v-row class="ml-6 mb-6">
|
|
|
<v-col cols="12">
|
|
|
<p class="apply-now">
|
|
|
Nous sommes toujours à la recherche de nouveaux talents. N'hésitez pas
|
|
|
@@ -44,40 +66,81 @@
|
|
|
</p>
|
|
|
</v-col>
|
|
|
</v-row>
|
|
|
+
|
|
|
<v-row>
|
|
|
<v-col cols="12">
|
|
|
- <v-btn class="btn-send" @click="dialog = true">
|
|
|
+ <v-btn
|
|
|
+ class="btn-send"
|
|
|
+ @click="dialog = true"
|
|
|
+ >
|
|
|
Envoyer ma candidature
|
|
|
</v-btn>
|
|
|
</v-col>
|
|
|
</v-row>
|
|
|
|
|
|
- <v-dialog v-model="dialog" max-width="600px">
|
|
|
+ <!-- Boite de dialogue "soumettre une candidature" -->
|
|
|
+ <v-dialog
|
|
|
+ v-model="dialog"
|
|
|
+ max-width="600px"
|
|
|
+ >
|
|
|
<v-card>
|
|
|
- <v-card-title class="text-center" style="font-family: Barlow">
|
|
|
+ <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>
|
|
|
- <v-text-field label="Prénom*" required></v-text-field>
|
|
|
- <v-text-field label="Téléphone*" required></v-text-field>
|
|
|
- <v-text-field label="Email*" required></v-text-field>
|
|
|
+ <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>
|
|
|
+ />
|
|
|
+
|
|
|
<v-file-input
|
|
|
label="Dépôt de lettre de motivation"
|
|
|
accept=".pdf, .jpeg, .png"
|
|
|
- ></v-file-input>
|
|
|
- <v-textarea label="Message*" required></v-textarea>
|
|
|
+ />
|
|
|
+
|
|
|
+ <v-textarea
|
|
|
+ label="Message*"
|
|
|
+ required
|
|
|
+ />
|
|
|
</v-form>
|
|
|
</v-card-text>
|
|
|
- <p class="text-right mr-6">* Champs obligatoires</p>
|
|
|
- <v-card-actions>
|
|
|
- <v-btn class="btn-more" @click="sendApplication">Envoyer</v-btn>
|
|
|
+
|
|
|
+ <p class="text-right mr-6">
|
|
|
+ * Champs obligatoires
|
|
|
+ </p>
|
|
|
+
|
|
|
+ <v-card-actions class="justify-center">
|
|
|
+ <v-btn
|
|
|
+ class="btn-more mb-4"
|
|
|
+ @click="sendApplication"
|
|
|
+ >
|
|
|
+ Envoyer
|
|
|
+ </v-btn>
|
|
|
</v-card-actions>
|
|
|
</v-card>
|
|
|
</v-dialog>
|
|
|
@@ -85,106 +148,142 @@
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
-import { ref } from "vue";
|
|
|
-import { useMaestroRequestService } from "~/composables/useMaestroRequestService";
|
|
|
-const { apiRequestService } = useMaestroRequestService();
|
|
|
+import { useEntityFetch } from "~/composables/data/useEntityFetch";
|
|
|
+import JobPosting from "~/models/Maestro/JobPosting";
|
|
|
+import { ComputedRef } from "vue";
|
|
|
+import { AnyJson } from "~/types/data";
|
|
|
|
|
|
-const dialog = ref(false);
|
|
|
+const i18n = useI18n();
|
|
|
+const router = useRouter()
|
|
|
+const { fetchCollection } = useEntityFetch()
|
|
|
|
|
|
-const sendApplication = () => {
|
|
|
- console.log("Formulaire envoyé");
|
|
|
- dialog.value = false;
|
|
|
-};
|
|
|
+const page: Ref<number> = ref(1);
|
|
|
|
|
|
-const query = computed(() => {
|
|
|
- const queryParams: {
|
|
|
- page: number;
|
|
|
- type?: string;
|
|
|
- [key: string]: number | string;
|
|
|
- } = {
|
|
|
- page: page.value,
|
|
|
- type: "ENTREPRISE",
|
|
|
- };
|
|
|
+const query: ComputedRef<AnyJson> = computed(() => {
|
|
|
+ return { type: "ENTREPRISE", page: page.value }
|
|
|
+ }
|
|
|
+)
|
|
|
|
|
|
- return queryParams;
|
|
|
-});
|
|
|
+const { data: jobCollection, pending, refresh } = fetchCollection(
|
|
|
+ JobPosting,
|
|
|
+ null,
|
|
|
+ query
|
|
|
+)
|
|
|
|
|
|
-const totalItems = ref(0);
|
|
|
-const config = useRuntimeConfig();
|
|
|
-const baseUrl = `${config.public.apiBaseUrl}/api/job-postings`;
|
|
|
+const jobs: ComputedRef<JobPosting[]> = computed(() => {
|
|
|
+ return jobCollection.value !== null ?
|
|
|
+ jobCollection.value.items as JobPosting[] :
|
|
|
+ []
|
|
|
+})
|
|
|
|
|
|
-const page: Ref<number> = ref(1);
|
|
|
-const itemsPerPage: Ref<number> = ref(10);
|
|
|
-const { t } = useI18n();
|
|
|
-
|
|
|
-const {
|
|
|
- data: jobs = [],
|
|
|
- pending,
|
|
|
- refresh,
|
|
|
-} = useLazyAsyncData("files", async () => {
|
|
|
- const response = await apiRequestService.get(baseUrl, query.value);
|
|
|
- const collection = response["hydra:member"];
|
|
|
- const currentDate = new Date();
|
|
|
-
|
|
|
- // Séparer les annonces 'featured'
|
|
|
- const featuredJobs = collection.filter(
|
|
|
- (item) => item.featured && new Date(item.startPublication) <= currentDate
|
|
|
- );
|
|
|
-
|
|
|
- // Filtrer et trier les autres annonces
|
|
|
- const regularJobs = collection.filter((item) => {
|
|
|
- const startPublicationDate = new Date(item.startPublication);
|
|
|
- const endPublicationDate = new Date(item.endPublication);
|
|
|
- return (
|
|
|
- !item.featured &&
|
|
|
- startPublicationDate <= currentDate &&
|
|
|
- endPublicationDate >= currentDate
|
|
|
- );
|
|
|
- });
|
|
|
-
|
|
|
- // Combinez les annonces 'featured' et les autres annonces
|
|
|
- const combinedJobs = [...featuredJobs, ...regularJobs];
|
|
|
-
|
|
|
- totalItems.value = combinedJobs.length;
|
|
|
- console.log(combinedJobs);
|
|
|
- return combinedJobs;
|
|
|
-});
|
|
|
-</script>
|
|
|
+const lastPage: ComputedRef<number | null> = computed(() => {
|
|
|
+ return jobCollection.value !== null && jobCollection.value.pagination ?
|
|
|
+ jobCollection.value.pagination.last ?? null :
|
|
|
+ null
|
|
|
+})
|
|
|
|
|
|
-<style scoped>
|
|
|
-<style scoped>
|
|
|
-.location {
|
|
|
- font-size: 1.3rem !important;
|
|
|
- color: #0e2d32;
|
|
|
-}
|
|
|
-.announcement-title {
|
|
|
- background: #0e2d32;
|
|
|
- color: white;
|
|
|
- display: flex;
|
|
|
- justify-content: space-between;
|
|
|
- height: 80px;
|
|
|
- padding: 10px 10px 10px 1;
|
|
|
+const pageUpdated = async (newVal: number): Promise<void> => {
|
|
|
+ page.value = newVal
|
|
|
+
|
|
|
+ pending.value = true
|
|
|
+ await navigateTo({ path: '', hash: '#join-us-anchor' })
|
|
|
+
|
|
|
+ setTimeout(
|
|
|
+ async () => await refresh(),
|
|
|
+ 100
|
|
|
+ )
|
|
|
}
|
|
|
|
|
|
-.title-job {
|
|
|
- font-family: "Barlow";
|
|
|
- font-style: normal;
|
|
|
- font-weight: 600;
|
|
|
- font-size: 1.5rem;
|
|
|
- line-height: 39px;
|
|
|
- color: #ffffff;
|
|
|
+/**
|
|
|
+ * 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">
|
|
|
+.progress {
|
|
|
+ margin: 32px auto 128px auto;
|
|
|
}
|
|
|
|
|
|
-.btn-more,
|
|
|
-.btn-send {
|
|
|
+.v-btn {
|
|
|
font-weight: 600;
|
|
|
height: 50px;
|
|
|
- background: #64afb7;
|
|
|
+ background: var(--secondary-color);
|
|
|
border-radius: 6px;
|
|
|
- color: white;
|
|
|
+ color: var(--on-secondary-color);
|
|
|
gap: 9px;
|
|
|
}
|
|
|
|
|
|
+.mission-container {
|
|
|
+ margin: 64px 12%;
|
|
|
+
|
|
|
+ .title-container {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ background: var(--primary-color);
|
|
|
+ color: var(--on-primary-color);
|
|
|
+ height: 80px;
|
|
|
+ padding: 10px 10px 10px 1px;
|
|
|
+
|
|
|
+ .title {
|
|
|
+ font-family: "Barlow",serif;
|
|
|
+ font-style: normal;
|
|
|
+ font-weight: 600;
|
|
|
+ font-size: 1.5rem;
|
|
|
+ line-height: 39px;
|
|
|
+ color: #ffffff;
|
|
|
+ text-decoration: none;
|
|
|
+ margin-left: 36px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .star {
|
|
|
+ margin-left: 12px;
|
|
|
+ font-size: 24px;
|
|
|
+ color: yellow;
|
|
|
+ vertical-align: baseline;
|
|
|
+ }
|
|
|
+
|
|
|
+ .btn-more {
|
|
|
+ margin-right: 8px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .location-container {
|
|
|
+ background: #9edbdd;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ padding: 10px;
|
|
|
+
|
|
|
+ .v-icon {
|
|
|
+ font-size: 1rem !important;
|
|
|
+ color: #0e2d32;
|
|
|
+ }
|
|
|
+
|
|
|
+ .location {
|
|
|
+ color: var(--primary-color);
|
|
|
+ margin-left: 10px;
|
|
|
+ font-size: 1.3rem;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+@media (max-width: 600px) {
|
|
|
+ .mission-container {
|
|
|
+ margin: 64px 6%;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
.btn-send {
|
|
|
display: flex;
|
|
|
justify-content: center;
|
|
|
@@ -195,23 +294,6 @@ const {
|
|
|
font-weight: 700;
|
|
|
}
|
|
|
|
|
|
-.announcement-location {
|
|
|
- background: #9edbdd;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- padding: 10px;
|
|
|
-}
|
|
|
-
|
|
|
-.icon-location {
|
|
|
- font-size: 1rem !important;
|
|
|
- color: #0e2d32;
|
|
|
-}
|
|
|
-
|
|
|
-.location {
|
|
|
- margin-left: 10px;
|
|
|
- font-size: 2rem;
|
|
|
-}
|
|
|
-
|
|
|
.apply-now {
|
|
|
text-align: center;
|
|
|
font-style: italic;
|
|
|
@@ -222,8 +304,11 @@ const {
|
|
|
margin-bottom: 2rem;
|
|
|
}
|
|
|
|
|
|
-.mission-container {
|
|
|
- margin-top: 3rem;
|
|
|
- margin-bottom: 5%;
|
|
|
+.v-dialog {
|
|
|
+ font-family: Barlow, serif;
|
|
|
+
|
|
|
+ .btn-more {
|
|
|
+ width: 128px;
|
|
|
+ }
|
|
|
}
|
|
|
</style>
|