Skip to content
Closed
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
35 changes: 34 additions & 1 deletion .Jules/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
## [Unreleased]

### Added
- 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.
- Pull-to-refresh with haptic feedback on `HomeScreen` and `GroupDetailsScreen` in mobile app.
- Keyboard navigation support for Groups page, enabling accessibility for power users.

### Planned
Expand Down Expand Up @@ -40,3 +40,36 @@
- `.jules/todo.md`
- `.jules/knowledge.md`
- `.jules/changelog.md`

---

<!--
## Template for future entries:

## [YYYY-MM-DD] - vX.X.X

### Added
- New feature or component

### Changed
- Modifications to existing code

### Fixed
- Bug fixes

### Improved
- Performance or UX improvements

### Deprecated
- Features to be removed

### Removed
- Deleted code or features

**Files Modified:**
- `path/to/file1`
- `path/to/file2`

**Notes:**
- Any additional context
-->
124 changes: 42 additions & 82 deletions .Jules/knowledge.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,34 +104,6 @@ colors: {
</Button>
```

### Clickable Cards & Accessibility

**Date:** 2026-01-01
**Context:** Making `motion.div` or non-button elements accessible

When making a div clickable (like a card), you must ensure it's accessible:
1. **Role**: Add `role="button"`.
2. **TabIndex**: Add `tabIndex={0}` so it's focusable.
3. **Keyboard Handler**: Add `onKeyDown` to handle 'Enter' and 'Space'.
4. **Label**: Add `aria-label` to describe the action.
5. **Focus Styles**: Add visible focus styles (e.g., `focus:ring`).

```tsx
<motion.div
onClick={handleClick}
role="button"
tabIndex={0}
aria-label="View Details"
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
handleClick();
}
}}
className="... focus:outline-none focus:ring-4 focus:ring-blue-500"
>
```

### Card Component with Title/Action

**Date:** 2026-01-01
Expand Down Expand Up @@ -178,46 +150,6 @@ addToast('Message', 'success|error|info');
- Auto-dismisses after 3 seconds
- Stacks vertically in bottom-right

### Form Validation Pattern

**Date:** 2026-01-01
**Context:** Implemented in Auth.tsx

```tsx
type FormErrors = { [key: string]: string };
const [fieldErrors, setFieldErrors] = useState<FormErrors>({});

// 1. Validation Logic
const validate = () => {
const newErrors: FormErrors = {};
if (!email) newErrors.email = 'Required';
setFieldErrors(newErrors);
return Object.keys(newErrors).length === 0;
};

// 2. Clear on type
const clearFieldError = (field: string) => {
if (fieldErrors[field]) {
setFieldErrors(prev => ({ ...prev, [field]: undefined }));
}
};

// 3. Render with accessibility
<form onSubmit={handleSubmit} noValidate>
<Input
error={fieldErrors.email}
onChange={(e) => {
setEmail(e.target.value);
clearFieldError('email');
}}
// Input component handles:
// aria-invalid={!!error}
// aria-describedby={`${id}-error`}
// Error message has id={`${id}-error`} and role="alert"
/>
</form>
```

---

## Mobile Patterns
Expand All @@ -243,6 +175,48 @@ Commonly used components:

Most screens use `<View style={{ flex: 1 }}>` - consider wrapping in `SafeAreaView` for notched devices.

### List Loading vs. Refreshing

**Date:** 2026-01-01
**Context:** Implementing pull-to-refresh on mobile lists

Always separate `isLoading` (initial blocking load) from `isRefreshing` (pull-to-refresh).

**Bad Pattern:**

```javascript
<FlatList
refreshing={isLoading}
onRefresh={fetchData}
/>
{isLoading ? <Spinner /> : <List />} // List disappears on refresh!
```

**Good Pattern:**

```javascript
const [isLoading, setIsLoading] = useState(true); // Initial load
const [isRefreshing, setIsRefreshing] = useState(false); // Pull-to-refresh

const fetchData = async (refresh = false) => {
if (refresh) setIsRefreshing(true); else setIsLoading(true);
// ... fetch data
setIsLoading(false);
setIsRefreshing(false);
}

// ...

{isLoading ? <Spinner /> : (
<FlatList
refreshing={isRefreshing}
onRefresh={() => fetchData(true)}
/>
)}
```

**Also:** Use `expo-haptics` for tactile feedback on refresh triggers.

---

## API Response Patterns
Expand Down Expand Up @@ -280,20 +254,6 @@ interface BalanceSummary {

---

## Testing & Verification

### Playwright Verification Patterns
**Date:** 2026-01-01
**Context:** Verifying accessibility changes with Playwright scripts

When writing Playwright scripts to verify frontend changes without backend:

1. **Auth Mocking:** You must mock `/users/me` persistently. If this call fails or returns 401, `AuthContext` will force a redirect to login, breaking navigation tests.
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": ...}}`).

---

## Known Issues & Gotchas

### Image URL Validation
Expand Down
37 changes: 18 additions & 19 deletions .Jules/todo.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,19 @@
- Files modified: `web/contexts/ToastContext.tsx`, `web/components/ui/Toast.tsx`, `web/App.tsx`, `web/pages/Auth.tsx`
- Impact: Modern feedback system that supports both themes

- [x] **[a11y]** Complete keyboard navigation for Groups page
- Completed: 2026-01-01
- [ ] **[a11y]** Complete keyboard navigation for Groups page
- File: `web/pages/Groups.tsx`
- Context: Add keyboard handling to group cards + search + modals
- Impact: Full keyboard accessibility for power users
- Size: ~50 lines
- Added: 2026-01-01

- [x] **[ux]** Comprehensive empty states with illustrations
- Completed: 2026-01-01
- Files: `web/pages/Groups.tsx`, `web/pages/Friends.tsx`
- Context: Create illustrated empty states with CTAs (not just text)
- Impact: Guides new users, makes app feel polished
- Size: ~70 lines
- Added: 2026-01-01

- [ ] **[ux]** Error boundary with retry for API failures
- Files: Create `web/components/ErrorBoundary.tsx`, wrap app
Expand All @@ -43,12 +43,10 @@

### Mobile

- [ ] **[ux]** Pull-to-refresh with haptic feedback on all list screens
- Files: `mobile/screens/HomeScreen.js`, `mobile/screens/GroupDetailsScreen.js`
- Context: Add RefreshControl + Expo Haptics to main lists
- Impact: Native feel, users can easily refresh data
- Size: ~45 lines
- Added: 2026-01-01
- [x] **[ux]** Pull-to-refresh with haptic feedback on all list screens
- Completed: 2026-01-11
- Files modified: `mobile/screens/HomeScreen.js`, `mobile/screens/GroupDetailsScreen.js`, `mobile/screens/FriendsScreen.js`
- Impact: Native feel, users can easily refresh data without losing context

- [ ] **[ux]** Complete skeleton loading for HomeScreen groups
- File: `mobile/screens/HomeScreen.js`
Expand All @@ -70,6 +68,13 @@

### Web

- [ ] **[ux]** Form validation with inline feedback
- Files: `web/pages/Auth.tsx`, `web/pages/GroupDetails.tsx`
- Context: Show real-time validation with error messages under inputs
- Impact: Users know immediately if input is valid
- Size: ~50 lines
- Added: 2026-01-01

- [ ] **[style]** Consistent hover/focus states across all buttons
- Files: `web/components/ui/Button.tsx`, usage across pages
- Context: Ensure all buttons have proper hover + focus-visible styles
Expand Down Expand Up @@ -146,13 +151,7 @@
- Files modified: `web/components/ui/EmptyState.tsx`, `web/pages/Groups.tsx`, `web/pages/Friends.tsx`
- Impact: Users now see a polished, illustrated empty state with clear CTAs when they have no groups or friends, instead of plain text.

- [x] **[a11y]** Complete keyboard navigation for Groups page
- Completed: 2026-01-12
- File: `web/pages/Groups.tsx`
- Impact: Users can now navigate groups, join/create buttons, and search using only the keyboard with proper focus indicators.
- [x] **[ux]** Form validation with inline feedback
- 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.

_No tasks completed yet. Move tasks here after completion._
- [x] **[ux]** Pull-to-refresh with haptic feedback on all list screens
- Completed: 2026-01-01
- Files modified: `mobile/screens/HomeScreen.js`, `mobile/screens/GroupDetailsScreen.js`
- Impact: Native feel, users can easily refresh data without losing context.
2 changes: 1 addition & 1 deletion .github/workflows/bundle-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
node-version: '22'
cache: 'npm'
cache-dependency-path: frontend/package-lock.json

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 18
node-version: 22

- name: Setup EAS
uses: expo/expo-github-action@v8
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
- name: 🏗 Setup Node
uses: actions/setup-node@v4
with:
node-version: 18
node-version: 22
cache: 'npm'
cache-dependency-path: frontend/package-lock.json

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/rn-bundle-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
node-version: '22'
cache: 'npm'
cache-dependency-path: mobile/package-lock.json

Expand Down
Loading
Loading