useState delete array element in the state containing object - javascript

my state orderDetail contain orderDetail json
I am getting the _id of the order which I want to delete in function eg _id: 60f1ab20891ced4818b5ea87,
now I want to remove this order from the orders array which is in orderdetail and update the state.
orderdetail = {
_id: 60f1ab20891ced4818b5ea86,
totalPrice: '400',
orders: [
{
_id: 60f1ab20891ced4818b5ea87,
quantity: '1',
price: 200,
name: 'Caramel Latte',
category: 'Steaming Cups'
},
{
_id: 60f1ab20891ced4818b5ea88,
quantity: '1',
price: 200,
name: 'Cinnamon Latte',
category: 'Steaming Cups'
}
],
confirm: 'done',
timestamp: 1626450720332,
name: 'xxx',
email: 'xxx',
}
what I did is clone state then uses for loop to find an index of the order then remove that index element in clone then update state to clone. any other less computation method?

What you need to so is set a new object with the orders array filtered as well as a new totalPrice.
For example
const [orderDetail, setOrderDetail] = useState( /* whatever */ )
const deleteOrder = (id) => {
setOrderDetail(prev => {
// filter out the order by ID
const orders = prev.orders.filter(({ _id }) => _id !== id)
return {
...prev,
orders, // overwrite orders
totalPrice: orders.reduce((total, { quantity, price }) =>
total + quantity * price, 0), // calculate new total
timestamp: Date.now() // perhaps you want to update this too
}
})
}
This uses the functional update version of the useState() hook to easily get access to the previous state value.

Related

Trying to iterate through an object's values and insert into new object (JS)

I am trying to create a series of new objects using the values from an existing object to push to my database.
Here is the existing object:
{
name: 'Pasta',
method: 'Cook pasta',
ingredients: [
{ measure: 'tbsp', quantity: '1', ingredient_name: 'lemon' },
{ measure: 'g', quantity: '1', ingredient_name: 'salt' },
{ measure: 'packet', quantity: '1', ingredient_name: 'spaghetti' },
{ measure: 'litre', quantity: '1', ingredient_name: 'water' }
]
}
Basically I have a function that inserts and returns the id of the recipe into one table, then inserts and returns/or finds the ids of the relevant ingredients and the final part (with which I am struggling) is to combine the returned recipe_id, ingredient_id and the correct measure and quantity (as written in the object above).
Here is where I have gotten to:
//starting point is here
async function addNewRecipe(newRecipe, db = connection) {
console.log(newRecipe)
const recipeDetails = {
recipe_name: newRecipe.name,
recipe_method: newRecipe.method,
}
const ingredientsArray = newRecipe.ingredients
const [{ id: recipeId }] = await db('recipes')
.insert(recipeDetails)
.returning('id')
const ingredientsWithIds = await getIngredients(ingredientsArray) //returns an array of ids
ingredientsWithIds.forEach((ingredientId) => {
let ingredientRecipeObj = {
recipe_id: recipeId, //works
ingredient_id: ingredientId, //works
measure: newRecipe.ingredients.measure, //not working - not sure how to match it with the relevant property in the newRecipe object above.
quantity: newRecipe.ingredients.quantity,//not working - not sure how to match it with the relevant property in the newRecipe object above.
}
//this is where the db insertion will occur
})
}
The desired output would be:
ingredientRecipeObj = {
recipe_id: 1
ingredient_id: 1
measure: tbsp
quantity: 1
} then insert this into db
followed by:
ingredientRecipeObj = {
recipe_id: 1
ingredient_id: 2
measure: g
quantity: 1
} then insert into db
etc. etc.
The problem seems to be that the function "getIngredients" returns only the IDs. Once you have fetched them, you have no way of knowing which ID is for which ingredient. One way to change that is to make the method return an array of both the ID and the ingredient name. Then you could match them like this:
const ingredientsWithIds = await getIngredients(ingredientsArray) //now an array of objects with ingredient_name and id
ingredientsWithIds.forEach((ingredient) => {
const recipeIngredient = ingredientsArray.find(ri => ri.ingredient_name === ingredient.ingredient_name)
const ingredientRecipeObj = {
recipe_id: recipeId,
ingredient_id: ingredient.id,
measure: recipeIngredient.measure,
quantity: recipeIngredient.quantity,
}
//this is where the db insertion will occur
})
Since you haven't posted the "getIngredients" function it is hard to say exactly how to adapt it to return the name as well.

Manipulating Data Array in React and Graphql

