Auto-fill transaction form

Close #27
This commit is contained in:
Edgar P. Burkhart 2025-01-03 18:50:50 +01:00
parent 0cb4a681f1
commit ff519ea7d1
Signed by: edpibu
GPG key ID: 9833D3C5A25BD227
5 changed files with 111 additions and 2 deletions

View file

@ -1,3 +1,11 @@
@keyframes border-pulse {
from {
border-color: var(--green);
}
to {
}
}
form {
display: grid;
gap: 0.5rem;
@ -90,6 +98,9 @@ form {
&:has(~ ul.errorlist) {
border-color: var(--red);
}
&.autocompleted:not(.mod) {
border-bottom-color: var(--green);
}
&:not([type="checkbox"]) {
width: 100%;

View file

@ -44,7 +44,6 @@ for (let form of forms) {
);
function setIcon(event) {
console.log(input.value);
icon.className = `ri-${
icons.includes(input.value) ? input.value : "square"
}-line`;
@ -55,6 +54,75 @@ for (let form of forms) {
setTimeout(setIcon, 0);
});
}
let ac_json = form.querySelector("#autocomplete");
if (ac_json) {
let autocomplete_data = JSON.parse(ac_json.textContent);
let fields = form.querySelectorAll("[name]");
function clearMod(event) {
event.target.classList.add("mod");
event.target.removeEventListener("input", clearMod);
}
function setMod() {
for (let f of fields) {
f.addEventListener("input", clearMod);
}
}
setMod();
form.addEventListener("reset", (event) => {
for (let f of fields) {
f.classList.remove("mod", "autocompleted");
}
setMod();
});
let old_values = [];
let field = form.querySelector(`[name="${autocomplete_data.field}"]`);
field.addEventListener("change", (event) => {
if (field.value in autocomplete_data.data) {
old_values = [];
for (let comp of autocomplete_data.data[field.value]) {
let f = form.querySelector(`[name="${comp.field}"]`);
if (!f.classList.contains("mod")) {
old_values.push({ field: f, value: f.value });
f.value = comp.value;
f.dispatchEvent(new Event("input"));
f.animate([{ borderColor: "var(--green)" }, {}], 750);
f.classList.remove("mod");
f.classList.add("autocompleted");
f.addEventListener("input", clearMod);
function ccAutocomplete(event) {
document.removeEventListener("keyup", cancelAutocomplete);
for (comp of old_values) {
comp.field.removeEventListener("input", ccAutocomplete);
}
}
f.addEventListener("input", ccAutocomplete);
}
}
function cancelAutocomplete(event) {
if (event.code == "Escape") {
for (comp of old_values) {
let f = comp.field;
f.value = comp.value;
f.dispatchEvent(new Event("input"));
f.animate([{ borderColor: "var(--red)" }, {}], 750);
f.classList.remove("mod");
f.classList.remove("autocompleted");
f.addEventListener("input", clearMod);
}
document.removeEventListener("keyup", cancelAutocomplete);
}
}
document.addEventListener("keyup", cancelAutocomplete);
form.addEventListener("reset", (event) => {
document.removeEventListener("keyup", cancelAutocomplete);
});
}
});
}
}
let accounts = document.querySelector("dl.accounts");

View file

@ -1,6 +1,7 @@
{% load i18n %}
{% load main_extras %}
{% block fields %}
{% if form.autocomplete %}{{ form.autocomplete|json_script:"autocomplete" }}{% endif %}
{% if form.non_field_errors %}
<ul class="errorlist">
{% for error in form.non_field_errors %}<li>{{ error }}</li>{% endfor %}

View file

@ -48,6 +48,7 @@ class TransactionForm(NummiForm):
def __init__(self, *args, **kwargs):
_user = kwargs.get("user")
_disable_statement = kwargs.pop("disable_statement", False)
_autocomplete = kwargs.pop("autocomplete", False)
super().__init__(*args, **kwargs)
self.fields["category"].queryset = self.fields["category"].queryset.filter(
@ -71,6 +72,34 @@ class TransactionForm(NummiForm):
),
}
if _autocomplete:
self.autocomplete = {
"field": "name",
"data": {
t.name: [
{
"field": "value",
"value": t.value,
},
{
"field": "category",
"value": t.category.id if t.category else "",
},
{
"field": "trader",
"value": t.trader,
},
{
"field": "payment",
"value": t.payment,
},
]
for t in _user.transaction_set.order_by("name", "-date").distinct(
"name"
)
},
}
if _disable_statement:
self.fields["statement"].disabled = True

View file

@ -33,7 +33,7 @@ class TransactionCreateView(NummiCreateView):
def get_form_kwargs(self):
if "statement" in self.kwargs:
return super().get_form_kwargs() | {"disable_statement": True}
return super().get_form_kwargs()
return super().get_form_kwargs() | {"autocomplete": True}
class InvoiceCreateView(NummiCreateView):