Redesign catalog product detail page
This commit is contained in:
@@ -484,43 +484,43 @@ 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 'Выберите подходящий параметр для этой позиции.';
|
||||
return 'Параметр товара.';
|
||||
}
|
||||
|
||||
function customizationDetails(group: ProductGroup) {
|
||||
@@ -543,6 +543,44 @@ function customizationDetails(group: ProductGroup) {
|
||||
return details;
|
||||
}
|
||||
|
||||
function selectedSummary(group: ProductGroup) {
|
||||
return visibleFields(group)
|
||||
.map((field) => {
|
||||
const value = getGroupState(group)[field.key];
|
||||
if (value === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return `${field.label}: ${formatOptionLabel(field.key, value)}`;
|
||||
})
|
||||
.filter((item): item is string => Boolean(item));
|
||||
}
|
||||
|
||||
function productBadges(product: ParsedProduct) {
|
||||
const badges: string[] = [];
|
||||
|
||||
if (product.widthMm !== null) {
|
||||
badges.push(`Ширина: ${product.widthMm} мм`);
|
||||
}
|
||||
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]}`);
|
||||
}
|
||||
|
||||
return badges;
|
||||
}
|
||||
|
||||
function incrementProduct(product: ProductNode) {
|
||||
if (getQuantity(product.id) === 0) {
|
||||
addProduct({
|
||||
@@ -589,194 +627,261 @@ function productDetailPath(group: ProductGroup) {
|
||||
<section class="space-y-5">
|
||||
<div v-if="loading" class="alert surface-card border-0">Загрузка каталога...</div>
|
||||
<div v-else-if="error" class="alert alert-error">{{ error.message }}</div>
|
||||
<div v-else-if="selectedGroup" class="space-y-4">
|
||||
<div v-else-if="selectedGroup" class="relative mx-auto max-w-[1380px] px-1 pb-10 sm:px-0">
|
||||
<NuxtLink
|
||||
v-if="previousGroup"
|
||||
:to="productDetailPath(previousGroup)"
|
||||
class="fixed left-6 top-1/2 z-10 hidden h-12 w-12 -translate-y-1/2 items-center justify-center rounded-full border border-[#dce9e1] bg-white text-xl text-[#163624] shadow-[0_12px_28px_rgba(18,56,36,0.08)] 2xl:flex"
|
||||
aria-label="Предыдущий товар"
|
||||
class="absolute left-0 top-28 z-10 hidden w-44 -translate-x-[72%] rounded-[28px] border border-[#e6efe9] bg-white p-3 shadow-[0_20px_40px_rgba(18,56,36,0.08)] transition hover:-translate-x-[76%] hover:shadow-[0_28px_48px_rgba(18,56,36,0.12)] 2xl:block"
|
||||
>
|
||||
←
|
||||
<img
|
||||
:src="createProductCover(previousGroup.typeLabel, previousGroup.key)"
|
||||
:alt="`Перейти к товару ${previousGroup.typeLabel}`"
|
||||
class="aspect-square w-full rounded-[20px] object-cover"
|
||||
loading="lazy"
|
||||
>
|
||||
<p class="mt-3 text-sm font-semibold leading-5 text-[#163624]">{{ previousGroup.typeLabel }}</p>
|
||||
</NuxtLink>
|
||||
|
||||
<NuxtLink
|
||||
v-if="nextGroup"
|
||||
:to="productDetailPath(nextGroup)"
|
||||
class="fixed right-6 top-1/2 z-10 hidden h-12 w-12 -translate-y-1/2 items-center justify-center rounded-full border border-[#dce9e1] bg-white text-xl text-[#163624] shadow-[0_12px_28px_rgba(18,56,36,0.08)] 2xl:flex"
|
||||
aria-label="Следующий товар"
|
||||
class="absolute right-0 top-28 z-10 hidden w-44 translate-x-[72%] rounded-[28px] border border-[#e6efe9] bg-white p-3 shadow-[0_20px_40px_rgba(18,56,36,0.08)] transition hover:translate-x-[76%] hover:shadow-[0_28px_48px_rgba(18,56,36,0.12)] 2xl:block"
|
||||
>
|
||||
→
|
||||
<img
|
||||
:src="createProductCover(nextGroup.typeLabel, nextGroup.key)"
|
||||
:alt="`Перейти к товару ${nextGroup.typeLabel}`"
|
||||
class="aspect-square w-full rounded-[20px] object-cover"
|
||||
loading="lazy"
|
||||
>
|
||||
<p class="mt-3 text-sm font-semibold leading-5 text-[#163624]">{{ nextGroup.typeLabel }}</p>
|
||||
</NuxtLink>
|
||||
|
||||
<div class="flex items-center justify-between gap-3">
|
||||
<NuxtLink to="/products" class="btn btn-ghost rounded-full px-3 text-[#163624]">
|
||||
← Назад
|
||||
<header class="mb-5 flex items-center gap-4 px-3 sm:px-6 xl:px-8">
|
||||
<NuxtLink
|
||||
to="/products"
|
||||
class="inline-flex h-11 w-11 shrink-0 items-center justify-center rounded-full border border-[#dce9e1] bg-white text-xl text-[#163624] shadow-[0_10px_24px_rgba(18,56,36,0.06)] transition hover:-translate-y-0.5"
|
||||
aria-label="Назад к списку товаров"
|
||||
>
|
||||
←
|
||||
</NuxtLink>
|
||||
|
||||
<div class="flex items-center gap-2">
|
||||
<NuxtLink
|
||||
v-if="previousGroup"
|
||||
:to="productDetailPath(previousGroup)"
|
||||
class="btn btn-ghost btn-circle"
|
||||
aria-label="Предыдущий товар"
|
||||
>
|
||||
←
|
||||
</NuxtLink>
|
||||
<NuxtLink
|
||||
v-if="nextGroup"
|
||||
:to="productDetailPath(nextGroup)"
|
||||
class="btn btn-ghost btn-circle"
|
||||
aria-label="Следующий товар"
|
||||
>
|
||||
→
|
||||
</NuxtLink>
|
||||
<div class="min-w-0">
|
||||
<h1 class="text-3xl font-bold leading-tight text-[#163624] md:text-[2.5rem]">{{ selectedGroup.typeLabel }}</h1>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="mb-5 grid gap-3 px-3 sm:px-6 2xl:hidden">
|
||||
<NuxtLink
|
||||
v-if="previousGroup"
|
||||
:to="productDetailPath(previousGroup)"
|
||||
class="flex items-center gap-3 rounded-[24px] border border-[#e6efe9] bg-white p-3 shadow-[0_14px_30px_rgba(18,56,36,0.06)]"
|
||||
>
|
||||
<img
|
||||
:src="createProductCover(previousGroup.typeLabel, previousGroup.key)"
|
||||
:alt="`Перейти к товару ${previousGroup.typeLabel}`"
|
||||
class="h-16 w-16 rounded-2xl object-cover"
|
||||
loading="lazy"
|
||||
>
|
||||
<span class="text-sm font-semibold text-[#163624]">{{ previousGroup.typeLabel }}</span>
|
||||
</NuxtLink>
|
||||
|
||||
<NuxtLink
|
||||
v-if="nextGroup"
|
||||
:to="productDetailPath(nextGroup)"
|
||||
class="flex items-center gap-3 rounded-[24px] border border-[#e6efe9] bg-white p-3 shadow-[0_14px_30px_rgba(18,56,36,0.06)]"
|
||||
>
|
||||
<img
|
||||
:src="createProductCover(nextGroup.typeLabel, nextGroup.key)"
|
||||
:alt="`Перейти к товару ${nextGroup.typeLabel}`"
|
||||
class="h-16 w-16 rounded-2xl object-cover"
|
||||
loading="lazy"
|
||||
>
|
||||
<span class="text-sm font-semibold text-[#163624]">{{ nextGroup.typeLabel }}</span>
|
||||
</NuxtLink>
|
||||
</div>
|
||||
|
||||
<div class="space-y-4">
|
||||
<div class="rounded-[28px] border border-[#e6efe9] bg-white p-5 md:p-7">
|
||||
<h1 class="text-3xl font-bold text-[#163624]">{{ selectedGroup.typeLabel }}</h1>
|
||||
|
||||
<div v-if="customizationDetails(selectedGroup).length" class="mt-4 flex flex-wrap gap-2">
|
||||
<span
|
||||
v-for="note in customizationDetails(selectedGroup)"
|
||||
:key="`${selectedGroup.key}-${note}`"
|
||||
class="rounded-full border border-[#dce9e1] bg-white px-3 py-1 text-xs font-semibold text-[#355947]"
|
||||
<div class="grid gap-5 px-3 sm:px-6 xl:grid-cols-[minmax(0,0.92fr)_minmax(0,1.15fr)_320px] xl:px-8">
|
||||
<div class="space-y-4">
|
||||
<div class="overflow-hidden rounded-[32px] border border-[#e6efe9] bg-white p-4 shadow-[0_20px_40px_rgba(18,56,36,0.06)]">
|
||||
<img
|
||||
:src="createProductCover(selectedGroup.typeLabel, articleLabel(selectedGroup))"
|
||||
:alt="selectedGroup.typeLabel"
|
||||
class="aspect-[5/4] w-full rounded-[26px] object-cover"
|
||||
loading="lazy"
|
||||
>
|
||||
{{ note }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="selectedSummary(selectedGroup).length"
|
||||
class="rounded-[28px] border border-[#e6efe9] bg-white p-4 shadow-[0_18px_36px_rgba(18,56,36,0.05)]"
|
||||
>
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<span
|
||||
v-for="item in selectedSummary(selectedGroup)"
|
||||
:key="`${selectedGroup.key}-${item}`"
|
||||
class="rounded-full border border-[#dce9e1] bg-[#f8fbf9] px-3 py-1.5 text-sm font-medium text-[#355947]"
|
||||
>
|
||||
{{ item }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="customizationDetails(selectedGroup).length"
|
||||
class="rounded-[28px] border border-[#dce9e1] bg-[#f7fbf8] p-4"
|
||||
>
|
||||
<div class="space-y-2">
|
||||
<p
|
||||
v-for="note in customizationDetails(selectedGroup)"
|
||||
:key="`${selectedGroup.key}-${note}`"
|
||||
class="text-sm leading-6 text-[#456555]"
|
||||
>
|
||||
{{ note }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="space-y-3">
|
||||
<div class="space-y-4">
|
||||
<article
|
||||
v-for="field in visibleFields(selectedGroup)"
|
||||
:key="`${selectedGroup.key}-${field.key}`"
|
||||
class="rounded-[24px] border border-[#e6efe9] bg-white p-5"
|
||||
class="rounded-[28px] border border-[#e6efe9] bg-white p-5 shadow-[0_18px_36px_rgba(18,56,36,0.05)]"
|
||||
>
|
||||
<div class="space-y-4">
|
||||
<div class="space-y-2">
|
||||
<h2 class="text-lg font-semibold text-[#163624]">{{ field.label }}</h2>
|
||||
<p class="text-sm leading-6 text-[#5d7468]">{{ fieldHelperText(selectedGroup, field.key) }}</p>
|
||||
</div>
|
||||
<p class="text-base font-semibold text-[#163624]">{{ field.label }}</p>
|
||||
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<label
|
||||
v-for="option in getAllFieldOptions(selectedGroup, field.key)"
|
||||
:key="`${selectedGroup.key}-${field.key}-${option}`"
|
||||
class="btn btn-sm rounded-full text-sm normal-case shadow-none transition"
|
||||
:class="[
|
||||
getGroupState(selectedGroup)[field.key] === option
|
||||
? 'bg-neutral text-neutral-content'
|
||||
: isOptionAvailable(selectedGroup, field.key, option)
|
||||
? 'bg-base-100 text-base-content hover:bg-base-200'
|
||||
: 'bg-[#eef1f4] text-[#7b8591] hover:bg-[#e3e7eb]',
|
||||
'cursor-pointer',
|
||||
]"
|
||||
<div class="mt-3 flex flex-wrap gap-2">
|
||||
<label
|
||||
v-for="option in getAllFieldOptions(selectedGroup, field.key)"
|
||||
:key="`${selectedGroup.key}-${field.key}-${option}`"
|
||||
class="cursor-pointer rounded-2xl border px-4 py-2 text-sm font-medium transition"
|
||||
:class="[
|
||||
getGroupState(selectedGroup)[field.key] === option
|
||||
? 'border-[#163624] bg-[#163624] text-white shadow-[0_12px_24px_rgba(22,54,36,0.18)]'
|
||||
: isOptionAvailable(selectedGroup, field.key, option)
|
||||
? 'border-[#dce9e1] bg-white text-[#163624] hover:border-[#163624]'
|
||||
: 'border-[#e6eaee] bg-[#f3f5f7] text-[#8a949d]',
|
||||
]"
|
||||
>
|
||||
<input
|
||||
type="radio"
|
||||
class="sr-only"
|
||||
:name="`${selectedGroup.key}-${field.key}`"
|
||||
:checked="getGroupState(selectedGroup)[field.key] === option"
|
||||
@change="updateField(selectedGroup, field.key, option)"
|
||||
>
|
||||
<input
|
||||
type="radio"
|
||||
class="sr-only"
|
||||
:name="`${selectedGroup.key}-${field.key}`"
|
||||
:checked="getGroupState(selectedGroup)[field.key] === option"
|
||||
@change="updateField(selectedGroup, field.key, option)"
|
||||
>
|
||||
<span>{{ formatOptionLabel(field.key, option) }}</span>
|
||||
</label>
|
||||
<span>{{ formatOptionLabel(field.key, option) }}</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<p class="mt-3 text-sm leading-6 text-[#607569]">{{ fieldHelperText(selectedGroup, field.key) }}</p>
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<aside class="self-start xl:sticky xl:top-24">
|
||||
<div class="rounded-[30px] border border-[#e6efe9] bg-white p-5 shadow-[0_24px_48px_rgba(18,56,36,0.08)]">
|
||||
<p class="text-xs font-semibold uppercase tracking-[0.18em] text-[#789182]">Артикул</p>
|
||||
<p class="mt-2 text-2xl font-bold leading-tight text-[#163624]">{{ articleLabel(selectedGroup) }}</p>
|
||||
|
||||
<div
|
||||
v-if="selectedSummary(selectedGroup).length"
|
||||
class="mt-5 rounded-[24px] border border-[#edf4ef] bg-[#f8fbf9] p-4"
|
||||
>
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<span
|
||||
v-for="item in selectedSummary(selectedGroup)"
|
||||
:key="`${selectedGroup.key}-summary-${item}`"
|
||||
class="rounded-full bg-white px-3 py-1.5 text-xs font-semibold text-[#355947]"
|
||||
>
|
||||
{{ item }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<article class="rounded-[24px] border border-[#e6efe9] bg-white p-5">
|
||||
<div class="space-y-4">
|
||||
<div class="space-y-1">
|
||||
<h2 class="text-lg font-semibold text-[#163624]">В корзину</h2>
|
||||
<p class="text-sm leading-6 text-[#5d7468]">
|
||||
Артикул: <span class="font-semibold text-[#163624]">{{ articleLabel(selectedGroup) }}</span>
|
||||
</p>
|
||||
</div>
|
||||
<button
|
||||
v-if="selectedQty(selectedGroup) === 0"
|
||||
class="btn mt-5 h-12 w-full rounded-full border-0 bg-[#139957] px-6 text-base font-semibold text-white hover:bg-[#0d854a]"
|
||||
:disabled="!selectedProduct(selectedGroup)"
|
||||
@click="incrementSelected(selectedGroup)"
|
||||
>
|
||||
В корзину
|
||||
</button>
|
||||
|
||||
<div
|
||||
v-else
|
||||
class="mt-5 flex items-center justify-between rounded-[24px] border border-[#dce9e1] bg-[#f8fbf9] px-2 py-2"
|
||||
>
|
||||
<button
|
||||
v-if="selectedQty(selectedGroup) === 0"
|
||||
class="btn h-11 rounded-full border-0 bg-[#139957] px-6 text-sm font-semibold text-white hover:bg-[#0d854a]"
|
||||
class="btn btn-square border-0 bg-white text-[#163624] shadow-none hover:bg-white"
|
||||
:disabled="selectedQty(selectedGroup) === 0"
|
||||
@click="decrementSelected(selectedGroup)"
|
||||
>
|
||||
-
|
||||
</button>
|
||||
<div class="min-w-12 text-center text-lg font-semibold text-[#163624]">{{ selectedQty(selectedGroup) }}</div>
|
||||
<button
|
||||
class="btn btn-square border-0 bg-white text-[#163624] shadow-none hover:bg-white"
|
||||
:disabled="!selectedProduct(selectedGroup)"
|
||||
@click="incrementSelected(selectedGroup)"
|
||||
>
|
||||
В корзину
|
||||
+
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
|
||||
<div v-else class="inline-flex rounded-[22px] border border-base-300 bg-base-100 px-2 py-1">
|
||||
<div class="flex items-center justify-between gap-2">
|
||||
<div class="mt-8 px-3 sm:px-6 xl:px-8">
|
||||
<div class="rounded-[32px] border border-[#e6efe9] bg-white p-5 shadow-[0_20px_40px_rgba(18,56,36,0.06)]">
|
||||
<p class="text-base font-semibold text-[#163624]">Доступные варианты</p>
|
||||
|
||||
<div class="mt-4 space-y-3">
|
||||
<article
|
||||
v-for="product in selectedGroup.products"
|
||||
:key="`${selectedGroup.key}-${product.id}`"
|
||||
class="flex flex-col gap-4 rounded-[24px] border border-[#edf4ef] bg-[#fbfcfb] p-4 lg:flex-row lg:items-center lg:justify-between"
|
||||
>
|
||||
<div class="min-w-0">
|
||||
<p class="text-base font-semibold text-[#163624]">{{ product.sku }}</p>
|
||||
|
||||
<div class="mt-3 flex flex-wrap gap-2">
|
||||
<span
|
||||
v-for="badge in productBadges(product)"
|
||||
:key="`${product.id}-${badge}`"
|
||||
class="rounded-full border border-[#dce9e1] bg-white px-3 py-1.5 text-xs font-medium text-[#355947]"
|
||||
>
|
||||
{{ badge }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex shrink-0 items-center justify-end">
|
||||
<button
|
||||
v-if="getQuantity(product.id) === 0"
|
||||
class="btn h-10 rounded-full border-0 bg-[#139957] px-5 text-sm font-semibold text-white hover:bg-[#0d854a]"
|
||||
@click="incrementProduct(product)"
|
||||
>
|
||||
В корзину
|
||||
</button>
|
||||
<div v-else class="ml-auto flex w-32 items-center justify-between rounded-[20px] border border-[#dce9e1] bg-white px-2 py-2">
|
||||
<button
|
||||
class="btn btn-square btn-sm"
|
||||
:disabled="selectedQty(selectedGroup) === 0"
|
||||
@click="decrementSelected(selectedGroup)"
|
||||
class="btn btn-xs btn-square border-0 bg-[#f3f7f4] text-[#163624] shadow-none hover:bg-[#eaf2ec]"
|
||||
:disabled="getQuantity(product.id) === 0"
|
||||
@click="decrementProduct(product.id)"
|
||||
>
|
||||
-
|
||||
</button>
|
||||
<div class="min-w-10 text-center text-lg font-semibold text-[#163624]">{{ selectedQty(selectedGroup) }}</div>
|
||||
<button class="btn btn-square btn-sm" :disabled="!selectedProduct(selectedGroup)" @click="incrementSelected(selectedGroup)">
|
||||
<span class="min-w-8 text-center text-sm font-semibold text-[#163624]">{{ getQuantity(product.id) }}</span>
|
||||
<button
|
||||
class="btn btn-xs btn-square border-0 bg-[#f3f7f4] text-[#163624] shadow-none hover:bg-[#eaf2ec]"
|
||||
@click="incrementProduct(product)"
|
||||
>
|
||||
+
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<article class="rounded-[24px] border border-[#e6efe9] bg-white p-5">
|
||||
<div class="space-y-4">
|
||||
<div class="space-y-1">
|
||||
<h2 class="text-lg font-semibold text-[#163624]">Товар в наличии</h2>
|
||||
<p class="text-sm leading-6 text-[#5d7468]">
|
||||
Все доступные варианты по этому типу товара.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="overflow-x-auto rounded-[20px] border border-[#edf4ef] bg-white">
|
||||
<table class="table border-separate border-spacing-0 bg-white [&_tbody_tr:hover]:bg-white [&_tbody_tr]:bg-white [&_td]:bg-white [&_th]:bg-white [&_thead_tr]:bg-white">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="border-b border-base-300">Артикул</th>
|
||||
<th class="border-b border-base-300">Ширина</th>
|
||||
<th class="border-b border-base-300">Длина</th>
|
||||
<th class="border-b border-base-300">Толщина</th>
|
||||
<th class="border-b border-base-300">Втулка</th>
|
||||
<th class="border-b border-base-300 text-right">Действие</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="product in selectedGroup.products" :key="`${selectedGroup.key}-${product.id}`">
|
||||
<td class="border-b border-base-200">{{ product.sku }}</td>
|
||||
<td class="border-b border-base-200">{{ product.widthMm ?? '—' }}</td>
|
||||
<td class="border-b border-base-200">{{ product.lengthM ?? '—' }}</td>
|
||||
<td class="border-b border-base-200">{{ product.thicknessMicron ?? '—' }}</td>
|
||||
<td class="border-b border-base-200">{{ product.sleeveBrand ?? '—' }}</td>
|
||||
<td class="border-b border-base-200 text-right">
|
||||
<button
|
||||
v-if="getQuantity(product.id) === 0"
|
||||
class="btn h-9 rounded-full border-0 bg-[#139957] px-4 text-xs font-semibold text-white hover:bg-[#0d854a]"
|
||||
@click="incrementProduct(product)"
|
||||
>
|
||||
В корзину
|
||||
</button>
|
||||
<div v-else class="ml-auto flex w-28 items-center justify-between rounded-xl border border-base-300 px-1 py-1">
|
||||
<button
|
||||
class="btn btn-xs btn-square"
|
||||
:disabled="getQuantity(product.id) === 0"
|
||||
@click="decrementProduct(product.id)"
|
||||
>
|
||||
-
|
||||
</button>
|
||||
<span class="min-w-8 text-center text-sm font-semibold">{{ getQuantity(product.id) }}</span>
|
||||
<button class="btn btn-xs btn-square" @click="incrementProduct(product)">+</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user