Missions.vue 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  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
  76. no-click-animation
  77. :retain-focus="false"
  78. >
  79. <JoinUsForm />
  80. <v-btn
  81. @click="dialog = false"
  82. >
  83. Annuler
  84. </v-btn>
  85. </v-dialog>
  86. </LayoutContainer>
  87. </template>
  88. <script setup lang="ts">
  89. import { useEntityFetch } from "~/composables/data/useEntityFetch";
  90. import JobPosting from "~/models/Maestro/JobPosting";
  91. import type { AnyJson } from "~/types/data";
  92. const { fetchCollection } = useEntityFetch()
  93. const page: Ref<number> = ref(1);
  94. const query: ComputedRef<AnyJson> = computed(() => {
  95. return { type: "ENTREPRISE", page: page.value }
  96. }
  97. )
  98. const { data: jobCollection, pending, refresh } = fetchCollection(
  99. JobPosting,
  100. null,
  101. query
  102. )
  103. // TODO: voir pourquoi on se retrouve obligé de passer par ce computed pour avoir le type TS correct?
  104. const jobs: ComputedRef<JobPosting[]> = computed(() => {
  105. return jobCollection.value !== null ?
  106. jobCollection.value.items as JobPosting[] :
  107. []
  108. })
  109. const onPageUpdated = async (newVal: number): Promise<void> => {
  110. page.value = newVal
  111. pending.value = true
  112. await refresh()
  113. // TODO: remplacer par un watcher sur pending?
  114. setTimeout(
  115. async () => await navigateTo({ path: '', hash: '#join-us-anchor' }),
  116. 200
  117. )
  118. }
  119. /**
  120. * Faut-il afficher la boite de dialogue de candidature
  121. */
  122. const dialog = ref(false);
  123. </script>
  124. <style scoped lang="scss">
  125. .progress {
  126. margin: 32px auto 128px auto;
  127. }
  128. .v-btn {
  129. font-weight: 600;
  130. height: 50px;
  131. background: var(--secondary-color);
  132. border-radius: 6px;
  133. color: var(--on-secondary-color);
  134. gap: 9px;
  135. }
  136. .mission-container {
  137. margin: 64px 12%;
  138. .title-container {
  139. display: flex;
  140. justify-content: space-between;
  141. align-items: center;
  142. background: var(--primary-color);
  143. color: var(--on-primary-color);
  144. height: 80px;
  145. padding: 10px 10px 10px 1px;
  146. .title {
  147. font-weight: 600;
  148. font-size: 1.5rem;
  149. line-height: 39px;
  150. color: var(--on-primary-color);
  151. text-decoration: none;
  152. margin-left: 36px;
  153. }
  154. .star {
  155. margin-left: 12px;
  156. font-size: 24px;
  157. color: yellow;
  158. vertical-align: baseline;
  159. }
  160. .btn-more {
  161. margin-right: 8px;
  162. display: flex;
  163. align-items: center;
  164. }
  165. }
  166. .location-container {
  167. background: var(--secondary-color);
  168. display: flex;
  169. align-items: center;
  170. padding: 10px;
  171. .v-icon {
  172. font-size: 1rem !important;
  173. color: var(--primary-color);
  174. }
  175. .location {
  176. color: var(--primary-color);
  177. margin-left: 10px;
  178. font-size: 1.3rem;
  179. }
  180. }
  181. }
  182. @media (max-width: 600px) {
  183. .mission-container {
  184. margin: 64px 6%;
  185. }
  186. }
  187. .btn-send {
  188. display: flex;
  189. justify-content: center;
  190. align-items: center;
  191. width: 30%;
  192. margin-left: auto;
  193. margin-right: auto;
  194. font-weight: 700;
  195. }
  196. .apply-now {
  197. text-align: center;
  198. font-style: italic;
  199. font-weight: 300;
  200. font-size: 34px;
  201. line-height: 40px;
  202. color: var(--primary-color);
  203. margin-bottom: 2rem;
  204. }
  205. .v-dialog {
  206. .btn-more {
  207. width: 128px;
  208. }
  209. }
  210. </style>