feat: add actions

This commit is contained in:
Herculino Trotta
2024-10-14 21:01:11 -03:00
parent 8a61946c16
commit aecbcb3430
11 changed files with 196 additions and 32 deletions

View File

@@ -2,6 +2,21 @@ from django.urls import path
import apps.transactions.views as views
urlpatterns = [
path(
"transactions/actions/pay",
views.bulk_pay_transactions,
name="transactions_bulk_pay",
),
path(
"transactions/actions/unpay/",
views.bulk_unpay_transactions,
name="transactions_bulk_unpay",
),
path(
"transactions/actions/delete/",
views.bulk_delete_transactions,
name="transactions_bulk_delete",
),
path(
"transaction/<int:transaction_id>/pay",
views.transaction_pay,

View File

@@ -1,3 +1,4 @@
from .transactions import *
from .tags import *
from .categories import *
from .actions import *

View File

@@ -0,0 +1,43 @@
from django.contrib.auth.decorators import login_required
from django.http import HttpResponse
from apps.common.decorators.htmx import only_htmx
from apps.transactions.models import Transaction
@only_htmx
@login_required
def bulk_pay_transactions(request):
selected_transactions = request.GET.getlist("transactions", [])
Transaction.objects.filter(id__in=selected_transactions).update(is_paid=True)
return HttpResponse(
status=204,
headers={"HX-Trigger": "updated, toast, paid"},
)
@only_htmx
@login_required
def bulk_unpay_transactions(request):
selected_transactions = request.GET.getlist("transactions", [])
Transaction.objects.filter(id__in=selected_transactions).update(is_paid=False)
return HttpResponse(
status=204,
headers={"HX-Trigger": "updated, toast, unpaid"},
)
@only_htmx
@login_required
def bulk_delete_transactions(request):
selected_transactions = request.GET.getlist("transactions", [])
Transaction.objects.filter(
id__in=selected_transactions, installment_plan__isnull=True
).delete()
return HttpResponse(
status=204,
headers={"HX-Trigger": "updated, toast"},
)

View File

@@ -8,6 +8,7 @@
{% include 'includes/scripts/hyperscript/hide_amount.html' %}
{% include 'includes/scripts/hyperscript/tooltip.html' %}
{% include 'includes/scripts/hyperscript/htmx_error_handler.html' %}
{% include 'includes/scripts/hyperscript/sounds.html' %}
{% javascript_pack 'htmx' attrs="defer" %}
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>

View File

@@ -0,0 +1,16 @@
<script type="text/hyperscript">
on paid if body do not include #settings-mute-sound
js
paidSound.pause()
paidSound.currentTime = 0
paidSound.play()
end
end
on unpaid if body do not include #settings-mute-sound
js
unpaidSound.pause()
unpaidSound.currentTime = 0
unpaidSound.play()
end
end
</script>

View File

@@ -1,6 +1,18 @@
<script type="text/hyperscript">
behavior tooltip
on mouseenter call bootstrap.Tooltip.getOrCreateInstance(me).show() end
on mouseleave call bootstrap.Tooltip.getOrCreateInstance(me).dispose() end
def initTooltips
-- Destroy existing tooltips
for tooltipTriggerEl in <[data-bs-toggle="tooltip"]/>
call bootstrap.Tooltip.getOrCreateInstance(tooltipTriggerEl).dispose()
end
-- Initialize new tooltips
for tooltipTriggerEl in <[data-bs-toggle="tooltip"]/>
call bootstrap.Tooltip.getOrCreateInstance(tooltipTriggerEl)
end
end
-- Initialize tooltips on page load
on load or htmx:afterSettle
call initTooltips()
end
</script>

View File

@@ -2,7 +2,14 @@
{% load i18n %}
{% regroup transactions by date|customnaturaldate as transactions_by_date %}
<div>
<div id="transactions-list"
_="on change from <input[type='checkbox']/> in me
if no <input[type='checkbox']:checked/> in me
add .tw-hidden to #actions-bar
else
remove .tw-hidden from #actions-bar
end
end">
{% for x in transactions_by_date %}
<div>
<div class="my-3 w-100 tw-text-base border-bottom bg-body">
@@ -17,7 +24,7 @@
</a>
</div>
<div class="collapse show" id="{{ x.grouper|slugify }}">
<div class="ps-3">
<div class="">
{% for trans in x.list %}
{% include 'transactions/fragments/item.html' with transaction=trans %}
{% endfor %}
@@ -36,4 +43,34 @@
</div>
</div>
{% endfor %}
<!-- Floating bar -->
<div class="tw-sticky tw-bottom-4 tw-left-0 tw-right-0 tw-z-50 tw-hidden mx-auto tw-w-fit" id="actions-bar">
<div class="card slide-in-left">
<div class="card-body p-2">
<button class="btn btn-secondary me-3"
hx-get="{% url 'transactions_bulk_pay' %}"
hx-include=".transaction"
_="install tooltip"
data-bs-toggle="tooltip"
data-bs-title="{% translate 'Mark as paid' %}">
<i class="fa-regular fa-circle-check tw-text-green-400"></i>
</button>
<button class="btn btn-secondary me-3"
hx-get="{% url 'transactions_bulk_unpay' %}"
hx-include=".transaction"
_="install tooltip"
data-bs-toggle="tooltip"
data-bs-title="{% translate 'Mark as unpaid' %}">
<i class="fa-regular fa-circle tw-text-red-400"></i>
</button>
<button class="btn btn-secondary"
hx-get="{% url 'transactions_bulk_delete' %}"
hx-include=".transaction"
_="install tooltip"
data-bs-toggle="tooltip"
data-bs-title="{% translate 'Delete' %}"><i class="fa-solid fa-trash text-danger"></i>
</button>
</div>
</div>
</div>
</div>

View File

@@ -54,7 +54,7 @@
<div class="d-flex justify-content-between mt-2">
<div class="d-flex align-items-baseline w-100">
<div class="text-start font-monospace tw-text-gray-300">
<span class="hierarchy-line-icon-4"></span>{{ account_data.name }}</div>
<span class="hierarchy-line-icon"></span>{{ account_data.name }}</div>
<div class="dotted-line flex-grow-1"></div>
<div class="amount" data-original-value="{% currency_display amount=account_data.balance prefix=account_data.currency.prefix suffix=account_data.currency.suffix decimal_places=account_data.currency.decimal_places%}"></div>
</div>

View File

@@ -1,32 +1,22 @@
{% load i18n %}
{% load currency_display %}
<div class="tw-border-s-6 tw-border-e-0 tw-border-t-0 tw-border-b-0 border-bottom
hover:tw-bg-zinc-900 p-2 {% if transaction.account.is_asset %}tw-border-dashed{% else %}tw-border-solid{% endif %}
{% if transaction.type == "EX" %}tw-border-red-500{% else %}tw-border-green-500{% endif %} transaction tw-relative
my-3"
<div class="transaction d-flex my-3">
<label class="px-3 d-flex align-items-center justify-content-center">
<input class="form-check-input" type="checkbox" name="transactions" value="{{ transaction.id }}" aria-label="{% translate 'Select' %}">
</label>
<div class="tw-border-s-6 tw-border-e-0 tw-border-t-0 tw-border-b-0 border-bottom
hover:tw-bg-zinc-900 p-2 {% if transaction.account.is_asset %}tw-border-dashed{% else %}tw-border-solid{% endif %}
{% if transaction.type == "EX" %}tw-border-red-500{% else %}tw-border-green-500{% endif %} transaction tw-relative
w-100 transaction-item"
_="on mouseover remove .tw-invisible from the first .transaction-actions in me end
on mouseout add .tw-invisible to the first .transaction-actions in me end">
<div class="row font-monospace tw-text-sm align-items-center">
<div class="col-lg-1 col-12 d-flex align-items-center tw-text-2xl lg:tw-text-xl text-lg-center pay-button">
<a class="text-decoration-none my-2 w-100"
<div class="row font-monospace tw-text-sm align-items-center">
<div class="col-lg-1 col-12 d-flex align-items-center tw-text-2xl lg:tw-text-xl text-lg-center text-center">
<a class="text-decoration-none my-lg-3 mx-lg-3 mx-2 my-2"
role="button"
hx-get="{% url 'transaction_pay' transaction_id=transaction.id %}"
hx-target="closest .transaction"
hx-swap="outerHTML"
_="on paid if body do not include #settings-mute-sound
js
paidSound.pause()
paidSound.currentTime = 0
paidSound.play()
end
end
on unpaid if body do not include #settings-mute-sound
js
unpaidSound.pause()
unpaidSound.currentTime = 0
unpaidSound.play()
end
end">
hx-swap="outerHTML">
{% if transaction.is_paid %}<i class="fa-regular fa-circle-check tw-text-green-400"></i>{% else %}<i
class="fa-regular fa-circle tw-text-red-400"></i>{% endif %}
</a>
@@ -154,3 +144,4 @@ my-3"
</div>
</div>
</div>
</div>