forked from verdnatura/salix-front
Merge pull request 'Travel section' (#11) from feature/ms-22-Travels into dev
Reviewed-on: hyervoni/salix-front-mindshore#11
This commit is contained in:
commit
dcdce926f4
|
@ -0,0 +1,33 @@
|
||||||
|
/**
|
||||||
|
* Filtra las opciones basadas en un valor de entrada y actualiza las opciones filtradas.
|
||||||
|
*
|
||||||
|
* @param {string} val - El valor de entrada para filtrar las opciones. (la emite el evento @filter del componente QSelect)
|
||||||
|
* @param {Function} update - Función de actualización que debe ser llamada para actualizar las opciones filtradas.(la provee el evento @filter del componente QSelect)
|
||||||
|
* @param {Function} abort - Función que puede ser llamada para abortar o cancelar el filtrado actual. (la provee el evento @filter del componente QSelect)
|
||||||
|
* @param {Object} optionsToFilter - Objeto que contiene las opciones originales y filtradas.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function normalizeString(text) {
|
||||||
|
return text
|
||||||
|
.toLowerCase()
|
||||||
|
.normalize('NFD')
|
||||||
|
.replace(/[\u0300-\u036f]/g, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function inputSelectFilter(val, update, abort, optionsToFilter) {
|
||||||
|
if (val === '') {
|
||||||
|
update(() => {
|
||||||
|
optionsToFilter.filtered = JSON.parse(
|
||||||
|
JSON.stringify(optionsToFilter.original)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
update(() => {
|
||||||
|
const searchQuery = val.toLowerCase();
|
||||||
|
optionsToFilter.filtered = optionsToFilter.original.filter((option) =>
|
||||||
|
normalizeString(option.label).includes(normalizeString(searchQuery))
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
|
@ -441,14 +441,14 @@ export default {
|
||||||
parking: 'Parking',
|
parking: 'Parking',
|
||||||
priority: 'Priority',
|
priority: 'Priority',
|
||||||
worker: 'Worker',
|
worker: 'Worker',
|
||||||
recyclable: 'Recyclable'
|
recyclable: 'Recyclable',
|
||||||
},
|
},
|
||||||
basicData: {
|
basicData: {
|
||||||
code: 'Code',
|
code: 'Code',
|
||||||
parking: 'Parking',
|
parking: 'Parking',
|
||||||
priority: 'Priority',
|
priority: 'Priority',
|
||||||
recyclable: 'Recyclable'
|
recyclable: 'Recyclable',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
worker: {
|
worker: {
|
||||||
pageTitles: {
|
pageTitles: {
|
||||||
|
@ -607,6 +607,41 @@ export default {
|
||||||
supplierName: 'Supplier name',
|
supplierName: 'Supplier name',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
travel: {
|
||||||
|
shared: {
|
||||||
|
reference: 'Reference',
|
||||||
|
agency: 'Agency',
|
||||||
|
wareHouseOut: 'Warehouse Out',
|
||||||
|
wareHouseIn: 'Warehouse In',
|
||||||
|
landed: 'Landed',
|
||||||
|
shipped: 'Shipped',
|
||||||
|
totalEntries: 'Total entries',
|
||||||
|
},
|
||||||
|
pageTitles: {
|
||||||
|
travel: 'Travels',
|
||||||
|
list: 'List',
|
||||||
|
create: 'Create',
|
||||||
|
summary: 'Summary',
|
||||||
|
},
|
||||||
|
list: {
|
||||||
|
clone: 'Clone',
|
||||||
|
addEntry: 'Add entry',
|
||||||
|
preview: 'Preview',
|
||||||
|
},
|
||||||
|
summary: {
|
||||||
|
confirmed: 'Confirmed',
|
||||||
|
entryId: 'Entry Id',
|
||||||
|
supplier: 'Supplier',
|
||||||
|
freight: 'Freight',
|
||||||
|
package: 'Package',
|
||||||
|
delivered: 'Delivered',
|
||||||
|
received: 'Received',
|
||||||
|
entries: 'Entries',
|
||||||
|
cloneShipping: 'Clone travel',
|
||||||
|
CloneTravelAndEntries: 'Clone travel and his entries',
|
||||||
|
AddEntry: 'Add entry',
|
||||||
|
},
|
||||||
|
},
|
||||||
components: {
|
components: {
|
||||||
topbar: {},
|
topbar: {},
|
||||||
userPanel: {
|
userPanel: {
|
||||||
|
|
|
@ -443,14 +443,14 @@ export default {
|
||||||
parking: 'Parking',
|
parking: 'Parking',
|
||||||
priority: 'Prioridad',
|
priority: 'Prioridad',
|
||||||
worker: 'Trabajador',
|
worker: 'Trabajador',
|
||||||
recyclable: 'Reciclable'
|
recyclable: 'Reciclable',
|
||||||
},
|
},
|
||||||
basicData: {
|
basicData: {
|
||||||
code: 'Código',
|
code: 'Código',
|
||||||
parking: 'Parking',
|
parking: 'Parking',
|
||||||
priority: 'Prioridad',
|
priority: 'Prioridad',
|
||||||
recyclable: 'Reciclable'
|
recyclable: 'Reciclable',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
worker: {
|
worker: {
|
||||||
pageTitles: {
|
pageTitles: {
|
||||||
|
@ -609,6 +609,41 @@ export default {
|
||||||
supplierName: 'Nombre del proveedor',
|
supplierName: 'Nombre del proveedor',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
travel: {
|
||||||
|
shared: {
|
||||||
|
reference: 'Referencia',
|
||||||
|
agency: 'Agencia',
|
||||||
|
wareHouseOut: 'Alm. salida',
|
||||||
|
wareHouseIn: 'Alm. entrada',
|
||||||
|
landed: 'F. entrega',
|
||||||
|
shipped: 'F. envío',
|
||||||
|
totalEntries: 'Ent. totales',
|
||||||
|
},
|
||||||
|
pageTitles: {
|
||||||
|
travel: 'Envíos',
|
||||||
|
list: 'Listado',
|
||||||
|
create: 'Crear',
|
||||||
|
summary: 'Resumen',
|
||||||
|
},
|
||||||
|
list: {
|
||||||
|
clone: 'Clonar',
|
||||||
|
addEntry: 'Añadir entrada',
|
||||||
|
preview: 'Vista previa',
|
||||||
|
},
|
||||||
|
summary: {
|
||||||
|
confirmed: 'Confirmado',
|
||||||
|
entryId: 'Id entrada',
|
||||||
|
supplier: 'Proveedor',
|
||||||
|
freight: 'Porte',
|
||||||
|
package: 'Embalaje',
|
||||||
|
delivered: 'Enviada',
|
||||||
|
received: 'Recibida',
|
||||||
|
entries: 'Entradas',
|
||||||
|
cloneShipping: 'Clonar envío',
|
||||||
|
CloneTravelAndEntries: 'Clonar travel y sus entradas',
|
||||||
|
AddEntry: 'Añadir entrada',
|
||||||
|
},
|
||||||
|
},
|
||||||
components: {
|
components: {
|
||||||
topbar: {},
|
topbar: {},
|
||||||
userPanel: {
|
userPanel: {
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { onMounted, computed, ref } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
/* import { QBadge, QBtn } from 'quasar';
|
/* import { QBadge, QBtn } from 'quasar';
|
||||||
import CustomerDescriptor from 'src/pages/Customer/Card/CustomerDescriptor.vue'; */
|
import CustomerDescriptor from 'src/pages/Customer/Card/CustomerDescriptor.vue'; */
|
||||||
import invoiceOutService from 'src/services/InvoiceOut.service';
|
import invoiceOutService from 'src/services/invoiceOut.service';
|
||||||
import { toCurrency } from 'src/filters';
|
import { toCurrency } from 'src/filters';
|
||||||
import { QBadge, QCheckbox, exportFile } from 'quasar';
|
import { QBadge, QCheckbox, exportFile } from 'quasar';
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,9 @@ const isAdministrative = computed(() => {
|
||||||
@on-fetch="(data) => setData(data)"
|
@on-fetch="(data) => setData(data)"
|
||||||
>
|
>
|
||||||
<template #header-left>
|
<template #header-left>
|
||||||
|
<a v-if="isAdministrative" class="header link" :href="supplierUrl">
|
||||||
<QIcon name="open_in_new" color="white" size="25px" />
|
<QIcon name="open_in_new" color="white" size="25px" />
|
||||||
|
</a>
|
||||||
</template>
|
</template>
|
||||||
<template #header>
|
<template #header>
|
||||||
<span>{{ supplier.name }} - {{ supplier.id }}</span>
|
<span>{{ supplier.name }} - {{ supplier.id }}</span>
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import suppliersService from 'src/services/Suppliers.service';
|
import suppliersService from 'src/services/suppliers.service';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import { useStateStore } from 'stores/useStateStore';
|
import { useStateStore } from 'stores/useStateStore';
|
||||||
|
import VnSearchbar from 'components/ui/VnSearchbar.vue';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
@ -14,7 +15,7 @@ const newSupplierName = ref();
|
||||||
const createSupplier = async () => {
|
const createSupplier = async () => {
|
||||||
const params = { name: newSupplierName.value };
|
const params = { name: newSupplierName.value };
|
||||||
const response = await suppliersService.createSupplier(params);
|
const response = await suppliersService.createSupplier(params);
|
||||||
router.push({ path: `/supplier/${response.data.id}` });
|
if (response.status === 200) router.push({ path: `/supplier/${response.data.id}` });
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -30,7 +31,11 @@ const createSupplier = async () => {
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<QPage class="q-pa-md">
|
<QPage class="q-pa-md">
|
||||||
<QForm @submit="createSupplier()" class="text-white">
|
<QForm
|
||||||
|
@submit="createSupplier()"
|
||||||
|
class="text-white q-mx-auto"
|
||||||
|
style="max-width: 800px"
|
||||||
|
>
|
||||||
<QCard class="card">
|
<QCard class="card">
|
||||||
<QInput
|
<QInput
|
||||||
v-model="newSupplierName"
|
v-model="newSupplierName"
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
<script setup>
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { useStateStore } from 'stores/useStateStore';
|
||||||
|
import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
|
||||||
|
|
||||||
|
const stateStore = useStateStore();
|
||||||
|
const { t } = useI18n();
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<template v-if="stateStore.isHeaderMounted()">
|
||||||
|
<Teleport to="#searchbar">
|
||||||
|
<VnSearchbar
|
||||||
|
data-key="SuppliersList"
|
||||||
|
:limit="20"
|
||||||
|
:label="t('Search suppliers')"
|
||||||
|
/>
|
||||||
|
</Teleport>
|
||||||
|
</template>
|
||||||
|
<QDrawer v-model="stateStore.leftDrawer" show-if-above :width="256">
|
||||||
|
<QScrollArea class="fit">
|
||||||
|
<!-- Aca iría left menu y descriptor -->
|
||||||
|
</QScrollArea>
|
||||||
|
</QDrawer>
|
||||||
|
<QPageContainer>
|
||||||
|
<QPage>
|
||||||
|
<QToolbar class="bg-vn-dark justify-end">
|
||||||
|
<div id="st-data"></div>
|
||||||
|
<QSpace />
|
||||||
|
<div id="st-actions"></div>
|
||||||
|
</QToolbar>
|
||||||
|
<div class="q-pa-md"><RouterView></RouterView></div>
|
||||||
|
</QPage>
|
||||||
|
</QPageContainer>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.q-scrollarea__content {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.descriptor {
|
||||||
|
max-width: 256px;
|
||||||
|
|
||||||
|
h5 {
|
||||||
|
margin: 0 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.q-card__actions {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#descriptor-skeleton .q-card__actions {
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<i18n>
|
||||||
|
</i18n>
|
|
@ -0,0 +1,305 @@
|
||||||
|
<script setup>
|
||||||
|
import { onMounted, ref, computed, onUpdated } from 'vue';
|
||||||
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import CardSummary from 'components/ui/CardSummary.vue';
|
||||||
|
import VnLv from 'src/components/ui/VnLv.vue';
|
||||||
|
import { getUrl } from 'src/composables/getUrl';
|
||||||
|
import { toDate } from 'src/filters';
|
||||||
|
import travelService from 'src/services/travel.service';
|
||||||
|
import { QCheckbox, QIcon } from 'quasar';
|
||||||
|
import { toCurrency } from 'filters/index';
|
||||||
|
|
||||||
|
onUpdated(() => summaryRef.value.fetch());
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const $props = defineProps({
|
||||||
|
id: {
|
||||||
|
type: Number,
|
||||||
|
required: false,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
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 headerMenuOptions = [
|
||||||
|
{ name: t('travel.summary.cloneShipping'), action: cloneTravel },
|
||||||
|
{ name: t('travel.summary.CloneTravelAndEntries'), action: null },
|
||||||
|
{ 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: 'orange', size: '25px' }),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const entriesTableColumns = computed(() => {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
label: t('travel.summary.confirmed'),
|
||||||
|
field: 'isConfirmed',
|
||||||
|
name: 'isConfirmed',
|
||||||
|
align: 'left',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('travel.summary.entryId'),
|
||||||
|
field: 'id',
|
||||||
|
name: 'id',
|
||||||
|
align: 'left',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('travel.summary.supplier'),
|
||||||
|
field: 'supplierName',
|
||||||
|
name: 'supplierName',
|
||||||
|
align: 'left',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('travel.shared.reference'),
|
||||||
|
field: 'reference',
|
||||||
|
name: 'reference',
|
||||||
|
align: 'left',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('travel.summary.freight'),
|
||||||
|
field: 'freightValue',
|
||||||
|
name: 'freightValue',
|
||||||
|
align: 'left',
|
||||||
|
format: (val) => {
|
||||||
|
return toCurrency(val);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('travel.summary.package'),
|
||||||
|
field: 'packageValue',
|
||||||
|
name: 'packageValue',
|
||||||
|
align: 'left',
|
||||||
|
format: (val) => {
|
||||||
|
return toCurrency(val);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ 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: '',
|
||||||
|
field: 'observation',
|
||||||
|
name: 'observation',
|
||||||
|
align: 'left',
|
||||||
|
toolTip: 'Observation three',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
|
const entriesTableRows = computed(() => {
|
||||||
|
if (!entries.value && !entries.value.length > 0) return [];
|
||||||
|
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 redirectToCreateView = (queryParams) => {
|
||||||
|
router.push({ name: 'TravelCreate', query: { travelData: queryParams } });
|
||||||
|
};
|
||||||
|
|
||||||
|
const openEntryDescriptor = () => {};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<CardSummary
|
||||||
|
ref="summaryRef"
|
||||||
|
:url="`Travels/${entityId}/getTravel`"
|
||||||
|
@on-fetch="(data) => setTravelData(data)"
|
||||||
|
>
|
||||||
|
<template #header-left>
|
||||||
|
<a class="header link" :href="travelUrl">
|
||||||
|
<QIcon name="open_in_new" color="white" size="25px" />
|
||||||
|
</a>
|
||||||
|
</template>
|
||||||
|
<template #header>
|
||||||
|
<span>{{ travel.ref }} - {{ travel.id }}</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #header-right>
|
||||||
|
<QBtn color="white" dense flat icon="more_vert" round size="md">
|
||||||
|
<QTooltip>
|
||||||
|
{{ 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>
|
||||||
|
</QMenu>
|
||||||
|
</QBtn>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #body>
|
||||||
|
<QCard class="vn-one">
|
||||||
|
<VnLv
|
||||||
|
:label="t('travel.shared.shipped')"
|
||||||
|
:value="toDate(travel.shipped)"
|
||||||
|
/>
|
||||||
|
<VnLv :label="t('travel.shared.landed')" :value="toDate(travel.landed)" />
|
||||||
|
<VnLv :label="t('travel.shared.agency')" :value="travel.agency?.name" />
|
||||||
|
<VnLv
|
||||||
|
:label="t('travel.shared.wareHouseOut')"
|
||||||
|
:value="travel.warehouseOut?.name"
|
||||||
|
/>
|
||||||
|
<VnLv
|
||||||
|
:label="t('travel.shared.wareHouseIn')"
|
||||||
|
:value="travel.warehouseIn?.name"
|
||||||
|
/>
|
||||||
|
<VnLv :label="t('travel.shared.reference')" :value="travel.ref" />
|
||||||
|
|
||||||
|
<VnLv label="m³" :value="travel.m3" />
|
||||||
|
<VnLv :label="t('travel.shared.totalEntries')" :value="travel.m3" />
|
||||||
|
<QCheckbox
|
||||||
|
v-model="travel.isDelivered"
|
||||||
|
:label="t('travel.summary.delivered')"
|
||||||
|
disable
|
||||||
|
dense
|
||||||
|
class="full-width q-my-xs"
|
||||||
|
/>
|
||||||
|
<QCheckbox
|
||||||
|
v-model="travel.isReceived"
|
||||||
|
:label="t('travel.summary.received')"
|
||||||
|
disable
|
||||||
|
dense
|
||||||
|
class="full-width q-mb-xs"
|
||||||
|
/>
|
||||||
|
</QCard>
|
||||||
|
<QCard class="vn-two" v-if="entriesTableRows.length > 0">
|
||||||
|
<a class="header" :href="travelUrl + 'entry'">
|
||||||
|
{{ t('travel.summary.entries') }}
|
||||||
|
<QIcon name="open_in_new" color="primary" />
|
||||||
|
</a>
|
||||||
|
<QTable
|
||||||
|
:rows="entriesTableRows"
|
||||||
|
:columns="entriesTableColumns"
|
||||||
|
hide-bottom
|
||||||
|
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>
|
||||||
|
</QTd>
|
||||||
|
</template>
|
||||||
|
</QTable>
|
||||||
|
</QCard>
|
||||||
|
</template>
|
||||||
|
</CardSummary>
|
||||||
|
</template>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.notes {
|
||||||
|
width: max-content;
|
||||||
|
}
|
||||||
|
.cardSummary .summaryBody > .q-card > .taxes {
|
||||||
|
border: 2px solid gray;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
> .vn-label-value {
|
||||||
|
text-align: right;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
margin-top: 5px;
|
||||||
|
justify-content: flex-end;
|
||||||
|
padding-right: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,29 @@
|
||||||
|
<script setup>
|
||||||
|
import { useDialogPluginComponent } from 'quasar';
|
||||||
|
import TravelSummary from './TravelSummary.vue';
|
||||||
|
|
||||||
|
const $props = defineProps({
|
||||||
|
id: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
defineEmits([...useDialogPluginComponent.emits]);
|
||||||
|
|
||||||
|
const { dialogRef, onDialogHide } = useDialogPluginComponent();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<QDialog ref="dialogRef" @hide="onDialogHide">
|
||||||
|
<TravelSummary v-if="$props.id" :id="$props.id" />
|
||||||
|
</QDialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.q-dialog .summary .header {
|
||||||
|
position: sticky;
|
||||||
|
z-index: $z-max;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,178 @@
|
||||||
|
<script setup>
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { reactive, computed } from 'vue';
|
||||||
|
import FetchData from 'components/FetchData.vue';
|
||||||
|
import { useTravelStore } from 'src/stores/travel';
|
||||||
|
import { useRouter, useRoute } from 'vue-router';
|
||||||
|
import { inputSelectFilter } from 'src/composables/inputSelectFilterFn.js';
|
||||||
|
import { toDate } from 'src/filters';
|
||||||
|
import { onBeforeMount } from 'vue';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
const route = useRoute();
|
||||||
|
const router = useRouter();
|
||||||
|
const travelStore = useTravelStore();
|
||||||
|
|
||||||
|
const newTravelDataForm = reactive({
|
||||||
|
ref: null,
|
||||||
|
agencyModeFk: null,
|
||||||
|
shipped: null,
|
||||||
|
landed: null,
|
||||||
|
warehouseOutFk: null,
|
||||||
|
warehouseInFk: null,
|
||||||
|
});
|
||||||
|
|
||||||
|
const agenciesOptions = reactive({
|
||||||
|
original: [],
|
||||||
|
filtered: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
const warehousesOptions = reactive({
|
||||||
|
original: [],
|
||||||
|
filtered: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
onBeforeMount(() => {
|
||||||
|
if (route.query.travelData) {
|
||||||
|
const travelData = JSON.parse(route.query.travelData);
|
||||||
|
for (let key in newTravelDataForm) {
|
||||||
|
if (key === 'landed' || key === 'shipped') {
|
||||||
|
newTravelDataForm[key] = travelData[key].substring(0, 10);
|
||||||
|
} else {
|
||||||
|
newTravelDataForm[key] = travelData[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const createTravel = async () => {
|
||||||
|
const response = await travelStore.createTravel(newTravelDataForm);
|
||||||
|
if (response.status === 200) router.push({ path: `/travel/${response.data.id}` });
|
||||||
|
};
|
||||||
|
|
||||||
|
const onFetchAgencies = (agencies) => {
|
||||||
|
agenciesOptions.original = agencies.map((agency) => {
|
||||||
|
return { value: agency.agencyFk, label: agency.name };
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onFetchWarehouses = (warehouses) => {
|
||||||
|
warehousesOptions.original = warehouses.map((warehouse) => {
|
||||||
|
return { value: warehouse.id, label: warehouse.name };
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const canSubmit = computed(() => {
|
||||||
|
for (const key in newTravelDataForm) {
|
||||||
|
if (!newTravelDataForm[key]) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
const redirectToTravelList = () => {
|
||||||
|
router.push({ name: 'TravelList' });
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<FetchData url="AgencyModes" @on-fetch="(data) => onFetchAgencies(data)" auto-load />
|
||||||
|
<FetchData url="Warehouses" @on-fetch="(data) => onFetchWarehouses(data)" auto-load />
|
||||||
|
<QPage class="q-pa-md">
|
||||||
|
<QForm
|
||||||
|
@submit="createTravel()"
|
||||||
|
class="text-white column q-mx-auto"
|
||||||
|
style="max-width: 800px"
|
||||||
|
>
|
||||||
|
<QCard class="row q-pa-xl full-width card">
|
||||||
|
<QInput
|
||||||
|
v-model="newTravelDataForm.ref"
|
||||||
|
:label="t('travel.shared.reference')"
|
||||||
|
filled
|
||||||
|
style="max-width: 100%"
|
||||||
|
/>
|
||||||
|
<QSelect
|
||||||
|
:options="agenciesOptions.filtered"
|
||||||
|
v-model="newTravelDataForm.agencyModeFk"
|
||||||
|
filled
|
||||||
|
use-input
|
||||||
|
@filter="
|
||||||
|
(val, update, abort) =>
|
||||||
|
inputSelectFilter(val, update, abort, agenciesOptions)
|
||||||
|
"
|
||||||
|
:label="t('travel.shared.agency')"
|
||||||
|
transition-show="jump-up"
|
||||||
|
transition-hide="jump-up"
|
||||||
|
style="max-width: 100%"
|
||||||
|
/>
|
||||||
|
<QInput
|
||||||
|
v-model="newTravelDataForm.shipped"
|
||||||
|
type="date"
|
||||||
|
filled
|
||||||
|
mask="date"
|
||||||
|
:label="t('travel.shared.shipped')"
|
||||||
|
/>
|
||||||
|
<QInput
|
||||||
|
v-model="newTravelDataForm.landed"
|
||||||
|
type="date"
|
||||||
|
filled
|
||||||
|
mask="date"
|
||||||
|
:label="t('travel.shared.landed')"
|
||||||
|
/>
|
||||||
|
<QSelect
|
||||||
|
:options="warehousesOptions.filtered"
|
||||||
|
v-model="newTravelDataForm.warehouseOutFk"
|
||||||
|
filled
|
||||||
|
use-input
|
||||||
|
@filter="
|
||||||
|
(val, update, abort) =>
|
||||||
|
inputSelectFilter(val, update, abort, warehousesOptions)
|
||||||
|
"
|
||||||
|
:label="t('travel.shared.wareHouseOut')"
|
||||||
|
transition-show="jump-up"
|
||||||
|
transition-hide="jump-up"
|
||||||
|
/>
|
||||||
|
<QSelect
|
||||||
|
:options="warehousesOptions.filtered"
|
||||||
|
v-model="newTravelDataForm.warehouseInFk"
|
||||||
|
filled
|
||||||
|
use-input
|
||||||
|
@filter="
|
||||||
|
(val, update, abort) =>
|
||||||
|
inputSelectFilter(val, update, abort, warehousesOptions)
|
||||||
|
"
|
||||||
|
:label="t('travel.shared.wareHouseIn')"
|
||||||
|
transition-show="jump-up"
|
||||||
|
transition-hide="jump-up"
|
||||||
|
/>
|
||||||
|
</QCard>
|
||||||
|
<div class="row">
|
||||||
|
<QBtn
|
||||||
|
:label="t('globals.create')"
|
||||||
|
type="submit"
|
||||||
|
color="primary"
|
||||||
|
class="q-mt-md"
|
||||||
|
:disable="!canSubmit"
|
||||||
|
/>
|
||||||
|
<QBtn
|
||||||
|
:label="t('globals.cancel')"
|
||||||
|
class="q-mt-md"
|
||||||
|
flat
|
||||||
|
:disable="!canSubmit"
|
||||||
|
@click="redirectToTravelList()"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</QForm>
|
||||||
|
</QPage>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.card {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
|
||||||
|
grid-gap: 20px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<i18n>
|
||||||
|
|
||||||
|
</i18n>
|
|
@ -0,0 +1,380 @@
|
||||||
|
<script setup>
|
||||||
|
import { reactive, ref } from 'vue';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
|
||||||
|
import { inputSelectFilter } from 'src/composables/inputSelectFilterFn.js';
|
||||||
|
import FetchData from 'components/FetchData.vue';
|
||||||
|
import { toDate } from 'src/filters';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
const props = defineProps({
|
||||||
|
dataKey: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const warehousesOptions = reactive({
|
||||||
|
original: [],
|
||||||
|
filtered: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
const continentsOptions = reactive({
|
||||||
|
original: [],
|
||||||
|
filtered: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
const agenciesOptions = reactive({
|
||||||
|
original: [],
|
||||||
|
filtered: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
const onFetchWarehouses = (warehouses) => {
|
||||||
|
warehousesOptions.original = warehouses.map((warehouse) => {
|
||||||
|
return { value: warehouse.id, label: warehouse.name };
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onFetchContinents = (continents) => {
|
||||||
|
continentsOptions.original = continents.map((continent) => {
|
||||||
|
return { value: continent.code, label: continent.name };
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onFetchAgencies = (agencies) => {
|
||||||
|
agenciesOptions.original = agencies.map((agency) => {
|
||||||
|
return { value: agency.agencyFk, label: agency.name };
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const add = (paramsObj, key) => {
|
||||||
|
if (paramsObj[key] === undefined) {
|
||||||
|
paramsObj[key] = 1;
|
||||||
|
} else {
|
||||||
|
paramsObj[key]++;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const decrement = (paramsObj, key) => {
|
||||||
|
if (paramsObj[key] === 0) return;
|
||||||
|
|
||||||
|
paramsObj[key]--;
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<FetchData url="Warehouses" @on-fetch="(data) => onFetchWarehouses(data)" auto-load />
|
||||||
|
<FetchData url="Continents" @on-fetch="(data) => onFetchContinents(data)" auto-load />
|
||||||
|
<FetchData url="AgencyModes" @on-fetch="(data) => onFetchAgencies(data)" auto-load />
|
||||||
|
|
||||||
|
<VnFilterPanel :data-key="props.dataKey" :search-button="true">
|
||||||
|
<template #tags="{ tag, formatFn }">
|
||||||
|
<div class="q-gutter-x-xs">
|
||||||
|
<strong>{{ t(`params.${tag.label}`) }}: </strong>
|
||||||
|
<span>{{ formatFn(tag.value) }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<!-- searchFn -->
|
||||||
|
<template #body="{ params }">
|
||||||
|
<QList dense>
|
||||||
|
<QItem class="q-my-sm">
|
||||||
|
<QItemSection>
|
||||||
|
<QInput
|
||||||
|
:label="t('params.search')"
|
||||||
|
dense
|
||||||
|
lazy-rules
|
||||||
|
outlined
|
||||||
|
rounded
|
||||||
|
v-model="params.search"
|
||||||
|
/>
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
<QItem class="q-mb-sm">
|
||||||
|
<QItemSection>
|
||||||
|
<QSelect
|
||||||
|
:label="t('params.agencyModeFk')"
|
||||||
|
:options="agenciesOptions.filtered"
|
||||||
|
use-input
|
||||||
|
option-value="value"
|
||||||
|
option-label="label"
|
||||||
|
emit-value
|
||||||
|
map-options
|
||||||
|
transition-show="jump-up"
|
||||||
|
transition-hide="jump-up"
|
||||||
|
dense
|
||||||
|
lazy-rules
|
||||||
|
outlined
|
||||||
|
rounded
|
||||||
|
@filter="
|
||||||
|
(val, update, abort) =>
|
||||||
|
inputSelectFilter(val, update, abort, agenciesOptions)
|
||||||
|
"
|
||||||
|
v-model="params.agencyModeFk"
|
||||||
|
/>
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
<QItem class="q-mb-sm">
|
||||||
|
<QItemSection>
|
||||||
|
<QSelect
|
||||||
|
:label="t('travel.shared.wareHouseOut')"
|
||||||
|
:options="warehousesOptions.filtered"
|
||||||
|
use-input
|
||||||
|
option-value="value"
|
||||||
|
option-label="label"
|
||||||
|
emit-value
|
||||||
|
map-options
|
||||||
|
transition-show="jump-up"
|
||||||
|
transition-hide="jump-up"
|
||||||
|
dense
|
||||||
|
lazy-rules
|
||||||
|
outlined
|
||||||
|
rounded
|
||||||
|
@filter="
|
||||||
|
(val, update, abort) =>
|
||||||
|
inputSelectFilter(
|
||||||
|
val,
|
||||||
|
update,
|
||||||
|
abort,
|
||||||
|
warehousesOptions
|
||||||
|
)
|
||||||
|
"
|
||||||
|
v-model="params.warehouseOutFk"
|
||||||
|
/>
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
<QItem class="q-mb-sm">
|
||||||
|
<QItemSection>
|
||||||
|
<QSelect
|
||||||
|
:label="t('params.wareHouseIn')"
|
||||||
|
:options="warehousesOptions.filtered"
|
||||||
|
use-input
|
||||||
|
option-value="value"
|
||||||
|
option-label="label"
|
||||||
|
emit-value
|
||||||
|
map-options
|
||||||
|
transition-show="jump-up"
|
||||||
|
transition-hide="jump-up"
|
||||||
|
dense
|
||||||
|
lazy-rules
|
||||||
|
outlined
|
||||||
|
rounded
|
||||||
|
@filter="
|
||||||
|
(val, update, abort) =>
|
||||||
|
inputSelectFilter(
|
||||||
|
val,
|
||||||
|
update,
|
||||||
|
abort,
|
||||||
|
warehousesOptions
|
||||||
|
)
|
||||||
|
"
|
||||||
|
v-model="params.warehouseInFk"
|
||||||
|
/>
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
<QItem class="q-mb-sm">
|
||||||
|
<QItemSection>
|
||||||
|
<QInput
|
||||||
|
v-model="params.scopeDays"
|
||||||
|
type="number"
|
||||||
|
:label="t('params.scopeDays')"
|
||||||
|
dense
|
||||||
|
lazy-rules
|
||||||
|
outlined
|
||||||
|
rounded
|
||||||
|
class="input-number"
|
||||||
|
>
|
||||||
|
<template #append>
|
||||||
|
<QBtn
|
||||||
|
icon="add"
|
||||||
|
flat
|
||||||
|
dense
|
||||||
|
size="12px"
|
||||||
|
@click="add(params, 'scopeDays')"
|
||||||
|
/>
|
||||||
|
<QBtn
|
||||||
|
icon="remove"
|
||||||
|
flat
|
||||||
|
dense
|
||||||
|
size="12px"
|
||||||
|
@click="decrement(params, 'scopeDays')"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</QInput>
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
<QItem class="q-mb-sm">
|
||||||
|
<QItemSection>
|
||||||
|
<QInput
|
||||||
|
dense
|
||||||
|
lazy-rules
|
||||||
|
outlined
|
||||||
|
rounded
|
||||||
|
placeholder="dd-mm-aaa"
|
||||||
|
: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="Close"
|
||||||
|
color="primary"
|
||||||
|
flat
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</QDate>
|
||||||
|
</QPopupProxy>
|
||||||
|
</QIcon>
|
||||||
|
</template>
|
||||||
|
</QInput>
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
<QItem class="q-mb-sm">
|
||||||
|
<QItemSection>
|
||||||
|
<QInput
|
||||||
|
dense
|
||||||
|
lazy-rules
|
||||||
|
outlined
|
||||||
|
rounded
|
||||||
|
placeholder="dd-mm-aaa"
|
||||||
|
:model-value="toDate(params.landedTo)"
|
||||||
|
: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="Close"
|
||||||
|
color="primary"
|
||||||
|
flat
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</QDate>
|
||||||
|
</QPopupProxy>
|
||||||
|
</QIcon>
|
||||||
|
</template>
|
||||||
|
</QInput>
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
<QItem class="q-mb-sm">
|
||||||
|
<QItemSection>
|
||||||
|
<QSelect
|
||||||
|
:label="t('params.continent')"
|
||||||
|
:options="continentsOptions.filtered"
|
||||||
|
use-input
|
||||||
|
option-value="value"
|
||||||
|
option-label="label"
|
||||||
|
emit-value
|
||||||
|
map-options
|
||||||
|
transition-show="jump-up"
|
||||||
|
transition-hide="jump-up"
|
||||||
|
dense
|
||||||
|
lazy-rules
|
||||||
|
outlined
|
||||||
|
rounded
|
||||||
|
@filter="
|
||||||
|
(val, update, abort) =>
|
||||||
|
inputSelectFilter(
|
||||||
|
val,
|
||||||
|
update,
|
||||||
|
abort,
|
||||||
|
continentsOptions
|
||||||
|
)
|
||||||
|
"
|
||||||
|
v-model="params.continent"
|
||||||
|
/>
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
<QItem class="q-mb-sm">
|
||||||
|
<QItemSection>
|
||||||
|
<QInput
|
||||||
|
v-model="params.totalEntries"
|
||||||
|
type="number"
|
||||||
|
:label="t('params.totalEntries')"
|
||||||
|
dense
|
||||||
|
lazy-rules
|
||||||
|
outlined
|
||||||
|
rounded
|
||||||
|
min="0"
|
||||||
|
class="input-number"
|
||||||
|
>
|
||||||
|
<template #append>
|
||||||
|
<QBtn
|
||||||
|
icon="add"
|
||||||
|
flat
|
||||||
|
dense
|
||||||
|
size="12px"
|
||||||
|
@click="add(params, 'totalEntries')"
|
||||||
|
/>
|
||||||
|
<QBtn
|
||||||
|
icon="remove"
|
||||||
|
flat
|
||||||
|
dense
|
||||||
|
size="12px"
|
||||||
|
@click="decrement(params, 'totalEntries')"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</QInput>
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
</QList>
|
||||||
|
</template>
|
||||||
|
</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": {
|
||||||
|
"search": "Id/Reference",
|
||||||
|
"agencyModeFk": "Agency",
|
||||||
|
"wareHouseIn": "Warehouse In",
|
||||||
|
"wareHouseOut": "Warehouse Out",
|
||||||
|
"scopeDays": "Days onward",
|
||||||
|
"landedFrom": "Landed from",
|
||||||
|
"landedTo": "Landed to",
|
||||||
|
"continent": "Continent out",
|
||||||
|
"totalEntries": "Total entries"
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"es": {
|
||||||
|
"params":{
|
||||||
|
"search": "Id/Referencia",
|
||||||
|
"agencyModeFk": "Agencia",
|
||||||
|
"wareHouseIn": "Alm. entrada",
|
||||||
|
"wareHouseOut": "Alm. salida",
|
||||||
|
"scopeDays": "Días adelante",
|
||||||
|
"landedFrom": "Llegada desde",
|
||||||
|
"landedTo": "Llegada hasta",
|
||||||
|
"continent": "Cont. Salida",
|
||||||
|
"totalEntries": "Ent. totales"
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</i18n>
|
|
@ -0,0 +1,144 @@
|
||||||
|
<script setup>
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { onMounted } from 'vue';
|
||||||
|
import { toDate } from 'src/filters/index';
|
||||||
|
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
import VnPaginate from 'src/components/ui/VnPaginate.vue';
|
||||||
|
import CardList2 from 'src/components/ui/CardList2.vue';
|
||||||
|
import VnLv from 'src/components/ui/VnLv.vue';
|
||||||
|
import TravelSummaryDialog from './Card/TravelSummaryDialog.vue';
|
||||||
|
import { useTravelStore } from 'src/stores/travel.js';
|
||||||
|
import { useQuasar } from 'quasar';
|
||||||
|
import { useStateStore } from 'stores/useStateStore';
|
||||||
|
import TravelFilter from './TravelFilter.vue';
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
const travelStore = useTravelStore();
|
||||||
|
const quasar = useQuasar();
|
||||||
|
const { t } = useI18n();
|
||||||
|
const stateStore = useStateStore();
|
||||||
|
|
||||||
|
const navigateToTravelId = (id) => {
|
||||||
|
router.push({ path: `/travel/${id}` });
|
||||||
|
};
|
||||||
|
|
||||||
|
const cloneTravel = (travelData) => {
|
||||||
|
const stringifiedTravelData = JSON.stringify(travelData);
|
||||||
|
redirectToCreateView(stringifiedTravelData);
|
||||||
|
};
|
||||||
|
|
||||||
|
const redirectToCreateView = (queryParams) => {
|
||||||
|
router.push({ name: 'TravelCreate', query: { travelData: queryParams } });
|
||||||
|
};
|
||||||
|
|
||||||
|
const viewSummary = (id) => {
|
||||||
|
quasar.dialog({
|
||||||
|
component: TravelSummaryDialog,
|
||||||
|
componentProps: {
|
||||||
|
id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await travelStore.init();
|
||||||
|
stateStore.rightDrawer = true;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<QDrawer v-model="stateStore.rightDrawer" side="right" :width="256" show-if-above>
|
||||||
|
<QScrollArea class="fit text-grey-8">
|
||||||
|
<TravelFilter data-key="TravelList" />
|
||||||
|
</QScrollArea>
|
||||||
|
</QDrawer>
|
||||||
|
<QPage class="column items-center q-pa-md">
|
||||||
|
<div class="card-list">
|
||||||
|
<VnPaginate
|
||||||
|
data-key="TravelList"
|
||||||
|
url="Travels/filter"
|
||||||
|
auto-load
|
||||||
|
order="shipped DESC, landed DESC"
|
||||||
|
>
|
||||||
|
<template #body="{ rows }">
|
||||||
|
<CardList2
|
||||||
|
v-for="row of rows"
|
||||||
|
:key="row.id"
|
||||||
|
:title="row.ref"
|
||||||
|
:id="row.id"
|
||||||
|
@click="navigateToTravelId(row.id)"
|
||||||
|
>
|
||||||
|
<template #list-items>
|
||||||
|
<VnLv
|
||||||
|
:label="t('travel.shared.agency')"
|
||||||
|
:value="row.agencyModeName"
|
||||||
|
/>
|
||||||
|
<VnLv
|
||||||
|
:label="t('travel.shared.wareHouseOut')"
|
||||||
|
:value="row.warehouseOutFk"
|
||||||
|
/>
|
||||||
|
<VnLv
|
||||||
|
:label="t('travel.shared.shipped')"
|
||||||
|
:value="toDate(row.shipped)"
|
||||||
|
/>
|
||||||
|
<VnLv
|
||||||
|
:label="t('travel.shared.landed')"
|
||||||
|
:value="toDate(row.landed)"
|
||||||
|
/>
|
||||||
|
<VnLv
|
||||||
|
:label="t('travel.shared.wareHouseIn')"
|
||||||
|
:value="row.warehouseInFk"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<VnLv
|
||||||
|
:label="t('travel.shared.totalEntries')"
|
||||||
|
:value="row.totalEntries"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #actions>
|
||||||
|
<QBtn
|
||||||
|
:label="t('travel.list.clone')"
|
||||||
|
@click.stop="cloneTravel(row)"
|
||||||
|
color="white"
|
||||||
|
outline
|
||||||
|
type="reset"
|
||||||
|
/>
|
||||||
|
<QBtn
|
||||||
|
:label="t('travel.list.addEntry')"
|
||||||
|
@click.stop="viewSummary(row.id)"
|
||||||
|
color="primary"
|
||||||
|
style="margin-top: 15px"
|
||||||
|
type="submit"
|
||||||
|
/>
|
||||||
|
<QBtn
|
||||||
|
:label="t('travel.list.preview')"
|
||||||
|
@click.stop="viewSummary(row.id)"
|
||||||
|
color="primary"
|
||||||
|
style="margin-top: 15px"
|
||||||
|
type="submit"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</CardList2>
|
||||||
|
</template>
|
||||||
|
</VnPaginate>
|
||||||
|
</div>
|
||||||
|
<QPageSticky :offset="[20, 20]">
|
||||||
|
<QBtn fab icon="add" color="primary" @click="redirectToCreateView()" />
|
||||||
|
<QTooltip>
|
||||||
|
{{ t('supplier.list.newSupplier') }}
|
||||||
|
</QTooltip>
|
||||||
|
</QPageSticky>
|
||||||
|
</QPage>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.card-list {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 60em;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<i18n>
|
||||||
|
|
||||||
|
</i18n>
|
|
@ -0,0 +1,17 @@
|
||||||
|
<script setup>
|
||||||
|
import { useStateStore } from 'stores/useStateStore';
|
||||||
|
import LeftMenu from 'src/components/LeftMenu.vue';
|
||||||
|
|
||||||
|
const stateStore = useStateStore();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<QDrawer v-model="stateStore.leftDrawer" show-if-above :width="256">
|
||||||
|
<QScrollArea class="fit text-grey-8">
|
||||||
|
<LeftMenu />
|
||||||
|
</QScrollArea>
|
||||||
|
</QDrawer>
|
||||||
|
<QPageContainer>
|
||||||
|
<RouterView></RouterView>
|
||||||
|
</QPageContainer>
|
||||||
|
</template>
|
|
@ -3,9 +3,21 @@ import Ticket from './ticket';
|
||||||
import Claim from './claim';
|
import Claim from './claim';
|
||||||
import InvoiceOut from './invoiceOut';
|
import InvoiceOut from './invoiceOut';
|
||||||
import Worker from './worker';
|
import Worker from './worker';
|
||||||
import Shelving from "./shelving";
|
import Shelving from './shelving';
|
||||||
import Wagon from './wagon';
|
import Wagon from './wagon';
|
||||||
import Route from './route';
|
import Route from './route';
|
||||||
import Supplier from './Supplier';
|
import Supplier from './Supplier';
|
||||||
|
import Travel from './travel';
|
||||||
|
|
||||||
export default [Customer, Ticket, Claim, InvoiceOut, Worker, Shelving, Wagon, Route, Supplier];
|
export default [
|
||||||
|
Customer,
|
||||||
|
Ticket,
|
||||||
|
Claim,
|
||||||
|
InvoiceOut,
|
||||||
|
Worker,
|
||||||
|
Shelving,
|
||||||
|
Wagon,
|
||||||
|
Route,
|
||||||
|
Supplier,
|
||||||
|
Travel,
|
||||||
|
];
|
||||||
|
|
|
@ -34,7 +34,7 @@ export default {
|
||||||
name: 'InvoiceOutGlobal',
|
name: 'InvoiceOutGlobal',
|
||||||
meta: {
|
meta: {
|
||||||
title: 'globalInvoicing',
|
title: 'globalInvoicing',
|
||||||
icon: 'view_list',
|
icon: 'contact_support',
|
||||||
},
|
},
|
||||||
component: () => import('src/pages/InvoiceOut/InvoiceOutGlobal.vue'),
|
component: () => import('src/pages/InvoiceOut/InvoiceOutGlobal.vue'),
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
import { RouterView } from 'vue-router';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
path: '/travel',
|
||||||
|
name: 'Travel',
|
||||||
|
meta: {
|
||||||
|
title: 'travel',
|
||||||
|
icon: 'vn:package',
|
||||||
|
},
|
||||||
|
component: RouterView,
|
||||||
|
redirect: { name: 'TravelMain' },
|
||||||
|
menus: {
|
||||||
|
main: ['TravelList'],
|
||||||
|
card: [],
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
name: 'TravelMain',
|
||||||
|
component: () => import('src/pages/Travel/TravelMain.vue'),
|
||||||
|
redirect: { name: 'TravelList' },
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'list',
|
||||||
|
name: 'TravelList',
|
||||||
|
meta: {
|
||||||
|
title: 'list',
|
||||||
|
icon: 'view_list',
|
||||||
|
},
|
||||||
|
component: () => import('src/pages/Travel/TravelList.vue'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'create',
|
||||||
|
name: 'TravelCreate',
|
||||||
|
meta: {
|
||||||
|
title: 'create',
|
||||||
|
},
|
||||||
|
component: () => import('src/pages/Travel/TravelCreate.vue'),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'TravelCard',
|
||||||
|
path: ':id',
|
||||||
|
component: () => import('src/pages/Travel/Card/TravelCard.vue'),
|
||||||
|
redirect: { name: 'TravelSummary' },
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
name: 'TravelSummary',
|
||||||
|
path: 'summary',
|
||||||
|
meta: {
|
||||||
|
title: 'summary',
|
||||||
|
},
|
||||||
|
component: () => import('src/pages/Travel/Card/TravelSummary.vue'),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
|
@ -6,7 +6,8 @@ import invoiceOut from './modules/invoiceOut';
|
||||||
import wagon from './modules/wagon';
|
import wagon from './modules/wagon';
|
||||||
import supplier from './modules/Supplier';
|
import supplier from './modules/Supplier';
|
||||||
import route from './modules/route';
|
import route from './modules/route';
|
||||||
import shelving from "src/router/modules/shelving";
|
import travel from './modules/travel';
|
||||||
|
import shelving from 'src/router/modules/shelving';
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
{
|
{
|
||||||
|
@ -55,6 +56,7 @@ const routes = [
|
||||||
wagon,
|
wagon,
|
||||||
route,
|
route,
|
||||||
supplier,
|
supplier,
|
||||||
|
travel,
|
||||||
{
|
{
|
||||||
path: '/:catchAll(.*)*',
|
path: '/:catchAll(.*)*',
|
||||||
name: 'NotFound',
|
name: 'NotFound',
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
const travelService = {
|
||||||
|
getTravels: async (filter = {}) => {
|
||||||
|
try {
|
||||||
|
return await axios.get('Travels/filter', filter);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`Error fetching travels`, err);
|
||||||
|
return err.response;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
createTravel: async (params) => {
|
||||||
|
try {
|
||||||
|
return await axios.patch('Travels', params);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`Error creating travel`, err);
|
||||||
|
return err.response;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
getTravelEntries: async (param) => {
|
||||||
|
try {
|
||||||
|
return await axios.get(`Travels/${param}/getEntries`);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`Error fetching travel entries`, err);
|
||||||
|
return err.response;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default travelService;
|
|
@ -1,6 +1,6 @@
|
||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
import { useUserConfig } from 'src/composables/useUserConfig';
|
import { useUserConfig } from 'src/composables/useUserConfig';
|
||||||
import invoiceOutService from 'src/services/InvoiceOut.service.js';
|
import invoiceOutService from 'src/services/invoiceOut.service';
|
||||||
import useNotify from 'src/composables/useNotify.js';
|
import useNotify from 'src/composables/useNotify.js';
|
||||||
|
|
||||||
const { notify } = useNotify();
|
const { notify } = useNotify();
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
import { defineStore } from 'pinia';
|
||||||
|
import travelService from 'src/services/travel.service';
|
||||||
|
|
||||||
|
export const useTravelStore = defineStore({
|
||||||
|
id: 'travel',
|
||||||
|
|
||||||
|
state: () => ({
|
||||||
|
initialDataLoading: true,
|
||||||
|
travels: [],
|
||||||
|
}),
|
||||||
|
actions: {
|
||||||
|
async init() {
|
||||||
|
await this.fetchAllData();
|
||||||
|
},
|
||||||
|
|
||||||
|
async fetchAllData() {
|
||||||
|
const { data } = await travelService.getTravels();
|
||||||
|
this.travels = data || [];
|
||||||
|
},
|
||||||
|
|
||||||
|
async createTravel(travelData) {
|
||||||
|
const params = {
|
||||||
|
ref: travelData.ref,
|
||||||
|
agencyModeFk: travelData.agencyModeFk.value,
|
||||||
|
warehouseOutFk: travelData.warehouseOutFk.value,
|
||||||
|
warehouseInFk: travelData.warehouseInFk.value,
|
||||||
|
landed: new Date(travelData.landed),
|
||||||
|
shipped: new Date(travelData.shipped),
|
||||||
|
};
|
||||||
|
|
||||||
|
return await travelService.createTravel(params);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
getters: {},
|
||||||
|
});
|
|
@ -16,6 +16,7 @@ export const useNavigationStore = defineStore('navigationStore', () => {
|
||||||
'wagon',
|
'wagon',
|
||||||
'route',
|
'route',
|
||||||
'supplier',
|
'supplier',
|
||||||
|
'travel',
|
||||||
];
|
];
|
||||||
const pinnedModules = ref([]);
|
const pinnedModules = ref([]);
|
||||||
const role = useRole();
|
const role = useRole();
|
||||||
|
|
Loading…
Reference in New Issue