init
This commit is contained in:
@@ -0,0 +1,188 @@
|
||||
<template>
|
||||
<el-card v-if="hasManualLines" shadow="never">
|
||||
<template #header>
|
||||
<span>Manual shipping payment</span>
|
||||
</template>
|
||||
|
||||
<template v-if="canSetDeliveryCost">
|
||||
<div class="mb-16">
|
||||
<el-alert
|
||||
type="warning"
|
||||
title="Shipping quote required"
|
||||
description="Publish a shipping quote to create the delivery payment session for the buyer. Until then, they cannot pay for shipping and the order cannot be fulfilled."
|
||||
:closable="false"
|
||||
show-icon
|
||||
/>
|
||||
</div>
|
||||
|
||||
<el-form
|
||||
ref="deliveryCostFormRef"
|
||||
label-position="top"
|
||||
:model="deliveryCostForm"
|
||||
:rules="deliveryCostRules"
|
||||
>
|
||||
<el-form-item :label="`Shipping cost (${order.fiatCurrency})`" prop="deliveryCost">
|
||||
<div class="w-full">
|
||||
<el-input-number
|
||||
v-model="deliveryCostForm.deliveryCost"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
:step="1"
|
||||
class="w-full"
|
||||
@update:model-value="deliveryCostFormRef?.clearValidate('deliveryCost')"
|
||||
/>
|
||||
<p class="secondary-text m-0">Set 0 for free shipping.</p>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-button type="primary" :loading="deliveryCostSaving" @click="submitDeliveryCost">
|
||||
Publish shipping quote
|
||||
</el-button>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<template v-else-if="quoted">
|
||||
<el-descriptions :column="1" class="mb-16 descriptions-row-labels">
|
||||
<el-descriptions-item label="Shipping cost">
|
||||
{{ formatFiatPrice(order.totals.shippingCostFiat ?? 0, order.fiatCurrency) }}
|
||||
</el-descriptions-item>
|
||||
|
||||
<el-descriptions-item v-if="order.shippingInvoice" label="Payment expires">
|
||||
{{ formatDate(order.shippingInvoice.expiresAt) }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
<template v-if="order.shippingInvoice">
|
||||
<order-monero-payment-panel
|
||||
:invoice="order.shippingInvoice"
|
||||
rate-label="quote"
|
||||
empty-text="Shipping payment session not created yet."
|
||||
/>
|
||||
</template>
|
||||
|
||||
<p v-else class="secondary-text m-0">Free shipping — no payment required.</p>
|
||||
</template>
|
||||
|
||||
<el-alert
|
||||
v-else-if="order.failureReason"
|
||||
type="error"
|
||||
title="Shipping quote unavailable"
|
||||
:description="failureReasonDescription"
|
||||
:closable="false"
|
||||
show-icon
|
||||
/>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, reactive, ref, type PropType } from 'vue';
|
||||
import type { FormInstance, FormRules } from 'element-plus';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import { useOrdersStore } from '@/stores/orders';
|
||||
import type { OrderExtended } from '@/types/order/OrderExtended';
|
||||
import { DeliveryMode } from '@/types/product/DeliveryMode';
|
||||
import { formatDate } from '@/utils/formatDate';
|
||||
import { formatFiatPrice } from '@/utils/formatFiatPrice';
|
||||
import { formatOrderFailureReason } from '@/utils/order/formatOrderFailureReason';
|
||||
import { isSet } from '@/utils/isSet';
|
||||
import { resolveAxiosErrorMessage } from '@/utils/resolveAxiosErrorMessage';
|
||||
|
||||
const props = defineProps({
|
||||
order: {
|
||||
type: Object as PropType<OrderExtended>,
|
||||
required: true
|
||||
}
|
||||
});
|
||||
|
||||
const { setDeliveryCost } = useOrdersStore();
|
||||
|
||||
const deliveryCostSaving = ref(false);
|
||||
const deliveryCostFormRef = ref<FormInstance>();
|
||||
|
||||
const deliveryCostForm = reactive({
|
||||
deliveryCost: 0
|
||||
});
|
||||
|
||||
const quoted = computed(() => isSet(props.order.quotedAt));
|
||||
|
||||
const hasManualLines = computed(() =>
|
||||
(props.order.lines ?? []).some(line => line.deliveryMode === DeliveryMode.Manual)
|
||||
);
|
||||
|
||||
const canSetDeliveryCost = computed(() => !props.order.failureReason && !quoted.value && hasManualLines.value);
|
||||
|
||||
const failureReasonDescription = computed(() => {
|
||||
if (!props.order.failureReason) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const reason = formatOrderFailureReason(props.order.failureReason);
|
||||
|
||||
return `This order cannot be fulfilled (${reason}). A shipping quote cannot be published.`;
|
||||
});
|
||||
|
||||
const deliveryCostRules = computed<FormRules>(() => ({
|
||||
deliveryCost: [
|
||||
{
|
||||
required: true,
|
||||
message: 'Shipping cost is required',
|
||||
trigger: 'change'
|
||||
}
|
||||
]
|
||||
}));
|
||||
|
||||
const submitDeliveryCost = async () => {
|
||||
const formEl = deliveryCostFormRef.value;
|
||||
|
||||
if (!formEl) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await formEl.validate();
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
|
||||
const deliveryCost = deliveryCostForm.deliveryCost;
|
||||
|
||||
const formattedCost = formatFiatPrice(deliveryCost, props.order.fiatCurrency);
|
||||
|
||||
const buyerImpactNote =
|
||||
deliveryCost > 0
|
||||
? 'This will create a payment session for the buyer.'
|
||||
: 'This will publish the quote for the buyer; no payment is required for free shipping.';
|
||||
|
||||
try {
|
||||
await ElMessageBox.confirm(
|
||||
`You are about to set the shipping quote to ${formattedCost}. ${buyerImpactNote} This cannot be undone. Ensure the quote is correct.`,
|
||||
'Publish shipping quote',
|
||||
{
|
||||
type: 'warning',
|
||||
confirmButtonText: 'Publish',
|
||||
cancelButtonText: 'Cancel'
|
||||
}
|
||||
);
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
|
||||
deliveryCostSaving.value = true;
|
||||
|
||||
try {
|
||||
await setDeliveryCost(props.order.id, {
|
||||
deliveryCost
|
||||
});
|
||||
|
||||
ElMessage.success('Shipping quote published.');
|
||||
} catch (error) {
|
||||
const fallback = 'Could not publish shipping quote.';
|
||||
|
||||
const message = resolveAxiosErrorMessage(error, fallback);
|
||||
|
||||
ElMessage.error(message);
|
||||
} finally {
|
||||
deliveryCostSaving.value = false;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
Reference in New Issue
Block a user