Expense Split Calculator JavaScript
👤 Sharing: AI
```javascript
function expenseSplitCalculator() {
let participants = [];
let expenses = [];
function addParticipant(name) {
participants.push({ name: name, owed: 0, paid: 0 });
}
function addExpense(description, amount, payer, beneficiaries) {
if (amount <= 0) {
console.error("Expense amount must be positive.");
return;
}
const payerIndex = participants.findIndex((p) => p.name === payer);
if (payerIndex === -1) {
console.error(`Payer "${payer}" not found.`);
return;
}
const beneficiaryIndices = beneficiaries.map((name) =>
participants.findIndex((p) => p.name === name)
);
if (beneficiaryIndices.some((index) => index === -1)) {
console.error("One or more beneficiaries not found.");
return;
}
expenses.push({ description, amount, payer, beneficiaries });
participants[payerIndex].paid += amount;
const splitAmount = amount / beneficiaries.length;
beneficiaries.forEach((beneficiary) => {
const beneficiaryIndex = participants.findIndex(
(p) => p.name === beneficiary
);
participants[beneficiaryIndex].owed += splitAmount;
});
}
function calculateBalances() {
return participants.map(participant => ({
name: participant.name,
balance: participant.paid - participant.owed
}));
}
function generateSettlements() {
const balances = calculateBalances();
const settlements = [];
// Separate participants into those who are owed money (creditors) and those who owe money (debtors)
const creditors = balances.filter(b => b.balance > 0).sort((a, b) => b.balance - a.balance);
const debtors = balances.filter(b => b.balance < 0).sort((a, b) => a.balance - b.balance);
let i = 0;
let j = 0;
while (i < creditors.length && j < debtors.length) {
const creditor = creditors[i];
const debtor = debtors[j];
const amount = Math.min(creditor.balance, Math.abs(debtor.balance));
settlements.push({
from: debtor.name,
to: creditor.name,
amount: amount
});
creditor.balance -= amount;
debtor.balance += amount;
if (creditor.balance === 0) {
i++;
}
if (debtor.balance === 0) {
j++;
}
}
return settlements;
}
function getParticipants() {
return participants.map(p => p.name); // Return just the names, not the entire object.
}
function getExpenses() {
return expenses;
}
return {
addParticipant,
addExpense,
calculateBalances,
generateSettlements,
getParticipants,
getExpenses
};
}
// Example usage (demonstrates the API, you can adapt to UI)
function runExample() {
const calculator = expenseSplitCalculator();
calculator.addParticipant("Alice");
calculator.addParticipant("Bob");
calculator.addParticipant("Charlie");
calculator.addExpense("Dinner", 60, "Alice", ["Alice", "Bob", "Charlie"]);
calculator.addExpense("Drinks", 30, "Bob", ["Bob", "Charlie"]);
calculator.addExpense("Taxi", 15, "Charlie", ["Alice", "Charlie"]);
console.log("Participants:", calculator.getParticipants());
console.log("Expenses:", calculator.getExpenses());
const balances = calculator.calculateBalances();
console.log("Balances:", balances);
const settlements = calculator.generateSettlements();
console.log("Settlements:", settlements);
}
//runExample(); // Uncomment to run the example. Remember to remove the comment before deploying, or it will execute on page load.
// **Important Considerations for UI Integration:**
// 1. **UI Input:** You'll need to create HTML elements (input fields, buttons, etc.) for users to input participants, expenses, payer, and beneficiaries.
// 2. **Event Handlers:** Attach event listeners to your UI elements (e.g., button clicks) to call the functions in the `expenseSplitCalculator` object (`addParticipant`, `addExpense`, etc.).
// 3. **Data Storage:** You might want to store the participants and expenses in local storage or a database to persist data between sessions.
// 4. **Display Results:** Use the `calculateBalances` and `generateSettlements` functions, and update the UI to display the results to the user. Use tables, lists, or other visual components to make the information clear.
// 5. **Error Handling:** Provide user-friendly error messages in the UI if there are issues with the input data (e.g., invalid amount, payer not found).
// 6. **Modularity:** The code is designed to be modular. You can further break down the UI logic into separate functions or modules for better organization.
```
👁️ Viewed: 8
Comments