Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 8 additions & 9 deletions .Jules/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,19 @@
## [Unreleased]

### Added
- **ErrorBoundary**: Implemented a global `ErrorBoundary` component (`web/components/ErrorBoundary.tsx`) that catches render errors and displays a user-friendly fallback UI.
- Supports both Neobrutalism and Glassmorphism themes.
- Provides "Retry" and "Back to Home" actions.
- Wrapped `AppRoutes` in `web/App.tsx` to prevent white-screen crashes.
- Verified with Playwright tests ensuring UI appears correctly on error.

### Changed
- Inline form validation in Auth page with real-time feedback and proper ARIA accessibility support (`aria-invalid`, `aria-describedby`, `role="alert"`).
- Dashboard skeleton loading state (`DashboardSkeleton`) to improve perceived performance during data fetch.
- Comprehensive `EmptyState` component for Groups and Friends pages to better guide new users.
- Toast notification system (`ToastContext`, `Toast` component) for providing non-blocking user feedback.
- Keyboard navigation support for Groups page, enabling accessibility for power users.

### Changed
- Updated JULES_PROMPT.md based on review of successful PRs:
- Emphasized complete system implementation over piecemeal changes
- Added best practices from successful PRs (Toast system, keyboard navigation iteration)
- Refined task categories to focus on complete features
- Enhanced validation checklist
- Added implementation phases guide
- Documented successful patterns to repeat
- Updated JULES_PROMPT.md based on review of successful PRs.

