# CLAUDE.md — BellSystems Control Panel v2
# Instructions for Claude Code

> Read this file at the start of every session.
> This is the v2 project — a clean rebuild. The old v1 code lives in `frontend/src/_archive/` for reference only.
> Also read `DESIGN.md` before writing any UI code.

---

## Project Structure

```
C:\development\bellsystems-cp-v2\
│   CLAUDE.md                    ← you are here
│   DESIGN.md                    ← design rules, component contracts, page layout spec
│   docker-compose.yml
│
├── backend/                     ← FastAPI backend — DO NOT MODIFY
│
└── frontend/
    ├── src/
    │   ├── _archive/            ← v1 reference code — READ ONLY, never import from here except auth
    │   ├── assets/
    │   │   ├── global-icons/    ← action SVGs (edit, delete, download, etc.)
    │   │   ├── side-menu-icons/ ← sidebar navigation SVGs
    │   │   ├── comms/           ← communication type SVGs
    │   │   ├── other-icons/     ← misc SVGs
    │   │   └── customer-status/ ← CRM status SVGs
    │   ├── components/
    │   │   ├── ui/              ← design system components (the ONLY place to source UI)
    │   │   ├── layout/          ← Sidebar, Header, MainLayout
    │   │   └── shared/
    │   ├── hooks/
    │   ├── lib/
    │   ├── modals/              ← all modal components live here, grouped by domain
    │   ├── pages/               ← one file per page, grouped by domain
    │   ├── providers/
    │   ├── router/
    │   │   └── index.jsx        ← all routes defined here
    │   ├── styles/
    │   │   ├── tokens.css       ← ALL design tokens (colors, fonts, spacing, shadows)
    │   │   ├── components.css   ← ALL component-level styles
    │   │   └── global.css       ← base resets, typography, scrollbar, .page-wrapper
    │   └── main.jsx             ← app entry point
    └── vite.config.js
```

---

## Project Overview

Bespoke SaaS Admin Console for BellSystems. Manages Devices, Customers (CRM),
Manufacturing, Firmware, MQTT, Melodies, Staff, and more.

- **Backend:** FastAPI at `backend/` — never modify
- **Archive:** `frontend/src/_archive/` — v1 reference, read-only
- **Active code:** `frontend/src/` (everything except `_archive/`)
- **Design rules:** `DESIGN.md` at project root — read before writing any UI
- **Style Guide:** live at `/dev/styleguide` — shows every component with every variant
- **API client:** `frontend/src/lib/api.js` wraps `_archive/api/client.js`

---

## Import Alias

`@/` maps to `frontend/src/`:

```js
import Button from '@/components/ui/Button'             ✅
import Select from '@/components/ui/Select'             ✅
import { useAuth } from '@/hooks/useAuth'               ✅
import MainLayout from '@/components/layout/MainLayout' ✅
```

Never use relative `../` paths except inside `providers/` and `hooks/` when referencing `_archive/`.

---

## The Golden Rules

- **Never modify `_archive/`** — it is read-only reference material
- **All new code goes in `frontend/src/`** — no exceptions
- **No `/v2/` prefix anywhere** — routes start from `/`, imports start from `@/`
- **Read `DESIGN.md` before writing any UI code**
- **Source every UI element from `@/components/ui/`** — no raw HTML elements for styled things
- **Use only CSS tokens** — never raw hex, rgb, or pixel values in component or page files
- **Use `.masonry-grid` for all content pages with multiple variable-height sections** — never `display: grid` with fixed columns for card layouts. See DESIGN.md §11.

---

## Available UI Components

Every component lives in `frontend/src/components/ui/`. These are the ONLY components to use.
Check the live Style Guide at `/dev/styleguide` to see all variants and states.

