Skip to content

feat(profile): production-ready profile block (avatar S3, i18n, +87 tests, UTC fix)#289

Open
abdout wants to merge 2 commits into
mainfrom
feat/profile-block
Open

feat(profile): production-ready profile block (avatar S3, i18n, +87 tests, UTC fix)#289
abdout wants to merge 2 commits into
mainfrom
feat/profile-block

Conversation

@abdout
Copy link
Copy Markdown
Contributor

@abdout abdout commented Apr 26, 2026

Summary

Production-ready profile block work, isolated from feat/cdn-cname-migration (PR #272) which is blocked on CNAME verification.

  • Avatar upload: was a no-op stub returning fake success — now persists via the shared S3 pipeline (file/upload/actions::uploadFile) with MIME validation and 5 MB cap.
  • updateProfileSettings: same lie (validated then no-op write) — now returns NOT_IMPLEMENTED until the User schema gains settings columns.
  • Contribution graph timezone bug: getYearDateRange used local-time new Date(year, 0, 1) while formatDateKey was UTC, shifting Jan 1 to Dec 31 in any positive UTC offset (Riyadh +3 etc.). Switched the helper to Date.UTC + setUTCDate so the calendar is timezone-stable.
  • viewerPermission (OWNER/ADMIN/STAFF/RELATED/PUBLIC) added to getProfileBasicData so the UI can mask emailAddress/employeeId for non-admins.
  • i18n: replaced hardcoded English error strings in edit-role-actions.ts, detail/actions.ts, and actions.ts (updatePinnedItems "Maximum 6...") with action error codes.
  • Removed dead Octicon icon-reference grid that was leaking debug UI into the profile overview tab.
  • Documented detail/actions.ts as foundation code for a future admin user-detail page.

Tests (5 → 92)

  • __tests__/actions.test.ts: rewrote weak prisma-mock smoke tests into 35 real tests (auth/tenant gates, schoolId scoping, role mapping, pinned items, activity logging, viewerPermission flagging).
  • __tests__/validation.test.ts (new, 22): every Zod schema + edge cases.
  • __tests__/contribution.test.ts (new, 12): year validation, leap-year day count, activity aggregation, streak math, missing-role-record path.
  • detail/__tests__/permissions.test.ts (new, 23): full RBAC matrix.
  • tests/e2e/profile/profile-flows.spec.ts (new, 6 specs): own profile, edit form, view-other, auth gate, teacher self-service.

Self-QA verdict (PASS)

Keyword Result
guard 17/17 mutating actions auth + tenant gated; 32 schoolId-scoped queries
architecture Mirror pattern intact; correct server/client split; Promise.all for parallel fetches
structure 17 source + 4 test files in standard layout
pattern auth → tenant → Zod parse → mutate → revalidatePath
design All 10 client UI files use @/components/ui or @/components/atom
stack Zero deprecated APIs
efficient unstable_cache (300s TTL) on contribution graph

Test plan

  • pnpm tsc --noEmit — 0 errors
  • pnpm vitest run src/components/school-dashboard/profile — 92/92 passing
  • HTTP smoke on production: ed.databayt.org 200, demo.databayt.org/en/profile 200
  • Browser-side verification (see / flow / lang / check) — pending browser MCP reconnection
  • Visual regression on demo.databayt.org/en/profile post-merge

Infra

  • Added NOT_IMPLEMENTED to ACTION_ERRORS for honest stub responses.

🤖 Generated with Claude Code

abdout and others added 2 commits April 26, 2026 16:09
…ontribution map, +87 tests

Block-level fixes
- Avatar upload: was a no-op stub returning fake success; now persists via the
  shared S3 pipeline (file/upload/actions::uploadFile) with MIME and 5MB caps.
- updateProfileSettings: same lie (validated then no-op write); now returns
  NOT_IMPLEMENTED until the User schema gains settings columns.
- Contribution graph timezone bug: getYearDateRange used local-time
  new Date(year, 0, 1) while formatDateKey was UTC, shifting Jan 1 to Dec 31
  in any positive UTC offset (Riyadh +3 etc.). Switched the helper to
  Date.UTC + setUTCDate so the calendar is timezone-stable.
- Added viewerPermission (OWNER/ADMIN/STAFF/RELATED/PUBLIC) to
  getProfileBasicData so the UI can mask emailAddress/employeeId for non-admins.
- Replaced hardcoded English error strings in edit-role-actions.ts and
  detail/actions.ts with action error codes (i18n compliance).
- Removed dead Octicon icon-reference grid that was leaking debug UI into
  the profile overview tab.
- Documented detail/actions.ts as foundation code for a future admin
  user-detail page (currently dead, kept intentionally).

Tests (5 → 92)
- __tests__/actions.test.ts: rewrote weak prisma-mock smoke tests into 35
  real tests covering auth/tenant gates, schoolId scoping, role mapping,
  pinned items, activity logging, viewerPermission flagging.
- __tests__/validation.test.ts (new, 22): every Zod schema + edge cases.
- __tests__/contribution.test.ts (new, 12): year validation, leap-year day
  count, activity aggregation, streak math, missing-role-record path.
- detail/__tests__/permissions.test.ts (new, 23): full RBAC matrix.
- tests/e2e/profile/profile-flows.spec.ts (new, 6 specs): own profile,
  edit form, view-other, auth gate, teacher self-service.

Infra
- Added NOT_IMPLEMENTED to ACTION_ERRORS for honest stub responses.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…code

Self-QA caught one missed translation leak in updatePinnedItems:
"Maximum 6 pinned items allowed" → VALIDATION_ERROR + MAX_PINNED_EXCEEDED detail.

Strengthens the corresponding test to assert both error code and detail.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 26, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
hogwarts Ready Ready Preview, Comment Apr 26, 2026 1:16pm

@github-actions github-actions Bot added area: platform Platform dashboard code type: tests Test changes labels Apr 26, 2026
return `http://${host}/en/profile`
}

function profileForId(userId: string, host = DEMO_HOST) {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: platform Platform dashboard code type: tests Test changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants