7167-testToMaster_2414 #266
|
@ -888,6 +888,7 @@ export default {
|
||||||
create: 'Create',
|
create: 'Create',
|
||||||
basicData: 'Basic Data',
|
basicData: 'Basic Data',
|
||||||
summary: 'Summary',
|
summary: 'Summary',
|
||||||
|
RouteRoadmap: 'Roadmaps',
|
||||||
tickets: 'Tickets',
|
tickets: 'Tickets',
|
||||||
log: 'Log',
|
log: 'Log',
|
||||||
autonomous: 'Autonomous',
|
autonomous: 'Autonomous',
|
||||||
|
|
|
@ -941,7 +941,8 @@ export default {
|
||||||
RouteList: 'Listado',
|
RouteList: 'Listado',
|
||||||
create: 'Crear',
|
create: 'Crear',
|
||||||
basicData: 'Datos básicos',
|
basicData: 'Datos básicos',
|
||||||
summary: 'Summary',
|
summary: 'Resumen',
|
||||||
|
RouteRoadmap: 'Troncales',
|
||||||
tickets: 'Tickets',
|
tickets: 'Tickets',
|
||||||
log: 'Historial',
|
log: 'Historial',
|
||||||
autonomous: 'Autónomos',
|
autonomous: 'Autónomos',
|
||||||
|
|
|
@ -0,0 +1,183 @@
|
||||||
|
<script setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import FetchData from 'components/FetchData.vue';
|
||||||
|
import VnFilterPanel from 'components/ui/VnFilterPanel.vue';
|
||||||
|
import VnSelectFilter from 'components/common/VnSelectFilter.vue';
|
||||||
|
import VnInputDate from 'components/common/VnInputDate.vue';
|
||||||
|
import VnInput from 'components/common/VnInput.vue';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
const props = defineProps({
|
||||||
|
dataKey: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(['search']);
|
||||||
|
|
||||||
|
const supplierList = ref([]);
|
||||||
|
const exprBuilder = (param, value) => {
|
||||||
|
switch (param) {
|
||||||
|
case 'tractorPlate':
|
||||||
|
case 'trailerPlate':
|
||||||
|
case 'driverName':
|
||||||
|
case 'phone':
|
||||||
|
return { [param]: { like: `%${value}%` } };
|
||||||
|
case 'supplierFk':
|
||||||
|
case 'price':
|
||||||
|
return { [param]: value };
|
||||||
|
case 'from':
|
||||||
|
return { etd: { gte: value } };
|
||||||
|
case 'to':
|
||||||
|
return { etd: { lte: value } };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<FetchData
|
||||||
|
url="Suppliers"
|
||||||
|
:filter="{ fields: ['id', 'nickname'] }"
|
||||||
|
sort-by="nickname"
|
||||||
|
limit="30"
|
||||||
|
@on-fetch="(data) => (supplierList = data)"
|
||||||
|
auto-load
|
||||||
|
/>
|
||||||
|
<VnFilterPanel
|
||||||
|
:data-key="props.dataKey"
|
||||||
|
:search-button="true"
|
||||||
|
:expr-builder="exprBuilder"
|
||||||
|
@search="emit('search')"
|
||||||
|
>
|
||||||
|
<template #tags="{ tag, formatFn }">
|
||||||
|
<div class="q-gutter-x-xs">
|
||||||
|
<strong>{{ t(`params.${tag.label}`) }}: </strong>
|
||||||
|
<span>{{ formatFn(tag.value) }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #body="{ params }">
|
||||||
|
<QItem class="q-my-sm">
|
||||||
|
<QItemSection>
|
||||||
|
<VnInputDate v-model="params.from" :label="t('From')" is-outlined />
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
<QItem class="q-my-sm">
|
||||||
|
<QItemSection>
|
||||||
|
<VnInputDate v-model="params.to" :label="t('To')" is-outlined />
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
<QItem class="q-my-sm">
|
||||||
|
<QItemSection>
|
||||||
|
<VnInput
|
||||||
|
v-model="params.tractorPlate"
|
||||||
|
:label="t('Tractor Plate')"
|
||||||
|
is-outlined
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
<QItem class="q-my-sm">
|
||||||
|
<QItemSection>
|
||||||
|
<VnInput
|
||||||
|
v-model="params.trailerPlate"
|
||||||
|
:label="t('Trailer Plate')"
|
||||||
|
is-outlined
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
<QItem v-if="supplierList" class="q-my-sm">
|
||||||
|
<QItemSection>
|
||||||
|
<VnSelectFilter
|
||||||
|
:label="t('Carrier')"
|
||||||
|
v-model="params.supplierFk"
|
||||||
|
:options="supplierList"
|
||||||
|
option-value="id"
|
||||||
|
option-label="nickname"
|
||||||
|
dense
|
||||||
|
outlined
|
||||||
|
rounded
|
||||||
|
emit-value
|
||||||
|
map-options
|
||||||
|
use-input
|
||||||
|
:input-debounce="0"
|
||||||
|
>
|
||||||
|
<template #option="{ itemProps, opt }">
|
||||||
|
<QItem v-bind="itemProps">
|
||||||
|
<QItemSection>
|
||||||
|
<QItemLabel
|
||||||
|
>{{ opt.id }} - {{ opt.nickname }}</QItemLabel
|
||||||
|
>
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
</template>
|
||||||
|
</VnSelectFilter>
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
<QItem class="q-my-sm">
|
||||||
|
<QItemSection>
|
||||||
|
<VnInput
|
||||||
|
v-model="params.price"
|
||||||
|
:label="t('Price')"
|
||||||
|
type="number"
|
||||||
|
is-outlined
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
<QItem class="q-my-sm">
|
||||||
|
<QItemSection>
|
||||||
|
<VnInput
|
||||||
|
v-model="params.driverName"
|
||||||
|
:label="t('Driver name')"
|
||||||
|
is-outlined
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
<QItem class="q-my-sm">
|
||||||
|
<QItemSection>
|
||||||
|
<VnInput
|
||||||
|
v-model="params.phone"
|
||||||
|
:label="t('Phone')"
|
||||||
|
is-outlined
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
</template>
|
||||||
|
</VnFilterPanel>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<i18n>
|
||||||
|
en:
|
||||||
|
params:
|
||||||
|
tractorPlate: Tractor Plate
|
||||||
|
trailerPlate: Trailer Plate
|
||||||
|
supplierFk: Carrier
|
||||||
|
price: Price
|
||||||
|
driverName: Driver name
|
||||||
|
phone: Phone
|
||||||
|
from: From
|
||||||
|
to: To
|
||||||
|
es:
|
||||||
|
params:
|
||||||
|
tractorPlate: Matrícula del tractor
|
||||||
|
trailerPlate: Matrícula del trailer
|
||||||
|
supplierFk: Transportista
|
||||||
|
price: Precio
|
||||||
|
driverName: Nombre del conductor
|
||||||
|
phone: Teléfono
|
||||||
|
from: Desde
|
||||||
|
to: Hasta
|
||||||
|
From: Desde
|
||||||
|
To: Hasta
|
||||||
|
Tractor Plate: Matrícula del tractor
|
||||||
|
Trailer Plate: Matrícula del trailer
|
||||||
|
Carrier: Transportista
|
||||||
|
Price: Precio
|
||||||
|
Driver name: Nombre del conductor
|
||||||
|
Phone: Teléfono
|
||||||
|
</i18n>
|
|
@ -0,0 +1,291 @@
|
||||||
|
<script setup>
|
||||||
|
import VnPaginate from 'components/ui/VnPaginate.vue';
|
||||||
|
import { useStateStore } from 'stores/useStateStore';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { computed, onMounted, onUnmounted, ref } from 'vue';
|
||||||
|
import { dashIfEmpty, toDateHour } from 'src/filters';
|
||||||
|
import { useValidator } from 'composables/useValidator';
|
||||||
|
import { useQuasar } from 'quasar';
|
||||||
|
import { useSession } from 'composables/useSession';
|
||||||
|
import toCurrency from 'filters/toCurrency';
|
||||||
|
import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
|
||||||
|
import SupplierDescriptorProxy from 'pages/Supplier/Card/SupplierDescriptorProxy.vue';
|
||||||
|
import VnSearchbar from 'components/ui/VnSearchbar.vue';
|
||||||
|
import RoadmapFilter from 'pages/Route/Roadmap/RoadmapFilter.vue';
|
||||||
|
import VnConfirm from 'components/ui/VnConfirm.vue';
|
||||||
|
import axios from 'axios';
|
||||||
|
import VnInputDate from 'components/common/VnInputDate.vue';
|
||||||
|
|
||||||
|
const stateStore = useStateStore();
|
||||||
|
const { t } = useI18n();
|
||||||
|
const { validate } = useValidator();
|
||||||
|
const quasar = useQuasar();
|
||||||
|
const session = useSession();
|
||||||
|
|
||||||
|
const to = Date.vnNew();
|
||||||
|
to.setDate(to.getDate() + 1);
|
||||||
|
to.setHours(0, 0, 0, 0);
|
||||||
|
|
||||||
|
const from = Date.vnNew();
|
||||||
|
from.setDate(from.getDate());
|
||||||
|
from.setHours(0, 0, 0, 0);
|
||||||
|
|
||||||
|
const params = ref({ from, to });
|
||||||
|
|
||||||
|
onMounted(() => (stateStore.rightDrawer = true));
|
||||||
|
onUnmounted(() => (stateStore.rightDrawer = false));
|
||||||
|
|
||||||
|
const selectedRows = ref([]);
|
||||||
|
const columns = computed(() => [
|
||||||
|
{
|
||||||
|
name: 'roadmap',
|
||||||
|
label: t('Roadmap'),
|
||||||
|
field: (row) => row.name,
|
||||||
|
sortable: true,
|
||||||
|
align: 'left',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'ETD',
|
||||||
|
label: t('ETD'),
|
||||||
|
field: (row) => toDateHour(row.etd),
|
||||||
|
sortable: true,
|
||||||
|
align: 'left',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'carrier',
|
||||||
|
label: t('Carrier'),
|
||||||
|
field: (row) => row.supplier?.nickname,
|
||||||
|
sortable: true,
|
||||||
|
align: 'left',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'plate',
|
||||||
|
label: t('Plate'),
|
||||||
|
field: (row) => row.tractorPlate,
|
||||||
|
sortable: true,
|
||||||
|
align: 'left',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'price',
|
||||||
|
label: t('Price'),
|
||||||
|
field: (row) => toCurrency(row.price),
|
||||||
|
sortable: true,
|
||||||
|
align: 'left',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'observations',
|
||||||
|
label: t('Observations'),
|
||||||
|
field: (row) => dashIfEmpty(row.observations),
|
||||||
|
sortable: true,
|
||||||
|
align: 'left',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'actions',
|
||||||
|
label: '',
|
||||||
|
sortable: false,
|
||||||
|
align: 'right',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const refreshKey = ref(0);
|
||||||
|
const isCloneDialogOpen = ref(false);
|
||||||
|
const etdDate = ref(null);
|
||||||
|
const workers = ref([]);
|
||||||
|
|
||||||
|
const filter = {
|
||||||
|
include: { relation: 'supplier', scope: { fields: ['nickname'] } },
|
||||||
|
where: {
|
||||||
|
and: [{ etd: { gte: from } }, { etd: { lte: to } }],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const cloneSelection = async () => {
|
||||||
|
await axios.post('Roadmaps/clone', {
|
||||||
|
etd: etdDate.value,
|
||||||
|
ids: selectedRows.value.map((row) => row?.id),
|
||||||
|
});
|
||||||
|
refreshKey.value++;
|
||||||
|
etdDate.value = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeSelection = async () => {
|
||||||
|
await Promise.all(
|
||||||
|
selectedRows.value.map((roadmap) => {
|
||||||
|
axios.delete(`Roadmaps/${roadmap.id}`);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
function confirmRemove() {
|
||||||
|
quasar
|
||||||
|
.dialog({
|
||||||
|
component: VnConfirm,
|
||||||
|
componentProps: {
|
||||||
|
title: t('Selected roadmaps will be removed'),
|
||||||
|
message: t('Are you sure you want to continue?'),
|
||||||
|
promise: removeSelection,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.onOk(() => refreshKey.value++);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<template v-if="stateStore.isHeaderMounted()">
|
||||||
|
<Teleport to="#searchbar">
|
||||||
|
<VnSearchbar
|
||||||
|
data-key="RoadmapList"
|
||||||
|
:label="t('Search roadmap')"
|
||||||
|
:info="t('You can search by roadmap reference')"
|
||||||
|
/>
|
||||||
|
</Teleport>
|
||||||
|
<Teleport to="#actions-append">
|
||||||
|
<div class="row q-gutter-x-sm">
|
||||||
|
<QBtn
|
||||||
|
flat
|
||||||
|
@click="stateStore.toggleRightDrawer()"
|
||||||
|
round
|
||||||
|
dense
|
||||||
|
icon="menu"
|
||||||
|
>
|
||||||
|
<QTooltip bottom anchor="bottom right">
|
||||||
|
{{ t('globals.collapseMenu') }}
|
||||||
|
</QTooltip>
|
||||||
|
</QBtn>
|
||||||
|
</div>
|
||||||
|
</Teleport>
|
||||||
|
</template>
|
||||||
|
<QDrawer v-model="stateStore.rightDrawer" side="right" :width="256" show-if-above>
|
||||||
|
<QScrollArea class="fit text-grey-8">
|
||||||
|
<RoadmapFilter data-key="RoadmapList" />
|
||||||
|
</QScrollArea>
|
||||||
|
</QDrawer>
|
||||||
|
<QDialog v-model="isCloneDialogOpen">
|
||||||
|
<QCard style="min-width: 350px">
|
||||||
|
<QCardSection>
|
||||||
|
<p class="text-h6 q-ma-none">
|
||||||
|
{{ t('Select the estimated date of departure (ETD)') }}
|
||||||
|
</p>
|
||||||
|
</QCardSection>
|
||||||
|
|
||||||
|
<QCardSection class="q-pt-none">
|
||||||
|
<VnInputDate :label="t('ETD')" v-model="etdDate" autofocus />
|
||||||
|
</QCardSection>
|
||||||
|
<QCardActions align="right">
|
||||||
|
<QBtn flat :label="t('Cancel')" v-close-popup class="text-primary" />
|
||||||
|
<QBtn color="primary" v-close-popup @click="cloneSelection">
|
||||||
|
{{ t('Clone') }}
|
||||||
|
</QBtn>
|
||||||
|
</QCardActions>
|
||||||
|
</QCard>
|
||||||
|
</QDialog>
|
||||||
|
<QPage class="column items-center">
|
||||||
|
<VnSubToolbar class="bg-vn-dark justify-end">
|
||||||
|
<template #st-actions>
|
||||||
|
<QBtn
|
||||||
|
icon="vn:clone"
|
||||||
|
color="primary"
|
||||||
|
class="q-mr-sm"
|
||||||
|
:disable="!selectedRows?.length"
|
||||||
|
@click="isCloneDialogOpen = true"
|
||||||
|
>
|
||||||
|
<QTooltip>{{ t('Clone Selected Routes') }}</QTooltip>
|
||||||
|
</QBtn>
|
||||||
|
<QBtn
|
||||||
|
icon="delete"
|
||||||
|
color="primary"
|
||||||
|
class="q-mr-sm"
|
||||||
|
:disable="!selectedRows?.length"
|
||||||
|
@click="confirmRemove"
|
||||||
|
>
|
||||||
|
<QTooltip>{{ t('Delete roadmap(s)') }}</QTooltip>
|
||||||
|
</QBtn>
|
||||||
|
</template>
|
||||||
|
</VnSubToolbar>
|
||||||
|
<div class="route-list">
|
||||||
|
<VnPaginate
|
||||||
|
:key="refreshKey"
|
||||||
|
data-key="RoadmapList"
|
||||||
|
url="Roadmaps"
|
||||||
|
:limit="20"
|
||||||
|
:filter="filter"
|
||||||
|
auto-load
|
||||||
|
>
|
||||||
|
<template #body="{ rows }">
|
||||||
|
<div class="q-pa-md">
|
||||||
|
<QTable
|
||||||
|
v-model:selected="selectedRows"
|
||||||
|
:columns="columns"
|
||||||
|
:rows="rows"
|
||||||
|
flat
|
||||||
|
row-key="id"
|
||||||
|
selection="multiple"
|
||||||
|
:rows-per-page-options="[0]"
|
||||||
|
hide-pagination
|
||||||
|
:pagination="{ sortBy: 'ID', descending: true }"
|
||||||
|
>
|
||||||
|
<template #body-cell-carrier="props">
|
||||||
|
<QTd :props="props">
|
||||||
|
<span class="link">
|
||||||
|
{{ props.value }}
|
||||||
|
<SupplierDescriptorProxy
|
||||||
|
:id="props.row?.supplier?.id"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</QTd>
|
||||||
|
</template>
|
||||||
|
<template #body-cell-actions="props">
|
||||||
|
<QTd :props="props">
|
||||||
|
<div class="flex items-center table-actions">
|
||||||
|
<QIcon
|
||||||
|
name="preview"
|
||||||
|
size="xs"
|
||||||
|
color="primary"
|
||||||
|
@click="previewRoute(props?.row?.id)"
|
||||||
|
class="cursor-pointer"
|
||||||
|
>
|
||||||
|
<QTooltip>{{ t('Preview') }}</QTooltip>
|
||||||
|
</QIcon>
|
||||||
|
</div>
|
||||||
|
</QTd>
|
||||||
|
</template>
|
||||||
|
</QTable>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</VnPaginate>
|
||||||
|
</div>
|
||||||
|
<!-- <QPageSticky :offset="[20, 20]">-->
|
||||||
|
<!-- <RouterLink :to="{ name: 'RouteCreate' }">-->
|
||||||
|
<!-- <QBtn fab icon="add" color="primary" />-->
|
||||||
|
<!-- <QTooltip>-->
|
||||||
|
<!-- {{ t('newRoute') }}-->
|
||||||
|
<!-- </QTooltip>-->
|
||||||
|
<!-- </RouterLink>-->
|
||||||
|
<!-- </QPageSticky>-->
|
||||||
|
</QPage>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.route-list {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-actions {
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<i18n>
|
||||||
|
es:
|
||||||
|
Search roadmap: Buscar trocal
|
||||||
|
You can search by roadmap reference: Puedes buscar por referencia de la trocal
|
||||||
|
Delete roadmap(s): Eliminar trocal(es)
|
||||||
|
Selected roadmaps will be removed: Las trocales seleccionadas serán eliminadas
|
||||||
|
Are you sure you want to continue?: ¿Seguro que quieres continuar?
|
||||||
|
The date can't be empty: La fecha no puede estar vacía
|
||||||
|
Clone Selected Routes: Clonar rutas seleccionadas
|
||||||
|
Roadmap: Trocal
|
||||||
|
Carrier: Transportista
|
||||||
|
Plate: Placa
|
||||||
|
Price: Precio
|
||||||
|
Observations: Observaciones
|
||||||
|
</i18n>
|
|
@ -10,7 +10,7 @@ export default {
|
||||||
component: RouterView,
|
component: RouterView,
|
||||||
redirect: { name: 'RouteMain' },
|
redirect: { name: 'RouteMain' },
|
||||||
menus: {
|
menus: {
|
||||||
main: ['RouteList', 'RouteAutonomous', 'CmrList'],
|
main: ['RouteList', 'RouteAutonomous', 'RouteRoadmap', 'CmrList'],
|
||||||
card: ['RouteBasicData', 'RouteTickets', 'RouteLog'],
|
card: ['RouteBasicData', 'RouteTickets', 'RouteLog'],
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
|
@ -29,6 +29,15 @@ export default {
|
||||||
},
|
},
|
||||||
component: () => import('src/pages/Route/RouteList.vue'),
|
component: () => import('src/pages/Route/RouteList.vue'),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'roadmap',
|
||||||
|
name: 'RouteRoadmap',
|
||||||
|
meta: {
|
||||||
|
title: 'RouteRoadmap',
|
||||||
|
icon: 'vn:troncales',
|
||||||
|
},
|
||||||
|
component: () => import('src/pages/Route/RouteRoadmap.vue'),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'create',
|
path: 'create',
|
||||||
name: 'RouteCreate',
|
name: 'RouteCreate',
|
||||||
|
|
Loading…
Reference in New Issue