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>