From e8ff766c24584da264640f91c0e281910f04483a Mon Sep 17 00:00:00 2001 From: Ruslan Bakiev <572431+veikab@users.noreply.github.com> Date: Thu, 9 Apr 2026 19:47:50 +0700 Subject: [PATCH] Refine catalog detail interactions --- .../catalog/CatalogConfigurator.vue | 188 ++++++++++-------- 1 file changed, 110 insertions(+), 78 deletions(-) diff --git a/app/components/catalog/CatalogConfigurator.vue b/app/components/catalog/CatalogConfigurator.vue index 2960a51..2aa3bfa 100644 --- a/app/components/catalog/CatalogConfigurator.vue +++ b/app/components/catalog/CatalogConfigurator.vue @@ -484,40 +484,40 @@ function fieldHelperText(group: ProductGroup, field: ParamFieldKey) { const setting = groupCatalogSetting(group); if (field === 'widthMm') { - return 'Нужная ширина рулона.'; + return 'Ширина определяет, насколько широкой будет полоса материала в работе и при намотке.'; } if (field === 'lengthM') { const customRange = formatLengthRange(setting); if (setting.allowCustomLength && customRange) { - return `Можно выбрать стандартный метраж или свой: ${customRange}.`; + return `Можно выбрать стандартный метраж из наличия или заказать свой вариант. Доступный диапазон: ${customRange}.`; } - return 'Нужный метраж рулона.'; + return 'Длина показывает, сколько метров материала будет в одном рулоне.'; } if (field === 'thicknessMicron') { - return 'Плотность и толщина материала.'; + return 'Толщина влияет на плотность, прочность и общее ощущение материала в работе.'; } if (field === 'sleeveBrand') { if (setting.allowCustomSleeveBrand) { - return 'Стандартная втулка или своя с логотипом.'; + return 'Можно выбрать стандартную втулку или сделать свою с логотипом под заказ.'; } - return 'Вариант втулки внутри рулона.'; + return 'Втулка находится внутри рулона и влияет на совместимость с вашим оборудованием.'; } if (field === 'colorTag') { - return 'Цвет ленты.'; + return 'Цвет нужен для визуального отличия, маркировки и внешнего вида готового рулона.'; } if (field === 'labelTag') { if (setting.allowCustomLabel) { - return 'Стандартная маркировка или своя надпись.'; + return 'Можно взять стандартную маркировку из каталога или нанести свою надпись.'; } - return 'Готовая надпись или маркировка.'; + return 'Надпись или маркировка помогает сразу выбрать нужный готовый вариант.'; } return 'Параметр товара.'; @@ -543,29 +543,41 @@ function customizationDetails(group: ProductGroup) { return details; } -function productBadges(product: ParsedProduct) { - const badges: string[] = []; +function totalAvailableQty(product: ParsedProduct) { + return product.availableInWarehouses.reduce((sum, balance) => sum + Number(balance.availableQty || 0), 0); +} - if (product.widthMm !== null) { - badges.push(`${product.widthMm} мм`); +function warehouseAvailability(product: ParsedProduct) { + return product.availableInWarehouses + .filter((balance) => Number(balance.availableQty || 0) > 0) + .map((balance) => `${balance.warehouse.code}: ${balance.availableQty}`) + .join(' · '); +} + +function availabilityTone(product: ParsedProduct) { + const qty = totalAvailableQty(product); + + if (qty <= 0) { + return 'bg-[#d95c5c]'; } - if (product.lengthM !== null) { - badges.push(`${product.lengthM} м`); - } - if (product.thicknessMicron !== null) { - badges.push(`${product.thicknessMicron} мкм`); - } - if (product.sleeveBrand) { - badges.push(product.sleeveBrand); - } - if (product.colorTags[0]) { - badges.push(product.colorTags[0]); - } - if (product.labelTags[0]) { - badges.push(product.labelTags[0]); + if (qty < 20) { + return 'bg-[#e2b534]'; } - return badges; + return 'bg-[#2aa36b]'; +} + +function availabilityLabel(product: ParsedProduct) { + const qty = totalAvailableQty(product); + + if (qty <= 0) { + return 'Нет в наличии'; + } + if (qty < 20) { + return 'Остаток ограничен'; + } + + return 'В наличии'; } function incrementProduct(product: ProductNode) { @@ -618,7 +630,7 @@ function productDetailPath(group: ProductGroup) {