Episode 2 — React Frontend Architecture NextJS / 2.9 — Custom Hooks and Reusable Logic

2.9.c — Separating business logic from UI

<< 2.9 Overview


Learning outcomes

  1. Place domain rules in pure modules testable without React.
  2. Keep hooks as orchestrators: effects, subscriptions, mapping to UI state.
  3. Avoid returning JSX from hooks meant for reuse.

Layering model

UI components (presentation)
  ↓ calls
Custom hooks (orchestration: React concerns)
  ↓ calls
Domain + services (pure rules, API adapters)

Example boundary

// domain/invoice.ts — pure, unit-tested
export function canSubmit(invoice: { total: number; lines: number }) {
  return invoice.lines > 0 && invoice.total >= 0;
}
// hooks/useInvoiceForm.ts
import { canSubmit } from "../domain/invoice";
import { useMemo, useState } from "react";

export function useInvoiceForm() {
  const [lines, setLines] = useState(0);
  const [total, setTotal] = useState(0);
  const submitAllowed = useMemo(() => canSubmit({ total, lines }), [total, lines]);
  return { lines, total, setLines, setTotal, submitAllowed };
}

The component only renders inputs and buttons using submitAllowed.



Appendix — Scenario bank (basic → advanced)

Flashcard: symptom → cause → fix → interview phrase.

