Files
consumocuidado/components/ProductForm.vue
2025-08-20 15:08:53 +02:00

347 lines
8.8 KiB
Vue

<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
venta</span
>
</BFormCheckbox>
</div>
<br />
<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
obligatorios, los demás son opcionales. Si el producto o servicio no tiene
precio asignado, aparecerá "Consultar precio".
</p>
<fieldset class="fieldset">
<div class="cont">
<FormInput
v-model="form.name"
:value="form.name ? form.name : ''"
type="text"
label-text="Nombre"
required
@input="form.name = $event"
/>
<FormInput
v-model="form.price"
min="0"
step="0.01"
type="number"
label-text="Precio"
placeholder="precio + iva"
/>
</div>
<div class="cont">
<FormInput
v-model="form.url"
type="text"
label-text="Url"
placeholder="enlace directo al producto en tu tienda o web"
/>
<small class="error" v-if="form.url && !isValidUrl(form.url)"
>La url no es válida</small
>
<br />
<FormInput
v-model="form.sku"
type="text"
label-text="SKU o identificador"
/>
</div>
<div class="cont-col">
<label for="imagen">Imagen</label>
<client-only>
<FormInputImage :imageUrl="form.image" @change="handleImage" />
</client-only>
</div>
<!-- <div class="cont-col">
<input
id="imagen"
type="file"
accept="image/*"
class="imagenInput"
placeholder="Elige una imagen"
@change="handleImage"
/>
</div> -->
<div class="cont-col">
<label for="">Descripción del producto</label>
<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.discount"
step="0.01"
type="number"
label-text="Descuento"
/>
</div>
<div class="cont-col">
<FormInput v-model="form.identifiers" label-text="Identificador único" />
</div>
</fieldset>
<fieldset class="fieldset">
<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
señalados con asterisco (*) son obligatorios, los demás son opcionales.
</p>
<div class="cont-col">
<label for="category">Categoría*</label>
<b-form-input
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">
{{ choice }}
</option>
</datalist>
<!-- <b-form-select required v-model="form.category" name="" id="category">
<option disabled value="">Categoría</option>
<option
v-for="(category, key) in categories"
:key="key"
:value="category"
>
{{ category }}
</option>
</b-form-select> -->
</div>
<div class="cont-col">
<label for="tags-basic">Palabras clave</label>
<b-form-tags
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
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" />
<fieldset class="fieldset">
<div class="cont-col">
<label for="">Condiciones de envío</label>
<p class="help-text">
Aquí podrás indicar las condiciones de envío específicas para este
producto. Si no lo rellenas se mostrarán las opciones por defecto que
puedes editar en tu formulario de edición de la Cooperativa en el
apartado condiciones de envío.
</p>
<textarea v-model="form.shipping_terms" class="textarea" type="text" />
</div>
<div class="cont-col">
<FormInput
v-model="form.shipping_cost"
step="0.01"
type="number"
label-text="Gastos de envío"
placeholder="ej. 4,50"
/>
</div>
</fieldset>
<div class="submit-btn" align="center">
<SubmitButton text="guardar" imageUrl="" />
</div>
</form>
</template>
<script>
import FormInputImage from './FormInputImage.vue'
import dataProcessing from '~/utils/dataProcessing'
export default {
components: { FormInputImage },
props: ['productForm'],
data() {
return {
form: {
sku: '',
name: '',
description: '',
image: null,
url: '',
price: '',
shipping_cost: '',
shipping_terms: '',
source: 'MANUAL',
active: true,
discount: '',
stock: null,
category: '',
tags: [],
attributes: [],
identifiers: '',
},
// tagsArray: ['tag1', 'tag2', 'tag3', 'tag33'],
categories: [
'Alimentación, bebida y tabaco',
'Arte y ocio',
'Bebés y niños pequeños',
'Bricolaje',
'Cámaras y ópticas',
'Casa y jardín',
'Economía e industria',
'Electrónica',
'Elementos religiosos y ceremoniales',
'Equipamiento deportivo',
'Juegos y juguetes',
'Maletas y bolsos de viaje',
'Material de oficina',
'Mobiliario',
'Multimedia',
'Productos para adultos',
'Productos para mascotas y animales',
'Ropa y accesorios',
'Salud y belleza',
'Software',
'Vehículos y recambios',
],
}
},
mounted() {
if (this.productForm) {
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/`)
this.categories = data
},
parseForm() {
const formData = new FormData()
Object.keys(this.form).forEach((key) => {
if ((key === 'tags') | (key === 'attributes')) {
formData.append(key, JSON.stringify(this.form[key]))
} else if (this.form[key] || this.form[key] === '')
formData.append(key, this.form[key])
})
if (typeof formData.get('image') === 'string') {
formData.delete('image')
}
return formData
},
async handleImage(e) {
this.form.image = e
},
sendProduct() {
const formData = this.parseForm()
this.$emit('send', formData)
},
},
}
</script>
<style lang="scss" scoped>
.form {
@include desktop {
width: 40%;
}
@include tablet {
width: 60%;
}
@include mobile {
width: 90%;
}
.imagenInput {
font-size: $s;
}
label, .label {
text-align: left;
color: $color-navy;
font-weight: $bold;
font-size: $xs;
}
.textarea {
width: 100%;
background-color: $color-grey-inputs;
border: 1px solid $color-grey-inputs-border;
border-radius: 4px;
padding: 10px 5px;
display: block;
margin-bottom: 10px;
}
}
.fieldset {
margin-top: 40px;
margin-bottom: 40px;
}
.cont {
display: flex;
justify-content: space-between;
@include mobile {
flex-direction: column;
}
}
.cont-col {
margin: 15px 0;
display: flex;
flex-direction: column;
h3 {
color: $color-navy;
font-size: $m;
margin: 10px 0 15px 0;
}
}
.submit-btn {
margin-top: 20px;
}
.help-text {
text-align: left;
font-size: $xs;
text-align: justify;
font-weight: $regular;
color: $color-greylayout;
font-family: $font-secondary;
background-color: $color-light;
margin-bottom: 20px;
margin-top: -10px;
a {
text-decoration: underline;
color: $color-greytext;
}
}
.error {
color: $color-error;
}
</style>