From 6ae38d26119baf867d039ee29682ed26f360072f Mon Sep 17 00:00:00 2001
From: Jon <jon@verdnatura.es>
Date: Mon, 29 Apr 2024 09:49:06 +0200
Subject: [PATCH 1/6] refactor: refs #6887 pending claim changes

---
 src/i18n/locale/en.yml                        |   3 +-
 src/i18n/locale/es.yml                        |   3 +-
 src/pages/Claim/Card/ClaimDescriptor.vue      |  14 +-
 src/pages/Claim/Card/ClaimSummary.vue         |  45 ++++++-
 src/pages/Zone/Card/ZoneDescriptor.vue        | 127 ++++++++++++++++++
 .../Zone/Card/ZoneDescriptorMenuItems.vue     | 108 +++++++++++++++
 src/pages/Zone/Card/ZoneDescriptorProxy.vue   |  16 +++
 7 files changed, 309 insertions(+), 7 deletions(-)
 create mode 100644 src/pages/Zone/Card/ZoneDescriptor.vue
 create mode 100644 src/pages/Zone/Card/ZoneDescriptorMenuItems.vue
 create mode 100644 src/pages/Zone/Card/ZoneDescriptorProxy.vue

diff --git a/src/i18n/locale/en.yml b/src/i18n/locale/en.yml
index ff57bf968..942018b84 100644
--- a/src/i18n/locale/en.yml
+++ b/src/i18n/locale/en.yml
@@ -513,7 +513,7 @@ claim:
         records: records
     card:
         claimId: Claim ID
-        assignedTo: Assigned
+        attendedBy: Attended by
         created: Created
         state: State
         ticketId: Ticket ID
@@ -551,6 +551,7 @@ claim:
         responsible: Responsible
         worker: Worker
         redelivery: Redelivery
+        changeState: Change state
     basicData:
         customer: Customer
         assignedTo: Assigned
diff --git a/src/i18n/locale/es.yml b/src/i18n/locale/es.yml
index f9278a9b0..3de5af50c 100644
--- a/src/i18n/locale/es.yml
+++ b/src/i18n/locale/es.yml
@@ -511,7 +511,7 @@ claim:
         records: registros
     card:
         claimId: ID reclamación
-        assignedTo: Asignada a
+        attendedBy: Atendida por
         created: Creada
         state: Estado
         ticketId: ID ticket
@@ -549,6 +549,7 @@ claim:
         responsible: Responsable
         worker: Trabajador
         redelivery: Devolución
+        changeState: Cambiar estado
     basicData:
         customer: Cliente
         assignedTo: Asignada a
diff --git a/src/pages/Claim/Card/ClaimDescriptor.vue b/src/pages/Claim/Card/ClaimDescriptor.vue
index 968f1e294..3b5dd82b8 100644
--- a/src/pages/Claim/Card/ClaimDescriptor.vue
+++ b/src/pages/Claim/Card/ClaimDescriptor.vue
@@ -11,6 +11,7 @@ import VnLv from 'src/components/ui/VnLv.vue';
 import useCardDescription from 'src/composables/useCardDescription';
 import VnUserLink from 'src/components/ui/VnUserLink.vue';
 import { getUrl } from 'src/composables/getUrl';
