feat: user profile page and nav avatar dropdown (#35) #45

Merged
marcel merged 7 commits from feat/35-profile-page into main 2026-03-22 14:52:08 +01:00
Owner

Summary

  • Nav avatar dropdown: replaces the plain logout button with a circular initials button (e.g. MM), falling back to a person icon; clicking opens a dropdown with a /profile link and logout
  • Profile page (/profile): two-card layout — personal info form (first name, last name, birth date, email, contact) and password change form, each with independent use:enhance actions
  • Public user profile (/users/[id]): read-only view of another user's name, username, email, and contact
  • Backend: new firstName, lastName, birthDate, contact fields on AppUser (V7 migration); PUT /api/users/me, POST /api/users/me/password, GET /api/users/{id} endpoints
  • Auth fix: handleFetch hook no longer skips auth headers for /api/users/me sub-paths (the hook's own user-load uses globalThis.fetch and is unaffected)
  • API regenerated with new endpoints and AppUser schema fields

Test plan

  • Nav: initials button visible after login; opens dropdown; profile link navigates to /profile; Escape closes dropdown
  • Profile page: save personal info; wrong current password shows error; mismatched passwords shows error; correct password change succeeds
  • Public profile: /users/<id> shows name and contact for a known user
  • npm run test — layout spec (7/7 pass), all other existing specs pass
  • npm run check — 0 errors
  • npm run lint — clean

🤖 Generated with Claude Code

## Summary - **Nav avatar dropdown**: replaces the plain logout button with a circular initials button (e.g. `MM`), falling back to a person icon; clicking opens a dropdown with a `/profile` link and logout - **Profile page** (`/profile`): two-card layout — personal info form (first name, last name, birth date, email, contact) and password change form, each with independent `use:enhance` actions - **Public user profile** (`/users/[id]`): read-only view of another user's name, username, email, and contact - **Backend**: new `firstName`, `lastName`, `birthDate`, `contact` fields on `AppUser` (V7 migration); `PUT /api/users/me`, `POST /api/users/me/password`, `GET /api/users/{id}` endpoints - **Auth fix**: `handleFetch` hook no longer skips auth headers for `/api/users/me` sub-paths (the hook's own user-load uses `globalThis.fetch` and is unaffected) - **API regenerated** with new endpoints and `AppUser` schema fields ## Test plan - [ ] Nav: initials button visible after login; opens dropdown; profile link navigates to `/profile`; Escape closes dropdown - [ ] Profile page: save personal info; wrong current password shows error; mismatched passwords shows error; correct password change succeeds - [ ] Public profile: `/users/<id>` shows name and contact for a known user - [ ] `npm run test` — layout spec (7/7 pass), all other existing specs pass - [ ] `npm run check` — 0 errors - [ ] `npm run lint` — clean 🤖 Generated with [Claude Code](https://claude.com/claude-code)
marcel added 6 commits 2026-03-20 23:12:05 +01:00
Add firstName, lastName, birthDate, contact to AppUser via V7 migration.
Add PUT /api/users/me and POST /api/users/me/password endpoints.
Add GET /api/users/{id} for public profile lookup.
Add EMAIL_ALREADY_IN_USE and WRONG_CURRENT_PASSWORD error codes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add profile_* message keys for the profile page forms in de/en/es.
Add EMAIL_ALREADY_IN_USE and WRONG_CURRENT_PASSWORD to ErrorCode type and
getErrorMessage switch.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Show user initials (e.g. MM) in a circular button when name is set,
or a fallback person icon. Clicking opens a dropdown with links to
/profile and a logout form.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
/profile: two-card layout with personal info form (name, birth date,
email, contact) and password change form, each with independent actions.
/users/[id]: read-only public view showing name, username, email, contact
with avatar circle initials.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The handleFetch hook previously skipped auth headers for all URLs
containing /api/users/me. Since the hook's own user-load call uses
globalThis.fetch (bypassing handleFetch), it is safe to remove this
exception — enabling profile update and password change actions to
authenticate properly.

Also regenerates API types with new profile endpoints and AppUser fields.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
fix(tests): fix type errors in spec files after adding user to App.PageData
Some checks failed
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
CI / Unit & Component Tests (pull_request) Successful in 1m57s
CI / Backend Unit Tests (pull_request) Successful in 1m55s
CI / E2E Tests (pull_request) Failing after 14m6s
a65c69b0ce
Add user: undefined to baseData in conversations and documents/new specs.
Change null to undefined for filePath/transcription in makeDoc fixture.
Add form: null to render calls missing it.
Fix birthYear conversion from string to number in persons/[id] server action.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
marcel added 1 commit 2026-03-20 23:19:35 +01:00
fix(profile): use dd.mm.yyyy date input for birth date field
Some checks failed
CI / Unit & Component Tests (pull_request) Successful in 2m4s
CI / Backend Unit Tests (pull_request) Successful in 1m57s
CI / E2E Tests (pull_request) Failing after 13m53s
CI / Unit & Component Tests (push) Successful in 2m35s
CI / E2E Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
18601db4f8
Replace the browser-native type="date" picker with a text input using
the same german format (dd.mm.yyyy with auto-dot insertion) as the
document date fields. A hidden input sends the ISO value to the server.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
marcel merged commit 18601db4f8 into main 2026-03-22 14:52:08 +01:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: marcel/familienarchiv#45