# Code Conventions

This document outlines the coding patterns and conventions used in this project.

## Component Organization

### Feature Folder Pattern

Components that represent a feature or screen should use a folder structure with a barrel export.

```
Feature/
├── index.tsx      # exports from Feature.tsx
├── Feature.tsx    # main component
├── SubComponent.tsx
└── utils.ts
```

**index.tsx:**

```tsx
export * from './Feature';
```

**Rationale:** Keeps imports clean (`import { Feature } from './Feature'`) while allowing the feature to grow into multiple files without changing import paths. Subcomponents that only serve this feature live in the same directory rather than being abstracted to a shared components folder.

### Types Alongside Components

Export component prop types from the same file as the component.

```tsx
export type FeatureProps = {
  value: string;
  onChange: (value: string) => void;
};

export const Feature = ({ value, onChange }: FeatureProps) => {
  // ...
};
```

**Rationale:** Keeps types discoverable and colocated with their usage. Consumers can import both the component and its types from the same path.

## State Management

### Manager Pattern for Hooks

Hooks that manage complex state should return a "manager" object. Components receive this manager as a prop.

```tsx
// Hook
export const useFeatureManager = () => {
  const [state, setState] = useState('');
  const [filter, setFilter] = useState('');

  const filteredItems = (() => {
    // derived state computation
  })();

  return {
    state,
    setState,
    filter,
    setFilter,
    filteredItems,
  };
};

export type FeatureManager = ReturnType<typeof useFeatureManager>;

// Parent component
const Parent = () => {
  const manager = useFeatureManager();
  return <Child manager={manager} />;
};

// Child component
const Child = ({ manager }: { manager: FeatureManager }) => {
  const { state, filteredItems } = manager;
  // ...
};
```

**Rationale:** Centralizes state logic in one place. Child components don't need to know about individual state setters - they just receive the manager. Makes refactoring easier since state shape changes only affect the hook.

### State Colocation in Hooks

All local state (search, filters, pagination, expanded states) should live in the feature's hook, not scattered across components.

```tsx
// Good
export const useFeatureManager = () => {
  const [search, setSearch] = useState('');
  const [currentPage, setCurrentPage] = useState(1);
  const [expandedId, setExpandedId] = useState<string | null>(null);
  // ...
};

// Avoid
const Component = () => {
  const [search, setSearch] = useState(''); // state in component
  // ...
};
```

**Rationale:** Single source of truth for feature state. Easier to understand, test, and modify. Prevents state synchronization bugs.

### Derived State in Hooks

Computed/derived values should be calculated in the hook, not in components.

```tsx
export const useFeatureManager = () => {
  const [items, setItems] = useState([]);
  const [filter, setFilter] = useState('');

  // Derived state computed in hook
  const filteredItems = (() => {
    return items.filter((item) => item.name.includes(filter));
  })();

  const itemCount = filteredItems.length;

  return { items, filter, setFilter, filteredItems, itemCount };
};
```

**Rationale:** Components stay focused on rendering. Business logic stays in one place. Derived values are computed once and shared across all consuming components.

## React Patterns

### Reach for useMemo / useCallback only when they do work

Default to writing the code plainly. Most derived values are cheap and re-computing them per render costs
less than the memo that guards them.

```tsx
// ✅ Fine — cheap, so just write it
const filteredItems = items.filter((item) => item.active);
const handleClick = () => doSomething();
```

But they are ordinary tools, not forbidden ones. Use them where they earn it:

- a value or callback in a **dependency array**, where an unstable identity re-runs an effect or
  re-subscribes a socket every render;
- a genuinely **expensive** computation over a large list;
- a prop passed to a **memoized** child.

```tsx
// ✅ Earns it — an unstable callback here would re-subscribe on every render
const onConnectionChange = useCallback((state) => setConnState(state), [setConnState]);
```

**This section used to say "NEVER — React 19's compiler handles memoization automatically", which was
wrong twice.** The React Compiler is a separate, opt-in build plugin and it is **not installed here**
(there is no `babel-plugin-react-compiler` in `package.json`); React 19 on its own memoizes nothing. And
the codebase never followed the rule — some 40 files use each hook. A convention that is both false and
universally ignored is worse than none, because it makes every other rule in this file look optional.

### Computation Functions Outside Components

Extract complex computations into functions declared below the component, not as IIFEs inside.

```tsx
export const Component = ({ data }: Props) => {
  const metrics = computeMetrics(data);
  const stats = computeStats(data, metrics.total);

  return <div>{/* ... */}</div>;
};

// Functions below component
function computeMetrics(data: Data[]): Metrics {
  // complex computation
}

function computeStats(data: Data[], total: number): Stats {
  // complex computation
}
```

**Rationale:** Keeps the component body focused on rendering logic. Functions are testable in isolation. Easier to read and understand the component's purpose.

### Fragment Shorthand

Use `<>` for fragments. Only import and use `Fragment` when a `key` prop is required.

```tsx
// Good - no key needed
return (
  <>
    <Header />
    <Content />
  </>
);

// Good - key required
import { Fragment } from 'react';

return items.map((item) => (
  <Fragment key={item.id}>
    <ItemHeader item={item} />
    <ItemContent item={item} />
  </Fragment>
));

// Avoid - unnecessary Fragment import
import { Fragment } from 'react';

return (
  <Fragment>
    <Header />
    <Content />
  </Fragment>
);
```

**Rationale:** `<>` is cleaner and more concise. `Fragment` is only needed for the `key` prop which `<>` doesn't support.

## Imports

### Single-Line Imports

Keep imports on a single line. If an import has too many items, split into multiple import statements.

```tsx
// Good
import { Button, Input, Select } from '@/components/ui';
import { Card, CardHeader, CardContent } from '@/components/ui/card';

// Good - split when too long
import { TableBody, TableCell, TableHead } from '@/components/ui/table';
import { TableHeader, TableRow } from '@/components/ui/table';

// Avoid - multiline imports
import { Button, Input, Select, Card } from '@/components/ui';
```

**Rationale:** Single-line imports are easier to scan and take less vertical space. Splitting by source module keeps related imports together.

## Utilities

### Use Existing Helpers

Prefer existing helper functions over inline implementations.

```tsx
// Good
import { formatCurrency } from 'helpers/formatters';

const display = formatCurrency(amount / 100, currency, 0);

// Avoid
const display = new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: currency,
  minimumFractionDigits: 0,
}).format(amount / 100);
```

**Rationale:** Consistent formatting across the app. Single place to modify behavior. Less code duplication and potential for bugs.
