4802- Added searchbar & filter panel #39

Merged
joan merged 35 commits from 4802-searchbar into dev 2023-03-02 08:53:44 +00:00
20 changed files with 239 additions and 196 deletions
Showing only changes of commit 55a9df0010 - Show all commits

View File

@ -1,5 +1,5 @@
<script setup> <script setup>
import { onMounted, ref, watch } from 'vue'; import { onMounted, onUnmounted, ref, watch } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useArrayData } from 'composables/useArrayData'; import { useArrayData } from 'composables/useArrayData';
@ -61,8 +61,8 @@ const arrayData = useArrayData(props.dataKey, {
}); });
const store = arrayData.store; const store = arrayData.store;
onMounted(async () => { onMounted(() => {
if (props.autoLoad) await fetch(); if (props.autoLoad) fetch();
}); });
watch( watch(
@ -106,8 +106,10 @@ async function paginate() {
} }
async function onLoad(...params) { async function onLoad(...params) {
if (!store.data) return;
const done = params[1]; const done = params[1];
if (!store.data || store.data.length === 0 || !props.url) return done(false); if (store.data.length === 0 || !props.url) return done(false);
pagination.value.page = pagination.value.page + 1; pagination.value.page = pagination.value.page + 1;
@ -119,22 +121,16 @@ async function onLoad(...params) {
</script> </script>
<template> <template>
<q-infinite-scroll @load="onLoad" :offset="offset" class="column items-center"> <div class="column items-center">
<div v-if="store" class="card-list q-gutter-y-md">
<slot name="body" :rows="store.data"></slot>
<div <div
v-if="!store.data.length && !isLoading" v-if="store.data && store.data.length === 0 && !isLoading"
class="info-row q-pa-md text-center" class="info-row q-pa-md text-center"
> >
<h5> <h5>
{{ t('components.smartCard.noData') }} {{ t('components.smartCard.noData') }}
</h5> </h5>
</div> </div>
<div v-if="isLoading" class="info-row q-pa-md text-center"> <div v-if="props.autoLoad && !store.data" class="card-list q-gutter-y-md">
<q-spinner color="orange" size="md" />
</div>
</div>
<div v-if="!store" class="card-list q-gutter-y-md">
<q-card class="card" v-for="$index in $props.limit" :key="$index"> <q-card class="card" v-for="$index in $props.limit" :key="$index">
<q-item v-ripple class="q-pa-none items-start cursor-pointer q-hoverable"> <q-item v-ripple class="q-pa-none items-start cursor-pointer q-hoverable">
<q-item-section class="q-pa-md"> <q-item-section class="q-pa-md">
@ -153,6 +149,19 @@ async function onLoad(...params) {
</q-item> </q-item>
</q-card> </q-card>
</div> </div>
</div>
<q-infinite-scroll
v-if="store.data"
@load="onLoad"
:offset="offset"
class="column items-center"
>
<div v-if="store" class="card-list q-gutter-y-md">
<slot name="body" :rows="store.data"></slot>
<div v-if="isLoading" class="info-row q-pa-md text-center">
<q-spinner color="orange" size="md" />
</div>
</div>
</q-infinite-scroll> </q-infinite-scroll>
</template> </template>

View File

@ -13,6 +13,11 @@ const props = defineProps({
required: false, required: false,
default: 'Search', default: 'Search',
}, },
info: {
type: String,
required: false,
default: '',
},
redirect: { redirect: {
type: Boolean, type: Boolean,
required: false, required: false,
@ -73,12 +78,20 @@ async function search() {
@click="searchText = ''" @click="searchText = ''"
class="cursor-pointer" class="cursor-pointer"
/> />
<q-icon v-if="props.info" name="info" class="cursor-info">
<q-tooltip>{{ props.info }}</q-tooltip>
</q-icon>
</template> </template>
</q-input> </q-input>
</q-form> </q-form>
</template> </template>
<style lang="scss"> <style lang="scss">
.cursor-info {
cursor: help;
}
#searchbar .q-field { #searchbar .q-field {
min-width: 350px; min-width: 350px;
} }

View File

@ -1,4 +1,4 @@
import { onMounted, ref } from 'vue'; import { onMounted, ref, computed } from 'vue';
import { useRouter, useRoute } from 'vue-router'; import { useRouter, useRoute } from 'vue-router';
import axios from 'axios'; import axios from 'axios';
import { useArrayDataStore } from 'stores/useArrayDataStore'; import { useArrayDataStore } from 'stores/useArrayDataStore';
@ -47,9 +47,7 @@ export function useArrayData(key, userOptions) {
}; };
Object.assign(filter, store.userFilter); Object.assign(filter, store.userFilter);
Object.assign(filter, store.filter); Object.assign(store.filter, filter);
store.filter = filter;
const params = { const params = {
filter: JSON.stringify(filter), filter: JSON.stringify(filter),
@ -67,6 +65,7 @@ export function useArrayData(key, userOptions) {
hasMoreData.value = response.data.length === limit; hasMoreData.value = response.data.length === limit;
if (append === true) { if (append === true) {
if (!store.data) store.data = [];
for (const row of response.data) store.data.push(row); for (const row of response.data) store.data.push(row);
} }
@ -79,8 +78,7 @@ export function useArrayData(key, userOptions) {
canceller = null; canceller = null;
} }
function destroy() {
function clear() {
if (arrayDataStore.get(key)) { if (arrayDataStore.get(key)) {
arrayDataStore.clear(key); arrayDataStore.clear(key);
} }
@ -110,7 +108,7 @@ export function useArrayData(key, userOptions) {
async function loadMore() { async function loadMore() {
if (!hasMoreData.value) return; if (!hasMoreData.value) return;
store.skip = store.limit * (page.value - 1); store.skip = store.limit * page.value;
page.value += 1; page.value += 1;
await fetch({ append: true }); await fetch({ append: true });
@ -134,15 +132,18 @@ export function useArrayData(key, userOptions) {
}); });
} }
const totalRows = computed(() => store.data && store.data.length | 0);
return { return {
fetch, fetch,
applyFilter, applyFilter,
addFilter, addFilter,
refresh, refresh,
clear, destroy,
loadMore, loadMore,
store, store,
hasMoreData, hasMoreData,
totalRows,
updateStateParams, updateStateParams,
}; };
} }

View File

@ -3,7 +3,7 @@ import { useI18n } from 'vue-i18n';
export default function (value, options = {}) { export default function (value, options = {}) {
if (!value) return; if (!value) return;
if (!options.dateStyle) { if (!options.dateStyle && !options.timeStyle) {
options.day = '2-digit'; options.day = '2-digit';
options.month = '2-digit'; options.month = '2-digit';
options.year = 'numeric'; options.year = 'numeric';

View File

@ -16,7 +16,6 @@ const stateStore = useStateStore();
v-model="stateStore.rightDrawer" v-model="stateStore.rightDrawer"
side="right" side="right"
:width="256" :width="256"
:breakpoint="1000"
:persistent="false" :persistent="false"
> >
<q-scroll-area class="fit text-grey-8"> <q-scroll-area class="fit text-grey-8">

View File

@ -1,19 +1,23 @@
<script setup> <script setup>
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useState } from 'composables/useState'; import { useStateStore } from 'stores/useStateStore';
import ClaimDescriptor from './ClaimDescriptor.vue'; import ClaimDescriptor from './ClaimDescriptor.vue';
import LeftMenu from 'components/LeftMenu.vue'; import LeftMenu from 'components/LeftMenu.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';
const state = useState(); const stateStore = useStateStore();
const { t } = useI18n(); const { t } = useI18n();
</script> </script>
<template> <template>
<teleport-slot to="#searchbar"> <teleport-slot to="#searchbar">
<VnSearchbar data-key="ClaimList" :label="t('Search by claim id or name')" /> <VnSearchbar
data-key="ClaimList"
:label="t('Search claim')"
:info="t('You can search by claim id or customer name')"
/>
</teleport-slot> </teleport-slot>
<q-drawer v-model="state.drawer.value" show-if-above :width="256" :breakpoint="500"> <q-drawer v-model="stateStore.leftDrawer" show-if-above :width="256">
<q-scroll-area class="fit"> <q-scroll-area class="fit">
<claim-descriptor /> <claim-descriptor />
<q-separator /> <q-separator />
@ -29,5 +33,6 @@ const { t } = useI18n();
<i18n> <i18n>
es: es:
Search by claim id or name: Buscar por id o nombre de la reclamación Search claim: Buscar reclamación
You can search by claim id or customer name: Puedes buscar por id de la reclamación o nombre del cliente
</i18n> </i18n>

View File

@ -1,25 +1,33 @@
<script setup> <script setup>
import axios from 'axios';
import { ref } from 'vue'; import { ref } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useQuasar } from 'quasar'; import { useQuasar } from 'quasar';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import axios from 'axios'; import { useArrayData } from 'src/composables/useArrayData';
import Paginate from 'src/components/PaginateData.vue'; import Paginate from 'src/components/PaginateData.vue';
import FetchData from 'components/FetchData.vue'; import FetchData from 'components/FetchData.vue';
import TeleportSlot from 'components/ui/TeleportSlot.vue'; import TeleportSlot from 'components/ui/TeleportSlot.vue';
import VnConfirm from 'src/components/ui/VnConfirm.vue';
import { toDate } from 'src/filters'; import { toDate } from 'src/filters';
const quasar = useQuasar(); const quasar = useQuasar();
const route = useRoute(); const route = useRoute();
const { t } = useI18n(); const { t } = useI18n();
const arrayData = useArrayData('ClaimRma');
const claim = ref([]); const claim = ref();
const fetcher = ref(); const fetcher = ref();
const claimFilter = {
fields: ['rma'],
};
async function onFetch(data) {
claim.value = data;
const filter = { const filter = {
include: {
relation: 'rmas',
scope: {
include: { include: {
relation: 'worker', relation: 'worker',
scope: { scope: {
@ -29,17 +37,21 @@ const filter = {
}, },
}, },
order: 'created DESC', order: 'created DESC',
}, where: {
code: claim.value.rma,
}, },
}; };
arrayData.applyFilter({ filter });
}
async function addRow() { async function addRow() {
const formData = { const formData = {
code: claim.value.rma, code: claim.value.rma,
}; };
await axios.post(`ClaimRmas`, formData); await axios.post(`ClaimRmas`, formData);
await fetcher.value.fetch(); await arrayData.refresh();
quasar.notify({ quasar.notify({
type: 'positive', type: 'positive',
@ -48,19 +60,17 @@ async function addRow() {
}); });
} }
const confirmShown = ref(false);
const rmaId = ref(null);
function confirmRemove(id) { function confirmRemove(id) {
confirmShown.value = true; quasar
rmaId.value = id; .dialog({
component: VnConfirm,
})
.onOk(() => remove(id));
} }
async function remove() { async function remove(id) {
const id = rmaId.value;
await axios.delete(`ClaimRmas/${id}`); await axios.delete(`ClaimRmas/${id}`);
await fetcher.value.fetch(); await arrayData.refresh();
confirmShown.value = false;
quasar.notify({ quasar.notify({
type: 'positive', type: 'positive',
@ -68,41 +78,36 @@ async function remove() {
icon: 'check', icon: 'check',
}); });
} }
function hide() {
rmaId.value = null;
}
</script> </script>
<template> <template>
<fetch-data <fetch-data
ref="fetcher"
:url="`Claims/${route.params.id}`" :url="`Claims/${route.params.id}`"
:filter="filter" :filter="claimFilter"
@on-fetch="(data) => (claim = data)" @on-fetch="onFetch"
auto-load auto-load
/> />
<paginate :data="claim.rmas"> <paginate data-key="ClaimRma" url="ClaimRmas">
<template #body="{ rows }"> <template #body="{ rows }">
<q-card class="card"> <q-card class="card">
<template v-for="row of rows" :key="row.id"> <template v-for="(row, index) of rows" :key="row.id">
<q-item class="q-pa-none items-start"> <q-item class="q-pa-none items-start">
<q-item-section class="q-pa-md"> <q-item-section class="q-pa-md">
<q-list> <q-list>
<q-item class="q-pa-none"> <q-item class="q-pa-none">
<q-item-section> <q-item-section>
<q-item-label caption>{{ <q-item-label caption>
t('claim.rma.user') {{ t('claim.rma.user') }}
}}</q-item-label> </q-item-label>
<q-item-label>{{ <q-item-label>
row.worker.user.name {{ row.worker.user.name }}
}}</q-item-label> </q-item-label>
</q-item-section> </q-item-section>
</q-item> </q-item>
<q-item class="q-pa-none"> <q-item class="q-pa-none">
<q-item-section> <q-item-section>
<q-item-label caption>{{ <q-item-label caption>
t('claim.rma.created') {{ t('claim.rma.created') }}
}}</q-item-label> </q-item-label>
<q-item-label> <q-item-label>
{{ {{
toDate(row.created, { toDate(row.created, {
@ -126,31 +131,12 @@ function hide() {
</q-btn> </q-btn>
</q-card-actions> </q-card-actions>
</q-item> </q-item>
<q-separator /> <q-separator v-if="index !== rows.length - 1" />
</template> </template>
</q-card> </q-card>
</template> </template>
</paginate> </paginate>
<q-dialog v-model="confirmShown" persistent @hide="hide">
<q-card>
<q-card-section class="row items-center">
<q-avatar icon="warning" color="primary" text-color="white" />
<span class="q-ml-sm">{{ t('globals.confirmRemove') }}</span>
</q-card-section>
<q-card-actions align="right">
<q-btn
flat
:label="t('globals.no')"
color="primary"
v-close-popup
autofocus
/>
<q-btn flat :label="t('globals.yes')" color="primary" @click="remove()" />
</q-card-actions>
</q-card>
</q-dialog>
<teleport-slot v-if="!quasar.platform.is.mobile" to="#header-actions"> <teleport-slot v-if="!quasar.platform.is.mobile" to="#header-actions">
<div class="row q-gutter-x-sm"> <div class="row q-gutter-x-sm">
<q-btn @click="addRow()" icon="add" color="primary" dense rounded> <q-btn @click="addRow()" icon="add" color="primary" dense rounded>

View File

@ -17,8 +17,17 @@ const router = useRouter();
const quasar = useQuasar(); const quasar = useQuasar();
const { t } = useI18n(); const { t } = useI18n();
onMounted(() => stateStore.toggleRightDrawer()); onMounted(() => {
onUnmounted(() => stateStore.toggleRightDrawer()); if (!stateStore.rightDrawer) {
stateStore.toggleRightDrawer();
}
});
onUnmounted(() => {
if (stateStore.rightDrawer) {
stateStore.toggleRightDrawer();
}
});
function stateColor(code) { function stateColor(code) {
if (code === 'pending') return 'green'; if (code === 'pending') return 'green';
@ -42,13 +51,17 @@ function viewSummary(id) {
<template> <template>
<teleport-slot to="#searchbar"> <teleport-slot to="#searchbar">
<VnSearchbar data-key="ClaimList" :label="t('Search by claim id or name')" /> <VnSearchbar
data-key="ClaimList"
:label="t('Search claim')"
:info="t('You can search by claim id or customer name')"
/>
</teleport-slot> </teleport-slot>
<teleport-slot to="#rightPanel"> <teleport-slot to="#rightPanel">
<ClaimFilter data-key="ClaimList" /> <ClaimFilter data-key="ClaimList" />
</teleport-slot> </teleport-slot>
<q-page class="q-pa-md"> <q-page class="q-pa-md">
<paginate data-key="ClaimList" url="Claims/filter" sort-by="id DESC" auto-load> <paginate data-key="ClaimList" url="Claims/filter" order="id DESC" auto-load>
<template #body="{ rows }"> <template #body="{ rows }">
<q-card class="card" v-for="row of rows" :key="row.id"> <q-card class="card" v-for="row of rows" :key="row.id">
<q-item <q-item
@ -164,5 +177,6 @@ function viewSummary(id) {
<i18n> <i18n>
es: es:
Search by claim id or name: Buscar por id o nombre de la reclamación Search claim: Buscar reclamación
You can search by claim id or customer name: Puedes buscar por id de la reclamación o nombre del cliente
</i18n> </i18n>

View File

@ -1,12 +1,12 @@
<script setup> <script setup>
import { useState } from 'src/composables/useState'; import { useStateStore } from 'stores/useStateStore';
import LeftMenu from 'components/LeftMenu.vue'; import LeftMenu from 'components/LeftMenu.vue';
const state = useState(); const stateStore = useStateStore();
</script> </script>
<template> <template>
<q-drawer v-model="state.drawer.value" show-if-above :width="256" :breakpoint="800"> <q-drawer v-model="stateStore.leftDrawer" show-if-above :width="256">
<q-scroll-area class="fit text-grey-8"> <q-scroll-area class="fit text-grey-8">
<LeftMenu /> <LeftMenu />
</q-scroll-area> </q-scroll-area>

View File

@ -4,16 +4,15 @@ import { useI18n } from 'vue-i18n';
import { useQuasar } from 'quasar'; import { useQuasar } from 'quasar';
import axios from 'axios'; import axios from 'axios';
import Paginate from 'src/components/PaginateData.vue'; import Paginate from 'src/components/PaginateData.vue';
import { useArrayData } from 'src/composables/useArrayData';
import VnConfirm from 'src/components/ui/VnConfirm.vue';
const quasar = useQuasar(); const quasar = useQuasar();
const { t } = useI18n(); const { t } = useI18n();
const rmas = ref([]); const arrayData = useArrayData('ClaimRmaList');
const card = ref(null); const isLoading = ref(false);
const input = ref();
function onFetch(data) {
rmas.value = data.value;
}
const newRma = ref({ const newRma = ref({
code: '', code: '',
@ -24,46 +23,38 @@ function onInputUpdate(value) {
newRma.value.code = value.toUpperCase(); newRma.value.code = value.toUpperCase();
} }
function submit() { async function submit() {
const formData = newRma.value; const formData = newRma.value;
if (formData.code === '') return; if (formData.code === '') return;
axios isLoading.value = true;
.post('ClaimRmas', formData) await axios.post('ClaimRmas', formData);
.then(() => { await arrayData.refresh();
isLoading.value = false;
input.value.$el.focus();
newRma.value = { newRma.value = {
code: '', code: '',
crated: new Date(), created: new Date(),
}; };
})
.then(() => card.value.refresh());
} }
const confirmShown = ref(false);
const rmaId = ref(null);
function confirm(id) { function confirm(id) {
confirmShown.value = true; quasar
rmaId.value = id; .dialog({
component: VnConfirm,
})
.onOk(() => remove(id));
} }
function remove() { async function remove(id) {
const id = rmaId.value; await axios.delete(`ClaimRmas/${id}`);
axios await arrayData.refresh();
.delete(`ClaimRmas/${id}`)
.then(() => {
confirmShown.value = false;
quasar.notify({ quasar.notify({
type: 'positive', type: 'positive',
message: 'Entry deleted', message: t('globals.rowRemoved'),
icon: 'check', icon: 'check',
}); });
})
.then(() => card.value.refresh());
}
function hide() {
rmaId.value = null;
} }
</script> </script>
@ -73,34 +64,74 @@ function hide() {
<q-card class="card q-pa-md"> <q-card class="card q-pa-md">
<q-form @submit="submit"> <q-form @submit="submit">
<q-input <q-input
ref="input"
v-model="newRma.code" v-model="newRma.code"
:label="t('claim.rmaList.code')" :label="t('claim.rmaList.code')"
@update:model-value="onInputUpdate" @update:model-value="onInputUpdate"
class="q-mb-md" class="q-mb-md"
:readonly="isLoading"
:loading="isLoading"
autofocus autofocus
/> />
<div class="text-caption">{{ rmas.length }} {{ t('claim.rmaList.records') }}</div> <div class="text-caption">
{{ arrayData.totalRows }} {{ t('claim.rmaList.records') }}
</div>
</q-form> </q-form>
</q-card> </q-card>
</q-page-sticky> </q-page-sticky>
<paginate
<paginate ref="card" url="/ClaimRmas" @on-fetch="onFetch" sort-by="id DESC" auto-load> data-key="ClaimRmaList"
url="ClaimRmas"
order="id DESC"
:offset="50"
auto-load
>
<template #body="{ rows }"> <template #body="{ rows }">
<q-card class="card"> <q-card class="card">
<template v-for="row of rows" :key="row.code"> <template v-if="isLoading">
<q-item class="q-pa-none items-start"> <q-item class="q-pa-none items-start">
<q-item-section class="q-pa-md"> <q-item-section class="q-pa-md">
<q-list> <q-list>
<q-item class="q-pa-none"> <q-item class="q-pa-none">
<q-item-section> <q-item-section>
<q-item-label caption>{{ t('claim.rmaList.code') }}</q-item-label> <q-item-label caption>
<q-skeleton />
</q-item-label>
<q-item-label
><q-skeleton type="text"
/></q-item-label>
</q-item-section>
</q-item>
</q-list>
</q-item-section>
<q-card-actions vertical class="justify-between">
<q-skeleton type="circle" class="q-mb-md" size="40px" />
</q-card-actions>
</q-item>
<q-separator />
</template>
<template v-for="row of rows" :key="row.id">
<q-item class="q-pa-none items-start">
<q-item-section class="q-pa-md">
<q-list>
<q-item class="q-pa-none">
<q-item-section>
<q-item-label caption>{{
t('claim.rmaList.code')
}}</q-item-label>
<q-item-label>{{ row.code }}</q-item-label> <q-item-label>{{ row.code }}</q-item-label>
</q-item-section> </q-item-section>
</q-item> </q-item>
</q-list> </q-list>
</q-item-section> </q-item-section>
<q-card-actions vertical class="justify-between"> <q-card-actions vertical class="justify-between">
<q-btn flat round color="primary" icon="vn:bin" @click="confirm(row.id)"> <q-btn
flat
round
color="primary"
icon="vn:bin"
@click="confirm(row.id)"
>
<q-tooltip>{{ t('globals.remove') }}</q-tooltip> <q-tooltip>{{ t('globals.remove') }}</q-tooltip>
</q-btn> </q-btn>
</q-card-actions> </q-card-actions>
@ -111,20 +142,6 @@ function hide() {
</template> </template>
</paginate> </paginate>
</q-page> </q-page>
<q-dialog v-model="confirmShown" persistent @hide="hide">
<q-card>
<q-card-section class="row items-center">
<q-avatar icon="warning" color="primary" text-color="white" />
<span class="q-ml-sm">{{ t('globals.confirmRemove') }}</span>
</q-card-section>
<q-card-actions align="right">
<q-btn flat :label="t('globals.no')" color="primary" v-close-popup autofocus />
<q-btn flat :label="t('globals.yes')" color="primary" @click="remove()" />
</q-card-actions>
</q-card>
</q-dialog>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -1,12 +1,12 @@
<script setup> <script setup>
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useState } from 'src/composables/useState'; import { useStateStore } from 'stores/useStateStore';
import CustomerDescriptor from './CustomerDescriptor.vue'; import CustomerDescriptor from './CustomerDescriptor.vue';
import LeftMenu from 'components/LeftMenu.vue'; import LeftMenu from 'components/LeftMenu.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';
const state = useState(); const stateStore = useStateStore();
const { t } = useI18n(); const { t } = useI18n();
</script> </script>
<template> <template>
@ -16,7 +16,11 @@ const { t } = useI18n();
:label="t('Search by customer id or name')" :label="t('Search by customer id or name')"
/> />
</teleport-slot> </teleport-slot>
<q-drawer v-model="state.drawer.value" show-if-above :width="256" :breakpoint="500"> <q-drawer
v-model="stateStore.leftDrawer"
show-if-above
:width="256"
>
<q-scroll-area class="fit"> <q-scroll-area class="fit">
<CustomerDescriptor /> <CustomerDescriptor />
<q-separator /> <q-separator />

View File

@ -10,13 +10,13 @@ import TeleportSlot from 'components/ui/TeleportSlot.vue';
import VnSearchbar from 'src/components/ui/VnSearchbar.vue'; import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
import CustomerFilter from './CustomerFilter.vue'; import CustomerFilter from './CustomerFilter.vue';
const state = useStateStore(); const stateStore = useStateStore();
const router = useRouter(); const router = useRouter();
const quasar = useQuasar(); const quasar = useQuasar();
const { t } = useI18n(); const { t } = useI18n();
onMounted(() => state.toggleRightDrawer()); onMounted(() => (stateStore.rightDrawer = true));
onUnmounted(() => state.toggleRightDrawer()); onUnmounted(() => (stateStore.rightDrawer = false));
function navigate(id) { function navigate(id) {
router.push({ path: `/customer/${id}` }); router.push({ path: `/customer/${id}` });

View File

@ -6,12 +6,7 @@ const stateStore = useStateStore();
</script> </script>
<template> <template>
<q-drawer <q-drawer v-model="stateStore.leftDrawer" show-if-above :width="256">
v-model="stateStore.leftDrawer"
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>

View File

@ -1,12 +1,12 @@
<script setup> <script setup>
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useState } from 'composables/useState'; import { useStateStore } from 'stores/useStateStore';
import InvoiceOutDescriptor from './InvoiceOutDescriptor.vue'; import InvoiceOutDescriptor from './InvoiceOutDescriptor.vue';
import LeftMenu from 'components/LeftMenu.vue'; import LeftMenu from 'components/LeftMenu.vue';
import TeleportSlot from 'components/ui/TeleportSlot.vue'; import TeleportSlot from 'components/ui/TeleportSlot.vue';
import VnSearchbar from 'components/ui/VnSearchbar.vue'; import VnSearchbar from 'components/ui/VnSearchbar.vue';
const state = useState(); const stateStore = useStateStore();
const { t } = useI18n(); const { t } = useI18n();
</script> </script>
<template> <template>
@ -16,7 +16,7 @@ const { t } = useI18n();
:label="t('Search by invoice reference')" :label="t('Search by invoice reference')"
/> />
</teleport-slot> </teleport-slot>
<q-drawer v-model="state.drawer.value" show-if-above :width="256" :breakpoint="500"> <q-drawer v-model="stateStore.leftDrawer" show-if-above :width="256">
<q-scroll-area class="fit"> <q-scroll-area class="fit">
<InvoiceOutDescriptor /> <InvoiceOutDescriptor />
<q-separator /> <q-separator />

View File

@ -11,13 +11,13 @@ import TeleportSlot from 'components/ui/TeleportSlot.vue';
import VnSearchbar from 'src/components/ui/VnSearchbar.vue'; import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
import InvoiceOutFilter from './InvoiceOutFilter.vue'; import InvoiceOutFilter from './InvoiceOutFilter.vue';
const state = useStateStore(); const stateStore = useStateStore();
const router = useRouter(); const router = useRouter();
const quasar = useQuasar(); const quasar = useQuasar();
const { t } = useI18n(); const { t } = useI18n();
onMounted(() => state.toggleRightDrawer()); onMounted(() => (stateStore.rightDrawer = true));
onUnmounted(() => state.toggleRightDrawer()); onUnmounted(() => (stateStore.rightDrawer = false));
function navigate(id) { function navigate(id) {
router.push({ path: `/invoiceOut/${id}` }); router.push({ path: `/invoiceOut/${id}` });
@ -47,7 +47,7 @@ function viewSummary(id) {
<paginate <paginate
data-key="InvoiceOutList" data-key="InvoiceOutList"
url="InvoiceOuts/filter" url="InvoiceOuts/filter"
sort-by="issued DESC, id DESC" order="issued DESC, id DESC"
auto-load auto-load
> >
<template #body="{ rows }"> <template #body="{ rows }">

View File

@ -1,12 +1,12 @@
<script setup> <script setup>
import { useState } from 'src/composables/useState'; import { useStateStore } from 'stores/useStateStore';
import LeftMenu from 'src/components/LeftMenu.vue'; import LeftMenu from 'src/components/LeftMenu.vue';
const state = useState(); const stateStore = useStateStore();
</script> </script>
<template> <template>
<q-drawer v-model="state.drawer.value" show-if-above :width="256" :breakpoint="800"> <q-drawer v-model="stateStore.leftDrawer" show-if-above :width="256">
<q-scroll-area class="fit text-grey-8"> <q-scroll-area class="fit text-grey-8">
<LeftMenu /> <LeftMenu />
</q-scroll-area> </q-scroll-area>

View File

@ -1,19 +1,19 @@
<script setup> <script setup>
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useState } from 'src/composables/useState'; import { useStateStore } from 'stores/useStateStore';
import TicketDescriptor from './TicketDescriptor.vue'; import TicketDescriptor from './TicketDescriptor.vue';
import LeftMenu from 'components/LeftMenu.vue'; import LeftMenu from 'components/LeftMenu.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';
const state = useState(); const stateStore = useStateStore();
const { t } = useI18n(); const { t } = useI18n();
</script> </script>
<template> <template>
<teleport-slot to="#searchbar"> <teleport-slot to="#searchbar">
<VnSearchbar data-key="TicketList" :label="t('Search by ticket id or alias')" /> <VnSearchbar data-key="TicketList" :label="t('Search by ticket id or alias')" />
</teleport-slot> </teleport-slot>
<q-drawer v-model="state.drawer.value" show-if-above :width="256" :breakpoint="500"> <q-drawer v-model="stateStore.leftDrawer" show-if-above :width="256">
<q-scroll-area class="fit"> <q-scroll-area class="fit">
<TicketDescriptor /> <TicketDescriptor />
<q-separator /> <q-separator />

View File

@ -17,8 +17,8 @@ const quasar = useQuasar();
const { t } = useI18n(); const { t } = useI18n();
const stateStore = useStateStore(); const stateStore = useStateStore();
onMounted(() => stateStore.toggleRightDrawer()); onMounted(() => (stateStore.rightDrawer = true));
onUnmounted(() => stateStore.toggleRightDrawer()); onUnmounted(() => (stateStore.rightDrawer = false));
const filter = { const filter = {
include: [ include: [
@ -82,7 +82,7 @@ function viewSummary(id) {
data-key="TicketList" data-key="TicketList"
url="Tickets/filter" url="Tickets/filter"
:filter="filter" :filter="filter"
sort-by="id DESC" order="id DESC"
auto-load auto-load
> >
<template #body="{ rows }"> <template #body="{ rows }">

View File

@ -1,12 +1,12 @@
<script setup> <script setup>
import { useState } from 'src/composables/useState'; import { useStateStore } from 'stores/useStateStore';
import LeftMenu from 'components/LeftMenu.vue'; import LeftMenu from 'components/LeftMenu.vue';
const state = useState(); const stateStore = useStateStore();
</script> </script>
<template> <template>
<q-drawer v-model="state.drawer.value" show-if-above :width="256" :breakpoint="800"> <q-drawer v-model="stateStore.leftDrawer" show-if-above :width="256">
<q-scroll-area class="fit text-grey-8"> <q-scroll-area class="fit text-grey-8">
<LeftMenu /> <LeftMenu />
</q-scroll-area> </q-scroll-area>

View File

@ -17,7 +17,7 @@ export const useArrayDataStore = defineStore('arrayDataStore', () => {
limit: 10, limit: 10,
skip: 0, skip: 0,
order: '', order: '',
data: ref([]) data: ref(),
}; };
} }
@ -28,6 +28,6 @@ export const useArrayDataStore = defineStore('arrayDataStore', () => {
return { return {
get, get,
set, set,
clear clear,
}; };
}); });