# Блоки в Libro.az — архитектура

## 1. Хранение

Блоки хранятся в таблице `pages`, колонка `blocks` (JSON):

```json
[
  {
    "id": "a1b2c3d4-...",
    "type": "heading",
    "data": { "text": "Salam", "fontSize": 24, "align": "center" },
    "order": 0
  },
  {
    "id": "e5f6g7h8-...",
    "type": "button_link",
    "data": {
      "text": "WhatsApp", "url": "+994501234567", "action": "whatsapp",
      "icon": "💬", "bgColor": "#25D366", "titleColor": "#fff",
      "borderRadius": 12, "shadow": "md", "animation": "pulse"
    },
    "order": 1
  }
]
```

Каждый блок — объект `{ id, type, data, order }`. `id` генерируется через `crypto.randomUUID()`.

## 2. Сохранение и загрузка

- **API:** `PUT /profile/{uid}/pages/{pid}/blocks` — принимает `{ blocks, theme_settings }`
- **Валидация:** `UpdateBlocksRequest` проверяет структуру блоков
- **Контроллер:** `PageController@updateBlocks` — сохраняет в БД

## 3. Live Preview

При открытии модалки редактирования:
```js
function openEdit(block) {
    editBlockData = JSON.parse(JSON.stringify(block.data)); // глубокая копия
    modal = 'editBlock';
}
```

Изменения в `editBlockData` (через `bind:value` или `oninput`) сразу обновляют превью через `liveUpdate()`:
```js
function liveUpdate() {
    blocks = blocks.map(b => b.id === editBlockId
        ? { ...b, data: JSON.parse(JSON.stringify(editBlockData)) }
        : b);
}
```

При клике «Yadda saxla» вызывается `save()` → PUT на сервер.

## 4. Типы блоков (10 шт.)

| Тип | Превью | Dizayn | Особенности |
|-----|--------|--------|------------|
| `avatar` | 4 стиля | ❌ | Загрузка фото + фона |
| `heading` | Размер + позиция | ❌ | fontSize, align |
| `text` | B/I/U/S формат | ❌ | contenteditable + execCommand |
| `button_link` | ✅ | 🎨 | Иконки, 5 действий, цвета, тень, анимация |
| `social_links` | ✅ | 🎨 | 3 дизайна (полный/сетка/контур), SVG |
| `image` | ✅ | 🎨 | Загрузка, радиус, тень |
| `video` | ❌ | ❌ | YouTube/Vimeo embed |
| `faq` | ✅ | 🎨 | Несколько Q&A, иконки, цвета |
| `spacer` | ❌ | ❌ | Высота (px) |
| `divider` | ❌ | ❌ | Линия |

## 5. Вкладки редактирования

Каждый блок имеет 2-3 вкладки:

| Вкладка | Содержание |
|---------|-----------|
| 📝 **Kontent** | Поля данных блока |
| 🎨 **Dizayn** | Визуальные настройки (кнопки/соцсети/картинки/FAQ) |
| ⚙️ **Nazwa** | Общие: скрытие, фон, отступы, якорь, расписание |

## 6. Общие настройки (Nazwa)

Хранятся в `data._*`:

| Поле | Описание |
|------|----------|
| `_hidden` | Скрыть блок |
| `_bgColor` | Цвет фона блока |
| `_pt` / `_pb` | Отступы сверху/снизу (px) |
| `_label` | Имя блока |
| `_anchor` | Якорь для навигации |
| `_scheduleStart/End` | Расписание показа |
| `_daysOfWeek` | Дни недели (0=Вс, 1=Пн...) |

## 7. Dizayn по типам

### Кнопка (`button_link`)
```json
{
  "titleColor": "#fff", "bgColor": "#4f46e5",
  "borderRadius": 12, "shadow": "none|sm|md",
  "animation": "none|shine|pulse|tada"
}
```

### Соцсети (`social_links`)
```json
{
  "design": "1|2|3",
  "iconSize": 22, "borderRadius": 12, "shadow": "none|sm|md"
}
```
- **1** — полная ширина, брендовый фон
- **2** — сетка 4 колонки, белый фон
- **3** — сетка, контурная обводка

### Картинка (`image`)
```json
{ "borderRadius": 8, "shadow": "none|sm|md", "maxHeight": 400, "zoom": false }
```

### FAQ
```json
{
  "iconPos": "left|right", "iconType": "plus|cross|arrow",
  "textColor": "#111827", "bgColor": "", "borderRadius": 12
}
```

## 8. Добавление нового типа блока

3 шага в 3 файлах:

1. **`UpdateBlocksRequest.php`** — добавить тип в `in:...`
2. **`Editor.svelte`** — `palette`, `defaults`, превью, Kontent, Dizayn (опционально)
3. **`BlockRenderer.svelte`** — рендеринг для публичной страницы

## 9. Публичная страница

`BlockRenderer.svelte` рендерит блоки на `/{slug}`. Проверяет `_hidden`, расписание, дни недели. Применяет дизайн-настройки через инлайн-стили.

## 10. Тема страницы

Хранится в `pages.theme_settings` (JSON):
```json
{
  "bg_type": "color|gradient|image",
  "bg_color": "#f0f0f0",
  "bg_gradient": "#e0e0e0",
  "bg_image": "/photo/...",
  "text_color": "#111827",
  "font_family": "Arial"
}
```

Применяется и в редакторе (превью телефона), и на публичной странице.
