mirror of
https://github.com/eitchtee/WYGIWYH.git
synced 2026-07-10 06:42:49 +02:00
150 lines
4.7 KiB
HTML
150 lines
4.7 KiB
HTML
{% extends "layouts/base.html" %}
|
|
|
|
{% block content %}
|
|
<canvas id="sankeyChart" height="379"></canvas>
|
|
|
|
<script>
|
|
function setupSankeyChart(data, chartId = 'sankeyChart') {
|
|
// Color generation function
|
|
function generateColors(nodes) {
|
|
const colorMap = {};
|
|
const incomeColor = '#4CAF50'; // Green
|
|
const expenseColor = '#F44336'; // Red
|
|
const savingsColor = '#4CAF50'; // Green (same as income)
|
|
const accountColor = '#2196F3'; // Blue
|
|
|
|
nodes.forEach((node) => {
|
|
if (node.name.includes('(')) {
|
|
const [category, currency] = node.name.split(' (');
|
|
if (category.toLowerCase() === 'savings') {
|
|
colorMap[node.name] = savingsColor;
|
|
} else if (data.flows.some(flow => flow.from_node === node.name)) {
|
|
colorMap[node.name] = incomeColor;
|
|
} else if (data.flows.some(flow => flow.to_node === node.name)) {
|
|
colorMap[node.name] = expenseColor;
|
|
} else {
|
|
colorMap[node.name] = accountColor;
|
|
}
|
|
} else {
|
|
colorMap[node.name] = accountColor;
|
|
}
|
|
});
|
|
|
|
return colorMap;
|
|
}
|
|
|
|
// Format currency value
|
|
function formatCurrency(value, currency) {
|
|
return new Intl.NumberFormat('pt-BR', {
|
|
minimumFractionDigits: currency.decimal_places,
|
|
maximumFractionDigits: currency.decimal_places
|
|
}).format(value);
|
|
}
|
|
|
|
// Generate colors for nodes
|
|
const colorMap = generateColors(data.nodes);
|
|
|
|
// Create a mapping of node names to indices
|
|
const nodeIndices = {};
|
|
const nodeSizes = {};
|
|
data.nodes.forEach((node, index) => {
|
|
nodeIndices[node.name] = index;
|
|
nodeSizes[node.name] = node.size;
|
|
});
|
|
|
|
console.log(data.flows.map(flow => ({
|
|
from: nodeIndices[flow.from_node],
|
|
to: nodeIndices[flow.to_node],
|
|
flow: flow.flow
|
|
})),);
|
|
console.log(nodeSizes)
|
|
// Format data for Chart.js
|
|
const chartData = {
|
|
datasets: [{
|
|
data: data.flows.map(flow => ({
|
|
from: nodeIndices[flow.from_node],
|
|
to: nodeIndices[flow.to_node],
|
|
flow: flow.flow
|
|
})),
|
|
colorFrom: (c) => colorMap[data.nodes[c.dataset.data[c.dataIndex].from].name],
|
|
colorTo: (c) => colorMap[data.nodes[c.dataset.data[c.dataIndex].to].name],
|
|
colorMode: 'to',
|
|
labels: data.nodes.map(node => node.name),
|
|
size: 'max',
|
|
}]
|
|
};
|
|
|
|
// Chart configuration
|
|
const config = {
|
|
type: 'sankey',
|
|
data: chartData,
|
|
options: {
|
|
responsive: true,
|
|
maintainAspectRatio: false,
|
|
plugins: {
|
|
tooltip: {
|
|
callbacks: {
|
|
label: (context) => {
|
|
const flow = data.flows[context.dataIndex];
|
|
const formattedValue = formatCurrency(flow.original_amount, flow.currency);
|
|
return [
|
|
`De: ${flow.from_node}`,
|
|
`Para: ${flow.to_node}`,
|
|
`Valor: ${flow.currency.prefix}${formattedValue}${flow.currency.suffix}`,
|
|
`Porcentagem: ${flow.percentage.toFixed(2)}%`
|
|
];
|
|
}
|
|
}
|
|
},
|
|
legend: {
|
|
display: false
|
|
},
|
|
title: {
|
|
display: true,
|
|
text: 'Fluxo de Transações',
|
|
font: {
|
|
size: 16
|
|
}
|
|
}
|
|
},
|
|
layout: {
|
|
padding: {
|
|
top: 20,
|
|
right: 20,
|
|
bottom: 20,
|
|
left: 20
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
// Destroy existing chart if it exists
|
|
const existingChart = Chart.getChart(chartId);
|
|
if (existingChart) {
|
|
existingChart.destroy();
|
|
}
|
|
|
|
// Create new chart
|
|
return new Chart(
|
|
document.getElementById(chartId),
|
|
config
|
|
);
|
|
}
|
|
|
|
// Usage in Django template or JavaScript file
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// Assuming you have the Sankey data in a variable called sankeyData
|
|
// For Django template:
|
|
const sankeyData = {{ sankey_data|safe }};
|
|
console.log(sankeyData);
|
|
|
|
const chart = setupSankeyChart(sankeyData);
|
|
|
|
// Optional: Handle resize
|
|
window.addEventListener('resize', () => {
|
|
chart.resize();
|
|
});
|
|
});
|
|
</script>
|
|
{% endblock %}
|