Clean up stock management modal [SCI-10422]

This commit is contained in:
Martin Artnik 2024-03-12 13:24:55 +01:00
parent 8407361083
commit 763c741662
4 changed files with 66 additions and 58 deletions

View file

@ -4,6 +4,10 @@
@apply text-sm font-medium text-sn-dark-grey;
}
.sci-label.error {
@apply text-sn-coral;
}
.sci-input-container-v2 {
@apply relative h-[2.75rem] flex items-center;
}
@ -24,6 +28,18 @@
@apply !border-sn-coral;
}
.sci-input-container-v2.error::before {
@apply !text-sn-coral;
@apply !text-xs;
bottom: -1rem;
content: attr(data-error-text);
left: 0;
position: absolute;
white-space: nowrap;
width: 100%;
}
.sci-input-container-v2 input:focus {
@apply border-sn-science-blue shadow-none;
}

View file

@ -26,7 +26,7 @@
<form class="flex flex-col gap-6" @submit.prevent novalidate>
<fieldset class="w-full flex justify-between">
<div class="flex flex-col w-40">
<label class="text-sn-grey text-sm font-normal" for="operations">{{ i18n.t('repository_stock_values.manage_modal.operation') }}</label>
<label class="sci-label" for="operations">{{ i18n.t('repository_stock_values.manage_modal.operation') }}</label>
<Select
:disabled="!stockValue?.id"
:value="operation"
@ -39,21 +39,18 @@
@update="value => amount = value"
name="stock_amount"
id="stock-amount"
:inputClass="`sci-input-container-v2 ${errors.amount ? 'error' : ''}`"
:labelClass="`text-sm font-normal ${errors.amount ? 'text-sn-delete-red' : 'text-sn-grey'}`"
type="number"
:value="amount"
:decimals="stockValue.decimals"
:placeholder="i18n.t('repository_stock_values.manage_modal.amount_placeholder_new')"
required
:label="i18n.t('repository_stock_values.manage_modal.amount')"
showLabel
autoFocus
:required="true"
:min="0"
:error="errors.amount"
/>
</div>
<div class="flex flex-col w-40">
<label :class="`text-sm font-normal ${errors.unit ? 'text-sn-delete-red' : 'text-sn-grey'}`" for="stock-unit">
<label class="sci-label" :class="{ 'error': !!errors.unit }" for="stock-unit">
{{ i18n.t('repository_stock_values.manage_modal.unit') }}
</label>
<Select
@ -93,24 +90,21 @@
</div>
<span class="ml-2">{{ i18n.t('repository_stock_values.manage_modal.create_reminder') }}</span>
</div>
<div v-if="reminderEnabled" class="stock-reminder-value flex gap-2 items-center">
<div v-if="reminderEnabled" class="stock-reminder-value flex gap-2 items-center w-40">
<Input
@update="value => lowStockTreshold = value"
name="treshold_amount"
id="treshold-amount"
fieldClass="flex gap-2"
inputClass="sci-input-container-v2 w-40"
labelClass="text-sm font-normal flex items-center"
type="number"
:value="lowStockTreshold"
:decimals="stockValue.decimals"
:placeholder="i18n.t('repository_stock_values.manage_modal.amount_placeholder_new')"
required
:required="true"
:label="i18n.t('repository_stock_values.manage_modal.reminder_at')"
showLabel
:min="0"
:error="errors.tresholdAmount"
/>
<span class="text-sm font-normal">
<span class="text-sm font-normal mt-5">
{{ unitLabel }}
</span>
</div>
@ -155,7 +149,7 @@ export default {
operation: null,
operations: [],
stockValue: null,
amount: '',
amount: null,
repositoryRowName: null,
stockUrl: null,
units: null,
@ -177,7 +171,7 @@ export default {
return unit ? unit[1] : '';
},
newAmount() {
const currentAmount = new Decimal(this.stockValue?.amount || 0);
const currentAmount = this.stockValue?.amount ? new Decimal(this.stockValue?.amount || 0) : null;
const amount = new Decimal(this.amount || 0);
let value;
switch (this.operation) {
@ -227,7 +221,7 @@ export default {
success: (result) => {
this.repositoryRowName = result.repository_row_name;
this.stockValue = result.stock_value;
this.amount = Number(new Decimal(result.stock_value.amount || 0));
this.amount = this.stockValue?.amount && Number(new Decimal(this.stockValue.amount));
this.units = result.stock_value.units;
this.unit = result.stock_value.unit;
this.reminderEnabled = result.stock_value.reminder_enabled;

View file

@ -1,75 +1,69 @@
<template>
<div class="relative" :class="fieldClass">
<label v-if="showLabel" :class="labelClass" :for="id">{{ label }}</label>
<div :class="inputClass">
<div class="relative w-full">
<label v-if="label" class="sci-label" :class="{ 'error': !!inputError }" :for="id">{{ label }}</label>
<div class="sci-input-container-v2" :class="{ 'error': !!inputError }" :data-error-text="inputError">
<input ref="input"
:type="type"
:id="id"
:name="name"
:value="inputValue"
:class="`${error ? 'error' : ''}`"
:value="value"
:class="{ 'error': !!inputError }"
:placeholder="placeholder"
:required="required"
inputmode="numeric"
:min="min"
:max="max"
:step="1/Math.pow(10, decimals)"
@input="updateValue"
/>
<div
class="mt-2 text-sn-delete-red whitespace-nowrap truncate text-xs font-normal absolute bottom-[-1rem] w-full"
:title="error"
:class="{ visible: error, invisible: !error}"
>
{{ error }}
</div>
</div>
</div>
</template>
<script>
export default {
name: 'Input',
props: {
id: { type: String, required: false },
fieldClass: { type: String, default: '' },
inputClass: { type: String, default: '' },
labelClass: { type: String, default: '' },
type: { type: String, default: 'text' },
name: { type: String, required: true },
value: { type: [String, Number], required: false },
decimals: { type: [Number, String], default: 0 },
placeholder: { type: String, default: '' },
required: { type: Boolean, default: false },
showLabel: { type: Boolean, default: false },
label: { type: String, required: false },
autoFocus: { type: Boolean, default: false },
error: { type: String, required: false }
error: { type: String, required: false },
min: { type: String },
max: { type: String },
blockInvalidInput: { type: Boolean, default: true }
},
computed: {
inputValue() {
if (this.type === 'text') return this.value;
return isNaN(this.value) ? '' : this.value;
data() {
return {
inputError: false,
lastValue: this.value
};
},
watch: {
value() {
this.lastValue = this.value;
}
},
methods: {
updateValue($event) {
switch (this.type) {
case 'text':
this.$emit('update', $event.target.value);
break;
case 'number':
const newValue = this.formatDecimalValue($event.target.value);
this.$refs.input.value = newValue;
if (!isNaN(newValue)) this.$emit('update', newValue);
break;
default:
break;
}
this.checkInputError($event);
this.$emit('update', $event.target.value);
},
formatDecimalValue(value) {
const decimalValue = value.replace(/[^-0-9.]/g, '');
if (this.decimals === '0') {
return decimalValue.split('.')[0];
checkInputError() {
const isValid = this.$refs.input.checkValidity();
if (isValid) {
this.lastValue = this.$refs.input.value;
} else if (this.blockInvalidInput) {
this.$refs.input.value = this.lastValue;
return;
}
return decimalValue.match(new RegExp(`^-?\\d*(\\.\\d{0,${this.decimals}})?`))[0];
this.inputError = this.error || (!isValid && this.i18n.t('input.errors.invalid_value'));
}
}
};

View file

@ -4008,6 +4008,10 @@ en:
From: 'From'
To: 'To'
input:
errors:
invalid_value: 'Invalid value'
marvinjs:
new_sketch: "New chemical drawing"
new_button: "New chemical drawing"