Enforce required label form fields before preview and create
This commit is contained in:
@@ -45,7 +45,7 @@ export function renderLabelCreatePage() {
|
|||||||
<div class="col-12 col-xl-7">
|
<div class="col-12 col-xl-7">
|
||||||
<div class="card border-0 shadow-sm">
|
<div class="card border-0 shadow-sm">
|
||||||
<div class="card-body p-4">
|
<div class="card-body p-4">
|
||||||
<form class="vstack gap-3" @submit.prevent="create()" autocomplete="off">
|
<form class="vstack gap-3" @submit.prevent="create()" autocomplete="off" x-ref="labelForm">
|
||||||
<div class="position-relative search-field-with-clear">
|
<div class="position-relative search-field-with-clear">
|
||||||
<label class="form-label">Search item definitions</label>
|
<label class="form-label">Search item definitions</label>
|
||||||
<input class="form-control pe-5" type="text" x-model="form.search" @input="onSearchInput()" placeholder="Search by item name" autocomplete="off" />
|
<input class="form-control pe-5" type="text" x-model="form.search" @input="onSearchInput()" placeholder="Search by item name" autocomplete="off" />
|
||||||
@@ -98,8 +98,8 @@ export function renderLabelCreatePage() {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12 col-md-4">
|
<div class="col-12 col-md-4">
|
||||||
<label class="form-label">Stock type</label>
|
<label class="form-label">Stock type <span class="text-danger">*</span></label>
|
||||||
<select class="form-select" x-model="form.stockType" x-ref="stockTypeSelect" autocomplete="off">
|
<select class="form-select" x-model="form.stockType" x-ref="stockTypeSelect" autocomplete="off" required>
|
||||||
<template x-for="option in stockTypeOptions" :key="option.value">
|
<template x-for="option in stockTypeOptions" :key="option.value">
|
||||||
<option :value="option.value" x-text="option.label"></option>
|
<option :value="option.value" x-text="option.label"></option>
|
||||||
</template>
|
</template>
|
||||||
@@ -232,6 +232,7 @@ export function renderLabelCreatePage() {
|
|||||||
class="form-control pe-5"
|
class="form-control pe-5"
|
||||||
type="text"
|
type="text"
|
||||||
x-model="locationSearch"
|
x-model="locationSearch"
|
||||||
|
x-ref="locationInput"
|
||||||
@input="onLocationInput()"
|
@input="onLocationInput()"
|
||||||
@keydown.escape="locationPickerOpen = false"
|
@keydown.escape="locationPickerOpen = false"
|
||||||
@click="openLocationPicker()"
|
@click="openLocationPicker()"
|
||||||
@@ -284,8 +285,8 @@ export function renderLabelCreatePage() {
|
|||||||
<div class="form-text" x-show="selectedLocationPath" x-text="selectedLocationPath"></div>
|
<div class="form-text" x-show="selectedLocationPath" x-text="selectedLocationPath"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12 col-md-6">
|
<div class="col-12 col-md-6">
|
||||||
<label class="form-label">Production date</label>
|
<label class="form-label">Production date <span class="text-danger">*</span></label>
|
||||||
<input class="form-control" type="date" x-model="form.productionDate" />
|
<input class="form-control" type="date" x-model="form.productionDate" required />
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12 col-md-6 grouped-field-with-clear">
|
<div class="col-12 col-md-6 grouped-field-with-clear">
|
||||||
<div class="grouped-field-footer mb-1">
|
<div class="grouped-field-footer mb-1">
|
||||||
@@ -647,12 +648,14 @@ export function labelCreatePageData(store) {
|
|||||||
this.form.locationId = String(location.id);
|
this.form.locationId = String(location.id);
|
||||||
this.locationSearch = location.name;
|
this.locationSearch = location.name;
|
||||||
this.locationPickerOpen = false;
|
this.locationPickerOpen = false;
|
||||||
|
this.syncLocationValidity();
|
||||||
this.persistDraft();
|
this.persistDraft();
|
||||||
},
|
},
|
||||||
clearLocation() {
|
clearLocation() {
|
||||||
this.form.locationId = '';
|
this.form.locationId = '';
|
||||||
this.locationSearch = '';
|
this.locationSearch = '';
|
||||||
this.locationPickerOpen = true;
|
this.locationPickerOpen = true;
|
||||||
|
this.syncLocationValidity();
|
||||||
this.persistDraft();
|
this.persistDraft();
|
||||||
},
|
},
|
||||||
openLocationPicker() {
|
openLocationPicker() {
|
||||||
@@ -669,6 +672,7 @@ export function labelCreatePageData(store) {
|
|||||||
if (this.selectedLocation && this.locationSearch !== this.selectedLocation.name) {
|
if (this.selectedLocation && this.locationSearch !== this.selectedLocation.name) {
|
||||||
this.form.locationId = '';
|
this.form.locationId = '';
|
||||||
}
|
}
|
||||||
|
this.syncLocationValidity();
|
||||||
},
|
},
|
||||||
handleLocationFocusOut(event) {
|
handleLocationFocusOut(event) {
|
||||||
const nextTarget = event.relatedTarget;
|
const nextTarget = event.relatedTarget;
|
||||||
@@ -721,6 +725,7 @@ export function labelCreatePageData(store) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
this.locationSearch = selected ? selected.name : '';
|
this.locationSearch = selected ? selected.name : '';
|
||||||
|
this.syncLocationValidity();
|
||||||
},
|
},
|
||||||
applyItemLocation(locationUuidB64) {
|
applyItemLocation(locationUuidB64) {
|
||||||
if (!locationUuidB64) {
|
if (!locationUuidB64) {
|
||||||
@@ -737,6 +742,34 @@ export function labelCreatePageData(store) {
|
|||||||
|
|
||||||
this.form.locationId = String(location.id);
|
this.form.locationId = String(location.id);
|
||||||
this.locationSearch = location.name;
|
this.locationSearch = location.name;
|
||||||
|
this.syncLocationValidity();
|
||||||
|
},
|
||||||
|
syncLocationValidity() {
|
||||||
|
const input = this.$refs.locationInput;
|
||||||
|
if (!input) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.locationSearch.trim()) {
|
||||||
|
input.setCustomValidity('Please select a storage location.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.form.locationId) {
|
||||||
|
input.setCustomValidity('Please choose a location from the list.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.setCustomValidity('');
|
||||||
|
},
|
||||||
|
validateBeforeSubmit() {
|
||||||
|
this.syncLocationValidity();
|
||||||
|
const form = this.$refs.labelForm;
|
||||||
|
if (!form) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return form.reportValidity();
|
||||||
},
|
},
|
||||||
syncExpireDateFromDays() {
|
syncExpireDateFromDays() {
|
||||||
if (this.form.expireDays === '') {
|
if (this.form.expireDays === '') {
|
||||||
@@ -826,6 +859,14 @@ export function labelCreatePageData(store) {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
async preview() {
|
async preview() {
|
||||||
|
this.submitError = '';
|
||||||
|
this.fieldErrors = {};
|
||||||
|
|
||||||
|
if (!this.validateBeforeSubmit()) {
|
||||||
|
this.previewState.error = 'Please fill out the required fields before previewing the label.';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
await runAsyncState(this.previewState, async () => {
|
await runAsyncState(this.previewState, async () => {
|
||||||
this.successMessage = '';
|
this.successMessage = '';
|
||||||
const result = await previewLabel(store, this.buildPayload());
|
const result = await previewLabel(store, this.buildPayload());
|
||||||
@@ -840,6 +881,11 @@ export function labelCreatePageData(store) {
|
|||||||
this.submitError = '';
|
this.submitError = '';
|
||||||
this.fieldErrors = {};
|
this.fieldErrors = {};
|
||||||
|
|
||||||
|
if (!this.validateBeforeSubmit()) {
|
||||||
|
this.submitError = 'Please fill out the required fields before creating the stock entry.';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
await runAsyncState(this.createState, async () => {
|
await runAsyncState(this.createState, async () => {
|
||||||
try {
|
try {
|
||||||
const entry = await createStockEntry(store, this.buildPayload());
|
const entry = await createStockEntry(store, this.buildPayload());
|
||||||
|
|||||||
Reference in New Issue
Block a user