Missions.vue 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. <template>
  2. <LayoutContainer>
  3. <div v-if="pending">
  4. <v-row class="justify-center progress">
  5. <v-progress-circular
  6. indeterminate
  7. color="grey"
  8. />
  9. </v-row>
  10. </div>
  11. <div
  12. v-else
  13. v-for="(job, index) in jobs"
  14. :key="index"
  15. class="mission-container"
  16. >
  17. <v-row class="title-container">
  18. <NuxtLink
  19. :to="`/nous-rejoindre/${job.id}`"
  20. class="title"
  21. >
  22. {{ job.title }} - {{ job.contractType }}
  23. <v-icon
  24. v-if="job.featured"
  25. class="star fas fa-star"
  26. />
  27. </NuxtLink>
  28. <v-btn
  29. :to="`/nous-rejoindre/${job.id}`"
  30. class="btn-more"
  31. >
  32. En savoir plus
  33. </v-btn>
  34. </v-row>
  35. <v-row class="location-container">
  36. <v-icon icon="fas fa-map-marker" />
  37. <div class="location">
  38. {{ job.city }}
  39. </div>
  40. </v-row>
  41. </div>
  42. <v-row>
  43. <v-col cols="12">
  44. <LayoutPagination
  45. v-if="jobCollection && jobCollection.pagination"
  46. :model-value="page"
  47. :pagination="jobCollection.pagination"
  48. @update:model-value="onPageUpdated"
  49. class="mt-4"
  50. />
  51. </v-col>
  52. </v-row>
  53. <v-row class="ml-6 mb-6">
  54. <v-col cols="12">
  55. <p class="apply-now">
  56. Nous sommes toujours à la recherche de nouveaux talents. N'hésitez pas
  57. à déposer votre candidature ci-dessous :
  58. </p>
  59. </v-col>
  60. </v-row>
  61. <v-row>
  62. <v-col cols="12">
  63. <v-btn
  64. class="btn-send"
  65. @click="dialog = true"
  66. >
  67. Envoyer ma candidature
  68. </v-btn>
  69. </v-col>
  70. </v-row>
  71. <!-- Boite de dialogue "soumettre une candidature" -->
  72. <v-dialog
  73. v-model="dialog"
  74. max-width="600px"
  75. :persistent="!jobApplicationSent"
  76. no-click-animation
  77. :retain-focus="false"
  78. >
  79. <div v-if="!jobApplicationSent">
  80. <JoinUsForm @submit="onFormSubmit"/>
  81. <v-btn @click="dialog = false">
  82. Annuler
  83. </v-btn>
  84. </div>
  85. <div v-else>
  86. <v-card class="pa-6 text-center">
  87. Votre candidature a bien été envoyée, merci de votre intérêt.<br/>
  88. Nous vous recontacterons dès que possible.
  89. </v-card>
  90. <v-btn @click="dialog = false">
  91. Fermer
  92. </v-btn>
  93. </div>
  94. </v-dialog>
  95. </LayoutContainer>
  96. </template>
  97. <script setup lang="ts">
  98. import { useEntityFetch } from "~/composables/data/useEntityFetch";
  99. import JobPosting from "~/models/Maestro/JobPosting";
  100. import type { AnyJson } from "~/types/data";
  101. const { fetchCollection } = useEntityFetch()
  102. const page: Ref<number> = ref(1);
  103. const query: ComputedRef<AnyJson> = computed(() => {
  104. return { type: "ENTREPRISE", page: page.value }
  105. }
  106. )
  107. const { data: jobCollection, pending, refresh } = fetchCollection(
  108. JobPosting,
  109. null,
  110. query
  111. )
  112. // TODO: voir pourquoi on se retrouve obligé de passer par ce computed pour avoir le type TS correct?
  113. const jobs: ComputedRef<JobPosting[]> = computed(() => {
  114. return jobCollection.value !== null ?
  115. jobCollection.value.items as JobPosting[] :
  116. []
  117. })
  118. const onPageUpdated = async (newVal: number): Promise<void> => {
  119. page.value = newVal
  120. pending.value = true
  121. await refresh()
  122. // TODO: remplacer par un watcher sur pending?
  123. setTimeout(
  124. async () => await navigateTo({ path: '', hash: '#join-us-anchor' }),
  125. 200
  126. )
  127. }
  128. /**
  129. * Faut-il afficher la boite de dialogue de candidature
  130. */
  131. const dialog = ref(false);
  132. const jobApplicationSent: Ref<boolean> = ref(false)
  133. const onFormSubmit = () => {
  134. jobApplicationSent.value = true
  135. }
  136. </script>
  137. <style scoped lang="scss">
  138. .progress {
  139. margin: 32px auto 128px auto;
  140. }
  141. .v-btn {
  142. font-weight: 600;
  143. height: 50px;
  144. background: var(--secondary-color);
  145. border-radius: 6px;
  146. color: var(--on-secondary-color);
  147. gap: 9px;
  148. }
  149. .mission-container {
  150. margin: 64px 12%;
  151. .title-container {
  152. display: flex;
  153. justify-content: space-between;
  154. align-items: center;
  155. background: var(--primary-color);
  156. color: var(--on-primary-color);
  157. height: 80px;
  158. padding: 10px 10px 10px 1px;
  159. .title {
  160. font-weight: 600;
  161. font-size: 1.5rem;
  162. line-height: 39px;
  163. color: var(--on-primary-color);
  164. text-decoration: none;
  165. margin-left: 36px;
  166. }
  167. .star {
  168. margin-left: 12px;
  169. font-size: 24px;
  170. color: yellow;
  171. vertical-align: baseline;
  172. }
  173. .btn-more {
  174. margin-right: 8px;
  175. display: flex;
  176. align-items: center;
  177. }
  178. }
  179. .location-container {
  180. background: var(--secondary-color);
  181. display: flex;
  182. align-items: center;
  183. padding: 10px;
  184. .v-icon {
  185. font-size: 1rem !important;
  186. color: var(--primary-color);
  187. }
  188. .location {
  189. color: var(--primary-color);
  190. margin-left: 10px;
  191. font-size: 1.3rem;
  192. }
  193. }
  194. }
  195. @media (max-width: 600px) {
  196. .mission-container {
  197. margin: 64px 6%;
  198. }
  199. }
  200. .btn-send {
  201. display: flex;
  202. justify-content: center;
  203. align-items: center;
  204. width: 30%;
  205. margin-left: auto;
  206. margin-right: auto;
  207. font-weight: 700;
  208. }
  209. .apply-now {
  210. text-align: center;
  211. font-style: italic;
  212. font-weight: 300;
  213. font-size: 34px;
  214. line-height: 40px;
  215. color: var(--primary-color);
  216. margin-bottom: 2rem;
  217. }
  218. .v-dialog {
  219. :deep(.v-card) {
  220. border-bottom-left-radius: 0;
  221. border-bottom-right-radius: 0;
  222. }
  223. .v-btn {
  224. width: 100%;
  225. border-top-left-radius: 0;
  226. border-top-right-radius: 0;
  227. }
  228. }
  229. </style>