| Component       | Import path                          | Purpose                                      |
|-----------------|--------------------------------------|----------------------------------------------|
| `Button`        | `@/components/ui/Button`             | All interactive actions                       |
| `StatusBadge`   | `@/components/ui/StatusBadge`        | Coloured status pills                         |
| `FormField`     | `@/components/ui/FormField`          | Every text/email/password/textarea input      |
| `Select`        | `@/components/ui/Select`             | Custom dropdown (used inside FormField type="select") |
| `Modal`         | `@/components/ui/Modal`              | All overlay dialogs                           |
| `ConfirmDialog` | `@/components/ui/ConfirmDialog`      | Destructive / confirmation prompts            |
| `DataTable`     | `@/components/ui/DataTable`          | All tabular data with sorting/selection       |
| `Pagination`    | `@/components/ui/Pagination`         | Page controls beneath DataTable               |
| `Spinner`       | `@/components/ui/Spinner`            | Loading indicators                            |
| `PageHeader`    | `@/components/ui/PageHeader`         | Page title block — every page starts with this |
| `Card`          | `@/components/ui/Card`               | Contained content sections                   |
| `Tabs`          | `@/components/ui/Tabs`               | Tabbed navigation within a page              |
| `Toast`         | `@/components/ui/Toast`              | Transient notifications (via `useToast`)     |
| `SearchBar`     | `@/components/ui/SearchBar`          | Search inputs with debounce                  |
| `Breadcrumbs`   | `@/components/ui/Breadcrumbs`        | Navigation trail on detail pages             |
| `Icon`          | `@/components/ui/Icon`               | Inline SVG icons by name                     |

---

## Folder Structure — Pages & Modals

Folders mirror the sidebar section hierarchy exactly.

```
frontend/src/pages/
├── auth/                        ← unauthenticated routes (login)
├── dashboard/                   ← General section
├── bellcloud/                   ← Bell Cloud section
│   ├── devices/
│   │   └── notes/
│   ├── users/
│   ├── melodies/
│   │   └── archetypes/
│   └── mqtt/
├── crm/                         ← Headquarters section
│   ├── comms/
│   │   └── mail/
│   ├── customers/
│   │   └── tabs/
│   ├── orders/
│   ├── quotations/
│   └── products/
├── engineering/                 ← Engineering section
│   ├── manufacturing/
│   ├── firmware/
│   └── developer/
├── public/                      ← Public / unauthenticated pages
│   ├── cloudflash/
│   └── serial/
├── settings/                    ← Console Settings section
│   └── staff/
└── dev/                         ← Internal dev tools (StyleGuide)
```

```
frontend/src/modals/
├── bellcloud/
│   ├── devices/
│   ├── melodies/
│   └── users/
├── crm/
│   └── products/
├── engineering/
│   └── manufacturing/
└── shared/
```

---

## Page Layout — How Every Page Is Structured

Every authenticated page is rendered inside `MainLayout`, which provides:
- **Sidebar** — fixed left, `224px` wide (`--sidebar-width`)
- **Header** — fixed top, `56px` tall (`--header-height`)
- **Content area** — the remaining viewport space

Inside the content area, every page uses the `.page-wrapper` class (defined in `global.css`):

```css
.page-wrapper {
  flex: 1;
  display: flex;
  flex-direction: column;
  padding: var(--space-12);     /* 48px on all sides — desktop */
  gap: var(--space-6);          /* 24px between top-level sections */
  min-width: 0;
}

@media (max-width: 768px) {
  .page-wrapper {
    padding: var(--space-8);    /* 32px on mobile */
    gap: var(--space-4);
  }
}
```

**This is the consistency guarantee**: because every page uses `.page-wrapper`, the `<PageHeader>` title on every page starts at exactly the same position — 48px from the top and 48px from the left edge of the content area. Never override these paddings. Never add extra wrappers around `page-wrapper` that introduce additional offset.

### Content width modes

Pages fall into two modes — choose based on how much content the page has:

**Full-width** (default — lists, tables, dashboards):
```jsx
<div className="page-wrapper">
```

