diff --git a/src/components/ui/NewVnSearchBar.vue b/src/components/ui/NewVnSearchBar.vue
new file mode 100644
index 00000000..d4abcec7
--- /dev/null
+++ b/src/components/ui/NewVnSearchBar.vue
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+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/UsersView.vue b/src/pages/Admin/UsersView.vue
index 33de8f70..c72167f2 100644
--- a/src/pages/Admin/UsersView.vue
+++ b/src/pages/Admin/UsersView.vue
@@ -4,7 +4,7 @@ import { useI18n } from 'vue-i18n';
import { useRouter } from 'vue-router';
import CardList from 'src/components/ui/CardList.vue';
-import VnSearchBar from 'src/components/ui/VnSearchBar.vue';
+import VnSearchBar from 'src/components/ui/NewVnSearchBar.vue';
import VnList from 'src/components/ui/VnList.vue';
import { useAppStore } from 'stores/app';
@@ -16,16 +16,11 @@ const router = useRouter();
const userStore = useUserStore();
const appStore = useAppStore();
const { isHeaderMounted } = storeToRefs(appStore);
-
const loading = ref(false);
const users = ref([]);
-
-const query = `SELECT u.id, u.name, u.nickname, u.active
- FROM account.user u
- WHERE u.name LIKE CONCAT('%', #user, '%')
- OR u.nickname LIKE CONCAT('%', #user, '%')
- OR u.id = #user
- ORDER BY u.name LIMIT 200`;
+const filter = {
+ fields: ['id', 'name', 'nickname', 'active']
+};
const onSearch = data => (users.value = data || []);
@@ -38,15 +33,35 @@ const supplantUser = async user => {
console.error('Error supplanting user:', error);
}
};
+
+const usersExprBuilder = (param, value) => {
+ switch (param) {
+ case 'search':
+ return /^\d+$/.test(value)
+ ? { id: value }
+ : {
+ or: [
+ { name: { like: `%${value}%` } },
+ { nickname: { like: `%${value}%` } }
+ ]
+ };
+ case 'name':
+ case 'nickname':
+ return { [param]: { like: `%${value}%` } };
+ case 'roleFk':
+ return { [param]: value };
+ }
+};