242 lines
6.8 KiB
Vue
242 lines
6.8 KiB
Vue
<template>
|
||
<aside
|
||
id="dtl-panel"
|
||
class="text-sm bg-black rounded-2xl"
|
||
:class="{ 'with-dialog': isDialogOpen }"
|
||
aria-labelledby="dtl-label"
|
||
@click="preventClose($event)"
|
||
>
|
||
<header
|
||
class="flex items-center | border-b pl-32 pr-16 py-8"
|
||
data-icon="leaf"
|
||
style="--column-gap: 0.5rem"
|
||
>
|
||
<h2 id="dtl-label" class="font-serif text-md">
|
||
{{
|
||
proposals.length === 1 && isDialogOpen
|
||
? activeProposal.title
|
||
? activeProposal.title
|
||
: 'Design to light'
|
||
: 'Design to light'
|
||
}}
|
||
</h2>
|
||
<button
|
||
v-if="!isDialogOpen"
|
||
@click="emits('close')"
|
||
class="btn btn--icon btn--transparent | ml-auto"
|
||
data-icon="close"
|
||
>
|
||
<span class="sr-only">Fermer</span>
|
||
</button>
|
||
</header>
|
||
<nav v-if="!isDialogOpen" class="tabs" role="tablist" tabindex="-1">
|
||
<button
|
||
v-for="(proposal, index) in proposals"
|
||
@click="activeProposal = proposal"
|
||
role="tab"
|
||
:aria-selected="activeProposal === proposal"
|
||
aria-controls=""
|
||
>
|
||
{{
|
||
proposal.title
|
||
? proposal.title
|
||
: index === 0
|
||
? 'Proposition initiale'
|
||
: 'Alternative ' + index
|
||
}}
|
||
</button>
|
||
</nav>
|
||
<section class="overflow-y" tabindex="-1">
|
||
<div
|
||
v-if="!isDialogOpen"
|
||
id="proposition"
|
||
class="flex relative | bg-white-05 text-grey-200 px-32 py-16"
|
||
style="--column-gap: 1rem"
|
||
>
|
||
<h3 class="sr-only">Proposition</h3>
|
||
<router-link class="link-full" :to="activeProposal.path">
|
||
<img
|
||
v-if="activeProposal.thumb"
|
||
:src="activeProposal.thumb"
|
||
alt=""
|
||
width="72"
|
||
height="72"
|
||
loading="lazy"
|
||
class="bg-white rounded-sm"
|
||
/>
|
||
</router-link>
|
||
<p>
|
||
Données basées sur la proposition <br />du {{ activeProposal.date }}
|
||
<br />{{ activeProposal.stepLabel }}
|
||
</p>
|
||
</div>
|
||
<div id="note-globale" class="px-32 py-16 border-b flow">
|
||
<h3>Note globale</h3>
|
||
<div class="flex" style="--column-gap: 1rem">
|
||
<p :data-grade="activeProposal.grades.global.letter">
|
||
<strong class="sr-only">{{
|
||
activeProposal.grades.global.letter
|
||
}}</strong>
|
||
</p>
|
||
<div class="flex-1">
|
||
<p>
|
||
<strong class="text-md font-medium">{{
|
||
activeProposal.grades.global.mention
|
||
}}</strong>
|
||
<span class="text-white-50 ml-8"
|
||
>{{ activeProposal.grades.global.number }}/10</span
|
||
>
|
||
</p>
|
||
<input
|
||
type="range"
|
||
min="0"
|
||
max="10"
|
||
:value="activeProposal.grades.global.number"
|
||
disabled
|
||
/>
|
||
<p>{{ activeProposal.grades.global.comment }}</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="positionnement" class="px-32 py-16 border-b flow">
|
||
<h3>Positionnement</h3>
|
||
<dl>
|
||
<dt id="design">Design</dt>
|
||
<dd>
|
||
<span class="sr-only">{{
|
||
activeProposal.grades.position.complexity
|
||
}}</span>
|
||
</dd>
|
||
<dt id="poids">Poids</dt>
|
||
<dd>
|
||
<span class="sr-only">{{
|
||
activeProposal.grades.position.weight
|
||
}}</span>
|
||
</dd>
|
||
</dl>
|
||
<button
|
||
class="dot"
|
||
v-for="(proposal, index) in proposals"
|
||
@click="activeProposal = proposal"
|
||
:aria-selected="activeProposal === proposal"
|
||
:style="
|
||
'--x:' +
|
||
proposal.grades.position.complexity +
|
||
';--y:' +
|
||
proposal.grades.position.weight
|
||
"
|
||
:title="proposal.title"
|
||
>
|
||
<span class="sr-only">{{ proposal.title }}</span>
|
||
</button>
|
||
</div>
|
||
<div id="indicateur" class="px-32 py-16 border-b flow">
|
||
<h3>Indicateur des composants impliqués</h3>
|
||
<div class="grid">
|
||
<template
|
||
v-for="indicator in activeProposal.grades.indicators"
|
||
:key="indicator.id"
|
||
>
|
||
<div
|
||
class="gauge"
|
||
:data-value="
|
||
indicator.value < 0 ? indicator.value : '+' + indicator.value
|
||
"
|
||
>
|
||
<label
|
||
:for="indicator.id"
|
||
:style="'--value:' + indicator.value"
|
||
>{{ indicator.label }}</label
|
||
>
|
||
<input
|
||
:id="indicator.id"
|
||
type="range"
|
||
min="-5"
|
||
max="5"
|
||
orient="vertical"
|
||
:value="indicator.value"
|
||
disabled
|
||
/>
|
||
</div>
|
||
</template>
|
||
</div>
|
||
</div>
|
||
<footer v-if="proposals.length === 1 && !isDialogOpen" class="p-16">
|
||
<button
|
||
:disabled="page.hasOptimizationRequest ? '' : undefined"
|
||
class="btn btn--white w-full"
|
||
@click="handleOptimizationButtonClick"
|
||
>
|
||
{{
|
||
page.hasOptimizationRequest
|
||
? "Demande d'expertise en cours de traitement…"
|
||
: 'Demander une expertise d’optimisation'
|
||
}}
|
||
</button>
|
||
</footer>
|
||
</section>
|
||
</aside>
|
||
<OptimizationRequestDialog
|
||
v-if="isOptimizationDialogOpen"
|
||
@close="isOptimizationDialogOpen = false"
|
||
/>
|
||
</template>
|
||
<script setup>
|
||
import OptimizationRequestDialog from './OptimizationRequestDialog.vue';
|
||
import dayjs from 'dayjs';
|
||
import 'dayjs/locale/fr';
|
||
import { storeToRefs } from 'pinia';
|
||
import { ref, onBeforeUnmount, computed } from 'vue';
|
||
import { useDialogStore } from '../../stores/dialog';
|
||
import { usePageStore } from '../../stores/page';
|
||
|
||
const { proposals } = defineProps({
|
||
proposals: Array,
|
||
});
|
||
|
||
const { page } = storeToRefs(usePageStore());
|
||
const { openedFile } = storeToRefs(useDialogStore());
|
||
|
||
const isDialogOpen = computed(() => {
|
||
if (openedFile.value) {
|
||
return true;
|
||
} else {
|
||
return false;
|
||
}
|
||
});
|
||
|
||
const isOptimizationDialogOpen = ref(false);
|
||
|
||
dayjs.locale('fr');
|
||
|
||
const emits = defineEmits(['close']);
|
||
|
||
proposals[0].isActive = true;
|
||
|
||
const activeProposal = ref(proposals[0]);
|
||
|
||
window.addEventListener('keyup', closeOnEscape);
|
||
window.addEventListener('click', close);
|
||
|
||
onBeforeUnmount(() => {
|
||
window.removeEventListener('keyup', closeOnEscape);
|
||
window.removeEventListener('click', close);
|
||
});
|
||
|
||
// Functions
|
||
function closeOnEscape(event) {
|
||
if (event.key === 'Escape') emits('close');
|
||
}
|
||
|
||
function close() {
|
||
emits('close');
|
||
}
|
||
|
||
function preventClose(event) {
|
||
event.stopImmediatePropagation();
|
||
}
|
||
|
||
function handleOptimizationButtonClick() {
|
||
isOptimizationDialogOpen.value = true;
|
||
}
|
||
</script>
|