I can see the product with different options
Some checks failed
CI / Check Style (push) Has been cancelled
CI / Run Clippy (push) Has been cancelled
CI / Run Tests (push) Has been cancelled

This commit is contained in:
Priec
2026-06-22 16:14:04 +02:00
parent 3f798432a0
commit 3a1ea7cdb4
5 changed files with 34 additions and 37 deletions

View File

@@ -37,9 +37,11 @@
{# --- Variants / options editor ------------------------------------------- #}
{# Each product is sold as one or more variants (a free-text label such as #}
{# "10cm x 13cm" or "5ml" plus its own price/stock/sku, and optional public & #}
{# business sale prices). Rows are managed client-side; names are indexed #}
{# (variants[i][...]) and read back by the controller. #}
{# "10cm x 13cm" or "5ml" plus its own price/stock, optional sku & business #}
{# price). Price and stock are required; the browser blocks save if a row is #}
{# incomplete. Rows are managed client-side; names are indexed (variants[i][…]) #}
{# and read back by the controller. #}
{% set opt = " (" ~ t(key="optional", lang=lang | default(value='sk')) ~ ")" %}
<script id="variants-data" type="application/json">{{ variants | json_encode() | safe }}</script>
<div class="space-y-3" x-data="variantEditor(JSON.parse(document.getElementById('variants-data').textContent))">
<div class="flex items-center justify-between">
@@ -55,32 +57,28 @@
<input type="hidden" :name="`variants[${i}][id]`" :value="row.id">
<div class="space-y-1 sm:col-span-5">
<label class="{{ sublabel }}">{{ t(key="option-label", lang=lang | default(value='sk')) }}</label>
<label class="{{ sublabel }}">{{ t(key="option-label", lang=lang | default(value='sk')) }}{{ opt }}</label>
<input :name="`variants[${i}][label]`" x-model="row.label" class="{{ inp }}" placeholder="napr. 10cm x 13cm">
</div>
<div class="space-y-1 sm:col-span-3">
<label class="{{ sublabel }}">{{ t(key="sku", lang=lang | default(value='sk')) }}</label>
<label class="{{ sublabel }}">{{ t(key="sku", lang=lang | default(value='sk')) }}{{ opt }}</label>
<input :name="`variants[${i}][sku]`" x-model="row.sku" class="{{ inp }}">
</div>
<div class="space-y-1 sm:col-span-2">
<label class="{{ sublabel }}">{{ t(key="stock", lang=lang | default(value='sk')) }}</label>
<input type="number" min="0" :name="`variants[${i}][stock]`" x-model="row.stock" class="{{ inp }}">
<input type="number" min="0" required :name="`variants[${i}][stock]`" x-model="row.stock" class="{{ inp }}">
</div>
<div class="flex items-end sm:col-span-2">
<button type="button" @click="remove(i)"
class="ml-auto rounded-radius px-2 py-2 text-sm text-danger hover:bg-danger/10" title="{{ t(key='delete', lang=lang | default(value='sk')) }}"></button>
</div>
<div class="space-y-1 sm:col-span-4">
<div class="space-y-1 sm:col-span-6">
<label class="{{ sublabel }}">{{ t(key="price", lang=lang | default(value='sk')) }}</label>
<input :name="`variants[${i}][price]`" x-model="row.price" inputmode="decimal" class="{{ inp }}" placeholder="0.00">
<input :name="`variants[${i}][price]`" x-model="row.price" inputmode="decimal" required class="{{ inp }}" placeholder="0.00">
</div>
<div class="space-y-1 sm:col-span-4">
<label class="{{ sublabel }}">{{ t(key="sale-price", lang=lang | default(value='sk')) }}</label>
<input :name="`variants[${i}][sale]`" x-model="row.sale" inputmode="decimal" class="{{ inp }}" placeholder="—">
</div>
<div class="space-y-1 sm:col-span-4">
<label class="{{ sublabel }}">{{ t(key="business-price", lang=lang | default(value='sk')) }}</label>
<div class="space-y-1 sm:col-span-6">
<label class="{{ sublabel }}">{{ t(key="business-price", lang=lang | default(value='sk')) }}{{ opt }}</label>
<input :name="`variants[${i}][business_sale]`" x-model="row.business_sale" inputmode="decimal" class="{{ inp }}" placeholder="—">
</div>
</div>
@@ -89,15 +87,14 @@
<script>
function variantEditor(initial) {
const blank = () => ({ id: '', label: '', sku: '', stock: 0, price: '', sale: '', business_sale: '' });
const blank = () => ({ id: '', label: '', sku: '', stock: '', price: '', business_sale: '' });
return {
rows: (initial || []).map(r => ({
id: r.id || '',
label: r.label || '',
sku: r.sku || '',
stock: (r.stock === null || r.stock === undefined) ? 0 : r.stock,
stock: (r.stock === null || r.stock === undefined) ? '' : r.stock,
price: r.price || '',
sale: r.sale || '',
business_sale: r.business_sale || '',
})),
init() { if (this.rows.length === 0) this.add(); },

View File

@@ -60,6 +60,19 @@
<template x-if="current">
<div class="space-y-6">
<!-- option picker (only when there's a real choice); first option is
selected by default and switching it updates the price + buy form -->
<template x-if="variants.length > 1">
<div class="max-w-sm space-y-1.5">
<label for="variant-select" class="text-sm font-medium text-on-surface-strong dark:text-on-surface-dark-strong">{{ t(key="choose-option", lang=lang | default(value='sk')) }}</label>
<select id="variant-select" x-model.number="sel" class="{{ fld }}">
<template x-for="(v, i) in variants" :key="v.id">
<option :value="i" x-text="(v.label || '—') + ' · ' + v.price + ' {{ product.currency }}' + (v.in_stock ? '' : ' ({{ t(key='out-of-stock', lang=lang | default(value='sk')) }})')"></option>
</template>
</select>
</div>
</template>
<div class="flex items-baseline gap-3">
<p class="text-2xl font-semibold" :class="current.on_sale ? 'text-danger' : 'text-primary dark:text-primary-dark'">
<span x-text="current.price"></span> {{ product.currency }}
@@ -73,18 +86,6 @@
<div class="whitespace-pre-line leading-relaxed text-on-surface/80 dark:text-on-surface-dark/80">{{ product.description }}</div>
{% endif %}
<!-- variant picker (only when there's a real choice) -->
<template x-if="variants.length > 1">
<div class="max-w-sm space-y-1.5">
<label for="variant-select" class="text-sm font-medium text-on-surface-strong dark:text-on-surface-dark-strong">{{ t(key="choose-option", lang=lang | default(value='sk')) }}</label>
<select id="variant-select" x-model.number="sel" class="{{ fld }}">
<template x-for="(v, i) in variants" :key="v.id">
<option :value="i" x-text="(v.label || '—') + ' · ' + v.price + ' {{ product.currency }}' + (v.in_stock ? '' : ' ({{ t(key='out-of-stock', lang=lang | default(value='sk')) }})')"></option>
</template>
</select>
</div>
</template>
<template x-if="current.in_stock">
<div class="space-y-2">
<form method="post" action="/cart/add" hx-post="/cart/add" hx-swap="none" class="flex flex-wrap items-end gap-3"