feature/FaltantesModuloTravel #185
|
@ -0,0 +1,114 @@
|
|||
<script setup>
|
||||
import { reactive, ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
import FetchData from 'components/FetchData.vue';
|
||||
import VnRow from 'components/ui/VnRow.vue';
|
||||
import VnSelectFilter from 'src/components/common/VnSelectFilter.vue';
|
||||
import VnInput from 'src/components/common/VnInput.vue';
|
||||
import FormModelPopup from './FormModelPopup.vue';
|
||||
|
||||
const emit = defineEmits(['onDataSaved']);
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const thermographFormData = reactive({
|
||||
thermographId: null,
|
||||
model: 'DISPOSABLE',
|
||||
warehouseId: null,
|
||||
temperatureFk: 'cool',
|
||||
});
|
||||
|
||||
const thermographsModels = ref(null);
|
||||
const warehousesOptions = ref([]);
|
||||
const temperaturesOptions = ref([]);
|
||||
|
||||
const onDataSaved = (dataSaved) => {
|
||||
emit('onDataSaved', dataSaved);
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<FetchData
|
||||
@on-fetch="(data) => (thermographsModels = data)"
|
||||
auto-load
|
||||
url="Thermographs/getThermographModels"
|
||||
/>
|
||||
<FetchData
|
||||
@on-fetch="(data) => (warehousesOptions = data)"
|
||||
auto-load
|
||||
url="Warehouses"
|
||||
:filter="{ fields: ['id', 'name'], order: 'name ASC', limit: 30 }"
|
||||
/>
|
||||
<FetchData
|
||||
@on-fetch="(data) => (temperaturesOptions = data)"
|
||||
auto-load
|
||||
url="Temperatures"
|
||||
/>
|
||||
<FormModelPopup
|
||||
url-create="Thermographs/createThermograph"
|
||||
model="thermograph"
|
||||
:title="t('New thermograph')"
|
||||
:form-initial-data="thermographFormData"
|
||||
@on-data-saved="onDataSaved($event)"
|
||||
>
|
||||
<template #form-inputs="{ data, validate }">
|
||||
<VnRow class="row q-gutter-md q-mb-md">
|
||||
<div class="col">
|
||||
<VnInput
|
||||
:label="t('Identifier')"
|
||||
v-model="data.thermographId"
|
||||
:required="true"
|
||||
:rules="validate('thermograph.id')"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<VnSelectFilter
|
||||
:label="t('Model')"
|
||||
:options="thermographsModels"
|
||||
hide-selected
|
||||
option-label="value"
|
||||
option-value="value"
|
||||
v-model="data.model"
|
||||
:required="true"
|
||||
:rules="validate('thermograph.model')"
|
||||
/>
|
||||
</div>
|
||||
</VnRow>
|
||||
<VnRow class="row q-gutter-md q-mb-xl">
|
||||
<div class="col">
|
||||
<VnSelectFilter
|
||||
:label="t('Warehouse')"
|
||||
:options="warehousesOptions"
|
||||
hide-selected
|
||||
option-label="name"
|
||||
option-value="id"
|
||||
v-model="data.warehouseId"
|
||||
:required="true"
|
||||
/>
|
||||
</div>
|
||||
<div class="col">
|
||||
<VnSelectFilter
|
||||
:label="t('Temperature')"
|
||||
:options="temperaturesOptions"
|
||||
hide-selected
|
||||
option-label="name"
|
||||
option-value="code"
|
||||
v-model="data.temperatureFk"
|
||||
:required="true"
|
||||
/>
|
||||
</div>
|
||||
</VnRow>
|
||||
</template>
|
||||
</FormModelPopup>
|
||||
</template>
|
||||
|
||||
<i18n>
|
||||
es:
|
||||
Identifier: Identificador
|
||||
Model: Modelo
|
||||
Warehouse: Almacén
|
||||
Temperature: Temperatura
|
||||
New thermograph: Nuevo termógrafo
|
||||
</i18n>
|
|
@ -276,13 +276,9 @@ const makeRequest = async () => {
|
|||
</QIcon>
|
||||
<QIcon name="info" class="cursor-pointer">
|
||||
<QTooltip>{{
|
||||
t(
|
||||
'components.editPictureForm.allowedFilesText',
|
||||
{
|
||||
allowedContentTypes:
|
||||
allowedContentTypes,
|
||||
}
|
||||
)
|
||||
t('globals.allowedFilesText', {
|
||||
allowedContentTypes: allowedContentTypes,
|
||||
})
|
||||
}}</QTooltip>
|
||||
</QIcon>
|
||||
</template>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<script setup>
|
||||
import { computed } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
const emit = defineEmits(['update:modelValue', 'update:options', 'keyup.enter']);
|
||||
|
||||
|
@ -14,6 +15,9 @@ const $props = defineProps({
|
|||
},
|
||||
});
|
||||
|
||||
const { t } = useI18n();
|
||||
const requiredFieldRule = (val) => !!val || t('globals.fieldRequired');
|
||||
|
||||
const value = computed({
|
||||
get() {
|
||||
return $props.modelValue;
|
||||
|
@ -46,6 +50,7 @@ const onEnterPress = () => {
|
|||
type="text"
|
||||
:class="{ required: $attrs.required }"
|
||||
@keyup.enter="onEnterPress()"
|
||||
:rules="$attrs.required ? [requiredFieldRule] : null"
|
||||
>
|
||||
<template v-if="$slots.prepend" #prepend>
|
||||
<slot name="prepend" />
|
||||
|
|
|
@ -24,6 +24,10 @@ const $props = defineProps({
|
|||
type: String,
|
||||
default: 'add',
|
||||
},
|
||||
tooltip: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
});
|
||||
|
||||
const role = useRole();
|
||||
|
@ -55,7 +59,9 @@ const toggleForm = () => {
|
|||
:name="actionIcon"
|
||||
:size="actionIcon === 'add' ? 'xs' : 'sm'"
|
||||
:class="['default-icon', { '--add-icon': actionIcon === 'add' }]"
|
||||
/>
|
||||
>
|
||||
<QTooltip v-if="tooltip">{{ tooltip }}</QTooltip>
|
||||
</QIcon>
|
||||
<QDialog v-model="showForm" transition-show="scale" transition-hide="scale">
|
||||
<slot name="form" />
|
||||
</QDialog>
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
<script setup>
|
||||
import FetchData from 'src/components/FetchData.vue';
|
||||
import { onMounted } from 'vue';
|
||||
import { ref, toRefs, computed, watch } from 'vue';
|
||||
import { onMounted } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import FetchData from 'src/components/FetchData.vue';
|
||||
const emit = defineEmits(['update:modelValue', 'update:options']);
|
||||
|
||||
const $props = defineProps({
|
||||
|
@ -55,6 +56,9 @@ const $props = defineProps({
|
|||
},
|
||||
});
|
||||
|
||||
const { t } = useI18n();
|
||||
const requiredFieldRule = (val) => !!val || t('globals.fieldRequired');
|
||||
|
||||
const { optionLabel, optionValue, options, modelValue } = toRefs($props);
|
||||
const myOptions = ref([]);
|
||||
const myOptionsOriginal = ref([]);
|
||||
|
@ -164,6 +168,7 @@ watch(modelValue, (newValue) => {
|
|||
fill-input
|
||||
ref="vnSelectRef"
|
||||
:class="{ required: $attrs.required }"
|
||||
:rules="$attrs.required ? [requiredFieldRule] : null"
|
||||
>
|
||||
<template v-if="isClearable" #append>
|
||||
<QIcon
|
||||
|
|
|
@ -9,6 +9,7 @@ const user = ref({
|
|||
lang: '',
|
||||
darkMode: null,
|
||||
companyFk: null,
|
||||
warehouseFk: null,
|
||||
});
|
||||
|
||||
const roles = ref([]);
|
||||
|
|
|
@ -68,6 +68,8 @@ export default {
|
|||
reason: 'reason',
|
||||
noResults: 'No results',
|
||||
system: 'System',
|
||||
fieldRequired: 'Field required',
|
||||
allowedFilesText: 'Allowed file types: { allowedContentTypes }',
|
||||
},
|
||||
errors: {
|
||||
statusUnauthorized: 'Access denied',
|
||||
|
@ -1084,8 +1086,8 @@ export default {
|
|||
extraCommunity: 'Extra community',
|
||||
travelCreate: 'New travel',
|
||||
basicData: 'Basic data',
|
||||
history: 'History',
|
||||
thermographs: 'Termographs',
|
||||
history: 'Log',
|
||||
thermographs: 'Thermograph',
|
||||
},
|
||||
summary: {
|
||||
confirmed: 'Confirmed',
|
||||
|
@ -1097,7 +1099,10 @@ export default {
|
|||
entries: 'Entries',
|
||||
cloneShipping: 'Clone travel',
|
||||
CloneTravelAndEntries: 'Clone travel and his entries',
|
||||
deleteTravel: 'Delete travel',
|
||||
AddEntry: 'Add entry',
|
||||
thermographs: 'Thermographs',
|
||||
hb: 'HB',
|
||||
},
|
||||
variables: {
|
||||
search: 'Id/Reference',
|
||||
|
@ -1109,6 +1114,31 @@ export default {
|
|||
continent: 'Continent out',
|
||||
totalEntries: 'Total entries',
|
||||
},
|
||||
basicData: {
|
||||
reference: 'Reference',
|
||||
agency: 'Agency',
|
||||
shipped: 'Shipped',
|
||||
landed: 'Landed',
|
||||
warehouseOut: 'Warehouse Out',
|
||||
warehouseIn: 'Warehouse In',
|
||||
delivered: 'Delivered',
|
||||
received: 'Received',
|
||||
},
|
||||
thermographs: {
|
||||
code: 'Code',
|
||||
temperature: 'Temperature',
|
||||
state: 'State',
|
||||
destination: 'Destination',
|
||||
created: 'Created',
|
||||
thermograph: 'Thermograph',
|
||||
reference: 'Reference',
|
||||
type: 'Type',
|
||||
company: 'Company',
|
||||
warehouse: 'Warehouse',
|
||||
travelFileDescription: 'Travel id { travelId }',
|
||||
file: 'File',
|
||||
description: 'Description',
|
||||
},
|
||||
},
|
||||
item: {
|
||||
pageTitles: {
|
||||
|
@ -1152,9 +1182,6 @@ export default {
|
|||
addToPinned: 'Add to pinned',
|
||||
removeFromPinned: 'Remove from pinned',
|
||||
},
|
||||
editPictureForm: {
|
||||
allowedFilesText: 'Allowed file types: { allowedContentTypes }',
|
||||
},
|
||||
VnLv: {
|
||||
copyText: '{copyValue} has been copied to the clipboard',
|
||||
},
|
||||
|
|
|
@ -68,6 +68,8 @@ export default {
|
|||
reason: 'motivo',
|
||||
noResults: 'Sin resultados',
|
||||
system: 'Sistema',
|
||||
fieldRequired: 'Campo requerido',
|
||||
allowedFilesText: 'Tipos de archivo permitidos: { allowedContentTypes }',
|
||||
},
|
||||
errors: {
|
||||
statusUnauthorized: 'Acceso denegado',
|
||||
|
@ -1097,7 +1099,10 @@ export default {
|
|||
entries: 'Entradas',
|
||||
cloneShipping: 'Clonar envío',
|
||||
CloneTravelAndEntries: 'Clonar travel y sus entradas',
|
||||
deleteTravel: 'Eliminar envío',
|
||||
AddEntry: 'Añadir entrada',
|
||||
thermographs: 'Termógrafos',
|
||||
hb: 'HB',
|
||||
},
|
||||
variables: {
|
||||
search: 'Id/Referencia',
|
||||
|
@ -1109,6 +1114,31 @@ export default {
|
|||
continent: 'Cont. Salida',
|
||||
totalEntries: 'Ent. totales',
|
||||
},
|
||||
basicData: {
|
||||
reference: 'Referencia',
|
||||
agency: 'Agencia',
|
||||
shipped: 'F. Envío',
|
||||
landed: 'F. entrega',
|
||||
warehouseOut: 'Alm. salida',
|
||||
warehouseIn: 'Alm. entrada',
|
||||
delivered: 'Enviada',
|
||||
received: 'Recibida',
|
||||
},
|
||||
thermographs: {
|
||||
code: 'Código',
|
||||
temperature: 'Temperatura',
|
||||
state: 'Estado',
|
||||
destination: 'Destino',
|
||||
created: 'Fecha creación',
|
||||
thermograph: 'Termógrafo',
|
||||
reference: 'Referencia',
|
||||
type: 'Tipo',
|
||||
company: 'Empresa',
|
||||
warehouse: 'Almacén',
|
||||
travelFileDescription: 'Id envío { travelId }',
|
||||
file: 'Fichero',
|
||||
description: 'Descripción',
|
||||
},
|
||||
},
|
||||
item: {
|
||||
pageTitles: {
|
||||
|
@ -1152,9 +1182,6 @@ export default {
|
|||
addToPinned: 'Añadir a fijados',
|
||||
removeFromPinned: 'Eliminar de fijados',
|
||||
},
|
||||
editPictureForm: {
|
||||
allowedFilesText: 'Tipos de archivo permitidos: { allowedContentTypes }',
|
||||
},
|
||||
VnLv: {
|
||||
copyText: '{copyValue} se ha copiado al portapepeles',
|
||||
},
|
||||
|
|
|
@ -23,11 +23,11 @@ const stateStore = useStateStore();
|
|||
const user = state.getUser();
|
||||
const newEntryForm = reactive({
|
||||
supplierFk: null,
|
||||
travelFk: route.query?.travelFk || null,
|
||||
travelFk: Number(route.query?.travelFk) || null,
|
||||
companyFk: user.value.companyFk || null,
|
||||
});
|
||||
const suppliersOptions = ref([]);
|
||||
const travelsOptionsOptions = ref([]);
|
||||
const travelsOptions = ref([]);
|
||||
const companiesOptions = ref([]);
|
||||
|
||||
const redirectToEntryBasicData = (_, { id }) => {
|
||||
|
@ -47,7 +47,7 @@ const redirectToEntryBasicData = (_, { id }) => {
|
|||
url="Travels/filter"
|
||||
:filter="{ fields: ['id', 'warehouseInName'] }"
|
||||
order="id"
|
||||
@on-fetch="(data) => (travelsOptionsOptions = data)"
|
||||
@on-fetch="(data) => (travelsOptions = data)"
|
||||
auto-load
|
||||
/>
|
||||
<FetchData
|
||||
|
@ -110,7 +110,7 @@ const redirectToEntryBasicData = (_, { id }) => {
|
|||
:label="t('Travel')"
|
||||
class="full-width"
|
||||
v-model="data.travelFk"
|
||||
:options="travelsOptionsOptions"
|
||||
:options="travelsOptions"
|
||||
option-value="id"
|
||||
option-label="warehouseInName"
|
||||
map-options
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
import FetchData from 'components/FetchData.vue';
|
||||
import FormModel from 'components/FormModel.vue';
|
||||
import VnRow from 'components/ui/VnRow.vue';
|
||||
import VnInput from 'src/components/common/VnInput.vue';
|
||||
import VnSelectFilter from 'src/components/common/VnSelectFilter.vue';
|
||||
import VnInputDate from 'components/common/VnInputDate.vue';
|
||||
|
||||
const route = useRoute();
|
||||
const { t } = useI18n();
|
||||
|
||||
const agenciesOptions = ref([]);
|
||||
</script>
|
||||
<template>
|
||||
<FetchData
|
||||
url="AgencyModes"
|
||||
@on-fetch="(data) => (agenciesOptions = data)"
|
||||
auto-load
|
||||
/>
|
||||
<FormModel
|
||||
:url="`Travels/${route.params.id}`"
|
||||
:url-update="`Travels/${route.params.id}`"
|
||||
model="travel"
|
||||
auto-load
|
||||
>
|
||||
<template #form="{ data }">
|
||||
<VnRow class="row q-gutter-md q-mb-md">
|
||||
<div class="col">
|
||||
<VnInput
|
||||
v-model="data.ref"
|
||||
:label="t('travel.basicData.reference')"
|
||||
/>
|
||||
</div>
|
||||
<div class="col">
|
||||
<VnSelectFilter
|
||||
:label="t('travel.basicData.agency')"
|
||||
v-model="data.agencyModeFk"
|
||||
:options="agenciesOptions"
|
||||
option-value="id"
|
||||
option-label="name"
|
||||
map-options
|
||||
hide-selected
|
||||
/>
|
||||
</div>
|
||||
</VnRow>
|
||||
<VnRow class="row q-gutter-md q-mb-md">
|
||||
<div class="col">
|
||||
<VnInputDate
|
||||
v-model="data.shipped"
|
||||
:label="t('travel.basicData.shipped')"
|
||||
/>
|
||||
</div>
|
||||
<div class="col">
|
||||
<VnInputDate
|
||||
v-model="data.landed"
|
||||
:label="t('travel.basicData.landed')"
|
||||
/>
|
||||
</div>
|
||||
</VnRow>
|
||||
<VnRow class="row q-gutter-md q-mb-md">
|
||||
<div class="col">
|
||||
<VnSelectFilter
|
||||
:label="t('travel.basicData.warehouseOut')"
|
||||
v-model="data.warehouseOutFk"
|
||||
:options="agenciesOptions"
|
||||
option-value="id"
|
||||
option-label="name"
|
||||
map-options
|
||||
hide-selected
|
||||
/>
|
||||
</div>
|
||||
<div class="col">
|
||||
<VnSelectFilter
|
||||
:label="t('travel.basicData.warehouseIn')"
|
||||
v-model="data.warehouseInFk"
|
||||
:options="agenciesOptions"
|
||||
option-value="id"
|
||||
option-label="name"
|
||||
map-options
|
||||
hide-selected
|
||||
/>
|
||||
</div>
|
||||
</VnRow>
|
||||
<VnRow class="row q-gutter-md q-mb-md">
|
||||
<div class="col">
|
||||
<QCheckbox
|
||||
:label="t('travel.basicData.delivered')"
|
||||
v-model="data.isDelivered"
|
||||
/>
|
||||
</div>
|
||||
<div class="col">
|
||||
<QCheckbox
|
||||
:label="t('travel.basicData.received')"
|
||||
v-model="data.isReceived"
|
||||
/>
|
||||
</div>
|
||||
</VnRow>
|
||||
</template>
|
||||
</FormModel>
|
||||
</template>
|
|
@ -17,7 +17,6 @@ const stateStore = useStateStore();
|
|||
<QPageContainer>
|
||||
<QPage>
|
||||
<VnSubToolbar />
|
||||
|
||||
<div class="q-pa-md"><RouterView></RouterView></div>
|
||||
</QPage>
|
||||
</QPageContainer>
|
||||
|
|
|
@ -2,10 +2,13 @@
|
|||
import { ref, computed } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { toDate } from 'src/filters';
|
||||
|
||||
import CardDescriptor from 'components/ui/CardDescriptor.vue';
|
||||
import VnLv from 'src/components/ui/VnLv.vue';
|
||||
import TravelDescriptorMenuItems from './TravelDescriptorMenuItems.vue';
|
||||
|
||||
import useCardDescription from 'src/composables/useCardDescription';
|
||||
import { toDate } from 'src/filters';
|
||||
|
||||
const $props = defineProps({
|
||||
id: {
|
||||
|
@ -28,6 +31,7 @@ const filter = {
|
|||
'warehouseInFk',
|
||||
'warehouseOutFk',
|
||||
'cargoSupplierFk',
|
||||
'agencyModeFk',
|
||||
],
|
||||
include: [
|
||||
{
|
||||
|
@ -66,6 +70,25 @@ const setData = (entity) => {
|
|||
@on-fetch="setData"
|
||||
data-key="travelData"
|
||||
>
|
||||
<template #header-extra-action>
|
||||
<QBtn
|
||||
round
|
||||
flat
|
||||
dense
|
||||
size="md"
|
||||
icon="local_airport"
|
||||
color="white"
|
||||
class="link"
|
||||
:to="{ name: 'TravelList' }"
|
||||
>
|
||||
<QTooltip>
|
||||
{{ t('Go to module index') }}
|
||||
</QTooltip>
|
||||
</QBtn>
|
||||
</template>
|
||||
<template #menu="{ entity }">
|
||||
<TravelDescriptorMenuItems :travel="entity" />
|
||||
</template>
|
||||
<template #body="{ entity }">
|
||||
<VnLv :label="t('globals.wareHouseIn')" :value="entity.warehouseIn.name" />
|
||||
<VnLv :label="t('globals.wareHouseOut')" :value="entity.warehouseOut.name" />
|
||||
|
@ -73,8 +96,32 @@ const setData = (entity) => {
|
|||
<VnLv :label="t('globals.landed')" :value="toDate(entity.landed)" />
|
||||
<VnLv :label="t('globals.totalEntries')" :value="entity.totalEntries" />
|
||||
</template>
|
||||
<template #actions="{ entity }">
|
||||
<QCardActions>
|
||||
<QBtn
|
||||
:to="{
|
||||
name: 'TravelList',
|
||||
query: {
|
||||
params: JSON.stringify({
|
||||
agencyModeFk: entity.agencyModeFk,
|
||||
}),
|
||||
},
|
||||
}"
|
||||
size="md"
|
||||
icon="local_airport"
|
||||
color="primary"
|
||||
>
|
||||
<QTooltip>{{ t('All travels with current agency') }}</QTooltip>
|
||||
</QBtn>
|
||||
</QCardActions>
|
||||
</template>
|
||||
</CardDescriptor>
|
||||
</template>
|
||||
<i18n>
|
||||
|
||||
<i18n>
|
||||
es:
|
||||
Go to module index: Ir al índice del módulo
|
||||
The travel will be deleted: El envío será eliminado
|
||||
Do you want to delete this travel?: ¿Quieres eliminar este envío?
|
||||
All travels with current agency: Todos los envíos con la agencia actual
|
||||
</i18n>
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
<script setup>
|
||||
import { computed } from 'vue';
|
||||
import { useQuasar } from 'quasar';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
import VnConfirm from 'components/ui/VnConfirm.vue';
|
||||
|
||||
import axios from 'axios';
|
||||
import useNotify from 'src/composables/useNotify.js';
|
||||
import { useRole } from 'src/composables/useRole';
|
||||
|
||||
const $props = defineProps({
|
||||
travel: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
});
|
||||
|
||||
const { t } = useI18n();
|
||||
const router = useRouter();
|
||||
const quasar = useQuasar();
|
||||
const { notify } = useNotify();
|
||||
const role = useRole();
|
||||
|
||||
const redirectToCreateView = (queryParams) => {
|
||||
router.push({ name: 'TravelCreate', query: { travelData: queryParams } });
|
||||
};
|
||||
|
||||
const cloneTravel = () => {
|
||||
const stringifiedTravelData = JSON.stringify($props.travel);
|
||||
redirectToCreateView(stringifiedTravelData);
|
||||
};
|
||||
|
||||
const cloneTravelWithEntries = () => {
|
||||
try {
|
||||
axios.post(`Travels/${$props.travel.id}/cloneWithEntries`);
|
||||
notify('globals.dataSaved', 'positive');
|
||||
} catch (err) {
|
||||
console.err('Error cloning travel with entries');
|
||||
}
|
||||
};
|
||||
|
||||
const isBuyer = computed(() => {
|
||||
return role.hasAny(['buyer']);
|
||||
});
|
||||
|
||||
const openDeleteEntryDialog = (id) => {
|
||||
quasar
|
||||
.dialog({
|
||||
component: VnConfirm,
|
||||
componentProps: {
|
||||
title: t('The travel will be deleted'),
|
||||
message: t('Do you want to delete this travel?'),
|
||||
},
|
||||
})
|
||||
.onOk(async () => {
|
||||
await deleteTravel(id);
|
||||
});
|
||||
};
|
||||
|
||||
const deleteTravel = async (id) => {
|
||||
try {
|
||||
await axios.delete(`Travels/${id}`);
|
||||
router.push({ name: 'TravelList' });
|
||||
notify('globals.dataDeleted', 'positive');
|
||||
} catch (err) {
|
||||
console.error('Error deleting travel');
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<QItem v-ripple clickable @click="cloneTravel(travel)">
|
||||
<QItemSection>{{ t('travel.summary.cloneShipping') }}</QItemSection>
|
||||
</QItem>
|
||||
<QItem v-ripple clickable @click="cloneTravelWithEntries()">
|
||||
<QItemSection>
|
||||
{{ t('travel.summary.CloneTravelAndEntries') }}
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
<QItem
|
||||
v-if="isBuyer && travel.totalEntries === 0"
|
||||
v-ripple
|
||||
clickable
|
||||
@click="openDeleteEntryDialog(travel.id)"
|
||||
>
|
||||
<QItemSection>
|
||||
{{ t('travel.summary.deleteTravel') }}
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
<QItem v-ripple clickable>
|
||||
<QItemSection>
|
||||
<RouterLink
|
||||
:to="{ name: 'EntryCreate', query: { travelFk: travel.id } }"
|
||||
class="color-vn-text"
|
||||
>
|
||||
{{ t('travel.summary.AddEntry') }}
|
||||
</RouterLink>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
</template>
|
||||
|
||||
<i18n>
|
||||
es:
|
||||
The travel will be deleted: El envío será eliminado
|
||||
Do you want to delete this travel?: ¿Quieres eliminar este envío?
|
||||
</i18n>
|
|
@ -0,0 +1,6 @@
|
|||
<script setup>
|
||||
import VnLog from 'src/components/common/VnLog.vue';
|
||||
</script>
|
||||
<template>
|
||||
<VnLog model="Entry" url="/TravelLogs"></VnLog>
|
||||
</template>
|
|
@ -1,22 +1,19 @@
|
|||
<script setup>
|
||||
import { onMounted, ref, computed, onUpdated } from 'vue';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { ref, computed, onUpdated } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
import { QCheckbox, QIcon } from 'quasar';
|
||||
import CardSummary from 'components/ui/CardSummary.vue';
|
||||
import VnLv from 'src/components/ui/VnLv.vue';
|
||||
import EntryDescriptorProxy from 'src/pages/Entry/Card/EntryDescriptorProxy.vue';
|
||||
import FetchData from 'src/components/FetchData.vue';
|
||||
import TravelDescriptorMenuItems from './TravelDescriptorMenuItems.vue';
|
||||
|
||||
import travelService from 'src/services/travel.service';
|
||||
import { toDate, toCurrency } from 'src/filters';
|
||||
import { getUrl } from 'src/composables/getUrl';
|
||||
import axios from 'axios';
|
||||
|
||||
onUpdated(() => summaryRef.value.fetch());
|
||||
|
||||
const route = useRoute();
|
||||
const { t } = useI18n();
|
||||
|
||||
const $props = defineProps({
|
||||
id: {
|
||||
type: Number,
|
||||
|
@ -25,89 +22,15 @@ const $props = defineProps({
|
|||
},
|
||||
});
|
||||
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const { t } = useI18n();
|
||||
|
||||
const entityId = computed(() => $props.id || route.params.id);
|
||||
const entries = ref([]);
|
||||
const summaryRef = ref();
|
||||
const travel = ref();
|
||||
const travelUrl = ref();
|
||||
|
||||
onMounted(async () => {
|
||||
travelUrl.value = (await getUrl('travel/')) + entityId.value;
|
||||
});
|
||||
|
||||
const cloneTravel = () => {
|
||||
const stringifiedTravelData = JSON.stringify(travel.value);
|
||||
redirectToCreateView(stringifiedTravelData);
|
||||
};
|
||||
|
||||
const cloneTravelWithEntries = () => {
|
||||
try {
|
||||
axios.post(`Travels/${$props.id}/cloneWithEntries`);
|
||||
} catch (err) {
|
||||
console.err('Error cloning travel with entries');
|
||||
}
|
||||
};
|
||||
|
||||
const headerMenuOptions = [
|
||||
{ name: t('travel.summary.cloneShipping'), action: cloneTravel },
|
||||
{ name: t('travel.summary.CloneTravelAndEntries'), action: cloneTravelWithEntries },
|
||||
{ name: t('travel.summary.AddEntry'), action: null },
|
||||
];
|
||||
|
||||
const tableColumnComponents = {
|
||||
isConfirmed: {
|
||||
component: () => QCheckbox,
|
||||
props: (prop) => ({
|
||||
disable: true,
|
||||
'model-value': Boolean(prop.value),
|
||||
}),
|
||||
},
|
||||
id: {
|
||||
component: () => 'span',
|
||||
props: () => {},
|
||||
event: () => openEntryDescriptor(),
|
||||
},
|
||||
supplierName: {
|
||||
component: () => 'span',
|
||||
props: () => {},
|
||||
event: () => {},
|
||||
},
|
||||
reference: {
|
||||
component: () => 'span',
|
||||
props: () => {},
|
||||
event: () => {},
|
||||
},
|
||||
freightValue: {
|
||||
component: () => 'span',
|
||||
props: () => {},
|
||||
event: () => {},
|
||||
},
|
||||
packageValue: {
|
||||
component: () => 'span',
|
||||
props: () => {},
|
||||
event: () => {},
|
||||
},
|
||||
cc: {
|
||||
component: () => 'span',
|
||||
props: () => {},
|
||||
event: () => {},
|
||||
},
|
||||
pallet: {
|
||||
component: () => 'span',
|
||||
props: () => {},
|
||||
event: () => {},
|
||||
},
|
||||
m3: {
|
||||
component: () => 'span',
|
||||
props: () => {},
|
||||
event: () => {},
|
||||
},
|
||||
observation: {
|
||||
component: (props) => (props.value ? QIcon : null),
|
||||
props: () => ({ name: 'insert_drive_file', color: 'primary', size: '25px' }),
|
||||
},
|
||||
};
|
||||
const entries = ref([]);
|
||||
const thermographs = ref([]);
|
||||
const warehouses = ref([]);
|
||||
|
||||
const entriesTableColumns = computed(() => {
|
||||
return [
|
||||
|
@ -116,24 +39,35 @@ const entriesTableColumns = computed(() => {
|
|||
field: 'isConfirmed',
|
||||
name: 'isConfirmed',
|
||||
align: 'left',
|
||||
showValue: false,
|
||||
},
|
||||
{
|
||||
label: t('travel.summary.entryId'),
|
||||
field: 'id',
|
||||
name: 'id',
|
||||
align: 'left',
|
||||
showValue: false,
|
||||
},
|
||||
{
|
||||
label: t('supplier.pageTitles.supplier'),
|
||||
field: 'supplierName',
|
||||
name: 'supplierName',
|
||||
align: 'left',
|
||||
showValue: true,
|
||||
},
|
||||
{
|
||||
label: t('globals.reference'),
|
||||
field: 'reference',
|
||||
name: 'reference',
|
||||
align: 'left',
|
||||
showValue: true,
|
||||
},
|
||||
{
|
||||
label: t('travel.summary.hb'),
|
||||
field: 'hb',
|
||||
name: 'hb',
|
||||
align: 'left',
|
||||
showValue: true,
|
||||
},
|
||||
{
|
||||
label: t('travel.summary.freight'),
|
||||
|
@ -143,6 +77,7 @@ const entriesTableColumns = computed(() => {
|
|||
format: (val) => {
|
||||
return toCurrency(val);
|
||||
},
|
||||
showValue: true,
|
||||
},
|
||||
{
|
||||
label: t('travel.summary.package'),
|
||||
|
@ -152,16 +87,62 @@ const entriesTableColumns = computed(() => {
|
|||
format: (val) => {
|
||||
return toCurrency(val);
|
||||
},
|
||||
showValue: true,
|
||||
},
|
||||
{ label: 'CC', field: 'cc', name: 'cc', align: 'left' },
|
||||
{ label: 'Pallet', field: 'pallet', name: 'pallet', align: 'left' },
|
||||
{ label: 'm³', field: 'm3', name: 'm3', align: 'left' },
|
||||
{ label: 'CC', field: 'cc', name: 'cc', align: 'left', showValue: true },
|
||||
{
|
||||
label: 'Pallet',
|
||||
field: 'pallet',
|
||||
name: 'pallet',
|
||||
align: 'left',
|
||||
showValue: true,
|
||||
},
|
||||
{ label: 'm³', field: 'm3', name: 'm3', align: 'left', showValue: true },
|
||||
{
|
||||
label: '',
|
||||
field: 'observation',
|
||||
name: 'observation',
|
||||
align: 'left',
|
||||
toolTip: 'Observation three',
|
||||
showValue: false,
|
||||
},
|
||||
];
|
||||
});
|
||||
|
||||
const thermographsTableColumns = computed(() => {
|
||||
return [
|
||||
{
|
||||
label: t('travel.thermographs.code'),
|
||||
field: 'thermographFk',
|
||||
name: 'thermographFk',
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
label: t('travel.thermographs.temperature'),
|
||||
field: 'temperatureFk',
|
||||
name: 'temperatureFk',
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
label: t('travel.thermographs.state'),
|
||||
field: 'result',
|
||||
name: 'result',
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
label: t('travel.thermographs.destination'),
|
||||
field: 'warehouseFk',
|
||||
name: 'destination',
|
||||
align: 'left',
|
||||
format: (val) =>
|
||||
warehouses.value.find((warehouse) => warehouse.id === val).name,
|
||||
},
|
||||
{
|
||||
label: t('travel.thermographs.created'),
|
||||
field: 'created',
|
||||
name: 'created',
|
||||
align: 'left',
|
||||
format: (val) => toDate(val),
|
||||
},
|
||||
];
|
||||
});
|
||||
|
@ -171,31 +152,98 @@ const entriesTableRows = computed(() => {
|
|||
return entries.value;
|
||||
});
|
||||
|
||||
async function setTravelData(data) {
|
||||
if (data) {
|
||||
travel.value = data;
|
||||
const entriesResponse = await travelService.getTravelEntries(travel.value.id);
|
||||
if (entriesResponse.data) entries.value = entriesResponse.data;
|
||||
}
|
||||
}
|
||||
const entriesTotalHb = computed(() =>
|
||||
entriesTableRows.value.reduce((acc, { hb }) => acc + hb, 0)
|
||||
);
|
||||
|
||||
const redirectToCreateView = (queryParams) => {
|
||||
router.push({ name: 'TravelCreate', query: { travelData: queryParams } });
|
||||
const entriesTotalFreight = computed(() =>
|
||||
toCurrency(
|
||||
entriesTableRows.value.reduce((acc, { freightValue }) => acc + freightValue, 0)
|
||||
)
|
||||
);
|
||||
|
||||
const entriesTotalPackageValue = computed(() =>
|
||||
toCurrency(
|
||||
entriesTableRows.value.reduce((acc, { packageValue }) => acc + packageValue, 0)
|
||||
)
|
||||
);
|
||||
|
||||
const entriesTotalCc = computed(() =>
|
||||
entriesTableRows.value.reduce((acc, { cc }) => acc + cc, 0)
|
||||
);
|
||||
|
||||
const entriesTotalPallet = computed(() =>
|
||||
entriesTableRows.value.reduce((acc, { pallet }) => acc + pallet, 0)
|
||||
);
|
||||
|
||||
const entriesTotalM3 = computed(() =>
|
||||
entriesTableRows.value.reduce((acc, { m3 }) => acc + m3, 0)
|
||||
);
|
||||
|
||||
const getTravelEntries = async (id) => {
|
||||
try {
|
||||
const { data } = await axios.get(`Travels/${id}/getEntries`);
|
||||
entries.value = data;
|
||||
} catch (err) {
|
||||
console.error('Error fetching travel entries');
|
||||
}
|
||||
};
|
||||
|
||||
const openEntryDescriptor = () => {};
|
||||
const getTravelThermographs = async (id) => {
|
||||
try {
|
||||
const filter = {
|
||||
include: {
|
||||
relation: 'warehouse',
|
||||
scope: {
|
||||
fields: ['id', 'name'],
|
||||
},
|
||||
},
|
||||
where: { travelFk: id },
|
||||
};
|
||||
|
||||
const { data } = await axios.get('TravelThermographs', {
|
||||
params: { filter: JSON.parse(JSON.stringify(filter)) },
|
||||
});
|
||||
thermographs.value = data;
|
||||
} catch (err) {
|
||||
console.error('Error fetching travel thermographs');
|
||||
}
|
||||
};
|
||||
|
||||
async function setTravelData(travelData) {
|
||||
try {
|
||||
if (travelData) {
|
||||
travel.value = travelData;
|
||||
await getTravelEntries(travel.value.id);
|
||||
await getTravelThermographs(travel.value.id);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(`Error setting travel data`, err);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<FetchData
|
||||
url="Warehouses"
|
||||
:filter="{ fields: ['id', 'name'] }"
|
||||
order="name"
|
||||
@on-fetch="(data) => (warehouses = data)"
|
||||
auto-load
|
||||
/>
|
||||
<CardSummary
|
||||
ref="summaryRef"
|
||||
:url="`Travels/${entityId}/getTravel`"
|
||||
@on-fetch="(data) => setTravelData(data)"
|
||||
>
|
||||
<template #header-left>
|
||||
<a class="header link" :href="travelUrl">
|
||||
<router-link
|
||||
class="header link"
|
||||
:to="{ name: 'TravelSummary', params: { id: entityId } }"
|
||||
>
|
||||
<QIcon name="open_in_new" color="white" size="sm" />
|
||||
</a>
|
||||
<QTooltip>{{ t('travel.pageTitles.summary') }}</QTooltip>
|
||||
</router-link>
|
||||
</template>
|
||||
<template #header>
|
||||
<span>{{ travel.ref }} - {{ travel.id }}</span>
|
||||
|
@ -207,10 +255,8 @@ const openEntryDescriptor = () => {};
|
|||
{{ t('components.cardDescriptor.moreOptions') }}
|
||||
</QTooltip>
|
||||
<QMenu>
|
||||
<QList dense v-for="option in headerMenuOptions" :key="option">
|
||||
<QItem v-ripple clickable @click="option.action">
|
||||
{{ option.name }}
|
||||
</QItem>
|
||||
<QList>
|
||||
<TravelDescriptorMenuItems :travel="travel" />
|
||||
</QList>
|
||||
</QMenu>
|
||||
</QBtn>
|
||||
|
@ -225,11 +271,10 @@ const openEntryDescriptor = () => {};
|
|||
/>
|
||||
<VnLv :label="t('travel.summary.delivered')" class="q-mb-xs">
|
||||
<template #value>
|
||||
<QCheckbox
|
||||
v-model="travel.isDelivered"
|
||||
disable
|
||||
dense
|
||||
class="full-width q-my-xs"
|
||||
<QIcon
|
||||
:name="travel.isDelivered ? 'check' : 'close'"
|
||||
:color="travel.isDelivered ? 'positive' : 'negative'"
|
||||
size="sm"
|
||||
/>
|
||||
</template>
|
||||
</VnLv>
|
||||
|
@ -242,11 +287,10 @@ const openEntryDescriptor = () => {};
|
|||
/>
|
||||
<VnLv :label="t('travel.summary.received')" class="q-mb-xs">
|
||||
<template #value>
|
||||
<QCheckbox
|
||||
v-model="travel.isReceived"
|
||||
disable
|
||||
dense
|
||||
class="full-width q-mb-xs"
|
||||
<QIcon
|
||||
:name="travel.isReceived ? 'check' : 'close'"
|
||||
:color="travel.isReceived ? 'positive' : 'negative'"
|
||||
size="sm"
|
||||
/>
|
||||
</template>
|
||||
</VnLv>
|
||||
|
@ -255,13 +299,12 @@ const openEntryDescriptor = () => {};
|
|||
<VnLv :label="t('globals.agency')" :value="travel.agency?.name" />
|
||||
<VnLv :label="t('globals.reference')" :value="travel.ref" />
|
||||
<VnLv label="m³" :value="travel.m3" />
|
||||
<VnLv :label="t('globals.totalEntries')" :value="travel.m3" />
|
||||
<VnLv :label="t('globals.totalEntries')" :value="travel.totalEntries" />
|
||||
</QCard>
|
||||
<QCard class="full-width" v-if="entriesTableRows.length > 0">
|
||||
<a class="header" :href="travelUrl + 'entry'">
|
||||
<span class="header">
|
||||
{{ t('travel.summary.entries') }}
|
||||
<QIcon name="open_in_new" color="primary" />
|
||||
</a>
|
||||
</span>
|
||||
<QTable
|
||||
:rows="entriesTableRows"
|
||||
:columns="entriesTableColumns"
|
||||
|
@ -269,36 +312,72 @@ const openEntryDescriptor = () => {};
|
|||
row-key="id"
|
||||
class="full-width q-mt-md"
|
||||
>
|
||||
<template #body-cell="props">
|
||||
<QTd :props="props">
|
||||
<component
|
||||
:is="
|
||||
tableColumnComponents[props.col.name].component(props)
|
||||
"
|
||||
v-bind="
|
||||
tableColumnComponents[props.col.name].props(props)
|
||||
"
|
||||
@click="
|
||||
tableColumnComponents[props.col.name].event(props)
|
||||
"
|
||||
class="col-content"
|
||||
>
|
||||
<template
|
||||
v-if="
|
||||
props.col.name !== 'observation' &&
|
||||
props.col.name !== 'isConfirmed'
|
||||
"
|
||||
>{{ props.value }}</template
|
||||
>
|
||||
<QTooltip v-if="props.col.toolTip">{{
|
||||
props.col.toolTip
|
||||
}}</QTooltip>
|
||||
</component>
|
||||
<template #header="props">
|
||||
<QTr :props="props" class="bg">
|
||||
<QTh v-for="col in props.cols" :key="col.name" :props="props">
|
||||
{{ t(col.label) }}
|
||||
</QTh>
|
||||
</QTr>
|
||||
</template>
|
||||
<template #body-cell-isConfirmed="{ col, value }">
|
||||
<QTd>
|
||||
<QIcon
|
||||
v-if="col.name === 'isConfirmed'"
|
||||
:name="value ? 'check' : 'close'"
|
||||
:color="value ? 'positive' : 'negative'"
|
||||
size="sm"
|
||||
/>
|
||||
</QTd>
|
||||
</template>
|
||||
<template #body-cell-id="{ col, value }">
|
||||
<QTd>
|
||||
<QBtn v-if="col.name === 'id'" flat color="blue">
|
||||
{{ value }}
|
||||
<EntryDescriptorProxy :id="value" />
|
||||
</QBtn>
|
||||
</QTd>
|
||||
</template>
|
||||
<template #body-cell-observation="{ value }">
|
||||
<QTd>
|
||||
<QIcon name="insert_drive_file" color="primary" size="24px">
|
||||
<QTooltip>{{ value }}</QTooltip>
|
||||
</QIcon>
|
||||
</QTd>
|
||||
</template>
|
||||
<template #bottom-row>
|
||||
<QTd></QTd>
|
||||
<QTd></QTd>
|
||||
<QTd></QTd>
|
||||
<QTd></QTd>
|
||||
<QTd class="text-bold">{{ entriesTotalHb }}</QTd>
|
||||
<QTd class="text-bold">{{ entriesTotalFreight }}</QTd>
|
||||
<QTd class="text-bold">{{ entriesTotalPackageValue }}</QTd>
|
||||
<QTd class="text-bold">{{ entriesTotalCc }}</QTd>
|
||||
<QTd class="text-bold">{{ entriesTotalPallet }}</QTd>
|
||||
<QTd class="text-bold">{{ entriesTotalM3 }}</QTd>
|
||||
</template>
|
||||
</QTable>
|
||||
</QCard>
|
||||
|
||||
<QCard class="full-width" v-if="thermographs.length > 0">
|
||||
<RouterLink
|
||||
class="header"
|
||||
:to="{
|
||||
name: 'TravelThermographsIndex',
|
||||
params: { id: travel.id },
|
||||
}"
|
||||
>
|
||||
{{ t('travel.summary.thermographs') }}
|
||||
<QIcon name="open_in_new" color="primary" />
|
||||
</RouterLink>
|
||||
<QTable
|
||||
:rows="thermographs"
|
||||
:columns="thermographsTableColumns"
|
||||
hide-bottom
|
||||
row-key="id"
|
||||
class="full-width q-mt-md"
|
||||
/>
|
||||
</QCard>
|
||||
</template>
|
||||
</CardSummary>
|
||||
</template>
|
||||
<style lang="scss" scoped></style>
|
||||
|
|
|
@ -0,0 +1,216 @@
|
|||
<script setup>
|
||||
import { computed, ref } from 'vue';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useQuasar } from 'quasar';
|
||||
|
||||
import VnPaginate from 'src/components/ui/VnPaginate.vue';
|
||||
import VnConfirm from 'components/ui/VnConfirm.vue';
|
||||
import FetchData from 'src/components/FetchData.vue';
|
||||
|
||||
import axios from 'axios';
|
||||
import useNotify from 'src/composables/useNotify.js';
|
||||
import { toDate } from 'src/filters';
|
||||
import { downloadFile } from 'src/composables/downloadFile';
|
||||
|
||||
const route = useRoute();
|
||||
const quasar = useQuasar();
|
||||
const router = useRouter();
|
||||
const { t } = useI18n();
|
||||
const { notify } = useNotify();
|
||||
|
||||
const thermographPaginateRef = ref(null);
|
||||
const warehouses = ref([]);
|
||||
|
||||
const thermographFilter = {
|
||||
include: {
|
||||
relation: 'warehouse',
|
||||
scope: {
|
||||
fields: ['id', 'name'],
|
||||
},
|
||||
},
|
||||
where: { travelFk: route.params.id },
|
||||
order: ['created'],
|
||||
};
|
||||
|
||||
const TableColumns = computed(() => {
|
||||
return [
|
||||
{
|
||||
label: t('travel.thermographs.code'),
|
||||
field: 'thermographFk',
|
||||
name: 'thermographFk',
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
label: t('travel.thermographs.temperature'),
|
||||
field: 'temperatureFk',
|
||||
name: 'temperatureFk',
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
label: t('travel.thermographs.state'),
|
||||
field: 'result',
|
||||
name: 'result',
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
label: t('travel.thermographs.destination'),
|
||||
field: 'warehouseFk',
|
||||
name: 'destination',
|
||||
align: 'left',
|
||||
format: (val) =>
|
||||
warehouses.value.find((warehouse) => warehouse.id === val)?.name,
|
||||
},
|
||||
{
|
||||
label: t('travel.thermographs.created'),
|
||||
field: 'created',
|
||||
name: 'created',
|
||||
align: 'left',
|
||||
format: (val) => toDate(val),
|
||||
},
|
||||
{
|
||||
name: 'downloadFile',
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
name: 'editFile',
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
name: 'removeThermograph',
|
||||
align: 'left',
|
||||
},
|
||||
];
|
||||
});
|
||||
|
||||
const openRemoveDialog = async (id) => {
|
||||
quasar
|
||||
.dialog({
|
||||
component: VnConfirm,
|
||||
componentProps: {
|
||||
message: t('Are you sure you want to remove the thermograph?'),
|
||||
},
|
||||
})
|
||||
.onOk(async () => {
|
||||
try {
|
||||
await removeThermograph(id);
|
||||
} catch (err) {
|
||||
console.error('Error removing thermograph');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const redirectToThermographForm = (action, id) => {
|
||||
const routeDetails = {
|
||||
name: action === 'create' ? 'TravelThermographsCreate' : 'TravelThermographsEdit',
|
||||
};
|
||||
|
||||
if (action === 'edit' && id) {
|
||||
const params = {};
|
||||
params.thermographId = id;
|
||||
routeDetails.params = params;
|
||||
}
|
||||
router.push(routeDetails);
|
||||
};
|
||||
|
||||
const removeThermograph = async (id) => {
|
||||
try {
|
||||
await axios.delete(`Travels/deleteThermograph?id=${id}`);
|
||||
await thermographPaginateRef.value.fetch();
|
||||
notify(t('Thermograph removed'), 'positive');
|
||||
} catch (err) {
|
||||
console.error('Error removing termograph');
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<FetchData
|
||||
url="Warehouses"
|
||||
:filter="{ fields: ['id', 'name'] }"
|
||||
order="name"
|
||||
@on-fetch="(data) => (warehouses = data)"
|
||||
auto-load
|
||||
/>
|
||||
<VnPaginate
|
||||
ref="thermographPaginateRef"
|
||||
data-key="TravelThermographs"
|
||||
url="TravelThermographs"
|
||||
:filter="thermographFilter"
|
||||
:params="{ travelFk: route.params.id }"
|
||||
auto-load
|
||||
>
|
||||
<template #body="{ rows }">
|
||||
<QTable
|
||||
:rows="rows"
|
||||
:columns="TableColumns"
|
||||
:no-data-label="t('No results')"
|
||||
:rows-per-page-options="[0]"
|
||||
row-key="id"
|
||||
class="full-width q-mt-md"
|
||||
>
|
||||
<template #body-cell-downloadFile="{ row }">
|
||||
<QTd auto-width>
|
||||
<QIcon
|
||||
name="cloud_download"
|
||||
color="primary"
|
||||
size="sm"
|
||||
class="cursor-pointer"
|
||||
@click="downloadFile(row.dmsFk)"
|
||||
>
|
||||
<QTooltip>{{ t('Download file') }}</QTooltip>
|
||||
</QIcon>
|
||||
</QTd>
|
||||
</template>
|
||||
<template #body-cell-editFile="{ row }">
|
||||
<QTd auto-width>
|
||||
<QIcon
|
||||
name="edit"
|
||||
color="primary"
|
||||
size="sm"
|
||||
class="cursor-pointer"
|
||||
@click="redirectToThermographForm('edit', row.id)"
|
||||
>
|
||||
<QTooltip>{{ t('Edit file') }}</QTooltip>
|
||||
</QIcon>
|
||||
</QTd>
|
||||
</template>
|
||||
<template #body-cell-removeThermograph="{ row }">
|
||||
<QTd auto-width>
|
||||
<QIcon
|
||||
name="delete"
|
||||
color="primary"
|
||||
size="sm"
|
||||
class="cursor-pointer"
|
||||
@click="openRemoveDialog(row.id)"
|
||||
>
|
||||
<QTooltip>{{ t('Remove thermograph') }}</QTooltip>
|
||||
</QIcon>
|
||||
</QTd>
|
||||
</template>
|
||||
</QTable>
|
||||
</template>
|
||||
</VnPaginate>
|
||||
<QPageSticky :offset="[20, 20]">
|
||||
<QBtn
|
||||
fab
|
||||
icon="add"
|
||||
color="primary"
|
||||
@click="redirectToThermographForm('create')"
|
||||
/>
|
||||
<QTooltip class="text-no-wrap">
|
||||
{{ t('Add thermograph') }}
|
||||
</QTooltip>
|
||||
</QPageSticky>
|
||||
</template>
|
||||
|
||||
<i18n>
|
||||
es:
|
||||
Add thermograph: Añadir termógrafo
|
||||
Download file: Descargar fichero
|
||||
Edit file: Editar fichero
|
||||
Remove thermograph: Eliminar termógrafo
|
||||
Thermograph removed: Termógrafo eliminado
|
||||
Are you sure you want to remove the thermograph?: ¿Seguro que quieres quitar el termógrafo?
|
||||
No results: Sin resultados
|
||||
</i18n>
|
|
@ -0,0 +1,348 @@
|
|||
<script setup>
|
||||
jsegarra marked this conversation as resolved
|
||||
import { useI18n } from 'vue-i18n';
|
||||
jsegarra marked this conversation as resolved
jsegarra
commented
Si desde el listado de termógrafos, le das a eliminar te dice:
Si desde el listado de termógrafos, le das a eliminar te dice:
1. Que ha habido un error
2. Que se ha eliminado
3. No elimina el registro de la tabla.
wbuezas
commented
@jsegarra en salix me da el mismo comportamiento que en lilium, por ejemplo si vas a los thermographs del first travel Aparecen 4 registros donde dos te deja borrar exitosamente y dos arroja un error el backend. Adjunto captura tomada de @jsegarra en salix me da el mismo comportamiento que en lilium, por ejemplo si vas a los thermographs del [first travel](http://localhost:9000/travel/3/summary#/travel/1/thermographs/index?limit=10)
Aparecen 4 registros donde dos te deja borrar exitosamente y dos arroja un error el backend.
Adjunto captura tomada de `salix`:
wbuezas
commented
Se fixea el problema de las notificaciones. Commit: Se fixea el problema de las notificaciones.
Commit: https://gitea.verdnatura.es/verdnatura/salix-front/commit/f24b9f5a75e55eb17903482da337d440189bcdb0
jsegarra
commented
1. Si subes un fichero que es de tipo zip por ejemplo sólo te muestra el triangulo de advertencia en un toast rojo.
2. Al crear te redirige a index pero la consola muestra errores. No sé muy bien si es por los errores o por el error que ocurre en mas partes de la aplicación.
3. Darle a eliminar termógrafo, da error porque no se pasa el Id
|
||||
import { reactive, ref, onBeforeMount } from 'vue';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
|
||||
import FetchData from 'components/FetchData.vue';
|
||||
import VnSelectFilter from 'src/components/common/VnSelectFilter.vue';
|
||||
import VnSelectDialog from 'components/common/VnSelectDialog.vue';
|
||||
import VnRow from 'components/ui/VnRow.vue';
|
||||
import VnInput from 'src/components/common/VnInput.vue';
|
||||
import CreateThermographForm from 'src/components/CreateThermographForm.vue';
|
||||
|
||||
import { useState } from 'src/composables/useState';
|
||||
import { useStateStore } from 'stores/useStateStore';
|
||||
import axios from 'axios';
|
||||
import useNotify from 'src/composables/useNotify.js';
|
||||
|
||||
const props = defineProps({
|
||||
viewAction: {
|
||||
type: String,
|
||||
default: 'create',
|
||||
},
|
||||
});
|
||||
|
||||
const stateStore = useStateStore();
|
||||
const { t } = useI18n();
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const state = useState();
|
||||
const { notify } = useNotify();
|
||||
|
||||
const thermographFilter = {
|
||||
fields: ['thermographFk'],
|
||||
where: {
|
||||
travelFk: null,
|
||||
},
|
||||
order: 'thermographFk ASC',
|
||||
};
|
||||
const fetchTravelThermographsRef = ref(null);
|
||||
const allowedContentTypes = ref('');
|
||||
const user = state.getUser();
|
||||
const thermographsOptions = ref([]);
|
||||
const dmsTypesOptions = ref([]);
|
||||
const companiesOptions = ref([]);
|
||||
const warehousesOptions = ref([]);
|
||||
const inputFileRef = ref(null);
|
||||
|
||||
const thermographForm = reactive({
|
||||
thermographId: null,
|
||||
state: null,
|
||||
reference: null,
|
||||
dmsTypeId: null,
|
||||
companyId: null,
|
||||
warehouseId: null,
|
||||
files: [],
|
||||
description: null,
|
||||
});
|
||||
|
||||
onBeforeMount(async () => {
|
||||
if (props.viewAction === 'create') {
|
||||
setCreateDefaultParams();
|
||||
} else {
|
||||
await setEditDefaultParams();
|
||||
}
|
||||
|
||||
if (route.query.thermographData) {
|
||||
const thermographData = JSON.parse(route.query.thermographData);
|
||||
for (let key in thermographForm) {
|
||||
thermographForm[key] = thermographData[key];
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const fetchDmsTypes = async () => {
|
||||
try {
|
||||
const params = {
|
||||
filter: {
|
||||
where: { code: 'miscellaneous' },
|
||||
},
|
||||
};
|
||||
const { data } = await axios.get('DmsTypes/findOne', { params });
|
||||
return data;
|
||||
} catch (err) {
|
||||
console.error('Error fetching Dms Types');
|
||||
}
|
||||
};
|
||||
|
||||
const setCreateDefaultParams = async () => {
|
||||
const dataResponse = await fetchDmsTypes();
|
||||
thermographForm.companyId = user.value.companyFk;
|
||||
thermographForm.warehouseId = user.value.warehouseFk;
|
||||
thermographForm.reference = route.params.id;
|
||||
thermographForm.dmsTypeId = dataResponse.id;
|
||||
thermographForm.state = 'Ok';
|
||||
thermographForm.description = t('travel.thermographs.travelFileDescription', {
|
||||
travelId: route.params.id,
|
||||
}).toUpperCase();
|
||||
};
|
||||
|
||||
const setEditDefaultParams = async () => {
|
||||
try {
|
||||
const filterObj = { include: { relation: 'dms' } };
|
||||
const filter = encodeURIComponent(JSON.stringify(filterObj));
|
||||
const { data } = await axios.get(
|
||||
`TravelThermographs/${route.params.thermographId}?filter=${filter}`
|
||||
);
|
||||
|
||||
if (data) {
|
||||
thermographForm.thermographId = data.thermographFk;
|
||||
thermographForm.state = data.result;
|
||||
thermographForm.reference = data.dms?.reference;
|
||||
thermographForm.warehouseId = data.dms?.warehouseFk;
|
||||
thermographForm.companyId = data.dms?.companyFk;
|
||||
thermographForm.dmsTypeId = data.dms?.dmsTypeFk;
|
||||
thermographForm.description = data.dms?.description || '';
|
||||
thermographForm.hasFile = data.dms?.hasFile;
|
||||
thermographForm.hasFileAttached = false;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Error fetching termograph');
|
||||
}
|
||||
};
|
||||
|
||||
const onSubmit = () => {
|
||||
props.viewAction === 'create' ? createThermograph() : updateThermograph();
|
||||
};
|
||||
|
||||
const createThermograph = async () => {
|
||||
const formData = new FormData();
|
||||
|
||||
thermographForm.files.forEach((file) => {
|
||||
formData.append(file.name, file);
|
||||
});
|
||||
|
||||
try {
|
||||
await axios.post(`/travels/${route.params.id}/createThermograph`, formData, {
|
||||
params: thermographForm,
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
},
|
||||
});
|
||||
router.push({ name: 'TravelThermographsIndex' });
|
||||
notify(t('Thermograph created'), 'positive');
|
||||
} catch (error) {
|
||||
console.error('Error creating thermograph');
|
||||
}
|
||||
};
|
||||
|
||||
const updateThermograph = async () => {
|
||||
const formData = new FormData();
|
||||
|
||||
thermographForm.files.forEach((file) => {
|
||||
formData.append(file.name, file);
|
||||
});
|
||||
|
||||
try {
|
||||
await axios.post(`travels/${route.params.id}/updateThermograph`, formData, {
|
||||
params: thermographForm,
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
},
|
||||
});
|
||||
router.push({ name: 'TravelThermographsIndex' });
|
||||
notify(t('Thermograph created'), 'positive');
|
||||
} catch (error) {
|
||||
console.error('Error creating thermograph');
|
||||
}
|
||||
};
|
||||
|
||||
const onThermographCreated = async (data) => {
|
||||
await fetchTravelThermographsRef.value.fetch();
|
||||
thermographForm.thermographId = data.thermographId;
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<FetchData
|
||||
url="DmsContainers/allowedContentTypes"
|
||||
@on-fetch="(data) => (allowedContentTypes = data.join(', '))"
|
||||
auto-load
|
||||
/>
|
||||
<FetchData
|
||||
ref="fetchTravelThermographsRef"
|
||||
url="TravelThermographs"
|
||||
@on-fetch="(data) => (thermographsOptions = data)"
|
||||
:filter="thermographFilter"
|
||||
auto-load
|
||||
/>
|
||||
<FetchData
|
||||
url="DmsTypes"
|
||||
:filter="{ order: 'name' }"
|
||||
@on-fetch="(data) => (dmsTypesOptions = data)"
|
||||
auto-load
|
||||
/>
|
||||
<FetchData
|
||||
url="Companies"
|
||||
@on-fetch="(data) => (companiesOptions = data)"
|
||||
:filter="{ order: 'code' }"
|
||||
auto-load
|
||||
/>
|
||||
<FetchData
|
||||
url="Warehouses"
|
||||
@on-fetch="(data) => (warehousesOptions = data)"
|
||||
:filter="{ order: 'name' }"
|
||||
auto-load
|
||||
/>
|
||||
<QPage class="column items-center full-width">
|
||||
<QForm
|
||||
model="travel"
|
||||
:form-initial-data="thermographForm"
|
||||
:observe-form-changes="viewAction === 'create'"
|
||||
:default-actions="true"
|
||||
@submit="onSubmit()"
|
||||
class="full-width"
|
||||
style="max-width: 800px"
|
||||
>
|
||||
<Teleport to="#st-actions" v-if="stateStore?.isSubToolbarShown()">
|
||||
<div>
|
||||
<QBtnGroup push class="q-gutter-x-sm">
|
||||
<slot name="moreActions" />
|
||||
<QBtn
|
||||
color="primary"
|
||||
icon="restart_alt"
|
||||
flat
|
||||
@click="reset()"
|
||||
:label="t('globals.reset')"
|
||||
/>
|
||||
<QBtn
|
||||
color="primary"
|
||||
icon="save"
|
||||
@click="onSubmit()"
|
||||
:label="t('globals.save')"
|
||||
/>
|
||||
</QBtnGroup>
|
||||
</div>
|
||||
</Teleport>
|
||||
<QCard class="q-pa-lg">
|
||||
jsegarra marked this conversation as resolved
jsegarra
commented
No hay opción de crear termógrafo No hay opción de crear termógrafo
Y por tanto no se puede evaluar el diálogo
wbuezas
commented
Probe y pude acceder con el boton Probe y pude acceder con el boton `(+)` que esta abajo a la derecha, que se encuentra en la vista de `TravelThermographs`, no te aparecio a vos?
wbuezas
commented
@jsegarra ahora si, cree el form necesario para crear un Ademas de esto que era el requerimiento principal, implemente algunas cosas como:
Commit: @jsegarra ahora si, cree el form necesario para crear un `thermograph` y lo aplique al input correspondiente.
Ademas de esto que era el requerimiento principal, implemente algunas cosas como:
- Un estado de error en los inputs `VnInput` y `VnSelectFilter` cuando se le agrega la prop `:required="true"`
- Algunas traducciones al objeto global para reutilizar
- Implementacion del icon `(i)` con informacion sobre los tipos de files aceptados por el input `QFile` en el componente `TravelThermographsForm`
Commit: https://gitea.verdnatura.es/verdnatura/salix-front/commit/c67f4cf858897cd2684946f44bd02c6eae808c68
jsegarra
commented
Se ve mal. Esto creo que ya nos pasó en otra PR antigua, creo que PR-3 Se ve mal. Esto creo que ya nos pasó en otra PR antigua, creo que PR-3
jsegarra
commented
Falta traducir el título del modal Falta traducir el título del modal
wbuezas
commented
Listo! Ambos comentarios corregidos. Además de esto me atreví a implementar la posibilidad de agregar un Commit: Listo! Ambos comentarios corregidos.
Además de esto me atreví a implementar la posibilidad de agregar un `Tooltip` al ícono de acción del input `VnSelectDialog` si se desea
Commit: https://gitea.verdnatura.es/verdnatura/salix-front/commit/1b316573385f08d51a2b8279ace91d71732fb6d6
|
||||
<VnRow class="row q-gutter-md q-mb-md">
|
||||
<div class="col">
|
||||
<VnSelectDialog
|
||||
:label="t('travel.thermographs.thermograph')"
|
||||
v-model="thermographForm.thermographId"
|
||||
:options="thermographsOptions"
|
||||
option-value="thermographFk"
|
||||
option-label="thermographFk"
|
||||
:disable="viewAction === 'edit'"
|
||||
:tooltip="t('New thermograph')"
|
||||
>
|
||||
<template #form>
|
||||
<CreateThermographForm
|
||||
@on-data-saved="onThermographCreated($event, data)"
|
||||
/>
|
||||
</template>
|
||||
</VnSelectDialog>
|
||||
</div>
|
||||
<div class="col">
|
||||
<VnInput
|
||||
v-model="thermographForm.state"
|
||||
:label="t('travel.thermographs.state')"
|
||||
/>
|
||||
</div>
|
||||
</VnRow>
|
||||
<VnRow class="row q-gutter-md q-mb-md">
|
||||
<div class="col">
|
||||
<VnInput
|
||||
v-model="thermographForm.reference"
|
||||
:label="t('travel.thermographs.reference')"
|
||||
/>
|
||||
</div>
|
||||
<div class="col">
|
||||
<VnSelectFilter
|
||||
:label="t('travel.thermographs.type')"
|
||||
v-model="thermographForm.dmsTypeId"
|
||||
:options="dmsTypesOptions"
|
||||
option-value="id"
|
||||
option-label="name"
|
||||
/>
|
||||
</div>
|
||||
</VnRow>
|
||||
<VnRow class="row q-gutter-md q-mb-md">
|
||||
<div class="col">
|
||||
<VnSelectFilter
|
||||
:label="t('travel.thermographs.company')"
|
||||
v-model="thermographForm.companyId"
|
||||
:options="companiesOptions"
|
||||
option-value="id"
|
||||
option-label="code"
|
||||
/>
|
||||
</div>
|
||||
<div class="col">
|
||||
<VnSelectFilter
|
||||
:label="t('travel.thermographs.warehouse')"
|
||||
v-model="thermographForm.warehouseId"
|
||||
:options="warehousesOptions"
|
||||
option-value="id"
|
||||
option-label="name"
|
||||
/>
|
||||
</div>
|
||||
</VnRow>
|
||||
<VnRow v-if="viewAction === 'edit'" class="row q-gutter-md q-mb-md">
|
||||
jsegarra marked this conversation as resolved
Outdated
jsegarra
commented
El icono del clip debería funcionar como cuando haces clic en el input. El icono del clip debería funcionar como cuando haces clic en el input.
Esto está subsanado en varios sitios.
wbuezas
commented
Corregido. Commit: Corregido.
Commit: https://gitea.verdnatura.es/verdnatura/salix-front/commit/c8153b641463dced58dc2e31a99744823d6c259c
|
||||
<div class="col">
|
||||
<QInput
|
||||
:label="t('travel.thermographs.description')"
|
||||
type="textarea"
|
||||
v-model="thermographForm.description"
|
||||
fill-input
|
||||
/>
|
||||
</div>
|
||||
</VnRow>
|
||||
<VnRow class="row q-gutter-md q-mb-md">
|
||||
<div class="col">
|
||||
<QFile
|
||||
ref="inputFileRef"
|
||||
:label="t('travel.thermographs.file')"
|
||||
multiple
|
||||
:accept="allowedContentTypes"
|
||||
v-model="thermographForm.files"
|
||||
>
|
||||
<template #append>
|
||||
<QIcon
|
||||
name="vn:attach"
|
||||
class="cursor-pointer q-mr-sm"
|
||||
@click="inputFileRef.pickFiles()"
|
||||
>
|
||||
<QTooltip>{{ t('Select files') }}</QTooltip>
|
||||
</QIcon>
|
||||
<QIcon name="info" class="cursor-pointer">
|
||||
<QTooltip>{{
|
||||
t('globals.allowedFilesText', {
|
||||
allowedContentTypes: allowedContentTypes,
|
||||
})
|
||||
}}</QTooltip>
|
||||
</QIcon>
|
||||
</template>
|
||||
</QFile>
|
||||
</div>
|
||||
</VnRow>
|
||||
</QCard>
|
||||
</QForm>
|
||||
</QPage>
|
||||
</template>
|
||||
|
||||
<i18n>
|
||||
es:
|
||||
Select files: Selecciona ficheros
|
||||
Thermograph created: Termógrafo creado
|
||||
New thermograph: Nuevo termógrafo
|
||||
</i18n>
|
|
@ -16,8 +16,8 @@ import { toCurrency } from 'src/filters';
|
|||
import { useArrayData } from 'composables/useArrayData';
|
||||
import { toDate } from 'src/filters';
|
||||
import { usePrintService } from 'composables/usePrintService';
|
||||
import travelService from 'src/services/travel.service';
|
||||
import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
|
||||
import axios from 'axios';
|
||||
|
||||
const router = useRouter();
|
||||
const stateStore = useStateStore();
|
||||
|
@ -223,9 +223,13 @@ const openReportPdf = () => {
|
|||
};
|
||||
|
||||
const saveFieldValue = async (val, field, index) => {
|
||||
const id = rows.value[index].id;
|
||||
const params = { [field]: val };
|
||||
await travelService.updateTravel(id, params);
|
||||
try {
|
||||
const id = rows.value[index].id;
|
||||
const params = { [field]: val };
|
||||
await axios.patch(`Travels/${id}`, params);
|
||||
} catch (err) {
|
||||
console.error('Error updating travel');
|
||||
}
|
||||
};
|
||||
|
||||
const navigateToTravelId = (id) => {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<script setup>
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { reactive, ref, onBeforeMount } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
|
||||
import FetchData from 'components/FetchData.vue';
|
||||
import VnSelectFilter from 'src/components/common/VnSelectFilter.vue';
|
||||
|
@ -9,10 +9,11 @@ import FormModel from 'components/FormModel.vue';
|
|||
import VnRow from 'components/ui/VnRow.vue';
|
||||
import VnInput from 'src/components/common/VnInput.vue';
|
||||
import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
|
||||
import { toDate } from 'src/filters';
|
||||
import VnInputDate from 'components/common/VnInputDate.vue';
|
||||
|
||||
const { t } = useI18n();
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
const newTravelForm = reactive({
|
||||
ref: null,
|
||||
|
@ -35,14 +36,14 @@ onBeforeMount(() => {
|
|||
if (route.query.travelData) {
|
||||
const travelData = JSON.parse(route.query.travelData);
|
||||
for (let key in newTravelForm) {
|
||||
if (key === 'landed' || key === 'shipped') {
|
||||
newTravelForm[key] = travelData[key].substring(0, 10);
|
||||
} else {
|
||||
newTravelForm[key] = travelData[key];
|
||||
}
|
||||
newTravelForm[key] = travelData[key];
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const redirectToTravelBasicData = (_, { id }) => {
|
||||
router.push({ name: 'TravelBasicData', params: { id } });
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -63,6 +64,7 @@ onBeforeMount(() => {
|
|||
model="travel"
|
||||
:form-initial-data="newTravelForm"
|
||||
:observe-form-changes="viewAction === 'create'"
|
||||
@on-data-saved="redirectToTravelBasicData"
|
||||
>
|
||||
<template #form="{ data }">
|
||||
<VnRow class="row q-gutter-md q-mb-md">
|
||||
|
@ -82,62 +84,13 @@ onBeforeMount(() => {
|
|||
</VnRow>
|
||||
<VnRow class="row q-gutter-md q-mb-md">
|
||||
<div class="col">
|
||||
<QInput
|
||||
rounded
|
||||
placeholder="dd-mm-aaa"
|
||||
<VnInputDate
|
||||
v-model="data.shipped"
|
||||
:label="t('globals.shipped')"
|
||||
:model-value="toDate(data.shipped)"
|
||||
>
|
||||
<template #append>
|
||||
<QIcon name="event" class="cursor-pointer">
|
||||
<QPopupProxy
|
||||
cover
|
||||
transition-show="scale"
|
||||
transition-hide="scale"
|
||||
>
|
||||
<QDate v-model="data.shipped">
|
||||
<div class="row items-center justify-end">
|
||||
<QBtn
|
||||
v-close-popup
|
||||
:label="t('globals.close')"
|
||||
color="primary"
|
||||
flat
|
||||
/>
|
||||
</div>
|
||||
</QDate>
|
||||
</QPopupProxy>
|
||||
</QIcon>
|
||||
</template>
|
||||
</QInput>
|
||||
/>
|
||||
</div>
|
||||
<div class="col">
|
||||
<QInput
|
||||
rounded
|
||||
placeholder="dd-mm-aaa"
|
||||
:label="t('globals.landed')"
|
||||
:model-value="toDate(data.landed)"
|
||||
>
|
||||
<template #append>
|
||||
<QIcon name="event" class="cursor-pointer">
|
||||
<QPopupProxy
|
||||
cover
|
||||
transition-show="scale"
|
||||
transition-hide="scale"
|
||||
>
|
||||
<QDate v-model="data.landed">
|
||||
<div class="row items-center justify-end">
|
||||
<QBtn
|
||||
v-close-popup
|
||||
:label="t('globals.close')"
|
||||
color="primary"
|
||||
flat
|
||||
/>
|
||||
</div>
|
||||
</QDate>
|
||||
</QPopupProxy>
|
||||
</QIcon>
|
||||
</template>
|
||||
</QInput>
|
||||
<VnInputDate :label="t('globals.landed')" v-model="data.landed" />
|
||||
</div>
|
||||
</VnRow>
|
||||
<VnRow class="row q-gutter-md q-mb-md">
|
||||
|
|
|
@ -6,8 +6,7 @@ import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
|
|||
import VnSelectFilter from 'src/components/common/VnSelectFilter.vue';
|
||||
import VnInput from 'src/components/common/VnInput.vue';
|
||||
import FetchData from 'components/FetchData.vue';
|
||||
|
||||
import { toDate } from 'src/filters';
|
||||
import VnInputDate from 'components/common/VnInputDate.vue';
|
||||
|
||||
const { t } = useI18n();
|
||||
const props = defineProps({
|
||||
|
@ -60,7 +59,7 @@ const decrement = (paramsObj, key) => {
|
|||
<span>{{ formatFn(tag.value) }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<template #body="{ params }">
|
||||
<template #body="{ params, searchFn }">
|
||||
<QItem>
|
||||
<QItemSection>
|
||||
<VnInput
|
||||
|
@ -75,6 +74,7 @@ const decrement = (paramsObj, key) => {
|
|||
<VnSelectFilter
|
||||
:label="t('params.agencyModeFk')"
|
||||
v-model="params.agencyModeFk"
|
||||
@update:model-value="searchFn()"
|
||||
:options="agenciesOptions"
|
||||
option-value="agencyFk"
|
||||
option-label="name"
|
||||
|
@ -90,6 +90,7 @@ const decrement = (paramsObj, key) => {
|
|||
<VnSelectFilter
|
||||
:label="t('params.warehouseOutFk')"
|
||||
v-model="params.warehouseOutFk"
|
||||
@update:model-value="searchFn()"
|
||||
:options="warehousesOptions"
|
||||
option-value="id"
|
||||
option-label="name"
|
||||
|
@ -105,6 +106,7 @@ const decrement = (paramsObj, key) => {
|
|||
<VnSelectFilter
|
||||
:label="t('params.warehouseInFk')"
|
||||
v-model="params.warehouseInFk"
|
||||
@update:model-value="searchFn()"
|
||||
:options="warehousesOptions"
|
||||
option-value="id"
|
||||
option-label="name"
|
||||
|
@ -147,68 +149,20 @@ const decrement = (paramsObj, key) => {
|
|||
</QItem>
|
||||
<QItem>
|
||||
<QItemSection>
|
||||
<QInput
|
||||
dense
|
||||
outlined
|
||||
rounded
|
||||
placeholder="dd-mm-aaa"
|
||||
<VnInputDate
|
||||
v-model="params.landedFrom"
|
||||
:label="t('params.landedFrom')"
|
||||
:model-value="toDate(params.landedFrom)"
|
||||
>
|
||||
<template #append>
|
||||
<QIcon name="event" class="cursor-pointer">
|
||||
<QPopupProxy
|
||||
cover
|
||||
transition-show="scale"
|
||||
transition-hide="scale"
|
||||
>
|
||||
<QDate v-model="params.landedFrom">
|
||||
<div class="row items-center justify-end">
|
||||
<QBtn
|
||||
v-close-popup
|
||||
:label="t('globals.close')"
|
||||
color="primary"
|
||||
flat
|
||||
/>
|
||||
</div>
|
||||
</QDate>
|
||||
</QPopupProxy>
|
||||
</QIcon>
|
||||
</template>
|
||||
</QInput>
|
||||
is-outlined
|
||||
/>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
<QItem>
|
||||
<QItemSection>
|
||||
<QInput
|
||||
dense
|
||||
outlined
|
||||
rounded
|
||||
placeholder="dd-mm-aaa"
|
||||
:model-value="toDate(params.landedTo)"
|
||||
<VnInputDate
|
||||
:label="t('params.landedTo')"
|
||||
>
|
||||
<template #append>
|
||||
<QIcon name="event" class="cursor-pointer">
|
||||
<QPopupProxy
|
||||
cover
|
||||
transition-show="scale"
|
||||
transition-hide="scale"
|
||||
>
|
||||
<QDate v-model="params.landedTo">
|
||||
<div class="row items-center justify-end">
|
||||
<QBtn
|
||||
v-close-popup
|
||||
:label="t('globals.close')"
|
||||
color="primary"
|
||||
flat
|
||||
/>
|
||||
</div>
|
||||
</QDate>
|
||||
</QPopupProxy>
|
||||
</QIcon>
|
||||
</template>
|
||||
</QInput>
|
||||
v-model="params.landedTo"
|
||||
is-outlined
|
||||
/>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
<QItem>
|
||||
|
@ -216,6 +170,7 @@ const decrement = (paramsObj, key) => {
|
|||
<VnSelectFilter
|
||||
:label="t('params.continent')"
|
||||
v-model="params.continent"
|
||||
@update:model-value="searchFn()"
|
||||
:options="continentsOptions"
|
||||
option-value="code"
|
||||
option-label="name"
|
||||
|
@ -261,18 +216,6 @@ const decrement = (paramsObj, key) => {
|
|||
</VnFilterPanel>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.input-number >>> input[type='number'] {
|
||||
-moz-appearance: textfield;
|
||||
}
|
||||
.input-number >>> input::-webkit-outer-spin-button,
|
||||
.input-number >>> input::-webkit-inner-spin-button {
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
<i18n>
|
||||
en:
|
||||
params:
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script setup>
|
||||
jsegarra marked this conversation as resolved
jsegarra
commented
Cuando pulsas en un detalle de un travel, se muestra el dialogo.
Cuando pulsas en un detalle de un travel, se muestra el dialogo.
Si pulsas sobre el primer icono:
1. No tiene tooltip
2. Redirige a salix y no a lilium. @alexm es correcto?
3. Redirige mal, pues le falta el summary después.
wbuezas
commented
Corregido. Commit: Corregido.
Commit: https://gitea.verdnatura.es/verdnatura/salix-front/commit/4dc31bfdcec15f752a40ef88df4fd70282230a29
jsegarra
commented
1 y 3 OK 1 y 3 OK
|
||||
import { onMounted } from 'vue';
|
||||
import { onMounted, ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useRouter } from 'vue-router';
|
||||
import VnPaginate from 'src/components/ui/VnPaginate.vue';
|
||||
|
@ -7,6 +7,8 @@ import CardList from 'src/components/ui/CardList.vue';
|
|||
import VnLv from 'src/components/ui/VnLv.vue';
|
||||
import TravelSummary from './Card/TravelSummary.vue';
|
||||
import TravelFilter from './TravelFilter.vue';
|
||||
import FetchData from 'components/FetchData.vue';
|
||||
|
||||
import { useStateStore } from 'stores/useStateStore';
|
||||
import { toDate } from 'src/filters/index';
|
||||
import { useSummaryDialog } from 'src/composables/useSummaryDialog';
|
||||
|
@ -16,6 +18,8 @@ const { t } = useI18n();
|
|||
const stateStore = useStateStore();
|
||||
const { viewSummary } = useSummaryDialog();
|
||||
|
||||
const warehouses = ref([]);
|
||||
|
||||
const navigateToTravelId = (id) => {
|
||||
router.push({ path: `/travel/${id}` });
|
||||
};
|
||||
|
@ -33,12 +37,35 @@ const redirectCreateEntryView = (travelData) => {
|
|||
router.push({ name: 'EntryCreate', query: { travelFk: travelData.id } });
|
||||
};
|
||||
|
||||
const getWarehouseName = (id) => {
|
||||
return warehouses.value.find((warehouse) => warehouse.id === id).name;
|
||||
};
|
||||
|
||||
const getDateQBadgeColor = (date) => {
|
||||
let today = Date.vnNew();
|
||||
today.setHours(0, 0, 0, 0);
|
||||
|
||||
date = new Date(date);
|
||||
date.setHours(0, 0, 0, 0);
|
||||
|
||||
const timeDifference = today - date;
|
||||
if (timeDifference == 0) return 'warning';
|
||||
if (timeDifference < 0) return 'success';
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
stateStore.rightDrawer = true;
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<FetchData
|
||||
url="Warehouses"
|
||||
:filter="{ fields: ['id', 'name'] }"
|
||||
order="name"
|
||||
@on-fetch="(data) => (warehouses = data)"
|
||||
auto-load
|
||||
/>
|
||||
<QDrawer v-model="stateStore.rightDrawer" side="right" :width="256" show-if-above>
|
||||
<QScrollArea class="fit text-grey-8">
|
||||
<TravelFilter data-key="TravelList" />
|
||||
|
@ -66,22 +93,43 @@ onMounted(async () => {
|
|||
:value="row.agencyModeName"
|
||||
/>
|
||||
<VnLv
|
||||
v-if="warehouses.length > 0"
|
||||
:label="t('globals.wareHouseOut')"
|
||||
:value="row.warehouseOutFk"
|
||||
/>
|
||||
<VnLv
|
||||
:label="t('globals.shipped')"
|
||||
:value="toDate(row.shipped)"
|
||||
/>
|
||||
<VnLv
|
||||
:label="t('globals.landed')"
|
||||
:value="toDate(row.landed)"
|
||||
:value="getWarehouseName(row.warehouseOutFk)"
|
||||
/>
|
||||
<VnLv :label="t('globals.shipped')">
|
||||
<template #value>
|
||||
<QBadge
|
||||
v-if="getDateQBadgeColor(row.shipped)"
|
||||
:color="getDateQBadgeColor(row.shipped)"
|
||||
class="q-ma-none"
|
||||
dense
|
||||
style="font-size: 14px"
|
||||
>
|
||||
{{ toDate(row.shipped) }}
|
||||
</QBadge>
|
||||
<span v-else>{{ toDate(row.shipped) }}</span>
|
||||
</template>
|
||||
</VnLv>
|
||||
<VnLv :label="t('globals.landed')">
|
||||
<template #value>
|
||||
<QBadge
|
||||
v-if="getDateQBadgeColor(row.landed)"
|
||||
:color="getDateQBadgeColor(row.landed)"
|
||||
class="q-ma-none"
|
||||
dense
|
||||
style="font-size: 14px"
|
||||
>
|
||||
{{ toDate(row.landed) }}
|
||||
</QBadge>
|
||||
<span v-else>{{ toDate(row.landed) }}</span>
|
||||
</template>
|
||||
</VnLv>
|
||||
<VnLv
|
||||
v-if="warehouses.length > 0"
|
||||
:label="t('globals.wareHouseIn')"
|
||||
:value="row.warehouseInFk"
|
||||
:value="getWarehouseName(row.warehouseInFk)"
|
||||
/>
|
||||
|
||||
<VnLv
|
||||
:label="t('globals.totalEntries')"
|
||||
:value="row.totalEntries"
|
||||
|
@ -125,9 +173,6 @@ onMounted(async () => {
|
|||
en:
|
||||
addEntry: Add entry
|
||||
|
||||
|
||||
es:
|
||||
addEntry: Añadir entrada
|
||||
|
||||
|
||||
</i18n>
|
||||
|
|
|
@ -43,7 +43,6 @@ export default {
|
|||
name: 'TravelCreate',
|
||||
meta: {
|
||||
title: 'travelCreate',
|
||||
icon: '',
|
||||
},
|
||||
component: () => import('src/pages/Travel/TravelCreate.vue'),
|
||||
},
|
||||
|
@ -69,9 +68,8 @@ export default {
|
|||
meta: {
|
||||
title: 'basicData',
|
||||
icon: 'vn:settings',
|
||||
// roles: [],
|
||||
},
|
||||
// component: () => import(),
|
||||
component: () => import('src/pages/Travel/Card/TravelBasicData.vue'),
|
||||
},
|
||||
{
|
||||
name: 'TravelHistory',
|
||||
|
@ -79,19 +77,45 @@ export default {
|
|||
meta: {
|
||||
title: 'history',
|
||||
icon: 'history',
|
||||
// roles: [],
|
||||
},
|
||||
// component: () => import(),
|
||||
component: () => import('src/pages/Travel/Card/TravelLog.vue'),
|
||||
},
|
||||
{
|
||||
name: 'TravelThermographs',
|
||||
path: 'thermographs',
|
||||
path: 'thermographs/:thermographId?',
|
||||
meta: {
|
||||
title: 'thermographs',
|
||||
icon: 'vn:thermometer',
|
||||
// roles: [],
|
||||
},
|
||||
// component: () => import(),
|
||||
redirect: {
|
||||
name: 'TravelThermographsIndex',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
name: 'TravelThermographsIndex',
|
||||
path: 'index',
|
||||
component: () =>
|
||||
import('src/pages/Travel/Card/TravelThermographs.vue'),
|
||||
},
|
||||
{
|
||||
name: 'TravelThermographsCreate',
|
||||
path: 'create',
|
||||
props: { viewAction: 'create' },
|
||||
component: () =>
|
||||
import(
|
||||
'src/pages/Travel/Card/TravelThermographsForm.vue'
|
||||
),
|
||||
},
|
||||
{
|
||||
name: 'TravelThermographsEdit',
|
||||
path: 'edit',
|
||||
props: { viewAction: 'edit' },
|
||||
component: () =>
|
||||
import(
|
||||
'src/pages/Travel/Card/TravelThermographsForm.vue'
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
import axios from 'axios';
|
||||
|
||||
const travelService = {
|
||||
getTravelEntries: async (param) => {
|
||||
try {
|
||||
return await axios.get(`Travels/${param}/getEntries`);
|
||||
} catch (err) {
|
||||
console.error(`Error fetching travel entries`, err);
|
||||
return err.response;
|
||||
}
|
||||
},
|
||||
|
||||
updateTravel: async (id, params) => {
|
||||
try {
|
||||
return await axios.patch(`Travels/${id}`, params);
|
||||
} catch (err) {
|
||||
console.error(`Error updating travel`, err);
|
||||
return err.response;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export default travelService;
|
Desde el listado de termógrafos, si le das a editar te muestra el formulario pero:
. Como puedes ver tienes [object%20Object]
Corregido.
Commit:
770f17a362