## Summary
- Added label update support to the single transaction `update()`
endpoint
- Previously, labels could only be updated via the bulk update endpoint
- Now both endpoints support label updates with consistent behavior
## Changes
- **UpdateTransactionRequest**: Added `label_ids` validation (array of
UUIDs that must belong to user)
- **TransactionController@update**: Now handles label updates alongside
other attributes
- Syncs labels when `label_ids` is provided
- Reloads labels relationship for fresh data in events
- Fires single `updated` event after all changes
- **AssignTransactionToBudget listener**: Ensures labels are loaded
fresh after queue serialization
- **Tests**: Added 6 comprehensive tests covering all label update
scenarios
## Behavior
- **Don't send `label_ids`** → labels unchanged (partial update)
- **Send `label_ids: []`** → removes all labels
- **Send `label_ids: [uuid1, uuid2]`** → replaces labels with these
## Testing
When labels are updated, the `TransactionUpdated` event fires and the
transaction is automatically assigned to matching budgets (via queued
listener).
All tests pass (29 tests, 134 assertions).
Fixes the issue where transactions wouldn't appear in budget after
adding a matching label via the single transaction update endpoint.
This PR simplifies the IndexedDB synchronization mechanism by removing
individual sync controllers and services, and instead using Inertia.js
shared props to provide data globally across the application.
## Benefits
1. **Simplified Architecture**: Removed complex sync logic for
static/semi-static data (accounts, categories, banks, labels, automation
rules)
2. **Better Performance**: Data is now shared via Inertia props,
eliminating unnecessary API calls and IndexedDB operations
3. **Reduced Complexity**: Significantly reduced codebase size (~2000
lines removed)
4. **Better UX**: Data is immediately available on page load without
waiting for sync operations
5. **Maintainability**: Fewer moving parts means easier to maintain and
debug
## Migration Notes
- Transaction syncing still uses IndexedDB for offline support
- All other data (accounts, categories, banks, labels, automation rules)
is now fetched via Inertia shared props
- Components automatically receive updated data on navigation without
manual sync operations
## Summary
Add a labeling system for transactions that differs from categories in
that labels are ephemeral and created on-the-fly when assigned (no
pre-creation required). A transaction can have multiple labels
(many-to-many relationship), and labels can be used for filtering in the
transaction table and as actions in automation rules.
<img width="1372" height="484" alt="image"
src="https://github.com/user-attachments/assets/fd342b11-dafb-44ed-b818-578e1ea856e6"
/>
<img width="1373" height="613" alt="image"
src="https://github.com/user-attachments/assets/aa5cfb8b-50b7-4101-a872-54904924f234"
/>
<img width="1035" height="594" alt="image"
src="https://github.com/user-attachments/assets/ffa946b2-b01f-496b-8cb8-ab55ab5b79ed"
/>
## Changes
### Backend (Laravel)
- Add `labels` table with user_id, name, color, and soft deletes
- Add `label_transaction` pivot table for transaction-label many-to-many
- Add `automation_rule_labels` pivot table for automation rule-label
many-to-many
- Create Label model with relationships to User, Transaction, and
AutomationRule
- Add LabelController for CRUD operations (returns JSON for on-the-fly
creation)
- Add LabelSyncController for frontend sync
- Add LabelPolicy for authorization
- Update TransactionController to handle bulk label updates
- Update AutomationRuleController to handle label actions
- Add validation for label_ids in transactions and automation rules
### Frontend (React/TypeScript)
- Add Label type and color utilities
- Add labels table to IndexedDB (Dexie version 6)
- Create label-sync service with findOrCreate functionality
- Create LabelCombobox component with multi-select and create-on-type
- Add labels column to transactions table
- Add labels filter to transaction filters
- Add bulk label assignment in bulk actions bar
- Add labels action in create automation rule dialog
- Update rule engine to include labels in evaluation results
## Testing
- 11 feature tests for label CRUD
- 3 tests for label sync
- All 241 feature tests pass
## Screenshots
N/A - UI changes can be reviewed in browser
## Summary
Add a new quick categorization page that allows users to categorize
transactions without categories one by one, in a game-like interface.
https://github.com/user-attachments/assets/14fd7386-e87e-4a75-ae94-e487e3a48112
## Features
- **Quick Categorization Page**: A clean, focused interface for
categorizing transactions
- White screen with centered transaction card
- Categories sorted by usage frequency (stored in localStorage)
- Smooth animations when categorizing (card exits, success feedback,
next card enters)
- Progress indicator showing remaining transactions
- **Keyboard Shortcuts**:
- `Ctrl+R`: Open automation rules dialog
- `Ctrl+N`: Skip current transaction
- `Escape`: Go back to transactions page
- Arrow keys + Enter: Navigate and select categories
- **Automation Rules Integration**:
- Rules button in header to manage automation rules
- When closing the rules dialog, all remaining transactions are checked
against rules
- Matching transactions are automatically categorized
- **UI/UX**:
- Command component for category search and selection
- Encrypted text component for account names
- Responsive amount display with positive/negative styling
- Skip button moved to header for cleaner card design
## Access
New "Categorize" button added to the transactions page toolbar (left of
"Add Transaction" button) showing the count of uncategorized
transactions.