diff --git a/src/App.vue b/src/App.vue
index 69fb8958..8b15cff2 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -1,11 +1,11 @@
+<script setup>
+import { useAppStore } from 'stores/app';
+import { onBeforeMount } from 'vue';
+const appStore = useAppStore();
+
+onBeforeMount(() => appStore.init());
+</script>
+
 <template>
     <router-view />
 </template>
-
-<script>
-import { defineComponent } from 'vue';
-
-export default defineComponent({
-    name: 'App'
-});
-</script>
diff --git a/src/components/common/VnForm.vue b/src/components/common/VnForm.vue
index 71f36fd3..cf2788cf 100644
--- a/src/components/common/VnForm.vue
+++ b/src/components/common/VnForm.vue
@@ -206,7 +206,6 @@ defineExpose({
             ref="addressFormRef"
             class="form"
             :class="separationBetweenInputs"
-            @submit="submit()"
         >
             <span v-if="title" class="text-h6 text-bold">
                 {{ title }}
diff --git a/src/components/ui/TicketDetails.vue b/src/components/ui/TicketDetails.vue
new file mode 100644
index 00000000..37af51ab
--- /dev/null
+++ b/src/components/ui/TicketDetails.vue
@@ -0,0 +1,152 @@
+<script setup>
+import { useI18n } from 'vue-i18n';
+import { currency, formatDateTitle } from 'src/lib/filters.js';
+import VnImg from 'src/components/ui/VnImg.vue';
+
+defineProps({
+    ticket: {
+        type: Object,
+        default: () => ({})
+    },
+    rows: {
+        type: Array,
+        default: () => []
+    }
+});
+
+const { t } = useI18n();
+
+const lineDiscountSubtotal = line => {
+    return line.quantity * line.price;
+};
+
+const lineSubtotal = line =>
+    lineDiscountSubtotal(line) * ((100 - line.discount) / 100);
+</script>
+
+<template>
+    <QCard class="vn-w-sm" style="padding: 32px">
+        <QCardSection class="no-padding q-mb-md">
+            <div class="text-h6">#{{ ticket.id }}</div>
+        </QCardSection>
+        <QCardSection class="no-padding q-mb-md q-gutter-y-xs">
+            <div class="text-subtitle1 text-bold">
+                {{ t('shippingInformation') }}
+            </div>
+            <div>
+                {{ t('preparation') }}
+                {{ formatDateTitle(ticket.shipped) }}
+            </div>
+            <div>
+                {{ t('delivery') }}
+                {{ formatDateTitle(ticket.landed) }}
+            </div>
+            <div>
+                {{ t(ticket.method != 'PICKUP' ? 'agency' : 'warehouse') }}
+                {{ ticket.agency }}
+            </div>
+        </QCardSection>
+        <QCardSection class="no-padding q-mb-md q-gutter-y-xs">
+            <div class="text-subtitle1 text-bold">
+                {{ t('deliveryAddress') }}
+            </div>
+            <div>{{ ticket.nickname }}</div>
+            <div>{{ ticket.street }}</div>
+            <div>
+                {{ ticket.postalCode }} {{ ticket.city }} ({{
+                    ticket.province
+                }})
+            </div>
+        </QCardSection>
+        <QCardSection
+            class="no-padding q-mb-md text-subtitle1 text-bold column"
+        >
+            <span class="text-right">
+                {{ t('total') }} {{ currency(ticket.taxBase) }}
+            </span>
+            <span class="text-right">
+                {{ t('totalTax') }} {{ currency(ticket.total) }}
+            </span>
+        </QCardSection>
+        <QSeparator inset />
+        <QList v-for="row in rows" :key="row.itemFk">
+            <QItem>
+                <QItemSection avatar>
+                    <VnImg
+                        storage="catalog"
+                        size="200x200"
+                        :id="row.image"
+                        rounded
+                    />
+                </QItemSection>
+                <QItemSection>
+                    <QItemLabel lines="1">
+                        {{ row.concept }}
+                    </QItemLabel>
+                    <QItemLabel lines="1" caption>
+                        {{ row.value5 }} {{ row.value6 }} {{ row.value7 }}
+                    </QItemLabel>
+                    <QItemLabel lines="1">
+                        {{ row.quantity }} x {{ currency(row.price) }}
+                    </QItemLabel>
+                </QItemSection>
+                <QItemSection side class="total">
+                    <QItemLabel>
+                        <span class="discount" v-if="row.discount">
+                            {{ currency(lineDiscountSubtotal(row)) }} -
+                            {{ currency(row.discount) }} =
+                        </span>
+                        {{ currency(lineSubtotal(row)) }}
+                    </QItemLabel>
+                </QItemSection>
+            </QItem>
+        </QList>
+    </QCard>
+</template>
+
+<i18n lang="yaml">
+en-US:
+    shippingInformation: Shipping Information
+    preparation: Preparation
+    delivery: Delivery
+    agency: Agency
+    warehouse: Store
+    deliveryAddress: Delivery address
+    total: Total
+    totalTax: Total + IVA
+es-ES:
+    shippingInformation: Datos de envío
+    preparation: Preparación
+    delivery: Entrega
+    agency: Agencia
+    warehouse: Almacén
+    deliveryAddress: Dirección de entrega
+    total: Total
+    totalTax: Total + IVA
+ca-ES:
+    shippingInformation: Dades d'enviament
+    preparation: Preparació
+    delivery: Lliurament
+    agency: Agència
+    warehouse: Magatzem
+    deliveryAddress: Adreça de lliurament
+    total: Total
+    totalTax: Total + IVA
+fr-FR:
+    shippingInformation: Informations sur la livraison
+    preparation: Préparation
+    delivery: Livraison
+    warehouse: Entrepôt
+    deliveryAddress: Adresse de livraison
+    total: Total
+    totalTax: Total + IVA
+pt-PT:
+    shippingInformation: Dados de envio
+    preparation: Preparação
+    delivery: Entrega
+    agency: Agência
+    warehouse: Armazém
+    deliveryAddress: Endereço de entrega
+    total: Total
+    totalTax: Total + IVA
+</i18n>
diff --git a/src/components/ui/VnTable.vue b/src/components/ui/VnTable.vue
new file mode 100644
index 00000000..a32240c5
--- /dev/null
+++ b/src/components/ui/VnTable.vue
@@ -0,0 +1,41 @@
+<script setup>
+import { useI18n } from 'vue-i18n';
+
+const { t } = useI18n();
+
+const props = defineProps({
+    noDataLabel: {
+        type: String,
+        default: ''
+    },
+    hideBottom: {
+        type: Boolean,
+        default: true
+    },
+    rowsPerPageOptions: {
+        type: Array,
+        default: () => [0]
+    }
+});
+</script>
+
+<template>
+    <QTable
+        v-bind="$attrs"
+        :no-data-label="props.noDataLabel || t('noInvoicesFound')"
+        :hide-bottom="props.hideBottom"
+        :rows-per-page-options="props.rowsPerPageOptions"
+        table-header-class="vntable-header-default"
+    >
+        <template v-for="(_, slotName) in $slots" v-slot:[slotName]="slotProps">
+            <slot :name="slotName" v-bind="slotProps" />
+        </template>
+    </QTable>
+</template>
+
+<style lang="scss">
+.vntable-header-default {
+    background-color: $accent !important;
+    color: white;
+}
+</style>
diff --git a/src/composables/usePrintService.js b/src/composables/usePrintService.js
new file mode 100644
index 00000000..e96e26e2
--- /dev/null
+++ b/src/composables/usePrintService.js
@@ -0,0 +1,38 @@
+import { useUserStore } from 'stores/user';
+
+import axios from 'axios';
+import { useQuasar } from 'quasar';
+
+export function usePrintService() {
+    const quasar = useQuasar();
+    const userStore = useUserStore();
+    const token = userStore.token;
+
+    function sendEmail(path, params) {
+        return axios.post(path, params).then(() =>
+            quasar.notify({
+                message: 'Notification sent',
+                type: 'positive',
+                icon: 'check'
+            })
+        );
+    }
+
+    function openReport(path, params) {
+        params = Object.assign(
+            {
+                access_token: token
+            },
+            params
+        );
+
+        const query = new URLSearchParams(params).toString();
+
+        window.open(`api/${path}?${query}`);
+    }
+
+    return {
+        sendEmail,
+        openReport
+    };
+}
diff --git a/src/i18n/en-US/index.js b/src/i18n/en-US/index.js
index 45c4b4d8..27bdec11 100644
--- a/src/i18n/en-US/index.js
+++ b/src/i18n/en-US/index.js
@@ -37,7 +37,7 @@ export default {
             'November',
             'December'
         ],
-        shortMonths: [
+        monthsShort: [
             'Jan',
             'Feb',
             'Mar',
diff --git a/src/i18n/es-ES/index.js b/src/i18n/es-ES/index.js
index 98af2234..a7475965 100644
--- a/src/i18n/es-ES/index.js
+++ b/src/i18n/es-ES/index.js
@@ -43,7 +43,7 @@ export default {
             'Noviembre',
             'Diciembre'
         ],
-        shortMonths: [
+        monthsShort: [
             'Ene',
             'Feb',
             'Mar',
diff --git a/src/i18n/fr-FR/index.js b/src/i18n/fr-FR/index.js
index 1ca353b8..659ae4b2 100644
--- a/src/i18n/fr-FR/index.js
+++ b/src/i18n/fr-FR/index.js
@@ -24,7 +24,7 @@ export default {
             'Novembre',
             'Décembre'
         ],
-        shortMonths: [
+        monthsShort: [
             'Jan',
             'Fév',
             'Mar',
diff --git a/src/i18n/pt-PT/index.js b/src/i18n/pt-PT/index.js
index ef31036b..5b92f163 100644
--- a/src/i18n/pt-PT/index.js
+++ b/src/i18n/pt-PT/index.js
@@ -24,7 +24,7 @@ export default {
             'Novembro',
             'Dezembro'
         ],
-        shortMonths: [
+        monthsShort: [
             'Jan',
             'Fev',
             'Mar',
diff --git a/src/pages/Account/AddressList.vue b/src/pages/Account/AddressList.vue
index 7efc9412..cd8e8857 100644
--- a/src/pages/Account/AddressList.vue
+++ b/src/pages/Account/AddressList.vue
@@ -3,6 +3,8 @@ import { useI18n } from 'vue-i18n';
 import { ref, onMounted, inject } from 'vue';
 import { useRouter } from 'vue-router';
 
+import CardList from 'src/components/ui/CardList.vue';
+
 import useNotify from 'src/composables/useNotify.js';
 import { useVnConfirm } from 'src/composables/useVnConfirm.js';
 import { useAppStore } from 'stores/app';
@@ -97,42 +99,33 @@ onMounted(async () => {
             no-caps
         />
     </Teleport>
-    <QPage class="column items-center">
-        <QList
-            class="full-width rounded-borders shadow-1 shadow-transition"
-            style="max-width: 544px"
-            separator
-        >
-            <QItem
+    <QPage class="vn-w-sm">
+        <QList class="rounded-borders shadow-1 shadow-transition" separator>
+            <CardList
                 v-for="(address, index) in addresses"
                 :key="index"
-                clickable
-                v-ripple
+                :rounded="false"
                 tag="label"
-                class="full-width row items-center justify-between address-item"
-                style="padding: 20px"
             >
-                <QItemSection>
-                    <div class="row">
-                        <QRadio
-                            v-model="defaultAddress"
-                            :val="address.id"
-                            class="q-mr-sm"
-                            @update:model-value="changeDefaultAddress"
-                        />
-                        <div>
-                            <QItemLabel class="text-bold q-mb-sm">
-                                {{ address.nickname }}
-                            </QItemLabel>
-                            <QItemLabel>{{ address.street }}</QItemLabel>
-                            <QItemLabel>
-                                {{ address.postalCode }},
-                                {{ address.city }}
-                            </QItemLabel>
-                        </div>
-                    </div>
-                </QItemSection>
-                <QItemSection class="actions-wrapper" side>
+                <template #prepend>
+                    <QRadio
+                        v-model="defaultAddress"
+                        :val="address.id"
+                        class="q-mr-sm"
+                        @update:model-value="changeDefaultAddress"
+                    />
+                </template>
+                <template #content>
+                    <span class="text-bold q-mb-sm">
+                        {{ address.nickname }}
+                    </span>
+                    <span>{{ address.street }}</span>
+                    <span>
+                        {{ address.postalCode }},
+                        {{ address.city }}
+                    </span>
+                </template>
+                <template #actions>
                     <QBtn
                         icon="delete"
                         flat
@@ -151,25 +144,12 @@ onMounted(async () => {
                         rounded
                         @click.stop="goToAddressDetails(address.id)"
                     />
-                </QItemSection>
-            </QItem>
+                </template>
+            </CardList>
         </QList>
     </QPage>
 </template>
 
-<style lang="scss" scoped>
-.address-item {
-    .actions-wrapper {
-        visibility: hidden;
-    }
-    &:hover {
-        .actions-wrapper {
-            visibility: visible;
-        }
-    }
-}
-</style>
-
 <i18n lang="yaml">
 en-US:
     addAddress: Add address
diff --git a/src/pages/Agencies/PackagesView.vue b/src/pages/Agencies/PackagesView.vue
index d9af6e7f..2ef44424 100644
--- a/src/pages/Agencies/PackagesView.vue
+++ b/src/pages/Agencies/PackagesView.vue
@@ -2,6 +2,8 @@
 import { ref, inject, onMounted, computed } from 'vue';
 import { useI18n } from 'vue-i18n';
 
+import VnTable from 'src/components/ui/VnTable.vue';
+
 const jApi = inject('jApi');
 const { t } = useI18n();
 
@@ -53,32 +55,15 @@ onMounted(() => getPackages());
 
 <template>
     <QPage class="flex justify-center q-pa-md">
-        <QTable
+        <VnTable
             :columns="columns"
             :rows="packages"
             :loading="loading"
-            class="q-mt-lg"
-            style="max-width: 100%; height: max-content"
-            table-header-class="packages-table-header"
-            hide-bottom
-        >
-            <template #body-cell-id="{ row }">
-                <QTd auto-width @click.stop>
-                    <QBtn flat color="blue">{{ row.id }}</QBtn>
-                    <ItemDescriptorProxy :id="row.id" />
-                </QTd>
-            </template>
-        </QTable>
+            style="height: max-content; max-width: 100%"
+        />
     </QPage>
 </template>
 
-<style lang="scss">
-.packages-table-header {
-    background-color: $accent !important;
-    color: white;
-}
-</style>
-
 <i18n lang="yaml">
 en-US:
     agency: Agency
diff --git a/src/pages/Ecomerce/BasketView.vue b/src/pages/Ecomerce/BasketView.vue
new file mode 100644
index 00000000..baac12d6
--- /dev/null
+++ b/src/pages/Ecomerce/BasketView.vue
@@ -0,0 +1 @@
+<template>Basket view</template>
diff --git a/src/pages/Ecomerce/Catalog.vue b/src/pages/Ecomerce/Catalog.vue
index 2a6bca06..6261955e 100644
--- a/src/pages/Ecomerce/Catalog.vue
+++ b/src/pages/Ecomerce/Catalog.vue
@@ -10,7 +10,7 @@
             dense
             standout
         >
-            <template v-slot:prepend>
+            <template #prepend>
                 <QIcon v-if="search === ''" name="search" />
                 <QIcon
                     v-else
@@ -220,7 +220,7 @@
                     </QCardActions>
                 </QCard>
             </div>
-            <template v-slot:loading>
+            <template #loading>
                 <div class="row justify-center q-my-md">
                     <QSpinner color="primary" name="dots" size="40px" />
                 </div>
@@ -343,8 +343,7 @@
 </style>
 
 <script>
-import { date, currency } from 'src/lib/filters.js';
-import { date as qdate } from 'quasar';
+import { date, currency, formatDate } from 'src/lib/filters.js';
 import axios from 'axios';
 import { useAppStore } from 'stores/app';
 import { storeToRefs } from 'pinia';
@@ -362,7 +361,7 @@ export default {
         return {
             uid: 0,
             search: '',
-            orderDate: qdate.formatDate(new Date(), 'YYYY/MM/DD'),
+            orderDate: formatDate(new Date(), 'YYYY/MM/DD'),
             category: null,
             categories: [],
             type: null,
@@ -453,7 +452,7 @@ export default {
             if (!value) return;
 
             const res = await this.$jApi.execQuery(
-                `CALL myBasket_getAvailable;
+                `CALL myOrder_getAvailable(${this.appStore.basketOrderId});
         SELECT DISTINCT t.id, l.name
           FROM vn.item i
             JOIN vn.itemType t ON t.id = i.typeFk
diff --git a/src/pages/Ecomerce/CheckoutView.vue b/src/pages/Ecomerce/CheckoutView.vue
new file mode 100644
index 00000000..5730758d
--- /dev/null
+++ b/src/pages/Ecomerce/CheckoutView.vue
@@ -0,0 +1 @@
+<template>Checkout</template>
diff --git a/src/pages/Ecomerce/Invoices.vue b/src/pages/Ecomerce/Invoices.vue
deleted file mode 100644
index f116c738..00000000
--- a/src/pages/Ecomerce/Invoices.vue
+++ /dev/null
@@ -1,190 +0,0 @@
-<template>
-    <Teleport v-if="isHeaderMounted" to="#actions">
-        <QSelect
-            v-model="year"
-            :options="years"
-            color="white"
-            dark
-            standout
-            dense
-            rounded
-        />
-    </Teleport>
-    <div class="vn-w-sm">
-        <div
-            v-if="!invoices?.length"
-            class="text-subtitle1 text-center text-grey-7 q-pa-md"
-        >
-            {{ $t('noInvoicesFound') }}
-        </div>
-        <QCard v-if="invoices?.length">
-            <QTable
-                :columns="columns"
-                :pagination="pagination"
-                :rows="invoices"
-                row-key="id"
-                hide-header
-                hide-bottom
-            >
-                <template v-slot:body="props">
-                    <QTr :props="props">
-                        <QTd key="ref" :props="props">
-                            {{ props.row.ref }}
-                        </QTd>
-                        <QTd key="issued" :props="props">
-                            {{ date(props.row.issued, 'ddd, MMMM Do') }}
-                        </QTd>
-                        <QTd key="amount" :props="props">
-                            {{ currency(props.row.amount) }}
-                        </QTd>
-                        <QTd key="hasPdf" :props="props">
-                            <QBtn
-                                v-if="props.row.hasPdf"
-                                icon="download"
-                                :title="$t('downloadInvoicePdf')"
-                                :href="invoiceUrl(props.row.id)"
-                                target="_blank"
-                                flat
-                                round
-                            />
-                            <QIcon
-                                v-else
-                                name="warning"
-                                :title="$t('notDownloadable')"
-                                color="warning"
-                                size="24px"
-                            />
-                        </QTd>
-                    </QTr>
-                </template>
-            </QTable>
-        </QCard>
-    </div>
-</template>
-
-<script>
-import { date, currency } from 'src/lib/filters.js';
-import { useAppStore } from 'stores/app';
-import { storeToRefs } from 'pinia';
-
-export default {
-    name: 'OrdersPendingIndex',
-    setup() {
-        const appStore = useAppStore();
-        const { isHeaderMounted } = storeToRefs(appStore);
-        return { isHeaderMounted };
-    },
-    data() {
-        const curYear = new Date().getFullYear();
-        const years = [];
-
-        for (let year = curYear - 5; year <= curYear; year++) {
-            years.push(year);
-        }
-
-        return {
-            columns: [
-                { name: 'ref', label: 'serial', field: 'ref', align: 'left' },
-                {
-                    name: 'issued',
-                    label: 'issued',
-                    field: 'issued',
-                    align: 'left'
-                },
-                { name: 'amount', label: 'amount', field: 'amount' },
-                {
-                    name: 'hasPdf',
-                    label: 'download',
-                    field: 'hasPdf',
-                    align: 'center'
-                }
-            ],
-            pagination: {
-                rowsPerPage: 0
-            },
-            year: curYear,
-            years,
-            invoices: null
-        };
-    },
-
-    async mounted() {
-        await this.fetchUser();
-    },
-
-    watch: {
-        async year() {
-            await this.fetchUser();
-        }
-    },
-
-    methods: {
-        date,
-        currency,
-
-        async fetchUser() {
-            const params = {
-                from: new Date(this.year, 0),
-                to: new Date(this.year, 11, 31, 23, 59, 59)
-            };
-            this._invoices = await this.$jApi.query(
-                `SELECT id, ref, issued, amount, hasPdf
-          FROM myInvoice
-          WHERE issued BETWEEN #from AND #to
-          ORDER BY issued DESC
-          LIMIT 500`,
-                params
-            );
-        },
-
-        invoiceUrl(id) {
-            return (
-                '?' +
-                new URLSearchParams({
-                    srv: 'rest:dms/invoice',
-                    invoice: id,
-                    access_token: this.$user.token
-                }).toString()
-            );
-        }
-    }
-};
-</script>
-
-<i18n lang="yaml">
-en-US:
-    noInvoicesFound: No invoices found
-    serial: Serial
-    issued: Date
-    amount: Import
-    downloadInvoicePdf: Download invoice PDF
-    notDownloadable: Not available for download, request the invoice to your salesperson
-es-ES:
-    noInvoicesFound: No se han encontrado facturas
-    serial: Serie
-    issued: Fecha
-    amount: Importe
-    downloadInvoicePdf: Descargar factura en PDF
-    notDownloadable: No disponible para descarga, solicita la factura a tu comercial
-ca-ES:
-    noInvoicesFound: No s'han trobat factures
-    serial: Sèrie
-    issued: Data
-    amount: Import
-    downloadInvoicePdf: Descarregar PDF
-    notDownloadable: No disponible per cescarrega, sol·licita la factura al teu comercial
-fr-FR:
-    noInvoicesFound: Aucune facture trouvée
-    serial: Série
-    issued: Date
-    amount: Montant
-    downloadInvoicePdf: Télécharger le PDF
-    notDownloadable: Non disponible en téléchargement, demander la facture à votre commercial
-pt-PT:
-    noInvoicesFound: Nenhuma fatura encontrada
-    serial: Serie
-    issued: Data
-    amount: Importe
-    downloadInvoicePdf: Baixar PDF
-    notDownloadable: Não disponível para download, solicite a fatura ao seu comercial
-</i18n>
diff --git a/src/pages/Ecomerce/InvoicesView.vue b/src/pages/Ecomerce/InvoicesView.vue
new file mode 100644
index 00000000..124d8e03
--- /dev/null
+++ b/src/pages/Ecomerce/InvoicesView.vue
@@ -0,0 +1,162 @@
+<script setup>
+import { ref, onMounted, inject, computed } from 'vue';
+import { useI18n } from 'vue-i18n';
+
+import VnTable from 'src/components/ui/VnTable.vue';
+
+import { currency, formatDate } from 'src/lib/filters.js';
+import { usePrintService } from 'src/composables/usePrintService';
+import { useAppStore } from 'stores/app';
+import { storeToRefs } from 'pinia';
+
+const { t } = useI18n();
+const jApi = inject('jApi');
+const { openReport } = usePrintService();
+const appStore = useAppStore();
+const { isHeaderMounted } = storeToRefs(appStore);
+
+const currentYear = ref(Date.vnNew().getFullYear());
+const years = ref([]);
+const invoices = ref([]);
+
+const columns = computed(() => [
+    { name: 'ref', label: t('invoice'), field: 'ref', align: 'left' },
+    {
+        name: 'issued',
+        label: t('issued'),
+        field: 'issued',
+        align: 'left',
+        format: val => formatDate(val, 'D MMM YYYY')
+    },
+    {
+        name: 'amount',
+        label: t('amount'),
+        field: 'amount',
+        format: val => currency(val)
+    },
+    {
+        name: 'hasPdf',
+        field: 'hasPdf',
+        align: 'center'
+    }
+]);
+
+const fetchInvoices = async () => {
+    const params = {
+        from: new Date(currentYear.value, 0),
+        to: new Date(currentYear.value, 11, 31, 23, 59, 59)
+    };
+    invoices.value = await jApi.query(
+        `SELECT id, ref, issued, amount, hasPdf
+          FROM myInvoice
+          WHERE issued BETWEEN #from AND #to
+          ORDER BY issued DESC
+          LIMIT 100`,
+        params
+    );
+};
+
+onMounted(async () => {
+    await fetchInvoices();
+    for (let year = currentYear.value - 5; year <= currentYear.value; year++) {
+        years.value.push(year);
+    }
+});
+</script>
+
+<template>
+    <Teleport v-if="isHeaderMounted" to="#actions">
+        <QSelect
+            v-model="currentYear"
+            :options="years"
+            color="white"
+            dark
+            standout
+            dense
+            rounded
+            @update:model-value="fetchInvoices()"
+        />
+    </Teleport>
+    <div class="vn-w-sm">
+        <VnTable
+            :columns="columns"
+            :rows="invoices"
+            :hide-header="!invoices?.length"
+        >
+            <template #body-cell-hasPdf="{ row }">
+                <QTd
+                    auto-width
+                    @click.stop
+                    class="flex full-width justify-center items-center"
+                >
+                    <QBtn
+                        v-if="row.hasPdf"
+                        icon="download"
+                        target="_blank"
+                        flat
+                        round
+                        @click="openReport(`InvoiceOuts/${row.id}/download`)"
+                    >
+                        <QTooltip>
+                            {{ t('downloadInvoicePdf') }}
+                        </QTooltip>
+                    </QBtn>
+                    <QIcon
+                        v-else
+                        name="warning"
+                        :title="t('notDownloadable')"
+                        color="warning"
+                        size="sm"
+                    >
+                        <QTooltip>
+                            {{ t('requestTheInvoiceToComercial') }}
+                        </QTooltip>
+                    </QIcon>
+                </QTd>
+            </template>
+        </VnTable>
+    </div>
+</template>
+
+<i18n lang="yaml">
+en-US:
+    noInvoicesFound: No invoices found
+    invoice: Invoice
+    issued: Date
+    amount: Import
+    downloadInvoicePdf: Download invoice PDF
+    notDownloadable: Not available for download, request the invoice to your salesperson
+    requestTheInvoiceToComercial: Request the invoice to your salesperson
+es-ES:
+    noInvoicesFound: No se han encontrado facturas
+    invoice: Factura
+    issued: Fecha
+    amount: Importe
+    downloadInvoicePdf: Descargar factura en PDF
+    notDownloadable: No disponible para descarga, solicita la factura a tu comercial
+    requestTheInvoiceToComercial: Solicita la factura a tu comercial
+ca-ES:
+    noInvoicesFound: No s'han trobat factures
+    invoice: Factura
+    issued: Data
+    amount: Import
+    downloadInvoicePdf: Descarregar PDF
+    notDownloadable: No disponible per cescarrega, sol·licita la factura al teu comercial
+    requestTheInvoiceToComercial: Sol·licita la factura al teu comercial
+fr-FR:
+    noInvoicesFound: Aucune facture trouvée
+    invoice: Facture
+    issued: Date
+    amount: Montant
+    downloadInvoicePdf: Télécharger le PDF
+    notDownloadable: Non disponible en téléchargement, demander la facture à votre commercial
+    requestTheInvoiceToComercial: Demander la facture à votre commercial
+pt-PT:
+    noInvoicesFound: Nenhuma fatura encontrada
+    invoice: Fatura
+    issued: Data
+    amount: Importe
+    downloadInvoicePdf: Baixar PDF
+    notDownloadable: Não disponível para download, solicite a fatura ao seu comercial
+    requestTheInvoiceToComercial: Solicite a fatura ao seu comercial
+</i18n>
diff --git a/src/pages/Ecomerce/Orders.vue b/src/pages/Ecomerce/OrdersView.vue
similarity index 54%
rename from src/pages/Ecomerce/Orders.vue
rename to src/pages/Ecomerce/OrdersView.vue
index e9ce1818..d94c2e4c 100644
--- a/src/pages/Ecomerce/Orders.vue
+++ b/src/pages/Ecomerce/OrdersView.vue
@@ -1,70 +1,135 @@
+<script setup>
+import { ref, onMounted, inject } from 'vue';
+import { useRoute } from 'vue-router';
+import { useI18n } from 'vue-i18n';
+
+import CardList from 'src/components/ui/CardList.vue';
+import VnInput from 'src/components/common/VnInput.vue';
+import VnConfirm from 'src/components/ui/VnConfirm.vue';
+
+import { currency, formatDateTitle } from 'src/lib/filters.js';
+import { tpvStore } from 'stores/tpv';
+
+const { t } = useI18n();
+const route = useRoute();
+const jApi = inject('jApi');
+
+const showAmountToPayDialog = ref(null);
+const amountToPay = ref(null);
+const orders = ref(null);
+const debt = ref(0);
+const tpv = tpvStore();
+
+onMounted(async () => {
+    await tpv.check(route);
+
+    orders.value = await jApi.query('CALL myTicket_list(NULL, NULL)');
+    debt.value = await jApi.getValue('SELECT -myClient_getDebt(NULL)');
+});
+
+const onPayClick = async () => {
+    showAmountToPayDialog.value = true;
+
+    if (debt.value <= 0) {
+        amountToPay.value = -debt.value;
+    }
+};
+
+const onConfirmPay = async () => {
+    if (amountToPay.value) {
+        const amount = amountToPay.value.toString().replace('.', ',');
+        amountToPay.value = parseFloat(amount);
+        await tpv.pay(amountToPay.value);
+    }
+};
+</script>
+
 <template>
     <Teleport v-if="isHeaderMounted" to="#actions">
         <div class="balance">
-            <span class="label">{{ $t('balance') }}</span>
+            <span class="label">{{ t('balance') }}</span>
             <span class="amount" :class="{ negative: debt < 0 }">
                 {{ currency(debt || 0) }}
             </span>
-            <QIcon
-                name="info"
-                :title="$t('paymentInfo')"
-                class="info"
-                size="24px"
-            />
+            <QIcon name="info" class="info" size="sm">
+                <QTooltip max-width="450px">
+                    {{ t('paymentInfo') }}
+                </QTooltip>
+            </QIcon>
         </div>
         <QBtn
             icon="payments"
-            :label="$t('makePayment')"
+            :label="t('makePayment')"
             @click="onPayClick()"
             rounded
             no-caps
-        />
+        >
+            <QTooltip>
+                {{ t('makePayment') }}
+            </QTooltip>
+        </QBtn>
         <QBtn
-            to="/ecomerce/basket"
+            :to="{ name: 'basket' }"
             icon="shopping_cart"
-            :label="$t('shoppingCart')"
+            :label="t('shoppingCart')"
             rounded
             no-caps
-        />
+        >
+            <QTooltip>
+                {{ t('shoppingCart') }}
+            </QTooltip>
+        </QBtn>
     </Teleport>
-    <div class="vn-w-sm">
+    <QPage class="vn-w-sm">
         <div
             v-if="!orders?.length"
             class="text-subtitle1 text-center text-grey-7 q-pa-md"
         >
-            {{ $t('noOrdersFound') }}
+            {{ t('noOrdersFound') }}
         </div>
-        <QCard v-if="orders?.length">
-            <QList bordered separator padding>
-                <QItem
-                    v-for="order in orders"
-                    :key="order.id"
-                    :to="`ticket/${order.id}`"
-                    clickable
-                    v-ripple
-                >
-                    <QItemSection>
-                        <QItemLabel>
-                            {{ date(order.landed, 'ddd, MMMM Do') }}
-                        </QItemLabel>
-                        <QItemLabel caption>#{{ order.id }}</QItemLabel>
-                        <QItemLabel caption>{{ order.nickname }}</QItemLabel>
-                        <QItemLabel caption>{{ order.agency }}</QItemLabel>
-                    </QItemSection>
-                    <QItemSection side top> {{ order.total }}€ </QItemSection>
-                </QItem>
-            </QList>
-        </QCard>
+        <QList v-if="orders?.length">
+            <CardList
+                v-for="order in orders"
+                :key="order.id"
+                :to="`ticket/${order.id}`"
+                tag="label"
+            >
+                <template #content>
+                    <QItemLabel
+                        class="full-width text-bold q-mb-sm flex row justify-between"
+                    >
+                        <span>{{ formatDateTitle(order.landed) }}</span>
+                        <span>{{ currency(order.total) }}</span>
+                    </QItemLabel>
+                    <QItemLabel>#{{ order.id }}</QItemLabel>
+                    <QItemLabel>{{ order.nickname }}</QItemLabel>
+                    <QItemLabel>{{ order.agency }}</QItemLabel>
+                </template>
+            </CardList>
+        </QList>
         <QPageSticky>
             <QBtn
                 fab
                 icon="add_shopping_cart"
                 color="accent"
-                to="/ecomerce/catalog"
-                :title="$t('startOrder')"
+                :to="{ name: 'catalog' }"
+                :title="t('startOrder')"
             />
         </QPageSticky>
-    </div>
+        <VnConfirm
+            v-model="showAmountToPayDialog"
+            :message="t('amountToPay')"
+            :promise="onConfirmPay"
+        >
+            <template #customHTML>
+                <VnInput
+                    v-model="amountToPay"
+                    :clearable="false"
+                    class="full-width"
+                />
+            </template>
+        </VnConfirm>
+    </QPage>
 </template>
 
 <style lang="scss" scoped>
@@ -92,57 +157,6 @@
 }
 </style>
 
-<script>
-import { date, currency } from 'src/lib/filters.js';
-import { tpvStore } from 'stores/tpv';
-import { useAppStore } from 'stores/app';
-import { storeToRefs } from 'pinia';
-
-export default {
-    name: 'OrdersPendingIndex',
-    setup() {
-        const appStore = useAppStore();
-        const { isHeaderMounted } = storeToRefs(appStore);
-        return { isHeaderMounted };
-    },
-    data() {
-        return {
-            orders: null,
-            debt: 0,
-            tpv: tpvStore()
-        };
-    },
-
-    async mounted() {
-        await this.tpv.check(this.$route);
-
-        this.orders = await this.$jApi.query('CALL myTicket_list(NULL, NULL)');
-        this.debt = await this.$jApi.getValue('SELECT -myClient_getDebt(NULL)');
-    },
-
-    methods: {
-        date,
-        currency,
-
-        async onPayClick() {
-            let amount = -this.debt;
-            amount = amount <= 0 ? null : amount;
-
-            let defaultAmountStr = '';
-            if (amount !== null) {
-                defaultAmountStr = amount;
-            }
-            amount = prompt(this.$t('amountToPay'), defaultAmountStr);
-
-            if (amount != null) {
-                amount = parseFloat(amount.replace(',', '.'));
-                await this.tpv.pay(amount);
-            }
-        }
-    }
-};
-</script>
-
 <i18n lang="yaml">
 en-US:
     startOrder: Start order
@@ -155,6 +169,7 @@ en-US:
         disregards future orders. For get your order shipped, this amount must be
         equal to or greater than 0. If you want to make a down payment, click the
         payment button, delete the suggested amount and enter the amount you want.
+    amountToPay: 'Amount to pay (€):'
 es-ES:
     startOrder: Empezar pedido
     noOrdersFound: No se encontrado pedidos
@@ -167,6 +182,7 @@ es-ES:
         esta cantidad debe ser igual o mayor que 0. Si quieres realizar una entrega a
         cuenta, pulsa el botón de pago, borra la cantidad sugerida e introduce la
         cantidad que desees.
+    amountToPay: 'Cantidad a pagar (€):'
 ca-ES:
     startOrder: Començar encàrrec
     noOrdersFound: No s'han trobat comandes
@@ -179,6 +195,7 @@ ca-ES:
         enviat, aquesta quantitat ha de ser igual o més gran que 0. Si vols fer un
         lliurament a compte, prem el botó de pagament, esborra la quantitat suggerida
         e introdueix la quantitat que vulguis.
+    amountToPay: 'Quantitat a pagar (€):'
 fr-FR:
     startOrder: Acheter
     noOrdersFound: Aucune commande trouvée
@@ -191,6 +208,7 @@ fr-FR:
         commande est expédiée, ce montant doit être égal ou supérieur à 0. Si vous
         voulez faire un versement, le montant suggéré effacé et entrez le montant que
         vous souhaitez.
+    amountToPay: 'Montant à payer (€):'
 pt-PT:
     startOrder: Iniciar encomenda
     noOrdersFound: Nenhum pedido encontrado
@@ -203,4 +221,5 @@ pt-PT:
         quantidade deve ser igual ou superior a 0. Se queres realizar um depósito à
         conta, clique no botão de pagamento, apague a quantidade sugerida e introduza
         a quantidade que deseje.
+    amountToPay: 'Valor a pagar (€):'
 </i18n>
diff --git a/src/pages/Ecomerce/PendingOrders.vue b/src/pages/Ecomerce/PendingOrders.vue
new file mode 100644
index 00000000..20737abb
--- /dev/null
+++ b/src/pages/Ecomerce/PendingOrders.vue
@@ -0,0 +1,137 @@
+<script setup>
+import { ref, inject, onMounted } from 'vue';
+import { useI18n } from 'vue-i18n';
+import { useRouter } from 'vue-router';
+
+import CardList from 'src/components/ui/CardList.vue';
+import { currency, formatDateTitle } from 'src/lib/filters.js';
+import { useVnConfirm } from 'src/composables/useVnConfirm.js';
+import useNotify from 'src/composables/useNotify.js';
+import { useAppStore } from 'stores/app';
+import { storeToRefs } from 'pinia';
+
+const jApi = inject('jApi');
+const { t } = useI18n();
+const { openConfirmationModal } = useVnConfirm();
+const { notify } = useNotify();
+const appStore = useAppStore();
+const { isHeaderMounted } = storeToRefs(appStore);
+const router = useRouter();
+
+const orders = ref([]);
+
+const getOrders = async () => {
+    try {
+        orders.value = await jApi.query(
+            `SELECT o.id, o.sent, o.deliveryMethodFk, o.taxableBase,
+        a.nickname, am.description agency
+        FROM myOrder o
+        JOIN myAddress a ON a.id = o.addressFk
+        JOIN vn.agencyMode am ON am.id = o.agencyModeFk
+        WHERE NOT o.isConfirmed
+        ORDER BY o.sent DESC`
+        );
+    } catch (error) {
+        console.error('Error getting orders:', error);
+    }
+};
+
+const removeOrder = async (id, index) => {
+    try {
+        await jApi.execQuery(
+            `START TRANSACTION;
+            DELETE FROM hedera.myOrder WHERE ((id = #id));
+            COMMIT`,
+            {
+                id
+            }
+        );
+        orders.value.splice(index, 1);
+        notify(t('dataSaved'), 'positive');
+    } catch (error) {
+        console.error('Error removing order:', error);
+    }
+};
+
+const loadOrder = orderId => {
+    // store.loadIntoBasket(orderId);
+    router.push({ name: 'catalog' });
+};
+
+onMounted(async () => {
+    getOrders();
+});
+</script>
+
+<template>
+    <Teleport v-if="isHeaderMounted" to="#actions">
+        <QBtn
+            :to="{ name: 'checkout' }"
+            icon="add_shopping_cart"
+            :label="t('newOrder')"
+            rounded
+            no-caps
+        >
+            <QTooltip>
+                {{ t('newOrder') }}
+            </QTooltip>
+        </QBtn>
+    </Teleport>
+    <QPage class="vn-w-sm">
+        <CardList
+            v-for="(order, index) in orders"
+            :key="index"
+            :to="{ name: 'basket', params: { id: order.id } }"
+        >
+            <template #content>
+                <QItemLabel class="text-bold q-mb-sm">{{
+                    formatDateTitle(order.sent)
+                }}</QItemLabel>
+                <QItemLabel> #{{ order.id }} </QItemLabel>
+                <QItemLabel>{{ order.nickname }}</QItemLabel>
+                <QItemLabel>{{ order.agency }}</QItemLabel>
+                <QItemLabel>{{ currency(order.taxableBase) }}</QItemLabel>
+            </template>
+            <template #actions>
+                <QBtn
+                    icon="delete"
+                    flat
+                    rounded
+                    @click.stop.prevent="
+                        openConfirmationModal(
+                            null,
+                            t('areYouSureDeleteOrder'),
+                            () => removeOrder(order.id, index)
+                        )
+                    "
+                />
+                <QBtn
+                    icon="shopping_bag"
+                    flat
+                    rounded
+                    @click.stop.prevent="loadOrder(order.id)"
+                />
+            </template>
+        </CardList>
+    </QPage>
+</template>
+
+<style lang="scss" scoped></style>
+
+<i18n lang="yaml">
+en-US:
+    newOrder: New order
+    areYouSureDeleteOrder: Are you sure you want to delete the order?
+es-ES:
+    newOrder: Nuevo pedido
+    areYouSureDeleteOrder: ¿Seguro que quieres borrar el pedido?
+ca-ES:
+    newOrder: Nova comanda
+    areYouSureDeleteOrder: Segur que vols esborrar la comanda?
+fr-FR:
+    newOrder: Nouvelle commande
+    areYouSureDeleteOrder: Êtes-vous sûr de vouloir supprimer la commande?
+pt-PT:
+    newOrder: Novo pedido
+    areYouSureDeleteOrder: Tem certeza de que deseja excluir o pedido?
+</i18n>
diff --git a/src/pages/Ecomerce/Ticket.vue b/src/pages/Ecomerce/Ticket.vue
deleted file mode 100644
index 3d5386e7..00000000
--- a/src/pages/Ecomerce/Ticket.vue
+++ /dev/null
@@ -1,151 +0,0 @@
-<template>
-    <Teleport v-if="isHeaderMounted" to="#actions">
-        <QBtn
-            icon="print"
-            :label="$t('printDeliveryNote')"
-            @click="onPrintClick()"
-            rounded
-            no-caps
-        />
-    </Teleport>
-    <div>
-        <QCard class="vn-w-sm">
-            <QCardSection>
-                <div class="text-h6">#{{ ticket.id }}</div>
-            </QCardSection>
-            <QCardSection>
-                <div class="text-h6">{{ $t('shippingInformation') }}</div>
-                <div>
-                    {{ $t('preparation') }}
-                    {{ date(ticket.shipped, 'ddd, MMMM Do') }}
-                </div>
-                <div>
-                    {{ $t('delivery') }}
-                    {{ date(ticket.shipped, 'ddd, MMMM Do') }}
-                </div>
-                <div>
-                    {{ $t(ticket.method != 'PICKUP' ? 'agency' : 'warehouse') }}
-                    {{ ticket.agency }}
-                </div>
-            </QCardSection>
-            <QCardSection>
-                <div class="text-h6">{{ $t('deliveryAddress') }}</div>
-                <div>{{ ticket.nickname }}</div>
-                <div>{{ ticket.street }}</div>
-                <div>
-                    {{ ticket.postalCode }} {{ ticket.city }} ({{
-                        ticket.province
-                    }})
-                </div>
-            </QCardSection>
-            <QSeparator inset />
-            <QList v-for="row in rows" :key="row.itemFk">
-                <QItem>
-                    <QItemSection avatar>
-                        <QAvatar size="68px">
-                            <img
-                                :src="`${$app.imageUrl}/catalog/200x200/${row.image}`"
-                            />
-                        </QAvatar>
-                    </QItemSection>
-                    <QItemSection>
-                        <QItemLabel lines="1">
-                            {{ row.concept }}
-                        </QItemLabel>
-                        <QItemLabel lines="1" caption>
-                            {{ row.value5 }} {{ row.value6 }} {{ row.value7 }}
-                        </QItemLabel>
-                        <QItemLabel lines="1">
-                            {{ row.quantity }} x {{ currency(row.price) }}
-                        </QItemLabel>
-                    </QItemSection>
-                    <QItemSection side class="total">
-                        <QItemLabel>
-                            <span class="discount" v-if="row.discount">
-                                {{ currency(discountSubtotal(row)) }} -
-                                {{ currency(row.discount) }} =
-                            </span>
-                            {{ currency(subtotal(row)) }}
-                        </QItemLabel>
-                    </QItemSection>
-                </QItem>
-            </QList>
-        </QCard>
-    </div>
-</template>
-
-<style lang="scss" scoped>
-.total {
-    justify-content: flex-end;
-}
-</style>
-
-<script>
-import { date, currency } from 'src/lib/filters.js';
-import { useAppStore } from 'stores/app';
-import { storeToRefs } from 'pinia';
-
-export default {
-    name: 'OrdersConfirmedView',
-    setup() {
-        const appStore = useAppStore();
-        const { isHeaderMounted } = storeToRefs(appStore);
-        return { isHeaderMounted };
-    },
-    data() {
-        return {
-            ticket: {},
-            rows: null,
-            services: null,
-            packages: null
-        };
-    },
-
-    async mounted() {
-        const params = {
-            ticket: parseInt(this.$route.params.id)
-        };
-        this.ticket = await this.$jApi.getObject(
-            'CALL myTicket_get(#ticket)',
-            params
-        );
-        this.rows = await this.$jApi.query(
-            'CALL myTicket_getRows(#ticket)',
-            params
-        );
-        this.services = await this.$jApi.query(
-            'CALL myTicket_getServices(#ticket)',
-            params
-        );
-        this.packages = await this.$jApi.query(
-            'CALL myTicket_getPackages(#ticket)',
-            params
-        );
-    },
-
-    methods: {
-        date,
-        currency,
-
-        discountSubtotal(line) {
-            return line.quantity * line.price;
-        },
-
-        subtotal(line) {
-            const discount = line.discount;
-            return this.discountSubtotal(line) * ((100 - discount) / 100);
-        },
-
-        onPrintClick() {
-            const params = new URLSearchParams({
-                access_token: this.$user.token,
-                recipientId: this.$user.id,
-                type: 'deliveryNote'
-            });
-            window.open(
-                `/api/Tickets/${this.ticket.id}/delivery-note-pdf?${params.toString()}`
-            );
-        }
-    }
-};
-</script>
diff --git a/src/pages/Ecomerce/TicketView.vue b/src/pages/Ecomerce/TicketView.vue
new file mode 100644
index 00000000..71799f6e
--- /dev/null
+++ b/src/pages/Ecomerce/TicketView.vue
@@ -0,0 +1,78 @@
+<script setup>
+import { onMounted, inject, ref } from 'vue';
+import { useRoute } from 'vue-router';
+import { useI18n } from 'vue-i18n';
+
+import TicketDetails from 'src/components/ui/TicketDetails.vue';
+
+import { useUserStore } from 'stores/user';
+import { useAppStore } from 'stores/app';
+import { storeToRefs } from 'pinia';
+
+const { t } = useI18n();
+const jApi = inject('jApi');
+const route = useRoute();
+const userStore = useUserStore();
+const appStore = useAppStore();
+const { isHeaderMounted } = storeToRefs(appStore);
+
+const ticket = ref({});
+const rows = ref([]);
+const services = ref(null);
+const packages = ref(null);
+
+onMounted(async () => {
+    const params = {
+        ticket: parseInt(route.params.id)
+    };
+    ticket.value = await jApi.getObject('CALL myTicket_get(#ticket)', params);
+    rows.value = await jApi.query('CALL myTicket_getRows(#ticket)', params);
+    services.value = await jApi.query(
+        'CALL myTicket_getServices(#ticket)',
+        params
+    );
+    packages.value = await jApi.query(
+        'CALL myTicket_getPackages(#ticket)',
+        params
+    );
+});
+
+const onPrintClick = () => {
+    const params = new URLSearchParams({
+        access_token: userStore.token,
+        recipientId: userStore.id,
+        type: 'deliveryNote'
+    });
+    window.open(
+        `/api/Tickets/${ticket.value.id}/delivery-note-pdf?${params.toString()}`
+    );
+};
+</script>
+
+<template>
+    <Teleport v-if="isHeaderMounted" to="#actions">
+        <QBtn
+            icon="print"
+            :label="t('printDeliveryNote')"
+            @click="onPrintClick()"
+            rounded
+            no-caps
+        />
+    </Teleport>
+    <QPage>
+        <TicketDetails :rows="rows" :ticket="ticket" />
+    </QPage>
+</template>
+
+<i18n lang="yaml">
+en-US:
+    printDeliveryNote: Print delivery note
+es-ES:
+    printDeliveryNote: Imprimir albarán
+ca-ES:
+    printDeliveryNote: Imprimir albarà
+fr-FR:
+    printDeliveryNote: Imprimer bulletin de livraison
+pt-PT:
+    printDeliveryNote: Imprimir nota de entrega
+</i18n>
diff --git a/src/router/routes.js b/src/router/routes.js
index accf1700..21c2434c 100644
--- a/src/router/routes.js
+++ b/src/router/routes.js
@@ -37,13 +37,38 @@ const routes = [
             {
                 name: 'confirmedOrders',
                 path: '/ecomerce/orders',
-                component: () => import('src/pages/Ecomerce/Orders.vue')
+                component: () => import('pages/Ecomerce/OrdersView.vue')
+            },
+            {
+                name: 'ticket',
+                path: '/ecomerce/ticket/:id',
+                component: () => import('pages/Ecomerce/TicketView.vue')
+            },
+            {
+                name: 'invoices',
+                path: '/ecomerce/invoices',
+                component: () => import('pages/Ecomerce/InvoicesView.vue')
+            },
+            {
+                name: 'pendingOrders',
+                path: '/ecomerce/pending',
+                component: () => import('pages/Ecomerce/PendingOrders.vue')
             },
             {
                 name: 'catalog',
                 path: '/ecomerce/catalog/:category?/:type?',
                 component: () => import('pages/Ecomerce/Catalog.vue')
             },
+            {
+                name: 'basket',
+                path: '/ecomerce/basket/:id?',
+                component: () => import('pages/Ecomerce/BasketView.vue')
+            },
+            {
+                name: 'checkout',
+                path: '/ecomerce/checkout',
+                component: () => import('pages/Ecomerce/CheckoutView.vue')
+            },
             {
                 name: 'agencyPackages',
                 path: '/agencies/packages',
diff --git a/src/stores/app.js b/src/stores/app.js
index 53be4e73..bda79ab3 100644
--- a/src/stores/app.js
+++ b/src/stores/app.js
@@ -1,5 +1,8 @@
 import { defineStore } from 'pinia';
 import { jApi } from 'boot/axios';
+import useNotify from 'src/composables/useNotify.js';
+
+const { notify } = useNotify();
 
 export const useAppStore = defineStore('hedera', {
     state: () => ({
@@ -9,7 +12,8 @@ export const useAppStore = defineStore('hedera', {
         useRightDrawer: false,
         rightDrawerOpen: false,
         isHeaderMounted: false,
-        menuEssentialLinks: []
+        menuEssentialLinks: [],
+        basketOrderId: null
     }),
 
     actions: {
@@ -38,9 +42,40 @@ export const useAppStore = defineStore('hedera', {
 
             this.menuEssentialLinks = sectionTree;
         },
+
         async loadConfig() {
             const imageUrl = await jApi.getValue('SELECT url FROM imageConfig');
             this.$patch({ imageUrl });
+        },
+
+        async init() {
+            this.getBasketOrderId();
+        },
+
+        getBasketOrderId() {
+            this.basketOrderId = localStorage.getItem('hederaBasket');
+        },
+
+        async checkOrder(orderId) {
+            try {
+                const resultSet = await jApi.execQuery(
+                    'CALL myOrder_checkConfig(#id)',
+                    { id: orderId }
+                );
+                resultSet.fetchValue();
+            } catch (err) {
+                console.error('Error checking order', err);
+            }
+        },
+
+        loadIntoBasket(orderId) {
+            console.log('loadIntoBasket', orderId);
+            console.log('this.basketOrderId', this.basketOrderId);
+            if (this.basketOrderId !== orderId) {
+                localStorage.setItem('hederaBasket', orderId);
+                this.basketOrderId = orderId;
+                notify('orderLoadedIntoBasket', 'positive');
+            }
         }
     }
 });