Files
GearBox/.planning/phases/18-global-items-public-profiles/18-05-PLAN.md

9.5 KiB

phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, must_haves
phase plan type wave depends_on files_modified autonomous requirements must_haves
18-global-items-public-profiles 05 execute 3
18-03
src/client/hooks/useProfile.ts
src/client/routes/users/$userId.tsx
src/client/routes/settings.tsx
src/client/routes/setups/index.tsx
src/client/components/ProfileSection.tsx
src/client/components/PublicSetupCard.tsx
false
PROF-01
PROF-02
PROF-03
PROF-04
PROF-05
truths artifacts key_links
User can edit display name, avatar, and bio in settings page
Public profile page at /users/:id shows display name, avatar, bio, and public setups
Public profile page works without login (no auth required)
User can toggle a setup between public and private in the setup detail/edit view
Public setups appear on the owner's profile page; private ones do not
path provides exports
src/client/hooks/useProfile.ts usePublicProfile, useUpdateProfile hooks
usePublicProfile
useUpdateProfile
path provides min_lines
src/client/routes/users/$userId.tsx Public profile page 40
path provides min_lines
src/client/components/ProfileSection.tsx Profile edit form within settings 30
path provides min_lines
src/client/components/PublicSetupCard.tsx Card for setup shown on public profile 15
from to via pattern
src/client/routes/users/$userId.tsx src/client/hooks/useProfile.ts usePublicProfile hook usePublicProfile
from to via pattern
src/client/hooks/useProfile.ts /api/users/:id/profile apiGet fetch apiGet.*users.*profile
from to via pattern
src/client/routes/settings.tsx src/client/components/ProfileSection.tsx component import ProfileSection
Build the user profile and public sharing client: profile edit section in settings, public profile page, setup visibility toggle, and public setup cards.

Purpose: Delivers the client-side experience for PROF-01 (profile edit), PROF-02 (public profile), PROF-03 (setup toggle), PROF-04 (public setup view), PROF-05 (profile lists public setups). Output: useProfile hook, public profile page, ProfileSection component, PublicSetupCard, updated settings and setup views

<execution_context> @$HOME/.claude/get-shit-done/workflows/execute-plan.md @$HOME/.claude/get-shit-done/templates/summary.md </execution_context>

@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/phases/18-global-items-public-profiles/18-CONTEXT.md @.planning/phases/18-global-items-public-profiles/18-RESEARCH.md @.planning/phases/18-global-items-public-profiles/18-03-SUMMARY.md

@src/client/routes/settings.tsx @src/client/routes/setups/index.tsx @src/client/hooks/useItems.ts @src/client/lib/api.ts

PUT /api/auth/profile { displayName?, avatarUrl?, bio? } -> updated user (auth required) GET /api/users/:id/profile -> { id, displayName, avatarUrl, bio, setups: [{ id, name, createdAt }] } (no auth) GET /api/setups/:id/public -> { id, name, isPublic, items: [...], totalWeight, totalCost } (no auth, 404 if private) Task 1: Profile hooks and profile edit UI src/client/hooks/useProfile.ts, src/client/components/ProfileSection.tsx, src/client/routes/settings.tsx src/client/routes/settings.tsx, src/client/hooks/useItems.ts, src/client/lib/api.ts **useProfile.ts** hook: Create at `src/client/hooks/useProfile.ts`.
  1. usePublicProfile(userId: number | null)useQuery with key ["profiles", userId], fetches apiGet("/api/users/${userId}/profile"), enabled: userId != null.

  2. useUpdateProfile()useMutation calling apiPut("/api/auth/profile", data). On success, invalidate ["profiles"] query key. Return mutation.

ProfileSection.tsx: Create at src/client/components/ProfileSection.tsx. Per D-09.

A form section that contains:

  • Display name text input (max 100 chars) with label
  • Bio textarea (max 500 chars) with character counter
  • Avatar: Show current avatar if set, with a "Change avatar" button that opens the existing ImageUpload component (per D-11, reuse existing image upload + MinIO storage). After upload, set avatarUrl to the returned filename (the route will handle presigned URL generation).
  • Save button calling useUpdateProfile() mutation
  • Success/error toast feedback (use existing toast pattern if available, otherwise simple inline message)

