Feat: Create Customer Modal
This commit is contained in:
		| @@ -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> | ||||
| After Width: | Height: | Size: 576 B | 
| @@ -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> | ||||
| @@ -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> | ||||
| @@ -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> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user