fixes #4801 Summary del módulo tickets #31
|
@ -0,0 +1,54 @@
|
|||
<script setup>
|
||||
defineProps({
|
||||
maxLength: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
item: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<div class="fetchedTags">
|
||||
<div class="wrap">
|
||||
<div class="inline-tag" :class="{ empty: !$props.item.value5 }">{{ $props.item.value5 }}</div>
|
||||
<div class="inline-tag" :class="{ empty: !$props.item.value6 }">{{ $props.item.value6 }}</div>
|
||||
<div class="inline-tag" :class="{ empty: !$props.item.value7 }">{{ $props.item.value7 }}</div>
|
||||
<div class="inline-tag" :class="{ empty: !$props.item.value8 }">{{ $props.item.value8 }}</div>
|
||||
<div class="inline-tag" :class="{ empty: !$props.item.value9 }">{{ $props.item.value9 }}</div>
|
||||
<div class="inline-tag" :class="{ empty: !$props.item.value10 }">{{ $props.item.value10 }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.fetchedTags {
|
||||
align-items: center;
|
||||
.wrap {
|
||||
width: 100%;
|
||||
flex-wrap: wrap;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.inline-tag {
|
||||
height: 1rem;
|
||||
margin: 0.05rem;
|
||||
color: $secondary;
|
||||
text-align: center;
|
||||
font-size: smaller;
|
||||
padding: 1px;
|
||||
flex: 1;
|
||||
border: 1px solid $color-spacer;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
min-width: 4rem;
|
||||
max-width: 4rem;
|
||||
}
|
||||
|
||||
.empty {
|
||||
border: 1px solid $color-spacer-light;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -22,3 +22,9 @@ $positive: #21ba45;
|
|||
$negative: #c10015;
|
||||
$info: #31ccec;
|
||||
$warning: #f2c037;
|
||||
|
||||
$color-spacer-light: rgba(255, 255, 255, .12);
|
||||
$color-spacer:rgba(255, 255, 255, .3);
|
||||
$border-thin-light: 1px solid $color-spacer-light;
|
||||
|
||||
$spacing-md: 16px;
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
export default function (value) {
|
||||
if (value == null || value === '') return '-';
|
||||
return value;
|
||||
}
|
|
@ -2,10 +2,12 @@ import toLowerCase from './toLowerCase';
|
|||
import toDate from './toDate';
|
||||
import toCurrency from './toCurrency';
|
||||
import toPercentage from './toPercentage';
|
||||
import dashIfEmpty from './dashIfEmpty';
|
||||
|
||||
export {
|
||||
toLowerCase,
|
||||
toDate,
|
||||
toCurrency,
|
||||
toPercentage,
|
||||
dashIfEmpty,
|
||||
};
|
||||
|
|
|
@ -187,6 +187,49 @@ export default {
|
|||
selectVideo: 'Select video:',
|
||||
notFound: 'No videos available',
|
||||
},
|
||||
summary: {
|
||||
state: 'State',
|
||||
salesPerson: 'Sales person',
|
||||
agency: 'Agency',
|
||||
zone: 'Zone',
|
||||
warehouse: 'Warehouse',
|
||||
route: 'Route',
|
||||
invoice: 'Invoice',
|
||||
shipped: 'Shipped',
|
||||
landed: 'Landed',
|
||||
packages: 'Packages',
|
||||
consigneePhone: 'Consignee phone',
|
||||
consigneeMobile: 'Consignee mobile',
|
||||
clientPhone: 'Client phone',
|
||||
clientMobile: 'Client mobile',
|
||||
consignee: 'Consignee',
|
||||
subtotal: 'Subtotal',
|
||||
vat: 'VAT',
|
||||
total: 'Total',
|
||||
saleLines: 'Line items',
|
||||
item: 'Item',
|
||||
visible: 'Visible',
|
||||
available: 'Available',
|
||||
quantity: 'Quantity',
|
||||
description: 'Description',
|
||||
price: 'Price',
|
||||
discount: 'Discount',
|
||||
amount: 'Amount',
|
||||
packing: 'Packing',
|
||||
hasComponentLack: 'Component lack',
|
||||
itemShortage: 'Not visible',
|
||||
claim: 'Claim',
|
||||
reserved: 'Reserved',
|
||||
created: 'Created',
|
||||
package: 'Package',
|
||||
taxClass: 'Tax class',
|
||||
services: 'Services',
|
||||
changeState: 'Change state',
|
||||
requester: 'Requester',
|
||||
atender: 'Atender',
|
||||
request: 'Request',
|
||||
goTo: 'Go to'
|
||||
}
|
||||
},
|
||||
claim: {
|
||||
pageTitles: {
|
||||
|
|
|
@ -186,6 +186,49 @@ export default {
|
|||
selectVideo: 'Seleccionar vídeo:',
|
||||
notFound: 'No hay vídeos disponibles',
|
||||
},
|
||||
summary: {
|
||||
state: 'Estado',
|
||||
salesPerson: 'Comercial',
|
||||
agency: 'Agencia',
|
||||
zone: 'Zona',
|
||||
warehouse: 'Almacén',
|
||||
route: 'Ruta',
|
||||
invoice: 'Factura',
|
||||
shipped: 'Enviado',
|
||||
landed: 'Entregado',
|
||||
packages: 'Bultos',
|
||||
consigneePhone: 'Tel. consignatario',
|
||||
consigneeMobile: 'Móv. consignatario',
|
||||
clientPhone: 'Tel. cliente',
|
||||
clientMobile: 'Móv. cliente',
|
||||
consignee: 'Consignatario',
|
||||
subtotal: 'Subtotal',
|
||||
vat: 'IVA',
|
||||
total: 'Total',
|
||||
saleLines: 'Líneas del pedido',
|
||||
item: 'Artículo',
|
||||
visible: 'Visible',
|
||||
available: 'Disponible',
|
||||
quantity: 'Cantidad',
|
||||
description: 'Descripción',
|
||||
price: 'Precio',
|
||||
discount: 'Descuento',
|
||||
amount: 'Importe',
|
||||
packing: 'Encajado',
|
||||
hasComponentLack: 'Faltan componentes',
|
||||
itemShortage: 'No visible',
|
||||
claim: 'Reclamación',
|
||||
reserved: 'Reservado',
|
||||
created: 'Fecha creación',
|
||||
package: 'Embalaje',
|
||||
taxClass: 'Tipo IVA',
|
||||
services: 'Servicios',
|
||||
changeState: 'Cambiar estado',
|
||||
requester: 'Solicitante',
|
||||
atender: 'Comprador',
|
||||
request: 'Petición de compra',
|
||||
goTo: 'Ir a'
|
||||
}
|
||||
},
|
||||
claim: {
|
||||
pageTitles: {
|
||||
|
|
|
@ -19,3 +19,11 @@ const { dialogRef, onDialogHide } = useDialogPluginComponent();
|
|||
<claim-summary v-if="$props.id" :id="$props.id" />
|
||||
</q-dialog>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.q-dialog .summary .header {
|
||||
position: sticky;
|
||||
z-index: $z-max;
|
||||
top: 0;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -19,3 +19,11 @@ const { dialogRef, onDialogHide } = useDialogPluginComponent();
|
|||
<customer-summary v-if="$props.id" :id="$props.id" />
|
||||
</q-dialog>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.q-dialog .summary .header {
|
||||
position: sticky;
|
||||
z-index: $z-max;
|
||||
top: 0;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -0,0 +1,553 @@
|
|||
<script setup>
|
||||
alexandre marked this conversation as resolved
|
||||
import { onMounted, ref, computed, onUpdated } from 'vue';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import axios from 'axios';
|
||||
import { dashIfEmpty, toDate, toCurrency } from 'src/filters';
|
||||
import SkeletonSummary from 'components/ui/SkeletonSummary.vue';
|
||||
import FetchData from 'components/FetchData.vue';
|
||||
import FetchedTags from 'components/ui/FetchedTags.vue';
|
||||
|
||||
onMounted(() => fetch());
|
||||
onUpdated(() => fetch());
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const $props = defineProps({
|
||||
id: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
|
||||
const entityId = computed(() => $props.id || route.params.id);
|
||||
|
||||
const ticket = ref();
|
||||
const salesLines = ref(null);
|
||||
const editableStates = ref([]);
|
||||
async function fetch() {
|
||||
const { data } = await axios.get(`Tickets/${entityId.value}/summary`);
|
||||
if (data) {
|
||||
ticket.value = data;
|
||||
salesLines.value = data.sales;
|
||||
alexandre marked this conversation as resolved
joan
commented
Quitar Console.log() Quitar Console.log()
|
||||
}
|
||||
}
|
||||
|
||||
function stateColor(state) {
|
||||
if (state.code === 'OK') return 'text-green';
|
||||
if (state.code === 'FREE') return 'text-blue-3';
|
||||
if (state.alertLevel === 1) return 'text-primary';
|
||||
if (state.alertLevel === 0) return 'text-red';
|
||||
}
|
||||
|
||||
function formattedAddress() {
|
||||
if (!ticket.value) return '';
|
||||
|
||||
const address = this.ticket.address;
|
||||
const postcode = address.postalCode;
|
||||
const province = address.province ? `(${address.province.name})` : '';
|
||||
|
||||
return `${address.street} - ${postcode} - ${address.city} ${province}`;
|
||||
}
|
||||
|
||||
function isEditable() {
|
||||
try {
|
||||
return !this.ticket.ticketState.state.alertLevel;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
async function changeState(value) {
|
||||
if (!this.ticket.id) return;
|
||||
|
||||
const formData = {
|
||||
ticketFk: this.ticket.id,
|
||||
code: value,
|
||||
};
|
||||
|
||||
await axios.post(`TicketTrackings/changeState`, formData);
|
||||
await router.go(route.fullPath);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<fetch-data url="States/editableStates" @on-fetch="(data) => (editableStates = data)" auto-load />
|
||||
<div class="summary container">
|
||||
<q-card>
|
||||
<skeleton-summary v-if="!ticket" />
|
||||
<template v-if="ticket">
|
||||
<div class="header bg-primary q-pa-sm q-mb-md">
|
||||
<span>
|
||||
Ticket #{{ ticket.id }} - {{ ticket.client.name }} ({{ ticket.client.id }}) -
|
||||
{{ ticket.nickname }}
|
||||
</span>
|
||||
<q-btn-dropdown
|
||||
side
|
||||
alexandre marked this conversation as resolved
joan
commented
En vez de ponerlo de color negro, quizás probaría con otro color de la gama "orange", de la paleta de colores, quizás un color más claro y apagado que el encabezado: En vez de ponerlo de color negro, quizás probaría con otro color de la gama "orange", de la paleta de colores, quizás un color más claro y apagado que el encabezado:
https://quasar.dev/style/color-palette
|
||||
top
|
||||
color="orange-11"
|
||||
text-color="black"
|
||||
:label="t('ticket.summary.changeState')"
|
||||
:disable="!isEditable()"
|
||||
>
|
||||
<q-list>
|
||||
<q-virtual-scroll
|
||||
style="max-height: 300px"
|
||||
:items="editableStates"
|
||||
separator
|
||||
v-slot="{ item, index }"
|
||||
>
|
||||
<q-item :key="index" dense clickable v-close-popup @click="changeState(item.code)">
|
||||
<q-item-section>
|
||||
<q-item-label>{{ item.name }}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-virtual-scroll>
|
||||
</q-list>
|
||||
</q-btn-dropdown>
|
||||
</div>
|
||||
<div class="row q-pa-md q-col-gutter-md q-mb-md">
|
||||
<div class="col">
|
||||
<q-list>
|
||||
<q-item>
|
||||
<q-item-section>
|
||||
<q-item-label caption>{{ t('ticket.summary.state') }}</q-item-label>
|
||||
<q-item-label :class="stateColor(ticket.ticketState.state)">
|
||||
{{ ticket.ticketState.state.name }}
|
||||
</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item>
|
||||
<q-item-section>
|
||||
<q-item-label caption>{{ t('ticket.summary.salesPerson') }}</q-item-label>
|
||||
<q-item-label class="link">{{ ticket.client.salesPersonUser.name }}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item>
|
||||
<q-item-section>
|
||||
<q-item-label caption>{{ t('ticket.summary.agency') }}</q-item-label>
|
||||
<q-item-label>{{ ticket.agencyMode.name }}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item>
|
||||
<q-item-section>
|
||||
<q-item-label caption>{{ t('ticket.summary.zone') }}</q-item-label>
|
||||
<q-item-label class="link">{{ ticket.routeFk }}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item>
|
||||
<q-item-section>
|
||||
<q-item-label caption>{{ t('ticket.summary.warehouse') }}</q-item-label>
|
||||
<q-item-label>{{ ticket.warehouse.name }}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item>
|
||||
<q-item-section>
|
||||
<q-item-label caption>{{ t('ticket.summary.invoice') }}</q-item-label>
|
||||
<q-item-label v-if="ticket.refFk" class="link">{{ ticket.refFk }}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</div>
|
||||
<div class="col">
|
||||
<q-list>
|
||||
<q-item>
|
||||
<q-item-section>
|
||||
<q-item-label caption>{{ t('ticket.summary.shipped') }}</q-item-label>
|
||||
<q-item-label>{{ toDate(ticket.shipped) }}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item>
|
||||
<q-item-section>
|
||||
<q-item-label caption>{{ t('ticket.summary.landed') }}</q-item-label>
|
||||
<q-item-label>{{ toDate(ticket.landed) }}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item>
|
||||
<q-item-section>
|
||||
<q-item-label caption>{{ t('ticket.summary.packages') }}</q-item-label>
|
||||
<q-item-label>{{ ticket.packages }}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item>
|
||||
<q-item-section>
|
||||
<q-item-label caption>{{ t('ticket.summary.consigneePhone') }}</q-item-label>
|
||||
<q-item-label>{{ ticket.address.phone }}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item>
|
||||
<q-item-section>
|
||||
<q-item-label caption>{{ t('ticket.summary.consigneeMobile') }}</q-item-label>
|
||||
<q-item-label>{{ ticket.address.mobile }}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item>
|
||||
<q-item-section>
|
||||
<q-item-label caption>{{ t('ticket.summary.clientPhone') }}</q-item-label>
|
||||
<q-item-label>{{ ticket.client.phone }}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item>
|
||||
<q-item-section>
|
||||
<q-item-label caption>{{ t('ticket.summary.clientMobile') }}</q-item-label>
|
||||
<q-item-label>{{ ticket.client.mobile }}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item>
|
||||
<q-item-section>
|
||||
<q-item-label caption>{{ t('ticket.summary.consignee') }}</q-item-label>
|
||||
<q-item-label>{{ formattedAddress() }}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</div>
|
||||
<div class="col">
|
||||
<q-list>
|
||||
<q-item v-for="note in ticket.notes" :key="note.id">
|
||||
<q-item-section>
|
||||
<q-item-label caption>
|
||||
{{ note.observationType.description }}
|
||||
</q-item-label>
|
||||
<q-item-label>
|
||||
{{ note.description }}
|
||||
</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</div>
|
||||
<div class="col">
|
||||
<q-list class="taxes">
|
||||
<q-item>
|
||||
<q-item-section>
|
||||
<q-item-label caption>{{ t('ticket.summary.subtotal') }}</q-item-label>
|
||||
<q-item-label>{{ toCurrency(ticket.totalWithoutVat) }}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item>
|
||||
<q-item-section>
|
||||
<q-item-label caption>{{ t('ticket.summary.vat') }}</q-item-label>
|
||||
<q-item-label>{{
|
||||
toCurrency(ticket.totalWithVat - ticket.totalWithoutVat)
|
||||
}}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item>
|
||||
<q-item-section>
|
||||
<q-item-label caption>{{ t('ticket.summary.total') }}</q-item-label>
|
||||
<q-item-label>{{ toCurrency(ticket.totalWithVat) }}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row q-pa-md" v-if="salesLines.length > 0">
|
||||
<div class="col">
|
||||
<q-list>
|
||||
<q-item-label header class="text-h6">
|
||||
{{ t('ticket.summary.saleLines') }}
|
||||
<router-link
|
||||
:to="{ name: 'TicketBasicData', params: { id: entityId } }"
|
||||
target="_blank"
|
||||
>
|
||||
<q-icon name="open_in_new" />
|
||||
</router-link>
|
||||
</q-item-label>
|
||||
<q-table :rows="ticket.sales" flat>
|
||||
<template #header="props">
|
||||
<q-tr :props="props">
|
||||
<q-th auto-width></q-th>
|
||||
<q-th auto-width>{{ t('ticket.summary.item') }}</q-th>
|
||||
<q-th auto-width>{{ t('ticket.summary.visible') }}</q-th>
|
||||
<q-th auto-width>{{ t('ticket.summary.available') }}</q-th>
|
||||
<q-th auto-width>{{ t('ticket.summary.quantity') }}</q-th>
|
||||
<q-th auto-width>{{ t('ticket.summary.description') }}</q-th>
|
||||
<q-th auto-width>{{ t('ticket.summary.price') }}</q-th>
|
||||
<q-th auto-width>{{ t('ticket.summary.discount') }}</q-th>
|
||||
<q-th auto-width>{{ t('ticket.summary.amount') }}</q-th>
|
||||
<q-th auto-width>{{ t('ticket.summary.packing') }}</q-th>
|
||||
</q-tr>
|
||||
</template>
|
||||
<template #body="props">
|
||||
<q-tr :props="props">
|
||||
<q-td>
|
||||
<q-btn
|
||||
flat
|
||||
round
|
||||
size="xs"
|
||||
icon="vn:claims"
|
||||
v-if="props.row.claim"
|
||||
color="primary"
|
||||
:to="{ name: 'ClaimCard', params: { id: props.row.claim.claimFk } }"
|
||||
>
|
||||
<q-tooltip
|
||||
>{{ t('ticket.summary.claim') }}:
|
||||
{{ props.row.claim.claimFk }}</q-tooltip
|
||||
>
|
||||
</q-btn>
|
||||
<q-btn
|
||||
flat
|
||||
round
|
||||
size="xs"
|
||||
icon="vn:claims"
|
||||
v-if="props.row.claimBeginning"
|
||||
color="primary"
|
||||
:to="{
|
||||
name: 'ClaimCard',
|
||||
params: { id: props.row.claimBeginning.claimFk },
|
||||
}"
|
||||
>
|
||||
<q-tooltip
|
||||
>{{ t('ticket.summary.claim') }}:
|
||||
{{ props.row.claimBeginning.claimFk }}</q-tooltip
|
||||
>
|
||||
</q-btn>
|
||||
<q-icon
|
||||
name="warning"
|
||||
v-show="props.row.visible < 0"
|
||||
size="xs"
|
||||
color="primary"
|
||||
>
|
||||
<q-tooltip
|
||||
>{{ t('ticket.summary.visible') }}:
|
||||
{{ props.row.visible }}</q-tooltip
|
||||
>
|
||||
</q-icon>
|
||||
<q-icon
|
||||
name="vn:reserva"
|
||||
v-show="props.row.reserved"
|
||||
size="xs"
|
||||
color="primary"
|
||||
>
|
||||
<q-tooltip>{{ t('ticket.summary.reserved') }}</q-tooltip>
|
||||
</q-icon>
|
||||
<q-icon
|
||||
name="vn:unavailable"
|
||||
v-show="props.row.itemShortage"
|
||||
size="xs"
|
||||
color="primary"
|
||||
>
|
||||
<q-tooltip>{{ t('ticket.summary.itemShortage') }}</q-tooltip>
|
||||
</q-icon>
|
||||
<q-icon
|
||||
name="vn:components"
|
||||
v-show="props.row.hasComponentLack"
|
||||
size="xs"
|
||||
color="primary"
|
||||
>
|
||||
<q-tooltip>{{ t('ticket.summary.hasComponentLack') }}</q-tooltip>
|
||||
</q-icon>
|
||||
</q-td>
|
||||
<q-td class="link">{{ props.row.itemFk }}</q-td>
|
||||
<q-td>{{ props.row.visible }}</q-td>
|
||||
<q-td>{{ props.row.available }}</q-td>
|
||||
<q-td>{{ props.row.quantity }}</q-td>
|
||||
<q-td>
|
||||
<div class="fetched-tags">
|
||||
<span>{{ props.row.item.name }}</span>
|
||||
<span v-if="props.row.item.subName" class="subName">{{
|
||||
props.row.item.subName
|
||||
}}</span>
|
||||
</div>
|
||||
<fetched-tags :item="props.row.item" :max-length="5"></fetched-tags>
|
||||
</q-td>
|
||||
<q-td>{{ props.row.price }}</q-td>
|
||||
<q-td>{{ props.row.discount }} %</q-td>
|
||||
<q-td
|
||||
>{{
|
||||
toCurrency(
|
||||
props.row.quantity *
|
||||
props.row.price *
|
||||
((100 - props.row.discount) / 100)
|
||||
)
|
||||
}}
|
||||
</q-td>
|
||||
<q-td>{{ dashIfEmpty(props.row.item.itemPackingTypeFk) }}</q-td>
|
||||
</q-tr>
|
||||
</template>
|
||||
</q-table>
|
||||
</q-list>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row q-pa-md" v-if="ticket.packagings.length > 0 || ticket.services.length > 0">
|
||||
<div class="col" v-if="ticket.packagings.length > 0">
|
||||
<q-list>
|
||||
<q-item-label header class="text-h6">
|
||||
{{ t('ticket.summary.packages') }}
|
||||
<q-icon name="open_in_new" />
|
||||
</q-item-label>
|
||||
alexandre marked this conversation as resolved
Outdated
joan
commented
Seguir la misma estructura de encabezado de apartados, similar al de CustomerSummary, con el icono en el lado derecho. Seguir la misma estructura de encabezado de apartados, similar al de CustomerSummary, con el icono en el lado derecho.
|
||||
<q-table :rows="ticket.packagings" flat>
|
||||
<template #header="props">
|
||||
<q-tr :props="props">
|
||||
<q-th auto-width>{{ t('ticket.summary.created') }}</q-th>
|
||||
alexandre marked this conversation as resolved
Outdated
joan
commented
Quitar fondo de la tabla Quitar fondo de la tabla
|
||||
<q-th auto-width>{{ t('ticket.summary.package') }}</q-th>
|
||||
<q-th auto-width>{{ t('ticket.summary.quantity') }}</q-th>
|
||||
</q-tr>
|
||||
</template>
|
||||
<template #body="props">
|
||||
<q-tr :props="props">
|
||||
<q-td>{{ toDate(props.row.created) }}</q-td>
|
||||
<q-td>{{ props.row.packaging.item.name }}</q-td>
|
||||
<q-td>{{ props.row.quantity }}</q-td>
|
||||
</q-tr>
|
||||
</template>
|
||||
</q-table>
|
||||
</q-list>
|
||||
</div>
|
||||
<div class="col" v-if="ticket.services.length > 0">
|
||||
<q-list>
|
||||
<q-item-label header class="text-h6">
|
||||
{{ t('ticket.summary.services') }}
|
||||
<q-icon name="open_in_new" />
|
||||
</q-item-label>
|
||||
<q-table :rows="ticket.services" flat>
|
||||
<template #header="props">
|
||||
<q-tr :props="props">
|
||||
<q-th auto-width>{{ t('ticket.summary.quantity') }}</q-th>
|
||||
<q-th auto-width>{{ t('ticket.summary.description') }}</q-th>
|
||||
<q-th auto-width>{{ t('ticket.summary.price') }}</q-th>
|
||||
<q-th auto-width>{{ t('ticket.summary.taxClass') }}</q-th>
|
||||
<q-th auto-width>{{ t('ticket.summary.amount') }}</q-th>
|
||||
alexandre marked this conversation as resolved
Outdated
joan
commented
Quitar el fondo de la tabla, ahora mismo es un card dentro de otro card. Quitar el fondo de la tabla, ahora mismo es un card dentro de otro card.
|
||||
</q-tr>
|
||||
</template>
|
||||
<template #body="props">
|
||||
<q-tr :props="props">
|
||||
<q-td>{{ props.row.quantity }}</q-td>
|
||||
<q-td>{{ props.row.description }}</q-td>
|
||||
<q-td>{{ toCurrency(props.row.price) }}</q-td>
|
||||
<q-td>{{ props.row.taxClass.description }}</q-td>
|
||||
<q-td>{{ toCurrency(props.row.quantity * props.row.price) }}</q-td>
|
||||
</q-tr>
|
||||
</template>
|
||||
</q-table>
|
||||
</q-list>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row q-pa-md" v-if="ticket.requests.length > 0">
|
||||
<div class="col">
|
||||
<q-list>
|
||||
<q-item-label header class="text-h6">
|
||||
{{ t('ticket.summary.request') }}
|
||||
<q-icon name="open_in_new" />
|
||||
</q-item-label>
|
||||
<q-table :rows="ticket.requests" flat>
|
||||
<template #header="props">
|
||||
<q-tr :props="props">
|
||||
<q-th auto-width>{{ t('ticket.summary.description') }}</q-th>
|
||||
<q-th auto-width>{{ t('ticket.summary.created') }}</q-th>
|
||||
<q-th auto-width>{{ t('ticket.summary.requester') }}</q-th>
|
||||
<q-th auto-width>{{ t('ticket.summary.atender') }}</q-th>
|
||||
<q-th auto-width>{{ t('ticket.summary.quantity') }}</q-th>
|
||||
<q-th auto-width>{{ t('ticket.summary.price') }}</q-th>
|
||||
<q-th auto-width>{{ t('ticket.summary.item') }}</q-th>
|
||||
<q-th auto-width>Ok</q-th>
|
||||
</q-tr>
|
||||
</template>
|
||||
alexandre marked this conversation as resolved
Outdated
joan
commented
Reducir el tamaño máximo de la vista previa y comprobar que se vea correctamente desde el listado de tickets. Ejemplo ClientSummary, tiene max-width de 1200px Reducir el tamaño máximo de la vista previa y comprobar que se vea correctamente desde el listado de tickets. Ejemplo ClientSummary, tiene max-width de 1200px
|
||||
<template #body="props">
|
||||
<q-tr :props="props">
|
||||
<q-td>{{ props.row.description }}</q-td>
|
||||
<q-td>{{ toDate(props.row.created) }}</q-td>
|
||||
<q-td>{{ props.row.requester.user.name }}</q-td>
|
||||
<q-td>{{ props.row.atender.user.name }}</q-td>
|
||||
<q-td>{{ props.row.quantity }}</q-td>
|
||||
<q-td>{{ toCurrency(props.row.price) }}</q-td>
|
||||
<q-td v-if="!props.row.sale">-</q-td>
|
||||
<q-td v-if="props.row.sale" class="link">{{ props.row.sale.itemFk }}</q-td>
|
||||
<q-td><q-checkbox v-model="props.row.isOk" :disable="true" /></q-td>
|
||||
</q-tr>
|
||||
</template>
|
||||
</q-table>
|
||||
</q-list>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</q-card>
|
||||
</div>
|
||||
</template>
|
||||
<style lang="scss" scoped>
|
||||
.container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.q-card {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
max-width: 1200px;
|
||||
}
|
||||
|
||||
.summary {
|
||||
.q-list {
|
||||
.q-item__label--header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
a {
|
||||
color: $primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
.fetched-tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
& span {
|
||||
flex-basis: 50%;
|
||||
}
|
||||
& span.subName {
|
||||
flex-basis: 50%;
|
||||
color: $secondary;
|
||||
text-transform: uppercase;
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
}
|
||||
.q-table__container {
|
||||
text-align: left;
|
||||
.q-icon {
|
||||
padding: 2%;
|
||||
}
|
||||
}
|
||||
.taxes {
|
||||
border: $border-thin-light;
|
||||
text-align: right;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.row {
|
||||
flex-wrap: wrap;
|
||||
|
||||
.col {
|
||||
min-width: 250px;
|
||||
padding-left: 1.5%;
|
||||
padding-right: 1.5%;
|
||||
}
|
||||
}
|
||||
|
||||
.header {
|
||||
font-size: 18px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
align-content: center;
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
|
||||
span {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.q-btn {
|
||||
flex: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.q-dialog .summary {
|
||||
max-width: 1200px;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,29 @@
|
|||
<script setup>
|
||||
import { useDialogPluginComponent } from 'quasar';
|
||||
import TicketSummary from './TicketSummary.vue';
|
||||
|
||||
const $props = defineProps({
|
||||
id: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
defineEmits([...useDialogPluginComponent.emits]);
|
||||
|
||||
const { dialogRef, onDialogHide } = useDialogPluginComponent();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<q-dialog ref="dialogRef" @hide="onDialogHide">
|
||||
<ticket-summary v-if="$props.id" :id="$props.id" />
|
||||
</q-dialog>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.q-dialog .summary .header {
|
||||
position: sticky;
|
||||
z-index: $z-max;
|
||||
top: 0;
|
||||
}
|
||||
</style>
|
|
@ -1,12 +1,13 @@
|
|||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useQuasar } from 'quasar';
|
||||
import { useRouter } from 'vue-router';
|
||||
import Paginate from 'components/Paginate.vue';
|
||||
import { toDate, toCurrency } from 'src/filters/index';
|
||||
// import TicketSummary from './Card/TicketSummary.vue';
|
||||
import TicketSummaryDialog from './Card/TicketSummaryDialog.vue';
|
||||
|
||||
const router = useRouter();
|
||||
const quasar = useQuasar();
|
||||
const { t } = useI18n();
|
||||
|
||||
const filter = {
|
||||
|
@ -48,15 +49,13 @@ function navigate(id) {
|
|||
router.push({ path: `/ticket/${id}` });
|
||||
}
|
||||
|
||||
const preview = ref({
|
||||
shown: false,
|
||||
});
|
||||
|
||||
function showPreview(id) {
|
||||
preview.value.shown = true;
|
||||
preview.value.data = {
|
||||
customerId: id,
|
||||
};
|
||||
function viewSummary(id) {
|
||||
quasar.dialog({
|
||||
component: TicketSummaryDialog,
|
||||
componentProps: {
|
||||
id,
|
||||
},
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -108,42 +107,16 @@ function showPreview(id) {
|
|||
</q-item-section>
|
||||
<q-separator vertical />
|
||||
<q-card-actions vertical class="justify-between">
|
||||
<!-- <q-btn color="grey-7" round flat icon="more_vert">
|
||||
<q-tooltip>{{ t('customer.list.moreOptions') }}</q-tooltip>
|
||||
<q-menu cover auto-close>
|
||||
<q-list>
|
||||
<q-item clickable>
|
||||
<q-item-section avatar>
|
||||
<q-icon name="add" />
|
||||
</q-item-section>
|
||||
<q-item-section>Add a note</q-item-section>
|
||||
</q-item>
|
||||
<q-item clickable>
|
||||
<q-item-section avatar>
|
||||
<q-icon name="history" />
|
||||
</q-item-section>
|
||||
<q-item-section>Display customer history</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-menu>
|
||||
</q-btn> -->
|
||||
|
||||
<q-btn flat round color="orange" icon="arrow_circle_right" @click="navigate(row.id)">
|
||||
<q-tooltip>{{ t('components.smartCard.openCard') }}</q-tooltip>
|
||||
</q-btn>
|
||||
<q-btn flat round color="grey-7" icon="preview" @click="showPreview(row.id)">
|
||||
<q-btn flat round color="grey-7" icon="preview" @click="viewSummary(row.id)">
|
||||
<q-tooltip>{{ t('components.smartCard.openSummary') }}</q-tooltip>
|
||||
</q-btn>
|
||||
<!-- <q-btn flat round color="grey-7" icon="vn:ticket">
|
||||
<q-tooltip>{{ t('customer.list.customerOrders') }}</q-tooltip>
|
||||
</q-btn> -->
|
||||
</q-card-actions>
|
||||
</q-item>
|
||||
</q-card>
|
||||
</template>
|
||||
</paginate>
|
||||
</q-page>
|
||||
<!-- <q-dialog v-model="preview.shown">
|
||||
<customer-summary :customer-id="preview.data.customerId" />
|
||||
</q-dialog> -->
|
||||
</template>
|
||||
|
|
Loading…
Reference in New Issue
La vista previa es accesible desde el listado de tickets (TicketList)