Add label printing functionality and error handling in stock and label flows
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/pr/woodpecker Pipeline was successful

This commit is contained in:
2026-04-10 22:08:01 +02:00
parent 1dc1bb4912
commit e1383c4d56
10 changed files with 627 additions and 21 deletions
+46 -2
View File
@@ -660,7 +660,7 @@ export function renderStockListPage() {
<div class="grouped-stock-items">
<template x-for="item in group.items" :key="item.id">
<a class="grouped-stock-item text-decoration-none" :class="groupedItemClass(item)" :href="detailHref(item)">
<div class="grouped-stock-item" :class="groupedItemClass(item)">
<div class="d-flex flex-column flex-lg-row justify-content-between gap-2">
<div>
<div class="fw-semibold" x-text="item.name"></div>
@@ -669,6 +669,7 @@ export function renderStockListPage() {
<span class="grouped-stock-subline-separator" aria-hidden="true">•</span>
<span x-text="shortDescription(item.description)"></span>
</div>
<a class="small text-decoration-none fw-semibold" :href="detailHref(item)">View item</a>
</div>
<div class="d-flex flex-wrap gap-3 small text-body-secondary grouped-stock-item-meta">
<span x-text="quantityLabel(item)"></span>
@@ -678,9 +679,13 @@ export function renderStockListPage() {
<span x-text="formatDate(item.expire_date)"></span>
</span>
<span class="font-monospace" x-text="shortId(item)"></span>
<button class="btn btn-sm btn-outline-danger grouped-stock-mark-gone" type="button" @click="markGoneFromGroup(item, group)">Mark gone</button>
</div>
</div>
</a>
<template x-if="editErrors[item.id]">
<div class="small text-danger mt-2" x-text="editErrors[item.id]"></div>
</template>
</div>
</template>
</div>
@@ -1231,6 +1236,26 @@ export function stockListPageData(store) {
async markGone(entry) {
await this.useEntry(entry);
},
async markGoneFromGroup(item, group) {
this.editErrors[item.id] = '';
try {
const result = await useStockItem(store, item.uuid_b64);
const alreadyGone = result.status === 'already_gone';
this.removeGroupedItem(group.id, item.id);
this.entries = this.entries.filter((candidate) => candidate.id !== item.id);
delete this.editForms[item.id];
delete this.editErrors[item.id];
store.addAlert({
type: alreadyGone ? 'info' : 'success',
message: alreadyGone
? `${item.name} was already out of stock and removed from the group.`
: `${item.name} was marked gone and removed from the group.`,
});
} catch (error) {
this.editErrors[item.id] = error.message || 'Mark gone failed.';
}
},
async saveEntryUpdate(entry, payload, localPatch) {
this.editErrors[entry.id] = '';
@@ -1273,5 +1298,24 @@ export function stockListPageData(store) {
quantity: nextEntry.quantity ?? '',
};
},
removeGroupedItem(groupId, itemId) {
this.groupedEntries = this.groupedEntries
.map((group) => {
if (group.id !== groupId) {
return group;
}
const nextItems = (group.items || []).filter((candidate) => candidate.id !== itemId);
if (!nextItems.length) {
return null;
}
return {
...group,
items: nextItems,
};
})
.filter(Boolean);
},
};
}