1 2<!doctype html> 3<html lang="tr"> 4 5<head> 6 <meta charset="UTF-8" /> 7 <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 8 <title>Kurumsal GiriÅ Yapın - AsistAll</title> 9 <!-- Google Fonts: Inter veya Poppins gibi modern fontlar --> 10 <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet" /> 11 <!-- Font Awesome --> 12 <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" /> 13 14 <style> 15 :root { 16 --primary-bg: #111189; 17 --white: #ffffff; 18 --gray-light: #f3f4f6; 19 --gray-text: #6b7280; 20 --dark-text: #111827; 21 --border-color: #e5e7eb; 22 --primary-blue: #0045a1; 23 } 24 25 body, 26 html { 27 margin: 0; 28 padding: 0; 29 height: 100%; 30 font-family: "Inter", sans-serif; 31 background-color: var(--primary-bg); 32 display: flex; 33 align-items: center; 34 justify-content: center; 35 } 36 37 .login-card { 38 background: var(--white); 39 width: 100%; 40 max-width: 750px; 41 padding: 60px 80px; 42 border-radius: 32px; 43 box-shadow: 0 20px 60px rgba(0, 0, 0, 0.25); 44 text-align: center; 45 position: relative; 46 } 47 48 .logo-container { 49 margin-bottom: 32px; 50 } 51 52 .logo-container img { 53 height: 65px; 54 } 55 56 h1 { 57 font-size: 1.4rem; 58 font-weight: 700; 59 color: var(--dark-text); 60 margin-bottom: 35px; 61 } 62 63 .lang-selector-container { 64 position: relative; 65 float: left; 66 margin-bottom: 28px; 67 z-index: 100; 68 } 69 70 .lang-selector { 71 display: inline-flex; 72 align-items: center; 73 gap: 8px; 74 background: var(--primary-bg); 75 color: white; 76 padding: 8px 16px; 77 border-radius: 8px; 78 font-size: 0.8rem; 79 cursor: pointer; 80 transition: background 0.2s; 81 border: none; 82 outline: none; 83 } 84 85 .lang-selector:hover { 86 background: #0d0d6b; 87 } 88 89 .lang-dropdown { 90 position: absolute; 91 top: 100%; 92 left: 0; 93 margin-top: 4px; 94 background: white; 95 border: 1px solid var(--border-color); 96 border-radius: 8px; 97 box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); 98 display: none; 99 min-width: 120px; 100 overflow: hidden; 101 } 102 103 .lang-dropdown.show { 104 display: block; 105 } 106 107 .lang-option { 108 padding: 10px 16px; 109 font-size: 0.85rem; 110 color: var(--dark-text); 111 cursor: pointer; 112 text-align: left; 113 transition: background 0.2s; 114 } 115 116 .lang-option:hover { 117 background: #f3f6f9; 118 } 119 120 .form-group { 121 margin-bottom: 16px; 122 text-align: left; 123 clear: both; 124 } 125 126 .input-wrapper { 127 position: relative; 128 } 129 130 input { 131 width: 100%; 132 padding: 16px 20px; 133 border: 1px solid var(--border-color); 134 background: #f3f6f9; 135 border-radius: 10px; 136 font-size: 0.9rem; 137 color: var(--dark-text); 138 outline: none; 139 box-sizing: border-box; 140 transition: all 0.3s; 141 } 142 143 input:focus { 144 border-color: var(--primary-blue); 145 background: white; 146 box-shadow: 0 0 0 4px rgba(0, 69, 161, 0.08); 147 } 148 149 /* Labelları daha saÄlam bir yöntemle gizleyelim veya üste taÅıyalım */ 150 .input-label { 151 position: absolute; 152 left: 20px; 153 top: 50%; 154 transform: translateY(-50%); 155 color: var(--gray-text); 156 pointer-events: none; 157 transition: all 0.2s; 158 font-size: 0.9rem; 159 } 160 161 /* Input doluysa veya focus ise label'ı tamamen kaldıralım */ 162 input:focus+.input-label, 163 input:not(:placeholder-shown)+.input-label, 164 input.has-value+.input-label { 165 opacity: 0; 166 visibility: hidden; 167 transform: translateY(-120%); 168 } 169 170 /* Browser Autofill fix */ 171 input:-webkit-autofill, 172 input:-webkit-autofill:hover, 173 input:-webkit-autofill:focus { 174 -webkit-box-shadow: 0 0 0px 1000px #f3f6f9 inset !important; 175 transition: background-color 5000s ease-in-out 0s; 176 } 177 178 .forgot-password { 179 display: block; 180 margin: 12px 0; 181 color: var(--gray-text); 182 font-size: 0.8rem; 183 text-decoration: none; 184 transition: color 0.2s; 185 text-align: center; 186 } 187 188 .forgot-password:hover { 189 color: var(--primary-blue); 190 } 191 192 .login-btn { 193 width: 100%; 194 background-color: var(--primary-blue); 195 color: white; 196 border: none; 197 padding: 14px; 198 border-radius: 8px; 199 font-size: 0.9rem; 200 font-weight: 600; 201 cursor: pointer; 202 margin-top: 24px; 203 transition: background 0.3s; 204 } 205 206 .login-btn:hover { 207 background-color: #003a85; 208 } 209 210 .new-agency { 211 display: block; 212 margin-top: 20px; 213 color: var(--primary-blue); 214 font-weight: 600; 215 font-size: 0.8rem; 216 text-decoration: underline; 217 } 218 219 .footer-info { 220 margin-top: 50px; 221 font-size: 0.75rem; 222 color: var(--dark-text); 223 font-weight: 500; 224 } 225 226 .footer-links { 227 margin-top: 12px; 228 } 229 230 .footer-links a { 231 color: var(--dark-text); 232 text-decoration: underline; 233 font-size: 0.75rem; 234 } 235 236 /* Password Toggle */ 237 .password-toggle { 238 position: absolute; 239 right: 18px; 240 top: 50%; 241 transform: translateY(-50%); 242 color: var(--gray-text); 243 cursor: pointer; 244 font-size: 1.1rem; 245 transition: color 0.2s; 246 z-index: 5; 247 } 248 249 .password-toggle:hover { 250 color: var(--primary-blue); 251 } 252 253 @media (max-width: 600px) { 254 .login-card { 255 margin: 20px; 256 padding: 40px 20px; 257 } 258 } 259 260 /* Modal Styles */
261 .modal-overlay { 262 display: none; 263 position: fixed; 264 top: 0; 265 left: 0; 266 width: 100%; 267 height: 100%; 268 background: rgba(0, 0, 0, 0.7); 269 z-index: 1000; 270 justify-content: center; 271 align-items: center; 272 backdrop-filter: blur(5px); 273 } 274 275 .modal-overlay.show { 276 display: flex; 277 } 278 279 .modal-content { 280 background: white; 281 width: 100%; 282 max-width: 800px; 283 max-height: 80vh; 284 border-radius: 20px; 285 padding: 40px; 286 position: relative; 287 overflow-y: auto; 288 text-align: left; 289 } 290 291 .modal-close { 292 position: absolute; 293 top: 20px; 294 right: 20px; 295 font-size: 24px; 296 cursor: pointer; 297 color: #666; 298 } 299 300 .modal-content h2 { 301 color: var(--primary-bg); 302 margin-bottom: 20px; 303 font-size: 1.5rem; 304 } 305 306 .modal-content h3 { 307 color: var(--primary-bg); 308 margin-top: 25px; 309 margin-bottom: 10px; 310 font-size: 1.1rem; 311 font-weight: 700; 312 } 313 314 .modal-content p { 315 font-size: 0.9rem; 316 line-height: 1.6; 317 color: #444; 318 margin-bottom: 15px; 319 } 320 </style> 321</head> 322 323<body> 324 <div class="login-card"> 325 <div class="logo-container"> 326 <img src="/static/octopusProject/images/asistalllogomavi.webp" alt="AsistAll Logo" /> 327 </div> 328 329 <h1 data-tr="Kurumsal GiriÅ Yapın" data-en="Corporate Login">Kurumsal GiriÅ Yapın</h1> 330 331 <div class="lang-selector-container"> 332 <button class="lang-selector" id="langBtn"> 333 <span id="currentLangText">Türkçe</span> 334 <i class="fas fa-chevron-down"></i> 335 </button> 336 <div class="lang-dropdown" id="langDropdown"> 337 <div class="lang-option" onclick="changeLang('tr')">Türkçe</div> 338 <div class="lang-option" onclick="changeLang('en')">English</div> 339 </div> 340 </div> 341 342 <div id="errorMessage" 343 style="display: none; color: #ff4d4f; font-size: 0.85rem; margin-bottom: 16px; text-align: center; border: 1px solid #ffccc7; background: #fff2f0; padding: 10px; border-radius: 8px;"> 344 </div> 345 346 <form id="loginForm"> 347 <div class="form-group"> 348 <div class="input-wrapper"> 349 <input type="text" id="username" placeholder=" " autocomplete="username" /> 350 <label for="username" class="input-label" data-tr="Kullanıcı adı" data-en="Username">Kullanıcı adı</label> 351 </div> 352 </div> 353 354 <div class="form-group"> 355 <div class="input-wrapper"> 356 <input type="password" id="password" placeholder=" " autocomplete="current-password" /> 357 <label for="password" class="input-label" data-tr="Åifre" data-en="Password">Åifre</label> 358 <i class="fas fa-eye password-toggle" id="togglePasswordIcon" onclick="togglePassword()"></i> 359 </div> 360 </div> 361 362 <a href="#" class="forgot-password" onclick="openB2bForgotPasswordModal(); return false;" 363 data-tr="Åifremi unuttum" data-en="Forgot password?">Åifremi unuttum</a> 364 365 <button type="submit" class="login-btn" data-tr="GiriÅ yap" data-en="Login">GiriÅ yap</button> 366 367 <a href="/b2b/corporate-register-docs/" class="new-agency" data-tr="Yeni Åirket Ãyelik" 368 data-en="New Company Registration">Yeni Åirket Ãyelik</a> 369 </form> 370 371 <div class="footer-info"> 372 <span data-tr="Tel: +971 52 740 0276" data-en="Phone: +971 52 740 0276 ">Tel: +971 52 740 0276</span> 373 </div> 374 375 <div class="footer-links"> 376 <a href="javascript:void(0)" onclick="openTermsModal()" data-tr="Kullanım KoÅulları" 377 data-en="Terms of Use">Kullanım KoÅulları</a> 378 </div> 379 </div> 380 381 <!-- Forgot Password Modal --> 382 <div class="modal-overlay" id="b2bForgotPasswordModal"> 383 <div class="modal-content" style="max-width: 450px;"> 384 <span class="modal-close" onclick="closeB2bForgotPasswordModal()">×</span> 385 <h2 data-tr="Åifre Yenile" data-en="Reset Password" 386 style="text-align:center; color: var(--dark-text); font-size: 1.3rem;">Åifre Yenile</h2> 387 388 <div id="b2bForgotAlert" 389 style="display: none; margin-bottom: 15px; padding: 12px; border-radius: 8px; font-size: 0.85rem; text-align: center;"> 390 </div> 391 392 <div id="b2bForgotStepEmail"> 393 <p style="text-align: center; font-size: 0.9rem; color: #666; margin-bottom: 20px;" 394 data-tr="Kayıtlı e-posta adresiniz ile doÄrulama kodu alıp yeni Åifrenizi belirleyin." 395 data-en="Enter your registered email address to receive a verification code."> 396 Kayıtlı e-posta adresiniz ile doÄrulama kodu alıp yeni Åifrenizi belirleyin. 397 </p> 398 <div class="form-group"> 399 <div class="input-wrapper"> 400 <input type="email" id="b2bForgotEmail" placeholder=" " /> 401 <label for="b2bForgotEmail" class="input-label" data-tr="E-posta" data-en="Email">E-posta</label> 402 </div> 403 </div> 404 <button type="button" class="login-btn" id="b2bForgotSendCodeBtn" onclick="handleB2bForgotPasswordSendCode()" 405 style="margin-top: 10px;" data-tr="Kod Gönder" data-en="Send Code">Kod Gönder</button> 406 </div> 407 408 <div id="b2bForgotStepCode" style="display: none;"> 409 <p style="text-align: center; font-size: 0.9rem; color: #666; margin-bottom: 20px;" 410 data-tr="E-posta adresinize gönderilen 6 haneli kodu girin." 411 data-en="Enter the 6-digit code sent to your email."> 412 E-posta adresinize gönderilen 6 haneli kodu girin. 413 </p> 414 <div class="form-group"> 415 <div class="input-wrapper"> 416 <input type="text" id="b2bForgotCode" placeholder=" " maxlength="6" inputmode="numeric" /> 417 <label for="b2bForgotCode" class="input-label" data-tr="DoÄrulama Kodu" 418 data-en="Verification Code">DoÄrulama Kodu</label> 419 </div> 420 </div> 421 <div style="display: flex; gap: 10px; margin-top: 10px;"> 422 <button type="button" class="login-btn" style="background: #6b7280; margin-top: 0;" 423 onclick="setB2bForgotStep('email')" data-tr="Geri" data-en="Back">Geri</button> 424 <button type="button" class="login-btn" id="b2bForgotVerifyCodeBtn" style="margin-top: 0;" 425 onclick="handleB2bForgotPasswordVerifyCode()" data-tr="Kodu DoÄrula" data-en="Verify Code">Kodu 426 DoÄrula</button> 427 </div> 428 </div> 429 430 <div id="b2bForgotStepReset" style="display: none;"> 431 <p style="text-align: center; font-size: 0.9rem; color: #666; margin-bottom: 20px;" 432 data-tr="Lütfen yeni Åifrenizi belirleyin." data-en="Please enter your new password."> 433 Lütfen yeni Åifrenizi belirleyin. 434 </p> 435 <div class="form-group"> 436 <div class="input-wrapper"> 437 <input type="password" id="b2bForgotNewPassword" placeholder=" " /> 438 <label for="b2bForgotNewPassword" class="input-label" data-tr="Yeni Åifre" data-en="New Password">Yeni 439 Åifre</label> 440 <i class="fas fa-eye password-toggle" onclick="toggleB2bForgotField(this, 'b2bForgotNewPassword')"></i> 441 </div> 442 </div> 443 <div class="form-group"> 444 <div class="input-wrapper"> 445 <input type="password" id="b2bForgotConfirmPassword" placeholder=" " /> 446 <label for="b2bForgotConfirmPassword" class="input-label" data-tr="Yeni Åifre (Tekrar)" 447 data-en="Confirm New Password">Yeni Åifre (Tekrar)</label> 448 <i class="fas fa-eye password-toggle" onclick="toggleB2bForgotField(this, 'b2bForgotConfirmPassword')"></i> 449 </div> 450 </div> 451 <button type="button" class="login-btn" id="b2bForgotResetBtn" onclick="handleB2bForgotPasswordReset()" 452 style="margin-top: 10px;" data-tr="Åifreyi Güncelle" data-en="Update Password">Åifreyi Güncelle</button> 453 </div> 454 </div> 455 </div> 456 457 <!-- Terms Modal --> 458 <div class="modal-overlay" id="termsModal"> 459 <div class="modal-content">
460 <span class="modal-close" onclick="closeTermsModal()">×</span> 461 <h2 id="termsModalTitle" data-tr="Kullanım KoÅulları" data-en="Terms of Use">Kullanım KoÅulları</h2> 462 <div id="termsContent"> 463 <!-- Dynamic content goes here --> 464 </div> 465 </div> 466 </div> 467 468
468<script> 469 async function openTermsModal() { 470 const modal = document.getElementById('termsModal'); 471 const content = document.getElementById('termsContent'); 472 const title = document.getElementById('termsModalTitle'); 473 474 content.innerHTML = ` 475 <div style="text-align: center; padding: 40px;"> 476 <i class="fas fa-spinner fa-spin" style="font-size: 2rem; color: var(--primary-blue);"></i> 477 <p style="margin-top: 10px; color: #666;">Yükleniyor / Loading...</p> 478 </div> 479 `; 480 modal.classList.add('show'); 481 document.body.style.overflow = 'hidden'; 482 483 try { 484 const response = await fetch('/legal/document/global-01-kullanim-kosullari/?format=json'); 485 if (response.ok) { 486 const data = await response.json(); 487 if (title) title.textContent = data.title; 488 content.innerHTML = data.html_content; 489 } else { 490 content.innerHTML = '<p>İçerik yüklenemedi. / Could not load content.</p>'; 491 } 492 } catch (error) { 493 content.innerHTML = '<p>BaÄlantı hatası. / Connection error.</p>'; 494 } 495 } 496 497 function closeTermsModal() { 498 document.getElementById('termsModal').classList.remove('show'); 499 document.body.style.overflow = ''; 500 } 501 502 function togglePassword() { 503 const passwordInput = document.getElementById('password'); 504 const icon = document.getElementById('togglePasswordIcon'); 505 506 if (passwordInput.type === 'password') { 507 passwordInput.type = 'text'; 508 icon.classList.remove('fa-eye'); 509 icon.classList.add('fa-eye-slash'); 510 } else { 511 passwordInput.type = 'password'; 512 icon.classList.remove('fa-eye-slash'); 513 icon.classList.add('fa-eye'); 514 } 515 } 516 517 // Dil DeÄiÅtirme MantıÄı 518 function changeLang(lang) { 519 document.getElementById('currentLangText').innerText = lang === 'tr' ? 'Türkçe' : 'English'; 520 document.getElementById('langDropdown').classList.remove('show'); 521 522 // Åehir/Dosya isimlerini bul ve deÄiÅtir 523 const elements = document.querySelectorAll('[data-tr]'); 524 elements.forEach(el => { 525 el.innerText = el.getAttribute(`data-${lang}`); 526 }); 527 528 // HTML lang attribute güncelle 529 document.documentElement.lang = lang; 530 531 // LocalStorage'a kaydet 532 localStorage.setItem('preferredLang', lang); 533 } 534 535 // Dropdown Toggle 536 document.getElementById('langBtn').addEventListener('click', (e) => { 537 e.stopPropagation(); 538 document.getElementById('langDropdown').classList.toggle('show'); 539 }); 540 541 // DıÅarı tıklayınca dropdown kapat 542 window.addEventListener('click', () => { 543 document.getElementById('langDropdown').classList.remove('show'); 544 }); 545 546 // Sayfa yüklendiÄinde ve input deÄiÅtikçe kontrol et (Autofill overlap hatası için) 547 function checkInputs() { 548 const inputs = document.querySelectorAll('input'); 549 inputs.forEach(input => { 550 if (input.value.length > 0) { 551 input.classList.add('has-value'); 552 } else { 553 input.classList.remove('has-value'); 554 } 555 }); 556 } 557 558 window.addEventListener('load', () => { 559 setTimeout(checkInputs, 100); 560 561 // Kayıtlı dil varsa onu yükle 562 const savedLang = localStorage.getItem('preferredLang'); 563 if (savedLang) changeLang(savedLang); 564 }); 565 566 const ASISTALL_APP_DEEP_LINK = window.ASISTALL_APP_DEEP_LINK || 'asistall://home'; 567 568 function isMobileOrTabletDevice() { 569 const ua = navigator.userAgent || navigator.vendor || window.opera || ''; 570 const mobileUa = /android|iphone|ipad|ipod|mobile|tablet|silk|kindle|playbook/i.test(ua); 571 const touchMac = navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1; 572 return mobileUa || touchMac || window.innerWidth <= 1024; 573 } 574 575 function tryOpenInstalledApp(fallbackUrl) { 576 const nextUrl = fallbackUrl || window.location.href; 577 if (!isMobileOrTabletDevice() || !ASISTALL_APP_DEEP_LINK) { 578 window.location.href = nextUrl; 579 return; 580 } 581 582 const startedAt = Date.now(); 583 let pageHidden = false;
584 let navigated = false; 585 586 const cleanup = () => { 587 window.removeEventListener('pagehide', onPageHide); 588 document.removeEventListener('visibilitychange', onVisibilityChange); 589 }; 590 591 const finishWithFallback = () => { 592 if (navigated) return; 593 navigated = true; 594 cleanup(); 595 window.location.href = nextUrl; 596 }; 597 598 const onPageHide = () => { 599 pageHidden = true; 600 navigated = true; 601 cleanup(); 602 }; 603 604 const onVisibilityChange = () => { 605 if (document.visibilityState === 'hidden') { 606 pageHidden = true; 607 } 608 }; 609 610 window.addEventListener('pagehide', onPageHide, { once: true }); 611 document.addEventListener('visibilitychange', onVisibilityChange); 612 613 const probeFrame = document.createElement('iframe'); 614 probeFrame.style.display = 'none'; 615 probeFrame.setAttribute('aria-hidden', 'true'); 616 probeFrame.src = ASISTALL_APP_DEEP_LINK; 617 document.body.appendChild(probeFrame); 618 619 window.setTimeout(() => { 620 if (!pageHidden && Date.now() - startedAt < 2200) { 621 finishWithFallback(); 622 } else { 623 cleanup(); 624 } 625 626 if (probeFrame.parentNode) { 627 probeFrame.parentNode.removeChild(probeFrame); 628 } 629 }, 1600); 630 } 631 632 document.getElementById('loginForm').addEventListener('submit', async (e) => { 633 e.preventDefault(); 634 635 const email = document.getElementById('username').value; 636 const password = document.getElementById('password').value; 637 const errorMessage = document.getElementById('errorMessage'); 638 const loginBtn = e.target.querySelector('button[type="submit"]'); 639 640 if (!email || !password) { 641 errorMessage.innerText = "Email ve Åifre gereklidir."; 642 errorMessage.style.display = 'block'; 643 return; 644 } 645 646 loginBtn.disabled = true; 647 loginBtn.innerText = "GiriÅ yapılıyor..."; 648 errorMessage.style.display = 'none'; 649 650 try { 651 const response = await fetch('/b2b/api/v1/auth/login', { 652 method: 'POST', 653 headers: { 654 'Content-Type': 'application/json', 655 'X-CSRFToken': 'a7N0v7wMFmqzxZVccrYjTCh1X4HPf1nuJrOxZwKyoHgKTb4dfL2604VIXmaHKVOG' 656 }, 657 body: JSON.stringify({ email, password }) 658 }); 659 660 const data = await response.json(); 661 662 if (data.success) { 663 // GiriÅ baÅarılı, ana sayfaya yönlendir 664 tryOpenInstalledApp("/"); 665 } else { 666 errorMessage.innerText = data.error || "GiriÅ baÅarısız."; 667 errorMessage.style.display = 'block'; 668 } 669 } catch (error) { 670 console.error('Login error:', error); 671 errorMessage.innerText = "Sunucu ile iletiÅim kurulamadı."; 672 errorMessage.style.display = 'block'; 673 } finally { 674 loginBtn.disabled = false; 675 loginBtn.innerText = "GiriÅ yap"; 676 } 677 }); 678 679 document.querySelectorAll('input').forEach(input => { 680 input.addEventListener('input', checkInputs); 681 input.addEventListener('change', checkInputs); 682 }); 683 684 // B2B Forgot Password Logic 685 function openB2bForgotPasswordModal() { 686 document.getElementById('b2bForgotAlert').style.display = 'none'; 687 setB2bForgotStep('email'); 688 b2bResetToken = ''; 689 document.getElementById('b2bForgotEmail').value = document.getElementById('username').value; 690 checkInputs(); 691 document.getElementById('b2bForgotPasswordModal').classList.add('show'); 692 document.body.style.overflow = 'hidden'; 693 } 694 695 function closeB2bForgotPasswordModal() { 696 document.getElementById('b2bForgotPasswordModal').classList.remove('show'); 697 document.body.style.overflow = ''; 698 } 699 700 function toggleB2bForgotField(icon, inputId) { 701 const input = document.getElementById(inputId); 702 if (input.type === 'password') { 703 input.type = 'text'; 704 icon.classList.remove('fa-eye'); 705 icon.classList.add('fa-eye-slash'); 706 } else { 707 input.type = 'password'; 708 icon.classList.remove('fa-eye-slash'); 709 icon.classList.add('fa-eye'); 710 } 711 } 712 713 function setB2bForgotStep(step) { 714 document.getElementById('b2bForgotStepEmail').style.display = step === 'email' ? 'block' : 'none'; 715 document.getElementById('b2bForgotStepCode').style.display = step === 'code' ? 'block' : 'none'; 716 document.getElementById('b2bForgotStepReset').style.display = step === 'reset' ? 'block' : 'none'; 717 } 718 719 function showB2bForgotAlert(message, type = 'error') { 720 const alert = document.getElementById('b2bForgotAlert'); 721 alert.style.display = 'block'; 722 alert.textContent = message; 723 if (type === 'success') { 724 alert.style.background = '#f6ffed'; 725 alert.style.borderColor = '#b7eb8f'; 726 alert.style.color = '#389e0d'; 727 } else { 728 alert.style.background = '#fff2f0'; 729 alert.style.borderColor = '#ffccc7'; 730 alert.style.color = '#cf1322'; 731 } 732 } 733 734 let b2bResetToken = ''; 735 736 async function handleB2bForgotPasswordSendCode() { 737 const email = document.getElementById('b2bForgotEmail').value.trim(); 738 if (!email) { 739 showB2bForgotAlert('E-posta gereklidir.'); 740 return; 741 } 742 743 const btn = document.getElementById('b2bForgotSendCodeBtn'); 744 btn.disabled = true; 745 btn.innerText = 'Gönderiliyor...'; 746
747 try { 748 const response = await fetch('/api/v1/auth/forgot-password', { 749 method: 'POST', 750 headers: { 'Content-Type': 'application/json' }, 751 body: JSON.stringify({ email }) 752 }); 753 const data = await response.json(); 754 if (data.success) { 755 showB2bForgotAlert(data.message || 'Kod gönderildi.', 'success'); 756 setB2bForgotStep('code'); 757 } else { 758 showB2bForgotAlert(data.error || 'İÅlem baÅarısız.'); 759 } 760 } catch (error) { 761 showB2bForgotAlert('Sunucu hatası.'); 762 } finally { 763 btn.disabled = false; 764 const lang = document.documentElement.lang; 765 btn.innerText = lang === 'en' ? 'Send Code' : 'Kod Gönder'; 766 } 767 } 768 769 async function handleB2bForgotPasswordVerifyCode() { 770 const email = document.getElementById('b2bForgotEmail').value.trim(); 771 const code = document.getElementById('b2bForgotCode').value.trim(); 772 if (!code) { 773 showB2bForgotAlert('Lütfen kodu girin.'); 774 return; 775 } 776 777 const btn = document.getElementById('b2bForgotVerifyCodeBtn'); 778 btn.disabled = true; 779 btn.innerText = 'DoÄrulanıyor...'; 780 781 try { 782 const response = await fetch('/api/v1/auth/verify-reset-code', { 783 method: 'POST', 784 headers: { 'Content-Type': 'application/json' }, 785 body: JSON.stringify({ email, code }) 786 }); 787 const data = await response.json(); 788 if (data.success) { 789 b2bResetToken = data.reset_token; 790 showB2bForgotAlert('Kod doÄrulandı. Yeni Åifrenizi belirleyin.', 'success'); 791 setB2bForgotStep('reset'); 792 } else { 793 showB2bForgotAlert(data.error || 'Kod geçersiz.'); 794 } 795 } catch (error) { 796 showB2bForgotAlert('Sunucu hatası.'); 797 } finally { 798 btn.disabled = false; 799 const lang = document.documentElement.lang; 800 btn.innerText = lang === 'en' ? 'Verify Code' : 'Kodu DoÄrula'; 801 } 802 } 803 804 async function handleB2bForgotPasswordReset() { 805 const newPassword = document.getElementById('b2bForgotNewPassword').value; 806 const confirmPassword = document.getElementById('b2bForgotConfirmPassword').value; 807 808 if (!newPassword || !confirmPassword) { 809 showB2bForgotAlert('Tüm alanları doldurun.'); 810 return; 811 } 812 if (newPassword !== confirmPassword) { 813 showB2bForgotAlert('Åifreler eÅleÅmiyor.'); 814 return; 815 } 816 817 const btn = document.getElementById('b2bForgotResetBtn'); 818 btn.disabled = true; 819 btn.innerText = 'Güncelleniyor...'; 820 821 try { 822 const response = await fetch('/api/v1/auth/reset-password', { 823 method: 'POST', 824 headers: { 'Content-Type': 'application/json' }, 825 body: JSON.stringify({ reset_token: b2bResetToken, new_password: newPassword }) 826 }); 827 const data = await response.json(); 828 if (data.success) { 829 showB2bForgotAlert(data.message || 'Åifreniz güncellendi.', 'success'); 830 document.getElementById('password').value = ''; 831 checkInputs(); 832 setTimeout(closeB2bForgotPasswordModal, 1500); 833 } else { 834 showB2bForgotAlert(data.error || 'İÅlem baÅarısız.'); 835 } 836 } catch (error) { 837 showB2bForgotAlert('Sunucu hatası.'); 838 } finally { 839 btn.disabled = false; 840 const lang = document.documentElement.lang; 841 btn.innerText = lang === 'en' ? 'Update Password' : 'Åifreyi Güncelle'; 842 } 843 } 844 </script>
844 845</body> 846 847</html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.