From 185fbceaa94c1379b6646e752ecfca768606a801 Mon Sep 17 00:00:00 2001 From: "s.zotov" Date: Sun, 12 Apr 2026 20:46:40 +0000 Subject: [PATCH] Add "Plan" --- Plan.md | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 Plan.md diff --git a/Plan.md b/Plan.md new file mode 100644 index 0000000..f945a36 --- /dev/null +++ b/Plan.md @@ -0,0 +1,101 @@ +# План рассылок + +## Yonote интеграция + +План рассылок загружается из базы данных Yonote (аналог Notion, российский). + +### Настройка + +В settings.json → `yonoteConfig`: + +```json +{ + "databaseId": "abc123", // ID базы в Yonote + "statusProperty": "Статус", // название колонки статуса + "dateProperty": "Дата", // дата отправки + "subjectProperty": "Тема", // тема письма + "preheaderProperty": "Прехедер", + "idProperty": "ID товаров", // IDs для блоков товаров + "extraProperties": ["Проект", "Теги", "Тип"] // доп. колонки +} +``` + +Токен Yonote — в `config.json` → `yonote_token`. + +### Загрузка данных + +`fetchPlanRows()`: +1. GET `/api/yonote/database/:id/rows` — пагинация по 100, макс 500 строк +2. Сортировка по `updatedAt` DESC +3. Фильтр по дате: -7 дней ... +60 дней +4. Извлечение полей из Yonote properties → плоская структура + +### Polling + +`startPlanPolling()` — каждые 3 минуты загружает обновления: +- Сравнивает fingerprints (JSON hash каждой строки) +- При изменениях → toast уведомление + browser Notification +- Кэширует в localStorage (`va-plan-cache`) + +## Календарь + +Мини-календарь в сайдбаре и на странице плана: + +- Точки под датами обозначают запланированные рассылки +- Клик на дату → показывает письма этого дня +- Навигация по месяцам (← →) +- Текущий день подсвечен + +## Группировка на странице плана + +Письма группируются по периодам: +- Просрочено (красный) +- Сегодня +- Завтра +- На этой неделе +- На следующей неделе +- Позже + +## Карточка сборки (Assembly Card) + +Когда письмо привязано к строке из Yonote, в сайдбаре показывается карточка: + +``` +┌─────────────────────┐ +│ ПЕРЕДАНО В СБОРКУ │ ← статус (цветной бейдж) +│ 📮 Тема письма 🧥 │ ← тема из Yonote +│ Подзаголовок │ ← preheader +│ [Тег1] [Тег2] │ ← теги/тип +│ ⎕ Figma │ ← ссылки из extra +│ │ +│ [Mindbox] [Отправлено]│ ← кнопки действий +└─────────────────────┘ +``` + +### Auto-matching + +При открытии письма `assemblyInfo` автоматически матчится со строкой в плане: +- По `rowId` (если сохранён в письме) +- Или по совпадению title + date + +### Статусы + +`setPlanRowStatus(row, newStatus)` — обновляет статус в Yonote. + +Кнопка "Отправлено" → статус "Отправлено" + останавливает трекинг времени. + +## Начало сборки + +`startAssemble(row)`: +1. Создаёт новое письмо с заполненным title, date, preheader из Yonote +2. Или открывает существующее (если уже привязано к rowId) +3. Автозаполняет ID pool из свойства "ID товаров" +4. Устанавливает assemblyInfo + +## Трекинг времени + +- `statsStart(letterId, ...)` — запускает 1-секундный интервал +- Считает активные секунды (паузится когда вкладка скрыта — `document.hidden`) +- `statsMarkHtmlCopied()` — отмечает что HTML скопирован +- `statsStop(finalStatus)` — сохраняет если >= 1 минуты +- Данные: `{letterId, letterName, userId, userName, project, tag, startedAt, finishedAt, activeSeconds, htmlCopied}`