closes #4834 create-worker-module #28
|
@ -9,7 +9,7 @@
|
||||||
// https://v2.quasar.dev/quasar-cli-vite/quasar-config-js
|
// https://v2.quasar.dev/quasar-cli-vite/quasar-config-js
|
||||||
|
|
||||||
const { configure } = require('quasar/wrappers');
|
const { configure } = require('quasar/wrappers');
|
||||||
const VueI18nPlugin = require('@intlify/unplugin-vue-i18n/vite')
|
const VueI18nPlugin = require('@intlify/unplugin-vue-i18n/vite');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
module.exports = configure(function (/* ctx */) {
|
module.exports = configure(function (/* ctx */) {
|
||||||
|
@ -140,6 +140,8 @@ module.exports = configure(function (/* ctx */) {
|
||||||
|
|
||||||
// Quasar plugins
|
// Quasar plugins
|
||||||
plugins: ['Notify', 'Dialog'],
|
plugins: ['Notify', 'Dialog'],
|
||||||
|
//all: 'auto',
|
||||||
|
//autoImportComponentCase: 'pascal',
|
||||||
},
|
},
|
||||||
|
|
||||||
// animations: 'all', // --- includes all animations
|
// animations: 'all', // --- includes all animations
|
||||||
|
|
|
@ -21,7 +21,14 @@ onMounted(() => stateStore.setMounted());
|
||||||
<template>
|
<template>
|
||||||
<q-header class="bg-dark" color="white" elevated>
|
<q-header class="bg-dark" color="white" elevated>
|
||||||
<q-toolbar class="q-py-sm q-px-md">
|
<q-toolbar class="q-py-sm q-px-md">
|
||||||
<q-btn flat @click="stateStore.toggleLeftDrawer()" round dense icon="menu">
|
<q-btn
|
||||||
|
@click="stateStore.toggleLeftDrawer()"
|
||||||
|
icon="menu"
|
||||||
|
class="q-mr-sm"
|
||||||
|
round
|
||||||
|
dense
|
||||||
|
flat
|
||||||
|
>
|
||||||
<q-tooltip bottom anchor="bottom right">
|
<q-tooltip bottom anchor="bottom right">
|
||||||
{{ t('globals.collapseMenu') }}
|
{{ t('globals.collapseMenu') }}
|
||||||
</q-tooltip>
|
</q-tooltip>
|
||||||
|
|
|
@ -16,7 +16,7 @@ const props = defineProps({
|
||||||
module: {
|
module: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: true,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const slots = useSlots();
|
const slots = useSlots();
|
||||||
|
@ -24,14 +24,18 @@ const { t } = useI18n();
|
||||||
|
|
||||||
onMounted(() => fetch());
|
onMounted(() => fetch());
|
||||||
|
|
||||||
|
const emit = defineEmits(['onFetch']);
|
||||||
|
|
||||||
const entity = ref();
|
const entity = ref();
|
||||||
async function fetch() {
|
async function fetch() {
|
||||||
const params = {};
|
const params = {};
|
||||||
|
|
||||||
if (props.filter) params.filter = props.filter;
|
if (props.filter) params.filter = JSON.stringify(props.filter);
|
||||||
|
|
||||||
const { data } = await axios.get(props.url, { params });
|
const { data } = await axios.get(props.url, { params });
|
||||||
entity.value = data;
|
entity.value = data;
|
||||||
|
|
||||||
|
emit('onFetch', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(props, async () => {
|
watch(props, async () => {
|
||||||
|
@ -46,9 +50,9 @@ watch(props, async () => {
|
||||||
<div class="header bg-primary q-pa-sm">
|
<div class="header bg-primary q-pa-sm">
|
||||||
<router-link :to="{ name: `${module}List` }">
|
<router-link :to="{ name: `${module}List` }">
|
||||||
<q-btn round flat dense size="md" icon="view_list" color="white">
|
<q-btn round flat dense size="md" icon="view_list" color="white">
|
||||||
<q-tooltip>{{
|
<q-tooltip>
|
||||||
t('components.cardDescriptor.mainList')
|
{{ t('components.cardDescriptor.mainList') }}
|
||||||
}}</q-tooltip>
|
</q-tooltip>
|
||||||
</q-btn>
|
</q-btn>
|
||||||
</router-link>
|
</router-link>
|
||||||
<router-link
|
<router-link
|
||||||
|
@ -80,8 +84,9 @@ watch(props, async () => {
|
||||||
</q-menu>
|
</q-menu>
|
||||||
</q-btn>
|
</q-btn>
|
||||||
</div>
|
</div>
|
||||||
|
<slot name="before" />
|
||||||
<div class="body q-py-sm">
|
<div class="body q-py-sm">
|
||||||
<q-list>
|
<q-list dense>
|
||||||
<q-item-label header class="ellipsis text-h5" :lines="1">
|
<q-item-label header class="ellipsis text-h5" :lines="1">
|
||||||
<slot name="description" :entity="entity">
|
<slot name="description" :entity="entity">
|
||||||
<span>
|
<span>
|
||||||
|
@ -98,6 +103,7 @@ watch(props, async () => {
|
||||||
</q-list>
|
</q-list>
|
||||||
<slot name="body" :entity="entity" />
|
<slot name="body" :entity="entity" />
|
||||||
</div>
|
</div>
|
||||||
|
<slot name="after" />
|
||||||
</template>
|
</template>
|
||||||
<!-- Skeleton -->
|
<!-- Skeleton -->
|
||||||
<skeleton-descriptor v-if="!entity" />
|
<skeleton-descriptor v-if="!entity" />
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
<script setup>
|
|
||||||
import { nextTick, ref } from 'vue';
|
|
||||||
|
|
||||||
const $props = defineProps({
|
|
||||||
to: {
|
|
||||||
type: String,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const isHeaderMounted = ref(false);
|
|
||||||
nextTick(() => {
|
|
||||||
isHeaderMounted.value = document.querySelector($props.to) !== null;
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<teleport v-if="isHeaderMounted" :to="$props.to">
|
|
||||||
<slot />
|
|
||||||
</teleport>
|
|
||||||
</template>
|
|
|
@ -87,15 +87,29 @@ async function search() {
|
||||||
</q-form>
|
</q-form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@media screen and (max-width: $breakpoint-xs-max) {
|
||||||
|
.q-field {
|
||||||
|
width: 250px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: $breakpoint-xs-max) {
|
||||||
|
.q-field {
|
||||||
|
width: 400px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.q-field {
|
||||||
|
transition: width 0.36s;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.cursor-info {
|
.cursor-info {
|
||||||
cursor: help;
|
cursor: help;
|
||||||
}
|
}
|
||||||
|
|
||||||
#searchbar .q-field {
|
|
||||||
min-width: 350px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.body--light #searchbar {
|
.body--light #searchbar {
|
||||||
.q-field--standout.q-field--highlighted .q-field__control {
|
.q-field--standout.q-field--highlighted .q-field__control {
|
||||||
background-color: $grey-7;
|
background-color: $grey-7;
|
||||||
|
|
|
@ -345,6 +345,47 @@ export default {
|
||||||
totalWithVat: 'Amount',
|
totalWithVat: 'Amount',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
worker: {
|
||||||
|
pageTitles: {
|
||||||
|
workers: 'Workers',
|
||||||
|
list: 'List',
|
||||||
|
basicData: 'Basic data',
|
||||||
|
summary: 'Summary',
|
||||||
|
},
|
||||||
|
list: {
|
||||||
|
name: 'Name',
|
||||||
|
email: 'Email',
|
||||||
|
phone: 'Phone',
|
||||||
|
mobile: 'Mobile',
|
||||||
|
active: 'Active',
|
||||||
|
department: 'Department',
|
||||||
|
schedule: 'Schedule',
|
||||||
|
},
|
||||||
|
card: {
|
||||||
|
workerId: 'Worker ID',
|
||||||
|
name: 'Name',
|
||||||
|
email: 'Email',
|
||||||
|
phone: 'Phone',
|
||||||
|
mobile: 'Mobile',
|
||||||
|
active: 'Active',
|
||||||
|
warehouse: 'Warehouse',
|
||||||
|
agency: 'Agency',
|
||||||
|
salesPerson: 'Sales person',
|
||||||
|
},
|
||||||
|
summary: {
|
||||||
|
basicData: 'Basic data',
|
||||||
|
boss: 'Boss',
|
||||||
|
phoneExtension: 'Phone extension',
|
||||||
|
entPhone: 'Enterprise phone',
|
||||||
|
personalPhone: 'Personal phone',
|
||||||
|
noBoss: 'No boss',
|
||||||
|
userData: 'User data',
|
||||||
|
userId: 'User ID',
|
||||||
|
role: 'Role',
|
||||||
|
sipExtension: 'Extension',
|
||||||
|
},
|
||||||
|
imageNotFound: 'Image not found',
|
||||||
|
},
|
||||||
components: {
|
components: {
|
||||||
topbar: {},
|
topbar: {},
|
||||||
userPanel: {
|
userPanel: {
|
||||||
|
|
|
@ -345,6 +345,47 @@ export default {
|
||||||
totalWithVat: 'Importe',
|
totalWithVat: 'Importe',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
worker: {
|
||||||
|
pageTitles: {
|
||||||
|
workers: 'Trabajadores',
|
||||||
|
list: 'Listado',
|
||||||
|
basicData: 'Datos básicos',
|
||||||
|
summary: 'Resumen',
|
||||||
|
},
|
||||||
|
list: {
|
||||||
|
name: 'Nombre',
|
||||||
|
email: 'Email',
|
||||||
|
phone: 'Teléfono',
|
||||||
|
mobile: 'Móvil',
|
||||||
|
active: 'Activo',
|
||||||
|
department: 'Departamento',
|
||||||
|
schedule: 'Horario',
|
||||||
|
},
|
||||||
|
card: {
|
||||||
|
workerId: 'ID Trabajador',
|
||||||
|
name: 'Nombre',
|
||||||
|
email: 'Email',
|
||||||
|
phone: 'Teléfono',
|
||||||
|
mobile: 'Móvil',
|
||||||
|
active: 'Activo',
|
||||||
|
warehouse: 'Almacén',
|
||||||
|
agency: 'Empresa',
|
||||||
|
salesPerson: 'Comercial',
|
||||||
|
},
|
||||||
|
summary: {
|
||||||
|
basicData: 'Datos básicos',
|
||||||
|
boss: 'Jefe',
|
||||||
|
phoneExtension: 'Extensión de teléfono',
|
||||||
|
entPhone: 'Teléfono de empresa',
|
||||||
|
personalPhone: 'Teléfono personal',
|
||||||
|
noBoss: 'Sin jefe',
|
||||||
|
userData: 'Datos de usuario',
|
||||||
|
userId: 'ID del usuario',
|
||||||
|
role: 'Rol',
|
||||||
|
sipExtension: 'Extensión',
|
||||||
|
},
|
||||||
|
imageNotFound: 'No se ha encontrado la imagen',
|
||||||
|
},
|
||||||
components: {
|
components: {
|
||||||
topbar: {},
|
topbar: {},
|
||||||
userPanel: {
|
userPanel: {
|
||||||
|
|
|
@ -3,20 +3,19 @@ import { useI18n } from 'vue-i18n';
|
||||||
import { useStateStore } from 'stores/useStateStore';
|
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 VnSearchbar from 'src/components/ui/VnSearchbar.vue';
|
import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
|
||||||
|
|
||||||
const stateStore = useStateStore();
|
const stateStore = useStateStore();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<teleport-slot to="#searchbar">
|
<Teleport to="#searchbar" v-if="stateStore.isHeaderMounted()">
|
||||||
<VnSearchbar
|
<VnSearchbar
|
||||||
data-key="ClaimList"
|
data-key="ClaimList"
|
||||||
:label="t('Search claim')"
|
:label="t('Search claim')"
|
||||||
:info="t('You can search by claim id or customer name')"
|
:info="t('You can search by claim id or customer name')"
|
||||||
/>
|
/>
|
||||||
</teleport-slot>
|
</Teleport>
|
||||||
<q-drawer v-model="stateStore.leftDrawer" show-if-above :width="256">
|
<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 />
|
||||||
|
|
|
@ -3,7 +3,6 @@ import { useI18n } from 'vue-i18n';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { useSession } from 'src/composables/useSession';
|
import { useSession } from 'src/composables/useSession';
|
||||||
import { useStateStore } from 'stores/useStateStore';
|
import { useStateStore } from 'stores/useStateStore';
|
||||||
import TeleportSlot from 'components/ui/TeleportSlot.vue';
|
|
||||||
import Paginate from 'src/components/PaginateData.vue';
|
import Paginate from 'src/components/PaginateData.vue';
|
||||||
import ClaimLogFilter from './ClaimLogFilter.vue';
|
import ClaimLogFilter from './ClaimLogFilter.vue';
|
||||||
|
|
||||||
|
@ -114,7 +113,7 @@ function actionColor(action) {
|
||||||
</Paginate>
|
</Paginate>
|
||||||
</q-timeline>
|
</q-timeline>
|
||||||
</div>
|
</div>
|
||||||
<TeleportSlot to="#actions-append">
|
<Teleport v-if="stateStore.isHeaderMounted()" to="#actions-append">
|
||||||
<div class="row q-gutter-x-sm">
|
<div class="row q-gutter-x-sm">
|
||||||
<q-btn flat @click="stateStore.toggleRightDrawer()" round dense icon="menu">
|
<q-btn flat @click="stateStore.toggleRightDrawer()" round dense icon="menu">
|
||||||
<q-tooltip bottom anchor="bottom right">
|
<q-tooltip bottom anchor="bottom right">
|
||||||
|
@ -122,7 +121,7 @@ function actionColor(action) {
|
||||||
</q-tooltip>
|
</q-tooltip>
|
||||||
</q-btn>
|
</q-btn>
|
||||||
</div>
|
</div>
|
||||||
</TeleportSlot>
|
</Teleport>
|
||||||
<q-drawer v-model="stateStore.rightDrawer" show-if-above side="right" :width="300">
|
<q-drawer v-model="stateStore.rightDrawer" show-if-above side="right" :width="300">
|
||||||
<q-scroll-area class="fit text-grey-8">
|
<q-scroll-area class="fit text-grey-8">
|
||||||
<ClaimLogFilter data-key="ClaimLogs" />
|
<ClaimLogFilter data-key="ClaimLogs" />
|
||||||
|
|
|
@ -1,22 +1,20 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed } from 'vue';
|
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
import { ref, computed } from 'vue';
|
||||||
import { useQuasar } from 'quasar';
|
import { useQuasar } from 'quasar';
|
||||||
import VnConfirm from 'src/components/ui/VnConfirm.vue';
|
|
||||||
import TeleportSlot from 'src/components/ui/TeleportSlot.vue';
|
|
||||||
|
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { useStateStore } from 'stores/useStateStore';
|
||||||
import { useSession } from 'src/composables/useSession';
|
import { useSession } from 'composables/useSession';
|
||||||
|
import VnConfirm from 'components/ui/VnConfirm.vue';
|
||||||
import FetchData from 'components/FetchData.vue';
|
import FetchData from 'components/FetchData.vue';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
const quasar = useQuasar();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
const stateStore = useStateStore();
|
||||||
const session = useSession();
|
const session = useSession();
|
||||||
const token = session.getToken();
|
const token = session.getToken();
|
||||||
const quasar = useQuasar();
|
|
||||||
|
|
||||||
const claimId = computed(() => router.currentRoute.value.params.id);
|
const claimId = computed(() => router.currentRoute.value.params.id);
|
||||||
|
|
||||||
|
@ -239,7 +237,10 @@ function onDrag() {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<teleport-slot v-if="!quasar.platform.is.mobile" to="#actions-prepend">
|
<Teleport
|
||||||
|
v-if="stateStore.isHeaderMounted() && !quasar.platform.is.mobile"
|
||||||
|
to="#actions-prepend"
|
||||||
|
>
|
||||||
<div class="row q-gutter-x-sm">
|
<div class="row q-gutter-x-sm">
|
||||||
<label for="fileInput">
|
<label for="fileInput">
|
||||||
<q-btn
|
<q-btn
|
||||||
|
@ -262,27 +263,34 @@ function onDrag() {
|
||||||
</label>
|
</label>
|
||||||
<q-separator vertical />
|
<q-separator vertical />
|
||||||
</div>
|
</div>
|
||||||
</teleport-slot>
|
</Teleport>
|
||||||
|
|
||||||
<teleport-slot to=".q-footer">
|
<q-page-sticky
|
||||||
<q-tabs align="justify" inline-label narrow-indicator>
|
v-if="quasar.platform.is.mobile"
|
||||||
<q-tab
|
position="bottom"
|
||||||
@click="inputFile.nativeEl.click()"
|
:offset="[0, 0]"
|
||||||
icon="add_circle"
|
expand
|
||||||
:label="t('globals.add')"
|
>
|
||||||
>
|
<q-toolbar class="bg-primary text-white q-pa-none">
|
||||||
<q-input
|
<q-tabs class="full-width" align="justify" inline-label narrow-indicator>
|
||||||
ref="inputFile"
|
<q-tab
|
||||||
type="file"
|
@click="inputFile.nativeEl.click()"
|
||||||
style="display: none"
|
icon="add_circle"
|
||||||
multiple
|
:label="t('globals.add')"
|
||||||
v-model="files"
|
>
|
||||||
@update:model-value="create()"
|
<q-input
|
||||||
/>
|
ref="inputFile"
|
||||||
<q-tooltip bottom> {{ t('globals.add') }} </q-tooltip>
|
type="file"
|
||||||
</q-tab>
|
style="display: none"
|
||||||
</q-tabs>
|
multiple
|
||||||
</teleport-slot>
|
v-model="files"
|
||||||
|
@update:model-value="create()"
|
||||||
|
/>
|
||||||
|
<q-tooltip bottom> {{ t('globals.add') }} </q-tooltip>
|
||||||
|
</q-tab>
|
||||||
|
</q-tabs>
|
||||||
|
</q-toolbar>
|
||||||
|
</q-page-sticky>
|
||||||
|
|
||||||
<!-- MULTIMEDIA DIALOG START-->
|
<!-- MULTIMEDIA DIALOG START-->
|
||||||
<q-dialog
|
<q-dialog
|
||||||
|
|
|
@ -5,9 +5,9 @@ import { useI18n } from 'vue-i18n';
|
||||||
import { useQuasar } from 'quasar';
|
import { useQuasar } from 'quasar';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { useArrayData } from 'src/composables/useArrayData';
|
import { useArrayData } from 'src/composables/useArrayData';
|
||||||
|
import { useStateStore } from 'stores/useStateStore';
|
||||||
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 VnConfirm from 'src/components/ui/VnConfirm.vue';
|
import VnConfirm from 'src/components/ui/VnConfirm.vue';
|
||||||
|
|
||||||
import { toDate } from 'src/filters';
|
import { toDate } from 'src/filters';
|
||||||
|
@ -15,6 +15,7 @@ import { toDate } from 'src/filters';
|
||||||
const quasar = useQuasar();
|
const quasar = useQuasar();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
const stateStore = useStateStore();
|
||||||
const arrayData = useArrayData('ClaimRma');
|
const arrayData = useArrayData('ClaimRma');
|
||||||
|
|
||||||
const claim = ref();
|
const claim = ref();
|
||||||
|
@ -44,6 +45,12 @@ async function onFetch(data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function addRow() {
|
async function addRow() {
|
||||||
|
if (!claim.value.rma) {
|
||||||
|
return quasar.notify({
|
||||||
|
message: `This claim is not associated to any RMA`,
|
||||||
|
type: 'negative',
|
||||||
|
});
|
||||||
|
}
|
||||||
const formData = {
|
const formData = {
|
||||||
code: claim.value.rma,
|
code: claim.value.rma,
|
||||||
};
|
};
|
||||||
|
@ -138,20 +145,31 @@ async function remove(id) {
|
||||||
</paginate>
|
</paginate>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<teleport-slot v-if="!quasar.platform.is.mobile" to="#actions-prepend">
|
|
||||||
|
<Teleport
|
||||||
|
v-if="stateStore.isHeaderMounted() && !quasar.platform.is.mobile"
|
||||||
|
to="#actions-prepend"
|
||||||
|
>
|
||||||
<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>
|
||||||
<q-tooltip bottom> {{ t('globals.add') }} </q-tooltip>
|
<q-tooltip bottom> {{ t('globals.add') }} </q-tooltip>
|
||||||
</q-btn>
|
</q-btn>
|
||||||
<q-separator vertical />
|
<q-separator vertical />
|
||||||
</div>
|
</div>
|
||||||
</teleport-slot>
|
</Teleport>
|
||||||
|
|
||||||
<teleport-slot to=".q-footer">
|
<q-page-sticky
|
||||||
<q-tabs align="justify" inline-label narrow-indicator>
|
v-if="quasar.platform.is.mobile"
|
||||||
<q-tab @click="addRow()" icon="add_circle" :label="t('globals.add')" />
|
position="bottom"
|
||||||
</q-tabs>
|
:offset="[0, 0]"
|
||||||
</teleport-slot>
|
expand
|
||||||
|
>
|
||||||
|
<q-toolbar class="bg-primary text-white q-pa-none">
|
||||||
|
<q-tabs class="full-width" align="justify" inline-label narrow-indicator>
|
||||||
|
<q-tab @click="addRow()" icon="add_circle" :label="t('globals.add')" />
|
||||||
|
</q-tabs>
|
||||||
|
</q-toolbar>
|
||||||
|
</q-page-sticky>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
@ -170,3 +188,8 @@ async function remove(id) {
|
||||||
z-index: 2998;
|
z-index: 2998;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<i18n>
|
||||||
|
es:
|
||||||
|
This claim is not associated to any RMA: Esta reclamación no está asociada a ninguna ARM
|
||||||
|
</i18n>
|
||||||
|
|
|
@ -3,12 +3,11 @@ import { useI18n } from 'vue-i18n';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import { useQuasar } from 'quasar';
|
import { useQuasar } from 'quasar';
|
||||||
import { useStateStore } from 'stores/useStateStore';
|
import { useStateStore } from 'stores/useStateStore';
|
||||||
import { toDate } from 'src/filters/index';
|
import { toDate } from 'filters/index';
|
||||||
import Paginate from 'src/components/PaginateData.vue';
|
import Paginate from 'components/PaginateData.vue';
|
||||||
import ClaimSummaryDialog from './Card/ClaimSummaryDialog.vue';
|
import ClaimSummaryDialog from './Card/ClaimSummaryDialog.vue';
|
||||||
import CustomerDescriptorPopover from 'src/pages/Customer/Card/CustomerDescriptorPopover.vue';
|
import CustomerDescriptorPopover from 'pages/Customer/Card/CustomerDescriptorPopover.vue';
|
||||||
import TeleportSlot from 'components/ui/TeleportSlot.vue';
|
import VnSearchbar from 'components/ui/VnSearchbar.vue';
|
||||||
import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
|
|
||||||
import ClaimFilter from './ClaimFilter.vue';
|
import ClaimFilter from './ClaimFilter.vue';
|
||||||
|
|
||||||
const stateStore = useStateStore();
|
const stateStore = useStateStore();
|
||||||
|
@ -37,22 +36,30 @@ function viewSummary(id) {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<teleport-slot to="#searchbar">
|
<template v-if="stateStore.isHeaderMounted()">
|
||||||
<VnSearchbar
|
<Teleport to="#searchbar">
|
||||||
data-key="ClaimList"
|
<VnSearchbar
|
||||||
:label="t('Search claim')"
|
data-key="ClaimList"
|
||||||
:info="t('You can search by claim id or customer name')"
|
:label="t('Search claim')"
|
||||||
/>
|
:info="t('You can search by claim id or customer name')"
|
||||||
</teleport-slot>
|
/>
|
||||||
<teleport-slot to="#actions-append">
|
</Teleport>
|
||||||
<div class="row q-gutter-x-sm">
|
<Teleport to="#actions-append">
|
||||||
<q-btn flat @click="stateStore.toggleRightDrawer()" round dense icon="menu">
|
<div class="row q-gutter-x-sm">
|
||||||
<q-tooltip bottom anchor="bottom right">
|
<q-btn
|
||||||
{{ t('globals.collapseMenu') }}
|
flat
|
||||||
</q-tooltip>
|
@click="stateStore.toggleRightDrawer()"
|
||||||
</q-btn>
|
round
|
||||||
</div>
|
dense
|
||||||
</teleport-slot>
|
icon="menu"
|
||||||
|
>
|
||||||
|
<q-tooltip bottom anchor="bottom right">
|
||||||
|
{{ t('globals.collapseMenu') }}
|
||||||
|
</q-tooltip>
|
||||||
|
</q-btn>
|
||||||
|
</div>
|
||||||
|
</Teleport>
|
||||||
|
</template>
|
||||||
<q-drawer v-model="stateStore.rightDrawer" side="right" :width="256" show-if-above>
|
<q-drawer v-model="stateStore.rightDrawer" side="right" :width="256" show-if-above>
|
||||||
<q-scroll-area class="fit text-grey-8">
|
<q-scroll-area class="fit text-grey-8">
|
||||||
<ClaimFilter data-key="ClaimList" />
|
<ClaimFilter data-key="ClaimList" />
|
||||||
|
|
|
@ -3,20 +3,19 @@ import { useI18n } from 'vue-i18n';
|
||||||
import { useStateStore } from 'stores/useStateStore';
|
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 VnSearchbar from 'src/components/ui/VnSearchbar.vue';
|
import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
|
||||||
|
|
||||||
const stateStore = useStateStore();
|
const stateStore = useStateStore();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<teleport-slot to="#searchbar">
|
<Teleport to="#searchbar" v-if="stateStore.isHeaderMounted()">
|
||||||
<VnSearchbar
|
<VnSearchbar
|
||||||
data-key="CustomerList"
|
data-key="CustomerList"
|
||||||
:label="t('Search customer')"
|
:label="t('Search customer')"
|
||||||
:info="t('You can search by customer id or name')"
|
:info="t('You can search by customer id or name')"
|
||||||
/>
|
/>
|
||||||
</teleport-slot>
|
</Teleport>
|
||||||
<q-drawer v-model="stateStore.leftDrawer" show-if-above :width="256">
|
<q-drawer v-model="stateStore.leftDrawer" show-if-above :width="256">
|
||||||
<q-scroll-area class="fit">
|
<q-scroll-area class="fit">
|
||||||
<CustomerDescriptor />
|
<CustomerDescriptor />
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { useRoute } from 'vue-router';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { toCurrency } from 'src/filters';
|
import { toCurrency } from 'src/filters';
|
||||||
import CardDescriptor from 'components/ui/CardDescriptor.vue';
|
import CardDescriptor from 'components/ui/CardDescriptor.vue';
|
||||||
|
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
|
||||||
|
|
||||||
const $props = defineProps({
|
const $props = defineProps({
|
||||||
id: {
|
id: {
|
||||||
|
@ -30,7 +31,10 @@ const entityId = computed(() => {
|
||||||
{{ t('customer.card.salesPerson') }}
|
{{ t('customer.card.salesPerson') }}
|
||||||
</q-item-label>
|
</q-item-label>
|
||||||
<q-item-label class="col q-ma-none">
|
<q-item-label class="col q-ma-none">
|
||||||
{{ entity.salesPersonUser.name }}
|
<span class="link">
|
||||||
|
{{ entity.salesPersonUser.name }}
|
||||||
|
<WorkerDescriptorProxy :id="entity.salesPersonFk" />
|
||||||
|
</span>
|
||||||
</q-item-label>
|
</q-item-label>
|
||||||
</q-item>
|
</q-item>
|
||||||
<q-item class="row">
|
<q-item class="row">
|
||||||
|
|
|
@ -5,7 +5,6 @@ import { useQuasar } from 'quasar';
|
||||||
import { useStateStore } from 'stores/useStateStore';
|
import { useStateStore } from 'stores/useStateStore';
|
||||||
import Paginate from 'src/components/PaginateData.vue';
|
import Paginate from 'src/components/PaginateData.vue';
|
||||||
import CustomerSummaryDialog from './Card/CustomerSummaryDialog.vue';
|
import CustomerSummaryDialog from './Card/CustomerSummaryDialog.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 CustomerFilter from './CustomerFilter.vue';
|
import CustomerFilter from './CustomerFilter.vue';
|
||||||
|
|
||||||
|
@ -29,22 +28,30 @@ function viewSummary(id) {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<teleport-slot to="#searchbar">
|
<template v-if="stateStore.isHeaderMounted()">
|
||||||
<VnSearchbar
|
<Teleport to="#searchbar">
|
||||||
data-key="CustomerList"
|
<VnSearchbar
|
||||||
:label="t('Search customer')"
|
data-key="CustomerList"
|
||||||
:info="t('You can search by customer id or name')"
|
:label="t('Search customer')"
|
||||||
/>
|
:info="t('You can search by customer id or name')"
|
||||||
</teleport-slot>
|
/>
|
||||||
<teleport-slot to="#actions-append">
|
</Teleport>
|
||||||
<div class="row q-gutter-x-sm">
|
<Teleport to="#actions-append">
|
||||||
<q-btn flat @click="stateStore.toggleRightDrawer()" round dense icon="menu">
|
<div class="row q-gutter-x-sm">
|
||||||
<q-tooltip bottom anchor="bottom right">
|
<q-btn
|
||||||
{{ t('globals.collapseMenu') }}
|
flat
|
||||||
</q-tooltip>
|
@click="stateStore.toggleRightDrawer()"
|
||||||
</q-btn>
|
round
|
||||||
</div>
|
dense
|
||||||
</teleport-slot>
|
icon="menu"
|
||||||
|
>
|
||||||
|
<q-tooltip bottom anchor="bottom right">
|
||||||
|
{{ t('globals.collapseMenu') }}
|
||||||
|
</q-tooltip>
|
||||||
|
</q-btn>
|
||||||
|
</div>
|
||||||
|
</Teleport>
|
||||||
|
</template>
|
||||||
<q-drawer v-model="stateStore.rightDrawer" side="right" :width="256" show-if-above>
|
<q-drawer v-model="stateStore.rightDrawer" side="right" :width="256" show-if-above>
|
||||||
<q-scroll-area class="fit text-grey-8">
|
<q-scroll-area class="fit text-grey-8">
|
||||||
<CustomerFilter data-key="CustomerList" />
|
<CustomerFilter data-key="CustomerList" />
|
||||||
|
@ -113,7 +120,7 @@ function viewSummary(id) {
|
||||||
<q-btn
|
<q-btn
|
||||||
flat
|
flat
|
||||||
round
|
round
|
||||||
color="orange"
|
color="primary"
|
||||||
icon="arrow_circle_right"
|
icon="arrow_circle_right"
|
||||||
@click="navigate(row.id)"
|
@click="navigate(row.id)"
|
||||||
>
|
>
|
||||||
|
|
|
@ -3,20 +3,19 @@ import { useI18n } from 'vue-i18n';
|
||||||
import { useStateStore } from 'stores/useStateStore';
|
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 VnSearchbar from 'components/ui/VnSearchbar.vue';
|
import VnSearchbar from 'components/ui/VnSearchbar.vue';
|
||||||
|
|
||||||
const stateStore = useStateStore();
|
const stateStore = useStateStore();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<teleport-slot to="#searchbar">
|
<Teleport to="#searchbar" v-if="stateStore.isHeaderMounted()">
|
||||||
<VnSearchbar
|
<VnSearchbar
|
||||||
data-key="InvoiceOutList"
|
data-key="InvoiceOutList"
|
||||||
:label="t('Search invoice')"
|
:label="t('Search invoice')"
|
||||||
:info="t('You can search by invoice reference')"
|
:info="t('You can search by invoice reference')"
|
||||||
/>
|
/>
|
||||||
</teleport-slot>
|
</Teleport>
|
||||||
<q-drawer v-model="stateStore.leftDrawer" show-if-above :width="256">
|
<q-drawer v-model="stateStore.leftDrawer" show-if-above :width="256">
|
||||||
<q-scroll-area class="fit">
|
<q-scroll-area class="fit">
|
||||||
<InvoiceOutDescriptor />
|
<InvoiceOutDescriptor />
|
||||||
|
|
|
@ -7,7 +7,6 @@ import { useStateStore } from 'stores/useStateStore';
|
||||||
import Paginate from 'src/components/PaginateData.vue';
|
import Paginate from 'src/components/PaginateData.vue';
|
||||||
import InvoiceOutSummaryDialog from './Card/InvoiceOutSummaryDialog.vue';
|
import InvoiceOutSummaryDialog from './Card/InvoiceOutSummaryDialog.vue';
|
||||||
import { toDate, toCurrency } from 'src/filters/index';
|
import { toDate, toCurrency } from 'src/filters/index';
|
||||||
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';
|
||||||
|
|
||||||
|
@ -34,22 +33,30 @@ function viewSummary(id) {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<teleport-slot to="#searchbar">
|
<template v-if="stateStore.isHeaderMounted()">
|
||||||
<VnSearchbar
|
<Teleport to="#searchbar">
|
||||||
data-key="InvoiceOutList"
|
<VnSearchbar
|
||||||
:label="t('Search invoice')"
|
data-key="InvoiceOutList"
|
||||||
:info="t('You can search by invoice reference')"
|
:label="t('Search invoice')"
|
||||||
/>
|
:info="t('You can search by invoice reference')"
|
||||||
</teleport-slot>
|
/>
|
||||||
<teleport-slot to="#actions-append">
|
</Teleport>
|
||||||
<div class="row q-gutter-x-sm">
|
<Teleport to="#actions-append">
|
||||||
<q-btn flat @click="stateStore.toggleRightDrawer()" round dense icon="menu">
|
<div class="row q-gutter-x-sm">
|
||||||
<q-tooltip bottom anchor="bottom right">
|
<q-btn
|
||||||
{{ t('globals.collapseMenu') }}
|
flat
|
||||||
</q-tooltip>
|
@click="stateStore.toggleRightDrawer()"
|
||||||
</q-btn>
|
round
|
||||||
</div>
|
dense
|
||||||
</teleport-slot>
|
icon="menu"
|
||||||
|
>
|
||||||
|
<q-tooltip bottom anchor="bottom right">
|
||||||
|
{{ t('globals.collapseMenu') }}
|
||||||
|
</q-tooltip>
|
||||||
|
</q-btn>
|
||||||
|
</div>
|
||||||
|
</Teleport>
|
||||||
|
</template>
|
||||||
<q-drawer v-model="stateStore.rightDrawer" side="right" :width="256" show-if-above>
|
<q-drawer v-model="stateStore.rightDrawer" side="right" :width="256" show-if-above>
|
||||||
<q-scroll-area class="fit text-grey-8">
|
<q-scroll-area class="fit text-grey-8">
|
||||||
<InvoiceOutFilter data-key="InvoiceOutList" />
|
<InvoiceOutFilter data-key="InvoiceOutList" />
|
||||||
|
|
|
@ -3,20 +3,19 @@ import { useI18n } from 'vue-i18n';
|
||||||
import { useStateStore } from 'stores/useStateStore';
|
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 VnSearchbar from 'src/components/ui/VnSearchbar.vue';
|
import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
|
||||||
|
|
||||||
const stateStore = useStateStore();
|
const stateStore = useStateStore();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<teleport-slot to="#searchbar">
|
<Teleport to="#searchbar" v-if="stateStore.isHeaderMounted()">
|
||||||
<VnSearchbar
|
<VnSearchbar
|
||||||
data-key="TicketList"
|
data-key="TicketList"
|
||||||
:label="t('Search ticket')"
|
:label="t('Search ticket')"
|
||||||
:info="t('You can search by ticket id or alias')"
|
:info="t('You can search by ticket id or alias')"
|
||||||
/>
|
/>
|
||||||
</teleport-slot>
|
</Teleport>
|
||||||
<q-drawer v-model="stateStore.leftDrawer" show-if-above :width="256">
|
<q-drawer v-model="stateStore.leftDrawer" show-if-above :width="256">
|
||||||
<q-scroll-area class="fit">
|
<q-scroll-area class="fit">
|
||||||
<TicketDescriptor />
|
<TicketDescriptor />
|
||||||
|
|
|
@ -7,8 +7,6 @@ import { useStateStore } from 'stores/useStateStore';
|
||||||
import Paginate from 'src/components/PaginateData.vue';
|
import Paginate from 'src/components/PaginateData.vue';
|
||||||
import { toDate, toCurrency } from 'src/filters/index';
|
import { toDate, toCurrency } from 'src/filters/index';
|
||||||
import TicketSummaryDialog from './Card/TicketSummaryDialog.vue';
|
import TicketSummaryDialog from './Card/TicketSummaryDialog.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 TicketFilter from './TicketFilter.vue';
|
import TicketFilter from './TicketFilter.vue';
|
||||||
|
|
||||||
|
@ -71,22 +69,30 @@ function viewSummary(id) {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<teleport-slot to="#searchbar">
|
<template v-if="stateStore.isHeaderMounted()">
|
||||||
<VnSearchbar
|
<Teleport to="#searchbar">
|
||||||
data-key="TicketList"
|
<VnSearchbar
|
||||||
:label="t('Search ticket')"
|
data-key="TicketList"
|
||||||
:info="t('You can search by ticket id or alias')"
|
:label="t('Search ticket')"
|
||||||
/>
|
:info="t('You can search by ticket id or alias')"
|
||||||
</teleport-slot>
|
/>
|
||||||
<teleport-slot to="#actions-append">
|
</Teleport>
|
||||||
<div class="row q-gutter-x-sm">
|
<Teleport to="#actions-append">
|
||||||
<q-btn flat @click="stateStore.toggleRightDrawer()" round dense icon="menu">
|
<div class="row q-gutter-x-sm">
|
||||||
<q-tooltip bottom anchor="bottom right">
|
<q-btn
|
||||||
{{ t('globals.collapseMenu') }}
|
flat
|
||||||
</q-tooltip>
|
@click="stateStore.toggleRightDrawer()"
|
||||||
</q-btn>
|
round
|
||||||
</div>
|
dense
|
||||||
</teleport-slot>
|
icon="menu"
|
||||||
|
>
|
||||||
|
<q-tooltip bottom anchor="bottom right">
|
||||||
|
{{ t('globals.collapseMenu') }}
|
||||||
|
</q-tooltip>
|
||||||
|
</q-btn>
|
||||||
|
</div>
|
||||||
|
</Teleport>
|
||||||
|
</template>
|
||||||
<q-drawer v-model="stateStore.rightDrawer" side="right" :width="256" show-if-above>
|
<q-drawer v-model="stateStore.rightDrawer" side="right" :width="256" show-if-above>
|
||||||
<q-scroll-area class="fit text-grey-8">
|
<q-scroll-area class="fit text-grey-8">
|
||||||
<TicketFilter data-key="TicketList" />
|
<TicketFilter data-key="TicketList" />
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
<script setup>
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { useStateStore } from 'stores/useStateStore';
|
||||||
|
import WorkerDescriptor from './WorkerDescriptor.vue';
|
||||||
|
import LeftMenu from 'components/LeftMenu.vue';
|
||||||
|
import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
|
||||||
|
|
||||||
|
const stateStore = useStateStore();
|
||||||
|
const { t } = useI18n();
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<Teleport to="#searchbar" v-if="stateStore.isHeaderMounted()">
|
||||||
|
<VnSearchbar
|
||||||
|
data-key="WorkerList"
|
||||||
|
:label="t('Search worker')"
|
||||||
|
:info="t('You can search by worker id or name')"
|
||||||
|
/>
|
||||||
|
</Teleport>
|
||||||
|
<q-drawer v-model="stateStore.leftDrawer" show-if-above :width="256">
|
||||||
|
<q-scroll-area class="fit">
|
||||||
|
<WorkerDescriptor />
|
||||||
|
<q-separator />
|
||||||
|
<left-menu source="card" />
|
||||||
|
</q-scroll-area>
|
||||||
|
</q-drawer>
|
||||||
|
<q-page-container>
|
||||||
|
<q-page class="q-pa-md">
|
||||||
|
<router-view></router-view>
|
||||||
|
</q-page>
|
||||||
|
</q-page-container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<i18n>
|
||||||
|
es:
|
||||||
|
Search worker: Buscar trabajador
|
||||||
|
You can search by worker id or name: Puedes buscar por id o nombre del trabajador
|
||||||
|
</i18n>
|
|
@ -0,0 +1,138 @@
|
||||||
|
<script setup>
|
||||||
|
import { computed, ref } from 'vue';
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { useSession } from 'src/composables/useSession';
|
||||||
|
import CardDescriptor from 'src/components/ui/CardDescriptor.vue';
|
||||||
|
|
||||||
|
const $props = defineProps({
|
||||||
|
id: {
|
||||||
|
type: Number,
|
||||||
|
required: false,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
const { t } = useI18n();
|
||||||
|
const { getToken } = useSession();
|
||||||
|
|
||||||
|
const entityId = computed(() => {
|
||||||
|
return $props.id || route.params.id;
|
||||||
|
});
|
||||||
|
|
||||||
|
const worker = ref();
|
||||||
|
const filter = {
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
relation: 'user',
|
||||||
|
scope: {
|
||||||
|
fields: ['email', 'name', 'nickname'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
relation: 'department',
|
||||||
|
scope: {
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
relation: 'department',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
relation: 'sip',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const sip = computed(() => worker.value.sip && worker.value.sip.extension);
|
||||||
|
|
||||||
|
function getWorkerAvatar() {
|
||||||
|
const token = getToken();
|
||||||
|
return `/api/Images/user/160x160/${route.params.id}/download?access_token=${token}`;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<card-descriptor
|
||||||
|
module="Worker"
|
||||||
|
:url="`Workers/${entityId}`"
|
||||||
|
:filter="filter"
|
||||||
|
@on-fetch="(data) => (worker = data)"
|
||||||
|
>
|
||||||
|
<template #before>
|
||||||
|
<q-img :src="getWorkerAvatar()" class="photo">
|
||||||
|
<template #error>
|
||||||
|
<div
|
||||||
|
class="absolute-full bg-grey-10 text-center q-pa-md flex flex-center"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<div class="text-grey-5" style="opacity: 0.4; font-size: 5vh">
|
||||||
|
<q-icon name="vn:claims" />
|
||||||
|
</div>
|
||||||
|
<div class="text-grey-5" style="opacity: 0.4">
|
||||||
|
{{ t('worker.imageNotFound') }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</q-img>
|
||||||
|
</template>
|
||||||
|
<template #description="{ entity }">
|
||||||
|
<span>
|
||||||
|
{{ entity.user.nickname }}
|
||||||
|
<q-tooltip>{{ entity.user.nickname }}</q-tooltip>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<template #body="{ entity }">
|
||||||
|
<q-list>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption> {{ t('worker.card.name') }} </q-item-label>
|
||||||
|
<q-item-label>{{ entity.user.nickname }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>
|
||||||
|
{{ t('worker.card.email') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label>{{ entity.user.email }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>
|
||||||
|
{{ t('worker.list.department') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label>
|
||||||
|
{{ entity.department.department.name }}
|
||||||
|
</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>
|
||||||
|
{{ t('worker.card.phone') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label>{{ entity.phone }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption
|
||||||
|
>{{ t('worker.summary.sipExtension') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label>{{ sip }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
</template>
|
||||||
|
</card-descriptor>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.photo {
|
||||||
|
height: 256px;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,16 @@
|
||||||
|
<script setup>
|
||||||
|
import WorkerDescriptor from './WorkerDescriptor.vue';
|
||||||
|
|
||||||
|
const $props = defineProps({
|
||||||
|
id: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<q-popup-proxy>
|
||||||
|
<WorkerDescriptor v-if="$props.id" :id="$props.id" />
|
||||||
|
</q-popup-proxy>
|
||||||
|
</template>
|
|
@ -0,0 +1,292 @@
|
||||||
|
<script setup>
|
||||||
|
import axios from 'axios';
|
||||||
|
import { ref, onMounted, computed, onUpdated } from 'vue';
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import SkeletonSummary from 'components/ui/SkeletonSummary.vue';
|
||||||
|
import WorkerDescriptorProxy from './WorkerDescriptorProxy.vue';
|
||||||
|
|
||||||
|
onMounted(() => fetch());
|
||||||
|
onUpdated(() => fetch());
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const $props = defineProps({
|
||||||
|
id: {
|
||||||
|
type: Number,
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const entityId = computed(() => $props.id || route.params.id);
|
||||||
|
|
||||||
|
const worker = ref(null);
|
||||||
|
|
||||||
|
const filter = {
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
relation: 'user',
|
||||||
|
scope: {
|
||||||
|
fields: ['email', 'name', 'nickname', 'roleFk'],
|
||||||
|
include: {
|
||||||
|
relation: 'role',
|
||||||
|
scope: {
|
||||||
|
fields: ['name'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
relation: 'department',
|
||||||
|
scope: {
|
||||||
|
include: {
|
||||||
|
relation: 'department',
|
||||||
|
scope: {
|
||||||
|
fields: ['name'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
relation: 'boss',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
relation: 'client',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
relation: 'sip',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
function fetch() {
|
||||||
|
const id = entityId.value;
|
||||||
|
axios.get(`/Workers/${id}`, { params: { filter } }).then((response) => {
|
||||||
|
worker.value = response.data;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function sipExtension() {
|
||||||
|
if (worker.value.sip) return worker.value.sip.extension;
|
||||||
|
return '-';
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="summary container">
|
||||||
|
<q-card>
|
||||||
|
<SkeletonSummary v-if="!worker" />
|
||||||
|
<template v-if="worker">
|
||||||
|
<div class="header bg-primary q-pa-sm q-mb-md">
|
||||||
|
{{ worker.id }} - {{ worker.firstName }} {{ worker.lastName }}
|
||||||
|
</div>
|
||||||
|
<div class="row q-pa-md q-col-gutter-md q-mb-md">
|
||||||
|
<div class="col">
|
||||||
|
<q-list>
|
||||||
|
<q-item-label header class="text-h6">
|
||||||
|
{{ t('worker.summary.basicData') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption> ID </q-item-label>
|
||||||
|
<q-item-label>{{ worker.id }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption
|
||||||
|
>{{ t('worker.card.name') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label>
|
||||||
|
{{ worker.user.nickname }}
|
||||||
|
</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption
|
||||||
|
>{{ t('worker.list.department') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label>{{
|
||||||
|
worker.department.department.name
|
||||||
|
}}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption
|
||||||
|
>{{ t('worker.list.email') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label>{{ worker.user.email }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item
|
||||||
|
class="items-start cursor-pointer q-hoverable"
|
||||||
|
v-if="worker.boss"
|
||||||
|
>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>
|
||||||
|
{{ t('worker.summary.boss') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label>
|
||||||
|
<span class="link">
|
||||||
|
{{ worker.boss.name }}
|
||||||
|
<WorkerDescriptorProxy :id="worker.bossFk" />
|
||||||
|
</span>
|
||||||
|
</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption
|
||||||
|
>{{ t('worker.summary.phoneExtension') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label>
|
||||||
|
{{
|
||||||
|
worker.mobileExtension == ''
|
||||||
|
? worker.mobileExtension
|
||||||
|
: '-'
|
||||||
|
}}
|
||||||
|
</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption
|
||||||
|
>{{ t('worker.summary.entPhone') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label>{{
|
||||||
|
worker.phone == '' ? worker.phone : '-'
|
||||||
|
}}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption
|
||||||
|
>{{ t('worker.summary.personalPhone') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label>{{
|
||||||
|
worker.client.phone == ''
|
||||||
|
? worker.client.phone
|
||||||
|
: '-'
|
||||||
|
}}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<q-list>
|
||||||
|
<q-item-label header class="text-h6">
|
||||||
|
{{ t('worker.summary.userData') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>
|
||||||
|
{{ t('worker.summary.userId') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label>{{ worker.user.id }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption
|
||||||
|
>{{ t('worker.card.name') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label>{{
|
||||||
|
worker.user.nickname
|
||||||
|
}}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption
|
||||||
|
>{{ t('worker.summary.role') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label>{{
|
||||||
|
worker.user.role.name
|
||||||
|
}}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption
|
||||||
|
>{{ t('worker.summary.sipExtension') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label>{{ sipExtension() }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</q-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.avatar {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
border-radius: 50%;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.q-card {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 1200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.negative {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary {
|
||||||
|
.q-list {
|
||||||
|
.q-item__label--header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: $primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.row {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
|
.col {
|
||||||
|
min-width: 250px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#slider-container {
|
||||||
|
max-width: 80%;
|
||||||
|
margin: 0 auto;
|
||||||
|
|
||||||
|
.q-slider {
|
||||||
|
.q-slider__marker-labels:nth-child(1) {
|
||||||
|
transform: none;
|
||||||
|
}
|
||||||
|
.q-slider__marker-labels:nth-child(2) {
|
||||||
|
transform: none;
|
||||||
|
left: auto !important;
|
||||||
|
right: 0%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.q-dialog .summary {
|
||||||
|
max-width: 1200px;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,21 @@
|
||||||
|
<script setup>
|
||||||
|
import { useDialogPluginComponent } from 'quasar';
|
||||||
|
import WorkerSummary from './WorkerSummary.vue';
|
||||||
|
|
||||||
|
const $props = defineProps({
|
||||||
|
id: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
defineEmits([...useDialogPluginComponent.emits]);
|
||||||
|
|
||||||
|
const { dialogRef, onDialogHide } = useDialogPluginComponent();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<q-dialog ref="dialogRef" @hide="onDialogHide">
|
||||||
|
<worker-summary v-if="$props.id" :id="$props.id" />
|
||||||
|
</q-dialog>
|
||||||
|
</template>
|
|
@ -0,0 +1,121 @@
|
||||||
|
<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 departments = ref();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<fetch-data url="Departments" @on-fetch="(data) => (departments = data)" auto-load />
|
||||||
|
<VnFilterPanel :data-key="props.dataKey" :search-button="true">
|
||||||
|
<template #tags="{ tag, formatFn }">
|
||||||
|
<div class="q-gutter-x-xs">
|
||||||
|
<strong>{{ t(`params.${tag.label}`) }}: </strong>
|
||||||
|
<span>{{ formatFn(tag.value) }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #body="{ params, searchFn }">
|
||||||
|
<q-list dense>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-input :label="t('FI')" v-model="params.fi" lazy-rules>
|
||||||
|
<template #prepend>
|
||||||
|
<q-icon name="badge" size="sm"></q-icon>
|
||||||
|
</template>
|
||||||
|
</q-input>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-input
|
||||||
|
:label="t('First Name')"
|
||||||
|
v-model="params.firstName"
|
||||||
|
lazy-rules
|
||||||
|
/>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-input
|
||||||
|
:label="t('Last Name')"
|
||||||
|
v-model="params.lastName"
|
||||||
|
lazy-rules
|
||||||
|
/>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-input
|
||||||
|
:label="t('User Name')"
|
||||||
|
v-model="params.userName"
|
||||||
|
lazy-rules
|
||||||
|
/>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section v-if="!departments">
|
||||||
|
<q-skeleton type="QInput" class="full-width" />
|
||||||
|
</q-item-section>
|
||||||
|
<q-item-section v-if="departments">
|
||||||
|
<q-select
|
||||||
|
:label="t('Department')"
|
||||||
|
v-model="params.departmentFk"
|
||||||
|
@update:model-value="searchFn()"
|
||||||
|
:options="departments"
|
||||||
|
option-value="id"
|
||||||
|
option-label="name"
|
||||||
|
emit-value
|
||||||
|
map-options
|
||||||
|
use-input
|
||||||
|
:input-debounce="0"
|
||||||
|
/>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item class="q-mb-md">
|
||||||
|
<q-item-section>
|
||||||
|
<q-input
|
||||||
|
:label="t('Extension')"
|
||||||
|
v-model="params.extension"
|
||||||
|
lazy-rules
|
||||||
|
/>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
</template>
|
||||||
|
</VnFilterPanel>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<i18n>
|
||||||
|
en:
|
||||||
|
params:
|
||||||
|
search: Contains
|
||||||
|
fi: FI
|
||||||
|
firstName: First name
|
||||||
|
lastName: Last name
|
||||||
|
userName: User
|
||||||
|
extension: Extension
|
||||||
|
es:
|
||||||
|
params:
|
||||||
|
search: Contiene
|
||||||
|
fi: NIF
|
||||||
|
firstName: Nombre
|
||||||
|
lastName: Apellidos
|
||||||
|
userName: Usuario
|
||||||
|
extension: Extensión
|
||||||
|
FI: NIF
|
||||||
|
First Name: Nombre
|
||||||
|
Last Name: Apellidos
|
||||||
|
User Name: Usuario
|
||||||
|
Department: Departamento
|
||||||
|
Extension: Extensión
|
||||||
|
</i18n>
|
|
@ -0,0 +1,155 @@
|
||||||
|
<script setup>
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
import { useQuasar } from 'quasar';
|
||||||
|
import { useStateStore } from 'stores/useStateStore';
|
||||||
|
import Paginate from 'src/components/PaginateData.vue';
|
||||||
|
import WorkerSummaryDialog from './Card/WorkerSummaryDialog.vue';
|
||||||
|
import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
|
||||||
|
import WorkerFilter from './WorkerFilter.vue';
|
||||||
|
|
||||||
|
const stateStore = useStateStore();
|
||||||
|
const router = useRouter();
|
||||||
|
const { t } = useI18n();
|
||||||
|
const quasar = useQuasar();
|
||||||
|
|
||||||
|
function navigate(id) {
|
||||||
|
router.push({ path: `/worker/${id}` });
|
||||||
|
}
|
||||||
|
|
||||||
|
function viewSummary(id) {
|
||||||
|
quasar.dialog({
|
||||||
|
component: WorkerSummaryDialog,
|
||||||
|
componentProps: {
|
||||||
|
id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<template v-if="stateStore.isHeaderMounted()">
|
||||||
|
<Teleport to="#searchbar">
|
||||||
|
<VnSearchbar
|
||||||
|
data-key="WorkerList"
|
||||||
|
:label="t('Search worker')"
|
||||||
|
:info="t('You can search by worker id or name')"
|
||||||
|
/>
|
||||||
|
</Teleport>
|
||||||
|
<Teleport to="#actions-append">
|
||||||
|
<div class="row q-gutter-x-sm">
|
||||||
|
<q-btn
|
||||||
|
flat
|
||||||
|
@click="stateStore.toggleRightDrawer()"
|
||||||
|
round
|
||||||
|
dense
|
||||||
|
icon="menu"
|
||||||
|
>
|
||||||
|
<q-tooltip bottom anchor="bottom right">
|
||||||
|
{{ t('globals.collapseMenu') }}
|
||||||
|
</q-tooltip>
|
||||||
|
</q-btn>
|
||||||
|
</div>
|
||||||
|
</Teleport>
|
||||||
|
</template>
|
||||||
|
<q-drawer v-model="stateStore.rightDrawer" side="right" :width="256" show-if-above>
|
||||||
|
<q-scroll-area class="fit text-grey-8">
|
||||||
|
<WorkerFilter data-key="WorkerList" />
|
||||||
|
</q-scroll-area>
|
||||||
|
</q-drawer>
|
||||||
|
<q-page class="column items-center q-pa-md">
|
||||||
|
<div class="card-list">
|
||||||
|
<paginate
|
||||||
|
data-key="WorkerList"
|
||||||
|
url="Workers/filter"
|
||||||
|
order="id DESC"
|
||||||
|
auto-load
|
||||||
|
>
|
||||||
|
<template #body="{ rows }">
|
||||||
|
<q-card class="card q-mb-md" v-for="row of rows" :key="row.id">
|
||||||
|
<q-item
|
||||||
|
class="q-pa-none items-start cursor-pointer q-hoverable"
|
||||||
|
v-ripple
|
||||||
|
clickable
|
||||||
|
>
|
||||||
|
<q-item-section class="q-pa-md" @click="navigate(row.id)">
|
||||||
|
<q-item-label class="text-h6">
|
||||||
|
{{ row.nickname }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label caption>#{{ row.id }}</q-item-label>
|
||||||
|
<q-list>
|
||||||
|
<q-item class="q-pa-none">
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>
|
||||||
|
{{ t('worker.list.name') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label>{{
|
||||||
|
row.userName
|
||||||
|
}}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item class="q-pa-none">
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>
|
||||||
|
{{ t('worker.list.email') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label>{{ row.email }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item class="q-pa-none">
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>{{
|
||||||
|
t('worker.list.department')
|
||||||
|
}}</q-item-label>
|
||||||
|
<q-item-label>
|
||||||
|
{{ row.department }}
|
||||||
|
</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
</q-item-section>
|
||||||
|
<q-separator vertical />
|
||||||
|
<q-card-actions vertical class="justify-between">
|
||||||
|
<q-btn
|
||||||
|
flat
|
||||||
|
round
|
||||||
|
color="primary"
|
||||||
|
icon="arrow_circle_right"
|
||||||
|
@click="navigate(row.id)"
|
||||||
|
>
|
||||||
|
<q-tooltip>
|
||||||
|
{{ t('components.smartCard.openCard') }}
|
||||||
|
</q-tooltip>
|
||||||
|
</q-btn>
|
||||||
|
<q-btn
|
||||||
|
flat
|
||||||
|
round
|
||||||
|
color="grey-7"
|
||||||
|
icon="preview"
|
||||||
|
@click="viewSummary(row.id)"
|
||||||
|
>
|
||||||
|
<q-tooltip>
|
||||||
|
{{ t('components.smartCard.openSummary') }}
|
||||||
|
</q-tooltip>
|
||||||
|
</q-btn>
|
||||||
|
</q-card-actions>
|
||||||
|
</q-item>
|
||||||
|
</q-card>
|
||||||
|
</template>
|
||||||
|
</paginate>
|
||||||
|
</div>
|
||||||
|
</q-page>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.card-list {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 60em;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<i18n>
|
||||||
|
es:
|
||||||
|
Search worker: Buscar trabajador
|
||||||
|
You can search by worker id or name: Puedes buscar por id o nombre del trabajador
|
||||||
|
</i18n>
|
|
@ -0,0 +1,17 @@
|
||||||
|
<script setup>
|
||||||
|
import { useStateStore } from 'stores/useStateStore';
|
||||||
|
import LeftMenu from 'src/components/LeftMenu.vue';
|
||||||
|
|
||||||
|
const stateStore = useStateStore();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<q-drawer v-model="stateStore.leftDrawer" show-if-above :width="256">
|
||||||
|
<q-scroll-area class="fit text-grey-8">
|
||||||
|
<LeftMenu />
|
||||||
|
</q-scroll-area>
|
||||||
|
</q-drawer>
|
||||||
|
<q-page-container>
|
||||||
|
<router-view></router-view>
|
||||||
|
</q-page-container>
|
||||||
|
</template>
|
|
@ -2,10 +2,12 @@ import Customer from './customer';
|
||||||
import Ticket from './ticket';
|
import Ticket from './ticket';
|
||||||
import Claim from './claim';
|
import Claim from './claim';
|
||||||
import InvoiceOut from './invoiceOut';
|
import InvoiceOut from './invoiceOut';
|
||||||
|
import Worker from './worker';
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
Customer,
|
Customer,
|
||||||
Ticket,
|
Ticket,
|
||||||
Claim,
|
Claim,
|
||||||
InvoiceOut
|
InvoiceOut,
|
||||||
|
Worker
|
||||||
]
|
]
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
import { RouterView } from 'vue-router';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
path: '/worker',
|
||||||
|
name: 'Worker',
|
||||||
|
meta: {
|
||||||
|
title: 'workers',
|
||||||
|
icon: 'vn:worker',
|
||||||
|
},
|
||||||
|
component: RouterView,
|
||||||
|
redirect: { name: 'WorkerMain' },
|
||||||
|
menus: {
|
||||||
|
main: ['WorkerList'],
|
||||||
|
card: [],
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
name: 'WorkerMain',
|
||||||
|
component: () => import('src/pages/Worker/WorkerMain.vue'),
|
||||||
|
redirect: { name: 'WorkerList' },
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'list',
|
||||||
|
name: 'WorkerList',
|
||||||
|
meta: {
|
||||||
|
title: 'list',
|
||||||
|
icon: 'view_list',
|
||||||
|
},
|
||||||
|
component: () => import('src/pages/Worker/WorkerList.vue'),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'WorkerCard',
|
||||||
|
path: ':id',
|
||||||
|
component: () => import('src/pages/Worker/Card/WorkerCard.vue'),
|
||||||
|
redirect: { name: 'WorkerSummary' },
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
name: 'WorkerSummary',
|
||||||
|
path: 'summary',
|
||||||
|
meta: {
|
||||||
|
title: 'summary',
|
||||||
|
},
|
||||||
|
component: () => import('src/pages/Worker/Card/WorkerSummary.vue'),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
|
@ -1,6 +1,7 @@
|
||||||
import customer from './modules/customer';
|
import customer from './modules/customer';
|
||||||
import ticket from './modules/ticket';
|
import ticket from './modules/ticket';
|
||||||
import claim from './modules/claim';
|
import claim from './modules/claim';
|
||||||
|
import worker from './modules/worker';
|
||||||
import invoiceOut from './modules/invoiceOut';
|
import invoiceOut from './modules/invoiceOut';
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
|
@ -26,6 +27,7 @@ const routes = [
|
||||||
customer,
|
customer,
|
||||||
ticket,
|
ticket,
|
||||||
claim,
|
claim,
|
||||||
|
worker,
|
||||||
invoiceOut,
|
invoiceOut,
|
||||||
{
|
{
|
||||||
path: '/:catchAll(.*)*',
|
path: '/:catchAll(.*)*',
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { useRole } from 'src/composables/useRole';
|
||||||
import routes from 'src/router/modules';
|
import routes from 'src/router/modules';
|
||||||
|
|
||||||
export const useNavigationStore = defineStore('navigationStore', () => {
|
export const useNavigationStore = defineStore('navigationStore', () => {
|
||||||
const modules = ['customer', 'claim', 'ticket', 'invoiceOut'];
|
const modules = ['customer', 'claim', 'ticket', 'invoiceOut', 'worker'];
|
||||||
const pinnedModules = ref([]);
|
const pinnedModules = ref([]);
|
||||||
const role = useRole();
|
const role = useRole();
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
describe('WorkerList', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
cy.viewport(1280, 720);
|
||||||
|
cy.login('developer');
|
||||||
|
cy.visit('/#/worker/list');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should load workers', () => {
|
||||||
|
cy.get('div[class="q-item__label text-h6"]').eq(0).should('have.text', 'Jessica Jones');
|
||||||
|
cy.get('div[class="q-item__label text-h6"]').eq(1).should('have.text', 'Bruce Banner');
|
||||||
|
cy.get('div[class="q-item__label text-h6"]').eq(2).should('have.text', 'Charles Xavier');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should open the worker summary', () => {
|
||||||
|
cy.get('div[class="q-item__section column q-item__section--side justify-center q-pa-md"]').eq(0).click();
|
||||||
|
cy.get('div[class="header bg-primary q-pa-sm q-mb-md"').should('have.text', '1110 - Jessica Jones');
|
||||||
|
cy.get('div[class="q-item__label q-item__label--header text-h6"]').eq(0).should('have.text', 'Basic data');
|
||||||
|
cy.get('div[class="q-item__label q-item__label--header text-h6"]').eq(1).should('have.text', 'User data');
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,15 @@
|
||||||
|
describe('WorkerSummary', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
cy.viewport(1280, 720)
|
||||||
|
cy.login('developer')
|
||||||
|
cy.visit('/#/worker/19/summary');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should load worker summary', () => {
|
||||||
|
cy.get('div[class="header bg-primary q-pa-sm q-mb-md"').should('have.text', '19 - salesBoss');
|
||||||
|
cy.get('div[class="q-item__label q-item__label--header text-h6"]').eq(0).should('have.text', 'Basic data');
|
||||||
|
cy.get('div[class="q-item__label q-item__label--header text-h6"]').eq(1).should('have.text', 'User data');
|
||||||
|
cy.get('div[class="q-item__section column q-item__section--main justify-center"]').eq(0).should('have.text', 'NamesalesBossNick');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
Loading…
Reference in New Issue