Files
web-frontend/app/components/orders/OrderSummaryCard.vue
2026-04-06 11:12:10 +07:00

101 lines
3.3 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup lang="ts">
import OrderStatusBadge from '~/components/orders/OrderStatusBadge.vue';
import { formatOrderCode } from '~/composables/useOrderCodePresentation';
import { formatPrice } from '~/composables/useOrderDetailPresentation';
type OrderCardItem = {
id: string;
productName: string;
quantity: number;
};
const props = defineProps<{
to: string;
code: string;
status: string;
createdAt: string | Date;
totalPrice?: number | null;
items: OrderCardItem[];
}>();
const DATE_FORMATTER = new Intl.DateTimeFormat('ru-RU', {
day: '2-digit',
month: 'short',
hour: '2-digit',
minute: '2-digit',
});
const coverPresets = ['#edf3ef', '#f1f4ee', '#edf2f4'];
function formatCreatedAt(value: string | Date) {
return DATE_FORMATTER.format(new Date(value));
}
function createProductCover(name: string, seedKey: string) {
const seed = `${name}${seedKey}`.split('').reduce((acc, char) => acc + char.charCodeAt(0), 0);
const background = coverPresets[seed % coverPresets.length];
const firstLetter = name.trim().charAt(0).toUpperCase() || 'P';
const svg = `
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 88 88">
<rect width="88" height="88" fill="${background}" rx="24" />
<text x="50%" y="56%" text-anchor="middle" fill="#11412c" font-family="Manrope, sans-serif" font-size="34" font-weight="700">${firstLetter}</text>
</svg>
`.trim();
return `data:image/svg+xml;utf8,${encodeURIComponent(svg)}`;
}
const visibleItems = computed(() => props.items.slice(0, 4));
const hiddenCount = computed(() => Math.max(props.items.length - visibleItems.value.length, 0));
const totalPriceLabel = computed(() => formatPrice(props.totalPrice) ?? '—');
const codeLabel = computed(() => formatOrderCode(props.code));
</script>
<template>
<NuxtLink
:to="to"
class="surface-card surface-card-interactive group block rounded-[30px] bg-white px-4 py-4 md:px-5"
>
<div class="grid gap-4 md:grid-cols-4 md:items-center md:gap-6">
<div class="min-w-0">
<h2 class="truncate text-lg font-bold text-[#123824]">{{ codeLabel }}</h2>
<p class="mt-1 text-sm text-[#688676]">{{ formatCreatedAt(createdAt) }}</p>
</div>
<div class="min-w-0">
<div class="flex flex-wrap items-center gap-2 md:gap-1">
<div class="flex -space-x-3">
<div
v-for="item in visibleItems"
:key="item.id"
class="h-11 w-11 overflow-hidden rounded-[16px] bg-[#edf3ef]"
:title="`${item.productName} × ${item.quantity}`"
>
<img
:src="createProductCover(item.productName, item.id)"
:alt="item.productName"
class="h-full w-full object-cover"
>
</div>
</div>
<div
v-if="hiddenCount > 0"
class="flex h-11 w-11 items-center justify-center rounded-[16px] bg-[#edf3ef] text-xs font-bold text-[#123824]"
>
+{{ hiddenCount }}
</div>
</div>
</div>
<div class="flex items-center md:justify-center">
<OrderStatusBadge :status="status" />
</div>
<div class="text-left md:text-right">
<p class="text-base font-bold text-[#123824]">{{ totalPriceLabel }}</p>
</div>
</div>
</NuxtLink>
</template>