feat(TicketDescriptorMenu): added ticket menu and VnSms component
gitea/salix-front/pipeline/head This commit looks good Details

Refs: #5387
This commit is contained in:
Joan Sanchez 2023-03-08 15:12:04 +01:00
parent c5625ad97b
commit c43f743804
3 changed files with 394 additions and 0 deletions

View File

@ -0,0 +1,179 @@
<script setup>
import { ref, computed, reactive } from 'vue';
import { useDialogPluginComponent } from 'quasar';
import { useI18n } from 'vue-i18n';
const { dialogRef, onDialogOK } = useDialogPluginComponent();
const { t, availableLocales } = useI18n();
defineEmits(['confirm', ...useDialogPluginComponent.emits]);
const props = defineProps({
subject: {
type: String,
required: false,
default: 'Verdnatura',
},
phone: {
type: String,
required: true,
},
template: {
type: String,
required: true,
},
});
const maxLength = 160;
const locale = ref('es');
const subject = ref(props.subject);
const phone = ref(props.phone);
const message = ref('');
// const templates = ['pendingPayment', 'minAmount'];
const template = reactive(props.template);
updateMessage();
function updateMessage() {
const params = { orderId: 123 };
message.value = t(`templates['${template}']`, params, { locale: locale.value });
}
const totalLength = computed(() => message.value.length);
const color = computed(() => {
if (totalLength.value == maxLength) return 'negative';
if ((totalLength.value / maxLength) * 100 > 90) return 'warning';
return 'positive';
});
const languages = availableLocales.map((locale) => ({ label: t(locale), value: locale }));
</script>
<template>
<q-dialog ref="dialogRef" persistent>
<q-card class="q-pa-sm">
<q-card-section class="row items-center q-pb-none">
<span class="text-h6 text-grey">
{{ t('Send SMS') }}
</span>
<q-space />
<q-btn icon="close" flat round dense v-close-popup />
</q-card-section>
<q-card-section>
<q-banner class="bg-warning" rounded dense>
This user uses "" as default language
</q-banner>
</q-card-section>
<q-card-section class="q-pb-xs">
<q-select
:label="t('Language')"
:options="languages"
v-model="locale"
@update:model-value="updateMessage()"
emit-value
map-options
:input-debounce="0"
rounded
outlined
dense
/>
</q-card-section>
<q-card-section class="q-pb-xs">
<q-input
:label="t('Phone')"
v-model="phone"
rounded
outlined
autofocus
dense
/>
</q-card-section>
<q-card-section class="q-pb-xs">
<q-input
:label="t('Subject')"
v-model="subject"
rounded
outlined
autofocus
dense
/>
</q-card-section>
<q-card-section class="q-mb-md" q-input>
<q-input
:label="t('Message')"
v-model="message"
type="textarea"
:maxlength="maxLength"
:counter="true"
:autogrow="true"
:bottom-slots="true"
:rules="[(value) => value.length < maxLength || 'Error!']"
stack-label
outlined
autofocus
dense
>
<template #append>
<q-icon
v-if="message !== ''"
name="close"
@click="message = ''"
class="cursor-pointer"
/>
</template>
<template #counter>
<q-chip :color="color" dense>
{{ totalLength }}/{{ maxLength }}
</q-chip>
</template>
</q-input>
</q-card-section>
<q-card-actions align="right">
<q-btn :label="t('globals.cancel')" color="primary" flat v-close-popup />
<q-btn :label="t('globals.confirm')" color="primary" @click="confirm" />
</q-card-actions>
</q-card>
</q-dialog>
</template>
<style lang="scss" scoped>
.q-chip {
transition: background 0.36s;
}
.q-card {
width: 400px;
}
</style>
<i18n>
en:
Message: Message
en: English
es: Spanish
fr: French
templates:
pendingPayment: 'Your order is pending of payment.
Please, enter the website and make the payment with a credit card. Thank you.'
minAmount: Test 2
es:
Language: Idioma
Message: Mensaje
templates:
pendingPayment: 'Su pedido está pendiente de pago.
Por favor, entre en la página web y efectue el pago con tarjeta. Muchas gracias.'
minAmount: 'Es necesario un importe mínimo de 50€ (Sin IVA) en su pedido { orderId } del día 08/03/2023 para recibirlo sin portes adicionales.'
en: Inglés
es: Español
fr: Francés
fr:
Language: Langage
Message: Message
templates:
pendingPayment: 'Votre commande est en attente de paiement.
Veuillez vous connecter sur le site web et effectuer le paiement par carte. Merci beaucoup.'
minAmount: 'Un montant minimum de 50 (TVA non incluse) est requis pour votre commande
4101055 du 03/08/2023 afin de la recevoir sans frais de port supplémentaires.'
en: Anglais
es: Espagnol
fr: Français
</i18n>

