I have a problem when I add a product the totalAmount shows me 20 I don't know why? and if I increment the totalAmount doesn't move how can I do it?
thanks
ts.file
productList = [
{ id: 1, name: 'Louis Vuis', price: 10, qtn: 1 },
{ id: 2, name: 'shubert helmet', price: 20, qtn: 1 },
];
productArray: any = [];
totalAmount: number;
ngOnInit() {
this.totalPrice();
}
add(product, idx) {
const found = this.productArray.find(
item => JSON.stringify(item) === JSON.stringify(product)
);
if (found) {
this.productArray[idx].qtn++;
} else {
this.productArray.push(product);
}
}
totalPrice() {
this.productList.forEach(item => {
this.totalAmount = (item.qtn * item.price)
console.log(this.totalAmount);
});
}
The problem is somewhere else I feel. What you are doing is right
totalPrice() {
this.productList.forEach(item => {
this.totalAmount = (item.qtn * item.price)
console.log(this.totalAmount);
});
}
But you are iterating the javascript object and assigning the value to total amount.
So while Iterating if you want to show price of each Item based on quantity you need to assign the value within a new key of product.
Something Like item.total = (item.qtn * item.price);
Incase you want to display the sum of all value in totalAmount you will need to do this.totalAmount += (item.qtn * item.price)
and when you add Quantity increment the quantity by 1 that you are doing , update the state and call this.totalPrice()
There are multiple issues,
When adding a product you are adding that in productArray but when calculating totalAmount you are calculating from productList. This will give you constant totalAmount no matter how many product you add in the productArray.
this.totalAmount = (item.qtn * item.price) will reassign the updated value into totalAmount instead of adding to the previous value. You need to write, this.totalAmount += (item.qtn * item.price)
From my understanding I am updating the totalPrice method. Not sure if it will help or not,
totalPrice() {
this.productList.forEach(item => {
let productIndexInProductArray = productArray.findIndex(p => p.id === item.id);
if(productIndexInProductArray > -1) {
this.totalAmount += (productArray[productIndexInProductArray].qtn * item.price)
console.log(this.totalAmount);
}
});
}
totalAmount: number=0;
this.totalAmount += (item.qtn * item.price)
Problem is totalAmount id define but not initialized
So first change is need to initialize totalAmount
totalAmount: number = 0;
Second change is need to do in totalPrice function because every time when you calculate amount that item amount set to totalAmount so totalAmount reset with every item that why you get last item amount in console. you need to add item amount in totalAmount like below
totalPrice() {
this.productList.forEach(item => {
this.totalAmount += (item.qtn * item.price)
console.log(this.totalAmount);
});
}
Related
So I have this app I made where it calculates the menu items total and includes a $5 delivery fee. The problem is the 4th option only includes the $5 fee in the total, but the other 3 options don't include the fee
Here's my codepen
https://codepen.io/shodoro/pen/dydNopX
Why is my 4th option, the smoothie $4 the only input checkbox that adds the delivery fee correctly?
The first 3 options don't include the $5 delivery fee in the total and I don't know how to fix it
Here's my JS
function updatePrice() {
let items = 0;
let deliveryFee = document.getElementById('fee')
let tax = document.getElementById('tax')
let tip = document.getElementById('tip')
tax = .1
tip = .2
document.querySelectorAll('input[type=checkbox]').forEach(checkBox => {
if (checkBox.checked) {
items += +checkBox.value
deliveryFee = 5
} else {
deliveryFee = 0
}
})
document.getElementById("price").textContent = `Food Total: $${(items).toFixed(2)}`;
document.getElementById("tax").textContent = `Tax (10%): $${(items * tax).toFixed(2)}`;
document.getElementById("tip").textContent = `Tip (20%): $${(items * tip).toFixed(2)}`;
document.getElementById("total").textContent = `Your order total is: $${((items * tax)+(items * tip)+(items)+(deliveryFee)).toFixed(2)}`;
}
Essential I want all options to include the delivery fee when clicking them, but also making sure the delivery fee resets to 0 whenever you uncheck all options.
That's because you are setting deliveryFee in a loop and so if, for example, the 12 piece wings item is checked, then it sets deliveryFee to 5 and then it's going to loop through to the next item (6 piece wings) and it will set deliveryFee to 0. So when it gets to the calculation for the total, it deliveryFee will be 0 and not 5. I think maybe you want something more like this:
function updatePrice() {
console.log('updatePrice');
let items = 0;
let deliveryFee = 0;
let tax = document.getElementById('tax')
let tip = document.getElementById('tip')
tax = .1
tip = .2
console.log('before forEach loop', items, deliveryFee);
document.querySelectorAll('input[type=checkbox]').forEach(checkBox => {
console.log(checkBox);
if (checkBox.checked) {
console.log('checked!')
items += +checkBox.value
if (deliveryFee == 0) {
console.log('First checked item, setting delivery fee to 5.')
deliveryFee = 5;
}
} else {
console.log('not checked!');
}
})
console.log('after forEach loop', items, deliveryFee);
if (items >= 10) {
deliveryFee = deliveryFee * 2;
}
let orderTotal = (items * tax)+(items * tip)+(items) + deliveryFee;
document.getElementById("price").textContent = `Food Total: $${(items).toFixed(2)}`;
document.getElementById("tax").textContent = `Tax (10%): $${(items * tax).toFixed(2)}`;
document.getElementById("tip").textContent = `Tip (20%): $${(items * tip).toFixed(2)}`;
document.getElementById("fee").textContent = `Delivery Fee: $${deliveryFee.toFixed(2)}`;
document.getElementById("total").textContent = `Your order total is: $${orderTotal}`;
}
How do I filter the data in collection in Firestore
If the first letter is "+" then I want to get filtered in Income section if the first letter is "-" then I want to get filtered in Expenditure Section
I tried this, but not working:
const getUsers = async()=>{
total_income_amount = await db.collection("users").get().then((querySnapshot) => {
const sum = querySnapshot.docs.filter((item) => item > 0).reduce((a, b) => a + b.data().amount, 0)
return sum
})
}
I am getting the output as 0
and I want the output with two decimal places
EDIT
Here's my code:
total_amount = db.collection("users").get().then((querySnapshot) => {
var total_sum = 0;
var income_sum = 0;
var exp_sum = 0;
querySnapshot.docs.forEach(doc => {
const amount = doc.data().amount;
amount >= 0.0? income_sum += amount : exp_sum -= amount;
total_sum += amount;
});
return {total: total_sum, income: income_sum, expense: exp_sum }
}).finally(result => console.log("Total: ", result));
You can loop through the list of values and append the values once rather than looping through it 5 times with a reduce & filter
total_amount = db.collection("users").get().then((querySnapshot) => {
var total_sum = 0;
var income_sum = 0;
var exp_sum = 0;
querySnapshot.docs.forEach(doc => {
const amount = doc.data().amount;
amount >= 0.0? income_sum += amount : exp_sum -= amount;
total_sum += amount;
});
return {total: total_sum, income: income_sum, expense: exp_sum }
})
.finally(result => console.log("TOTALS", result);
EDIT
It's not good to make major changes to your Question
but in general, you can truncate all number's to a decimal place using toFixed() on the final output
https://www.w3schools.com/jsref/jsref_tofixed.asp
UPDATE
Ensure your numbers are converted to real numbers from user inputs with Number(value) if the typeof returned is not a number, you can know if it is valid or not.
Once this has been done, ensure you return the correct calls as needed as scripts also only fire once.
when rendering values inside HTML, you want to use an embedded <span> tag with the appropriate id tag rather than editing it via javascript
Why is this helper function returning a value for subtotal and tax but NAN for fees and ordertotal?
OrderSummary.jsx
const taxRate = 0.0925;
const OrderSummary = ({ addCSS, classes, merchantId, merchantName, step, setStep }) => {
const context = useContext(ProductContext);
let items = Array.isArray(context.cart) ? context.cart : [];
if (step === 4) {
items = Array.isArray(context.order) ? context.order : [];
}
const subtotal = items.reduce((acc, cur) => {
return acc + cur.total * (cur.company_id === merchantId) * 1;
}, 0);
let tax = subtotal * taxRate;
tax = parseFloat(tax.toFixed(2));
let fee = subtotal * ApplicationFee * 0.01;
fee = parseFloat(fee.toFixed(2));
const total = subtotal + tax + fee;
<LineItem>
<S2>Subtotal</S2>
<S2>{formatCurrency(subtotal)}</S2>
</LineItem>
<LineItem>
<S2>Tax</S2>
<S2>{formatCurrency(tax)}</S2>
</LineItem>
<LineItem>
<S2>Fee</S2>
<S2>{formatCurrency(fee)}</S2>
</LineItem>
<Total>
<H5>Order Total</H5>
<H5>{formatCurrency(total)}</H5>
</Total>
helperFunctions.jsx
export const formatCurrency = (num) => {
if (typeof num !== 'number') return num
return new Intl.NumberFormat('en-US', {style: 'currency', currency: 'USD'}).format(num)
}
addTotals = () => {
let subTotal = 0;
this.state.cart.map((item) => (subTotal += item.total));
const tempFees = subTotal * ApplicationFee * 0.01;
const fees = parseFloat(tempFees.toFixed(2));
const total = subTotal + fees;
this.setState(() => {
return {
cartSubTotal: subTotal,
cartFees: fees,
cartTotal: total,
};
});
};
Image shows a Subtotal and Tax being calculated but NAN for Fee and Order Total
Believe it or not, but NaN (Not A Number) is a number:
typeof NaN !== 'number' // false
... so your first check just misses that case, and NaN (as value) gets nicely formatted to $NaN string by Intl.NumberFormat.
So you should consider checking how exactly fee is calculated in your case. This might fix your orderTotal, too (any calculation involving NaN results in NaN).
Another option is adding specific NaN check to your formatting function to prevent showing weird characters, like this:
if (Number.isNaN(num)) // ...
... but it's really hard to tell what should be displayed in this case.
I was making an expense tracker basic code (without ui, only the initial script), but i had a problem while trying to console.log the sum of the total spent money by the user, my code only doubles the spent money for each bought item so i decided to ask here for help.
The code:
//initial code
const account = {
name: 'user',
expenses: [],
addExpense: function(description, amount) {
account.expenses.push({
description: description,
amount: amount
});
},
getAccountSummary: function() {
let expenses = account.expenses;
for (let i = 0; i < expenses.length; i++ ) {
let value = expenses[i].amount + expenses[i].amount;
console.log(value);
}
}
}
//output calls
account.addExpense('Milk', 8);
account.addExpense('Netflix', 30);
account.addExpense('Steam summer sale', 26);
account.addExpense('Coffee', 4);
console.log(account.getAccountSummary());
The code always logs this values below:
16
60
52
8
which are actually the double of the input values (8, 30, 26, 4).
The output i'm looking for is the sum of all of those value which is in this case:
68
Hope my question was clear.
When you want a value that is based on items in an array, then you should be looking at reduce
const account = {
name: 'user',
expenses: [],
addExpense: function(description, amount) {
account.expenses.push({
description: description,
amount: amount
});
},
getAccountSummary: function() {
return account.expenses.reduce((acc,{amount}) => acc+amount,0);
}
}
expenses[i].amount is been added 2 times at let value = expenses[i].amount + expenses[i].amount;, that's why is been doubled.
If you want to print the sum inside the getAccountSummary, you can do something like this:
getAccountSummary: function() {
const expenses = account.expenses;
let value = 0
for (let i = 0; i < expenses.length; i++ ) {
value += expenses[i].amount;
}
console.log(value);
}
But if you want to return the sum on getAccountSummary so you can print it (which seems more reasonable), then you could do this:
getAccountSummary: function() {
const expenses = account.expenses;
let value = 0
for (let i = 0; i < expenses.length; i++ ) {
value += expenses[i].amount;
}
return value;
}
And you should be able to call console.log(account.getAccountSummary());
You can use forEach() to iterate over expenses as well.
In your getAccountSummary
Use
let value = 0;
for (let i = 0; i < expenses.length; i++ ) {
value += expenses[i].amount ;
console.log(value);
}
Hope it will help you.
The main issue was that you were logging the values directly, instead of returning them for later logging.
Also, there's no need to use the "function" keyword in modern Javascript.
Here's my solution, gives the expected output.
const account = {
name: 'user',
expenses: [],
addExpense(description, amount) {
account.expenses.push({
description: description,
amount: amount
});
},
getAccountSummary() {
return account.expenses.reduce((result, expense) => result + expense.amount, 0)
}
}
//output calls
account.addExpense('Milk', 8);
account.addExpense('Netflix', 30);
account.addExpense('Steam summer sale', 26);
account.addExpense('Coffee', 4);
console.log(account.getAccountSummary()); // 68
I have an object, this.items, that I am running a for in on, then using the find method to get all the products by id. I'm attempting to set a salesTax amount based on a conditional (if taxPercent > 0), but the loop is going through more than the expected amount of times and thus the taxPercent is larger than required.
total() {
let total = 0
let tax = []
let importDuty = .05
for (let productId in this.items) {
total += this.inventory.products.find(product => {
if (product.taxPercent > 0) {
tax.push(product.price * product.taxPercent)
}
return product.id == productId
}).price * this.items[productId]
}
tax = tax.reduce((a, b) => a + b, 0)
let importDutyToApply = total * importDuty
total = total + importDutyToApply + tax
let response = {
'total': total,
'tax': tax
}
return response
}
I'm wondering how I can set the total tax to apply for any items that do not have the taxPercent set to 0. So, if I had three items and one of them required a 10 percent tax on $100, the total should be $10. Likewise if I had many items with some requiring the 10 percent tax and others not, it would only add up for the ones that require it. Any thoughts?
The function you pass to find gets called a load of times. You just want to add tax for the product it found, not for everything it looked at on the way.
const product = this.inventory.products.find( product => product.id == productId );
if (product.taxPercent > 0) {
tax.push(product.price * product.taxPercent)
}
total += product.price * this.items[productId]