578 lines
21 KiB
Vue
578 lines
21 KiB
Vue
<script setup>
|
|
import { ref, onMounted, inject, computed } from 'vue';
|
|
import { useI18n } from 'vue-i18n';
|
|
import { useRoute, useRouter } from 'vue-router';
|
|
|
|
import VnSelect from 'src/components/common/VnSelect.vue';
|
|
|
|
import { formatDateTitle, formatDate } from 'src/lib/filters.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 route = useRoute();
|
|
const router = useRouter();
|
|
const { notify } = useNotify();
|
|
const appStore = useAppStore();
|
|
const { localeDates } = storeToRefs(appStore);
|
|
|
|
const stepperRef = ref(null);
|
|
|
|
const loading = ref(false);
|
|
const today = ref(null);
|
|
const addresses = ref([]);
|
|
const agencies = ref([]);
|
|
const warehouses = ref([]);
|
|
const currentStep = ref('method');
|
|
const id = route.params.id;
|
|
const orderForm = ref({
|
|
method: 'AGENCY',
|
|
date: '',
|
|
address: ''
|
|
});
|
|
|
|
const steps = {
|
|
AGENCY: [
|
|
{
|
|
name: 'method',
|
|
stepDone: false,
|
|
validateStep: () =>
|
|
validateStep('method', t('pleaseSelectAnOption'))
|
|
},
|
|
{
|
|
name: 'date',
|
|
stepDone: false,
|
|
validateStep: () => validateStep('date', t('pleaseSelectADate'))
|
|
},
|
|
{
|
|
name: 'address',
|
|
validateStep: () =>
|
|
validateStep('address', t('pleaseSelectAnAddress'))
|
|
},
|
|
{
|
|
name: 'agency',
|
|
onStepMounted: async () => {
|
|
await getAgencies();
|
|
},
|
|
validateStep: () =>
|
|
validateStep('agency', t('pleaseSelectAnAgency'))
|
|
},
|
|
{
|
|
name: 'confirm',
|
|
onBeforeNextStep: async () => {
|
|
await submit();
|
|
}
|
|
}
|
|
],
|
|
PICKUP: [
|
|
{
|
|
name: 'method',
|
|
validateStep: () =>
|
|
validateStep('method', t('pleaseSelectAnOption'))
|
|
},
|
|
{
|
|
name: 'date',
|
|
validateStep: () => validateStep('date', t('pleaseSelectADate'))
|
|
},
|
|
{
|
|
name: 'address',
|
|
validateStep: () =>
|
|
validateStep('address', t('pleaseSelectAnAddress'))
|
|
},
|
|
{
|
|
name: 'pickup',
|
|
validateStep: () =>
|
|
validateStep('agency', t('pleaseSelectAWarehouse')),
|
|
onStepMounted: async () => {
|
|
await getWarehouses();
|
|
}
|
|
},
|
|
{
|
|
name: 'confirm',
|
|
onBeforeNextStep: async () => {
|
|
await submit();
|
|
}
|
|
}
|
|
]
|
|
};
|
|
|
|
const confirmArrivalText = computed(() => {
|
|
const { method, agency, date } = orderForm.value;
|
|
|
|
if (!agency) {
|
|
return '';
|
|
}
|
|
|
|
const arrivalType = method === 'AGENCY' ? t('arrival') : t('pickup');
|
|
return `${arrivalType} ${formatDateTitle(date)}`;
|
|
});
|
|
|
|
const confirmAddressText = computed(() => {
|
|
if (!orderForm.value.address) return '';
|
|
const address = addresses.value.find(
|
|
address => address.id === orderForm.value.address
|
|
);
|
|
return address.street;
|
|
});
|
|
|
|
const confirmPlaceText = computed(() => {
|
|
const { agency, method } = orderForm.value;
|
|
if (!agency) return '';
|
|
|
|
if (method === 'AGENCY') {
|
|
const agencyItem = agencies.value.find(a => a.id === agency);
|
|
return agencyItem ? `${t('agency')} ${agencyItem.description}` : '';
|
|
}
|
|
|
|
if (method === 'PICKUP') {
|
|
const warehouseItem = warehouses.value.find(w => w.id === agency);
|
|
return warehouseItem
|
|
? `${t('warehouse')} ${warehouseItem.description}`
|
|
: '';
|
|
}
|
|
|
|
return '';
|
|
});
|
|
|
|
const validateStep = (formField, errorMessage) => {
|
|
const validation = !!orderForm.value[formField];
|
|
if (!validation) {
|
|
notify(errorMessage, 'negative');
|
|
}
|
|
return validation;
|
|
};
|
|
|
|
const getAddresses = async () => {
|
|
try {
|
|
addresses.value = await jApi.query(
|
|
`SELECT a.id, a.nickname, p.name province, a.city, a.street, a.isActive, c.name
|
|
FROM myAddress a
|
|
LEFT JOIN vn.province p ON p.id = a.provinceFk
|
|
JOIN vn.country c ON c.id = p.countryFk
|
|
WHERE a.isActive`
|
|
);
|
|
} catch (error) {
|
|
console.error('Error getting addresses:', error);
|
|
}
|
|
};
|
|
|
|
const getAgencies = async () => {
|
|
try {
|
|
const { results } = await jApi.execQuery(
|
|
`CALL vn.zone_getAgency(#address, #date);
|
|
SELECT DISTINCT a.agencyModeFk id, a.description
|
|
FROM tmp.zoneGetAgency a
|
|
JOIN vn.deliveryMethod d
|
|
ON d.id = a.deliveryMethodFk
|
|
WHERE d.code IN ('AGENCY', 'DELIVERY')
|
|
AND a.isVisible
|
|
ORDER BY a.description;
|
|
DROP TEMPORARY TABLE tmp.zoneGetAgency`,
|
|
{
|
|
address: orderForm.value.address,
|
|
date: new Date(orderForm.value.date)
|
|
}
|
|
);
|
|
agencies.value = results[1].data;
|
|
} catch (error) {
|
|
console.error('Error getting agencies:', error);
|
|
}
|
|
};
|
|
|
|
const getWarehouses = async () => {
|
|
try {
|
|
const { results } = await jApi.execQuery(
|
|
`CALL vn.zone_getAgency(#address, #date);
|
|
SELECT DISTINCT a.agencyModeFk id, a.description
|
|
FROM tmp.zoneGetAgency a
|
|
JOIN vn.deliveryMethod d
|
|
ON d.id = a.deliveryMethodFk
|
|
WHERE d.code IN ('PICKUP')
|
|
AND a.isVisible
|
|
ORDER BY a.description;
|
|
DROP TEMPORARY TABLE tmp.zoneGetAgency;`,
|
|
{
|
|
address: orderForm.value.address,
|
|
date: new Date(orderForm.value.date)
|
|
}
|
|
);
|
|
warehouses.value = results[1].data;
|
|
|
|
if (!warehouses.value || !warehouses.value.length) {
|
|
notify(t('noWarehousesAvailableForDate'), 'negative');
|
|
}
|
|
} catch (error) {
|
|
console.error('Error getting agencies:', error);
|
|
}
|
|
};
|
|
|
|
const onNextStep = async stepIndex => {
|
|
const currentStep = steps[orderForm.value.method][stepIndex];
|
|
if (currentStep.onBeforeNextStep) {
|
|
await currentStep.onBeforeNextStep();
|
|
}
|
|
|
|
if (currentStep.validateStep && !currentStep.validateStep()) {
|
|
return;
|
|
}
|
|
|
|
currentStep.stepDone = true;
|
|
await stepperRef.value.next();
|
|
|
|
const nextStep = steps[orderForm.value.method][stepIndex + 1];
|
|
if (nextStep && nextStep.onStepMounted) {
|
|
await nextStep.onStepMounted();
|
|
}
|
|
};
|
|
|
|
const onPreviousStep = async stepIndex => {
|
|
await stepperRef.value.previous();
|
|
|
|
const previousStep = steps[orderForm.value.method][stepIndex - 1];
|
|
|
|
if (previousStep.onStepMounted) {
|
|
await previousStep.onStepMounted();
|
|
}
|
|
};
|
|
|
|
const getDefaultValues = async () => {
|
|
return await jApi.query(
|
|
`SELECT deliveryMethod, agencyModeFk, addressFk, defaultAgencyFk
|
|
FROM myBasketDefaults`
|
|
);
|
|
};
|
|
|
|
const submit = async () => {
|
|
loading.value = true;
|
|
let query =
|
|
'CALL myOrder_create(@orderId, #date, #method, #agency, #address); SELECT @orderId;';
|
|
if (id) {
|
|
orderForm.value.id = id;
|
|
query =
|
|
'CALL myOrder_configure(#id, #date, #method, #agency, #address)';
|
|
}
|
|
|
|
let resultSet;
|
|
try {
|
|
const { date, ...restOfForm } = orderForm.value;
|
|
const _date = new Date(date);
|
|
resultSet = await jApi.execQuery(query, { ...restOfForm, date: _date });
|
|
if (id) {
|
|
notify(t('orderUpdated'), 'positive');
|
|
if (route.query.continue === 'catalog') {
|
|
router.push({ name: 'catalog' });
|
|
} else {
|
|
router.push({ name: 'basket', params: { id } });
|
|
}
|
|
} else {
|
|
const orderId = resultSet.results[1].data[0]['@orderId'];
|
|
appStore.loadIntoBasket(orderId);
|
|
router.push({ name: 'catalog' });
|
|
}
|
|
} catch (error) {
|
|
console.error('Error submitting order:', error);
|
|
} finally {
|
|
loading.value = false;
|
|
}
|
|
};
|
|
|
|
onMounted(async () => {
|
|
today.value = Date.vnNew();
|
|
today.value.setHours(0, 0, 0, 0);
|
|
|
|
if (route.params.id) {
|
|
const [order] = await jApi.query(
|
|
`SELECT m.code deliveryMethod, o.sent, o.agencyModeFk, o.addressFk
|
|
FROM myOrder o
|
|
JOIN vn.deliveryMethod m ON m.id = o.deliveryMethodFk
|
|
WHERE o.id = #id`,
|
|
{ id: route.params.id }
|
|
);
|
|
|
|
if (order) {
|
|
orderForm.value.method = order.deliveryMethod;
|
|
orderForm.value.date = formatDate(order.sent, 'YYYY/MM/DD');
|
|
orderForm.value.agency = order.agencyModeFk;
|
|
orderForm.value.address = order.addressFk;
|
|
}
|
|
} else {
|
|
const [defaultValues] = await getDefaultValues();
|
|
if (defaultValues) {
|
|
orderForm.value.method = defaultValues.deliveryMethod;
|
|
}
|
|
}
|
|
|
|
getAddresses();
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<QPage class="vn-w-sm">
|
|
<QStepper
|
|
v-if="steps[orderForm.method] && steps[orderForm.method].length"
|
|
v-model="currentStep"
|
|
ref="stepperRef"
|
|
animated
|
|
keep-alive
|
|
class="default-radius"
|
|
>
|
|
<QStep
|
|
v-for="(step, stepIndex) in steps[orderForm.method]"
|
|
:key="stepIndex"
|
|
:name="step.name"
|
|
:done="step.stepDone"
|
|
done-color="accent"
|
|
>
|
|
<!-- Method step -->
|
|
<div
|
|
v-if="step.name === 'method'"
|
|
class="column justify-center items-center"
|
|
>
|
|
<span class="text-h6 step-title">
|
|
{{ t('receiveOrPickOrder') }}
|
|
</span>
|
|
<div class="column" style="max-width: max-content">
|
|
<QRadio
|
|
v-model="orderForm.method"
|
|
val="AGENCY"
|
|
:label="t('receiveOrder')"
|
|
/>
|
|
<QRadio
|
|
v-model="orderForm.method"
|
|
val="PICKUP"
|
|
:label="t('pickupInStore')"
|
|
/>
|
|
</div>
|
|
</div>
|
|
<!-- Date step -->
|
|
<div
|
|
v-if="step.name === 'date'"
|
|
class="flex justify-center items-center"
|
|
>
|
|
<span class="text-h6 step-title">
|
|
{{ t('orderDateDelivery') }}
|
|
</span>
|
|
<QDate
|
|
v-model="orderForm.date"
|
|
class="margin-auto"
|
|
color="accent"
|
|
:locale="localeDates"
|
|
/>
|
|
</div>
|
|
<!-- Address step -->
|
|
<QList
|
|
v-if="step.name === 'address'"
|
|
class="vn-w-xs q-gutter-y-sm column"
|
|
>
|
|
<span class="text-h6 step-title">
|
|
{{
|
|
t(
|
|
orderForm.method === 'PICKUP'
|
|
? 'addressStepQuestionPickup'
|
|
: 'addressStepQuestion'
|
|
)
|
|
}}
|
|
</span>
|
|
<QItem
|
|
v-for="(address, index) in addresses"
|
|
:key="index"
|
|
tag="label"
|
|
v-ripple
|
|
>
|
|
<QItemSection avatar>
|
|
<QRadio
|
|
v-model="orderForm.address"
|
|
:val="address.id"
|
|
/>
|
|
</QItemSection>
|
|
<QItemSection>
|
|
<QItemLabel>{{ address.nickname }}</QItemLabel>
|
|
<QItemLabel caption>
|
|
{{ address.street }}
|
|
</QItemLabel>
|
|
</QItemSection>
|
|
</QItem>
|
|
</QList>
|
|
<!-- Agency step (AGENCY) -->
|
|
<div
|
|
v-if="step.name === 'agency'"
|
|
class="flex justify-center items-center"
|
|
>
|
|
<span class="text-h6 step-title">
|
|
{{ t('orderDateDelivery') }}
|
|
</span>
|
|
<VnSelect
|
|
v-model="orderForm.agency"
|
|
option-label="description"
|
|
option-value="id"
|
|
:options="agencies"
|
|
/>
|
|
</div>
|
|
<div
|
|
v-if="step.name === 'pickup'"
|
|
class="flex justify-center items-center"
|
|
>
|
|
<span class="text-h6 step-title">
|
|
{{ t('pickupWarehouse') }}
|
|
</span>
|
|
<VnSelect
|
|
v-model="orderForm.agency"
|
|
option-label="description"
|
|
option-value="id"
|
|
:options="warehouses"
|
|
/>
|
|
</div>
|
|
<!-- Confirm step -->
|
|
<div
|
|
v-if="step.name === 'confirm'"
|
|
class="flex column justify-center items-center"
|
|
>
|
|
<span class="text-h6 step-title">
|
|
{{ t('confirmData') }}
|
|
</span>
|
|
<div class="column vn-w-xs full-width">
|
|
<span>{{ confirmArrivalText }}</span>
|
|
<span v-if="orderForm.method === 'AGENCY'">
|
|
{{ confirmAddressText }}
|
|
</span>
|
|
<span>{{ confirmPlaceText }}</span>
|
|
</div>
|
|
</div>
|
|
<QStepperNavigation class="flex justify-between">
|
|
<QBtn
|
|
flat
|
|
color="primary"
|
|
@click="onPreviousStep(stepIndex)"
|
|
label="Back"
|
|
class="q-ml-sm"
|
|
:class="{ invisible: currentStep === 'method' }"
|
|
/>
|
|
<QBtn
|
|
@click="onNextStep(stepIndex)"
|
|
color="primary"
|
|
label="next"
|
|
/>
|
|
</QStepperNavigation>
|
|
</QStep>
|
|
</QStepper>
|
|
</QPage>
|
|
</template>
|
|
|
|
<style lang="scss" scoped>
|
|
.step-title {
|
|
min-width: 100%;
|
|
margin-bottom: 16px;
|
|
text-align: center;
|
|
font-weight: bold;
|
|
}
|
|
</style>
|
|
|
|
<i18n lang="yaml">
|
|
en-US:
|
|
receiveOrPickOrder: Do you want to receive or pickup the order?
|
|
receiveOrder: Receive in my store
|
|
pickupInStore: Store pickup
|
|
orderDateDelivery: What day you want to receive the order?
|
|
howDoYouWantToReceive: How do you want to receive the order?
|
|
confirmData: Confirm data
|
|
arrival: Arrival
|
|
orderUpdated: Order updated
|
|
pleaseSelectAnOption: Please select an option
|
|
pleaseSelectADate: Please select a date
|
|
pleaseSelectAnAddress: Please select an address
|
|
pleaseSelectAnAgency: Please select an agency
|
|
pickupWarehouse: What store you want to pickup your order?
|
|
noWarehousesAvailableForDate: There are no stores available for the selected date, check the date of order pickup and that selected address contains a correct province and zip code
|
|
noAgeciesAvailableForDate: There are no agencies available for the selected date and consignee, check the date of the order and that selected address contains a correct province and zip code
|
|
pleaseSelectAWarehouse: Please select a store
|
|
warehouse: Warehouse
|
|
pickup: Pickup
|
|
addressStepQuestion: Where do you want to receive the order?
|
|
addressStepQuestionPickup: To which address do you want to associate the order? (Optional)
|
|
es-ES:
|
|
receiveOrPickOrder: ¿Quieres recibir o recoger el pedido?
|
|
receiveOrder: Recibir en mi tienda
|
|
pickupInStore: Recoger en almacén
|
|
orderDateDelivery: ¿Qué día quieres recibir el pedido?
|
|
howDoYouWantToReceive: ¿Cómo quieres recibir el pedido?
|
|
confirmData: Confirma los datos
|
|
arrival: Llegada
|
|
orderUpdated: Pedido actualizado
|
|
pleaseSelectAnOption: Por favor, selecciona una opción
|
|
pleaseSelectADate: Por favor, selecciona una fecha
|
|
pleaseSelectAnAddress: Por favor, selecciona una dirección
|
|
pleaseSelectAnAgency: Por favor, selecciona una agencia
|
|
pickupWarehouse: ¿En qué almacén quieres recoger tu pedido?
|
|
noWarehousesAvailableForDate: No hay almacenes disponibles para la fecha seleccionada, comprueba la fecha de recogida del pedido y que consignatario seleccionado contiene una provincia y código postal correctos
|
|
noAgeciesAvailableForDate: No hay almacenes disponibles para la fecha seleccionada, comprueba la fecha de recogida del pedido y que consignatario seleccionado contiene una provincia y código postal correctos
|
|
pleaseSelectAWarehouse: Por favor elige un almacén
|
|
warehouse: Almacén
|
|
pickup: Recogida
|
|
addressStepQuestion: ¿Dónde quieres recibir el pedido?
|
|
addressStepQuestionPickup: ¿A qué dirección quieres asociar el pedido? (Opcional)
|
|
ca-ES:
|
|
receiveOrPickOrder: Vols rebre o recollir la comanda?
|
|
receiveOrder: Rebre en mi tenda
|
|
pickupInStore: Recollir en magatzem
|
|
orderDateDelivery: Quin dia vols rebre la comanda?
|
|
howDoYouWantToReceive: Com vols rebre la comanda?
|
|
confirmData: Confirma les dades
|
|
arrival: Arribada
|
|
orderUpdated: Comanda actualitzada
|
|
pleaseSelectAnOption: Si us plau tria una opció
|
|
pleaseSelectADate: Si us plau tria una data
|
|
pleaseSelectAnAddress: Si us plau tria una adreça
|
|
pleaseSelectAnAgency: Si us plau tria una agència
|
|
pickupWarehouse: En quin magatzem vols recollir la comanda?
|
|
noWarehousesAvailableForDate: No hi ha magatzems disponibles per a la data seleccionada, comprova la data de recollida de la comanda i que consignatari seleccionat conté una província i codi postal correctes
|
|
noAgeciesAvailableForDate: No hi ha agències disponibles per a la data i el consignatari seleccionats, comprova la data de la comanda i que consignatari seleccionat conté una província i codi postal correctes
|
|
pleaseSelectAWarehouse: Si us plau tria un magatzem
|
|
warehouse: Magatzem
|
|
pickup: Recollida
|
|
addressStepQuestion: On vols rebre la comanda?
|
|
addressStepQuestionPickup: A què direcció vols associar la comanda? (Opcional)
|
|
fr-FR:
|
|
receiveOrPickOrder: Voulez-vous recevoir ou récuperer l'ordre?
|
|
receiveOrder: Livraison à la boutique
|
|
pickupInStore: Récupérer en entrepôt
|
|
orderDateDelivery: Date de livraison?
|
|
howDoYouWantToReceive: Agence de livraison
|
|
confirmData: Confirmez les coordonnées
|
|
arrival: Arrivée
|
|
orderUpdated: Mise à jour commande
|
|
pleaseSelectAnOption: Veuillez choisir une option
|
|
pleaseSelectADate: Veuillez choisir une date
|
|
pleaseSelectAnAddress: Veuillez choisir une adresse
|
|
pleaseSelectAnAgency: Veuillez choisir une agence
|
|
pickupWarehouse: Dans quel magasin vuoulez-vous retirer votre commande?
|
|
noWarehousesAvailableForDate: Pas de magasins disponibles à la date sélectionnée, changer la date de retrait et vérifier quel destinataire a été sélectionné contient une province et un code postal correct
|
|
noAgeciesAvailableForDate: Aucune agence disponibles pour la date et le destinataire sélectionné, changer la date d'envoi de la commande et vérifier quel destinataire a été sélectionné contient une province et un code postal correct
|
|
pleaseSelectAWarehouse: Veuillez choisir un entrepôt
|
|
warehouse: Entrepôt
|
|
pickup: Retrait
|
|
addressStepQuestion: Adresse livraison?
|
|
addressStepQuestionPickup: À quelle adresse voulez-vous associer la commande? (Optionnel)
|
|
pt-PT:
|
|
receiveOrPickOrder: Queres receber ou levantar a encomenda?
|
|
receiveOrder: Receber na minha loja
|
|
pickupInStore: Levantar no armazém
|
|
orderDateDelivery: Como queres receber a encomenda?
|
|
confirmData: Confirme os dados
|
|
arrival: Chegada
|
|
orderUpdated: Encomenda actualizada
|
|
pleaseSelectAnOption: Por favor, escolha uma opção
|
|
pleaseSelectADate: Por favor, escolha uma data
|
|
pleaseSelectAnAddress: Por favor, escolha um endereço
|
|
pleaseSelectAnAgency: Por favor, escolha uma agência
|
|
pickupWarehouse: Em qual armazém queres levantar a encomenda?
|
|
noWarehousesAvailableForDate: Não há armazéns disponíveis para a data seleccionada, modifique a data para levantar a encomenda e verifique qual destinatário selecionou contém uma província e código postal corretos
|
|
noAgeciesAvailableForDate: Não há agências disponíveis para a data e o consignatario escolhido, modifique a data de envío do pedido e verifique qual destinatário selecionou contém uma província e código postal corretos
|
|
pleaseSelectAWarehouse: Por favor, escolha um armazém
|
|
warehouse: Armazém
|
|
pickup: Recolhida
|
|
addressStepQuestion: Onde queres receber a encomenda?
|
|
addressStepQuestionPickup: Para qual endereço deseja associar o pedido? (Opcional)
|
|
</i18n>
|