diff --git a/CHANGELOG.md b/CHANGELOG.md index e34523545..b72bc2c8a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- (Worker) => Se crea la sección Taquilla +- (General) => Se mantiene el filtro lateral en cualquier parte de la seccíon. + ### Fixed - (General) => Se vuelven a mostrar los parámetros en la url al aplicar un filtro diff --git a/package.json b/package.json index 063cf6de4..7be20a842 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "salix-front", - "version": "24.20.0", + "version": "24.22.0", "description": "Salix frontend", "productName": "Salix", "author": "Verdnatura", diff --git a/quasar.config.js b/quasar.config.js index dd7a91002..b59c62eeb 100644 --- a/quasar.config.js +++ b/quasar.config.js @@ -29,7 +29,7 @@ module.exports = configure(function (/* ctx */) { // app boot file (/src/boot) // --> boot files are part of "main.js" // https://v2.quasar.dev/quasar-cli/boot-files - boot: ['i18n', 'axios', 'vnDate', 'validations', 'quasar.defaults'], + boot: ['i18n', 'axios', 'vnDate', 'validations', 'quasar', 'quasar.defaults'], // https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#css css: ['app.scss'], diff --git a/src/components/CreateBankEntityForm.vue b/src/components/CreateBankEntityForm.vue index 2d098beb0..b2c5226e6 100644 --- a/src/components/CreateBankEntityForm.vue +++ b/src/components/CreateBankEntityForm.vue @@ -3,17 +3,12 @@ import { reactive, ref, onMounted, nextTick } from 'vue'; import { useI18n } from 'vue-i18n'; import VnInput from 'src/components/common/VnInput.vue'; -import VnSelectFilter from 'src/components/common/VnSelectFilter.vue'; +import VnSelect from 'src/components/common/VnSelect.vue'; import FetchData from 'components/FetchData.vue'; import VnRow from 'components/ui/VnRow.vue'; import FormModelPopup from './FormModelPopup.vue'; -const props = defineProps({ - showEntityField: { - type: Boolean, - default: true, - }, -}); +defineProps({ showEntityField: { type: Boolean, default: true } }); const emit = defineEmits(['onDataSaved']); const { t } = useI18n(); @@ -26,7 +21,7 @@ const bankEntityFormData = reactive({ }); const countriesFilter = { - fields: ['id', 'country', 'code'], + fields: ['id', 'name', 'code'], }; const countriesOptions = ref([]); @@ -58,32 +53,28 @@ onMounted(async () => { > diff --git a/src/components/CreateNewProvinceForm.vue b/src/components/CreateNewProvinceForm.vue index b972db2c9..2d626ed99 100644 --- a/src/components/CreateNewProvinceForm.vue +++ b/src/components/CreateNewProvinceForm.vue @@ -4,7 +4,7 @@ import { useI18n } from 'vue-i18n'; import FetchData from 'components/FetchData.vue'; import VnRow from 'components/ui/VnRow.vue'; -import VnSelectFilter from 'src/components/common/VnSelectFilter.vue'; +import VnSelect from 'src/components/common/VnSelect.vue'; import VnInput from 'src/components/common/VnInput.vue'; import FormModelPopup from './FormModelPopup.vue'; @@ -40,24 +40,20 @@ const onDataSaved = (dataSaved) => { > diff --git a/src/components/CreateThermographForm.vue b/src/components/CreateThermographForm.vue index d4511a0e7..061c47712 100644 --- a/src/components/CreateThermographForm.vue +++ b/src/components/CreateThermographForm.vue @@ -4,7 +4,7 @@ import { useI18n } from 'vue-i18n'; import FetchData from 'components/FetchData.vue'; import VnRow from 'components/ui/VnRow.vue'; -import VnSelectFilter from 'src/components/common/VnSelectFilter.vue'; +import VnSelect from 'src/components/common/VnSelect.vue'; import VnInput from 'src/components/common/VnInput.vue'; import FormModelPopup from './FormModelPopup.vue'; @@ -54,51 +54,42 @@ const onDataSaved = (dataSaved) => { > diff --git a/src/components/CrudModel.vue b/src/components/CrudModel.vue index fb3ac10c3..000de4336 100644 --- a/src/components/CrudModel.vue +++ b/src/components/CrudModel.vue @@ -81,6 +81,7 @@ defineExpose({ hasChanges, saveChanges, getChanges, + formData, }); async function fetch(data) { @@ -124,11 +125,16 @@ async function onSubmit() { }); } isLoading.value = true; - await saveChanges(); + await saveChanges($props.saveFn ? formData.value : null); } async function saveChanges(data) { - if ($props.saveFn) return $props.saveFn(data, getChanges); + if ($props.saveFn) { + $props.saveFn(data, getChanges); + isLoading.value = false; + hasChanges.value = false; + return; + } const changes = data || getChanges(); try { await axios.post($props.saveUrl || $props.url + '/crud', changes); diff --git a/src/components/EditPictureForm.vue b/src/components/EditPictureForm.vue index 3d7f3615b..a51ca11ad 100644 --- a/src/components/EditPictureForm.vue +++ b/src/components/EditPictureForm.vue @@ -2,7 +2,7 @@ import { reactive, computed, ref } from 'vue'; import { useI18n } from 'vue-i18n'; -import VnSelectFilter from 'src/components/common/VnSelectFilter.vue'; +import VnSelect from 'src/components/common/VnSelect.vue'; import FetchData from 'components/FetchData.vue'; import VnRow from 'components/ui/VnRow.vue'; import VnInput from 'src/components/common/VnInput.vue'; @@ -246,61 +246,55 @@ const makeRequest = async () => {
-
- -
+
-
- - - - -
+ + + +
-
- -
+
-import { ref, reactive } from 'vue'; +import { ref, markRaw } from 'vue'; import { useI18n } from 'vue-i18n'; -import VnSelectFilter from 'src/components/common/VnSelectFilter.vue'; +import VnSelect from 'src/components/common/VnSelect.vue'; import VnInput from 'src/components/common/VnInput.vue'; +import VnInputDate from 'src/components/common/VnInputDate.vue'; +import VnRow from 'components/ui/VnRow.vue'; +import { QCheckbox } from 'quasar'; import axios from 'axios'; import useNotify from 'src/composables/useNotify.js'; @@ -28,11 +31,16 @@ const $props = defineProps({ const { t } = useI18n(); const { notify } = useNotify(); -const formData = reactive({ - field: null, - newValue: null, -}); +const inputs = { + input: markRaw(VnInput), + number: markRaw(VnInput), + date: markRaw(VnInputDate), + checkbox: markRaw(QCheckbox), + select: markRaw(VnSelect), +}; +const newValue = ref(null); +const selectedField = ref(null); const closeButton = ref(null); const isLoading = ref(false); @@ -47,8 +55,8 @@ const submitData = async () => { isLoading.value = true; const rowsToEdit = $props.rows.map((row) => ({ id: row.id, itemFk: row.itemFk })); const payload = { - field: formData.field, - newValue: formData.newValue, + field: selectedField.value.field, + newValue: newValue.value, lines: rowsToEdit, }; @@ -75,19 +83,20 @@ const closeForm = () => { {{ ` ${rows.length} ` }} {{ t('buy(s)') }} -
- -
-
- -
+ +
import { ref, reactive, computed } from 'vue'; import { useI18n } from 'vue-i18n'; -import { useRoute } from 'vue-router'; import VnRow from 'components/ui/VnRow.vue'; import FetchData from 'components/FetchData.vue'; import VnInput from 'src/components/common/VnInput.vue'; -import VnSelectFilter from 'components/common/VnSelectFilter.vue'; +import VnSelect from 'components/common/VnSelect.vue'; import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue'; import axios from 'axios'; import { dashIfEmpty } from 'src/filters'; +const props = defineProps({ + url: { + type: String, + required: true, + }, +}); + const emit = defineEmits(['itemSelected']); const { t } = useI18n(); -const route = useRoute(); const itemFilter = { include: [ @@ -73,7 +78,7 @@ const tableColumns = computed(() => [ { label: t('entry.buys.color'), name: 'ink', - field: 'inkName', + field: (row) => row?.ink?.name, align: 'left', }, ]); @@ -100,7 +105,7 @@ const fetchResults = async () => { } filter.where = where; - const { data } = await axios.get(`Entries/${route.params.id}/lastItemBuys`, { + const { data } = await axios.get(props.url, { params: { filter: JSON.stringify(filter) }, }); tableRows.value = data; @@ -147,48 +152,32 @@ const selectItem = ({ id }) => {

{{ t('Filter item') }}

-
- -
-
- -
-
- -
-
- -
-
- -
+ + + + +
{

{{ t('Filter travels') }}

-
- -
-
- -
-
- -
-
- -
-
- -
+ + + + +
{ }); onBeforeRouteLeave((to, from, next) => { - if (hasChanges.value) + if (hasChanges.value && $props.observeFormChanges) quasar.dialog({ component: VnConfirm, componentProps: { @@ -156,9 +156,12 @@ const startFormWatcher = () => { async function fetch() { try { - const { data } = await axios.get($props.url, { + let { data } = await axios.get($props.url, { params: { filter: JSON.stringify($props.filter) }, }); + + if (Array.isArray(data)) data = data[0] ?? {}; + state.set($props.model, data); originalData.value = data && JSON.parse(JSON.stringify(data)); diff --git a/src/components/FormModelPopup.vue b/src/components/FormModelPopup.vue index 74abd2726..25213a8b7 100644 --- a/src/components/FormModelPopup.vue +++ b/src/components/FormModelPopup.vue @@ -6,7 +6,7 @@ import FormModel from 'components/FormModel.vue'; const emit = defineEmits(['onDataSaved']); -const $props = defineProps({ +defineProps({ title: { type: String, default: '', @@ -76,14 +76,6 @@ defineExpose({

{{ subtitle }}

- +import { computed, ref } from 'vue'; +import { useI18n } from 'vue-i18n'; + +import VnInput from 'components/common/VnInput.vue'; +import FetchData from 'components/FetchData.vue'; +import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue'; +import VnSelect from 'components/common/VnSelect.vue'; +import VnFilterPanelChip from 'components/ui/VnFilterPanelChip.vue'; + +import axios from 'axios'; + +const { t } = useI18n(); +const props = defineProps({ + dataKey: { + type: String, + required: true, + }, + customTags: { + type: Array, + default: () => [], + }, + exprBuilder: { + type: Function, + default: null, + }, +}); + +const itemCategories = ref([]); +const selectedCategoryFk = ref(null); +const selectedTypeFk = ref(null); +const itemTypesOptions = ref([]); +const suppliersOptions = ref([]); +const tagOptions = ref([]); +const tagValues = ref([]); + +const categoryList = computed(() => { + return (itemCategories.value || []) + .filter((category) => category.display) + .map((category) => ({ + ...category, + icon: `vn:${(category.icon || '').split('-')[1]}`, + })); +}); + +const selectedCategory = computed(() => + (itemCategories.value || []).find( + (category) => category?.id === selectedCategoryFk.value + ) +); + +const selectedType = computed(() => { + return (itemTypesOptions.value || []).find( + (type) => type?.id === selectedTypeFk.value + ); +}); + +const selectCategory = async (params, categoryId, search) => { + if (params.categoryFk === categoryId) { + resetCategory(params); + search(); + return; + } + selectedCategoryFk.value = categoryId; + params.categoryFk = categoryId; + await fetchItemTypes(categoryId); + search(); +}; + +const resetCategory = (params) => { + selectedCategoryFk.value = null; + itemTypesOptions.value = null; + if (params) { + params.categoryFk = null; + params.typeFk = null; + } +}; + +const applyTags = (params, search) => { + params.tags = tagValues.value + .filter((tag) => tag.selectedTag && tag.value) + .map((tag) => ({ + tagFk: tag.selectedTag.id, + tagName: tag.selectedTag.name, + value: tag.value, + })); + search(); +}; + +const fetchItemTypes = async (id) => { + try { + const filter = { + fields: ['id', 'name', 'categoryFk'], + where: { categoryFk: id }, + include: 'category', + order: 'name ASC', + }; + const { data } = await axios.get('ItemTypes', { + params: { filter: JSON.stringify(filter) }, + }); + itemTypesOptions.value = data; + } catch (err) { + console.error('Error fetching item types', err); + } +}; + +const getCategoryClass = (category, params) => { + if (category.id === params?.categoryFk) { + return 'active'; + } +}; + +const getSelectedTagValues = async (tag) => { + try { + tag.value = null; + const filter = { + fields: ['value'], + order: 'value ASC', + limit: 30, + }; + + const params = { filter: JSON.stringify(filter) }; + const { data } = await axios.get(`Tags/${tag.selectedTag.id}/filterValue`, { + params, + }); + tag.valueOptions = data; + } catch (err) { + console.error('Error getting selected tag values'); + } +}; + +const removeTag = (index, params, search) => { + (tagValues.value || []).splice(index, 1); + applyTags(params, search); +}; + + + + + + + +en: + params: + supplier: Supplier + from: From + to: To + active: Is active + visible: Is visible + floramondo: Is floramondo + salesPersonFk: Buyer + categoryFk: Category + +es: + params: + supplier: Proveedor + from: Desde + to: Hasta + active: Activo + visible: Visible + floramondo: Floramondo + salesPersonFk: Comprador + categoryFk: Categoría + diff --git a/src/components/RegularizeStockForm.vue b/src/components/RegularizeStockForm.vue index 28236be17..4f97033b3 100644 --- a/src/components/RegularizeStockForm.vue +++ b/src/components/RegularizeStockForm.vue @@ -2,7 +2,7 @@ import { reactive, ref } from 'vue'; import { useI18n } from 'vue-i18n'; -import VnSelectFilter from 'src/components/common/VnSelectFilter.vue'; +import VnSelect from 'src/components/common/VnSelect.vue'; import FetchData from 'components/FetchData.vue'; import VnRow from 'components/ui/VnRow.vue'; import FormModelPopup from './FormModelPopup.vue'; @@ -50,16 +50,15 @@ const onDataSaved = (data) => { >