Skip to content

Commit

Permalink
Nouvelle fonctionnalité : qualité des aménagements
Browse files Browse the repository at this point in the history
QualityText component

possibilité de déclarer la qualité de l'aménagement et affichage sur tooltip

LineTooltip : si la donnée qualité n'est pas définie, le LineTooltip n'affiche pas de ligne supplémentaire

qualityText : notion de Inconnue manquante fix

factorisation des label de qualityNames

qualité : réduction du nombre d'état (satisfaisant et non satisfaisant) + adapatation du LineTooltip

composant StatsQuality créé et ajouté dans le bloc aperçu de la page des lignes

ajout du composant qualité sur la page d'accueil
  • Loading branch information
Paul LOPEZ committed Dec 1, 2024
1 parent 34a6adf commit a761caf
Show file tree
Hide file tree
Showing 11 changed files with 145 additions and 8 deletions.
3 changes: 3 additions & 0 deletions assets/icons/satisfactory.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions assets/icons/unsatisfactory.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
28 changes: 28 additions & 0 deletions components/StatsQuality.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<template>
<div v-if="stat.nbZone > 0" class="my-5 not-prose p-4 bg-[#F9FAFB]">
<div class="flex justify-between">
<div class="text-base font-normal text-gray-900">
<span class="italic">Au total, </span>
<span class="text-lvv-pink font-bold">{{ displayDistanceInKm(stat.distance, precision) }}</span> ({{ displayPercent(stat.percent) }})
<span class="italic">{{ stat.distance < (2 * 1000) ? 'est non satisfaisant' : 'sont non satisfaisants' }}</span>
</div>
<div class="text-base font-normal text-gray-900">
<span class="text-lvv-pink font-bold">{{ stat.nbZone }}</span>
<span class="italic">{{ stat.nbZone <= 1 ? ' zone problématique subsiste' : ' zones problématiques subsistent' }}</span>
</div>
</div>
</div>
</template>

<script setup lang="ts">
import type { Geojson } from '~/types';
const { getStatsQuality, displayDistanceInKm, displayPercent } = useStats();
const { voies, precision } = defineProps<{
voies: Geojson[];
precision?: number;
}>();
const stat = getStatsQuality(voies);
</script>
2 changes: 2 additions & 0 deletions components/content/Overview.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
</div>
<ProgressBar :voies="[geojson]" />
<Stats :voies="[geojson]" :precision="1" />
<StatsQuality v-if="displayQuality()" :voies="[geojson]" :precision="1" />
<Typology :voies="[geojson]" />
</div>
<section aria-labelledby="shipping-heading" class="mt-10">
Expand All @@ -23,6 +24,7 @@
const { path } = useRoute();
const { getLineColor } = useColors();
const { getTotalDistance, displayDistanceInKm } = useStats();
const { displayQuality } = useConfig();
const { voie } = defineProps({ voie: Object });
Expand Down
38 changes: 38 additions & 0 deletions components/content/QualityText.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<template>
<span v-if="displayQuality()" :class="qualities[type].color.text" class="font-bold">{{ qualities[type].title }}</span>
</template>

<script setup lang="ts">
import type { LaneQuality } from '~/types';
const { displayQuality } = useConfig();
const { qualityNames } = useStats();
const { type } = defineProps<{
type: LaneQuality
}>();
type QualityText = {
[key in LaneQuality]: {
title: string;
color: {
text: string;
}
}
}
const qualities: QualityText = {
unsatisfactory: {
title: qualityNames.unsatisfactory,
color: {
text: 'text-[#FF0000]'
}
},
satisfactory: {
title: qualityNames.satisfactory,
color: {
text: 'text-[#00b050]'
}
}
};
</script>
34 changes: 31 additions & 3 deletions components/tooltips/LineTooltip.vue
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,15 @@
{{ typologyNames[feature.properties.type] ?? 'Inconnu' }}
</div>
</div>
<div v-if="displayQuality() && feature.properties.quality" class="py-1 flex items-center justify-between">
<div class="text-base font-bold">
Qualité
</div>
<div class="text-xs" :class=" getQuality(feature.properties.quality).class">
<Icon :name="getQuality(feature.properties.quality).icon" class="h-4 w-4 align-middle" :class="getQuality(feature.properties.quality).classIcon" />
{{ getQuality(feature.properties.quality).label }}
</div>
</div>
</div>
<div class="bg-lvv-blue-600 flex justify-center">
<a class="p-1 text-white text-base italic hover:underline" :href="getSectionDetailsUrl(feature.properties)" target="_blank">
Expand All @@ -63,11 +72,11 @@
</template>

