Кабинет
Составить документ
@@ -7276,7 +7373,13 @@ window.addEventListener('hashchange', handleHash);
function tab(name){
document.querySelectorAll('.tabpane').forEach(p=>p.classList.toggle('on',p.id==='p-'+name));
if(name==='sroki' && typeof renderDeadlines==='function') renderDeadlines();
- if(name==='shab' && typeof renderContextTemplates==='function') renderContextTemplates();
+ if(name==='shab' && typeof renderContextTemplates==='function') renderContextTemplates();
+ if(name==='requisites' && typeof _loadRequisites==='function') _loadRequisites();
+ if(name==='docs') {
+ var contracts = typeof _getContracts === 'function' ? _getContracts() : [];
+ if (contracts.length && typeof renderDocChecklist === 'function') renderDocChecklist(contracts[0].type);
+ else if (typeof renderDocChecklist === 'function') renderDocChecklist('');
+ }
if(name==='balance' && typeof _refreshBalanceTab==='function') _refreshBalanceTab();
document.querySelectorAll('.side a').forEach(a=>a.classList.remove('on'));
const map={cases:'t-cases',case:'t-case',sroki:'t-sroki',shab:'t-shab',create:'t-create'};
@@ -7585,6 +7688,280 @@ function _compressAsync(showToast) {
.catch(function(){});
}
+// ── ЧЕКЛИСТ ДОКУМЕНТОВ ──────────────────────────────────────────────────────
+
+var DOC_CHECKLISTS = {
+ 'аренда': {
+ label: 'Договор аренды', icon: '🏠',
+ docs: [
+ { id:'contract', label:'Договор аренды (подписанный)', risk:'critical', tip:'Нет договора — нет правовых оснований пользования помещением' },
+ { id:'act_in', label:'Акт приёмки-передачи при заезде', risk:'critical', tip:'Без акта арендодатель может заявить что ВЫ испортили помещение' },
+ { id:'photo_in', label:'Фотофиксация помещения при заезде', risk:'high', tip:'Без фото сложно доказать состояние на дату заезда' },
+ { id:'deposit_rec', label:'Квитанция об оплате депозита', risk:'high', tip:'Без квитанции спорно — платили ли депозит и какую сумму' },
+ { id:'payments', label:'Квитанции/платёжки об аренде', risk:'medium', tip:'Сложнее доказать факт регулярной оплаты' },
+ { id:'notice', label:'Уведомление о непродлении (если нужно)', risk:'critical', tip:'Без уведомления — договор автоматически продлится' },
+ { id:'act_out', label:'Акт возврата помещения (при съезде)', risk:'high', tip:'Без акта арендодатель может требовать доплату «за пользование»' },
+ ]
+ },
+ 'подряд': {
+ label: 'Договор подряда/услуг', icon: '🔨',
+ docs: [
+ { id:'contract', label:'Договор подряда/услуг', risk:'critical', tip:'Нет договора — нет оснований требовать исполнения' },
+ { id:'tz', label:'ТЗ / спецификация работ', risk:'critical', tip:'Без ТЗ любой результат подрядчик назовёт «надлежащим»' },
+ { id:'act', label:'Акт сдачи-приёмки работ', risk:'high', tip:'Без акта работы считаются невыполненными' },
+ { id:'payments', label:'Платёжки об оплате', risk:'medium', tip:'Нужны для доказательства оплаты' },
+ { id:'warranty', label:'Гарантийные обязательства', risk:'high', tip:'Без чётких условий гарантии подрядчик откажет в ремонте' },
+ ]
+ },
+ 'купля-продажа': {
+ label: 'Купля-продажа', icon: '🛒',
+ docs: [
+ { id:'contract', label:'Договор купли-продажи', risk:'critical', tip:'Нет договора — нет оснований' },
+ { id:'upd', label:'УПД / накладная ТОРГ-12', risk:'high', tip:'Без накладной нельзя доказать факт поставки' },
+ { id:'act', label:'Акт приёмки по качеству', risk:'critical', tip:'Без акта принятое считается надлежащим' },
+ { id:'payments', label:'Платёжные документы', risk:'medium', tip:'Доказательство оплаты' },
+ ]
+ },
+ 'дду': {
+ label: 'ДДУ / новостройка', icon: '🏗️',
+ docs: [
+ { id:'ddu', label:'ДДУ зарегистрированный в Росреестре', risk:'critical', tip:'Без регистрации нет защиты по 214-ФЗ' },
+ { id:'payments', label:'Квитанции об оплате по ДДУ', risk:'high', tip:'Нужны для расчёта неустойки' },
+ { id:'act', label:'Акт осмотра с замечаниями', risk:'critical', tip:'Без замечаний в акте претензии по дефектам сложнее' },
+ { id:'act_in', label:'Акт приёмки-передачи квартиры', risk:'high', tip:'Дата акта = начало гарантийного срока' },
+ { id:'notice', label:'Уведомления застройщика о сроках', risk:'medium', tip:'Фиксирует когда было обещано и когда нарушено' },
+ ]
+ },
+ 'недвижимость': {
+ label: 'Купля-продажа недвижимости', icon: '🏠',
+ docs: [
+ { id:'egrn', label:'Выписка из ЕГРН (свежая, до 30 дней)', risk:'critical', tip:'Аресты, ипотека, запреты — всё здесь' },
+ { id:'osnov', label:'Основание права продавца', risk:'critical', tip:'Откуда у него право — дарение/наследство/купля — возможны оспаривания' },
+ { id:'forma9', label:'Справка о зарегистрированных (Ф.9)', risk:'high', tip:'Прописанные после сделки не выписываются автоматически' },
+ { id:'spr_sup', label:'Согласие супруга (нотариально)', risk:'critical', tip:'Без согласия сделку оспорит супруг' },
+ { id:'zhkh', label:'Справка об отсутствии долгов ЖКХ', risk:'medium', tip:'Чужие долги могут перейти к вам' },
+ { id:'contract', label:'ДКП зарегистрированный в Росреестре', risk:'critical', tip:'До регистрации квартира юридически не ваша' },
+ ]
+ },
+ 'трудовой': {
+ label: 'Трудовой договор', icon: '💼',
+ docs: [
+ { id:'contract', label:'Трудовой договор', risk:'critical', tip:'Без договора нет доказательств условий труда' },
+ { id:'order', label:'Приказ о приёме на работу', risk:'high', tip:'Подтверждение трудовых отношений' },
+ { id:'instruc', label:'Должностная инструкция', risk:'high', tip:'Без неё обязанности расширяют как хотят' },
+ { id:'payslips', label:'Расчётные листки', risk:'medium', tip:'Доказательство начисленной зарплаты' },
+ { id:'ndfl2', label:'Справка 2-НДФЛ', risk:'high', tip:'Без неё компенсации считают от минималки' },
+ ]
+ },
+ 'займ': {
+ label: 'Займ / расписка', icon: '💰',
+ docs: [
+ { id:'receipt', label:'Расписка или договор займа', risk:'critical', tip:'Нет расписки — нет доказательств займа' },
+ { id:'transfer', label:'Подтверждение передачи денег', risk:'critical', tip:'Без подтверждения должник скажет «не получал»' },
+ { id:'percent', label:'Условие о процентах', risk:'medium', tip:'Без пункта о % займ считается беспроцентным' },
+ { id:'deadline', label:'Срок возврата', risk:'high', tip:'Без срока — по первому требованию, но сложно взыскать' },
+ ]
+ },
+};
+
+function renderDocChecklist(contractType) {
+ var el = document.getElementById('docs-checklist');
+ if (!el) return;
+
+ var type = (contractType || '').toLowerCase();
+ // Определяем ближайший тип
+ var key = null;
+ if (/аренд/.test(type)) key = 'аренда';
+ else if (/подряд|услуг/.test(type)) key = 'подряд';
+ else if (/купли.продажи|поставк/.test(type)) key = 'купля-продажа';
+ else if (/дду|долев|новостройк/.test(type)) key = 'дду';
+ else if (/недвижим|квартир/.test(type)) key = 'недвижимость';
+ else if (/трудов/.test(type)) key = 'трудовой';
+ else if (/займ|расписк/.test(type)) key = 'займ';
+
+ if (!key) {
+ el.innerHTML = '
Загрузите договор — Елена определит тип и покажет нужный чеклист.
';
+ return;
+ }
+
+ var saved = {};
+ try { saved = JSON.parse(localStorage.getItem('zashita_doccheck_' + key) || '{}'); } catch(e){}
+
+ var cl = DOC_CHECKLISTS[key];
+ var missing = cl.docs.filter(function(d){ return !saved[d.id]; });
+ var critical = missing.filter(function(d){ return d.risk === 'critical'; }).length;
+
+ var html = '
' +
+ '
' + cl.icon + '' +
+ '
' + cl.label + '
' +
+ (critical > 0
+ ? '
⚠️ ' + critical + ' критических пункта требуют внимания
'
+ : '
✅ Пакет документов в порядке
') +
+ '
';
+
+ html += '
';
+ cl.docs.forEach(function(doc) {
+ var checked = !!saved[doc.id];
+ var riskColor = {critical:'#dc2626', high:'#d97706', medium:'#2563eb'}[doc.risk] || '#6b7280';
+ html +=
+ '
';
+ });
+ html += '
';
+
+ // Кнопка загрузить недостающие
+ if (missing.length) {
+ html += '
' +
+ 'Не хватает ' + missing.length + ' документа: ' +
+ missing.map(function(d){ return d.label.split('(')[0].trim(); }).join(', ') + '.
' +
+ 'Загрузите их в Елену — она проверит и зафиксирует в деле.' +
+ '
';
+ }
+
+ el.innerHTML = html;
+}
+
+function _toggleDocCheck(key, docId, checked) {
+ try {
+ var saved = JSON.parse(localStorage.getItem('zashita_doccheck_' + key) || '{}');
+ saved[docId] = checked;
+ localStorage.setItem('zashita_doccheck_' + key, JSON.stringify(saved));
+ renderDocChecklist(key);
+ } catch(e){}
+}
+
+// ── РЕКВИЗИТЫ — ПОДПИСЬ И ПЕЧАТЬ ────────────────────────────────────────────
+
+function _uploadRequisite(type, input) {
+ var file = input.files[0];
+ if (!file) return;
+ var reader = new FileReader();
+ reader.onload = function(e) {
+ var img = new Image();
+ img.onload = function() {
+ // Canvas: убираем белый фон (простая threshold-обработка)
+ var canvas = document.createElement('canvas');
+ canvas.width = img.width;
+ canvas.height = img.height;
+ var ctx = canvas.getContext('2d');
+ ctx.drawImage(img, 0, 0);
+ var data = ctx.getImageData(0, 0, canvas.width, canvas.height);
+ var d = data.data;
+ for (var i = 0; i < d.length; i += 4) {
+ var r = d[i], g = d[i+1], b = d[i+2];
+ // Белый / светло-серый → прозрачный
+ if (r > 220 && g > 220 && b > 220) {
+ d[i+3] = 0;
+ }
+ }
+ ctx.putImageData(data, 0, 0);
+ var png = canvas.toDataURL('image/png');
+ localStorage.setItem('zashita_' + type, png);
+ _showRequisite(type, png);
+ toast('✅ ' + (type === 'sig' ? 'Подпись' : 'Печать') + ' сохранена');
+ };
+ img.src = e.target.result;
+ };
+ reader.readAsDataURL(file);
+}
+
+function _showRequisite(type, dataUrl) {
+ var prev = document.getElementById(type + '-preview');
+ var imgEl = document.getElementById(type + '-img');
+ if (prev) prev.style.display = '';
+ if (imgEl) imgEl.src = dataUrl;
+ if (type === 'stamp') {
+ var sel = document.getElementById('stamp-type-sel');
+ var sizeEl = document.getElementById('stamp-size');
+ var sizes = {round:'⌀ 40 мм', rect_ip:'38×70 мм', rect_ooo:'38×58 мм', triangle:'35×50 мм'};
+ var selVal = sel ? sel.value : 'round';
+ if (sizeEl) sizeEl.textContent = 'Размер: ' + (sizes[selVal] || '');
+ }
+}
+
+function _clearRequisite(type) {
+ localStorage.removeItem('zashita_' + type);
+ var prev = document.getElementById(type + '-preview');
+ if (prev) prev.style.display = 'none';
+ toast((type === 'sig' ? 'Подпись' : 'Печать') + ' удалена');
+}
+
+function _drawSignature() {
+ var modal = document.getElementById('sig-draw-modal');
+ if (modal) { modal.style.display = 'flex'; _initSigCanvas(); }
+}
+
+var _sigDrawing = false;
+function _initSigCanvas() {
+ var c = document.getElementById('sig-canvas');
+ if (!c || c._inited) return;
+ c._inited = true;
+ var ctx = c.getContext('2d');
+ ctx.strokeStyle = '#1a1a2e';
+ ctx.lineWidth = 2;
+ ctx.lineCap = 'round';
+ var getPos = function(e) {
+ var rect = c.getBoundingClientRect();
+ var src = e.touches ? e.touches[0] : e;
+ return { x: src.clientX - rect.left, y: src.clientY - rect.top };
+ };
+ c.onmousedown = c.ontouchstart = function(e){ e.preventDefault(); _sigDrawing = true; var p = getPos(e); ctx.beginPath(); ctx.moveTo(p.x, p.y); };
+ c.onmousemove = c.ontouchmove = function(e){ e.preventDefault(); if (!_sigDrawing) return; var p = getPos(e); ctx.lineTo(p.x, p.y); ctx.stroke(); };
+ c.onmouseup = c.ontouchend = function(){ _sigDrawing = false; };
+}
+
+function _clearCanvas() {
+ var c = document.getElementById('sig-canvas');
+ if (c) c.getContext('2d').clearRect(0, 0, c.width, c.height);
+}
+
+function _saveSigCanvas() {
+ var c = document.getElementById('sig-canvas');
+ if (!c) return;
+ var png = c.toDataURL('image/png');
+ localStorage.setItem('zashita_sig', png);
+ _showRequisite('sig', png);
+ var modal = document.getElementById('sig-draw-modal');
+ if (modal) modal.style.display = 'none';
+ toast('✅ Подпись сохранена');
+}
+
+function _saveRequisites() {
+ var fields = ['name','inn','addr','phone','email'];
+ var data = {};
+ fields.forEach(function(f){
+ var el = document.getElementById('req-' + f);
+ if (el) data[f] = el.value;
+ });
+ try { localStorage.setItem('zashita_requisites', JSON.stringify(data)); } catch(e){}
+}
+
+function _loadRequisites() {
+ try {
+ var data = JSON.parse(localStorage.getItem('zashita_requisites') || '{}');
+ ['name','inn','addr','phone','email'].forEach(function(f){
+ var el = document.getElementById('req-' + f);
+ if (el && data[f]) el.value = data[f];
+ });
+ } catch(e){}
+ // Загружаем сохранённые изображения
+ ['sig','stamp'].forEach(function(type){
+ var saved = localStorage.getItem('zashita_' + type);
+ if (saved) _showRequisite(type, saved);
+ });
+}
+
// Флаг памяти — используется для контекстного приветствия (с защитой от race condition)
window._hasMemory = (function() {
try {