budget-go/frontend/js/chart/distribution.js
2025-03-26 12:34:05 +01:00

155 lines
3.1 KiB
JavaScript

import { isInRange } from '../lib/dateFilter'
const getDate = (value) => {
const d = new Date(value)
let month = d.getUTCMonth() + 1
const year = d.getUTCFullYear()
if (month < 10) {
month = `0${month}`
}
return `${month}/${year}`
}
const computeBar = (transactions, stacked, dateFrom, dateTo, selectedCategories) => {
const indexes = {}
const labels = []
const bars = {}
const emptyCategory = {
id: -1,
label: 'Sans catégorie',
color: '#cccccc',
}
transactions.forEach((transaction) => {
if (!isInRange(transaction.date, dateFrom, dateTo)) {
return
}
let category = transaction.category ?? emptyCategory
if (!selectedCategories[category.label]) {
return
}
let date = getDate(transaction.date)
if (!Object.hasOwn(indexes, date)) {
indexes[date] = labels.length
labels.push(date)
}
if (!Object.hasOwn(bars, category.label)) {
bars[category.label] = {
label: category.label,
data: [],
borderColor: category.color,
backgroundColor: category.color,
fill: true,
cubicInterpolationMode: 'monotone',
}
}
})
for (let key in bars) {
labels.forEach(() => {
bars[key].data.push(0)
})
}
transactions.forEach((transaction) => {
if (!isInRange(transaction.date, dateFrom, dateTo)) {
return
}
let category = transaction.category ?? emptyCategory
if (!selectedCategories[category.label]) {
return
}
let date = getDate(transaction.date)
bars[category.label].data[indexes[date]] += transaction.debit - transaction.credit
})
labels.forEach((label, key) => {
for (let bKey in bars) {
if (bars[bKey].data[key] < 0) {
bars[bKey].data[key] = 0
}
}
})
if (stacked) {
labels.forEach((label, key) => {
let sum = 0
for (let bKey in bars) {
sum += bars[bKey].data[key]
}
for (let bKey in bars) {
bars[bKey].data[key] = (bars[bKey].data[key] * 100) / sum
}
})
}
return {
labels: labels,
datasets: Object.values(bars),
}
}
const computeDoughnut = (transactions, dateFrom, dateTo, selectedCategories) => {
const indexes = {}
const labels = []
const data = []
const backgroundColor = []
const emptyCategory = {
id: -1,
label: 'Sans catégorie',
color: '#cccccc',
}
transactions.forEach((transaction) => {
if (!isInRange(transaction.date, dateFrom, dateTo)) {
return
}
let category = transaction.category ?? emptyCategory
if (!selectedCategories[category.label]) {
return
}
if (!Object.hasOwn(indexes, category.id)) {
indexes[category.id] = labels.length
labels.push(category.label)
backgroundColor.push(category.color)
data[indexes[category.id]] = 0
}
data[indexes[category.id]] += transaction.debit - transaction.credit
})
for (let i in data) {
if (data[i] < 0) {
data[i] = 0
}
}
return {
labels: labels,
datasets: [
{
data: Object.values(data),
backgroundColor: backgroundColor,
},
],
}
}
export { computeDoughnut, computeBar }