feat: more changes and fixes

This commit is contained in:
Herculino Trotta
2025-11-05 13:09:31 -03:00
parent 0a4d4c12b9
commit a878af28f1
34 changed files with 595 additions and 556 deletions

View File

@@ -59,7 +59,7 @@
{
label: "{% trans 'Projected Expenses' %}",
data: accountData.datasets[3].data,
backgroundColor: '#f8717180', // Added transparency
backgroundColor: '#f8717180',
stack: 'stack0'
},
{
@@ -77,7 +77,7 @@
{
label: "{% trans 'Projected Income' %}",
data: accountData.datasets[2].data,
backgroundColor: '#4dde8080', // Added transparency
backgroundColor: '#4dde8080',
stack: 'stack0'
},

View File

@@ -59,7 +59,7 @@
{
label: "{% trans 'Projected Expenses' %}",
data: currencyData.datasets[3].data,
backgroundColor: '#f8717180', // Added transparency
backgroundColor: '#f8717180',
stack: 'stack0'
},
{
@@ -77,7 +77,7 @@
{
label: "{% trans 'Projected Income' %}",
data: currencyData.datasets[2].data,
backgroundColor: '#4dde8080', // Added transparency
backgroundColor: '#4dde8080',
stack: 'stack0'
},

View File

@@ -1,37 +1,45 @@
{% load i18n %}
{% load crispy_forms_tags %}
<form _="install init_tom_select
on change trigger updated
init trigger updated" id="category-form">
{% crispy category_form %}
</form>
<div class="grid grid-cols-1 lg:grid-cols-2 gap-3">
<div class="w-full">
<div class="card bg-base-100 shadow-xl h-full">
<div class="card-header bg-base-200 p-4 font-semibold">
{% trans "Income/Expense by Account" %}
</div>
<div class="card-body">
<div id="account-card" class="show-loading" hx-get="{% url 'category_sum_by_account' %}"
hx-trigger="updated from:window" hx-include="#category-form, #picker-form, #picker-type">
</div>
</div>
</div>
</div>
<div class="w-full">
<div class="card bg-base-100 shadow-xl h-full">
<div class="card-header bg-base-200 p-4 font-semibold">
{% trans "Income/Expense by Currency" %}
</div>
<div class="card-body">
<div id="currency-card" class="show-loading" hx-get="{% url 'category_sum_by_currency' %}"
hx-trigger="updated from:window" hx-include="#category-form, #picker-form, #picker-type">
<div class="flex flex-col gap-3">
<div class="row">
<div class="col-12">
<div class="card card-border bg-base-100">
<div class="card-body">
<form _="install init_tom_select
on change trigger updated
init trigger updated" id="category-form">
{% crispy category_form %}
</form>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-12 lg:col-6">
<div class="card bg-base-100 shadow-xl h-full">
<div class="card-header bg-base-200 p-4 font-semibold rounded-box shadow">
{% trans "Income/Expense by Account" %}
</div>
<div class="card-body">
<div id="account-card" class="show-loading" hx-get="{% url 'category_sum_by_account' %}"
hx-trigger="updated from:window" hx-include="#category-form, #picker-form, #picker-type">
</div>
</div>
</div>
</div>
<div class="col-12 lg:col-6">
<div class="card bg-base-100 shadow-xl h-full">
<div class="card-header bg-base-200 p-4 font-semibold rounded-box shadow">
{% trans "Income/Expense by Currency" %}
</div>
<div class="card-body">
<div id="currency-card" class="show-loading" hx-get="{% url 'category_sum_by_currency' %}"
hx-trigger="updated from:window" hx-include="#category-form, #picker-form, #picker-type">
</div>
</div>
</div>
</div>
</div>
</div>

View File

@@ -3,56 +3,58 @@
<div hx-get="{% url 'category_overview' %}" hx-trigger="updated from:window" class="show-loading" hx-swap="outerHTML"
hx-include="#picker-form, #picker-type, #view-type, #show-tags, #showing, #show-entities">
<div class="h-full text-center mb-4">
<div class="join" role="group" id="view-type" _="on change trigger updated">
<input type="radio" class="join-item btn btn-outline btn-primary rounded-full"
name="view_type"
id="table-view"
autocomplete="off"
value="table"
aria-label="{% trans 'Table' %}"
{% if view_type == "table" %}checked{% endif %}>
<input type="radio"
class="join-item btn btn-outline btn-primary rounded-full"
name="view_type"
id="bars-view"
autocomplete="off"
value="bars"
aria-label="{% trans 'Bars' %}"
{% if view_type == "bars" %}checked{% endif %}>
<div class="tabs tabs-box mx-auto w-fit" role="group" id="view-type" _="on change trigger updated">
<label class="tab">
<input type="radio"
name="view_type"
id="table-view"
autocomplete="off"
value="table"
aria-label="{% trans 'Table' %}"
{% if view_type == "table" %}checked{% endif %}>
<i class="fa-solid fa-table fa-fw me-2"></i>
{% trans 'Table' %}
</label>
<label class="tab">
<input type="radio"
name="view_type"
id="bars-view"
autocomplete="off"
value="bars"
aria-label="{% trans 'Bars' %}"
{% if view_type == "bars" %}checked{% endif %}>
<i class="fa-solid fa-chart-bar fa-fw me-2"></i>
{% trans 'Bars' %}
</label>
</div>
</div>
<div class="mt-3 mb-1 flex flex-col md:flex-row justify-between">
<div class="my-3 flex flex-col gap-3 md:flex-row justify-between">
<div class="flex gap-4">
{% if view_type == 'table' %}
<div class="form-control" id="show-tags">
<input type="hidden" name="show_tags" value="off">
<label class="label cursor-pointer gap-2">
<input type="checkbox" class="toggle" id="show-tags-switch" name="show_tags"
<div id="show-tags">
<label class="label">
<input type="hidden" name="show_tags" value="off">
<input type="checkbox" class="toggle toggle-primary toggle-sm" id="show-tags-switch" name="show_tags"
_="on change trigger updated" {% if show_tags %}checked{% endif %}>
{% spaceless %}
<span class="label-text">
<span>
{% trans 'Tags' %}
</span>
<c-ui.help-icon
content="{% trans 'Transaction amounts associated with multiple tags will be counted once for each tag' %}"
icon="fa-solid fa-circle-exclamation"></c-ui.help-icon>
{% endspaceless %}
</span>
<c-ui.help-icon
content="{% trans 'Transaction amounts associated with multiple tags will be counted once for each tag' %}"
icon="fa-solid fa-circle-exclamation"></c-ui.help-icon>
</label>
</div>
<div class="form-control" id="show-entities" {% if not show_tags %}style="display: none;"{% endif %}>
<input type="hidden" name="show_entities" value="off">
<label class="label cursor-pointer gap-2">
<input type="checkbox" class="toggle" id="show-entities-switch" name="show_entities"
<div id="show-entities" class="{% if not show_tags %}hidden{% endif %}">
<label class="label">
<input type="hidden" name="show_entities" value="off">
<input type="checkbox" class="toggle toggle-primary toggle-sm" id="show-entities-switch" name="show_entities"
_="on change trigger updated" {% if show_entities %}checked{% endif %}>
{% spaceless %}
<span class="label-text">
<span>
{% trans 'Entities' %}
</span>
<c-ui.help-icon
content="{% trans 'Transaction amounts associated with multiple tags and entities will be counted once for each tag' %}"
icon="fa-solid fa-circle-exclamation"></c-ui.help-icon>
{% endspaceless %}
</span>
<c-ui.help-icon
content="{% trans 'Transaction amounts associated with multiple tags will be counted once for each tag' %}"
icon="fa-solid fa-circle-exclamation"></c-ui.help-icon>
</label>
</div>
{% endif %}
@@ -70,8 +72,10 @@
</div>
{% if total_table %}
{% if view_type == "table" %}
<div class="overflow-x-auto">
<table class="table table-zebra">
<div class="card bg-base-100 card-border">
<c-config.search></c-config.search>
<div class="overflow-x-auto">
<table class="table">
<thead>
<tr>
<th scope="col">{% trans 'Category' %}</th>
@@ -176,7 +180,7 @@
{% for tag_id, tag in category.tags.items %}
{% if tag.name or not tag.name and category.tags.values|length > 1 %}
<tr class="bg-base-200">
<td class="ps-4">
<td class="ps-6">
<i class="fa-solid fa-hashtag fa-fw me-2 text-base-content/60"></i>{% if tag.name %}{{ tag.name }}{% else %}{% trans 'Untagged' %}{% endif %}
</td>
<td>
@@ -269,7 +273,7 @@
{% for entity_id, entity in tag.entities.items %}
{% if entity.name or not entity.name and tag.entities.values|length > 1 %}
<tr class="bg-base-300">
<td class="ps-5">
<td class="ps-10">
<i class="fa-solid fa-user-group fa-fw me-2 text-base-content/60"></i>{% if entity.name %}{{ entity.name }}{% else %}{% trans 'No entity' %}{% endif %}
</td>
<td>
@@ -366,13 +370,16 @@
{% endfor %}
</tbody>
</table>
</div>
</div>
{% elif view_type == "bars" %}
<div>
<div class="chart-container relative h-[78vh] w-full" _="init call setupChart() end">
<canvas id="categoryChart"></canvas>
<div class="card bg-base-100 card-border">
<div class="card-body">
<div class="chart-container relative h-[75vh] w-full" _="init call setupChart() end">
<canvas id="categoryChart"></canvas>
</div>
</div>
</div>

View File

@@ -1,7 +1,7 @@
{% load i18n %}
<div hx-get="{% url 'insights_late_transactions' %}" hx-trigger="updated from:window" class="show-loading"
<div hx-get="{% url 'insights_latest_transactions' %}" hx-trigger="updated from:window" class="show-loading"
id="transactions-list" hx-swap="outerHTML">
{% if transactions %}
{% for transaction in transactions %}

View File

@@ -7,7 +7,7 @@
<div class="show-loading" hx-get="{% url 'insights_sankey_by_currency' %}" hx-trigger="updated from:window"
hx-swap="outerHTML" hx-include="#picker-form, #picker-type">
{% endif %}
<div class="chart-container relative min-h-[85vh] max-h-[85vh] h-full w-full"
<div class="card bg-base-100 card-border chart-container relative min-h-[85vh] max-h-[85vh] h-full w-full"
id="sankeyContainer"
_="init call setupSankeyChart() end">
<canvas id="sankeyChart"></canvas>
@@ -15,7 +15,14 @@
</div>
<script>
var style = getComputedStyle(document.body);
var incomeColor = style.getPropertyValue('--color-success');
var expenseColor = style.getPropertyValue('--color-error');
var primaryColor = style.getPropertyValue('--color-primary');
var contentColor = style.getPropertyValue('--color-base-content');
console.log('Sankey colors:', incomeColor, expenseColor, primaryColor, contentColor);
var data = {{ sankey_data|safe }};
console.log(convertColorToRgba(incomeColor))
function setupSankeyChart(chartId = 'sankeyChart') {
function formatCurrency(value, currency) {
@@ -35,11 +42,11 @@
const colors = {};
data.nodes.forEach(node => {
if (node.id.startsWith('income_')) {
colors[node.id] = '#4dde80'; // Green for income
colors[node.id] = convertColorToRgba(incomeColor); // Green for income
} else if (node.id.startsWith('expense_')) {
colors[node.id] = '#f87171'; // Red for expenses
colors[node.id] = convertColorToRgba(expenseColor); // Red for expenses
} else {
colors[node.id] = '#fbb700'; // Primary for others
colors[node.id] = convertColorToRgba(primaryColor); // Primary for others
}
});
@@ -63,7 +70,7 @@
colorMode: 'gradient',
alpha: 0.5,
size: 'max',
color: "white",
color: contentColor,
nodePadding: 30,
priority: data.nodes.reduce((acc, node) => {
acc[node.id] = node.priority;

View File

@@ -6,8 +6,8 @@
{% block content %}
<div class="container-fluid">
<div class="row">
<div class="col-12 md:col-3">
<div class="row gy-3">
<div class="col-12 md:col-3 gy-3">
<div class="flex flex-col gap-3">
<div class="card bg-base-100 card-borderS">
<div class="card-body">
@@ -73,22 +73,22 @@
remove .btn-active from <.insights-list button/>
add .btn-active to event.target
set event.target's @aria-selected to 'true'">
<button class="btn btn-ghost justify-start"
<button class="btn btn-ghost justify-start text-start"
type="button" role="tab" aria-controls="v-pills-content" aria-selected="false"
hx-get="{% url 'insights_sankey_by_account' %}">
{% trans 'Account Flow' %}
</button>
<button class="btn btn-ghost justify-start" data-bs-target="#v-pills-content"
<button class="btn btn-ghost justify-start text-start" data-bs-target="#v-pills-content"
type="button" role="tab" aria-controls="v-pills-content" aria-selected="false"
hx-get="{% url 'insights_sankey_by_currency' %}"
>{% trans 'Currency Flow' %}
</button>
<button class="btn btn-ghost justify-start" data-bs-target="#v-pills-content"
<button class="btn btn-ghost justify-start text-start" data-bs-target="#v-pills-content"
type="button" role="tab" aria-controls="v-pills-content" aria-selected="false"
hx-get="{% url 'category_explorer_index' %}">
{% trans 'Category Explorer' %}
</button>
<button class="btn btn-ghost justify-start" data-bs-target="#v-pills-content"
<button class="btn btn-ghost justify-start text-start" data-bs-target="#v-pills-content"
type="button" role="tab" aria-controls="v-pills-content" aria-selected="false"
hx-get="{% url 'category_overview' %}"
>{% trans 'Categories Overview' %}
@@ -106,17 +106,17 @@
remove .btn-active from <.insights-list button/>
add .btn-active to event.target
set event.target's @aria-selected to 'true'">
<button class="btn btn-ghost justify-start" data-bs-target="#v-pills-content"
<button class="btn btn-ghost justify-start text-start" data-bs-target="#v-pills-content"
type="button" role="tab" aria-controls="v-pills-content" aria-selected="false"
hx-get="{% url 'insights_late_transactions' %}">
{% trans 'Late Transactions' %}
</button>
<button class="btn btn-ghost justify-start" data-bs-target="#v-pills-content"
<button class="btn btn-ghost justify-start text-start" data-bs-target="#v-pills-content"
type="button" role="tab" aria-controls="v-pills-content" aria-selected="false"
hx-get="{% url 'insights_latest_transactions' %}">
{% trans 'Latest Transactions' %}
</button>
<button class="btn btn-ghost justify-start" data-bs-target="#v-pills-content"
<button class="btn btn-ghost justify-start text-start" data-bs-target="#v-pills-content"
type="button" role="tab" aria-controls="v-pills-content" aria-selected="false"
hx-get="{% url 'insights_emergency_fund' %}">
{% trans 'Emergency Fund' %}
@@ -126,7 +126,7 @@
</div>
</div>
</div>
<div class="col-12 md:col-9">
<div class="col-12 md:col-9 gy-3">
<div id="tab-content" class="show-loading"></div>
</div>
</div>