Gogs преди 7 години
родител
ревизия
7bb778e345

+ 5 - 3
src/App.vue

@@ -4,7 +4,7 @@
             tab-content(title="Qué productos necesita?")
                 product-step
             tab-content(title="Quién es el cliente?")
-                .step 2
+                customer-step
             tab-content(title="Cómo quieres pagar?")
                 .step 3
 </template>
@@ -15,13 +15,15 @@
     import { FormWizard, TabContent } from 'vue-form-wizard'
     import 'vue-form-wizard/dist/vue-form-wizard.min.css'
 
-    import ProductStep from '@/components/steps/product/Main'
+    import ProductStep from '@/components/steps/Product'
+    import CustomerStep from '@/components/steps/Customer'
 
     export default {
         components: {
             FormWizard,
             TabContent,
-            ProductStep
+            ProductStep,
+            CustomerStep
         },
         methods: mapActions([
             'initSale',

+ 1 - 1
src/components/common/AddCard.vue

@@ -7,7 +7,7 @@
     export default {
         methods: {
             onClick(e) {
-                this.$emit('onClick')
+                this.$emit('onClickAdd')
             }
         }
     }

+ 9 - 0
src/components/common/Card.vue

@@ -36,6 +36,7 @@
 
 <style lang="sass">
     @import '../../assets/variables'
+
     .card
         width: 130px
         height: 160px
@@ -77,4 +78,12 @@
             color: $app-bg-color
             position: absolute
             bottom: 0
+
+        @keyframes card-bubble
+            30%
+                transform: scaleX(0.75) scaleY(1.25)
+            40%
+                transform: scaleX(1.25) scaleY(0.75)
+            60%
+                transform: scaleX(0.85) scaleY(1.15)
 </style>

+ 1 - 1
src/components/common/CardGrid.vue

@@ -3,7 +3,7 @@
         .card-grid-loading(v-if='loading')
             spinner
         .card-grid(v-else)
-            add-card(v-if='canAdd' @onClick='onClickAdd')
+            add-card(v-if='canAdd' @onClickAdd='onClickAdd')
             card(v-for='item in items' :key='item.id' :title='item.name' :image='item.imageMedium' :isSelected='item.id === selectedId' :description='getDescription(item)' @onClick='onClickCard(item)')
 </template>
 

+ 101 - 0
src/components/common/Cart.vue

@@ -0,0 +1,101 @@
+<template lang="pug">
+    .cart(:style='{ width, height }')
+        .cart-total
+            h2.currency-cart-total {{ totalInCurrencyFormat() }}
+        .cart-items-wrapper
+            transition-group(name='list' tag='ul' class='cart-items')
+                cart-item(v-for='item in items' :key='item.id' :item='item')
+</template>
+
+<script>
+    import CartItem from './CartItem'
+
+    export default {
+        props: {
+            items: {
+                type: Array,
+                default: [],
+                required: true
+            },
+            width: {
+                type: String,
+                default: '300px'
+            },
+            height: {
+                type: String,
+                default: '100%'
+            },
+            total: {
+                type: Number,
+                default: 0
+            },
+            thousandsSeparator: {
+                type: String,
+                default: '.'
+            },
+            decimalPlaces: {
+                type: Number,
+                default: 0
+            },
+            decimalSeparator: {
+                type: String,
+                default: ','
+            },
+            currencySymbol: {
+                type: String,
+                default: '$'
+            },
+            symbolPosition: {
+                type: String,
+                default: 'before'
+            }
+        },
+        components: {
+            CartItem
+        },
+        methods: {
+            totalInCurrencyFormat() {
+                return this.total.toFixed(this.decimalPlaces).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,')
+            },
+            computeTotal() {
+                this.$emit('onTotalComputed', this.total)
+            },
+        },
+        data() {
+            return {
+                total: 0
+            }
+        }
+    }
+</script>
+
+<style lang="sass">
+    @import '../../assets/variables'
+    .cart
+        border-left: 1px solid $app-border-color
+        padding-left: 10px
+        display: inline-block
+        vertical-align: top
+        .cart-total
+            width: 100%
+            height: 50px
+            .currency-cart-total
+                width: 100%
+                height: 50px
+                margin: 0
+                font-size: 30pt
+        .cart-items-wrapper
+            width: 100%
+            height: calc(100% - 100px)
+            overflow-y: auto
+            overflow-x: hidden
+            .cart-items
+                width: 100%
+                padding: 0
+                margin: 0
+            .list-enter-active, .list-leave-active
+                transition: all 0.3s
+            .list-enter, .list-leave-to
+                opacity: 0
+                transform: translateX(300px)
+</style>

+ 144 - 0
src/components/common/CartItem.vue

@@ -0,0 +1,144 @@
+<template lang="pug">
+    li.cart-item
+        h3.item-name {{ getName() }}
+        input.item-quantity(type='number' min='1' :value='quantity' v-model='quantity')
+        span.item-x x
+        span.item-price {{ getPrice() }}
+        span.item-equals =
+        span.item-subtotal {{ getSubTotal() }}
+        .cart-item-options-wrapper
+            .cart-item-options
+                .cart-item-option(class='fa fa-plus')
+                .cart-item-option(class='fa fa-minus')
+                .cart-item-option(class='fa fa-trash')
+</template>
+
+<script>
+    export default {
+        props: {
+            item: {
+                type: Object,
+                default: {
+                    displayName: '',
+                    price: 0,
+                    quantity: 0
+                },
+                required: true
+            }
+        },
+        computed: {
+            quantity: {
+                get() {
+                    return this.item.quantity
+                },
+                set(value) {
+                    this.item.quantity = parseFloat(value) || 1
+                }
+            }
+        },
+        watch: {
+            item(value) {
+                console.log(value)
+            }
+        },
+        methods: {
+            getName() {
+                return this.item.displayName || 'No name'
+            },
+            getPrice() {
+                return this.item.price || 0
+            },
+            getSubTotal() {
+                return this.getPrice() * (this.quantity || 0)
+            }
+        }
+    }
+</script>
+
+<style lang="sass">
+    @import '../../assets/variables'
+    .cart-item
+        width: 100%
+        height: 90px
+        list-style: none outside none
+        border-bottom: 1px solid $app-border-color
+        box-sizing: border-box
+        position: relative
+        &:nth-child(1)
+            border-top: 1px solid $app-border-color
+        &:hover
+            transition-duration: 1000ms
+            border-bottom: 2px solid $app-main-color
+        .item-name
+            width: 100%
+            height: 20px
+            margin: 10px 0 5px 0
+            float: left
+            font-size: 8pt
+            display: inline-block
+        .item-quantity
+            width: 50px
+            height: 28px
+            margin-top: 6px
+            text-align: right
+            float: left
+            display: inline-block
+        .item-x
+            width: 20px
+            height: 20px
+            margin-top: 12px
+            text-align: right
+            float: left
+            display: inline-block
+        .item-price
+            width: 80px
+            height: 20px
+            margin-top: 12px
+            text-align: right
+            float: left
+            display: inline-block
+        .item-equals
+            width: 20px
+            height: 20px
+            margin-top: 12px
+            text-align: center
+            float: left
+            display: inline-block
+        .item-subtotal
+            width: 100px
+            height: 20px
+            margin-top: 12px
+            text-align: right
+            font-weight: bold
+            display: inline-block
+        .cart-item-options-wrapper
+            width: 100%
+            height: 20px
+            position: absolute
+            bottom: 0
+            display: flex
+            justify-content: center
+            .cart-item-options
+                width: 90px
+                height: 20px
+                border: 1px solid #d3d3d3
+                border-bottom: none
+                display: flex
+                justify-content: center
+                .cart-item-option
+                    width: 18px
+                    height: 18px
+                    margin: 0 5px
+                    color: #666
+                    &:hover
+                        cursor: pointer
+                    &.fa
+                        padding-left: 2px
+                        line-height: 20px
+                        &.fa-plus:hover
+                            color: #2196f3
+                        &.fa-minus:hover
+                            color: #ffc107
+                        &.fa-trash:hover
+                            color: #f44336
+</style>

+ 2 - 2
src/components/common/Spinner.vue

@@ -32,13 +32,13 @@
             background: $app-main-color
             margin: 0 3px 0 0
             display: inline-block
-            animation: spinner-bubbling $animation-duration infinite ease-in-out
+            animation: spinner-wave $animation-duration infinite ease-in-out
 
         @for $i from 1 through $rect-count
             .spinner-rect-#{$i}
                 animation-delay: - $animation-duration + $delay-range / ($rect-count - 1) * ($i - 1)
 
-        @keyframes spinner-bubbling
+        @keyframes spinner-wave
             0%, 40%, 100%
                 transform: scaleY(0.4)
             20%

+ 15 - 0
src/components/common/index.js

@@ -0,0 +1,15 @@
+import AddCard from './AddCard'
+import Card from './Card'
+import CardGrid from './CardGrid'
+import Cart from './Cart'
+import Searcher from './Searcher'
+import Spinner from './Spinner'
+
+export {
+    AddCard,
+    Card,
+    CardGrid,
+    Cart,
+    Searcher,
+    Spinner
+}

+ 18 - 0
src/components/forms/CustomerForm.vue

@@ -0,0 +1,18 @@
+<template lang="pug">
+    .customer-form
+</template>
+
+<script>
+    export default {
+        props: {
+            mode: {
+                type: String,
+                default: 'form'
+            }
+        }
+    }
+</script>
+
+<style lang="sass">
+    .customer-form
+</style>

+ 32 - 0
src/components/modals/CustomerModal.vue

@@ -0,0 +1,32 @@
+<template lang="pug">
+    modal(name='customer-modal' transition='nide-modal-fade' @before-close='beforeClose' :classes="['v--modal', 'customer-modal']")
+</template>
+
+<script>
+    export default {
+        props: {
+            title: {
+                type: String,
+                default: ''
+            },
+            show: {
+                type: Boolean,
+                default: false
+            }
+        },
+        methods: {
+            beforeClose(e) {
+                if (this.show) {
+                    e.stop()
+                }
+            }
+        },
+        mounted() {
+            console.log(this)
+        }
+    }
+</script>
+
+<style lang="sass">
+    .customer-modal
+</style>

+ 41 - 0
src/components/steps/Customer.vue

@@ -0,0 +1,41 @@
+<template lang="pug">
+    .pos-step
+        .customer-selection-step
+            .customer-selector
+                searcher(:items='customers' :keys="['name', 'displayName']")
+                card-grid(:items='customers' :loading='loadingCustomers' canAdd @onAdd='showCustomerForm')
+                customer-modal(:show='showingCustomerForm' @onAccept='submitCustomer')
+</template>
+
+<script>
+    import { mapGetters, mapActions } from 'vuex'
+    import { Searcher, CardGrid } from '@/components/common'
+
+    import CustomerModal from '@/components/modals/CustomerModal'
+
+    import { SHOW_CUSTOMER_FORM, SUBMIT_CUSTOMER } from '@/constants/actionTypes'
+
+    export default {
+        components: {
+            Searcher,
+            CardGrid
+        },
+        computed: mapGetters([
+            'customers',
+            'loadingCustomers',
+            'showingCustomerForm'
+        ]),
+        methods: mapActions([
+            SHOW_CUSTOMER_FORM,
+            SUBMIT_CUSTOMER
+        ])
+    }
+</script>
+
+<style lang="sass">
+    .pos-step
+        .customer-selection-step
+            width: 100%
+            height: 100%
+            display: flex
+</style>

+ 11 - 0
src/components/steps/Payment.vue

@@ -0,0 +1,11 @@
+<template lang="pug">
+    .pos-step
+</template>
+
+<script>
+    export default {
+    }
+</script>
+
+<style lang="sass">
+</style>

+ 12 - 5
src/components/steps/product/Main.vue → src/components/steps/Product.vue

@@ -2,23 +2,30 @@
     .pos-step
         .products-selector
             searcher(:items='products' :keys="['name', 'displayName']")
-            card-grid(:items='products' :loading='loadingProducts')
+            card-grid(:items='products' :loading='loadingProducts' @onSelect='selectProduct')
+        cart(:items='cartItems' @onTotalComputed='changeCartTotal')
 </template>
 
 <script>
     import { mapGetters, mapActions } from 'vuex'
+    import { Searcher, CardGrid, Cart } from '@/components/common'
 
-    import Searcher from '@/components/common/Searcher'
-    import CardGrid from '@/components/common/CardGrid'
+    import { SELECT_PRODUCT, CHANGE_CART_TOTAL } from '@/constants/actionTypes'
 
     export default {
         components: {
             Searcher,
-            CardGrid
+            CardGrid,
+            Cart
         },
         computed: mapGetters([
             'products',
-            'loadingProducts'
+            'loadingProducts',
+            'cartItems'
+        ]),
+        methods: mapActions([
+            SELECT_PRODUCT,
+            CHANGE_CART_TOTAL
         ])
     }
 </script>

+ 35 - 7
src/constants/actionTypes.js

@@ -1,13 +1,41 @@
-export const INIT_USER = 'INIT_USER'
+const INIT_USER = 'initUser'
 
-export const INIT_PRODUCTS = 'INIT_PRODUCTS'
+const INIT_PRODUCTS = 'initProducts'
 
-export const INIT_PAYMENT_TERMS = 'INIT_PAYMENT_TERMS'
+const SELECT_PRODUCT = 'selectProduct'
 
-export const INIT_JOURNALS = 'INIT_JOURNALS' 
+const INIT_PAYMENT_TERMS = 'initPaymentTerms'
 
-export const INIT_DATE = 'INIT_DATE'
+const INIT_JOURNALS = 'initJournals' 
 
-export const INIT_CUSTOMERS = 'INIT_CUSTOMERS'
+const INIT_DATE = 'initDate'
 
-export const INIT_CURRENCIES = 'INIT_CURRENCIES'
+const INIT_CUSTOMERS = 'initCustomers'
+
+const SHOW_CUSTOMER_FORM = 'showCustomerForm'
+
+const HIDE_CUSTOMER_FORM = 'hideCustomerForm'
+
+const SUBMIT_CUSTOMER = 'submitCustomer'
+
+const INIT_CURRENCIES = 'initCurrencies'
+
+const ADD_TO_CART = 'addToCart'
+
+const CHANGE_CART_TOTAL = 'changeCartTotal'
+
+export {
+    INIT_USER,
+    INIT_PRODUCTS,
+    SELECT_PRODUCT,
+    INIT_PAYMENT_TERMS,
+    INIT_JOURNALS,
+    INIT_DATE,
+    INIT_CUSTOMERS,
+    SHOW_CUSTOMER_FORM,
+    HIDE_CUSTOMER_FORM,
+    SUBMIT_CUSTOMER,
+    INIT_CURRENCIES,
+    ADD_TO_CART,
+    CHANGE_CART_TOTAL
+}

+ 44 - 14
src/constants/mutationTypes.js

@@ -1,28 +1,58 @@
+const SET_USER = 'setUser'
 
-export const SET_USER = 'SET_USER'
+const SET_LOADING_USER = 'setLoadingUser'
 
-export const SET_LOADING_USER = 'SET_LOADING_USER'
+const SET_PRODUCTS = 'setProducts'
 
-export const SET_PRODUCTS = 'SET_PRODUCTS'
+const SET_LOADING_PRODUCTS = 'setLoadingProducts'
 
-export const SET_LOADING_PRODUCTS = 'SET_LOADING_PRODUCTS'
+const SELECT_PRODUCT = 'selectProduct'
 
-export const SET_PAYMENT_TERMS = 'SET_PAYMENT_TERMS'
+const SET_PRODUCT_WITH_VARIANT = 'setProductWithVariant'
 
-export const SET_LOADING_PAYMENT_TERMS = 'SET_LOADING_PAYMENT_TERMS'
+const SET_PAYMENT_TERMS = 'setPaymentTerms'
 
-export const SET_JOURNALS = 'SET_JOURNALS'
+const SET_LOADING_PAYMENT_TERMS = 'setLoadingPaymentTerms'
 
-export const SET_LOADING_JOURNALS= 'SET_LOADING_JOURNALS'
+const SET_JOURNALS = 'setJournals'
 
-export const SET_DATE = 'SET_DATE'
+const SET_LOADING_JOURNALS= 'setLoadingJournals'
 
-export const SET_LOADING_DATE = 'SET_LOADING_DATE'
+const SET_DATE = 'setDate'
 
-export const SET_CUSTOMERS = 'SET_CUSTOMERS'
+const SET_LOADING_DATE = 'setLoadingDate'
 
-export const SET_LOADING_CUSTOMERS = 'SET_LOADING_CUSTOMERS'
+const SET_CUSTOMERS = 'setCustomers'
 
-export const SET_CURRENCIES = 'SET_CURRENCIES'
+const SET_LOADING_CUSTOMERS = 'setLoadingCustomers'
 
-export const SET_LOADING_CURRENCIES = 'SET_LOADING_CURRENCIES'
+const SET_SHOW_CUSTOMER_FORM = 'setShowCustomerForm'
+
+const SET_CURRENCIES = 'setCurrencies'
+
+const SET_LOADING_CURRENCIES = 'setLoadingCurrencies'
+
+const PUSH_TO_CART = 'pushToCart'
+
+const SET_CART_TOTAL = 'setCartTotal'
+
+export {
+    SET_USER,
+    SET_LOADING_USER,
+    SET_PRODUCTS,
+    SET_LOADING_PRODUCTS,
+    SELECT_PRODUCT,
+    SET_PAYMENT_TERMS,
+    SET_LOADING_PAYMENT_TERMS,
+    SET_JOURNALS,
+    SET_LOADING_JOURNALS,
+    SET_DATE,
+    SET_LOADING_DATE,
+    SET_CUSTOMERS,
+    SET_LOADING_CUSTOMERS,
+    SET_SHOW_CUSTOMER_FORM,
+    SET_CURRENCIES,
+    SET_LOADING_CURRENCIES,
+    PUSH_TO_CART,
+    SET_CART_TOTAL
+}

+ 9 - 3
src/constants/resourcePaths.js

@@ -1,7 +1,13 @@
 const BASE_URL = '/eiru_sales'
 
-export const INIT_SALE_URL = `${BASE_URL}/init`
+const INIT_SALE_URL = `${BASE_URL}/init`
 
-export const CREATE_CUSTOMER_URL = `${BASE_URL}/create_customer`
+const CREATE_CUSTOMER_URL = `${BASE_URL}/create_customer`
 
-export const PROCESS_SALE_URL = `${BASE_URL}/process`
+const PROCESS_SALE_URL = `${BASE_URL}/process`
+
+export {
+    INIT_SALE_URL,
+    CREATE_CUSTOMER_URL,
+    PROCESS_SALE_URL
+}

+ 1 - 1
src/store/actions.js

@@ -29,7 +29,7 @@ const actions = {
      */
     explodeData({ dispatch }, payload) {
         for (let value in payload) {
-            dispatch(`INIT_${value.split(/(?=[A-Z])/).join('_').toUpperCase()}`, payload[value])
+            dispatch(`init${value[0].toUpperCase()}${value.slice(1)}`, payload[value])
         }
     },
     /**

+ 3 - 1
src/store/index.js

@@ -3,6 +3,7 @@ import Vuex from 'vuex'
 
 import actions from '@/store/actions'
 
+import cart from '@/store/modules/cart'
 import currency from '@/store/modules/currency'
 import customer from '@/store/modules/customer'
 import date from '@/store/modules/date'
@@ -16,6 +17,7 @@ Vue.use(Vuex)
 const store = new Vuex.Store({
     actions,
     modules: {
+        cart,
         currency,
         customer,
         date,
@@ -24,7 +26,7 @@ const store = new Vuex.Store({
         product,
         user
     },
-    strict: false
+    strict: true
 })
 
 export default store

+ 87 - 0
src/store/modules/cart.js

@@ -0,0 +1,87 @@
+import { PUSH_TO_CART, SET_CART_TOTAL } from '@/constants/mutationTypes'
+import { ADD_TO_CART, CHANGE_CART_TOTAL } from '@/constants/actionTypes'
+
+const initialState = {
+    cartItems: [],
+    cartTotal: 0
+}
+
+const state = {
+    cartItems: initialState.cartItems,
+    cartTotal: initialState.cartTotal
+}
+
+const getters = {
+    /**
+     * 
+     * @param {*} state 
+     */
+    cartItems(state) {
+        return state.cartItems
+    },
+    /**
+     * 
+     * @param {*} state 
+     */
+    cartTotal(state) {
+        return state.cartTotal
+    }
+}
+
+const mutations = {
+    /**
+     * 
+     * @param {*} state 
+     * @param {*} payload 
+     */
+    [PUSH_TO_CART] (state, payload) {
+        let productFound = state.cartItems.find(item => item.id === payload.id)
+
+        if (productFound) {
+            productFound.quantity = productFound.quantity + 1
+            return
+        }
+
+        Object.assign(payload, {
+            quantity: 1,
+            price: payload.listPrice,
+            discount: 0
+        })
+        
+        state.cartItems = [payload, ...state.cartItems]
+    },
+    /**
+     * 
+     * @param {*} state 
+     * @param {*} payload 
+     */
+    [SET_CART_TOTAL] (state, payload) {
+        state.cartTotal = payload
+    }
+}
+
+const actions = {
+    /**
+     * 
+     * @param {*} param0 
+     * @param {*} payload 
+     */
+    [ADD_TO_CART] ({ commit }, payload) {
+        commit(PUSH_TO_CART, payload)
+    },
+    /**
+     * 
+     * @param {*} param0 
+     * @param {*} payload 
+     */
+    [CHANGE_CART_TOTAL] ({ commit }, payload) {
+        commit(SET_CART_TOTAL, payload)   
+    }
+}
+
+export default {
+    state,
+    getters,
+    mutations,
+    actions
+}

+ 2 - 2
src/store/modules/currency.js

@@ -62,6 +62,6 @@ const actions = {
 export default {
     state,
     getters,
-    actions,
-    mutations
+    mutations,
+    actions
 }

+ 45 - 6
src/store/modules/customer.js

@@ -1,14 +1,16 @@
-import { SET_CUSTOMERS, SET_LOADING_CUSTOMERS } from '@/constants/mutationTypes'
-import { INIT_CUSTOMERS } from '@/constants/actionTypes'
+import { SET_CUSTOMERS, SET_LOADING_CUSTOMERS, SET_SHOW_CUSTOMER_FORM } from '@/constants/mutationTypes'
+import { INIT_CUSTOMERS, SHOW_CUSTOMER_FORM, HIDE_CUSTOMER_FORM, SUBMIT_CUSTOMER } from '@/constants/actionTypes'
 
 const initialState = {
     customers: [],
-    loadingCustomers: false
+    loadingCustomers: false,
+    showingCustomerForm: false
 }
 
 const state = {
     customers: initialState.customers,
-    loadingCustomers: !initialState.loadingCustomers
+    loadingCustomers: !initialState.loadingCustomers,
+    showingCustomerForm: initialState.showingCustomerForm
 }
 
 const getters = {
@@ -25,6 +27,13 @@ const getters = {
      */
     loadingCustomers(state) {
         return state.loadingCustomers
+    },
+    /**
+     * 
+     * @param {*} state 
+     */
+    showingCustomerForm(state) {
+        return state.showingCustomerForm
     }
 }
 
@@ -44,6 +53,14 @@ const mutations = {
      */
     [SET_LOADING_CUSTOMERS] (state, payload) {
         state.loadingCustomers = !!payload
+    },
+    /**
+     * 
+     * @param {*} state 
+     * @param {*} payload 
+     */
+    [SET_SHOW_CUSTOMER_FORM] (state, payload) {
+        state.showingCustomerForm = !!payload
     }
 }
 
@@ -56,12 +73,34 @@ const actions = {
     [INIT_CUSTOMERS] ({ commit }, payload) {
         commit(SET_CUSTOMERS, payload)
         commit(SET_LOADING_CUSTOMERS)
+    },
+    /**
+     * 
+     * @param {*} param0 
+     * @param {*} payload 
+     */
+    [SHOW_CUSTOMER_FORM] ({ commit }) {
+        commit(SET_SHOW_CUSTOMER_FORM, true)
+    },
+    /**
+     * 
+     * @param {*} param0 
+     */
+    [HIDE_CUSTOMER_FORM] ({ commit }) {
+        commit(SET_SHOW_CUSTOMER_FORM, false)
+    },
+    /**
+     * 
+     * @param {*} param0 
+     */
+    [SUBMIT_CUSTOMER] ({ commit }) {
+        console.log('submit')
     }
 }
 
 export default {
     state,
     getters,
-    actions,
-    mutations
+    mutations,
+    actions
 }

+ 2 - 2
src/store/modules/date.js

@@ -62,6 +62,6 @@ const actions = {
 export default {
     state,
     getters,
-    actions,
-    mutations
+    mutations,
+    actions
 }

+ 2 - 2
src/store/modules/journal.js

@@ -62,6 +62,6 @@ const actions = {
 export default {
     state,
     getters,
-    actions,
-    mutations
+    mutations,
+    actions
 }

+ 2 - 2
src/store/modules/payment.js

@@ -61,6 +61,6 @@ const actions = {
 export default {
     state,
     getters,
-    actions,
-    mutations
+    mutations,
+    actions
 }

+ 45 - 6
src/store/modules/product.js

@@ -1,14 +1,18 @@
-import { SET_PRODUCTS, SET_LOADING_PRODUCTS } from '@/constants/mutationTypes'
-import { INIT_PRODUCTS } from '@/constants/actionTypes'
+import { SET_PRODUCTS, SET_LOADING_PRODUCTS, SET_PRODUCT_WITH_VARIANT } from '@/constants/mutationTypes'
+import { INIT_PRODUCTS, SELECT_PRODUCT, ADD_TO_CART } from '@/constants/actionTypes'
 
 const initialState = {
     products: [],
-    loadingProducts: false
+    loadingProducts: false,
+    showVariants: false,
+    productWithVariant: null
 }
 
 const state = {
     products: initialState.products,
-    loadingProducts: !initialState.loadingProducts
+    loadingProducts: !initialState.loadingProducts,
+    showVariants: initialState.showVariants,
+    productWithVariant: initialState.productWithVariant
 }
 
 const getters = {
@@ -25,6 +29,20 @@ const getters = {
      */
     loadingProducts(state) {
         return state.loadingProducts
+    },
+    /**
+     * 
+     * @param {*} state 
+     */
+    showVariants(state) {
+        return state.showVariants
+    },
+    /**
+     * 
+     * @param {*} state 
+     */
+    productWithVariant(state) {
+        return state.productWithVariant
     }
 }
 
@@ -44,6 +62,14 @@ const mutations = {
      */
     [SET_LOADING_PRODUCTS] (state, payload) {
         state.loadingProducts = !!payload
+    },
+    /**
+     * 
+     * @param {*} state 
+     * @param {*} payload 
+     */
+    [SET_PRODUCT_WITH_VARIANT] (state, payload) {
+        state.productWithVariant = payload
     }
 }
 
@@ -56,13 +82,26 @@ const actions = {
     [INIT_PRODUCTS] ({ commit }, payload) {
         commit(SET_PRODUCTS, payload)
         commit(SET_LOADING_PRODUCTS)
+    },
+    /**
+     * 
+     * @param {*} param0 
+     * @param {*} payload 
+     */
+    [SELECT_PRODUCT] ({ commit, dispatch }, payload) {
+        if (payload.variantCount > 1) {
+            commit(SET_PRODUCT_WITH_VARIANT, payload)
+            return
+        }
+
+        dispatch(ADD_TO_CART, payload.variants[0])
     }
 }
 
 export default {
     state,
     getters,
-    actions,
-    mutations
+    mutations,
+    actions
 }
 

+ 2 - 2
src/store/modules/user.js

@@ -62,6 +62,6 @@ const actions = {
 export default {
     state,
     getters,
-    actions,
-    mutations
+    mutations,
+    actions
 }