arcadiasuite/plus/public/js/dashboard_financeiro.js

273 lines
7.3 KiB
JavaScript

Chart.register(ChartDataLabels);
function formatBrl(v) {
return 'R$ ' + convertFloatToMoeda(v)
}
function getData(el, key) {
return JSON.parse(el.dataset[key] || '[]')
}
function gerarCores(qtd) {
const paleta = [
'#4254BA',
'#2196F3',
'#FFC107',
'#F44336',
'#9C27B0',
'#00BCD4',
'#FF5722',
'#795548',
'#3F51B5',
'#8BC34A',
'#E91E63',
'#009688'
]
return paleta.slice(0, qtd)
}
function criarPizza(id) {
const el = document.getElementById(id)
if (!el) return
const existing = Chart.getChart(el)
if (existing) existing.destroy()
const labels = getData(el, 'labels')
const valores = getData(el, 'valores')
const cores = gerarCores(valores.length)
const total = valores.reduce((a, b) => a + b, 0)
new Chart(el, {
type: 'pie',
data: {
labels: labels,
datasets: [{
data: valores,
backgroundColor: cores,
borderColor: '#fff',
borderWidth: 2
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
tooltip: {
callbacks: {
label: function (ctx) {
let nome = ctx.label
let valor = ctx.raw
let percentual = total > 0
? ((valor / total) * 100).toFixed(1).replace('.', ',')
: '0,0'
return `${nome}: ${formatBrl(valor)} (${percentual}%)`
}
}
},
datalabels: {
color: '#fff',
font: { weight: 'bold', size: 12 },
formatter: (value, ctx) => {
const sum = ctx.chart.data.datasets[0].data
.reduce((a, b) => a + b, 0)
if (sum === 0) return ''
const pct = ((value / sum) * 100)
.toFixed(1)
.replace('.', ',')
return pct + '%'
}
},
legend: {
position: 'bottom',
labels: { usePointStyle: true }
}
}
}
})
}
function criarFluxo() {
const el = document.getElementById('graficoFluxo')
if (!el) return
const ctx = el.getContext('2d')
const labels = getData(el, 'labels')
const pagar = getData(el, 'pagar')
const receber = getData(el, 'receber')
const gPagar = ctx.createLinearGradient(0, 0, 0, 300)
gPagar.addColorStop(0, 'rgba(255,99,132,0.35)')
gPagar.addColorStop(1, 'rgba(255,99,132,0)')
const gReceber = ctx.createLinearGradient(0, 0, 0, 300)
gReceber.addColorStop(0, 'rgba(75,192,192,0.35)')
gReceber.addColorStop(1, 'rgba(75,192,192,0)')
new Chart(el, {
type: 'line',
data: {
labels: labels,
datasets: [
{
label: 'Contas a Pagar',
data: pagar,
borderColor: 'rgb(255,99,132)',
backgroundColor: gPagar,
tension: 0.35,
borderWidth: 3,
pointRadius: 4,
pointHoverRadius: 6,
pointBackgroundColor: 'rgb(255,99,132)',
pointBorderColor: '#fff',
pointBorderWidth: 2,
fill: true
},
{
label: 'Contas a Receber',
data: receber,
borderColor: 'rgb(75,192,192)',
backgroundColor: gReceber,
tension: 0.35,
borderWidth: 3,
pointRadius: 4,
pointHoverRadius: 6,
pointBackgroundColor: 'rgb(75,192,192)',
pointBorderColor: '#fff',
pointBorderWidth: 2,
fill: true
}
]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: 'top',
labels: { usePointStyle: true }
},
tooltip: {
callbacks: {
label: function(context) {
return `${context.dataset.label}: ${formatBrl(context.raw ?? 0)}`
}
}
},
datalabels: {
anchor: 'end',
align: 'top',
offset: 10,
color: '#ffffff',
textStrokeColor: '#000000',
textStrokeWidth: 3,
shadowBlur: 4,
shadowColor: 'rgba(0,0,0,0.7)',
font: {
size: 13,
weight: 'bold'
},
formatter: function (value) {
return formatBrl(value)
}
}
},
scales: {
y: {
beginAtZero: true,
ticks: {
callback: v => formatBrl(v)
},
grid: {
color: 'rgba(0,0,0,0.05)'
}
},
x: {
grid: { display: false }
}
}
}
})
}
function criarLucro() {
const el = document.getElementById('graficoLucro')
if (!el) return
const existing = Chart.getChart(el)
if (existing) existing.destroy()
const labels = getData(el, 'labels')
const valores = getData(el, 'valores')
const ctx = el.getContext('2d')
const gradient = ctx.createLinearGradient(0, 0, 0, 250)
gradient.addColorStop(0, 'rgba(76, 175, 80, 0.5)') // verde
gradient.addColorStop(1, 'rgba(76, 175, 80, 0.05)')
new Chart(el, {
type: 'bar',
data: {
labels: labels,
datasets: [{
label: 'Lucro Mensal',
data: valores,
backgroundColor: gradient,
borderColor: '#4CAF50',
borderWidth: 2,
borderRadius: 8
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
tooltip: {
callbacks: {
label: ctx => `${ctx.dataset.label}: ${formatBrl(ctx.raw)}`
}
},
legend: {
display: false
}
},
scales: {
y: {
beginAtZero: false,
ticks: {
callback: v => formatBrl(v)
}
},
x: {
grid: { display: false }
}
}
}
})
}
document.addEventListener('DOMContentLoaded', () => {
criarFluxo()
criarPizza('graficoPagarCategoria')
criarPizza('graficoReceberCategoria')
criarLucro()
})