Usando vuex

This commit is contained in:
Alejandro Tasistro 2025-05-23 00:01:55 -03:00
parent 45dcf643bf
commit 8f0d715f8c
4 changed files with 145 additions and 140 deletions

View file

@ -7,29 +7,31 @@
</button>
</div>
<div class="control">
<input id="cantidad" v-model="cantidad" class="input is-small" type="number" style="text-align: center">
<input id="cantidad" v-model="cantidadControl" class="input is-small" type="number"
style="text-align: center">
</div>
<div class="control" @click="incrementar();">
<button class="button is-small">
<i class="fa fa-solid fa-plus"></i>
</button>
</div>
<button :disabled="disableConfirm()" class="button is-small is-success ml-1" @click="confirmar()">
<button :disabled="!hayCambios" class="button is-small is-success ml-1" @click="confirmar()">
<span class="icon">
<i class="fas fa-check"></i>
</span>
</button>
<button :disabled="!puedeBorrar()" class="button is-small is-danger ml-1" @click="borrar()">
<button :disabled="!puedeBorrar" class="button is-small is-danger ml-1" @click="borrar()">
<span class="icon">
<i class="fas fa-trash-alt"></i>
</span>
</button>
</div>
<div v-if="producto.requiere_notas" v-bind:class="{'has-icons-right': notas_warning_visible}" class="control is-full-width has-icons-left">
<div v-if="requiere_notas" :class="{'has-icons-right': notas_warning_visible}"
class="control is-full-width has-icons-left">
<span class="icon is-small is-left">
<i class="fas fa-sticky-note"></i>
</span>
<input v-model="notas" v-bind:class="{'is-danger': notas_warning_visible}" id="notas" class="input" type="text" placeholder="Talle o color" />
<input v-model="notasControl" v-bind:class="{'is-danger': notas_warning_visible}" id="notas" class="input" type="text" placeholder="Talle o color"/>
<span v-if="notas_warning_visible" class="icon is-small is-right">
<i class="fas fa-exclamation-triangle"></i>
</span>
@ -43,98 +45,110 @@
</template>
<script>
export default {
props: {
producto: Object
import { mapActions, mapGetters } from "vuex";
export default {
props: {
producto_id: {
type: Number,
required: true,
},
data() {
return {
cantidad: this.cantidadEnChismosa(),
notas: this.notasEnChismosa(),
notas_warning_visible: false,
requiere_notas: {
type: Number,
required: true,
}
},
data() {
return {
cantidadControl: 0,
notasControl: '',
notas_warning_visible: false,
}
},
watch: {
cantidadEnChismosa() {
this.actualizar();
},
notasEnChismosa() {
this.actualizar();
}
},
mounted() {
this.actualizar();
},
computed: {
...mapGetters('pedido', ["enChismosa", "cantidad", "notas"]),
cantidadEnChismosa() {
return this.cantidad(this.producto_id);
},
notasEnChismosa() {
return this.notas(this.producto_id);
},
hayCambios() {
return this.cantidadControl !== this.cantidadEnChismosa || this.notasControl !== this.notasEnChismosa;
},
puedeBorrar() {
return this.enChismosa(this.producto_id);
},
faltaNotas() {
return this.requiere_notas && this.cantidadControl > 0 && !this.notasControl;
},
},
methods: {
...mapActions('pedido', ["modificarChismosa"]),
decrementar() {
this.cantidadControl -= 1;
},
incrementar() {
this.cantidadControl += 1;
},
borrar() {
this.cantidadControl = 0;
this.confirmar();
},
async confirmar() {
if (this.faltaNotas) {
this.notas_warning_visible = true;
return;
}
},
mounted() {
Event.$on('sync-subpedido', (cantidad, productoId, notas) => {
if (this.producto.id === productoId)
this.sincronizar(cantidad, notas);
await this.modificarChismosa({
producto_id: this.producto_id,
cantidad: this.cantidadControl,
notas: this.notasControl
});
},
methods: {
notasEnChismosa() {
return this.producto.pivot !== undefined ? this.producto.pivot.notas : "";
},
cantidadEnChismosa() {
return this.producto.pivot !== undefined ? this.producto.pivot.cantidad : 0;
},
decrementar() {
this.cantidad -= 1;
},
incrementar() {
this.cantidad += 1;
},
confirmar() {
if (this.warningNotas()) {
this.notas_warning_visible = true;
return;
}
console.log("Emit sync " + this.cantidad + " " + this.notas);
Event.$emit('sync-subpedido', this.cantidad, this.producto.id, this.notas);
},
borrar() {
this.cantidad = 0;
this.confirmar();
},
sincronizar(cantidad, notas) {
this.notas_warning_visible = false;
this.notas = notas;
this.cantidad = cantidad;
if (this.producto.pivot !== undefined) {
this.producto.pivot.cantidad = cantidad;
this.producto.pivot.notas = notas;
}
},
hayCambios() {
if (this.cantidad != this.cantidadEnChismosa()) return true;
return this.cantidad > 0 && this.notas != this.notasEnChismosa();
},
puedeBorrar() {
return this.cantidadEnChismosa() > 0;
},
warningNotas() {
return this.producto.requiere_notas && this.cantidad > 0 && !this.notas;
},
disableConfirm() {
return !this.hayCambios();
},
}
actualizar() {
this.cantidadControl = this.cantidadEnChismosa;
this.notasControl = this.notasEnChismosa;
},
}
}
</script>
<style>
/* Chrome, Safari, Edge, Opera */
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
/* Chrome, Safari, Edge, Opera */
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
/* Firefox */
input[type=number] {
appearance: textfield;
-moz-appearance: textfield;
}
.contador {
min-width: 178px;
}
/* Firefox */
input[type=number] {
appearance: textfield;
-moz-appearance: textfield;
}
.is-danger {
background-color: #fca697;
}
.is-danger::placeholder {
color: #fff;
opacity: 1; /* Firefox */
}
</style>
.contador {
min-width: 178px;
}
.is-danger {
background-color: #fca697;
}
.is-danger::placeholder {
color: #fff;
opacity: 1; /* Firefox */
}
</style>

View file

@ -1,53 +1,25 @@
<script>
import ProductoCantidad from "./ProductoCantidad.vue";
import { mapGetters } from "vuex";
export default {
name: "ProductoCard",
components: { ProductoCantidad },
props: {
producto: Object
producto: {
type: Object,
required: true
}
},
data() {
return {
cantidad: this.producto.cantidad,
enChismosa: this.producto.cantidad,
notas: this.producto.notas,
}
computed: {
...mapGetters('pedido',["enChismosa", "cantidad"]),
fuePedido() {
return this.enChismosa(this.producto.id);
},
cantidadEnChismosa() {
return this.cantidad(this.producto.id);
}
},
mounted() {
Event.$on('sync-subpedido', (cantidad, productoId, notas) => {
if (this.producto.id === productoId)
this.sincronizar(cantidad, notas);
});
},
methods: {
decrementar() {
this.cantidad -= 1;
},
incrementar() {
this.cantidad += 1;
},
confirmar() {
Event.$emit('sync-subpedido', this.cantidad, this.producto.id, this.notas);
},
borrar() {
this.cantidad = 0;
this.confirmar();
},
sincronizar(cantidad, notas) {
this.cantidad = cantidad;
this.producto.cantidad = cantidad;
this.enChismosa = cantidad;
this.notas = notas;
this.producto.notas = notas;
},
hayCambios() {
return this.cantidad !== this.enChismosa || this.notas !== this.producto.notas;
},
puedeBorrar() {
return this.enChismosa > 0;
},
}
}
</script>
@ -59,7 +31,7 @@ export default {
<p class="title is-6">
{{ producto.nombre }}
</p>
<span class="subtitle is-7 hidden-from-tablet" v-if="enChismosa">{{ enChismosa }} en chismosa</span>
<span class="subtitle is-7 hidden-from-tablet" v-if="fuePedido">{{ cantidadEnChismosa }}</span>
</div>
<div class="column is-one-quarter has-text-right">
<p class="has-text-weight-bold has-text-primary">
@ -73,13 +45,16 @@ export default {
</div>
<footer class="columns">
<div class="column is-three-quarters">
<producto-cantidad :producto="producto"></producto-cantidad>
<producto-cantidad
:producto_id="producto.id"
:requiere_notas="producto.requiere_notas">
</producto-cantidad>
</div>
<div class="column">
<p class="subtitle is-7 is-hidden-mobile" v-if="enChismosa > 0">{{ enChismosa }} en chismosa</p>
<p class="subtitle is-7 is-hidden-mobile" v-if="fuePedido">{{ cantidadEnChismosa }} en chismosa</p>
</div>
</footer>
</div><!-- END BOX -->
</div>
</div>
</template>

View file

@ -2,18 +2,25 @@
<tr>
<td>{{ this.producto.nombre }}</td>
<td class="has-text-right">
<producto-cantidad :producto="producto"></producto-cantidad>
<producto-cantidad
:producto_id="producto.id"
:requiere_notas="producto.requiere_notas">
</producto-cantidad>
</td>
<td class="has-text-right">{{ this.producto.pivot.total }}</td>
<td class="has-text-right">{{ cantidad(producto.id) }}</td>
</tr>
</template>
<script>
import ProductoCantidad from "./ProductoCantidad.vue";
import { mapGetters } from "vuex";
export default {
components: { ProductoCantidad },
props: {
producto: Object
},
computed: {
...mapGetters('pedido',["cantidad"]),
},
}
</script>

View file

@ -1,3 +1,5 @@
import axios from "axios";
const state = {
lastFetch: null,
pedido_id: null,
@ -40,7 +42,14 @@ const actions = {
const response = await axios.get(`/api/subpedidos/${pedido.id}`);
commit('setState', response.data.data);
},
async modificarChismosa({ commit }, producto_id, cantidad, notas) {},
async modificarChismosa({ commit }, { producto_id, cantidad, notas }) {
const response = await axios.post("/api/subpedidos/" + state.pedido_id + "/sync", {
cantidad: cantidad,
producto_id: producto_id,
notas: notas,
});
commit('setState', response.data.data);
},
async modificarDevoluciones({ commit }, monto, notas) {}
};
@ -52,10 +61,10 @@ const getters = {
return ((producto_id) => state.productos.some(p => p.id === producto_id));
},
cantidad() {
return ((producto_id) => state.productos.find(p => p.id === producto_id).pivot.cantidad);
return ((producto_id) => state.productos.find(p => p.id === producto_id)?.pivot.cantidad ?? 0);
},
notas() {
return ((producto_id) => state.productos.find(p => p.id === producto_id).pivot.notas);
return ((producto_id) => state.productos.find(p => p.id === producto_id)?.pivot.notas ?? "");
}
}