Skip to content

Admin in-file cleanup: mail, discovery, users, moderation, home, analytics, hosts, pages - #45

Closed
theobong wants to merge 6 commits into
chore/admin-campaign-07-cleanup-afrom
chore/admin-campaign-08-cleanup-b
Closed

theobong wants to merge 6 commits into
chore/admin-campaign-07-cleanup-afrom
chore/admin-campaign-08-cleanup-b

Conversation

@theobong

Copy link
Copy Markdown
Member

What changed

A behavior-neutral cleanup of Mail, Inbox, Jurisdictions, Users, Moderation, Home, Analytics, Host messaging and Signup pages. Nothing on screen or in any request changes:

  • The remaining very long components are split into focused files and hooks: the mail page and reader, the jurisdiction detail and directory, the user and moderation details, the gov-claim detail, the home page, analytics, the host detail and the page detail.
  • Magic numbers are named, and shared values come from the shared constants.
  • The mail folder/box state gets a real type.
  • Cryptic helper names are spelled out.
  • Dead code is deleted, and file-local symbols are no longer exported.

Visible in: admin (nothing should change).

Before you start

Verify

[Admin]

Mail:

  1. Open "Mail". Switch between "Outreach" and "Inbox", try each chip, and search. Expect: the same lists, counts and chips as before.
  2. Open a thread, type a reply, then open the thread's bounce actions if it has any. Expect: the reply draft stays while you stay on the thread.
  3. Click "Compose" and "Default template". Expect: both modals work as before.

Jurisdictions:
4. Open "Jurisdictions". Switch the filter, sort and layer, and open a jurisdiction. Expect: the same detail: boundary map, notes, handle, contacts grid, email template and actions.
5. Edit a contact and click "Save draft". Expect: the toast "Draft saved for ".

Users and moderation:
6. Open "Users", select an account, and switch the "Activity" tabs. Expect: the same detail and actions.
7. Open "Moderation", select an item, then switch to "Gov claims" and select a claim. Expect: the same detail, checks and decision buttons.
8. In "Organizations" → Members → "Add member", search for a user. Expect: the same picker.

Home, analytics, hosts, pages:
9. Open the "Dashboard". Expect: the same tiles, preview rows, analytics cell and live map.
10. Open "Analytics" and click "Export". Expect: the same cards and the same CSV.
11. Open "Host messaging" and select a host. Expect: the same broadcast log and actions.
12. Open "Signup pages" and select a page. Expect: the same preview and actions.

Regression

Everything that shares the moved code: [Admin]

  1. In each of these sections, run one action (flag, suspend, reply, save) and follow one deep link from the Dashboard. Expect: the same toasts and selection behavior as before.

Not covered

  • The split files are covered by the full characterization suite, which is unchanged apart from import paths: 112 files, 1,141 tests.

Findings addressed

  • Mail: MailPage (354 lines, complexity 44) is split into state, hooks, a folder switch, a stats strip, a toolbar, list and detail panes, and compose and template modals. MailReader (221 lines) is split into head, links, message, notes, bounce footer and composer; its draft and mutations stay in the reader. The mail box state is now a union type.
  • Jurisdictions: JurisdictionDetail (438 lines, complexity 30) is split into an editor hook plus panels. DiscoveryPage (complexity 44) is split into filter and selection hooks, a toolbar and the list body. The nested ternaries became tables, with one routing-status pill and one row skeleton.
  • Users and moderation: the user, moderation and gov-claim details are split into focused files; users-page.tsx no longer holds about 10 components.
  • Home, analytics, hosts, pages: HomePage, AnalyticsPage, HostDetail, PageDetail and pageBlockView are split. The preview fetch limit is named once, replacing PREVIEW_ROWS + 1 in about 7 places.
  • Magic values: now named, for example the reply scroll delay, the truncation size, the geometry stale time, the age thresholds, the picker debounce (200 ms, kept local because it is not the 250 ms search debounce) and the avatar sizes. Shared values come from lib/timing, lib/bytes and lib/display.
  • Names: fmtRouted, fmtAge and fmtPop become formatRoutedDate, formatWaitingAge and formatPopulation, and short local variables get real names.
  • Dead code:
    • the mail reader's reset effect, which could never fire because the reader is keyed by thread;
    • the ts() wrapper;
    • unused exports.

Decisions for the reviewer

  • None. The two discovery hooks the ledger called dead (flag, save draft) now have tests, and the notes hooks wait on the notes decision. All stay.

Tests changed

  • Existing assertions are unchanged. The inbox guard against rendering mail as HTML now scans every non-test mail and inbox component (a directory scan instead of a hand-kept list), so the next split cannot slip past it.
  • New tests cover the mail page state, template insertion, jurisdiction view helpers, the directory query, user status actions and org members.

Verification

  • Node v22.23.2. pnpm lint, pnpm typecheck, pnpm build and pnpm test pass: 112 files, 1,141 tests.
  • The mail and discovery split was also checked with a throwaway harness. It rendered the old and new pages side by side with the same data and interactions across 13 scenarios, and compared the full HTML and every API call. All were identical.
  • An adversarial review per chunk found no behavior change. It specifically confirmed that no draft or mutation moved below a detail early return, that no subtree gained a remounting key, and that every constant kept its value.

🤖 Generated with Claude Code

@byteful byteful closed this Sep 24, 2026
@byteful
byteful deleted the chore/admin-campaign-08-cleanup-b branch September 24, 2026 20:13
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.

2 participants