# Vue.js + Carrito

Apliquemos todo lo aprendido del carrito de compras con Vue.js + Composition API

# Apoya el Directo 😃

CURSO EN UDEMY OFERTA!

Aprende desde cero a trabajar con Vue.js y Firebase aquí: http://curso-vue-js-udemy.bluuweb.cl Nos vemos en clases!

CURSO EN UDEMY OFERTA!

Aprende desde cero a trabajar con React.js y Firebase aquí: http://curso-react-js-udemy.bluuweb.cl Nos vemos en clases!

CURSO EN UDEMY OFERTA!

Aprende desde cero a trabajar con Bootstrap 4! aquí: http://curso-bootstrap-4-udemy.bluuweb.cl Nos vemos en clases!

# Preguntas y Respuestas

# Vuex

import { createStore } from 'vuex'

export default createStore({
  state: {
    productos: [],
    carrito: {}
  },
  mutations: {
    setProductos(state, payload) {
      state.productos = payload
    },
    setCarrito(state, payload) {
      state.carrito[payload.id] = { ...payload }
      console.log(state.carrito)
    },
    setVaciar(state) {
      state.carrito = {}
    },
    aumentar(state, payload) {
      state.carrito[payload].cantidad = state.carrito[payload].cantidad + 1
    },
    disminuir(state, payload) {
      state.carrito[payload].cantidad = state.carrito[payload].cantidad - 1
      if (state.carrito[payload].cantidad === 0) {
        delete state.carrito[payload]
      }
    }
  },
  actions: {
    async fetchData({commit}) {
      try {
        const res = await fetch('api.json')
        const productos = await res.json()
        commit('setProductos', productos)
      } catch (error) {
        console.log(error)
      }
    },
    agregarCarrito({ commit, state }, producto) {
      state.carrito.hasOwnProperty(producto.id)
        ? producto.cantidad = state.carrito[producto.id].cantidad + 1
        : producto.cantidad = 1
      commit('setCarrito', producto)
    }
  },
  getters: {
    totalCantidad(state) {
      return Object.values(state.carrito).reduce((acc, {cantidad}) => acc + cantidad, 0)
    },
    totalPrecio(state) {
      return Object.values(state.carrito).reduce((acc, {cantidad, precio}) => acc + cantidad * precio, 0)
    }
  }
})

# App.vue

<template>
  <div class="container">
    <h1>Carrito con vue.js</h1>
    <hr>
    <Carrito />
    <div class="row">
      <div 
        v-for="producto of productos" :key="producto.id"
        class="col-12 col-sm-4 col-md-3 col-lg-2 mb-3 mb-3"
      >
        <Card 
          :producto="producto"
        />
      </div>
    </div>
  </div>
</template>

<script>
import {useStore} from 'vuex'
import { computed, onMounted } from 'vue'
import Card from './components/Card'
import Carrito from './components/Carrito'

export default {
  name: 'App',
  components: {
    Card, Carrito
  },
  setup(){
    const store = useStore()
    onMounted(async() => {
      store.dispatch('fetchData')
    })

    const productos = computed(() => store.state.productos)

    return {productos}
  }
}
</script>

# Card.vue

<template>
    <div class="card">
        <img :src="producto.thumbnailUrl" :alt="`imagen ${producto.title}`" class="card-img-top" />
        <div class="card-body">
        <h5 class="card-title"></h5>
        <p class="card-text">$ <span>{{producto.precio}}</span></p>
        <button class="btn btn-dark" @click="comprar(producto)">Comprar</button>
        </div>
    </div>
</template>

<script>
import {useStore} from 'vuex'
export default {
    props: ['producto'],
    setup(){
        const store = useStore()
        const comprar = producto => {
            store.dispatch('agregarCarrito', producto)
        }
        return {comprar}
    }
}
</script>

# Carrito.vue

<template>
    <div class="my-5">
        <h4>Carrito de compras</h4>
        <table class="table">
            <thead>
            <tr>
                <th scope="col">#</th>
                <th scope="col">Item</th>
                <th scope="col">Cantidad</th>
                <th scope="col">Acción</th>
                <th scope="col">Total</th>
            </tr>
            </thead>
            <tbody id="items">
                <Items
                    v-for="item in carrito" :key="item.id"
                    :item="item"
                />
            </tbody>
            <tfoot>
            <tr id="footer-carrito">
                <th scope="row" colspan="5" v-if="Object.keys(carrito).length === 0">Carrito vacío - comience a comprar!</th>
                <Footer v-else/>
            </tr>
            </tfoot>
        </table>
    </div>
</template>

<script>
import { computed } from 'vue'
import {useStore} from 'vuex'
import Items from './Items'
import Footer from './Footer'
export default {
    components: {Items, Footer},
    setup(){
        const store = useStore()
        const carrito = computed(() => store.state.carrito)

        return {carrito}
    }
}
</script>

# Item.vue

<template>
  <tr>
    <th scope="row">{{item.id}}</th>
    <td>{{item.title}}</td>
    <td>{{item.cantidad}}</td>
    <td>
        <button class="btn btn-info btn-sm" @click="aumentar(item.id)">
            +
        </button>
        <button class="btn btn-danger btn-sm" @click="disminuir(item.id)">
            -
        </button>
    </td>
    <td>${{item.precio * item.cantidad}}</td>
  </tr>
</template>

<script>
import {useStore} from 'vuex'
export default {
    props: ['item'],
    setup(){
        const store = useStore()
        const aumentar = id => {store.commit('aumentar', id)}
        const disminuir = id => {store.commit('disminuir', id)}
        return {aumentar, disminuir}
    }
}
</script>
<template>
  <th scope="row" colspan="2">Total productos</th>
    <td>{{totalCantidad}}</td>
    <td>
        <button class="btn btn-danger btn-sm" id="vaciar-carrito" @click="vaciar">
            vaciar todo
        </button>
    </td>
    <td class="font-weight-bold">$ <span>{{totalPrecio}}</span></td>
</template>

<script>
import { computed } from 'vue'
import {useStore} from 'vuex'
export default {
    setup(){
        const store = useStore()
        const totalCantidad = computed(() => store.getters.totalCantidad)
        const totalPrecio = computed(() => store.getters.totalPrecio)
        const vaciar = () => {store.commit('setVaciar')}

        return {totalCantidad, totalPrecio, vaciar}
    }
}
</script>