1

I want to "overwrite" my cart. So I get the information I want but the problem is I can't get the information of my old cart. I don't get it how it cannot be properly retrieved. And whole the time I'm getting quantity of 1.

Here is the app.post request:

app.post("/add-to-cart/:id", async (req, res) => {
  try {
    // fetch your data
    const id = req.params.id,
      { data } = await axios.get("http://localhost:4200/products"),
      singleProduct = await data.find((product) => product._id === id);

    // create/get a cart
    let cart;
    if (!req.session.cart) {
      req.session.cart = cart = new Cart({});
    } else {
      // req.session does not save the Cart object, but saves it as JSON objects
      cart = new Cart(req.session.cart ? req.session.cart : {});
    }
    console.log("This is variable cart: ",cart)
    cart.addProduct(singleProduct);
    res.redirect("/");
    console.log(req.session)
  } catch (error) {
    console.log(error);
  }
});

It seems that something is wrong here: let cart = new Cart(req.body.cart ? req.body.cart : {});

So this is the console.log output:

enter image description here

This is the Cart code:

module.exports = function Cart(oldCart) {
    this.productItems = oldCart.productItems || {};
    this.totalQty = oldCart.totalQty || 0.00;
    this.totalPrice = oldCart.totalPrice || 0.00;
    
    this.addProduct = function(item) {
        
        let storedItem = this.productItems;
              
        if (!storedItem){
            storedItem = this.productItems = {item: item, qty: 0, price: 0};
        }
        else{
            storedItem.qty++;
            this.totalQty ++;
            storedItem = {item: item, qty: storedItem.qty, price: storedItem.price}
            
            storedItem.price = storedItem.item.price * storedItem.qty;
            
            console.log("item from database",storedItem)
            
            this.totalPrice += storedItem.item.price;
        }
    }

    };
Jan Tuđan
  • 233
  • 3
  • 17
  • What is the code for `Cart`? – theusaf Aug 28 '21 at 22:42
  • I updated it in my question. – Jan Tuđan Aug 28 '21 at 22:43
  • It doesn't look like `Cart` has an `add()` method, but there is an `addProduct()` method. Is that the method you meant to use? – theusaf Aug 28 '21 at 22:46
  • `cart.addProduct(singleProduct, id);` like @theusaf said – flakerimi Aug 28 '21 at 22:50
  • Not really... I wanted to use default function `add()` which is contained in `Mongoose` if I'm not mistaken, perhaps something in `MongoDB` could be combined in this way? – Jan Tuđan Aug 28 '21 at 22:50
  • `cart` is instance of `Cart`, maybe you want to use `push` – flakerimi Aug 28 '21 at 22:53
  • Okay, my mistake, apologies, I needed to use `addProduct()` function, but still I have an issue, it says `Cannot read property '' of undefined` – Jan Tuđan Aug 28 '21 at 23:08
  • I updated my question, please take a look, I'd be thankful. – Jan Tuđan Aug 28 '21 at 23:13
  • @JanTuđan It is likely due to `this.productItems` being undefined? If you pass an empty object into your `Cart` constructor, `this.productItems` becomes undefined, thus "Cannot read property 'documentId' of undefined" – theusaf Aug 29 '21 at 03:18
  • @theusaf yes, and the old cart is being undefined, do you know how to fix this to work properly? I updated a question for a bit. – Jan Tuđan Aug 31 '21 at 13:39
  • What is `req.body` at the start? (try logging before the `try`/`catch` statement.) Are you using any request body middleware? – theusaf Aug 31 '21 at 14:47
  • At the start it is empty. How it should be? I'm not using any middleware. – Jan Tuđan Aug 31 '21 at 14:57
  • To confirm, `req.body` returns `{}` and you are not using any middleware, like `app.use(express.json())`, etc? – theusaf Aug 31 '21 at 15:26
  • Yes `req.body` returns `{}`, but for the 2nd part of your question, I'm sorry I wasn't sure if usage like this is middleware, to be more correct I'm using `app.use(express.json())` + `app.use(cors());` and I'm using `axios` to communicate with other microservice. – Jan Tuđan Aug 31 '21 at 15:35
  • From that, it seems like it could also be a problem with your client-side code, not posting the data properly? Could you provide that code as well? – theusaf Aug 31 '21 at 15:36
  • Well until now I was just trying to post the data with `Postman` and total quantity was constantly 1. And when I tried to res.send(req.body) with app.get i just get the `{}` so I don't really get what's the problem. I haven't established a connection between that route and the frontend yet if you think so, maybe that's the problem? – Jan Tuđan Aug 31 '21 at 15:44
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/236612/discussion-between-theusaf-and-jan-tudan). – theusaf Aug 31 '21 at 15:45

