diff --git a/src/components/NavBar.vue b/src/components/NavBar.vue index ef5bdc6ac..040dde628 100644 --- a/src/components/NavBar.vue +++ b/src/components/NavBar.vue @@ -61,6 +61,7 @@ onMounted(() => stateStore.setMounted()); /> <QSpace /> <div id="searchbar" class="searchbar"></div> + <div id="searchbar-after"></div> <QSpace /> <div class="q-pl-sm q-gutter-sm row items-center no-wrap"> <div id="actions-prepend"></div> diff --git a/src/components/VnTable/VnTable.vue b/src/components/VnTable/VnTable.vue index 95b4b5866..17fabf10d 100644 --- a/src/components/VnTable/VnTable.vue +++ b/src/components/VnTable/VnTable.vue @@ -181,7 +181,7 @@ onMounted(() => { watch( () => $props.columns, (value) => splitColumns(value), - { immediate: true } + { immediate: true }, ); const isTableMode = computed(() => mode.value == TABLE_MODE); @@ -212,7 +212,7 @@ function splitColumns(columns) { // Status column if (splittedColumns.value.chips.length) { splittedColumns.value.columnChips = splittedColumns.value.chips.filter( - (c) => !c.isId + (c) => !c.isId, ); if (splittedColumns.value.columnChips.length) splittedColumns.value.columns.unshift({ @@ -484,7 +484,9 @@ function handleSelection({ evt, added, rows: selectedRows }, rows) { btn.isPrimary ? 'text-primary-light' : 'color-vn-text ' " :style="`visibility: ${ - (btn.show && btn.show(row)) ?? true ? 'visible' : 'hidden' + ((btn.show && btn.show(row)) ?? true) + ? 'visible' + : 'hidden' }`" @click="btn.action(row)" /> diff --git a/src/components/common/RightAdvancedMenu.vue b/src/components/common/RightAdvancedMenu.vue new file mode 100644 index 000000000..f5797a164 --- /dev/null +++ b/src/components/common/RightAdvancedMenu.vue @@ -0,0 +1,53 @@ +<script setup> +import { useI18n } from 'vue-i18n'; +import { useStateStore } from 'stores/useStateStore'; +import { useHasContent } from 'src/composables/useHasContent'; +import { watch } from 'vue'; + +const { t } = useI18n(); +const stateStore = useStateStore(); +const hasContent = useHasContent('#advanced-menu'); + +const $props = defineProps({ + isMainSection: { + type: Boolean, + default: false, + }, +}); + +watch( + () => $props.isMainSection, + (val) => { + if (stateStore) stateStore.rightAdvancedDrawer = val; + }, + { immediate: true } +); +</script> +<template> + <Teleport to="#searchbar-after" v-if="stateStore.isHeaderMounted()"> + <QBtn + v-if="hasContent || $slots['advanced-menu']" + flat + @click="stateStore.toggleRightAdvancedDrawer()" + round + dense + icon="tune" + > + <QTooltip bottom anchor="bottom right"> + {{ t('globals.advancedMenu') }} + </QTooltip> + </QBtn> + </Teleport> + <QDrawer + v-model="stateStore.rightAdvancedDrawer" + side="right" + :width="256" + :overlay="!isMainSection" + v-bind="$attrs" + > + <QScrollArea class="fit"> + <div id="advanced-menu"></div> + <slot v-if="!hasContent" name="advanced-menu" /> + </QScrollArea> + </QDrawer> +</template> diff --git a/src/components/common/RightMenu.vue b/src/components/common/RightMenu.vue index 9512d32d4..1eded089e 100644 --- a/src/components/common/RightMenu.vue +++ b/src/components/common/RightMenu.vue @@ -17,7 +17,7 @@ onMounted(() => { }); </script> <template> - <Teleport to="#actions-append" v-if="stateStore.isHeaderMounted()"> + <Teleport to="#actions-prepend" v-if="stateStore.isHeaderMounted()"> <div class="row q-gutter-x-sm"> <QBtn v-if="hasContent || $slots['right-panel']" diff --git a/src/components/common/VnLog.vue b/src/components/common/VnLog.vue index 9eca3c711..fb80a7175 100644 --- a/src/components/common/VnLog.vue +++ b/src/components/common/VnLog.vue @@ -15,6 +15,7 @@ import FetchData from '../FetchData.vue'; import VnSelect from './VnSelect.vue'; import VnUserLink from '../ui/VnUserLink.vue'; import VnPaginate from '../ui/VnPaginate.vue'; +import RightMenu from './RightMenu.vue'; const stateStore = useStateStore(); const validationsStore = useValidator(); @@ -130,7 +131,7 @@ const actionsIcon = { }; const validDate = new RegExp( /^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])/.source + - /T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(.[0-9]+)?(Z)?$/.source + /T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(.[0-9]+)?(Z)?$/.source, ); function castJsonValue(value) { @@ -192,7 +193,7 @@ function getLogTree(data) { user: log.user, userFk: log.userFk, logs: [], - }) + }), ); } // Model @@ -210,7 +211,7 @@ function getLogTree(data) { id: log.changedModelId, showValue: log.changedModelValue, logs: [], - }) + }), ); nLogs = 0; } @@ -282,7 +283,7 @@ function setDate(type) { to = date.adjustDate( to, { hour: 21, minute: 59, second: 59, millisecond: 999 }, - true + true, ); switch (type) { @@ -365,7 +366,7 @@ async function clearFilter() { dateTo.value = undefined; userRadio.value = undefined; Object.keys(checkboxOptions.value).forEach( - (opt) => (checkboxOptions.value[opt].selected = false) + (opt) => (checkboxOptions.value[opt].selected = false), ); await applyFilter(); } @@ -378,7 +379,7 @@ watch( () => router.currentRoute.value.params.id, () => { applyFilter(); - } + }, ); </script> <template> @@ -391,7 +392,7 @@ watch( const changedModel = item.changedModel; return { locale: useCapitalize( - validations[changedModel]?.locale?.name ?? changedModel + validations[changedModel]?.locale?.name ?? changedModel, ), value: changedModel, }; @@ -507,7 +508,7 @@ watch( :title=" date.formatDate( log.creationDate, - 'DD/MM/YYYY hh:mm:ss' + 'DD/MM/YYYY hh:mm:ss', ) ?? `date:'dd/MM/yyyy HH:mm:ss'` " > @@ -577,7 +578,7 @@ watch( t( `actions.${ actionsText[log.action] - }` + }`, ) " /> @@ -677,139 +678,144 @@ watch( </div> </template> </VnPaginate> - <Teleport to="#right-panel" v-if="stateStore.isHeaderMounted()"> - <QList dense> - <QSeparator /> - <QItem class="q-mt-sm"> - <QInput - :label="t('globals.search')" - v-model="searchInput" - class="full-width" - clearable - clear-icon="close" - @keyup.enter="() => selectFilter('search')" - @focusout="() => selectFilter('search')" - @clear="() => selectFilter('search')" - > - <template #append> - <QIcon name="info" class="cursor-pointer"> - <QTooltip>{{ t('tooltips.search') }}</QTooltip> - </QIcon> - </template> - </QInput> - </QItem> - <QItem> - <VnSelect - class="full-width" - :label="t('globals.entity')" - v-model="selectedFilters.changedModel" - option-label="locale" - option-value="value" - :options="actions" - @update:model-value="selectFilter('action')" - hide-selected - /> - </QItem> - <QItem class="q-mt-sm"> - <QOptionGroup - size="sm" - v-model="userRadio" - :options="userTypes" - color="primary" - @update:model-value="selectFilter('userRadio')" - right-label - > - <template #label="{ label }"> - {{ t(`Users.${label}`) }} - </template> - </QOptionGroup> - </QItem> - <QItem class="q-mt-sm"> - <QItemSection v-if="userRadio !== null"> + <RightMenu> + <template #right-panel> + <QList dense> + <QSeparator /> + <QItem class="q-mt-sm"> + <QInput + :label="t('globals.search')" + v-model="searchInput" + class="full-width" + clearable + clear-icon="close" + @keyup.enter="() => selectFilter('search')" + @focusout="() => selectFilter('search')" + @clear="() => selectFilter('search')" + > + <template #append> + <QIcon name="info" class="cursor-pointer"> + <QTooltip>{{ t('tooltips.search') }}</QTooltip> + </QIcon> + </template> + </QInput> + </QItem> + <QItem> <VnSelect class="full-width" - :label="t('globals.user')" - v-model="userSelect" - option-label="name" - option-value="id" - :url="`${model}Logs/${$route.params.id}/editors`" - :fields="['id', 'nickname', 'name', 'image']" - sort-by="nickname" - @update:model-value="selectFilter('userSelect')" + :label="t('globals.entity')" + v-model="selectedFilters.changedModel" + option-label="locale" + option-value="value" + :options="actions" + @update:model-value="selectFilter('action')" hide-selected + /> + </QItem> + <QItem class="q-mt-sm"> + <QOptionGroup + size="sm" + v-model="userRadio" + :options="userTypes" + color="primary" + @update:model-value="selectFilter('userRadio')" + right-label > - <template #option="{ opt, itemProps }"> - <QItem v-bind="itemProps" class="q-pa-xs row items-center"> - <QItemSection class="col-3 items-center"> - <VnAvatar :worker-id="opt.id" /> - </QItemSection> - <QItemSection class="col-9 justify-center"> - <span>{{ opt.name }}</span> - <span class="text-grey">{{ opt.nickname }}</span> - </QItemSection> - </QItem> + <template #label="{ label }"> + {{ t(`Users.${label}`) }} </template> - </VnSelect> - </QItemSection> - </QItem> - <QItem class="q-mt-sm"> - <QInput - :label="t('globals.changes')" - v-model="changeInput" - class="full-width" - clearable - clear-icon="close" - @keyup.enter="selectFilter('change')" - @focusout="selectFilter('change')" - @clear="selectFilter('change')" + </QOptionGroup> + </QItem> + <QItem class="q-mt-sm"> + <QItemSection v-if="userRadio !== null"> + <VnSelect + class="full-width" + :label="t('globals.user')" + v-model="userSelect" + option-label="name" + option-value="id" + :url="`${model}Logs/${route.params.id}/editors`" + :fields="['id', 'nickname', 'name', 'image']" + sort-by="nickname" + @update:model-value="selectFilter('userSelect')" + hide-selected + > + <template #option="{ opt, itemProps }"> + <QItem + v-bind="itemProps" + class="q-pa-xs row items-center" + > + <QItemSection class="col-3 items-center"> + <VnAvatar :worker-id="opt.id" /> + </QItemSection> + <QItemSection class="col-9 justify-center"> + <span>{{ opt.name }}</span> + <span class="text-grey">{{ opt.nickname }}</span> + </QItemSection> + </QItem> + </template> + </VnSelect> + </QItemSection> + </QItem> + <QItem class="q-mt-sm"> + <QInput + :label="t('globals.changes')" + v-model="changeInput" + class="full-width" + clearable + clear-icon="close" + @keyup.enter="selectFilter('change')" + @focusout="selectFilter('change')" + @clear="selectFilter('change')" + > + <template #append> + <QIcon name="info" class="cursor-pointer"> + <QTooltip max-width="250px">{{ + t('tooltips.changes') + }}</QTooltip> + </QIcon> + </template> + </QInput> + </QItem> + <QItem + :class="index == 'create' ? 'q-mt-md' : 'q-mt-xs'" + v-for="(checkboxOption, index) in checkboxOptions" + :key="index" > - <template #append> - <QIcon name="info" class="cursor-pointer"> - <QTooltip max-width="250px">{{ - t('tooltips.changes') - }}</QTooltip> - </QIcon> - </template> - </QInput> - </QItem> - <QItem - :class="index == 'create' ? 'q-mt-md' : 'q-mt-xs'" - v-for="(checkboxOption, index) in checkboxOptions" - :key="index" - > - <QCheckbox - size="sm" - v-model="checkboxOption.selected" - :label="t(`actions.${checkboxOption.label}`)" - @update:model-value="selectFilter" - /> - </QItem> - <QItem class="q-mt-sm"> - <QInput - class="full-width" - :label="t('globals.date')" - @click="dateFromDialog = true" - @focus="(evt) => evt.target.blur()" - @clear="selectFilter('date', 'to')" - v-model="dateFrom" - clearable - clear-icon="close" - /> - </QItem> - <QItem class="q-mt-sm"> - <QInput - class="full-width" - :label="t('to')" - @click="dateToDialog = true" - @focus="(evt) => evt.target.blur()" - @clear="selectFilter('date', 'from')" - v-model="dateTo" - clearable - clear-icon="close" - /> - </QItem> - </QList> - </Teleport> + <QCheckbox + size="sm" + v-model="checkboxOption.selected" + :label="t(`actions.${checkboxOption.label}`)" + @update:model-value="selectFilter" + /> + </QItem> + <QItem class="q-mt-sm"> + <QInput + class="full-width" + :label="t('globals.date')" + @click="dateFromDialog = true" + @focus="(evt) => evt.target.blur()" + @clear="selectFilter('date', 'to')" + v-model="dateFrom" + clearable + clear-icon="close" + /> + </QItem> + <QItem class="q-mt-sm"> + <QInput + class="full-width" + :label="t('to')" + @click="dateToDialog = true" + @focus="(evt) => evt.target.blur()" + @clear="selectFilter('date', 'from')" + v-model="dateTo" + clearable + clear-icon="close" + /> + </QItem> + </QList> + </template> + </RightMenu> <QDialog v-model="dateFromDialog"> <QDate :years-in-month-view="false" diff --git a/src/components/common/VnSection.vue b/src/components/common/VnSection.vue index cacb3d551..e56784d4e 100644 --- a/src/components/common/VnSection.vue +++ b/src/components/common/VnSection.vue @@ -1,5 +1,5 @@ <script setup> -import RightMenu from './RightMenu.vue'; +import RightAdvancedMenu from './RightAdvancedMenu.vue'; import VnSearchbar from 'components/ui/VnSearchbar.vue'; import VnTableFilter from '../VnTable/VnTableFilter.vue'; import { onBeforeMount, onMounted, onUnmounted, computed, ref } from 'vue'; @@ -54,6 +54,7 @@ const sectionValue = computed(() => $props.section ?? $props.dataKey); const isMainSection = ref(false); const searchbarId = 'section-searchbar'; +const advancedMenuSlot = 'advanced-menu'; const hasContent = useHasContent(`#${searchbarId}`); onBeforeMount(() => { @@ -93,9 +94,9 @@ function checkIsMain() { /> <div :id="searchbarId"></div> </slot> - <RightMenu> - <template #right-panel v-if="$slots['rightMenu'] || rightFilter"> - <slot name="rightMenu"> + <RightAdvancedMenu :is-main-section="isMainSection"> + <template #advanced-menu v-if="$slots[advancedMenuSlot] || rightFilter"> + <slot :name="advancedMenuSlot"> <VnTableFilter v-if="rightFilter && columns" :data-key="dataKey" @@ -104,7 +105,7 @@ function checkIsMain() { /> </slot> </template> - </RightMenu> + </RightAdvancedMenu> <slot name="body" v-if="isMainSection" /> <RouterView v-else /> </template> diff --git a/src/components/ui/__tests__/VnSearchbar.spec.js b/src/components/ui/__tests__/VnSearchbar.spec.js new file mode 100644 index 000000000..25649194d --- /dev/null +++ b/src/components/ui/__tests__/VnSearchbar.spec.js @@ -0,0 +1,71 @@ +import { vi, describe, expect, it, beforeEach, afterEach } from 'vitest'; +import { createWrapper } from 'app/test/vitest/helper'; +import VnSearchbar from 'src/components/ui/VnSearchbar.vue'; + +describe('VnSearchbar', () => { + let vm; + let wrapper; + let applyFilterSpy; + const searchText = 'Bolas de madera'; + const userParams = {staticKey: 'staticValue'}; + + beforeEach(async () => { + wrapper = createWrapper(VnSearchbar, { + propsData: { + dataKey: 'testKey', + filter: null, + whereFilter: null, + searchRemoveParams: true, + }, + }); + wrapper = wrapper.wrapper; + vm = wrapper.vm; + + vm.searchText = searchText; + vm.arrayData.store.userParams = userParams; + applyFilterSpy = vi.spyOn(vm.arrayData, 'applyFilter').mockImplementation(() => {}); + + }); + + afterEach(() => { + vi.clearAllMocks(); + }); + + it('search resets pagination and applies filter', async () => { + const resetPaginationSpy = vi.spyOn(vm.arrayData, 'resetPagination').mockImplementation(() => {}); + await vm.search(); + + expect(resetPaginationSpy).toHaveBeenCalled(); + expect(applyFilterSpy).toHaveBeenCalledWith({ + params: { search: searchText }, + }); + }); + + it('search includes static params if searchRemoveParams is false', async () => { + wrapper.setProps({ searchRemoveParams: false }); + await vm.$nextTick(); + await vm.search(); + + expect(applyFilterSpy).toHaveBeenCalledWith({ + params: { staticKey: 'staticValue', search: searchText }, + filter: {skip: 0}, + }); + }); + + it('updates store when dataKey changes', async () => { + expect(vm.store.userParams).toEqual(userParams); + wrapper.setProps({ dataKey: 'newTestKey' }); + await vm.$nextTick(); + expect(vm.store.userParams).toEqual({}); + }); + + it('computes the "to" property correctly for redirection', () => { + vm.arrayData.store.searchUrl = 'searchParam'; + vm.arrayData.store.currentFilter = { category: 'plants' }; + const expectedQuery = JSON.stringify({ + ...vm.arrayData.store.currentFilter, + search: searchText, + }); + expect(vm.to.query.searchParam).toBe(expectedQuery); + }); +}); \ No newline at end of file diff --git a/src/composables/useHasContent.js b/src/composables/useHasContent.js index 8ab018376..21cb1f14d 100644 --- a/src/composables/useHasContent.js +++ b/src/composables/useHasContent.js @@ -5,7 +5,7 @@ export function useHasContent(selector) { const hasContent = ref(); onMounted(() => { - container.value = document.querySelector(selector); + container.value = document?.querySelector(selector); if (!container.value) return; const observer = new MutationObserver(() => { diff --git a/src/i18n/locale/en.yml b/src/i18n/locale/en.yml index 7f6eb1d20..0ec63283f 100644 --- a/src/i18n/locale/en.yml +++ b/src/i18n/locale/en.yml @@ -7,7 +7,8 @@ globals: entity: Entity user: User details: Details - collapseMenu: Collapse left menu + collapseMenu: Collapse lateral menu + advancedMenu: Advanced menu backToDashboard: Return to dashboard notifications: Notifications userPanel: User panel diff --git a/src/i18n/locale/es.yml b/src/i18n/locale/es.yml index 296aa07a1..447f792ab 100644 --- a/src/i18n/locale/es.yml +++ b/src/i18n/locale/es.yml @@ -8,6 +8,7 @@ globals: user: Usuario details: Detalles collapseMenu: Contraer menú lateral + advancedMenu: Menú avanzado backToDashboard: Volver al tablón notifications: Notificaciones userPanel: Panel de usuario diff --git a/src/pages/Claim/Card/ClaimAction.vue b/src/pages/Claim/Card/ClaimAction.vue index 2e890dba8..8ac7c224f 100644 --- a/src/pages/Claim/Card/ClaimAction.vue +++ b/src/pages/Claim/Card/ClaimAction.vue @@ -4,7 +4,6 @@ import { useQuasar } from 'quasar'; import { useI18n } from 'vue-i18n'; import { useRoute } from 'vue-router'; import axios from 'axios'; -import { useStateStore } from 'src/stores/useStateStore'; import { toDate, toPercentage, toCurrency } from 'filters/index'; import { tMobile } from 'src/composables/tMobile'; import CrudModel from 'src/components/CrudModel.vue'; @@ -13,11 +12,11 @@ import VnSelect from 'src/components/common/VnSelect.vue'; import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue'; import TicketDescriptorProxy from 'src/pages/Ticket/Card/TicketDescriptorProxy.vue'; import { useArrayData } from 'composables/useArrayData'; +import RightMenu from 'src/components/common/RightMenu.vue'; const { t } = useI18n(); const quasar = useQuasar(); const route = useRoute(); -const stateStore = computed(() => useStateStore()); const claim = ref(null); const claimRef = ref(); const claimId = route.params.id; @@ -201,58 +200,62 @@ async function post(query, params) { auto-load @on-fetch="(data) => (destinationTypes = data)" /> - <Teleport to="#right-panel" v-if="stateStore.isHeaderMounted() && claim"> - <QCard class="totalClaim q-my-md q-pa-sm no-box-shadow"> - {{ `${t('Total claimed')}: ${toCurrency(totalClaimed)}` }} - </QCard> - <QCard class="q-mb-md q-pa-sm no-box-shadow"> - <QItem class="justify-between"> - <QItemLabel class="slider-container"> - <p class="text-primary"> - {{ t('claim.actions') }} - </p> - <QSlider - class="responsibility { 'background-color:primary': quasar.platform.is.mobile }" - v-model="claim.responsibility" - :label-value="t('claim.responsibility')" - @change="(value) => save({ responsibility: value })" - label-always - color="primary" - markers - :marker-labels="marker_labels" - :min="DEFAULT_MIN_RESPONSABILITY" - :max="DEFAULT_MAX_RESPONSABILITY" + <RightMenu v-if="claim"> + <template #right-panel> + <QCard class="totalClaim q-my-md q-pa-sm no-box-shadow"> + {{ `${t('Total claimed')}: ${toCurrency(totalClaimed)}` }} + </QCard> + <QCard class="q-mb-md q-pa-sm no-box-shadow"> + <QItem class="justify-between"> + <QItemLabel class="slider-container"> + <p class="text-primary"> + {{ t('claim.actions') }} + </p> + <QSlider + class="responsibility { 'background-color:primary': quasar.platform.is.mobile }" + v-model="claim.responsibility" + :label-value="t('claim.responsibility')" + @change="(value) => save({ responsibility: value })" + label-always + color="primary" + markers + :marker-labels="marker_labels" + :min="DEFAULT_MIN_RESPONSABILITY" + :max="DEFAULT_MAX_RESPONSABILITY" + /> + </QItemLabel> + </QItem> + </QCard> + <QCard class="q-mb-md q-pa-sm no-box-shadow" style="margin-bottom: 1em"> + <QItemLabel class="mana q-mb-md"> + <QCheckbox + v-model="claim.isChargedToMana" + @update:model-value="(value) => save({ isChargedToMana: value })" /> + <span>{{ t('mana') }}</span> </QItemLabel> - </QItem> - </QCard> - <QCard class="q-mb-md q-pa-sm no-box-shadow" style="margin-bottom: 1em"> - <QItemLabel class="mana q-mb-md"> - <QCheckbox - v-model="claim.isChargedToMana" - @update:model-value="(value) => save({ isChargedToMana: value })" + </QCard> + <QCard class="q-mb-md q-pa-sm no-box-shadow" style="position: static"> + <QInput + :disable=" + !( + claim.responsibility >= + Math.ceil(DEFAULT_MAX_RESPONSABILITY) / 2 + ) + " + :label="t('confirmGreuges')" + class="q-field__native text-grey-2" + type="number" + placeholder="0" + id="multiplicatorValue" + name="multiplicatorValue" + min="0" + max="50" + v-model="multiplicatorValue" /> - <span>{{ t('mana') }}</span> - </QItemLabel> - </QCard> - <QCard class="q-mb-md q-pa-sm no-box-shadow" style="position: static"> - <QInput - :disable=" - !(claim.responsibility >= Math.ceil(DEFAULT_MAX_RESPONSABILITY) / 2) - " - :label="t('confirmGreuges')" - class="q-field__native text-grey-2" - type="number" - placeholder="0" - id="multiplicatorValue" - name="multiplicatorValue" - min="0" - max="50" - v-model="multiplicatorValue" - /> - </QCard> - </Teleport> - <Teleport to="#st-data" v-if="stateStore.isSubToolbarShown()"> </Teleport> + </QCard> + </template> + </RightMenu> <CrudModel v-if="claim" data-key="ClaimEnds" diff --git a/src/pages/Claim/ClaimList.vue b/src/pages/Claim/ClaimList.vue index 35b051cdc..ba74ba212 100644 --- a/src/pages/Claim/ClaimList.vue +++ b/src/pages/Claim/ClaimList.vue @@ -134,7 +134,7 @@ const STATE_COLOR = { order: ['cs.priority ASC', 'created ASC'], }" > - <template #rightMenu> + <template #advanced-menu> <ClaimFilter data-key="ClaimList" ref="claimFilterRef" /> </template> <template #body> diff --git a/src/pages/Order/Card/OrderCatalog.vue b/src/pages/Order/Card/OrderCatalog.vue index 186f216fb..d7efdb726 100644 --- a/src/pages/Order/Card/OrderCatalog.vue +++ b/src/pages/Order/Card/OrderCatalog.vue @@ -1,7 +1,7 @@ <script setup> import { useStateStore } from 'stores/useStateStore'; import { useRoute, useRouter } from 'vue-router'; -import { onMounted, ref, computed, watch } from 'vue'; +import { onMounted, ref, watch } from 'vue'; import axios from 'axios'; import { useI18n } from 'vue-i18n'; import VnPaginate from 'src/components/ui/VnPaginate.vue'; @@ -9,6 +9,7 @@ import CatalogItem from 'src/components/ui/CatalogItem.vue'; 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'; const route = useRoute(); const router = useRouter(); @@ -89,14 +90,16 @@ watch( :search-remove-params="false" /> </Teleport> - <Teleport to="#right-panel" v-if="stateStore.isHeaderMounted()"> - <OrderCatalogFilter - :data-key="dataKey" - :tag-value="tagValue" - :tags="tags" - :initial-catalog-params="catalogParams" - /> - </Teleport> + <RightMenu> + <template #right-panel> + <OrderCatalogFilter + :data-key="dataKey" + :tag-value="tagValue" + :tags="tags" + :initial-catalog-params="catalogParams" + /> + </template> + </RightMenu> <QPage class="column items-center q-pa-md" data-cy="orderCatalogPage"> <div class="full-width"> <VnPaginate :data-key="dataKey"> @@ -141,5 +144,5 @@ watch( <i18n> es: You can search items by name or id: Puedes buscar items por nombre o id - Search items: Buscar items + Search items: Buscar artículos </i18n> diff --git a/src/pages/Order/Card/OrderLines.vue b/src/pages/Order/Card/OrderLines.vue index 536d1decb..e9c53d161 100644 --- a/src/pages/Order/Card/OrderLines.vue +++ b/src/pages/Order/Card/OrderLines.vue @@ -4,7 +4,6 @@ import { useI18n } from 'vue-i18n'; import { ref, computed, watch } from 'vue'; import { useQuasar } from 'quasar'; import axios from 'axios'; -import { useStateStore } from 'stores/useStateStore'; import { useArrayData } from 'composables/useArrayData'; import { confirm } from 'src/pages/Order/composables/confirmOrder'; import { toCurrency, toDate } from 'src/filters'; @@ -17,9 +16,9 @@ import VnLv from 'src/components/ui/VnLv.vue'; import FetchedTags from 'src/components/ui/FetchedTags.vue'; import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue'; import VnCurrency from 'src/components/ui/VnCurrency.vue'; +import RightMenu from 'src/components/common/RightMenu.vue'; const router = useRouter(); -const stateStore = useStateStore(); const route = useRoute(); const { t } = useI18n(); const quasar = useQuasar(); @@ -240,7 +239,7 @@ watch( lineFilter.value.where.orderFk = router.currentRoute.value.params.id; tableLinesRef.value.reload(); - } + }, ); </script> @@ -265,52 +264,53 @@ watch( @on-fetch="(data) => (orderSummary = { ...orderSummary, ...data })" auto-load /> - <Teleport to="#right-panel" v-if="stateStore.isHeaderMounted()"> - <QCard - class="order-lines-summary q-pa-lg" - v-if="orderSummary.vat && orderSummary.total" - > - <p class="header text-right block"> - {{ t('summary') }} - </p> - <VnLv - :label="t('subtotal') + ': '" - :value="toCurrency(orderSummary.total - orderSummary.vat)" + <RightMenu> + <template #right-panel> + <QCard + class="order-lines-summary q-pa-lg" + v-if="orderSummary.vat && orderSummary.total" > - <template #value> - <VnCurrency - :model="{ - price: orderSummary.total - orderSummary.vat, - foreignPrice: - orderSummary.foreignTotal - orderSummary.foreignVat, - }" - array-data-model="Order" - /> - </template> - </VnLv> - <VnLv :label="t('VAT') + ': '"> - <template #value> - <VnCurrency - :model="orderSummary" - array-data-model="Order" - local-field="vat" - foreign-field="foreignVat" - /> - </template> - </VnLv> - <VnLv :label="t('total') + ': '"> - <template #value> - <VnCurrency - :model="orderSummary" - array-data-model="Order" - local-field="total" - foreign-field="foreignTotal" - /> - </template> - </VnLv> - </QCard> - </Teleport> - + <p class="header text-right block"> + {{ t('summary') }} + </p> + <VnLv + :label="t('subtotal') + ': '" + :value="toCurrency(orderSummary.total - orderSummary.vat)" + > + <template #value> + <VnCurrency + :model="{ + price: orderSummary.total - orderSummary.vat, + foreignPrice: + orderSummary.foreignTotal - orderSummary.foreignVat, + }" + array-data-model="Order" + /> + </template> + </VnLv> + <VnLv :label="t('VAT') + ': '"> + <template #value> + <VnCurrency + :model="orderSummary" + array-data-model="Order" + local-field="vat" + foreign-field="foreignVat" + /> + </template> + </VnLv> + <VnLv :label="t('total') + ': '"> + <template #value> + <VnCurrency + :model="orderSummary" + array-data-model="Order" + local-field="total" + foreign-field="foreignTotal" + /> + </template> + </VnLv> + </QCard> + </template> + </RightMenu> <VnTable ref="tableLinesRef" data-key="OrderLines" diff --git a/src/pages/Order/OrderList.vue b/src/pages/Order/OrderList.vue index 5296255e2..6340c0a15 100644 --- a/src/pages/Order/OrderList.vue +++ b/src/pages/Order/OrderList.vue @@ -192,7 +192,7 @@ const getDateColor = (date) => { order: ['landed DESC', 'clientFk ASC', 'id DESC'], }" > - <template #rightMenu> + <template #advanced-menu> <OrderFilter data-key="OrderList" /> </template> <template #body> diff --git a/src/pages/Ticket/Card/TicketBoxing.vue b/src/pages/Ticket/Card/TicketBoxing.vue index 816419dd5..26b38d706 100644 --- a/src/pages/Ticket/Card/TicketBoxing.vue +++ b/src/pages/Ticket/Card/TicketBoxing.vue @@ -1,7 +1,7 @@ <script setup> import axios from 'axios'; import { date, useQuasar } from 'quasar'; -import { useStateStore } from 'src/stores/useStateStore'; +import RightMenu from 'src/components/common/RightMenu.vue'; import { computed, onMounted, reactive, ref } from 'vue'; import { useI18n } from 'vue-i18n'; import { useRouter } from 'vue-router'; @@ -9,9 +9,7 @@ import { useRouter } from 'vue-router'; const router = useRouter(); const { t } = useI18n(); const quasar = useQuasar(); -const stateStore = useStateStore(); onMounted(async () => { - stateStore.rightDrawer = true; await fetch(); }); @@ -86,69 +84,73 @@ async function getVideoList(expeditionId, timed) { </script> <template> - <Teleport to="#right-panel" v-if="stateStore.isHeaderMounted()"> - <QList bordered separator style="max-width: 318px"> - <QItem v-if="lastExpedition && videoList.length"> - <QItemSection> - <QItemLabel class="text-h6"> - {{ t('ticket.boxing.selectTime') }} ({{ time.min }}-{{ - time.max - }}) - </QItemLabel> - <QRange - v-model="time" - @change="getVideoList(lastExpedition, time)" - :min="0" - :max="24" - :step="1" - :left-label-value="time.min + ':00'" - :right-label-value="time.max + ':00'" - label - markers - snap - color="primary" - /> - </QItemSection> - </QItem> - <QItem v-if="lastExpedition && videoList.length"> - <QItemSection> - <QSelect - color="primary" - v-model="slide" - :options="videoList" - :label="t('ticket.boxing.selectVideo')" - emit-value - map-options - > - <template #prepend> - <QIcon name="schedule" /> - </template> - </QSelect> - </QItemSection> - </QItem> - <QItem - v-for="expedition in expeditions" - :key="expedition.id" - @click="getVideoList(expedition.id)" - clickable - v-ripple - > - <QItemSection> - <QItemLabel class="text-h6">#{{ expedition.id }}</QItemLabel> - </QItemSection> - <QItemSection> - <QItemLabel caption>{{ t('globals.created') }}</QItemLabel> - <QItemLabel> - {{ date.formatDate(expedition.created, 'YYYY-MM-DD HH:mm:ss') }} - </QItemLabel> - <QItemLabel caption>{{ t('globals.item') }}</QItemLabel> - <QItemLabel>{{ expedition.packagingItemFk }}</QItemLabel> - <QItemLabel caption>{{ t('ticket.boxing.worker') }}</QItemLabel> - <QItemLabel>{{ expedition.userName }}</QItemLabel> - </QItemSection> - </QItem> - </QList> - </Teleport> + <RightMenu> + <template #right-panel> + <QList bordered separator style="max-width: 318px"> + <QItem v-if="lastExpedition && videoList.length"> + <QItemSection> + <QItemLabel class="text-h6"> + {{ t('ticket.boxing.selectTime') }} ({{ time.min }}-{{ + time.max + }}) + </QItemLabel> + <QRange + v-model="time" + @change="getVideoList(lastExpedition, time)" + :min="0" + :max="24" + :step="1" + :left-label-value="time.min + ':00'" + :right-label-value="time.max + ':00'" + label + markers + snap + color="primary" + /> + </QItemSection> + </QItem> + <QItem v-if="lastExpedition && videoList.length"> + <QItemSection> + <QSelect + color="primary" + v-model="slide" + :options="videoList" + :label="t('ticket.boxing.selectVideo')" + emit-value + map-options + > + <template #prepend> + <QIcon name="schedule" /> + </template> + </QSelect> + </QItemSection> + </QItem> + <QItem + v-for="expedition in expeditions" + :key="expedition.id" + @click="getVideoList(expedition.id)" + clickable + v-ripple + > + <QItemSection> + <QItemLabel class="text-h6">#{{ expedition.id }}</QItemLabel> + </QItemSection> + <QItemSection> + <QItemLabel caption>{{ t('globals.created') }}</QItemLabel> + <QItemLabel> + {{ + date.formatDate(expedition.created, 'YYYY-MM-DD HH:mm:ss') + }} + </QItemLabel> + <QItemLabel caption>{{ t('globals.item') }}</QItemLabel> + <QItemLabel>{{ expedition.packagingItemFk }}</QItemLabel> + <QItemLabel caption>{{ t('ticket.boxing.worker') }}</QItemLabel> + <QItemLabel>{{ expedition.userName }}</QItemLabel> + </QItemSection> + </QItem> + </QList> + </template> + </RightMenu> <QCard> <QCarousel animated v-model="slide" height="max-content"> <QCarouselSlide diff --git a/src/pages/Ticket/Card/TicketComponents.vue b/src/pages/Ticket/Card/TicketComponents.vue index 64815752a..842607e0c 100644 --- a/src/pages/Ticket/Card/TicketComponents.vue +++ b/src/pages/Ticket/Card/TicketComponents.vue @@ -1,5 +1,5 @@ <script setup> -import { ref, computed, onMounted, watch, nextTick } from 'vue'; +import { ref, computed, watch, nextTick } from 'vue'; import { useI18n } from 'vue-i18n'; import { useRoute } from 'vue-router'; @@ -9,15 +9,14 @@ import FetchData from 'components/FetchData.vue'; import ZoneDescriptorProxy from 'src/pages/Zone/Card/ZoneDescriptorProxy.vue'; import VnImg from 'src/components/ui/VnImg.vue'; -import { useStateStore } from 'stores/useStateStore'; import { dashIfEmpty } from 'src/filters'; import { useArrayData } from 'composables/useArrayData'; import { toCurrency } from 'filters/index'; import axios from 'axios'; import VnTable from 'src/components/VnTable/VnTable.vue'; +import RightMenu from 'src/components/common/RightMenu.vue'; const route = useRoute(); -const stateStore = useStateStore(); const { t } = useI18n(); const salesRef = ref(null); const arrayData = useArrayData('ticketData'); @@ -164,10 +163,6 @@ const getTicketVolume = async () => { const { data } = await axios.get(`Tickets/${ticketData.value.id}/getVolume`); ticketVolume.value = data[0].volume; }; - -onMounted(() => { - stateStore.rightDrawer = true; -}); </script> <template> @@ -178,93 +173,121 @@ onMounted(() => { @on-fetch="(data) => (components = data)" auto-load /> - <Teleport to="#right-panel" v-if="stateStore.isHeaderMounted()"> - <QCard class="q-pa-sm color-vn-text" bordered flat style="border-color: black"> - <QCardSection horizontal> - <span class="text-weight-bold text-subtitle1 text-center full-width"> - {{ t('basicData.total') }} - </span> - </QCardSection> - <QCardSection horizontal> - <span class="q-mr-xs color-vn-label" - >{{ t('ticketComponents.baseToCommission') }}: - </span> - <span>{{ toCurrency(getBase) }}</span> - </QCardSection> - <QCardSection horizontal> - <span class="q-mr-xs color-vn-label" - >{{ t('ticketComponents.totalWithoutVat') }}: - </span> - <span>{{ toCurrency(getTotal) }}</span> - </QCardSection> - </QCard> - <QCard class="q-pa-sm color-vn-text" bordered flat style="border-color: black"> - <QCardSection horizontal> - <span class="text-weight-bold text-subtitle1 text-center full-width"> - {{ t('ticketComponents.components') }} - </span> - </QCardSection> - <QCardSection - v-for="(component, index) in componentsList" - :key="index" - horizontal + <RightMenu> + <template #right-panel> + <QCard + class="q-pa-sm color-vn-text" + bordered + flat + style="border-color: black" > - <span v-if="component.name" class="q-mr-xs color-vn-label"> - {{ component.name }}: - </span> - <span v-if="component.value">{{ - toCurrency(component.value, 'EUR', 3) - }}</span> - </QCardSection> - </QCard> - <QCard class="q-pa-sm color-vn-text" bordered flat style="border-color: black"> - <QCardSection horizontal> - <span class="text-weight-bold text-subtitle1 text-center full-width"> - {{ t('ticketComponents.zoneBreakdown') }} - </span> - </QCardSection> - <QCardSection horizontal> - <span class="q-mr-xs color-vn-label"> {{ t('basicData.price') }}: </span> - <span>{{ toCurrency(ticketData?.zonePrice, 'EUR', 2) }}</span> - </QCardSection> - <QCardSection horizontal> - <span class="q-mr-xs color-vn-label"> - {{ t('ticketComponents.bonus') }}: - </span> - <span>{{ toCurrency(ticketData?.zoneBonus, 'EUR', 2) }}</span> - </QCardSection> - <QCardSection horizontal> - <span class="q-mr-xs color-vn-label"> {{ t('ticketList.zone') }}: </span> - <span class="link"> - {{ dashIfEmpty(ticketData?.zone?.name) }} - <ZoneDescriptorProxy :id="ticketData?.zone?.id" /> - </span> - </QCardSection> - <QCardSection v-if="ticketData?.zone?.isVolumetric" horizontal> - <span class="q-mr-xs color-vn-label"> {{ t('volume.volume') }}: </span> - <span>{{ ticketVolume }}</span> - </QCardSection> - <QCardSection horizontal> - <span class="q-mr-xs color-vn-label"> - {{ t('ticketComponents.packages') }}: - </span> - <span>{{ dashIfEmpty(ticketData?.packages) }}</span> - </QCardSection> - </QCard> - <QCard class="q-pa-sm color-vn-text" bordered flat style="border-color: black"> - <QCardSection horizontal> - <span class="text-weight-bold text-subtitle1 text-center full-width"> - {{ t('ticketComponents.theoricalCost') }} - </span> - </QCardSection> - <QCardSection horizontal> - <span class="q-mr-xs color-vn-label"> - {{ t('ticketComponents.totalPrice') }}: - </span> - <span>{{ toCurrency(theoricalCost, 'EUR', 2) }}</span> - </QCardSection> - </QCard> - </Teleport> + <QCardSection horizontal> + <span class="text-weight-bold text-subtitle1 text-center full-width"> + {{ t('basicData.total') }} + </span> + </QCardSection> + <QCardSection horizontal> + <span class="q-mr-xs color-vn-label" + >{{ t('ticketComponents.baseToCommission') }}: + </span> + <span>{{ toCurrency(getBase) }}</span> + </QCardSection> + <QCardSection horizontal> + <span class="q-mr-xs color-vn-label" + >{{ t('ticketComponents.totalWithoutVat') }}: + </span> + <span>{{ toCurrency(getTotal) }}</span> + </QCardSection> + </QCard> + <QCard + class="q-pa-sm color-vn-text" + bordered + flat + style="border-color: black" + > + <QCardSection horizontal> + <span class="text-weight-bold text-subtitle1 text-center full-width"> + {{ t('ticketComponents.components') }} + </span> + </QCardSection> + <QCardSection + v-for="(component, index) in componentsList" + :key="index" + horizontal + > + <span v-if="component.name" class="q-mr-xs color-vn-label"> + {{ component.name }}: + </span> + <span v-if="component.value">{{ + toCurrency(component.value, 'EUR', 3) + }}</span> + </QCardSection> + </QCard> + <QCard + class="q-pa-sm color-vn-text" + bordered + flat + style="border-color: black" + > + <QCardSection horizontal> + <span class="text-weight-bold text-subtitle1 text-center full-width"> + {{ t('ticketComponents.zoneBreakdown') }} + </span> + </QCardSection> + <QCardSection horizontal> + <span class="q-mr-xs color-vn-label"> + {{ t('basicData.price') }}: + </span> + <span>{{ toCurrency(ticketData?.zonePrice, 'EUR', 2) }}</span> + </QCardSection> + <QCardSection horizontal> + <span class="q-mr-xs color-vn-label"> + {{ t('ticketComponents.bonus') }}: + </span> + <span>{{ toCurrency(ticketData?.zoneBonus, 'EUR', 2) }}</span> + </QCardSection> + <QCardSection horizontal> + <span class="q-mr-xs color-vn-label"> + {{ t('ticketList.zone') }}: + </span> + <span class="link"> + {{ dashIfEmpty(ticketData?.zone?.name) }} + <ZoneDescriptorProxy :id="ticketData?.zone?.id" /> + </span> + </QCardSection> + <QCardSection v-if="ticketData?.zone?.isVolumetric" horizontal> + <span class="q-mr-xs color-vn-label"> + {{ t('volume.volume') }}: + </span> + <span>{{ ticketVolume }}</span> + </QCardSection> + <QCardSection horizontal> + <span class="q-mr-xs color-vn-label"> + {{ t('ticketComponents.packages') }}: + </span> + <span>{{ dashIfEmpty(ticketData?.packages) }}</span> + </QCardSection> + </QCard> + <QCard + class="q-pa-sm color-vn-text" + bordered + flat + style="border-color: black" + > + <QCardSection horizontal> + <span class="text-weight-bold text-subtitle1 text-center full-width"> + {{ t('ticketComponents.theoricalCost') }} + </span> + </QCardSection> + <QCardSection horizontal> + <span class="q-mr-xs color-vn-label"> + {{ t('ticketComponents.totalPrice') }}: + </span> + <span>{{ toCurrency(theoricalCost, 'EUR', 2) }}</span> + </QCardSection> + </QCard> + </template> + </RightMenu> <VnTable ref="tableRef" data-key="TicketComponents" diff --git a/src/pages/Ticket/Card/TicketSale.vue b/src/pages/Ticket/Card/TicketSale.vue index 588b9ef76..d82614e94 100644 --- a/src/pages/Ticket/Card/TicketSale.vue +++ b/src/pages/Ticket/Card/TicketSale.vue @@ -16,7 +16,6 @@ import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue'; import TicketSaleMoreActions from './TicketSaleMoreActions.vue'; import TicketTransfer from './TicketTransfer.vue'; -import { useStateStore } from 'stores/useStateStore'; import { toCurrency, toPercentage } from 'src/filters'; import { useArrayData } from 'composables/useArrayData'; import { useVnConfirm } from 'composables/useVnConfirm'; @@ -26,10 +25,10 @@ import VnTable from 'src/components/VnTable/VnTable.vue'; import VnUsesMana from 'src/components/ui/VnUsesMana.vue'; import VnConfirm from 'src/components/ui/VnConfirm.vue'; import VnCurrency from 'src/components/ui/VnCurrency.vue'; +import RightMenu from 'src/components/common/RightMenu.vue'; const route = useRoute(); const router = useRouter(); -const stateStore = useStateStore(); const { t } = useI18n(); const { notify } = useNotify(); const { openConfirmationModal } = useVnConfirm(); @@ -420,7 +419,6 @@ const setTransferParams = async () => { }; onMounted(async () => { - stateStore.rightDrawer = true; getConfig(); }); @@ -621,47 +619,56 @@ watch( </QBtnGroup> </template> </VnSubToolbar> - <Teleport to="#right-panel" v-if="stateStore.isHeaderMounted() && store.data"> - <div - class="q-pa-md q-mb-md q-ma-md color-vn-text" - style="border: 2px solid black" - > - <QCardSection class="justify-end text-subtitle1" horizontal> - <span class="q-mr-xs color-vn-label" - >{{ t('ticketSale.subtotal') }}: - </span> - <VnCurrency - :model="store.data" - :currency-code="store.data.currency.code" - local-field="totalWithoutVat" - foreign-field="foreignTotalWithoutVat" - /> - </QCardSection> - <QCardSection class="justify-end text-subtitle1" horizontal> - <span class="q-mr-xs color-vn-label"> {{ t('ticketSale.tax') }}: </span> - <VnCurrency - :model="{ - vat: store.data.totalWithVat - store.data?.totalWithoutVat, - foreignVat: - store.data.foreignTotalWithVat - - store.data?.foreignTotalWithoutVat, - }" - :currency-code="store.data.currency.code" - local-field="vat" - foreign-field="foreignVat" - /> - </QCardSection> - <QCardSection class="justify-end text-weight-bold text-subtitle1" horizontal> - <span class="q-mr-xs color-vn-label"> {{ t('basicData.total') }}: </span> - <VnCurrency - :model="store.data" - :currency-code="store.data.currency.code" - local-field="totalWithVat" - foreign-field="foreignTotalWithVat" - /> - </QCardSection> - </div> - </Teleport> + <RightMenu> + <template #right-panel> + <div + class="q-pa-md q-mb-md q-ma-md color-vn-text" + style="border: 2px solid black" + > + <QCardSection class="justify-end text-subtitle1" horizontal> + <span class="q-mr-xs color-vn-label" + >{{ t('ticketSale.subtotal') }}: + </span> + <VnCurrency + :model="store.data" + :currency-code="store.data.currency.code" + local-field="totalWithoutVat" + foreign-field="foreignTotalWithoutVat" + /> + </QCardSection> + <QCardSection class="justify-end text-subtitle1" horizontal> + <span class="q-mr-xs color-vn-label"> + {{ t('ticketSale.tax') }}: + </span> + <VnCurrency + :model="{ + vat: store.data.totalWithVat - store.data?.totalWithoutVat, + foreignVat: + store.data.foreignTotalWithVat - + store.data?.foreignTotalWithoutVat, + }" + :currency-code="store.data.currency.code" + local-field="vat" + foreign-field="foreignVat" + /> + </QCardSection> + <QCardSection + class="justify-end text-weight-bold text-subtitle1" + horizontal + > + <span class="q-mr-xs color-vn-label"> + {{ t('basicData.total') }}: + </span> + <VnCurrency + :model="store.data" + :currency-code="store.data.currency.code" + local-field="totalWithVat" + foreign-field="foreignTotalWithVat" + /> + </QCardSection> + </div> + </template> + </RightMenu> <VnTable ref="tableRef" data-key="TicketSales" diff --git a/src/pages/Ticket/TicketList.vue b/src/pages/Ticket/TicketList.vue index 85f16fc6a..db5d67519 100644 --- a/src/pages/Ticket/TicketList.vue +++ b/src/pages/Ticket/TicketList.vue @@ -471,7 +471,7 @@ function isLittle(row) { exprBuilder, }" > - <template #rightMenu> + <template #advanced-menu> <TicketFilter data-key="TicketList" /> </template> <template #body> diff --git a/src/pages/Worker/Card/WorkerCalendar.vue b/src/pages/Worker/Card/WorkerCalendar.vue index e9cb793f4..5ca95a1a4 100644 --- a/src/pages/Worker/Card/WorkerCalendar.vue +++ b/src/pages/Worker/Card/WorkerCalendar.vue @@ -1,18 +1,16 @@ <script setup> import { nextTick, ref, watch } from 'vue'; import { useI18n } from 'vue-i18n'; -import { useRoute } from 'vue-router'; +import { useRoute, useRouter } from 'vue-router'; import WorkerCalendarFilter from 'pages/Worker/Card/WorkerCalendarFilter.vue'; import FetchData from 'components/FetchData.vue'; import WorkerCalendarItem from 'pages/Worker/Card/WorkerCalendarItem.vue'; +import RightMenu from 'src/components/common/RightMenu.vue'; -import { useStateStore } from 'stores/useStateStore'; import axios from 'axios'; -import { useRouter } from 'vue-router'; const router = useRouter(); -const stateStore = useStateStore(); const route = useRoute(); const { t } = useI18n(); const workerIsFreelance = ref(); @@ -171,16 +169,18 @@ watch([year, businessFk], () => refreshData()); ref="WorkerFreelanceRef" auto-load /> - <Teleport to="#right-panel" v-if="stateStore.isHeaderMounted()"> - <WorkerCalendarFilter - ref="workerCalendarFilterRef" - v-model:business-fk="businessFk" - v-model:year="year" - v-model:absence-type="absenceType" - :contract-holidays="contractHolidays" - :year-holidays="yearHolidays" - /> - </Teleport> + <RightMenu> + <template #right-panel> + <WorkerCalendarFilter + ref="workerCalendarFilterRef" + v-model:business-fk="businessFk" + v-model:year="year" + v-model:absence-type="absenceType" + :contract-holidays="contractHolidays" + :year-holidays="yearHolidays" + /> + </template> + </RightMenu> <QPage class="column items-center"> <QCard v-if="workerIsFreelance"> <QCardSection class="text-center"> diff --git a/src/pages/Worker/Card/WorkerTimeControl.vue b/src/pages/Worker/Card/WorkerTimeControl.vue index 919331e2d..c580e5202 100644 --- a/src/pages/Worker/Card/WorkerTimeControl.vue +++ b/src/pages/Worker/Card/WorkerTimeControl.vue @@ -10,6 +10,7 @@ import WorkerTimeForm from 'pages/Worker/Card/WorkerTimeForm.vue'; import WorkerTimeReasonForm from 'pages/Worker/Card/WorkerTimeReasonForm.vue'; import WorkerDateLabel from './WorkerDateLabel.vue'; import WorkerTimeControlCalendar from 'pages/Worker/Card/WorkerTimeControlCalendar.vue'; +import RightMenu from 'src/components/common/RightMenu.vue'; import useNotify from 'src/composables/useNotify.js'; import axios from 'axios'; @@ -483,33 +484,35 @@ onMounted(async () => { </QBtnGroup> </div> </Teleport> - <Teleport to="#right-panel" v-if="stateStore.isHeaderMounted()"> - <div class="q-pa-md q-mb-md" style="border: 2px solid #222"> - <QCardSection horizontal> - <span class="text-weight-bold text-subtitle1 text-center full-width"> - {{ t('Hours') }} - </span> - </QCardSection> - <QCardSection class="column items-center" horizontal> - <div> - <span class="details-label">{{ t('Total semana') }} </span> - <span>: {{ formattedWeekTotalHours }}</span> - </div> - <div> - <span class="details-label">{{ t('Termina a las') }}: </span> - <span>{{ dashIfEmpty(getFinishTime()) }}</span> - </div> - </QCardSection> - </div> - <WorkerTimeControlCalendar - v-model:model-value="selectedDateFormatted" - :selected-dates="selectedCalendarDates" - :active-date="false" - :worker-time-control-mails="workerTimeControlMails" - @click-date="onInputChange" - @on-moved="getMailStates" - /> - </Teleport> + <RightMenu> + <template #right-panel> + <div class="q-pa-md q-mb-md" style="border: 2px solid #222"> + <QCardSection horizontal> + <span class="text-weight-bold text-subtitle1 text-center full-width"> + {{ t('Hours') }} + </span> + </QCardSection> + <QCardSection class="column items-center" horizontal> + <div> + <span class="details-label">{{ t('Total semana') }} </span> + <span>: {{ formattedWeekTotalHours }}</span> + </div> + <div> + <span class="details-label">{{ t('Termina a las') }}: </span> + <span>{{ dashIfEmpty(getFinishTime()) }}</span> + </div> + </QCardSection> + </div> + <WorkerTimeControlCalendar + v-model:model-value="selectedDateFormatted" + :selected-dates="selectedCalendarDates" + :active-date="false" + :worker-time-control-mails="workerTimeControlMails" + @click-date="onInputChange" + @on-moved="getMailStates" + /> + </template> + </RightMenu> <QPage class="column items-center"> <QTable :columns="columns" :rows="['']" hide-bottom class="full-width"> <template #header="props"> diff --git a/src/pages/Worker/WorkerFilter.vue b/src/pages/Worker/WorkerFilter.vue index dfb5659fe..8210ba0e3 100644 --- a/src/pages/Worker/WorkerFilter.vue +++ b/src/pages/Worker/WorkerFilter.vue @@ -98,6 +98,15 @@ const getLocale = (label) => { /> </QItemSection> </QItem> + <QItem> + <QItemSection> + <QCheckbox + :label="t('globals.params.myTeam')" + v-model="params.myTeam" + toggle-indeterminate + /> + </QItemSection> + </QItem> </template> </VnFilterPanel> </template> diff --git a/src/pages/Worker/WorkerList.vue b/src/pages/Worker/WorkerList.vue index 8e02e59a4..d6eb0684d 100644 --- a/src/pages/Worker/WorkerList.vue +++ b/src/pages/Worker/WorkerList.vue @@ -199,7 +199,7 @@ async function autofillBic(worker) { order: 'id DESC', }" > - <template #rightMenu> + <template #advanced-menu> <WorkerFilter data-key="WorkerList" /> </template> <template #body> diff --git a/src/router/modules/ticket.js b/src/router/modules/ticket.js index 35681ec93..4d5cccc41 100644 --- a/src/router/modules/ticket.js +++ b/src/router/modules/ticket.js @@ -168,7 +168,7 @@ const ticketCard = { name: 'TicketBoxing', meta: { title: 'boxing', - icon: 'science', + icon: 'view_in_ar', }, component: () => import('src/pages/Ticket/Card/TicketBoxing.vue'), }, diff --git a/src/stores/useStateStore.js b/src/stores/useStateStore.js index 686e76c77..e48b67279 100644 --- a/src/stores/useStateStore.js +++ b/src/stores/useStateStore.js @@ -5,6 +5,7 @@ export const useStateStore = defineStore('stateStore', () => { const isMounted = ref(false); const leftDrawer = ref(false); const rightDrawer = ref(false); + const rightAdvancedDrawer = ref(false); const subToolbar = ref(false); function toggleLeftDrawer() { @@ -15,6 +16,10 @@ export const useStateStore = defineStore('stateStore', () => { rightDrawer.value = !rightDrawer.value; } + function toggleRightAdvancedDrawer() { + rightAdvancedDrawer.value = !rightAdvancedDrawer.value; + } + function rightDrawerChangeValue(value) { rightDrawer.value = value; } @@ -46,10 +51,12 @@ export const useStateStore = defineStore('stateStore', () => { return { leftDrawer, rightDrawer, + rightAdvancedDrawer, setMounted, isHeaderMounted, toggleLeftDrawer, toggleRightDrawer, + toggleRightAdvancedDrawer, isLeftDrawerShown, isRightDrawerShown, isSubToolbarShown,