From 248e02f53008e6ad58dff144bbf81e7329caabc0 Mon Sep 17 00:00:00 2001 From: wbuezas <wbuezas@verdnatura.es> Date: Mon, 5 Feb 2024 08:25:35 -0300 Subject: [PATCH 01/42] WIP --- src/i18n/en/index.js | 1 + src/i18n/es/index.js | 1 + .../InvoiceOut/Card/InvoiceOutSummary.vue | 43 +++--- src/pages/InvoiceOut/InvoiceOutList.vue | 68 +++------- .../InvoiceOut/InvoiceOutNegativeBases.vue | 123 +++--------------- 5 files changed, 67 insertions(+), 169 deletions(-) diff --git a/src/i18n/en/index.js b/src/i18n/en/index.js index baaf414d6..9585bf7fb 100644 --- a/src/i18n/en/index.js +++ b/src/i18n/en/index.js @@ -531,6 +531,7 @@ export default { company: 'Company', dued: 'Due date', shortDued: 'Due date', + amount: 'Amount', }, card: { issued: 'Issued', diff --git a/src/i18n/es/index.js b/src/i18n/es/index.js index 0ea506b55..30e982ea2 100644 --- a/src/i18n/es/index.js +++ b/src/i18n/es/index.js @@ -531,6 +531,7 @@ export default { company: 'Empresa', dued: 'Fecha vencimineto', shortDued: 'F. vencimiento', + amount: 'Importe', }, card: { issued: 'Fecha emisión', diff --git a/src/pages/InvoiceOut/Card/InvoiceOutSummary.vue b/src/pages/InvoiceOut/Card/InvoiceOutSummary.vue index 5a56a3957..afdc4ea7d 100644 --- a/src/pages/InvoiceOut/Card/InvoiceOutSummary.vue +++ b/src/pages/InvoiceOut/Card/InvoiceOutSummary.vue @@ -2,11 +2,15 @@ import { onMounted, ref, computed } from 'vue'; import { useRoute } from 'vue-router'; import { useI18n } from 'vue-i18n'; -import axios from 'axios'; -import { toCurrency, toDate } from 'src/filters'; + import CardSummary from 'components/ui/CardSummary.vue'; import VnLv from 'src/components/ui/VnLv.vue'; +import TicketDescriptorProxy from 'src/pages/Ticket/Card/TicketDescriptorProxy.vue'; +import CustomerDescriptorProxy from 'src/pages/Customer/Card/CustomerDescriptorProxy.vue'; + import { getUrl } from 'src/composables/getUrl'; +import { toCurrency, toDate } from 'src/filters'; +import axios from 'axios'; onMounted(async () => { fetch(); @@ -66,30 +70,34 @@ const taxColumns = ref([ const ticketsColumns = ref([ { - name: 'item', - label: 'invoiceOut.summary.ticketId', + name: 'id', + label: t('invoiceOut.summary.ticketId'), field: (row) => row.id, sortable: true, + align: 'left', }, { - name: 'quantity', - label: 'invoiceOut.summary.nickname', + name: 'alias', + label: t('invoiceOut.summary.nickname'), field: (row) => row.nickname, sortable: true, + align: 'left', }, { name: 'landed', - label: 'invoiceOut.summary.shipped', + label: t('invoiceOut.summary.shipped'), field: (row) => row.shipped, format: (value) => toDate(value), sortable: true, + align: 'left', }, { name: 'landed', - label: 'invoiceOut.summary.totalWithVat', + label: t('invoiceOut.summary.totalWithVat'), field: (row) => row.totalWithVat, format: (value) => toCurrency(value), sortable: true, + align: 'left', }, ]); </script> @@ -139,17 +147,22 @@ const ticketsColumns = ref([ </template> </QTable> </QCard> - <QCard class="vn-three"> + <QCard class="vn-max"> <div class="header"> {{ t('invoiceOut.summary.tickets') }} </div> <QTable v-if="tickets" :columns="ticketsColumns" :rows="tickets" flat> - <template #header="props"> - <QTr :props="props"> - <QTh v-for="col in props.cols" :key="col.name" :props="props"> - {{ t(col.label) }} - </QTh> - </QTr> + <template #body-cell-id="{ row }"> + <QTd> + <QBtn flat dense color="blue"> {{ row.id }}</QBtn> + <TicketDescriptorProxy :id="row.id" /> + </QTd> + </template> + <template #body-cell-alias="{ row }"> + <QTd> + <QBtn flat dense color="blue"> {{ row.nickname }}</QBtn> + <CustomerDescriptorProxy :id="row.clientFk" /> + </QTd> </template> </QTable> </QCard> diff --git a/src/pages/InvoiceOut/InvoiceOutList.vue b/src/pages/InvoiceOut/InvoiceOutList.vue index 8d3583da3..00e008af5 100644 --- a/src/pages/InvoiceOut/InvoiceOutList.vue +++ b/src/pages/InvoiceOut/InvoiceOutList.vue @@ -1,17 +1,20 @@ <script setup> -import { onMounted, onUnmounted, ref, watch } from 'vue'; +import { onMounted, onUnmounted, ref } from 'vue'; import { useI18n } from 'vue-i18n'; import { useRouter } from 'vue-router'; import { exportFile, useQuasar } from 'quasar'; -import { useStateStore } from 'stores/useStateStore'; + import VnPaginate from 'src/components/ui/VnPaginate.vue'; import InvoiceOutSummaryDialog from './Card/InvoiceOutSummaryDialog.vue'; -import { toDate, toCurrency } from 'src/filters/index'; import VnSearchbar from 'src/components/ui/VnSearchbar.vue'; -import InvoiceOutFilter from './InvoiceOutFilter.vue'; import VnLv from 'src/components/ui/VnLv.vue'; import CardList from 'src/components/ui/CardList.vue'; import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue'; +import CustomerDescriptorProxy from '../Customer/Card/CustomerDescriptorProxy.vue'; + +import InvoiceOutFilter from './InvoiceOutFilter.vue'; +import { toDate, toCurrency } from 'src/filters/index'; +import { useStateStore } from 'stores/useStateStore'; const { t } = useI18n(); const selectedCards = ref(new Map()); @@ -139,39 +142,7 @@ const downloadCsv = () => { :disable="selectedCards.size === 0" :label="t('globals.download')" /> - <!-- <QBtnDropdown - class="q-mr-xl" - color="primary" - :disable="!manageCheckboxes && arrayElements.length < 1" - :label="t('globals.download')" - v-else - > - <QList> - <QItem clickable v-close-popup @click="downloadCsv(rows)"> - <QItemSection> - <QItemLabel> - {{ - t('globals.allRows', { - numberRows: rows.length, - }) - }} - </QItemLabel> - </QItemSection> - </QItem> - <QItem clickable v-close-popup @click="downloadCsv(rows)"> - <QItemSection> - <QItemLabel> - {{ - t('globals.selectRows', { - numberRows: rows.length, - }) - }} - </QItemLabel> - </QItemSection> - </QItem> - </QList> - </QBtnDropdown> --> <QCheckbox left-label :label="t('globals.markAll')" @@ -196,18 +167,24 @@ const downloadCsv = () => { > <template #list-items> <VnLv - :label="t('invoiceOut.list.shortIssued')" - :title-label="t('invoiceOut.list.issued')" + :label="t('invoiceOut.list.amount')" :value="toDate(row.issued)" /> <VnLv :label="t('invoiceOut.list.amount')" :value="toCurrency(row.amount)" /> - <VnLv - :label="t('invoiceOut.list.client')" - :value="row.clientSocialName" - /> + + <VnLv :label="t('invoiceOut.list.client')"> + <template #value> + <span class="link" @click.stop> + {{ row?.clientSocialName }} + <CustomerDescriptorProxy + :id="row?.clientFk" + /> + </span> + </template> + </VnLv> <VnLv :label="t('invoiceOut.list.shortCreated')" :title-label="t('invoiceOut.list.created')" @@ -224,13 +201,6 @@ const downloadCsv = () => { /> </template> <template #actions> - <QBtn - :label="t('components.smartCard.openCard')" - @click.stop="navigate(row.id)" - class="bg-vn-dark" - outline - type="reset" - /> <QBtn :label="t('components.smartCard.openSummary')" @click.stop="viewSummary(row.id)" diff --git a/src/pages/InvoiceOut/InvoiceOutNegativeBases.vue b/src/pages/InvoiceOut/InvoiceOutNegativeBases.vue index c832d577c..8b7da4b9b 100644 --- a/src/pages/InvoiceOut/InvoiceOutNegativeBases.vue +++ b/src/pages/InvoiceOut/InvoiceOutNegativeBases.vue @@ -1,17 +1,17 @@ <script setup> import { ref, computed, onBeforeMount } from 'vue'; import { useI18n } from 'vue-i18n'; -import { QCheckbox, QBtn } from 'quasar'; import CustomerDescriptorProxy from 'src/pages/Customer/Card/CustomerDescriptorProxy.vue'; import InvoiceOutNegativeFilter from './InvoiceOutNegativeBasesFilter.vue'; import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue'; +import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue'; +import TicketDescriptorProxy from 'src/pages/Ticket/Card/TicketDescriptorProxy.vue'; import { toCurrency } from 'src/filters'; import { useInvoiceOutGlobalStore } from 'src/stores/invoiceOutGlobal.js'; import { useStateStore } from 'stores/useStateStore'; import { useArrayData } from 'composables/useArrayData'; -import VnUserLink from 'src/components/ui/VnUserLink.vue'; const invoiceOutGlobalStore = useInvoiceOutGlobalStore(); const stateStore = useStateStore(); @@ -47,76 +47,6 @@ onBeforeMount(async () => { const rows = computed(() => arrayData.value.store.data); -const selectedCustomerId = ref(0); -const selectedWorkerId = ref(0); - -const tableColumnComponents = { - company: { - component: 'span', - props: () => {}, - event: () => {}, - }, - country: { - component: 'span', - props: () => {}, - event: () => {}, - }, - clientId: { - component: QBtn, - props: () => ({ flat: true, color: 'blue' }), - event: (prop) => selectCustomerId(prop.value), - }, - client: { - component: 'span', - props: () => {}, - event: () => {}, - }, - amount: { - component: 'span', - props: () => {}, - event: () => {}, - }, - base: { - component: 'span', - props: () => {}, - event: () => {}, - }, - ticketId: { - component: 'span', - props: () => {}, - event: () => {}, - }, - active: { - component: QCheckbox, - props: (prop) => ({ - disable: true, - 'model-value': Boolean(prop.value), - }), - event: () => {}, - }, - hasToInvoice: { - component: QCheckbox, - props: (prop) => ({ - disable: true, - 'model-value': Boolean(prop.value), - }), - event: () => {}, - }, - verifiedData: { - component: QCheckbox, - props: (prop) => ({ - disable: true, - 'model-value': Boolean(prop.value), - }), - event: () => {}, - }, - comercial: { - component: QBtn, - props: () => ({ flat: true, color: 'blue' }), - event: (prop) => selectWorkerId(prop.row.comercialId), - }, -}; - const columns = computed(() => [ { label: t('invoiceOut.negativeBases.company'), @@ -205,14 +135,6 @@ const downloadCSV = async () => { params ); }; - -const selectCustomerId = (id) => { - selectedCustomerId.value = id; -}; - -const selectWorkerId = (id) => { - selectedWorkerId.value = id; -}; </script> <template> @@ -236,31 +158,22 @@ const selectWorkerId = (id) => { :pagination="{ rowsPerPage: 0 }" class="full-width q-mt-md" > - <template #body-cell="props"> - <QTd :props="props"> - <component - :is="tableColumnComponents[props.col.name].component" - class="col-content" - v-bind="tableColumnComponents[props.col.name].props(props)" - @click="tableColumnComponents[props.col.name].event(props)" - > - <template - v-if=" - props.col.name !== 'active' && - props.col.name !== 'hasToInvoice' && - props.col.name !== 'verifiedData' - " - >{{ props.value }} - </template> - <CustomerDescriptorProxy - v-if="props.col.name === 'clientId'" - :id="selectedCustomerId" - /> - <VnUserLink - v-if="props.col.name === 'comercial'" - :worker-id="selectedWorkerId" - /> - </component> + <template #body-cell-clientId="{ row }"> + <QTd> + <QBtn flat dense color="blue"> {{ row.clientId }}</QBtn> + <CustomerDescriptorProxy :id="row.clientId" /> + </QTd> + </template> + <template #body-cell-ticketId="{ row }"> + <QTd> + <QBtn flat dense color="blue"> {{ row.ticketFk }}</QBtn> + <TicketDescriptorProxy :id="row.ticketFk" /> + </QTd> + </template> + <template #body-cell-comercial="{ row }"> + <QTd> + <QBtn flat dense color="blue">{{ row.comercialName }}</QBtn> + <WorkerDescriptorProxy :id="row.comercialId" /> </QTd> </template> </QTable> From df620566ef36a875fd67ff4bb2b2a34fad244e5f Mon Sep 17 00:00:00 2001 From: wbuezas <wbuezas@verdnatura.es> Date: Mon, 12 Feb 2024 08:11:44 -0300 Subject: [PATCH 02/42] Invoice out globals corrections --- src/i18n/en/index.js | 2 +- src/i18n/es/index.js | 2 +- src/pages/InvoiceOut/InvoiceOutGlobalForm.vue | 17 ++--------- src/stores/invoiceOutGlobal.js | 30 ++++++++----------- 4 files changed, 18 insertions(+), 33 deletions(-) diff --git a/src/i18n/en/index.js b/src/i18n/en/index.js index 9585bf7fb..5d6b1f65b 100644 --- a/src/i18n/en/index.js +++ b/src/i18n/en/index.js @@ -565,7 +565,7 @@ export default { fillDates: 'Invoice date and the max date should be filled', invoiceDateLessThanMaxDate: 'Invoice date can not be less than max date', invoiceWithFutureDate: 'Exists an invoice with a future date', - noTicketsToInvoice: 'There are not clients to invoice', + noTicketsToInvoice: 'There are not tickets to invoice', criticalInvoiceError: 'Critical invoicing error, process stopped', }, table: { diff --git a/src/i18n/es/index.js b/src/i18n/es/index.js index 30e982ea2..5c60e840d 100644 --- a/src/i18n/es/index.js +++ b/src/i18n/es/index.js @@ -567,7 +567,7 @@ export default { invoiceDateLessThanMaxDate: 'La fecha de la factura no puede ser menor que la fecha máxima', invoiceWithFutureDate: 'Existe una factura con una fecha futura', - noTicketsToInvoice: 'No hay clientes para facturar', + noTicketsToInvoice: 'No existen tickets para facturar', criticalInvoiceError: 'Error crítico en la facturación, proceso detenido', }, table: { diff --git a/src/pages/InvoiceOut/InvoiceOutGlobalForm.vue b/src/pages/InvoiceOut/InvoiceOutGlobalForm.vue index c61b9f7ff..a000d6d4f 100644 --- a/src/pages/InvoiceOut/InvoiceOutGlobalForm.vue +++ b/src/pages/InvoiceOut/InvoiceOutGlobalForm.vue @@ -13,13 +13,8 @@ const { t } = useI18n(); const invoiceOutGlobalStore = useInvoiceOutGlobalStore(); // invoiceOutGlobalStore state and getters -const { - initialDataLoading, - formInitialData, - - invoicing, - status, -} = storeToRefs(invoiceOutGlobalStore); +const { initialDataLoading, formInitialData, invoicing, status } = + storeToRefs(invoiceOutGlobalStore); // invoiceOutGlobalStore actions const { makeInvoice, setStatusValue } = invoiceOutGlobalStore; @@ -32,13 +27,7 @@ const printersOptions = ref([]); const clientsOptions = ref([]); -const formData = ref({ - companyFk: null, - invoiceDate: null, - maxShipped: null, - clientId: null, - printer: null, -}); +const formData = ref({}); const optionsInitialData = computed(() => { return ( diff --git a/src/stores/invoiceOutGlobal.js b/src/stores/invoiceOutGlobal.js index 7151aac5f..9929a0127 100644 --- a/src/stores/invoiceOutGlobal.js +++ b/src/stores/invoiceOutGlobal.js @@ -73,6 +73,9 @@ export const useInvoiceOutGlobalStore = defineStore({ const stringDate = data.issued.substring(0, 10); this.minInvoicingDate = stringDate; this.formInitialData.invoiceDate = stringDate; + + this.minInvoicingDate = new Date(data.issued); + this.formInitialData.invoiceDate = this.minInvoicingDate; } catch (err) { console.error('Error fetching invoice out global initial data'); throw new Error(); @@ -103,12 +106,9 @@ export const useInvoiceOutGlobalStore = defineStore({ if (clientsToInvoice == 'all') params.clientId = undefined; - const addressesResponse = await await axios.post( - 'InvoiceOuts/clientsToInvoice', - params - ); + const { data } = await axios.post('InvoiceOuts/clientsToInvoice', params); - this.addresses = addressesResponse.data; + this.addresses = data; if (!this.addresses || !this.addresses.length > 0) { notify( @@ -118,9 +118,9 @@ export const useInvoiceOutGlobalStore = defineStore({ throw new Error("There aren't addresses to invoice"); } - this.addresses.forEach(async (address) => { + for (const address of this.addresses) { await this.invoiceClient(address, formData); - }); + } } catch (err) { this.handleError(err); } @@ -186,13 +186,10 @@ export const useInvoiceOutGlobalStore = defineStore({ this.status = 'invoicing'; this.invoicing = true; - const invoiceResponse = await axios.post( - 'InvoiceOuts/invoiceClient', - params - ); + const { data } = await axios.post('InvoiceOuts/invoiceClient', params); - if (invoiceResponse.data) { - this.makePdfAndNotify(invoiceResponse.data, address); + if (data) { + await this.makePdfAndNotify(data, address); } this.isInvoicing = false; @@ -203,7 +200,7 @@ export const useInvoiceOutGlobalStore = defineStore({ err.response.status >= 400 && err.response.status < 500 ) { - this.invoiceClientError(address, err.response); + this.invoiceClientError(address, err.response?.data?.error?.message); this.addressIndex++; return; } else { @@ -227,12 +224,11 @@ export const useInvoiceOutGlobalStore = defineStore({ this.nPdfs++; this.nRequests--; } catch (err) { - this.invoiceClientError(client, err, true); + this.invoiceClientError(client, err.response?.data?.error?.message, true); } }, - invoiceClientError(client, response, isWarning) { - const message = response.data?.error?.message || response.message; + invoiceClientError(client, message, isWarning) { this.errors.unshift({ client, message, isWarning }); }, From 8adee21f2beba0b1be5164fc6ff777117461b46e Mon Sep 17 00:00:00 2001 From: wbuezas <wbuezas@verdnatura.es> Date: Wed, 14 Feb 2024 08:05:06 -0300 Subject: [PATCH 03/42] WIP --- .../Card/InvoiceOutDescriptorMenu.vue | 69 +++++++++++++++---- .../InvoiceOut/Card/InvoiceOutSummary.vue | 4 +- 2 files changed, 59 insertions(+), 14 deletions(-) diff --git a/src/pages/InvoiceOut/Card/InvoiceOutDescriptorMenu.vue b/src/pages/InvoiceOut/Card/InvoiceOutDescriptorMenu.vue index ab8b6470b..94c05f772 100644 --- a/src/pages/InvoiceOut/Card/InvoiceOutDescriptorMenu.vue +++ b/src/pages/InvoiceOut/Card/InvoiceOutDescriptorMenu.vue @@ -6,35 +6,80 @@ const { t } = useI18n(); <template> <QItem v-ripple clickable> - <QItemSection>{{ t('Transfer invoice to') }}</QItemSection> + <QItemSection>{{ t('Transfer invoice to...') }}</QItemSection> </QItem> <QItem v-ripple clickable> - <QItemSection>{{ t('See invoice') }}</QItemSection> + <QItemSection>{{ t('Show invoice...') }}</QItemSection> + <QItemSection side> + <QIcon name="keyboard_arrow_right" /> + </QItemSection> + <QMenu anchor="top end" self="top start"> + <QList> + <QItem v-ripple clickable> + <QItemSection>{{ t('As PDF') }}</QItemSection> + </QItem> + <QItem v-ripple clickable> + <QItemSection>{{ t('As CSV') }}</QItemSection> + </QItem> + </QList> + </QMenu> </QItem> <QItem v-ripple clickable> - <QItemSection>{{ t('Send invoice') }}</QItemSection> + <QItemSection>{{ t('Send invoice...') }}</QItemSection> + <QItemSection side> + <QIcon name="keyboard_arrow_right" /> + </QItemSection> + <QMenu anchor="top end" self="top start"> + <QList> + <QItem v-ripple clickable> + <QItemSection>{{ t('Send PDF') }}</QItemSection> + </QItem> + <QItem v-ripple clickable> + <QItemSection>{{ t('Send CSV') }}</QItemSection> + </QItem> + </QList> + </QMenu> </QItem> <QItem v-ripple clickable> <QItemSection>{{ t('Delete invoice') }}</QItemSection> </QItem> <QItem v-ripple clickable> - <QItemSection>{{ t('Post invoice') }}</QItemSection> + <QItemSection>{{ t('Book invoice') }}</QItemSection> </QItem> <QItem v-ripple clickable> - <QItemSection>{{ t('Regenerate invoice PDF') }}</QItemSection> + <QItemSection>{{ t('Generate PDF invoice') }}</QItemSection> </QItem> <QItem v-ripple clickable> - <QItemSection>{{ t('Pass') }}</QItemSection> + <QItemSection>{{ t('Refund...') }}</QItemSection> + <QItemSection side> + <QIcon name="keyboard_arrow_right" /> + </QItemSection> + <QMenu anchor="top end" self="top start"> + <QList> + <QItem v-ripple clickable> + <QItemSection>{{ t('With warehouse') }}</QItemSection> + </QItem> + <QItem v-ripple clickable> + <QItemSection>{{ t('Without warehouse') }}</QItemSection> + </QItem> + </QList> + </QMenu> </QItem> </template> <i18n> es: - Transfer invoice to: Transferir factura a - See invoice: Ver factura - Send invoice: Enviar factura + Transfer invoice to...: Transferir factura a... + Show invoice...: Ver factura... + Send invoice...: Enviar factura... Delete invoice: Eliminar factura - Post invoice: Asentar factura - Regenerate invoice PDF: Regenerar PDF factura - Pass: Abono + Book invoice: Asentar factura + Generate PDF invoice: Generar PDF factura + Refund...: Abono + As PDF: como PDF + As CSV: como CSV + Send PDF: Enviar PDF + Send CSV: Enviar CSV + With warehouse: Con almacén + Without warehouse: Sin almacén </i18n> diff --git a/src/pages/InvoiceOut/Card/InvoiceOutSummary.vue b/src/pages/InvoiceOut/Card/InvoiceOutSummary.vue index afdc4ea7d..5721818e4 100644 --- a/src/pages/InvoiceOut/Card/InvoiceOutSummary.vue +++ b/src/pages/InvoiceOut/Card/InvoiceOutSummary.vue @@ -154,13 +154,13 @@ const ticketsColumns = ref([ <QTable v-if="tickets" :columns="ticketsColumns" :rows="tickets" flat> <template #body-cell-id="{ row }"> <QTd> - <QBtn flat dense color="blue"> {{ row.id }}</QBtn> + <QBtn flat color="primary"> {{ row.id }}</QBtn> <TicketDescriptorProxy :id="row.id" /> </QTd> </template> <template #body-cell-alias="{ row }"> <QTd> - <QBtn flat dense color="blue"> {{ row.nickname }}</QBtn> + <QBtn flat dense color="primary"> {{ row.nickname }}</QBtn> <CustomerDescriptorProxy :id="row.clientFk" /> </QTd> </template> From ac555a01468560efa8a08841aa51299d9ff4c4bb Mon Sep 17 00:00:00 2001 From: wbuezas <wbuezas@verdnatura.es> Date: Thu, 15 Feb 2024 11:36:53 -0300 Subject: [PATCH 04/42] Transfer invoice form --- src/components/TransferInvoiceForm.vue | 190 ++++++++++++++++++ .../InvoiceOut/Card/InvoiceOutDescriptor.vue | 11 +- .../Card/InvoiceOutDescriptorMenu.vue | 18 +- 3 files changed, 214 insertions(+), 5 deletions(-) create mode 100644 src/components/TransferInvoiceForm.vue diff --git a/src/components/TransferInvoiceForm.vue b/src/components/TransferInvoiceForm.vue new file mode 100644 index 000000000..e62c7638c --- /dev/null +++ b/src/components/TransferInvoiceForm.vue @@ -0,0 +1,190 @@ +<script setup> +import { ref, reactive } from 'vue'; +import { useI18n } from 'vue-i18n'; +import { useRouter } from 'vue-router'; + +import VnRow from 'components/ui/VnRow.vue'; +import FetchData from 'components/FetchData.vue'; +import VnSelectFilter from 'components/common/VnSelectFilter.vue'; +import axios from 'axios'; +import useNotify from 'src/composables/useNotify.js'; + +const $props = defineProps({ + invoiceOutData: { + type: Object, + default: () => {}, + }, +}); + +const { t } = useI18n(); +const router = useRouter(); +const { notify } = useNotify(); + +const transferInvoiceParams = reactive({ + id: $props.invoiceOutData?.id, + refFk: $props.invoiceOutData?.ref, +}); +const closeButton = ref(null); +const isLoading = ref(false); +const clientsOptions = ref([]); +const rectificativeTypeOptions = ref([]); +const siiTypeInvoiceOutsOptions = ref([]); +const invoiceCorrectionTypesOptions = ref([]); + +const closeForm = () => { + if (closeButton.value) closeButton.value.click(); +}; + +const transferInvoice = async () => { + try { + const { data } = await axios.post( + 'InvoiceOuts/transferInvoice', + transferInvoiceParams + ); + notify(t('Transferred invoice'), 'positive'); + closeForm(); + router.push('InvoiceOutSummary', { id: data.id }); + } catch (err) { + console.error('Error transfering invoice', err); + } +}; +</script> + +<template> + <FetchData + url="Clients" + @on-fetch="(data) => (clientsOptions = data)" + :filter="{ fields: ['id', 'name'], order: 'id', limit: 30 }" + auto-load + /> + <FetchData + url="CplusRectificationTypes" + :filter="{ order: 'description' }" + @on-fetch="(data) => (rectificativeTypeOptions = data)" + auto-load + /> + <FetchData + url="SiiTypeInvoiceOuts" + :filter="{ where: { code: { like: 'R%' } } }" + @on-fetch="(data) => (siiTypeInvoiceOutsOptions = data)" + auto-load + /> + <FetchData + url="InvoiceCorrectionTypes" + @on-fetch="(data) => (invoiceCorrectionTypesOptions = data)" + auto-load + /> + <QForm @submit="transferInvoice()" class="all-pointer-events"> + <QCard class="column" style="padding: 32px; z-index: 100"> + <span ref="closeButton" class="close-icon" v-close-popup> + <QIcon name="close" size="sm" /> + </span> + <h1 class="title">{{ t('Transfer invoice') }}</h1> + <VnRow class="row q-gutter-md q-mb-md"> + <div class="col"> + <VnSelectFilter + :label="t('Client')" + :options="clientsOptions" + hide-selected + option-label="name" + option-value="id" + v-model="transferInvoiceParams.newClientFk" + :required="true" + > + <template #option="scope"> + <QItem v-bind="scope.itemProps"> + <QItemSection> + <QItemLabel> + #{{ scope.opt?.id }} - + {{ scope.opt?.name }} + </QItemLabel> + </QItemSection> + </QItem> + </template> + </VnSelectFilter> + </div> + <div class="col"> + <VnSelectFilter + :label="t('Rectificative type')" + :options="rectificativeTypeOptions" + hide-selected + option-label="description" + option-value="id" + v-model="transferInvoiceParams.cplusRectificationTypeFk" + :required="true" + /> + </div> + </VnRow> + <VnRow class="row q-gutter-md q-mb-md"> + <div class="col"> + <VnSelectFilter + :label="t('Class')" + :options="siiTypeInvoiceOutsOptions" + hide-selected + option-label="description" + option-value="id" + v-model="transferInvoiceParams.siiTypeInvoiceOutFk" + :required="true" + > + <template #option="scope"> + <QItem v-bind="scope.itemProps"> + <QItemSection> + <QItemLabel> + {{ scope.opt?.code }} - + {{ scope.opt?.description }} + </QItemLabel> + </QItemSection> + </QItem> + </template> + </VnSelectFilter> + </div> + <div class="col"> + <VnSelectFilter + :label="t('Type')" + :options="invoiceCorrectionTypesOptions" + hide-selected + option-label="description" + option-value="id" + v-model="transferInvoiceParams.invoiceCorrectionTypeFk" + :required="true" + /> + </div> + </VnRow> + <div class="q-mt-lg row justify-end"> + <QBtn + :label="t('Transfer client')" + type="submit" + color="primary" + :disabled="isLoading" + :loading="isLoading" + /> + </div> + </QCard> + </QForm> +</template> + +<i18n> +es: + Transfer invoice: Transferir factura + Transfer client: Transferir cliente + Client: Cliente + Rectificative type: Tipo rectificativa + Class: Clase + Type: Tipo + Transferred invoice: Factura transferida +</i18n> + +<style lang="scss" scoped> +.title { + font-size: 17px; + font-weight: bold; + line-height: 20px; +} + +.close-icon { + position: absolute; + top: 20px; + right: 20px; + cursor: pointer; +} +</style> diff --git a/src/pages/InvoiceOut/Card/InvoiceOutDescriptor.vue b/src/pages/InvoiceOut/Card/InvoiceOutDescriptor.vue index 9c1bb3649..e01706e84 100644 --- a/src/pages/InvoiceOut/Card/InvoiceOutDescriptor.vue +++ b/src/pages/InvoiceOut/Card/InvoiceOutDescriptor.vue @@ -2,13 +2,15 @@ import { ref, computed } from 'vue'; import { useRoute } from 'vue-router'; import { useI18n } from 'vue-i18n'; -import { toCurrency, toDate } from 'src/filters'; + import CardDescriptor from 'components/ui/CardDescriptor.vue'; import CustomerDescriptorProxy from 'pages/Customer/Card/CustomerDescriptorProxy.vue'; import VnLv from 'src/components/ui/VnLv.vue'; -import useCardDescription from 'src/composables/useCardDescription'; import InvoiceOutDescriptorMenu from './InvoiceOutDescriptorMenu.vue'; +import useCardDescription from 'src/composables/useCardDescription'; +import { toCurrency, toDate } from 'src/filters'; + const $props = defineProps({ id: { type: Number, @@ -23,7 +25,6 @@ const { t } = useI18n(); const entityId = computed(() => { return $props.id || route.params.id; }); -const descriptor = ref(); const filter = { include: [ @@ -42,6 +43,8 @@ const filter = { ], }; +const descriptor = ref(); + function ticketFilter(invoice) { return JSON.stringify({ refFk: invoice.ref }); } @@ -61,7 +64,7 @@ const setData = (entity) => (data.value = useCardDescription(entity.ref, entity. data-key="invoiceOutData" > <template #menu="{ entity }"> - <InvoiceOutDescriptorMenu :invoice-out="entity" /> + <InvoiceOutDescriptorMenu :invoice-out-data="entity" /> </template> <template #body="{ entity }"> <VnLv :label="t('invoiceOut.card.issued')" :value="toDate(entity.issued)" /> diff --git a/src/pages/InvoiceOut/Card/InvoiceOutDescriptorMenu.vue b/src/pages/InvoiceOut/Card/InvoiceOutDescriptorMenu.vue index 94c05f772..a7e94951a 100644 --- a/src/pages/InvoiceOut/Card/InvoiceOutDescriptorMenu.vue +++ b/src/pages/InvoiceOut/Card/InvoiceOutDescriptorMenu.vue @@ -1,11 +1,23 @@ <script setup> +import { ref } from 'vue'; import { useI18n } from 'vue-i18n'; +import TransferInvoiceForm from 'src/components/TransferInvoiceForm.vue'; + +const $props = defineProps({ + invoiceOutData: { + type: Object, + default: () => {}, + }, +}); + const { t } = useI18n(); + +const transferInvoiceDialogRef = ref(); </script> <template> - <QItem v-ripple clickable> + <QItem v-ripple clickable @click="transferInvoiceDialogRef.show()"> <QItemSection>{{ t('Transfer invoice to...') }}</QItemSection> </QItem> <QItem v-ripple clickable> @@ -65,6 +77,10 @@ const { t } = useI18n(); </QList> </QMenu> </QItem> + + <QDialog ref="transferInvoiceDialogRef"> + <TransferInvoiceForm :invoice-out-data="invoiceOutData" /> + </QDialog> </template> <i18n> From af12512de9d2804f2176c8a68e04ddc11083b934 Mon Sep 17 00:00:00 2001 From: wbuezas <wbuezas@verdnatura.es> Date: Thu, 15 Feb 2024 18:10:54 -0300 Subject: [PATCH 05/42] WIP --- src/pages/InvoiceOut/Card/InvoiceOutDescriptorMenu.vue | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/pages/InvoiceOut/Card/InvoiceOutDescriptorMenu.vue b/src/pages/InvoiceOut/Card/InvoiceOutDescriptorMenu.vue index a7e94951a..3521ba0d7 100644 --- a/src/pages/InvoiceOut/Card/InvoiceOutDescriptorMenu.vue +++ b/src/pages/InvoiceOut/Card/InvoiceOutDescriptorMenu.vue @@ -14,6 +14,10 @@ const $props = defineProps({ const { t } = useI18n(); const transferInvoiceDialogRef = ref(); + +const showInvoicePdf = () => {}; + +const showInvoiceCsv = () => {}; </script> <template> @@ -27,10 +31,10 @@ const transferInvoiceDialogRef = ref(); </QItemSection> <QMenu anchor="top end" self="top start"> <QList> - <QItem v-ripple clickable> + <QItem v-ripple clickable @click="showInvoicePdf()"> <QItemSection>{{ t('As PDF') }}</QItemSection> </QItem> - <QItem v-ripple clickable> + <QItem v-ripple clickable @click="showInvoiceCsv()"> <QItemSection>{{ t('As CSV') }}</QItemSection> </QItem> </QList> From 41e5110a8a4bbf6b276e0ab16a4ec987834f0487 Mon Sep 17 00:00:00 2001 From: wbuezas <wbuezas@verdnatura.es> Date: Fri, 16 Feb 2024 08:10:47 -0300 Subject: [PATCH 06/42] Invoice out list and summary changes --- src/pages/InvoiceOut/InvoiceOutList.vue | 69 ++++++++++++------------- 1 file changed, 34 insertions(+), 35 deletions(-) diff --git a/src/pages/InvoiceOut/InvoiceOutList.vue b/src/pages/InvoiceOut/InvoiceOutList.vue index 7d19359d4..7bdf2ffbd 100644 --- a/src/pages/InvoiceOut/InvoiceOutList.vue +++ b/src/pages/InvoiceOut/InvoiceOutList.vue @@ -2,7 +2,6 @@ import { onMounted, onUnmounted, ref } from 'vue'; import { useI18n } from 'vue-i18n'; import { useRouter } from 'vue-router'; -import { exportFile, useQuasar } from 'quasar'; import VnPaginate from 'src/components/ui/VnPaginate.vue'; import InvoiceOutSummary from './Card/InvoiceOutSummary.vue'; @@ -16,12 +15,14 @@ import InvoiceOutFilter from './InvoiceOutFilter.vue'; import { toDate, toCurrency } from 'src/filters/index'; import { useStateStore } from 'stores/useStateStore'; import { useSummaryDialog } from 'src/composables/useSummaryDialog'; +import { useSession } from 'src/composables/useSession'; const { t } = useI18n(); const selectedCards = ref(new Map()); -const quasar = useQuasar(); const router = useRouter(); const stateStore = useStateStore(); +const session = useSession(); +const token = session.getToken(); const { viewSummary } = useSummaryDialog(); onMounted(() => (stateStore.rightDrawer = true)); @@ -55,35 +56,31 @@ const toggleAllCards = (cardsData) => { } }; -const downloadCsv = () => { - if (selectedCards.value.size === 0) return; - const selectedCardsArray = Array.from(selectedCards.value.values()); - let file; - for (var i = 0; i < selectedCardsArray.length; i++) { - if (i == 0) file += Object.keys(selectedCardsArray[i]).join(';') + '\n'; - file += - Object.keys(selectedCardsArray[i]) - .map(function (key) { - return selectedCardsArray[i][key]; - }) - .join(';') + '\n'; - } - const status = exportFile('file.csv', file, { - encoding: 'windows-1252', - mimeType: 'text/csv;charset=windows-1252;', - }); - if (status === true) { - quasar.notify({ - message: t('fileAllowed'), - color: 'positive', - icon: 'check', - }); - } else { - quasar.notify({ - message: t('fileDenied'), - color: 'negative', - icon: 'warning', - }); +const openPdf = () => { + try { + if (selectedCards.value.size === 0) return; + const selectedCardsArray = Array.from(selectedCards.value.values()); + + if (selectedCards.value.size === 1) { + const [invoiceOut] = selectedCardsArray; + const url = `api/InvoiceOuts/${invoiceOut.id}/download?access_token=${token}`; + window.open(url, '_blank'); + } else { + const invoiceOutIdsArray = selectedCardsArray.map( + (invoiceOut) => invoiceOut.id + ); + const invoiceOutIds = invoiceOutIdsArray.join(','); + + const params = new URLSearchParams({ + access_token: token, + ids: invoiceOutIds, + }); + + const url = `api/InvoiceOuts/downloadZip?${params}`; + window.open(url, '_blank'); + } + } catch (err) { + console.error('Error opening PDF'); } }; </script> @@ -129,13 +126,14 @@ const downloadCsv = () => { <VnSubToolbar class="bg-vn-dark justify-end"> <template #st-actions> <QBtn - @click="downloadCsv()" + @click="openPdf()" class="q-mr-xl" color="primary" :disable="selectedCards.size === 0" :label="t('globals.download')" - /> - + > + <QTooltip>{{ t('downloadPdf') }}</QTooltip> + </QBtn> <QCheckbox left-label :label="t('globals.markAll')" @@ -167,7 +165,6 @@ const downloadCsv = () => { :label="t('invoiceOut.list.amount')" :value="toCurrency(row.amount)" /> - <VnLv :label="t('invoiceOut.list.client')"> <template #value> <span class="link" @click.stop> @@ -216,9 +213,11 @@ en: fileDenied: Browser denied file download... fileAllowed: Successful download of CSV file youCanSearchByInvoiceReference: You can search by invoice reference + downloadPdf: Download PDF es: searchInvoice: Buscar factura emitida fileDenied: El navegador denegó la descarga de archivos... fileAllowed: Descarga exitosa de archivo CSV youCanSearchByInvoiceReference: Puedes buscar por referencia de la factura + downloadPdf: Download PDF </i18n> From 6ace34cbb15cdae23cd5ffa6b35ccb84effce71b Mon Sep 17 00:00:00 2001 From: wbuezas <wbuezas@verdnatura.es> Date: Mon, 19 Feb 2024 17:23:50 -0300 Subject: [PATCH 07/42] descriptor menu show invoice actions --- .../Card/InvoiceOutDescriptorMenu.vue | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/pages/InvoiceOut/Card/InvoiceOutDescriptorMenu.vue b/src/pages/InvoiceOut/Card/InvoiceOutDescriptorMenu.vue index 3521ba0d7..ca2bf1304 100644 --- a/src/pages/InvoiceOut/Card/InvoiceOutDescriptorMenu.vue +++ b/src/pages/InvoiceOut/Card/InvoiceOutDescriptorMenu.vue @@ -4,6 +4,9 @@ import { useI18n } from 'vue-i18n'; import TransferInvoiceForm from 'src/components/TransferInvoiceForm.vue'; +import { useSession } from 'src/composables/useSession'; +import { usePrintService } from 'composables/usePrintService'; + const $props = defineProps({ invoiceOutData: { type: Object, @@ -11,13 +14,23 @@ const $props = defineProps({ }, }); +const session = useSession(); +const token = session.getToken(); const { t } = useI18n(); +const { openReport } = usePrintService(); const transferInvoiceDialogRef = ref(); -const showInvoicePdf = () => {}; +const showInvoicePdf = () => { + const url = `api/InvoiceOuts/${$props.invoiceOutData.id}/download?access_token=${token}`; + window.open(url, '_blank'); +}; -const showInvoiceCsv = () => {}; +const showInvoiceCsv = () => { + openReport(`InvoiceOuts/${$props.invoiceOutData.ref}/invoice-csv`, { + recipientId: $props.invoiceOutData.client.id, + }); +}; </script> <template> From 587baa645e37cc98d9a655f500411b0f412e4b15 Mon Sep 17 00:00:00 2001 From: wbuezas <wbuezas@verdnatura.es> Date: Tue, 20 Feb 2024 08:47:24 -0300 Subject: [PATCH 08/42] generic FormPopup creation and SendInvoiceForm creation --- src/components/FormPopup.vue | 93 +++++++++++++++++++ .../Card/InvoiceOutDescriptorMenu.vue | 15 ++- src/pages/InvoiceOut/Card/SendInvoiceForm.vue | 41 ++++++++ 3 files changed, 147 insertions(+), 2 deletions(-) create mode 100644 src/components/FormPopup.vue create mode 100644 src/pages/InvoiceOut/Card/SendInvoiceForm.vue diff --git a/src/components/FormPopup.vue b/src/components/FormPopup.vue new file mode 100644 index 000000000..951d697d5 --- /dev/null +++ b/src/components/FormPopup.vue @@ -0,0 +1,93 @@ +<script setup> +import { ref } from 'vue'; +import { useI18n } from 'vue-i18n'; + +const emit = defineEmits(['onDataSaved']); + +const $props = defineProps({ + title: { + type: String, + default: '', + }, + subtitle: { + type: String, + default: '', + }, + defaultSaveButton: { + type: Boolean, + default: true, + }, + defaultCancelButton: { + type: Boolean, + default: true, + }, +}); + +const { t } = useI18n(); + +const closeButton = ref(null); +const isLoading = ref(false); + +const onDataSaved = (dataSaved) => { + emit('onDataSaved', dataSaved); + closeForm(); +}; + +const closeForm = () => { + if (closeButton.value) closeButton.value.click(); +}; +</script> + +<template> + <QForm + @submit="onDataSaved($event)" + class="all-pointer-events full-width" + style="max-width: 800px" + > + <QCard class="q-pa-lg"> + <span ref="closeButton" class="close-icon" v-close-popup> + <QIcon name="close" size="sm" /> + </span> + <h1 class="title">{{ title }}</h1> + <p>{{ subtitle }}</p> + <slot name="form-inputs" /> + <div class="q-mt-lg row justify-end"> + <QBtn + v-if="defaultSaveButton" + :label="t('globals.save')" + type="submit" + color="primary" + :disabled="isLoading" + :loading="isLoading" + /> + <QBtn + v-if="defaultCancelButton" + :label="t('globals.cancel')" + type="reset" + color="primary" + flat + class="q-ml-sm" + :disabled="isLoading" + :loading="isLoading" + v-close-popup + /> + <slot name="customButtons" /> + </div> + </QCard> + </QForm> +</template> + +<style lang="scss" scoped> +.title { + font-size: 17px; + font-weight: bold; + line-height: 20px; +} + +.close-icon { + position: absolute; + top: 20px; + right: 20px; + cursor: pointer; +} +</style> diff --git a/src/pages/InvoiceOut/Card/InvoiceOutDescriptorMenu.vue b/src/pages/InvoiceOut/Card/InvoiceOutDescriptorMenu.vue index ca2bf1304..76b9cefdc 100644 --- a/src/pages/InvoiceOut/Card/InvoiceOutDescriptorMenu.vue +++ b/src/pages/InvoiceOut/Card/InvoiceOutDescriptorMenu.vue @@ -3,6 +3,7 @@ import { ref } from 'vue'; import { useI18n } from 'vue-i18n'; import TransferInvoiceForm from 'src/components/TransferInvoiceForm.vue'; +import SendInvoiceForm from './SendInvoiceForm.vue'; import { useSession } from 'src/composables/useSession'; import { usePrintService } from 'composables/usePrintService'; @@ -20,6 +21,8 @@ const { t } = useI18n(); const { openReport } = usePrintService(); const transferInvoiceDialogRef = ref(); +const sendInvoiceFormRef = ref(); +const invoiceFormType = ref(null); const showInvoicePdf = () => { const url = `api/InvoiceOuts/${$props.invoiceOutData.id}/download?access_token=${token}`; @@ -31,6 +34,11 @@ const showInvoiceCsv = () => { recipientId: $props.invoiceOutData.client.id, }); }; + +const showSendInvoiceForm = (type) => { + invoiceFormType.value = type; + sendInvoiceFormRef.value.show(); +}; </script> <template> @@ -60,10 +68,10 @@ const showInvoiceCsv = () => { </QItemSection> <QMenu anchor="top end" self="top start"> <QList> - <QItem v-ripple clickable> + <QItem v-ripple clickable @click="showSendInvoiceForm()"> <QItemSection>{{ t('Send PDF') }}</QItemSection> </QItem> - <QItem v-ripple clickable> + <QItem v-ripple clickable @click="showSendInvoiceForm()"> <QItemSection>{{ t('Send CSV') }}</QItemSection> </QItem> </QList> @@ -98,6 +106,9 @@ const showInvoiceCsv = () => { <QDialog ref="transferInvoiceDialogRef"> <TransferInvoiceForm :invoice-out-data="invoiceOutData" /> </QDialog> + <QDialog ref="sendInvoiceFormRef"> + <SendInvoiceForm /> + </QDialog> </template> <i18n> diff --git a/src/pages/InvoiceOut/Card/SendInvoiceForm.vue b/src/pages/InvoiceOut/Card/SendInvoiceForm.vue new file mode 100644 index 000000000..3956dab08 --- /dev/null +++ b/src/pages/InvoiceOut/Card/SendInvoiceForm.vue @@ -0,0 +1,41 @@ +<script setup> +import { ref } from 'vue'; +import { useI18n } from 'vue-i18n'; + +import VnRow from 'components/ui/VnRow.vue'; +import VnInput from 'src/components/common/VnInput.vue'; +import FormPopup from 'src/components/FormPopup.vue'; + +const emit = defineEmits(['onDataSaved']); + +const { t } = useI18n(); + +const email = ref(null); + +const onDataSaved = (dataSaved) => { + emit('onDataSaved', dataSaved); +}; +</script> + +<template> + <FormPopup + :title="t('New thermograph')" + :subtitle="t('Are you sure you want to send it?')" + @on-data-saved="onDataSaved($event)" + > + <template #form-inputs> + <VnRow class="row q-gutter-md q-mb-md"> + <div class="col"> + <VnInput :label="t('Email')" v-model="email" type="email" /> + </div> + </VnRow> + </template> + </FormPopup> +</template> + +<i18n> +es: + Email: Email + Confirm: Confirmar + Are you sure you want to send it?: ¿Seguro que quieres enviarlo? +</i18n> From c407566d676d707154438d3a4f9dc9365358d4f0 Mon Sep 17 00:00:00 2001 From: wbuezas <wbuezas@verdnatura.es> Date: Wed, 21 Feb 2024 11:27:32 -0300 Subject: [PATCH 09/42] descriptor menu actions --- src/components/FormPopup.vue | 19 +- src/components/TransferInvoiceForm.vue | 44 ++--- src/composables/useVnConfirm.js | 23 +++ .../Card/InvoiceOutDescriptorMenu.vue | 163 ++++++++++++++++-- 4 files changed, 192 insertions(+), 57 deletions(-) create mode 100644 src/composables/useVnConfirm.js diff --git a/src/components/FormPopup.vue b/src/components/FormPopup.vue index 951d697d5..b6eff5d80 100644 --- a/src/components/FormPopup.vue +++ b/src/components/FormPopup.vue @@ -2,7 +2,7 @@ import { ref } from 'vue'; import { useI18n } from 'vue-i18n'; -const emit = defineEmits(['onDataSaved']); +const emit = defineEmits(['onSubmit']); const $props = defineProps({ title: { @@ -13,7 +13,7 @@ const $props = defineProps({ type: String, default: '', }, - defaultSaveButton: { + defaultSubmitButton: { type: Boolean, default: true, }, @@ -21,6 +21,10 @@ const $props = defineProps({ type: Boolean, default: true, }, + customSubmitButtonLabel: { + type: String, + default: '', + }, }); const { t } = useI18n(); @@ -28,8 +32,8 @@ const { t } = useI18n(); const closeButton = ref(null); const isLoading = ref(false); -const onDataSaved = (dataSaved) => { - emit('onDataSaved', dataSaved); +const onSubmit = () => { + emit('onSubmit'); closeForm(); }; @@ -40,7 +44,7 @@ const closeForm = () => { <template> <QForm - @submit="onDataSaved($event)" + @submit="onSubmit($event)" class="all-pointer-events full-width" style="max-width: 800px" > @@ -53,8 +57,8 @@ const closeForm = () => { <slot name="form-inputs" /> <div class="q-mt-lg row justify-end"> <QBtn - v-if="defaultSaveButton" - :label="t('globals.save')" + v-if="defaultSubmitButton" + :label="customSubmitButtonLabel || t('globals.save')" type="submit" color="primary" :disabled="isLoading" @@ -63,7 +67,6 @@ const closeForm = () => { <QBtn v-if="defaultCancelButton" :label="t('globals.cancel')" - type="reset" color="primary" flat class="q-ml-sm" diff --git a/src/components/TransferInvoiceForm.vue b/src/components/TransferInvoiceForm.vue index e62c7638c..b7d8f3081 100644 --- a/src/components/TransferInvoiceForm.vue +++ b/src/components/TransferInvoiceForm.vue @@ -6,6 +6,8 @@ import { useRouter } from 'vue-router'; import VnRow from 'components/ui/VnRow.vue'; import FetchData from 'components/FetchData.vue'; import VnSelectFilter from 'components/common/VnSelectFilter.vue'; +import FormPopup from './FormPopup.vue'; + import axios from 'axios'; import useNotify from 'src/composables/useNotify.js'; @@ -25,7 +27,6 @@ const transferInvoiceParams = reactive({ refFk: $props.invoiceOutData?.ref, }); const closeButton = ref(null); -const isLoading = ref(false); const clientsOptions = ref([]); const rectificativeTypeOptions = ref([]); const siiTypeInvoiceOutsOptions = ref([]); @@ -74,12 +75,13 @@ const transferInvoice = async () => { @on-fetch="(data) => (invoiceCorrectionTypesOptions = data)" auto-load /> - <QForm @submit="transferInvoice()" class="all-pointer-events"> - <QCard class="column" style="padding: 32px; z-index: 100"> - <span ref="closeButton" class="close-icon" v-close-popup> - <QIcon name="close" size="sm" /> - </span> - <h1 class="title">{{ t('Transfer invoice') }}</h1> + <FormPopup + @on-submit="transferInvoice()" + :title="t('Transfer invoice')" + :custom-submit-button-label="t('Transfer client')" + :default-cancel-button="false" + > + <template #form-inputs> <VnRow class="row q-gutter-md q-mb-md"> <div class="col"> <VnSelectFilter @@ -150,17 +152,8 @@ const transferInvoice = async () => { /> </div> </VnRow> - <div class="q-mt-lg row justify-end"> - <QBtn - :label="t('Transfer client')" - type="submit" - color="primary" - :disabled="isLoading" - :loading="isLoading" - /> - </div> - </QCard> - </QForm> + </template> + </FormPopup> </template> <i18n> @@ -173,18 +166,3 @@ es: Type: Tipo Transferred invoice: Factura transferida </i18n> - -<style lang="scss" scoped> -.title { - font-size: 17px; - font-weight: bold; - line-height: 20px; -} - -.close-icon { - position: absolute; - top: 20px; - right: 20px; - cursor: pointer; -} -</style> diff --git a/src/composables/useVnConfirm.js b/src/composables/useVnConfirm.js new file mode 100644 index 000000000..430a290be --- /dev/null +++ b/src/composables/useVnConfirm.js @@ -0,0 +1,23 @@ +import VnConfirm from 'components/ui/VnConfirm.vue'; +import { useQuasar } from 'quasar'; + +export function useSummaryDialog() { + const quasar = useQuasar(); + + const openConfirmationModal = (title, message, promise, successFn) => { + quasar + .dialog({ + component: VnConfirm, + componentProps: { + title: title, + message: message, + promise: promise, + }, + }) + .onOk(async () => { + if (successFn) successFn(); + }); + }; + + return { openConfirmationModal }; +} diff --git a/src/pages/InvoiceOut/Card/InvoiceOutDescriptorMenu.vue b/src/pages/InvoiceOut/Card/InvoiceOutDescriptorMenu.vue index 76b9cefdc..fc84c042b 100644 --- a/src/pages/InvoiceOut/Card/InvoiceOutDescriptorMenu.vue +++ b/src/pages/InvoiceOut/Card/InvoiceOutDescriptorMenu.vue @@ -1,12 +1,17 @@ <script setup> import { ref } from 'vue'; import { useI18n } from 'vue-i18n'; +import { useRouter } from 'vue-router'; +import { useQuasar } from 'quasar'; import TransferInvoiceForm from 'src/components/TransferInvoiceForm.vue'; -import SendInvoiceForm from './SendInvoiceForm.vue'; +import SendEmailDialog from 'components/common/SendEmailDialog.vue'; +import useNotify from 'src/composables/useNotify'; import { useSession } from 'src/composables/useSession'; import { usePrintService } from 'composables/usePrintService'; +import { useSummaryDialog } from 'composables/useVnConfirm'; +import axios from 'axios'; const $props = defineProps({ invoiceOutData: { @@ -15,14 +20,18 @@ const $props = defineProps({ }, }); +const { notify } = useNotify(); +const router = useRouter(); const session = useSession(); const token = session.getToken(); const { t } = useI18n(); -const { openReport } = usePrintService(); +const { openReport, sendEmail } = usePrintService(); +const { openConfirmationModal } = useSummaryDialog(); +const quasar = useQuasar(); const transferInvoiceDialogRef = ref(); -const sendInvoiceFormRef = ref(); -const invoiceFormType = ref(null); +const invoiceFormType = ref('pdf'); +const defaultEmailAddress = ref($props.invoiceOutData.client?.email); const showInvoicePdf = () => { const url = `api/InvoiceOuts/${$props.invoiceOutData.id}/download?access_token=${token}`; @@ -35,9 +44,86 @@ const showInvoiceCsv = () => { }); }; -const showSendInvoiceForm = (type) => { +const showSendInvoiceDialog = (type) => { invoiceFormType.value = type; - sendInvoiceFormRef.value.show(); + quasar.dialog({ + component: SendEmailDialog, + componentProps: { + data: { + address: defaultEmailAddress.value, + }, + promise: sendEmailInvoice, + }, + }); +}; + +const sendEmailInvoice = async ({ address }) => { + try { + if (!address) notify(`The email can't be empty`, 'negative'); + + if (invoiceFormType.value === 'pdf') { + return sendEmail(`InvoiceOuts/${$props.invoiceOutData.ref}/invoice-email`, { + recipientId: $props.invoiceOutData.client.id, + recipient: address, + }); + } else { + return sendEmail( + `InvoiceOuts/${$props.invoiceOutData.ref}/invoice-csv-email`, + { + recipientId: $props.invoiceOutData.client.id, + recipient: address, + } + ); + } + } catch (err) { + console.error('Error sending email', err); + } +}; + +const redirectToInvoiceOutList = () => { + router.push({ name: 'InvoiceOutList' }); +}; + +const deleteInvoice = async () => { + try { + await axios.post(`InvoiceOuts/${$props.invoiceOutData.id}/delete`); + notify(t('InvoiceOut deleted'), 'positive'); + } catch (err) { + console.error('Error deleting invoice out', err); + } +}; + +const bookInvoice = async () => { + try { + await axios.post(`InvoiceOuts/${$props.invoiceOutData.ref}/book`); + notify(t('InvoiceOut booked'), 'positive'); + } catch (err) { + console.error('Error booking invoice out', err); + } +}; + +const generateInvoicePdf = async () => { + try { + await axios.post(`InvoiceOuts/${$props.invoiceOutData.id}/createPdf`); + notify(t('The invoice PDF document has been regenerated'), 'positive'); + } catch (err) { + console.error('Error generating invoice out pdf', err); + } +}; + +const refundInvoice = async (withWarehouse) => { + try { + const params = { ref: $props.invoiceOutData.ref, withWarehouse: withWarehouse }; + const { data } = await axios.post('InvoiceOuts/refund', params); + notify( + t('refundInvoiceSuccessMessage', { + refundTicket: data[0].id, + }), + 'positive' + ); + } catch (err) { + console.error('Error generating invoice out pdf', err); + } }; </script> @@ -68,22 +154,53 @@ const showSendInvoiceForm = (type) => { </QItemSection> <QMenu anchor="top end" self="top start"> <QList> - <QItem v-ripple clickable @click="showSendInvoiceForm()"> + <QItem v-ripple clickable @click="showSendInvoiceDialog('pdf')"> <QItemSection>{{ t('Send PDF') }}</QItemSection> </QItem> - <QItem v-ripple clickable @click="showSendInvoiceForm()"> + <QItem v-ripple clickable @click="showSendInvoiceDialog('csv')"> <QItemSection>{{ t('Send CSV') }}</QItemSection> </QItem> </QList> </QMenu> </QItem> - <QItem v-ripple clickable> + <QItem + v-ripple + clickable + @click=" + openConfirmationModal( + t('Confirm deletion'), + t('Are you sure you want to delete this invoice?'), + deleteInvoice, + redirectToInvoiceOutList + ) + " + > <QItemSection>{{ t('Delete invoice') }}</QItemSection> </QItem> - <QItem v-ripple clickable> + <QItem + v-ripple + clickable + @click=" + openConfirmationModal( + '', + t('Are you sure you want to book this invoice?'), + bookInvoice + ) + " + > <QItemSection>{{ t('Book invoice') }}</QItemSection> </QItem> - <QItem v-ripple clickable> + <QItem + v-ripple + clickable + @click=" + openConfirmationModal( + t('Generate PDF invoice document'), + t('Are you sure you want to generate/regenerate the PDF invoice?'), + generateInvoicePdf + ) + " + > <QItemSection>{{ t('Generate PDF invoice') }}</QItemSection> </QItem> <QItem v-ripple clickable> @@ -93,22 +210,22 @@ const showSendInvoiceForm = (type) => { </QItemSection> <QMenu anchor="top end" self="top start"> <QList> - <QItem v-ripple clickable> + <QItem v-ripple clickable @click="refundInvoice(true)"> <QItemSection>{{ t('With warehouse') }}</QItemSection> </QItem> - <QItem v-ripple clickable> + <QItem v-ripple clickable @click="refundInvoice(false)"> <QItemSection>{{ t('Without warehouse') }}</QItemSection> </QItem> </QList> </QMenu> + <QTooltip> + {{ t('Create a single ticket with all the content of the current invoice') }} + </QTooltip> </QItem> <QDialog ref="transferInvoiceDialogRef"> <TransferInvoiceForm :invoice-out-data="invoiceOutData" /> </QDialog> - <QDialog ref="sendInvoiceFormRef"> - <SendInvoiceForm /> - </QDialog> </template> <i18n> @@ -126,4 +243,18 @@ es: Send CSV: Enviar CSV With warehouse: Con almacén Without warehouse: Sin almacén + InvoiceOut deleted: Factura eliminada + Confirm deletion: Confirmar eliminación + Are you sure you want to delete this invoice?: Estas seguro de eliminar esta factura? + Are you sure you want to book this invoice?: Estas seguro de querer asentar esta factura? + InvoiceOut booked: Factura asentada + Generate PDF invoice document: Generar PDF de la factura + Are you sure you want to generate/regenerate the PDF invoice?: ¿Seguro que quieres generar/regenerar el PDF de la factura? + The invoice PDF document has been regenerated: El documento PDF de la factura ha sido regenerado + Create a single ticket with all the content of the current invoice: Crear un ticket único con todo el contenido de la factura actual + refundInvoiceSuccessMessage: Se ha creado el siguiente ticket de abono {refundTicket} + The email can't be empty: El email no puede estar vacío + +en: + refundInvoiceSuccessMessage: The following refund ticket have been created {refundTicket} </i18n> From 4af2ef49a07befb22748fae0b934a501b6611ebf Mon Sep 17 00:00:00 2001 From: Javier Segarra <jsegarra@verdnatura.es> Date: Mon, 26 Feb 2024 07:11:33 +0100 Subject: [PATCH 10/42] refs #6930: replace tokenUSer with tokenMultimedia --- src/components/NavBar.vue | 4 ++-- src/components/UserPanel.vue | 2 +- src/components/ui/VnAvatar.vue | 4 ++-- src/composables/downloadFile.js | 4 ++-- src/composables/useSession.js | 16 ++++++++++++++-- src/pages/Claim/Card/ClaimBasicData.vue | 4 ++-- src/pages/Claim/Card/ClaimPhoto.vue | 4 ++-- src/pages/Claim/Card/ClaimSummary.vue | 4 ++-- src/pages/Customer/Card/CustomerBasicData.vue | 4 ++-- src/pages/Entry/EntryLatestBuys.vue | 4 ++-- src/pages/Item/Card/ItemDescriptor.vue | 4 ++-- src/pages/Order/Card/OrderCatalogItem.vue | 4 ++-- src/pages/Order/OrderLines.vue | 4 ++-- src/pages/Route/Cmr/CmrList.vue | 4 ++-- src/pages/Route/RouteList.vue | 16 ++++++++-------- src/pages/Wagon/WagonCounter.vue | 4 ++-- src/pages/Worker/Card/WorkerDescriptor.vue | 4 ++-- 17 files changed, 51 insertions(+), 39 deletions(-) diff --git a/src/components/NavBar.vue b/src/components/NavBar.vue index 12366e174..17b8c2b7e 100644 --- a/src/components/NavBar.vue +++ b/src/components/NavBar.vue @@ -10,12 +10,12 @@ import UserPanel from 'components/UserPanel.vue'; import VnBreadcrumbs from './common/VnBreadcrumbs.vue'; const { t } = useI18n(); -const session = useSession(); const stateStore = useStateStore(); const quasar = useQuasar(); const state = useState(); const user = state.getUser(); -const token = session.getToken(); +const { getTokenMultimedia } = useSession(); +const token = getTokenMultimedia(); const appName = 'Lilium'; onMounted(() => stateStore.setMounted()); diff --git a/src/components/UserPanel.vue b/src/components/UserPanel.vue index e0b6b86ed..a18dad79a 100644 --- a/src/components/UserPanel.vue +++ b/src/components/UserPanel.vue @@ -44,7 +44,7 @@ const darkMode = computed({ }); const user = state.getUser(); -const token = session.getToken(); +const token = session.getTokenMultimedia(); onMounted(async () => { updatePreferences(); diff --git a/src/components/ui/VnAvatar.vue b/src/components/ui/VnAvatar.vue index 5a5483084..287f741e0 100644 --- a/src/components/ui/VnAvatar.vue +++ b/src/components/ui/VnAvatar.vue @@ -10,8 +10,8 @@ const $props = defineProps({ size: { type: String, default: null }, title: { type: String, default: null }, }); -const session = useSession(); -const token = session.getToken(); +const { getTokenMultimedia } = useSession(); +const token = getTokenMultimedia(); const { t } = useI18n(); const title = computed(() => $props.title ?? t('globals.system')); diff --git a/src/composables/downloadFile.js b/src/composables/downloadFile.js index 877d2a254..b26dec731 100644 --- a/src/composables/downloadFile.js +++ b/src/composables/downloadFile.js @@ -1,8 +1,8 @@ import { useSession } from 'src/composables/useSession'; import { getUrl } from './getUrl'; -const session = useSession(); -const token = session.getToken(); +const {getTokenMultimedia} = useSession(); +const token = getTokenMultimedia(); export async function downloadFile(dmsId) { let appUrl = await getUrl('', 'lilium'); diff --git a/src/composables/useSession.js b/src/composables/useSession.js index 008337b02..4d182a934 100644 --- a/src/composables/useSession.js +++ b/src/composables/useSession.js @@ -10,12 +10,20 @@ export function useSession() { return localToken || sessionToken || ''; } + function getTokenMultimedia() { + const localTokenMultimedia = localStorage.getItem('tokenMultimedia'); + const sessionTokenMultimedia = sessionStorage.getItem('tokenMultimedia'); + + return localTokenMultimedia || sessionTokenMultimedia || ''; + } function setToken(data) { if (data.keepLogin) { localStorage.setItem('token', data.token); + localStorage.setItem('tokenMultimedia', data.tokenMultimedia); } else { sessionStorage.setItem('token', data.token); + sessionStorage.setItem('tokenMultimedia', data.tokenMultimedia); } } @@ -23,6 +31,9 @@ export function useSession() { if (localStorage.getItem('token')) localStorage.removeItem('token') + if (localStorage.getItem('tokenMultimedia')) + localStorage.removeItem('tokenMultimedia') + if (sessionStorage.getItem('token')) sessionStorage.removeItem('token'); @@ -37,8 +48,8 @@ export function useSession() { }); } - async function login(token, keepLogin) { - setToken({ token, keepLogin }); + async function login(token, tokenMultimedia, keepLogin) { + setToken({ token, tokenMultimedia, keepLogin }); await useRole().fetch(); await useUserConfig().fetch(); @@ -53,6 +64,7 @@ export function useSession() { return { getToken, + getTokenMultimedia, setToken, destroy, login, diff --git a/src/pages/Claim/Card/ClaimBasicData.vue b/src/pages/Claim/Card/ClaimBasicData.vue index 35f93c736..1c4f998d8 100644 --- a/src/pages/Claim/Card/ClaimBasicData.vue +++ b/src/pages/Claim/Card/ClaimBasicData.vue @@ -13,8 +13,8 @@ import { useSession } from 'src/composables/useSession'; const route = useRoute(); const { t } = useI18n(); -const session = useSession(); -const token = session.getToken(); +const { getTokenMultimedia } = useSession(); +const token = getTokenMultimedia(); const claimFilter = { fields: [ diff --git a/src/pages/Claim/Card/ClaimPhoto.vue b/src/pages/Claim/Card/ClaimPhoto.vue index 6ac116ce0..dd97b60df 100644 --- a/src/pages/Claim/Card/ClaimPhoto.vue +++ b/src/pages/Claim/Card/ClaimPhoto.vue @@ -11,8 +11,8 @@ import FetchData from 'components/FetchData.vue'; const router = useRouter(); const quasar = useQuasar(); const { t } = useI18n(); -const session = useSession(); -const token = session.getToken(); +const { getTokenMultimedia } = useSession(); +const token = getTokenMultimedia(); const claimId = computed(() => router.currentRoute.value.params.id); diff --git a/src/pages/Claim/Card/ClaimSummary.vue b/src/pages/Claim/Card/ClaimSummary.vue index cdc1f15be..9281cc08a 100644 --- a/src/pages/Claim/Card/ClaimSummary.vue +++ b/src/pages/Claim/Card/ClaimSummary.vue @@ -14,8 +14,8 @@ import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue'; const route = useRoute(); const { t } = useI18n(); -const session = useSession(); -const token = session.getToken(); +const { getTokenMultimedia } = useSession(); +const token = getTokenMultimedia(); const $props = defineProps({ id: { diff --git a/src/pages/Customer/Card/CustomerBasicData.vue b/src/pages/Customer/Card/CustomerBasicData.vue index 458d50082..d23b08f17 100644 --- a/src/pages/Customer/Card/CustomerBasicData.vue +++ b/src/pages/Customer/Card/CustomerBasicData.vue @@ -11,8 +11,8 @@ import VnInput from 'src/components/common/VnInput.vue'; const route = useRoute(); const { t } = useI18n(); -const session = useSession(); -const token = session.getToken(); +const { getTokenMultimedia } = useSession(); +const token = getTokenMultimedia(); const workers = ref([]); const workersCopy = ref([]); diff --git a/src/pages/Entry/EntryLatestBuys.vue b/src/pages/Entry/EntryLatestBuys.vue index f4a423f3b..db66b8f0b 100644 --- a/src/pages/Entry/EntryLatestBuys.vue +++ b/src/pages/Entry/EntryLatestBuys.vue @@ -15,8 +15,8 @@ import { useSession } from 'composables/useSession'; import { dashIfEmpty } from 'src/filters'; const router = useRouter(); -const session = useSession(); -const token = session.getToken(); +const { getTokenMultimedia } = useSession(); +const token = getTokenMultimedia(); const stateStore = useStateStore(); const { t } = useI18n(); diff --git a/src/pages/Item/Card/ItemDescriptor.vue b/src/pages/Item/Card/ItemDescriptor.vue index 362fcfc67..af6de04e8 100644 --- a/src/pages/Item/Card/ItemDescriptor.vue +++ b/src/pages/Item/Card/ItemDescriptor.vue @@ -36,7 +36,7 @@ const quasar = useQuasar(); const route = useRoute(); const router = useRouter(); const { t } = useI18n(); -const { getToken } = useSession(); +const { getTokenMultimedia } = useSession(); const state = useState(); const user = state.getUser(); @@ -72,7 +72,7 @@ onMounted(async () => { }); const getItemAvatar = async () => { - const token = getToken(); + const token = getTokenMultimedia(); const timeStamp = `timestamp=${Date.now()}`; image.value = `/api/Images/catalog/200x200/${entityId.value}/download?access_token=${token}&${timeStamp}`; }; diff --git a/src/pages/Order/Card/OrderCatalogItem.vue b/src/pages/Order/Card/OrderCatalogItem.vue index ee73bcffb..a197ceafc 100644 --- a/src/pages/Order/Card/OrderCatalogItem.vue +++ b/src/pages/Order/Card/OrderCatalogItem.vue @@ -11,8 +11,8 @@ import toCurrency from '../../../filters/toCurrency'; const DEFAULT_PRICE_KG = 0; -const session = useSession(); -const token = session.getToken(); +const { getTokenMultimedia } = useSession(); +const token = getTokenMultimedia(); const { t } = useI18n(); defineProps({ diff --git a/src/pages/Order/OrderLines.vue b/src/pages/Order/OrderLines.vue index a2ee42481..4b6c21c75 100644 --- a/src/pages/Order/OrderLines.vue +++ b/src/pages/Order/OrderLines.vue @@ -17,9 +17,9 @@ import axios from 'axios'; const route = useRoute(); const { t } = useI18n(); -const session = useSession(); +const { getTokenMultimedia } = useSession(); const quasar = useQuasar(); -const token = session.getToken(); +const token = getTokenMultimedia(); const orderSummary = ref({ total: null, vat: null, diff --git a/src/pages/Route/Cmr/CmrList.vue b/src/pages/Route/Cmr/CmrList.vue index dc5602c1c..c0a6d263d 100644 --- a/src/pages/Route/Cmr/CmrList.vue +++ b/src/pages/Route/Cmr/CmrList.vue @@ -12,8 +12,8 @@ import CustomerDescriptorProxy from 'pages/Customer/Card/CustomerDescriptorProxy const stateStore = useStateStore(); const { t } = useI18n(); -const session = useSession(); -const token = session.getToken(); +const { getTokenMultimedia } = useSession(); +const token = getTokenMultimedia(); const selected = ref([]); const columns = computed(() => [ diff --git a/src/pages/Route/RouteList.vue b/src/pages/Route/RouteList.vue index 0b4aa6795..be8a29ceb 100644 --- a/src/pages/Route/RouteList.vue +++ b/src/pages/Route/RouteList.vue @@ -16,7 +16,7 @@ import RouteSearchbar from 'pages/Route/Card/RouteSearchbar.vue'; import RouteFilter from 'pages/Route/Card/RouteFilter.vue'; import RouteSummary from 'pages/Route/Card/RouteSummary.vue'; import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue'; -import {useSession} from "composables/useSession"; +import { useSession } from 'composables/useSession'; import { useSummaryDialog } from 'src/composables/useSummaryDialog'; const stateStore = useStateStore(); @@ -144,21 +144,21 @@ const cloneRoutes = () => { }; const showRouteReport = () => { - const ids = selectedRows.value.map(row => row?.id) - const idString = ids.join(',') + const ids = selectedRows.value.map((row) => row?.id); + const idString = ids.join(','); let url; if (selectedRows.value.length <= 1) { - url = `api/Routes/${idString}/driver-route-pdf?access_token=${session.getToken()}`; + url = `api/Routes/${idString}/driver-route-pdf?access_token=${session.getTokenMultimedia()}`; } else { const params = new URLSearchParams({ - access_token: session.getToken(), - id: idString - }) + access_token: session.getTokenMultimedia(), + id: idString, + }); url = `api/Routes/downloadZip?${params.toString()}`; } window.open(url, '_blank'); -} +}; const markAsServed = () => { selectedRows.value.forEach((row) => { diff --git a/src/pages/Wagon/WagonCounter.vue b/src/pages/Wagon/WagonCounter.vue index bd5d2ca67..15a1ab7ba 100644 --- a/src/pages/Wagon/WagonCounter.vue +++ b/src/pages/Wagon/WagonCounter.vue @@ -7,8 +7,8 @@ import VnConfirm from 'components/ui/VnConfirm.vue'; const quasar = useQuasar(); const { t } = useI18n(); -const session = useSession(); -const token = session.getToken(); +const { getTokenMultimedia } = useSession(); +const token = getTokenMultimedia(); const counters = ref({ alquilerBandeja: { count: 0, id: 96001, title: 'CC Bandeja', isTray: true }, diff --git a/src/pages/Worker/Card/WorkerDescriptor.vue b/src/pages/Worker/Card/WorkerDescriptor.vue index bec56bee7..5144b3bfa 100644 --- a/src/pages/Worker/Card/WorkerDescriptor.vue +++ b/src/pages/Worker/Card/WorkerDescriptor.vue @@ -22,7 +22,7 @@ const $props = defineProps({ const route = useRoute(); const { t } = useI18n(); -const { getToken } = useSession(); +const { getTokenMultimedia } = useSession(); const entityId = computed(() => { return $props.id || route.params.id; @@ -56,7 +56,7 @@ const filter = { const sip = computed(() => worker.value?.sip && worker.value.sip.extension); function getWorkerAvatar() { - const token = getToken(); + const token = getTokenMultimedia(); return `/api/Images/user/160x160/${entityId.value}/download?access_token=${token}`; } const data = ref(useCardDescription()); From d86675446827f092d816ff701d516aea1940bb26 Mon Sep 17 00:00:00 2001 From: Javier Segarra <jsegarra@verdnatura.es> Date: Mon, 26 Feb 2024 07:47:22 +0100 Subject: [PATCH 11/42] refs #6930: handle tokenMultimedia --- src/pages/Login/LoginMain.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/Login/LoginMain.vue b/src/pages/Login/LoginMain.vue index e2ccdac16..7a141e878 100644 --- a/src/pages/Login/LoginMain.vue +++ b/src/pages/Login/LoginMain.vue @@ -31,7 +31,7 @@ async function onSubmit() { if (!data) return; - await session.login(data.token, keepLogin.value); + await session.login(data.token, data.multimediaToken.id, keepLogin.value); quasar.notify({ message: t('login.loginSuccess'), From 564533604047c2185de21fbf2762453212ae0449 Mon Sep 17 00:00:00 2001 From: alexm <alexm@verdnatura.es> Date: Wed, 28 Feb 2024 07:55:11 +0100 Subject: [PATCH 12/42] refs #6795 hotFix(claimSummary) fix ItemDescriptorProxy --- src/pages/Claim/Card/ClaimSummary.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/Claim/Card/ClaimSummary.vue b/src/pages/Claim/Card/ClaimSummary.vue index b93cbbd81..7d6def871 100644 --- a/src/pages/Claim/Card/ClaimSummary.vue +++ b/src/pages/Claim/Card/ClaimSummary.vue @@ -259,7 +259,7 @@ function openDialog(dmsId) { > <ItemDescriptorProxy v-if="col.name == 'description'" - :id="props.row.id" + :id="props.row.sale.itemFk" :sale-fk="props.row.saleFk" ></ItemDescriptorProxy> </QTh> From bddfe8f9d7ff94ca253b2e34acf57434712976c2 Mon Sep 17 00:00:00 2001 From: Javier Segarra <jsegarra@verdnatura.es> Date: Wed, 28 Feb 2024 08:33:26 +0100 Subject: [PATCH 13/42] refs #6930 feat: call shareToken endpoint --- src/pages/Login/LoginMain.vue | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/pages/Login/LoginMain.vue b/src/pages/Login/LoginMain.vue index 7a141e878..0bdc02142 100644 --- a/src/pages/Login/LoginMain.vue +++ b/src/pages/Login/LoginMain.vue @@ -30,8 +30,15 @@ async function onSubmit() { const { data } = await axios.post('Accounts/login', params); if (!data) return; + const { + data: { multimediaToken }, + } = await axios.get('VnUsers/ShareToken', { + headers: { Authorization: data.token }, + }); - await session.login(data.token, data.multimediaToken.id, keepLogin.value); + if (!multimediaToken) return; + + await session.login(data.token, multimediaToken.id, keepLogin.value); quasar.notify({ message: t('login.loginSuccess'), From 0d80fd37a4127c7f395916f505cf6873bef53ba3 Mon Sep 17 00:00:00 2001 From: Javier Segarra <jsegarra@verdnatura.es> Date: Wed, 28 Feb 2024 11:28:57 +0100 Subject: [PATCH 14/42] refs #6930 feat: call loutMultimedia endpoint --- src/boot/axios.js | 2 +- src/composables/useSession.js | 37 ++++++++++++++++++++++++++++------- 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/src/boot/axios.js b/src/boot/axios.js index c58cc2d08..e3e7289af 100644 --- a/src/boot/axios.js +++ b/src/boot/axios.js @@ -11,7 +11,7 @@ axios.defaults.baseURL = '/api/'; const onRequest = (config) => { const token = session.getToken(); - if (token.length && config.headers) { + if (token.length && !config.headers.Authorization) { config.headers.Authorization = token; } diff --git a/src/composables/useSession.js b/src/composables/useSession.js index 4d182a934..580efbdf8 100644 --- a/src/composables/useSession.js +++ b/src/composables/useSession.js @@ -1,6 +1,7 @@ import { useState } from './useState'; import { useRole } from './useRole'; import { useUserConfig } from './useUserConfig'; +import axios from 'axios'; export function useSession() { @@ -27,15 +28,37 @@ export function useSession() { } } - function destroy() { - if (localStorage.getItem('token')) - localStorage.removeItem('token') - - if (localStorage.getItem('tokenMultimedia')) + async function destroy() { + if (localStorage.getItem('tokenMultimedia')){ + await axios.post('VnUsers/logoutMultimedia', null, { + headers: {Authorization: localStorage.getItem('tokenMultimedia') } + }); localStorage.removeItem('tokenMultimedia') - if (sessionStorage.getItem('token')) - sessionStorage.removeItem('token'); + } + if (localStorage.getItem('token')){ + await axios.post('VnUsers/logout', null, { + headers: {Authorization: localStorage.getItem('token') } + }); + localStorage.removeItem('token') + } + + + if (sessionStorage.getItem('tokenMultimedia')){ + await axios.post('VnUsers/logoutMultimedia', null, { + headers: {Authorization: sessionStorage.getItem('tokenMultimedia') } + }); + sessionStorage.removeItem('tokenMultimedia') + + } + if (sessionStorage.getItem('token')){ + await axios.post('VnUsers/logout', null, { + headers: {Authorization: sessionStorage.getItem('token') } + }); + sessionStorage.removeItem('token') + } + + const { setUser } = useState(); From 39381f29d739b2ccc865a91adf1dd5c55a460981 Mon Sep 17 00:00:00 2001 From: Javier Segarra <jsegarra@verdnatura.es> Date: Wed, 28 Feb 2024 13:15:59 +0100 Subject: [PATCH 15/42] refs #6980 test: fix failed tests --- .../vitest/__tests__/composables/useSession.spec.js | 13 ++++++++----- test/vitest/__tests__/pages/Login/Login.spec.js | 6 +++--- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/test/vitest/__tests__/composables/useSession.spec.js b/test/vitest/__tests__/composables/useSession.spec.js index 4f900aca6..f9f3dcb80 100644 --- a/test/vitest/__tests__/composables/useSession.spec.js +++ b/test/vitest/__tests__/composables/useSession.spec.js @@ -54,7 +54,8 @@ describe('session', () => { expect(localStorage.getItem('token')).toEqual('tokenToBeGone'); expect(user.value).toEqual(previousUser); - session.destroy(); + vi.spyOn(axios, 'post').mockResolvedValue({ data: true }); + await session.destroy(); user = state.getUser(); expect(localStorage.getItem('token')).toBeNull(); @@ -92,9 +93,10 @@ describe('session', () => { }); const expectedToken = 'mySessionToken'; + const expectedTokenMultimedia = 'mySessionTokenMultimedia'; const keepLogin = false; - await session.login(expectedToken, keepLogin); + await session.login(expectedToken,expectedTokenMultimedia, keepLogin); const roles = state.getRoles(); const localToken = localStorage.getItem('token'); @@ -104,7 +106,7 @@ describe('session', () => { expect(localToken).toBeNull(); expect(sessionToken).toEqual(expectedToken); - session.destroy(); // this clears token and user for any other test + await session.destroy(); // this clears token and user for any other test }); it('should fetch the user roles and then set token in the localStorage', async () => { @@ -114,9 +116,10 @@ describe('session', () => { }); const expectedToken = 'myLocalToken'; + const expectedTokenMultimedia = 'myLocalTokenMultimedia'; const keepLogin = true; - await session.login(expectedToken, keepLogin); + await session.login(expectedToken, expectedTokenMultimedia, keepLogin); const roles = state.getRoles(); const localToken = localStorage.getItem('token'); @@ -126,7 +129,7 @@ describe('session', () => { expect(localToken).toEqual(expectedToken); expect(sessionToken).toBeNull(); - session.destroy(); // this clears token and user for any other test + await session.destroy(); // this clears token and user for any other test }); }); }); diff --git a/test/vitest/__tests__/pages/Login/Login.spec.js b/test/vitest/__tests__/pages/Login/Login.spec.js index fadfc898f..6e2de9870 100644 --- a/test/vitest/__tests__/pages/Login/Login.spec.js +++ b/test/vitest/__tests__/pages/Login/Login.spec.js @@ -22,9 +22,9 @@ describe('Login', () => { darkMode: false, }, }; - vi.spyOn(axios, 'post').mockResolvedValue({ data: { token: 'token' } }); + vi.spyOn(axios, 'post').mockResolvedValueOnce({ data: { token: 'token' } }); vi.spyOn(axios, 'get').mockResolvedValue({ - data: { roles: [], user: expectedUser }, + data: { roles: [], user: expectedUser , multimediaToken: {id:'multimediaToken' }}, }); vi.spyOn(vm.quasar, 'notify'); @@ -36,7 +36,7 @@ describe('Login', () => { expect(vm.quasar.notify).toHaveBeenCalledWith( expect.objectContaining({ type: 'positive' }) ); - vm.session.destroy(); + await vm.session.destroy(); }); it('should not set the token into session if any error occurred', async () => { From 4b860e05837c623f98f6725bfec90ab3993d6938 Mon Sep 17 00:00:00 2001 From: wbuezas <wbuezas@verdnatura.es> Date: Tue, 5 Mar 2024 08:54:15 -0300 Subject: [PATCH 16/42] Change issued title --- src/pages/InvoiceOut/InvoiceOutList.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/InvoiceOut/InvoiceOutList.vue b/src/pages/InvoiceOut/InvoiceOutList.vue index 7bdf2ffbd..ad54d9908 100644 --- a/src/pages/InvoiceOut/InvoiceOutList.vue +++ b/src/pages/InvoiceOut/InvoiceOutList.vue @@ -158,7 +158,7 @@ const openPdf = () => { > <template #list-items> <VnLv - :label="t('invoiceOut.list.amount')" + :label="t('invoiceOut.list.issued')" :value="toDate(row.issued)" /> <VnLv From 12a470b7d919e3dda0f8955a46fea6ea3a06d88b Mon Sep 17 00:00:00 2001 From: wbuezas <wbuezas@verdnatura.es> Date: Tue, 5 Mar 2024 09:27:44 -0300 Subject: [PATCH 17/42] Add links to invoice out summary tickets table --- .../InvoiceOut/Card/InvoiceOutSummary.vue | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/src/pages/InvoiceOut/Card/InvoiceOutSummary.vue b/src/pages/InvoiceOut/Card/InvoiceOutSummary.vue index 5721818e4..d74969319 100644 --- a/src/pages/InvoiceOut/Card/InvoiceOutSummary.vue +++ b/src/pages/InvoiceOut/Card/InvoiceOutSummary.vue @@ -2,16 +2,14 @@ import { onMounted, ref, computed } from 'vue'; import { useRoute } from 'vue-router'; import { useI18n } from 'vue-i18n'; - +import axios from 'axios'; +import { toCurrency, toDate } from 'src/filters'; import CardSummary from 'components/ui/CardSummary.vue'; import VnLv from 'src/components/ui/VnLv.vue'; +import { getUrl } from 'src/composables/getUrl'; import TicketDescriptorProxy from 'src/pages/Ticket/Card/TicketDescriptorProxy.vue'; import CustomerDescriptorProxy from 'src/pages/Customer/Card/CustomerDescriptorProxy.vue'; -import { getUrl } from 'src/composables/getUrl'; -import { toCurrency, toDate } from 'src/filters'; -import axios from 'axios'; - onMounted(async () => { fetch(); salixUrl.value = await getUrl(''); @@ -70,14 +68,14 @@ const taxColumns = ref([ const ticketsColumns = ref([ { - name: 'id', + name: 'item', label: t('invoiceOut.summary.ticketId'), field: (row) => row.id, sortable: true, align: 'left', }, { - name: 'alias', + name: 'quantity', label: t('invoiceOut.summary.nickname'), field: (row) => row.nickname, sortable: true, @@ -147,21 +145,25 @@ const ticketsColumns = ref([ </template> </QTable> </QCard> - <QCard class="vn-max"> + <QCard class="vn-three"> <div class="header"> {{ t('invoiceOut.summary.tickets') }} </div> <QTable v-if="tickets" :columns="ticketsColumns" :rows="tickets" flat> - <template #body-cell-id="{ row }"> + <template #body-cell-item="{ value }"> <QTd> - <QBtn flat color="primary"> {{ row.id }}</QBtn> - <TicketDescriptorProxy :id="row.id" /> + <QBtn flat color="primary"> + {{ value }} + <TicketDescriptorProxy :id="value" /> + </QBtn> </QTd> </template> - <template #body-cell-alias="{ row }"> + <template #body-cell-quantity="{ value, row }"> <QTd> - <QBtn flat dense color="primary"> {{ row.nickname }}</QBtn> - <CustomerDescriptorProxy :id="row.clientFk" /> + <QBtn flat color="primary" dense> + {{ value }} + <CustomerDescriptorProxy :id="row.id" /> + </QBtn> </QTd> </template> </QTable> From 87ab080b38e5d2c32bde79684a38e16aaa93dd7b Mon Sep 17 00:00:00 2001 From: wbuezas <wbuezas@verdnatura.es> Date: Tue, 5 Mar 2024 09:53:46 -0300 Subject: [PATCH 18/42] Change negative bases download button icon and tooltip --- src/pages/InvoiceOut/InvoiceOutNegativeBases.vue | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/pages/InvoiceOut/InvoiceOutNegativeBases.vue b/src/pages/InvoiceOut/InvoiceOutNegativeBases.vue index 5e82adf2a..e1740257a 100644 --- a/src/pages/InvoiceOut/InvoiceOutNegativeBases.vue +++ b/src/pages/InvoiceOut/InvoiceOutNegativeBases.vue @@ -140,7 +140,9 @@ const downloadCSV = async () => { <template> <template v-if="stateStore.isHeaderMounted()"> <Teleport to="#st-actions" v-if="stateStore?.isSubToolbarShown()"> - <QBtn color="primary" icon-right="archive" no-caps @click="downloadCSV()" /> + <QBtn color="primary" icon-right="download" no-caps @click="downloadCSV()"> + <QTooltip>{{ t('Download as CSV') }}</QTooltip> + </QBtn> </Teleport> </template> <QDrawer v-model="stateStore.rightDrawer" side="right" :width="256" show-if-above> @@ -187,4 +189,7 @@ const downloadCSV = async () => { } </style> -<i18n></i18n> +<i18n> +es: + Download as CSV: Descargar como CSV +</i18n> From 859c87940d92761381b53b53cb69b2f4cdea2815 Mon Sep 17 00:00:00 2001 From: wbuezas <wbuezas@verdnatura.es> Date: Wed, 6 Mar 2024 08:15:50 -0300 Subject: [PATCH 19/42] Several changes --- src/pages/InvoiceOut/InvoiceOutGlobal.vue | 11 ++++++- src/pages/InvoiceOut/InvoiceOutList.vue | 2 +- .../InvoiceOut/InvoiceOutNegativeBases.vue | 30 +++++++++++++++++-- src/router/modules/invoiceOut.js | 2 +- src/stores/invoiceOutGlobal.js | 8 ++--- 5 files changed, 42 insertions(+), 11 deletions(-) diff --git a/src/pages/InvoiceOut/InvoiceOutGlobal.vue b/src/pages/InvoiceOut/InvoiceOutGlobal.vue index 7e2b43a76..6f7e4c7fd 100644 --- a/src/pages/InvoiceOut/InvoiceOutGlobal.vue +++ b/src/pages/InvoiceOut/InvoiceOutGlobal.vue @@ -21,6 +21,7 @@ const { nPdfs, totalPdfs, errors, + addresses, } = storeToRefs(invoiceOutGlobalStore); const selectedCustomerId = ref(null); @@ -86,6 +87,14 @@ const selectCustomerId = (id) => { selectedCustomerId.value = id; }; +const statusText = computed(() => { + return status.value === 'invoicing' + ? `${t(`status.${status.value}`)} ${ + addresses.value[getAddressNumber.value]?.clientId + }` + : t(`status.${status.value}`); +}); + onMounted(() => (stateStore.rightDrawer = true)); onUnmounted(() => { stateStore.rightDrawer = false; @@ -103,7 +112,7 @@ onUnmounted(() => { <QPage class="column items-center q-pa-md"> <QCard v-if="status" class="card"> <QCardSection class="card-section"> - <span class="text">{{ t(`status.${status}`) }}</span> + <span class="text">{{ statusText }}</span> <span class="text">{{ t('invoiceOut.globalInvoices.statusCard.percentageText', { getPercentage: getPercentage, diff --git a/src/pages/InvoiceOut/InvoiceOutList.vue b/src/pages/InvoiceOut/InvoiceOutList.vue index ad54d9908..ca68f0770 100644 --- a/src/pages/InvoiceOut/InvoiceOutList.vue +++ b/src/pages/InvoiceOut/InvoiceOutList.vue @@ -119,7 +119,7 @@ const openPdf = () => { <VnPaginate auto-load data-key="InvoiceOutList" - order="issued DESC, id DESC" + :order="['issued DESC', 'id DESC']" url="InvoiceOuts/filter" > <template #body="{ rows }"> diff --git a/src/pages/InvoiceOut/InvoiceOutNegativeBases.vue b/src/pages/InvoiceOut/InvoiceOutNegativeBases.vue index e1740257a..fb3596499 100644 --- a/src/pages/InvoiceOut/InvoiceOutNegativeBases.vue +++ b/src/pages/InvoiceOut/InvoiceOutNegativeBases.vue @@ -1,5 +1,5 @@ <script setup> -import { ref, computed, onBeforeMount } from 'vue'; +import { ref, computed, onBeforeMount, onMounted, nextTick } from 'vue'; import { useI18n } from 'vue-i18n'; import CustomerDescriptorProxy from 'src/pages/Customer/Card/CustomerDescriptorProxy.vue'; @@ -45,6 +45,14 @@ onBeforeMount(async () => { stateStore.rightDrawer = true; }); +const componentIsRendered = ref(false); + +onMounted(() => + nextTick(() => { + componentIsRendered.value = true; + }) +); + const rows = computed(() => arrayData.value.store.data); const columns = computed(() => [ @@ -139,7 +147,10 @@ const downloadCSV = async () => { <template> <template v-if="stateStore.isHeaderMounted()"> - <Teleport to="#st-actions" v-if="stateStore?.isSubToolbarShown()"> + <Teleport + to="#st-actions" + v-if="stateStore?.isSubToolbarShown() && componentIsRendered" + > <QBtn color="primary" icon-right="download" no-caps @click="downloadCSV()"> <QTooltip>{{ t('Download as CSV') }}</QTooltip> </QBtn> @@ -178,6 +189,21 @@ const downloadCSV = async () => { <WorkerDescriptorProxy :id="row.comercialId" /> </QTd> </template> + <template #body-cell-active="{ row }"> + <QTd> + <QCheckbox :model-value="!!row.isActive" disable /> + </QTd> + </template> + <template #body-cell-hasToInvoice="{ row }"> + <QTd> + <QCheckbox :model-value="!!row.hasToInvoice" disable /> + </QTd> + </template> + <template #body-cell-verifiedData="{ row }"> + <QTd> + <QCheckbox :model-value="!!row.isTaxDataChecked" disable /> + </QTd> + </template> </QTable> </QPage> </template> diff --git a/src/router/modules/invoiceOut.js b/src/router/modules/invoiceOut.js index 084cf6ac3..b9648e96a 100644 --- a/src/router/modules/invoiceOut.js +++ b/src/router/modules/invoiceOut.js @@ -43,7 +43,7 @@ export default { name: 'InvoiceOutNegativeBases', meta: { title: 'negativeBases', - icon: 'view_list', + icon: 'vn:ticket', }, component: () => import('src/pages/InvoiceOut/InvoiceOutNegativeBases.vue'), diff --git a/src/stores/invoiceOutGlobal.js b/src/stores/invoiceOutGlobal.js index 9929a0127..b1bcc0e7d 100644 --- a/src/stores/invoiceOutGlobal.js +++ b/src/stores/invoiceOutGlobal.js @@ -107,7 +107,6 @@ export const useInvoiceOutGlobalStore = defineStore({ if (clientsToInvoice == 'all') params.clientId = undefined; const { data } = await axios.post('InvoiceOuts/clientsToInvoice', params); - this.addresses = data; if (!this.addresses || !this.addresses.length > 0) { @@ -188,10 +187,8 @@ export const useInvoiceOutGlobalStore = defineStore({ const { data } = await axios.post('InvoiceOuts/invoiceClient', params); - if (data) { - await this.makePdfAndNotify(data, address); - } - + if (data) await this.makePdfAndNotify(data, address); + this.addressIndex++; this.isInvoicing = false; } catch (err) { if ( @@ -201,7 +198,6 @@ export const useInvoiceOutGlobalStore = defineStore({ err.response.status < 500 ) { this.invoiceClientError(address, err.response?.data?.error?.message); - this.addressIndex++; return; } else { this.invoicing = false; From 0e79676f588a444b1e87a7e1e590da954267ab24 Mon Sep 17 00:00:00 2001 From: wbuezas <wbuezas@verdnatura.es> Date: Fri, 8 Mar 2024 09:02:49 -0300 Subject: [PATCH 20/42] Create manual invoice WIP --- src/components/CreateManualInvoiceForm.vue | 155 +++++++++++++++++++++ src/components/FormModelPopup.vue | 6 +- src/pages/InvoiceOut/InvoiceOutList.vue | 26 +++- 3 files changed, 183 insertions(+), 4 deletions(-) create mode 100644 src/components/CreateManualInvoiceForm.vue diff --git a/src/components/CreateManualInvoiceForm.vue b/src/components/CreateManualInvoiceForm.vue new file mode 100644 index 000000000..de5decaad --- /dev/null +++ b/src/components/CreateManualInvoiceForm.vue @@ -0,0 +1,155 @@ +<script setup> +import { reactive, ref } from 'vue'; +import { useI18n } from 'vue-i18n'; +import { useRouter } from 'vue-router'; + +import FetchData from 'components/FetchData.vue'; +import VnRow from 'components/ui/VnRow.vue'; +import VnSelectFilter from 'src/components/common/VnSelectFilter.vue'; +import VnInput from 'src/components/common/VnInput.vue'; +import FormModelPopup from './FormModelPopup.vue'; +import VnInputDate from './common/VnInputDate.vue'; + +const emit = defineEmits(['onDataSaved']); + +const { t } = useI18n(); +const router = useRouter(); + +const manualInvoiceFormData = reactive({ + maxShipped: Date.vnNew(), +}); + +const isInvoicing = ref(false); +const invoiceOutSerialsOptions = ref([]); +const taxAreasOptions = ref([]); +const ticketsOptions = ref([]); +const clientsOptions = ref([]); + +const onDataSaved = (formData, requestResponse) => { + emit('onDataSaved', formData, requestResponse); + router.push({ name: 'InvoiceOutSummary', params: { id: requestResponse.id } }); +}; +</script> + +<template> + <FetchData + url="InvoiceOutSerials" + :filter="{ where: { code: { neq: 'R' } }, order: ['code'] }" + @on-fetch="(data) => (invoiceOutSerialsOptions = data)" + auto-load + /> + <FetchData + url="TaxAreas" + :filter="{ order: ['code'] }" + @on-fetch="(data) => (taxAreasOptions = data)" + auto-load + /> + <FetchData + url="Tickets" + :filter="{ fields: ['id', 'nickname'], order: 'shipped DESC', limit: 30 }" + @on-fetch="(data) => (ticketsOptions = data)" + auto-load + /> + <FetchData + url="Clients" + :filter="{ fields: ['id', 'name'], order: 'name ASC', limit: 30 }" + @on-fetch="(data) => (clientsOptions = data)" + auto-load + /> + <FormModelPopup + :title="t('Create manual invoice')" + url-create="InvoiceOuts/createManualInvoice" + model="invoiceOut" + :form-initial-data="manualInvoiceFormData" + @on-data-saved="onDataSaved" + > + <template #form-inputs="{ data }"> + <VnRow class="row q-gutter-md q-mb-md"> + <div class="col"> + <VnSelectFilter + :label="t('Ticket')" + :options="ticketsOptions" + hide-selected + option-label="id" + option-value="id" + v-model="data.ticketFk" + @update:model-value="data.clientFk = null" + > + <template #option="scope"> + <QItem v-bind="scope.itemProps"> + <QItemSection> + <QItemLabel> #{{ scope.opt?.id }} </QItemLabel> + <QItemLabel caption>{{ + scope.opt?.nickname + }}</QItemLabel> + </QItemSection> + </QItem> + </template> + </VnSelectFilter> + </div> + <span class="row items-center" style="max-width: max-content">{{ + t('Or') + }}</span> + <div class="col"> + <VnSelectFilter + :label="t('Client')" + :options="clientsOptions" + hide-selected + option-label="name" + option-value="id" + v-model="data.clientFk" + @update:model-value="data.ticketFk = null" + /> + </div> + <div class="col"> + <VnInputDate :label="t('Max date')" v-model="data.maxShipped" /> + </div> + </VnRow> + <VnRow class="row q-gutter-md q-mb-md"> + <div class="col"> + <VnSelectFilter + :label="t('Serial')" + :options="invoiceOutSerialsOptions" + hide-selected + option-label="description" + option-value="code" + v-model="data.serial" + :required="true" + /> + </div> + <div class="col"> + <VnSelectFilter + :label="t('Area')" + :options="taxAreasOptions" + hide-selected + option-label="code" + option-value="code" + v-model="data.taxArea" + :required="true" + /> + </div> + </VnRow> + <VnRow class="row q-gutter-md q-mb-md"> + <VnInput + :label="t('Reference')" + type="textarea" + v-model="data.reference" + fill-input + autogrow + /> + </VnRow> + </template> + </FormModelPopup> +</template> + +<i18n> +es: + Create manual invoice: Crear factura manual + Ticket: Ticket + Client: Cliente + Max date: Fecha límite + Serial: Serie + Area: Area + Reference: Referencia + Or: O +</i18n> diff --git a/src/components/FormModelPopup.vue b/src/components/FormModelPopup.vue index 04322a3c8..cc22c77db 100644 --- a/src/components/FormModelPopup.vue +++ b/src/components/FormModelPopup.vue @@ -42,8 +42,8 @@ const { t } = useI18n(); const closeButton = ref(null); const isLoading = ref(false); -const onDataSaved = (dataSaved) => { - emit('onDataSaved', dataSaved); +const onDataSaved = (formData, requestResponse) => { + emit('onDataSaved', formData, requestResponse); closeForm(); }; @@ -59,7 +59,7 @@ const closeForm = () => { :default-actions="false" :url-create="urlCreate" :model="model" - @on-data-saved="onDataSaved($event)" + @on-data-saved="onDataSaved" > <template #form="{ data, validate }"> <span ref="closeButton" class="close-icon" v-close-popup> diff --git a/src/pages/InvoiceOut/InvoiceOutList.vue b/src/pages/InvoiceOut/InvoiceOutList.vue index ca68f0770..17b37b962 100644 --- a/src/pages/InvoiceOut/InvoiceOutList.vue +++ b/src/pages/InvoiceOut/InvoiceOutList.vue @@ -10,6 +10,7 @@ import VnLv from 'src/components/ui/VnLv.vue'; import CardList from 'src/components/ui/CardList.vue'; import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue'; import CustomerDescriptorProxy from '../Customer/Card/CustomerDescriptorProxy.vue'; +import CreateManualInvoiceForm from 'src/components/CreateManualInvoiceForm.vue'; import InvoiceOutFilter from './InvoiceOutFilter.vue'; import { toDate, toCurrency } from 'src/filters/index'; @@ -18,13 +19,15 @@ import { useSummaryDialog } from 'src/composables/useSummaryDialog'; import { useSession } from 'src/composables/useSession'; const { t } = useI18n(); -const selectedCards = ref(new Map()); const router = useRouter(); const stateStore = useStateStore(); const session = useSession(); const token = session.getToken(); const { viewSummary } = useSummaryDialog(); +const manualInvoiceDialogRef = ref(null); +const selectedCards = ref(new Map()); + onMounted(() => (stateStore.rightDrawer = true)); onUnmounted(() => (stateStore.rightDrawer = false)); @@ -83,6 +86,10 @@ const openPdf = () => { console.error('Error opening PDF'); } }; + +const openCreateInvoiceModal = () => { + manualInvoiceDialogRef.value.show(); +}; </script> <template> @@ -204,6 +211,20 @@ const openPdf = () => { </div> </template> </VnPaginate> + <QPageSticky :offset="[20, 20]"> + <QBtn fab icon="add" color="primary" @click="openCreateInvoiceModal()" /> + <QTooltip> + {{ t('createInvoice') }} + </QTooltip> + </QPageSticky> + + <QDialog + ref="manualInvoiceDialogRef" + transition-show="scale" + transition-hide="scale" + > + <CreateManualInvoiceForm /> + </QDialog> </QPage> </template> @@ -214,10 +235,13 @@ en: fileAllowed: Successful download of CSV file youCanSearchByInvoiceReference: You can search by invoice reference downloadPdf: Download PDF + createInvoice: Make invoice es: searchInvoice: Buscar factura emitida fileDenied: El navegador denegó la descarga de archivos... fileAllowed: Descarga exitosa de archivo CSV youCanSearchByInvoiceReference: Puedes buscar por referencia de la factura downloadPdf: Download PDF + createInvoice: Crear factura + </i18n> From ed99aea4a3cbecc4d23f576851c9fb97593be769 Mon Sep 17 00:00:00 2001 From: wbuezas <wbuezas@verdnatura.es> Date: Fri, 8 Mar 2024 15:05:11 -0300 Subject: [PATCH 21/42] Finish create manual invoice popup form --- src/components/CreateManualInvoiceForm.vue | 27 ++++++++++++++++++---- src/components/FormModel.vue | 9 ++++---- src/components/FormModelPopup.vue | 13 ++++++++--- src/css/app.scss | 4 ++++ 4 files changed, 42 insertions(+), 11 deletions(-) diff --git a/src/components/CreateManualInvoiceForm.vue b/src/components/CreateManualInvoiceForm.vue index de5decaad..f03afbf35 100644 --- a/src/components/CreateManualInvoiceForm.vue +++ b/src/components/CreateManualInvoiceForm.vue @@ -1,5 +1,5 @@ <script setup> -import { reactive, ref } from 'vue'; +import { reactive, ref, computed } from 'vue'; import { useI18n } from 'vue-i18n'; import { useRouter } from 'vue-router'; @@ -19,15 +19,17 @@ const manualInvoiceFormData = reactive({ maxShipped: Date.vnNew(), }); -const isInvoicing = ref(false); +const formModelPopupRef = ref(); const invoiceOutSerialsOptions = ref([]); const taxAreasOptions = ref([]); const ticketsOptions = ref([]); const clientsOptions = ref([]); +const isLoading = computed(() => formModelPopupRef.value?.isLoading); -const onDataSaved = (formData, requestResponse) => { +const onDataSaved = async (formData, requestResponse) => { emit('onDataSaved', formData, requestResponse); - router.push({ name: 'InvoiceOutSummary', params: { id: requestResponse.id } }); + if (requestResponse && requestResponse.id) + router.push({ name: 'InvoiceOutSummary', params: { id: requestResponse.id } }); }; </script> @@ -57,6 +59,7 @@ const onDataSaved = (formData, requestResponse) => { auto-load /> <FormModelPopup + ref="formModelPopupRef" :title="t('Create manual invoice')" url-create="InvoiceOuts/createManualInvoice" model="invoiceOut" @@ -64,6 +67,10 @@ const onDataSaved = (formData, requestResponse) => { @on-data-saved="onDataSaved" > <template #form-inputs="{ data }"> + <span v-if="isLoading" class="text-primary invoicing-text"> + <QIcon name="warning" class="fill-icon q-mr-sm" size="md" /> + {{ t('Invoicing in progress...') }} + </span> <VnRow class="row q-gutter-md q-mb-md"> <div class="col"> <VnSelectFilter @@ -142,6 +149,17 @@ const onDataSaved = (formData, requestResponse) => { </FormModelPopup> </template> +<style lang="scss" scoped> +.invoicing-text { + display: flex; + justify-content: center; + align-items: center; + color: $primary; + font-size: 24px; + margin-bottom: 8px; +} +</style> + <i18n> es: Create manual invoice: Crear factura manual @@ -152,4 +170,5 @@ es: Area: Area Reference: Referencia Or: O + Invoicing in progress...: Facturación en progreso... </i18n> diff --git a/src/components/FormModel.vue b/src/components/FormModel.vue index 9f5ae319c..ca7bd30e5 100644 --- a/src/components/FormModel.vue +++ b/src/components/FormModel.vue @@ -69,10 +69,6 @@ const $props = defineProps({ const emit = defineEmits(['onFetch', 'onDataSaved']); -defineExpose({ - save, -}); - const componentIsRendered = ref(false); onMounted(async () => { @@ -205,6 +201,11 @@ watch(formUrl, async () => { reset(); fetch(); }); + +defineExpose({ + save, + isLoading, +}); </script> <template> <div class="column items-center full-width"> diff --git a/src/components/FormModelPopup.vue b/src/components/FormModelPopup.vue index cc22c77db..2d8886610 100644 --- a/src/components/FormModelPopup.vue +++ b/src/components/FormModelPopup.vue @@ -1,5 +1,5 @@ <script setup> -import { ref } from 'vue'; +import { ref, computed } from 'vue'; import { useI18n } from 'vue-i18n'; import FormModel from 'components/FormModel.vue'; @@ -39,21 +39,28 @@ const $props = defineProps({ const { t } = useI18n(); +const formModelRef = ref(null); const closeButton = ref(null); -const isLoading = ref(false); const onDataSaved = (formData, requestResponse) => { emit('onDataSaved', formData, requestResponse); closeForm(); }; -const closeForm = () => { +const isLoading = computed(() => formModelRef.value?.isLoading); + +const closeForm = async () => { if (closeButton.value) closeButton.value.click(); }; + +defineExpose({ + isLoading, +}); </script> <template> <FormModel + ref="formModelRef" :form-initial-data="formInitialData" :observe-form-changes="false" :default-actions="false" diff --git a/src/css/app.scss b/src/css/app.scss index 38dd642a3..388492432 100644 --- a/src/css/app.scss +++ b/src/css/app.scss @@ -97,6 +97,10 @@ select:-webkit-autofill { background-color: var(--vn-light-gray); } +.fill-icon { + font-variation-settings: 'FILL' 1; +} + /* Estilo para el asterisco en campos requeridos */ .q-field.required .q-field__label:after { content: ' *'; From 049e3c722a897e48bb8dbc118b14eaaf3e0962f7 Mon Sep 17 00:00:00 2001 From: wbuezas <wbuezas@verdnatura.es> Date: Fri, 8 Mar 2024 15:09:28 -0300 Subject: [PATCH 22/42] Fix translation --- src/pages/InvoiceOut/InvoiceOutList.vue | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/pages/InvoiceOut/InvoiceOutList.vue b/src/pages/InvoiceOut/InvoiceOutList.vue index 17b37b962..f193a6e8c 100644 --- a/src/pages/InvoiceOut/InvoiceOutList.vue +++ b/src/pages/InvoiceOut/InvoiceOutList.vue @@ -241,7 +241,6 @@ es: fileDenied: El navegador denegó la descarga de archivos... fileAllowed: Descarga exitosa de archivo CSV youCanSearchByInvoiceReference: Puedes buscar por referencia de la factura - downloadPdf: Download PDF + downloadPdf: Descargar PDF createInvoice: Crear factura - </i18n> From 0c3dc30b8c329273fdcc79969cea991ec9c22e06 Mon Sep 17 00:00:00 2001 From: pablone <pablone@verdnatura.es> Date: Tue, 12 Mar 2024 09:49:58 +0100 Subject: [PATCH 23/42] fix(styles): refs #7001 create VnTitle and correct background-page color --- src/components/common/VnTitle.vue | 25 +++++++++++ src/css/app.scss | 2 +- src/pages/Claim/Card/ClaimSummary.vue | 10 +++-- src/pages/Entry/Card/EntrySummary.vue | 63 +-------------------------- 4 files changed, 34 insertions(+), 66 deletions(-) create mode 100644 src/components/common/VnTitle.vue diff --git a/src/components/common/VnTitle.vue b/src/components/common/VnTitle.vue new file mode 100644 index 000000000..1d53e47a1 --- /dev/null +++ b/src/components/common/VnTitle.vue @@ -0,0 +1,25 @@ +<script setup> +const $props = defineProps({ + url: { type: String, default: null }, + text: { type: String, default: null }, + icon: { type: String, default: null }, +}); +</script> +<template> + <div class="titleBox"> + <div class="header-link"> + <a :href="$props.url" class="link"> + {{ text }} + <QIcon :name="$props.icon" /> + </a> + </div> + </div> +</template> +<style scoped> +a { + font-size: large; +} +.titleBox { + padding-bottom: 2%; +} +</style> diff --git a/src/css/app.scss b/src/css/app.scss index 38dd642a3..459a7f2dc 100644 --- a/src/css/app.scss +++ b/src/css/app.scss @@ -18,7 +18,7 @@ body.body--light { body.body--dark { --vn-pageColor: #222; - --vn-SectionColor: #3c3b3b; + --vn-SectionColor: #403c3c; background-color: var(--vn-pageColor); --vn-text: white; --vn-gray: var(--vn-SectionColor); diff --git a/src/pages/Claim/Card/ClaimSummary.vue b/src/pages/Claim/Card/ClaimSummary.vue index bf6b57973..2d8592b6d 100644 --- a/src/pages/Claim/Card/ClaimSummary.vue +++ b/src/pages/Claim/Card/ClaimSummary.vue @@ -11,6 +11,7 @@ import VnLv from 'src/components/ui/VnLv.vue'; import ClaimNotes from 'src/pages/Claim/Card/ClaimNotes.vue'; import VnUserLink from 'src/components/ui/VnUserLink.vue'; import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue'; +import VnTitle from 'src/components/common/VnTitle.vue'; const route = useRoute(); const { t } = useI18n(); @@ -179,10 +180,11 @@ function openDialog(dmsId) { </template> <template #body="{ entity: { claim, salesClaimed, developments } }"> <QCard class="vn-one"> - <a class="header header-link" :href="`#/claim/${entityId}/basic-data`"> - {{ t('claim.pageTitles.basicData') }} - <QIcon name="open_in_new" /> - </a> + <VnTitle + :url="`#/claim/${entityId}/basic-data`" + :text="t('claim.pageTitles.basicData')" + icon="open_in_new" + /> <VnLv :label="t('claim.summary.created')" :value="toDate(claim.created)" diff --git a/src/pages/Entry/Card/EntrySummary.vue b/src/pages/Entry/Card/EntrySummary.vue index b6863f8f7..be30468d5 100644 --- a/src/pages/Entry/Card/EntrySummary.vue +++ b/src/pages/Entry/Card/EntrySummary.vue @@ -175,8 +175,8 @@ const fetchEntryBuys = async () => { <template #body> <QCard class="vn-one"> - <a class="header header-link" :href="`#/entry/${entityId}/basic-data`"> - {{ t('globals.summary.basicData') }} + <a class="header link" :href="`#/entry/${entityId}/basic-data`"> + textos <QIcon name="open_in_new" /> </a> @@ -274,65 +274,6 @@ const fetchEntryBuys = async () => { {{ t('entry.summary.buys') }} <QIcon name="open_in_new" /> </a> - <QTable - :rows="entryBuys" - :columns="entriesTableColumns" - hide-bottom - row-key="index" - class="full-width q-mt-md" - > - <template #body="{ cols, row, rowIndex }"> - <QTr no-hover> - <QTd v-for="col in cols" :key="col.name"> - <component - :is="tableColumnComponents[col.name].component(props)" - v-bind="tableColumnComponents[col.name].props(props)" - @click="tableColumnComponents[col.name].event(props)" - class="col-content" - > - <template - v-if=" - col.name !== 'observation' && - col.name !== 'isConfirmed' - " - >{{ col.value }}</template - > - <QTooltip v-if="col.toolTip">{{ - col.toolTip - }}</QTooltip> - </component> - </QTd> - </QTr> - <QTr no-hover> - <QTd> - <span>{{ row.item.itemType.code }}</span> - </QTd> - <QTd> - <span>{{ row.item.id }}</span> - </QTd> - <QTd> - <span>{{ row.item.size }}</span> - </QTd> - <QTd> - <span>{{ toCurrency(row.item.minPrice) }}</span> - </QTd> - <QTd colspan="6"> - <span>{{ row.item.concept }}</span> - <span v-if="row.item.subName" class="subName"> - {{ row.item.subName }} - </span> - <fetched-tags :item="row.item" :max-length="5" /> - </QTd> - </QTr> - <!-- Esta última row es utilizada para agregar un espaciado y así marcar una diferencia visual entre los diferentes buys --> - <QTr - v-if="rowIndex !== entryBuys.length - 1" - class="separation-row" - > - <QTd colspan="10" style="height: 24px" /> - </QTr> - </template> - </QTable> </QCard> </template> </CardSummary> From fff5e1849eaea53bc72a174b3eb6f4c618f7a7c3 Mon Sep 17 00:00:00 2001 From: wbuezas <wbuezas@verdnatura.es> Date: Tue, 12 Mar 2024 09:59:27 -0300 Subject: [PATCH 24/42] Delete unused form --- src/pages/InvoiceOut/Card/SendInvoiceForm.vue | 41 ------------------- 1 file changed, 41 deletions(-) delete mode 100644 src/pages/InvoiceOut/Card/SendInvoiceForm.vue diff --git a/src/pages/InvoiceOut/Card/SendInvoiceForm.vue b/src/pages/InvoiceOut/Card/SendInvoiceForm.vue deleted file mode 100644 index 3956dab08..000000000 --- a/src/pages/InvoiceOut/Card/SendInvoiceForm.vue +++ /dev/null @@ -1,41 +0,0 @@ -<script setup> -import { ref } from 'vue'; -import { useI18n } from 'vue-i18n'; - -import VnRow from 'components/ui/VnRow.vue'; -import VnInput from 'src/components/common/VnInput.vue'; -import FormPopup from 'src/components/FormPopup.vue'; - -const emit = defineEmits(['onDataSaved']); - -const { t } = useI18n(); - -const email = ref(null); - -const onDataSaved = (dataSaved) => { - emit('onDataSaved', dataSaved); -}; -</script> - -<template> - <FormPopup - :title="t('New thermograph')" - :subtitle="t('Are you sure you want to send it?')" - @on-data-saved="onDataSaved($event)" - > - <template #form-inputs> - <VnRow class="row q-gutter-md q-mb-md"> - <div class="col"> - <VnInput :label="t('Email')" v-model="email" type="email" /> - </div> - </VnRow> - </template> - </FormPopup> -</template> - -<i18n> -es: - Email: Email - Confirm: Confirmar - Are you sure you want to send it?: ¿Seguro que quieres enviarlo? -</i18n> From 06fa4aebc5b095e3b7f78736bf9b73350a5dc567 Mon Sep 17 00:00:00 2001 From: wbuezas <wbuezas@verdnatura.es> Date: Tue, 12 Mar 2024 11:40:06 -0300 Subject: [PATCH 25/42] add invoice out list download icon --- src/pages/InvoiceOut/InvoiceOutList.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/InvoiceOut/InvoiceOutList.vue b/src/pages/InvoiceOut/InvoiceOutList.vue index f193a6e8c..cf33b2cec 100644 --- a/src/pages/InvoiceOut/InvoiceOutList.vue +++ b/src/pages/InvoiceOut/InvoiceOutList.vue @@ -134,10 +134,10 @@ const openCreateInvoiceModal = () => { <template #st-actions> <QBtn @click="openPdf()" - class="q-mr-xl" + class="q-mr-md" color="primary" + icon="cloud_download" :disable="selectedCards.size === 0" - :label="t('globals.download')" > <QTooltip>{{ t('downloadPdf') }}</QTooltip> </QBtn> From 09e18dfc017e2210f18e994e5cea31b3bd88bbb7 Mon Sep 17 00:00:00 2001 From: alexm <alexm@verdnatura.es> Date: Thu, 14 Mar 2024 09:07:34 +0100 Subject: [PATCH 26/42] refs #7033 deploy(2412): dev to test --- test/cypress/integration/worker/workerList.spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/cypress/integration/worker/workerList.spec.js b/test/cypress/integration/worker/workerList.spec.js index b5c57f920..bc4b2383e 100644 --- a/test/cypress/integration/worker/workerList.spec.js +++ b/test/cypress/integration/worker/workerList.spec.js @@ -16,7 +16,7 @@ describe('WorkerList', () => { it('should open the worker summary', () => { cy.openListSummary(0); cy.get('.summaryHeader div').should('have.text', '1110 - Jessica Jones'); - cy.get('.summary .header').eq(0).invoke('text').should('include', 'Basic data'); - cy.get('.summary .header').eq(1).should('have.text', 'User data'); + cy.get('.summary .header-link').eq(0).invoke('text').should('include', 'Basic data'); + cy.get('.summary .header-link').eq(1).should('have.text', 'User data'); }); }); From 78e3cff397201b110203925299b669f34ad146ae Mon Sep 17 00:00:00 2001 From: alexm <alexm@verdnatura.es> Date: Thu, 14 Mar 2024 09:08:27 +0100 Subject: [PATCH 27/42] refs #7033 deploy: init version 2414 --- CHANGELOG.md | 8 ++++++++ package.json | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a679cdfc..dbf6bdcc3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2414.01] - 2024-04-04 + +### Added + +### Changed + +### Fixed + ## [2400.01] - 2024-01-04 ### Added diff --git a/package.json b/package.json index beae0b7b9..a35020b66 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "salix-front", - "version": "24.12.0", + "version": "24.14.0", "description": "Salix frontend", "productName": "Salix", "author": "Verdnatura", From f1d21915eb55bc76b3bc21f821418a111f0f22e8 Mon Sep 17 00:00:00 2001 From: Javier Segarra <jsegarra@verdnatura.es> Date: Thu, 14 Mar 2024 09:28:28 +0000 Subject: [PATCH 28/42] fix vnlocation.spec --- test/cypress/integration/VnLocation.spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/cypress/integration/VnLocation.spec.js b/test/cypress/integration/VnLocation.spec.js index 02b924e4d..5892e3ad5 100644 --- a/test/cypress/integration/VnLocation.spec.js +++ b/test/cypress/integration/VnLocation.spec.js @@ -40,9 +40,9 @@ describe('VnLocation', () => { cy.waitForElement('.q-card'); }); - it('Show all options', function() { + it('Show locations options', function() { cy.get(inputLocation).click(); - cy.get(locationOptions).should('have.length', 1); + cy.get(locationOptions).should('have.length', 5); }); }); }) From 00a47cd5b254ea73750a58176b7d275bf1e1b235 Mon Sep 17 00:00:00 2001 From: pablone <pablone@verdnatura.es> Date: Thu, 14 Mar 2024 15:06:06 +0100 Subject: [PATCH 29/42] refactor(style): refs #7001 add style font vnTitle vnChip --- src/components/NavBar.vue | 2 +- src/components/common/VnBreadcrumbs.vue | 2 +- src/components/common/VnChip.vue | 13 +++ src/components/common/VnDmsList.vue | 2 +- src/components/common/VnLog.vue | 21 ++--- src/components/common/VnSelectDialog.vue | 2 +- src/components/common/VnSmsDialog.vue | 5 +- src/components/common/VnTitle.vue | 14 ++-- src/components/ui/CardDescriptor.vue | 10 +-- src/components/ui/CardList.vue | 16 ++-- src/components/ui/CardSummary.vue | 12 +-- src/components/ui/VnSearchbar.vue | 2 +- src/components/ui/VnSms.vue | 8 +- src/css/app.scss | 51 ++++++------ src/css/quasar.variables.scss | 8 +- src/pages/Claim/Card/ClaimDescriptor.vue | 6 +- src/pages/Claim/Card/ClaimLines.vue | 13 +-- src/pages/Claim/Card/ClaimSummary.vue | 48 ++++++----- src/pages/Claim/ClaimList.vue | 6 +- .../Customer/Card/CustomerConsignees.vue | 4 +- src/pages/Customer/Card/CustomerGreuges.vue | 4 +- src/pages/Customer/Card/CustomerNotes.vue | 4 +- .../Customer/Card/CustomerRecoveries.vue | 4 +- src/pages/Customer/Card/CustomerSummary.vue | 81 +++++++------------ .../Defaulter/CustomerBalanceDueTotal.vue | 6 +- .../Customer/Payments/CustomerPayments.vue | 3 +- .../Department/Card/DepartmentSummary.vue | 12 ++- src/pages/Entry/Card/EntryBuys.vue | 2 +- src/pages/Entry/Card/EntrySummary.vue | 25 +++--- src/pages/Entry/EntryLatestBuysFilter.vue | 2 +- src/pages/InvoiceIn/Card/InvoiceInSummary.vue | 63 +++++++-------- .../InvoiceOut/Card/InvoiceOutSummary.vue | 16 +--- src/pages/InvoiceOut/InvoiceOutGlobal.vue | 4 +- src/pages/Login/VerifyEmail.vue | 7 +- src/pages/Order/Card/OrderCatalogFilter.vue | 2 +- src/pages/Order/Card/OrderCatalogItem.vue | 6 +- src/pages/Order/Card/OrderSummary.vue | 2 +- src/pages/Order/OrderCatalog.vue | 2 +- src/pages/Order/OrderLines.vue | 16 ++-- src/pages/Order/OrderList.vue | 2 +- src/pages/Order/OrderVolume.vue | 4 +- src/pages/Route/Cmr/CmrList.vue | 1 + .../Supplier/Card/SupplierConsumption.vue | 2 +- src/pages/Supplier/Card/SupplierContacts.vue | 2 +- src/pages/Supplier/Card/SupplierSummary.vue | 3 +- src/pages/Ticket/Card/TicketDescriptor.vue | 5 +- src/pages/Ticket/Card/TicketSummary.vue | 62 +++++++------- src/pages/Ticket/TicketList.vue | 1 + src/pages/Travel/Card/TravelSummary.vue | 5 +- src/pages/Travel/TravelList.vue | 2 + src/pages/Worker/Card/WorkerSummary.vue | 13 ++- 51 files changed, 304 insertions(+), 304 deletions(-) create mode 100644 src/components/common/VnChip.vue diff --git a/src/components/NavBar.vue b/src/components/NavBar.vue index 12366e174..c51ed3024 100644 --- a/src/components/NavBar.vue +++ b/src/components/NavBar.vue @@ -106,7 +106,7 @@ const pinnedModulesRef = ref(); width: max-content; } .q-header { - background-color: var(--vn-dark); + background-color: var(--vn-section-color); } </style> <i18n> diff --git a/src/components/common/VnBreadcrumbs.vue b/src/components/common/VnBreadcrumbs.vue index 666f14c72..09bc198f7 100644 --- a/src/components/common/VnBreadcrumbs.vue +++ b/src/components/common/VnBreadcrumbs.vue @@ -71,7 +71,7 @@ function getBreadcrumb(param) { } &--last, &__separator { - color: var(--vn-label); + color: var(--vn-label-color); } } @media (max-width: $breakpoint-md) { diff --git a/src/components/common/VnChip.vue b/src/components/common/VnChip.vue new file mode 100644 index 000000000..dd2de2c64 --- /dev/null +++ b/src/components/common/VnChip.vue @@ -0,0 +1,13 @@ +<script setup> +const $props = defineProps({ + color: { type: String, default: null }, + text: { type: String, default: null }, + dense: { type: String, default: null }, + textColor: { type: String, default: 'black' }, +}); +</script> +<template> + <QChip :color="$props.color" :text-color="textColor" :dense="$props.dense">{{ + text + }}</QChip> +</template> diff --git a/src/components/common/VnDmsList.vue b/src/components/common/VnDmsList.vue index 5057c0790..07940274e 100644 --- a/src/components/common/VnDmsList.vue +++ b/src/components/common/VnDmsList.vue @@ -304,7 +304,7 @@ function parseDms(data) { row-gap: 20px; } .labelColor { - color: var(--vn-label); + color: var(--vn-label-color); } </style> <i18n> diff --git a/src/components/common/VnLog.vue b/src/components/common/VnLog.vue index eae391cc4..732f0e964 100644 --- a/src/components/common/VnLog.vue +++ b/src/components/common/VnLog.vue @@ -14,6 +14,7 @@ import VnJsonValue from '../common/VnJsonValue.vue'; import FetchData from '../FetchData.vue'; import VnSelectFilter from './VnSelectFilter.vue'; import VnUserLink from '../ui/VnUserLink.vue'; +import VnChip from '../common/VnChip.vue'; const stateStore = useStateStore(); const validationsStore = useValidator(); @@ -443,10 +444,10 @@ setLogTree(); > <QItemSection> <QItemLabel class="model-info q-mb-xs" v-if="!byRecord"> - <QChip - dense + <VnChip size="md" - class="model-name q-mr-xs text-white" + text-color="white" + class="model-name q-mr-xs" v-if=" !(modelLog.changedModel && modelLog.changedModelId) && modelLog.model @@ -455,9 +456,9 @@ setLogTree(); backgroundColor: useColor(modelLog.model), }" :title="modelLog.model" - > - {{ t(modelLog.modelI18n) }} - </QChip> + :text="t(modelLog.modelI18n)" + dense="dense" + /> <span class="model-id" v-if="modelLog.id" >#{{ modelLog.id }}</span > @@ -819,7 +820,7 @@ setLogTree(); </template> <style lang="scss" scoped> .q-card { - background-color: var(--vn-gray); + background-color: var(--vn-section-color); } .q-item { min-height: 0px; @@ -916,7 +917,7 @@ setLogTree(); font-style: italic; } .model-id { - color: var(--vn-label); + color: var(--vn-label-color); font-size: 0.9rem; } .q-btn { @@ -942,7 +943,7 @@ setLogTree(); } .change-info { overflow: hidden; - background-color: var(--vn-dark); + background-color: var(--vn-section-color); & > .date { overflow: hidden; white-space: nowrap; @@ -981,7 +982,7 @@ setLogTree(); position: relative; overflow: hidden; text-overflow: ellipsis; - background-color: var(--vn-gray); + background-color: var(--vn-section-color); white-space: nowrap; box-sizing: border-box; & > .q-icon { diff --git a/src/components/common/VnSelectDialog.vue b/src/components/common/VnSelectDialog.vue index 355a25109..770173728 100644 --- a/src/components/common/VnSelectDialog.vue +++ b/src/components/common/VnSelectDialog.vue @@ -79,7 +79,7 @@ const toggleForm = () => { border-radius: 50px; &.--add-icon { - color: var(--vn-text); + color: var(--vn-text-color); background-color: $primary; } } diff --git a/src/components/common/VnSmsDialog.vue b/src/components/common/VnSmsDialog.vue index 59021cef4..3027b14c7 100644 --- a/src/components/common/VnSmsDialog.vue +++ b/src/components/common/VnSmsDialog.vue @@ -4,6 +4,7 @@ import { useI18n } from 'vue-i18n'; import { useDialogPluginComponent } from 'quasar'; import VnInput from 'src/components/common/VnInput.vue'; +import VnChip from 'src/components/common/VnChip.vue'; const { dialogRef, onDialogOK } = useDialogPluginComponent(); const { t, availableLocales } = useI18n(); @@ -137,9 +138,7 @@ async function send() { /> </template> <template #counter> - <QChip :color="color" dense> - {{ totalLength }}/{{ maxLength }} - </QChip> + <VnChip :color="color" :text="totalLength + '/' + maxLength" /> </template> </QInput> </QCardSection> diff --git a/src/components/common/VnTitle.vue b/src/components/common/VnTitle.vue index 1d53e47a1..8e994eb92 100644 --- a/src/components/common/VnTitle.vue +++ b/src/components/common/VnTitle.vue @@ -2,20 +2,24 @@ const $props = defineProps({ url: { type: String, default: null }, text: { type: String, default: null }, - icon: { type: String, default: null }, + icon: { type: String, default: 'open_in_new' }, }); </script> <template> <div class="titleBox"> <div class="header-link"> - <a :href="$props.url" class="link"> - {{ text }} - <QIcon :name="$props.icon" /> + <a :href="$props.url" :class="$props.url ? 'link' : 'normalTitle'"> + {{ $props.text }} + <QIcon v-if="url" :name="$props.icon" /> </a> </div> </div> </template> -<style scoped> +<style scoped lang="scss"> +.normalTitle { + color: whitesmoke; + cursor: auto; +} a { font-size: large; } diff --git a/src/components/ui/CardDescriptor.vue b/src/components/ui/CardDescriptor.vue index c53193e6f..e5e4baae4 100644 --- a/src/components/ui/CardDescriptor.vue +++ b/src/components/ui/CardDescriptor.vue @@ -171,7 +171,7 @@ const emit = defineEmits(['onFetch']); <style lang="scss"> .body { - background-color: var(--vn-gray); + background-color: var(--vn-section-color); .text-h5 { padding-top: 5px; padding-bottom: 5px; @@ -187,7 +187,7 @@ const emit = defineEmits(['onFetch']); display: flex; padding: 2px 16px; .label { - color: var(--vn-label); + color: var(--vn-label-color); font-size: 12px; &:not(:has(a))::after { @@ -195,7 +195,7 @@ const emit = defineEmits(['onFetch']); } } .value { - color: var(--vn-text); + color: var(--vn-text-color); font-size: 14px; margin-left: 12px; overflow: hidden; @@ -220,13 +220,13 @@ const emit = defineEmits(['onFetch']); } } .subtitle { - color: var(--vn-text); + color: var(--vn-text-color); font-size: 16px; margin-bottom: 15px; } .list-box { .q-item__label { - color: var(--vn-label); + color: var(--vn-label-color); } } .descriptor { diff --git a/src/components/ui/CardList.vue b/src/components/ui/CardList.vue index eba69a952..9779c58eb 100644 --- a/src/components/ui/CardList.vue +++ b/src/components/ui/CardList.vue @@ -1,5 +1,6 @@ <script setup> import { useI18n } from 'vue-i18n'; +import VnChip from 'src/components/common/VnChip.vue'; const { t } = useI18n(); @@ -28,9 +29,12 @@ const toggleCardCheck = (item) => { <div class="title text-primary text-weight-bold text-h5"> {{ $props.title }} </div> - <QChip class="q-chip-color" outline size="sm"> - {{ t('ID') }}: {{ $props.id }} - </QChip> + <VnChip + :text="'ID:' + $props.id" + class="q-chip-color" + outline + size="sm" + /> </div> <QCheckbox v-if="showCheckbox" @@ -61,7 +65,7 @@ const toggleCardCheck = (item) => { } .q-chip-color { - color: var(--vn-label); + color: var(--vn-label-color) !important; } .card-list-body { @@ -75,7 +79,7 @@ const toggleCardCheck = (item) => { width: 50%; .label { width: 35%; - color: var(--vn-label); + color: var(--vn-label-color); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; @@ -117,7 +121,7 @@ const toggleCardCheck = (item) => { transition: background-color 0.2s; } .card:hover { - background-color: var(--vn-gray); + background-color: var(--vn-section-color); } .list-items { width: 75%; diff --git a/src/components/ui/CardSummary.vue b/src/components/ui/CardSummary.vue index aeca84c80..226981408 100644 --- a/src/components/ui/CardSummary.vue +++ b/src/components/ui/CardSummary.vue @@ -87,7 +87,7 @@ watch(props, async () => { justify-content: space-evenly; gap: 10px; padding: 10px; - background-color: var(--vn-gray); + background-color: var(--vn-section-color); > .q-card.vn-one { flex: 1; @@ -104,7 +104,7 @@ watch(props, async () => { > .q-card { width: 100%; - background-color: var(--vn-gray); + background-color: var(--vn-section-color); padding: 7px; font-size: 16px; min-width: 275px; @@ -114,7 +114,7 @@ watch(props, async () => { flex-direction: row; margin-top: 2px; .label { - color: var(--vn-label); + color: var(--vn-label-color); width: 8em; overflow: hidden; white-space: nowrap; @@ -124,7 +124,7 @@ watch(props, async () => { flex-shrink: 0; } .value { - color: var(--vn-text); + color: var(--vn-text-color); overflow: hidden; } } @@ -143,12 +143,12 @@ watch(props, async () => { margin-bottom: 9px; & .q-checkbox__label { margin-left: 31px; - color: var(--vn-text); + color: var(--vn-text-color); } & .q-checkbox__inner { position: absolute; left: 0; - color: var(--vn-label); + color: var(--vn-label-color); } } } diff --git a/src/components/ui/VnSearchbar.vue b/src/components/ui/VnSearchbar.vue index f06b44334..ee0313143 100644 --- a/src/components/ui/VnSearchbar.vue +++ b/src/components/ui/VnSearchbar.vue @@ -158,7 +158,7 @@ async function search() { } #searchbar { .q-field--standout.q-field--highlighted .q-field__control { - background-color: var(--vn-text); + background-color: var(--vn-text-color); } } </style> diff --git a/src/components/ui/VnSms.vue b/src/components/ui/VnSms.vue index ceb24b2bb..d45eef103 100644 --- a/src/components/ui/VnSms.vue +++ b/src/components/ui/VnSms.vue @@ -4,6 +4,7 @@ import { date } from 'quasar'; import VnPaginate from 'src/components/ui/VnPaginate.vue'; import VnAvatar from '../ui/VnAvatar.vue'; import VnUserLink from 'src/components/ui/VnUserLink.vue'; +import VnChip from '../common/VnChip.vue'; const $props = defineProps({ url: { type: String, default: null }, @@ -89,15 +90,14 @@ function formatNumber(number) { ) }}</QItemLabel> <QItemLabel class="row center"> - <QChip + <VnChip :color=" row.sms.status == 'OK' ? 'positive' : 'negative' " - > - {{ row.sms.status }} - </QChip> + :text="row.sms.status" + /> </QItemLabel> </QItemSection> </QItem> diff --git a/src/css/app.scss b/src/css/app.scss index 459a7f2dc..7d8a29920 100644 --- a/src/css/app.scss +++ b/src/css/app.scss @@ -2,29 +2,24 @@ @import './icons.scss'; body.body--light { - --fount-color: black; - --vn-sectionColor: #ffffff; - --vn-pageColor: #e0e0e0; - background-color: var(--vn-pageColor); + --font-color: black; + --vn-section-color: #e0e0e0; + --vn-page-color: #ffffff; + background-color: #ffffff; .q-header .q-toolbar { - color: var(--fount-color); + color: var(--font-color); } - --vn-text: var(--fount-color); - --vn-gray: var(--vn-sectionColor); - --vn-label: #5f5f5f; - --vn-dark: var(--vn-sectionColor); - --vn-light-gray: #e7e3e3; + --vn-text-color: var(--font-color); + --vn-label-color: #5f5f5f; + --vn-accent-color: #e7e3e3; } body.body--dark { - --vn-pageColor: #222; - --vn-SectionColor: #403c3c; - background-color: var(--vn-pageColor); - --vn-text: white; - --vn-gray: var(--vn-SectionColor); - --vn-label: #a8a8a8; - --vn-dark: var(--vn-SectionColor); - --vn-light-gray: #424242; + --vn-section-color: #403c3c; + background-color: #222; + --vn-text-color: white; + --vn-label-color: #a8a8a8; + --vn-accent-color: #424242; } a { @@ -59,19 +54,23 @@ a { // Removes chrome autofill background input:-webkit-autofill, select:-webkit-autofill { - color: var(--vn-text); + color: var(--vn-text-color); font-family: $typography-font-family; - -webkit-text-fill-color: var(--vn-text); + -webkit-text-fill-color: var(--vn-text-color); -webkit-background-clip: text !important; background-clip: text !important; } .bg-vn-dark { - background-color: var(--vn-dark); + background-color: var(--vn-section-color); +} + +.bg-vn-dark { + background-color: var(--vn-section-color); } .color-vn-text { - color: var(--vn-text); + color: var(--vn-text-color); } .color-vn-white { @@ -79,8 +78,8 @@ select:-webkit-autofill { } .vn-card { - background-color: var(--vn-gray); - color: var(--vn-text); + background-color: var(--vn-section-color); + color: var(--vn-text-color); border-radius: 8px; } @@ -90,11 +89,11 @@ select:-webkit-autofill { } .bg-vn-primary-row { - background-color: var(--vn-dark); + background-color: var(--vn-section-color); } .bg-vn-secondary-row { - background-color: var(--vn-light-gray); + background-color: var(--vn-accent-color); } /* Estilo para el asterisco en campos requeridos */ diff --git a/src/css/quasar.variables.scss b/src/css/quasar.variables.scss index b70e3e8d0..8423a9a35 100644 --- a/src/css/quasar.variables.scss +++ b/src/css/quasar.variables.scss @@ -14,10 +14,10 @@ // Tip: to add new colors https://quasar.dev/style/color-palette/#adding-your-own-colors $primary: #ec8916; $secondary: $primary; -$positive: #21ba45; -$negative: #c10015; -$info: #31ccec; -$warning: #f2c037; +$positive: #c8e484; +$negative: #fb5252; +$info: #84d0e2; +$warning: #f4b974; // Pendiente de cuadrar con la base de datos $success: $positive; $alert: $negative; diff --git a/src/pages/Claim/Card/ClaimDescriptor.vue b/src/pages/Claim/Card/ClaimDescriptor.vue index b5b9aae99..968f1e294 100644 --- a/src/pages/Claim/Card/ClaimDescriptor.vue +++ b/src/pages/Claim/Card/ClaimDescriptor.vue @@ -107,7 +107,11 @@ onMounted(async () => { <template #body="{ entity }"> <VnLv v-if="entity.claimState" :label="t('claim.card.state')"> <template #value> - <QBadge :color="stateColor(entity.claimState.code)" dense> + <QBadge + :color="stateColor(entity.claimState.code)" + text-color="black" + dense + > {{ entity.claimState.description }} </QBadge> </template> diff --git a/src/pages/Claim/Card/ClaimLines.vue b/src/pages/Claim/Card/ClaimLines.vue index 90dd31199..248b5a69a 100644 --- a/src/pages/Claim/Card/ClaimLines.vue +++ b/src/pages/Claim/Card/ClaimLines.vue @@ -12,6 +12,7 @@ import FetchData from 'components/FetchData.vue'; import VnDiscount from 'components/common/vnDiscount.vue'; import ClaimLinesImport from './ClaimLinesImport.vue'; import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue'; +import VnChip from 'src/components/common/VnChip.vue'; const quasar = useQuasar(); const route = useRoute(); @@ -161,16 +162,16 @@ function showImportDialog() { <div class="row q-gutter-md"> <div> {{ t('Amount') }} - <QChip :dense="$q.screen.lt.sm"> - {{ toCurrency(amount) }} - </QChip> + <VnChip :dense="$q.screen.lt.sm" :text="toCurrency(amount)" /> </div> <QSeparator dark vertical /> <div> {{ t('Amount Claimed') }} - <QChip color="positive" :dense="$q.screen.lt.sm"> - {{ toCurrency(amountClaimed) }} - </QChip> + <VnChip + color="positive" + :dense="$q.screen.lt.sm" + :text="toCurrency(amountClaimed)" + /> </div> </div> </Teleport> diff --git a/src/pages/Claim/Card/ClaimSummary.vue b/src/pages/Claim/Card/ClaimSummary.vue index 2d8592b6d..4e690526b 100644 --- a/src/pages/Claim/Card/ClaimSummary.vue +++ b/src/pages/Claim/Card/ClaimSummary.vue @@ -12,6 +12,7 @@ import ClaimNotes from 'src/pages/Claim/Card/ClaimNotes.vue'; import VnUserLink from 'src/components/ui/VnUserLink.vue'; import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue'; import VnTitle from 'src/components/common/VnTitle.vue'; +import VnChip from 'src/components/common/VnChip.vue'; const route = useRoute(); const { t } = useI18n(); @@ -183,7 +184,6 @@ function openDialog(dmsId) { <VnTitle :url="`#/claim/${entityId}/basic-data`" :text="t('claim.pageTitles.basicData')" - icon="open_in_new" /> <VnLv :label="t('claim.summary.created')" @@ -191,9 +191,11 @@ function openDialog(dmsId) { /> <VnLv :label="t('claim.summary.state')"> <template #value> - <QChip :color="stateColor(claim.claimState.code)" dense> - {{ claim.claimState.description }} - </QChip> + <VnChip + :color="stateColor(claim.claimState.code)" + :text="claim.claimState.description" + dense="dense" + /> </template> </VnLv> <VnLv :label="t('globals.salesPerson')"> @@ -227,10 +229,10 @@ function openDialog(dmsId) { /> </QCard> <QCard class="vn-three"> - <a class="header header-link" :href="`#/claim/${entityId}/notes`"> - {{ t('claim.summary.notes') }} - <QIcon name="open_in_new" /> - </a> + <VnTitle + :url="`#/claim/${entityId}/notes`" + :text="t('claim.summary.notes')" + /> <ClaimNotes :id="entityId" :add-note="false" @@ -239,10 +241,10 @@ function openDialog(dmsId) { /> </QCard> <QCard class="vn-two" v-if="salesClaimed.length > 0"> - <a class="header header-link" :href="`#/claim/${entityId}/lines`"> - {{ t('claim.summary.details') }} - <QIcon name="open_in_new" /> - </a> + <VnTitle + :url="`#/claim/${entityId}/lines`" + :text="t('claim.summary.details')" + /> <QTable :columns="detailsColumns" :rows="salesClaimed" @@ -281,11 +283,10 @@ function openDialog(dmsId) { </QTable> </QCard> <QCard class="vn-two" v-if="developments.length > 0"> - <a class="header header-link" :href="claimUrl + 'development'"> - {{ t('claim.summary.development') }} - <QIcon name="open_in_new" /> - </a> - + <VnTitle + :url="claimUrl + 'development'" + :text="t('claim.summary.development')" + /> <QTable :columns="developmentColumns" :rows="developments" @@ -304,10 +305,10 @@ function openDialog(dmsId) { </QTable> </QCard> <QCard class="vn-max" v-if="claimDms.length > 0"> - <a class="header header-link" :href="`#/claim/${entityId}/photos`"> - {{ t('claim.summary.photos') }} - <QIcon name="open_in_new" /> - </a> + <VnTitle + :url="`#/claim/${entityId}/photos`" + :text="t('claim.summary.photos')" + /> <div class="container"> <div class="multimedia-container" @@ -347,10 +348,7 @@ function openDialog(dmsId) { </QCard> <QCard class="vn-max"> - <a class="header header-link" :href="claimUrl + 'action'"> - {{ t('claim.summary.actions') }} - <QIcon name="open_in_new" class="link" /> - </a> + <VnTitle :url="claimUrl + 'action'" :text="t('claim.summary.actions')" /> <div id="slider-container" class="q-px-xl q-py-md"> <QSlider v-model="claim.responsibility" diff --git a/src/pages/Claim/ClaimList.vue b/src/pages/Claim/ClaimList.vue index 6a793314f..f8ba8d541 100644 --- a/src/pages/Claim/ClaimList.vue +++ b/src/pages/Claim/ClaimList.vue @@ -108,7 +108,11 @@ function navigate(event, id) { /> <VnLv :label="t('claim.list.state')"> <template #value> - <QBadge :color="stateColor(row.stateCode)" dense> + <QBadge + text-color="black" + :color="stateColor(row.stateCode)" + dense + > {{ row.stateDescription }} </QBadge> </template> diff --git a/src/pages/Customer/Card/CustomerConsignees.vue b/src/pages/Customer/Card/CustomerConsignees.vue index ad666ff32..6713d53a3 100644 --- a/src/pages/Customer/Card/CustomerConsignees.vue +++ b/src/pages/Customer/Card/CustomerConsignees.vue @@ -150,14 +150,14 @@ const toCustomerConsigneeEdit = (consigneeId) => { <style lang="scss" scoped> .consignees-card { - border: 2px solid var(--vn-light-gray); + border: 2px solid var(--vn-accent-color); border-radius: 10px; padding: 10px; display: flex; cursor: pointer; &:hover { - background-color: var(--vn-light-gray); + background-color: var(--vn-accent-color); } } </style> diff --git a/src/pages/Customer/Card/CustomerGreuges.vue b/src/pages/Customer/Card/CustomerGreuges.vue index d92d7b4ee..158f418ba 100644 --- a/src/pages/Customer/Card/CustomerGreuges.vue +++ b/src/pages/Customer/Card/CustomerGreuges.vue @@ -180,13 +180,13 @@ const toCustomerGreugeCreate = () => { <style lang="scss"> .consignees-card { - border: 2px solid var(--vn-light-gray); + border: 2px solid var(--vn-accent-color); border-radius: 10px; padding: 10px; } .label-color { - color: var(--vn-label); + color: var(--vn-label-color); } </style> diff --git a/src/pages/Customer/Card/CustomerNotes.vue b/src/pages/Customer/Card/CustomerNotes.vue index 781c57e50..9c1a07ca3 100644 --- a/src/pages/Customer/Card/CustomerNotes.vue +++ b/src/pages/Customer/Card/CustomerNotes.vue @@ -85,12 +85,12 @@ const toCustomerNoteCreate = () => { <style lang="scss"> .custom-border { - border: 2px solid var(--vn-light-gray); + border: 2px solid var(--vn-accent-color); border-radius: 10px; padding: 10px; } .label-color { - color: var(--vn-label); + color: var(--vn-label-color); } </style> diff --git a/src/pages/Customer/Card/CustomerRecoveries.vue b/src/pages/Customer/Card/CustomerRecoveries.vue index 7247145f2..886968290 100644 --- a/src/pages/Customer/Card/CustomerRecoveries.vue +++ b/src/pages/Customer/Card/CustomerRecoveries.vue @@ -137,13 +137,13 @@ const toCustomerRecoverieCreate = () => { <style lang="scss"> .consignees-card { - border: 2px solid var(--vn-light-gray); + border: 2px solid var(--vn-accent-color); border-radius: 10px; padding: 10px; } .label-color { - color: var(--vn-label); + color: var(--vn-label-color); } </style> diff --git a/src/pages/Customer/Card/CustomerSummary.vue b/src/pages/Customer/Card/CustomerSummary.vue index 184b990b6..504404f5a 100644 --- a/src/pages/Customer/Card/CustomerSummary.vue +++ b/src/pages/Customer/Card/CustomerSummary.vue @@ -7,6 +7,7 @@ import CardSummary from 'components/ui/CardSummary.vue'; import { getUrl } from 'src/composables/getUrl'; import VnLv from 'src/components/ui/VnLv.vue'; import VnLinkPhone from 'src/components/ui/VnLinkPhone.vue'; +import VnTitle from 'src/components/common/VnTitle.vue'; const route = useRoute(); const { t } = useI18n(); @@ -62,10 +63,10 @@ const creditWarning = computed(() => { <CardSummary ref="summary" :url="`Clients/${entityId}/summary`"> <template #body="{ entity }"> <QCard class="vn-one"> - <a class="header header-link" :href="`#/customer/${entityId}/basic-data`"> - {{ t('customer.summary.basicData') }} - <QIcon name="open_in_new" /> - </a> + <VnTitle + :url="`#/customer/${entityId}/basic-data`" + :text="t('customer.summary.basicData')" + /> <VnLv :label="t('customer.summary.customerId')" :value="entity.id" /> <VnLv :label="t('customer.summary.name')" :value="entity.name" /> <VnLv :label="t('customer.summary.contact')" :value="entity.contact" /> @@ -96,13 +97,10 @@ const creditWarning = computed(() => { /> </QCard> <QCard class="vn-one"> - <a - class="header header-link" - :href="`#/customer/${entityId}/fiscal-data`" - > - {{ t('customer.summary.fiscalAddress') }} - <QIcon name="open_in_new" /> - </a> + <VnTitle + :url="`#/customer/${entityId}/fiscal-data`" + :text="t('customer.summary.fiscalAddress')" + /> <VnLv :label="t('customer.summary.socialName')" :value="entity.socialName" @@ -124,14 +122,10 @@ const creditWarning = computed(() => { <VnLv :label="t('customer.summary.street')" :value="entity.street" /> </QCard> <QCard class="vn-one"> - <a - class="header header-link" - :href="`#/customer/${entityId}/fiscal-data`" - link - > - {{ t('customer.summary.fiscalData') }} - <QIcon name="open_in_new" /> - </a> + <VnTitle + :url="`#/customer/${entityId}/fiscal-data`" + :text="t('customer.summary.fiscalData')" + /> <QCheckbox :label="t('customer.summary.isEqualizated')" v-model="entity.isEqualizated" @@ -169,14 +163,10 @@ const creditWarning = computed(() => { /> </QCard> <QCard class="vn-one"> - <a - class="header header-link" - :href="`#/customer/${entityId}/billing-data`" - link - > - {{ t('customer.summary.billingData') }} - <QIcon name="open_in_new" /> - </a> + <VnTitle + :url="`#/customer/${entityId}/billing-data`" + :text="t('customer.summary.billingData')" + /> <VnLv :label="t('customer.summary.payMethod')" :value="entity.payMethod.name" @@ -202,14 +192,10 @@ const creditWarning = computed(() => { /> </QCard> <QCard class="vn-one" v-if="entity.defaultAddress"> - <a - class="header header-link" - :href="`#/customer/${entityId}/consignees`" - link - > - {{ t('customer.summary.consignee') }} - <QIcon name="open_in_new" /> - </a> + <VnTitle + :url="`#/customer/${entityId}/consignees`" + :text="t('customer.summary.consignee')" + /> <VnLv :label="t('customer.summary.addressName')" :value="entity.defaultAddress.nickname" @@ -224,10 +210,10 @@ const creditWarning = computed(() => { /> </QCard> <QCard class="vn-one" v-if="entity.account"> - <a class="header header-link" :href="`#/customer/${entityId}/web-access`"> - {{ t('customer.summary.webAccess') }} - <QIcon name="open_in_new" /> - </a> + <VnTitle + :url="`#/customer/${entityId}/web-access`" + :text="t('customer.summary.webAccess')" + /> <VnLv :label="t('customer.summary.username')" :value="entity.account.name" @@ -239,9 +225,7 @@ const creditWarning = computed(() => { /> </QCard> <QCard class="vn-one" v-if="entity.account"> - <div class="header header-link"> - {{ t('customer.summary.businessData') }} - </div> + <VnTitle :text="t('customer.summary.businessData')" /> <VnLv :label="t('customer.summary.totalGreuge')" :value="toCurrency(entity.totalGreuge)" @@ -266,14 +250,11 @@ const creditWarning = computed(() => { /> </QCard> <QCard class="vn-one" v-if="entity.account"> - <a - class="header header-link" - :href="`https://grafana.verdnatura.es/d/40buzE4Vk/comportamiento-pagos-clientes?orgId=1&var-clientFk=${entityId}`" - link - > - {{ t('customer.summary.financialData') }} - <QIcon name="vn:grafana" /> - </a> + <VnTitle + :url="`https://grafana.verdnatura.es/d/40buzE4Vk/comportamiento-pagos-clientes?orgId=1&var-clientFk=${entityId}`" + :text="t('customer.summary.financialData')" + icon="vn:grafana" + /> <VnLv :label="t('customer.summary.risk')" :value="toCurrency(entity?.debt?.debt)" diff --git a/src/pages/Customer/Defaulter/CustomerBalanceDueTotal.vue b/src/pages/Customer/Defaulter/CustomerBalanceDueTotal.vue index c4a50a10f..c49ed5e32 100644 --- a/src/pages/Customer/Defaulter/CustomerBalanceDueTotal.vue +++ b/src/pages/Customer/Defaulter/CustomerBalanceDueTotal.vue @@ -30,16 +30,16 @@ const { t } = useI18n(); border: 1px solid black; } .title_balance { - color: var(--vn-text); + color: var(--vn-text-color); margin-top: 0; margin-bottom: 0; } .key_balance { - color: var(--vn-label); + color: var(--vn-label-color); margin-bottom: 0; } .value_balance { - color: var(--vn-text); + color: var(--vn-text-color); margin-bottom: 0; } </style> diff --git a/src/pages/Customer/Payments/CustomerPayments.vue b/src/pages/Customer/Payments/CustomerPayments.vue index eedaaf137..5a0404eef 100644 --- a/src/pages/Customer/Payments/CustomerPayments.vue +++ b/src/pages/Customer/Payments/CustomerPayments.vue @@ -196,7 +196,7 @@ function stateColor(row) { </template> <template #body-cell-state="{ row }"> <QTd auto-width class="text-center"> - <QBadge :color="stateColor(row)"> + <QBadge text-color="black" :color="stateColor(row)"> {{ row.isConfirmed ? t('Confirmed') @@ -227,6 +227,7 @@ function stateColor(row) { v-if="col.name == 'state'" > <QBadge + text-color="black" :color=" stateColor(row) " diff --git a/src/pages/Department/Card/DepartmentSummary.vue b/src/pages/Department/Card/DepartmentSummary.vue index d6fac56c6..1d42183c3 100644 --- a/src/pages/Department/Card/DepartmentSummary.vue +++ b/src/pages/Department/Card/DepartmentSummary.vue @@ -5,6 +5,7 @@ import { useI18n } from 'vue-i18n'; import CardSummary from 'components/ui/CardSummary.vue'; import { getUrl } from 'src/composables/getUrl'; import VnLv from 'src/components/ui/VnLv.vue'; +import VnTitle from 'src/components/common/VnTitle.vue'; const route = useRoute(); const { t } = useI18n(); @@ -36,13 +37,10 @@ onMounted(async () => { </template> <template #body="{ entity: department }"> <QCard class="column"> - <a - class="header header-link" - :href="`#/department/department/${entityId}/basic-data`" - > - {{ t('Basic data') }} - <QIcon name="open_in_new" /> - </a> + <VnTitle + :url="`#/department/department/${entityId}/basic-data`" + :text="t('Basic data')" + /> <div class="full-width row wrap justify-between content-between"> <div class="column" style="min-width: 50%"> <VnLv diff --git a/src/pages/Entry/Card/EntryBuys.vue b/src/pages/Entry/Card/EntryBuys.vue index 679afff1b..bd3bab78b 100644 --- a/src/pages/Entry/Card/EntryBuys.vue +++ b/src/pages/Entry/Card/EntryBuys.vue @@ -449,7 +449,7 @@ const showLockIcon = (groupingMode, mode) => { <style lang="scss" scoped> .separation-row { - background-color: var(--vn-gray) !important; + background-color: var(--vn-section-color) !important; } .grid-style-transition { transition: transform 0.28s, background-color 0.28s; diff --git a/src/pages/Entry/Card/EntrySummary.vue b/src/pages/Entry/Card/EntrySummary.vue index be30468d5..d89d7cf87 100644 --- a/src/pages/Entry/Card/EntrySummary.vue +++ b/src/pages/Entry/Card/EntrySummary.vue @@ -5,9 +5,8 @@ import { useI18n } from 'vue-i18n'; import CardSummary from 'components/ui/CardSummary.vue'; import VnLv from 'src/components/ui/VnLv.vue'; -import VnRow from 'components/ui/VnRow.vue'; import TravelDescriptorProxy from 'src/pages/Travel/Card/TravelDescriptorProxy.vue'; -import FetchedTags from 'components/ui/FetchedTags.vue'; +import VnTitle from 'src/components/common/VnTitle.vue'; import { toDate, toCurrency } from 'src/filters'; import { getUrl } from 'src/composables/getUrl'; @@ -164,7 +163,7 @@ const fetchEntryBuys = async () => { :url="`Entries/${entityId}/getEntry`" @on-fetch="(data) => setEntryData(data)" > - <template #header-left> + <template> <a class="header-link" :href="entryUrl"> <QIcon name="open_in_new" color="white" size="sm" /> </a> @@ -175,10 +174,10 @@ const fetchEntryBuys = async () => { <template #body> <QCard class="vn-one"> - <a class="header link" :href="`#/entry/${entityId}/basic-data`"> - textos - <QIcon name="open_in_new" /> - </a> + <VnTitle + :url="`#/entry/${entityId}/basic-data`" + :text="t('basic data')" + /> <VnLv :label="t('entry.summary.commission')" :value="entry.commission" /> @@ -219,10 +218,7 @@ const fetchEntryBuys = async () => { /> </QCard> <QCard class="vn-one"> - <a class="header header-link" :href="entryUrl"> - {{ t('Travel data') }} - <QIcon name="open_in_new" /> - </a> + <VnTitle :url="entryUrl" :text="t('Travel data')" /> <VnLv :label="t('entry.summary.travelReference')"> <template #value> @@ -270,10 +266,7 @@ const fetchEntryBuys = async () => { /> </QCard> <QCard class="vn-two" style="min-width: 100%"> - <a class="header header-link"> - {{ t('entry.summary.buys') }} - <QIcon name="open_in_new" /> - </a> + <VnTitle :text="t('entry.summary.buys')" /> </QCard> </template> </CardSummary> @@ -281,7 +274,7 @@ const fetchEntryBuys = async () => { <style lang="scss" scoped> .separation-row { - background-color: var(--vn-gray) !important; + background-color: var(--vn-section-color) !important; } </style> diff --git a/src/pages/Entry/EntryLatestBuysFilter.vue b/src/pages/Entry/EntryLatestBuysFilter.vue index 23361ffb3..5eaf001d8 100644 --- a/src/pages/Entry/EntryLatestBuysFilter.vue +++ b/src/pages/Entry/EntryLatestBuysFilter.vue @@ -412,7 +412,7 @@ const removeTag = (index, params, search) => { width: 60px; height: 60px; font-size: 1.4rem; - background-color: var(--vn-light-gray); + background-color: var(--vn-accent-color); &.active { background-color: $primary; diff --git a/src/pages/InvoiceIn/Card/InvoiceInSummary.vue b/src/pages/InvoiceIn/Card/InvoiceInSummary.vue index 6d2d11509..e30d9151c 100644 --- a/src/pages/InvoiceIn/Card/InvoiceInSummary.vue +++ b/src/pages/InvoiceIn/Card/InvoiceInSummary.vue @@ -6,6 +6,8 @@ import { toCurrency, toDate } from 'src/filters'; import { getUrl } from 'src/composables/getUrl'; import CardSummary from 'components/ui/CardSummary.vue'; import VnLv from 'src/components/ui/VnLv.vue'; +import VnChip from 'src/components/common/VnChip.vue'; +import VnTitle from 'src/components/common/VnTitle.vue'; onMounted(async () => { salixUrl.value = await getUrl(''); @@ -209,10 +211,10 @@ function getLink(param) { <!--Basic Data--> <QCard class="vn-one"> <QCardSection class="q-pa-none"> - <a class="header header-link" :href="getLink('basic-data')"> - {{ t('invoiceIn.pageTitles.basicData') }} - <QIcon name="open_in_new" /> - </a> + <VnTitle + :url="getLink('basic-data')" + :text="t('invoiceIn.pageTitles.basicData')" + /> </QCardSection> <VnLv :label="t('invoiceIn.summary.supplier')" @@ -233,10 +235,10 @@ function getLink(param) { </QCard> <QCard class="vn-one"> <QCardSection class="q-pa-none"> - <a class="header header-link" :href="getLink('basic-data')"> - {{ t('invoiceIn.pageTitles.basicData') }} - <QIcon name="open_in_new" /> - </a> + <VnTitle + :url="getLink('basic-data')" + :text="t('invoiceIn.pageTitles.basicData')" + /> </QCardSection> <VnLv :ellipsis-value="false" @@ -258,10 +260,10 @@ function getLink(param) { </QCard> <QCard class="vn-one"> <QCardSection class="q-pa-none"> - <a class="header header-link" :href="getLink('basic-data')"> - {{ t('invoiceIn.pageTitles.basicData') }} - <QIcon name="open_in_new" /> - </a> + <VnTitle + :url="getLink('basic-data')" + :text="t('invoiceIn.pageTitles.basicData')" + /> </QCardSection> <VnLv :label="t('invoiceIn.summary.sage')" @@ -283,10 +285,10 @@ function getLink(param) { </QCard> <QCard class="vn-one"> <QCardSection class="q-pa-none"> - <a class="header header-link" :href="getLink('basic-data')"> - {{ t('invoiceIn.pageTitles.basicData') }} - <QIcon name="open_in_new" /> - </a> + <VnTitle + :url="getLink('basic-data')" + :text="t('invoiceIn.pageTitles.basicData')" + /> </QCardSection> <QCardSection class="q-pa-none"> <div class="bordered q-px-sm q-mx-auto"> @@ -300,7 +302,7 @@ function getLink(param) { /> <VnLv :label="t('invoiceIn.summary.dueTotal')"> <template #value> - <QChip + <VnChip dense class="q-pa-xs" :color="amountsNotMatch ? 'negative' : 'transparent'" @@ -309,9 +311,8 @@ function getLink(param) { ? t('invoiceIn.summary.noMatch') : t('invoiceIn.summary.dueTotal') " - > - {{ toCurrency(invoiceIn.totals.totalDueDay) }} - </QChip> + :text="toCurrency(invoiceIn.totals.totalDueDay)" + /> </template> </VnLv> </div> @@ -319,10 +320,7 @@ function getLink(param) { </QCard> <!--Vat--> <QCard v-if="invoiceIn.invoiceInTax.length"> - <a class="header header-link" :href="getLink('vat')"> - {{ t('invoiceIn.card.vat') }} - <QIcon name="open_in_new" /> - </a> + <VnTitle :url="getLink('vat')" :text="t('invoiceIn.card.vat')" /> <QTable :columns="vatColumns" :rows="invoiceIn.invoiceInTax" @@ -352,10 +350,7 @@ function getLink(param) { </QCard> <!--Due Day--> <QCard v-if="invoiceIn.invoiceInDueDay.length"> - <a class="header header-link" :href="getLink('due-day')"> - {{ t('invoiceIn.card.dueDay') }} - <QIcon name="open_in_new" /> - </a> + <VnTitle :url="getLink('due-day')" :text="t('invoiceIn.card.dueDay')" /> <QTable class="full-width" :columns="dueDayColumns" @@ -382,10 +377,10 @@ function getLink(param) { </QCard> <!--Intrastat--> <QCard v-if="invoiceIn.invoiceInIntrastat.length"> - <a class="header header-link" :href="getLink('intrastat')"> - {{ t('invoiceIn.card.intrastat') }} - <QIcon name="open_in_new" /> - </a> + <VnTitle + :url="getLink('intrastat')" + :text="t('invoiceIn.card.intrastat')" + /> <QTable :columns="intrastatColumns" :rows="invoiceIn.invoiceInIntrastat" @@ -415,10 +410,10 @@ function getLink(param) { </template> <style lang="scss" scoped> .bg { - background-color: var(--vn-light-gray); + background-color: var(--vn-accent-color); } .bordered { - border: 1px solid var(--vn-text); + border: 1px solid var(--vn-text-color); max-width: 18em; } </style> diff --git a/src/pages/InvoiceOut/Card/InvoiceOutSummary.vue b/src/pages/InvoiceOut/Card/InvoiceOutSummary.vue index 73acc0ad1..311b029ad 100644 --- a/src/pages/InvoiceOut/Card/InvoiceOutSummary.vue +++ b/src/pages/InvoiceOut/Card/InvoiceOutSummary.vue @@ -7,6 +7,7 @@ import { toCurrency, toDate } from 'src/filters'; import CardSummary from 'components/ui/CardSummary.vue'; import VnLv from 'src/components/ui/VnLv.vue'; import { getUrl } from 'src/composables/getUrl'; +import VnTitle from 'src/components/common/VnTitle.vue'; onMounted(async () => { fetch(); @@ -101,10 +102,7 @@ const ticketsColumns = ref([ </template> <template #body="{ entity: { invoiceOut } }"> <QCard class="vn-one"> - <a class="header header-link"> - {{ t('invoiceOut.pageTitles.basicData') }} - <QIcon name="open_in_new" /> - </a> + <VnTitle :text="t('invoiceOut.pageTitles.basicData')" /> <VnLv :label="t('invoiceOut.summary.issued')" :value="toDate(invoiceOut.issued)" @@ -127,10 +125,7 @@ const ticketsColumns = ref([ /> </QCard> <QCard class="vn-three"> - <a class="header header-link"> - {{ t('invoiceOut.summary.taxBreakdown') }} - <QIcon name="open_in_new" /> - </a> + <VnTitle :text="t('invoiceOut.summary.taxBreakdown')" /> <QTable :columns="taxColumns" :rows="invoiceOut.taxesBreakdown" flat> <template #header="props"> <QTr :props="props"> @@ -142,10 +137,7 @@ const ticketsColumns = ref([ </QTable> </QCard> <QCard class="vn-three"> - <a class="header header-link"> - {{ t('invoiceOut.summary.tickets') }} - <QIcon name="open_in_new" /> - </a> + <VnTitle :text="t('invoiceOut.summary.tickets')" /> <QTable v-if="tickets" :columns="ticketsColumns" :rows="tickets" flat> <template #header="props"> <QTr :props="props"> diff --git a/src/pages/InvoiceOut/InvoiceOutGlobal.vue b/src/pages/InvoiceOut/InvoiceOutGlobal.vue index 7e2b43a76..6378ff8e5 100644 --- a/src/pages/InvoiceOut/InvoiceOutGlobal.vue +++ b/src/pages/InvoiceOut/InvoiceOutGlobal.vue @@ -156,7 +156,7 @@ onUnmounted(() => { display: flex; justify-content: center; width: 100%; - background-color: var(--vn-dark); + background-color: var(--vn-section-color); padding: 16px; .card-section { @@ -167,7 +167,7 @@ onUnmounted(() => { .text { font-size: 14px; - color: var(--vn-text); + color: var(--vn-text-color); } } diff --git a/src/pages/Login/VerifyEmail.vue b/src/pages/Login/VerifyEmail.vue index 4c02e5869..1febd0eaa 100644 --- a/src/pages/Login/VerifyEmail.vue +++ b/src/pages/Login/VerifyEmail.vue @@ -57,10 +57,13 @@ onMounted(async () => { :href="button.url" > <div class="row items-center no-wrap q-gutter-md"> - <div class="circle q-pa-sm" style="background-color: var(--vn-gray)"> + <div + class="circle q-pa-sm" + style="background-color: var(--vn-section-color)" + > <QImg :src="button.icon" class="q-pa-md" /> </div> - <div class="text-h5" style="color: var(--vn-gray)"> + <div class="text-h5" style="color: var(--vn-section-color)"> {{ t(button.text) }} </div> </div> diff --git a/src/pages/Order/Card/OrderCatalogFilter.vue b/src/pages/Order/Card/OrderCatalogFilter.vue index 760c48726..402df1173 100644 --- a/src/pages/Order/Card/OrderCatalogFilter.vue +++ b/src/pages/Order/Card/OrderCatalogFilter.vue @@ -420,7 +420,7 @@ const getCategoryClass = (category, params) => { .category-icon { border-radius: 50%; - background-color: var(--vn-light-gray); + background-color: var(--vn-accent-color); font-size: 2.6rem; padding: 8px; cursor: pointer; diff --git a/src/pages/Order/Card/OrderCatalogItem.vue b/src/pages/Order/Card/OrderCatalogItem.vue index ee73bcffb..8a949adad 100644 --- a/src/pages/Order/Card/OrderCatalogItem.vue +++ b/src/pages/Order/Card/OrderCatalogItem.vue @@ -88,11 +88,11 @@ const dialog = ref(null); font-size: 11px; .label { - color: var(--vn-label); + color: var(--vn-label-color); } .value { - color: var(--vn-text); + color: var(--vn-text-color); } } } @@ -125,7 +125,7 @@ const dialog = ref(null); gap: 4px; .subName { - color: var(--vn-label); + color: var(--vn-label-color); text-transform: uppercase; } diff --git a/src/pages/Order/Card/OrderSummary.vue b/src/pages/Order/Card/OrderSummary.vue index f9704a480..cba4723e8 100644 --- a/src/pages/Order/Card/OrderSummary.vue +++ b/src/pages/Order/Card/OrderSummary.vue @@ -248,7 +248,7 @@ const detailsColumns = ref([ .subName { text-transform: uppercase; - color: var(--vn-label); + color: var(--vn-label-color); } } } diff --git a/src/pages/Order/OrderCatalog.vue b/src/pages/Order/OrderCatalog.vue index 21442d10d..1ed03c47d 100644 --- a/src/pages/Order/OrderCatalog.vue +++ b/src/pages/Order/OrderCatalog.vue @@ -104,7 +104,7 @@ function extractTags(items) { .no-result { font-size: 24px; font-weight: bold; - color: var(--vn-label); + color: var(--vn-label-color); text-align: center; } </style> diff --git a/src/pages/Order/OrderLines.vue b/src/pages/Order/OrderLines.vue index a2ee42481..930230c7b 100644 --- a/src/pages/Order/OrderLines.vue +++ b/src/pages/Order/OrderLines.vue @@ -14,6 +14,7 @@ import VnConfirm from 'components/ui/VnConfirm.vue'; import { toCurrency, toDate } from 'src/filters'; import { useSession } from 'composables/useSession'; import axios from 'axios'; +import VnChip from 'src/components/common/VnChip.vue'; const route = useRoute(); const { t } = useI18n(); @@ -150,9 +151,12 @@ async function confirmOrder() { > {{ row?.item?.name }} </div> - <QChip class="q-chip-color" outline size="sm"> - {{ t('ID') }}: {{ row.id }} - </QChip> + <VnChip + class="q-chip-color" + outline + size="sm" + :text="t('ID') + ':' + row.id" + /> </div> </template> <template #list-items> @@ -213,7 +217,7 @@ async function confirmOrder() { gap: 2%; .label { - color: var(--vn-label); + color: var(--vn-label-color); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; @@ -246,13 +250,13 @@ async function confirmOrder() { } .subname { - color: var(--vn-label); + color: var(--vn-label-color); } .no-result { font-size: 24px; font-weight: bold; - color: var(--vn-label); + color: var(--vn-label-color); text-align: center; } </style> diff --git a/src/pages/Order/OrderList.vue b/src/pages/Order/OrderList.vue index b7b233a64..203eaccd1 100644 --- a/src/pages/Order/OrderList.vue +++ b/src/pages/Order/OrderList.vue @@ -104,7 +104,7 @@ function navigate(id) { /> <VnLv :label="t('order.field.landed')"> <template #value> - <QBadge color="positive" dense> + <QBadge text-color="black" color="positive" dense> {{ toDate(row?.landed) }} </QBadge> </template> diff --git a/src/pages/Order/OrderVolume.vue b/src/pages/Order/OrderVolume.vue index 5bb106edc..67f409b45 100644 --- a/src/pages/Order/OrderVolume.vue +++ b/src/pages/Order/OrderVolume.vue @@ -106,7 +106,7 @@ const loadVolumes = async (rows) => { gap: 2%; .label { - color: var(--vn-label); + color: var(--vn-label-color); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; @@ -132,7 +132,7 @@ const loadVolumes = async (rows) => { .no-result { font-size: 24px; font-weight: bold; - color: var(--vn-label); + color: var(--vn-label-color); text-align: center; } </style> diff --git a/src/pages/Route/Cmr/CmrList.vue b/src/pages/Route/Cmr/CmrList.vue index dc5602c1c..1baf22c17 100644 --- a/src/pages/Route/Cmr/CmrList.vue +++ b/src/pages/Route/Cmr/CmrList.vue @@ -123,6 +123,7 @@ function downloadPdfs() { <template #body-cell-hasCmrDms="{ value }"> <QTd align="center"> <QBadge + text-color="black" :id="value ? 'true' : 'false'" :label=" value diff --git a/src/pages/Supplier/Card/SupplierConsumption.vue b/src/pages/Supplier/Card/SupplierConsumption.vue index 59dd2281c..86c5e586b 100644 --- a/src/pages/Supplier/Card/SupplierConsumption.vue +++ b/src/pages/Supplier/Card/SupplierConsumption.vue @@ -195,7 +195,7 @@ onMounted(async () => { <style scoped lang="scss"> .label { - color: var(--vn-label); + color: var(--vn-label-color); } </style> diff --git a/src/pages/Supplier/Card/SupplierContacts.vue b/src/pages/Supplier/Card/SupplierContacts.vue index d69b74a4c..ce65ecac6 100644 --- a/src/pages/Supplier/Card/SupplierContacts.vue +++ b/src/pages/Supplier/Card/SupplierContacts.vue @@ -107,7 +107,7 @@ onMounted(() => { <style lang="scss" scoped> .border { border-radius: 0px !important; - border: 1px solid var(--vn-text) !important; + border: 1px solid var(--vn-text-color) !important; } </style> diff --git a/src/pages/Supplier/Card/SupplierSummary.vue b/src/pages/Supplier/Card/SupplierSummary.vue index 2da9bcfdc..2b1131e5e 100644 --- a/src/pages/Supplier/Card/SupplierSummary.vue +++ b/src/pages/Supplier/Card/SupplierSummary.vue @@ -8,6 +8,7 @@ import { getUrl } from 'src/composables/getUrl'; import { useRole } from 'src/composables/useRole'; import { dashIfEmpty } from 'src/filters'; import VnUserLink from 'src/components/ui/VnUserLink.vue'; +import VnTitle from 'src/components/common/VnTitle.vue'; onUpdated(() => summaryRef.value.fetch()); @@ -51,7 +52,7 @@ const isAdministrative = computed(() => { :url="`Suppliers/${entityId}/getSummary`" @on-fetch="(data) => setData(data)" > - <template #header-left> + <template> <a v-if="isAdministrative" class="header header-link" :href="supplierUrl"> <QIcon name="open_in_new" color="white" size="sm" /> </a> diff --git a/src/pages/Ticket/Card/TicketDescriptor.vue b/src/pages/Ticket/Card/TicketDescriptor.vue index f0ded019b..dfbcfc106 100644 --- a/src/pages/Ticket/Card/TicketDescriptor.vue +++ b/src/pages/Ticket/Card/TicketDescriptor.vue @@ -98,7 +98,10 @@ const setData = (entity) => </VnLv> <VnLv v-if="entity.ticketState" :label="t('ticket.card.state')"> <template #value> - <QBadge :color="entity.ticketState.state.classColor"> + <QBadge + text-color="black" + :color="entity.ticketState.state.classColor" + > {{ entity.ticketState.state.name }} </QBadge> </template> diff --git a/src/pages/Ticket/Card/TicketSummary.vue b/src/pages/Ticket/Card/TicketSummary.vue index fbca21086..a7608cae8 100644 --- a/src/pages/Ticket/Card/TicketSummary.vue +++ b/src/pages/Ticket/Card/TicketSummary.vue @@ -12,6 +12,8 @@ import VnLv from 'src/components/ui/VnLv.vue'; import VnLinkPhone from 'src/components/ui/VnLinkPhone.vue'; import { getUrl } from 'src/composables/getUrl'; import VnUserLink from 'src/components/ui/VnUserLink.vue'; +import VnChip from 'src/components/common/VnChip.vue'; +import VnTitle from 'src/components/common/VnTitle.vue'; onUpdated(() => summaryRef.value.fetch()); @@ -74,7 +76,7 @@ async function changeState(value) { code: value, }; - await axios.post(`TicketTrackings/changeState`, formData); + await axios.post(`Tickets/state`, formData); router.go(route.fullPath); } </script> @@ -102,8 +104,8 @@ async function changeState(value) { <QBtnDropdown side top - color="orange-11" - text-color="black" + color="black" + text-color="white" :label="t('ticket.summary.changeState')" :disable="!isEditable()" > @@ -147,15 +149,17 @@ async function changeState(value) { </div> </QCard> <QCard class="vn-one"> - <a class="header header-link" :href="ticketUrl + 'basic-data/step-one'"> - {{ t('globals.summary.basicData') }} - <QIcon name="open_in_new" /> - </a> + <VnTitle + :url="ticketUrl + 'basic-data/step-one'" + :text="t('globals.summary.basicData')" + /> <VnLv :label="t('ticket.summary.state')"> <template #value> - <QChip :color="ticket.ticketState?.state?.classColor ?? 'dark'"> - {{ ticket.ticketState?.state?.name }} - </QChip> + <VnChip + :color="ticket.ticketState?.state?.classColor ?? 'dark'" + dense="dense" + :text="ticket.ticketState?.state?.name" + /> </template> </VnLv> <VnLv :label="t('ticket.summary.salesPerson')"> @@ -193,10 +197,10 @@ async function changeState(value) { /> </QCard> <QCard class="vn-one"> - <a class="header header-link" :href="ticketUrl + 'basic-data/step-one'"> - {{ t('globals.summary.basicData') }} - <QIcon name="open_in_new" /> - </a> + <VnTitle + :url="ticketUrl + 'basic-data/step-one'" + :text="t('globals.summary.basicData')" + /> <VnLv :label="t('ticket.summary.shipped')" :value="toDate(ticket.shipped)" @@ -236,10 +240,10 @@ async function changeState(value) { /> </QCard> <QCard class="vn-one"> - <a class="header header-link" :href="ticketUrl + 'observation'"> - {{ t('ticket.pageTitles.notes') }} - <QIcon name="open_in_new" /> - </a> + <VnTitle + :url="ticketUrl + 'observation'" + :text="t('ticket.pageTitles.notes')" + /> <VnLv v-for="note in ticket.notes" :key="note.id" @@ -258,10 +262,10 @@ async function changeState(value) { </VnLv> </QCard> <QCard class="vn-max"> - <a class="header header-link" :href="ticketUrl + 'sale'"> - {{ t('ticket.summary.saleLines') }} - <QIcon name="open_in_new" /> - </a> + <VnTitle + :url="ticketUrl + 'sale'" + :text="t('ticket.summary.saleLines')" + /> <QTable :rows="ticket.sales"> <template #header="props"> <QTr :props="props"> @@ -396,10 +400,7 @@ async function changeState(value) { class="vn-max" v-if="ticket.packagings.length > 0 || ticket.services.length > 0" > - <a class="header header-link" :href="ticketUrl + 'package'"> - {{ t('globals.packages') }} - <QIcon name="open_in_new" /> - </a> + <VnTitle :url="ticketUrl + 'package'" :text="t('globals.packages')" /> <QTable :rows="ticket.packagings" flat> <template #header="props"> <QTr :props="props"> @@ -416,11 +417,10 @@ async function changeState(value) { </QTr> </template> </QTable> - - <a class="header header-link q-mt-xl" :href="ticketUrl + 'service'"> - {{ t('ticket.summary.service') }} - <QIcon name="open_in_new" /> - </a> + <VnTitle + :url="ticketUrl + 'service'" + :text="t('ticket.summary.service')" + /> <QTable :rows="ticket.services" flat> <template #header="props"> <QTr :props="props"> diff --git a/src/pages/Ticket/TicketList.vue b/src/pages/Ticket/TicketList.vue index 72c2da57c..c5d25fed2 100644 --- a/src/pages/Ticket/TicketList.vue +++ b/src/pages/Ticket/TicketList.vue @@ -89,6 +89,7 @@ function navigate(id) { <VnLv :label="t('ticket.list.state')"> <template #value> <QBadge + text-color="black" :color="row.classColor ?? 'orange'" class="q-ma-none" dense diff --git a/src/pages/Travel/Card/TravelSummary.vue b/src/pages/Travel/Card/TravelSummary.vue index 5a2c6bdb2..65050dfcd 100644 --- a/src/pages/Travel/Card/TravelSummary.vue +++ b/src/pages/Travel/Card/TravelSummary.vue @@ -5,6 +5,7 @@ import { useI18n } from 'vue-i18n'; import CardSummary from 'components/ui/CardSummary.vue'; import VnLv from 'src/components/ui/VnLv.vue'; +import VnTitle from 'src/components/common/VnTitle.vue'; import EntryDescriptorProxy from 'src/pages/Entry/Card/EntryDescriptorProxy.vue'; import FetchData from 'src/components/FetchData.vue'; import TravelDescriptorMenuItems from './TravelDescriptorMenuItems.vue'; @@ -294,9 +295,7 @@ async function setTravelData(travelData) { <VnLv :label="t('globals.totalEntries')" :value="travel.totalEntries" /> </QCard> <QCard class="full-width" v-if="entriesTableRows.length > 0"> - <span class="header header-link"> - {{ t('travel.summary.entries') }} - </span> + <VnTitle :text="t('travel.summary.entries')" /> <QTable :rows="entriesTableRows" :columns="entriesTableColumns" diff --git a/src/pages/Travel/TravelList.vue b/src/pages/Travel/TravelList.vue index edcfbac52..257586367 100644 --- a/src/pages/Travel/TravelList.vue +++ b/src/pages/Travel/TravelList.vue @@ -100,6 +100,7 @@ onMounted(async () => { <VnLv :label="t('globals.shipped')"> <template #value> <QBadge + text-color="black" v-if="getDateQBadgeColor(row.shipped)" :color="getDateQBadgeColor(row.shipped)" class="q-ma-none" @@ -114,6 +115,7 @@ onMounted(async () => { <VnLv :label="t('globals.landed')"> <template #value> <QBadge + text-color="black" v-if="getDateQBadgeColor(row.landed)" :color="getDateQBadgeColor(row.landed)" class="q-ma-none" diff --git a/src/pages/Worker/Card/WorkerSummary.vue b/src/pages/Worker/Card/WorkerSummary.vue index 9d0e18b15..dad21cda5 100644 --- a/src/pages/Worker/Card/WorkerSummary.vue +++ b/src/pages/Worker/Card/WorkerSummary.vue @@ -8,6 +8,7 @@ import VnLv from 'src/components/ui/VnLv.vue'; import VnLinkPhone from 'src/components/ui/VnLinkPhone.vue'; import CardSummary from 'components/ui/CardSummary.vue'; import VnUserLink from 'src/components/ui/VnUserLink.vue'; +import VnTitle from 'src/components/common/VnTitle.vue'; const route = useRoute(); const { t } = useI18n(); @@ -71,10 +72,10 @@ const filter = { </template> <template #body="{ entity: worker }"> <QCard class="vn-one"> - <a class="header header-link" :href="workerUrl + `basic-data`"> - {{ t('worker.summary.basicData') }} - <QIcon name="open_in_new" /> - </a> + <VnTitle + :url="workerUrl + `basic-data`" + :text="t('worker.summary.basicData')" + /> <VnLv :label="t('worker.card.name')" :value="worker.user.nickname" /> <VnLv :label="t('worker.list.department')" @@ -111,9 +112,7 @@ const filter = { <VnLv :label="t('worker.summary.locker')" :value="worker.locker" /> </QCard> <QCard class="vn-one"> - <div class="header header-link"> - {{ t('worker.summary.userData') }} - </div> + <VnTitle :text="t('worker.summary.userData')" /> <VnLv :label="t('worker.summary.userId')" :value="worker.user.id" /> <VnLv :label="t('worker.card.name')" :value="worker.user.nickname" /> <VnLv :label="t('worker.summary.role')" :value="worker.user.role.name" /> From 0fe0a6385bc26465a104b6264bda80759563aaf6 Mon Sep 17 00:00:00 2001 From: alexm <alexm@verdnatura.es> Date: Fri, 15 Mar 2024 10:43:25 +0100 Subject: [PATCH 30/42] hotFix(Readme): change bun to pnpm --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 86fe11ca7..e87a84d60 100644 --- a/README.md +++ b/README.md @@ -5,13 +5,13 @@ Lilium frontend ## Install the dependencies ```bash -bun install +pnpm install ``` ### Install quasar cli ```bash -sudo bun install -g @quasar/cli +sudo npm install -g @quasar/cli ``` ### Start the app in development mode (hot-code reloading, error reporting, etc.) @@ -23,13 +23,13 @@ quasar dev ### Run unit tests ```bash -bun run test:unit +pnpm run test:unit ``` ### Run e2e tests ```bash -npm run test:e2e +pnpm run test:e2e ``` ### Build the app for production From 445d95057a7395dacbea495dd0daa0810df11bcd Mon Sep 17 00:00:00 2001 From: Javier Segarra <jsegarra@verdnatura.es> Date: Fri, 15 Mar 2024 12:42:08 +0100 Subject: [PATCH 31/42] refs #6930 feat: trycatchfinally logout --- src/composables/useSession.js | 69 ++++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 26 deletions(-) diff --git a/src/composables/useSession.js b/src/composables/useSession.js index 580efbdf8..507e63c0f 100644 --- a/src/composables/useSession.js +++ b/src/composables/useSession.js @@ -2,9 +2,11 @@ import { useState } from './useState'; import { useRole } from './useRole'; import { useUserConfig } from './useUserConfig'; import axios from 'axios'; - +import useNotify from './useNotify'; export function useSession() { + const { notify } = useNotify(); + function getToken() { const localToken = localStorage.getItem('token'); const sessionToken = sessionStorage.getItem('token'); @@ -29,37 +31,52 @@ export function useSession() { } async function destroy() { - if (localStorage.getItem('tokenMultimedia')){ - await axios.post('VnUsers/logoutMultimedia', null, { - headers: {Authorization: localStorage.getItem('tokenMultimedia') } - }); - localStorage.removeItem('tokenMultimedia') - + if (localStorage.getItem('tokenMultimedia')) { + try { + await axios.post('Accounts/logout', null, { + headers: { Authorization: localStorage.getItem('tokenMultimedia') }, + }); + } catch (error) { + notify('errors.userConfig', 'negative'); + } finally { + localStorage.removeItem('tokenMultimedia'); + } } - if (localStorage.getItem('token')){ - await axios.post('VnUsers/logout', null, { - headers: {Authorization: localStorage.getItem('token') } - }); - localStorage.removeItem('token') + if (localStorage.getItem('token')) { + try { + await axios.post('VnUsers/logout', null, { + headers: { Authorization: localStorage.getItem('token') }, + }); + } catch (error) { + notify('errors.userConfig', 'negative'); + } finally { + localStorage.removeItem('token'); + } } - - if (sessionStorage.getItem('tokenMultimedia')){ - await axios.post('VnUsers/logoutMultimedia', null, { - headers: {Authorization: sessionStorage.getItem('tokenMultimedia') } - }); - sessionStorage.removeItem('tokenMultimedia') - + if (sessionStorage.getItem('tokenMultimedia')) { + try { + await axios.post('Accounts/logout', null, { + headers: { Authorization: sessionStorage.getItem('tokenMultimedia') }, + }); + } catch (error) { + notify('errors.userConfig', 'negative'); + } finally { + sessionStorage.removeItem('tokenMultimedia'); + } } - if (sessionStorage.getItem('token')){ - await axios.post('VnUsers/logout', null, { - headers: {Authorization: sessionStorage.getItem('token') } - }); - sessionStorage.removeItem('token') + if (sessionStorage.getItem('token')) { + try { + await axios.post('VnUsers/logout', null, { + headers: { Authorization: sessionStorage.getItem('token') }, + }); + } catch (error) { + notify('errors.userConfig', 'negative'); + } finally { + sessionStorage.removeItem('token'); + } } - - const { setUser } = useState(); setUser({ From 0d3d002baf5265acbb226270ea5ac2d25e76e282 Mon Sep 17 00:00:00 2001 From: Javier Segarra <jsegarra@verdnatura.es> Date: Fri, 15 Mar 2024 12:43:56 +0100 Subject: [PATCH 32/42] refs #6930 perf: replace label --- src/composables/useSession.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/composables/useSession.js b/src/composables/useSession.js index 507e63c0f..aa20dde20 100644 --- a/src/composables/useSession.js +++ b/src/composables/useSession.js @@ -37,7 +37,7 @@ export function useSession() { headers: { Authorization: localStorage.getItem('tokenMultimedia') }, }); } catch (error) { - notify('errors.userConfig', 'negative'); + notify('errors.statusUnauthorized', 'negative'); } finally { localStorage.removeItem('tokenMultimedia'); } @@ -48,7 +48,7 @@ export function useSession() { headers: { Authorization: localStorage.getItem('token') }, }); } catch (error) { - notify('errors.userConfig', 'negative'); + notify('errors.statusUnauthorized', 'negative'); } finally { localStorage.removeItem('token'); } @@ -60,7 +60,7 @@ export function useSession() { headers: { Authorization: sessionStorage.getItem('tokenMultimedia') }, }); } catch (error) { - notify('errors.userConfig', 'negative'); + notify('errors.statusUnauthorized', 'negative'); } finally { sessionStorage.removeItem('tokenMultimedia'); } @@ -71,7 +71,7 @@ export function useSession() { headers: { Authorization: sessionStorage.getItem('token') }, }); } catch (error) { - notify('errors.userConfig', 'negative'); + notify('errors.statusUnauthorized', 'negative'); } finally { sessionStorage.removeItem('token'); } From 63d195cbbf0de82a9bc1236bc0671b5dd296e914 Mon Sep 17 00:00:00 2001 From: Javier Segarra <jsegarra@verdnatura.es> Date: Fri, 15 Mar 2024 13:21:26 +0100 Subject: [PATCH 33/42] refs #6930 perf: refactor destroy method --- src/composables/useSession.js | 65 +++++++++++------------------------ 1 file changed, 20 insertions(+), 45 deletions(-) diff --git a/src/composables/useSession.js b/src/composables/useSession.js index aa20dde20..45d439b46 100644 --- a/src/composables/useSession.js +++ b/src/composables/useSession.js @@ -29,52 +29,27 @@ export function useSession() { sessionStorage.setItem('tokenMultimedia', data.tokenMultimedia); } } - + async function destroyToken(url, storage, key) { + if (storage.getItem(key)) { + try { + await axios.post(url, null, { + headers: { Authorization: storage.getItem(key) }, + }); + } catch (error) { + notify('errors.statusUnauthorized', 'negative'); + } finally { + storage.removeItem(key); + } + } + } async function destroy() { - if (localStorage.getItem('tokenMultimedia')) { - try { - await axios.post('Accounts/logout', null, { - headers: { Authorization: localStorage.getItem('tokenMultimedia') }, - }); - } catch (error) { - notify('errors.statusUnauthorized', 'negative'); - } finally { - localStorage.removeItem('tokenMultimedia'); - } - } - if (localStorage.getItem('token')) { - try { - await axios.post('VnUsers/logout', null, { - headers: { Authorization: localStorage.getItem('token') }, - }); - } catch (error) { - notify('errors.statusUnauthorized', 'negative'); - } finally { - localStorage.removeItem('token'); - } - } - - if (sessionStorage.getItem('tokenMultimedia')) { - try { - await axios.post('Accounts/logout', null, { - headers: { Authorization: sessionStorage.getItem('tokenMultimedia') }, - }); - } catch (error) { - notify('errors.statusUnauthorized', 'negative'); - } finally { - sessionStorage.removeItem('tokenMultimedia'); - } - } - if (sessionStorage.getItem('token')) { - try { - await axios.post('VnUsers/logout', null, { - headers: { Authorization: sessionStorage.getItem('token') }, - }); - } catch (error) { - notify('errors.statusUnauthorized', 'negative'); - } finally { - sessionStorage.removeItem('token'); - } + const tokens = { + tokenMultimedia: 'Accounts/logout', + token: 'VnUsers/logout', + }; + for (const [key, url] of Object.entries(tokens)) { + await destroyToken(url, localStorage, key); + await destroyToken(url, sessionStorage, key); } const { setUser } = useState(); From 55ef37584a9f3b87a461048c4326bee385123a52 Mon Sep 17 00:00:00 2001 From: Javier Segarra <jsegarra@verdnatura.es> Date: Fri, 15 Mar 2024 14:07:28 +0100 Subject: [PATCH 34/42] refs #6993 fix test front --- test/vitest/__tests__/components/Paginate.spec.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/vitest/__tests__/components/Paginate.spec.js b/test/vitest/__tests__/components/Paginate.spec.js index 2a22ce438..f3bf01489 100644 --- a/test/vitest/__tests__/components/Paginate.spec.js +++ b/test/vitest/__tests__/components/Paginate.spec.js @@ -57,13 +57,13 @@ describe('VnPaginate', () => { await vm.paginate(); - expect(vm.store.skip).toEqual(3); - expect(vm.store.data.length).toEqual(6); + expect(vm.store.skip).toEqual(6); + expect(vm.store.data.length).toEqual(9); await vm.paginate(); - expect(vm.store.skip).toEqual(6); - expect(vm.store.data.length).toEqual(9); + expect(vm.store.skip).toEqual(9); + expect(vm.store.data.length).toEqual(12); }); }); From 62253e228270744980194554a47e278d9e86f1ae Mon Sep 17 00:00:00 2001 From: alexm <alexm@verdnatura.es> Date: Mon, 18 Mar 2024 13:33:02 +0100 Subject: [PATCH 35/42] refs #6546 test(VnPaginate) skip --- test/vitest/__tests__/components/Paginate.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/vitest/__tests__/components/Paginate.spec.js b/test/vitest/__tests__/components/Paginate.spec.js index 2a22ce438..4b87a6ea3 100644 --- a/test/vitest/__tests__/components/Paginate.spec.js +++ b/test/vitest/__tests__/components/Paginate.spec.js @@ -2,7 +2,7 @@ import { vi, describe, expect, it, beforeAll, afterEach } from 'vitest'; import { createWrapper, axios } from 'app/test/vitest/helper'; import VnPaginate from 'src/components/ui/VnPaginate.vue'; -describe('VnPaginate', () => { +describe.skip('VnPaginate', () => { const expectedUrl = '/api/customers'; let vm; From 9094ae8c883e9cd89602c181c3a6cc53d9a7607f Mon Sep 17 00:00:00 2001 From: alexm <alexm@verdnatura.es> Date: Mon, 18 Mar 2024 15:02:50 +0100 Subject: [PATCH 36/42] test(VnPaginate) fix --- test/vitest/__tests__/components/Paginate.spec.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/test/vitest/__tests__/components/Paginate.spec.js b/test/vitest/__tests__/components/Paginate.spec.js index dcd74c72b..cf5e5d2ea 100644 --- a/test/vitest/__tests__/components/Paginate.spec.js +++ b/test/vitest/__tests__/components/Paginate.spec.js @@ -2,7 +2,7 @@ import { vi, describe, expect, it, beforeAll, afterEach } from 'vitest'; import { createWrapper, axios } from 'app/test/vitest/helper'; import VnPaginate from 'src/components/ui/VnPaginate.vue'; -describe.skip('VnPaginate', () => { +describe('VnPaginate', () => { const expectedUrl = '/api/customers'; let vm; @@ -49,6 +49,8 @@ describe.skip('VnPaginate', () => { ], }); vm.arrayData.hasMoreData.value = true; + await vm.$nextTick(); + vm.store.data = [ { id: 1, name: 'Tony Stark' }, { id: 2, name: 'Jessica Jones' }, @@ -57,13 +59,13 @@ describe.skip('VnPaginate', () => { await vm.paginate(); - expect(vm.store.skip).toEqual(6); - expect(vm.store.data.length).toEqual(9); + expect(vm.store.skip).toEqual(3); + expect(vm.store.data.length).toEqual(6); await vm.paginate(); - expect(vm.store.skip).toEqual(9); - expect(vm.store.data.length).toEqual(12); + expect(vm.store.skip).toEqual(6); + expect(vm.store.data.length).toEqual(9); }); }); From 22eef14bb3fb4a976e3a76524ecbcb4979acda85 Mon Sep 17 00:00:00 2001 From: pablone <pablone@verdnatura.es> Date: Tue, 19 Mar 2024 11:15:54 +0100 Subject: [PATCH 37/42] feat(light theme): refs #7001 add light theme --- src/components/LeftMenu.vue | 2 +- src/components/UserPanel.vue | 2 +- src/components/common/VnLog.vue | 2 +- src/components/common/VnTitle.vue | 6 +--- src/components/ui/VnSearchbar.vue | 7 +++- src/components/ui/VnSubToolbar.vue | 2 +- src/css/app.scss | 30 ++++++++++------ src/layouts/MainLayout.vue | 2 -- src/layouts/OutLayout.vue | 2 +- src/pages/Claim/ClaimList.vue | 1 - src/pages/Customer/CustomerList.vue | 1 - .../Customer/Defaulter/CustomerDefaulter.vue | 2 +- src/pages/Dashboard/DashboardMain.vue | 6 +++- src/pages/Entry/EntryLatestBuys.vue | 2 +- src/pages/InvoiceIn/InvoiceInList.vue | 1 - src/pages/InvoiceOut/InvoiceOutList.vue | 36 +------------------ src/pages/Order/Card/OrderCatalogItem.vue | 2 +- src/pages/Route/RouteList.vue | 2 +- src/pages/Route/RouteRoadmap.vue | 17 +++++---- src/pages/Route/RouteTickets.vue | 6 ++-- .../Shelving/Card/ShelvingDescriptorMenu.vue | 17 +++++---- src/pages/Travel/ExtraCommunity.vue | 2 +- src/pages/Travel/TravelList.vue | 2 -- src/pages/Wagon/Type/WagonTypeList.vue | 1 - src/pages/Wagon/WagonList.vue | 1 - src/pages/Worker/WorkerList.vue | 1 - 26 files changed, 64 insertions(+), 91 deletions(-) diff --git a/src/components/LeftMenu.vue b/src/components/LeftMenu.vue index 1721adfec..278a67129 100644 --- a/src/components/LeftMenu.vue +++ b/src/components/LeftMenu.vue @@ -234,6 +234,6 @@ async function togglePinned(item, event) { max-width: 256px; } .header { - color: #999999; + color: var(--vn-label-color); } </style> diff --git a/src/components/UserPanel.vue b/src/components/UserPanel.vue index a18dad79a..007d595cc 100644 --- a/src/components/UserPanel.vue +++ b/src/components/UserPanel.vue @@ -87,7 +87,7 @@ function copyUserToken() { </script> <template> - <QMenu anchor="bottom left"> + <QMenu anchor="bottom left" class="bg-vn-section-color"> <div class="row no-wrap q-pa-md"> <div class="column panel"> <div class="text-h6 q-mb-md"> diff --git a/src/components/common/VnLog.vue b/src/components/common/VnLog.vue index 732f0e964..0c8a70092 100644 --- a/src/components/common/VnLog.vue +++ b/src/components/common/VnLog.vue @@ -837,7 +837,7 @@ setLogTree(); max-width: 400px; & > .header { - color: $dark; + color: var(--vn-section-color); overflow: hidden; white-space: nowrap; text-overflow: ellipsis; diff --git a/src/components/common/VnTitle.vue b/src/components/common/VnTitle.vue index 8e994eb92..e772f3e37 100644 --- a/src/components/common/VnTitle.vue +++ b/src/components/common/VnTitle.vue @@ -8,7 +8,7 @@ const $props = defineProps({ <template> <div class="titleBox"> <div class="header-link"> - <a :href="$props.url" :class="$props.url ? 'link' : 'normalTitle'"> + <a :href="$props.url" :class="$props.url ? 'link' : 'color-vn-text'"> {{ $props.text }} <QIcon v-if="url" :name="$props.icon" /> </a> @@ -16,10 +16,6 @@ const $props = defineProps({ </div> </template> <style scoped lang="scss"> -.normalTitle { - color: whitesmoke; - cursor: auto; -} a { font-size: large; } diff --git a/src/components/ui/VnSearchbar.vue b/src/components/ui/VnSearchbar.vue index 371c12397..143efcd0f 100644 --- a/src/components/ui/VnSearchbar.vue +++ b/src/components/ui/VnSearchbar.vue @@ -163,7 +163,12 @@ async function search() { } #searchbar { .q-field--standout.q-field--highlighted .q-field__control { - background-color: var(--vn-text-color); + background-color: white; + color: black; + .q-field__native, + .q-icon { + color: black !important; + } } } </style> diff --git a/src/components/ui/VnSubToolbar.vue b/src/components/ui/VnSubToolbar.vue index 1a6549856..018447057 100644 --- a/src/components/ui/VnSubToolbar.vue +++ b/src/components/ui/VnSubToolbar.vue @@ -14,7 +14,7 @@ onUnmounted(() => { </script> <template> - <QToolbar class="bg-vn-dark justify-end sticky"> + <QToolbar class="justify-end sticky"> <slot name="st-data"> <div id="st-data"></div> </slot> diff --git a/src/css/app.scss b/src/css/app.scss index 5692cacaf..34d7b0a42 100644 --- a/src/css/app.scss +++ b/src/css/app.scss @@ -5,21 +5,30 @@ body.body--light { --font-color: black; --vn-section-color: #e0e0e0; --vn-page-color: #ffffff; - background-color: #ffffff; - .q-header .q-toolbar { - color: var(--font-color); - } --vn-text-color: var(--font-color); --vn-label-color: #5f5f5f; --vn-accent-color: #e7e3e3; + + background-color: var(--vn-page-color); + + .q-header .q-toolbar { + color: var(--font-color); + } + .q-card, + .q-table, + .q-table__bottom, + .q-drawer { + background-color: var(--vn-section-color); + } } body.body--dark { --vn-section-color: #403c3c; - background-color: #222; --vn-text-color: white; --vn-label-color: #a8a8a8; --vn-accent-color: #424242; + + background-color: #222; } a { @@ -34,6 +43,9 @@ a { .tx-color-link { color: $color-link !important; } +.tx-color-font { + color: $color-link !important; +} .header-link { color: $color-link !important; @@ -61,11 +73,7 @@ select:-webkit-autofill { background-clip: text !important; } -.bg-vn-dark { - background-color: var(--vn-section-color); -} - -.bg-vn-dark { +.bg-vn-section-color { background-color: var(--vn-section-color); } @@ -98,7 +106,7 @@ select:-webkit-autofill { .vn-table-separation-row { height: 16px !important; - background-color: var(--vn-gray) !important; + background-color: var(--vn-section-color) !important; } /* Estilo para el asterisco en campos requeridos */ diff --git a/src/layouts/MainLayout.vue b/src/layouts/MainLayout.vue index 021ee685a..88c5ee293 100644 --- a/src/layouts/MainLayout.vue +++ b/src/layouts/MainLayout.vue @@ -11,5 +11,3 @@ const quasar = useQuasar(); <QFooter v-if="quasar.platform.is.mobile"></QFooter> </QLayout> </template> - -<style lang="scss" scoped></style> diff --git a/src/layouts/OutLayout.vue b/src/layouts/OutLayout.vue index f66fcff1f..0eb1329a4 100644 --- a/src/layouts/OutLayout.vue +++ b/src/layouts/OutLayout.vue @@ -40,7 +40,7 @@ const langs = ['en', 'es']; <template> <QLayout view="hHh LpR fFf"> - <QHeader reveal class="bg-vn-dark"> + <QHeader reveal class="bg-vn-section-color"> <QToolbar class="justify-end"> <QBtn id="switchLanguage" diff --git a/src/pages/Claim/ClaimList.vue b/src/pages/Claim/ClaimList.vue index f8ba8d541..6e0a08f2c 100644 --- a/src/pages/Claim/ClaimList.vue +++ b/src/pages/Claim/ClaimList.vue @@ -122,7 +122,6 @@ function navigate(event, id) { <QBtn :label="t('globals.description')" @click.stop - class="bg-vn-dark" outline style="margin-top: 15px" > diff --git a/src/pages/Customer/CustomerList.vue b/src/pages/Customer/CustomerList.vue index 56c3749d4..f4b4223fc 100644 --- a/src/pages/Customer/CustomerList.vue +++ b/src/pages/Customer/CustomerList.vue @@ -84,7 +84,6 @@ const redirectToCreateView = () => { <QBtn :label="t('components.smartCard.openCard')" @click.stop="navigate(row.id)" - class="bg-vn-dark" outline /> <QBtn diff --git a/src/pages/Customer/Defaulter/CustomerDefaulter.vue b/src/pages/Customer/Defaulter/CustomerDefaulter.vue index 1dfd331e2..c685615c6 100644 --- a/src/pages/Customer/Defaulter/CustomerDefaulter.vue +++ b/src/pages/Customer/Defaulter/CustomerDefaulter.vue @@ -207,7 +207,7 @@ const refreshData = () => { </QScrollArea> </QDrawer> - <VnSubToolbar class="bg-vn-dark"> + <VnSubToolbar> <template #st-data> <CustomerBalanceDueTotal :amount="balanceDueTotal" /> <div class="flex items-center q-ml-lg"> diff --git a/src/pages/Dashboard/DashboardMain.vue b/src/pages/Dashboard/DashboardMain.vue index da6a2cb7d..6da39ce25 100644 --- a/src/pages/Dashboard/DashboardMain.vue +++ b/src/pages/Dashboard/DashboardMain.vue @@ -21,7 +21,7 @@ const pinnedModules = computed(() => navigation.getPinnedModules()); :width="256" :breakpoint="1000" > - <QScrollArea class="fit text-grey-8"> + <QScrollArea class="fit"> <LeftMenu /> </QScrollArea> </QDrawer> @@ -67,6 +67,10 @@ const pinnedModules = computed(() => navigation.getPinnedModules()); </template> <style lang="scss" scoped> +.left-menu { + color: var(--vn-font-color); +} + .flex-container { display: flex; flex-wrap: wrap; diff --git a/src/pages/Entry/EntryLatestBuys.vue b/src/pages/Entry/EntryLatestBuys.vue index bbc4a16cf..876fe6a9e 100644 --- a/src/pages/Entry/EntryLatestBuys.vue +++ b/src/pages/Entry/EntryLatestBuys.vue @@ -636,7 +636,7 @@ onUnmounted(() => (stateStore.rightDrawer = false)); auto-load @on-fetch="(data) => (intrastatOptions = data)" /> - <QToolbar class="bg-vn-dark justify-end"> + <QToolbar class="justify-end"> <div id="st-data"> <TableVisibleColumns :all-columns="allColumnNames" diff --git a/src/pages/InvoiceIn/InvoiceInList.vue b/src/pages/InvoiceIn/InvoiceInList.vue index 9508c669c..46c95c734 100644 --- a/src/pages/InvoiceIn/InvoiceInList.vue +++ b/src/pages/InvoiceIn/InvoiceInList.vue @@ -112,7 +112,6 @@ function navigate(id) { <QBtn :label="t('components.smartCard.openCard')" @click.stop="navigate(row.id)" - class="bg-vn-dark" outline type="reset" /> diff --git a/src/pages/InvoiceOut/InvoiceOutList.vue b/src/pages/InvoiceOut/InvoiceOutList.vue index 08f893db2..d2954d77d 100644 --- a/src/pages/InvoiceOut/InvoiceOutList.vue +++ b/src/pages/InvoiceOut/InvoiceOutList.vue @@ -123,7 +123,7 @@ const downloadCsv = () => { url="InvoiceOuts/filter" > <template #body="{ rows }"> - <VnSubToolbar class="bg-vn-dark justify-end"> + <VnSubToolbar class="justify-end"> <template #st-actions> <QBtn @click="downloadCsv()" @@ -132,39 +132,6 @@ const downloadCsv = () => { :disable="selectedCards.size === 0" :label="t('globals.download')" /> - <!-- <QBtnDropdown - class="q-mr-xl" - color="primary" - :disable="!manageCheckboxes && arrayElements.length < 1" - :label="t('globals.download')" - v-else - > - <QList> - <QItem clickable v-close-popup @click="downloadCsv(rows)"> - <QItemSection> - <QItemLabel> - {{ - t('globals.allRows', { - numberRows: rows.length, - }) - }} - </QItemLabel> - </QItemSection> - </QItem> - - <QItem clickable v-close-popup @click="downloadCsv(rows)"> - <QItemSection> - <QItemLabel> - {{ - t('globals.selectRows', { - numberRows: rows.length, - }) - }} - </QItemLabel> - </QItemSection> - </QItem> - </QList> - </QBtnDropdown> --> <QCheckbox left-label :label="t('globals.markAll')" @@ -220,7 +187,6 @@ const downloadCsv = () => { <QBtn :label="t('components.smartCard.openCard')" @click.stop="navigate(row.id)" - class="bg-vn-dark" outline type="reset" /> diff --git a/src/pages/Order/Card/OrderCatalogItem.vue b/src/pages/Order/Card/OrderCatalogItem.vue index 294a9fbc9..0e1005493 100644 --- a/src/pages/Order/Card/OrderCatalogItem.vue +++ b/src/pages/Order/Card/OrderCatalogItem.vue @@ -163,7 +163,7 @@ const dialog = ref(null); position: absolute; bottom: 12px; right: 12px; - background: linear-gradient($dark, $primary); + background: linear-gradient(var(--vn-section-color), $primary); border-radius: 50%; width: 40px; height: 40px; diff --git a/src/pages/Route/RouteList.vue b/src/pages/Route/RouteList.vue index d308696e1..94c05ad54 100644 --- a/src/pages/Route/RouteList.vue +++ b/src/pages/Route/RouteList.vue @@ -224,7 +224,7 @@ const openTicketsDialog = (id) => { <FetchData url="AgencyModes" @on-fetch="(data) => (agencyList = data)" auto-load /> <FetchData url="Vehicles" @on-fetch="(data) => (vehicleList = data)" auto-load /> <QPage class="column items-center"> - <VnSubToolbar class="bg-vn-dark justify-end"> + <VnSubToolbar class="justify-end"> <template #st-actions> <QBtn icon="vn:clone" diff --git a/src/pages/Route/RouteRoadmap.vue b/src/pages/Route/RouteRoadmap.vue index 3dca18d66..b1d5d4159 100644 --- a/src/pages/Route/RouteRoadmap.vue +++ b/src/pages/Route/RouteRoadmap.vue @@ -13,9 +13,9 @@ import RoadmapFilter from 'pages/Route/Roadmap/RoadmapFilter.vue'; import VnConfirm from 'components/ui/VnConfirm.vue'; import axios from 'axios'; import VnInputDate from 'components/common/VnInputDate.vue'; -import {useSummaryDialog} from "composables/useSummaryDialog"; -import RoadmapSummary from "pages/Route/Roadmap/RoadmapSummary.vue"; -import {useRouter} from "vue-router"; +import { useSummaryDialog } from 'composables/useSummaryDialog'; +import RoadmapSummary from 'pages/Route/Roadmap/RoadmapSummary.vue'; +import { useRouter } from 'vue-router'; const stateStore = useStateStore(); const { t } = useI18n(); @@ -128,7 +128,7 @@ function confirmRemove() { } function navigateToRoadmapSummary(event, row) { - router.push({ name: 'RoadmapSummary', params: { id: row.id } }) + router.push({ name: 'RoadmapSummary', params: { id: row.id } }); } </script> @@ -182,7 +182,7 @@ function navigateToRoadmapSummary(event, row) { </QCard> </QDialog> <QPage class="column items-center"> - <VnSubToolbar class="bg-vn-dark justify-end"> + <VnSubToolbar class="justify-end"> <template #st-actions> <QBtn icon="vn:clone" @@ -244,7 +244,12 @@ function navigateToRoadmapSummary(event, row) { name="preview" size="xs" color="primary" - @click.stop="viewSummary(props?.row?.id, RoadmapSummary)" + @click.stop=" + viewSummary( + props?.row?.id, + RoadmapSummary + ) + " class="cursor-pointer" > <QTooltip>{{ t('Preview') }}</QTooltip> diff --git a/src/pages/Route/RouteTickets.vue b/src/pages/Route/RouteTickets.vue index 8410232c5..c1ca5507e 100644 --- a/src/pages/Route/RouteTickets.vue +++ b/src/pages/Route/RouteTickets.vue @@ -15,8 +15,8 @@ import VnConfirm from 'components/ui/VnConfirm.vue'; import FetchData from 'components/FetchData.vue'; import { openBuscaman } from 'src/utils/buscaman'; import SendSmsDialog from 'components/common/SendSmsDialog.vue'; -import RouteSearchbar from "pages/Route/Card/RouteSearchbar.vue"; -import {useStateStore} from "stores/useStateStore"; +import RouteSearchbar from 'pages/Route/Card/RouteSearchbar.vue'; +import { useStateStore } from 'stores/useStateStore'; const { t } = useI18n(); const quasar = useQuasar(); @@ -257,7 +257,7 @@ const openSmsDialog = async () => { </QCard> </QDialog> <QPage class="column items-center"> - <QToolbar class="bg-vn-dark justify-end"> + <QToolbar class="justify-end"> <div id="st-actions" class="q-pa-sm"> <QBtn icon="vn:wand" color="primary" class="q-mr-sm" @click="sortRoutes"> <QTooltip>{{ t('Sort routes') }}</QTooltip> diff --git a/src/pages/Shelving/Card/ShelvingDescriptorMenu.vue b/src/pages/Shelving/Card/ShelvingDescriptorMenu.vue index 684a46807..16351fdd4 100644 --- a/src/pages/Shelving/Card/ShelvingDescriptorMenu.vue +++ b/src/pages/Shelving/Card/ShelvingDescriptorMenu.vue @@ -17,15 +17,14 @@ const quasar = useQuasar(); const { t } = useI18n(); function confirmRemove() { - quasar - .dialog({ - component: VnConfirm, - componentProps: { - title: t('Confirm deletion'), - message: t('Are you sure you want to delete this shelving?'), - promise: remove - }, - }) + quasar.dialog({ + component: VnConfirm, + componentProps: { + title: t('Confirm deletion'), + message: t('Are you sure you want to delete this shelving?'), + promise: remove, + }, + }); } async function remove() { diff --git a/src/pages/Travel/ExtraCommunity.vue b/src/pages/Travel/ExtraCommunity.vue index e7805a7ed..443a10451 100644 --- a/src/pages/Travel/ExtraCommunity.vue +++ b/src/pages/Travel/ExtraCommunity.vue @@ -430,7 +430,7 @@ const handleDragScroll = (event) => { /> </Teleport> </template> - <VnSubToolbar class="bg-vn-dark justify-end"> + <VnSubToolbar class="justify-end"> <template #st-actions> <QBtn color="primary" diff --git a/src/pages/Travel/TravelList.vue b/src/pages/Travel/TravelList.vue index 257586367..77fb34697 100644 --- a/src/pages/Travel/TravelList.vue +++ b/src/pages/Travel/TravelList.vue @@ -141,13 +141,11 @@ onMounted(async () => { <QBtn :label="t('components.smartCard.clone')" @click.stop="cloneTravel(row)" - class="bg-vn-dark" outline /> <QBtn :label="t('addEntry')" @click.stop="redirectCreateEntryView(row)" - class="bg-vn-dark" outline style="margin-top: 15px" /> diff --git a/src/pages/Wagon/Type/WagonTypeList.vue b/src/pages/Wagon/Type/WagonTypeList.vue index a7c713039..23f56e4c3 100644 --- a/src/pages/Wagon/Type/WagonTypeList.vue +++ b/src/pages/Wagon/Type/WagonTypeList.vue @@ -61,7 +61,6 @@ async function remove(row) { <QBtn :label="t('components.smartCard.openCard')" @click.stop="navigate(row.id)" - class="bg-vn-dark" outline /> <QBtn diff --git a/src/pages/Wagon/WagonList.vue b/src/pages/Wagon/WagonList.vue index 18417f433..a8b6728c3 100644 --- a/src/pages/Wagon/WagonList.vue +++ b/src/pages/Wagon/WagonList.vue @@ -80,7 +80,6 @@ async function remove(row) { <QBtn :label="t('components.smartCard.openCard')" @click.stop="navigate(row.id)" - class="bg-vn-dark" outline /> <QBtn diff --git a/src/pages/Worker/WorkerList.vue b/src/pages/Worker/WorkerList.vue index 5214a9066..b11d531dd 100644 --- a/src/pages/Worker/WorkerList.vue +++ b/src/pages/Worker/WorkerList.vue @@ -82,7 +82,6 @@ const redirectToCreateView = () => { <QBtn :label="t('components.smartCard.openCard')" @click.stop="navigate(row.id)" - class="bg-vn-dark" outline /> <QBtn From 2ea6fd2ea6b955ba531aa2adeefe30d1e6087690 Mon Sep 17 00:00:00 2001 From: wbuezas <wbuezas@verdnatura.es> Date: Tue, 19 Mar 2024 13:50:15 -0300 Subject: [PATCH 38/42] Change vnconfirm export name --- src/composables/useVnConfirm.js | 2 +- src/pages/InvoiceOut/Card/InvoiceOutDescriptorMenu.vue | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/composables/useVnConfirm.js b/src/composables/useVnConfirm.js index 430a290be..76c3f4f28 100644 --- a/src/composables/useVnConfirm.js +++ b/src/composables/useVnConfirm.js @@ -1,7 +1,7 @@ import VnConfirm from 'components/ui/VnConfirm.vue'; import { useQuasar } from 'quasar'; -export function useSummaryDialog() { +export function useVnConfirm() { const quasar = useQuasar(); const openConfirmationModal = (title, message, promise, successFn) => { diff --git a/src/pages/InvoiceOut/Card/InvoiceOutDescriptorMenu.vue b/src/pages/InvoiceOut/Card/InvoiceOutDescriptorMenu.vue index fc84c042b..10af631bc 100644 --- a/src/pages/InvoiceOut/Card/InvoiceOutDescriptorMenu.vue +++ b/src/pages/InvoiceOut/Card/InvoiceOutDescriptorMenu.vue @@ -10,7 +10,7 @@ import SendEmailDialog from 'components/common/SendEmailDialog.vue'; import useNotify from 'src/composables/useNotify'; import { useSession } from 'src/composables/useSession'; import { usePrintService } from 'composables/usePrintService'; -import { useSummaryDialog } from 'composables/useVnConfirm'; +import { useVnConfirm } from 'composables/useVnConfirm'; import axios from 'axios'; const $props = defineProps({ @@ -26,7 +26,7 @@ const session = useSession(); const token = session.getToken(); const { t } = useI18n(); const { openReport, sendEmail } = usePrintService(); -const { openConfirmationModal } = useSummaryDialog(); +const { openConfirmationModal } = useVnConfirm(); const quasar = useQuasar(); const transferInvoiceDialogRef = ref(); From 25aea39bfcb9200793183b14f135fd8f5777884d Mon Sep 17 00:00:00 2001 From: pablone <pablone@verdnatura.es> Date: Wed, 20 Mar 2024 08:03:25 +0100 Subject: [PATCH 39/42] fix(spec): refs #7001 fix som e2e spec --- test/cypress/integration/invoiceIn/invoiceInList.spec.js | 4 ++-- test/cypress/integration/worker/workerList.spec.js | 7 +++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/test/cypress/integration/invoiceIn/invoiceInList.spec.js b/test/cypress/integration/invoiceIn/invoiceInList.spec.js index ce79dc976..5e2a5aa4c 100644 --- a/test/cypress/integration/invoiceIn/invoiceInList.spec.js +++ b/test/cypress/integration/invoiceIn/invoiceInList.spec.js @@ -4,7 +4,7 @@ describe('InvoiceInList', () => { const firstChipId = ':nth-child(1) > :nth-child(1) > .justify-between > .flex > .q-chip > .q-chip__content'; const firstDetailBtn = '.q-card:nth-child(1) .q-btn:nth-child(2)'; - const summaryHeaders = '.summaryBody .header'; + const summaryHeaders = '.summaryBody .header-link'; const screen = '.q-page-container > .q-drawer-container > .fullscreen'; beforeEach(() => { @@ -17,7 +17,7 @@ describe('InvoiceInList', () => { cy.get(firstChipId) .invoke('text') .then((content) => { - const id = content.substring(4); + const id = content.replace(/\D/g, ''); cy.get(firstCard).click(); cy.url().should('include', `/invoice-in/${id}/summary`); }); diff --git a/test/cypress/integration/worker/workerList.spec.js b/test/cypress/integration/worker/workerList.spec.js index bc4b2383e..c950f9fed 100644 --- a/test/cypress/integration/worker/workerList.spec.js +++ b/test/cypress/integration/worker/workerList.spec.js @@ -16,7 +16,10 @@ describe('WorkerList', () => { it('should open the worker summary', () => { cy.openListSummary(0); cy.get('.summaryHeader div').should('have.text', '1110 - Jessica Jones'); - cy.get('.summary .header-link').eq(0).invoke('text').should('include', 'Basic data'); - cy.get('.summary .header-link').eq(1).should('have.text', 'User data'); + cy.get('.summary .header-link') + .eq(0) + .invoke('text') + .should('include', 'Basic data'); + cy.get('.summary .header-link').eq(1).should('have.text', 'User data '); }); }); From 2fa5b1303da385ee7bb1e136e6a24b8cab31c61a Mon Sep 17 00:00:00 2001 From: pablone <pablone@verdnatura.es> Date: Wed, 20 Mar 2024 11:28:50 +0100 Subject: [PATCH 40/42] remove(vnChip): refs #7001 remove component --- src/components/common/VnChip.vue | 10 ++++------ src/components/common/VnLog.vue | 13 ++++++------- src/components/common/VnSmsDialog.vue | 5 +++-- src/components/ui/CardList.vue | 10 +++------- src/components/ui/VnSms.vue | 8 ++++---- src/css/app.scss | 12 +++++++++++- src/pages/Claim/Card/ClaimLines.vue | 13 ++++++------- src/pages/Claim/Card/ClaimSummary.vue | 9 +++------ src/pages/InvoiceIn/Card/InvoiceInSummary.vue | 8 ++++---- src/pages/Order/OrderLines.vue | 10 +++------- src/pages/Ticket/Card/TicketSummary.vue | 9 +++------ 11 files changed, 50 insertions(+), 57 deletions(-) diff --git a/src/components/common/VnChip.vue b/src/components/common/VnChip.vue index dd2de2c64..bb9b46e71 100644 --- a/src/components/common/VnChip.vue +++ b/src/components/common/VnChip.vue @@ -1,13 +1,11 @@ <script setup> -const $props = defineProps({ - color: { type: String, default: null }, +defineProps({ text: { type: String, default: null }, - dense: { type: String, default: null }, textColor: { type: String, default: 'black' }, }); </script> <template> - <QChip :color="$props.color" :text-color="textColor" :dense="$props.dense">{{ - text - }}</QChip> + <QChip v-bind="$attrs"> + <slot>{{ text }}</slot> + </QChip> </template> diff --git a/src/components/common/VnLog.vue b/src/components/common/VnLog.vue index 0c8a70092..5c70b900d 100644 --- a/src/components/common/VnLog.vue +++ b/src/components/common/VnLog.vue @@ -14,7 +14,6 @@ import VnJsonValue from '../common/VnJsonValue.vue'; import FetchData from '../FetchData.vue'; import VnSelectFilter from './VnSelectFilter.vue'; import VnUserLink from '../ui/VnUserLink.vue'; -import VnChip from '../common/VnChip.vue'; const stateStore = useStateStore(); const validationsStore = useValidator(); @@ -444,10 +443,10 @@ setLogTree(); > <QItemSection> <QItemLabel class="model-info q-mb-xs" v-if="!byRecord"> - <VnChip + <QChip + dense size="md" - text-color="white" - class="model-name q-mr-xs" + class="model-name q-mr-xs text-white" v-if=" !(modelLog.changedModel && modelLog.changedModelId) && modelLog.model @@ -456,9 +455,9 @@ setLogTree(); backgroundColor: useColor(modelLog.model), }" :title="modelLog.model" - :text="t(modelLog.modelI18n)" - dense="dense" - /> + > + {{ t(modelLog.modelI18n) }} + </QChip> <span class="model-id" v-if="modelLog.id" >#{{ modelLog.id }}</span > diff --git a/src/components/common/VnSmsDialog.vue b/src/components/common/VnSmsDialog.vue index 3027b14c7..59021cef4 100644 --- a/src/components/common/VnSmsDialog.vue +++ b/src/components/common/VnSmsDialog.vue @@ -4,7 +4,6 @@ import { useI18n } from 'vue-i18n'; import { useDialogPluginComponent } from 'quasar'; import VnInput from 'src/components/common/VnInput.vue'; -import VnChip from 'src/components/common/VnChip.vue'; const { dialogRef, onDialogOK } = useDialogPluginComponent(); const { t, availableLocales } = useI18n(); @@ -138,7 +137,9 @@ async function send() { /> </template> <template #counter> - <VnChip :color="color" :text="totalLength + '/' + maxLength" /> + <QChip :color="color" dense> + {{ totalLength }}/{{ maxLength }} + </QChip> </template> </QInput> </QCardSection> diff --git a/src/components/ui/CardList.vue b/src/components/ui/CardList.vue index 9779c58eb..e8392b13e 100644 --- a/src/components/ui/CardList.vue +++ b/src/components/ui/CardList.vue @@ -1,6 +1,5 @@ <script setup> import { useI18n } from 'vue-i18n'; -import VnChip from 'src/components/common/VnChip.vue'; const { t } = useI18n(); @@ -29,12 +28,9 @@ const toggleCardCheck = (item) => { <div class="title text-primary text-weight-bold text-h5"> {{ $props.title }} </div> - <VnChip - :text="'ID:' + $props.id" - class="q-chip-color" - outline - size="sm" - /> + <QChip class="q-chip-color" outline size="sm"> + {{ t('ID') }}: {{ $props.id }} + </QChip> </div> <QCheckbox v-if="showCheckbox" diff --git a/src/components/ui/VnSms.vue b/src/components/ui/VnSms.vue index d45eef103..ceb24b2bb 100644 --- a/src/components/ui/VnSms.vue +++ b/src/components/ui/VnSms.vue @@ -4,7 +4,6 @@ import { date } from 'quasar'; import VnPaginate from 'src/components/ui/VnPaginate.vue'; import VnAvatar from '../ui/VnAvatar.vue'; import VnUserLink from 'src/components/ui/VnUserLink.vue'; -import VnChip from '../common/VnChip.vue'; const $props = defineProps({ url: { type: String, default: null }, @@ -90,14 +89,15 @@ function formatNumber(number) { ) }}</QItemLabel> <QItemLabel class="row center"> - <VnChip + <QChip :color=" row.sms.status == 'OK' ? 'positive' : 'negative' " - :text="row.sms.status" - /> + > + {{ row.sms.status }} + </QChip> </QItemLabel> </QItemSection> </QItem> diff --git a/src/css/app.scss b/src/css/app.scss index 34d7b0a42..f1fc22527 100644 --- a/src/css/app.scss +++ b/src/css/app.scss @@ -1,5 +1,10 @@ // app global css in SCSS form @import './icons.scss'; +body { + .q-chip__content { + color: 'red'; + } +} body.body--light { --font-color: black; @@ -11,7 +16,8 @@ body.body--light { background-color: var(--vn-page-color); - .q-header .q-toolbar { + .q-header .q-toolbar, + .q-chip { color: var(--font-color); } .q-card, @@ -29,6 +35,10 @@ body.body--dark { --vn-accent-color: #424242; background-color: #222; + + .q-chip { + color: black; + } } a { diff --git a/src/pages/Claim/Card/ClaimLines.vue b/src/pages/Claim/Card/ClaimLines.vue index 248b5a69a..90dd31199 100644 --- a/src/pages/Claim/Card/ClaimLines.vue +++ b/src/pages/Claim/Card/ClaimLines.vue @@ -12,7 +12,6 @@ import FetchData from 'components/FetchData.vue'; import VnDiscount from 'components/common/vnDiscount.vue'; import ClaimLinesImport from './ClaimLinesImport.vue'; import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue'; -import VnChip from 'src/components/common/VnChip.vue'; const quasar = useQuasar(); const route = useRoute(); @@ -162,16 +161,16 @@ function showImportDialog() { <div class="row q-gutter-md"> <div> {{ t('Amount') }} - <VnChip :dense="$q.screen.lt.sm" :text="toCurrency(amount)" /> + <QChip :dense="$q.screen.lt.sm"> + {{ toCurrency(amount) }} + </QChip> </div> <QSeparator dark vertical /> <div> {{ t('Amount Claimed') }} - <VnChip - color="positive" - :dense="$q.screen.lt.sm" - :text="toCurrency(amountClaimed)" - /> + <QChip color="positive" :dense="$q.screen.lt.sm"> + {{ toCurrency(amountClaimed) }} + </QChip> </div> </div> </Teleport> diff --git a/src/pages/Claim/Card/ClaimSummary.vue b/src/pages/Claim/Card/ClaimSummary.vue index 12b650dcf..2d4d5603c 100644 --- a/src/pages/Claim/Card/ClaimSummary.vue +++ b/src/pages/Claim/Card/ClaimSummary.vue @@ -12,7 +12,6 @@ import ClaimNotes from 'src/pages/Claim/Card/ClaimNotes.vue'; import VnUserLink from 'src/components/ui/VnUserLink.vue'; import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue'; import VnTitle from 'src/components/common/VnTitle.vue'; -import VnChip from 'src/components/common/VnChip.vue'; const route = useRoute(); const { t } = useI18n(); @@ -192,11 +191,9 @@ function openDialog(dmsId) { /> <VnLv :label="t('claim.summary.state')"> <template #value> - <VnChip - :color="stateColor(claim.claimState.code)" - :text="claim.claimState.description" - dense="dense" - /> + <QChip color="stateColor(claim.claimState.code)" dense> + {{ claim.claimState.description }}</QChip + > </template> </VnLv> <VnLv :label="t('globals.salesPerson')"> diff --git a/src/pages/InvoiceIn/Card/InvoiceInSummary.vue b/src/pages/InvoiceIn/Card/InvoiceInSummary.vue index e30d9151c..fc15d3bd9 100644 --- a/src/pages/InvoiceIn/Card/InvoiceInSummary.vue +++ b/src/pages/InvoiceIn/Card/InvoiceInSummary.vue @@ -6,7 +6,6 @@ import { toCurrency, toDate } from 'src/filters'; import { getUrl } from 'src/composables/getUrl'; import CardSummary from 'components/ui/CardSummary.vue'; import VnLv from 'src/components/ui/VnLv.vue'; -import VnChip from 'src/components/common/VnChip.vue'; import VnTitle from 'src/components/common/VnTitle.vue'; onMounted(async () => { @@ -302,7 +301,7 @@ function getLink(param) { /> <VnLv :label="t('invoiceIn.summary.dueTotal')"> <template #value> - <VnChip + <QChip dense class="q-pa-xs" :color="amountsNotMatch ? 'negative' : 'transparent'" @@ -311,8 +310,9 @@ function getLink(param) { ? t('invoiceIn.summary.noMatch') : t('invoiceIn.summary.dueTotal') " - :text="toCurrency(invoiceIn.totals.totalDueDay)" - /> + > + {{ toCurrency(invoiceIn.totals.totalDueDay) }} + </QChip> </template> </VnLv> </div> diff --git a/src/pages/Order/OrderLines.vue b/src/pages/Order/OrderLines.vue index 053615fb4..5a31598e1 100644 --- a/src/pages/Order/OrderLines.vue +++ b/src/pages/Order/OrderLines.vue @@ -14,7 +14,6 @@ import VnConfirm from 'components/ui/VnConfirm.vue'; import { toCurrency, toDate } from 'src/filters'; import { useSession } from 'composables/useSession'; import axios from 'axios'; -import VnChip from 'src/components/common/VnChip.vue'; const route = useRoute(); const { t } = useI18n(); @@ -151,12 +150,9 @@ async function confirmOrder() { > {{ row?.item?.name }} </div> - <VnChip - class="q-chip-color" - outline - size="sm" - :text="t('ID') + ':' + row.id" - /> + <QChip class="q-chip-color" outline size="sm"> + {{ t('ID') }}: {{ row.id }} + </QChip> </div> </template> <template #list-items> diff --git a/src/pages/Ticket/Card/TicketSummary.vue b/src/pages/Ticket/Card/TicketSummary.vue index a7608cae8..85d98f353 100644 --- a/src/pages/Ticket/Card/TicketSummary.vue +++ b/src/pages/Ticket/Card/TicketSummary.vue @@ -12,7 +12,6 @@ import VnLv from 'src/components/ui/VnLv.vue'; import VnLinkPhone from 'src/components/ui/VnLinkPhone.vue'; import { getUrl } from 'src/composables/getUrl'; import VnUserLink from 'src/components/ui/VnUserLink.vue'; -import VnChip from 'src/components/common/VnChip.vue'; import VnTitle from 'src/components/common/VnTitle.vue'; onUpdated(() => summaryRef.value.fetch()); @@ -155,11 +154,9 @@ async function changeState(value) { /> <VnLv :label="t('ticket.summary.state')"> <template #value> - <VnChip - :color="ticket.ticketState?.state?.classColor ?? 'dark'" - dense="dense" - :text="ticket.ticketState?.state?.name" - /> + <QChip :color="ticket.ticketState?.state?.classColor ?? 'dark'"> + {{ ticket.ticketState?.state?.name }} + </QChip> </template> </VnLv> <VnLv :label="t('ticket.summary.salesPerson')"> From 5580d1560689d6daf9c53b8e32304ef1dcc63041 Mon Sep 17 00:00:00 2001 From: pablone <pablone@verdnatura.es> Date: Wed, 20 Mar 2024 11:30:43 +0100 Subject: [PATCH 41/42] remove: refs #7001 custom chip --- src/components/common/VnChip.vue | 11 ----------- src/pages/Claim/Card/ClaimSummary.vue | 6 +++--- 2 files changed, 3 insertions(+), 14 deletions(-) delete mode 100644 src/components/common/VnChip.vue diff --git a/src/components/common/VnChip.vue b/src/components/common/VnChip.vue deleted file mode 100644 index bb9b46e71..000000000 --- a/src/components/common/VnChip.vue +++ /dev/null @@ -1,11 +0,0 @@ -<script setup> -defineProps({ - text: { type: String, default: null }, - textColor: { type: String, default: 'black' }, -}); -</script> -<template> - <QChip v-bind="$attrs"> - <slot>{{ text }}</slot> - </QChip> -</template> diff --git a/src/pages/Claim/Card/ClaimSummary.vue b/src/pages/Claim/Card/ClaimSummary.vue index 2d4d5603c..612e0d755 100644 --- a/src/pages/Claim/Card/ClaimSummary.vue +++ b/src/pages/Claim/Card/ClaimSummary.vue @@ -191,9 +191,9 @@ function openDialog(dmsId) { /> <VnLv :label="t('claim.summary.state')"> <template #value> - <QChip color="stateColor(claim.claimState.code)" dense> - {{ claim.claimState.description }}</QChip - > + <QChip :color="stateColor(claim.claimState.code)" dense> + {{ claim.claimState.description }} + </QChip> </template> </VnLv> <VnLv :label="t('globals.salesPerson')"> From 1da314e425611b1b34bd4c1c62775522d4ad8c26 Mon Sep 17 00:00:00 2001 From: pablone <pablone@verdnatura.es> Date: Wed, 20 Mar 2024 11:41:16 +0100 Subject: [PATCH 42/42] fix(claimLines): refs #7001 add style to clear qchip --- src/css/app.scss | 16 +++++----------- src/pages/Claim/Card/ClaimLines.vue | 2 +- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/src/css/app.scss b/src/css/app.scss index f1fc22527..c9b489043 100644 --- a/src/css/app.scss +++ b/src/css/app.scss @@ -1,10 +1,5 @@ // app global css in SCSS form @import './icons.scss'; -body { - .q-chip__content { - color: 'red'; - } -} body.body--light { --font-color: black; @@ -16,8 +11,7 @@ body.body--light { background-color: var(--vn-page-color); - .q-header .q-toolbar, - .q-chip { + .q-header .q-toolbar { color: var(--font-color); } .q-card, @@ -35,10 +29,6 @@ body.body--dark { --vn-accent-color: #424242; background-color: #222; - - .q-chip { - color: black; - } } a { @@ -124,6 +114,10 @@ select:-webkit-autofill { content: ' *'; } +.q-chip { + color: black; +} + input[type='number'] { -moz-appearance: textfield; } diff --git a/src/pages/Claim/Card/ClaimLines.vue b/src/pages/Claim/Card/ClaimLines.vue index 90dd31199..70c257c69 100644 --- a/src/pages/Claim/Card/ClaimLines.vue +++ b/src/pages/Claim/Card/ClaimLines.vue @@ -161,7 +161,7 @@ function showImportDialog() { <div class="row q-gutter-md"> <div> {{ t('Amount') }} - <QChip :dense="$q.screen.lt.sm"> + <QChip :dense="$q.screen.lt.sm" text-color="white"> {{ toCurrency(amount) }} </QChip> </div>