From 18df5742d535020bc1a7501660be7c5af9f050f8 Mon Sep 17 00:00:00 2001 From: Rodia <alejandro.ayala@onecluster.org> Date: Sat, 26 Oct 2024 12:57:14 -0500 Subject: [PATCH] Feat: Create Customer Modal --- .../assets/icons/rectangle-xmark-solid.svg | 1 + .../src/components/CreateCustomerModal.vue | 86 ++++++ .../don-confiao/src/components/ModalView.vue | 19 ++ .../don-confiao/src/components/Purchase.vue | 280 +++++++++--------- 4 files changed, 251 insertions(+), 135 deletions(-) create mode 100644 tienda_ilusion/don_confiao/frontend/don-confiao/src/assets/icons/rectangle-xmark-solid.svg create mode 100644 tienda_ilusion/don_confiao/frontend/don-confiao/src/components/CreateCustomerModal.vue create mode 100644 tienda_ilusion/don_confiao/frontend/don-confiao/src/components/ModalView.vue diff --git a/tienda_ilusion/don_confiao/frontend/don-confiao/src/assets/icons/rectangle-xmark-solid.svg b/tienda_ilusion/don_confiao/frontend/don-confiao/src/assets/icons/rectangle-xmark-solid.svg new file mode 100644 index 0000000..cb18c6e --- /dev/null +++ b/tienda_ilusion/don_confiao/frontend/don-confiao/src/assets/icons/rectangle-xmark-solid.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--!Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M64 32C28.7 32 0 60.7 0 96L0 416c0 35.3 28.7 64 64 64l384 0c35.3 0 64-28.7 64-64l0-320c0-35.3-28.7-64-64-64L64 32zM175 175c9.4-9.4 24.6-9.4 33.9 0l47 47 47-47c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9l-47 47 47 47c9.4 9.4 9.4 24.6 0 33.9s-24.6 9.4-33.9 0l-47-47-47 47c-9.4 9.4-24.6 9.4-33.9 0s-9.4-24.6 0-33.9l47-47-47-47c-9.4-9.4-9.4-24.6 0-33.9z"/></svg> \ No newline at end of file diff --git a/tienda_ilusion/don_confiao/frontend/don-confiao/src/components/CreateCustomerModal.vue b/tienda_ilusion/don_confiao/frontend/don-confiao/src/components/CreateCustomerModal.vue new file mode 100644 index 0000000..4a449b0 --- /dev/null +++ b/tienda_ilusion/don_confiao/frontend/don-confiao/src/components/CreateCustomerModal.vue @@ -0,0 +1,86 @@ +<template> + <v-dialog v-model="showModal" max-width="600px"> + <v-card> + <v-card-title> + <span class="headline">Información del Cliente</span> + </v-card-title> + <v-card-text> + <v-form ref="form" v-model="valid"> + <v-text-field + v-model="customer.name" + label="Nombre" + :rules="[rules.required]" + required + ></v-text-field> + <v-text-field + v-model="customer.email" + label="Correo Electrónico" + :rules="[rules.required, rules.email]" + required + ></v-text-field> + <v-text-field + v-model="customer.phone" + label="Teléfono" + :rules="[rules.required]" + required + ></v-text-field> + </v-form> + </v-card-text> + <v-card-actions> + <v-spacer></v-spacer> + <v-btn color="blue darken-1" text @click="closeModal">Cancelar</v-btn> + <v-btn color="blue darken-1" text @click="submitForm">Guardar</v-btn> + </v-card-actions> + </v-card> + </v-dialog> +</template> + +<script> + export default { + data() { + return { + showModal: false, + valid: false, + customer: { + name: '', + email: '', + phone: '' + }, + rules: { + required: value => !!value || 'Este campo es requerido.', + email: value => { + const pattern = /^[^ ]+@[^ ]+\.[a-z]{2,3}$/; + return pattern.test(value) || 'El correo no es válido.'; + } + } + }; + }, + methods: { + openModal() { + this.showModal = true; + }, + closeModal() { + this.showModal = false; + this.resetForm(); + }, + submitForm() { + if (this.$refs.form.validate()) { + // Aquí puedes manejar el envío del formulario + console.log('Cliente guardado:', this.customer); + this.closeModal(); + } + }, + resetForm() { + this.customer = { + name: '', + email: '', + phone: '' + }; + this.$refs.form.reset(); + } + } + }; +</script> + +<style scoped> +</style> diff --git a/tienda_ilusion/don_confiao/frontend/don-confiao/src/components/ModalView.vue b/tienda_ilusion/don_confiao/frontend/don-confiao/src/components/ModalView.vue new file mode 100644 index 0000000..0d5d02b --- /dev/null +++ b/tienda_ilusion/don_confiao/frontend/don-confiao/src/components/ModalView.vue @@ -0,0 +1,19 @@ +<template> + <div class="modal"> + <div class="head"> + <p>Nuevo Movimiento</p> + <img @click="close" src="@/assets/close-icon.svg" alt="cerrar"/> + </div> + <div class="body"> + <slot></slot> + </div> + </div> +</template> + +<script setup> + import { defineEmits } from "vue"; + + const emit = defineEmits(["close"]); + + const close = () => emit("close"); +</script> diff --git a/tienda_ilusion/don_confiao/frontend/don-confiao/src/components/Purchase.vue b/tienda_ilusion/don_confiao/frontend/don-confiao/src/components/Purchase.vue index 56a6ae0..a062b9a 100644 --- a/tienda_ilusion/don_confiao/frontend/don-confiao/src/components/Purchase.vue +++ b/tienda_ilusion/don_confiao/frontend/don-confiao/src/components/Purchase.vue @@ -15,10 +15,12 @@ required class="mr-4" ></v-autocomplete> + <v-btn color="primary" @click="openModal">Agregar Cliente</v-btn> + <CreateCustomerModal ref="customerModal" /> </v-col> <v-col lg="2" - > + > <v-text-field v-model="purchase.date" label="Fecha" @@ -112,141 +114,149 @@ </template> <script> - export default { - name: 'DonConfiao', - props: { - msg: String - }, - data() { - return { - valid: false, - client_search: '', - product_search: '', - purchase: { - date: this.getCurrentDate(), - client: null, - notes: '', - saleline_set: [{product:'', unit_price: 0, quantity: 0}], - }, - rules: { - required: value => !!value || 'Requerido.', - }, - menuItems: [ - { title: 'Inicio', route: '/'}, - { title: 'Compras', route:'/compras'}, - ], - clients: [], - products: [], - }; - }, - created() { - this.fetchClients(); - this.fetchProducts(); - }, - watch: { - group () { - this.drawer = false - }, - }, - computed: { - calculateTotal() { - return this.purchase.saleline_set.reduce((total, saleline) => { - return total + this.calculateSubtotal(saleline); - }, 0); - }, - filteredClients() { - return this.clients.filter(client => { - if (this.client_search === '') { - return []; - } else { - return client.name.toLowerCase().includes(this.client_search.toLowerCase()); - } - }); - }, - filteredProducts() { - return this.products.filter(product => { - if (this.product_search === '') { - return []; - } else { - return product.name.toLowerCase().includes(this.product_search.toLowerCase()); - } - }); - }, - }, - methods: { - getCurrentDate() { - const today = new Date(); - const yyyy = today.getFullYear(); - const mm = String(today.getMonth() + 1).padStart(2, '0'); - const dd = String(today.getDate()).padStart(2, '0'); - return `${yyyy}-${mm}-${dd}`; - }, + import CustomerForm from './CreateCustomerModal.vue'; - onProductChange(index) { - const selectedProductId = this.purchase.saleline_set[index].product; - const selectedProduct = this.products.find(p => p.id == selectedProductId); - this.purchase.saleline_set[index].unit_price = selectedProduct.price; - }, - fetchClients() { - fetch('/don_confiao/api/customers/') - .then(response => response.json()) - .then(data => { - this.clients = data; - }) - .catch(error => { - console.error(error); - }); - }, - fetchProducts() { - fetch('/don_confiao/api/products/') - .then(response => response.json()) - .then(data => { - console.log(data); - this.products = data; - }) - .catch(error => { - console.error(error); - }); - }, - addLine() { - this.purchase.saleline_set.push({ product: '', unit_price: 0, quantity:0 }); - }, - removeLine(index) { - this.purchase.saleline_set.splice(index, 1); - }, - calculateSubtotal(line) { - return line.unit_price * line.quantity; - }, - async submit() { - if (this.$refs.form.validate()) { - try { - const response = await fetch('/don_confiao/api/sales/', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(this.purchase), - }); - if (response.ok) { - const data = await response.json(); - console.log('Compra enviada:', data); - this.$router.push("SummaryPurchase"); - } else { - console.error('Error al enviar la compra:', response.statusText); - } - } catch (error) { - console.error('Error de red:', error); - } - } - }, - navigate(route) { - this.$router.push(route); - }, - formatPrice(price) { - return new Intl.NumberFormat('es-ES', { style: 'currency', currency: 'COP' }).format(price); - }, - }, - }; + export default { + name: 'DonConfiao', + components: { + CustomerForm + }, + props: { + msg: String + }, + data() { + return { + valid: false, + client_search: '', + product_search: '', + purchase: { + date: this.getCurrentDate(), + client: null, + notes: '', + saleline_set: [{product:'', unit_price: 0, quantity: 0}], + }, + rules: { + required: value => !!value || 'Requerido.', + }, + menuItems: [ + { title: 'Inicio', route: '/'}, + { title: 'Compras', route:'/compras'}, + ], + clients: [], + products: [], + }; + }, + created() { + this.fetchClients(); + this.fetchProducts(); + }, + watch: { + group () { + this.drawer = false + }, + }, + computed: { + calculateTotal() { + return this.purchase.saleline_set.reduce((total, saleline) => { + return total + this.calculateSubtotal(saleline); + }, 0); + }, + filteredClients() { + return this.clients.filter(client => { + if (this.client_search === '') { + return []; + } else { + return client.name.toLowerCase().includes(this.client_search.toLowerCase()); + } + }); + }, + filteredProducts() { + return this.products.filter(product => { + if (this.product_search === '') { + return []; + } else { + return product.name.toLowerCase().includes(this.product_search.toLowerCase()); + } + }); + }, + }, + methods: { + openModal() { + this.$refs.customerModal.openModal(); + }, + getCurrentDate() { + const today = new Date(); + const yyyy = today.getFullYear(); + const mm = String(today.getMonth() + 1).padStart(2, '0'); + const dd = String(today.getDate()).padStart(2, '0'); + return `${yyyy}-${mm}-${dd}`; + }, + + onProductChange(index) { + const selectedProductId = this.purchase.saleline_set[index].product; + const selectedProduct = this.products.find(p => p.id == selectedProductId); + this.purchase.saleline_set[index].unit_price = selectedProduct.price; + }, + fetchClients() { + fetch('/don_confiao/api/customers/') + .then(response => response.json()) + .then(data => { + this.clients = data; + }) + .catch(error => { + console.error(error); + }); + }, + fetchProducts() { + fetch('/don_confiao/api/products/') + .then(response => response.json()) + .then(data => { + console.log(data); + this.products = data; + }) + .catch(error => { + console.error(error); + }); + }, + addLine() { + this.purchase.saleline_set.push({ product: '', unit_price: 0, quantity:0 }); + }, + removeLine(index) { + this.purchase.saleline_set.splice(index, 1); + }, + calculateSubtotal(line) { + return line.unit_price * line.quantity; + }, + async submit() { + if (this.$refs.form.validate()) { + try { + const response = await fetch('/don_confiao/api/sales/', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(this.purchase), + }); + if (response.ok) { + const data = await response.json(); + console.log('Compra enviada:', data); + this.$router.push("SummaryPurchase"); + } else { + console.error('Error al enviar la compra:', response.statusText); + } + } catch (error) { + console.error('Error de red:', error); + } + } + }, + navigate(route) { + this.$router.push(route); + }, + formatPrice(price) { + return new Intl.NumberFormat('es-ES', { style: 'currency', currency: 'COP' }).format(price); + }, + }, + }; </script> <style> </style>