added discount
This commit is contained in:
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
<link rel="icon" type="image/png" href="/favicon.png" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>LB Quote Generator</title>
|
<title>LB Quote Generator</title>
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
BIN
public/favicon.png
Normal file
BIN
public/favicon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 571 B |
22
quotes.json
22
quotes.json
@ -460,5 +460,27 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"shippingCost": 0
|
"shippingCost": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2908,
|
||||||
|
"date": "March 20, 2026",
|
||||||
|
"customer": {
|
||||||
|
"name": "test",
|
||||||
|
"address": "",
|
||||||
|
"city": "",
|
||||||
|
"province": "on",
|
||||||
|
"postalCode": "",
|
||||||
|
"phone": "",
|
||||||
|
"email": ""
|
||||||
|
},
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"Item ID": "MDL-5H2",
|
||||||
|
"Description": "Earth Drill, 5.5HP Honda, 20:1Transmission",
|
||||||
|
"Price": 4674.3552899999995,
|
||||||
|
"quantity": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"shippingCost": 0
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -4,21 +4,27 @@ import { Plus } from 'lucide-react';
|
|||||||
export default function ItemSelector({ items, onAddItem }) {
|
export default function ItemSelector({ items, onAddItem }) {
|
||||||
const [selectedItemIndex, setSelectedItemIndex] = useState('');
|
const [selectedItemIndex, setSelectedItemIndex] = useState('');
|
||||||
const [quantity, setQuantity] = useState(1);
|
const [quantity, setQuantity] = useState(1);
|
||||||
|
const [discount, setDiscount] = useState('');
|
||||||
|
|
||||||
const handleAdd = () => {
|
const handleAdd = () => {
|
||||||
if (selectedItemIndex !== '' && quantity > 0) {
|
if (selectedItemIndex !== '' && quantity > 0) {
|
||||||
const selectedItem = items[selectedItemIndex];
|
const selectedItem = items[selectedItemIndex];
|
||||||
onAddItem({ ...selectedItem, quantity: parseInt(quantity, 10) });
|
onAddItem({
|
||||||
|
...selectedItem,
|
||||||
|
quantity: parseInt(quantity, 10),
|
||||||
|
discount: parseFloat(discount) || 0
|
||||||
|
});
|
||||||
setSelectedItemIndex('');
|
setSelectedItemIndex('');
|
||||||
setQuantity(1);
|
setQuantity(1);
|
||||||
|
setDiscount('');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="glass-card no-print">
|
<div className="glass-card no-print">
|
||||||
<h2>Add Items to Quote</h2>
|
<h2>Add Items to Quote</h2>
|
||||||
<div className="form-grid" style={{ alignItems: 'flex-end', gridTemplateColumns: '1fr 80px auto' }}>
|
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '1rem', alignItems: 'flex-end' }}>
|
||||||
<div className="form-group">
|
<div className="form-group" style={{ flex: '1 1 250px' }}>
|
||||||
<label htmlFor="itemSelect">Select Product</label>
|
<label htmlFor="itemSelect">Select Product</label>
|
||||||
<select
|
<select
|
||||||
id="itemSelect"
|
id="itemSelect"
|
||||||
@ -33,18 +39,36 @@ export default function ItemSelector({ items, onAddItem }) {
|
|||||||
))}
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div className="form-group">
|
<div className="form-group" style={{ flex: '0 0 auto' }}>
|
||||||
|
<label htmlFor="discount">Discount (%)</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
id="discount"
|
||||||
|
min="0"
|
||||||
|
max="100"
|
||||||
|
style={{ width: '100px' }}
|
||||||
|
value={discount}
|
||||||
|
onChange={(e) => setDiscount(e.target.value)}
|
||||||
|
placeholder="0"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="form-group" style={{ flex: '0 0 auto' }}>
|
||||||
<label htmlFor="quantity">Quantity</label>
|
<label htmlFor="quantity">Quantity</label>
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
id="quantity"
|
id="quantity"
|
||||||
min="1"
|
min="1"
|
||||||
style={{ width: '80px' }}
|
style={{ width: '100px' }}
|
||||||
value={quantity}
|
value={quantity}
|
||||||
onChange={(e) => setQuantity(e.target.value)}
|
onChange={(e) => setQuantity(e.target.value)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<button className="btn btn-primary" onClick={handleAdd} disabled={selectedItemIndex === ''}>
|
<button
|
||||||
|
className="btn btn-primary"
|
||||||
|
onClick={handleAdd}
|
||||||
|
disabled={selectedItemIndex === ''}
|
||||||
|
style={{ flex: '0 0 auto', height: '44px' }}
|
||||||
|
>
|
||||||
<Plus size={20} /> Add
|
<Plus size={20} /> Add
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -24,7 +24,11 @@ export default function QuoteSummary({ items, customer, shippingCost, onShipping
|
|||||||
};
|
};
|
||||||
|
|
||||||
const calculateSubtotal = () => {
|
const calculateSubtotal = () => {
|
||||||
return items.reduce((total, item) => total + (item.Price * item.quantity), 0);
|
return items.reduce((total, item) => {
|
||||||
|
const itemTotal = item.Price * item.quantity;
|
||||||
|
const discountAmount = itemTotal * ((item.discount || 0) / 100);
|
||||||
|
return total + (itemTotal - discountAmount);
|
||||||
|
}, 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
const subtotal = calculateSubtotal();
|
const subtotal = calculateSubtotal();
|
||||||
@ -55,19 +59,25 @@ export default function QuoteSummary({ items, customer, shippingCost, onShipping
|
|||||||
<th>Item ID</th>
|
<th>Item ID</th>
|
||||||
<th>Description</th>
|
<th>Description</th>
|
||||||
<th>Unit Price</th>
|
<th>Unit Price</th>
|
||||||
|
<th>Discount</th>
|
||||||
<th>Quantity</th>
|
<th>Quantity</th>
|
||||||
<th>Total</th>
|
<th>Total</th>
|
||||||
<th className="no-print">Action</th>
|
<th className="no-print">Action</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{items.map((item, index) => (
|
{items.map((item, index) => {
|
||||||
|
const itemTotal = item.Price * item.quantity;
|
||||||
|
const discountAmount = itemTotal * ((item.discount || 0) / 100);
|
||||||
|
const finalPrice = itemTotal - discountAmount;
|
||||||
|
return (
|
||||||
<tr key={index}>
|
<tr key={index}>
|
||||||
<td>{item['Item ID']}</td>
|
<td>{item['Item ID']}</td>
|
||||||
<td>{item.Description}</td>
|
<td>{item.Description}</td>
|
||||||
<td>{formatCurrency(item.Price)}</td>
|
<td>{formatCurrency(item.Price)}</td>
|
||||||
|
<td>{item.discount ? `${item.discount}%` : '-'}</td>
|
||||||
<td>{item.quantity}</td>
|
<td>{item.quantity}</td>
|
||||||
<td>{formatCurrency(item.Price * item.quantity)}</td>
|
<td>{formatCurrency(finalPrice)}</td>
|
||||||
<td className="no-print">
|
<td className="no-print">
|
||||||
<button
|
<button
|
||||||
className="btn btn-icon btn-danger"
|
className="btn btn-icon btn-danger"
|
||||||
@ -78,7 +88,8 @@ export default function QuoteSummary({ items, customer, shippingCost, onShipping
|
|||||||
</button>
|
</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
))}
|
);
|
||||||
|
})}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user