import { ComposableFunctionArgs , Context , Logger , } from '@vue-storefront/core' ; import { AddConfigurableProductsToCartInput , AddDownloadableProductsToCartInput , AddVirtualProductsToCartInput , AddProductsToCartInput , Cart , CartItem , Product , RemoveItemFromCartInput , UpdateCartItemsInput , } from '@vue-storefront/magento-api' ; import { UseCartFactoryParams , useCartFactory , } from '../../factories/useCartFactory' ; const factoryParams = { load : async ( context , params ) => { const apiState = context . $magento . config . state ; Logger . debug ( '[Magento Storefront]: Loading Cart' ) ; const customerToken = apiState . getCustomerToken ( ) ; const virtual = ! params . realCart ; const createVirtualCart = ( ) => ( null as Cart ) ; const createRealCart = async ( ) : Promise < string > => { Logger . debug ( '[Magento Storefront]: useCart.load.createNewCart' ) ; apiState . setCartId ( ) ; const { data } = await context . $magento . api . createEmptyCart ( ) ; Logger . debug ( '[Result]:' , { data } ) ; apiState . setCartId ( data . createEmptyCart ) ; return data . createEmptyCart ; } ; const getCartData = async ( id ) => { Logger . debug ( '[Magento Storefront]: useCart.load.getCartData ID->' , id ) ; const { data , errors } = await context . $magento . api . cart ( id ) ; Logger . debug ( '[Result]:' , { data } ) ; if ( ! data ?. cart && errors ?. length ) { throw errors [ 0 ] ; } return data . cart as unknown as Cart ; } ; const getCart = async ( virtualCart , cartId ? ) => { if ( ! cartId ) { if ( virtualCart ) { return createVirtualCart ( ) ; } cartId = await createRealCart ( ) ; apiState . setCartId ( cartId ) ; } return getCartData ( cartId ) ; } ; if ( customerToken ) { try { const { data , errors } = await context . $magento . api . customerCart ( ) ; Logger . debug ( '[Result]:' , { data , errors } ) ; if ( ! data ?. customerCart && errors ?. length ) { throw errors [ 0 ] ; } apiState . setCartId ( data . customerCart . id ) ; return data . customerCart as unknown as Cart ; } catch { apiState . setCustomerToken ( ) ; } } try { const cartId = apiState . getCartId ( ) ; return await getCart ( virtual , cartId ) ; } catch { apiState . setCartId ( ) ; return await getCart ( virtual ) ; } } , addItem : async ( context , { product , quantity , currentCart , customQuery , } ) => { Logger . debug ( '[Magento]: Add item to cart' , { product , quantity , currentCart , } ) ; const apiState = context . $magento . config . state ; let currentCartId = apiState . getCartId ( ) ; if ( ! currentCartId ) { await factoryParams . load ( context , { realCart : true , } ) ; currentCartId = apiState . getCartId ( ) ; } if ( ! product ) { return ; } try { switch ( product . __typename ) { case 'SimpleProduct' : const simpleCartInput = { cartId : currentCartId , cartItems : [ { quantity , sku : product . sku , } , ] , } ; const simpleProduct = await context . $magento . api . addProductsToCart ( simpleCartInput ) ; Logger . debug ( '[Result]:' , { data : simpleProduct } ) ; return simpleProduct . data . addProductsToCart . cart as unknown as Cart ; case 'ConfigurableProduct' : const cartItems = [ { parent_sku : product . sku , data : { quantity , sku : product . configurable_product_options_selection ?. variant ?. sku || '' , } , } , ] ; const configurableCartInput = { cart_id : currentCartId , cart_items : cartItems , } ; const configurableProduct = await context . $magento . api . addConfigurableProductsToCart ( configurableCartInput ) ; Logger . debug ( '[Result]:' , { data : configurableProduct } ) ; return configurableProduct . data . addConfigurableProductsToCart . cart as unknown as Cart ; case 'BundleProduct' : const createEnteredOptions = ( ) => product . bundle_options . map ( ( bundleOption ) => ( { ... bundleOption , value : bundleOption . value . toString ( ) , } ) ) ; const bundleCartInput = { cartId : currentCartId , cartItems : [ { quantity , sku : product . sku , entered_options : createEnteredOptions ( ) , } , ] , } ; const bundleProduct = await context . $magento . api . addProductsToCart ( bundleCartInput ) ; Logger . debug ( '[Result]:' , { data : bundleProduct } ) ; return bundleProduct . data . addProductsToCart . cart as unknown as Cart ; case 'DownloadableProduct' : const downloadableCartItems = [ { data : { quantity , sku : product . sku , } , downloadable_product_links : product . downloadable_product_links . map ( ( dpl ) => ( { link_id : dpl . id } ) ) , } , ] ; const downloadableCartInput = { cart_id : currentCartId , cart_items : downloadableCartItems , } ; const downloadableProduct = await context . $magento . api . addDownloadableProductsToCart ( downloadableCartInput ) ; Logger . debug ( '[Result DownloadableProduct]:' , { data : downloadableProduct } ) ; return downloadableProduct . data . addDownloadableProductsToCart . cart as unknown as Cart ; case 'VirtualProduct' : const virtualCartInput = { cart_id : currentCartId , cart_items : [ { data : { quantity , sku : product . sku , } , } , ] , } ; const virtualProduct = await context . $magento . api . addVirtualProductsToCart ( virtualCartInput ) ; Logger . debug ( '[Result VirtualProduct]:' , { data : virtualProduct } ) ; return virtualProduct . data . addVirtualProductsToCart . cart as unknown as Cart ; default : throw new Error ( `Product Type ${ product . __typename } not supported in add to cart yet` ) ; } } catch { await factoryParams . clear ( context , null ) ; await factoryParams . addItem ( context , { product , quantity , currentCart , customQuery , } ) ; } } , removeItem : async ( context , { currentCart , product , } ) => { Logger . debug ( '[Magento]: Remove item from cart' , { product , currentCart , } ) ; const item = currentCart . items . find ( ( cartItem ) => cartItem . uid === product . uid ) ; if ( ! item ) { return ; } const removeItemParams = { cart_id : currentCart . id , cart_item_uid : item . uid , } ; const { data } = await context . $magento . api . removeItemFromCart ( removeItemParams ) ; Logger . debug ( '[Result]:' , { data } ) ; return data . removeItemFromCart . cart as unknown as Cart ; } , updateItemQty : async ( context , { currentCart , product , quantity , } ) => { Logger . debug ( '[Magento]: Update product quantity on cart' , { product , quantity , currentCart , } ) ; const updateCartParams = { cart_id : currentCart . id , cart_items : [ { cart_item_uid : product . uid , quantity , } , ] , } ; try { const { data } = await context . $magento . api . updateCartItems ( updateCartParams ) ; Logger . debug ( '[Result]:' , { data } ) ; return data . updateCartItems . cart as unknown as Cart ; } catch { return await factoryParams . load ( context , { realCart : true , } ) ; } } , clear : ( context , _params = null ) => { context . $magento . config . state . setCartId ( null ) ; return factoryParams . load ( context , { } ) ; } , applyCoupon : async ( context , { currentCart , couponCode , } ) => { Logger . debug ( '[Magento]: Apply coupon on cart' , { couponCode , currentCart , } ) ; const { data } = await context . $magento . api . applyCouponToCart ( { cart_id : currentCart . id , coupon_code : couponCode , } ) ; Logger . debug ( '[Result]:' , { data } ) ; return { updatedCart : data . applyCouponToCart . cart as unknown as Cart , updatedCoupon : { code : couponCode } , } ; } , removeCoupon : async ( context , { currentCart } ) => { Logger . debug ( '[Magento]: Remove coupon from cart' , { currentCart } ) ; const { data } = await context . $magento . api . removeCouponFromCart ( { cart_id : currentCart . id , } ) ; Logger . debug ( '[Result]:' , { data } ) ; return { updatedCart : data . removeCouponFromCart . cart as unknown as Cart , updatedCoupon : { code : '' } , } ; } , isInCart : ( context , { currentCart , product , } ) => ! ! currentCart ?. items . find ( ( cartItem ) => cartItem . product . uid === product . uid ) , } ; export default useCartFactory < Cart , CartItem , Product > ( factoryParams ) ;