Fix cooldown timer visibility after Start; add real-time modal validation; update context.md with prod server
- Cooldown counter now always rendered (hidden) when auto_reply active, shown dynamically via polling - Modal form validates fields on blur/input with red highlight via .input-invalid class - Telegram: switched back to tel.4mont.ru proxy (working via /etc/hosts on 192.168.33.19) - context.md: added prod server 45.129.3.83, deploy commands, NPM routing notes Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+12
-4
@@ -79,9 +79,9 @@
|
||||
<div class="autoreply-status">
|
||||
<span class="status-dot status-dot--green"></span>
|
||||
<span>Автоответ активен</span>
|
||||
{% if api_cooldown_seconds_left and api_cooldown_seconds_left > 0 %}
|
||||
· Следующий ответ через <span id="cooldown-counter" data-seconds="{{ api_cooldown_seconds_left }}">{{ api_cooldown_seconds_left }}</span> сек.
|
||||
{% endif %}
|
||||
<span id="cooldown-wrap" {% if not api_cooldown_seconds_left or api_cooldown_seconds_left <= 0 %}style="display:none"{% endif %}>
|
||||
· Следующий ответ через <span id="cooldown-counter" data-seconds="{{ api_cooldown_seconds_left or 0 }}">{{ api_cooldown_seconds_left or 0 }}</span> сек.
|
||||
</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
@@ -410,7 +410,15 @@ initPools();
|
||||
} else if (data.last_log_id !== lastLogId) {
|
||||
window.location.reload();
|
||||
}
|
||||
if (cooldownCtrl && data.cooldown > 0) cooldownCtrl.update(data.cooldown);
|
||||
const wrap = document.getElementById('cooldown-wrap');
|
||||
if (wrap) {
|
||||
if (data.cooldown > 0) {
|
||||
wrap.style.display = '';
|
||||
if (cooldownCtrl) cooldownCtrl.update(data.cooldown);
|
||||
} else {
|
||||
wrap.style.display = 'none';
|
||||
}
|
||||
}
|
||||
if (fetchCtrl && data.next_fetch_seconds > 0) fetchCtrl.update(data.next_fetch_seconds);
|
||||
if (data.next_fetch_seconds === 0 && data.queue_len === 0 && data.auto_reply_enabled) {
|
||||
window.location.reload();
|
||||
|
||||
+33
-15
@@ -189,25 +189,43 @@ closeBtn.addEventListener('click', () => modal.classList.remove('active'));
|
||||
modal.addEventListener('click', e => { if (e.target === modal) modal.classList.remove('active'); });
|
||||
document.addEventListener('keydown', e => { if (e.key === 'Escape') modal.classList.remove('active'); });
|
||||
|
||||
document.getElementById('request-form').addEventListener('submit', async e => {
|
||||
const form = document.getElementById('request-form');
|
||||
|
||||
function validateField(name) {
|
||||
const input = form[name];
|
||||
const errEl = document.getElementById('err-' + name);
|
||||
const val = input.value.trim();
|
||||
let msg = '';
|
||||
|
||||
if (name === 'name' && !val)
|
||||
msg = 'Введите имя';
|
||||
if (name === 'email' && (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(val)))
|
||||
msg = 'Введите корректный email';
|
||||
if (name === 'phone' && val.replace(/\D/g, '').length < 10)
|
||||
msg = 'Введите корректный телефон';
|
||||
|
||||
errEl.textContent = msg;
|
||||
input.classList.toggle('input-invalid', !!msg);
|
||||
return !msg;
|
||||
}
|
||||
|
||||
['name', 'email', 'phone'].forEach(name => {
|
||||
const input = form[name];
|
||||
input.addEventListener('blur', () => validateField(name));
|
||||
input.addEventListener('input', () => {
|
||||
if (input.classList.contains('input-invalid')) validateField(name);
|
||||
});
|
||||
});
|
||||
|
||||
form.addEventListener('submit', async e => {
|
||||
e.preventDefault();
|
||||
const form = e.target;
|
||||
const name = form.name.value.trim();
|
||||
const email = form.email.value.trim();
|
||||
const phone = form.phone.value.trim();
|
||||
let valid = true;
|
||||
const validName = validateField('name');
|
||||
const validEmail = validateField('email');
|
||||
const validPhone = validateField('phone');
|
||||
if (!validName || !validEmail || !validPhone) return;
|
||||
|
||||
['name','email','phone'].forEach(f => document.getElementById('err-' + f).textContent = '');
|
||||
document.getElementById('modal-error').style.display = 'none';
|
||||
|
||||
if (!name)
|
||||
{ document.getElementById('err-name').textContent = 'Введите имя'; valid = false; }
|
||||
if (!email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email))
|
||||
{ document.getElementById('err-email').textContent = 'Введите корректный email'; valid = false; }
|
||||
if (!phone || phone.replace(/\D/g, '').length < 10)
|
||||
{ document.getElementById('err-phone').textContent = 'Введите корректный телефон'; valid = false; }
|
||||
if (!valid) return;
|
||||
|
||||
const btn = document.getElementById('request-submit');
|
||||
btn.disabled = true; btn.textContent = 'Отправка…';
|
||||
|
||||
|
||||
Reference in New Issue
Block a user