1 Answers1

1

You can use the express-session package to store session data on the server-side per session/user:

const session = require("express-session");

app.use(session({
  secret: "some secret"
}));

app.post("/add-to-cart/:id", async (req, res) => {
  try {
    // fetch your data
    const id = req.params.id,
      { data } = await axios.get("http://localhost:4200/products"),
      singleProduct = await data.find((product) => product._id === id);

    // create/get a cart
    let cart;
    if (!req.session.cart) {
      cart = new Cart({});
    } else {
      // req.session does not save the Cart object, but saves it as JSON objects
      cart = new Cart(req.session.cart);
    }
    req.session.cart = cart;
    cart.addProduct(singleProduct);
    res.redirect("/");
  } catch (error) {
    console.log(error);
  }
});

Then, if the client needs to fetch the cart data, you can create a path for that:

app.get("/get-cart", (req, res) => {
  const cartData = req.session.cart || {};
  res.send(JSON.stringify(cartData));
});

In the code you provided, I also noticed some issues with your Cart class.

When setting your default values of totalQty and totalPrice, you use oldCart.totalQty || oldCart.totalQty==0.00, which will set it to the totalQty, or a boolean which checks if the totalQty is 0.00.

Also, your addProduct function checks if storedItem is falsey/truthy, which it will always be truthy (default value = {}), result in your logic using an empty object for your item, and resulting in prop of undefined errors.

To fix this: do something like:

module.exports = function Cart(oldCart) {
  this.productItems = oldCart.productItems || {};
  this.totalQty = oldCart.totalQty || 0;
  this.totalPrice = oldCart.totalPrice || 0.00;

  this.addProduct = function(item) {
    let storedItem = this.productItems;
    if (!storedItem.hasOwnProperty("item")) {
      storedItem = this.productItems = {item: item, qty: 1, price: item.price};
      this.totalQty = 1;
      this.totalPrice = item.price;
    } else {
      storedItem = {item: item, qty: storedItem.qty, price: storedItem.price};
      console.log("STORED ITEM: ", storedItem);
      this.productItems = storedItem;
      storedItem.qty++;
      storedItem.price = storedItem.item.price * storedItem.qty;
      this.totalQty++;
      this.totalPrice += storedItem.item.price;
    }
  }
}
theusaf
  • 1,781
  • 1
  • 9
  • 19
  • Okay, the session works, I get the previous cart but the problem is that I get the price of null and quantity of undefined. Total quantity goes maximum to 1. – Jan Tuđan Aug 31 '21 at 18:19
  • This doesn't work for me, everything is 0 when I test it – Jan Tuđan Aug 31 '21 at 19:11
  • I updated my question how this looks like now, it seems it's the problem with cart logic. – Jan Tuđan Aug 31 '21 at 19:11
  • @JanTuđan It was due to me forgetting to set `req.session.cart` to the new cart when there was a cart already. See updated answer, which should fix the problem (at least, everything works when I tested it) – theusaf Aug 31 '21 at 20:30
  • Wow thanks alot man this perfectly works! Two more things, Can I get this as simple json data? Because I need to output this in frontend. And 2nd thing if I just want specific things like product name, quantity, price, how to do that? Because I have some data which I don't want to send. – Jan Tuđan Aug 31 '21 at 20:51
  • well, the `app.get()` code in the answer sends the json of it. If you don't want to send certain keys, you can: create a copy of the object, and delete the unwanted keys, or create an object with only the data you want from the source object. – theusaf Aug 31 '21 at 21:20
  • But they are sent as a string and I can't control with them. And I got another issue, on the first time console shows me nothing, second time it shows me price and quantity are equal to 0, and the fourth time it shows me quantity of 2, and price * 2 – Jan Tuđan Aug 31 '21 at 21:26
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/236626/discussion-between-theusaf-and-jan-tudan). – theusaf Aug 31 '21 at 21:28
  • this is the question which bothers me now, take a look when you can: https://stackoverflow.com/questions/69006505/trying-to-send-data-from-client-side-but-req-session-doesnt-work-properly – Jan Tuđan Sep 01 '21 at 10:45