refactor(catalog): compact group card with visual toggles and bottom accordion
This commit is contained in:
@@ -308,6 +308,14 @@ function formatOptionLabel(field: ParamFieldKey, value: ParamValue) {
|
|||||||
return String(value);
|
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) {
|
function incrementProduct(product: ProductNode) {
|
||||||
if (getQuantity(product.id) === 0) {
|
if (getQuantity(product.id) === 0) {
|
||||||
addProduct({
|
addProduct({
|
||||||
@@ -376,17 +384,48 @@ function decrementSelected(group: ProductGroup) {
|
|||||||
:key="group.key"
|
:key="group.key"
|
||||||
class="surface-card rounded-3xl p-4 md:p-5"
|
class="surface-card rounded-3xl p-4 md:p-5"
|
||||||
>
|
>
|
||||||
<div class="flex flex-wrap items-center justify-between gap-3">
|
<div class="flex flex-wrap items-center gap-3">
|
||||||
<div class="flex items-center gap-3">
|
<h2 class="text-xl font-bold text-[#133826]">{{ group.typeLabel }}</h2>
|
||||||
<h2 class="text-xl font-bold text-[#133826]">{{ group.typeLabel }}</h2>
|
<span class="badge badge-outline">{{ group.products.length }} вариантов</span>
|
||||||
<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>
|
</div>
|
||||||
|
|
||||||
<div class="mt-4 grid gap-4 xl:grid-cols-[1fr_340px]">
|
<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-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="space-y-4">
|
||||||
<div class="grid gap-3 md:grid-cols-2 2xl:grid-cols-3">
|
<div class="grid gap-3 md:grid-cols-2 2xl:grid-cols-3">
|
||||||
<div
|
<div
|
||||||
@@ -411,41 +450,6 @@ function decrementSelected(group: ProductGroup) {
|
|||||||
|
|
||||||
<p class="text-sm text-base-content/70">Совпадающих вариантов: {{ matchingCount(group) }}</p>
|
<p class="text-sm text-base-content/70">Совпадающих вариантов: {{ matchingCount(group) }}</p>
|
||||||
</div>
|
</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>
|
||||||
|
|
||||||
<div v-if="getGroupState(group).isExpanded" class="mt-4 overflow-x-auto rounded-2xl bg-base-100 p-2">
|
<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>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</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>
|
</article>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user