refactor(catalog): move box selection into configurator

This commit is contained in:
Ruslan Bakiev
2026-04-03 15:42:51 +07:00
parent fd015ad1b7
commit 2ec5a43ed3

View File

@@ -4,7 +4,7 @@ import { ClientProductsDocument, type ClientProductsQuery } from '~/composables/
import { useClientCart } from '~/composables/useClientCart';
type ProductNode = ClientProductsQuery['clientProducts'][number];
type ParamFieldKey = 'widthMm' | 'lengthM' | 'thicknessMicron' | 'sleeveBrand';
type ParamFieldKey = 'widthMm' | 'lengthM' | 'thicknessMicron' | 'sleeveBrand' | 'quantityPerBox';
type ParamValue = number | string;
type ParsedProduct = ProductNode & {
@@ -23,15 +23,17 @@ type GroupState = {
lengthM: number | null;
thicknessMicron: number | null;
sleeveBrand: string | null;
quantityPerBox: string | null;
isExpanded: boolean;
};
const PARAM_KEYS: ParamFieldKey[] = ['widthMm', 'lengthM', 'thicknessMicron', 'sleeveBrand'];
const PARAM_KEYS: ParamFieldKey[] = ['widthMm', 'lengthM', 'thicknessMicron', 'sleeveBrand', 'quantityPerBox'];
const parameterFields: Array<{ key: ParamFieldKey; label: string }> = [
{ key: 'widthMm', label: 'Ширина' },
{ key: 'lengthM', label: 'Длина' },
{ key: 'thicknessMicron', label: 'Толщина' },
{ key: 'sleeveBrand', label: 'Втулка' },
{ key: 'quantityPerBox', label: 'Короб' },
];
const coverPresets = [
@@ -177,6 +179,13 @@ function getAllFieldOptions(group: ProductGroup, field: ParamFieldKey) {
const values = new Set<ParamValue>();
for (const product of group.products) {
if (field === 'quantityPerBox') {
for (const option of product.quantityPerBoxOptions) {
values.add(option);
}
continue;
}
const value = product[field];
if (value !== null && value !== undefined) {
values.add(value);
@@ -202,6 +211,7 @@ function createGroupState(group: ProductGroup): GroupState {
lengthM: firstProduct?.lengthM ?? null,
thicknessMicron: firstProduct?.thicknessMicron ?? null,
sleeveBrand: firstProduct?.sleeveBrand ?? null,
quantityPerBox: firstProduct?.quantityPerBoxOptions[0] ?? null,
isExpanded: false,
};
}
@@ -230,7 +240,17 @@ function getGroupState(group: ProductGroup) {
}
function matchesProductState(product: ParsedProduct, state: GroupState, keys: ParamFieldKey[]) {
return keys.every((key) => state[key] === null || product[key] === state[key]);
return keys.every((key) => {
if (state[key] === null) {
return true;
}
if (key === 'quantityPerBox') {
return product.quantityPerBoxOptions.includes(String(state[key]));
}
return product[key] === state[key];
});
}
function matchingProducts(group: ProductGroup) {
@@ -254,22 +274,6 @@ function selectedProduct(group: ProductGroup) {
return matches.length === 1 ? matches[0] : null;
}
function boxQuantityLabel(group: ProductGroup) {
const product = selectedProduct(group);
if (product?.quantityPerBoxOptions.length) {
return product.quantityPerBoxOptions.join(' / ');
}
const values = new Set<string>();
for (const item of group.products) {
for (const option of item.quantityPerBoxOptions) {
values.add(option);
}
}
return sortParamValues([...values]).join(' / ') || '—';
}
function formatOptionLabel(field: ParamFieldKey, value: ParamValue) {
if (field === 'widthMm') {
return `${value} мм`;
@@ -311,6 +315,7 @@ function updateField(group: ProductGroup, field: ParamFieldKey, value: ParamValu
state.lengthM = fallback.lengthM ?? null;
state.thicknessMicron = fallback.thicknessMicron ?? null;
state.sleeveBrand = fallback.sleeveBrand ?? null;
state.quantityPerBox = fallback.quantityPerBoxOptions[0] ?? null;
}
function articleLabel(group: ProductGroup) {
@@ -439,15 +444,13 @@ function decrementSelected(group: ProductGroup) {
<aside class="rounded-[28px] bg-base-100 p-4 md:p-5 xl:col-span-1">
<div class="flex h-full flex-col justify-between gap-4">
<div class="space-y-3">
<p class="text-xs font-semibold uppercase tracking-[0.18em] text-base-content/45">Артикул</p>
<p class="text-xl font-bold text-[#163624]">{{ articleLabel(group) }}</p>
<p class="text-xs leading-5 text-base-content/65">Короб: {{ boxQuantityLabel(group) }}</p>
</div>
<div class="space-y-3">
<button
v-if="selectedQty(group) === 0"
class="btn btn-success h-11 w-full rounded-full border-0 text-sm font-semibold text-success-content"
class="btn h-11 w-full rounded-full border-0 bg-[#139957] text-sm font-semibold text-white hover:bg-[#0d854a]"
:disabled="!selectedProduct(group)"
@click="incrementSelected(group)"
>