### Planned
- See `todo.md` for queued tasks
Expand Down
90 changes: 39 additions & 51 deletions .Jules/knowledge.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,35 @@ colors: {

## Component Patterns

### Error Boundary Pattern

**Date:** 2026-01-14
**Context:** Implementing global error handling

React Error Boundaries must use Class Components for logic, but we often need Hooks (like `useTheme`) for the UI.

**Solution: Separation of Concerns**
1. **ErrorFallback (Functional):** Handles UI, uses hooks (`useTheme`, `useNavigate`).
2. **ErrorBoundary (Class):** Handles lifecycle methods (`componentDidCatch`).

**Key Implementation Detail:**
If the ErrorBoundary wraps the main Router/Layout, the fallback UI might lose context providers (like ThemeWrapper).
*Fix:* Explicitly wrap the content of `ErrorFallback` in `<ThemeWrapper>` to ensure it has the correct background/text colors even if the main layout crashes.

```tsx
// ErrorFallback uses hooks
const ErrorFallback = () => {
const { style } = useTheme();
return <ThemeWrapper>...</ThemeWrapper>;
}

// ErrorBoundary uses lifecycle
class ErrorBoundary extends Component {
static getDerivedStateFromError() { return { hasError: true }; }
render() { return this.state.hasError ? <ErrorFallback /> : this.props.children; }
}
```

### Button Component Variants

**Date:** 2026-01-01
Expand Down Expand Up @@ -292,6 +321,16 @@ When writing Playwright scripts to verify frontend changes without backend:
2. **Route Matching:** Use specific route patterns (e.g., `**/users/me`) and ensure they don't accidentally swallow longer paths (like `**/users/me/balance-summary`) if using wildcards carelessly. Register specific paths before general ones if using `page.route` order dependence, or use specific globs.
3. **Response Structure:** Mocks must match the structure expected by `axios` interceptors and components. If `axios` returns `res.data` as the body, and the component expects `res.data.groups`, the mock body should be `{"groups": [...]}` (not `{"data": {"groups": ...}}`).

### Clean Up After Verification

**Date:** 2026-01-14
**Context:** Reviewing verification process

**Important:** When using tools like Playwright for temporary verification:
1. **Uninstall dependencies:** If you installed `@playwright/test`, uninstall it before submitting.
2. **Remove artifacts:** Delete `test-results`, `.last-run.json`, and the test script itself.
3. **Revert code:** If you added "bomb" components or buttons to trigger errors, revert those files completely.

---

## Known Issues & Gotchas
Expand Down Expand Up @@ -406,57 +445,6 @@ Tailwind breakpoints used:

---

## Project Direction & Goals

### What Splitwiser Is About

**Date:** 2026-01-01

Splitwiser is focused on (per README):
1. **Modern expense splitting** - Making group expenses effortless
2. **Group management** - Create and manage expense groups
3. **Real-time synchronization** - Keep data synced across devices
4. **Secure authentication** - JWT-based auth with refresh tokens
5. **Receipt management** - Track and store receipt images
6. **Debt simplification** - Minimize number of transactions
7. **Multi-currency support** - Handle different currencies
8. **Exceptional UX** - Beautiful, intuitive, delightful interactions
9. **Cross-platform** - Web (React/Vite/TypeScript) and mobile (Expo/React Native)

**Current Implementation Details:**
- Web app uses dual-theme design system (Glassmorphism & Neobrutalism)
- Mobile uses React Native Paper (Material Design)
- Backend: FastAPI + MongoDB

**NOT focused on:**
- Generic business app features
- Traditional accounting workflows
- Enterprise features
- One-off utilities

**When picking tasks, ask:**
- Does this improve expense splitting experience?
- For web: Does it work in BOTH themes?
- Will users notice and appreciate this?
- Does it align with the README's core features?

---

_Document errors and their solutions here as you encounter them._

```markdown
<!-- Template for documenting errors:
### Error: [Error Name]
**Date:** YYYY-MM-DD
**Context:** What you were trying to do
**Error Message:** The actual error
**Solution:** How you fixed it
**Files Affected:** List of files
-->
```

---

## Recent Implementation Reviews

### ✅ Successful PR Pattern: Toast Notification System (#227)
Expand Down
8 changes: 6 additions & 2 deletions .Jules/todo.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@
- Impact: Guides new users, makes app feel polished
- Size: ~70 lines

- [ ] **[ux]** Error boundary with retry for API failures
- [x] **[ux]** Error boundary with retry for API failures
- Completed: 2026-01-14
- Files: Create `web/components/ErrorBoundary.tsx`, wrap app
- Context: Catch errors gracefully with retry button
- Impact: App doesn't crash, users can recover
- Size: ~60 lines
- Added: 2026-01-01

### Mobile

Expand Down Expand Up @@ -154,5 +154,9 @@
- Completed: 2026-01-11
- Files modified: `web/pages/Auth.tsx`
- Impact: Users know immediately if input is valid via inline error messages and red borders.
- [x] **[ux]** Error boundary with retry for API failures
- Completed: 2026-01-14
- Files modified: `web/components/ErrorBoundary.tsx`, `web/App.tsx`
- Impact: Prevents app crashes and provides a recovery mechanism with a dual-theme UI.

_No tasks completed yet. Move tasks here after completion._
5 changes: 4 additions & 1 deletion web/App.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react';
import { HashRouter, Navigate, Route, Routes } from 'react-router-dom';
import { ErrorBoundary } from './components/ErrorBoundary';
import { Layout } from './components/layout/Layout';
import { ThemeWrapper } from './components/layout/ThemeWrapper';
import { AuthProvider, useAuth } from './contexts/AuthContext';
Expand Down Expand Up @@ -51,8 +52,10 @@ const App = () => {
<ToastProvider>
<AuthProvider>
<HashRouter>
<ErrorBoundary>
<AppRoutes />
<ToastContainer />
</ErrorBoundary>
<ToastContainer />
</HashRouter>
</AuthProvider>
</ToastProvider>
Expand Down
82 changes: 82 additions & 0 deletions web/components/ErrorBoundary.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import React, { Component, ReactNode } from 'react';
import { AlertTriangle, Home, RefreshCw } from 'lucide-react';
import { THEMES } from '../constants';
import { useTheme } from '../contexts/ThemeContext';
import { Button } from './ui/Button';
import { ThemeWrapper } from './layout/ThemeWrapper';

// Functional component for the UI to use hooks
const ErrorFallback = () => {
const { style } = useTheme();

const handleRetry = () => {
window.location.reload();
};

const handleHome = () => {
window.location.href = '/';
};

const isNeo = style === THEMES.NEOBRUTALISM;

return (
<ThemeWrapper>
<div className="flex flex-col items-center justify-center min-h-screen p-6 text-center">
<div className={`mb-6 p-4 rounded-full ${isNeo ? 'bg-neo-main border-2 border-black shadow-[4px_4px_0px_0px_rgba(0,0,0,1)]' : 'bg-red-500/10 text-red-500 backdrop-blur-md border border-red-500/20'}`}>
<AlertTriangle size={48} className={isNeo ? 'text-white' : ''} />
</div>

<h2 className={`text-2xl font-bold mb-2 ${isNeo ? 'font-mono uppercase' : ''}`}>
Something went wrong
</h2>

<p className="text-gray-500 mb-8 max-w-md">
We encountered an unexpected error. Please try refreshing the page or go back to home.
</p>

<div className="flex flex-col sm:flex-row gap-4">
<Button onClick={handleRetry} variant="primary">
<RefreshCw size={18} />
Retry
</Button>
<Button onClick={handleHome} variant="secondary">
<Home size={18} />
Back to Home
</Button>
</div>
</div>
</ThemeWrapper>
);
};

interface Props {
children: ReactNode;
}

interface State {
hasError: boolean;
error?: Error;
}

export class ErrorBoundary extends Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = { hasError: false };
}

static getDerivedStateFromError(error: Error): State {
return { hasError: true, error };
}

componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
console.error('ErrorBoundary caught an error:', error, errorInfo);
}

render() {
if (this.state.hasError) {
return <ErrorFallback />;
}

return this.props.children;
}
}
Loading