diff --git a/.claude/commands/pre-push.md b/.claude/commands/pre-push.md
deleted file mode 100644
index d82f741..0000000
--- a/.claude/commands/pre-push.md
+++ /dev/null
@@ -1,5 +0,0 @@
-Before pushing to remote version control, ensure that the following is completed:
-
-1. run linters and formatters.
-2. run all tests using `mix test`.
-3. check any files that were created in the recent commits that part within the `docs/logs` folder and update any relevant content that is out of date with the code changes.
diff --git a/.claude/commands/update-doc-logs.md b/.claude/commands/update-doc-logs.md
new file mode 100644
index 0000000..1df0ab9
--- /dev/null
+++ b/.claude/commands/update-doc-logs.md
@@ -0,0 +1,7 @@
+Do the following TODO. If the instructions are not relevant, do nothing.
+
+1. Check any files that were created in the recent commits that part within the `docs/logs` folder.
+
+2. If the changes are related to a different domain or topics altogether, create a new log file with similar front matter to record the topic.
+
+3. Update any existing logs that have relevant content that is out of date with the code changes. If there are major changes to an existing log file. Instead of editing what is there already, add a new section in the same file with a record of the datetime of the change.
diff --git a/docs/logs/add-expenses-feature.md b/docs/logs/add-expenses-feature.md
new file mode 100644
index 0000000..b63b8c2
--- /dev/null
+++ b/docs/logs/add-expenses-feature.md
@@ -0,0 +1,193 @@
+---
+title: Adding Expenses Feature to SplitApp
+date: 2025-08-24
+time: 20:35:00
+author: Claude
+tags: [expenses, feature, money, liveview, associations]
+---
+
+# Adding Expenses Feature to SplitApp
+
+## Overview
+This document outlines the implementation of the Expenses feature, which allows users to create, track, and manage expenses. The feature integrates with the existing Groups system and includes proper money handling with multi-currency support.
+
+## Database Changes
+
+### 1. Expenses Table
+Created a new `expenses` table with the following fields:
+- `id` - Primary key
+- `title` - String field for expense title (required)
+- `description` - Text field for expense description (optional)
+- `amount` - Map field storing Money type with amount and currency (required)
+- `created_by_id` - Foreign key to users table (required)
+- `inserted_at` - Timestamp
+- `updated_at` - Timestamp
+
+**Migration file:** `priv/repo/migrations/20250824203547_create_expenses.exs`
+
+### 2. Expense Assignments Join Table
+Created an `expense_assignments` join table for many-to-many relationship between expenses and users:
+- `expense_id` - Foreign key to expenses table
+- `user_id` - Foreign key to users table
+- `inserted_at` - Timestamp
+- `updated_at` - Timestamp
+- Composite unique index on `[expense_id, user_id]`
+
+### 3. Expense Groups Join Table
+Created an `expense_groups` join table for many-to-many relationship between expenses and groups:
+- `expense_id` - Foreign key to expenses table
+- `group_id` - Foreign key to groups table
+- `inserted_at` - Timestamp
+- `updated_at` - Timestamp
+- Composite unique index on `[expense_id, group_id]`
+
+## Code Changes
+
+### 1. Money Library Integration (`mix.exs`)
+Added `money` library dependency for proper currency handling:
+```elixir
+{:money, "~> 1.12"}
+```
+
+### 2. Context and Schemas
+
+#### Expenses Context (`lib/split_app/expenses.ex`)
+Generated using Phoenix context generator with functions:
+- `list_expenses/0` - List all expenses
+- `list_expenses_by_user/1` - List expenses created by specific user
+- `get_expense!/1` - Get a single expense
+- `create_expense/1` - Create a new expense
+- `update_expense/2` - Update an expense
+- `delete_expense/1` - Delete an expense
+- `change_expense/2` - Generate changeset for forms
+
+#### Expense Schema (`lib/split_app/expenses/expense.ex`)
+- Fields: `title`, `description`, `amount` (Money type)
+- Associations:
+ - `belongs_to :created_by` (User who created the expense)
+ - `many_to_many :assigned_users` through `expense_assignments`
+ - `many_to_many :groups` through `expense_groups`
+- Custom validation for Money type ensuring:
+ - Amount is greater than 0
+ - Currency is present
+ - Valid Money struct format
+
+### 3. Web Layer
+
+#### Expense LiveViews (Generated)
+- `lib/split_app_web/live/expense_live/index.ex` - List user's expenses
+- `lib/split_app_web/live/expense_live/show.ex` - Show single expense
+- `lib/split_app_web/live/expense_live/form_component.ex` - Create/edit expenses
+ - Custom money input handling
+ - Currency selection support
+ - Integration with current user context
+
+#### Dashboard Updates (`lib/split_app_web/live/dashboard_live.ex`)
+Enhanced dashboard to show user's recent expenses alongside groups.
+
+#### Live Helpers (`lib/split_app_web/live/live_helpers.ex`)
+Added utility functions for LiveView components and common patterns.
+
+### 4. Router Updates (`lib/split_app_web/router.ex`)
+
+Added authenticated routes for expenses:
+```elixir
+live "/expenses", ExpenseLive.Index, :index
+live "/expenses/new", ExpenseLive.Index, :new
+live "/expenses/:id/edit", ExpenseLive.Index, :edit
+live "/expenses/:id", ExpenseLive.Show, :show
+live "/expenses/:id/show/edit", ExpenseLive.Show, :edit
+```
+
+### 5. Group Integration
+
+#### Group LiveViews Updates
+Updated group show and index pages to display related expenses and provide links to create expenses within group context.
+
+## Features Implemented
+
+### Money Handling
+- **Multi-Currency Support**: Uses Money library for proper currency handling
+- **Validation**: Ensures positive amounts and valid currency codes
+- **Display**: Proper formatting of money amounts in UI
+- **Input**: Custom form inputs for amount and currency selection
+
+### Expense Management
+- **Create Expenses**: Users can create expenses with title, description, and amount
+- **Edit/Delete**: Full CRUD operations for user's own expenses
+- **User Context**: Expenses are automatically associated with creator
+- **Filtering**: Users see only their own expenses by default
+
+### Associations
+- **User Assignment**: Expenses can be assigned to multiple users (foundation for splitting)
+- **Group Integration**: Expenses can be associated with groups
+- **Creator Tracking**: System tracks who created each expense
+
+### UI/UX Features
+- **Expense List**: Clean table view of user's expenses with amounts, titles, and dates
+- **Money Display**: Proper currency formatting (e.g., "$25.50 USD")
+- **Form Validation**: Real-time validation of money amounts and required fields
+- **Integration**: Seamless navigation between expenses, groups, and dashboard
+
+## Testing
+
+### Test Files Created
+- `test/split_app/expenses/expense_test.exs` - Unit tests for Expense schema
+- `test/split_app_web/live/expense_live_test.exs` - Integration tests for LiveViews
+- `test/support/fixtures/expenses_fixtures.ex` - Test data fixtures
+
+### Test Coverage
+- Schema validations for Money type
+- CRUD operations in context
+- LiveView interactions and form submissions
+- Money formatting and display
+
+## Migration Commands
+
+```bash
+# Add money library
+# (Added to mix.exs manually)
+
+# Generate the Expenses context and schema
+mix phx.gen.context Expenses Expense expenses title:string description:text amount:map created_by_id:references:users
+
+# Generate LiveView pages
+mix phx.gen.live Expenses Expense expenses title:string description:text amount:map created_by_id:references:users --no-context --no-schema
+
+# Run migrations
+mix ecto.migrate
+
+# Install new dependencies
+mix deps.get
+```
+
+## Future Enhancements
+
+This foundation enables future expense splitting functionality:
+- **Expense Splitting**: Calculate splits between assigned users
+- **Settlement Tracking**: Track who owes what to whom
+- **Group Expense Views**: Show all expenses within a group
+- **Balance Calculations**: Calculate user balances across groups
+- **Payment Tracking**: Mark when debts are settled
+- **Expense Categories**: Categorize expenses (food, transport, etc.)
+- **Receipt Uploads**: Attach receipt images to expenses
+- **Recurring Expenses**: Support for recurring/scheduled expenses
+
+## Technical Notes
+
+### Money Type Implementation
+The Money library stores currency amounts as a map in the database:
+```elixir
+%{amount: 2550, currency: :USD} # Represents $25.50 USD
+```
+
+This ensures:
+- Precise decimal arithmetic (no floating point errors)
+- Multi-currency support
+- Consistent currency handling across the application
+- Proper serialization/deserialization from database
+
+### Performance Considerations
+- Indexes on `created_by_id` for efficient user expense queries
+- Composite unique indexes on join tables prevent duplicates
+- Ordered queries for chronological expense display
\ No newline at end of file
diff --git a/lib/split_app/expenses.ex b/lib/split_app/expenses.ex
new file mode 100644
index 0000000..d1c731a
--- /dev/null
+++ b/lib/split_app/expenses.ex
@@ -0,0 +1,136 @@
+defmodule SplitApp.Expenses do
+ @moduledoc """
+ The Expenses context.
+ """
+
+ import Ecto.Query, warn: false
+ alias SplitApp.Repo
+
+ alias SplitApp.Expenses.Expense
+
+ @doc """
+ Returns the list of expenses.
+
+ ## Examples
+
+ iex> list_expenses()
+ [%Expense{}, ...]
+
+ """
+ def list_expenses do
+ Repo.all(Expense)
+ end
+
+ @doc """
+ Returns the list of expenses for a specific user.
+
+ ## Examples
+
+ iex> list_expenses_by_user(123)
+ [%Expense{}, ...]
+
+ """
+ def list_expenses_by_user(user_id) do
+ from(e in Expense,
+ where: e.created_by_id == ^user_id,
+ order_by: [desc: e.inserted_at]
+ )
+ |> Repo.all()
+ end
+
+ @doc """
+ Gets a single expense.
+
+ Raises `Ecto.NoResultsError` if the Expense does not exist.
+
+ ## Examples
+
+ iex> get_expense!(123)
+ %Expense{}
+
+ iex> get_expense!(456)
+ ** (Ecto.NoResultsError)
+
+ """
+ def get_expense!(id), do: Repo.get!(Expense, id)
+
+ @doc """
+ Gets a single expense with preloaded associations.
+
+ ## Examples
+
+ iex> get_expense_with_associations!(123)
+ %Expense{assigned_users: [...], groups: [...]}
+
+ """
+ def get_expense_with_associations!(id) do
+ Expense
+ |> Repo.get!(id)
+ |> Repo.preload([:created_by, :assigned_users, :groups])
+ end
+
+ @doc """
+ Creates a expense.
+
+ ## Examples
+
+ iex> create_expense(%{field: value})
+ {:ok, %Expense{}}
+
+ iex> create_expense(%{field: bad_value})
+ {:error, %Ecto.Changeset{}}
+
+ """
+ def create_expense(attrs \\ %{}) do
+ %Expense{}
+ |> Expense.changeset(attrs)
+ |> Repo.insert()
+ end
+
+ @doc """
+ Updates a expense.
+
+ ## Examples
+
+ iex> update_expense(expense, %{field: new_value})
+ {:ok, %Expense{}}
+
+ iex> update_expense(expense, %{field: bad_value})
+ {:error, %Ecto.Changeset{}}
+
+ """
+ def update_expense(%Expense{} = expense, attrs) do
+ expense
+ |> Expense.changeset(attrs)
+ |> Repo.update()
+ end
+
+ @doc """
+ Deletes a expense.
+
+ ## Examples
+
+ iex> delete_expense(expense)
+ {:ok, %Expense{}}
+
+ iex> delete_expense(expense)
+ {:error, %Ecto.Changeset{}}
+
+ """
+ def delete_expense(%Expense{} = expense) do
+ Repo.delete(expense)
+ end
+
+ @doc """
+ Returns an `%Ecto.Changeset{}` for tracking expense changes.
+
+ ## Examples
+
+ iex> change_expense(expense)
+ %Ecto.Changeset{data: %Expense{}}
+
+ """
+ def change_expense(%Expense{} = expense, attrs \\ %{}) do
+ Expense.changeset(expense, attrs)
+ end
+end
diff --git a/lib/split_app/expenses/expense.ex b/lib/split_app/expenses/expense.ex
new file mode 100644
index 0000000..2a7cab4
--- /dev/null
+++ b/lib/split_app/expenses/expense.ex
@@ -0,0 +1,33 @@
+defmodule SplitApp.Expenses.Expense do
+ use Ecto.Schema
+ import Ecto.Changeset
+
+ schema "expenses" do
+ field :title, :string
+ field :description, :string
+ field :amount, Money.Ecto.Map.Type
+
+ belongs_to :created_by, SplitApp.Accounts.User, foreign_key: :created_by_id
+ many_to_many :assigned_users, SplitApp.Accounts.User, join_through: "expense_assignments"
+ many_to_many :groups, SplitApp.Groups.Group, join_through: "expense_groups"
+
+ timestamps(type: :utc_datetime)
+ end
+
+ @doc false
+ def changeset(expense, attrs) do
+ expense
+ |> cast(attrs, [:title, :description, :amount, :created_by_id])
+ |> validate_required([:title, :amount, :created_by_id])
+ |> validate_money(:amount)
+ end
+
+ defp validate_money(changeset, field) do
+ validate_change(changeset, field, fn
+ _, %Money{amount: amount, currency: currency} when amount > 0 and not is_nil(currency) -> []
+ _, %Money{amount: amount} when amount <= 0 -> [{field, "amount must be greater than 0"}]
+ _, %Money{currency: nil} -> [{field, "currency is required"}]
+ _, _ -> [{field, "must be a valid money amount"}]
+ end)
+ end
+end
diff --git a/lib/split_app_web/live/dashboard_live.ex b/lib/split_app_web/live/dashboard_live.ex
index 1d76520..7914e28 100644
--- a/lib/split_app_web/live/dashboard_live.ex
+++ b/lib/split_app_web/live/dashboard_live.ex
@@ -1,31 +1,59 @@
defmodule SplitAppWeb.DashboardLive do
use SplitAppWeb, :live_view
alias SplitApp.Groups
+ alias SplitApp.Expenses
@impl true
def mount(_params, _session, socket) do
user = socket.assigns.current_user
groups = Groups.list_user_groups(user)
+ recent_expenses = Expenses.list_expenses_by_user(user.id) |> Enum.take(5)
{:ok,
socket
|> assign(:groups, groups)
- |> assign(:page_title, "My Groups")}
+ |> assign(:recent_expenses, recent_expenses)
+ |> assign(:page_title, "Dashboard")}
end
@impl true
def render(assigns) do
~H"""
-
+
<.header>
Welcome, {@current_user.email}!
- <:subtitle>Here are all the groups you're a part of
+ <:subtitle>Manage your expenses and groups
+
+
+