From 3c29e83ffcb4ebe5f5a6917477a490145c7427c2 Mon Sep 17 00:00:00 2001 From: WASRUSGEN Date: Thu, 28 May 2026 14:50:59 +0300 Subject: [PATCH] =?UTF-8?q?feat:=20personalized=20returning=20visitor=20ch?= =?UTF-8?q?at=20=E2=80=94=20name,=20last=20contract,=20credits,=20urgent?= =?UTF-8?q?=20deadlines?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mockup.html | 217 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 208 insertions(+), 9 deletions(-) diff --git a/mockup.html b/mockup.html index 0471a26..e9759d3 100644 --- a/mockup.html +++ b/mockup.html @@ -894,6 +894,12 @@ body{font-family:var(--font-ui);background:var(--surf);color:var(--ink);line-hei @keyframes twBlink{0%,100%{opacity:1}50%{opacity:0}} .hero-tw-text{font-size:14px;font-weight:600;color:rgba(255,255,255,.82);line-height:1.4} .ret-tw-wrap{margin:0 0 22px;display:flex;align-items:baseline;gap:7px;min-height:32px} +/* ── RETURNING CHAT ── */ +.ret-chat{background:rgba(255,255,255,.97);border-radius:18px;overflow:hidden;box-shadow:0 8px 40px rgba(0,0,0,.22);margin:0 0 14px} +.ret-chat-stat-row{display:flex;gap:8px;margin-bottom:4px;flex-wrap:wrap} +.ret-stat{background:rgba(255,255,255,.15);border:1px solid rgba(255,255,255,.25);border-radius:10px;padding:5px 12px;font-size:12px;font-weight:700;color:rgba(255,255,255,.95)} +.ret-stat.warn{background:rgba(239,68,68,.25);border-color:rgba(239,68,68,.4)} +.ret-stat.green{background:rgba(34,197,94,.2);border-color:rgba(34,197,94,.35)} .ret-tw-wrap .hero-tw-cur{font-size:20px;color:rgba(255,255,255,.45)} .ret-tw-wrap .hero-tw-text{font-size:18px;font-weight:700;color:rgba(255,255,255,.95)} .ret-ord-lbl{font-size:11px;font-weight:700;color:rgba(255,255,255,.45);text-transform:uppercase;letter-spacing:.6px;margin-bottom:7px} @@ -1166,14 +1172,29 @@ body{font-family:var(--font-ui);background:var(--surf);color:var(--ink);line-hei
Елена
Елена — ваш референт
@@ -2605,7 +2626,7 @@ function toast(msg){ } function go(id){document.querySelectorAll('.screen').forEach(s=>s.classList.toggle('on',s.id===id)); if(id==='admin' && typeof _initAdmin==='function') setTimeout(_initAdmin,50); - if(id==='start') { _hchatDone=false; var m=document.getElementById('hchat-msgs'); if(m){m.innerHTML='';} var r=document.getElementById('hchat-replies'); if(r)r.style.display='none'; var ir=document.getElementById('hchat-input-row'); if(ir)ir.style.display='none'; setTimeout(initHeroChat,300); };window.scrollTo(0,0);} + if(id==='start') { _hchatDone=false; var m=document.getElementById('hchat-msgs'); if(m){m.innerHTML='';} var r=document.getElementById('hchat-replies'); if(r)r.style.display='none'; var ir=document.getElementById('hchat-input-row'); if(ir)ir.style.display='none'; setTimeout(initHeroChat,300); var rm=document.getElementById('rchat-msgs'); if(rm)rm.innerHTML=''; };window.scrollTo(0,0);} /* ── СВОЙ ЗАПРОС ── */ let _customOpen = false; let _voiceRec = null; @@ -2901,7 +2922,8 @@ function checkReturning() { } retPhrases.push('новый документ — за несколько секунд'); retPhrases.push('все ваши дела в кабинете 📂'); - startTypewriter(document.getElementById('hero-tw-ret'), retPhrases, 55); + // personalized chat instead of typewriter + setTimeout(initReturnChat, 300); } } window.addEventListener('DOMContentLoaded', checkReturning); @@ -3754,6 +3776,183 @@ window.addEventListener('DOMContentLoaded', function(){ } }); +/* ── RETURNING CHAT ── */ + +function _rcAddTyping() { + var msgs = document.getElementById('rchat-msgs'); + if (!msgs) return; + var el = document.createElement('div'); + el.className = 'hc-typing'; el.id = 'rc-typing'; + el.innerHTML = '
'; + msgs.appendChild(el); msgs.scrollTop = msgs.scrollHeight; +} +function _rcRemoveTyping() { + var el = document.getElementById('rc-typing'); if (el) el.remove(); +} +function _rcAddBubble(html, isUser) { + var msgs = document.getElementById('rchat-msgs'); + if (!msgs) return; + var row = document.createElement('div'); + row.className = 'hc-msg' + (isUser ? ' hc-user-msg' : ''); + if (!isUser) { + row.innerHTML = '
' + html + '
'; + } else { + row.innerHTML = '
' + html + '
'; + } + msgs.appendChild(row); msgs.scrollTop = msgs.scrollHeight; +} +function _rcShowControls() { + var r = document.getElementById('rchat-replies'); + var i = document.getElementById('rchat-input-row'); + if (r) r.style.display = ''; + if (i) i.style.display = ''; +} + +function initReturnChat() { + var msgs = document.getElementById('rchat-msgs'); + if (!msgs) return; + msgs.innerHTML = ''; + + // ── Собираем персональные данные ── + var lastOrder = JSON.parse(localStorage.getItem('zashita_last_order') || 'null'); + var credits = parseInt(localStorage.getItem('zashita_credits') || '0'); + var subPlan = localStorage.getItem('zashita_sub_plan'); + var stats = JSON.parse(localStorage.getItem('zashita_intake_stats')|| '[]'); + var refunds = JSON.parse(localStorage.getItem('zashita_refund_requests') || '[]'); + + // Имя из stats или last_order + var name = ''; + if (stats.length && stats[0].name) name = stats[0].name; + + // Ближайший срочный дедлайн + var urgentDL = null; + if (typeof _DEADLINES !== 'undefined') { + var today = new Date(); today.setHours(0,0,0,0); + _DEADLINES.forEach(function(d){ + if (d.done || !d.date) return; + var dt = new Date(d.date); dt.setHours(0,0,0,0); + var diff = Math.round((dt - today) / 86400000); + if (diff >= 0 && diff <= 7) { + if (!urgentDL || diff < urgentDL.diff) urgentDL = { dl: d, diff: diff }; + } + }); + } + + // Pending refund + var pendingRefund = refunds.find(function(r){ return r.status === 'pending'; }); + + // ── Статус-чипсы над чатом ── + var statsRow = document.getElementById('ret-stats-row'); + if (statsRow) { + var chips = []; + if (credits > 0) chips.push('
💳 ' + credits + ' кредитов
'); + else if (subPlan) chips.push('
✅ Подписка активна
'); + if (urgentDL) chips.push('
⚠️ ' + urgentDL.dl.title + ' — через ' + urgentDL.diff + ' дн.
'); + if (pendingRefund) chips.push('
↩ Заявка на возврат на рассмотрении
'); + statsRow.innerHTML = chips.join(''); + } + + // ── Строим персональные сообщения ── + var greeting = name + ? (name + ', рада снова Вас видеть! 👋') + : 'С возвращением! Рада снова Вас видеть 👋'; + + var context = ''; + if (lastOrder && lastOrder.ttl) { + context = 'Помню ваш последний документ: ' + lastOrder.ttl + '.'; + if (lastOrder.plan) context += ' Тариф: ' + lastOrder.plan + '.'; + } + if (credits > 0) { + context += (context ? ' ' : '') + 'На балансе ' + credits + ' кредитов.'; + } else if (subPlan) { + var sNames = {1:'Старт', 2:'Бизнес', 3:'Безлимит'}; + context += (context ? ' ' : '') + 'Подписка ' + (sNames[subPlan]||'') + ' активна.'; + } + + var callToAction = ''; + if (urgentDL) { + callToAction = '⚠️ Срочно: ' + urgentDL.dl.title + ' — через ' + urgentDL.diff + + (urgentDL.diff === 1 ? ' день' : urgentDL.diff < 5 ? ' дня' : ' дней') + + '. Нужно действовать.'; + } else if (pendingRefund) { + callToAction = 'Ваша заявка на возврат в обработке — ответим в течение 10 рабочих дней.'; + } else if (!credits && !subPlan) { + callToAction = 'Кредиты закончились — пополните баланс, чтобы продолжить.'; + } else { + callToAction = 'Чем займёмся сегодня?'; + } + + // ── Последовательность сообщений ── + var delay = 0; + + // msg 1: greeting + delay += 400; + (function(d){ setTimeout(_rcAddTyping, d); })(delay); + delay += 700; + (function(d, txt){ setTimeout(function(){ _rcRemoveTyping(); _rcAddBubble(txt, false); }, d); })(delay, greeting); + + // msg 2: context (only if we have something) + if (context) { + delay += 400; + (function(d){ setTimeout(_rcAddTyping, d); })(delay); + delay += 900; + (function(d, txt){ setTimeout(function(){ _rcRemoveTyping(); _rcAddBubble(txt, false); }, d); })(delay, context); + } + + // msg 3: call to action + delay += 300; + (function(d){ setTimeout(_rcAddTyping, d); })(delay); + delay += 600; + (function(d, txt){ setTimeout(function(){ _rcRemoveTyping(); _rcAddBubble(txt, false); }, d); })(delay, callToAction); + + // show controls + delay += 400; + (function(d){ setTimeout(_rcShowControls, d); })(delay); + + // Update quick replies based on context + if (urgentDL) { + var repl = document.getElementById('rchat-replies'); + if (repl) repl.innerHTML = + '
⏱️ Срочные сроки
' + + '
📂 Мои дела
' + + '
📄 Новый договор
' + + '
💳 Баланс
'; + } +} + +function retChatSend() { + var inp = document.getElementById('rchat-inp'); + if (!inp) return; + var txt = inp.value.trim(); if (!txt) return; + inp.value = ''; + var r = document.getElementById('rchat-replies'); + var i = document.getElementById('rchat-input-row'); + if (r) r.style.display = 'none'; if (i) i.style.display = 'none'; + _rcAddBubble(txt, true); + var t = txt.toLowerCase(); + var intent = 'question'; + if (/срок|уведомл|дедлайн/.test(t)) intent = 'deadlines'; + else if (/баланс|кредит|оплат/.test(t)) intent = 'pay'; + else if (/новый|загруз|проверит|договор/.test(t)) intent = 'new'; + else if (/дела|кабинет/.test(t)) intent = 'cabinet'; + var replies = { + deadlines: { elena: 'Открываю ваши сроки — всё самое срочное там 📋', action: function(){ go('cabinet'); tab('sroki'); } }, + pay: { elena: 'Показываю баланс и варианты пополнения 💳', action: function(){ go('pay'); } }, + new: { elena: 'Отличное решение! Загружайте новый документ — разберём 🔍', action: function(){ go('elena'); } }, + cabinet: { elena: 'Открываю ваши дела 📂', action: function(){ go('cabinet'); } }, + question: { elena: 'Хорошо! Перехожу к Елене — она ответит на любой юридический вопрос 💬', action: function(){ go('elena'); } } + }; + var resp = replies[intent] || replies.question; + setTimeout(function(){ + _rcAddTyping(); + setTimeout(function(){ + _rcRemoveTyping(); + _rcAddBubble(resp.elena, false); + setTimeout(resp.action, 900); + }, 700); + }, 300); +} + /* ── ГОЛОСОВОЙ ВВОД ── */ var _voiceActive = false; var _voiceRecog = null;