- {{ t(`You didn't enter any filter`) }}
+
+ {{ t(`No filters applied`) }}
es:
- You didn't enter any filter: No has introducido ningún filtro
+ No filters applied: No se han aplicado filtros
Applied filters: Filtros aplicados
Remove filters: Eliminar filtros
Refresh: Refrescar
diff --git a/src/components/ui/VnSearchbar.vue b/src/components/ui/VnSearchbar.vue
index 7585f09b3..47a7fc24c 100644
--- a/src/components/ui/VnSearchbar.vue
+++ b/src/components/ui/VnSearchbar.vue
@@ -51,14 +51,7 @@ const props = defineProps({
const router = useRouter();
const route = useRoute();
-const arrayData = useArrayData(props.dataKey, {
- url: props.url,
- filter: props.filter,
- where: props.where,
- limit: props.limit,
- order: props.order,
- userParams: props.userParams,
-});
+const arrayData = useArrayData(props.dataKey, { ...props });
const store = arrayData.store;
const searchText = ref('');
diff --git a/src/composables/useArrayData.js b/src/composables/useArrayData.js
index 01f8ca294..c7808f9a8 100644
--- a/src/composables/useArrayData.js
+++ b/src/composables/useArrayData.js
@@ -30,9 +30,20 @@ export function useArrayData(key, userOptions) {
});
function setOptions() {
+ const allowedOptions = [
+ 'url',
+ 'filter',
+ 'where',
+ 'order',
+ 'limit',
+ 'skip',
+ 'userParams',
+ 'userFilter'
+ ];
if (typeof userOptions === 'object') {
for (const option in userOptions) {
- if (userOptions[option] == null) continue;
+ const isEmpty = userOptions[option] == null || userOptions[option] == ''
+ if (isEmpty || !allowedOptions.includes(option)) continue;
if (Object.prototype.hasOwnProperty.call(store, option)) {
store[option] = userOptions[option];
@@ -62,6 +73,7 @@ export function useArrayData(key, userOptions) {
Object.assign(params, store.userParams);
+ store.isLoading = true
const response = await axios.get(store.url, {
signal: canceller.signal,
params,
@@ -82,6 +94,8 @@ export function useArrayData(key, userOptions) {
updateStateParams();
}
+ store.isLoading = false
+
canceller = null;
}
@@ -139,7 +153,8 @@ export function useArrayData(key, userOptions) {
});
}
- const totalRows = computed(() => store.data && store.data.length | 0);
+ const totalRows = computed(() => store.data && store.data.length || 0);
+ const isLoading = computed(() => store.isLoading || false)
return {
fetch,
@@ -152,5 +167,6 @@ export function useArrayData(key, userOptions) {
hasMoreData,
totalRows,
updateStateParams,
+ isLoading
};
}
diff --git a/src/i18n/en/index.js b/src/i18n/en/index.js
index be4603ea8..078ad3815 100644
--- a/src/i18n/en/index.js
+++ b/src/i18n/en/index.js
@@ -60,6 +60,7 @@ export default {
pageTitles: {
customers: 'Customers',
list: 'List',
+ webPayments: 'Web Payments',
createCustomer: 'Create customer',
summary: 'Summary',
basicData: 'Basic Data',
diff --git a/src/i18n/es/index.js b/src/i18n/es/index.js
index b3336ca7a..5a069fba8 100644
--- a/src/i18n/es/index.js
+++ b/src/i18n/es/index.js
@@ -60,9 +60,10 @@ export default {
pageTitles: {
customers: 'Clientes',
list: 'Listado',
+ webPayments: 'Pagos Web',
createCustomer: 'Crear cliente',
- summary: 'Resumen',
basicData: 'Datos básicos',
+ summary: 'Resumen'
},
list: {
phone: 'Teléfono',
diff --git a/src/pages/Customer/CustomerPayments.vue b/src/pages/Customer/CustomerPayments.vue
new file mode 100644
index 000000000..c1853ac20
--- /dev/null
+++ b/src/pages/Customer/CustomerPayments.vue
@@ -0,0 +1,294 @@
+
+
+
+
+
+
+
+
+ {{ t('globals.collapseMenu') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('Web Payments') }}
+
+
+ {{ t('Change view') }}
+
+
+
+
+
+
+
+
+ {{ t('Confirm transaction') }}
+
+
+
+
+
+
+ {{ row.clientFk }}
+
+
+
+
+
+
+
+ {{
+ row.isConfirmed
+ ? t('Confirmed')
+ : t('Unconfirmed')
+ }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ col.label }}
+
+
+
+ {{ col.value }}
+
+
+
+ {{ col.value }}
+
+
+
+
+
+
+
+
+
+
+
+ {{
+ t('Confirm transaction')
+ }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+es:
+ Web Payments: Pagos Web
+ Confirm transaction: Confirmar transacción
+ Transaction ID: ID transacción
+ Customer ID: ID cliente
+ Customer Name: Nombre cliente
+ State: Estado
+ Dated: Fecha
+ Amount: Importe
+ Actions: Acciones
+ Confirmed: Confirmada
+ Unconfirmed: Sin confirmar
+ Change view: Cambiar vista
+ Payment confirmed: Pago confirmado
+
diff --git a/src/pages/Customer/CustomerPaymentsFilter.vue b/src/pages/Customer/CustomerPaymentsFilter.vue
new file mode 100644
index 000000000..1d26b2d6a
--- /dev/null
+++ b/src/pages/Customer/CustomerPaymentsFilter.vue
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+ {{ t(`params.${tag.label}`) }}:
+ {{ formatFn(tag.value) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+en:
+ params:
+ orderFk: Order
+ clientFk: Customer
+ amount: Amount
+es:
+ params:
+ orderFk: Pedido
+ clientFk: Cliente
+ amount: Importe
+ Order ID: ID pedido
+ Customer ID: ID cliente
+ Amount: Importe
+
diff --git a/src/router/modules/customer.js b/src/router/modules/customer.js
index 7b48413f2..c7e978eec 100644
--- a/src/router/modules/customer.js
+++ b/src/router/modules/customer.js
@@ -10,7 +10,7 @@ export default {
component: RouterView,
redirect: { name: 'CustomerMain' },
menus: {
- main: ['CustomerList', 'CustomerCreate'],
+ main: ['CustomerList', 'CustomerPayments', 'CustomerCreate'],
card: ['CustomerBasicData'],
},
children: [
@@ -29,6 +29,15 @@ export default {
},
component: () => import('src/pages/Customer/CustomerList.vue')
},
+ {
+ path: 'payments',
+ name: 'CustomerPayments',
+ meta: {
+ title: 'webPayments',
+ icon: 'vn:onlinepayment',
+ },
+ component: () => import('src/pages/Customer/CustomerPayments.vue')
+ },
{
path: 'create',
name: 'CustomerCreate',
diff --git a/src/stores/useArrayDataStore.js b/src/stores/useArrayDataStore.js
index 9d904d757..f9a32a6fa 100644
--- a/src/stores/useArrayDataStore.js
+++ b/src/stores/useArrayDataStore.js
@@ -18,6 +18,7 @@ export const useArrayDataStore = defineStore('arrayDataStore', () => {
skip: 0,
order: '',
data: ref(),
+ isLoading: false
};
}
diff --git a/test/vitest/__tests__/pages/Customer/CustomerPayments.spec.js b/test/vitest/__tests__/pages/Customer/CustomerPayments.spec.js
new file mode 100644
index 000000000..b56b29c20
--- /dev/null
+++ b/test/vitest/__tests__/pages/Customer/CustomerPayments.spec.js
@@ -0,0 +1,54 @@
+import { vi, describe, expect, it, beforeAll, afterEach } from 'vitest';
+import { createWrapper, axios } from 'app/test/vitest/helper';
+import CustomerPayments from 'pages/Customer/CustomerPayments.vue';
+
+describe('CustomerPayments', () => {
+ let vm;
+
+
+ beforeAll(() => {
+ vm = createWrapper(CustomerPayments, {
+ global: {
+ stubs: ['Paginate'],
+ mocks: {
+ fetch: vi.fn(),
+ },
+ }
+ }).vm;
+ });
+
+ afterEach(() => {
+ vi.clearAllMocks();
+ });
+
+ describe('confirmTransaction()', () => {
+ it('should make a POST request and then call to quasar notify method', async () => {
+ vi.spyOn(axios, 'post').mockResolvedValue({ data: true });
+ vi.spyOn(vm.quasar, 'notify');
+
+ await vm.confirmTransaction({ id: 1 });
+
+
+ expect(vm.quasar.notify).toHaveBeenCalledWith(
+ expect.objectContaining({
+ message: 'Payment confirmed',
+ type: 'positive'
+ })
+ );
+ });
+ });
+
+ describe('stateColor()', () => {
+ it('should return "positive" when isConfirmed property is truthy', async () => {
+ const result = await vm.stateColor({ isConfirmed: true });
+
+ expect(result).toEqual('positive');
+ });
+
+ it('should return "primary" when isConfirmed property is falsy', async () => {
+ const result = await vm.stateColor({ isConfirmed: false });
+
+ expect(result).toEqual('primary');
+ });
+ });
+});