121 lines
2.8 KiB
Vue
121 lines
2.8 KiB
Vue
|
|
<script setup lang="ts">
|
||
|
|
import {
|
||
|
|
PropDate,
|
||
|
|
PropNumber,
|
||
|
|
PropOptions,
|
||
|
|
PropString,
|
||
|
|
} from 'src/stores/product-service/types';
|
||
|
|
|
||
|
|
import SelectInput from '../shared/SelectInput.vue';
|
||
|
|
import DatePicker from '../shared/DatePicker.vue';
|
||
|
|
|
||
|
|
defineProps<{
|
||
|
|
prop: PropString | PropNumber | PropDate | PropOptions;
|
||
|
|
placeholder?: string;
|
||
|
|
readonly?: boolean;
|
||
|
|
disable?: boolean;
|
||
|
|
}>();
|
||
|
|
|
||
|
|
const model = defineModel<string | number | null | undefined>();
|
||
|
|
|
||
|
|
function numberDisplay(prop: PropNumber, data: number): string {
|
||
|
|
if (isNaN(data)) data = 0;
|
||
|
|
|
||
|
|
let formattedNumber: string;
|
||
|
|
|
||
|
|
if (prop.comma && prop.decimal) {
|
||
|
|
formattedNumber = data.toLocaleString('en-US', {
|
||
|
|
minimumFractionDigits: prop.decimalPlace,
|
||
|
|
maximumFractionDigits: prop.decimalPlace,
|
||
|
|
});
|
||
|
|
} else if (prop.comma && !prop.decimal) {
|
||
|
|
formattedNumber = data.toLocaleString('en-US', {
|
||
|
|
minimumFractionDigits: 0,
|
||
|
|
maximumFractionDigits: 0,
|
||
|
|
});
|
||
|
|
} else if (!prop.comma && prop.decimal) {
|
||
|
|
formattedNumber = data.toFixed(prop.decimalPlace);
|
||
|
|
} else {
|
||
|
|
formattedNumber = Math.round(data).toString();
|
||
|
|
}
|
||
|
|
|
||
|
|
return formattedNumber;
|
||
|
|
}
|
||
|
|
|
||
|
|
function numberParse(formatted: string, prop: PropNumber): number {
|
||
|
|
let parsedNumber: number;
|
||
|
|
|
||
|
|
let cleanedFormatted = formatted.replace(/,/g, '');
|
||
|
|
|
||
|
|
if (prop.decimal) {
|
||
|
|
parsedNumber = parseFloat(cleanedFormatted);
|
||
|
|
} else {
|
||
|
|
parsedNumber = parseInt(cleanedFormatted, 10);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (isNaN(parsedNumber)) {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
return parsedNumber;
|
||
|
|
}
|
||
|
|
</script>
|
||
|
|
<template>
|
||
|
|
<q-input
|
||
|
|
v-if="prop.type === 'string'"
|
||
|
|
:readonly
|
||
|
|
:disable
|
||
|
|
class="col-7"
|
||
|
|
:model-value="readonly || disable ? model || '-' : model"
|
||
|
|
dense
|
||
|
|
outlined
|
||
|
|
:placeholder
|
||
|
|
:maxlength="prop.isPhoneNumber ? prop.phoneNumberLength : undefined"
|
||
|
|
@update:model-value="
|
||
|
|
(v) => {
|
||
|
|
model = v;
|
||
|
|
}
|
||
|
|
"
|
||
|
|
@focus="(e) => (e.target as HTMLInputElement).select()"
|
||
|
|
/>
|
||
|
|
<q-input
|
||
|
|
v-if="prop.type === 'number'"
|
||
|
|
:readonly
|
||
|
|
:disable
|
||
|
|
class="col-7"
|
||
|
|
debounce="500"
|
||
|
|
dense
|
||
|
|
outlined
|
||
|
|
:model-value="numberDisplay(prop, Number(model))"
|
||
|
|
@update:model-value="
|
||
|
|
(v) => {
|
||
|
|
let cleanedFormatted = v?.toString().replace(/,/g, '');
|
||
|
|
|
||
|
|
const x = numberParse(
|
||
|
|
numberDisplay(prop as PropNumber, Number(cleanedFormatted)),
|
||
|
|
prop as PropNumber,
|
||
|
|
);
|
||
|
|
model = x;
|
||
|
|
}
|
||
|
|
"
|
||
|
|
@focus="(e) => (e.target as HTMLInputElement).select()"
|
||
|
|
/>
|
||
|
|
<DatePicker
|
||
|
|
v-if="prop.type === 'date'"
|
||
|
|
:readonly
|
||
|
|
:disabled="disable"
|
||
|
|
class="col-7"
|
||
|
|
v-model="model as string"
|
||
|
|
/>
|
||
|
|
<SelectInput
|
||
|
|
v-if="prop.type === 'array'"
|
||
|
|
:readonly
|
||
|
|
:disable
|
||
|
|
:label="$t('form.selection')"
|
||
|
|
v-model="model as string"
|
||
|
|
class="col-7"
|
||
|
|
:option="prop.options.map((opt) => ({ label: opt, value: opt }))"
|
||
|
|
/>
|
||
|
|
</template>
|
||
|
|
<style scoped></style>
|