I'm attempting to manipulate this data in react with graphql. As you can see, I have this data or input in the graphql playground, and this is how I wanted the input to look:
In my frontend, I have a cartItem with an objects inside and array, including the product name, id, and so on. I wanted the input to look like the example I provided above. Is there a way to make that happen?
Codes and Data
This is how my cart's Item Data looks.
CartItem Data:
[
{
id: "6109401fd86d352a70e3694e",
name: "asasasasa",
sku: "sasa",
shippingTime: "1628812800000",
quantity: 1,
},
{
id: "61051c14f25d8830a8e238c0",
name: "Pringles Sour Cream & Onion Potato Crisps 158g",
sku: "sad89f79dsafs",
shippingTime: "1627084800000",
quantity: 1,
},
];
As stated in the preceding example, all I wanted was the product's id and quantity.
Order.js
const [cartItems, setCartItems] = useContext(CartContext);
const [createOrder, { data, loading }] = useMutation(CREATE_ORDER_MUTATION);
const qty = cartItems.map(({ quantity }) => {
return quantity;
});
const cartItemId = cartItems.map(({ id }) => {
return id;
});
function onSubmit() {
createOrder({
variables: {
qty: qty,
products: cartItemId,
paymentMethod: paymentMethod,
address: address,
},
})
}
Whenever I need to console someone. If you log the cartItemId, you'll get something like this:
Same goes with my qty.
Please let me know if you have any other questions or require any additional code, and I will gladly offer it.
Apollo Mutation:
const CREATE_ORDER_MUTATION = gql`
mutation createOrder(
$qty: Int!
$products: String!
$paymentMethod: String!
$address: String!
) {
createOrder(
orderedItems: [{ qty: $qty, products: $products }]
paymentMethod: $paymentMethod
address: $address
) {
id
orderedItems {
qty
products {
id
name
sku
description
}
}
}
}
`;
The code below will transform the cartItems into the desired result. You can loop through the cartItems and create an object with the required structure for each item.
const orderedItems = cartItems.map(({ id, quantity }) => {
return {
qty: quantity,
products: id,
};
});
Complete code will look something like this
const [cartItems, setCartItems] = useContext(CartContext);
const [createOrder, { data, loading }] = useMutation(CREATE_ORDER_MUTATION);
// Restructure the array to desired format
const orderedItems = cartItems.map(({ id, quantity }) => {
return {
qty: quantity,
products: id,
};
});
console.log(orderedItems); // To check if it looks correct
function onSubmit() {
createOrder({
variables: {
orderedItems: orderedItem,
paymentMethod: paymentMethod,
address: address,
},
})
}

How to post every object using axios

As my "finalArr" has many items, how can I post every item using map. Below code works fine if I have only one item. But I'm facing problem when "finalArr" have more items in it.
const orders = [{
name: finalArr[0][0].name,
productImage: finalArr[0][0].productImage,
price: finalArr[0][0].price,
quantity: finalArr[0][1],
}, ];
const customerData = {
username,
orders,
};
axios
.post("http://localhost:5000/api/cart", customerData)
.then((res) => {
console.log(res.data);
})
Use Array.prototype.map. Try below:
const orders = finalArr.map(e => ({
name: e[0].name,
productImage: e[0].productImage,
price: e[0].price,
quantity: e[1],
}));

Insert online shopping cart items into MongoDB using Mongoose

I am attempting to insert a cart of items as a JSON object into a MongoDB collection using a mongoose schema.
The customer's ID is getting stored (which comes from the User DB), but the cart items are not. Here is my code:
Sample order data contained in local variable app.js called cartData: { data:[] }:
{
data: [
item {
name: "Product Name 1",
price: '2.99',
sku: '13579',
count: 8
},
item {
name: 'Product Name 2',
price: '21.99',
sku: '24680',
count: 2
}
]
}
Cart.js (Cart Schema):
const mongoose = require("mongoose")
const CartSchema = new mongoose.Schema({
customerID: {
type: String,
required: true
},
cartContents: {
type: [Object]
},
date: {
type: Date,
default: Date.now
}
}, { collection: "ordersDB" })
const Cart = mongoose.model('Cart', CartSchema)
module.exports = Cart
app.js (Order Submit Code):
const Cart = require("../models/Cart")
const customerID = req.user.customerID //Acquired from user database
const newOrder = new Cart({
customerID,
cartData
})
newOrder.save()
.then(customer => {
req.flash("successful", "Your order has been submitted!")
res.redirect("/somepage")
})
.catch(err => console.log(err))
Result:
_id: abcd1234
> cart: Object
> type: Array
> <The Infinite Abyss Of Nothingness aka Empty>
customerID: "1234567890"
date: 2019-12-11T21:14:40.825+00:00
__v: 0
Any insight on this problem would be greatly appreciated.
Based on provided schema Mongoose expects you to pass a field called cartContents. Any other field not compatible with your schema will be ignored. To fix that just name your field explicitly:
const newOrder = new Cart({
customerID,
cartContents: cartData
})

Create random data during Promise.all

I'd like to create a mock data based on a JSON array to test front-end.
Object structure in the JSON array:
Mock:
{
category: string,
items: string[]
}
Category:
{
name: string,
products: Product[]
}
Product:
{
name: string,
prices: Price[]
}
Price:
{
date: Date,
value: number
}
I'd like to create random Prices for each Product, therefore I created the following helper function:
// Creates Price array with random values within a given time window
// `times` is a `lodash` function
const getRandomPrices = (numberOfDays, minValue, maxValue) => times(numberOfDays, n => ({
date: new Date(new Date().setDate(new Date().getDate() - n)),
value: Math.floor(Math.random() * maxValue) + minValue
}))
And I’m seeding my MongoDB database with the following function:
// data is Mock[]
// Price, Product and Category are MongoDB schemas
const createCategories = data.map(async c => {
const createProducts = c.items.map(async p => {
const prices = getRandomPrices(15, 100, 1000)
const createPrices = prices.map(price => Price.create(price))
return Product.create({
name: p,
prices: await Promise.all(createPrices)
})
})
return Category.create({
name: c.category,
products: await Promise.all(createProducts)
})
})
await Promise.all(createCategories)
console.log('done')
My problem is that I have same Price data for any Product in any Category and my questions are:
how can I randomize prices?
where am I doing wrong?

Categories