diff --git a/mockup.html b/mockup.html index 3055481..dc3a732 100644 --- a/mockup.html +++ b/mockup.html @@ -2205,13 +2205,50 @@ body{font-family:var(--font-ui);background:var(--surf);color:var(--ink);line-hei
-
Кабинет

Шаблоны

-
Готовые документы — заполню под ваш случай. Составлять с нуля не нужно 💛
-
-
📝
Протокол разногласий
убрать невыгодные пункты
-
✉️
Претензия
оплата / неустойка
-
🛡️
Ответ на претензию
отбить требование
-
🚪
Расторжение
выйти без потерь
+
+
Кабинет

Шаблоны

+
+
Заполню под ваш случай автоматически. Данные из ваших договоров — уточню только что нужно 💛
+
+ + +
+ + +
Все шаблоны:
+
+
+
📬
Уведомление о непродлении
+
аренда · за 30 дней до окончания
+
+
+
✉️
Претензия об оплате
+
взыскать долг · ст. 395 ГК
+
+
+
⚠️
Претензия о качестве
+
товар / работы · ЗоЗПП / ст. 723 ГК
+
+
+
🛡️
Ответ на претензию
+
отбить требование · с аргументами
+
+
+
💰
Требование о возврате депозита
+
после окончания аренды
+
+
+
🚪
Соглашение о расторжении
+
по соглашению сторон · без суда
+
+
+
Акт приёмки-передачи
+
подряд / услуги · фиксируем факт
+
+
+
📑
Доверенность
+
в суд · на авто · для сделок
+
@@ -4281,6 +4318,260 @@ function _fmtDate(dateStr) { return p[2].replace(/^0/,'') + ' ' + m[parseInt(p[1])-1] + ' ' + p[0]; } +// ── ШАБЛОНЫ — контекст + генерация ────────────────────────────────────────── + +var _TEMPLATE_META = { + notice_no_renewal: { icon:'📬', name:'Уведомление о непродлении', triggers:['аренда','непродлени','уведомит'] }, + claim_payment: { icon:'✉️', name:'Претензия об оплате', triggers:['не платит','долг','оплат','задолженн'] }, + claim_quality: { icon:'⚠️', name:'Претензия о качестве', triggers:['качеств','брак','дефект','неисправ'] }, + deposit_return: { icon:'💰', name:'Требование о возврате депозита', triggers:['депозит','обеспечительн'] }, + termination_agreement: { icon:'🚪', name:'Соглашение о расторжении', triggers:['расторг','выйти'] }, +}; + +// Рендерит контекстные шаблоны при открытии вкладки +function renderContextTemplates() { + var el = document.getElementById('shab-context'); + if (!el) return; + + var suggested = []; + + // 1. Из активных дедлайнов + (_DEADLINES || []).forEach(function(d) { + if (d.done) return; + var t = (d.title || '').toLowerCase(); + Object.keys(_TEMPLATE_META).forEach(function(key) { + var meta = _TEMPLATE_META[key]; + if (meta.triggers.some(function(tr){ return t.includes(tr); })) { + var st = _dlStatus(d.date); + if (st.days <= 14) { // только срочные + suggested.push({ key: key, source: 'deadline', dl: d, urgency: st }); + } + } + }); + }); + + // 2. Из истории чата + var history = _chatHistory.slice(-20); + var histText = history.map(function(m){ return m.content || ''; }).join(' ').toLowerCase(); + Object.keys(_TEMPLATE_META).forEach(function(key) { + var meta = _TEMPLATE_META[key]; + var alreadyIn = suggested.some(function(s){ return s.key === key; }); + if (!alreadyIn && meta.triggers.some(function(tr){ return histText.includes(tr); })) { + suggested.push({ key: key, source: 'chat' }); + } + }); + + if (!suggested.length) { el.innerHTML = ''; return; } + + var html = '
💡 Рекомендую для вашей ситуации:
' + + '
'; + + suggested.slice(0, 3).forEach(function(s) { + var meta = _TEMPLATE_META[s.key]; + var badge = ''; + if (s.source === 'deadline' && s.urgency) { + var cls = s.urgency.cls === 'overdue' ? 'crit' : s.urgency.cls === 'soon' ? 'warn' : 'ok'; + badge = '' + + s.urgency.badge + ''; + } else if (s.source === 'chat') { + badge = 'из разговора'; + } + html += '
' + + '
' + meta.icon + '
' + + '
' + meta.name + badge + '
' + + '
Нажмите — Елена уточнит и заполнит
' + + '
'; + }); + + html += '
'; + el.innerHTML = html; +} + +// Запускает флоу: уточнение → генерация +var _tplCurrent = null; // текущий шаблон в процессе заполнения + +function _startTemplate(templateKey) { + var meta = _TEMPLATE_META[templateKey] || { name: templateKey, icon: '📄' }; + _tplCurrent = { key: templateKey, parties: {}, contract_data: {}, extra: '' }; + + // Собираем что уже знаем + var contracts = _getContracts(); + var ctx = _buildElenaContext(); + var postalData = typeof _postalData !== 'undefined' ? _postalData : null; + + // Пытаемся предзаполнить из данных клиента + if (postalData && postalData.sender) { + _tplCurrent.parties.from_name = postalData.sender; + _tplCurrent.parties.from_addr = postalData.senderAddr; + _tplCurrent.parties.to_name = postalData.counterparty; + _tplCurrent.parties.to_addr = postalData.counterAddr; + } else { + var b2b = null; + try { b2b = JSON.parse(localStorage.getItem('zashita_b2b') || 'null'); } catch(e){} + if (b2b && b2b.name) _tplCurrent.parties.from_name = b2b.name; + } + + // Данные из последнего договора + if (contracts.length) { + var c = contracts[0]; + _tplCurrent.contract_data.type = c.type; + _tplCurrent.contract_data.counterparty = c.counterparty; + if (c.end) _tplCurrent.contract_data.end_date = c.end; + } + + // Показываем модальный флоу уточнения + _showTemplateClarify(meta); +} + +function _showTemplateClarify(meta) { + var old = document.getElementById('tpl-modal'); if (old) old.remove(); + + // Определяем какой вопрос задаём + var fromName = _tplCurrent.parties.from_name || ''; + var toName = _tplCurrent.parties.to_name || _tplCurrent.contract_data.counterparty || ''; + + var question = ''; + if (fromName && toName) { + question = 'Документ от ' + fromName + '' + toName + '. Всё верно?'; + } else if (fromName) { + question = 'От вас (' + fromName + '). Кому адресуем? Укажите получателя.'; + } else { + question = 'Кто отправитель и получатель документа?'; + } + + var modal = document.createElement('div'); + modal.id = 'tpl-modal'; + modal.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:1000;display:flex;align-items:flex-end;justify-content:center'; + modal.innerHTML = + '
' + + '
' + + '' + + '
' + + '
Елена · ' + (meta.icon||'📄') + ' ' + (meta.name||'Документ') + '
' + + '
Уточню данные и заполню за секунды
' + + '
' + + '' + + '
' + + + '
' + question + '
' + + + '
' + + '' + + '' + + '' + + '
' + + + '
' + + '' + + '' + + '
' + + '
'; + + document.body.appendChild(modal); + setTimeout(function(){ + var inp = document.getElementById('tpl-from'); + if (inp && !inp.value) inp.focus(); + else { var t = document.getElementById('tpl-to'); if (t && !t.value) t.focus(); } + }, 200); +} + +function _generateFromModal() { + if (!_tplCurrent) return; + + var fromVal = (document.getElementById('tpl-from') || {}).value || ''; + var toVal = (document.getElementById('tpl-to') || {}).value || ''; + var extraVal = (document.getElementById('tpl-extra') || {}).value || ''; + + if (!fromVal && !toVal) { toast('Укажите хотя бы одну из сторон'); return; } + + _tplCurrent.parties.from_name = fromVal; + _tplCurrent.parties.to_name = toVal; + _tplCurrent.extra = extraVal; + + // Закрываем модал, показываем progress + var modal = document.getElementById('tpl-modal'); + if (modal) modal.innerHTML = + '
' + + '' + + '
Елена заполняет документ…
' + + '
Обычно занимает 5-10 секунд
' + + '
'; + + fetch(API_BASE + '/api/generate', { + method: 'POST', + headers: {'Content-Type':'application/json'}, + body: JSON.stringify({ + template: _tplCurrent.key, + parties: _tplCurrent.parties, + contract_data: _tplCurrent.contract_data, + extra: _tplCurrent.extra + }) + }) + .then(function(r){ return r.json(); }) + .then(function(data){ + var m = document.getElementById('tpl-modal'); if (m) m.remove(); + if (data.error) { toast('Ошибка: ' + data.error); return; } + _showGeneratedDoc(data); + }) + .catch(function(e){ + var m = document.getElementById('tpl-modal'); if (m) m.remove(); + toast('Ошибка генерации: ' + e.message); + }); +} + +function _showGeneratedDoc(data) { + var old = document.getElementById('tpl-result'); if (old) old.remove(); + + var modal = document.createElement('div'); + modal.id = 'tpl-result'; + modal.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:1000;display:flex;align-items:center;justify-content:center;padding:16px'; + modal.innerHTML = + '
' + + '
' + + '
' + + '
📄 ' + (data.title || 'Документ') + '
' + + '
Готов · ' + (data.date || '') + ' · проверьте перед использованием
' + + '
' + + '' + + '
' + + '
' + + '
' +
+          (data.text || '').replace(/' +
+      '
' + + '
' + + '' + + '' + + '' + + '
' + + '
'; + + document.body.appendChild(modal); + + // Сохраняем в досье + _updateDossier({ decisions: ['Составлен документ: ' + (data.title||data.template)] }); +} + +function _printDoc() { + var text = document.getElementById('tpl-doc-text'); + if (!text) return; + var w = window.open('', '_blank'); + w.document.write('Документ' + + '' + + '
' + text.innerHTML + '
' + + '