Pre-populate form with current profile data. On mount, fetch current user profile via an appropriate mechanism (could be from auth context or a dedicated endpoint).

settings.tsx: Read the existing settings page. Add a "Profile" section at the top (before API Keys and other settings). Import and render <ProfileSection />. The section should have a heading "Profile" with a brief description "Your public profile information." bun run lint 2>&1 | tail -5 <acceptance_criteria> - grep -q "usePublicProfile" src/client/hooks/useProfile.ts - grep -q "useUpdateProfile" src/client/hooks/useProfile.ts - grep -q "ProfileSection" src/client/components/ProfileSection.tsx - grep -q "ProfileSection" src/client/routes/settings.tsx </acceptance_criteria> Profile edit section in settings page with display name, bio, and avatar upload. Hooks handle fetch and mutation. Form saves correctly.

Task 2: Public profile page and setup visibility toggle src/client/routes/users/$userId.tsx, src/client/components/PublicSetupCard.tsx, src/client/routes/setups/index.tsx src/client/routes/setups/index.tsx, src/client/hooks/useProfile.ts **users/$userId.tsx**: Create at `src/client/routes/users/$userId.tsx`. Per D-10.

Public profile page (no auth required to view):

  • TanStack Router: createFileRoute("/users/$userId") with params
  • Fetch profile with usePublicProfile(Number(userId))
  • Layout: Avatar (or placeholder icon), display name (or "User #{id}" fallback), bio text
  • Below profile: "Public Setups" heading with grid of PublicSetupCard components
  • Empty state if no public setups: "No public setups yet"
  • Loading skeleton while fetching
  • 404 handling if user not found

PublicSetupCard.tsx: Create at src/client/components/PublicSetupCard.tsx.

A card for setups shown on the public profile:

  • Setup name as heading
  • Created date formatted
  • Links to /setups/${id}/public for the public view (or you can create an inline expandable view)
  • Light card styling with subtle border/shadow, matching existing setup cards

setups/index.tsx or setup detail: Update the setup list or detail view to include the isPublic toggle per D-14.

  • In the setup detail/edit view, add a toggle switch or checkbox labeled "Public" next to the setup name
  • When toggled, call the existing setup update mutation with isPublic: true/false
  • Show a small icon or badge on the setup list indicating public status (e.g., a globe icon or "Public" chip)
  • Default all existing setups to show as private (per D-12) bun run lint 2>&1 | tail -5 <acceptance_criteria>
    • test -f "src/client/routes/users/$userId.tsx"
    • grep -q "usePublicProfile" "src/client/routes/users/$userId.tsx"
    • test -f src/client/components/PublicSetupCard.tsx
    • grep -q "isPublic|public" src/client/routes/setups/index.tsx </acceptance_criteria> Public profile page shows user info and public setups. Setup detail has visibility toggle. Public setups appear on profile. Private setups are hidden from profile.
Task 3: Verify profiles and public sharing UI none Human verification of user profiles and public sharing. Review what was built: profile edit in settings, public profile page, setup visibility toggle.

Steps to verify:

  1. Start dev server: bun run dev
  2. Go to Settings — should see a new "Profile" section at top
  3. Enter a display name and bio, save — should show success
  4. Upload an avatar image — should display
  5. Go to Setups, open a setup detail, find the "Public" toggle
  6. Toggle a setup to public
  7. Navigate to /users/{your-user-id} — should see profile with the public setup listed
  8. Open an incognito/private window (no auth)
  9. Visit the same /users/{id} URL — should show profile and public setup without login
  10. Toggle the setup back to private — it should disappear from the profile page bun run build 2>&1 | tail -3 User approves profiles and sharing UI: profile edit works, public profile shows correct data, setup toggle works, unauthenticated access functions correctly.
- `bun run lint` passes - `bun run build` succeeds - Visual verification: profile edit, public profile page, setup toggle, and public access

<success_criteria> Profile can be edited in settings. Public profile page works without auth. Setup visibility toggle works. Public setups appear on profile, private ones don't. Avatar upload uses existing image infrastructure. </success_criteria>

After completion, create `.planning/phases/18-global-items-public-profiles/18-05-SUMMARY.md`