Кабинет
Шаблоны
-
Готовые документы — заполню под ваш случай. Составлять с нуля не нужно 💛
-
-
-
-
+
@@ -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 = 'Документ ' +
+ '' +
+ '
📝
Протокол разногласий
убрать невыгодные пункты
✉️
Претензия
оплата / неустойка
🛡️
Ответ на претензию
отбить требование
🚪
Расторжение
выйти без потерь
+
+
+
+
+
+
+
+
Кабинет
Шаблоны
+
+ Заполню под ваш случай автоматически. Данные из ваших договоров — уточню только что нужно 💛
+ Все шаблоны:
+
+
+
+ 📬
Уведомление о непродлении
+ аренда · за 30 дней до окончания
+
+
+ ✉️
Претензия об оплате
+ взыскать долг · ст. 395 ГК
+
+
+ ⚠️
Претензия о качестве
+ товар / работы · ЗоЗПП / ст. 723 ГК
+
+
+ 🛡️
Ответ на претензию
+ отбить требование · с аргументами
+
+
+ 💰
Требование о возврате депозита
+ после окончания аренды
+
+
+ 🚪
Соглашение о расторжении
+ по соглашению сторон · без суда
+
+
+ ✅
Акт приёмки-передачи
+ подряд / услуги · фиксируем факт
+
+
📑
Доверенность
+ в суд · на авто · для сделок
+ 💡 Рекомендую для вашей ситуации:
' +
+ '';
+
+ 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 += '
';
+ 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 =
+ '' +
+ '
';
+ });
+
+ html += '' + meta.icon + '
' +
+ '' + meta.name + badge + '
' +
+ 'Нажмите — Елена уточнит и заполнит
' +
+ '' +
+ '
';
+
+ 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 =
+ '' +
+ '
' +
+ '
' +
+
+ '
' +
+ '' +
+ '
' +
+ '' +
+ 'Елена · ' + (meta.icon||'📄') + ' ' + (meta.name||'Документ') + '
' +
+ 'Уточню данные и заполню за секунды
' +
+ '' + question + '
' +
+
+ '' +
+ '' +
+ '' +
+ '' +
+ '
' +
+
+ '' +
+ '' +
+ '' +
+ '
' +
+ '' +
+ '
' +
+ '
';
+
+ 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 =
+ '
' +
+ 'Елена заполняет документ…
' +
+ 'Обычно занимает 5-10 секунд
' +
+ '' +
+ '
';
+
+ 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('' +
+ '
' +
+ '' +
+ '
' +
+ '' +
+ '📄 ' + (data.title || 'Документ') + '
' +
+ 'Готов · ' + (data.date || '') + ' · проверьте перед использованием
' +
+ '' +
+ '
' +
+ '' + + (data.text || '').replace(/' + + '
' +
+ '' +
+ '' +
+ '' +
+ '
' +
+ '' + text.innerHTML + '' + + '