diff --git a/examples/nextjs/components/Cart/Cart.js b/examples/nextjs/components/Cart/Cart.js index 4b9ee60d..107a09d7 100644 --- a/examples/nextjs/components/Cart/Cart.js +++ b/examples/nextjs/components/Cart/Cart.js @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useContext } from 'react'; import Link from 'next/link'; import Image from 'next/image'; import { useCheckout, useCart } from '@nacelle/react-hooks'; @@ -8,6 +8,7 @@ import { formatCurrency } from '@nacelle/react-dev-utils'; import ItemQuantity from 'components/ItemQuantity'; import useDetectDevice from 'hooks/useDetectDevice'; import * as styles from './Cart.styles'; +import { EventLogContext } from 'providers/EventDispatcher'; const checkoutCredentials = { nacelleSpaceId: process.env.NACELLE_SPACE_ID, @@ -21,9 +22,10 @@ const Cart = () => { checkoutCredentials, cart ); - + const { dispatchEvent } = useContext(EventLogContext); useEffect(() => { if (checkoutData) { + dispatchEvent({ type: 'CHECKOUT_INIT', payload: checkoutData }); const { processCheckout } = checkoutData.data; window.location = processCheckout.url; } @@ -75,6 +77,7 @@ const Cart = () => { const CartItem = ({ item, cartActions, isMobile }) => { const [itemQuantity, updateQuantity] = useState(item.quantity || 0); + const { dispatchEvent } = useContext(EventLogContext); const formatPrice = formatCurrency(item.locale, item.priceCurrency); @@ -96,7 +99,10 @@ const CartItem = ({ item, cartActions, isMobile }) => { return updateQuantity(qty); }; - const removeItemFromCart = () => cartActions.removeFromCart(item); + const removeItemFromCart = () => { + dispatchEvent({ type: 'REMOVE_FROM_CART', payload: item }); + return cartActions.removeFromCart(item); + }; return (
diff --git a/examples/nextjs/components/ProductCard/ProductCard.js b/examples/nextjs/components/ProductCard/ProductCard.js index bb616eb0..7cede00e 100644 --- a/examples/nextjs/components/ProductCard/ProductCard.js +++ b/examples/nextjs/components/ProductCard/ProductCard.js @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React, { useState, useContext } from 'react'; import Link from 'next/link'; import Image from 'next/image'; import { useCart } from '@nacelle/react-hooks'; @@ -8,6 +8,7 @@ import { formatCurrency } from '@nacelle/react-dev-utils'; import ItemQuantity from 'components/ItemQuantity'; import useDetectDevice from 'hooks/useDetectDevice'; import * as styles from './ProductCard.styles'; +import { EventLogContext } from 'providers/EventDispatcher'; const LinkPDP = ({ pdpLink, children }) => { if (!pdpLink) { @@ -34,6 +35,7 @@ const ProductCard = ({ const [quantity, setQuantity] = useState(0); const [, { addToCart, toggleCart }] = useCart(); const device = useDetectDevice(); + const { dispatchEvent } = useContext(EventLogContext); const productLink = `/products/${product.handle}`; const productVariant = product.variants[0]; @@ -44,8 +46,8 @@ const ProductCard = ({ const addItemToCart = () => { const item = { ...product, variant: productVariant, quantity }; - addToCart(item); + dispatchEvent({ type: 'ADD_TO_CART', payload: item }); return toggleCart(); }; diff --git a/examples/nextjs/pages/_app.js b/examples/nextjs/pages/_app.js index f24e65ea..9ace67cc 100644 --- a/examples/nextjs/pages/_app.js +++ b/examples/nextjs/pages/_app.js @@ -6,17 +6,20 @@ import { CartProvider } from '@nacelle/react-hooks'; import Layout from 'components/Layout'; import $nacelle from 'services/nacelle.js'; import { ProductSearchProvider } from 'providers/ProductSearch'; +import { EventDispatcherProvider } from 'providers/EventDispatcher'; import * as styles from 'styles/global.styles'; function MyApp({ Component, pageProps, space, products }) { return ( - - - - - + + + + + + + ); } diff --git a/examples/nextjs/pages/pages/[handle].js b/examples/nextjs/pages/pages/[handle].js index df01eee9..db8895b7 100644 --- a/examples/nextjs/pages/pages/[handle].js +++ b/examples/nextjs/pages/pages/[handle].js @@ -1,11 +1,17 @@ -import React from 'react'; +import React, { useEffect, useContext } from 'react'; import { useRouter } from 'next/router'; import $nacelle from 'services/nacelle.js'; import { dataToPaths } from 'utils'; +import { EventLogContext } from 'providers/EventDispatcher'; const Page = ({ page }) => { const router = useRouter(); + const { dispatchEvent } = useContext(EventLogContext); + useEffect(() => { + dispatchEvent({ type: 'PAGE_VIEW' }); + }, []); + // If the page is not yet generated, this will be displayed // initially until getStaticProps() finishes running if (router.isFallback) { diff --git a/examples/nextjs/pages/products/[handle].js b/examples/nextjs/pages/products/[handle].js index 7c9dbd23..7c2e3094 100644 --- a/examples/nextjs/pages/products/[handle].js +++ b/examples/nextjs/pages/products/[handle].js @@ -1,14 +1,20 @@ -import React from 'react'; +import React, { useEffect, useContext } from 'react'; import { useRouter } from 'next/router'; import $nacelle from 'services/nacelle'; import { dataToPaths } from 'utils'; import ProductCard from 'components/ProductCard'; import * as styles from 'styles/pages.styles'; +import { EventLogContext } from 'providers/EventDispatcher'; const ProductDetail = ({ product }) => { const router = useRouter(); + const { dispatchEvent } = useContext(EventLogContext); + useEffect(() => { + dispatchEvent({ type: 'PRODUCT_VIEW', payload: product }); + }, []); + // If the page is not yet generated, this will be displayed // initially until getStaticProps() finishes running if (router.isFallback) { diff --git a/examples/nextjs/providers/EventDispatcher.js b/examples/nextjs/providers/EventDispatcher.js new file mode 100644 index 00000000..3a650a52 --- /dev/null +++ b/examples/nextjs/providers/EventDispatcher.js @@ -0,0 +1,63 @@ +import React, { useEffect, useReducer } from 'react'; + +export const EventLogContext = React.createContext(); + +const eventReducer = (state, event) => { + if ( + event.type === 'PAGE_VIEW' || + event.type === 'PRODUCT_VIEW' || + event.type === 'ADD_TO_CART' || + event.type === 'REMOVE_FROM_CART' || + event.type === 'CHECKOUT_INIT' + ) { + return [...state, event]; + } + return state; +}; + +export const EventDispatcherProvider = ({ children }) => { + const [eventLog, dispatchEvent] = useReducer(eventReducer, []); + + useEffect(() => { + if (eventLog.length > 0 && typeof window !== 'undefined') { + const event = eventLog.pop(); + switch (event.type) { + case 'PAGE_VIEW': + console.log('PAGE VIEW EVENT FIRED'); + break; + case 'PRODUCT_VIEW': + console.log( + 'PRODUCT_VIEW EVENT FIRED', + JSON.stringify(event.payload, null, 2) + ); + break; + case 'ADD_TO_CART': + console.log( + 'ADD_TO_CART EVENT FIRED', + JSON.stringify(event.payload, null, 2) + ); + break; + case 'REMOVE_FROM_CART': + console.log( + 'REMOVE_FROM_CART EVENT FIRED', + JSON.stringify(event.payload, null, 2) + ); + break; + case 'CHECKOUT_INIT': + console.log( + 'CHECKOUT_INIT EVENT FIRED', + JSON.stringify(event.payload, null, 2) + ); + break; + default: + break; + } + } + }, [eventLog]); + + return ( + + {children} + + ); +};