/** * state.js — Центральное состояние приложения. * * ПАТТЕРН (из decoupling-final-plan.md, Фаза 0): * action → мутация state → render(state) * * ПРАВИЛА: * 1. ВСЕ состояния приложения — только здесь, в объекте state. * 2. DOM — проекция state, никто не читает данные из DOM. * Если что-то нужно узнать — смотри в state, а не в element.innerHTML. * 3. Мутировал любое поле state → обязан вызвать render(state). * Никаких прямых манипуляций DOM в обход render(). * 4. В любой момент console.log(state) показывает ВСЁ состояние приложения. * * СТРУКТУРА (Фаза 0 — минимальная, будет расширяться в Фазах 1-4): * * state.files — бывший fileQueue, массив загруженных файлов. * Каждый элемент: { name, size, lastModified, file, doc_id, * uploaded, parsed, parseInfo, supp_id, supp_type, status } * * state.contractId — бывший contractId, ID контракта в БД. * Приходит с бэкенда после первого успешного upload. * null пока не загружен ни один файл. * * state.batchId — бывший batchId, уникальный ID сессии (UUID). * Используется для привязки всех файлов сессии при классификации. * Генерируется один раз при загрузке страницы. * * state.groups — бывший window._groupsData. * Массив групп после классификации. Каждая группа: * { contract_number, counterparty, documents[], unresolved? } * null если классификация ещё не запускалась. * * state._activeCompare — бывшие _activeCompareES и _activeCompareTimer. * Управляет ОДНИМ активным SSE-сравнением. * Правило: только одно сравнение одновременно — все кнопки блокируются. * { es: EventSource|null, timer: intervalId|null } * * state.ui — UI-состояние, не связанное с данными. * ui.steps: { upload, classify, groups, compare } * Каждый шаг: '○' (не начат) | '⏳' (в процессе) | '✓' (завершён) * В Фазе 4 будет renderStepper(state). */ var state = { // ── Файлы (бывший fileQueue) ────────────────────────────── files: [], // ── Контракт (бывший contractId) ────────────────────────── contractId: null, // ── Сессия (бывший batchId) ─────────────────────────────── // crypto.randomUUID() — браузерный API, поддержка 92%+ (Chrome 92+, FF 95+, Safari 15.4+) batchId: crypto.randomUUID(), // ── Группы (бывший window._groupsData) ──────────────────── groups: null, // ── Активное сравнение ──────────────────────────────────── _activeCompare: { es: null, // EventSource (SSE-соединение с /process-v2) timer: null // setInterval ID для индикатора времени }, // ── UI-состояние ────────────────────────────────────────── ui: { steps: { upload: '○', classify: '○', groups: '○', compare: '○' } } };