feat: add frontend
This commit is contained in:
42
frontend/components/Header.vue
Normal file
42
frontend/components/Header.vue
Normal file
@@ -0,0 +1,42 @@
|
||||
<template>
|
||||
<div class="header">
|
||||
<nuxt-link to="/">
|
||||
<div class="secondary-logo">
|
||||
<img src="/logo/logo_apes.svg" height="50px" alt="Logo APES"/>
|
||||
</div>
|
||||
<div class="main-logo">
|
||||
<img src="/logo/main_logo.svg" width="245px" alt="Boussole PLUSS"/>
|
||||
</div>
|
||||
</nuxt-link>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "assets/css/spacing";
|
||||
@import "assets/css/color";
|
||||
|
||||
.header {
|
||||
width: 100%;
|
||||
height: 115px;
|
||||
margin-bottom: $xx_medium;
|
||||
background-repeat: no-repeat;
|
||||
background-image: url("/decoration/background.svg");
|
||||
background-position: bottom center, 50%;
|
||||
background-size: cover;
|
||||
|
||||
.secondary-logo img {
|
||||
padding: 12px 0 0 12px;
|
||||
}
|
||||
|
||||
.main-logo {
|
||||
position: absolute;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
top: 40px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 225px;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
29
frontend/components/Home.vue
Normal file
29
frontend/components/Home.vue
Normal file
@@ -0,0 +1,29 @@
|
||||
<template>
|
||||
<div>
|
||||
<Header/>
|
||||
<div class="content">
|
||||
<section>
|
||||
<h1>La démarche</h1>
|
||||
<p>
|
||||
Les crises successives que nous subissons révèlent encore plus la fragilité d'une économie productive
|
||||
prioritairement mondialisée. S'il est impératif que les producteurs locaux reprennent la main sur certaines
|
||||
filières, il faut aussi, pour favoriser la transition écologique et sociale, que la production locale soit
|
||||
avant tout utile, solidaire et soutenable.
|
||||
</p>
|
||||
</section>
|
||||
<section>
|
||||
<h1>La boussole comme auto-évaluation</h1>
|
||||
<p>
|
||||
Nous proposons dix points de repères pour permettre aux différents écosystèmes de production locale sur un
|
||||
territoire d'agir conjointement et collectivement dans ce sens et faire en sorte que les acteurs locaux
|
||||
puissent innover, expérimenter et renforcer la production locale quantitativement et qualitativement.
|
||||
</p>
|
||||
</section>
|
||||
<div class="button-container">
|
||||
<nuxt-link class="button orange" to="/login">Démarrer</nuxt-link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
79
frontend/components/Legend.vue
Normal file
79
frontend/components/Legend.vue
Normal file
@@ -0,0 +1,79 @@
|
||||
<template>
|
||||
<div>
|
||||
<span class="bold">Légende</span>
|
||||
<ul>
|
||||
<!-- <li v-for="axe in axes" :key="axe.identifier" :class="'axe-'+axe.identifier">{{ axe.shortTitle }}</li>-->
|
||||
<li class="axe-1">Pouvoir d'agir</li>
|
||||
<li class="axe-2">Multi-secteur</li>
|
||||
<li class="axe-3">Local global</li>
|
||||
<li class="axe-4">Utilité (sociale et écologique)</li>
|
||||
<li class="axe-5">Communs</li>
|
||||
<li class="axe-6">Démocratie</li>
|
||||
<li class="axe-7">Coopération</li>
|
||||
<li class="axe-8">Finances</li>
|
||||
<li class="axe-9">Moyens de production</li>
|
||||
<li class="axe-10">Travail</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!--<script lang="ts">-->
|
||||
<!--import { Component, Vue} from "nuxt-property-decorator";-->
|
||||
<!--import {axeStore} from "~/utils/store-accessor";-->
|
||||
<!--import {Axe} from "~/repositories/models/axe.model";-->
|
||||
|
||||
<!--@Component-->
|
||||
<!--export default class Legend extends Vue {-->
|
||||
|
||||
<!-- async created() {-->
|
||||
<!-- await axeStore.getAxes();-->
|
||||
<!-- }-->
|
||||
|
||||
<!-- get axes(): Axe[] {-->
|
||||
<!-- return axeStore.axes;-->
|
||||
<!-- }-->
|
||||
<!--}-->
|
||||
<!--</script>-->
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@import "assets/css/color";
|
||||
@import "assets/css/spacing";
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
}
|
||||
ul li::before {
|
||||
content: "";
|
||||
|
||||
border: 0 solid;
|
||||
border-radius: 50%;
|
||||
display: inline-block;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
|
||||
margin-right: $xxx_small;
|
||||
}
|
||||
|
||||
ul li+li {
|
||||
border-top: 1px solid #E8E8E8;
|
||||
}
|
||||
|
||||
ul li {
|
||||
line-height: 16px;
|
||||
padding: $xxx_small 0;
|
||||
}
|
||||
|
||||
.axe-1::before { color: #CA8AE8; background: #CA8AE8 }
|
||||
.axe-2::before { color: #22B9A6; background: #22B9A6}
|
||||
.axe-3::before { color: #E7E145; background: #E7E145}
|
||||
.axe-4::before { color: #F39345; background: #F39345}
|
||||
.axe-5::before { color: #9FCC8B; background: #9FCC8B}
|
||||
.axe-6::before { color: #FDA6C5; background: #FDA6C5}
|
||||
.axe-7::before { color: #7E91F1; background: #7E91F1}
|
||||
.axe-8::before { color: #F37665; background: #F37665}
|
||||
.axe-9::before { color: #E9D280; background: #E9D280}
|
||||
.axe-10::before { color: #7BD1F5; background: #7BD1F5}
|
||||
|
||||
</style>
|
29
frontend/components/Loader.vue
Normal file
29
frontend/components/Loader.vue
Normal file
@@ -0,0 +1,29 @@
|
||||
<template>
|
||||
<div class="lds-dual-ring"></div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "assets/css/spacing";
|
||||
@import "assets/css/color";
|
||||
|
||||
.lds-dual-ring:after {
|
||||
content: " ";
|
||||
display: block;
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
margin: 8px;
|
||||
border-radius: 50%;
|
||||
border: 6px solid;
|
||||
border-color: #8BCDCD transparent #8BCDCD transparent;
|
||||
animation: lds-dual-ring 1.2s linear infinite;
|
||||
}
|
||||
@keyframes lds-dual-ring {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
136
frontend/components/PolarAreaChart.vue
Normal file
136
frontend/components/PolarAreaChart.vue
Normal file
@@ -0,0 +1,136 @@
|
||||
<template>
|
||||
<PolarArea
|
||||
:chart-options="chartOptions"
|
||||
:chart-data="chartData"
|
||||
:chart-id="chartId"
|
||||
:dataset-id-key="datasetIdKey"
|
||||
:plugins="plugins"
|
||||
:css-classes="cssClasses"
|
||||
:styles="styles"
|
||||
:width="width"
|
||||
:height="height"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import {PolarArea} from 'vue-chartjs/legacy'
|
||||
|
||||
import {ArcElement, Chart as ChartJS, Legend, RadialLinearScale, Title, Tooltip} from 'chart.js'
|
||||
import {Component, Prop, Vue, Watch} from "nuxt-property-decorator";
|
||||
|
||||
ChartJS.register(Title, Tooltip, Legend, ArcElement, RadialLinearScale);
|
||||
|
||||
@Component({
|
||||
components: {
|
||||
PolarArea
|
||||
}
|
||||
})
|
||||
export default class PolarAreaChart extends Vue {
|
||||
|
||||
@Prop({
|
||||
default: 'polar-chart',
|
||||
type: String
|
||||
})
|
||||
public chartId!: string;
|
||||
|
||||
@Prop({
|
||||
default: 'label',
|
||||
type: String
|
||||
})
|
||||
public datasetIdKey!: string;
|
||||
|
||||
@Prop({
|
||||
default: 400,
|
||||
type: Number
|
||||
})
|
||||
public width!: number;
|
||||
|
||||
@Prop({
|
||||
default: 400,
|
||||
type: Number
|
||||
})
|
||||
public height!: number;
|
||||
|
||||
@Prop({
|
||||
default: '',
|
||||
type: String
|
||||
})
|
||||
public cssClasses!: string;
|
||||
|
||||
@Prop({
|
||||
type: Object
|
||||
})
|
||||
public styles!: Object;
|
||||
|
||||
@Prop({
|
||||
default: () => [],
|
||||
type: Array
|
||||
})
|
||||
public plugins!: [];
|
||||
|
||||
@Prop({
|
||||
default: () => [],
|
||||
type: Array<number>
|
||||
})
|
||||
public data!: number[];
|
||||
|
||||
readonly chartData = {
|
||||
labels: [
|
||||
"Pouvoir d'agir",
|
||||
"Multi-secteur",
|
||||
"Local global",
|
||||
"Utilité (sociale et écologique)",
|
||||
"Communs",
|
||||
"Démocratie",
|
||||
"Coopération",
|
||||
"Finances",
|
||||
"Moyens de production",
|
||||
"Travail"
|
||||
],
|
||||
datasets: [
|
||||
{
|
||||
backgroundColor: [
|
||||
"#CA8AE8",
|
||||
"#22B9A6",
|
||||
"#E7E145",
|
||||
"#F39345",
|
||||
"#9FCC8B",
|
||||
"#FDA6C5",
|
||||
"#7E91F1",
|
||||
"#F37665",
|
||||
"#E9D280",
|
||||
"#7BD1F5"
|
||||
],
|
||||
data: this.data,
|
||||
borderWidth: 1,
|
||||
borderColor: "#666666"
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
readonly chartOptions = {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
// animation: false,
|
||||
scales: {
|
||||
r: {
|
||||
suggestedMin: 0,
|
||||
suggestedMax: 10,
|
||||
ticks: {
|
||||
display: false
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
legend: {
|
||||
display: false
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Watch("data", {})
|
||||
private renderChart() {
|
||||
this.chartData.datasets[0].data = this.data;
|
||||
}
|
||||
}
|
||||
</script>
|
99
frontend/components/QuizAxeDetails.vue
Normal file
99
frontend/components/QuizAxeDetails.vue
Normal file
@@ -0,0 +1,99 @@
|
||||
<template>
|
||||
<section :style="cssVars" class="axe-details">
|
||||
<h2 class="title">
|
||||
<span><span class="upper">{{ axe.identifier }}</span><span>{{ axe.shortTitle }}</span></span>
|
||||
<span class="upper">{{ score.scoreAvg | formatRate }} / 10</span>
|
||||
</h2>
|
||||
<div v-for="response in responses" :key="response._links.self.href">
|
||||
<p class="question">
|
||||
<span>
|
||||
{{ response.question }}
|
||||
</span>
|
||||
<span class="note">{{ response.score }} / 10</span>
|
||||
</p>
|
||||
<p v-if="response.comment" class="comment">{{ response.comment }}</p>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import {Component, Prop, Vue} from "nuxt-property-decorator";
|
||||
import {Axe} from "~/repositories/models/axe.model";
|
||||
import {ResponseWithQuestion, Score} from "~/repositories/models/quiz.model";
|
||||
|
||||
@Component
|
||||
export default class QuizAxeDetails extends Vue {
|
||||
|
||||
@Prop({
|
||||
type: Object,
|
||||
required: true
|
||||
})
|
||||
public axe!: Axe;
|
||||
|
||||
@Prop({
|
||||
type: Object,
|
||||
required: true
|
||||
})
|
||||
public score!: Score;
|
||||
|
||||
@Prop({
|
||||
type: Array
|
||||
})
|
||||
public responses!: ResponseWithQuestion[];
|
||||
|
||||
get cssVars() {
|
||||
return {
|
||||
'--color': this.axe ? this.axe.color : "#ffffff"
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "assets/css/font";
|
||||
@import "assets/css/color";
|
||||
@import "assets/css/spacing";
|
||||
|
||||
.axe-details {
|
||||
margin-top: $x_small;
|
||||
}
|
||||
|
||||
.title {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: $tertiary-font-size;
|
||||
font-weight: 700;
|
||||
color: black;
|
||||
border-bottom: 3px solid var(--color);
|
||||
margin: $xx_small 0;
|
||||
line-height: 1rem;
|
||||
}
|
||||
|
||||
.title .upper {
|
||||
font-size: 28px;
|
||||
font-weight: bold;
|
||||
color: var(--color);
|
||||
}
|
||||
|
||||
.title .upper:first-child {
|
||||
margin-right: $xxx_small;
|
||||
}
|
||||
|
||||
.question {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
color: black;
|
||||
margin: $xx_small 0 0 0;
|
||||
}
|
||||
|
||||
.question .note {
|
||||
color: var(--color);
|
||||
}
|
||||
|
||||
.comment {
|
||||
font-size: $small-font-size;
|
||||
margin: $xxx_small 0 1rem 0;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
</style>
|
173
frontend/components/QuizPart.vue
Normal file
173
frontend/components/QuizPart.vue
Normal file
@@ -0,0 +1,173 @@
|
||||
<template>
|
||||
<article :style="cssVars">
|
||||
<header>
|
||||
<quiz-progress :number-steps=totalAxes :current-step=axeNumber :color="color"/>
|
||||
<h1 class="title">
|
||||
<span class="part-number">{{ axeNumber }}</span>
|
||||
<span>{{ title }}</span>
|
||||
</h1>
|
||||
<div class="icon">
|
||||
<img :src="icon" width="200px" alt="" aria-hidden="true"/>
|
||||
</div>
|
||||
</header>
|
||||
<section v-for="question in questions" :key="question._links.self.href" class="question">
|
||||
<details>
|
||||
<summary> {{ question.label }}</summary>
|
||||
<p>{{ question.description }}</p>
|
||||
</details>
|
||||
<div class="rating">
|
||||
<rating :color="color" :initial-value="getCurrentScore(question)" @rate="rate => onRate(rate, question)" />
|
||||
</div>
|
||||
<input :value="getCurrentComment(question)" type="text" placeholder="Commentaire" maxlength="500" @input="event => onComment(event.target.value, question)"/>
|
||||
</section>
|
||||
</article>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import {Component, Prop, Vue} from "nuxt-property-decorator";
|
||||
import {Question} from "~/repositories/models/question.model";
|
||||
import {quizStore} from "~/utils/store-accessor";
|
||||
import {QuizRate} from "~/repositories/models/quiz.model";
|
||||
|
||||
@Component
|
||||
export default class Quiz extends Vue {
|
||||
|
||||
@Prop({
|
||||
required: true
|
||||
})
|
||||
private title!: string;
|
||||
|
||||
@Prop({
|
||||
required: true
|
||||
})
|
||||
private axeNumber!: number;
|
||||
|
||||
@Prop({
|
||||
required: true
|
||||
})
|
||||
private totalAxes!: number;
|
||||
|
||||
@Prop({
|
||||
required: true,
|
||||
type: String,
|
||||
})
|
||||
public icon !: string;
|
||||
|
||||
@Prop({
|
||||
required: true,
|
||||
type: Array<Question>
|
||||
})
|
||||
private questions!: Array<Question>;
|
||||
|
||||
@Prop({
|
||||
required: true,
|
||||
type: String,
|
||||
})
|
||||
public color !: string;
|
||||
|
||||
// private responses = new Map<string, {
|
||||
// score?: number;
|
||||
// comment?: string | null
|
||||
// }>();
|
||||
|
||||
get cssVars() {
|
||||
return {
|
||||
'--color': this.color
|
||||
}
|
||||
}
|
||||
|
||||
onRate(score: number, question: Question) {
|
||||
quizStore.updateScoreResponse({axeId: this.axeNumber, questionId: question._links.self.href, score});
|
||||
this.emitRatingState();
|
||||
}
|
||||
|
||||
onComment(comment: string, question: Question) {
|
||||
quizStore.updateCommentResponse({axeId: this.axeNumber, questionId: question._links.self.href, comment});
|
||||
}
|
||||
|
||||
getCurrentScore(question: Question): number | undefined {
|
||||
const rate = quizStore.responses.get(question._links.self.href) as QuizRate;
|
||||
return rate ? rate.score : undefined;
|
||||
}
|
||||
|
||||
getCurrentComment(question: Question): string | undefined {
|
||||
const rate = quizStore.responses.get(question._links.self.href) as QuizRate;
|
||||
return rate ? rate.comment : undefined;
|
||||
}
|
||||
|
||||
emitRatingState() {
|
||||
const questions = quizStore.questionsRatedPerAxe.get(this.axeNumber);
|
||||
const unratedQuestions = questions ? questions.filter(value => !value.rated) : [];
|
||||
this.$emit('rate', {
|
||||
isFullRated: unratedQuestions.length === 0
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@import "assets/css/color";
|
||||
@import "assets/css/font";
|
||||
@import "assets/css/spacing";
|
||||
|
||||
$size: 31px;
|
||||
|
||||
.part-number {
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: var(--color);
|
||||
border: 3px solid var(--color);
|
||||
font-size: 1rem;
|
||||
line-height: $size;
|
||||
width: $size;
|
||||
height: $size;
|
||||
}
|
||||
|
||||
.title {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
text-align: left;
|
||||
> span {
|
||||
padding: 0 $x_small;
|
||||
}
|
||||
}
|
||||
|
||||
.icon {
|
||||
text-align: center;
|
||||
margin: $small;
|
||||
}
|
||||
|
||||
.question {
|
||||
width: 100%;
|
||||
}
|
||||
.question details {
|
||||
margin-bottom: $x_small;
|
||||
}
|
||||
.question details summary {
|
||||
font-weight: 700;
|
||||
font-size: $title-font-size;
|
||||
margin-bottom: $xxx_small;
|
||||
}
|
||||
|
||||
.question details p {
|
||||
font-size: $secondary-font-size;
|
||||
color: $gray_4;
|
||||
margin-left: $x_small;
|
||||
}
|
||||
|
||||
.question .rating {
|
||||
margin: 0 auto;
|
||||
max-width: 401px;
|
||||
}
|
||||
|
||||
.question input[type="text"] {
|
||||
width: 100%;
|
||||
border: 1px solid $gray_2;
|
||||
border-radius: 8px;
|
||||
background: none;
|
||||
margin: $small 0;
|
||||
font-weight: 400;
|
||||
font-size: $tertiary-font-size;
|
||||
}
|
||||
|
||||
</style>
|
56
frontend/components/QuizProgress.vue
Normal file
56
frontend/components/QuizProgress.vue
Normal file
@@ -0,0 +1,56 @@
|
||||
<template>
|
||||
<div :style="cssVars" class="progress">
|
||||
<span v-for="step in numberSteps" :key="step" class="step" :class="{ active: step <= currentStep }"></span>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Component, Prop, Vue} from "nuxt-property-decorator";
|
||||
|
||||
@Component
|
||||
export default class QuizProgress extends Vue {
|
||||
|
||||
@Prop({
|
||||
type: Number
|
||||
})
|
||||
private numberSteps!: number;
|
||||
|
||||
@Prop({
|
||||
required: true,
|
||||
type: Number
|
||||
})
|
||||
private currentStep!: number;
|
||||
|
||||
@Prop({
|
||||
required: true,
|
||||
type: String
|
||||
})
|
||||
private color!: string;
|
||||
|
||||
get cssVars() {
|
||||
return {
|
||||
'--color': this.color
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@import "assets/css/color";
|
||||
@import "assets/css/spacing";
|
||||
|
||||
.progress {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
.step {
|
||||
border-radius: 2px;
|
||||
border: 6px solid $gray_2;
|
||||
margin: $x_small $xxx_small;
|
||||
width: 30px;
|
||||
}
|
||||
|
||||
.active {
|
||||
border-color: var(--color);
|
||||
}
|
||||
|
||||
</style>
|
158
frontend/components/Rating.vue
Normal file
158
frontend/components/Rating.vue
Normal file
@@ -0,0 +1,158 @@
|
||||
<template>
|
||||
<div :style="cssVars">
|
||||
<div class="rating" tabindex="0" @keyup="handleKeyUp">
|
||||
<span v-for="i in index" :key="i" :class="{ checked: isChecked(i) }">
|
||||
<input
|
||||
:id="'rating' + componentId + '-' + i"
|
||||
type="radio" name="rating" :value="i"
|
||||
@click="setChecked(i)">
|
||||
<label :for="'rating' + componentId + '-' + i" :aria-label="i"></label>
|
||||
</span>
|
||||
</div>
|
||||
<div class="legend" aria-hidden="true">
|
||||
<span>pas du tout</span>
|
||||
<span>en partie</span>
|
||||
<span>totalement</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
||||
import {Component, Prop, Vue} from "nuxt-property-decorator";
|
||||
|
||||
@Component
|
||||
export default class Rating extends Vue {
|
||||
|
||||
@Prop({
|
||||
type: String,
|
||||
default: "#DC6A00"
|
||||
})
|
||||
readonly color !: string;
|
||||
|
||||
|
||||
@Prop({
|
||||
type: Number,
|
||||
required: false
|
||||
})
|
||||
readonly initialValue !: number | undefined;
|
||||
|
||||
readonly MAX_VALUE = 10;
|
||||
|
||||
created() {
|
||||
if (this.initialValue) {
|
||||
this.checkedValue = this.initialValue;
|
||||
}
|
||||
}
|
||||
|
||||
readonly index = Array.apply(0, Array(this.MAX_VALUE)).map((_, b) => {
|
||||
return b + 1;
|
||||
}).reverse();
|
||||
|
||||
public checkedValue = 0;
|
||||
private _uid: any;
|
||||
|
||||
public setChecked(index: number) {
|
||||
if (index < 1) {
|
||||
index = 1;
|
||||
} else if (index > this.MAX_VALUE) {
|
||||
index = this.MAX_VALUE;
|
||||
}
|
||||
this.checkedValue = index;
|
||||
this.$emit('rate', index);
|
||||
}
|
||||
|
||||
public increment() {
|
||||
this.setChecked(this.checkedValue + 1);
|
||||
}
|
||||
|
||||
public decrement() {
|
||||
this.setChecked(this.checkedValue - 1);
|
||||
}
|
||||
|
||||
public isChecked(index: number) {
|
||||
return this.checkedValue >= index;
|
||||
}
|
||||
|
||||
get componentId() {
|
||||
return this._uid;
|
||||
}
|
||||
|
||||
handleKeyUp(event: KeyboardEvent) {
|
||||
switch (event.key) {
|
||||
case "ArrowLeft":
|
||||
this.decrement();
|
||||
break;
|
||||
case "ArrowRight":
|
||||
this.increment();
|
||||
break;
|
||||
}
|
||||
event.preventDefault();
|
||||
return false;
|
||||
}
|
||||
|
||||
get cssVars() {
|
||||
return {
|
||||
'--color': this.color
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@import "assets/css/color";
|
||||
@import "assets/css/spacing";
|
||||
@import "assets/css/font";
|
||||
|
||||
$width: 401px;
|
||||
$input_width: 32px;
|
||||
|
||||
.rating {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
flex-direction: row-reverse;
|
||||
max-width: $width;
|
||||
}
|
||||
|
||||
.rating span {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.rating span input {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.rating span label {
|
||||
display: inline-block;
|
||||
width: $input_width;
|
||||
height: $input_width;
|
||||
color: $white;
|
||||
line-height: $input_width;
|
||||
border-radius: 50%;
|
||||
border: 1px solid $black;
|
||||
}
|
||||
|
||||
.rating span:hover ~ span label,
|
||||
.rating span:hover label,
|
||||
.rating span.checked label,
|
||||
.rating span.checked ~ span label {
|
||||
background-color: var(--color);
|
||||
color: #FFF;
|
||||
border: 0;
|
||||
cursor: pointer;
|
||||
width: $input_width;
|
||||
}
|
||||
|
||||
.legend {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
max-width: $width;
|
||||
color: $gray_3;
|
||||
font-weight: 400;
|
||||
font-size: $small-font-size;
|
||||
}
|
||||
</style>
|
56
frontend/components/TeamHeader.vue
Normal file
56
frontend/components/TeamHeader.vue
Normal file
@@ -0,0 +1,56 @@
|
||||
<template>
|
||||
<header>
|
||||
<nuxt-link to="/" class="title">
|
||||
<svg width="13" height="16" viewBox="0 0 13 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M0 7.07348C0 6.81265 0.101912 6.56214 0.284 6.37538L5.784 0.73436C6.17647 0.331827 6.82353 0.331826 7.216 0.734359L12.716 6.37538C12.8981 6.56214 13 6.81265 13 7.07348V15C13 15.5523 12.5523 16 12 16H1C0.447715 16 0 15.5523 0 15V7.07348Z"
|
||||
fill="#8BCDCD"/>
|
||||
</svg>
|
||||
Boussolle <span class="bold">PLUSS</span>
|
||||
</nuxt-link>
|
||||
<span class="team">
|
||||
Équipe : {{ team }}
|
||||
</span>
|
||||
</header>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import {Component, Vue} from "nuxt-property-decorator";
|
||||
|
||||
@Component
|
||||
export default class TeamHeader extends Vue {
|
||||
|
||||
get team() {
|
||||
return this.$auth.user ? this.$auth.user.username : "Non connecté";
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "assets/css/color";
|
||||
@import "assets/css/spacing";
|
||||
@import "assets/css/font";
|
||||
|
||||
header {
|
||||
margin-top: $xx_small;
|
||||
color: $black;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.title {
|
||||
text-transform: uppercase;
|
||||
color: $black;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.title svg {
|
||||
margin-right: $xxx_small;
|
||||
}
|
||||
|
||||
.team {
|
||||
font-size: $small-font-size;
|
||||
}
|
||||
|
||||
</style>
|
Reference in New Issue
Block a user