<script setup lang="ts">
import type { LineStringFeature } from '~/types';
import type { LaneQuality, LineStringFeature } from '~/types';
const { getLineColor } = useColors();
const { getRevName } = useConfig();
const { getDistance, typologyNames } = useStats();
const { getRevName, displayQuality } = useConfig();
const { getDistance, typologyNames, qualityNames } = useStats();
const { getVoieCyclablePath } = useUrl();
const { feature, lines } = defineProps<{
Expand Down Expand Up @@ -136,4 +145,23 @@ function getStatus(properties: LineStringFeature['properties']): { label: string
};
return statusMapping[properties.status];
}
function getQuality(quality: LaneQuality): { label: string, class: string, icon: string, classIcon: string } {
const statusMapping = {
unsatisfactory: {
label: qualityNames.unsatisfactory,
class: 'rounded-xl px-1 border border-red-600',
classIcon: 'text-red-600',
icon: 'mdi:close'
},
satisfactory: {
label: qualityNames.satisfactory,
class: 'rounded-xl px-1 border border-green-600',
classIcon: 'text-green-600',
icon: 'mdi:check'
}
};
return statusMapping[quality];
}
</script>
10 changes: 9 additions & 1 deletion composables/useConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,13 @@ export const useConfig = () => {
return config.nbVoiesCyclables;
}

return { getRevName, getAssoName, getAssoLink, getNbVoiesCyclables };
function displayQuality(): boolean {
return config.qualityDisplay;
}

function displayQualityOnHomePage(): boolean {
return config.qualityDisplayOnHomePage;
}

return { getRevName, getAssoName, getAssoLink, getNbVoiesCyclables, displayQuality, displayQualityOnHomePage };
};
25 changes: 23 additions & 2 deletions composables/useStats.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { groupBy } from '../helpers/helpers';
import { isLineStringFeature, type Feature, type Geojson, type LaneType, type LineStringFeature } from '../types';
import { isLineStringFeature, type Feature, type Geojson, type LaneType, type LineStringFeature, type LaneQuality } from '../types';

export const useStats = () => {
function getAllUniqLineStrings(voies: Geojson[]) {
Expand Down Expand Up @@ -137,6 +137,20 @@ export const useStats = () => {
};
}

function getStatsQuality(voies: Geojson[]): { distance: number, percent: number, nbZone: number } {
const features = getAllUniqLineStrings(voies);
const totalDistance = getDistance({ features });
const unsatisfactoryFeatures = features.filter(feature => feature.properties.quality === 'unsatisfactory');

const unsatisfactoryDistance = getDistance({ features: unsatisfactoryFeatures });

return {
distance: unsatisfactoryDistance,
percent: Math.round(unsatisfactoryDistance / totalDistance * 100),
nbZone: unsatisfactoryFeatures.length
};
}

const typologyNames: Record<LaneType, string> = {
bidirectionnelle: 'Piste bidirectionnelle',
bilaterale: 'Piste bilatérale',
Expand All @@ -150,6 +164,11 @@ export const useStats = () => {
inconnu: 'Inconnu'
};

const qualityNames: Record<LaneQuality, string> = {
unsatisfactory: 'Non satisfaisant',
satisfactory: 'Satisfaisant'
};

function getStatsByTypology(voies: Geojson[]) {
const lineStringFeatures = getAllUniqLineStrings(voies);
const totalDistance = getDistance({ features: lineStringFeatures });
Expand Down Expand Up @@ -180,6 +199,8 @@ export const useStats = () => {
getStatsByTypology,
displayDistanceInKm,
displayPercent,
typologyNames
typologyNames,
qualityNames,
getStatsQuality
};
};
4 changes: 3 additions & 1 deletion config.json
Original file line number Diff line number Diff line change
Expand Up @@ -141,5 +141,7 @@
"color": "#873E99",
"link": "https://destinations2026-sytral.fr/processes/t10"
}
]
],
"qualityDisplay": false,
"qualityDisplayOnHomePage": false
}
3 changes: 2 additions & 1 deletion pages/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
</div>
<ProgressBar :voies="voies" class="mt-8 md:mt-10" />
<Stats :voies="voies" class="mt-8" />
<StatsQuality v-if="displayQuality() && displayQualityOnHomePage()" :voies="voies" class="mt-8" />
<Typology :voies="voies" class="mt-8 max-w-2xl mx-auto" />
</div>
<div class="max-w-7xl mx-auto mt-14 px-4 sm:px-6 lg:px-8 lg:mt-24">
Expand All @@ -37,7 +38,7 @@
</template>

<script setup>
const { getRevName } = useConfig();
const { getRevName, displayQuality, displayQualityOnHomePage } = useConfig();
const { data: voies } = await useAsyncData(() => {
return queryContent('voies-cyclables').where({ _type: 'json' }).find();
Expand Down
3 changes: 3 additions & 0 deletions types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ export type LaneType =

export type LaneStatus = 'done' | 'wip' | 'planned' | 'tested' | 'postponed' | 'unknown' | 'variante' | 'variante-postponed';

export type LaneQuality = 'unsatisfactory' | 'satisfactory';

export type LineStringFeature = {
type: 'Feature';
properties: {
Expand All @@ -22,6 +24,7 @@ export type LineStringFeature = {
type: LaneType;
doneAt?: string;
link?: string;
quality?: LaneQuality;
};
geometry: {
type: 'LineString';
Expand Down

0 comments on commit a761caf

Please sign in to comment.