๐ฐSplit Bill Calculator
Advanced split bill calculator with tip calculation, tax splitting, and receipt scanning. Split restaurant bills and group expenses fairly among friends with multiple calculation methods and detailed breakdowns.
๐ค What Is a Split Bill Calculator?
Think of a fair referee for restaurant checks - that's our Split Bill Calculator! It divides bills perfectly among friends, handles tips and taxes automatically, and ensures everyone pays their exact share. No more awkward math at the dinner table!
๐งพ Quick Bill Split
Perfect for restaurants where everyone pays equally
๐ณ Your split results will appear here
๐ Item-by-Item Split
Perfect for when different people ordered different items
๐ Detailed split results will appear here
๐ฅ Group Expense Tracker
Track multiple expenses and see who owes what
๐ฅ Group settlement results will appear here
๐ Sample Bill Scenarios
๐ฝ๏ธ Restaurant Dinner
$125.50 โข 4 people โข 18% tip โข $12.50 tax
โ Coffee Shop
$32.80 โข 3 people โข 15% tip โข $2.80 tax
๐ Fast Food
$45.75 โข 5 people โข 10% tip โข $4.15 tax
๐ฅ Fine Dining
$285.00 โข 6 people โข 20% tip โข $25.65 tax
๐ Food Delivery
$78.90 โข 3 people โข 18% tip โข $7.12 tax
๐ป Bar Tab
$156.40 โข 7 people โข 20% tip โข $14.04 tax
๐ณ Split Breakdown
Subtotal per person:
${results.perPersonSubtotal.toFixed(2)}
Tax per person:
${results.perPersonTax.toFixed(2)}
Tip per person (${results.tipPercent}%):
${results.perPersonTip.toFixed(2)}
Each person pays:
${results.perPersonTotal.toFixed(2)}
${subtotal.toFixed(2)}
Items Subtotal
${tipAmount.toFixed(2)}
Total Tip (${tipPercent}%)
${totalAmount.toFixed(2)}
Grand Total
${Object.values(personTotals).map(person => `
`).join('')}
`;
}
// Display group results
function displayGroupResults(balances) {
const container = document.getElementById('groupResultContainer');
// Separate who owes and who is owed
const owedMoney = Object.values(balances).filter(p => p.balance > 0.01);
const owesMoney = Object.values(balances).filter(p => p.balance < -0.01);
container.innerHTML = `
${person.name}
${person.total.toFixed(2)}
Items: ${person.subtotal.toFixed(2)}
Tax: ${person.tax.toFixed(2)}
Tip: ${person.tip.toFixed(2)}
Tax: ${person.tax.toFixed(2)}
Tip: ${person.tip.toFixed(2)}
${splitBillState.expenses.length}
Total Expenses
${splitBillState.expenses.reduce((sum, e) => sum + e.amount, 0).toFixed(2)}
Total Amount
${owedMoney.length + owesMoney.length}
People Involved
๐ฐ Should Receive
${owedMoney.map(person => `
${person.name}
+${person.balance.toFixed(2)}
`).join('') || 'No one is owed money
'}
๐ธ Should Pay
${owesMoney.map(person => `
${person.name}
${Math.abs(person.balance).toFixed(2)}
`).join('') || 'Everyone is settled up
'}
${content.replace(/\n/g, '
')}`; } chatMessages.appendChild(messageDiv); chatMessages.scrollTop = chatMessages.scrollHeight; } async function sendToGemini() { const input = document.getElementById('geminiInput'); const message = input.value.trim(); if (!message) return; addMessage('user', message); input.value = ''; const loadingMsg = document.createElement('div'); loadingMsg.className = 'message assistant'; loadingMsg.innerHTML = 'โจ Gemini:
Thinking...'; loadingMsg.id = 'loading-message'; document.getElementById('chatMessages').appendChild(loadingMsg); try { const response = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=${aiModalState.apiKey}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ contents: [{ parts: [{ text: `Context: User is using a Split Bill Calculator tool on WIA Pin Code platform. The tool can split restaurant bills, calculate tips, divide expenses item-by-item, and track group expenses. WIA Pin Code is a universal address system for countries without postal codes. Split Bill Calculator features: - Simple bill splitting with tip calculation - Item-by-item division for detailed splits - Group expense tracking and settlement - Multiple calculation methods and tax handling User question: ${message} Please provide helpful advice about bill splitting, tipping etiquette, group dining, and expense sharing while noting this is general guidance.` }] }], generationConfig: { temperature: 0.7, maxOutputTokens: 1000 } }) }); const data = await response.json(); document.getElementById('loading-message').remove(); if (data.candidates && data.candidates[0] && data.candidates[0].content) { const reply = data.candidates[0].content.parts[0].text; addMessage('assistant', reply); } else { addMessage('assistant', 'Sorry, I could not generate a response. Please try again.'); } } catch (error) { document.getElementById('loading-message')?.remove(); if (error.message.includes('API key')) { addMessage('error', 'Invalid API key. Please check your API key and try again.'); showAPIKeySetup(); } else { addMessage('error', 'Failed to connect to Gemini. Please check your internet connection and try again.'); } } } // ========== EVENT LISTENERS ========== document.addEventListener('DOMContentLoaded', function() { // Enter key support for inputs ['billTotal', 'numPeople', 'taxAmount', 'tipPercent'].forEach(id => { const element = document.getElementById(id); if (element) { element.addEventListener('keypress', function(e) { if (e.key === 'Enter') { calculateSimpleSplit(); } }); element.addEventListener('input', clearErrors); } }); // Enter key for person name const personNameInput = document.getElementById('personName'); if (personNameInput) { personNameInput.addEventListener('keypress', function(e) { if (e.key === 'Enter') { addPerson(); } }); } // Enter key for item inputs const itemNameInput = document.getElementById('itemName'); const itemPriceInput = document.getElementById('itemPrice'); if (itemNameInput && itemPriceInput) { [itemNameInput, itemPriceInput].forEach(input => { input.addEventListener('keypress', function(e) { if (e.key === 'Enter') { addItem(); } }); }); } document.getElementById('aiBtn').addEventListener('click', openAIModal); document.getElementById('aiModal').addEventListener('click', function(e) { if (e.target === this) { closeAIModal(); } }); document.addEventListener('keydown', function(e) { if (e.key === 'Enter') { const geminiInput = document.getElementById('geminiInput'); if (document.activeElement === geminiInput) { sendToGemini(); } } if (e.key === 'Escape') { closeAIModal(); } }); updateAPIKeyStatus(); updateCurrentYear(); updateToolCount(); }); // ========== DYNAMIC TOOL COUNT ========== async function updateToolCount() { try { const response = await fetch('/api/tool-count.php'); const data = await response.json(); document.querySelectorAll('.dynamic-tools-count').forEach(el => { el.textContent = `${data.count}+ free online tools in 211 languages. No signup, no fees, just tools that work.`; }); document.querySelectorAll('.dynamic-count').forEach(el => { const prefix = el.getAttribute('data-text') || ''; const suffix = el.getAttribute('data-suffix') || ''; const icon = el.textContent.split(' ')[0] || ''; el.textContent = `${icon} ${prefix} ${data.count}+ ${suffix}`; }); } catch (error) { const fallbackCount = 333; document.querySelectorAll('.dynamic-tools-count').forEach(el => { el.textContent = `${fallbackCount}+ free online tools in 211 languages. No signup, no fees, just tools that work.`; }); document.querySelectorAll('.dynamic-count').forEach(el => { const prefix = el.getAttribute('data-text') || ''; const suffix = el.getAttribute('data-suffix') || ''; const icon = el.textContent.split(' ')[0] || ''; el.textContent = `${icon} ${prefix} ${fallbackCount}+ ${suffix}`; }); console.log('Tool count API not available, using current count:', fallbackCount); } } function updateCurrentYear() { const currentYear = new Date().getFullYear(); document.querySelectorAll('.current-year').forEach(el => { el.textContent = currentYear; }); } // ========== ANALYTICS ========== window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'G-XXXXXXXXX'); trackEvent('page_view', { tool: TOOL_CONFIG.name, category: TOOL_CONFIG.category });