docs: детализация дизайна Фазы 1C (React SPA)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -233,3 +233,80 @@ check_runs(id uuid pk, domain_id uuid fk→domains, result jsonb /*сводка
|
||||
### Разбивка
|
||||
|
||||
Реализуется **одним планом** `phase1b-persistence-api` (по решению — без под-планов).
|
||||
|
||||
## Фаза 1C — детализация (React SPA)
|
||||
|
||||
Строится поверх готового REST API (Фаза 1B). Полный UI на весь API.
|
||||
|
||||
### Стек
|
||||
|
||||
- **Vite + React + TypeScript**, **react-router** (v6+), **TanStack Query v5** (server-state).
|
||||
- **Tailwind CSS + shadcn/ui** (компоненты копируются в проект, `components.json`, alias `@`).
|
||||
- Формы: **react-hook-form + zod**.
|
||||
- Тесты: **Vitest + React Testing Library**.
|
||||
- В dev — Vite `server.proxy` `/api` → `http://localhost:8080`. В prod — `vite build` → `dist/`
|
||||
вшивается в Go-бинарь (`embed.FS`) и отдаётся тем же сервером (same-origin, CORS не нужен).
|
||||
|
||||
### Эстетическое направление
|
||||
|
||||
**Refined technical console.** Тёмная тема по умолчанию, плотная точная сетка, инженерный тон.
|
||||
- Типографика: характерный UI-гротеск (НЕ Inter/Roboto/system) + **моноширинный** для DNS-записей,
|
||||
зон и дифов (например IBM Plex Mono / JetBrains Mono). Пары: display для заголовков, mono для данных.
|
||||
- Семантическое цветовое кодирование дифа: **add** (emerald), **update** (amber), **delete/prune**
|
||||
(rose), **in-sync** (muted/slate), **read-only NS/SOA** (dimmed). Единая палитра через CSS-переменные.
|
||||
- Атмосфера: тонкие текстуры/границы, аккуратные тени, без generic purple-on-white. Диф — центральный,
|
||||
самый выразительный экран.
|
||||
|
||||
### Структура (`web/`)
|
||||
|
||||
```
|
||||
web/
|
||||
vite.config.ts — alias @, proxy /api → :8080, build outDir dist
|
||||
components.json — shadcn
|
||||
src/
|
||||
main.tsx, App.tsx — QueryClientProvider + router
|
||||
lib/ — utils, константа DEFAULT_PROJECT_ID = seed …0002
|
||||
api/
|
||||
client.ts — типизированная fetch-обёртка (base /api/v1/projects/{pid})
|
||||
types.ts — зеркало Go DTO (Account, Template, Domain, Changeset, RecordView …)
|
||||
hooks/ — TanStack Query: useAccounts/useTemplates/useDomains/useCheck/useApply/useImport
|
||||
components/
|
||||
ui/ — shadcn-компоненты
|
||||
Layout.tsx, DiffView.tsx, RecordEditor.tsx
|
||||
pages/
|
||||
DomainsPage, DomainDiffPage, AccountsPage, TemplatesPage
|
||||
```
|
||||
|
||||
### Экраны
|
||||
|
||||
- **Domains** — список доменов, импорт зон по учётке (`POST /domains/import`), привязка шаблона
|
||||
(`PATCH /domains/{id}`), переход к дифу.
|
||||
- **DomainDiff** (`/domains/:id`) — `GET .../check` → **DiffView**: секции Updates / Prunes / ReadOnly
|
||||
+ счётчик in-sync. Кнопка **Apply**: чекбокс «применить удаления (prune)» — **по умолчанию выключен**,
|
||||
требует явного подтверждения (визуально акцентированное предупреждение). `POST .../apply`.
|
||||
- **Accounts** — CRUD учёток. Форма создания: поле API-ключа (secret, только на вход), **инструкция +
|
||||
ссылка**, где получить ключ в панели Selectel. Секрет никогда не показывается обратно.
|
||||
- **Templates** — CRUD шаблонов + **RecordEditor** (редактор набора записей `doc.records`: type/name/ttl/values,
|
||||
включая SRV для почтового автодискавера).
|
||||
|
||||
### Мультитенантность
|
||||
|
||||
Фаза 1C — без логина: `DEFAULT_PROJECT_ID` (seed `…0002`) зашит в клиенте. Логин и переключение
|
||||
проектов — Фаза 2 (тогда pid берётся из сессии).
|
||||
|
||||
### Подача в prod (Go)
|
||||
|
||||
- `internal/web/web.go` — `embed.FS` каталога `web/dist` + handler со **SPA-fallback** на `index.html`.
|
||||
- `cmd/server` монтирует статику на `/`, API остаётся на `/api/v1` (роутинг chi: API-роуты имеют приоритет,
|
||||
всё прочее → SPA).
|
||||
|
||||
### Тестирование 1C
|
||||
|
||||
- `api/client` — юниты на мок `fetch` (пути, сериализация, обработка ошибок).
|
||||
- `DiffView` — рендер секций Updates/Prunes/ReadOnly, цветовое кодирование.
|
||||
- Apply-guard — по умолчанию prune выключен; включается только явным действием.
|
||||
- Go `internal/web` — статика отдаётся, `/api/*` не перехватывается, SPA-fallback на неизвестный путь.
|
||||
|
||||
### Разбивка
|
||||
|
||||
Один план `phase1c-react-spa`.
|
||||
|
||||
Reference in New Issue
Block a user