I’m excited to share something from my recent project work. While I can’t reveal the full details of the project just yet, I wanted to contribute a useful component that I believe many of you might find helpful in your own applications.
As part of my work, I needed to build a VAT (Value Added Tax) calculator that would help users calculate tax amounts accurately and efficiently. Being part of the FSI (Financial Services Industry) community, I’ve always believed in sharing knowledge and helping others grow. So, I decided to extract this component and share it as open source.
The calculator I’m sharing today isn’t just your basic tax calculator – it’s a professional-grade React component that handles different currencies, VAT rates, and even gives users the flexibility to add or remove VAT from amounts. Whether you’re building an e-commerce platform, accounting software, or just need a reliable way to calculate VAT, this component has got you covered.
VAT Calculator with React – Open Source Code
<div id="vat-calculator"></div>
<script>
const { useState } = React;
function VATCalculator() {
const [amount, setAmount] = useState(0);
const [vatRate, setVatRate] = useState(20);
const [calculationType, setCalculationType] = useState("Add VAT");
const [currency, setCurrency] = useState("GBP");
const [rounding, setRounding] = useState("nearest");
const [vatAmount, setVatAmount] = useState(0);
const [totalAmount, setTotalAmount] = useState(0);
const handleCalculation = () => {
let vat = 0;
let total = 0;
if (calculationType === "Add VAT") {
vat = amount * (vatRate / 100);
total = amount + vat;
} else if (calculationType === "Remove VAT") {
vat = amount - amount / (1 + vatRate / 100);
total = amount - vat;
}
// Handle rounding
if (rounding === "nearest") {
vat = Math.round(vat * 100) / 100;
total = Math.round(total * 100) / 100;
}
setVatAmount(vat);
setTotalAmount(total);
};
return (
<div style={{ maxWidth: "500px", margin: "auto", padding: "20px", borderRadius: "10px", backgroundColor: "#f4f4f4", color: "#343a40" }}>
<h2 style={{ color: "#bf7f00" }}>VAT Calculator</h2>
<p>The VAT Calculator is a quick and easy tool for calculating VAT on goods and services. It helps businesses and individuals add or remove VAT from any amount, ensuring accuracy when invoicing or budgeting. Whether you’re a business calculating VAT to pay or a customer checking VAT on a purchase, this tool simplifies your tax calculations.</p>
<div className="form-group" style={{ marginBottom: "15px" }}>
<label htmlFor="amount">Amount ({currency}):</label>
<input type="number" id="amount" value={amount} onChange={(e) => setAmount(parseFloat(e.target.value))} placeholder="Enter amount" style={{ width: "100%", padding: "10px", fontSize: "16px", borderRadius: "5px", border: "1px solid #ccc" }} />
</div>
<div className="form-group" style={{ marginBottom: "15px" }}>
<label htmlFor="vat-rate">VAT Rate (%):</label>
<input type="number" id="vat-rate" value={vatRate} onChange={(e) => setVatRate(parseFloat(e.target.value))} placeholder="Enter VAT rate" style={{ width: "100%", padding: "10px", fontSize: "16px", borderRadius: "5px", border: "1px solid #ccc" }} />
</div>
<div className="form-group" style={{ marginBottom: "15px" }}>
<label htmlFor="calculation-type">Calculation Type:</label>
<select id="calculation-type" value={calculationType} onChange={(e) => setCalculationType(e.target.value)} style={{ width: "100%", padding: "10px", fontSize: "16px", borderRadius: "5px", border: "1px solid #ccc" }}>
<option value="Add VAT">Add VAT</option>
<option value="Remove VAT">Remove VAT</option>
</select>
</div>
<div className="form-group" style={{ marginBottom: "15px" }}>
<label htmlFor="currency">Currency:</label>
<select id="currency" value={currency} onChange={(e) => setCurrency(e.target.value)} style={{ width: "100%", padding: "10px", fontSize: "16px", borderRadius: "5px", border: "1px solid #ccc" }}>
<option value="GBP">GBP</option>
<option value="EUR">EUR</option>
<option value="USD">USD</option>
</select>
</div>
<div className="form-group" style={{ marginBottom: "15px" }}>
<label htmlFor="rounding">Rounding Preference:</label>
<select id="rounding" value={rounding} onChange={(e) => setRounding(e.target.value)} style={{ width: "100%", padding: "10px", fontSize: "16px", borderRadius: "5px", border: "1px solid #ccc" }}>
<option value="nearest">Round to the nearest penny</option>
<option value="decimal">Keep decimals</option>
</select>
</div>
<button onClick={handleCalculation} style={{ width: "100%", padding: "10px", backgroundColor: "#343a40", color: "#ffffff", fontSize: "16px", borderRadius: "5px", cursor: "pointer" }}>Calculate VAT</button>
<div className="results" style={{ marginTop: "20px", padding: "15px", backgroundColor: "#e9ecef", borderRadius: "5px" }}>
<p><strong>VAT Amount:</strong> {currency} {vatAmount.toFixed(2)}</p>
<p><strong>Total Amount:</strong> {currency} {totalAmount.toFixed(2)}</p>
</div>
</div>
);
}
ReactDOM.render(<VATCalculator />, document.getElementById('vat-calculator'));
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
State Management
const [amount, setAmount] = useState(0);
const [vatRate, setVatRate] = useState(20);
These lines set up our basic state variables using React’s useState hook. We’re initializing the amount to 0 and the default VAT rate to 20%. Each state variable has its corresponding setter function that we’ll use to update values.
VAT Calculation Logic
if (calculationType === "Add VAT") {
vat = amount * (vatRate / 100);
total = amount + vat;
} else if (calculationType === "Remove VAT") {
vat = amount - amount / (1 + vatRate / 100);
total = amount - vat;
}
This is where the magic happens. The calculator handles two types of calculations:
- Adding VAT: Multiplies the amount by the VAT rate percentage
- Removing VAT: Works backward from a VAT-inclusive amount to find the original price
Rounding Implementation
if (rounding === "nearest") {
vat = Math.round(vat * 100) / 100;
total = Math.round(total * 100) / 100;
}
This handles decimal precision. By multiplying by 100, rounding, and dividing by 100, we ensure amounts are rounded to two decimal places when needed.
Currency Selection
<select id="currency" value={currency} onChange={(e) => setCurrency(e.target.value)}>
<option value="GBP">GBP</option>
<option value="EUR">EUR</option>
<option value="USD">USD</option>
</select>
The currency selector gives users flexibility to work with different currencies. While it doesn’t convert between currencies, it properly displays the selected currency symbol with the calculated amounts.
User Input Handling
<input type="number" id="amount" value={amount}
onChange={(e) => setAmount(parseFloat(e.target.value))} />
This line shows how we handle numeric input. The parseFloat conversion ensures we’re always working with numbers rather than strings for our calculations.
Result Display
<div className="results">
<p><strong>VAT Amount:</strong> {currency} {vatAmount.toFixed(2)}</p>
<p><strong>Total Amount:</strong> {currency} {totalAmount.toFixed(2)}</p>
</div>
The results section displays both the VAT amount and the total amount, formatted to two decimal places using toFixed(2). The currency symbol is displayed based on the user’s selection.
Styling Approach
The component uses inline styles for simplicity and portability, but in a real application, you might want to move these to a separate CSS file or use styled-components. The styling focuses on creating a clean, professional interface with good spacing and clear visual hierarchy.
This calculator component demonstrates several React best practices:
- Controlled components for form inputs
- Clear separation of calculation logic
- Flexible configuration options
- User-friendly error prevention
- Professional styling and layout
Feel free to use this component in your own projects! You can easily customize the VAT rates, add more currencies, or modify the styling to match your application’s theme.
Remember to properly test the component with different inputs and edge cases before using it in a production environment. While this version handles basic calculations well, you might want to add input validation and error handling depending on your specific needs.