Skip to content

feat(admin): extract per-section components from admin page monolith#145

Merged
MBombeck merged 1 commit intomainfrom
feat/v141-admin-section-extraction
May 8, 2026
Merged

feat(admin): extract per-section components from admin page monolith#145
MBombeck merged 1 commit intomainfrom
feat/v141-admin-section-extraction

Conversation

@MBombeck
Copy link
Copy Markdown
Owner

@MBombeck MBombeck commented May 8, 2026

Summary

Splits the 2,702-line admin page into focused per-section files. The status-first card grid foundation in #133 already moved the dashboard surface out; this commit moves the inner panels — closes the A4 per-section extraction carve-out tracked for v1.4.1.

What changed

Before

  • src/app/admin/page.tsx: 2,702 lines, 19 inline section functions, shared helpers + types + hooks + UI primitives all in one file.

After

  • src/app/admin/page.tsx: 77 lines. Just the route shell — auth gate, page title, and the 14 sections rendered in the same order as before.
  • src/components/admin/:
File LOC Purpose
_shared.tsx 276 Types, hooks (useAdminSettings, useUpdateSettings, useSystemStatus), primitives (PasswordInput, StatusItem, SettingsToggle), getApiErrorMessage
system-status-section.tsx 155 At-a-glance system metrics
general-settings-section.tsx 54 Registration toggle + default locale
services-section.tsx 68 Telegram / ntfy / WebPush / API global toggles
umami-section.tsx 173 Umami config + test button
glitchtip-section.tsx 172 Glitchtip config + test button
web-push-vapid-section.tsx 148 VAPID key management
bug-report-section.tsx 109 GitHub bug-report repo + token
reminders-section.tsx 318 Late/missed thresholds + manual run
user-management-section.tsx 341 Users table + edit + reset-password dialogs
api-token-overview-section.tsx 144 API tokens read-only viewer
login-overview-section.tsx 181 Audit-log preview
danger-zone-section.tsx 118 Wipe-all-data action
feedback-inbox-section.tsx 511 Inbox + category badge + detail dialog (kept together because the dialog only consumes inbox state)

Behavior

Mechanical extraction only — no logic change. Same DOM, same i18n keys, same query keys, same section anchors (id="section-…" so the sidebar deep-links still scroll into place). One small parameter cleanup: UserManagementSection no longer takes a queryClient prop; it grabs its own via useQueryClient() like every other section does (the prop was a leftover from the original page being a client component that already held a queryClient instance).

Quality gates

  • pnpm typecheck — clean
  • pnpm test — 658/658 pass
  • pnpm lint — 0 errors (12 pre-existing unused-var warnings, none new)
  • pnpm exec prettier --check src/components/admin src/app/admin — clean

Why now

Closes the structural cleanup carve-out from v1.4.0 (the foundation in #133 shipped the status-first redesign; the inner monolith was tracked for v1.4.1). Future per-section work — adding tests, refining UX, splitting the feedback dialog further — now has a per-file scope instead of every diff touching the same 2,700-line file.

🤖 Generated with Claude Code

The admin page was a single 2,702-line client component with
nineteen inline functions covering everything from system status
to feedback inbox. The status-card grid foundation in #133 already
moved the at-a-glance dashboard out; this commit moves the inner
panels.

Split into one file per logical section in src/components/admin/:

  _shared.tsx                         276 LOC  shared types, hooks,
                                                primitives (PasswordInput,
                                                StatusItem, SettingsToggle,
                                                useAdminSettings,
                                                useUpdateSettings,
                                                useSystemStatus,
                                                getApiErrorMessage)
  system-status-section.tsx           155
  general-settings-section.tsx         54
  services-section.tsx                 68
  umami-section.tsx                   173
  glitchtip-section.tsx               172
  web-push-vapid-section.tsx          148
  bug-report-section.tsx              109
  reminders-section.tsx               318
  user-management-section.tsx         341
  api-token-overview-section.tsx      144
  login-overview-section.tsx          181
  danger-zone-section.tsx             118
  feedback-inbox-section.tsx          511 (inbox + category badge
                                            + detail dialog)

src/app/admin/page.tsx is now a 77-line shell that imports the
14 sections and the existing status-card-grid.tsx. No behavior
change — every section keeps the same DOM, the same query keys,
the same i18n keys, the same id="…" anchors so deep-links from
the sidebar still scroll into place. UserManagementSection no
longer takes a queryClient prop; it grabs its own via
useQueryClient() like every other section does.

Co-Authored-By: Marc-André Bombeck <mbombeck@gmail.com>
@MBombeck MBombeck merged commit 6da9428 into main May 8, 2026
6 checks passed
@MBombeck MBombeck deleted the feat/v141-admin-section-extraction branch May 8, 2026 13:58
MBombeck added a commit that referenced this pull request May 8, 2026
Production at healthlog.bombeck.io has been 503-ing since the v1.4.1
deploys started landing on apps-01 (Coolify). The container boots —
Next.js prints "Ready" and the pg-boss workers run — but never
accepts HTTP on :3000, so the Docker healthcheck fails and Traefik
takes the upstream out of rotation. A manual restart, a Coolify
force-rebuild, and a docker-compose pin to the GHCR :1.4.0 multi-arch
image all failed to bring the site back up — Coolify rebuilds the
image from main HEAD on every deploy regardless of the compose
directives.

This commit resets the working tree to commit 21bd46d (v1.4.0
release). Same content that's been running for self-hosters since
yesterday's tag-and-release. The next Coolify deploy will build
from this tree and produce a healthy container.

The v1.4.1 work is NOT lost:
  - PRs #144, #145, #137, #146, #147, #148, #149, #150 remain in
    git history.
  - Their commits are still tagged (`v1.4.1`), still on the GHCR
    multi-arch image (`ghcr.io/mbombeck/healthlog:1.4.1`), still in
    the GitHub Release notes.
  - Self-hosters who have already pulled the v1.4.1 image keep it.
  - Local development continues from main HEAD with the v1.4.1
    code — the regression only surfaced under the Coolify build
    flow.

Re-applying v1.4.1 to production will need a separate cycle to
reproduce the runtime failure under the Coolify build path. That
work is tracked in docs/ops/v141-followup-issues.md (added back
when the tree is reapplied) and the deploy gating in
.github/workflows/e2e.yml will catch this class of bug going
forward.

No DB migration. No env-var change. No API contract change.
Co-Authored-By: Marc-André Bombeck <mbombeck@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant