0
0
Fork 0

Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix-front into 5186-CreateParkingSection

This commit is contained in:
Jorge Penadés 2024-03-14 08:54:21 +01:00
commit 0c012ed71a
44 changed files with 474 additions and 146 deletions

View File

@ -1,5 +1,5 @@
<script setup> <script setup>
import { reactive, ref } from 'vue'; import { reactive, ref, onMounted, nextTick } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import VnInput from 'src/components/common/VnInput.vue'; import VnInput from 'src/components/common/VnInput.vue';
@ -16,9 +16,8 @@ const props = defineProps({
}); });
const emit = defineEmits(['onDataSaved']); const emit = defineEmits(['onDataSaved']);
const { t } = useI18n(); const { t } = useI18n();
const bicInputRef = ref(null);
const bankEntityFormData = reactive({ const bankEntityFormData = reactive({
name: null, name: null,
bic: null, bic: null,
@ -32,9 +31,14 @@ const countriesFilter = {
const countriesOptions = ref([]); const countriesOptions = ref([]);
const onDataSaved = (data) => { const onDataSaved = (formData, requestResponse) => {
emit('onDataSaved', data); emit('onDataSaved', formData, requestResponse);
}; };
onMounted(async () => {
await nextTick();
bicInputRef.value.focus();
});
</script> </script>
<template> <template>
@ -50,7 +54,7 @@ const onDataSaved = (data) => {
:title="t('title')" :title="t('title')"
:subtitle="t('subtitle')" :subtitle="t('subtitle')"
:form-initial-data="bankEntityFormData" :form-initial-data="bankEntityFormData"
@on-data-saved="onDataSaved($event)" @on-data-saved="onDataSaved"
> >
<template #form-inputs="{ data, validate }"> <template #form-inputs="{ data, validate }">
<VnRow class="row q-gutter-md q-mb-md"> <VnRow class="row q-gutter-md q-mb-md">
@ -64,6 +68,7 @@ const onDataSaved = (data) => {
</div> </div>
<div class="col"> <div class="col">
<VnInput <VnInput
ref="bicInputRef"
:label="t('swift')" :label="t('swift')"
v-model="data.bic" v-model="data.bic"
:required="true" :required="true"

View File

@ -10,6 +10,7 @@ import { useValidator } from 'src/composables/useValidator';
import useNotify from 'src/composables/useNotify.js'; import useNotify from 'src/composables/useNotify.js';
import SkeletonForm from 'components/ui/SkeletonForm.vue'; import SkeletonForm from 'components/ui/SkeletonForm.vue';
import VnConfirm from './ui/VnConfirm.vue'; import VnConfirm from './ui/VnConfirm.vue';
import { tMobile } from 'src/composables/tMobile';
const quasar = useQuasar(); const quasar = useQuasar();
const state = useState(); const state = useState();
@ -43,6 +44,10 @@ const $props = defineProps({
type: Boolean, type: Boolean,
default: true, default: true,
}, },
defaultButtons: {
type: Object,
default: () => {},
},
autoLoad: { autoLoad: {
type: Boolean, type: Boolean,
default: false, default: false,
@ -61,6 +66,10 @@ const $props = defineProps({
type: Function, type: Function,
default: null, default: null,
}, },
clearStoreOnUnmount: {
type: Boolean,
default: true,
},
saveFn: { saveFn: {
type: Function, type: Function,
default: null, default: null,
@ -109,7 +118,12 @@ onBeforeRouteLeave((to, from, next) => {
}); });
onUnmounted(() => { onUnmounted(() => {
state.unset($props.model); // Restauramos los datos originales en el store si se realizaron cambios en el formulario pero no se guardaron, evitando modificaciones erróneas.
if (hasChanges.value) {
state.set($props.model, originalData.value);
return;
}
if ($props.clearStoreOnUnmount) state.unset($props.model);
}); });
const isLoading = ref(false); const isLoading = ref(false);
@ -119,7 +133,19 @@ const hasChanges = ref(!$props.observeFormChanges);
const originalData = ref({ ...$props.formInitialData }); const originalData = ref({ ...$props.formInitialData });
const formData = computed(() => state.get($props.model)); const formData = computed(() => state.get($props.model));
const formUrl = computed(() => $props.url); const formUrl = computed(() => $props.url);
const defaultButtons = computed(() => ({
save: {
color: 'primary',
icon: 'restart_alt',
label: 'globals.save',
},
reset: {
color: 'primary',
icon: 'save',
label: 'globals.reset',
},
...$props.defaultButtons,
}));
const startFormWatcher = () => { const startFormWatcher = () => {
watch( watch(
() => formData.value, () => formData.value,
@ -131,10 +157,6 @@ const startFormWatcher = () => {
); );
}; };
function tMobile(...args) {
if (!quasar.platform.is.mobile) return t(...args);
}
async function fetch() { async function fetch() {
const { data } = await axios.get($props.url, { const { data } = await axios.get($props.url, {
params: { filter: JSON.stringify($props.filter) }, params: { filter: JSON.stringify($props.filter) },
@ -233,21 +255,21 @@ watch(formUrl, async () => {
<QBtnGroup push class="q-gutter-x-sm"> <QBtnGroup push class="q-gutter-x-sm">
<slot name="moreActions" /> <slot name="moreActions" />
<QBtn <QBtn
:label="tMobile('globals.reset')" :label="tMobile(defaultButtons.reset.label)"
color="primary" :color="defaultButtons.reset.color"
icon="restart_alt" :icon="defaultButtons.reset.icon"
flat flat
@click="reset" @click="reset"
:disable="!hasChanges" :disable="!hasChanges"
:title="t('globals.reset')" :title="t(defaultButtons.reset.label)"
/> />
<QBtn <QBtn
:label="tMobile('globals.save')" :label="tMobile(defaultButtons.save.label)"
color="primary" :color="defaultButtons.save.color"
icon="save" :icon="defaultButtons.save.icon"
@click="save" @click="save"
:disable="!hasChanges" :disable="!hasChanges"
:title="t('globals.save')" :title="t(defaultButtons.save.label)"
/> />
</QBtnGroup> </QBtnGroup>
</div> </div>

View File

@ -42,8 +42,8 @@ const { t } = useI18n();
const closeButton = ref(null); const closeButton = ref(null);
const isLoading = ref(false); const isLoading = ref(false);
const onDataSaved = (dataSaved) => { const onDataSaved = (formData, requestResponse) => {
emit('onDataSaved', dataSaved); emit('onDataSaved', formData, requestResponse);
closeForm(); closeForm();
}; };
@ -59,7 +59,7 @@ const closeForm = () => {
:default-actions="false" :default-actions="false"
:url-create="urlCreate" :url-create="urlCreate"
:model="model" :model="model"
@on-data-saved="onDataSaved($event)" @on-data-saved="onDataSaved"
> >
<template #form="{ data, validate }"> <template #form="{ data, validate }">
<span ref="closeButton" class="close-icon" v-close-popup> <span ref="closeButton" class="close-icon" v-close-popup>

View File

@ -1,5 +1,5 @@
<script setup> <script setup>
import { computed } from 'vue'; import { computed, ref } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
const emit = defineEmits(['update:modelValue', 'update:options', 'keyup.enter']); const emit = defineEmits(['update:modelValue', 'update:options', 'keyup.enter']);
@ -17,7 +17,7 @@ const $props = defineProps({
const { t } = useI18n(); const { t } = useI18n();
const requiredFieldRule = (val) => !!val || t('globals.fieldRequired'); const requiredFieldRule = (val) => !!val || t('globals.fieldRequired');
const vnInputRef = ref(null);
const value = computed({ const value = computed({
get() { get() {
return $props.modelValue; return $props.modelValue;
@ -40,6 +40,14 @@ const styleAttrs = computed(() => {
const onEnterPress = () => { const onEnterPress = () => {
emit('keyup.enter'); emit('keyup.enter');
}; };
const focus = () => {
vnInputRef.value.focus();
};
defineExpose({
focus,
});
</script> </script>
<template> <template>

View File

@ -59,6 +59,9 @@ const toggleForm = () => {
:name="actionIcon" :name="actionIcon"
:size="actionIcon === 'add' ? 'xs' : 'sm'" :size="actionIcon === 'add' ? 'xs' : 'sm'"
:class="['default-icon', { '--add-icon': actionIcon === 'add' }]" :class="['default-icon', { '--add-icon': actionIcon === 'add' }]"
:style="{
'font-variation-settings': `'FILL' ${1}`,
}"
> >
<QTooltip v-if="tooltip">{{ tooltip }}</QTooltip> <QTooltip v-if="tooltip">{{ tooltip }}</QTooltip>
</QIcon> </QIcon>

View File

@ -4,6 +4,7 @@ import { useI18n } from 'vue-i18n';
import SkeletonDescriptor from 'components/ui/SkeletonDescriptor.vue'; import SkeletonDescriptor from 'components/ui/SkeletonDescriptor.vue';
import { useArrayData } from 'composables/useArrayData'; import { useArrayData } from 'composables/useArrayData';
import { useSummaryDialog } from 'src/composables/useSummaryDialog'; import { useSummaryDialog } from 'src/composables/useSummaryDialog';
import { useState } from 'src/composables/useState';
const $props = defineProps({ const $props = defineProps({
url: { url: {
@ -35,6 +36,8 @@ const $props = defineProps({
default: null, default: null,
}, },
}); });
const state = useState();
const slots = useSlots(); const slots = useSlots();
const { t } = useI18n(); const { t } = useI18n();
const { viewSummary } = useSummaryDialog(); const { viewSummary } = useSummaryDialog();
@ -64,6 +67,7 @@ async function getData() {
isLoading.value = true; isLoading.value = true;
try { try {
const { data } = await arrayData.fetch({ append: false, updateRouter: false }); const { data } = await arrayData.fetch({ append: false, updateRouter: false });
state.set($props.dataKey, data);
emit('onFetch', data); emit('onFetch', data);
} finally { } finally {
isLoading.value = false; isLoading.value = false;

View File

@ -1,11 +1,10 @@
<script setup> <script setup>
import { onMounted, ref, watch } from 'vue'; import { onMounted, ref, watch } from 'vue';
import { useRoute } from 'vue-router';
import axios from 'axios'; import axios from 'axios';
import SkeletonSummary from 'components/ui/SkeletonSummary.vue'; import SkeletonSummary from 'components/ui/SkeletonSummary.vue';
import VnLv from 'src/components/ui/VnLv.vue'; import VnLv from 'src/components/ui/VnLv.vue';
onMounted(() => fetch());
const entity = ref(); const entity = ref();
const props = defineProps({ const props = defineProps({
url: { url: {
@ -16,14 +15,25 @@ const props = defineProps({
type: Object, type: Object,
default: null, default: null,
}, },
entityId: {
type: Number,
default: null,
},
}); });
const emit = defineEmits(['onFetch']); const emit = defineEmits(['onFetch']);
const route = useRoute();
const isSummary = ref();
defineExpose({ defineExpose({
entity, entity,
fetch, fetch,
}); });
onMounted(() => {
isSummary.value = String(route.path).endsWith('/summary');
fetch();
});
async function fetch() { async function fetch() {
const params = {}; const params = {};
@ -48,7 +58,17 @@ watch(props, async () => {
<template v-if="entity"> <template v-if="entity">
<div class="summaryHeader bg-primary q-pa-sm text-weight-bolder"> <div class="summaryHeader bg-primary q-pa-sm text-weight-bolder">
<slot name="header-left"> <slot name="header-left">
<span></span> <router-link
v-if="!isSummary && route.meta.moduleName"
class="header link"
:to="{
name: `${route.meta.moduleName}Summary`,
params: { id: entityId || entity.id },
}"
>
<QIcon name="open_in_new" color="white" size="sm" />
</router-link>
<span v-else></span>
</slot> </slot>
<slot name="header" :entity="entity"> <slot name="header" :entity="entity">
<VnLv :label="`${entity.id} -`" :value="entity.name" /> <VnLv :label="`${entity.id} -`" :value="entity.name" />

View File

@ -118,7 +118,12 @@ async function search() {
autofocus autofocus
> >
<template #prepend> <template #prepend>
<QIcon name="search" v-if="!quasar.platform.is.mobile" /> <QIcon
v-if="!quasar.platform.is.mobile"
class="cursor-pointer"
name="search"
@click="search"
/>
</template> </template>
<template #append> <template #append>
<QIcon <QIcon

View File

@ -97,6 +97,11 @@ select:-webkit-autofill {
background-color: var(--vn-light-gray); background-color: var(--vn-light-gray);
} }
.vn-table-separation-row {
height: 16px !important;
background-color: var(--vn-gray) !important;
}
/* Estilo para el asterisco en campos requeridos */ /* Estilo para el asterisco en campos requeridos */
.q-field.required .q-field__label:after { .q-field.required .q-field__label:after {
content: ' *'; content: ' *';

View File

@ -31,6 +31,7 @@ export default {
close: 'Close', close: 'Close',
cancel: 'Cancel', cancel: 'Cancel',
confirm: 'Confirm', confirm: 'Confirm',
assign: 'Assign',
back: 'Back', back: 'Back',
yes: 'Yes', yes: 'Yes',
no: 'No', no: 'No',
@ -854,6 +855,7 @@ export default {
notifications: 'Notifications', notifications: 'Notifications',
workerCreate: 'New worker', workerCreate: 'New worker',
department: 'Department', department: 'Department',
pda: 'PDA',
}, },
list: { list: {
name: 'Name', name: 'Name',
@ -895,6 +897,13 @@ export default {
subscribed: 'Subscribed to the notification', subscribed: 'Subscribed to the notification',
unsubscribed: 'Unsubscribed from the notification', unsubscribed: 'Unsubscribed from the notification',
}, },
pda: {
newPDA: 'New PDA',
currentPDA: 'Current PDA',
model: 'Model',
serialNumber: 'Serial number',
removePDA: 'Deallocate PDA',
},
create: { create: {
name: 'Name', name: 'Name',
lastName: 'Last name', lastName: 'Last name',

View File

@ -31,6 +31,7 @@ export default {
close: 'Cerrar', close: 'Cerrar',
cancel: 'Cancelar', cancel: 'Cancelar',
confirm: 'Confirmar', confirm: 'Confirmar',
assign: 'Asignar',
back: 'Volver', back: 'Volver',
yes: 'Si', yes: 'Si',
no: 'No', no: 'No',
@ -315,8 +316,8 @@ export default {
reference: 'Referencia', reference: 'Referencia',
invoiceNumber: 'Núm. factura', invoiceNumber: 'Núm. factura',
ordered: 'Pedida', ordered: 'Pedida',
confirmed: 'Confirmado', confirmed: 'Confirmada',
booked: 'Asentado', booked: 'Contabilizada',
raid: 'Redada', raid: 'Redada',
excludedFromAvailable: 'Inventario', excludedFromAvailable: 'Inventario',
travelReference: 'Referencia', travelReference: 'Referencia',
@ -853,6 +854,7 @@ export default {
notifications: 'Notificaciones', notifications: 'Notificaciones',
workerCreate: 'Nuevo trabajador', workerCreate: 'Nuevo trabajador',
department: 'Departamentos', department: 'Departamentos',
pda: 'PDA',
}, },
list: { list: {
name: 'Nombre', name: 'Nombre',
@ -894,6 +896,13 @@ export default {
subscribed: 'Se ha suscrito a la notificación', subscribed: 'Se ha suscrito a la notificación',
unsubscribed: 'Se ha dado de baja de la notificación', unsubscribed: 'Se ha dado de baja de la notificación',
}, },
pda: {
newPDA: 'Nueva PDA',
currentPDA: 'PDA Actual',
model: 'Modelo',
serialNumber: 'Número de serie',
removePDA: 'Desasignar PDA',
},
create: { create: {
name: 'Nombre', name: 'Nombre',
lastName: 'Apellido', lastName: 'Apellido',

View File

@ -172,6 +172,7 @@ function openDialog(dmsId) {
<CardSummary <CardSummary
ref="summary" ref="summary"
:url="`Claims/${entityId}/getSummary`" :url="`Claims/${entityId}/getSummary`"
:entity-id="entityId"
@on-fetch="getClaimDms" @on-fetch="getClaimDms"
> >
<template #header="{ entity: { claim } }"> <template #header="{ entity: { claim } }">

View File

@ -61,6 +61,7 @@ const onFilterTravelSelected = (formData, id) => {
:url-update="`Entries/${route.params.id}`" :url-update="`Entries/${route.params.id}`"
model="entry" model="entry"
auto-load auto-load
:clear-store-on-unmount="false"
> >
<template #form="{ data }"> <template #form="{ data }">
<VnRow class="row q-gutter-md q-mb-md"> <VnRow class="row q-gutter-md q-mb-md">

View File

@ -43,7 +43,7 @@ const tableColumnComponents = computed(() => ({
item: { item: {
component: QBtn, component: QBtn,
props: { props: {
color: 'blue', color: 'primary',
flat: true, flat: true,
}, },
event: () => ({}), event: () => ({}),
@ -54,6 +54,7 @@ const tableColumnComponents = computed(() => ({
type: 'number', type: 'number',
min: 0, min: 0,
class: 'input-number', class: 'input-number',
dense: true,
}, },
event: getInputEvents, event: getInputEvents,
}, },
@ -67,6 +68,7 @@ const tableColumnComponents = computed(() => ({
'use-input': true, 'use-input': true,
'hide-selected': true, 'hide-selected': true,
options: packagingsOptions.value, options: packagingsOptions.value,
dense: true,
}, },
event: getInputEvents, event: getInputEvents,
}, },
@ -76,6 +78,7 @@ const tableColumnComponents = computed(() => ({
type: 'number', type: 'number',
min: 0, min: 0,
class: 'input-number', class: 'input-number',
dense: true,
}, },
event: getInputEvents, event: getInputEvents,
}, },
@ -84,6 +87,7 @@ const tableColumnComponents = computed(() => ({
props: { props: {
type: 'number', type: 'number',
min: 0, min: 0,
dense: true,
}, },
event: getInputEvents, event: getInputEvents,
}, },
@ -92,6 +96,7 @@ const tableColumnComponents = computed(() => ({
props: { props: {
type: 'number', type: 'number',
min: 0, min: 0,
dense: true,
}, },
event: getInputEvents, event: getInputEvents,
}, },
@ -100,6 +105,7 @@ const tableColumnComponents = computed(() => ({
props: { props: {
type: 'number', type: 'number',
min: 0, min: 0,
dense: true,
}, },
event: getInputEvents, event: getInputEvents,
}, },
@ -108,6 +114,7 @@ const tableColumnComponents = computed(() => ({
props: { props: {
type: 'number', type: 'number',
min: 0, min: 0,
dense: true,
}, },
event: getInputEvents, event: getInputEvents,
}, },
@ -116,6 +123,7 @@ const tableColumnComponents = computed(() => ({
props: { props: {
type: 'number', type: 'number',
min: 0, min: 0,
dense: true,
}, },
event: getInputEvents, event: getInputEvents,
}, },
@ -124,6 +132,7 @@ const tableColumnComponents = computed(() => ({
props: { props: {
type: 'number', type: 'number',
min: 0, min: 0,
dense: true,
}, },
event: getInputEvents, event: getInputEvents,
}, },
@ -276,7 +285,7 @@ const toggleGroupingMode = async (buy, mode) => {
} }
}; };
const showLockIcon = (groupingMode, mode) => { const lockIconType = (groupingMode, mode) => {
if (mode === 'packing') { if (mode === 'packing') {
return groupingMode === 2 ? 'lock' : 'lock_open'; return groupingMode === 2 ? 'lock' : 'lock_open';
} else { } else {
@ -320,17 +329,21 @@ const showLockIcon = (groupingMode, mode) => {
:columns="entriesTableColumns" :columns="entriesTableColumns"
selection="multiple" selection="multiple"
row-key="id" row-key="id"
hide-bottom
class="full-width q-mt-md" class="full-width q-mt-md"
:grid="$q.screen.lt.md" :grid="$q.screen.lt.md"
v-model:selected="rowsSelected" v-model:selected="rowsSelected"
:no-data-label="t('globals.noResults')"
> >
<template #body="props"> <template #body="props">
<QTr> <QTr>
<QTd> <QTd>
<QCheckbox v-model="props.selected" /> <QCheckbox v-model="props.selected" />
</QTd> </QTd>
<QTd v-for="col in props.cols" :key="col.name"> <QTd
v-for="col in props.cols"
:key="col.name"
style="max-width: 100px"
>
<component <component
:is="tableColumnComponents[col.name].component" :is="tableColumnComponents[col.name].component"
v-bind="tableColumnComponents[col.name].props" v-bind="tableColumnComponents[col.name].props"
@ -350,7 +363,7 @@ const showLockIcon = (groupingMode, mode) => {
> >
<QBtn <QBtn
:icon=" :icon="
showLockIcon(props.row.groupingMode, col.name) lockIconType(props.row.groupingMode, col.name)
" "
@click="toggleGroupingMode(props.row, col.name)" @click="toggleGroupingMode(props.row, col.name)"
class="cursor-pointer" class="cursor-pointer"
@ -359,6 +372,16 @@ const showLockIcon = (groupingMode, mode) => {
dense dense
unelevated unelevated
push push
:style="{
'font-variation-settings': `'FILL' ${
lockIconType(
props.row.groupingMode,
col.name
) === 'lock'
? 1
: 0
}`,
}"
/> />
</template> </template>
<template <template
@ -397,7 +420,7 @@ const showLockIcon = (groupingMode, mode) => {
</QTr> </QTr>
<!-- Esta última row es utilizada para agregar un espaciado y así marcar una diferencia visual entre los diferentes buys --> <!-- Esta última row es utilizada para agregar un espaciado y así marcar una diferencia visual entre los diferentes buys -->
<QTr v-if="props.rowIndex !== rows.length - 1" class="separation-row"> <QTr v-if="props.rowIndex !== rows.length - 1" class="separation-row">
<QTd colspan="12" style="height: 24px" /> <QTd colspan="12" class="vn-table-separation-row" />
</QTr> </QTr>
</template> </template>
<template #item="props"> <template #item="props">
@ -448,9 +471,6 @@ const showLockIcon = (groupingMode, mode) => {
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
.separation-row {
background-color: var(--vn-gray) !important;
}
.grid-style-transition { .grid-style-transition {
transition: transform 0.28s, background-color 0.28s; transition: transform 0.28s, background-color 0.28s;
} }

View File

@ -1,5 +1,5 @@
<script setup> <script setup>
import { ref, computed } from 'vue'; import { ref, computed, watch } from 'vue';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
@ -7,6 +7,7 @@ import CardDescriptor from 'components/ui/CardDescriptor.vue';
import VnLv from 'src/components/ui/VnLv.vue'; import VnLv from 'src/components/ui/VnLv.vue';
import useCardDescription from 'src/composables/useCardDescription'; import useCardDescription from 'src/composables/useCardDescription';
import { useState } from 'src/composables/useState';
import { toDate } from 'src/filters'; import { toDate } from 'src/filters';
import { usePrintService } from 'composables/usePrintService'; import { usePrintService } from 'composables/usePrintService';
@ -25,6 +26,8 @@ const $props = defineProps({
const route = useRoute(); const route = useRoute();
const { t } = useI18n(); const { t } = useI18n();
const { openReport } = usePrintService(); const { openReport } = usePrintService();
const state = useState();
const entryDescriptorRef = ref(null);
const entryFilter = { const entryFilter = {
include: [ include: [
@ -71,6 +74,8 @@ const data = ref(useCardDescription());
const setData = (entity) => const setData = (entity) =>
(data.value = useCardDescription(entity.supplier.nickname, entity.id)); (data.value = useCardDescription(entity.supplier.nickname, entity.id));
const currentEntry = computed(() => state.get('entry'));
const getEntryRedirectionFilter = (entry) => { const getEntryRedirectionFilter = (entry) => {
let entryTravel = entry && entry.travel; let entryTravel = entry && entry.travel;
@ -95,17 +100,20 @@ const getEntryRedirectionFilter = (entry) => {
const showEntryReport = () => { const showEntryReport = () => {
openReport(`Entries/${route.params.id}/entry-order-pdf`); openReport(`Entries/${route.params.id}/entry-order-pdf`);
}; };
watch;
</script> </script>
<template> <template>
<CardDescriptor <CardDescriptor
ref="entryDescriptorRef"
module="Entry" module="Entry"
:url="`Entries/${entityId}`" :url="`Entries/${entityId}`"
:filter="entryFilter" :filter="entryFilter"
:title="data.title" :title="data.title"
:subtitle="data.subtitle" :subtitle="data.subtitle"
@on-fetch="setData" @on-fetch="setData"
data-key="entryData" data-key="entry"
> >
<template #menu="{ entity }"> <template #menu="{ entity }">
<QItem v-ripple clickable @click="showEntryReport(entity)"> <QItem v-ripple clickable @click="showEntryReport(entity)">
@ -126,17 +134,17 @@ const showEntryReport = () => {
:value="entity.travel?.warehouseOut?.name" :value="entity.travel?.warehouseOut?.name"
/> />
</template> </template>
<template #icons="{ entity }"> <template #icons>
<QCardActions class="q-gutter-x-md"> <QCardActions class="q-gutter-x-md">
<QIcon <QIcon
v-if="entity.isExcludedFromAvailable" v-if="currentEntry.isExcludedFromAvailable"
name="vn:inventory" name="vn:inventory"
color="primary" color="primary"
size="xs" size="xs"
> >
<QTooltip>{{ t('Inventory entry') }}</QTooltip> <QTooltip>{{ t('Inventory entry') }}</QTooltip>
</QIcon> </QIcon>
<QIcon v-if="entity.isRaid" name="vn:web" color="primary" size="xs"> <QIcon v-if="currentEntry.isRaid" name="vn:net" color="primary" size="xs">
<QTooltip>{{ t('Virtual entry') }}</QTooltip> <QTooltip>{{ t('Virtual entry') }}</QTooltip>
</QIcon> </QIcon>
</QCardActions> </QCardActions>

View File

@ -165,20 +165,27 @@ const fetchEntryBuys = async () => {
@on-fetch="(data) => setEntryData(data)" @on-fetch="(data) => setEntryData(data)"
> >
<template #header-left> <template #header-left>
<a class="header-link" :href="entryUrl"> <router-link
v-if="route.name !== 'EntrySummary'"
:to="{ name: 'EntrySummary', params: { id: entityId } }"
class="header link"
:href="entryUrl"
>
<QIcon name="open_in_new" color="white" size="sm" /> <QIcon name="open_in_new" color="white" size="sm" />
</a> </router-link>
</template> </template>
<template #header> <template #header>
<span>{{ entry.id }} - {{ entry.supplier.nickname }}</span> <span>{{ entry.id }} - {{ entry.supplier.nickname }}</span>
</template> </template>
<template #body> <template #body>
<QCard class="vn-one"> <QCard class="vn-one">
<a class="header header-link" :href="`#/entry/${entityId}/basic-data`"> <router-link
:to="{ name: 'EntryBasicData', params: { id: entityId } }"
class="header header-link"
>
{{ t('globals.summary.basicData') }} {{ t('globals.summary.basicData') }}
<QIcon name="open_in_new" /> <QIcon name="open_in_new" />
</a> </router-link>
<VnLv :label="t('entry.summary.commission')" :value="entry.commission" /> <VnLv :label="t('entry.summary.commission')" :value="entry.commission" />
@ -192,37 +199,15 @@ const fetchEntryBuys = async () => {
:label="t('entry.summary.invoiceNumber')" :label="t('entry.summary.invoiceNumber')"
:value="entry.invoiceNumber" :value="entry.invoiceNumber"
/> />
<QCheckbox
:label="t('entry.summary.ordered')"
v-model="entry.isOrdered"
:disable="true"
/>
<QCheckbox
:label="t('entry.summary.confirmed')"
v-model="entry.isConfirmed"
:disable="true"
/>
<QCheckbox
:label="t('entry.summary.booked')"
v-model="entry.isBooked"
:disable="true"
/>
<QCheckbox
:label="t('entry.summary.raid')"
v-model="entry.isRaid"
:disable="true"
/>
<QCheckbox
:label="t('entry.summary.excludedFromAvailable')"
v-model="entry.isExcludedFromAvailable"
:disable="true"
/>
</QCard> </QCard>
<QCard class="vn-one"> <QCard class="vn-one">
<a class="header header-link" :href="entryUrl"> <router-link
{{ t('Travel data') }} :to="{ name: 'EntryBasicData', params: { id: entityId } }"
class="header header-link"
>
{{ t('globals.summary.basicData') }}
<QIcon name="open_in_new" /> <QIcon name="open_in_new" />
</a> </router-link>
<VnLv :label="t('entry.summary.travelReference')"> <VnLv :label="t('entry.summary.travelReference')">
<template #value> <template #value>
@ -250,7 +235,7 @@ const fetchEntryBuys = async () => {
<QCheckbox <QCheckbox
:label="t('entry.summary.travelDelivered')" :label="t('entry.summary.travelDelivered')"
v-model="entry.isDelivered" v-model="entry.travel.isDelivered"
:disable="true" :disable="true"
/> />
<VnLv <VnLv
@ -265,7 +250,41 @@ const fetchEntryBuys = async () => {
<QCheckbox <QCheckbox
:label="t('entry.summary.travelReceived')" :label="t('entry.summary.travelReceived')"
v-model="entry.isReceived" v-model="entry.travel.isReceived"
:disable="true"
/>
</QCard>
<QCard class="vn-one">
<router-link
:to="{ name: 'TravelSummary', params: { id: entry.travel.id } }"
class="header header-link"
>
{{ t('Travel data') }}
<QIcon name="open_in_new" />
</router-link>
<QCheckbox
:label="t('entry.summary.ordered')"
v-model="entry.isOrdered"
:disable="true"
/>
<QCheckbox
:label="t('entry.summary.confirmed')"
v-model="entry.isConfirmed"
:disable="true"
/>
<QCheckbox
:label="t('entry.summary.booked')"
v-model="entry.isBooked"
:disable="true"
/>
<QCheckbox
:label="t('entry.summary.raid')"
v-model="entry.isRaid"
:disable="true"
/>
<QCheckbox
:label="t('entry.summary.excludedFromAvailable')"
v-model="entry.isExcludedFromAvailable"
:disable="true" :disable="true"
/> />
</QCard> </QCard>
@ -277,9 +296,9 @@ const fetchEntryBuys = async () => {
<QTable <QTable
:rows="entryBuys" :rows="entryBuys"
:columns="entriesTableColumns" :columns="entriesTableColumns"
hide-bottom
row-key="index" row-key="index"
class="full-width q-mt-md" class="full-width q-mt-md"
:no-data-label="t('globals.noResults')"
> >
<template #body="{ cols, row, rowIndex }"> <template #body="{ cols, row, rowIndex }">
<QTr no-hover> <QTr no-hover>
@ -325,11 +344,8 @@ const fetchEntryBuys = async () => {
</QTd> </QTd>
</QTr> </QTr>
<!-- Esta última row es utilizada para agregar un espaciado y así marcar una diferencia visual entre los diferentes buys --> <!-- Esta última row es utilizada para agregar un espaciado y así marcar una diferencia visual entre los diferentes buys -->
<QTr <QTr v-if="rowIndex !== entryBuys.length - 1">
v-if="rowIndex !== entryBuys.length - 1" <QTd colspan="10" class="vn-table-separation-row" />
class="separation-row"
>
<QTd colspan="10" style="height: 24px" />
</QTr> </QTr>
</template> </template>
</QTable> </QTable>
@ -338,13 +354,7 @@ const fetchEntryBuys = async () => {
</CardSummary> </CardSummary>
</template> </template>
<style lang="scss" scoped>
.separation-row {
background-color: var(--vn-gray) !important;
}
</style>
<i18n> <i18n>
es: es:
Travel data: 'Datos envío' Travel data: Datos envío
</i18n> </i18n>

View File

@ -74,7 +74,7 @@ onMounted(async () => {
</QIcon> </QIcon>
<QIcon <QIcon
v-if="row.isRaid" v-if="row.isRaid"
name="vn:web" name="vn:net"
color="primary" color="primary"
size="xs" size="xs"
> >

View File

@ -95,7 +95,11 @@ const ticketsColumns = ref([
</script> </script>
<template> <template>
<CardSummary ref="summary" :url="`InvoiceOuts/${entityId}/summary`"> <CardSummary
ref="summary"
:url="`InvoiceOuts/${entityId}/summary`"
:entity-id="entityId"
>
<template #header="{ entity: { invoiceOut } }"> <template #header="{ entity: { invoiceOut } }">
<div>{{ invoiceOut.ref }} - {{ invoiceOut.client?.socialName }}</div> <div>{{ invoiceOut.ref }} - {{ invoiceOut.client?.socialName }}</div>
</template> </template>

View File

@ -132,12 +132,11 @@ const openBuscaman = async (route, ticket) => {
<template> <template>
<div class="q-pa-md"> <div class="q-pa-md">
<CardSummary ref="summary" :url="`Routes/${entityId}/summary`"> <CardSummary
<template #header-left> ref="summary"
<RouterLink :to="{ name: `RouteSummary`, params: { id: entityId } }"> :url="`Routes/${entityId}/summary`"
<QIcon name="open_in_new" color="white" size="sm" /> :entity-id="entityId"
</RouterLink> >
</template>
<template #header="{ entity }"> <template #header="{ entity }">
<span>{{ `${entity?.route.id} - ${entity?.route?.description}` }}</span> <span>{{ `${entity?.route.id} - ${entity?.route?.description}` }}</span>
</template> </template>

View File

@ -91,6 +91,24 @@ function downloadPdfs() {
} }
</script> </script>
<template> <template>
<template v-if="stateStore.isHeaderMounted()">
<Teleport to="#actions-append">
<div class="row q-gutter-x-sm">
<QBtn
flat
@click="stateStore.toggleRightDrawer()"
round
dense
icon="menu"
>
<QTooltip bottom anchor="bottom right">
{{ t('globals.collapseMenu') }}
</QTooltip>
</QBtn>
</div>
</Teleport>
</template>
<div class="column items-center"> <div class="column items-center">
<div class="list"> <div class="list">
<VnPaginate <VnPaginate

View File

@ -18,13 +18,16 @@ const quasar = useQuasar();
const { notify } = useNotify(); const { notify } = useNotify();
const route = useRoute(); const route = useRoute();
const { t } = useI18n(); const { t } = useI18n();
const bankEntitiesRef = ref(null);
const supplier = ref(null); const supplier = ref(null);
const supplierAccountRef = ref(null); const supplierAccountRef = ref(null);
const wireTransferFk = ref(null); const wireTransferFk = ref(null);
const bankEntitiesOptions = ref([]); const bankEntitiesOptions = ref([]);
const onBankEntityCreated = (data) => { const onBankEntityCreated = async (dataSaved, rowData) => {
bankEntitiesOptions.value.push(data); await bankEntitiesRef.value.fetch();
rowData.bankEntityFk = dataSaved.id;
}; };
const onChangesSaved = () => { const onChangesSaved = () => {
@ -63,6 +66,7 @@ onMounted(() => {
</script> </script>
<template> <template>
<FetchData <FetchData
ref="bankEntitiesRef"
url="BankEntities" url="BankEntities"
@on-fetch="(data) => (bankEntitiesOptions = data)" @on-fetch="(data) => (bankEntitiesOptions = data)"
auto-load auto-load
@ -114,13 +118,16 @@ onMounted(() => {
:label="t('worker.create.bankEntity')" :label="t('worker.create.bankEntity')"
v-model="row.bankEntityFk" v-model="row.bankEntityFk"
:options="bankEntitiesOptions" :options="bankEntitiesOptions"
option-label="name" option-label="bic"
option-value="id" option-value="id"
hide-selected hide-selected
> >
<template #form> <template #form>
<CreateBankEntityForm <CreateBankEntityForm
@on-data-saved="onBankEntityCreated($event)" @on-data-saved="
(_, requestResponse) =>
onBankEntityCreated(requestResponse, row)
"
:show-entity-field="false" :show-entity-field="false"
/> />
</template> </template>

View File

@ -83,8 +83,13 @@ const redirectToUpdateView = (addressData) => {
<QPageSticky :offset="[20, 20]"> <QPageSticky :offset="[20, 20]">
<QBtn fab icon="add" color="primary" @click="redirectToCreateView()" /> <QBtn fab icon="add" color="primary" @click="redirectToCreateView()" />
<QTooltip> <QTooltip>
{{ t('supplier.list.newSupplier') }} {{ t('New address') }}
</QTooltip> </QTooltip>
</QPageSticky> </QPageSticky>
</QPage> </QPage>
</template> </template>
<i18n>
es:
New address: Nueva dirección
</i18n>

View File

@ -26,6 +26,7 @@ const workersOptions = ref([]);
:url-update="`Suppliers/${route.params.id}`" :url-update="`Suppliers/${route.params.id}`"
model="supplier" model="supplier"
auto-load auto-load
:clear-store-on-unmount="false"
> >
<template #form="{ data, validate }"> <template #form="{ data, validate }">
<VnRow class="row q-gutter-md q-mb-md"> <VnRow class="row q-gutter-md q-mb-md">

View File

@ -33,6 +33,7 @@ const formatPayDems = (data) => {
:url-update="`Suppliers/${route.params.id}`" :url-update="`Suppliers/${route.params.id}`"
model="supplier" model="supplier"
auto-load auto-load
:clear-store-on-unmount="false"
> >
<template #form="{ data, validate }"> <template #form="{ data, validate }">
<VnRow class="row q-gutter-md q-mb-md"> <VnRow class="row q-gutter-md q-mb-md">

View File

@ -1,5 +1,5 @@
<script setup> <script setup>
import { ref, onMounted } from 'vue'; import { ref, onMounted, nextTick } from 'vue';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
@ -11,6 +11,15 @@ const route = useRoute();
const { t } = useI18n(); const { t } = useI18n();
const supplierContactRef = ref(null); const supplierContactRef = ref(null);
const insertRow = () => {
supplierContactRef.value.insert();
nextTick(() => {
const inputs = document.querySelectorAll('[input-name-focusable]');
const lastInput = inputs[inputs.length - 1];
if (lastInput) lastInput.focus();
});
};
onMounted(() => { onMounted(() => {
if (supplierContactRef.value) supplierContactRef.value.reload(); if (supplierContactRef.value) supplierContactRef.value.reload();
}); });
@ -38,6 +47,7 @@ onMounted(() => {
<VnRow class="row q-gutter-md"> <VnRow class="row q-gutter-md">
<div class="col"> <div class="col">
<VnInput <VnInput
input-name-focusable
:label="t('supplier.contacts.name')" :label="t('supplier.contacts.name')"
v-model="row.name" v-model="row.name"
/> />
@ -92,7 +102,7 @@ onMounted(() => {
size="sm" size="sm"
class="cursor-pointer" class="cursor-pointer"
color="primary" color="primary"
@click="supplierContactRef.insert()" @click="insertRow()"
> >
<QTooltip> <QTooltip>
{{ t('Add contact') }} {{ t('Add contact') }}

View File

@ -9,6 +9,7 @@ import VnLv from 'src/components/ui/VnLv.vue';
import { toDateString } from 'src/filters'; import { toDateString } from 'src/filters';
import useCardDescription from 'src/composables/useCardDescription'; import useCardDescription from 'src/composables/useCardDescription';
import { getUrl } from 'src/composables/getUrl'; import { getUrl } from 'src/composables/getUrl';
import { useState } from 'src/composables/useState';
const $props = defineProps({ const $props = defineProps({
id: { id: {
@ -21,6 +22,7 @@ const $props = defineProps({
const route = useRoute(); const route = useRoute();
const { t } = useI18n(); const { t } = useI18n();
const url = ref(); const url = ref();
const state = useState();
const filter = { const filter = {
fields: [ fields: [
@ -71,6 +73,8 @@ const setData = (entity) => {
data.value = useCardDescription(entity.ref, entity.id); data.value = useCardDescription(entity.ref, entity.id);
}; };
const supplier = computed(() => state.get('supplier'));
const getEntryQueryParams = (supplier) => { const getEntryQueryParams = (supplier) => {
if (!supplier) return null; if (!supplier) return null;
@ -101,7 +105,7 @@ const getEntryQueryParams = (supplier) => {
:subtitle="data.subtitle" :subtitle="data.subtitle"
:filter="filter" :filter="filter"
@on-fetch="setData" @on-fetch="setData"
data-key="Supplier" data-key="supplier"
> >
<template #header-extra-action> <template #header-extra-action>
<QBtn <QBtn
@ -133,10 +137,10 @@ const getEntryQueryParams = (supplier) => {
<VnLv :label="t('supplier.summary.payDay')" :value="entity.payDay" /> <VnLv :label="t('supplier.summary.payDay')" :value="entity.payDay" />
<VnLv :label="t('supplier.summary.account')" :value="entity.account" /> <VnLv :label="t('supplier.summary.account')" :value="entity.account" />
</template> </template>
<template #icons="{ entity }"> <template #icons>
<QCardActions class="q-gutter-x-md"> <QCardActions v-if="supplier" class="q-gutter-x-md">
<QIcon <QIcon
v-if="!entity.isActive" v-if="!supplier.isActive"
name="vn:disabled" name="vn:disabled"
color="primary" color="primary"
size="xs" size="xs"
@ -144,7 +148,7 @@ const getEntryQueryParams = (supplier) => {
<QTooltip>{{ t('Inactive supplier') }}</QTooltip> <QTooltip>{{ t('Inactive supplier') }}</QTooltip>
</QIcon> </QIcon>
<QIcon <QIcon
v-if="!entity.isSerious" v-if="!supplier.isSerious"
name="vn:supplierfalse" name="vn:supplierfalse"
color="primary" color="primary"
size="xs" size="xs"
@ -167,6 +171,7 @@ const getEntryQueryParams = (supplier) => {
<QTooltip>{{ t('All entries with current supplier') }}</QTooltip> <QTooltip>{{ t('All entries with current supplier') }}</QTooltip>
</QBtn> </QBtn>
<QBtn <QBtn
v-if="entity.client?.fi"
:to="{ :to="{
name: 'CustomerCard', name: 'CustomerCard',
params: { id: entity.client?.id }, params: { id: entity.client?.id },

View File

@ -53,6 +53,7 @@ function handleLocation(data, location) {
:url-update="`Suppliers/${route.params.id}/updateFiscalData`" :url-update="`Suppliers/${route.params.id}/updateFiscalData`"
model="supplier" model="supplier"
auto-load auto-load
:clear-store-on-unmount="false"
> >
<template #form="{ data, validate }"> <template #form="{ data, validate }">
<VnRow class="row q-gutter-md q-mb-md"> <VnRow class="row q-gutter-md q-mb-md">

View File

@ -51,25 +51,20 @@ const isAdministrative = computed(() => {
:url="`Suppliers/${entityId}/getSummary`" :url="`Suppliers/${entityId}/getSummary`"
@on-fetch="(data) => setData(data)" @on-fetch="(data) => setData(data)"
> >
<template #header-left>
<a v-if="isAdministrative" class="header header-link" :href="supplierUrl">
<QIcon name="open_in_new" color="white" size="sm" />
</a>
</template>
<template #header> <template #header>
<span>{{ supplier.name }} - {{ supplier.id }}</span> <span>{{ supplier.name }} - {{ supplier.id }}</span>
</template> </template>
<template #body> <template #body>
<QCard class="vn-one"> <QCard class="vn-one">
<a <router-link
v-if="isAdministrative" v-if="isAdministrative"
class="header header-link" class="header link"
:href="`#/supplier/${entityId}/basic-data`" :to="{ name: 'SupplierBasicData', params: { id: entityId } }"
> >
{{ t('globals.summary.basicData') }} {{ t('globals.summary.basicData') }}
<QIcon name="open_in_new" /> <QIcon name="open_in_new" />
</a> </router-link>
<span v-else> {{ t('globals.summary.basicData') }}</span> <span v-else> {{ t('globals.summary.basicData') }}</span>
<VnLv label="Id" :value="supplier.id" /> <VnLv label="Id" :value="supplier.id" />
<VnLv label="Alias" :value="supplier.nickname" /> <VnLv label="Alias" :value="supplier.nickname" />
@ -98,14 +93,14 @@ const isAdministrative = computed(() => {
/> />
</QCard> </QCard>
<QCard class="vn-one"> <QCard class="vn-one">
<a <router-link
v-if="isAdministrative" v-if="isAdministrative"
class="header header-link" class="header link"
:href="`#/supplier/${entityId}/billing-data`" :to="{ name: 'SupplierBillingData', params: { id: entityId } }"
> >
{{ t('supplier.summary.billingData') }} {{ t('supplier.summary.billingData') }}
<QIcon name="open_in_new" /> <QIcon name="open_in_new" />
</a> </router-link>
<span v-else> {{ t('supplier.summary.billingData') }}</span> <span v-else> {{ t('supplier.summary.billingData') }}</span>
<VnLv <VnLv
:label="t('supplier.summary.payMethod')" :label="t('supplier.summary.payMethod')"
@ -121,14 +116,14 @@ const isAdministrative = computed(() => {
<VnLv :label="t('supplier.summary.account')" :value="supplier.account" /> <VnLv :label="t('supplier.summary.account')" :value="supplier.account" />
</QCard> </QCard>
<QCard class="vn-one"> <QCard class="vn-one">
<a <router-link
v-if="isAdministrative" v-if="isAdministrative"
class="header header-link" class="header link"
:href="`#/supplier/${entityId}/fiscal-data`" :to="{ name: 'SupplierFiscalData', params: { id: entityId } }"
> >
{{ t('supplier.summary.fiscalData') }} {{ t('supplier.summary.fiscalData') }}
<QIcon name="open_in_new" /> <QIcon name="open_in_new" />
</a> </router-link>
<span v-else> {{ t('supplier.summary.fiscalData') }}</span> <span v-else> {{ t('supplier.summary.fiscalData') }}</span>
<VnLv <VnLv
:label="t('supplier.summary.sageTaxType')" :label="t('supplier.summary.sageTaxType')"
@ -156,14 +151,14 @@ const isAdministrative = computed(() => {
/> />
</QCard> </QCard>
<QCard class="vn-one"> <QCard class="vn-one">
<a <router-link
v-if="isAdministrative" v-if="isAdministrative"
class="header header-link" class="header link"
:href="`#/supplier/${entityId}/fiscal-data`" :to="{ name: 'SupplierFiscalData', params: { id: entityId } }"
> >
{{ t('supplier.summary.fiscalAddress') }} {{ t('supplier.summary.fiscalAddress') }}
<QIcon name="open_in_new" /> <QIcon name="open_in_new" />
</a> </router-link>
<span v-else> {{ t('supplier.summary.fiscalAddress') }}</span> <span v-else> {{ t('supplier.summary.fiscalAddress') }}</span>
<VnLv :label="t('supplier.summary.socialName')" :value="supplier.name" /> <VnLv :label="t('supplier.summary.socialName')" :value="supplier.name" />
<VnLv :label="t('supplier.summary.taxNumber')" :value="supplier.nif" /> <VnLv :label="t('supplier.summary.taxNumber')" :value="supplier.nif" />

View File

@ -42,7 +42,7 @@ const redirectToCreateView = () => {
</QScrollArea> </QScrollArea>
</QDrawer> </QDrawer>
<div class="vn-card-list"> <div class="vn-card-list">
<VnPaginate data-key="SuppliersList" url="Suppliers/filter" auto-load> <VnPaginate data-key="SuppliersList" url="Suppliers/filter">
<template #body="{ rows }"> <template #body="{ rows }">
<CardList <CardList
v-for="row of rows" v-for="row of rows"

View File

@ -236,19 +236,9 @@ async function setTravelData(travelData) {
:url="`Travels/${entityId}/getTravel`" :url="`Travels/${entityId}/getTravel`"
@on-fetch="(data) => setTravelData(data)" @on-fetch="(data) => setTravelData(data)"
> >
<template #header-left>
<router-link
class="header link"
:to="{ name: 'TravelSummary', params: { id: entityId } }"
>
<QIcon name="open_in_new" color="white" size="sm" />
<QTooltip>{{ t('travel.pageTitles.summary') }}</QTooltip>
</router-link>
</template>
<template #header> <template #header>
<span>{{ travel.ref }} - {{ travel.id }}</span> <span>{{ travel.ref }} - {{ travel.id }}</span>
</template> </template>
<template #header-right> <template #header-right>
<QBtn color="white" dense flat icon="more_vert" round size="md"> <QBtn color="white" dense flat icon="more_vert" round size="md">
<QTooltip> <QTooltip>

View File

@ -0,0 +1,140 @@
<script setup>
import { useI18n } from 'vue-i18n';
import { useRoute } from 'vue-router';
import { onMounted, ref, computed } from 'vue';
import FetchData from 'components/FetchData.vue';
import FormModel from 'components/FormModel.vue';
import VnSelectFilter from 'src/components/common/VnSelectFilter.vue';
import useNotify from 'src/composables/useNotify.js';
import axios from 'axios';
import { useRole } from 'src/composables/useRole';
const route = useRoute();
const { t } = useI18n();
const { notify } = useNotify();
const { hasAny } = useRole();
const fetchCurrentDeviceRef = ref(null);
const deviceProductionsFilter = {
fields: ['id', 'serialNumber', 'modelFk'],
where: { stateFk: 'idle' },
order: 'id',
};
const deviceProductionsOptions = ref([]);
const newPDA = ref({});
const currentPDA = ref(null);
const isAllowedToEdit = computed(() => hasAny(['hr', 'productionAssi']));
const setCurrentPDA = (data) => {
currentPDA.value = data;
currentPDA.value.description = `ID: ${currentPDA.value.deviceProductionFk} ${t(
'worker.pda.model'
)}: ${currentPDA.value.deviceProduction.modelFk} ${t('worker.pda.serialNumber')}: ${
currentPDA.value.deviceProduction.serialNumber
}`;
};
const deallocatePDA = async (data) => {
try {
await axios.post(`Workers/${route.params.id}/deallocatePDA`, {
pda: currentPDA.value.deviceProductionFk,
});
data.pda = null;
currentPDA.value = null;
await fetchCurrentDeviceRef.value.fetch();
notify(t('PDA deallocated'), 'positive');
} catch (err) {
console.error('Error deallocating PDA');
}
};
onMounted(async () => await fetchCurrentDeviceRef.value.fetch());
</script>
<template>
<FetchData
url="DeviceProductions"
:filter="deviceProductionsFilter"
auto-load
@on-fetch="(data) => (deviceProductionsOptions = data)"
/>
<FetchData
ref="fetchCurrentDeviceRef"
url="DeviceProductionUsers"
:filter="{
where: { userFk: route.params.id },
include: { relation: 'deviceProduction' },
}"
auto-load
@on-fetch="(data) => setCurrentPDA(data[0])"
/>
<QPage class="column items-center q-pa-md">
<FormModel
url="DeviceProductionUsers"
:url-create="`Workers/${route.params.id}/allocatePDA`"
model="DeviceProductionUser"
:form-initial-data="newPDA"
auto-load
:default-buttons="{ save: { label: 'globals.assign', color: 'primary' } }"
@on-data-saved="(_, data) => setCurrentPDA(data)"
>
<template #form="{ data }">
<QField
v-if="currentPDA && currentPDA.description"
:label="t('worker.pda.currentPDA')"
:model-value="currentPDA.description"
:editable="false"
class="full-width"
>
<template #control>
<div tabindex="0">
{{ currentPDA.description }}
</div>
</template>
<template v-if="isAllowedToEdit" #append>
<QIcon
name="delete"
size="sm"
class="cursor-pointer"
color="primary"
@click="deallocatePDA(data)"
>
<QTooltip>
{{ t('worker.pda.removePDA') }}
</QTooltip>
</QIcon>
</template>
</QField>
<VnSelectFilter
v-else
:label="t('worker.pda.newPDA')"
v-model="data.pda"
:options="deviceProductionsOptions"
option-label="serialNumber"
option-value="id"
hide-selected
:disable="!isAllowedToEdit"
>
<template #option="scope">
<QItem v-bind="scope.itemProps">
<QItemSection>
<QItemLabel>ID: {{ scope.opt?.id }}</QItemLabel>
<QItemLabel caption>
{{ scope.opt?.modelFk }},
{{ scope.opt?.serialNumber }}
</QItemLabel>
</QItemSection>
</QItem>
</template>
</VnSelectFilter>
</template>
</FormModel>
</QPage>
</template>
<i18n>
es:
PDA deallocated: PDA desasignada
</i18n>

View File

@ -6,6 +6,7 @@ export default {
meta: { meta: {
title: 'suppliers', title: 'suppliers',
icon: 'vn:supplier', icon: 'vn:supplier',
moduleName: 'Supplier',
}, },
component: RouterView, component: RouterView,
redirect: { name: 'SupplierMain' }, redirect: { name: 'SupplierMain' },

View File

@ -6,6 +6,7 @@ export default {
meta: { meta: {
title: 'claims', title: 'claims',
icon: 'vn:claims', icon: 'vn:claims',
moduleName: 'Claim',
}, },
component: RouterView, component: RouterView,
redirect: { name: 'ClaimMain' }, redirect: { name: 'ClaimMain' },

View File

@ -6,6 +6,7 @@ export default {
meta: { meta: {
title: 'customers', title: 'customers',
icon: 'vn:client', icon: 'vn:client',
moduleName: 'Customer',
}, },
component: RouterView, component: RouterView,
redirect: { name: 'CustomerMain' }, redirect: { name: 'CustomerMain' },

View File

@ -6,6 +6,7 @@ export default {
meta: { meta: {
title: 'entries', title: 'entries',
icon: 'vn:entry', icon: 'vn:entry',
moduleName: 'Entry',
}, },
component: RouterView, component: RouterView,
redirect: { name: 'EntryMain' }, redirect: { name: 'EntryMain' },

View File

@ -6,6 +6,7 @@ export default {
meta: { meta: {
title: 'invoiceIns', title: 'invoiceIns',
icon: 'vn:invoice-in', icon: 'vn:invoice-in',
moduleName: 'InvoiceIn',
}, },
component: RouterView, component: RouterView,
redirect: { name: 'InvoiceInMain' }, redirect: { name: 'InvoiceInMain' },

View File

@ -6,6 +6,7 @@ export default {
meta: { meta: {
title: 'invoiceOuts', title: 'invoiceOuts',
icon: 'vn:invoice-out', icon: 'vn:invoice-out',
moduleName: 'InvoiceOut',
}, },
component: RouterView, component: RouterView,
redirect: { name: 'InvoiceOutMain' }, redirect: { name: 'InvoiceOutMain' },

View File

@ -6,6 +6,7 @@ export default {
meta: { meta: {
title: 'order', title: 'order',
icon: 'vn:basket', icon: 'vn:basket',
moduleName: 'Order',
}, },
component: RouterView, component: RouterView,
redirect: { name: 'OrderMain' }, redirect: { name: 'OrderMain' },

View File

@ -6,6 +6,7 @@ export default {
meta: { meta: {
title: 'routes', title: 'routes',
icon: 'vn:delivery', icon: 'vn:delivery',
moduleName: 'Route',
}, },
component: RouterView, component: RouterView,
redirect: { name: 'RouteMain' }, redirect: { name: 'RouteMain' },

View File

@ -6,6 +6,7 @@ export default {
meta: { meta: {
title: 'shelving', title: 'shelving',
icon: 'vn:inventory', icon: 'vn:inventory',
moduleName: 'Shelving',
}, },
component: RouterView, component: RouterView,
redirect: { name: 'ShelvingMain' }, redirect: { name: 'ShelvingMain' },

View File

@ -6,6 +6,7 @@ export default {
meta: { meta: {
title: 'tickets', title: 'tickets',
icon: 'vn:ticket', icon: 'vn:ticket',
moduleName: 'Ticket',
}, },
component: RouterView, component: RouterView,
redirect: { name: 'TicketMain' }, redirect: { name: 'TicketMain' },

View File

@ -6,6 +6,7 @@ export default {
meta: { meta: {
title: 'travel', title: 'travel',
icon: 'local_airport', icon: 'local_airport',
moduleName: 'Travel',
}, },
component: RouterView, component: RouterView,
redirect: { name: 'TravelMain' }, redirect: { name: 'TravelMain' },

View File

@ -6,6 +6,7 @@ export default {
meta: { meta: {
title: 'wagons', title: 'wagons',
icon: 'vn:trolley', icon: 'vn:trolley',
moduleName: 'Wagon',
}, },
component: RouterView, component: RouterView,
redirect: { name: 'WagonMain' }, redirect: { name: 'WagonMain' },

View File

@ -6,12 +6,13 @@ export default {
meta: { meta: {
title: 'workers', title: 'workers',
icon: 'vn:worker', icon: 'vn:worker',
moduleName: 'Worker',
}, },
component: RouterView, component: RouterView,
redirect: { name: 'WorkerMain' }, redirect: { name: 'WorkerMain' },
menus: { menus: {
main: ['WorkerList', 'WorkerDepartment'], main: ['WorkerList', 'WorkerDepartment'],
card: ['WorkerNotificationsManager'], card: ['WorkerNotificationsManager', 'WorkerPda'],
departmentCard: ['BasicData'], departmentCard: ['BasicData'],
}, },
children: [ children: [
@ -75,6 +76,15 @@ export default {
component: () => component: () =>
import('src/pages/Worker/Card/WorkerNotificationsManager.vue'), import('src/pages/Worker/Card/WorkerNotificationsManager.vue'),
}, },
{
name: 'WorkerPda',
path: 'pda',
meta: {
title: 'pda',
icon: 'phone_android',
},
component: () => import('src/pages/Worker/Card/WorkerPda.vue'),
},
], ],
}, },
], ],