diff --git a/src/components/ui/NewVnSearchBar.vue b/src/components/ui/NewVnSearchBar.vue
new file mode 100644
index 00000000..33d51176
--- /dev/null
+++ b/src/components/ui/NewVnSearchBar.vue
@@ -0,0 +1,119 @@
+
+
+
+
+
+
+
+
+
+
+
+en-US:
+ search: Search
+es-ES:
+ search: Buscar
+ca-ES:
+ search: Cercar
+fr-FR:
+ search: Rechercher
+pt-PT:
+ search: Pesquisar
+
diff --git a/src/composables/serviceUtils.js b/src/composables/serviceUtils.js
new file mode 100644
index 00000000..ce124398
--- /dev/null
+++ b/src/composables/serviceUtils.js
@@ -0,0 +1,116 @@
+import { api } from '@/boot/axios';
+
+function buildFilter(params, builderFunc) {
+ let and = [];
+
+ for (let param in params) {
+ let value = params[param];
+ if (value == null) continue;
+ let expr = builderFunc(param, value);
+ if (expr) and.push(expr);
+ }
+ return simplifyOperation(and, 'and');
+}
+
+const simplifyOperation = (operation, operator) => {
+ switch (operation.length) {
+ case 0:
+ return undefined;
+ case 1:
+ return operation[0];
+ default:
+ return { [operator]: operation };
+ }
+};
+
+async function fetch({
+ url,
+ append = false,
+ params,
+ exprBuilder,
+ mapKey,
+ existingData = [],
+ existingMap = new Map(),
+ oneRecord = false
+}) {
+ if (!url) return;
+
+ let exprFilter;
+ if (exprBuilder) {
+ exprFilter = buildFilter(params, (param, value) => {
+ if (param === 'filter') return;
+ const res = exprBuilder(param, value);
+ if (res) delete params[param];
+ return res;
+ });
+ }
+
+ if (params.filter?.where || exprFilter) {
+ params.filter.where = { ...params.filter.where, ...exprFilter };
+ }
+
+ if (!params?.filter?.order?.length) {
+ delete params?.filter?.order;
+ }
+
+ params.filter = JSON.stringify(params.filter);
+
+ const response = await api.get(url, { params });
+ const processedData = processData(response.data, {
+ mapKey,
+ map: !!mapKey,
+ append,
+ oneRecord,
+ existingData,
+ existingMap
+ });
+
+ return { response, data: processedData.data, map: processedData.map };
+}
+
+function processData(data, options) {
+ const {
+ mapKey,
+ map = true,
+ append = true,
+ oneRecord = false,
+ existingData = [],
+ existingMap = new Map()
+ } = options;
+ let resultData = [...existingData];
+ let resultMap = new Map(existingMap);
+
+ if (oneRecord) {
+ return Array.isArray(data) ? data[0] : data;
+ }
+
+ if (!append) {
+ resultData = [];
+ resultMap = new Map();
+ }
+
+ if (!Array.isArray(data)) {
+ resultData = data;
+ } else if (!map && append) {
+ resultData.push(...data);
+ } else {
+ for (const row of data) {
+ const key = row[mapKey];
+ const val = { ...row, key };
+ if (key && resultMap.has(key)) {
+ const { position } = resultMap.get(key);
+ val.position = position;
+ resultMap.set(key, val);
+ resultData[position] = val;
+ } else {
+ val.position = resultMap.size;
+ resultMap.set(key, val);
+ resultData.push(val);
+ }
+ }
+ }
+
+ return { data: resultData, map: resultMap };
+}
+
+export { buildFilter, fetch, processData };
diff --git a/src/pages/Admin/ItemsView.vue b/src/pages/Admin/ItemsView.vue
index 03f7d8a8..8b464f36 100644
--- a/src/pages/Admin/ItemsView.vue
+++ b/src/pages/Admin/ItemsView.vue
@@ -3,28 +3,47 @@ import { ref } from 'vue';
import CardList from 'src/components/ui/CardList.vue';
import VnImg from 'src/components/ui/VnImg.vue';
-import VnSearchBar from 'src/components/ui/VnSearchBar.vue';
import VnList from 'src/components/ui/VnList.vue';
+import VnSearchBar from 'src/components/ui/NewVnSearchBar.vue';
import { useAppStore } from 'stores/app';
import { storeToRefs } from 'pinia';
const appStore = useAppStore();
const { isHeaderMounted } = storeToRefs(appStore);
-
const loading = ref(false);
const items = ref([]);
-
-const query = `SELECT i.id, i.longName, i.size, i.category,
- i.value5, i.value6, i.value7,
- i.image, im.updated
- FROM vn.item i
- LEFT JOIN image im
- ON im.collectionFk = 'catalog'
- AND im.name = i.image
- WHERE (i.longName LIKE CONCAT('%', #search, '%')
- OR i.id = #search) AND i.isActive
- ORDER BY i.longName LIMIT 50`;
+const itemFilterProps = {
+ fields: ['id', 'name', 'longName', 'description', 'isActive'], // Incluye explícitamente 'longName'
+ include: [
+ {
+ relation: 'itemType',
+ scope: {
+ fields: ['id', 'name']
+ }
+ },
+ {
+ relation: 'intrastat',
+ scope: {
+ fields: ['id', 'description']
+ }
+ },
+ {
+ relation: 'origin',
+ scope: {
+ fields: ['id', 'name']
+ }
+ },
+ {
+ relation: 'production',
+ scope: {
+ fields: ['id', 'name']
+ }
+ }
+ ],
+ isActive: true,
+ order: 'name ASC'
+};
const onSearch = data => (items.value = data || []);
@@ -32,9 +51,10 @@ const onSearch = data => (items.value = data || []);
@@ -68,7 +88,7 @@ const onSearch = data => (items.value = data || []);
- {{ item.longName }}
+ {{ item.name }}
{{ item.value5 }} {{ item.value6 }}