diff --git a/src/components/common/VnCardBeta.vue b/src/components/common/VnCardBeta.vue index 7c82316dc..620dc2ad2 100644 --- a/src/components/common/VnCardBeta.vue +++ b/src/components/common/VnCardBeta.vue @@ -1,10 +1,9 @@ <script setup> import { onBeforeMount } from 'vue'; -import { useRouter, onBeforeRouteUpdate } from 'vue-router'; +import { useRouter, onBeforeRouteUpdate, onBeforeRouteLeave } from 'vue-router'; import { useArrayData } from 'src/composables/useArrayData'; import { useStateStore } from 'stores/useStateStore'; import useCardSize from 'src/composables/useCardSize'; -import LeftMenu from 'components/LeftMenu.vue'; import VnSubToolbar from '../ui/VnSubToolbar.vue'; const props = defineProps({ @@ -27,7 +26,13 @@ const arrayData = useArrayData(props.dataKey, { oneRecord: true, }); +onBeforeRouteLeave(() => { + stateStore.cardDescriptorChangeValue(null); +}); + onBeforeMount(async () => { + stateStore.cardDescriptorChangeValue(props.descriptor); + const route = router.currentRoute.value; try { await fetch(route.params.id); @@ -62,11 +67,6 @@ function hasRouteParam(params, valueToCheck = ':addressId') { } </script> <template> - <Teleport to="#left-panel" v-if="stateStore.isHeaderMounted()"> - <component :is="descriptor" /> - <QSeparator /> - <LeftMenu source="card" /> - </Teleport> <VnSubToolbar /> <div :class="[useCardSize(), $attrs.class]"> <RouterView :key="$route.path" /> diff --git a/src/components/common/VnModule.vue b/src/components/common/VnModule.vue index 038ee1d60..747a7c951 100644 --- a/src/components/common/VnModule.vue +++ b/src/components/common/VnModule.vue @@ -12,7 +12,7 @@ const $props = defineProps({ }, }); onMounted( - () => (stateStore.leftDrawer = useQuasar().screen.gt.xs ? $props.leftDrawer : false) + () => (stateStore.leftDrawer = useQuasar().screen.gt.xs ? $props.leftDrawer : false), ); const teleportRef = ref({}); @@ -35,8 +35,14 @@ onMounted(() => { <template> <QDrawer v-model="stateStore.leftDrawer" show-if-above :width="256"> <QScrollArea class="fit text-grey-8"> - <div id="left-panel" ref="teleportRef"></div> - <LeftMenu v-if="!hasContent" /> + <div id="left-panel" ref="teleportRef"> + <template v-if="stateStore.cardDescriptor"> + <component :is="stateStore.cardDescriptor" /> + <QSeparator /> + <LeftMenu source="card" /> + </template> + <template v-else> <LeftMenu /></template> + </div> </QScrollArea> </QDrawer> <QPageContainer> diff --git a/src/pages/Customer/Card/CustomerSummary.vue b/src/pages/Customer/Card/CustomerSummary.vue index 324da0771..c98bf1ffb 100644 --- a/src/pages/Customer/Card/CustomerSummary.vue +++ b/src/pages/Customer/Card/CustomerSummary.vue @@ -325,7 +325,7 @@ const sumRisk = ({ clientRisks }) => { </QCard> <QCard class="vn-max"> <VnTitle :text="t('Latest tickets')" /> - <CustomerSummaryTable /> + <CustomerSummaryTable :id="entityId" /> </QCard> </template> </CardSummary> diff --git a/src/pages/Customer/components/CustomerSummaryTable.vue b/src/pages/Customer/components/CustomerSummaryTable.vue index bb6f4442b..09c7e714c 100644 --- a/src/pages/Customer/components/CustomerSummaryTable.vue +++ b/src/pages/Customer/components/CustomerSummaryTable.vue @@ -20,7 +20,12 @@ const { t } = useI18n(); const route = useRoute(); const router = useRouter(); const { viewSummary } = useSummaryDialog(); - +const $props = defineProps({ + id: { + type: Number, + default: null, + }, +}); const filter = { include: [ { @@ -43,7 +48,7 @@ const filter = { }, }, ], - where: { clientFk: route.params.id }, + where: { clientFk: $props.id ?? route.params.id }, order: ['shipped DESC', 'id'], limit: 30, }; diff --git a/src/pages/Order/Card/OrderCatalog.vue b/src/pages/Order/Card/OrderCatalog.vue index 4b3992f21..dbb66c0ec 100644 --- a/src/pages/Order/Card/OrderCatalog.vue +++ b/src/pages/Order/Card/OrderCatalog.vue @@ -10,6 +10,7 @@ import OrderCatalogFilter from 'src/pages/Order/Card/OrderCatalogFilter.vue'; import VnSearchbar from 'src/components/ui/VnSearchbar.vue'; import { useArrayData } from 'src/composables/useArrayData'; import RightMenu from 'src/components/common/RightMenu.vue'; +import { onUnmounted } from 'vue'; const route = useRoute(); const router = useRouter(); @@ -23,16 +24,40 @@ const catalogParams = { const arrayData = useArrayData(dataKey, { url: 'Orders/CatalogFilter', userParams: catalogParams, + exprBuilder, + searchUrl: 'table', }); const store = arrayData.store; const tags = ref([]); const itemRefs = ref({}); -onMounted(() => { +onMounted(async () => { stateStore.rightDrawer = true; checkOrderConfirmation(); + + if ( + arrayData.store.userParams && + Object.keys(arrayData.store.userParams).some((key) => !key.startsWith('order')) + ) { + await arrayData.fetch({}); + } }); +onUnmounted(() => { + arrayData.destroy(); +}); + +function exprBuilder(param, value) { + switch (param) { + case 'categoryFk': + case 'typeFk': + return { [param]: value }; + case 'search': + if (/^\d+$/.test(value)) return { 'i.id': value }; + else return { 'i.name': { like: `%${value}%` } }; + } +} + async function checkOrderConfirmation() { const response = await axios.get(`Orders/${route.params.id}`); if (response.data.isConfirmed === 1) { @@ -96,6 +121,7 @@ watch( :tag-value="tagValue" :tags="tags" :initial-catalog-params="catalogParams" + :arrayData /> </template> </RightMenu> diff --git a/src/pages/Order/Card/OrderCatalogFilter.vue b/src/pages/Order/Card/OrderCatalogFilter.vue index 76e608983..d16a92017 100644 --- a/src/pages/Order/Card/OrderCatalogFilter.vue +++ b/src/pages/Order/Card/OrderCatalogFilter.vue @@ -24,6 +24,10 @@ const props = defineProps({ type: Array, required: true, }, + arrayData: { + type: Object, + required: true, + }, }); const { t } = useI18n(); @@ -74,17 +78,6 @@ const loadTypes = async (id) => { typeList.value = data; }; -function exprBuilder(param, value) { - switch (param) { - case 'categoryFk': - case 'typeFk': - return { [param]: value }; - case 'search': - if (/^\d+$/.test(value)) return { 'i.id': value }; - else return { 'i.name': { like: `%${value}%` } }; - } -} - const applyTags = (tagInfo, params, search) => { if (!tagInfo || !tagInfo.values.length) { params.tagGroups = null; @@ -152,9 +145,8 @@ function addOrder(value, field, params) { :data-key="props.dataKey" :hidden-tags="['filter', 'orderFk', 'orderBy']" :unremovable-params="['orderFk', 'orderBy']" - :expr-builder="exprBuilder" :custom-tags="['tagGroups', 'categoryFk']" - :redirect="false" + :arrayData > <template #tags="{ tag, formatFn }"> <strong v-if="tag.label === 'typeFk' && typeList"> diff --git a/src/pages/Route/Vehicle/Card/VehicleSummary.vue b/src/pages/Route/Vehicle/Card/VehicleSummary.vue index 981870cb2..e4b0a9497 100644 --- a/src/pages/Route/Vehicle/Card/VehicleSummary.vue +++ b/src/pages/Route/Vehicle/Card/VehicleSummary.vue @@ -22,7 +22,12 @@ const links = { }; </script> <template> - <CardSummary data-key="Vehicle" :url="`Vehicles/${entityId}`" :filter="VehicleFilter"> + <CardSummary + data-key="Vehicle" + :url="`Vehicles/${entityId}`" + module-name="Vehicle" + :filter="VehicleFilter" + > <template #header="{ entity }"> <div>{{ entity.id }} - {{ entity.numberPlate }}</div> </template> diff --git a/src/pages/Ticket/TicketAdvance.vue b/src/pages/Ticket/TicketAdvance.vue index 05bd14075..94b4623aa 100644 --- a/src/pages/Ticket/TicketAdvance.vue +++ b/src/pages/Ticket/TicketAdvance.vue @@ -456,6 +456,7 @@ watch( :pagination="{ rowsPerPage: 0 }" :no-data-label="t('globals.noResults')" :right-search="false" + :order="['futureTotalWithVat ASC']" auto-load :disable-option="{ card: true }" > diff --git a/src/pages/Worker/Card/WorkerCalendarItem.vue b/src/pages/Worker/Card/WorkerCalendarItem.vue index 893a81c6d..86d227ad3 100644 --- a/src/pages/Worker/Card/WorkerCalendarItem.vue +++ b/src/pages/Worker/Card/WorkerCalendarItem.vue @@ -79,7 +79,7 @@ const editEvent = async (event) => { }; const { data } = await axios.patch( `Workers/${route.params.id}/updateAbsence`, - params + params, ); if (data) emit('refresh'); @@ -108,14 +108,14 @@ const handleDateSelected = (date) => { if (!event) createEvent(_date); }; -const handleEventSelected = (event, { year, month, day }) => { +const handleEventSelected = async (event, { year, month, day }) => { if (!props.absenceType) { notify(t('Choose an absence type from the right menu'), 'warning'); return; } const date = new Date(year, month - 1, day); - if (!event?.absenceId) createEvent(date); + if (!event?.absenceId) await createEvent(date); else if (event.type == props.absenceType.code) deleteEvent(event, date); else editEvent(event); }; diff --git a/src/stores/useStateStore.js b/src/stores/useStateStore.js index e48b67279..ca447bc11 100644 --- a/src/stores/useStateStore.js +++ b/src/stores/useStateStore.js @@ -7,7 +7,11 @@ export const useStateStore = defineStore('stateStore', () => { const rightDrawer = ref(false); const rightAdvancedDrawer = ref(false); const subToolbar = ref(false); + const cardDescriptor = ref(null); + function cardDescriptorChangeValue(descriptor) { + cardDescriptor.value = descriptor; + } function toggleLeftDrawer() { leftDrawer.value = !leftDrawer.value; } @@ -49,6 +53,8 @@ export const useStateStore = defineStore('stateStore', () => { } return { + cardDescriptor, + cardDescriptorChangeValue, leftDrawer, rightDrawer, rightAdvancedDrawer, diff --git a/test/cypress/integration/route/vehicle/vehicleList.spec.js b/test/cypress/integration/route/vehicle/vehicleList.spec.js new file mode 100644 index 000000000..2b3c9cdbc --- /dev/null +++ b/test/cypress/integration/route/vehicle/vehicleList.spec.js @@ -0,0 +1,59 @@ +describe('Vehicle list', () => { + const selectors = { + saveFormBtn: 'FormModelPopup_save', + summaryPopupBtn: 'tr:last-child > .q-table--col-auto-width > .q-btn', + summaryGoToSummaryBtn: '.header > .q-icon', + summaryHeader: '.summaryHeader > div', + numberPlate: 'tr:last-child > [data-col-field="numberPlate"] > .no-padding', + }; + + const data = { + 'Nº Plate': { val: '9465-LPA' }, + 'Trade Mark': { val: 'WAYNE INDUSTRIES' }, + Model: { val: 'BATREMOLQUE' }, + Type: { val: 'remolque', type: 'select' }, + Warehouse: { val: 'Warehouse One', type: 'select' }, + Country: { val: 'Portugal', type: 'select' }, + Description: { val: 'Exclusive for batpod transport' }, + }; + + const expected = data['Nº Plate'].val; + const summaryUrl = '/summary'; + + beforeEach(() => { + cy.viewport(1920, 1080); + cy.login('developer'); + cy.visit(`/#/route/vehicle/list`); + cy.typeSearchbar('{enter}'); + }); + + it('should list vehicles', () => { + cy.get('.q-table') + .children() + .should('be.visible') + .should('have.length.greaterThan', 0); + }); + + it('Should add new vehicle', () => { + cy.addBtnClick(); + cy.fillInForm(data); + cy.dataCy(selectors.saveFormBtn).should('be.visible').click(); + + cy.checkNotification('Data created'); + cy.get(selectors.summaryHeader).should('contain', expected); + cy.url().should('include', summaryUrl); + }); + + it('should open summary by clicking a vehicle', () => { + cy.get(selectors.numberPlate).click(); + cy.get(selectors.summaryHeader).should('contain', expected); + cy.url().should('include', summaryUrl); + }); + + it('should redirect to vehicle summary when click summary icon on summary pop-up', () => { + cy.get(selectors.summaryPopupBtn).click(); + cy.get(selectors.summaryHeader).should('contain', expected); + cy.get(selectors.summaryGoToSummaryBtn).click(); + cy.url().should('include', summaryUrl); + }); +});