This commit is contained in:
2026-08-28 17:31:02 +02:00
commit 2b30e8bd39
694 changed files with 49243 additions and 0 deletions
+186
View File
@@ -0,0 +1,186 @@
<template>
<el-card class="order-summary-panel" shadow="never">
<template #header>
<span>Summary</span>
</template>
<el-descriptions :column="1" direction="vertical" class="order-summary-panel__details">
<el-descriptions-item label="Order ID">
<span class="mono text-break">{{ order.id }}</span>
</el-descriptions-item>
<el-descriptions-item label="Access token">
<el-input
class="mono access-token-input"
:model-value="order.accessToken"
type="password"
show-password
readonly
/>
</el-descriptions-item>
<el-descriptions-item label="Created">{{ formatDate(order.createdAt) }}</el-descriptions-item>
<el-descriptions-item v-if="order.failureReason" label="Failure reason">
<span class="failure-reason">{{ formatOrderFailureReason(order.failureReason) }}</span>
</el-descriptions-item>
</el-descriptions>
<div class="order-summary-panel__totals order-totals pt-24">
<div class="flex justify-between gap-12 mb-12">
<span>Subtotal</span>
<span>{{ subtotalFormatted }}</span>
</div>
<p v-if="discounts.length > 0" class="order-totals__section m-0 mb-8">Discounts</p>
<div
v-for="discount in discounts"
:key="discount.id"
class="flex justify-between gap-12 mb-4 order-totals__discount"
>
<span>{{ discount.code }}</span>
<span>{{ formatFiatPrice(discount.amountFiat, fiatCurrency) }}</span>
</div>
<div class="flex justify-between gap-12 mt-12 mb-12">
<span>Total discounts</span>
<span>{{ discountTotalFormatted }}</span>
</div>
<template v-if="hasManualLines">
<div class="flex justify-between gap-12 mt-12 mb-12 order-totals__order-total">
<span>Total</span>
<span>{{ totalFormatted }}</span>
</div>
<div class="flex justify-between gap-12 mb-12">
<span>Shipping</span>
<span>{{ shippingFormatted }}</span>
</div>
<div class="flex justify-between gap-12 order-totals__total pt-8">
<span>Grand total</span>
<span>{{ grandTotalFormatted }}</span>
</div>
</template>
<div v-else class="flex justify-between gap-12 order-totals__total pt-8 mt-12">
<span>Total</span>
<span>{{ totalFormatted }}</span>
</div>
</div>
</el-card>
</template>
<script setup lang="ts">
import { computed, type PropType } from 'vue';
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';
const props = defineProps({
order: {
type: Object as PropType<OrderExtended>,
required: true
}
});
const fiatCurrency = computed(() => props.order.fiatCurrency);
const discounts = computed(() => props.order.discounts ?? []);
const hasManualLines = computed(() =>
(props.order.lines ?? []).some(line => line.deliveryMode === DeliveryMode.Manual)
);
const subtotalFormatted = computed(() => formatFiatPrice(props.order.totals.subtotalFiat, fiatCurrency.value));
const discountTotalFormatted = computed(() =>
formatOrderDiscountTotal(props.order.totals.discountTotalFiat, fiatCurrency.value)
);
const totalFormatted = computed(() => formatFiatPrice(props.order.totals.totalFiat, fiatCurrency.value));
const shippingFormatted = computed(() => {
const shippingAmount = props.order.totals.shippingCostFiat;
if (shippingAmount === null) {
return '—';
}
return formatFiatPrice(shippingAmount, fiatCurrency.value);
});
const grandTotalFormatted = computed(() => {
const grandTotal = props.order.totals.grandTotalFiat ?? props.order.totals.totalFiat;
return formatFiatPrice(grandTotal, fiatCurrency.value);
});
const formatOrderDiscountTotal = (discountTotalFiat: number, currency: string): string => {
if (discountTotalFiat <= 0) {
return formatFiatPrice(0, currency);
}
return `${formatFiatPrice(discountTotalFiat, currency)}`;
};
</script>
<style scoped lang="scss">
.order-summary-panel {
height: 100%;
display: flex;
flex-direction: column;
:deep(.el-card__body) {
flex: 1;
display: flex;
flex-direction: column;
min-height: 0;
}
}
.order-summary-panel__details {
flex-shrink: 0;
:deep(.el-descriptions__content) {
min-width: 0;
}
}
.order-summary-panel__totals {
flex-shrink: 0;
margin-top: auto;
}
.access-token-input {
width: 100%;
max-width: min(350px, 100%);
}
.failure-reason {
color: var(--el-color-danger);
}
.order-totals__section {
color: var(--el-text-color-secondary);
}
.order-totals__discount {
color: var(--el-text-color-secondary);
font-size: var(--el-font-size-small);
}
.order-totals__order-total {
font-weight: 600;
}
.order-totals__total {
font-size: var(--el-font-size-large);
font-weight: 600;
border-top: 1px solid var(--el-border-color-lighter);
}
</style>