View File

@ -5,6 +5,7 @@ import { useI18n } from 'vue-i18n';
import { toDate } from 'src/filters'; import { toDate } from 'src/filters';
import CustomerDescriptorPopover from 'src/pages/Customer/Card/CustomerDescriptorPopover.vue'; import CustomerDescriptorPopover from 'src/pages/Customer/Card/CustomerDescriptorPopover.vue';
import CardDescriptor from 'components/ui/CardDescriptor.vue'; import CardDescriptor from 'components/ui/CardDescriptor.vue';
import TicketDescriptorMenu from './TicketDescriptorMenu.vue';
const $props = defineProps({ const $props = defineProps({
id: { id: {
@ -61,6 +62,9 @@ function stateColor(state) {
<template> <template>
<card-descriptor module="Ticket" :url="`Tickets/${entityId}`" :filter="filter"> <card-descriptor module="Ticket" :url="`Tickets/${entityId}`" :filter="filter">
<template #menu="{ entity }">
<TicketDescriptorMenu :ticket="entity" />
</template>
<template #description="{ entity }"> <template #description="{ entity }">
<span> <span>
{{ entity.client.name }} {{ entity.client.name }}

View File

@ -0,0 +1,211 @@
<script setup>
import axios from 'axios';
import { ref } from 'vue';
import { useQuasar } from 'quasar';
import { useI18n } from 'vue-i18n';
import { useRouter } from 'vue-router';
import { usePrintService } from 'composables/usePrintService';
import SendEmailDialog from 'components/common/SendEmailDialog.vue';
import VnConfirm from 'components/ui/VnConfirm.vue';
import VnSmsDialog from 'components/common/VnSmsDialog.vue';
const $props = defineProps({
ticket: {
type: Object,
required: true,
},
});
const router = useRouter();
const quasar = useQuasar();
const { t } = useI18n();
const { openReport, sendEmail } = usePrintService();
const ticket = ref($props.ticket);
function openDeliveryNote(type = 'deliveryNote', documentType = 'pdf') {
const path = `Tickets/${ticket.value.id}/delivery-note-${documentType}`;
openReport(path, {
recipientId: ticket.value.clientFk,
type: type,
});
}
function sendDeliveryNote(type = 'deliveryNote', documentType = 'pdf') {
const id = ticket.value.id;
const customer = ticket.value.client;
return sendEmail(`Tickets/${id}/delivery-note-email`, {
recipientId: customer.id,
type: type,
});
}
// function confirmPickupOrder() {
// const customer = ticket.value.client;
// quasar.dialog({
// component: SendEmailDialog,
// componentProps: {
// address: customer.email,
// send: sendPickupOrder,
// },
// });
// }
function sendSms() {
quasar.dialog({
component: VnSmsDialog,
componentProps: {
phone: '123',
template: 'pendingPayment'
}
})
}
function confirmDelete() {
quasar
.dialog({
component: VnConfirm,
})
.onOk(() => remove());
}
async function remove() {
const id = ticket.value.id;
await axios.delete(`Claims/${id}`);
quasar.notify({
message: t('globals.dataDeleted'),
type: 'positive',
icon: 'check',
});
await router.push({ name: 'TicketList' });
}
</script>
<template>
<q-item v-ripple clickable>
<q-item-section avatar>
<q-icon name="summarize" />
</q-item-section>
<q-item-section>{{ t('Open Delivery Note...') }}</q-item-section>
<q-item-section side>
<q-icon name="keyboard_arrow_right" />
</q-item-section>
<q-menu anchor="top end" self="top start" auto-close>
<q-list>
<q-item @click="openDeliveryNote()" v-ripple clickable>
<q-item-section avatar>
<q-icon name="picture_as_pdf" />
</q-item-section>
<q-item-section>{{ t('With prices') }}</q-item-section>
</q-item>
<q-item @click="openDeliveryNote('withoutPrices')" v-ripple clickable>
<q-item-section avatar>
<q-icon name="picture_as_pdf" />
</q-item-section>
<q-item-section>{{ t('Without Prices') }}</q-item-section>
</q-item>
<q-item
@click="openDeliveryNote('deliveryNote', 'csv')"
v-ripple
clickable
>
<q-item-section avatar>
<q-icon name="picture_as_pdf" />
</q-item-section>
<q-item-section>{{ t('As CSV') }}</q-item-section>
</q-item>
<q-item @click="confirmPickupOrder" v-ripple clickable>
<q-item-section avatar>
<q-icon name="send" />
</q-item-section>
<q-item-section>{{ t('Send Delivery Note') }}</q-item-section>
</q-item>
</q-list>
</q-menu>
</q-item>
<q-item v-ripple clickable>
<q-item-section avatar>
<q-icon name="send" />
</q-item-section>
<q-item-section>{{ t('Send Delivery Note...') }}</q-item-section>
<q-item-section side>
<q-icon name="keyboard_arrow_right" />
</q-item-section>
<q-menu anchor="top end" self="top start" auto-close>
<q-list>
<q-item @click="sendDeliveryNote()" v-ripple clickable>
<q-item-section>{{ t('With prices') }}</q-item-section>
</q-item>
<q-item @click="sendDeliveryNote('withoutPrices')" v-ripple clickable>
<q-item-section>{{ t('Without Prices') }}</q-item-section>
</q-item>
<q-item
@click="sendDeliveryNote('deliveryNote', 'csv')"
v-ripple
clickable
>
<q-item-section>{{ t('As CSV') }}</q-item-section>
</q-item>
</q-list>
</q-menu>
</q-item>
<q-item @click="openDeliveryNote('proforma')" v-ripple clickable>
<q-item-section avatar>
<q-icon name="receipt" />
</q-item-section>
<q-item-section>{{ t('Open Proforma Invoice') }}</q-item-section>
</q-item>
<q-item v-ripple clickable>
<q-item-section avatar>
<q-icon name="sms" />
</q-item-section>
<q-item-section>{{ t('Send SMS...') }}</q-item-section>
<q-item-section side>
<q-icon name="keyboard_arrow_right" />
</q-item-section>
<q-menu anchor="top end" self="top start" auto-close>
<q-list>
<q-item @click="sendSms()" v-ripple clickable>
<q-item-section avatar>
<q-icon name="picture_as_pdf" />
</q-item-section>
<q-item-section>{{ t('Pending payment') }}</q-item-section>
</q-item>
</q-list>
</q-menu>
</q-item>
<q-separator />
<q-item @click="confirmDelete()" v-ripple clickable>
<q-item-section avatar>
<q-icon name="delete" />
</q-item-section>
<q-item-section>{{ t('Delete ticket') }}</q-item-section>
</q-item>
</template>
<i18n>
es:
Delivery Note: Albarán
Open Delivery Note: Abrir albarán
Delete ticket: Eliminar ticket
</i18n>
<!--
<i18n>
{
"en": {
"pickupOrder": "Pickup order",
"openPickupOrder": "Open pickup order",
"sendPickupOrder": "Send pickup order",
"deleteClaim": "Delete claim",
"confirmDeletion": "Confirm deletion",
"confirmDeletionMessage": "Are you sure you want to delete this claim?"
},
"es": {
"pickupOrder": "Orden de recogida",
"openPickupOrder": "Abrir orden de recogida",
"sendPickupOrder": "Enviar orden de recogida",
"deleteClaim": "Eliminar reclamación",
"confirmDeletion": "Confirmar eliminación",
"confirmDeletionMessage": "Seguro que quieres eliminar esta reclamación?"
}
}
</i18n> -->