create product functionality and page

This commit is contained in:
María
2025-08-21 11:55:20 +02:00
parent 2633959ce8
commit 4a05f8915b
4 changed files with 212 additions and 58 deletions

View File

@@ -10,7 +10,7 @@
:src="croppieImage"
:stencil-props="{ aspectRatio: 1 }"
/>
<div>
<div class="buttons">
<button class="filter-button" @click.prevent="crop">Aplicar</button>
<button @click.prevent="cancel">Cancelar</button>
</div>
@@ -31,7 +31,7 @@ export default {
components: { Cropper },
props: {
imageUrl: {
type: String,
type: [String, Object],
default: null,
},
},
@@ -106,5 +106,10 @@ export default {
}
.input {
max-width: 100%;
margin-bottom: 1em;
}
.buttons {
margin-top: 1em;
}
</style>

View File

@@ -1,12 +1,10 @@
<template>
<form class="form" @submit.prevent="sendProduct">
{{ form }}
<div class="cont-col">
<BFormCheckbox
id="customSwitch1"
v-model="form.active"
class="label"
:value="form.active"
>Activo
<span class="help-text"
>Desactiva el producto si quieres paralizar temporalmente su
@@ -15,7 +13,7 @@
</BFormCheckbox>
</div>
<br />
<FormHeader title="general" />
<FormHeader title="General" />
<p class="help-text">
Estos son los datos básicos de un producto. Procura completar el mayor
número de campos posible. Los campos señalados con asterisco (*) son
@@ -34,35 +32,41 @@
/>
<FormInput
v-model="form.price"
:value="form.price ? form.price : ''"
min="0"
step="0.01"
type="number"
label-text="Precio"
placeholder="precio + iva"
@input="form.price = $event"
/>
</div>
<div class="cont">
<FormInput
v-model="form.url"
:value="form.url ? form.url : ''"
type="text"
label-text="Url"
placeholder="enlace directo al producto en tu tienda o web"
@input="form.url = $event"
/>
<small class="error" v-if="form.url && !isValidUrl(form.url)"
>La url no es válida</small
>
<small v-if="form.url && !isValidUrl(form.url)" class="error">
La url no es válida
</small>
<br />
<FormInput
v-model="form.sku"
:value="form.sku ? form.sku : ''"
type="text"
label-text="SKU o identificador"
@input="form.sku = $event"
/>
</div>
<div class="cont-col">
<label for="imagen">Imagen</label>
<client-only>
<FormInputImage :imageUrl="form.image" @change="handleImage" />
</client-only>
<ClientOnly>
<FormInputImage :image-url="form.image" @change="handleImage" />
</ClientOnly>
</div>
<!-- <div class="cont-col">
<input
@@ -79,20 +83,33 @@
<textarea v-model="form.description" class="textarea" type="text" />
</div>
<div class="cont">
<FormInput v-model="form.stock" type="number" label-text="Stock" />
<FormInput
v-model="form.stock"
:value="form.stock ? form.stock : ''"
type="number"
label-text="Stock"
@input="form.stock = $event"
/>
<FormInput
v-model="form.discount"
:value="form.discount ? form.discount : ''"
step="0.01"
type="number"
label-text="Descuento"
@input="form.discount = $event"
/>
</div>
<div class="cont-col">
<FormInput v-model="form.identifiers" label-text="Identificador único" />
<FormInput
v-model="form.identifiers"
:value="form.identifiers ? form.identifiers : ''"
label-text="Identificador único"
@input="form.identifiers = $event"
/>
</div>
</fieldset>
<fieldset class="fieldset">
<FormHeader title="categorías" />
<FormHeader title="Categorías" />
<p class="help-text">
Estos datos ayudan a que tu producto sea encontrado por los clientes.
Procura completar el mayor número de campos posibles. Los campos
@@ -101,15 +118,14 @@
<div class="cont-col">
<label for="category">Categoría*</label>
<b-form-input
<BFormInput
id="category"
v-model="form.category"
autocomplete="off"
list="my-list-id"
id="category"
></b-form-input>
/>
<datalist id="my-list-id">
<option v-for="(choice, index) in categories" :key="index">
<option v-for="(choice, index) in categories" :key="`category-${index}`">
{{ choice }}
</option>
</datalist>
@@ -126,22 +142,22 @@
</div>
<div class="cont-col">
<label for="tags-basic">Palabras clave</label>
<b-form-tags
<BFormTags
v-model="form.tags"
placeholder="Añade palabras clave (moda, complementos...)"
input-id="tags-basic"
></b-form-tags>
/>
</div>
<div class="cont-col">
<label for="tags-basic">Atributos</label>
<b-form-tags
<BFormTags
v-model="form.attributes"
placeholder="Añade características del producto (talla, color...)"
input-id="tags-basic"
></b-form-tags>
/>
</div>
</fieldset>
<FormHeader title="envío" />
<FormHeader title="Envío" />
<fieldset class="fieldset">
<div class="cont-col">
<label for="">Condiciones de envío</label>
@@ -156,16 +172,20 @@
<div class="cont-col">
<FormInput
v-model="form.shipping_cost"
:value="form.shipping_cost ? form.shipping_cost : ''"
step="0.01"
type="number"
label-text="Gastos de envío"
placeholder="ej. 4,50"
@input="form.shipping_cost = $event"
/>
</div>
</fieldset>
<div class="submit-btn" align="center">
<SubmitButton text="guardar" imageUrl="" />
<SubmitButton text="guardar" image-url="" />
</div>
PRODUCT FORM: {{ productForm }} <br><br><br>
FORM: {{ form }}
</form>
</template>
@@ -174,7 +194,13 @@ import FormInputImage from './FormInputImage.vue'
import dataProcessing from '~/utils/dataProcessing'
export default {
components: { FormInputImage },
props: ['productForm'],
props: {
productForm: {
type: Object,
default: () => ({}),
},
},
emits: ['send'],
data() {
return {
form: {
@@ -222,19 +248,24 @@ export default {
}
},
mounted() {
if (this.productForm) {
async mounted() {
await this.getAllCategories()
if (this.productForm && Object.keys(this.productForm).length > 0) {
Object.keys(this.form).forEach((key) => {
this.form[key] = this.productForm[key]
})
}
this.getAllCategories()
},
methods: {
isValidUrl: dataProcessing.isValidUrl,
async getAllCategories() {
const { data } = await this.$api.get(`/products/all_categories/`)
const config = useRuntimeConfig()
const data = await $fetch(`/products/all_categories/`,{
baseURL: config.public.baseURL,
method: 'GET',
})
this.categories = data
},
parseForm() {
@@ -249,7 +280,7 @@ export default {
if (typeof formData.get('image') === 'string') {
formData.delete('image')
}
//console.log('FormData:', formData)
return formData
},
@@ -259,6 +290,7 @@ export default {
sendProduct() {
const formData = this.parseForm()
//TODO: review with Diego. I changed formaData with this.form
this.$emit('send', formData)
},
},
@@ -333,7 +365,7 @@ export default {
font-family: $font-secondary;
background-color: $color-light;
margin-bottom: 20px;
margin-top: -10px;
margin-top: 6px;
a {
text-decoration: underline;