Add preset expiration day picker to label form
This commit is contained in:
@@ -22,6 +22,7 @@ const STOCK_LEVEL_OPTIONS = [
|
||||
];
|
||||
|
||||
const QUANTITY_UNIT_OPTIONS = ['g', 'ml', 'pc'];
|
||||
const EXPIRATION_DAY_OPTIONS = ['3', '5', '8', '10', '15', '20', '25', '30', '45', '60', '90', '120', '150', '180'];
|
||||
|
||||
export function renderLabelCreatePage() {
|
||||
return `
|
||||
@@ -300,15 +301,47 @@ export function renderLabelCreatePage() {
|
||||
</div>
|
||||
<div class="row g-2">
|
||||
<div class="col-5">
|
||||
<input
|
||||
class="form-control"
|
||||
type="number"
|
||||
min="0"
|
||||
step="1"
|
||||
x-model="form.expireDays"
|
||||
@input="syncExpireDateFromDays()"
|
||||
placeholder="30"
|
||||
/>
|
||||
<div
|
||||
class="position-relative"
|
||||
x-ref="expireDaysPicker"
|
||||
@focusin="expireDaysPickerOpen = true"
|
||||
@focusout="handleExpireDaysFocusOut($event)"
|
||||
>
|
||||
<input
|
||||
class="form-control"
|
||||
type="text"
|
||||
inputmode="numeric"
|
||||
x-model="form.expireDays"
|
||||
@input="onExpireDaysInput()"
|
||||
@click="openExpireDaysPicker()"
|
||||
@keydown.escape="expireDaysPickerOpen = false"
|
||||
placeholder="30"
|
||||
autocomplete="off"
|
||||
/>
|
||||
<template x-if="expireDaysPickerOpen">
|
||||
<div class="shadow-sm position-absolute start-0 end-0 z-3 mt-1 quantity-unit-picker expiration-days-picker">
|
||||
<template x-if="filteredExpireDayOptions.length">
|
||||
<div class="expiration-days-grid">
|
||||
<template x-for="days in filteredExpireDayOptions" :key="days">
|
||||
<button
|
||||
class="btn btn-outline-secondary btn-sm expiration-days-option"
|
||||
type="button"
|
||||
@click="pickExpireDays(days)"
|
||||
:class="{ 'active': form.expireDays === days }"
|
||||
>
|
||||
<span class="fw-semibold" x-text="days"></span>
|
||||
</button>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
<template x-if="!filteredExpireDayOptions.length">
|
||||
<div class="text-body-secondary small p-3">
|
||||
No matching day values found.
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-7">
|
||||
<input
|
||||
@@ -466,11 +499,13 @@ export function labelCreatePageData(store) {
|
||||
stockTypeOptions: STOCK_TYPE_OPTIONS,
|
||||
stockLevelOptions: STOCK_LEVEL_OPTIONS,
|
||||
quantityUnitOptions: QUANTITY_UNIT_OPTIONS,
|
||||
expirationDayOptions: EXPIRATION_DAY_OPTIONS,
|
||||
suggestions: [],
|
||||
locations: [],
|
||||
locationSearch: '',
|
||||
locationPickerOpen: false,
|
||||
quantityUnitPickerOpen: false,
|
||||
expireDaysPickerOpen: false,
|
||||
previewUrl: '',
|
||||
successMessage: '',
|
||||
submitError: '',
|
||||
@@ -580,6 +615,26 @@ export function labelCreatePageData(store) {
|
||||
|
||||
return this.quantityUnitOptions;
|
||||
},
|
||||
get filteredExpireDayOptions() {
|
||||
const query = this.form.expireDays.trim();
|
||||
if (!query) {
|
||||
return this.expirationDayOptions;
|
||||
}
|
||||
|
||||
if (this.expirationDayOptions.includes(query)) {
|
||||
return this.expirationDayOptions;
|
||||
}
|
||||
|
||||
const matches = this.expirationDayOptions.filter((days) =>
|
||||
days.includes(query),
|
||||
);
|
||||
|
||||
if (matches.length) {
|
||||
return matches;
|
||||
}
|
||||
|
||||
return this.expirationDayOptions;
|
||||
},
|
||||
get selectedLocation() {
|
||||
return this.locations.find(
|
||||
(location) => String(location.id) === String(this.form.locationId),
|
||||
@@ -606,6 +661,9 @@ export function labelCreatePageData(store) {
|
||||
openQuantityUnitPicker() {
|
||||
this.quantityUnitPickerOpen = true;
|
||||
},
|
||||
openExpireDaysPicker() {
|
||||
this.expireDaysPickerOpen = true;
|
||||
},
|
||||
onLocationInput() {
|
||||
this.locationPickerOpen = true;
|
||||
if (this.selectedLocation && this.locationSearch !== this.selectedLocation.name) {
|
||||
@@ -631,10 +689,27 @@ export function labelCreatePageData(store) {
|
||||
|
||||
this.quantityUnitPickerOpen = false;
|
||||
},
|
||||
onExpireDaysInput() {
|
||||
this.expireDaysPickerOpen = true;
|
||||
this.syncExpireDateFromDays();
|
||||
},
|
||||
handleExpireDaysFocusOut(event) {
|
||||
const nextTarget = event.relatedTarget;
|
||||
if (nextTarget && this.$refs.expireDaysPicker?.contains(nextTarget)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.expireDaysPickerOpen = false;
|
||||
},
|
||||
pickQuantityUnit(unit) {
|
||||
this.form.uom = unit;
|
||||
this.quantityUnitPickerOpen = false;
|
||||
},
|
||||
pickExpireDays(days) {
|
||||
this.form.expireDays = days;
|
||||
this.expireDaysPickerOpen = false;
|
||||
this.syncExpireDateFromDays();
|
||||
},
|
||||
syncLocationSelection() {
|
||||
if (!this.form.locationId) {
|
||||
this.locationSearch = '';
|
||||
|
||||
Reference in New Issue
Block a user