CH2-001 — Business vs UI #1

  • Level: Beginner
  • Symptom: duplicate useEffect blocks across 13 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: No pure function tests; only brittle E2E for core calculations.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-002 — Business vs UI #2

  • Level: Beginner+
  • Symptom: duplicate useEffect blocks across 26 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Authorization checks only in UI hiding missing server enforcement.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-003 — Business vs UI #3

  • Level: Intermediate
  • Symptom: duplicate useEffect blocks across 39 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Hook returns ready-made <Card/> elements mixing view and rules.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-004 — Business vs UI #4

  • Level: Intermediate+
  • Symptom: duplicate useEffect blocks across 52 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: DTO mapping duplicated in three hooks with drift.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-005 — Business vs UI #5

  • Level: Advanced
  • Symptom: duplicate useEffect blocks across 65 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Fat useInvoice hook imports UI icons for side effects.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-006 — Business vs UI #6

  • Level: Advanced+
  • Symptom: duplicate useEffect blocks across 78 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Currency math in component without shared money.ts module.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-007 — Business vs UI #7

  • Level: Beginner
  • Symptom: duplicate useEffect blocks across 91 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Business rules embedded in JSX ternary chains unreadable in review.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-008 — Business vs UI #8

  • Level: Beginner+
  • Symptom: duplicate useEffect blocks across 104 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: No pure function tests; only brittle E2E for core calculations.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-009 — Business vs UI #9

  • Level: Intermediate
  • Symptom: duplicate useEffect blocks across 117 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Authorization checks only in UI hiding missing server enforcement.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-010 — Business vs UI #10

  • Level: Intermediate+
  • Symptom: duplicate useEffect blocks across 130 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Hook returns ready-made <Card/> elements mixing view and rules.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-011 — Business vs UI #11

  • Level: Advanced
  • Symptom: duplicate useEffect blocks across 143 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: DTO mapping duplicated in three hooks with drift.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-012 — Business vs UI #12

  • Level: Advanced+
  • Symptom: duplicate useEffect blocks across 156 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Fat useInvoice hook imports UI icons for side effects.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-013 — Business vs UI #13

  • Level: Beginner
  • Symptom: duplicate useEffect blocks across 169 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Currency math in component without shared money.ts module.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-014 — Business vs UI #14

  • Level: Beginner+
  • Symptom: duplicate useEffect blocks across 182 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Business rules embedded in JSX ternary chains unreadable in review.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-015 — Business vs UI #15

  • Level: Intermediate
  • Symptom: duplicate useEffect blocks across 195 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: No pure function tests; only brittle E2E for core calculations.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-016 — Business vs UI #16

  • Level: Intermediate+
  • Symptom: duplicate useEffect blocks across 8 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Authorization checks only in UI hiding missing server enforcement.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-017 — Business vs UI #17

  • Level: Advanced
  • Symptom: duplicate useEffect blocks across 21 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Hook returns ready-made <Card/> elements mixing view and rules.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-018 — Business vs UI #18

  • Level: Advanced+
  • Symptom: duplicate useEffect blocks across 34 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: DTO mapping duplicated in three hooks with drift.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-019 — Business vs UI #19

  • Level: Beginner
  • Symptom: duplicate useEffect blocks across 47 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Fat useInvoice hook imports UI icons for side effects.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-020 — Business vs UI #20

  • Level: Beginner+
  • Symptom: duplicate useEffect blocks across 60 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Currency math in component without shared money.ts module.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-021 — Business vs UI #21

  • Level: Intermediate
  • Symptom: duplicate useEffect blocks across 73 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Business rules embedded in JSX ternary chains unreadable in review.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-022 — Business vs UI #22

  • Level: Intermediate+
  • Symptom: duplicate useEffect blocks across 86 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: No pure function tests; only brittle E2E for core calculations.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-023 — Business vs UI #23

  • Level: Advanced
  • Symptom: duplicate useEffect blocks across 99 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Authorization checks only in UI hiding missing server enforcement.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-024 — Business vs UI #24

  • Level: Advanced+
  • Symptom: duplicate useEffect blocks across 112 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Hook returns ready-made <Card/> elements mixing view and rules.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-025 — Business vs UI #25

  • Level: Beginner
  • Symptom: duplicate useEffect blocks across 125 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: DTO mapping duplicated in three hooks with drift.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-026 — Business vs UI #26

  • Level: Beginner+
  • Symptom: duplicate useEffect blocks across 138 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Fat useInvoice hook imports UI icons for side effects.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-027 — Business vs UI #27

  • Level: Intermediate
  • Symptom: duplicate useEffect blocks across 151 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Currency math in component without shared money.ts module.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-028 — Business vs UI #28

  • Level: Intermediate+
  • Symptom: duplicate useEffect blocks across 164 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Business rules embedded in JSX ternary chains unreadable in review.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-029 — Business vs UI #29

  • Level: Advanced
  • Symptom: duplicate useEffect blocks across 177 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: No pure function tests; only brittle E2E for core calculations.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-030 — Business vs UI #30

  • Level: Advanced+
  • Symptom: duplicate useEffect blocks across 190 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Authorization checks only in UI hiding missing server enforcement.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-031 — Business vs UI #31

  • Level: Beginner
  • Symptom: duplicate useEffect blocks across 3 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Hook returns ready-made <Card/> elements mixing view and rules.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-032 — Business vs UI #32

  • Level: Beginner+
  • Symptom: duplicate useEffect blocks across 16 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: DTO mapping duplicated in three hooks with drift.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-033 — Business vs UI #33

  • Level: Intermediate
  • Symptom: duplicate useEffect blocks across 29 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Fat useInvoice hook imports UI icons for side effects.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-034 — Business vs UI #34

  • Level: Intermediate+
  • Symptom: duplicate useEffect blocks across 42 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Currency math in component without shared money.ts module.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-035 — Business vs UI #35

  • Level: Advanced
  • Symptom: duplicate useEffect blocks across 55 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Business rules embedded in JSX ternary chains unreadable in review.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-036 — Business vs UI #36

  • Level: Advanced+
  • Symptom: duplicate useEffect blocks across 68 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: No pure function tests; only brittle E2E for core calculations.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-037 — Business vs UI #37

  • Level: Beginner
  • Symptom: duplicate useEffect blocks across 81 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Authorization checks only in UI hiding missing server enforcement.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-038 — Business vs UI #38

  • Level: Beginner+
  • Symptom: duplicate useEffect blocks across 94 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Hook returns ready-made <Card/> elements mixing view and rules.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-039 — Business vs UI #39

  • Level: Intermediate
  • Symptom: duplicate useEffect blocks across 107 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: DTO mapping duplicated in three hooks with drift.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-040 — Business vs UI #40

  • Level: Intermediate+
  • Symptom: duplicate useEffect blocks across 120 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Fat useInvoice hook imports UI icons for side effects.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-041 — Business vs UI #41

  • Level: Advanced
  • Symptom: duplicate useEffect blocks across 133 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Currency math in component without shared money.ts module.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-042 — Business vs UI #42

  • Level: Advanced+
  • Symptom: duplicate useEffect blocks across 146 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Business rules embedded in JSX ternary chains unreadable in review.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-043 — Business vs UI #43

  • Level: Beginner
  • Symptom: duplicate useEffect blocks across 159 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: No pure function tests; only brittle E2E for core calculations.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-044 — Business vs UI #44

  • Level: Beginner+
  • Symptom: duplicate useEffect blocks across 172 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Authorization checks only in UI hiding missing server enforcement.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-045 — Business vs UI #45

  • Level: Intermediate
  • Symptom: duplicate useEffect blocks across 185 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Hook returns ready-made <Card/> elements mixing view and rules.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-046 — Business vs UI #46

  • Level: Intermediate+
  • Symptom: duplicate useEffect blocks across 198 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: DTO mapping duplicated in three hooks with drift.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-047 — Business vs UI #47

  • Level: Advanced
  • Symptom: duplicate useEffect blocks across 11 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Fat useInvoice hook imports UI icons for side effects.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-048 — Business vs UI #48

  • Level: Advanced+
  • Symptom: duplicate useEffect blocks across 24 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Currency math in component without shared money.ts module.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-049 — Business vs UI #49

  • Level: Beginner
  • Symptom: duplicate useEffect blocks across 37 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Business rules embedded in JSX ternary chains unreadable in review.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-050 — Business vs UI #50

  • Level: Beginner+
  • Symptom: duplicate useEffect blocks across 50 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: No pure function tests; only brittle E2E for core calculations.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-051 — Business vs UI #51

  • Level: Intermediate
  • Symptom: duplicate useEffect blocks across 63 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Authorization checks only in UI hiding missing server enforcement.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-052 — Business vs UI #52

  • Level: Intermediate+
  • Symptom: duplicate useEffect blocks across 76 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Hook returns ready-made <Card/> elements mixing view and rules.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-053 — Business vs UI #53

  • Level: Advanced
  • Symptom: duplicate useEffect blocks across 89 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: DTO mapping duplicated in three hooks with drift.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-054 — Business vs UI #54

  • Level: Advanced+
  • Symptom: duplicate useEffect blocks across 102 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Fat useInvoice hook imports UI icons for side effects.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-055 — Business vs UI #55

  • Level: Beginner
  • Symptom: duplicate useEffect blocks across 115 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Currency math in component without shared money.ts module.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-056 — Business vs UI #56

  • Level: Beginner+
  • Symptom: duplicate useEffect blocks across 128 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Business rules embedded in JSX ternary chains unreadable in review.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-057 — Business vs UI #57

  • Level: Intermediate
  • Symptom: duplicate useEffect blocks across 141 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: No pure function tests; only brittle E2E for core calculations.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-058 — Business vs UI #58

  • Level: Intermediate+
  • Symptom: duplicate useEffect blocks across 154 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Authorization checks only in UI hiding missing server enforcement.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-059 — Business vs UI #59

  • Level: Advanced
  • Symptom: duplicate useEffect blocks across 167 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Hook returns ready-made <Card/> elements mixing view and rules.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-060 — Business vs UI #60

  • Level: Advanced+
  • Symptom: duplicate useEffect blocks across 180 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: DTO mapping duplicated in three hooks with drift.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-061 — Business vs UI #61

  • Level: Beginner
  • Symptom: duplicate useEffect blocks across 193 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Fat useInvoice hook imports UI icons for side effects.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-062 — Business vs UI #62

  • Level: Beginner+
  • Symptom: duplicate useEffect blocks across 6 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Currency math in component without shared money.ts module.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-063 — Business vs UI #63

  • Level: Intermediate
  • Symptom: duplicate useEffect blocks across 19 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Business rules embedded in JSX ternary chains unreadable in review.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-064 — Business vs UI #64

  • Level: Intermediate+
  • Symptom: duplicate useEffect blocks across 32 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: No pure function tests; only brittle E2E for core calculations.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-065 — Business vs UI #65

  • Level: Advanced
  • Symptom: duplicate useEffect blocks across 45 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Authorization checks only in UI hiding missing server enforcement.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-066 — Business vs UI #66

  • Level: Advanced+
  • Symptom: duplicate useEffect blocks across 58 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Hook returns ready-made <Card/> elements mixing view and rules.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-067 — Business vs UI #67

  • Level: Beginner
  • Symptom: duplicate useEffect blocks across 71 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: DTO mapping duplicated in three hooks with drift.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-068 — Business vs UI #68

  • Level: Beginner+
  • Symptom: duplicate useEffect blocks across 84 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Fat useInvoice hook imports UI icons for side effects.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-069 — Business vs UI #69

  • Level: Intermediate
  • Symptom: duplicate useEffect blocks across 97 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Currency math in component without shared money.ts module.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-070 — Business vs UI #70

  • Level: Intermediate+
  • Symptom: duplicate useEffect blocks across 110 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Business rules embedded in JSX ternary chains unreadable in review.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-071 — Business vs UI #71

  • Level: Advanced
  • Symptom: duplicate useEffect blocks across 123 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: No pure function tests; only brittle E2E for core calculations.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-072 — Business vs UI #72

  • Level: Advanced+
  • Symptom: duplicate useEffect blocks across 136 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Authorization checks only in UI hiding missing server enforcement.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-073 — Business vs UI #73

  • Level: Beginner
  • Symptom: duplicate useEffect blocks across 149 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Hook returns ready-made <Card/> elements mixing view and rules.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-074 — Business vs UI #74

  • Level: Beginner+
  • Symptom: duplicate useEffect blocks across 162 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: DTO mapping duplicated in three hooks with drift.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-075 — Business vs UI #75

  • Level: Intermediate
  • Symptom: duplicate useEffect blocks across 175 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Fat useInvoice hook imports UI icons for side effects.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-076 — Business vs UI #76

  • Level: Intermediate+
  • Symptom: duplicate useEffect blocks across 188 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Currency math in component without shared money.ts module.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-077 — Business vs UI #77

  • Level: Advanced
  • Symptom: duplicate useEffect blocks across 1 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Business rules embedded in JSX ternary chains unreadable in review.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-078 — Business vs UI #78

  • Level: Advanced+
  • Symptom: duplicate useEffect blocks across 14 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: No pure function tests; only brittle E2E for core calculations.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-079 — Business vs UI #79

  • Level: Beginner
  • Symptom: duplicate useEffect blocks across 27 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Authorization checks only in UI hiding missing server enforcement.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-080 — Business vs UI #80

  • Level: Beginner+
  • Symptom: duplicate useEffect blocks across 40 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Hook returns ready-made <Card/> elements mixing view and rules.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-081 — Business vs UI #81

  • Level: Intermediate
  • Symptom: duplicate useEffect blocks across 53 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: DTO mapping duplicated in three hooks with drift.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-082 — Business vs UI #82

  • Level: Intermediate+
  • Symptom: duplicate useEffect blocks across 66 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Fat useInvoice hook imports UI icons for side effects.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-083 — Business vs UI #83

  • Level: Advanced
  • Symptom: duplicate useEffect blocks across 79 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Currency math in component without shared money.ts module.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-084 — Business vs UI #84

  • Level: Advanced+
  • Symptom: duplicate useEffect blocks across 92 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Business rules embedded in JSX ternary chains unreadable in review.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-085 — Business vs UI #85

  • Level: Beginner
  • Symptom: duplicate useEffect blocks across 105 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: No pure function tests; only brittle E2E for core calculations.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-086 — Business vs UI #86

  • Level: Beginner+
  • Symptom: duplicate useEffect blocks across 118 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Authorization checks only in UI hiding missing server enforcement.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-087 — Business vs UI #87

  • Level: Intermediate
  • Symptom: duplicate useEffect blocks across 131 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Hook returns ready-made <Card/> elements mixing view and rules.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-088 — Business vs UI #88

  • Level: Intermediate+
  • Symptom: duplicate useEffect blocks across 144 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: DTO mapping duplicated in three hooks with drift.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-089 — Business vs UI #89

  • Level: Advanced
  • Symptom: duplicate useEffect blocks across 157 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Fat useInvoice hook imports UI icons for side effects.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-090 — Business vs UI #90

  • Level: Advanced+
  • Symptom: duplicate useEffect blocks across 170 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Currency math in component without shared money.ts module.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-091 — Business vs UI #91

  • Level: Beginner
  • Symptom: duplicate useEffect blocks across 183 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Business rules embedded in JSX ternary chains unreadable in review.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-092 — Business vs UI #92

  • Level: Beginner+
  • Symptom: duplicate useEffect blocks across 196 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: No pure function tests; only brittle E2E for core calculations.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-093 — Business vs UI #93

  • Level: Intermediate
  • Symptom: duplicate useEffect blocks across 9 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Authorization checks only in UI hiding missing server enforcement.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-094 — Business vs UI #94

  • Level: Intermediate+
  • Symptom: duplicate useEffect blocks across 22 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Hook returns ready-made <Card/> elements mixing view and rules.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-095 — Business vs UI #95

  • Level: Advanced
  • Symptom: duplicate useEffect blocks across 35 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: DTO mapping duplicated in three hooks with drift.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-096 — Business vs UI #96

  • Level: Advanced+
  • Symptom: duplicate useEffect blocks across 48 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Fat useInvoice hook imports UI icons for side effects.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-097 — Business vs UI #97

  • Level: Beginner
  • Symptom: duplicate useEffect blocks across 61 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Currency math in component without shared money.ts module.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-098 — Business vs UI #98

  • Level: Beginner+
  • Symptom: duplicate useEffect blocks across 74 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Business rules embedded in JSX ternary chains unreadable in review.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-099 — Business vs UI #99

  • Level: Intermediate
  • Symptom: duplicate useEffect blocks across 87 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: No pure function tests; only brittle E2E for core calculations.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-100 — Business vs UI #100

  • Level: Intermediate+
  • Symptom: duplicate useEffect blocks across 100 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Authorization checks only in UI hiding missing server enforcement.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-101 — Business vs UI #101

  • Level: Advanced
  • Symptom: duplicate useEffect blocks across 113 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Hook returns ready-made <Card/> elements mixing view and rules.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-102 — Business vs UI #102

  • Level: Advanced+
  • Symptom: duplicate useEffect blocks across 126 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: DTO mapping duplicated in three hooks with drift.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-103 — Business vs UI #103

  • Level: Beginner
  • Symptom: duplicate useEffect blocks across 139 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Fat useInvoice hook imports UI icons for side effects.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-104 — Business vs UI #104

  • Level: Beginner+
  • Symptom: duplicate useEffect blocks across 152 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Currency math in component without shared money.ts module.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-105 — Business vs UI #105

  • Level: Intermediate
  • Symptom: duplicate useEffect blocks across 165 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Business rules embedded in JSX ternary chains unreadable in review.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-106 — Business vs UI #106

  • Level: Intermediate+
  • Symptom: duplicate useEffect blocks across 178 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: No pure function tests; only brittle E2E for core calculations.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-107 — Business vs UI #107

  • Level: Advanced
  • Symptom: duplicate useEffect blocks across 191 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Authorization checks only in UI hiding missing server enforcement.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-108 — Business vs UI #108

  • Level: Advanced+
  • Symptom: duplicate useEffect blocks across 4 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Hook returns ready-made <Card/> elements mixing view and rules.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-109 — Business vs UI #109

  • Level: Beginner
  • Symptom: duplicate useEffect blocks across 17 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: DTO mapping duplicated in three hooks with drift.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-110 — Business vs UI #110

  • Level: Beginner+
  • Symptom: duplicate useEffect blocks across 30 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Fat useInvoice hook imports UI icons for side effects.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-111 — Business vs UI #111

  • Level: Intermediate
  • Symptom: duplicate useEffect blocks across 43 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Currency math in component without shared money.ts module.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-112 — Business vs UI #112

  • Level: Intermediate+
  • Symptom: duplicate useEffect blocks across 56 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Business rules embedded in JSX ternary chains unreadable in review.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-113 — Business vs UI #113

  • Level: Advanced
  • Symptom: duplicate useEffect blocks across 69 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: No pure function tests; only brittle E2E for core calculations.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-114 — Business vs UI #114

  • Level: Advanced+
  • Symptom: duplicate useEffect blocks across 82 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Authorization checks only in UI hiding missing server enforcement.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-115 — Business vs UI #115

  • Level: Beginner
  • Symptom: duplicate useEffect blocks across 95 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Hook returns ready-made <Card/> elements mixing view and rules.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-116 — Business vs UI #116

  • Level: Beginner+
  • Symptom: duplicate useEffect blocks across 108 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: DTO mapping duplicated in three hooks with drift.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-117 — Business vs UI #117

  • Level: Intermediate
  • Symptom: duplicate useEffect blocks across 121 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Fat useInvoice hook imports UI icons for side effects.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-118 — Business vs UI #118

  • Level: Intermediate+
  • Symptom: duplicate useEffect blocks across 134 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Currency math in component without shared money.ts module.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-119 — Business vs UI #119

  • Level: Advanced
  • Symptom: duplicate useEffect blocks across 147 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Business rules embedded in JSX ternary chains unreadable in review.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-120 — Business vs UI #120

  • Level: Advanced+
  • Symptom: duplicate useEffect blocks across 160 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: No pure function tests; only brittle E2E for core calculations.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-121 — Business vs UI #121

  • Level: Beginner
  • Symptom: duplicate useEffect blocks across 173 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Authorization checks only in UI hiding missing server enforcement.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-122 — Business vs UI #122

  • Level: Beginner+
  • Symptom: duplicate useEffect blocks across 186 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Hook returns ready-made <Card/> elements mixing view and rules.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-123 — Business vs UI #123

  • Level: Intermediate
  • Symptom: duplicate useEffect blocks across 199 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: DTO mapping duplicated in three hooks with drift.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-124 — Business vs UI #124

  • Level: Intermediate+
  • Symptom: duplicate useEffect blocks across 12 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Fat useInvoice hook imports UI icons for side effects.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-125 — Business vs UI #125

  • Level: Advanced
  • Symptom: duplicate useEffect blocks across 25 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Currency math in component without shared money.ts module.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-126 — Business vs UI #126

  • Level: Advanced+
  • Symptom: duplicate useEffect blocks across 38 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Business rules embedded in JSX ternary chains unreadable in review.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-127 — Business vs UI #127

  • Level: Beginner
  • Symptom: duplicate useEffect blocks across 51 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: No pure function tests; only brittle E2E for core calculations.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-128 — Business vs UI #128

  • Level: Beginner+
  • Symptom: duplicate useEffect blocks across 64 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Authorization checks only in UI hiding missing server enforcement.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-129 — Business vs UI #129

  • Level: Intermediate
  • Symptom: duplicate useEffect blocks across 77 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Hook returns ready-made <Card/> elements mixing view and rules.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-130 — Business vs UI #130

  • Level: Intermediate+
  • Symptom: duplicate useEffect blocks across 90 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: DTO mapping duplicated in three hooks with drift.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-131 — Business vs UI #131

  • Level: Advanced
  • Symptom: duplicate useEffect blocks across 103 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Fat useInvoice hook imports UI icons for side effects.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-132 — Business vs UI #132

  • Level: Advanced+
  • Symptom: duplicate useEffect blocks across 116 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Currency math in component without shared money.ts module.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-133 — Business vs UI #133

  • Level: Beginner
  • Symptom: duplicate useEffect blocks across 129 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Business rules embedded in JSX ternary chains unreadable in review.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-134 — Business vs UI #134

  • Level: Beginner+
  • Symptom: duplicate useEffect blocks across 142 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: No pure function tests; only brittle E2E for core calculations.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-135 — Business vs UI #135

  • Level: Intermediate
  • Symptom: duplicate useEffect blocks across 155 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Authorization checks only in UI hiding missing server enforcement.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-136 — Business vs UI #136

  • Level: Intermediate+
  • Symptom: duplicate useEffect blocks across 168 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Hook returns ready-made <Card/> elements mixing view and rules.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-137 — Business vs UI #137

  • Level: Advanced
  • Symptom: duplicate useEffect blocks across 181 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: DTO mapping duplicated in three hooks with drift.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-138 — Business vs UI #138

  • Level: Advanced+
  • Symptom: duplicate useEffect blocks across 194 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Fat useInvoice hook imports UI icons for side effects.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-139 — Business vs UI #139

  • Level: Beginner
  • Symptom: duplicate useEffect blocks across 7 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Currency math in component without shared money.ts module.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-140 — Business vs UI #140

  • Level: Beginner+
  • Symptom: duplicate useEffect blocks across 20 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Business rules embedded in JSX ternary chains unreadable in review.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-141 — Business vs UI #141

  • Level: Intermediate
  • Symptom: duplicate useEffect blocks across 33 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: No pure function tests; only brittle E2E for core calculations.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-142 — Business vs UI #142

  • Level: Intermediate+
  • Symptom: duplicate useEffect blocks across 46 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Authorization checks only in UI hiding missing server enforcement.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-143 — Business vs UI #143

  • Level: Advanced
  • Symptom: duplicate useEffect blocks across 59 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Hook returns ready-made <Card/> elements mixing view and rules.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-144 — Business vs UI #144

  • Level: Advanced+
  • Symptom: duplicate useEffect blocks across 72 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: DTO mapping duplicated in three hooks with drift.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-145 — Business vs UI #145

  • Level: Beginner
  • Symptom: duplicate useEffect blocks across 85 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Fat useInvoice hook imports UI icons for side effects.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-146 — Business vs UI #146

  • Level: Beginner+
  • Symptom: duplicate useEffect blocks across 98 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Currency math in component without shared money.ts module.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-147 — Business vs UI #147

  • Level: Intermediate
  • Symptom: duplicate useEffect blocks across 111 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Business rules embedded in JSX ternary chains unreadable in review.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-148 — Business vs UI #148

  • Level: Intermediate+
  • Symptom: duplicate useEffect blocks across 124 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: No pure function tests; only brittle E2E for core calculations.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-149 — Business vs UI #149

  • Level: Advanced
  • Symptom: duplicate useEffect blocks across 137 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Authorization checks only in UI hiding missing server enforcement.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-150 — Business vs UI #150

  • Level: Advanced+
  • Symptom: duplicate useEffect blocks across 150 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Hook returns ready-made <Card/> elements mixing view and rules.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-151 — Business vs UI #151

  • Level: Beginner
  • Symptom: duplicate useEffect blocks across 163 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: DTO mapping duplicated in three hooks with drift.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-152 — Business vs UI #152

  • Level: Beginner+
  • Symptom: duplicate useEffect blocks across 176 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Fat useInvoice hook imports UI icons for side effects.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-153 — Business vs UI #153

  • Level: Intermediate
  • Symptom: duplicate useEffect blocks across 189 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Currency math in component without shared money.ts module.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-154 — Business vs UI #154

  • Level: Intermediate+
  • Symptom: duplicate useEffect blocks across 2 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Business rules embedded in JSX ternary chains unreadable in review.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-155 — Business vs UI #155

  • Level: Advanced
  • Symptom: duplicate useEffect blocks across 15 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: No pure function tests; only brittle E2E for core calculations.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-156 — Business vs UI #156

  • Level: Advanced+
  • Symptom: duplicate useEffect blocks across 28 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Authorization checks only in UI hiding missing server enforcement.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-157 — Business vs UI #157

  • Level: Beginner
  • Symptom: duplicate useEffect blocks across 41 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Hook returns ready-made <Card/> elements mixing view and rules.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-158 — Business vs UI #158

  • Level: Beginner+
  • Symptom: duplicate useEffect blocks across 54 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: DTO mapping duplicated in three hooks with drift.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-159 — Business vs UI #159

  • Level: Intermediate
  • Symptom: duplicate useEffect blocks across 67 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Fat useInvoice hook imports UI icons for side effects.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-160 — Business vs UI #160

  • Level: Intermediate+
  • Symptom: duplicate useEffect blocks across 80 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Currency math in component without shared money.ts module.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-161 — Business vs UI #161

  • Level: Advanced
  • Symptom: duplicate useEffect blocks across 93 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Business rules embedded in JSX ternary chains unreadable in review.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-162 — Business vs UI #162

  • Level: Advanced+
  • Symptom: duplicate useEffect blocks across 106 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: No pure function tests; only brittle E2E for core calculations.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-163 — Business vs UI #163

  • Level: Beginner
  • Symptom: duplicate useEffect blocks across 119 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Authorization checks only in UI hiding missing server enforcement.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-164 — Business vs UI #164

  • Level: Beginner+
  • Symptom: duplicate useEffect blocks across 132 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Hook returns ready-made <Card/> elements mixing view and rules.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-165 — Business vs UI #165

  • Level: Intermediate
  • Symptom: duplicate useEffect blocks across 145 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: DTO mapping duplicated in three hooks with drift.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-166 — Business vs UI #166

  • Level: Intermediate+
  • Symptom: duplicate useEffect blocks across 158 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Fat useInvoice hook imports UI icons for side effects.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-167 — Business vs UI #167

  • Level: Advanced
  • Symptom: duplicate useEffect blocks across 171 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Currency math in component without shared money.ts module.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

CH2-168 — Business vs UI #168

  • Level: Advanced+
  • Symptom: duplicate useEffect blocks across 184 screens or flaky tests after hook refactor.
  • Maintainability smell: hook name does not match behavior; grep fails.
  • Root cause class: Business rules embedded in JSX ternary chains unreadable in review.
  • Primary remediation: Extract canEditInvoice(user, invoice) pure helpers with unit tests.
  • Verify: RTL hook test + one story + bundle diff if heavy.
  • Interview one-liner: Hooks orchestrate; pure functions decide—UI renders outcomes.

<< 2.9 Overview