**Centered** (forms, settings, pages with very few items):
```jsx
<div className="page-wrapper page-wrapper--centered">
```
Centered mode caps each direct child at `--content-max-width-sm` (640px) by default and centers it horizontally. Override when needed:
```jsx
<div className="page-wrapper page-wrapper--centered"
     style={{ '--page-content-max-width': 'var(--content-max-width-md)' }}>
```
Available tokens: `--content-max-width-xs` (480px), `--content-max-width-sm` (640px), `--content-max-width-md` (800px), `--content-max-width-lg` (1024px).

---

## Rules for Every Page

### Before writing any code
1. Read `DESIGN.md` — confirm tokens and components to use
2. Check `frontend/src/components/ui/` — use existing components only
3. Check the Style Guide at `/dev/styleguide` for the correct variant/props
4. Check `frontend/src/_archive/` for the equivalent v1 page — copy API calls and data shape only, never styling

### Page template

```jsx
// frontend/src/pages/[domain]/PageName.jsx

import PageHeader from '@/components/ui/PageHeader'
import { useAuth } from '@/hooks/useAuth'
// Import ONLY from @/components/ui/ — never raw HTML elements for styled things

export default function PageName() {
  // 1. Auth
  const { user } = useAuth()

  // 2. State & data fetching

  // 3. Event handlers

  // 4. Render — always handle: loading, error, empty, data states
  return (
    <div className="page-wrapper">
      <PageHeader title="Page Title" subtitle="Optional description">
        {/* Action buttons — use <Button variant="primary"> etc. */}
      </PageHeader>

      {/* Page content — use Card, DataTable, Tabs, etc. */}
    </div>
  )
}
```

### Styling rules
- **Tailwind** for layout only: `flex`, `grid`, `items-center`, `min-w-0`, etc.
- **CSS token variables** for ALL colors, spacing, typography — `var(--token-name)`
- **No** `.module.css` or per-page scoped CSS files
- **No** `style={{ }}` inline styles except for genuinely dynamic values (e.g. calculated widths)
- **No** raw hex, rgb, or pixel values anywhere

### Toolbar buttons — matching SearchBar height

`.btn` has `line-height: 1` while `.searchbar-input` has `line-height: var(--line-height-base)` (1.5). This makes buttons shorter than the search bar by default. Whenever a `<Button>`, `<SegmentedControl>`, or `<IconButtonGroup>` sits in the same toolbar row as a `<SearchBar>`, all buttons must use `padding-top/bottom: var(--space-3)` and `line-height: var(--line-height-base)`.

**Already handled automatically (no extra props needed):**
- `SegmentedControl` — `.seg-ctrl__btn` in `components.css` enforces `--space-3` padding and `var(--line-height-base)` globally.
- `IconButtonGroup` — `.icon-btn-group__btn` in `components.css` enforces `--space-3` padding globally.

**Must be overridden manually — standalone `<Button>` in the same row as a `<SearchBar>`:**

```jsx
// Option A — inline style prop on the button:
<Button
  size="md"
  style={{ paddingTop: 'var(--space-3)', paddingBottom: 'var(--space-3)', lineHeight: 'var(--line-height-base)' }}
>
  Label
</Button>

// Option B (preferred when multiple buttons share a toolbar) — scoped CSS block:
<>
  <style>{`
    .my-toolbar .btn {
      padding-top: var(--space-3) !important;
      padding-bottom: var(--space-3) !important;
      line-height: var(--line-height-base) !important;
    }
  `}</style>
  <div className="my-toolbar" style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-2)' }}>
    <IconButtonGroup … />
    <Button variant="primary" size="md">Compose</Button>
  </div>
</>
```

