Add request access modal on login page with Telegram notification
- Modal form: name, company, email, phone (required), manager (optional), product checkboxes - Products loaded from DB via GET /api/public/services-by-category (public route) - POST /api/request-access sends styled Telegram message with divider and emojis - Dark-themed modal matching login page design - CSS: overlay, card, fields, checkbox list, error, footer buttons
This commit is contained in:
+146
-1
@@ -71,12 +71,157 @@
|
||||
</div>
|
||||
<button type="submit" class="login-submit">Войти</button>
|
||||
</form>
|
||||
<a class="login-request-btn" href="mailto:rgalyaviev@mont.com?subject=%D0%94%D0%BE%D1%81%D1%82%D1%83%D0%BF%20%D0%BA%20%D0%BF%D0%BE%D0%BB%D0%B8%D0%B3%D0%BE%D0%BD%D1%83">Запросить доступ</a>
|
||||
<button type="button" class="login-request-btn" id="btn-request-access" data-open-access-modal="1">Запросить доступ</button>
|
||||
</div>
|
||||
<footer class="login-footer">
|
||||
<a href="mailto:rgalyaviev@mont.com" class="login-footer-link">Made by Galyaviev</a>
|
||||
</footer>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<!-- Request Access Modal -->
|
||||
<div id="access-modal" class="access-modal-overlay" style="display:none" aria-modal="true" role="dialog">
|
||||
<div class="access-modal">
|
||||
<div class="access-modal-header">
|
||||
<div class="access-modal-title">Запросить доступ</div>
|
||||
<div class="access-modal-sub">Заполните форму — мы свяжемся с вами в ближайшее время</div>
|
||||
</div>
|
||||
<div class="access-modal-body">
|
||||
<div class="access-field">
|
||||
<label>Имя и фамилия <span class="req">*</span></label>
|
||||
<input id="am-name" type="text" placeholder="Иван Иванов" />
|
||||
</div>
|
||||
<div class="access-field">
|
||||
<label>Название компании <span class="req">*</span></label>
|
||||
<input id="am-company" type="text" placeholder="ООО Компания" />
|
||||
</div>
|
||||
<div class="access-field">
|
||||
<label>Email <span class="req">*</span></label>
|
||||
<input id="am-email" type="email" placeholder="ivan@company.ru" />
|
||||
</div>
|
||||
<div class="access-field">
|
||||
<label>Телефон <span class="req">*</span></label>
|
||||
<input id="am-phone" type="tel" placeholder="+7 (999) 000-00-00" />
|
||||
</div>
|
||||
<div class="access-field">
|
||||
<label>Ваш менеджер в МОНТ</label>
|
||||
<input id="am-manager" type="text" placeholder="Если известно — укажите имя" />
|
||||
</div>
|
||||
<div class="access-field">
|
||||
<label>Интересующие продукты</label>
|
||||
<div id="am-products" class="access-products-wrap">
|
||||
<div class="access-products-loading">Загрузка...</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="am-error" class="access-modal-error" style="display:none"></div>
|
||||
</div>
|
||||
<div class="access-modal-footer">
|
||||
<button type="button" class="access-btn-cancel" id="am-cancel">Отмена</button>
|
||||
<button type="button" class="access-btn-submit" id="am-submit">Запросить доступ</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
const overlay = document.getElementById('access-modal');
|
||||
const btnCancel = document.getElementById('am-cancel');
|
||||
const btnSubmit = document.getElementById('am-submit');
|
||||
const errEl = document.getElementById('am-error');
|
||||
let productsLoaded = false;
|
||||
|
||||
function openModal() {
|
||||
overlay.style.display = 'flex';
|
||||
document.body.style.overflow = 'hidden';
|
||||
if (!productsLoaded) loadProducts();
|
||||
}
|
||||
|
||||
function closeModal() {
|
||||
overlay.style.display = 'none';
|
||||
document.body.style.overflow = '';
|
||||
errEl.style.display = 'none';
|
||||
}
|
||||
|
||||
async function loadProducts() {
|
||||
const wrap = document.getElementById('am-products');
|
||||
try {
|
||||
const res = await fetch('/api/public/services-by-category');
|
||||
const data = await res.json();
|
||||
wrap.innerHTML = '';
|
||||
for (const [cat, svcs] of Object.entries(data)) {
|
||||
const group = document.createElement('div');
|
||||
group.className = 'access-products-group';
|
||||
group.innerHTML = '<div class="access-products-cat">' + cat + '</div>';
|
||||
for (const svc of svcs) {
|
||||
const lbl = document.createElement('label');
|
||||
lbl.className = 'access-product-item';
|
||||
lbl.innerHTML = '<input type="checkbox" value="' + svc.name.replace(/"/g, '"') + '" /><span>' + svc.name + '</span>';
|
||||
group.appendChild(lbl);
|
||||
}
|
||||
wrap.appendChild(group);
|
||||
}
|
||||
productsLoaded = true;
|
||||
} catch(e) {
|
||||
wrap.innerHTML = '<div class="access-products-loading">Не удалось загрузить список</div>';
|
||||
}
|
||||
}
|
||||
|
||||
async function submitForm() {
|
||||
const name = document.getElementById('am-name').value.trim();
|
||||
const company = document.getElementById('am-company').value.trim();
|
||||
const email = document.getElementById('am-email').value.trim();
|
||||
const phone = document.getElementById('am-phone').value.trim();
|
||||
const manager = document.getElementById('am-manager').value.trim();
|
||||
const checked = [...document.querySelectorAll('#am-products input[type=checkbox]:checked')];
|
||||
const products = checked.map(c => c.value);
|
||||
|
||||
if (!name || !company || !email || !phone) {
|
||||
errEl.textContent = 'Пожалуйста, заполните все обязательные поля';
|
||||
errEl.style.display = 'block';
|
||||
return;
|
||||
}
|
||||
|
||||
btnSubmit.disabled = true;
|
||||
btnSubmit.textContent = 'Отправка...';
|
||||
errEl.style.display = 'none';
|
||||
|
||||
try {
|
||||
const res = await fetch('/api/request-access', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({name, company, email, phone, manager, products}),
|
||||
});
|
||||
if (!res.ok) {
|
||||
const d = await res.json().catch(() => ({}));
|
||||
throw new Error(d.detail || 'Ошибка отправки');
|
||||
}
|
||||
btnSubmit.textContent = 'Отправлено!';
|
||||
setTimeout(closeModal, 1500);
|
||||
} catch(e) {
|
||||
errEl.textContent = e.message || 'Ошибка отправки, попробуйте позже';
|
||||
errEl.style.display = 'block';
|
||||
btnSubmit.disabled = false;
|
||||
btnSubmit.textContent = 'Запросить доступ';
|
||||
}
|
||||
}
|
||||
|
||||
// Wire up request-access button
|
||||
document.querySelectorAll('.login-request-btn, [data-open-access-modal]').forEach(el => {
|
||||
el.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
openModal();
|
||||
});
|
||||
});
|
||||
|
||||
btnCancel.addEventListener('click', closeModal);
|
||||
btnSubmit.addEventListener('click', submitForm);
|
||||
overlay.addEventListener('click', function(e) {
|
||||
if (e.target === overlay) closeModal();
|
||||
});
|
||||
document.addEventListener('keydown', function(e) {
|
||||
if (e.key === 'Escape') closeModal();
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user