A modern, intuitive expense splitting application built with Nuxt 3 and Pinia. Designed to help groups of friends, roommates, or colleagues easily track shared expenses and calculate who owes whom.
- π₯ Participant Management: Add, edit, and remove participants with validation
- πΈ Expense Tracking: Record expenses with payer, amount, and description
- π Balance Calculation: Automatic calculation of individual balances
- π Smart Settlement: Generates optimal payment plans to settle debts with minimum transactions
- π Statistics: View detailed stats for each participant (total paid, owed, net balance)
- πΎ Local Storage: Automatically saves participants between sessions
- π± Responsive Design: Works seamlessly on mobile and desktop
- π¨ Modern UI: Clean interface built with TailwindCSS
- π§ͺ Tested: Comprehensive test coverage with Vitest
- Nuxt 3 - Vue.js meta-framework for production-ready apps
- Vue 3 - Progressive JavaScript framework
- Pinia - Intuitive, type-safe state management
- TypeScript - Type-safe development
- TailwindCSS - Utility-first CSS framework
- Vitest - Fast unit testing framework
- Node.js v16 or later
- Yarn 1.22.22 or later (or npm)
# Clone the repository
git clone https://github.com/simone98dm/splitmoney.git
# Navigate to project directory
cd splitmoney
# Install dependencies
yarn install
# Start development server
yarn devThe application will be available at http://localhost:3000
# Start development server
yarn dev
# Build for production
yarn build
# Preview production build
yarn preview
# Generate static site
yarn generate
# Run tests
yarn test
# Run tests with UI
yarn test:ui
# Run tests with coverage
yarn test:coverageThe application uses two main Pinia stores:
- Manages participant list with localStorage persistence
- Provides validation for participant names (unique, max 20 chars)
- Supports CRUD operations: add, edit, remove participants
- Calculates individual statistics per participant
- Prevents removal of participants with existing expenses
- Manages expense list and calculations
- Calculates total expenses and individual balances
- Generates optimal settlement plans using a greedy algorithm
- Minimizes the number of transactions needed to settle debts
interface Expense {
id: number;
payer: string;
amount: number;
description: string;
timestamp: number;
}
interface Transfer {
from: string;
to: string;
amount: number;
}
interface ParticipantStats {
totalPaid: number;
totalOwed: number;
netBalance: number;
numberOfExpenses: number;
averageExpense: number;
}- Calculate Individual Balances: For each expense, the amount is divided equally among all participants
- Identify Debtors and Creditors: Participants with negative balance owe money; positive balance means they should receive money
- Optimize Settlements: Uses a greedy algorithm to minimize the number of transactions:
- Sort debtors and creditors by amount
- Match the largest debtor with the largest creditor
- Create transactions until all balances are settled
If three friends (Alice, Bob, Charlie) share expenses:
- Alice pays β¬60
- Bob pays β¬30
- Total: β¬90 β Each person's share: β¬30
Balances:
- Alice: +β¬30 (paid β¬60, owes β¬30)
- Bob: β¬0 (paid β¬30, owes β¬30)
- Charlie: -β¬30 (paid β¬0, owes β¬30)
Settlement: Charlie pays β¬30 to Alice
- Enter a participant name in the input field (max 20 characters)
- Click "Aggiungi" button
- Participants are automatically saved to localStorage
- Select who paid from the dropdown
- Enter the amount
- Optionally add a description
- Click "Aggiungi Spesa"
- Individual balances are displayed for each participant
- Click "Calcola Divisione" to generate the settlement plan
- The app shows the minimum number of transfers needed to settle all debts
- Edit Participant: Click edit icon next to participant name
- Remove Participant: Only possible if they have no recorded expenses
- Remove Expense: Click delete icon next to any expense
The project includes comprehensive unit tests for the expense store:
# Run all tests
yarn test
# Run tests in watch mode
yarn test --watch
# Run tests with coverage report
yarn test --coverage
# Run tests with UI interface
yarn test:uiTests cover:
- Expense addition and removal
- Balance calculation logic
- Settlement algorithm accuracy
- Edge cases and rounding
Strict type checking enabled for better code quality and developer experience.
- Composition API: Uses Vue 3 Composition API with
<script setup> - TypeScript: Fully typed with interfaces for all data structures
- Reactive State: Uses
refandcomputedfor reactive data - Store Composition: Uses
storeToRefsfor reactive store properties
- Components are small and focused on single responsibilities
- Business logic is separated into stores
- Validation logic is centralized in stores
- Type safety throughout the application
Contributions are welcome! Please follow these steps:
- Fork the repository
- Create a feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
- Write tests for new features
- Follow existing code style and conventions
- Update documentation as needed
- Ensure all tests pass before submitting PR
This project is open source and available under the MIT License.
Simone Dal Mas
- Website: simone98dm.dev
- GitHub: @simone98dm
- Built with Nuxt 3
- State management by Pinia
- Styled with TailwindCSS
- Tested with Vitest
Made with β€οΈ by simone98dm