+import ZoneDescriptorProxy from 'src/pages/Zone/Card/ZoneDescriptorProxy.vue';
 
 const $props = defineProps({
     id: {
@@ -127,17 +128,24 @@ onMounted(async () => {
             </VnLv>
             <VnLv
                 v-if="entity.worker"
-                :label="t('claim.card.assignedTo')"
+                :label="t('claim.card.attendedBy')"
                 :value="entity.worker.user.name"
             >
                 <template #value>
                     <VnUserLink
-                        :name="entity.worker.user.name"
+                        :name="entity.worker.user.nickname"
                         :worker-id="entity.worker.id"
                     />
                 </template>
             </VnLv>
-            <VnLv :label="t('claim.card.zone')" :value="entity.ticket?.zone?.name" />
+            <VnLv :label="t('claim.card.zone')">
+                <template #value>
+                    <span class="link">
+                        {{ entity.ticket?.zone?.name }}
+                        <ZoneDescriptorProxy :id="entity.ticket?.zoneFk" />
+                    </span>
+                </template>
+            </VnLv>
             <VnLv
                 :label="t('claim.card.province')"
                 :value="entity.ticket?.address?.province?.name"
diff --git a/src/pages/Claim/Card/ClaimSummary.vue b/src/pages/Claim/Card/ClaimSummary.vue
index f45d5765d..c4c2785d5 100644
--- a/src/pages/Claim/Card/ClaimSummary.vue
+++ b/src/pages/Claim/Card/ClaimSummary.vue
@@ -1,6 +1,6 @@
 <script setup>
 import { onMounted, ref, computed } from 'vue';
-import { useRoute } from 'vue-router';
+import { useRoute, useRouter } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 import { toDate, toCurrency } from 'src/filters';
 import CardSummary from 'components/ui/CardSummary.vue';
@@ -13,8 +13,10 @@ import VnUserLink from 'src/components/ui/VnUserLink.vue';
 import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
 import VnTitle from 'src/components/common/VnTitle.vue';
 import CustomerDescriptorProxy from 'src/pages/Customer/Card/CustomerDescriptorProxy.vue';
+import axios from 'axios';
 
 const route = useRoute();
+const router = useRouter();
 const { t } = useI18n();
 const { getTokenMultimedia } = useSession();
 const token = getTokenMultimedia();
@@ -27,7 +29,7 @@ const $props = defineProps({
 });
 
 const entityId = computed(() => $props.id || route.params.id);
-
+const ClaimStates = ref([]);
 const claimUrl = ref();
 const salixUrl = ref();
 const claimDmsRef = ref();
@@ -162,6 +164,10 @@ function openDialog(dmsId) {
     multimediaSlide.value = dmsId;
     multimediaDialog.value = true;
 }
+async function changeState(value) {
+    await axios.patch(`Claims/updateClaim/${entityId.value}`, { claimStateFk: value });
+    router.go(route.fullPath);
+}
 </script>
 
 <template>
@@ -171,6 +177,7 @@ function openDialog(dmsId) {
         @on-fetch="(data) => setClaimDms(data)"
         ref="claimDmsRef"
     />
+    <FetchData url="ClaimStates" @on-fetch="(data) => (ClaimStates = data)" auto-load />
     <CardSummary
         ref="summary"
         :url="`Claims/${entityId}/getSummary`"
@@ -180,6 +187,36 @@ function openDialog(dmsId) {
         <template #header="{ entity: { claim } }">
             {{ claim.id }} - {{ claim.client.name }} ({{ claim.client.id }})
         </template>
+        <template #header-right>
+            <QBtnDropdown
+                side
+                top
+                color="black"
+                text-color="white"
+                :label="t('ticket.summary.changeState')"
+            >
+                <QList>
+                    <QVirtualScroll
+                        style="max-height: 300px"
+                        :items="ClaimStates"
+                        separator
+                        v-slot="{ item, index }"
+                    >
+                        <QItem
+                            :key="index"
+                            dense
+                            clickable
+                            v-close-popup
+                            @click="changeState(item.id)"
+                        >
+                            <QItemSection>
+                                <QItemLabel>{{ item.description }}</QItemLabel>
+                            </QItemSection>
+                        </QItem>
+                    </QVirtualScroll>
+                </QList>
+            </QBtnDropdown>
+        </template>
         <template #body="{ entity: { claim, salesClaimed, developments } }">
             <QCard class="vn-one">
                 <VnTitle
@@ -447,4 +484,8 @@ function openDialog(dmsId) {
 .zindex {
     z-index: 1;
 }
+
+.change-state {
+    width: 10%;
+}
 </style>
diff --git a/src/pages/Zone/Card/ZoneDescriptor.vue b/src/pages/Zone/Card/ZoneDescriptor.vue
new file mode 100644
index 000000000..665cb6f0e
--- /dev/null
+++ b/src/pages/Zone/Card/ZoneDescriptor.vue
@@ -0,0 +1,127 @@
+<script setup>
+import { ref, computed } from 'vue';
+import { useRoute } from 'vue-router';
+import { useI18n } from 'vue-i18n';
+
+import CardDescriptor from 'components/ui/CardDescriptor.vue';
+import VnLv from 'src/components/ui/VnLv.vue';
+import ZoneDescriptorMenuItems from './ZoneDescriptorMenuItems.vue';
+
+import useCardDescription from 'src/composables/useCardDescription';
+import { toDate } from 'src/filters';
+
+const $props = defineProps({
+    id: {
+        type: Number,
+        required: false,
+        default: null,
+    },
+});
+
+const route = useRoute();
+const { t } = useI18n();
+
+const filter = {
+    fields: [
+        'id',
+        'ref',
+        'shipped',
+        'landed',
+        'totalEntries',
+        'warehouseInFk',
+        'warehouseOutFk',
+        'cargoSupplierFk',
+        'agencyModeFk',
+    ],
+    include: [
+        {
+            relation: 'warehouseIn',
+            scope: {
+                fields: ['name'],
+            },
+        },
+        {
+            relation: 'warehouseOut',
+            scope: {
+                fields: ['name'],
+            },
+        },
+    ],
+};
+
+const entityId = computed(() => {
+    return $props.id || route.params.id;
+});
+
+const data = ref(useCardDescription());
+
+const setData = (entity) => {
+    data.value = useCardDescription(entity.ref, entity.id);
+};
+</script>
+
+<template>
+    <CardDescriptor
+        module="Zone"
+        :url="`Zones/${entityId}`"
+        :title="data.title"
+        :subtitle="data.subtitle"
+        :filter="filter"
+        @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: 'ZoneList' }"
+            >
+                <QTooltip>
+                    {{ t('Go to module index') }}
+                </QTooltip>
+            </QBtn>
+        </template>
+        <template #menu="{ entity }">
+            <ZoneDescriptorMenuItems :travel="entity" />
+        </template>
+        <template #body="{ entity }">
+            <VnLv :label="t('globals.wareHouseIn')" :value="entity.warehouseIn.name" />
+            <VnLv :label="t('globals.wareHouseOut')" :value="entity.warehouseOut.name" />
+            <VnLv :label="t('globals.shipped')" :value="toDate(entity.shipped)" />
+            <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: 'ZoneList',
+                        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>
+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>
diff --git a/src/pages/Zone/Card/ZoneDescriptorMenuItems.vue b/src/pages/Zone/Card/ZoneDescriptorMenuItems.vue
new file mode 100644
index 000000000..920d83dfe
--- /dev/null
+++ b/src/pages/Zone/Card/ZoneDescriptorMenuItems.vue
@@ -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: 'ZoneCreate', query: { travelData: queryParams } });
+};
+
+const cloneZone = () => {
+    const stringifiedZoneData = JSON.stringify($props.travel);
+    redirectToCreateView(stringifiedZoneData);
+};
+
+const cloneZoneWithEntries = () => {
+    try {
+        axios.post(`Zones/${$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 deleteZone(id);
+        });
+};
+
+const deleteZone = async (id) => {
+    try {
+        await axios.delete(`Zones/${id}`);
+        router.push({ name: 'ZoneList' });
+        notify('globals.dataDeleted', 'positive');
+    } catch (err) {
+        console.error('Error deleting travel');
+    }
+};
+</script>
+
+<template>
+    <QItem v-ripple clickable @click="cloneZone(travel)">
+        <QItemSection>{{ t('travel.summary.cloneShipping') }}</QItemSection>
+    </QItem>
+    <QItem v-ripple clickable @click="cloneZoneWithEntries()">
+        <QItemSection>
+            {{ t('travel.summary.CloneZoneAndEntries') }}
+        </QItemSection>
+    </QItem>
+    <QItem
+        v-if="isBuyer && travel.totalEntries === 0"
+        v-ripple
+        clickable
+        @click="openDeleteEntryDialog(travel.id)"
+    >
+        <QItemSection>
+            {{ t('travel.summary.deleteZone') }}
+        </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>
diff --git a/src/pages/Zone/Card/ZoneDescriptorProxy.vue b/src/pages/Zone/Card/ZoneDescriptorProxy.vue
new file mode 100644
index 000000000..15c5fb0e5
--- /dev/null
+++ b/src/pages/Zone/Card/ZoneDescriptorProxy.vue
@@ -0,0 +1,16 @@
+<script setup>
+import ZoneDescriptor from './ZoneDescriptor.vue';
+
+const $props = defineProps({
+    id: {
+        type: Number,
+        required: true,
+    },
+});
+</script>
+
+<template>
+    <QPopupProxy>
+        <ZoneDescriptor v-if="$props.id" :id="$props.id" />
+    </QPopupProxy>
+</template>

From a5d6ca447bb37092b259aab3cc32ffa729eed0e2 Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Mon, 29 Apr 2024 12:12:20 +0200
Subject: [PATCH 2/6] fix: TicketSummary.packages label

---
 src/pages/Ticket/Card/TicketSummary.vue | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/pages/Ticket/Card/TicketSummary.vue b/src/pages/Ticket/Card/TicketSummary.vue
index 364ae04a6..af501240b 100644
--- a/src/pages/Ticket/Card/TicketSummary.vue
+++ b/src/pages/Ticket/Card/TicketSummary.vue
@@ -188,7 +188,7 @@ async function changeState(value) {
                     :label="t('ticket.summary.landed')"
                     :value="toDate(ticket.landed)"
                 />
-                <VnLv :label="t('global.packages')" :value="ticket.packages" />
+                <VnLv :label="t('globals.packages')" :value="ticket.packages" />
                 <VnLv :value="ticket.address.phone">
                     <template #label>
                         {{ t('ticket.summary.consigneePhone') }}

From 5b15558dbf4dd017c0588ffd64cf2f64307799a4 Mon Sep 17 00:00:00 2001
From: Jon <jon@verdnatura.es>
Date: Tue, 30 Apr 2024 10:32:32 +0200
Subject: [PATCH 3/6] refactor: refs #6887 fixed errors

---
 src/css/app.scss                         |   9 --
 src/i18n/locale/en.yml                   |   6 +
 src/i18n/locale/es.yml                   |   6 +
 src/pages/Claim/Card/ClaimDescriptor.vue |   5 +-
 src/pages/Claim/Card/ClaimSummary.vue    |   6 +-
 src/pages/Zone/Card/ZoneCard.vue         |   6 +
 src/pages/Zone/Card/ZoneDescriptor.vue   |  72 ++++-------
 src/router/modules/index.js              |   2 +
 src/router/modules/zone.js               | 158 +++++++++++++++++++++++
 src/router/routes.js                     |   2 +
 src/stores/useNavigationStore.js         |   1 +
 11 files changed, 212 insertions(+), 61 deletions(-)
 create mode 100644 src/pages/Zone/Card/ZoneCard.vue
 create mode 100644 src/router/modules/zone.js

diff --git a/src/css/app.scss b/src/css/app.scss
index 770df8e01..2e524e693 100644
--- a/src/css/app.scss
+++ b/src/css/app.scss
@@ -141,15 +141,6 @@ select:-webkit-autofill {
     background-color: var(--vn-section-color);
 }
 
-.q-checkbox {
-    & .q-checkbox__label {
-        color: var(--vn-text-color);
-    }
-    & .q-checkbox__inner {
-        color: var(--vn-label-color);
-    }
-}
-
 .tr-header {
     color: var(--vn-label-color);
 }
diff --git a/src/i18n/locale/en.yml b/src/i18n/locale/en.yml
index 942018b84..7a341dded 100644
--- a/src/i18n/locale/en.yml
+++ b/src/i18n/locale/en.yml
@@ -1166,6 +1166,12 @@ item:
         type: Type
         intrastat: Intrastat
         origin: Origin
+zone:
+    pageTitles:
+        zones: Zone
+        zonesList: Zones
+        deliveryList: Delivery days
+        upcomingList: Upcoming deliveries
 components:
     topbar: {}
     itemsFilterPanel:
diff --git a/src/i18n/locale/es.yml b/src/i18n/locale/es.yml
index 3de5af50c..9286cbccb 100644
--- a/src/i18n/locale/es.yml
+++ b/src/i18n/locale/es.yml
@@ -1165,6 +1165,12 @@ item:
         type: Tipo
         intrastat: Intrastat
         origin: Origen
+zone:
+    pageTitles:
+        zones: Zona
+        zonesList: Zonas
+        deliveryList: Días de entrega
+        upcomingList: Próximos repartos
 components:
     topbar: {}
     itemsFilterPanel:
diff --git a/src/pages/Claim/Card/ClaimDescriptor.vue b/src/pages/Claim/Card/ClaimDescriptor.vue
index 3b5dd82b8..aae999117 100644
--- a/src/pages/Claim/Card/ClaimDescriptor.vue
+++ b/src/pages/Claim/Card/ClaimDescriptor.vue
@@ -74,8 +74,9 @@ const filter = {
 
 const STATE_COLOR = {
     pending: 'warning',
-    managed: 'info',
+    incomplete: 'info',
     resolved: 'positive',
+    canceled: 'negative',
 };
 function stateColor(code) {
     return STATE_COLOR[code];
@@ -142,7 +143,7 @@ onMounted(async () => {
                 <template #value>
                     <span class="link">
                         {{ entity.ticket?.zone?.name }}
-                        <ZoneDescriptorProxy :id="entity.ticket?.zoneFk" />
+                        <ZoneDescriptorProxy :id="entity.ticket?.zone?.id" />
                     </span>
                 </template>
             </VnLv>
diff --git a/src/pages/Claim/Card/ClaimSummary.vue b/src/pages/Claim/Card/ClaimSummary.vue
index c4c2785d5..36a26008e 100644
--- a/src/pages/Claim/Card/ClaimSummary.vue
+++ b/src/pages/Claim/Card/ClaimSummary.vue
@@ -14,6 +14,7 @@ import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
 import VnTitle from 'src/components/common/VnTitle.vue';
 import CustomerDescriptorProxy from 'src/pages/Customer/Card/CustomerDescriptorProxy.vue';
 import axios from 'axios';
+import dashIfEmpty from 'src/filters/dashIfEmpty';
 
 const route = useRoute();
 const router = useRouter();
@@ -101,8 +102,9 @@ const detailsColumns = ref([
 
 const STATE_COLOR = {
     pending: 'warning',
-    managed: 'info',
+    incomplete: 'info',
     resolved: 'positive',
+    canceled: 'negative',
 };
 function stateColor(code) {
     return STATE_COLOR[code];
@@ -260,7 +262,7 @@ async function changeState(value) {
                 </VnLv>
                 <VnLv
                     :label="t('claim.basicData.pickup')"
-                    :value="t(`claim.basicData.${claim.pickup}`)"
+                    :value="`${dashIfEmpty(claim.pickup)}`"
                 />
             </QCard>
             <QCard class="vn-three">
diff --git a/src/pages/Zone/Card/ZoneCard.vue b/src/pages/Zone/Card/ZoneCard.vue
new file mode 100644
index 000000000..948636c55
--- /dev/null
+++ b/src/pages/Zone/Card/ZoneCard.vue
@@ -0,0 +1,6 @@
+<script setup>
+import VnCard from 'components/common/VnCard.vue';
+</script>
+<template>
+    <VnCard data-key="Zone" base-url="Zones" />
+</template>
diff --git a/src/pages/Zone/Card/ZoneDescriptor.vue b/src/pages/Zone/Card/ZoneDescriptor.vue
index 665cb6f0e..b56443c84 100644
--- a/src/pages/Zone/Card/ZoneDescriptor.vue
+++ b/src/pages/Zone/Card/ZoneDescriptor.vue
@@ -8,7 +8,6 @@ import VnLv from 'src/components/ui/VnLv.vue';
 import ZoneDescriptorMenuItems from './ZoneDescriptorMenuItems.vue';
 
 import useCardDescription from 'src/composables/useCardDescription';
-import { toDate } from 'src/filters';
 
 const $props = defineProps({
     id: {
@@ -22,28 +21,11 @@ const route = useRoute();
 const { t } = useI18n();
 
 const filter = {
-    fields: [
-        'id',
-        'ref',
-        'shipped',
-        'landed',
-        'totalEntries',
-        'warehouseInFk',
-        'warehouseOutFk',
-        'cargoSupplierFk',
-        'agencyModeFk',
-    ],
     include: [
         {
-            relation: 'warehouseIn',
+            relation: 'agencyMode',
             scope: {
-                fields: ['name'],
-            },
-        },
-        {
-            relation: 'warehouseOut',
-            scope: {
-                fields: ['name'],
+                fields: ['name', 'id'],
             },
         },
     ],
@@ -58,6 +40,13 @@ const data = ref(useCardDescription());
 const setData = (entity) => {
     data.value = useCardDescription(entity.ref, entity.id);
 };
+
+function extractHour(dateTime) {
+    const date = new Date(dateTime);
+    const hours = date.getHours().toString().padStart(2, '0');
+    const minutes = date.getMinutes().toString().padStart(2, '0');
+    return `${hours}:${minutes}`;
+}
 </script>
 
 <template>
@@ -76,52 +65,39 @@ const setData = (entity) => {
                 flat
                 dense
                 size="md"
-                icon="local_airport"
+                icon="preview"
                 color="white"
                 class="link"
                 :to="{ name: 'ZoneList' }"
             >
                 <QTooltip>
-                    {{ t('Go to module index') }}
+                    {{ t('Summary') }}
                 </QTooltip>
             </QBtn>
         </template>
         <template #menu="{ entity }">
-            <ZoneDescriptorMenuItems :travel="entity" />
+            <ZoneDescriptorMenuItems :zone="entity" />
         </template>
         <template #body="{ entity }">
-            <VnLv :label="t('globals.wareHouseIn')" :value="entity.warehouseIn.name" />
-            <VnLv :label="t('globals.wareHouseOut')" :value="entity.warehouseOut.name" />
-            <VnLv :label="t('globals.shipped')" :value="toDate(entity.shipped)" />
-            <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: 'ZoneList',
-                        query: {
-                            params: JSON.stringify({
-                                agencyModeFk: entity.agencyModeFk,
-                            }),
-                        },
-                    }"
-                    size="md"
-                    icon="local_airport"
-                    color="primary"
-                >
-                    <QTooltip>{{ t('All travels with current agency') }}</QTooltip>
-                </QBtn>
-            </QCardActions>
+            {{ console.log('entity', entity) }}
+            <VnLv :label="t('Agency')" :value="entity.agencyMode.name" />
+            <VnLv :label="t('Closing hour')" :value="extractHour(entity.hour)" />
+            <VnLv :label="t('traveling days')" :value="entity.travelingDays" />
+            <VnLv :label="t('Price')" :value="entity.price" />
+            <VnLv :label="t('Bonus')" :value="entity.bonus" />
         </template>
     </CardDescriptor>
 </template>
 
 <i18n>
 es:
-    Go to module index: Ir al índice del módulo
+    Summary: Detalles
     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
+    Agency: Agencia
+    Closing hour: Hora de cierre
+    traveling days: Días de viaje
+    Price: Precio
+    Bonus: Bonificación
 </i18n>
diff --git a/src/router/modules/index.js b/src/router/modules/index.js
index 302ba7fe0..2fe40038f 100644
--- a/src/router/modules/index.js
+++ b/src/router/modules/index.js
@@ -15,6 +15,7 @@ import Department from './department';
 import Entry from './entry';
 import roadmap from './roadmap';
 import Parking from './parking';
+import Zone from './zone';
 
 export default [
     Item,
@@ -34,4 +35,5 @@ export default [
     Entry,
     roadmap,
     Parking,
+    Zone,
 ];
diff --git a/src/router/modules/zone.js b/src/router/modules/zone.js
new file mode 100644
index 000000000..bd74a76f3
--- /dev/null
+++ b/src/router/modules/zone.js
@@ -0,0 +1,158 @@
+import { RouterView } from 'vue-router';
+
+export default {
+    path: '/zone',
+    name: 'Zone',
+    meta: {
+        title: 'zones',
+        icon: 'vn:zone',
+        moduleName: 'Zone',
+    },
+    component: RouterView,
+    redirect: { name: 'ZoneMain' },
+    menus: {
+        main: ['ZoneList' /*'ZoneDeliveryList', 'ZoneUpcomingList'*/],
+        card: [
+            //
+        ],
+    },
+    children: [
+        {
+            path: '/zone',
+            name: 'ZoneMain',
+            component: () => import('src/pages/Zone/ZoneMain.vue'),
+            redirect: { name: 'ZoneList' },
+            children: [
+                {
+                    path: 'list',
+                    name: 'ZoneList',
+                    meta: {
+                        title: 'zonesList',
+                        icon: 'vn:zone',
+                    },
+                    component: () => import('src/pages/Zone/ZoneList.vue'),
+                },
+                // {
+                //     path: 'create',
+                //     name: 'ZoneCreate',
+                //     meta: {
+                //         title: 'zoneCreate',
+                //         icon: 'create',
+                //     },
+                //     component: () => import('src/pages/Zone/ZoneCreate.vue'),
+                // },
+                // {
+                //     path: ':id/edit',
+                //     name: 'ZoneEdit',
+                //     meta: {
+                //         title: 'zoneEdit',
+                //         icon: 'edit',
+                //     },
+                //     component: () => import('src/pages/Zone/ZoneCreate.vue'),
+                // },
+                // {
+                //     path: 'counter',
+                //     name: 'ZoneCounter',
+                //     meta: {
+                //         title: 'zoneCounter',
+                //         icon: 'add_circle',
+                //     },
+                //     component: () => import('src/pages/Zone/ZoneCounter.vue'),
+                // },
+            ],
+        },
+        {
+            name: 'ZoneCard',
+            path: ':id',
+            component: () => import('src/pages/Zone/Card/ZoneCard.vue'),
+            redirect: { name: 'ZoneSummary' },
+            children: [
+                {
+                    name: 'ZoneSummary',
+                    path: 'summary',
+                    meta: {
+                        title: 'summary',
+                        icon: 'launch',
+                    },
+                    component: () => import('src/pages/Zone/Card/ZoneSummary.vue'),
+                },
+                // {
+                //     path: '/zone/delivery',
+                //     name: 'ZoneDeliveryMain',
+                //     component: () => import('src/pages/Zone/ZoneMain.vue'),
+                //     redirect: { name: 'ZoneDeliveryList' },
+                //     children: [
+                //         {
+                //             path: 'list',
+                //             name: 'ZoneDeliveryList',
+                //             meta: {
+                //                 title: 'deliveryList',
+                //                 icon: 'today',
+                //             },
+                //             component: () =>
+                //                 import('src/pages/Zone/Delivery/ZoneDeliveryList.vue'),
+                //         },
+                //         {
+                //             path: 'create',
+                //             name: 'ZoneDeliveryCreate',
+                //             meta: {
+                //                 title: 'deliveryCreate',
+                //                 icon: 'create',
+                //             },
+                //             component: () =>
+                //                 import('src/pages/Zone/Delivery/ZoneDeliveryCreate.vue'),
+                //         },
+                //         {
+                //             path: ':id/edit',
+                //             name: 'ZoneDeliveryEdit',
+                //             meta: {
+                //                 title: 'deliveryEdit',
+                //                 icon: 'edit',
+                //             },
+                //             component: () =>
+                //                 import('src/pages/Zone/Delivery/ZoneDeliveryCreate.vue'),
+                //         },
+                //     ],
+                // },
+                // {
+                //     path: '/zone/upcoming',
+                //     name: 'ZoneUpcomingMain',
+                //     component: () => import('src/pages/Zone/ZoneMain.vue'),
+                //     redirect: { name: 'ZoneUpcomingList' },
+                //     children: [
+                //         {
+                //             path: 'list',
+                //             name: 'ZoneUpcomingList',
+                //             meta: {
+                //                 title: 'upcomingList',
+                //                 icon: 'today',
+                //             },
+                //             component: () =>
+                //                 import('src/pages/Zone/Upcoming/ZoneUpcomingList.vue'),
+                //         },
+                //         {
+                //             path: 'create',
+                //             name: 'ZoneUpcomingCreate',
+                //             meta: {
+                //                 title: 'upcomingCreate',
+                //                 icon: 'create',
+                //             },
+                //             component: () =>
+                //                 import('src/pages/Zone/Upcoming/ZoneUpcomingCreate.vue'),
+                //         },
+                //         {
+                //             path: ':id/edit',
+                //             name: 'ZoneUpcomingEdit',
+                //             meta: {
+                //                 title: 'upcomingEdit',
+                //                 icon: 'edit',
+                //             },
+                //             component: () =>
+                //                 import('src/pages/Zone/Upcoming/ZoneUpcomingCreate.vue'),
+                //         },
+                //     ],
+                // },
+            ],
+        },
+    ],
+};
diff --git a/src/router/routes.js b/src/router/routes.js
index 51e726a62..14bf6665f 100644
--- a/src/router/routes.js
+++ b/src/router/routes.js
@@ -15,6 +15,7 @@ import order from 'src/router/modules/order';
 import entry from 'src/router/modules/entry';
 import roadmap from 'src/router/modules/roadmap';
 import parking from 'src/router/modules/parking';
+import zone from 'src/router/modules/zone';
 
 const routes = [
     {
@@ -71,6 +72,7 @@ const routes = [
             roadmap,
             entry,
             parking,
+            zone,
             {
                 path: '/:catchAll(.*)*',
                 name: 'NotFound',
diff --git a/src/stores/useNavigationStore.js b/src/stores/useNavigationStore.js
index f075301f6..ee1e04e9b 100644
--- a/src/stores/useNavigationStore.js
+++ b/src/stores/useNavigationStore.js
@@ -21,6 +21,7 @@ export const useNavigationStore = defineStore('navigationStore', () => {
         'ticket',
         'worker',
         'wagon',
+        'zone',
     ];
     const pinnedModules = ref([]);
     const role = useRole();

From a512f094d6950375135b4d0d5d9e7d337c497a5f Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Tue, 30 Apr 2024 12:06:24 +0200
Subject: [PATCH 4/6] perf: ZoneDescriptor

---
 src/pages/Zone/Card/ZoneDescriptor.vue        |  16 +-
 .../Zone/Card/ZoneDescriptorMenuItems.vue     | 143 ++++++++----------
 2 files changed, 72 insertions(+), 87 deletions(-)

diff --git a/src/pages/Zone/Card/ZoneDescriptor.vue b/src/pages/Zone/Card/ZoneDescriptor.vue
index b56443c84..486e4f063 100644
--- a/src/pages/Zone/Card/ZoneDescriptor.vue
+++ b/src/pages/Zone/Card/ZoneDescriptor.vue
@@ -57,7 +57,7 @@ function extractHour(dateTime) {
         :subtitle="data.subtitle"
         :filter="filter"
         @on-fetch="setData"
-        data-key="travelData"
+        data-key="zoneData"
     >
         <template #header-extra-action>
             <QBtn
@@ -75,14 +75,14 @@ function extractHour(dateTime) {
                 </QTooltip>
             </QBtn>
         </template>
-        <template #menu="{ entity }">
+        <!-- <template #menu="{ entity }">
             <ZoneDescriptorMenuItems :zone="entity" />
-        </template>
+        </template> -->
         <template #body="{ entity }">
             {{ console.log('entity', entity) }}
             <VnLv :label="t('Agency')" :value="entity.agencyMode.name" />
             <VnLv :label="t('Closing hour')" :value="extractHour(entity.hour)" />
-            <VnLv :label="t('traveling days')" :value="entity.travelingDays" />
+            <VnLv :label="t('zoneing days')" :value="entity.zoneingDays" />
             <VnLv :label="t('Price')" :value="entity.price" />
             <VnLv :label="t('Bonus')" :value="entity.bonus" />
         </template>
@@ -92,12 +92,12 @@ function extractHour(dateTime) {
 <i18n>
 es:
     Summary: Detalles
-    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
+    The zone will be deleted: El envío será eliminado
+    Do you want to delete this zone?: ¿Quieres eliminar este envío?
+    All zones with current agency: Todos los envíos con la agencia actual
     Agency: Agencia
     Closing hour: Hora de cierre
-    traveling days: Días de viaje
+    zoneing days: Días de viaje
     Price: Precio
     Bonus: Bonificación
 </i18n>
diff --git a/src/pages/Zone/Card/ZoneDescriptorMenuItems.vue b/src/pages/Zone/Card/ZoneDescriptorMenuItems.vue
index 920d83dfe..b6c7f28b3 100644
--- a/src/pages/Zone/Card/ZoneDescriptorMenuItems.vue
+++ b/src/pages/Zone/Card/ZoneDescriptorMenuItems.vue
@@ -1,108 +1,93 @@
 <script setup>
-import { computed } from 'vue';
 import { useQuasar } from 'quasar';
 import { useRouter } from 'vue-router';
 import { useI18n } from 'vue-i18n';
+const { dialog, notify } = useQuasar();
 
 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: {
+    zone: {
         type: Object,
         default: () => {},
     },
 });
 
 const { t } = useI18n();
-const router = useRouter();
-const quasar = useQuasar();
-const { notify } = useNotify();
-const role = useRole();
+const { push, currentRoute } = useRouter();
+const zoneId = currentRoute.value.params.id;
 
-const redirectToCreateView = (queryParams) => {
-    router.push({ name: 'ZoneCreate', query: { travelData: queryParams } });
-};
-
-const cloneZone = () => {
-    const stringifiedZoneData = JSON.stringify($props.travel);
-    redirectToCreateView(stringifiedZoneData);
-};
-
-const cloneZoneWithEntries = () => {
-    try {
-        axios.post(`Zones/${$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 deleteZone(id);
-        });
-};
-
-const deleteZone = async (id) => {
-    try {
-        await axios.delete(`Zones/${id}`);
-        router.push({ name: 'ZoneList' });
-        notify('globals.dataDeleted', 'positive');
-    } catch (err) {
-        console.error('Error deleting travel');
-    }
+const actions = {
+    clone: async () => {
+        const opts = { message: t('Zone cloned'), type: 'positive' };
+        let clonedZoneId;
+
+        try {
+            const { data } = await axios.post(`Zones/${zoneId}/clone`, {
+                shipped: $props.zone.value.shipped,
+            });
+            clonedZoneId = data;
+        } catch (e) {
+            opts.message = t('It was not able to clone the zone');
+            opts.type = 'negative';
+        } finally {
+            notify(opts);
+
+            if (clonedZoneId) push({ name: 'ZoneSummary', params: { id: clonedZoneId } });
+        }
+    },
+    remove: async () => {
+        try {
+            await axios.post(`Zones/${zoneId}/setDeleted`);
+
+            notify({ message: t('Zone deleted'), type: 'positive' });
+            notify({
+                message: t('You can undo this action within the first hour'),
+                icon: 'info',
+            });
+
+            push({ name: 'ZoneList' });
+        } catch (e) {
+            notify({ message: e.message, type: 'negative' });
+        }
+    },
 };
+function openConfirmDialog(callback) {
+    dialog({
+        component: VnConfirm,
+        componentProps: {
+            promise: actions[callback],
+        },
+    });
+}
 </script>
-
 <template>
-    <QItem v-ripple clickable @click="cloneZone(travel)">
-        <QItemSection>{{ t('travel.summary.cloneShipping') }}</QItemSection>
-    </QItem>
-    <QItem v-ripple clickable @click="cloneZoneWithEntries()">
-        <QItemSection>
-            {{ t('travel.summary.CloneZoneAndEntries') }}
+    <QItem @click="openConfirmDialog('clone')" v-ripple clickable>
+        <QItemSection avatar>
+            <QIcon name="content_copy" />
         </QItemSection>
+        <QItemSection>{{ t('To clone zone') }}</QItemSection>
     </QItem>
-    <QItem
-        v-if="isBuyer && travel.totalEntries === 0"
-        v-ripple
-        clickable
-        @click="openDeleteEntryDialog(travel.id)"
-    >
-        <QItemSection>
-            {{ t('travel.summary.deleteZone') }}
-        </QItemSection>
-    </QItem>
-    <QItem v-ripple clickable>
-        <QItemSection>
-            <RouterLink
-                :to="{ name: 'EntryCreate', query: { travelFk: travel.id } }"
-                class="color-vn-text"
-            >
-                {{ t('travel.summary.AddEntry') }}
-            </RouterLink>
+    <QItem @click="openConfirmDialog('remove')" v-ripple clickable>
+        <QItemSection avatar>
+            <QIcon name="delete" />
         </QItemSection>
+        <QItemSection>{{ t('deleteOrder') }}</QItemSection>
     </QItem>
 </template>
 
 <i18n>
+en:
+    deleteOrder: Delete order
+    confirmDeletion: Confirm deletion
+    confirmDeletionMessage: Are you sure you want to delete this order?
+
 es:
-    The travel will be deleted: El envío será eliminado
-    Do you want to delete this travel?: ¿Quieres eliminar este envío?
+    To clone zone: Clonar zone
+    deleteOrder: Eliminar pedido
+    confirmDeletion: Confirmar eliminación
+    confirmDeletionMessage: Seguro que quieres eliminar este pedido?
+
 </i18n>

From 167591980108fda44d1d7b1272d21e707b05c05a Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Thu, 2 May 2024 14:33:24 +0200
Subject: [PATCH 5/6] fix: minor build bugs

---
 src/pages/Claim/Card/ClaimBasicData.vue |  4 --
 src/router/modules/zone.js              | 92 +++++++++++++------------
 2 files changed, 47 insertions(+), 49 deletions(-)

diff --git a/src/pages/Claim/Card/ClaimBasicData.vue b/src/pages/Claim/Card/ClaimBasicData.vue
index be2efa31a..e2450a5e5 100644
--- a/src/pages/Claim/Card/ClaimBasicData.vue
+++ b/src/pages/Claim/Card/ClaimBasicData.vue
@@ -41,10 +41,6 @@ const claimStates = ref([]);
 const claimStatesCopy = ref([]);
 const optionsList = ref([]);
 
-function setWorkers(data) {
-    workers.value = data;
-    workersCopy.value = data;
-}
 const workersOptions = ref([]);
 
 function setClaimStates(data) {
diff --git a/src/router/modules/zone.js b/src/router/modules/zone.js
index bd74a76f3..079dfaa84 100644
--- a/src/router/modules/zone.js
+++ b/src/router/modules/zone.js
@@ -11,56 +11,58 @@ export default {
     component: RouterView,
     redirect: { name: 'ZoneMain' },
     menus: {
-        main: ['ZoneList' /*'ZoneDeliveryList', 'ZoneUpcomingList'*/],
+        main: [
+            /*'ZoneList', 'ZoneDeliveryList', 'ZoneUpcomingList'*/
+        ],
         card: [
             //
         ],
     },
     children: [
-        {
-            path: '/zone',
-            name: 'ZoneMain',
-            component: () => import('src/pages/Zone/ZoneMain.vue'),
-            redirect: { name: 'ZoneList' },
-            children: [
-                {
-                    path: 'list',
-                    name: 'ZoneList',
-                    meta: {
-                        title: 'zonesList',
-                        icon: 'vn:zone',
-                    },
-                    component: () => import('src/pages/Zone/ZoneList.vue'),
-                },
-                // {
-                //     path: 'create',
-                //     name: 'ZoneCreate',
-                //     meta: {
-                //         title: 'zoneCreate',
-                //         icon: 'create',
-                //     },
-                //     component: () => import('src/pages/Zone/ZoneCreate.vue'),
-                // },
-                // {
-                //     path: ':id/edit',
-                //     name: 'ZoneEdit',
-                //     meta: {
-                //         title: 'zoneEdit',
-                //         icon: 'edit',
-                //     },
-                //     component: () => import('src/pages/Zone/ZoneCreate.vue'),
-                // },
-                // {
-                //     path: 'counter',
-                //     name: 'ZoneCounter',
-                //     meta: {
-                //         title: 'zoneCounter',
-                //         icon: 'add_circle',
-                //     },
-                //     component: () => import('src/pages/Zone/ZoneCounter.vue'),
-                // },
-            ],
-        },
+        // {
+        // path: '/zone',
+        // name: 'ZoneMain',
+        // component: () => import('src/pages/Zone/ZoneMain.vue'),
+        // redirect: { name: 'ZoneList' },
+        // children: [
+        //     {
+        //         path: 'list',
+        //         name: 'ZoneList',
+        //         meta: {
+        //             title: 'zonesList',
+        //             icon: 'vn:zone',
+        //         },
+        //         component: () => import('src/pages/Zone/ZoneList.vue'),
+        //     },
+        // {
+        //     path: 'create',
+        //     name: 'ZoneCreate',
+        //     meta: {
+        //         title: 'zoneCreate',
+        //         icon: 'create',
+        //     },
+        //     component: () => import('src/pages/Zone/ZoneCreate.vue'),
+        // },
+        // {
+        //     path: ':id/edit',
+        //     name: 'ZoneEdit',
+        //     meta: {
+        //         title: 'zoneEdit',
+        //         icon: 'edit',
+        //     },
+        //     component: () => import('src/pages/Zone/ZoneCreate.vue'),
+        // },
+        // {
+        //     path: 'counter',
+        //     name: 'ZoneCounter',
+        //     meta: {
+        //         title: 'zoneCounter',
+        //         icon: 'add_circle',
+        //     },
+        //     component: () => import('src/pages/Zone/ZoneCounter.vue'),
+        // },
+        // ],
+        // },
         {
             name: 'ZoneCard',
             path: ':id',

From 1a79bd6fb8a30637b49680dcf83b8b45006308db Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Thu, 2 May 2024 14:40:56 +0200
Subject: [PATCH 6/6] feat: zoneSummary

---
 src/pages/Zone/Card/ZoneSummary.vue | 94 +++++++++++++++++++++++++++++
 1 file changed, 94 insertions(+)
 create mode 100644 src/pages/Zone/Card/ZoneSummary.vue

diff --git a/src/pages/Zone/Card/ZoneSummary.vue b/src/pages/Zone/Card/ZoneSummary.vue
new file mode 100644
index 000000000..00df03cb0
--- /dev/null
+++ b/src/pages/Zone/Card/ZoneSummary.vue
@@ -0,0 +1,94 @@
+<script setup>
+import { ref, onMounted, computed } from 'vue';
+import { useRoute } from 'vue-router';
+import { useI18n } from 'vue-i18n';
+import { dashIfEmpty } from 'src/filters';
+import { getUrl } from 'src/composables/getUrl';
+import VnLv from 'src/components/ui/VnLv.vue';
+import VnLinkPhone from 'src/components/ui/VnLinkPhone.vue';
+import CardSummary from 'components/ui/CardSummary.vue';
+import VnUserLink from 'src/components/ui/VnUserLink.vue';
+import VnTitle from 'src/components/common/VnTitle.vue';
+
+const route = useRoute();
+const { t } = useI18n();
+
+const $props = defineProps({
+    id: {
+        type: Number,
+        default: 0,
+    },
+});
+
+const entityId = computed(() => $props.id || route.params.id);
+const zoneUrl = ref();
+
+onMounted(async () => {
+    zoneUrl.value = (await getUrl('')) + `zone/${entityId.value}/`;
+});
+
+const filter = computed(() => {
+    return { where: { id: entityId.value } };
+});
+</script>
+
+<template>
+    <CardSummary
+        data-key="zoneData"
+        ref="summary"
+        :url="`Zones/summary`"
+        :filter="filter"
+    >
+        <template #header="{ entity }">
+            <div>{{ entity.id }} - {{ entity.firstName }} {{ entity.lastName }}</div>
+        </template>
+        <template #body="{ entity: zone }">
+            <QCard class="vn-one">
+                <VnTitle
+                    :url="zoneUrl + `basic-data`"
+                    :text="t('zone.summary.basicData')"
+                />
+                <VnLv :label="t('zone.card.name')" :value="zone.user?.nickname" />
+                <VnLv
+                    :label="t('zone.list.department')"
+                    :value="zone.department?.department?.name"
+                />
+                <VnLv :label="t('zone.list.email')" :value="zone.user.email" copy />
+                <VnLv :label="t('zone.summary.boss')" link>
+                    <template #value>
+                        <VnUserLink
+                            v-if="zone.boss"
+                            :name="dashIfEmpty(zone.boss?.name)"
+                            :zone-id="zone.bossFk"
+                        />
+                    </template>
+                </VnLv>
+                <VnLv :value="zone.mobileExtension">
+                    <template #label>
+                        {{ t('zone.summary.phoneExtension') }}
+                        <VnLinkPhone :phone-number="zone.mobileExtension" />
+                    </template>
+                </VnLv>
+                <VnLv :value="zone.phone">
+                    <template #label>
+                        {{ t('zone.summary.entPhone') }}
+                        <VnLinkPhone :phone-number="zone.phone" />
+                    </template>
+                </VnLv>
+                <VnLv :label="t('zone.summary.locker')" :value="zone.locker" />
+            </QCard>
+            <QCard class="vn-one">
+                <VnTitle :text="t('zone.summary.userData')" />
+                <VnLv :label="t('zone.summary.userId')" :value="zone.user.id" />
+                <VnLv :label="t('zone.card.name')" :value="zone.user.nickname" />
+                <VnLv :label="t('zone.summary.role')" :value="zone.user.role.name" />
+                <VnLv :value="zone?.sip?.extension">
+                    <template #label>
+                        {{ t('zone.summary.sipExtension') }}
+                        <VnLinkPhone :phone-number="zone?.sip?.extension" />
+                    </template>
+                </VnLv>
+            </QCard>
+        </template>
+    </CardSummary>
+</template>