121 lines
5.1 KiB
Vue
121 lines
5.1 KiB
Vue
<template>
|
|
<div class="card-section space-y-4">
|
|
|
|
<div v-if="store.loading" class="flex justify-center py-10">
|
|
<UIcon name="svg-spinners:ring-resize" class="text-3xl text-primary" />
|
|
</div>
|
|
|
|
<div v-else-if="store.variants.length === 0" class="flex flex-col items-center gap-3 py-10 text-gray-400">
|
|
<UIcon name="i-lucide-layers" class="text-4xl" />
|
|
<p class="text-sm text-center">
|
|
{{ isEditMode ? 'No variants found for this product.' : 'Save the product first, then variants will appear here.' }}
|
|
</p>
|
|
</div>
|
|
|
|
<template v-else>
|
|
<p class="text-sm text-gray-400">
|
|
Each variant is a combination of attributes (e.g. Color: Red / Size: M).
|
|
Edit price offset, stock and other details per variant independently.
|
|
</p>
|
|
|
|
<div v-for="variant in store.variants" :key="variant.id_product_attribute"
|
|
class="border border-(--border-light) dark:border-(--border-dark) rounded-xl p-4 space-y-4">
|
|
|
|
<!-- Variant header -->
|
|
<div class="flex items-center justify-between flex-wrap gap-2">
|
|
<div class="flex items-center gap-2">
|
|
<span class="font-semibold text-black dark:text-white text-sm">
|
|
{{ variant.attribute_label || `Variant #${variant.id_product_attribute}` }}
|
|
</span>
|
|
<UBadge v-if="variant.default_on" color="success" variant="subtle" size="sm">
|
|
Default
|
|
</UBadge>
|
|
</div>
|
|
|
|
<UButton size="sm" color="info"
|
|
:loading="!!store.variantSaving[variant.id_product_attribute!]"
|
|
@click="handleSaveVariant(variant)">
|
|
Save variant
|
|
</UButton>
|
|
</div>
|
|
|
|
<UAlert v-if="store.variantErrors[variant.id_product_attribute!]" color="error"
|
|
variant="subtle" :title="store.variantErrors[variant.id_product_attribute!]" />
|
|
|
|
<!-- Variant fields -->
|
|
<div class="grid grid-cols-2 md:grid-cols-4 gap-4">
|
|
<UFormField label="Reference">
|
|
<UInput v-model="variant.reference" placeholder="REF-001-A" class="w-full" />
|
|
</UFormField>
|
|
|
|
<UFormField label="EAN-13">
|
|
<UInput v-model="variant.ean13" placeholder="4006381333931" :maxlength="13"
|
|
class="w-full" />
|
|
</UFormField>
|
|
|
|
<UFormField label="Price offset">
|
|
<UInputNumber v-model="variant.price" :step="0.01"
|
|
:format-options="{ minimumFractionDigits: 2 }" class="w-full" />
|
|
</UFormField>
|
|
|
|
<UFormField label="Wholesale price">
|
|
<UInputNumber v-model="variant.wholesale_price" :min="0" :step="0.01"
|
|
:format-options="{ minimumFractionDigits: 2 }" class="w-full" />
|
|
</UFormField>
|
|
|
|
<UFormField label="Stock quantity">
|
|
<UInputNumber v-model="variant.quantity" :min="0" class="w-full" />
|
|
</UFormField>
|
|
|
|
<UFormField label="Min. quantity">
|
|
<UInputNumber v-model="variant.minimal_quantity" :min="1" class="w-full" />
|
|
</UFormField>
|
|
|
|
<UFormField label="Weight offset (kg)">
|
|
<UInputNumber v-model="variant.weight" :step="0.001" class="w-full" />
|
|
</UFormField>
|
|
|
|
<UFormField label="">
|
|
<div class="flex items-center gap-2 pt-6">
|
|
<USwitch v-model="variant.default_on" color="success"
|
|
@update:model-value="onSetDefault(variant)" />
|
|
<span class="text-sm text-black dark:text-white">Set as default</span>
|
|
</div>
|
|
</UFormField>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { useAddProductStore } from '@/stores/admin/addProduct'
|
|
import type { ProductVariantForm } from '@/types/product'
|
|
|
|
const props = defineProps<{ isEditMode: boolean }>()
|
|
|
|
const store = useAddProductStore()
|
|
|
|
async function handleSaveVariant(variant: ProductVariantForm) {
|
|
if (!variant.id_product_attribute) return
|
|
await store.saveVariant(variant.id_product_attribute, {
|
|
reference: variant.reference,
|
|
ean13: variant.ean13,
|
|
price: variant.price,
|
|
wholesale_price: variant.wholesale_price,
|
|
quantity: variant.quantity,
|
|
minimal_quantity: variant.minimal_quantity,
|
|
weight: variant.weight,
|
|
default_on: variant.default_on,
|
|
})
|
|
}
|
|
|
|
function onSetDefault(selected: ProductVariantForm) {
|
|
if (!selected.default_on) return
|
|
store.variants.forEach(v => {
|
|
if (v.id_product_attribute !== selected.id_product_attribute) v.default_on = false
|
|
})
|
|
}
|
|
</script>
|