|
| 1 | +<template> |
| 2 | + <CatalogBanner> |
| 3 | + <template #title> Le catalogue des projets de transition écologique </template> |
| 4 | + <template #description> Accédez à la liste des projets de transition écologique destinées aux entreprises. </template> |
| 5 | + </CatalogBanner> |
| 6 | + |
| 7 | + <div class="fr-container fr-mt-6v"> |
| 8 | + <div |
| 9 | + class="fr-grid-row" |
| 10 | + :class="{ 'fr-grid-row--center': hasSpinner }" |
| 11 | + > |
| 12 | + <TeeSpinner |
| 13 | + v-if="hasSpinner" |
| 14 | + class="fr-grid-row--center" |
| 15 | + scale="6" |
| 16 | + /> |
| 17 | + <TeeError |
| 18 | + v-else-if="hasError" |
| 19 | + :mailto="Contact.email" |
| 20 | + :email="Contact.email" |
| 21 | + /> |
| 22 | + <div v-else> |
| 23 | + <div class="fr-col-12 fr-col-justify--left fr-mt-3v"> |
| 24 | + <ThemeFilter /> |
| 25 | + </div> |
| 26 | + <ThemeHeaderCard |
| 27 | + v-if="hasThemeCard" |
| 28 | + class="fr-col-12 fr-mt-3v" |
| 29 | + :objective="objective as Objective" |
| 30 | + radius-corner="tr" |
| 31 | + radius-size="2-5v" |
| 32 | + /> |
| 33 | + <div v-if="hasFilteredProjects"> |
| 34 | + <div class="fr-col-12 fr-mt-3v"> |
| 35 | + <h2 class="fr-text--bold fr-mb-0">Quel est votre projet ?</h2> |
| 36 | + </div> |
| 37 | + <div class="fr-col-12 fr-text--blue-france tee-font-style--italic fr-mt-3v"> |
| 38 | + <TeeCounterResult :to-count="filteredProjects" /> |
| 39 | + </div> |
| 40 | + <div class="fr-grid-row fr-grid-row--gutters fr-grid-row--left fr-mt-3v"> |
| 41 | + <router-link |
| 42 | + v-for="project in filteredProjects" |
| 43 | + :id="project.slug" |
| 44 | + :key="project.id" |
| 45 | + :to="getRouteToProjectDetail(project)" |
| 46 | + class="fr-col-12 fr-col-sm-6 fr-col-md-6 fr-col-lg-4 no-outline" |
| 47 | + > |
| 48 | + <ProjectCard |
| 49 | + :project="project" |
| 50 | + class="fr-radius-a--1v fr-card--shadow" |
| 51 | + /> |
| 52 | + </router-link> |
| 53 | + </div> |
| 54 | + </div> |
| 55 | + <TeeNoResult |
| 56 | + v-else |
| 57 | + message="Aucun projet n'a pu être identifiée avec les critères choisis..." |
| 58 | + /> |
| 59 | + </div> |
| 60 | + </div> |
| 61 | + </div> |
| 62 | +</template> |
| 63 | + |
| 64 | +<script setup lang="ts"> |
| 65 | +import { useNavigationStore } from '@/stores/navigation' |
| 66 | +import { useProgramStore } from '@/stores/program' |
| 67 | +import { useProjectStore } from '@/stores/project' |
| 68 | +import { Objective, type ProgramData, Project as ProjectType, RouteName, TrackId } from '@/types' |
| 69 | +import Contact from '@/utils/contact' |
| 70 | +import Matomo from '@/utils/matomo' |
| 71 | +import { Project } from '@/utils/project/project' |
| 72 | +import { computed, onBeforeMount } from 'vue' |
| 73 | +import type { RouteLocationRaw } from 'vue-router' |
| 74 | +
|
| 75 | +const projectStore = useProjectStore() |
| 76 | +const programStore = useProgramStore() |
| 77 | +const navigationStore = useNavigationStore() |
| 78 | +
|
| 79 | +const projects = ref<ProjectType[]>() |
| 80 | +const programs = ref<ProgramData[]>() |
| 81 | +const hasError = ref<boolean>(false) |
| 82 | +
|
| 83 | +const objective = computed(() => { |
| 84 | + return programStore.hasObjectiveTypeSelected() ? (programStore.programFilters.objectiveTypeSelected as Objective) : '' |
| 85 | +}) |
| 86 | +
|
| 87 | +const filteredProjects = Project.filter(projects, programs, objective) |
| 88 | +
|
| 89 | +const hasSpinner = computed(() => { |
| 90 | + return navigationStore.hasSpinner |
| 91 | +}) |
| 92 | +
|
| 93 | +const hasThemeCard = computed(() => { |
| 94 | + return programStore.hasObjectiveTypeSelected() && !hasSpinner.value |
| 95 | +}) |
| 96 | +
|
| 97 | +const hasFilteredProjects = computed(() => { |
| 98 | + return filteredProjects.value?.length |
| 99 | +}) |
| 100 | +
|
| 101 | +const getRouteToProjectDetail = (project: ProjectType): RouteLocationRaw => { |
| 102 | + return { |
| 103 | + name: RouteName.CatalogProjectDetail, |
| 104 | + params: { projectSlug: project.slug } |
| 105 | + } |
| 106 | +} |
| 107 | +
|
| 108 | +onBeforeMount(async () => { |
| 109 | + navigationStore.hasSpinner = true |
| 110 | + const programResult = await programStore.programs |
| 111 | + const projectResult = await projectStore.projects |
| 112 | + if (programResult.isOk && projectResult.isOk) { |
| 113 | + programs.value = programResult.value |
| 114 | + projects.value = projectResult.value |
| 115 | + } else { |
| 116 | + hasError.value = true |
| 117 | + } |
| 118 | +
|
| 119 | + navigationStore.hasSpinner = false |
| 120 | +
|
| 121 | + // analytics / send event |
| 122 | + Matomo.sendEvent(TrackId.Results, 'show_results_catalog_projects') |
| 123 | +}) |
| 124 | +</script> |
0 commit comments