Skip to content

Web UI refactoring: SRP, hooks extraction, deduplication & test coverage #76

@jonit-dev

Description

@jonit-dev

Problem

The web UI has grown organically with several code quality issues:

  • Settings.tsx is 1,104 lines — handles config loading, preset CRUD, tab navigation, auto-save, cron orchestration, and inline tab content
  • No form management abstraction — manual useState + updateField scattered per page
  • Duplicated logic across pages — cron reinstall (5x), trigger job (2x), loading spinners (8x), schedule state init (2x)
  • Prop drilling — 5+ handler functions drilled from Settings into AiRuntimeTab
  • Inconsistent UI patternswindow.confirm() in Board, alert() in ProviderEnvEditor, raw <textarea> bypassing the design system
  • Direct DOM manipulationclassList.add/remove + setTimeout in Settings for scroll highlighting
  • Dead/redundant codetypes.ts re-exports with aliases, unused function parameters, meaningless .bind() call in useApi
  • Test suite is shallow — Settings tests don't render components (just check arrays), 10/13 Scheduling tests are skipped, no unit tests for hooks/utilities

Full PRD: docs/prds/web-refactor-plan.md


Phase 1: Extract Shared Hooks & Utilities

  • useCronReinstall — consolidate 5 identical cron-reinstall-with-toast blocks (Settings.tsx lines 470-494, 529-549; Scheduling.tsx lines 188-209, 340-364)
  • useTriggerJob — consolidate duplicate job trigger logic in Dashboard.tsx:121-133 and Scheduling.tsx:221-247
  • useConfigForm — generic config→form state + updateField + dirty tracking (used by Settings & Scheduling)
  • usePresetManagement — encapsulate all preset CRUD, eliminate 5-prop drilling into AiRuntimeTab

Phase 2: Break Up Settings.tsx (1,104 → ~250 lines)

  • Extract remaining inline tabs to sub-components: SchedulesTab.tsx, IntegrationsTab.tsx, AdvancedTab.tsx
  • Move BUILT_IN_PRESET_IDS + preset data to web/constants/presets.ts (currently copy-pasted in 2 files)
  • Remove getPresetOptions unused _customPresets parameter
  • Replace DOM manipulation (classList.add/remove + setTimeout) with React state + ref patterns

Phase 3: Fix Inconsistencies & Dead Code

  • Replace window.confirm() (Board.tsx:144) with confirmation modal
  • Replace alert() (ProviderEnvEditor.tsx:56) with addToast()
  • Fix closeBoardIssue (api.ts:391-401) to use apiFetch instead of reimplementing error handling
  • Create <LoadingState> component (eliminate 8 identical spinner blocks)
  • Create <Textarea> UI component (eliminate raw <textarea> with duplicated Tailwind classes)
  • Clean up types.ts — remove dead types (PRD, PullRequest, ActionLog, Notification, Project), remove alias re-exports
  • Move IScheduleConfigForm from ScheduleConfig.tsx to types.ts
  • Fix useApi meaningless .bind() call (api.ts:575)
  • Move IAgentInfo out of function body in Scheduling.tsx:463-476, useMemo the agents array

Phase 4: Testing Infrastructure & Coverage

Current state: vitest + RTL + Playwright installed, but tests are shallow or skipped.

  • Fix/delete 10 skipped tests in Scheduling.test.tsx (marked "SKIPPED: UX revamp")
  • Replace Settings.test.tsx array-checking tests with actual RTL render tests
  • Add renderHook unit tests for all new hooks (useCronReinstall, useTriggerJob, useConfigForm, usePresetManagement)
  • Add comprehensive unit tests for cron.ts utilities (497 lines, minimal coverage)
  • Add RTL integration tests for Dashboard, Board pages
  • Add data-testid attributes to key UI elements for stable Playwright selectors
  • Consider adding vitest run to yarn verify

Execution Order

Phase 1 (hooks) → Phase 2 (Settings breakup) → Phase 3 (cleanup) → Phase 4 (tests)

Phases 1-3 sequential (each builds on previous). Phase 4 can partially overlap with Phase 3.

Success Criteria

  • No file in web/ exceeds 400 lines
  • Zero duplicated logic patterns (cron reinstall, trigger job, loading state)
  • All hooks have unit tests with renderHook
  • Settings.tsx is an orchestrator only (~200-300 lines)
  • No window.confirm(), alert(), or direct DOM manipulation
  • All skipped tests updated or removed
  • BUILT_IN_PRESET_IDS defined in exactly one place

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions