How do I add woocommerce endpoint to the state?

I’m sorry,
I realized that I was putting the wrong data in frontity.settings,

the correct way is:

...
state: {
   source: {
     api: "https://wp.laotramirada.com.uy/wp-json",
     postTypes: [
       {
         type: 'product',
         endpoint: 'product',
         archive: 'product',
       }
     ]              
   },
 }
...

Should I combine a handler with postTypes to get all the necessary data?

Not sure if combining the handler with postTypes will work. I think the best option is to choose between:

  • Using a custom endpoint and use a handler to point to that data.
  • Using the CPT product and add more info (if necessary) from your WordPress.

Just to clarify it a bit more we have two cases:

If you use the CPT you defined

With that settings, you are telling Frontity to fetch that CPT. As you have defined it:

  • If you access to https://mysite.com/product/first-product (from Frontity) you’ll be getting the info from the endpoint https://wp.mysite.com/wp-json/wp/v2/product?slug=first-product (from your WP).
  • If you access to https://mysite.com/product you’ll be getting a list of all your products, fetched from https://wp.mysite.com/wp-json/wp/v2/product?slug=first-product.

You could add more info to that endpoint from your WP.

If you use your own handler

We usually use handlers to fetch data from a custom endpoint, or to change the way we populate the state.

With the handler you are telling Frontity: if we access the url https://mysite.com/products/slug you are going to run the function defined inside it. Inside this function, we usually fetch data from a new endpoint, and how we populate the frontity.state in order to consume that info later.

If you want to show a lists of your products when you access https://mysite.com/products, you’d need to create a new handler to match that pattern, and fetch all the products from your endpoint.

You’d need a new handler for example if you want to point to woocommerce API instead of wp-json/wp/v2.


In this case, if you’re fetching the data from a CPT, I guess the best option would be to use the CPT without a handler. And if you want to fetch the data from a different endpoint you may want to use a handler.

Let us know if this info helps you :slightly_smiling_face:

Hi Mario,
If I access to /product/polo I get “is404”… :sleepy:

I’ve created a repo to share the code if you have time to see it

thks

I found a handler to get all data:

const homeHandler = {
  name: 'home',
  priority: 20,
  pattern: '/',

  func: async ({ route, params, state, libraries }) => {
    // 1. get products data
    const response = await libraries.source.api.get({
      endpoint: '/wc/v3/products',
    });

    // 2. add product to state
    const productsData = await response.json();

    // 3. add route to data
    Object.assign(state.source.data[route], {
      productsData,
      isHome: true
    });
  }
}

With the products in the state,
I can implement operations such as adding to the cart, generating the order, etc.

I update when I have progress :smiley:

6 Likes

This is great :blush:

I can’t wait to see the final result @vscopise

Do you have a handler for the individual products? Something like this:

const homeHandler = {
  name: 'producto',
  priority: 10,
  pattern: '/producto/:slug',
  func: async ({ route, params, state, libraries }) => {
    // 1. get products data
    const response = await libraries.source.api.get({
      endpoint: '/wc/v3/products',
      params: { slug: params.slug }
    });

    // 2. add product to state
    const [product] = await libraries.source.populate({ state, response });

    // 3. add route to data
    Object.assign(state.source.data[route], {
      id: product.id,
      isProduct: true
    });
  }
}

Then access the data using:

const data = state.source.get(state.router.link);
const product = state.source.product[data.id];

Just curious. We’ve never worked with the woocommerce API :man_shrugging:

Here is the handler to get a product :grinning:

const productHandler = {
  name: 'product',
  priority: 10,
  pattern: '/product/:slug',

  func: async ({ route, params, state, libraries }) => {

    // 1. get product data
    const response = await libraries.source.api.get({
      endpoint: '/wc/v3/products',
      params: { slug: params.slug}
    });

    // 2. add product to state
    const productData = await response.json();        

    // 3. add route to data
    Object.assign(state.source.data[route], {
      productData,
      isProduct: true
    });

  }
}
1 Like

Nice! :slight_smile:

I would like to share the code done so far to see your opinions
https://github.com/vscopise/frontity-wc :slightly_smiling_face:

I would also like to ask you if you recommend Bootstrap, Material-UI or if you prefer another UI-framework to Frontity

Our recommended framework is Chakra UI because it works seamlessly with Emotion :+1:

Looks great so far. Thanks for sharing :smile:

1 Like

2 posts were split to a new topic: Illegal escape sequence in your template literal

I can save and get the cart from the localstorage:

const addToCart = ({ state, actions }) => ({ productId, quantity }) => {
  state.theme.cart.push({ productId, quantity });
  localStorage.setItem(
    'frontity_wc_cart',
    JSON.stringify(state.theme.cart)
  );
  actions.theme.calculateCartTotal();
}


...
actions: {
  theme: {
    afterCSR: ({ state, actions, libraries }) => {
      const cachedCart = window.localStorage.getItem('frontity_wc_cart');
      if (cachedCart && cachedCart.length !== 0) {
        state.theme.cart = JSON.parse(cachedCart);
        state.theme.cart.map(cartItem => {
          //here I need to read the details of the products of the cart 
          //and save them in the state
        });
      }
    }
  }

How can I get the details of the products stored in the cart?

As far as I can tell you should do it in the same way as desribed by @luisherranz in How do I add woocommerce endpoint to the state?

Does it not work? What approaches have you tried? Do you have an errors that occur with your solution?

@luisherranz describes a handler to load a product, which is not necessary now, since I handle products like Custom Post Types.
Now I need to load the products from the shopping cart (which I charge from localStorage) at the start of the app, I have the product id(s) from the localStorage

Thks! :grinning:

Using localStorage now I be able to get the saved cart, in my connected component:

const HeaderCart = ({ state, actions }) => {
  ...

  if (state.frontity.platform === 'client') {
    if ( 0 === state.theme.cart.length ) {
      const storedCart = localStorage.getItem(
        'frontity_wc_cart'
      );

      if (storedCart && storedCart.length !== 0) {
        state.theme.cart = JSON.parse(storedCart);
        state.theme.cart.map(cartItem => {

          // here i need to fetch each product from the api...

        })
      };
    }
  }

Do I need a handler to get each product?

the solution was a handler to read the necessary products:

const HeaderCart = ({ state, actions }) => {
  ...
  
  useEffect(() => {
    if (state.frontity.platform === 'client') {
      if (0 === state.theme.cart.length) {
        const storedCart = localStorage.getItem(
          'frontity_wc_cart'
        );
        if (storedCart && storedCart.length !== 0) {
          state.theme.cart = JSON.parse(storedCart);
          state.theme.cart.map(cartItem => {
            actions.source.fetch(
              `/product/${cartItem.productId}`,
            );
          })
        };
      }
    }
  }, []);

and the handler:

export const productHandler = {
  name: 'product',
  priority: 10,
  pattern: '/product/:slug',
  func: async ({ route, params, state, libraries }) => {
    // 1. get product
    const response = await libraries.source.api.get({
      endpoint: `product/${params.slug}`,
    });
    // 2. add product to state
    const [product] = await libraries.source.populate({ response, state });
    // 3. add route to data
    Object.assign(state.source.data[route], { product });
  }
}

It is important to consider when the product is loaded in the state to be able to display it in the component

Thanks everybody ! :grinning:

1 Like

Great work @vscopise!! :clap:

Out of curiousity: why did you end up using useEffect instead of afterCSR to do the fetches?

Good point @luisherranz,

now the handler is in afterCSR.

Until now you can see my progress in
https://frontity-wc.now.sh/
https://github.com/vscopise/frontity-wc
:v: :v:

1 Like

Hey @vscopise! This method is awesome. I only just got around to trying it out. Did you ever get around to figuring out the payment handling and sending the order back to wordpress for processing? Working on it now, just curious if you already found a decent method.

1 Like