refactor(catalog): compact group card with visual toggles and bottom accordion

This commit is contained in:
Ruslan Bakiev
2026-04-03 12:35:28 +07:00
parent 04e2f78086
commit d2c5ee600f

View File

@@ -308,6 +308,14 @@ function formatOptionLabel(field: ParamFieldKey, value: ParamValue) {
return String(value);
}
function selectedFieldValue(group: ProductGroup, field: ParamFieldKey) {
const value = getGroupState(group)[field];
if (value === null) {
return '—';
}
return formatOptionLabel(field, value);
}
function incrementProduct(product: ProductNode) {
if (getQuantity(product.id) === 0) {
addProduct({
@@ -376,17 +384,48 @@ function decrementSelected(group: ProductGroup) {
:key="group.key"
class="surface-card rounded-3xl p-4 md:p-5"
>
<div class="flex flex-wrap items-center justify-between gap-3">
<div class="flex items-center gap-3">
<div class="flex flex-wrap items-center gap-3">
<h2 class="text-xl font-bold text-[#133826]">{{ group.typeLabel }}</h2>
<span class="badge badge-outline">{{ group.products.length }} вариантов</span>
</div>
<button class="btn btn-ghost btn-sm" @click="toggleExpanded(group)">
{{ getGroupState(group).isExpanded ? 'Свернуть таблицу' : 'Показать все варианты' }}
</button>
<div class="mt-4 grid gap-4 xl:grid-cols-[360px_1fr]">
<aside class="rounded-2xl bg-base-100 p-3">
<img
:src="createProductCover(group.typeLabel, group.key)"
:alt="`Превью группы ${group.typeLabel}`"
class="h-56 w-full rounded-2xl object-cover"
loading="lazy"
>
<div class="mt-3 flex flex-wrap gap-2">
<span class="badge badge-neutral">SKU: {{ selectedProduct(group)?.sku ?? '—' }}</span>
<span class="badge badge-outline">Совпадений: {{ matchingCount(group) }}</span>
</div>
<div class="mt-4 grid gap-4 xl:grid-cols-[1fr_340px]">
<div class="mt-3 flex items-center justify-between rounded-2xl border border-base-300 bg-base-100 px-2 py-1">
<button
class="btn btn-square btn-sm"
:disabled="selectedQty(group) === 0"
@click="decrementSelected(group)"
>
-
</button>
<span class="min-w-10 text-center font-semibold">{{ selectedQty(group) }}</span>
<button class="btn btn-square btn-sm" @click="incrementSelected(group)">+</button>
</div>
<div class="mt-3 flex flex-wrap gap-2">
<span
v-for="field in parameterFields"
:key="`selected-${group.key}-${field.key}`"
class="badge badge-outline"
>
{{ field.label }}: {{ selectedFieldValue(group, field.key) }}
</span>
</div>
</aside>
<div class="space-y-4">
<div class="grid gap-3 md:grid-cols-2 2xl:grid-cols-3">
<div
@@ -411,41 +450,6 @@ function decrementSelected(group: ProductGroup) {
<p class="text-sm text-base-content/70">Совпадающих вариантов: {{ matchingCount(group) }}</p>
</div>
<aside class="rounded-2xl bg-base-100 p-4">
<p class="text-xs font-semibold uppercase tracking-wide text-base-content/60">Выбранная позиция</p>
<template v-if="selectedProduct(group)">
<div class="mt-2 flex items-start gap-3">
<img
:src="createProductCover(selectedProduct(group)!.name, selectedProduct(group)!.sku)"
:alt="`Превью ${selectedProduct(group)!.sku}`"
class="h-16 w-16 rounded-xl object-cover"
loading="lazy"
>
<div class="min-w-0">
<p class="text-sm font-semibold text-[#133826]">{{ selectedProduct(group)?.name }}</p>
<p class="mt-1 text-xs text-base-content/65">SKU: {{ selectedProduct(group)?.sku }}</p>
</div>
</div>
<div class="mt-4 flex items-center justify-between rounded-2xl border border-base-300 bg-base-100 px-2 py-1">
<button
class="btn btn-square btn-sm"
:disabled="selectedQty(group) === 0"
@click="decrementSelected(group)"
>
-
</button>
<span class="min-w-10 text-center font-semibold">{{ selectedQty(group) }}</span>
<button class="btn btn-square btn-sm" @click="incrementSelected(group)">+</button>
</div>
</template>
<p v-else class="mt-2 text-sm text-base-content/70">
Нет точного совпадения. Измените параметры или раскройте полный список вариантов.
</p>
</aside>
</div>
<div v-if="getGroupState(group).isExpanded" class="mt-4 overflow-x-auto rounded-2xl bg-base-100 p-2">
@@ -489,6 +493,22 @@ function decrementSelected(group: ProductGroup) {
</tbody>
</table>
</div>
<button
class="btn btn-ghost mt-3 w-full justify-center gap-2"
@click="toggleExpanded(group)"
>
<svg
class="h-4 w-4 transition-transform"
:class="{ 'rotate-180': getGroupState(group).isExpanded }"
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M5 7.5L10 12.5L15 7.5" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" />
</svg>
<span>{{ getGroupState(group).isExpanded ? 'Свернуть все варианты' : 'Развернуть все варианты' }}</span>
</button>
</article>
</div>