144 lines
3.5 KiB
Vue
144 lines
3.5 KiB
Vue
<template>
|
|
<div class="stats">
|
|
<h5 class="mb-2 text-center">Répartion des dépenses</h5>
|
|
|
|
<div class="row mt-3 mb-5">
|
|
<div
|
|
v-for="(item, key) in categories"
|
|
:key="key"
|
|
class="col-auto checkbox"
|
|
:class="{ 'checkbox--unchecked': !selectedCategories[item.label] }"
|
|
>
|
|
<BFormCheckbox v-model="selectedCategories[item.label]">
|
|
<!-- eslint-disable vue/no-v-html -->
|
|
<span
|
|
class="cursor"
|
|
v-html="renderCategory(item)"
|
|
></span>
|
|
</BFormCheckbox>
|
|
</div>
|
|
|
|
<div class="col-auto">
|
|
<span
|
|
class="cursor fw-bold"
|
|
@click="selectAllCategories()"
|
|
>Toutes</span
|
|
>
|
|
-
|
|
<span
|
|
class="cursor fw-bold"
|
|
@click="unSelectAllCategories()"
|
|
>Aucune</span
|
|
>
|
|
-
|
|
<span
|
|
class="cursor fw-bold"
|
|
@click="inverseCategories()"
|
|
>Inverser</span
|
|
>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-12 col-lg-4">
|
|
<Doughnut
|
|
:data="computeDoughnut(data, dateFrom, dateTo, selectedCategories)"
|
|
:options="fixedOptions({ plugins: { legend: { display: false } } })"
|
|
:style="chartStyle(380)"
|
|
/>
|
|
</div>
|
|
<div class="col-12 col-lg-8">
|
|
<div class="d-flex justify-content-between">
|
|
<BFormCheckbox v-model="isStacked"> En pourcentage </BFormCheckbox>
|
|
</div>
|
|
<div>
|
|
<Bar
|
|
:data="computeBar(data, isStacked, dateFrom, dateTo, selectedCategories)"
|
|
:options="stackOptions({ plugins: { legend: { display: false } } })"
|
|
:style="chartStyle(380)"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, toRefs, watch, onMounted } from 'vue'
|
|
import { getStorage, saveStorage } from '../../lib/storage'
|
|
import { computeDoughnut, computeBar } from '../../chart/distribution'
|
|
import { renderCategory } from '../../lib/renderers'
|
|
import { Doughnut, Bar } from 'vue-chartjs'
|
|
import { BFormCheckbox } from 'bootstrap-vue-next'
|
|
import { chartStyle } from '../../lib/chartStyle'
|
|
|
|
const props = defineProps({
|
|
data: {
|
|
type: Array,
|
|
required: true,
|
|
},
|
|
categories: {
|
|
type: Array,
|
|
required: true,
|
|
},
|
|
dateFrom: {
|
|
type: [String, null],
|
|
required: true,
|
|
},
|
|
dateTo: {
|
|
type: [String, null],
|
|
required: true,
|
|
},
|
|
})
|
|
|
|
const isStacked = ref(getStorage('dashboard:distribution:isStacked'))
|
|
const selectedCategories = ref({})
|
|
const { categories } = toRefs(props)
|
|
|
|
watch(isStacked, (v) => saveStorage('dashboard:distribution:isStacked', v))
|
|
|
|
const fixedOptions = (opts) => {
|
|
let value = opts || {}
|
|
|
|
return {
|
|
...value,
|
|
responsive: false,
|
|
maintainAspectRatio: true,
|
|
}
|
|
}
|
|
|
|
const stackOptions = (opts) => {
|
|
let options = { ...fixedOptions(opts) }
|
|
|
|
options.scales = {
|
|
y: { stacked: true, ticks: { beginAtZero: true } },
|
|
x: { stacked: true },
|
|
}
|
|
|
|
return options
|
|
}
|
|
|
|
const inverseCategories = () => {
|
|
for (let i in selectedCategories.value) {
|
|
selectedCategories.value[i] = !selectedCategories.value[i]
|
|
}
|
|
}
|
|
|
|
const selectAllCategories = () => {
|
|
for (let i in selectedCategories.value) {
|
|
selectedCategories.value[i] = true
|
|
}
|
|
}
|
|
|
|
const unSelectAllCategories = () => {
|
|
for (let i in selectedCategories.value) {
|
|
selectedCategories.value[i] = false
|
|
}
|
|
}
|
|
|
|
onMounted(() => {
|
|
for (let item of categories.value) {
|
|
selectedCategories.value[item.label] = true
|
|
}
|
|
})
|
|
</script>
|