diff --git a/locales/en.yml b/locales/en.yml
index d03d80d3f6..221c854716 100644
--- a/locales/en.yml
+++ b/locales/en.yml
@@ -97,6 +97,10 @@ tools:
title: Percentage calculator
description: Easily calculate percentages from a value to another value, or from a percentage to a value.
+ tip-calculator:
+ title: Tip calculator
+ description: Calculate the tip for a bill and split it among multiple people.
+
svg-placeholder-generator:
title: SVG placeholder generator
description: Generate svg images to use as a placeholder in your applications.
diff --git a/src/tools/index.ts b/src/tools/index.ts
index 388cfaf494..4143e205e8 100644
--- a/src/tools/index.ts
+++ b/src/tools/index.ts
@@ -58,6 +58,7 @@ import { tool as dateTimeConverter } from './date-time-converter';
import { tool as deviceInformation } from './device-information';
import { tool as cypher } from './encryption';
import { tool as etaCalculator } from './eta-calculator';
+import { tool as tipCalculator } from './tip-calculator';
import { tool as percentageCalculator } from './percentage-calculator';
import { tool as gitMemo } from './git-memo';
import { tool as hashText } from './hash-text';
@@ -168,7 +169,7 @@ export const toolsByCategory: ToolCategory[] = [
},
{
name: 'Math',
- components: [mathEvaluator, etaCalculator, percentageCalculator],
+ components: [mathEvaluator, etaCalculator, percentageCalculator, tipCalculator],
},
{
name: 'Measurement',
diff --git a/src/tools/tip-calculator/index.ts b/src/tools/tip-calculator/index.ts
new file mode 100644
index 0000000000..d1e528fae5
--- /dev/null
+++ b/src/tools/tip-calculator/index.ts
@@ -0,0 +1,13 @@
+import { Calculator } from '@vicons/tabler';
+import { defineTool } from '../tool';
+import { translate } from '@/plugins/i18n.plugin';
+
+export const tool = defineTool({
+ name: translate('tools.tip-calculator.title'),
+ path: '/tip-calculator',
+ description: translate('tools.tip-calculator.description'),
+ keywords: ['tip', 'calculator', 'bill', 'split', 'restaurant', 'money', 'payment'],
+ component: () => import('./tip-calculator.vue'),
+ icon: Calculator,
+ createdAt: new Date('2024-04-17'),
+});
diff --git a/src/tools/tip-calculator/tip-calculator.e2e.spec.ts b/src/tools/tip-calculator/tip-calculator.e2e.spec.ts
new file mode 100644
index 0000000000..f122afefab
--- /dev/null
+++ b/src/tools/tip-calculator/tip-calculator.e2e.spec.ts
@@ -0,0 +1,49 @@
+import { expect, test } from '@playwright/test';
+
+test.describe('Tool - Tip calculator', () => {
+ test.beforeEach(async ({ page }) => {
+ await page.goto('/tip-calculator');
+ });
+
+ test('Has correct title', async ({ page }) => {
+ await expect(page).toHaveTitle('Tip calculator - IT Tools');
+ });
+
+ test('Correctly calculates tip and split', async ({ page }) => {
+ // Fill bill amount
+ await page.getByTestId('billAmount').locator('input').fill('100');
+
+ // Fill tip percentage
+ await page.getByTestId('tipPercentage').locator('input').fill('15');
+
+ // Fill number of people
+ await page.getByTestId('numberOfPeople').locator('input').fill('2');
+
+ // Check results
+ // 100 * 0.15 = 15.00
+ await expect(page.getByTestId('tipAmountResult').locator('input')).toHaveValue('15.00');
+
+ // 100 + 15 = 115.00
+ await expect(page.getByTestId('totalBillResult').locator('input')).toHaveValue('115.00');
+
+ // 115 / 2 = 57.50
+ await expect(page.getByTestId('amountPerPersonResult').locator('input')).toHaveValue('57.50');
+ });
+
+ test('Quick tip buttons work', async ({ page }) => {
+ await page.getByTestId('billAmount').locator('input').fill('100');
+
+ // Click 20% button
+ await page.getByRole('button', { name: '20%' }).click();
+
+ await expect(page.getByTestId('tipPercentage').locator('input')).toHaveValue('20');
+ await expect(page.getByTestId('tipAmountResult').locator('input')).toHaveValue('20.00');
+ });
+
+ test('Displays initial/empty results correctly', async ({ page }) => {
+ // Initial state with empty bill
+ await expect(page.getByTestId('tipAmountResult').locator('input')).toHaveValue('0.00');
+ await expect(page.getByTestId('totalBillResult').locator('input')).toHaveValue('0.00');
+ await expect(page.getByTestId('amountPerPersonResult').locator('input')).toHaveValue('0.00');
+ });
+});
diff --git a/src/tools/tip-calculator/tip-calculator.vue b/src/tools/tip-calculator/tip-calculator.vue
new file mode 100644
index 0000000000..55f5b28637
--- /dev/null
+++ b/src/tools/tip-calculator/tip-calculator.vue
@@ -0,0 +1,69 @@
+
+
+
+
+
+
+ Bill details
+
+
+
+
Tip Percentage
+
+
+ %
+
+
+
+
+
Number of People
+
+
+
+
+
+
+
+
+ Results
+
+
+
{{ res.label }}:
+
+
+
+
+
+
+
+
+ Quick Tip %
+
+ {{ tip }}%
+
+
+
+
+
+