# Система тем оформления (Platform-wide Theming)

Платформа поддерживает **10 дизайн-тем**, переключаемых суперадминистратором. Тема применяется **глобально** ко всем сервисам: лендинг, веб-панели (рецепция, админ клуба, суперадмин) и мобильное приложение.

## Права доступа

| Действие | Суперадмин | Админ клуба | Остальные роли |
|----------|------------|-------------|----------------|
| Просмотр текущей темы | + | + (только чтение) | — |
| Смена темы платформы | + | x | x |
| Предпросмотр тем | + | x | x |

## 10 тем оформления

| ID | Название | Стиль | Тёмная | Шрифты | Primary |
|----|----------|-------|--------|--------|---------|
| `fitpulse-orange` | FitPulse Orange | Энергичный минимализм | — | Inter | `#FF6B00` |
| `midnight-gym` | Midnight Gym | Тёмная + неон | да | Space Grotesk + Inter | `#00E5FF` |
| `fresh-wellness` | Fresh Wellness | Мягкий экологичный | — | Nunito | `#2E7D32` |
| `power-red` | Power Red | Агрессивный спортивный | да | Oswald + Roboto | `#D32F2F` |
| `azure-professional` | Azure Professional | Корпоративный | — | Plus Jakarta Sans | `#1565C0` |
| `sunrise-gradient` | Sunrise Gradient | Яркие градиенты | — | Manrope | `#FF5722` |
| `nordic-minimal` | Nordic Minimal | Скандинавский минимализм | — | DM Sans | `#212121` |
| `vibrant-purple` | Vibrant Purple | Фиолетовый hi-tech | да | Outfit | `#7B1FA2` |
| `ocean-calm` | Ocean Calm | Бирюзовый + SPA | — | Poppins | `#00897B` |
| `royal-gold` | Royal Gold | Люксовый чёрно-золотой | да | Playfair Display + Lato | `#FFB300` |

## Архитектура тем (все сервисы)

```
Суперадмин-панель: /settings/themes -> PUT /v1/admin/theme -> Backend API (таблица themes)
                                                                    |
                                                        GET /v1/theme/current
                                                 ┌──────┬───┬──────┬──────┐
                                                 v      v   v      v      v
                                            Лендинг  Web  Club  Mobile  Platform
```

## Backend: NestJS модуль `themes/`

```typescript
// Prisma-модель
model PlatformTheme {
  id        String   @id @default("current")  // Всегда одна запись
  themeId   String   @map("theme_id")         // ID из каталога (e.g. "fitpulse-orange")
  updatedBy String?  @map("updated_by")       // UUID суперадмина
  updatedAt DateTime @updatedAt
}

// Эндпоинты
GET  /v1/theme/current           // Публичный — текущая тема (id + colors + fonts)
PUT  /v1/admin/theme             // @Roles('super_admin') — смена темы
GET  /v1/admin/themes            // @Roles('super_admin') — каталог всех 10 тем
```

## Frontend: применение тем

**Web (Next.js — все 4 приложения + лендинг):**
- `ThemeProvider` (React Context) -> `useTheme()` хук
- При старте: `GET /v1/theme/current` -> кэш в localStorage
- Применение: `document.documentElement.style.setProperty(key, value)` для CSS-переменных
- Tailwind v4: обновление `--color-*` токенов из `@theme inline`
- Google Fonts: динамическая загрузка `<link>` по URL из темы
- Атрибуты: `data-theme`, `data-dark` на `<html>`

**Mobile (React Native):**
- `useThemeQuery()` -> React Query (TanStack), staleTime 5 мин
- Zustand store `themeStore` хранит текущую тему
- Применение: `ThemeContext` -> все компоненты используют `useThemeColors()`
- Шрифты: `expo-font` для загрузки Google Fonts
- Dark mode: автоматически через `isDark` флаг темы

**Лендинг (Next.js):**
- SSR: начальная тема через `getServerSideProps` / `fetch` на бэкенд
- CSR: `ThemeProvider` как в остальных приложениях
- Шрифты: `next/font/google` с динамическим семейством

## CSS-переменные (13 токенов на тему)

```
--primary, --primary-foreground, --background, --card,
--error, --success, --warning, --muted, --border,
--sidebar-bg, --sidebar-text, --sidebar-active, --text
```

Плюс шрифты: `--font-heading`, `--font-body`

## Текущая реализация (что уже сделано)

- `apps/web-platform-admin/src/lib/themes.ts` — каталог 10 тем
- `apps/web-platform-admin/src/components/theme-provider.tsx` — ThemeProvider + useTheme
- `apps/web-platform-admin/src/app/(dashboard)/settings/themes/page.tsx` — UI переключения
- Ссылка «Темы оформления» в сайдбаре суперадмина
- E2E тесты (7 тестов в e2e/platform-ui.spec.ts)

## Чеклист кросс-сервисной интеграции

**Backend API (`apps/api/src/modules/themes/`):**
- [ ] Prisma-модель `PlatformTheme` (id, themeId, updatedBy, updatedAt)
- [ ] `GET /v1/theme/current` — публичный, Redis-кэш 5 мин
- [ ] `PUT /v1/admin/theme` — @Roles('super_admin'), audit log
- [ ] `GET /v1/admin/themes` — каталог 10 тем
- [ ] Webhook событие `theme.changed`
- [ ] Unit-тесты модуля themes

**Shared package (`packages/shared-types/`):**
- [ ] Вынести каталог тем -> `packages/shared-types/themes.ts`
- [ ] Импорт каталога во всех сервисах из shared-types

**Лендинг:**
- [ ] ThemeProvider — получение темы через `GET /v1/theme/current`
- [ ] SSR: начальная тема через fetch на бэкенд
- [ ] CSS-переменные + динамические шрифты (next/font/google)

**Web-Admin рецепция:**
- [ ] ThemeProvider — получение темы через API
- [ ] CSS-переменные + Tailwind v4 tokens

**Web-Club-Admin:**
- [ ] ThemeProvider — получение темы через API
- [ ] CSS-переменные + Tailwind v4 tokens

**Platform-Admin:**
- [ ] Переключить с localStorage на API (`PUT /v1/admin/theme`)
- [ ] При смене темы: invalidate Redis-кэш

**Mobile:**
- [ ] Zustand store `themeStore` с текущей темой
- [ ] React Query: `useThemeQuery()`, staleTime 5 мин
- [ ] `ThemeContext` -> `useThemeColors()` хук
- [ ] expo-font: динамическая загрузка шрифтов
- [ ] Dark mode: StatusBar, NavigationContainer theme по флагу `isDark`
