0
0
Fork 0

Added ticket filter panel

This commit is contained in:
Joan Sanchez 2023-02-16 15:01:02 +01:00
parent bd904ad82a
commit 984b1f9e24
6 changed files with 318 additions and 62 deletions

View File

@ -1,7 +1,9 @@
<script setup> <script setup>
import { onMounted, ref, computed } from 'vue'; import { onMounted, ref, computed } from 'vue';
import { useI18n } from 'vue-i18n';
import { useArrayData } from 'composables/useArrayData'; import { useArrayData } from 'composables/useArrayData';
const { t } = useI18n();
const props = defineProps({ const props = defineProps({
dataKey: { dataKey: {
type: String, type: String,
@ -49,27 +51,35 @@ async function remove(key) {
} }
</script> </script>
<template> <template>
<div> <div class="q-pa-sm truncate-chip-labels">
<q-list> <span v-if="tags.length === 0">You didn't enter any filter</span>
<q-item-label header class="text-uppercase" dense> <q-chip
Applied filters v-for="chip of tags"
</q-item-label> :key="chip.label"
</q-list> @remove="remove(chip.label)"
<div class="q-pa-sm truncate-chip-labels"> icon="label"
<span v-if="tags.length === 0">You didn't enter any filter</span> color="primary"
<q-chip class="text-dark"
v-for="chip of tags" size="sm"
:key="chip.label" removable
@remove="remove(chip.label)" >
icon="label" <slot name="tags" :tag="chip">
color="primary" <div class="q-gutter-md">
size="sm" <strong>{{ chip.label }}:</strong>
removable <span>"{{ chip.value }}"</span>
> </div>
<strong>{{ chip.label }}: </strong> </slot>
<span>"{{ chip.value }}"</span> </q-chip>
</q-chip> </div>
</div> <q-toolbar>
<q-item-label header class="q-pa-none text-uppercase" dense>
{{ t('appliedFilters') }}
</q-item-label>
<q-space />
<q-btn icon="clear_all" color="primary" size="sm" round flat dense />
<q-btn icon="refresh" color="primary" size="sm" round flat dense />
</q-toolbar>
<q-form @submit="search" @keyup.enter="search">
<div v-show="props.searchButton"> <div v-show="props.searchButton">
<q-separator /> <q-separator />
<q-item> <q-item>
@ -79,14 +89,25 @@ async function remove(key) {
type="submit" type="submit"
color="primary" color="primary"
class="full-width" class="full-width"
icon="search"
rounded rounded
dense
/> />
</q-item-section> </q-item-section>
</q-item> </q-item>
</div> </div>
<q-separator /> <q-separator />
<q-form @submit="search" @keyup.enter="search"> <slot name="body" :params="userParams"></slot>
<slot name="body" :params="userParams"></slot> </q-form>
</q-form>
</div>
</template> </template>
<i18n>
{
"en": {
"appliedFilters": "Applied filters"
},
"es": {
"appliedFilters": "Filtros aplicados"
}
}
</i18n>

View File

@ -49,7 +49,6 @@ async function search() {
const firstRow = rows[0]; const firstRow = rows[0];
const stateName = `${moduleRoute.name}Card`; const stateName = `${moduleRoute.name}Card`;
await router.push({ name: stateName, params: { id: firstRow.id } }); await router.push({ name: stateName, params: { id: firstRow.id } });
arrayData.updateStateParams();
} else if (route.matched.length > 3) { } else if (route.matched.length > 3) {
await router.push({ name: moduleRoute.name }); await router.push({ name: moduleRoute.name });
arrayData.updateStateParams(); arrayData.updateStateParams();

View File

@ -127,14 +127,16 @@ export function useArrayData(key, userOptions) {
} }
function updateStateParams() { function updateStateParams() {
const query = {};
if (store.order) query.order = store.order;
if (store.limit) query.limit = store.limit;
if (store.skip) query.skip = store.skip;
if (store.userParams && Object.keys(store.userParams).length !== 0)
query.params = JSON.stringify(store.userParams);
router.replace({ router.replace({
path: route.path, path: route.path,
query: { query: query,
order: store.order,
limit: store.limit,
skip: store.skip,
params: JSON.stringify(store.userParams),
},
}); });
} }

View File

@ -0,0 +1,261 @@
<script setup>
import { ref } from 'vue';
import { useI18n } from 'vue-i18n';
import FetchData from 'components/FetchData.vue';
import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
const { t } = useI18n();
const props = defineProps({
dataKey: {
type: String,
required: true,
},
});
const workers = ref([]);
const workersCopy = ref([]);
const provinces = ref([]);
const states = ref([]);
const agencies = ref([]);
const warehouses = ref([]);
function setWorkers(data) {
workers.value = data;
workersCopy.value = data;
}
</script>
<template>
<fetch-data url="Provinces" @on-fetch="(data) => (provinces = data)" auto-load />
<fetch-data url="States" @on-fetch="(data) => (states = data)" auto-load />
<fetch-data
url="Workers/activeWithInheritedRole"
:filter="{ where: { role: 'salesPerson' } }"
@on-fetch="setWorkers"
auto-load
/>
<VnFilterPanel :data-key="props.dataKey" :search-button="true">
<template #tags="{ tag }">
<div class="q-gutter-x-xs">
<strong>{{ t(tag.label) }}: </strong>
<span>"{{ tag.value }}"</span>
</div>
</template>
<template #body="{ params }">
<q-list dense>
<q-item>
<q-item-section>
<q-input
v-model="params.clientFk"
label="Customer ID"
lazy-rules
autofocus
/>
</q-item-section>
<q-item-section>
<q-input v-model="params.orderFk" label="Order ID" lazy-rules />
</q-item-section>
</q-item>
<q-item>
<q-item-section>
<q-input
v-model="params.dateFrom"
label="From"
autofocus
readonly
>
<template #append>
<q-icon name="event" class="cursor-pointer">
<q-popup-proxy
cover
transition-show="scale"
transition-hide="scale"
>
<q-date v-model="params.dateFrom">
<div class="row items-center justify-end">
<q-btn
v-close-popup
label="Close"
color="primary"
flat
/>
</div>
</q-date>
</q-popup-proxy>
</q-icon>
</template>
</q-input>
</q-item-section>
<q-item-section>
<q-input v-model="params.dateTo" label="To" autofocus readonly>
<template #append>
<q-icon name="event" class="cursor-pointer">
<q-popup-proxy
cover
transition-show="scale"
transition-hide="scale"
>
<q-date v-model="params.dateTo">
<div class="row items-center justify-end">
<q-btn
v-close-popup
label="Close"
color="primary"
flat
/>
</div>
</q-date>
</q-popup-proxy>
</q-icon>
</template>
</q-input>
</q-item-section>
</q-item>
<q-item>
<q-item-section>
<q-select
v-model="params.salesPersonFk"
:options="workers"
option-value="id"
option-label="name"
emit-value
label="Salesperson"
map-options
use-input
:input-debounce="0"
>
<template #prepend>
<q-avatar color="orange" size="xs">
<q-img
v-if="params.salesPersonFk"
:src="`/api/Images/user/160x160/${params.salesPersonFk}/download?access_token=${token}`"
spinner-color="white"
/>
</q-avatar>
</template>
</q-select>
</q-item-section>
</q-item>
<q-item>
<q-item-section>
<q-select
label="State"
v-model="params.stateFk"
:options="states"
option-value="id"
option-label="name"
emit-value
map-options
/>
</q-item-section>
</q-item>
<q-item>
<q-item-section>
<q-input v-model="params.refFk" label="Invoice Out" lazy-rules />
</q-item-section>
</q-item>
<q-item>
<q-item-section>
<q-checkbox
v-model="params.myTeam"
label="My team"
toggle-indeterminate
/>
</q-item-section>
<q-item-section>
<q-checkbox
v-model="params.problems"
label="Has problems"
toggle-indeterminate
/>
</q-item-section>
</q-item>
<q-item>
<q-item-section>
<q-checkbox
v-model="params.pending"
label="Pending"
toggle-indeterminate
/>
</q-item-section>
<q-item-section>
<q-checkbox
v-model="params.hasRoute"
label="Has route"
toggle-indeterminate
/>
</q-item-section>
</q-item>
<q-item>
<q-item-section>
<q-checkbox
v-model="params.hasInvoice"
label="With invoice"
toggle-indeterminate
/>
</q-item-section>
</q-item>
<q-separator />
<q-expansion-item label="More options" expand-separator>
<q-item>
<q-item-section>
<q-select
label="Province"
v-model="params.provinceFk"
:options="provinces"
option-value="id"
option-label="name"
emit-value
map-options
/>
</q-item-section>
</q-item>
<q-item>
<q-item-section>
<q-select
label="Agency"
v-model="params.agencyModeFk"
:options="agencies"
option-value="id"
option-label="name"
emit-value
map-options
/>
</q-item-section>
</q-item>
<q-item>
<q-item-section>
<q-select
label="Warehouse"
v-model="params.warehouseFk"
:options="warehouses"
option-value="id"
option-label="name"
emit-value
map-options
/>
</q-item-section>
</q-item>
</q-expansion-item>
</q-list>
</template>
</VnFilterPanel>
</template>
<i18n>
{
"en": {
"search": "Contains",
"clientFk": 'Client',
"dateFrom": 'From',
"dateTo": 'To'
},
"es": {
"search": "Contiene",
"clientFk": 'Cliente',
"dateFrom": 'Desde',
"dateTo": 'Hasta'
}
}
</i18n>

View File

@ -10,8 +10,7 @@ import TicketSummaryDialog from './Card/TicketSummaryDialog.vue';
import TeleportSlot from 'components/ui/TeleportSlot.vue'; import TeleportSlot from 'components/ui/TeleportSlot.vue';
import VnSearchbar from 'src/components/ui/VnSearchbar.vue'; import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue'; import TicketFilter from './TicketFilter.vue';
// import FetchData from 'components/FetchData.vue';
const router = useRouter(); const router = useRouter();
const quasar = useQuasar(); const quasar = useQuasar();
@ -76,33 +75,7 @@ function viewSummary(id) {
<VnSearchbar data-key="TicketList" label="Search by ticket id or alias" /> <VnSearchbar data-key="TicketList" label="Search by ticket id or alias" />
</teleport-slot> </teleport-slot>
<teleport-slot to="#rightPanel"> <teleport-slot to="#rightPanel">
<VnFilterPanel data-key="TicketList"> <TicketFilter data-key="TicketList" />
<template #body="{ params }">
<q-list>
<q-item>
<q-item-section>
<q-input
v-model="params.search"
label="Search by id or name"
class="full-width"
lazy-rules
autofocus
/>
</q-item-section>
</q-item>
<q-item>
<q-item-section>
<q-input
v-model="params.clientFk"
label="Customer ID"
lazy-rules
autofocus
/>
</q-item-section>
</q-item>
</q-list>
</template>
</VnFilterPanel>
</teleport-slot> </teleport-slot>
<q-page class="q-pa-md"> <q-page class="q-pa-md">
<paginate <paginate

View File

@ -6,7 +6,7 @@ const state = useState();
</script> </script>
<template> <template>
<q-drawer v-model="state.drawer.value" show-if-above :width="256" :breakpoint="500"> <q-drawer v-model="state.drawer.value" show-if-above :width="256" :breakpoint="800">
<q-scroll-area class="fit text-grey-8"> <q-scroll-area class="fit text-grey-8">
<LeftMenu /> <LeftMenu />
</q-scroll-area> </q-scroll-area>