Commit Graph

216 Commits

Author SHA1 Message Date
Víctor Falcón 0d76913e5d
test: Fix and improve Browser test suite (#62) 2026-01-19 10:04:25 +01:00
Víctor Falcón 253fe447bd fix: broken dashboard while loading 2026-01-16 11:30:04 +01:00
Víctor Falcón 21a4d87f85
fix: Use user currency in top spending categories card (#57)
## Summary
- Fixed top spending categories card to display amounts in the user's
currency instead of hardcoded USD
- Uses `auth.user.currency_code` from page props, consistent with other
dashboard components

Issue: #56
2026-01-16 08:16:37 +01:00
Víctor Falcón d16282dbad
feat: Auto-open encryption key modal after login (#54)
## Summary

This PR implements automatic opening of the encryption key unlock modal
immediately after user login when they visit the dashboard. The modal
will only appear once per login session and will not show up on
subsequent dashboard visits or if the user manually clears their
encryption key.

## Problem

Previously, users had to manually click the encryption key button in the
sidebar after logging in to unlock their encrypted data. This extra step
could be confusing for new users and added friction to the login flow.

## Solution

The encryption key modal now automatically opens when users visit the
dashboard immediately after logging in, but **only if**:
1. The user just completed a login (session flag is set)
2. Their encryption key is not already in browser storage
3. Encrypted challenge data is available

## Implementation Details

### Backend Changes

#### 1. Custom Login Response Classes
Created two new response classes that override Fortify's default login
responses:

**`app/Http/Responses/LoginResponse.php`**
- Implements `LoginResponse` contract
- Sets `show_encryption_prompt` session flash variable after successful
login
- Handles both regular login and JSON API responses

**`app/Http/Responses/TwoFactorLoginResponse.php`**
- Implements `TwoFactorLoginResponse` contract  
- Sets the same session flag after successful 2FA authentication
- Ensures the modal appears for 2FA users as well

#### 2. Service Provider Registration
**`app/Providers/FortifyServiceProvider.php`**
- Registered custom response classes as singletons in the container
- Fortify now uses our custom responses instead of defaults

#### 3. Dashboard Controller
**`app/Http/Controllers/DashboardController.php`**
- Passes `showEncryptionPrompt` flag from session to frontend
- Uses `session('show_encryption_prompt', false)` which automatically
consumes the flash data

### Frontend Changes

**`resources/js/pages/dashboard.tsx`**
- Added `DashboardProps` interface extending `SharedData` with
`showEncryptionPrompt` boolean
- Updated `useEffect` hook to check three conditions before auto-opening
modal:
1. `props.showEncryptionPrompt` - User just logged in (from session
flash)
  2. `!isKeySet` - Encryption key not in browser storage
  3. `encryptedMessageData` - Encrypted challenge data loaded
- Includes `UnlockMessageDialog` component that conditionally renders

## How It Works

### User Flow

1. **User logs in** → Custom `LoginResponse` or `TwoFactorLoginResponse`
sets `show_encryption_prompt` flash session variable
2. **Redirect to dashboard** → `DashboardController` retrieves and
passes the flag to frontend (consuming it)
3. **Dashboard loads** → React component checks all three conditions
4. **Modal appears** → If conditions are met, `UnlockMessageDialog`
opens automatically
5. **Session flag consumed** → Subsequent page loads won't trigger the
modal

### Why Session Flash?

Laravel's session flash data is perfect for this use case because:
- It's automatically removed after being accessed once
- It survives redirects (crucial for post-login flow)
- It's server-side, so it can't be manipulated by client-side code
- No database changes or additional state management needed

### Edge Cases Handled

 **User clears encryption key manually** → Modal won't auto-open on
dashboard visit (no session flag)
 **User refreshes dashboard** → Modal won't re-appear (flash data
consumed)
 **User logs out and back in** → Modal appears again (new session flag)
 **2FA enabled users** → Modal appears after successful 2FA challenge
 **Key already in browser** → Modal doesn't appear (key check passes)

## Testing

-  All existing dashboard tests pass (2 tests)
-  All authentication tests pass (58 tests)
-  Code formatted with Laravel Pint
-  Code formatted with Prettier
-  ESLint validation passes

## Files Changed

- `app/Http/Responses/LoginResponse.php` (new)
- `app/Http/Responses/TwoFactorLoginResponse.php` (new)
- `app/Providers/FortifyServiceProvider.php` (modified)
- `app/Http/Controllers/DashboardController.php` (modified)
- `resources/js/pages/dashboard.tsx` (modified)

## Breaking Changes

None. This is an additive feature that enhances the existing
authentication flow without breaking any existing functionality.
2026-01-11 20:29:49 +01:00
Víctor Falcón c9877a503d feat: Persis transactions filter on the URL 2026-01-11 19:09:57 +01:00
Víctor Falcón 1343e1c75f feat: Persist cashflow period on the URL 2026-01-11 19:05:25 +01:00
Víctor Falcón 5618893be8 feat: Group small expending categories on the Sankey chart 2026-01-11 19:04:20 +01:00
Víctor Falcón 4a5c60c630 feat: New discord offer 2026-01-10 10:27:32 +01:00
Víctor Falcón c1ddc1477d fix: scroll category combobox to top while searching 2026-01-09 10:02:25 +01:00
Víctor Falcón 0646b380ce feat: new roadmap and feedback links 2026-01-08 19:17:01 +01:00
Víctor Falcón 02ab53fe19 style: animate unlock button 2026-01-07 18:16:05 +01:00
Víctor Falcón 9af941cb47 ui: add cursor pointer to the buttons 2026-01-07 11:12:03 +01:00
Víctor Falcón 9bd1fcea37
Demo Account Experience (#51)
## Summary

<img width="1220" height="1001" alt="whispermoney test_"
src="https://github.com/user-attachments/assets/c35751d5-385b-449c-81d6-14b5b6577ff2"
/>

Introduces a fully-functional demo account that lets prospective users
explore Whisper Money without creating an account. Users can click
"Check Demo" on the welcome page to instantly access a pre-populated
account with realistic financial data spanning 12 months.

## What's New

**Try Before You Sign Up**
- New "Check Demo" button on the welcome page for instant access
- Pre-configured demo account with real-world financial scenarios
- 12 months of sample transactions across multiple account types
(checking, savings, credit cards, investments)
- Pre-built automation rules, labels, and categories to showcase the
full app experience

**Demo Account Limitations**
- Demo accounts are read-only for sensitive operations (can't change
password, email, or payment settings)
- Clear messaging throughout the UI when demo restrictions apply
- Settings pages show helpful notices about demo limitations
- Automatic daily reset to maintain fresh demo experience

**Developer Experience**
- `php artisan demo:reset` command for manual resets
- Configurable via environment variables (DEMO_EMAIL, DEMO_PASSWORD,
DEMO_ENCRYPTION_KEY)
- Comprehensive test coverage for demo restrictions and data generation

## User Impact

This feature removes the friction of signing up before understanding the
product's value. Users can:
- Explore all features with realistic data
- Test automation rules and see them in action
- View charts and insights based on a year of financial activity
- Experience the full privacy-first encryption workflow
- Understand the product before committing to create an account

Perfect for demos, screenshots, documentation, and helping users make
informed decisions about whether Whisper Money fits their needs.
2026-01-07 10:58:14 +01:00
Víctor Falcón cb1d6a230f fix: issue on filters when no label created 2026-01-06 11:42:04 +01:00
Víctor Falcón abeeeec53f cashflow: sankey chart improve 2026-01-06 08:47:30 +01:00
Víctor Falcón 6269173766 cashflow: use user currency_code 2026-01-06 08:36:30 +01:00
Víctor Falcón 1cec4a6421
Add Cashflow Analytics Feature (#49)
Summary
- Add new Cashflow page with income/expense analytics, Sankey chart
visualization, and trend analysis
- Add Cashflow summary widget to the dashboard
- Implement feature flag system using Laravel Pennant to control feature
visibility per user
- Add artisan commands to enable/disable features: `php artisan
feature:enable/disable [feature] [email|all]`

## New Features
- **Cashflow Page**: Period-based income/expense breakdown with category
analysis
- **Sankey Chart**: Visual flow diagram showing money movement between
categories
- **Trend Chart**: 12-month historical cashflow visualization
- **Dashboard Widget**: Quick cashflow summary card
- **Feature Flags**: Cashflow feature hidden behind feature flag,
controllable per-user

## How to enable it
This feature it's under a feature flag until we are sure it's working
fine. If you want to test it, [send us a message on the general channel
in our discord](https://discord.gg/9UQWZECDDv). If you're self hosting
just run `php artisan feature:enable CashflowFeature {your_email}`.

## New Cashflow Page
<img width="1278" height="1185" alt="image"
src="https://github.com/user-attachments/assets/83469f24-9f96-4e5f-bef9-86c076d31243"
/>
<img width="1274" height="1035" alt="image"
src="https://github.com/user-attachments/assets/8949ff9d-c370-4fc4-81c6-268307c587a5"
/>

## New Dashboard Widget
<img width="1180" height="289" alt="image"
src="https://github.com/user-attachments/assets/ad984a66-9ffd-4079-85ce-0b2d28278d76"
/>
<img width="1179" height="286" alt="image"
src="https://github.com/user-attachments/assets/bff60286-8ea2-4e9c-8fa6-22755566648f"
/>
2026-01-05 13:06:50 +01:00
Víctor Falcón b957ddbe0d
Preview account transactions (#48)
While importing new transactions, sometimes is difficult to now which
ones are already imported, and which one are new.

With this importer update you can quickly view the transactions that
already exist in your account, and see which ones you have and which
ones you don't have to import again.

<img width="1220" height="1169" alt="image"
src="https://github.com/user-attachments/assets/38de3208-a7d4-4578-8683-753bd0bf7c93"
/>
2026-01-04 16:17:15 +01:00
Víctor Falcón 0f879cec0e transactions: increase date column size 2026-01-02 14:56:05 +01:00
Víctor Falcón 13d6c54e12 avoid new lines on transactions date column 2026-01-02 14:48:42 +01:00
Víctor Falcón 7d90a53deb bugsing: only send error if production 2026-01-02 14:34:41 +01:00
Víctor Falcón a2bae48827 catch: play video error 2026-01-01 12:18:00 +01:00
Víctor Falcón 407f0f85d9 frontend: update transaction search input width 2025-12-31 13:01:12 +01:00
Víctor Falcón d592391de8 Push sourcemap to bugsink 2025-12-31 12:56:25 +01:00
Víctor Falcón 8f9f1e809d Config bugsink for React frontend 2025-12-31 12:22:01 +01:00
Víctor Falcón b79ba27008 ui: change text on unlock message dialog 2025-12-30 15:46:58 +01:00
Víctor Falcón 4fa77dc929 landing: video player ui 2025-12-30 15:37:02 +01:00
Víctor Falcón 1e3de4b1e0 landing: add encryption video 2025-12-30 15:35:10 +01:00
Víctor Falcón 2eccee09a2 ui: amount display when encryption key is not set 2025-12-30 14:25:19 +01:00
Víctor Falcón b2d1bcf54c fix: wrong user menu text 2025-12-30 11:16:15 +01:00
Víctor Falcón bc9a84f929 typo: privacy mode 2025-12-30 11:13:07 +01:00
Víctor Falcón 5fe961a308 chore: update privacy mode to update transactions descriptions 2025-12-30 11:03:58 +01:00
Víctor Falcón 104723cbef chore: update landing images 2025-12-30 10:47:42 +01:00
Víctor Falcón c72b148fb4
SSR was missing the privacy mode provider (#46) 2025-12-30 08:55:03 +01:00
Víctor Falcón 46454f193f
Update balance with manually created transactions (#45)
<img width="1195" height="874" alt="image"
src="https://github.com/user-attachments/assets/1d2f5e10-dad5-4136-8f65-5e8a3e8b30c5"
/>
2025-12-30 07:55:34 +01:00
Víctor Falcón 700f9325a3 Add currency selection to user profile settings (#41) 2025-12-30 07:22:19 +01:00
Víctor Falcón 0f66ab7478 chore: update user-menu-content ui 2025-12-30 07:22:19 +01:00
Víctor Falcón 037699b424 chore: add repo star count to landing 2025-12-30 07:22:19 +01:00
Víctor Falcón db81c9b888 feat: add version tracking with git tags and changelog
- Add version field to package.json (0.1.0)
- Install release-it for automated releases with conventional changelog
- Create .release-it.json configuration
- Create initial CHANGELOG.md
- Share version via Inertia (reads from package.json)
- Display version in user dropdown menu
2025-12-30 07:22:19 +01:00
Víctor Falcón 818a49e799 fix(charts): mobile ui, and desktop tooltips 2025-12-30 07:22:19 +01:00
Víctor Falcón 14a9343c1d fix(mobile): account chart 2025-12-30 07:22:19 +01:00
Víctor Falcón c5df59c285 feat: add multiple chart view modes for net worth evolution (#37)
## Summary

- Add four view modes for net worth and account balance charts:
- **Stacked Accounts**: existing stacked bar chart showing balances by
account
  - **Line**: net worth line chart with linear/log scale toggle
  - **Change**: bar chart showing MoM%, YoY%, Rolling 12M changes
- **Waterfall**: bridge chart showing Start -> Change -> End transition

- Add Vitest for frontend unit testing with 52 tests covering all
calculation functions
- Proper sign handling for liabilities (credit cards and loans subtract
from net worth)
- Log scale disabled with warning when net worth includes zero or
negative values
- Shared components and logic between dashboard and account detail
charts

## New Files

- `vitest.config.ts` - Vitest configuration
- `resources/js/lib/chart-calculations.ts` - Pure computation functions
- `resources/js/lib/chart-calculations.test.ts` - 52 unit tests
- `resources/js/hooks/use-chart-views.ts` - Shared chart view state hook
- `resources/js/components/charts/` - Reusable chart components

## Test plan

- [x] Dashboard net worth chart shows view toggle and all four views
work
- [ ] Account detail page chart shows view toggle and three views work
(no stacked)
- [x] Line chart scale toggle works (log disabled with warning when
applicable)
- [x] Change chart series toggle (MoM, YoY, 12M EUR, 12M %) works
- [x] Waterfall chart month selector works
- [x] All 52 unit tests pass (`bun run test`)
- [x] Build succeeds (`bun run build`)
- [x] Dark mode styling correct
2025-12-30 07:22:19 +01:00
Víctor Falcón 6f42b91585 ui: add hasKeyboard prop to modals 2025-12-30 07:22:19 +01:00
Víctor Falcón a785a27554 ui(fix): add hasKeyboard prop to dialogs
This property move the modal to the top on mobile, so we left space
bellow for the keyboard. On desktop is vertically centered as it was
before.
2025-12-30 07:22:19 +01:00
Víctor Falcón a6c2914e58 ui(fix): use amount display for chart current balance 2025-12-30 07:22:19 +01:00
Víctor Falcón f8ec902d83 ui(fix): responsive design on account show page 2025-12-30 07:22:19 +01:00
Víctor Falcón 5ddcfbee30 ui(fix): transaction filters on small screens 2025-12-30 07:22:19 +01:00
Víctor Falcón ba61cc1ef8 welcome-page: explain e2e encryption 2025-12-30 07:22:18 +01:00
Víctor Falcón fa63c49175 welcome-page: remove lead form 2025-12-30 07:22:18 +01:00
Víctor Falcón f8c4fb0def add best value to yearly price 2025-12-30 07:22:18 +01:00