Files
brand_book/docs/SPRINTS.md
T
AR 15 M4 eda348deea docs: close Sprint 5/5.5, prepare Sprint 6
- fix: CeoBlock padding 40px 48px → 40px 0 (v1.2)
- fix: BlockMetaBar.saveFullVersion() used defaultVersion instead of meta.version, causing version rollback in DB on snapshot save
- docs: mark Sprint 5 and 5.5 as completed in SPRINTS.md
- docs: update LLM_CONTEXT v4.5 — all 8 blocks documented, Sprint 6 current
- chore: Sidebar version → Sprint 6 · v0.6.0
- chore: add .vercel to .gitignore

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 19:59:25 +05:00

481 lines
38 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# План спринтов — Брендбук О!Клиника
> Недельные спринты. Каждый спринт = 1 рабочая неделя.
> Базовая дата начала: уточняется при старте разработки.
---
## Обозначения
- **FE** — задача фронтенда (Next.js)
- **BE** — задача бэкенда (NestJS + Prisma)
- **DB** — изменения схемы базы данных
- **Design** — дизайн-решения, требующие согласования
---
## Sprint 1 — Инициализация проекта + страница «Логотип» ✅ ЗАВЕРШЁН
**Цель:** Рабочее окружение, monorepo, базовая архитектура, первая живая страница брендбука — «Логотип».
### Задачи — инфраструктура
- [x] FE: Инициализация Next.js 16 (App Router, Tailwind 4, TypeScript) в `apps/web`
- [x] BE: Инициализация NestJS 11 в `apps/api`
- [x] DB: PostgreSQL 16 + Prisma 7, схема User + ExperimentalComponent
- [x] Настройка Docker Compose (порт 5433 — 5432 занят на хосте)
- [x] Настройка monorepo (pnpm workspaces)
- [x] Создание `.env.example`
- [x] Git: создание веток `develop` и `sprint/1`, подключён remote git.pirogov.ai
- [x] FE: Layout с боковой навигацией (все разделы, статус «скоро»)
- [x] FE: Fira Sans подключён через next/font/google, CSS-токены бренда в globals.css
### Задачи — страница «Логотип»
- [x] Design: PNG логотипа извлечён из PDF программно (PyMuPDF + Pillow)
- [x] FE: Прозрачная версия логотипа (удалён белый фон через numpy)
- [x] FE: Страница `/foundation/logo`
- [x] FE: Иерархия версий (Основной / Общий) с реальным изображением из PDF
- [x] FE: Цветовые варианты: светлый / инвертированный (CSS filter) / на форме
- [x] FE: Охранная зона с визуализацией отступов
- [x] FE: Таблица минимальных размеров (до 46 р. и от 48 р.)
- [x] FE: 6 правил недопустимого использования
- [x] FE: Placeholder «Скачать вектор» (кнопка неактивна)
### Фактические результаты
- Брендбук запущен локально на `http://localhost:3001`
- Название клиники исправлено: «Клиника ухо, горло, нос им. проф. Е.Н.Оленевой»
- Инвертированный логотип корректно отображается (белый на тёмном фоне)
### Технические решения Sprint 1
- PostgreSQL запущен на порту **5433** (5432 занят на хосте)
- Логотип хранится как PNG с прозрачным фоном (`public/logo/logo-transparent.png`)
- Инверсия логотипа: CSS `filter: brightness(0) invert(1)` на прозрачном PNG
- Next.js запускается на порту **3001** (3000 занят на хосте)
---
## Sprint 2 — Цвета, типографика и оффлайн элементы (Brand Foundation) ✅ ЗАВЕРШЁН
**Цель:** Секция «Фундамент бренда» — цвета, оба шрифта, а также первый оффлайн-раздел.
### Задачи — цвета
- [x] Design: Зафиксировать HEX-эквиваленты всех цветов бренда (053M, 073M, 066M, 050M, 081M, 080M)
- [x] FE: Создать CSS-переменные / дизайн-токены для всей цветовой палитры
- [x] FE: Страница «Цвета» — палитра с кодами Oracal/Pantone, HEX, RGB, HSL, копирование в клик
- [x] FE: Проверка контрастности пар цветов (WCAG AA/AAA)
- [x] FE: Экспорт токенов в JSON (Figma-compatible)
### Задачи — типографика
- [x] FE: Страница «Типографика» — раздел DINPro (бренд/оффлайн) + раздел Fira Sans (веб)
- [x] FE: Шкала размеров для обоих шрифтов: h1h6, body, caption, label, overline
- [x] FE: Чёткое указание: где DINPro, где Fira Sans
- [x] FE: Живые примеры текста обоими шрифтами
### Задачи — оффлайн элементы (справочный раздел)
- [x] FE: Раздел «Оффлайн элементы» в навигации брендбука
- [x] FE: Страница «Форма сотрудников» — схема размещения логотипа, таблица размеров
- [x] FE: Страница «Бейджи» — размеры 70×30 мм, варианты (светлый/тёмный), состав текста
- [x] FE: Страница «Внутренняя навигация» — шаблоны табличек, материалы, цвета Oracal
- [x] FE: Страница «Брендирование транспорта» — макет трамвая, цветовая схема
- [x] FE: Страница «Печатные материалы» — листовки, визитки, Telegram-бот
### Фактические результаты
- Страница `/foundation/colors` — 7 цветов с HEX/RGB/HSL/CSS-var и копированием, WCAG-контраст 7 пар, экспорт JSON
- Страница `/foundation/typography` — DINPro (оффлайн) + Fira Sans (веб), таблица применения, полные шкалы, живой пример
- Страница `/offline/uniform` — реальные фото из PDF (беж + синий вариант), таблица размеров, правила
- Страница `/offline/badges` — реальные фото из PDF (лицевая + оборотная), состав текста, пример
- Страница `/offline/navigation` — макеты из PDF (Кабинет 04, карточка врача), фото дверей с номерами (13, 31), указатели по этажам
- Страница `/offline/transport` — макет трамвая из PDF (оба вида, реальный рендер), таблица зон, цвета Oracal
- Страница `/offline/print` — убрана из навигации (нет данных из брендбука)
- Sidebar: убраны «скоро» для Цветов, Типографики и всех страниц Оффлайн кроме Печати
- Версия обновлена до **Sprint 2 · v0.2.0**
- **Деплой на Vercel:** https://web-oclinica.vercel.app (production, бесплатно)
- **Тайтлы страниц:** единый формат «Раздел. Цифровой брендбук Клиники ухо, горло, нос им. проф. Е.Н.Оленевой»
### Технические решения Sprint 2
- Страница «Цвета» — `"use client"` для clipboard API и экспорта JSON
- WCAG relative luminance вычисляется на клиенте, без зависимостей
- DINPro отображается с фоллбэком Arial (лицензионный шрифт)
- Реальные фото и макеты из PDF: PyMuPDF (fitz) — извлечение растровых изображений и рендер векторных страниц
- Рендер PDF страниц: 2.5–3.0x масштаб → JPEG, кроп до нужной области через Pillow
### Ретроспектива Sprint 2 — LLM-контекст
- [x] Docs: Создан `docs/LLM_CONTEXT.md` — сводный файл дизайн-данных для LLM (v2.1)
- [x] TZ: Добавлено требование ФТ-03-LLM — LLM-блок на каждой странице брендбука
- [ ] FE: Добавить LLM-блоки на страницы Sprint 1–2 (логотип, цвета, типографика, оффлайн) — перенесено в Sprint 3
**Результат спринта:** Разделы «Цвета», «Типографика» и «Оффлайн элементы» полностью готовы с реальными материалами из брендбука.
---
## Sprint 3 — Базовые компоненты: кнопки и поля ввода ✅ ЗАВЕРШЁН
**Цель:** Все варианты кнопок и форм-контролов в брендбуке. LLM-блоки на страницах.
### Задачи — LLM-контекст
- [x] FE: Добавить LLM-блок на страницу «Логотип» (`/foundation/logo`) — v1.0
- [x] FE: Добавить LLM-блок на страницу «Цвета» (`/foundation/colors`) — v2.1
- [x] FE: Добавить LLM-блок на страницу «Типографика» (`/foundation/typography`) — v2.0
- [x] FE: Создать переиспользуемый компонент `components/llm/LlmBlock.tsx` (LlmBlock, LlmSection, LlmTable, LlmRules)
- [x] Docs: Обновить `docs/LLM_CONTEXT.md` по итогам спринта — версия 3.0
### Задачи — компоненты
- [x] FE: Компонент Button (`components/ui/Button.tsx`) — варианты primary/outline/teal/pill, размеры sm/md/lg, loading
- [x] FE: Компонент Input (`.bb-input`) — text, password, focus/error/disabled, height 50px как на сайте
- [x] FE: Компонент Textarea (`.bb-textarea`) — resize:vertical, min-height 100px
- [x] FE: Компонент Select (`.bb-select`) — height 50px, кастомная стрелка SVG
- [x] FE: Компонент Checkbox (`.bb-checkbox`) и Radio (`.bb-radio`)
- [x] FE: Компонент Toggle/Switch (`components/ui/Toggle.tsx`) — React "use client", defaultChecked/disabled/label
- [x] FE: Страница `/components/buttons` — 4 варианта по реальному сайту, размеры, состояния, «Где применяется», LLM-блок v2.0
- [x] FE: Страница `/components/forms` — все 6 контролов, контекст на сайте с макетом, LLM-блок v2.0
- [x] FE: Копирование HTML/CSS кода в один клик (`components/ui/CodeCopy.tsx`)
### Фактические результаты
- **4 варианта кнопок** — скопированы с реального сайта perm.oclinica.ru: primary(#FFA39C), outline(#BF9975), teal(#60959c), pill(#e9e4d4)
- **6 форм-контролов** — input/textarea/select/checkbox/radio/toggle с полной документацией состояний
- **Input/Select** — height 50px, border 1px solid #ccc, border-radius 4px (entityform CSS с реального сайта)
- **Макет формы** на фоне #b8e6ed как «Узнайте стоимость операции» на oclinica.ru/lor
- **LLM-блоки** добавлены на логотип, цвета, типографику, кнопки, форм-контролы
- **Компоненты:** Button.tsx, Toggle.tsx, CodeCopy.tsx в `components/ui/`
- **Sidebar:** Sprint 3 · v0.3.0, кнопки/формы убраны из «скоро»
- **Деплой:** https://web-oclinica.vercel.app (production)
**Результат спринта:** Раздел «Базовые компоненты» полностью готов. Стили соответствуют реальному сайту.
---
## Sprint 4 — Карточки (Cards) ✅ ЗАВЕРШЁН
**Цель:** Все типы карточек, используемых на сайте.
### Задачи
- [x] Docs: Обновить `docs/LLM_CONTEXT.md` → версия 4.0
- [x] FE: Добавить LLM-блок на страницу «Карточки» — v1.0
- [x] FE: Карточка врача (DoctorCard) — фото 110×160px, имя, специализация, стаж, кнопка outline
- [x] FE: Карточка услуги / заболевания (ServiceCard) — иконка + заголовок + описание
- [x] FE: Карточка новости — превью, дата, заголовок, анонс, hover #eef4d1 (CSS сайта)
- [x] FE: Карточка отзыва — рейтинг SVG-звёзды, 4-строчный clamp, фон #eef4d1
- [x] FE: Карточка цены — услуга + стоимость + highlighted-вариант
- [x] FE: Бейджи (6 вариантов), теги (default/active), алерты (info/success/warning/error)
- [x] FE: Страница `/components/cards` с документацией и LLM-блоком
### Фактические результаты
- **5 типов карточек:** DoctorCard, NewsCard, ReviewCard, PriceCard, ServiceCard
- **NewsCard hover** — bg `#eef4d1` + box-shadow `0 0 16px #9e9e9a` (1:1 с реальным CSS сайта)
- **ReviewCard** — фон `#eef4d1` из CSS сайта, WebkitLineClamp: 4
- **Бейджи** — 6 вариантов (primary/success/warning/danger/neutral/outline-blue)
- **Алерты** — info (#dff0fa), success (#d1fae5), warning (#fef3c7), error (#fee2e2)
- **Исправлены цвета Oracal** — точные RGB из каталога для всех 6 плёнок
- **Деплой:** https://web-oclinica.vercel.app (production)
**Результат спринта:** Все карточки задокументированы. Цвета Oracal исправлены по каталогу.
---
## Принцип документирования (Sprint 5+)
> **Правило:** Брендбук документирует только то, что реально существует на сайте `perm.oclinica.ru`.
> Никаких придуманных вариантов. Процесс: сначала изучаем реальный сайт → потом воспроизводим в брендбуке.
---
## Sprint 5 — Все блоки текущего сайта ✅ ЗАВЕРШЁН
**Цель:** Задокументировать ВСЕ блоки страницы perm.oclinica.ru/lor за один спринт.
Источник: скриншот страницы + CSS сайта. Только фронтенд, mock-данные.
### Блоки с реального сайта (сверху вниз, по скриншоту /lor)
**Шапка и навигация**`/blocks/navigation`
- [x] FE: Топ-бар: адрес «К. Цеткин, 9», телефон /342/ 255-53-84 (25px), кнопка «Заказать звонок» (pill)
- [x] FE: Логотип «КЛИНИКА УХО ГОРЛО НОС ИМ. ПРОФ. Е.Н. ОЛЕНЕВОЙ»
- [x] FE: Главное меню 18px: Клиника / ЛОР врачи / Заболевания / Вопрос-ответ / ЛОР операции / Сурдология / Цены / Контакты
- [x] FE: v1.1 — адрес, ссылки, размеры шрифтов, цвета синхронизированы с реальным сайтом
**Hero-баннер**`/blocks/hero`
- [x] FE: Баннер — единый фон #f9f4e7 (светло-кремовый, замерян пикселем), галочки #bf9975
- [x] FE: Правая часть: реальное фото врача с пациентом (спарсено с сайта → public/hero-doctor.jpg)
- [x] LLM: v1.1 — исправлен цвет фона, кнопка outline, галочки бежевые
- [x] FE: v1.2 — H1: 36px/#cb9768, заголовок баннера: 22px/#333, CTA: pill-стиль, дефис в H1
- [x] FE: v1.3 — счётчик «Поделиться ✉ 98572», убраны кнопки VK/FB/TW
**Вводный текст (CEO-блок)**`/blocks/ceo`
- [x] FE: Текст специализации клиники, Q&A вопросы-стимулы
- [x] FE: v1.1 — адрес «ул. Клары Цеткин, 9» (было «ул. Цитная, 9»), цвет ссылок #52b4bd
**Блок врачей**`/blocks/doctors`
- [x] FE: Заголовок text-3xl + 3 стат-блока (без фона, #60959c + border-bottom) + сетка 6 карточек
- [x] FE: Реальные фото 6 врачей (спарсены с сайта → public/doctors/)
- [x] FE: Реальные имена и специализации врачей из слайдера /lor
- [x] LLM: v1.1
- [x] FE: v1.2 — H2: 36px/#000000, line-height 38px
**Блок отзывов**`/blocks/reviews`
- [x] FE: Карусель: кавычка, текст отзыва, «Читать полностью», стрелки
- [x] FE: v1.1 — H2: 36px/#000000, line-height 38px
**Формы записи**`/blocks/contact-forms`
- [x] FE: Форма «Будьте здоровы!» (фон #d4f6f8, поля: имя/телефон/врач, кнопка «Запишите меня!»)
- [x] FE: Форма «Узнайте стоимость операции» (фон #d4f6f8, поля: имя/телефон, кнопка «Перезвоните мне»)
- [x] FE: v1.1 — H2: 36px/#000000, фон обеих форм: #d4f6f8 (ранее #b8e6ed и #fff)
- [x] FE: v1.2 — кнопка bb-btn-lg 18px bold (было bb-btn-md 14px), border-radius 4px (было 7px)
**Блок новостей**`/blocks/news`
- [x] FE: 4 карточки новостей в ряд (дата + заголовок), кнопка «Все новости» (mock)
- [x] FE: v1.1 — H2: 36px/#000000, фон секции: #f2fee6 (ранее белый)
**Footer (подвал)**`/blocks/contact`
- [x] FE: 4 колонки ссылок по реальному сайту (О клинике 13, Заболевания 5, Вопрос-ответ 6, Операции 11)
- [x] FE: Два адреса: Клары Цеткин, 9 + Газеты Звезда, 31А
- [x] FE: Два графика работы по филиалам
- [x] FE: Соцсети: VK, YT, TG, OK, Дзен
- [x] FE: v1.1 — полное обновление контента по реальному сайту
### Общее к Sprint 5
- [x] FE: LLM-блоки на hero v1.1 и doctors v1.1
- [x] Docs: Типографика сайта — реальные стили на 23.03.2026 (новый раздел в /foundation/typography)
- [x] Docs: Цвета — исправлен #f9f4e7 (Hero), #b8e6ed (форма), #e9e4d4 (пилюли)
- [x] FE: Убрать `soon` у Hero и Doctors в Sidebar
- [x] FE: CEO-блок v1.1
- [x] FE: Блоки отзывов, форм записи, новостей — компоненты + страницы документации
- [x] FE: Сравнение ВСЕХ блоков с реальным сайтом и синхронизация (24.03.2026)
- [x] Docs: Обновление `docs/LLM_CONTEXT.md` v4.3
- [x] FE: Исправлены CSS-стили ВСЕХ блоков по реальному сайту (24.03.2026):
- H1 страницы: 36px, #cb9768 (ранее ~20px, #53514e)
- H2 секций: 36px, #000000 (ранее ~20-30px, #111827)
- Hero заголовок: 22px, #333 (ранее 16px, #111827)
- CTA-кнопка Hero: pill (ранее outline)
- Фон форм: #d4f6f8 (ранее #b8e6ed и #fff)
- Фон новостей: #f2fee6 (ранее #fff)
- Типографика сайта: обновлена таблица стилей
- [x] FE: Добавлена «История версий» с changelog на каждую страницу блока
- [x] BE: Метаданные блоков (version, isInPreview, changelog) перенесены в PostgreSQL
- Prisma schema: добавлено поле `changelog Json @default("[]")`
- Seed обновлён: 8 блоков с актуальными версиями и историей изменений
- API: PATCH /blocks/by-path принимает changelog
- CORS: открыт для любого localhost порта
- BlockMetaBar: загружает version + changelog из API, fallback на defaultVersion/defaultChangelog
- Компонент BlockChangelog: отображает историю версий из API или из кода
- Надпись «API офлайн» заменена на серую точку
- [x] FE: Footer (блок `/blocks/contact` готов)
- [x] FE: CEO-блок v1.2 — убраны горизонтальные отступы (padding 40px 48px → 40px 0)
- [x] FE: Исправлен баг BlockMetaBar.saveFullVersion() — использовал defaultVersion вместо meta.version, что откатывало версию в БД при сохранении снапшота
**Результат спринта:** Hero v1.3, Doctors v1.2, CEO v1.2, Reviews v1.1, ContactForms v1.2, News v1.1, Navigation v1.3, Contact v1.1 — все блоки /lor задокументированы. Метаданные блоков хранятся в БД. Система снапшотов работает корректно.
---
## Sprint 5.5 — «Просмотр текущей страницы» (внеочередной) ✅ ЗАВЕРШЁН
**Цель:** Добавить интерактивный раздел брендбука, который собирает главную страницу из уже задокументированных блоков.
Показывает живой превью того, как выглядит сайт на основе данных брендбука.
### Концепция UX
**Маршрут:** `/pages/preview`
**Сайдбар:** добавить в раздел «Страницы» с пометкой (если ещё нет блоков — показывает заглушку с кнопкой)
**Два состояния страницы:**
1. **Пустое состояние** (первый вход, или если превью не создавалось):
- Заголовок «Просмотр текущей страницы»
- Описание: «Здесь будет собрана главная страница из задокументированных блоков»
- Активная кнопка «Создать» (`.bb-btn bb-btn-primary`)
- После нажатия → переход в «созданное» состояние
2. **Созданное состояние** (после нажатия «Создать»):
- Превью главной страницы из всех доступных блоков в порядке сверху вниз, как на perm.oclinica.ru/lor
- Кнопка «Пересобрать» в шапке (сбрасывает до исходного состояния)
- Сборка только из блоков, у которых есть готовый компонент (не mock-заглушки)
- Блоки рендерятся как реальные React-компоненты внутри `<section>`
**Порядок блоков в превью** (по perm.oclinica.ru/lor, только готовые):
1. Hero-баннер (`/blocks/hero` → компонент HeroBlock)
2. Блок врачей (`/blocks/doctors` → компонент DoctorsBlock)
3. Блок отзывов (`/blocks/reviews` → когда будет готов)
4. Форма записи (`/blocks/contact-forms` → когда будет готова)
5. Блок новостей (`/blocks/news` → когда будет готов)
6. Footer (`/blocks/contact` → когда будет готов)
**Техническая реализация (FE only, без бэкенда):**
- Состояние сохраняется в `localStorage` (`preview-created: true/false`)
- Каждый задокументированный блок выносится в переиспользуемый React-компонент
- Страница `/pages/preview` импортирует компоненты и рендерит их в нужном порядке
- Блоки, которых ещё нет → показывается placeholder с текстом «Блок в разработке»
### Задачи
- [x] FE: Страница `/pages/preview` — пустое состояние с кнопкой «Создать»
- [x] FE: Логика `localStorage` — сохранение/сброс состояния превью
- [x] FE: Рефактор `/blocks/hero/page.tsx` — вынести баннер в компонент `HeroBlock` (переиспользуемый)
- [x] FE: Рефактор `/blocks/doctors/page.tsx` — вынести в компонент `DoctorsBlock`
- [x] FE: Placeholder-компонент для блоков, которые ещё не готовы (серая рамка с названием блока)
- [x] FE: Сборка превью: рендер всех доступных компонентов в порядке реального сайта
- [x] FE: Sidebar — добавить «Просмотр страницы» в раздел «Страницы»
- [x] FE: Кнопка «Пересобрать» в созданном состоянии
- [x] FE: Toggle «В превью» через localStorage (fallback при API офлайн)
- [x] BE: BlockMetaBar + PreviewClient подключены к NestJS API `/blocks`
- [x] BE: Метаданные блоков (version, changelog, isInPreview) в PostgreSQL
- [x] Docs: Добавить `/pages/preview` v1.0 в LLM_CONTEXT.md
- [x] FE: Кнопка «Сохранить версию» — фиксация version + changelog из кода в БД
- [x] BE: Модель BlockSnapshot (html, css, version, changelog) + миграция
- [x] BE: API эндпоинты: POST/GET `/blocks/snapshots`, GET `/blocks/snapshots/:id`
- [x] FE: BlockMetaBar — dropdown переключения между сохранёнными версиями
- [x] FE: HTML-снимок блока при сохранении версии (innerHTML + CSS capture)
- [x] FE: Все 8 страниц блоков — split на Server/Client Components для snapshot support
- [x] FE: Навигация v1.3 — подменю с hover-dropdown, navData.ts, обновлённые стили блоков
### Зависимости
- Зависит от: Sprint 5 (блоки hero и doctors уже готовы — ✅)
- По мере добавления новых блоков в Sprint 5 — они автоматически подключаются к превью
### Ожидаемый результат
- Раздел «Просмотр текущей страницы» работает в браузере
- Кнопка «Создать» собирает главную страницу из задокументированных блоков
- Отсутствующие блоки отображаются как плейсхолдеры
- Кнопка «Пересобрать» позволяет сбросить и пересоздать
---
## Sprint 6 — Страницы (сборки из блоков)
**Цель:** Задокументировать полные страницы как сборки уже готовых блоков.
Данные пока mock — реальные появятся в Sprint 8.
### Задачи
- [ ] Research: Страница заболевания perm.oclinica.ru/lor/rinit — порядок блоков, что отличается от главной
- [ ] Research: Страница врачей /lor/doctors — фильтры, сетка, пагинация
- [ ] FE: `/pages/home` — сборка блоков из Sprint 5 в порядке реальной страницы /lor
- [ ] FE: `/pages/disease` — страница заболевания по /lor/rinit
- [ ] FE: `/pages/doctors` — список врачей с фильтрами (mock) и пагинацией
- [ ] FE: `/pages/prices` — страница цен (Research: реальная структура таблицы)
- [ ] FE: `/pages/contacts` — контакты + карта
- [ ] FE: `/pages/doctor` — профиль врача
- [ ] FE: Убрать `soon` у страниц в Sidebar
- [ ] Docs: Обновить `docs/LLM_CONTEXT.md`
**Результат спринта:** Все страницы брендбука задокументированы (с mock-данными).
---
## Sprint 7 — Авторизация (viewer / editor)
**Цель:** Реализовать систему ролей из ТЗ: `viewer` видит брендбук, `editor` видит кнопки дублирования.
Требует бэкенд (NestJS) и БД (PostgreSQL + Prisma).
### Задачи — бэкенд
- [ ] BE: Prisma-модель `User` (id, email, name, passwordHash, role: viewer/editor, createdAt)
- [ ] BE: Prisma миграция + seed (создать тестовых пользователей: 1 viewer, 1 editor)
- [ ] BE: NestJS модуль `auth` — JWT-авторизация, `/api/auth/login`, `/api/auth/me`
- [ ] BE: JWT-токен в httpOnly cookie (не localStorage) — ФТ-64
- [ ] BE: Guard для защиты эндпоинтов по роли
### Задачи — фронтенд
- [ ] FE: Страница `/login` — форма email + пароль + кнопка «Войти» — ФТ-61
- [ ] FE: Редирект неавторизованных на `/login` — ФТ-60
- [ ] FE: После входа — редирект обратно на запрошенную страницу — ФТ-62
- [ ] FE: В шапке брендбука: имя пользователя, роль, кнопка «Выйти» — ФТ-63
- [ ] FE: `editor` видит шапку с дополнительными действиями; `viewer` — только чтение
**Результат спринта:** Рабочая авторизация, два типа пользователей, защищённые маршруты.
---
## Sprint 8 — Реальные данные (интеграция с oclinica.ru)
**Цель:** Подключить реальные данные с сайта клиники — врачи, новости, услуги, цены, отзывы.
Данные проксируются через NestJS с кэшем 15 минут — ИНТ-01-04.
### Задачи — бэкенд
- [ ] BE: Research — проверить доступные эндпоинты oclinica.ru (JSON:API Drupal или /node?_format=json)
- [ ] BE: NestJS модуль `oclinica` — HTTP-клиент к oclinica.ru API
- [ ] BE: Кэш TTL 15 минут (in-memory или Redis) — ИНТ-03
- [ ] BE: Graceful degradation: если API недоступен — возврат mock-данных — ИНТ-04
- [ ] BE: Эндпоинты: `/api/doctors`, `/api/news`, `/api/services`, `/api/prices`, `/api/reviews`
### Задачи — фронтенд
- [ ] FE: Блок «Наши врачи» (`/blocks/doctors`) — реальные карточки врачей с фото
- [ ] FE: Блок «Новости» (`/blocks/news`) — реальные новости
- [ ] FE: Страницы (`/pages/*`) — замена mock-данных на реальные
**Результат спринта:** Брендбук показывает реальных врачей, новости, услуги с сайта клиники.
---
## Sprint 9 — Эксперименты: дублирование компонентов
**Цель:** Реализовать систему создания дублей — `editor` может дублировать любой компонент/блок,
редактировать атрибуты и отправить на согласование. ФТ-50 – ФТ-56.
### Задачи — бэкенд
- [ ] BE: Prisma-модель `ExperimentalComponent` (id, name, baseComponent, attributes JSON, status, authorId, createdAt, updatedAt)
- [ ] BE: Prisma миграция
- [ ] BE: NestJS модуль `components` — CRUD: `POST /api/components`, `GET /api/components`, `PATCH /api/components/:id`, `DELETE /api/components/:id`
- [ ] BE: Эндпоинт смены статуса: `PATCH /api/components/:id/status` (draft→review→approved)
- [ ] BE: Guard: мутирующие операции только для `editor` — ФТ-52, ФТ-55
### Задачи — фронтенд
- [ ] FE: Кнопка «Дублировать» на каждом компоненте/блоке (видна только `editor`) — ФТ-51
- [ ] FE: Форма редактирования атрибутов дубля — ФТ-52:
- Текстовые поля (заголовки, описания)
- Color picker — только из токенов бренда (`--brand-*`)
- Выбор размера из допустимых значений
- Real-time preview при изменении
- Кнопки: «Сохранить как черновик», «Отмена»
- [ ] FE: Раздел `/variants/blocks` — список всех дублей компонентов — ФТ-50, ФТ-56:
- `viewer`: только approved
- `editor`: все (draft, review, approved)
- [ ] FE: Карточка дубля: название, автор, дата, статус, базовый компонент, превью — ФТ-56
- [ ] FE: Управление статусом для `editor`: draft→review→approved, удаление draft — ФТ-54, ФТ-55
**Результат спринта:** Рабочая система создания и согласования дублей компонентов.
---
## Sprint 10 — Финальная полировка и деплой
**Цель:** Финальный релиз — smoke-тест, адаптивность, деплой бэкенда.
### Задачи
- [ ] BE+FE: Полный smoke-тест всего брендбука (все роли, все страницы)
- [ ] FE: LLM-блоки на всех страницах — проверка актуальности
- [ ] FE: Мобильная адаптация — финальная проверка (1440 / 768 / 375px)
- [ ] FE: Accessibility-аудит WCAG AA — особенно форма дублирования
- [ ] Деплой BE: выбрать хостинг для NestJS + PostgreSQL (Railway / Render / VPS клиники)
- [ ] Деплой: автоматический деплой через Gitea Actions → Vercel (push в `main`)
- [ ] Docs: Финальное обновление `docs/LLM_CONTEXT.md`, `DEPLOY.md`
### Текущий статус деплоя
- **Фронтенд:** https://web-oclinica.vercel.app (Vercel Hobby)
- **Команда деплоя:** `cd apps/web && vercel --prod --yes`
- **Бэкенд:** локально (Docker Compose), хостинг выбирается в Sprint 10
**Результат спринта:** Брендбук полностью готов, оба сервиса задеплоены, реальные данные, роли работают.
---
## Сводная таблица
| Спринт | Тема | Слой | Суть |
|--------|---------------------------------|---------------|--------------------------------------------------------|
| 1 | Инициализация + Логотип | FE | PDF брендбука, первая страница |
| 2 | Цвета, Типографика, Оффлайн | FE | PDF + Oracal каталог |
| 3 | Кнопки и форм-контролы | FE | CSS реального сайта |
| 4 | Карточки, бейджи, алерты | FE | CSS реального сайта |
| 5 | ВСЕ блоки сайта | FE | Все блоки /lor, mock-данные |
| 5.5 | Просмотр текущей страницы | FE | Кнопка «Создать», сборка из блоков, localStorage |
| 6 | Все страницы (сборки) | FE | Сборки из блоков, mock-данные |
| 7 | Авторизация (viewer / editor) | BE + FE | JWT, роли, login-страница, шапка с именем |
| 8 | Реальные данные | BE + FE | NestJS прокси → oclinica.ru, кэш 15 мин |
| 9 | Эксперименты (дубли) | BE + FE | Duplicate button, форма атрибутов, статусы, раздел |
| 10 | Финальная полировка | BE + FE | Smoke-тест, деплой бэкенда, адаптивность |
---
## Backlog (вне основных спринтов)
- Раздел «Логотип»: активация кнопки скачивания SVG (после получения вектора)
- Экспериментальная секция — если потребуется CRUD API (NestJS + Prisma)
- Тёмная тема — только если появится на реальном сайте
- Мультиязычность — только если появится на реальном сайте