### Date & time formatting
- **Greek/European date style everywhere** — DD/MM/YYYY, never US-style MM/DD/YYYY
- **All date/time formatting must use `@/lib/formatters`** — never use raw `toLocaleDateString()`, `Intl.DateTimeFormat`, `toLocaleString()`, or `toISOString().slice()` in pages or modals
- **For `datetime-local` input values** — use `toDatetimeLocal(iso)` and `nowLocal()` from formatters. Never use `new Date(x).toISOString().slice(0, 16)` — it converts to UTC and shifts the time (timezone bug)
- **Currency** — use `fmtEuro(n)` from formatters (Greek locale: `1.250,00 €`)

Available formatters (`import { ... } from '@/lib/formatters'`):

| Function            | Output example                     | Use for                              |
|---------------------|------------------------------------|--------------------------------------|
| `fmtDate`           | `05/03/2026`                       | Short numeric dates (tables, lists)  |
| `fmtDateMedium`     | `5 Mar 2026`                       | Medium dates (cards, details)        |
| `fmtDateLong`       | `5 March 2026`                     | Long dates (headings, summaries)     |
| `fmtDateFull`       | `Wednesday, 5 March 2026`          | Dashboard, full context              |
| `fmtDateTime`       | `5 March 2026, 2:30 pm`            | Date + 12h time                      |
| `fmtDateTimeMedium` | `5 Mar 2026, 14:30`                | Date + 24h time (compact)            |
| `fmtDateTimeFull`   | `Wed, 5 Mar 2026, 2:30 pm`         | Emails, comms                        |
| `fmtTime24`         | `14:30:05`                         | Time with seconds                    |
| `fmtRelative`       | `5 minutes ago`                    | Relative timestamps                  |
| `toDatetimeLocal`   | `2026-03-05T14:30`                 | `datetime-local` input values        |
| `nowLocal`          | `2026-03-05T14:30`                 | Current time for form defaults       |
| `toDateInput`       | `2026-03-05`                       | `date` input values                  |
| `fmtEuro`           | `1.250,00 €`                       | Euro currency                        |

### Data fetching
- Use `frontend/src/lib/api.js` (wraps `_archive/api/client.js`)
- Every data-fetching component must handle **loading**, **error**, and **empty** states

### Modals
- Never defined inside page files
- Live in `frontend/src/modals/[sidebar-section]/[domain]/ModalName.jsx` — mirror the pages folder structure
- Pass data via props, actions via callbacks

---

## Missing Components — Stop and Ask

If building a page requires a UI component that does not exist in
frontend/src/components/ui/, Claude Code must STOP and say:

"I need a [ComponentName] component which doesn't exist yet.
Please build it and add it to the StyleGuide before I continue."

Do NOT:
- Invent an inline one-off component inside a page file
- Use raw HTML elements styled with inline CSS as a substitute
- Proceed and leave a placeholder

The StyleGuide at frontend/src/pages/dev/StyleGuide.jsx is the source
of truth for what components exist and how they look. Every component
used in a page must have a visible example there first.

## Building a New Page — Checklist

- [ ] File in correct `frontend/src/pages/[domain]/` folder
- [ ] Root element is `<div className="page-wrapper">` — nothing else, nothing wrapping it
- [ ] First child inside `page-wrapper` is `<PageHeader title="...">`
- [ ] Only components from `frontend/src/components/ui/` used
- [ ] No raw hex colors or pixel spacing values anywhere
- [ ] Loading state implemented
- [ ] Error state implemented
- [ ] Empty state implemented
- [ ] Mobile responsive (375px minimum)
- [ ] Modals in `frontend/src/modals/`
- [ ] Route added to `frontend/src/router/index.jsx`

---

## API Client

```js
// frontend/src/lib/api.js
export { default } from '../_archive/api/client'
```

All pages import from `@/lib/api`, never directly from `_archive`.

---

## Auth

`frontend/src/hooks/useAuth.js` re-exports from the archive AuthContext.
`frontend/src/providers/AuthProvider.jsx` re-exports the AuthProvider.

These are the ONLY two files permitted to import from `_archive/auth/`.
All other files use `@/hooks/useAuth`.
